--- /dev/null
+freebsd_12_task:
+ freebsd_instance:
+ image: freebsd-12-0-release-amd64
+ cpu: 8
+ memory: 8G
+ env:
+ CIRRUS_CLONE_DEPTH: 1
+ install_script: pkg install -y
+ bison curl cyrus-sasl git glib gmake gnutls
+ nettle perl5 pixman pkgconf png usbredir
+ script:
+ - mkdir build
+ - cd build
+ - ../configure || { cat config.log; exit 1; }
+ - gmake -j8
+ - gmake -j8 V=1 check
/qapi/qapi-builtin-visit.[ch]
/qapi/qapi-commands-*.[ch]
/qapi/qapi-commands.[ch]
+/qapi/qapi-emit-events.[ch]
/qapi/qapi-events-*.[ch]
/qapi/qapi-events.[ch]
/qapi/qapi-introspect.[ch]
/pc-bios/optionrom/linuxboot_dma.bin
/pc-bios/optionrom/linuxboot_dma.raw
/pc-bios/optionrom/linuxboot_dma.img
+/pc-bios/optionrom/pvh.asm
+/pc-bios/optionrom/pvh.bin
+/pc-bios/optionrom/pvh.raw
+/pc-bios/optionrom/pvh.img
/pc-bios/optionrom/multiboot.asm
/pc-bios/optionrom/multiboot.bin
/pc-bios/optionrom/multiboot.raw
--- /dev/null
+before_script:
+ - apt-get update -qq
+ - apt-get install -y -qq flex bison libglib2.0-dev libpixman-1-dev genisoimage
+
+build-system1:
+ script:
+ - apt-get install -y -qq libgtk-3-dev libvte-dev nettle-dev libcacard-dev
+ libusb-dev libvde-dev libspice-protocol-dev libgl1-mesa-dev
+ - ./configure --enable-werror --target-list="aarch64-softmmu alpha-softmmu
+ cris-softmmu hppa-softmmu lm32-softmmu moxie-softmmu microblazeel-softmmu
+ mips64el-softmmu m68k-softmmu ppc-softmmu riscv64-softmmu sparc-softmmu"
+ - make -j2
+ - make -j2 check
+
+build-system2:
+ script:
+ - apt-get install -y -qq libsdl2-dev libgcrypt-dev libbrlapi-dev libaio-dev
+ libfdt-dev liblzo2-dev librdmacm-dev libibverbs-dev libibumad-dev
+ - ./configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu
+ microblaze-softmmu mips-softmmu riscv32-softmmu s390x-softmmu sh4-softmmu
+ sparc64-softmmu x86_64-softmmu xtensa-softmmu nios2-softmmu or1k-softmmu"
+ - make -j2
+ - make -j2 check
+
+build-disabled:
+ script:
+ - ./configure --enable-werror --disable-rdma --disable-slirp --disable-curl
+ --disable-capstone --disable-live-block-migration --disable-glusterfs
+ --disable-replication --disable-coroutine-pool --disable-smartcard
+ --disable-guest-agent --disable-curses --disable-libxml2 --disable-tpm
+ --disable-qom-cast-debug --disable-spice --disable-vhost-vsock
+ --disable-vhost-net --disable-vhost-crypto --disable-vhost-user
+ --target-list="i386-softmmu ppc64-softmmu mips64-softmmu i386-linux-user"
+ - make -j2
+ - make -j2 check-qtest SPEED=slow
+
+build-tcg-disabled:
+ script:
+ - apt-get install -y -qq clang libgtk-3-dev libbluetooth-dev libusb-dev
+ - ./configure --cc=clang --enable-werror --disable-tcg --audio-drv-list=""
+ - make -j2
+ - make check-unit
+ - make check-qapi-schema
+ - cd tests/qemu-iotests/
+ - ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048
+ 052 063 077 086 101 104 106 113 147 148 150 151 152 157 159 160
+ 163 170 171 183 184 192 194 197 205 208 215 221 222 226 227 236
+ - ./check -qcow2 001 002 003 004 005 007 008 009 010 011 012 013 017 018 019
+ 020 021 022 024 025 027 028 029 031 032 033 034 035 036 037 038
+ 039 040 042 043 046 047 048 049 050 051 052 053 054 056 057 058
+ 060 061 062 063 065 066 067 068 069 071 072 073 074 079 080 082
+ 085 086 089 090 091 095 096 097 098 099 102 103 104 105 107 108
+ 110 111 114 117 120 122 124 126 127 129 130 132 133 134 137 138
+ 139 140 141 142 143 144 145 147 150 151 152 154 155 156 157 158
+ 161 165 170 172 174 176 177 179 184 186 187 190 192 194 195 196
+ 197 200 202 203 205 208 209 214 215 216 217 218 222 226 227 229 234
+
+build-user:
+ script:
+ - ./configure --enable-werror --disable-system --disable-guest-agent
+ --disable-capstone --disable-slirp --disable-fdt
+ - make -j2
+ - make run-tcg-tests-i386-linux-user run-tcg-tests-x86_64-linux-user
+
+build-clang:
+ script:
+ - apt-get install -y -qq clang libsdl2-dev
+ xfslibs-dev libiscsi-dev libnfs-dev libseccomp-dev gnutls-dev librbd-dev
+ - ./configure --cc=clang --cxx=clang++ --enable-werror
+ --target-list="alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu
+ ppc-softmmu s390x-softmmu x86_64-softmmu arm-linux-user"
+ - make -j2
+ - make -j2 check
- gcovr
homebrew:
packages:
- - libffi
- - gettext
- glib
- pixman
global:
- SRC_DIR="."
- BUILD_DIR="."
+ - BASE_CONFIG="--disable-docs --disable-tools"
- TEST_CMD="make check -j3 V=1"
before_script:
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
- - ${SRC_DIR}/configure ${CONFIG} || { cat config.log && exit 1; }
+ - ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
script:
- make -j3 && ${TEST_CMD}
- env:
- - CONFIG="--enable-debug --enable-debug-tcg"
+ - CONFIG="--enable-debug --enable-debug-tcg --disable-user"
+ # TCG debug can be run just on it's own and is mostly agnostic to user/softmmu distinctions
- env:
- - CONFIG="--disable-linux-aio --disable-cap-ng --disable-attr --disable-brlapi --disable-uuid --disable-libusb --disable-user"
+ - CONFIG="--enable-debug-tcg --disable-system"
+
+
+ - env:
+ - CONFIG="--disable-linux-aio --disable-cap-ng --disable-attr --disable-brlapi --disable-libusb --disable-user --disable-replication"
- env:
- CONFIG="--enable-modules --disable-linux-user"
+ # Alternate coroutines implementations are only really of interest to KVM users
+ # However we can't test against KVM on Travis so we can only run unit tests
- env:
- - CONFIG="--with-coroutine=ucontext --disable-linux-user"
+ - CONFIG="--with-coroutine=ucontext --disable-tcg"
+ - TEST_CMD="make check-unit -j3 V=1"
- env:
- - CONFIG="--with-coroutine=sigaltstack --disable-linux-user"
+ - CONFIG="--with-coroutine=sigaltstack --disable-tcg"
+ - TEST_CMD="make check-unit -j3 V=1"
+
+ # Check we can build docs and tools
+ - env:
+ - BASE_CONFIG="--enable-tools --enable-docs"
+ - CONFIG="--target-list=x86_64-softmmu,aarch64-linux-user"
+ addons:
+ apt:
+ packages:
+ - python-sphinx
+ - texinfo
+ - perl
# Test out-of-tree builds
- env:
- TEST_CMD=""
- - env:
- - CONFIG="--disable-tcg"
- - TEST_CMD=""
-
-
# 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"
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"
- env:
- - CONFIG="--disable-system --disable-docs"
+ - CONFIG="--disable-system"
- TEST_CMD="make -j3 check-tcg V=1"
----------------------
Overall
L: qemu-devel@nongnu.org
-M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
M: Richard Henderson <rth@twiddle.net>
R: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
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: Halil Pasic <pasic@linux.ibm.com>
M: Cornelia Huck <cohuck@redhat.com>
M: Christian Borntraeger <borntraeger@de.ibm.com>
-S: Maintained
+S: Supported
F: target/s390x/kvm.c
F: target/s390x/kvm_s390x.h
F: target/s390x/kvm-stub.c
F: hw/ssi/pl022.c
F: include/hw/ssi/pl022.h
F: hw/timer/pl031.c
+F: include/hw/timer/pl031.h
F: include/hw/arm/primecell.h
F: hw/timer/cmsdk-apb-timer.c
F: include/hw/timer/cmsdk-apb-timer.h
F: include/hw/misc/iotkit-sysinfo.h
F: hw/misc/armsse-cpuid.c
F: include/hw/misc/armsse-cpuid.h
+F: hw/misc/armsse-mhu.c
+F: include/hw/misc/armsse-mhu.h
+
+Musca
+M: Peter Maydell <peter.maydell@linaro.org>
+L: qemu-arm@nongnu.org
+S: Maintained
+F: hw/arm/musca.c
Musicpal
M: Jan Kiszka <jan.kiszka@web.de>
T: git https://github.com/bonzini/qemu.git scsi-next
SSI
-M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
M: Alistair Francis <alistair@alistair23.me>
S: Maintained
F: hw/ssi/*
Xilinx SPI
M: Alistair Francis <alistair@alistair23.me>
-M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
S: Maintained
F: hw/ssi/xilinx_*
F: scsi/*
Block Jobs
-M: Jeff Cody <jcody@redhat.com>
+M: John Snow <jsnow@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: blockjob.c
F: block/stream.c
F: block/mirror.c
F: qapi/job.json
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
+T: git https://github.com/jnsnow/qemu.git jobs
Block QAPI, monitor, command line
M: Markus Armbruster <armbru@redhat.com>
F: include/qom/cpu.h
Device Tree
-M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
M: Alexander Graf <agraf@suse.de>
S: Maintained
F: device_tree.c
F: include/io/
F: tests/test-io-*
+User authorization
+M: Daniel P. Berrange <berrange@redhat.com>
+S: Maintained
+F: authz/
+F: qapi/authz.json
+F: include/authz/
+F: tests/test-authz-*
+
Sockets
M: Daniel P. Berrange <berrange@redhat.com>
M: Gerd Hoffmann <kraxel@redhat.com>
F: util/qemu-sockets.c
F: qapi/sockets.json
+File monitor
+M: Daniel P. Berrange <berrange@redhat.com>
+S: Odd fixes
+F: util/filemonitor*.c
+F: include/qemu/filemonitor.h
+F: tests/test-util-filemonitor.c
+
Throttling infrastructure
M: Alberto Garcia <berto@igalia.com>
S: Supported
RBD
M: Josh Durgin <jdurgin@redhat.com>
-M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: block/rbd.c
-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
-S: Supported
+L: sheepdog@lists.wpkg.org
+S: Odd Fixes
F: block/sheepdog.c
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
VHDX
-M: Jeff Cody <jcody@redhat.com>
+M: Jeff Cody <codyprime@gmail.com>
L: qemu-block@nongnu.org
S: Supported
F: block/vhdx*
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
VDI
M: Stefan Weil <sw@weilnetz.de>
T: git https://repo.or.cz/qemu/ericb.git nbd
NFS
-M: Jeff Cody <jcody@redhat.com>
M: Peter Lieven <pl@kamp.de>
L: qemu-block@nongnu.org
S: Maintained
F: block/nfs.c
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
SSH
M: Richard W.M. Jones <rjones@redhat.com>
-M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: block/ssh.c
-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 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 https://github.com/codyprime/qemu-kvm-jtc.git block
Null Block Driver
M: Fam Zheng <fam@euphon.net>
F: .shippable.yml
F: tests/docker/
F: tests/vm/
+F: scripts/archive-source.sh
W: https://travis-ci.org/qemu/qemu
W: https://app.shippable.com/github/qemu/qemu
W: http://patchew.org/QEMU/
+FreeBSD Hosted Continuous Integration
+M: Ed Maste <emaste@freebsd.org>
+M: Li-Wen Hsu <lwhsu@freebsd.org>
+L: qemu-devel@nongnu.org
+S: Maintained
+F: .cirrus.yml
+W: https://cirrus-ci.com/github/qemu/qemu
+
+GitLab Continuous Integration
+M: Thomas Huth <thuth@redhat.com>
+S: Maintained
+F: .gitlab-ci.yml
+
Guest Test Compilation Support
M: Alex Bennée <alex.bennee@linaro.org>
R: Philippe Mathieu-Daudé <f4bug@amsat.org>
GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
-#see Makefile.objs for the definition of QAPI_MODULES
GENERATED_QAPI_FILES = qapi/qapi-builtin-types.h qapi/qapi-builtin-types.c
GENERATED_QAPI_FILES += qapi/qapi-types.h qapi/qapi-types.c
GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-types-%.h)
GENERATED_QAPI_FILES += qapi/qapi-commands.h qapi/qapi-commands.c
GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-commands-%.h)
GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-commands-%.c)
+GENERATED_QAPI_FILES += qapi/qapi-emit-events.h qapi/qapi-emit-events.c
GENERATED_QAPI_FILES += qapi/qapi-events.h qapi/qapi-events.c
GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-events-%.h)
GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-events-%.c)
dummy := $(call unnest-vars,, \
stub-obj-y \
+ authz-obj-y \
chardev-obj-y \
util-obj-y \
qga-obj-y \
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
SOFTMMU_SUBDIR_RULES=$(filter %-softmmu,$(SUBDIR_RULES))
+$(SOFTMMU_SUBDIR_RULES): $(authz-obj-y)
$(SOFTMMU_SUBDIR_RULES): $(block-obj-y)
$(SOFTMMU_SUBDIR_RULES): $(crypto-obj-y)
$(SOFTMMU_SUBDIR_RULES): $(io-obj-y)
qemu-img.o: qemu-img-cmds.h
-qemu-img$(EXESUF): qemu-img.o $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
-qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
-qemu-io$(EXESUF): qemu-io.o $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
+qemu-img$(EXESUF): qemu-img.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
+qemu-nbd$(EXESUF): qemu-nbd.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
+qemu-io$(EXESUF): qemu-io.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o $(COMMON_LDADDS)
fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/9p-marshal.o fsdev/9p-iov-marshal.o $(COMMON_LDADDS)
fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
-scsi/qemu-pr-helper$(EXESUF): scsi/qemu-pr-helper.o scsi/utils.o $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
+scsi/qemu-pr-helper$(EXESUF): scsi/qemu-pr-helper.o scsi/utils.o $(authz-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
ifdef CONFIG_MPATH
scsi/qemu-pr-helper$(EXESUF): LIBS += -ludev -lmultipath -lmpathpersist
endif
qemu-ga: qemu-ga$(EXESUF) $(QGA_VSS_PROVIDER) $(QEMU_GA_MSI)
endif
-elf2dmp: LIBS = $(CURL_LIBS)
-elf2dmp: $(elf2dmp-obj-y)
+elf2dmp$(EXESUF): LIBS += $(CURL_LIBS)
+elf2dmp$(EXESUF): $(elf2dmp-obj-y)
$(call LINK, $^)
ifdef CONFIG_IVSHMEM
efi-pcnet.rom efi-rtl8139.rom efi-virtio.rom \
efi-e1000e.rom efi-vmxnet3.rom \
bamboo.dtb canyonlands.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
-multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin \
+multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin \
s390-ccw.img s390-netboot.img \
spapr-rtas.bin slof.bin skiboot.lid \
palcode-clipper \
-QAPI_MODULES = block-core block char common crypto introspect job migration
-QAPI_MODULES += misc net rdma rocker run-state sockets tpm trace transaction
-QAPI_MODULES += ui
-
#######################################################################
# Common libraries for tools and emulators
-stub-obj-y = stubs/ crypto/
+stub-obj-y = stubs/ util/ crypto/
util-obj-y = util/ qobject/ qapi/
-util-obj-y += qapi/qapi-builtin-types.o
-util-obj-y += qapi/qapi-types.o
-util-obj-y += $(QAPI_MODULES:%=qapi/qapi-types-%.o)
-util-obj-y += qapi/qapi-builtin-visit.o
-util-obj-y += qapi/qapi-visit.o
-util-obj-y += $(QAPI_MODULES:%=qapi/qapi-visit-%.o)
-util-obj-y += qapi/qapi-events.o
-util-obj-y += $(QAPI_MODULES:%=qapi/qapi-events-%.o)
-util-obj-y += qapi/qapi-introspect.o
chardev-obj-y = chardev/
slirp-obj-$(CONFIG_SLIRP) = slirp/
+#######################################################################
+# authz-obj-y is code used by both qemu system emulation and qemu-img
+
+authz-obj-y = authz/
+
#######################################################################
# block-obj-y is code used by both qemu system emulation and qemu-img
######################################################################
# qapi
-common-obj-y += qapi/qapi-commands.o
-common-obj-y += $(QAPI_MODULES:%=qapi/qapi-commands-%.o)
-common-obj-y += qapi/qapi-introspect.o
common-obj-y += qmp.o hmp.o
+common-obj-y += qapi/
endif
#######################################################################
trace-events-subdirs += accel/kvm
trace-events-subdirs += accel/tcg
trace-events-subdirs += audio
+trace-events-subdirs += authz
trace-events-subdirs += block
trace-events-subdirs += chardev
trace-events-subdirs += crypto
trace-events-subdirs += qapi
trace-events-subdirs += qom
trace-events-subdirs += scsi
-trace-events-subdirs += slirp
trace-events-subdirs += target/arm
trace-events-subdirs += target/i386
trace-events-subdirs += target/mips
obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o
obj-y += qtest.o
obj-y += hw/
+obj-y += qapi/
obj-y += memory.o
obj-y += memory_mapping.o
obj-y += dump.o
dummy := $(call unnest-vars,,target-obj-y)
target-obj-y-save := $(target-obj-y)
dummy := $(call unnest-vars,.., \
+ authz-obj-y \
block-obj-y \
block-obj-m \
chardev-obj-y \
all-obj-y += $(common-obj-y)
all-obj-y += $(target-obj-y)
all-obj-y += $(qom-obj-y)
+all-obj-$(CONFIG_SOFTMMU) += $(authz-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y) $(chardev-obj-y)
all-obj-$(CONFIG_USER_ONLY) += $(crypto-aes-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
.fd = fd,
};
+ trace_kvm_set_ioeventfd_mmio(fd, (uint64_t)addr, val, assign, size,
+ datamatch);
if (!kvm_enabled()) {
return -ENOSYS;
}
.fd = fd,
};
int r;
+ trace_kvm_set_ioeventfd_pio(fd, addr, val, assign, size, datamatch);
if (!kvm_enabled()) {
return -ENOSYS;
}
kvm_irqchip_add_msi_route(char *name, int vector, int virq) "dev %s vector %d virq %d"
kvm_irqchip_update_msi_route(int virq) "Updating MSI route virq=%d"
kvm_irqchip_release_virq(int virq) "virq %d"
+kvm_set_ioeventfd_mmio(int fd, uint64_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%" PRIx64 " val=0x%x assign: %d size: %d match: %d"
+kvm_set_ioeventfd_pio(int fd, uint16_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%x val=0x%x assign: %d size: %d match: %d"
kvm_set_user_memory(uint32_t slot, uint32_t flags, uint64_t guest_phys_addr, uint64_t memory_size, uint64_t userspace_addr, int ret) "Slot#%d flags=0x%x gpa=0x%"PRIx64 " size=0x%"PRIx64 " ua=0x%"PRIx64 " ret=%d"
#ifndef CONFIG_SOFTMMU
tcg_debug_assert(!have_mmap_lock());
#endif
+ if (qemu_mutex_iothread_locked()) {
+ qemu_mutex_unlock_iothread();
+ }
assert_no_pages_locked();
}
struct tb_desc desc;
uint32_t h;
- cf_mask &= ~CF_CLUSTER_MASK;
- cf_mask |= cpu->cluster_index << CF_CLUSTER_SHIFT;
-
desc.env = (CPUArchState *)cpu->env_ptr;
desc.cs_base = cs_base;
desc.flags = flags;
if (qemu_mutex_iothread_locked()) {
qemu_mutex_unlock_iothread();
}
+ assert_no_pages_locked();
}
/* if an exception is pending, we execute it here */
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);
+ index = tlb_index(env, mmu_idx, addr);
+ entry = tlb_entry(env, mmu_idx, addr);
}
assert(tlb_hit(entry->addr_code, addr));
}
if (!VICTIM_TLB_HIT(addr_write, addr)) {
tlb_fill(ENV_GET_CPU(env), addr, 1 << s_bits, MMU_DATA_STORE,
mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+ tlbe = tlb_entry(env, mmu_idx, addr);
}
tlb_addr = tlb_addr_write(tlbe) & ~TLB_INVALID_MASK;
}
if (!VICTIM_TLB_HIT(ADDR_READ, addr)) {
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+ entry = tlb_entry(env, mmu_idx, addr);
}
tlb_addr = entry->ADDR_READ;
}
if (!VICTIM_TLB_HIT(ADDR_READ, addr)) {
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+ entry = tlb_entry(env, mmu_idx, addr);
}
tlb_addr = entry->ADDR_READ;
}
if (!VICTIM_TLB_HIT(addr_write, addr)) {
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+ entry = tlb_entry(env, mmu_idx, addr);
}
tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
}
if (!VICTIM_TLB_HIT(addr_write, addr)) {
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+ entry = tlb_entry(env, mmu_idx, addr);
}
tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
}
static void audio_process_options (const char *prefix,
struct audio_option *opt)
{
- char *optname;
- const char qemu_prefix[] = "QEMU_";
- size_t preflen, optlen;
+ gchar *prefix_upper;
if (audio_bug(__func__, !prefix)) {
dolog ("prefix = NULL\n");
return;
}
- preflen = strlen (prefix);
+ prefix_upper = g_utf8_strup(prefix, -1);
for (; opt->name; opt++) {
- size_t len, i;
+ char *optname;
int def;
if (!opt->valp) {
continue;
}
- len = strlen (opt->name);
- /* len of opt->name + len of prefix + size of qemu_prefix
- * (includes trailing zero) + zero + underscore (on behalf of
- * sizeof) */
- optlen = len + preflen + sizeof (qemu_prefix) + 1;
- optname = g_malloc (optlen);
-
- pstrcpy (optname, optlen, qemu_prefix);
-
- /* copy while upper-casing, including trailing zero */
- for (i = 0; i <= preflen; ++i) {
- optname[i + sizeof (qemu_prefix) - 1] = qemu_toupper(prefix[i]);
- }
- pstrcat (optname, optlen, "_");
- pstrcat (optname, optlen, opt->name);
+ optname = g_strdup_printf("QEMU_%s_%s", prefix_upper, opt->name);
def = 1;
switch (opt->tag) {
*opt->overriddenp = !def;
g_free (optname);
}
+ g_free(prefix_upper);
}
static void audio_print_settings (struct audsettings *as)
SWVoiceOut *sw;
HWVoiceOut *hw_cap = &cap->hw;
- sc = audio_calloc(__func__, 1, sizeof(*sc));
- if (!sc) {
- dolog ("Could not allocate soft capture voice (%zu bytes)\n",
- sizeof (*sc));
- return -1;
- }
+ sc = g_malloc0(sizeof(*sc));
sc->cap = cap;
sw = &sc->sw;
if (audio_validate_settings (as)) {
dolog ("Invalid settings were passed when trying to add capture\n");
audio_print_settings (as);
- goto err0;
+ return NULL;
}
- cb = audio_calloc(__func__, 1, sizeof(*cb));
- if (!cb) {
- dolog ("Could not allocate capture callback information, size %zu\n",
- sizeof (*cb));
- goto err0;
- }
+ cb = g_malloc0(sizeof(*cb));
cb->ops = *ops;
cb->opaque = cb_opaque;
HWVoiceOut *hw;
CaptureVoiceOut *cap;
- cap = audio_calloc(__func__, 1, sizeof(*cap));
- if (!cap) {
- dolog ("Could not allocate capture voice, size %zu\n",
- sizeof (*cap));
- goto err1;
- }
+ cap = g_malloc0(sizeof(*cap));
hw = &cap->hw;
QLIST_INIT (&hw->sw_head);
/* XXX find a more elegant way */
hw->samples = 4096 * 4;
- hw->mix_buf = audio_calloc(__func__, hw->samples,
- sizeof(struct st_sample));
- if (!hw->mix_buf) {
- dolog ("Could not allocate capture mix buffer (%d samples)\n",
- hw->samples);
- goto err2;
- }
+ hw->mix_buf = g_new0(struct st_sample, hw->samples);
audio_pcm_init_info (&hw->info, as);
- cap->buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
- if (!cap->buf) {
- dolog ("Could not allocate capture buffer "
- "(%d samples, each %d bytes)\n",
- hw->samples, 1 << hw->info.shift);
- goto err3;
- }
+ cap->buf = g_malloc0_n(hw->samples, 1 << hw->info.shift);
hw->clip = mixeng_clip
[hw->info.nchannels == 2]
audio_attach_capture (hw);
}
return cap;
-
- err3:
- g_free (cap->hw.mix_buf);
- err2:
- g_free (cap);
- err1:
- g_free (cb);
- err0:
- return NULL;
}
}
#define AUDIO_CAP "sdl"
#include "audio_int.h"
-#define USE_SEMAPHORE (SDL_MAJOR_VERSION < 2)
-
typedef struct SDLVoiceOut {
HWVoiceOut hw;
int live;
-#if USE_SEMAPHORE
- int rpos;
-#endif
int decr;
} SDLVoiceOut;
static struct SDLAudioState {
int exit;
-#if USE_SEMAPHORE
- SDL_mutex *mutex;
- SDL_sem *sem;
-#endif
int initialized;
bool driver_created;
} glob_sdl;
AUD_log (AUDIO_CAP, "Reason: %s\n", SDL_GetError ());
}
-static int sdl_lock (SDLAudioState *s, const char *forfn)
-{
-#if USE_SEMAPHORE
- if (SDL_LockMutex (s->mutex)) {
- sdl_logerr ("SDL_LockMutex for %s failed\n", forfn);
- return -1;
- }
-#else
- SDL_LockAudio();
-#endif
-
- return 0;
-}
-
-static int sdl_unlock (SDLAudioState *s, const char *forfn)
-{
-#if USE_SEMAPHORE
- if (SDL_UnlockMutex (s->mutex)) {
- sdl_logerr ("SDL_UnlockMutex for %s failed\n", forfn);
- return -1;
- }
-#else
- SDL_UnlockAudio();
-#endif
-
- return 0;
-}
-
-static int sdl_post (SDLAudioState *s, const char *forfn)
-{
-#if USE_SEMAPHORE
- if (SDL_SemPost (s->sem)) {
- sdl_logerr ("SDL_SemPost for %s failed\n", forfn);
- return -1;
- }
-#endif
-
- return 0;
-}
-
-#if USE_SEMAPHORE
-static int sdl_wait (SDLAudioState *s, const char *forfn)
-{
- if (SDL_SemWait (s->sem)) {
- sdl_logerr ("SDL_SemWait for %s failed\n", forfn);
- return -1;
- }
- return 0;
-}
-#endif
-
-static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn)
-{
- if (sdl_unlock (s, forfn)) {
- return -1;
- }
-
- return sdl_post (s, forfn);
-}
-
static int aud_to_sdlfmt (audfmt_e fmt)
{
switch (fmt) {
static void sdl_close (SDLAudioState *s)
{
if (s->initialized) {
- sdl_lock (s, "sdl_close");
+ SDL_LockAudio();
s->exit = 1;
- sdl_unlock_and_post (s, "sdl_close");
+ SDL_UnlockAudio();
SDL_PauseAudio (1);
SDL_CloseAudio ();
s->initialized = 0;
SDLAudioState *s = &glob_sdl;
HWVoiceOut *hw = &sdl->hw;
int samples = len >> hw->info.shift;
+ int to_mix, decr;
- if (s->exit) {
+ if (s->exit || !sdl->live) {
return;
}
- while (samples) {
- int to_mix, decr;
-
- /* dolog ("in callback samples=%d\n", samples); */
-#if USE_SEMAPHORE
- sdl_wait (s, "sdl_callback");
- if (s->exit) {
- return;
- }
-
- if (sdl_lock (s, "sdl_callback")) {
- return;
- }
-
- if (audio_bug(__func__, sdl->live < 0 || sdl->live > hw->samples)) {
- dolog ("sdl->live=%d hw->samples=%d\n",
- sdl->live, hw->samples);
- return;
- }
-
- if (!sdl->live) {
- goto again;
- }
-#else
- if (s->exit || !sdl->live) {
- break;
- }
-#endif
+ /* dolog ("in callback samples=%d live=%d\n", samples, sdl->live); */
- /* dolog ("in callback live=%d\n", live); */
- to_mix = audio_MIN (samples, sdl->live);
- decr = to_mix;
- while (to_mix) {
- int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
- struct st_sample *src = hw->mix_buf + hw->rpos;
-
- /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
- hw->clip (buf, src, chunk);
-#if USE_SEMAPHORE
- sdl->rpos = (sdl->rpos + chunk) % hw->samples;
-#else
- hw->rpos = (hw->rpos + chunk) % hw->samples;
-#endif
- to_mix -= chunk;
- buf += chunk << hw->info.shift;
- }
- samples -= decr;
- sdl->live -= decr;
- sdl->decr += decr;
-
-#if USE_SEMAPHORE
- again:
- if (sdl_unlock (s, "sdl_callback")) {
- return;
- }
-#endif
+ to_mix = audio_MIN(samples, sdl->live);
+ decr = to_mix;
+ while (to_mix) {
+ int chunk = audio_MIN(to_mix, hw->samples - hw->rpos);
+ struct st_sample *src = hw->mix_buf + hw->rpos;
+
+ /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
+ hw->clip(buf, src, chunk);
+ hw->rpos = (hw->rpos + chunk) % hw->samples;
+ to_mix -= chunk;
+ buf += chunk << hw->info.shift;
}
+ samples -= decr;
+ sdl->live -= decr;
+ sdl->decr += decr;
+
/* dolog ("done len=%d\n", len); */
-#if (SDL_MAJOR_VERSION >= 2)
/* SDL2 does not clear the remaining buffer for us, so do it on our own */
if (samples) {
memset(buf, 0, samples << hw->info.shift);
}
-#endif
}
static int sdl_write_out (SWVoiceOut *sw, void *buf, int len)
{
int decr;
SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
- SDLAudioState *s = &glob_sdl;
- if (sdl_lock (s, "sdl_run_out")) {
- return 0;
- }
+ SDL_LockAudio();
if (sdl->decr > live) {
ldebug ("sdl->decr %d live %d sdl->live %d\n",
decr = audio_MIN (sdl->decr, live);
sdl->decr -= decr;
-#if USE_SEMAPHORE
- sdl->live = live - decr;
- hw->rpos = sdl->rpos;
-#else
sdl->live = live;
-#endif
- if (sdl->live > 0) {
- sdl_unlock_and_post (s, "sdl_run_out");
- }
- else {
- sdl_unlock (s, "sdl_run_out");
- }
+ SDL_UnlockAudio();
+
return decr;
}
return NULL;
}
-#if USE_SEMAPHORE
- s->mutex = SDL_CreateMutex ();
- if (!s->mutex) {
- sdl_logerr ("Failed to create SDL mutex\n");
- SDL_QuitSubSystem (SDL_INIT_AUDIO);
- return NULL;
- }
-
- s->sem = SDL_CreateSemaphore (0);
- if (!s->sem) {
- sdl_logerr ("Failed to create SDL semaphore\n");
- SDL_DestroyMutex (s->mutex);
- SDL_QuitSubSystem (SDL_INIT_AUDIO);
- return NULL;
- }
-#endif
-
s->driver_created = true;
return s;
}
{
SDLAudioState *s = opaque;
sdl_close (s);
-#if USE_SEMAPHORE
- SDL_DestroySemaphore (s->sem);
- SDL_DestroyMutex (s->mutex);
-#endif
SDL_QuitSubSystem (SDL_INIT_AUDIO);
s->driver_created = false;
}
uint8_t dlen[4];
uint32_t datalen = wav->bytes;
uint32_t rifflen = datalen + 36;
- Monitor *mon = cur_mon;
if (wav->f) {
le_store (rlen, rifflen, 4);
le_store (dlen, datalen, 4);
if (fseek (wav->f, 4, SEEK_SET)) {
- monitor_printf (mon, "wav_destroy: rlen fseek failed\nReason: %s\n",
- strerror (errno));
+ error_report("wav_destroy: rlen fseek failed: %s",
+ strerror(errno));
goto doclose;
}
if (fwrite (rlen, 4, 1, wav->f) != 1) {
- monitor_printf (mon, "wav_destroy: rlen fwrite failed\nReason %s\n",
- strerror (errno));
+ error_report("wav_destroy: rlen fwrite failed: %s",
+ strerror(errno));
goto doclose;
}
if (fseek (wav->f, 32, SEEK_CUR)) {
- monitor_printf (mon, "wav_destroy: dlen fseek failed\nReason %s\n",
- strerror (errno));
+ error_report("wav_destroy: dlen fseek failed: %s",
+ strerror(errno));
goto doclose;
}
if (fwrite (dlen, 1, 4, wav->f) != 4) {
- monitor_printf (mon, "wav_destroy: dlen fwrite failed\nReason %s\n",
- strerror (errno));
+ error_report("wav_destroy: dlen fwrite failed: %s",
+ strerror(errno));
goto doclose;
}
doclose:
WAVState *wav = opaque;
if (fwrite (buf, size, 1, wav->f) != 1) {
- monitor_printf (cur_mon, "wav_capture: fwrite error\nReason: %s",
- strerror (errno));
+ error_report("wav_capture: fwrite error: %s", strerror(errno));
}
wav->bytes += size;
}
int wav_start_capture (CaptureState *s, const char *path, int freq,
int bits, int nchannels)
{
- Monitor *mon = cur_mon;
WAVState *wav;
uint8_t hdr[] = {
0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
CaptureVoiceOut *cap;
if (bits != 8 && bits != 16) {
- monitor_printf (mon, "incorrect bit count %d, must be 8 or 16\n", bits);
+ error_report("incorrect bit count %d, must be 8 or 16", bits);
return -1;
}
if (nchannels != 1 && nchannels != 2) {
- monitor_printf (mon, "incorrect channel count %d, must be 1 or 2\n",
- nchannels);
+ error_report("incorrect channel count %d, must be 1 or 2",
+ nchannels);
return -1;
}
wav->f = fopen (path, "wb");
if (!wav->f) {
- monitor_printf (mon, "Failed to open wave file `%s'\nReason: %s\n",
- path, strerror (errno));
+ error_report("Failed to open wave file `%s': %s",
+ path, strerror(errno));
g_free (wav);
return -1;
}
wav->freq = freq;
if (fwrite (hdr, sizeof (hdr), 1, wav->f) != 1) {
- monitor_printf (mon, "Failed to write header\nReason: %s\n",
- strerror (errno));
+ error_report("Failed to write header: %s", strerror(errno));
goto error_free;
}
cap = AUD_add_capture (&as, &ops, wav);
if (!cap) {
- monitor_printf (mon, "Failed to add audio capture\n");
+ error_report("Failed to add audio capture");
goto error_free;
}
error_free:
g_free (wav->path);
if (fclose (wav->f)) {
- monitor_printf (mon, "Failed to close wave file\nReason: %s\n",
- strerror (errno));
+ error_report("Failed to close wave file: %s", strerror(errno));
}
g_free (wav);
return -1;
--- /dev/null
+authz-obj-y += base.o
+authz-obj-y += simple.o
+authz-obj-y += list.o
+authz-obj-y += listfile.o
+authz-obj-$(CONFIG_AUTH_PAM) += pamacct.o
+
+pamacct.o-libs = -lpam
--- /dev/null
+/*
+ * QEMU authorization framework base class
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "authz/base.h"
+#include "authz/trace.h"
+
+bool qauthz_is_allowed(QAuthZ *authz,
+ const char *identity,
+ Error **errp)
+{
+ QAuthZClass *cls = QAUTHZ_GET_CLASS(authz);
+ bool allowed;
+
+ allowed = cls->is_allowed(authz, identity, errp);
+ trace_qauthz_is_allowed(authz, identity, allowed);
+
+ return allowed;
+}
+
+
+bool qauthz_is_allowed_by_id(const char *authzid,
+ const char *identity,
+ Error **errp)
+{
+ QAuthZ *authz;
+ Object *obj;
+ Object *container;
+
+ container = object_get_objects_root();
+ obj = object_resolve_path_component(container,
+ authzid);
+ if (!obj) {
+ error_setg(errp, "Cannot find QAuthZ object ID %s",
+ authzid);
+ return false;
+ }
+
+ if (!object_dynamic_cast(obj, TYPE_QAUTHZ)) {
+ error_setg(errp, "Object '%s' is not a QAuthZ subclass",
+ authzid);
+ return false;
+ }
+
+ authz = QAUTHZ(obj);
+
+ return qauthz_is_allowed(authz, identity, errp);
+}
+
+
+static const TypeInfo authz_info = {
+ .parent = TYPE_OBJECT,
+ .name = TYPE_QAUTHZ,
+ .instance_size = sizeof(QAuthZ),
+ .class_size = sizeof(QAuthZClass),
+ .abstract = true,
+};
+
+static void qauthz_register_types(void)
+{
+ type_register_static(&authz_info);
+}
+
+type_init(qauthz_register_types)
+
--- /dev/null
+/*
+ * QEMU access control list authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "authz/list.h"
+#include "authz/trace.h"
+#include "qom/object_interfaces.h"
+#include "qapi/qapi-visit-authz.h"
+
+static bool qauthz_list_is_allowed(QAuthZ *authz,
+ const char *identity,
+ Error **errp)
+{
+ QAuthZList *lauthz = QAUTHZ_LIST(authz);
+ QAuthZListRuleList *rules = lauthz->rules;
+
+ while (rules) {
+ QAuthZListRule *rule = rules->value;
+ QAuthZListFormat format = rule->has_format ? rule->format :
+ QAUTHZ_LIST_FORMAT_EXACT;
+
+ trace_qauthz_list_check_rule(authz, rule->match, identity,
+ format, rule->policy);
+ switch (format) {
+ case QAUTHZ_LIST_FORMAT_EXACT:
+ if (g_str_equal(rule->match, identity)) {
+ return rule->policy == QAUTHZ_LIST_POLICY_ALLOW;
+ }
+ break;
+ case QAUTHZ_LIST_FORMAT_GLOB:
+ if (g_pattern_match_simple(rule->match, identity)) {
+ return rule->policy == QAUTHZ_LIST_POLICY_ALLOW;
+ }
+ break;
+ default:
+ g_warn_if_reached();
+ return false;
+ }
+ rules = rules->next;
+ }
+
+ trace_qauthz_list_default_policy(authz, identity, lauthz->policy);
+ return lauthz->policy == QAUTHZ_LIST_POLICY_ALLOW;
+}
+
+
+static void
+qauthz_list_prop_set_policy(Object *obj,
+ int value,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZList *lauthz = QAUTHZ_LIST(obj);
+
+ lauthz->policy = value;
+}
+
+
+static int
+qauthz_list_prop_get_policy(Object *obj,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZList *lauthz = QAUTHZ_LIST(obj);
+
+ return lauthz->policy;
+}
+
+
+static void
+qauthz_list_prop_get_rules(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ QAuthZList *lauthz = QAUTHZ_LIST(obj);
+
+ visit_type_QAuthZListRuleList(v, name, &lauthz->rules, errp);
+}
+
+static void
+qauthz_list_prop_set_rules(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ QAuthZList *lauthz = QAUTHZ_LIST(obj);
+ QAuthZListRuleList *oldrules;
+
+ oldrules = lauthz->rules;
+ visit_type_QAuthZListRuleList(v, name, &lauthz->rules, errp);
+
+ qapi_free_QAuthZListRuleList(oldrules);
+}
+
+
+static void
+qauthz_list_finalize(Object *obj)
+{
+ QAuthZList *lauthz = QAUTHZ_LIST(obj);
+
+ qapi_free_QAuthZListRuleList(lauthz->rules);
+}
+
+
+static void
+qauthz_list_class_init(ObjectClass *oc, void *data)
+{
+ QAuthZClass *authz = QAUTHZ_CLASS(oc);
+
+ object_class_property_add_enum(oc, "policy",
+ "QAuthZListPolicy",
+ &QAuthZListPolicy_lookup,
+ qauthz_list_prop_get_policy,
+ qauthz_list_prop_set_policy,
+ NULL);
+
+ object_class_property_add(oc, "rules", "QAuthZListRule",
+ qauthz_list_prop_get_rules,
+ qauthz_list_prop_set_rules,
+ NULL, NULL, NULL);
+
+ authz->is_allowed = qauthz_list_is_allowed;
+}
+
+
+QAuthZList *qauthz_list_new(const char *id,
+ QAuthZListPolicy policy,
+ Error **errp)
+{
+ return QAUTHZ_LIST(
+ object_new_with_props(TYPE_QAUTHZ_LIST,
+ object_get_objects_root(),
+ id, errp,
+ "policy", QAuthZListPolicy_str(policy),
+ NULL));
+}
+
+ssize_t qauthz_list_append_rule(QAuthZList *auth,
+ const char *match,
+ QAuthZListPolicy policy,
+ QAuthZListFormat format,
+ Error **errp)
+{
+ QAuthZListRule *rule;
+ QAuthZListRuleList *rules, *tmp;
+ size_t i = 0;
+
+ rule = g_new0(QAuthZListRule, 1);
+ rule->policy = policy;
+ rule->match = g_strdup(match);
+ rule->format = format;
+ rule->has_format = true;
+
+ tmp = g_new0(QAuthZListRuleList, 1);
+ tmp->value = rule;
+
+ rules = auth->rules;
+ if (rules) {
+ while (rules->next) {
+ i++;
+ rules = rules->next;
+ }
+ rules->next = tmp;
+ return i + 1;
+ } else {
+ auth->rules = tmp;
+ return 0;
+ }
+}
+
+
+ssize_t qauthz_list_insert_rule(QAuthZList *auth,
+ const char *match,
+ QAuthZListPolicy policy,
+ QAuthZListFormat format,
+ size_t index,
+ Error **errp)
+{
+ QAuthZListRule *rule;
+ QAuthZListRuleList *rules, *tmp;
+ size_t i = 0;
+
+ rule = g_new0(QAuthZListRule, 1);
+ rule->policy = policy;
+ rule->match = g_strdup(match);
+ rule->format = format;
+ rule->has_format = true;
+
+ tmp = g_new0(QAuthZListRuleList, 1);
+ tmp->value = rule;
+
+ rules = auth->rules;
+ if (rules && index > 0) {
+ while (rules->next && i < (index - 1)) {
+ i++;
+ rules = rules->next;
+ }
+ tmp->next = rules->next;
+ rules->next = tmp;
+ return i + 1;
+ } else {
+ tmp->next = auth->rules;
+ auth->rules = tmp;
+ return 0;
+ }
+}
+
+
+ssize_t qauthz_list_delete_rule(QAuthZList *auth, const char *match)
+{
+ QAuthZListRule *rule;
+ QAuthZListRuleList *rules, *prev;
+ size_t i = 0;
+
+ prev = NULL;
+ rules = auth->rules;
+ while (rules) {
+ rule = rules->value;
+ if (g_str_equal(rule->match, match)) {
+ if (prev) {
+ prev->next = rules->next;
+ } else {
+ auth->rules = rules->next;
+ }
+ rules->next = NULL;
+ qapi_free_QAuthZListRuleList(rules);
+ return i;
+ }
+ prev = rules;
+ rules = rules->next;
+ i++;
+ }
+
+ return -1;
+}
+
+
+static const TypeInfo qauthz_list_info = {
+ .parent = TYPE_QAUTHZ,
+ .name = TYPE_QAUTHZ_LIST,
+ .instance_size = sizeof(QAuthZList),
+ .instance_finalize = qauthz_list_finalize,
+ .class_size = sizeof(QAuthZListClass),
+ .class_init = qauthz_list_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+
+static void
+qauthz_list_register_types(void)
+{
+ type_register_static(&qauthz_list_info);
+}
+
+
+type_init(qauthz_list_register_types);
--- /dev/null
+/*
+ * QEMU access control list file authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "authz/listfile.h"
+#include "authz/trace.h"
+#include "qemu/error-report.h"
+#include "qemu/main-loop.h"
+#include "qemu/sockets.h"
+#include "qemu/filemonitor.h"
+#include "qom/object_interfaces.h"
+#include "qapi/qapi-visit-authz.h"
+#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qobject.h"
+#include "qapi/qmp/qerror.h"
+#include "qapi/qobject-input-visitor.h"
+
+
+static bool
+qauthz_list_file_is_allowed(QAuthZ *authz,
+ const char *identity,
+ Error **errp)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(authz);
+ if (fauthz->list) {
+ return qauthz_is_allowed(fauthz->list, identity, errp);
+ }
+
+ return false;
+}
+
+
+static QAuthZ *
+qauthz_list_file_load(QAuthZListFile *fauthz, Error **errp)
+{
+ GError *err = NULL;
+ gchar *content = NULL;
+ gsize len;
+ QObject *obj = NULL;
+ QDict *pdict;
+ Visitor *v = NULL;
+ QAuthZ *ret = NULL;
+
+ trace_qauthz_list_file_load(fauthz, fauthz->filename);
+ if (!g_file_get_contents(fauthz->filename, &content, &len, &err)) {
+ error_setg(errp, "Unable to read '%s': %s",
+ fauthz->filename, err->message);
+ goto cleanup;
+ }
+
+ obj = qobject_from_json(content, errp);
+ if (!obj) {
+ goto cleanup;
+ }
+
+ pdict = qobject_to(QDict, obj);
+ if (!pdict) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "obj", "dict");
+ goto cleanup;
+ }
+
+ v = qobject_input_visitor_new(obj);
+
+ ret = (QAuthZ *)user_creatable_add_type(TYPE_QAUTHZ_LIST,
+ NULL, pdict, v, errp);
+
+ cleanup:
+ visit_free(v);
+ qobject_unref(obj);
+ if (err) {
+ g_error_free(err);
+ }
+ g_free(content);
+ return ret;
+}
+
+
+static void
+qauthz_list_file_event(int wd G_GNUC_UNUSED,
+ QFileMonitorEvent ev G_GNUC_UNUSED,
+ const char *name G_GNUC_UNUSED,
+ void *opaque)
+{
+ QAuthZListFile *fauthz = opaque;
+ Error *err = NULL;
+
+ if (ev != QFILE_MONITOR_EVENT_MODIFIED &&
+ ev != QFILE_MONITOR_EVENT_CREATED) {
+ return;
+ }
+
+ object_unref(OBJECT(fauthz->list));
+ fauthz->list = qauthz_list_file_load(fauthz, &err);
+ trace_qauthz_list_file_refresh(fauthz,
+ fauthz->filename, fauthz->list ? 1 : 0);
+ if (!fauthz->list) {
+ error_report_err(err);
+ }
+}
+
+static void
+qauthz_list_file_complete(UserCreatable *uc, Error **errp)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(uc);
+ gchar *dir = NULL, *file = NULL;
+
+ fauthz->list = qauthz_list_file_load(fauthz, errp);
+
+ if (!fauthz->refresh) {
+ return;
+ }
+
+ fauthz->file_monitor = qemu_file_monitor_new(errp);
+ if (!fauthz->file_monitor) {
+ return;
+ }
+
+ dir = g_path_get_dirname(fauthz->filename);
+ if (g_str_equal(dir, ".")) {
+ error_setg(errp, "Filename must be an absolute path");
+ goto cleanup;
+ }
+ file = g_path_get_basename(fauthz->filename);
+ if (g_str_equal(file, ".")) {
+ error_setg(errp, "Path has no trailing filename component");
+ goto cleanup;
+ }
+
+ fauthz->file_watch = qemu_file_monitor_add_watch(
+ fauthz->file_monitor, dir, file,
+ qauthz_list_file_event, fauthz, errp);
+ if (fauthz->file_watch < 0) {
+ goto cleanup;
+ }
+
+ cleanup:
+ g_free(file);
+ g_free(dir);
+}
+
+
+static void
+qauthz_list_file_prop_set_filename(Object *obj,
+ const char *value,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(obj);
+
+ g_free(fauthz->filename);
+ fauthz->filename = g_strdup(value);
+}
+
+
+static char *
+qauthz_list_file_prop_get_filename(Object *obj,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(obj);
+
+ return g_strdup(fauthz->filename);
+}
+
+
+static void
+qauthz_list_file_prop_set_refresh(Object *obj,
+ bool value,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(obj);
+
+ fauthz->refresh = value;
+}
+
+
+static bool
+qauthz_list_file_prop_get_refresh(Object *obj,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(obj);
+
+ return fauthz->refresh;
+}
+
+
+static void
+qauthz_list_file_finalize(Object *obj)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(obj);
+
+ object_unref(OBJECT(fauthz->list));
+ g_free(fauthz->filename);
+ qemu_file_monitor_free(fauthz->file_monitor);
+}
+
+
+static void
+qauthz_list_file_class_init(ObjectClass *oc, void *data)
+{
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+ QAuthZClass *authz = QAUTHZ_CLASS(oc);
+
+ ucc->complete = qauthz_list_file_complete;
+
+ object_class_property_add_str(oc, "filename",
+ qauthz_list_file_prop_get_filename,
+ qauthz_list_file_prop_set_filename,
+ NULL);
+ object_class_property_add_bool(oc, "refresh",
+ qauthz_list_file_prop_get_refresh,
+ qauthz_list_file_prop_set_refresh,
+ NULL);
+
+ authz->is_allowed = qauthz_list_file_is_allowed;
+}
+
+
+static void
+qauthz_list_file_init(Object *obj)
+{
+ QAuthZListFile *authz = QAUTHZ_LIST_FILE(obj);
+
+ authz->file_watch = -1;
+#ifdef CONFIG_INOTIFY1
+ authz->refresh = TRUE;
+#endif
+}
+
+
+QAuthZListFile *qauthz_list_file_new(const char *id,
+ const char *filename,
+ bool refresh,
+ Error **errp)
+{
+ return QAUTHZ_LIST_FILE(
+ object_new_with_props(TYPE_QAUTHZ_LIST_FILE,
+ object_get_objects_root(),
+ id, errp,
+ "filename", filename,
+ "refresh", refresh ? "yes" : "no",
+ NULL));
+}
+
+
+static const TypeInfo qauthz_list_file_info = {
+ .parent = TYPE_QAUTHZ,
+ .name = TYPE_QAUTHZ_LIST_FILE,
+ .instance_init = qauthz_list_file_init,
+ .instance_size = sizeof(QAuthZListFile),
+ .instance_finalize = qauthz_list_file_finalize,
+ .class_size = sizeof(QAuthZListFileClass),
+ .class_init = qauthz_list_file_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+
+static void
+qauthz_list_file_register_types(void)
+{
+ type_register_static(&qauthz_list_file_info);
+}
+
+
+type_init(qauthz_list_file_register_types);
--- /dev/null
+/*
+ * QEMU PAM authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "authz/pamacct.h"
+#include "authz/trace.h"
+#include "qom/object_interfaces.h"
+
+#include <security/pam_appl.h>
+
+
+static bool qauthz_pam_is_allowed(QAuthZ *authz,
+ const char *identity,
+ Error **errp)
+{
+ QAuthZPAM *pauthz = QAUTHZ_PAM(authz);
+ const struct pam_conv pam_conversation = { 0 };
+ pam_handle_t *pamh = NULL;
+ int ret;
+
+ trace_qauthz_pam_check(authz, identity, pauthz->service);
+ ret = pam_start(pauthz->service,
+ identity,
+ &pam_conversation,
+ &pamh);
+ if (ret != PAM_SUCCESS) {
+ error_setg(errp, "Unable to start PAM transaction: %s",
+ pam_strerror(NULL, ret));
+ return false;
+ }
+
+ ret = pam_acct_mgmt(pamh, PAM_SILENT);
+ pam_end(pamh, ret);
+ if (ret != PAM_SUCCESS) {
+ error_setg(errp, "Unable to authorize user '%s': %s",
+ identity, pam_strerror(pamh, ret));
+ return false;
+ }
+
+ return true;
+}
+
+
+static void
+qauthz_pam_prop_set_service(Object *obj,
+ const char *service,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZPAM *pauthz = QAUTHZ_PAM(obj);
+
+ g_free(pauthz->service);
+ pauthz->service = g_strdup(service);
+}
+
+
+static char *
+qauthz_pam_prop_get_service(Object *obj,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZPAM *pauthz = QAUTHZ_PAM(obj);
+
+ return g_strdup(pauthz->service);
+}
+
+
+static void
+qauthz_pam_complete(UserCreatable *uc, Error **errp)
+{
+}
+
+
+static void
+qauthz_pam_finalize(Object *obj)
+{
+ QAuthZPAM *pauthz = QAUTHZ_PAM(obj);
+
+ g_free(pauthz->service);
+}
+
+
+static void
+qauthz_pam_class_init(ObjectClass *oc, void *data)
+{
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+ QAuthZClass *authz = QAUTHZ_CLASS(oc);
+
+ ucc->complete = qauthz_pam_complete;
+ authz->is_allowed = qauthz_pam_is_allowed;
+
+ object_class_property_add_str(oc, "service",
+ qauthz_pam_prop_get_service,
+ qauthz_pam_prop_set_service,
+ NULL);
+}
+
+
+QAuthZPAM *qauthz_pam_new(const char *id,
+ const char *service,
+ Error **errp)
+{
+ return QAUTHZ_PAM(
+ object_new_with_props(TYPE_QAUTHZ_PAM,
+ object_get_objects_root(),
+ id, errp,
+ "service", service,
+ NULL));
+}
+
+
+static const TypeInfo qauthz_pam_info = {
+ .parent = TYPE_QAUTHZ,
+ .name = TYPE_QAUTHZ_PAM,
+ .instance_size = sizeof(QAuthZPAM),
+ .instance_finalize = qauthz_pam_finalize,
+ .class_size = sizeof(QAuthZPAMClass),
+ .class_init = qauthz_pam_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+
+static void
+qauthz_pam_register_types(void)
+{
+ type_register_static(&qauthz_pam_info);
+}
+
+
+type_init(qauthz_pam_register_types);
--- /dev/null
+/*
+ * QEMU simple authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "authz/simple.h"
+#include "authz/trace.h"
+#include "qom/object_interfaces.h"
+
+static bool qauthz_simple_is_allowed(QAuthZ *authz,
+ const char *identity,
+ Error **errp)
+{
+ QAuthZSimple *sauthz = QAUTHZ_SIMPLE(authz);
+
+ trace_qauthz_simple_is_allowed(authz, sauthz->identity, identity);
+ return g_str_equal(identity, sauthz->identity);
+}
+
+static void
+qauthz_simple_prop_set_identity(Object *obj,
+ const char *value,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZSimple *sauthz = QAUTHZ_SIMPLE(obj);
+
+ g_free(sauthz->identity);
+ sauthz->identity = g_strdup(value);
+}
+
+
+static char *
+qauthz_simple_prop_get_identity(Object *obj,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZSimple *sauthz = QAUTHZ_SIMPLE(obj);
+
+ return g_strdup(sauthz->identity);
+}
+
+
+static void
+qauthz_simple_finalize(Object *obj)
+{
+ QAuthZSimple *sauthz = QAUTHZ_SIMPLE(obj);
+
+ g_free(sauthz->identity);
+}
+
+
+static void
+qauthz_simple_class_init(ObjectClass *oc, void *data)
+{
+ QAuthZClass *authz = QAUTHZ_CLASS(oc);
+
+ authz->is_allowed = qauthz_simple_is_allowed;
+
+ object_class_property_add_str(oc, "identity",
+ qauthz_simple_prop_get_identity,
+ qauthz_simple_prop_set_identity,
+ NULL);
+}
+
+
+QAuthZSimple *qauthz_simple_new(const char *id,
+ const char *identity,
+ Error **errp)
+{
+ return QAUTHZ_SIMPLE(
+ object_new_with_props(TYPE_QAUTHZ_SIMPLE,
+ object_get_objects_root(),
+ id, errp,
+ "identity", identity,
+ NULL));
+}
+
+
+static const TypeInfo qauthz_simple_info = {
+ .parent = TYPE_QAUTHZ,
+ .name = TYPE_QAUTHZ_SIMPLE,
+ .instance_size = sizeof(QAuthZSimple),
+ .instance_finalize = qauthz_simple_finalize,
+ .class_size = sizeof(QAuthZSimpleClass),
+ .class_init = qauthz_simple_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+
+static void
+qauthz_simple_register_types(void)
+{
+ type_register_static(&qauthz_simple_info);
+}
+
+
+type_init(qauthz_simple_register_types);
--- /dev/null
+# See docs/devel/tracing.txt for syntax documentation.
+
+# authz/base.c
+qauthz_is_allowed(void *authz, const char *identity, bool allowed) "AuthZ %p check identity=%s allowed=%d"
+
+# auth/simple.c
+qauthz_simple_is_allowed(void *authz, const char *wantidentity, const char *gotidentity) "AuthZ simple %p check want identity=%s got identity=%s"
+
+# auth/list.c
+qauthz_list_check_rule(void *authz, const char *identity, const char *rule, int format, int policy) "AuthZ list %p check rule=%s identity=%s format=%d policy=%d"
+qauthz_list_default_policy(void *authz, const char *identity, int policy) "AuthZ list %p default identity=%s policy=%d"
+
+# auth/listfile.c
+qauthz_list_file_load(void *authz, const char *filename) "AuthZ file %p load filename=%s"
+qauthz_list_file_refresh(void *authz, const char *filename, int success) "AuthZ file %p load filename=%s success=%d"
+
+# auth/pam.c
+qauthz_pam_check(void *authz, const char *identity, const char *service) "AuthZ PAM %p identity=%s service=%s"
#endif
}
-/* if filename is absolute, just copy it to dest. Otherwise, build a
+/* if filename is absolute, just return its duplicate. Otherwise, build a
path to it by considering it is relative to base_path. URL are
supported. */
-void path_combine(char *dest, int dest_size,
- const char *base_path,
- const char *filename)
+char *path_combine(const char *base_path, const char *filename)
{
+ const char *protocol_stripped = NULL;
const char *p, *p1;
+ char *result;
int len;
- if (dest_size <= 0)
- return;
if (path_is_absolute(filename)) {
- pstrcpy(dest, dest_size, filename);
- } else {
- const char *protocol_stripped = NULL;
+ return g_strdup(filename);
+ }
- if (path_has_protocol(base_path)) {
- protocol_stripped = strchr(base_path, ':');
- if (protocol_stripped) {
- protocol_stripped++;
- }
+ if (path_has_protocol(base_path)) {
+ protocol_stripped = strchr(base_path, ':');
+ if (protocol_stripped) {
+ protocol_stripped++;
}
- p = protocol_stripped ?: base_path;
+ }
+ p = protocol_stripped ?: base_path;
- p1 = strrchr(base_path, '/');
+ p1 = strrchr(base_path, '/');
#ifdef _WIN32
- {
- const char *p2;
- p2 = strrchr(base_path, '\\');
- if (!p1 || p2 > p1)
- p1 = p2;
+ {
+ const char *p2;
+ p2 = strrchr(base_path, '\\');
+ if (!p1 || p2 > p1) {
+ p1 = p2;
}
+ }
#endif
- if (p1)
- p1++;
- else
- p1 = base_path;
- if (p1 > p)
- p = p1;
- len = p - base_path;
- if (len > dest_size - 1)
- len = dest_size - 1;
- memcpy(dest, base_path, len);
- dest[len] = '\0';
- pstrcat(dest, dest_size, filename);
+ if (p1) {
+ p1++;
+ } else {
+ p1 = base_path;
}
+ if (p1 > p) {
+ p = p1;
+ }
+ len = p - base_path;
+
+ result = g_malloc(len + strlen(filename) + 1);
+ memcpy(result, base_path, len);
+ strcpy(result + len, filename);
+
+ return result;
}
/*
return -EACCES;
}
-void bdrv_get_full_backing_filename_from_filename(const char *backed,
- const char *backing,
- char *dest, size_t sz,
- Error **errp)
+/*
+ * If @backing is empty, this function returns NULL without setting
+ * @errp. In all other cases, NULL will only be returned with @errp
+ * set.
+ *
+ * Therefore, a return value of NULL without @errp set means that
+ * there is no backing file; if @errp is set, there is one but its
+ * absolute filename cannot be generated.
+ */
+char *bdrv_get_full_backing_filename_from_filename(const char *backed,
+ const char *backing,
+ Error **errp)
{
- if (backing[0] == '\0' || path_has_protocol(backing) ||
- path_is_absolute(backing))
- {
- pstrcpy(dest, sz, backing);
+ if (backing[0] == '\0') {
+ return NULL;
+ } else if (path_has_protocol(backing) || path_is_absolute(backing)) {
+ return g_strdup(backing);
} else if (backed[0] == '\0' || strstart(backed, "json:", NULL)) {
error_setg(errp, "Cannot use relative backing file names for '%s'",
backed);
+ return NULL;
} else {
- path_combine(dest, sz, backed, backing);
+ return path_combine(backed, backing);
}
}
-void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,
- Error **errp)
+/*
+ * If @filename is empty or NULL, this function returns NULL without
+ * setting @errp. In all other cases, NULL will only be returned with
+ * @errp set.
+ */
+static char *bdrv_make_absolute_filename(BlockDriverState *relative_to,
+ const char *filename, Error **errp)
{
- char *backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
+ char *dir, *full_name;
- bdrv_get_full_backing_filename_from_filename(backed, bs->backing_file,
- dest, sz, errp);
+ if (!filename || filename[0] == '\0') {
+ return NULL;
+ } else if (path_has_protocol(filename) || path_is_absolute(filename)) {
+ return g_strdup(filename);
+ }
+
+ dir = bdrv_dirname(relative_to, errp);
+ if (!dir) {
+ return NULL;
+ }
+
+ full_name = g_strconcat(dir, filename, NULL);
+ g_free(dir);
+ return full_name;
+}
+
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
+{
+ return bdrv_make_absolute_filename(bs, bs->backing_file, errp);
}
void bdrv_register(BlockDriver *bdrv)
"node is used as backing hd of '%s'",
bdrv_get_device_or_node_name(parent));
+ bdrv_refresh_filename(backing_hd);
+
parent->open_flags &= ~BDRV_O_NO_BACKING;
pstrcpy(parent->backing_file, sizeof(parent->backing_file),
backing_hd->filename);
}
if (file != NULL) {
+ bdrv_refresh_filename(blk_bs(file));
filename = blk_bs(file)->filename;
} else {
/*
ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children, errp);
g_slist_free(ignore_children);
- return ret;
+ if (ret < 0) {
+ return ret;
+ }
+
+ if (!c->has_backup_perm) {
+ c->has_backup_perm = true;
+ c->backup_perm = c->perm;
+ c->backup_shared_perm = c->shared_perm;
+ }
+ /*
+ * Note: it's OK if c->has_backup_perm was already set, as we can find the
+ * same child twice during check_perm procedure
+ */
+
+ c->perm = perm;
+ c->shared_perm = shared;
+
+ return 0;
}
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared)
{
uint64_t cumulative_perms, cumulative_shared_perms;
+ c->has_backup_perm = false;
+
c->perm = perm;
c->shared_perm = shared;
static void bdrv_child_abort_perm_update(BdrvChild *c)
{
+ if (c->has_backup_perm) {
+ c->perm = c->backup_perm;
+ c->shared_perm = c->backup_shared_perm;
+ c->has_backup_perm = false;
+ }
+
bdrv_abort_perm_update(c->bs);
}
bdrv_unref(backing_hd);
}
- bdrv_refresh_filename(bs);
-
out:
bdrv_refresh_limits(bs, NULL);
}
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
const char *bdref_key, Error **errp)
{
- char *backing_filename = g_malloc0(PATH_MAX);
+ char *backing_filename = NULL;
char *bdref_key_dot;
const char *reference = NULL;
int ret = 0;
+ bool implicit_backing = false;
BlockDriverState *backing_hd;
QDict *options;
QDict *tmp_parent_options = NULL;
*/
reference = qdict_get_try_str(parent_options, bdref_key);
if (reference || qdict_haskey(options, "file.filename")) {
- backing_filename[0] = '\0';
+ /* keep backing_filename NULL */
} else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
qobject_unref(options);
goto free_exit;
} else {
- bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX,
- &local_err);
+ if (qdict_size(options) == 0) {
+ /* If the user specifies options that do not modify the
+ * backing file's behavior, we might still consider it the
+ * implicit backing file. But it's easier this way, and
+ * just specifying some of the backing BDS's options is
+ * only possible with -drive anyway (otherwise the QAPI
+ * schema forces the user to specify everything). */
+ implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
+ }
+
+ backing_filename = bdrv_get_full_backing_filename(bs, &local_err);
if (local_err) {
ret = -EINVAL;
error_propagate(errp, local_err);
qdict_put_str(options, "driver", bs->backing_format);
}
- backing_hd = bdrv_open_inherit(*backing_filename ? backing_filename : NULL,
- reference, options, 0, bs, &child_backing,
- errp);
+ backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
+ &child_backing, errp);
if (!backing_hd) {
bs->open_flags |= BDRV_O_NO_BACKING;
error_prepend(errp, "Could not open backing file: ");
}
bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs));
+ if (implicit_backing) {
+ bdrv_refresh_filename(backing_hd);
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
+ backing_hd->filename);
+ }
+
/* Hook up the backing file link; drop our reference, bs owns the
* backing_hd reference now */
bdrv_set_backing_hd(bs, backing_hd, &local_err);
g_free(child_key_dot);
}
- bdrv_refresh_filename(bs);
-
/* Check if any unknown options were used */
if (qdict_size(options) != 0) {
const QDictEntry *entry = qdict_first(options);
if (local_err != NULL) {
error_propagate(errp, local_err);
} else {
+ bdrv_refresh_filename(reopen_state->bs);
error_setg(errp, "failed while preparing to reopen image '%s'",
reopen_state->bs->filename);
}
static bool should_update_child(BdrvChild *c, BlockDriverState *to)
{
- BdrvChild *to_c;
+ GQueue *queue;
+ GHashTable *found;
+ bool ret;
if (c->role->stay_at_node) {
return false;
* if A is a child of B, that means we cannot replace A by B there
* because that would create a loop. Silently detaching A from B
* is also not really an option. So overall just leaving A in
- * place there is the most sensible choice. */
- QLIST_FOREACH(to_c, &to->children, next) {
- if (to_c == c) {
- return false;
+ * place there is the most sensible choice.
+ *
+ * We would also create a loop in any cases where @c is only
+ * indirectly referenced by @to. Prevent this by returning false
+ * if @c is found (by breadth-first search) anywhere in the whole
+ * subtree of @to.
+ */
+
+ ret = true;
+ found = g_hash_table_new(NULL, NULL);
+ g_hash_table_add(found, to);
+ queue = g_queue_new();
+ g_queue_push_tail(queue, to);
+
+ while (!g_queue_is_empty(queue)) {
+ BlockDriverState *v = g_queue_pop_head(queue);
+ BdrvChild *c2;
+
+ QLIST_FOREACH(c2, &v->children, next) {
+ if (c2 == c) {
+ ret = false;
+ break;
+ }
+
+ if (g_hash_table_contains(found, c2->bs)) {
+ continue;
+ }
+
+ g_queue_push_tail(queue, c2->bs);
+ g_hash_table_add(found, c2->bs);
}
}
- return true;
+ g_queue_free(queue);
+ g_hash_table_destroy(found);
+
+ return ret;
}
void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
if (ret == 0) {
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
+ backing_file ?: "");
}
return ret;
}
/* success - we can delete the intermediate states, and link top->base */
/* TODO Check graph modification op blockers (BLK_PERM_GRAPH_MOD) once
* we've figured out how they should work. */
- backing_file_str = backing_file_str ? backing_file_str : base->filename;
+ if (!backing_file_str) {
+ bdrv_refresh_filename(base);
+ backing_file_str = base->filename;
+ }
QLIST_FOREACH_SAFE(c, &top->parents, next_parent, next) {
/* Check whether we are allowed to switch c from top to base */
return bs->supported_zero_flags & BDRV_REQ_MAY_UNMAP;
}
-const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
-{
- if (bs->backing && bs->backing->bs->encrypted)
- return bs->backing_file;
- else if (bs->encrypted)
- return bs->filename;
- else
- return NULL;
-}
-
void bdrv_get_backing_filename(BlockDriverState *bs,
char *filename, int filename_size)
{
return drv->bdrv_get_info(bs, bdi);
}
-ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs)
+ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs,
+ Error **errp)
{
BlockDriver *drv = bs->drv;
if (drv && drv->bdrv_get_specific_info) {
- return drv->bdrv_get_specific_info(bs);
+ return drv->bdrv_get_specific_info(bs, errp);
}
return NULL;
}
int is_protocol = 0;
BlockDriverState *curr_bs = NULL;
BlockDriverState *retval = NULL;
- Error *local_error = NULL;
if (!bs || !bs->drv || !backing_file) {
return NULL;
filename_full = g_malloc(PATH_MAX);
backing_file_full = g_malloc(PATH_MAX);
- filename_tmp = g_malloc(PATH_MAX);
is_protocol = path_has_protocol(backing_file);
/* If either of the filename paths is actually a protocol, then
* compare unmodified paths; otherwise make paths relative */
if (is_protocol || path_has_protocol(curr_bs->backing_file)) {
+ char *backing_file_full_ret;
+
if (strcmp(backing_file, curr_bs->backing_file) == 0) {
retval = curr_bs->backing->bs;
break;
}
/* Also check against the full backing filename for the image */
- bdrv_get_full_backing_filename(curr_bs, backing_file_full, PATH_MAX,
- &local_error);
- if (local_error == NULL) {
- if (strcmp(backing_file, backing_file_full) == 0) {
+ backing_file_full_ret = bdrv_get_full_backing_filename(curr_bs,
+ NULL);
+ if (backing_file_full_ret) {
+ bool equal = strcmp(backing_file, backing_file_full_ret) == 0;
+ g_free(backing_file_full_ret);
+ if (equal) {
retval = curr_bs->backing->bs;
break;
}
- } else {
- error_free(local_error);
- local_error = NULL;
}
} else {
/* If not an absolute filename path, make it relative to the current
* image's filename path */
- path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
- backing_file);
-
- /* We are going to compare absolute pathnames */
- if (!realpath(filename_tmp, filename_full)) {
+ filename_tmp = bdrv_make_absolute_filename(curr_bs, backing_file,
+ NULL);
+ /* We are going to compare canonicalized absolute pathnames */
+ if (!filename_tmp || !realpath(filename_tmp, filename_full)) {
+ g_free(filename_tmp);
continue;
}
+ g_free(filename_tmp);
/* We need to make sure the backing filename we are comparing against
* is relative to the current image filename (or absolute) */
- path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
- curr_bs->backing_file);
-
- if (!realpath(filename_tmp, backing_file_full)) {
+ filename_tmp = bdrv_get_full_backing_filename(curr_bs, NULL);
+ if (!filename_tmp || !realpath(filename_tmp, backing_file_full)) {
+ g_free(filename_tmp);
continue;
}
+ g_free(filename_tmp);
if (strcmp(backing_file_full, filename_full) == 0) {
retval = curr_bs->backing->bs;
g_free(filename_full);
g_free(backing_file_full);
- g_free(filename_tmp);
return retval;
}
size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, img_size);
if (backing_file && !(flags & BDRV_O_NO_BACKING)) {
BlockDriverState *bs;
- char *full_backing = g_new0(char, PATH_MAX);
+ char *full_backing;
int back_flags;
QDict *backing_options = NULL;
- bdrv_get_full_backing_filename_from_filename(filename, backing_file,
- full_backing, PATH_MAX,
- &local_err);
+ full_backing =
+ bdrv_get_full_backing_filename_from_filename(filename, backing_file,
+ &local_err);
if (local_err) {
- g_free(full_backing);
goto out;
}
+ assert(full_backing);
/* backing files always opened read-only */
back_flags = flags;
bdrv_detach_aio_context(child->bs);
}
+ if (bs->quiesce_counter) {
+ aio_enable_external(bs->aio_context);
+ }
bs->aio_context = NULL;
}
return;
}
+ if (bs->quiesce_counter) {
+ aio_disable_external(new_context);
+ }
+
bs->aio_context = new_context;
QLIST_FOREACH(child, &bs->children, next) {
bs->walking_aio_notifiers = false;
}
+/* The caller must own the AioContext lock for the old AioContext of bs, but it
+ * must not own the AioContext lock for new_context (unless new_context is
+ * the same as the current context of bs). */
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
{
- AioContext *ctx = bdrv_get_aio_context(bs);
-
- aio_disable_external(ctx);
- bdrv_parent_drained_begin(bs, NULL, false);
- bdrv_drain(bs); /* ensure there are no in-flight requests */
-
- while (aio_poll(ctx, false)) {
- /* wait for all bottom halves to execute */
+ if (bdrv_get_aio_context(bs) == new_context) {
+ return;
}
+ bdrv_drained_begin(bs);
bdrv_detach_aio_context(bs);
/* This function executes in the old AioContext so acquire the new one in
*/
aio_context_acquire(new_context);
bdrv_attach_aio_context(bs, new_context);
- bdrv_parent_drained_end(bs, NULL, false);
- aio_enable_external(ctx);
+ bdrv_drained_end(bs);
aio_context_release(new_context);
}
return to_replace_bs;
}
-static bool append_open_options(QDict *d, BlockDriverState *bs)
+/**
+ * Iterates through the list of runtime option keys that are said to
+ * be "strong" for a BDS. An option is called "strong" if it changes
+ * a BDS's data. For example, the null block driver's "size" and
+ * "read-zeroes" options are strong, but its "latency-ns" option is
+ * not.
+ *
+ * If a key returned by this function ends with a dot, all options
+ * starting with that prefix are strong.
+ */
+static const char *const *strong_options(BlockDriverState *bs,
+ const char *const *curopt)
+{
+ static const char *const global_options[] = {
+ "driver", "filename", NULL
+ };
+
+ if (!curopt) {
+ return &global_options[0];
+ }
+
+ curopt++;
+ if (curopt == &global_options[ARRAY_SIZE(global_options) - 1] && bs->drv) {
+ curopt = bs->drv->strong_runtime_opts;
+ }
+
+ return (curopt && *curopt) ? curopt : NULL;
+}
+
+/**
+ * Copies all strong runtime options from bs->options to the given
+ * QDict. The set of strong option keys is determined by invoking
+ * strong_options().
+ *
+ * Returns true iff any strong option was present in bs->options (and
+ * thus copied to the target QDict) with the exception of "filename"
+ * and "driver". The caller is expected to use this value to decide
+ * whether the existence of strong options prevents the generation of
+ * a plain filename.
+ */
+static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
{
- const QDictEntry *entry;
- QemuOptDesc *desc;
bool found_any = false;
+ const char *const *option_name = NULL;
- for (entry = qdict_first(bs->options); entry;
- entry = qdict_next(bs->options, entry))
- {
- /* Exclude all non-driver-specific options */
- for (desc = bdrv_runtime_opts.desc; desc->name; desc++) {
- if (!strcmp(qdict_entry_key(entry), desc->name)) {
- break;
+ if (!bs->drv) {
+ return false;
+ }
+
+ while ((option_name = strong_options(bs, option_name))) {
+ bool option_given = false;
+
+ assert(strlen(*option_name) > 0);
+ if ((*option_name)[strlen(*option_name) - 1] != '.') {
+ QObject *entry = qdict_get(bs->options, *option_name);
+ if (!entry) {
+ continue;
+ }
+
+ qdict_put_obj(d, *option_name, qobject_ref(entry));
+ option_given = true;
+ } else {
+ const QDictEntry *entry;
+ for (entry = qdict_first(bs->options); entry;
+ entry = qdict_next(bs->options, entry))
+ {
+ if (strstart(qdict_entry_key(entry), *option_name, NULL)) {
+ qdict_put_obj(d, qdict_entry_key(entry),
+ qobject_ref(qdict_entry_value(entry)));
+ option_given = true;
+ }
}
}
- if (desc->name) {
- continue;
+
+ /* While "driver" and "filename" need to be included in a JSON filename,
+ * their existence does not prohibit generation of a plain filename. */
+ if (!found_any && option_given &&
+ strcmp(*option_name, "driver") && strcmp(*option_name, "filename"))
+ {
+ found_any = true;
}
+ }
- qdict_put_obj(d, qdict_entry_key(entry),
- qobject_ref(qdict_entry_value(entry)));
- found_any = true;
+ if (!qdict_haskey(d, "driver")) {
+ /* Drivers created with bdrv_new_open_driver() may not have a
+ * @driver option. Add it here. */
+ qdict_put_str(d, "driver", bs->drv->format_name);
}
return found_any;
}
+/* Note: This function may return false positives; it may return true
+ * even if opening the backing file specified by bs's image header
+ * would result in exactly bs->backing. */
+static bool bdrv_backing_overridden(BlockDriverState *bs)
+{
+ if (bs->backing) {
+ return strcmp(bs->auto_backing_file,
+ bs->backing->bs->filename);
+ } else {
+ /* No backing BDS, so if the image header reports any backing
+ * file, it must have been suppressed */
+ return bs->auto_backing_file[0] != '\0';
+ }
+}
+
/* Updates the following BDS fields:
* - exact_filename: A filename which may be used for opening a block device
* which (mostly) equals the given BDS (even without any
void bdrv_refresh_filename(BlockDriverState *bs)
{
BlockDriver *drv = bs->drv;
+ BdrvChild *child;
QDict *opts;
+ bool backing_overridden;
+ bool generate_json_filename; /* Whether our default implementation should
+ fill exact_filename (false) or not (true) */
if (!drv) {
return;
}
- /* This BDS's file name will most probably depend on its file's name, so
- * refresh that first */
- if (bs->file) {
- bdrv_refresh_filename(bs->file->bs);
+ /* This BDS's file name may depend on any of its children's file names, so
+ * refresh those first */
+ QLIST_FOREACH(child, &bs->children, next) {
+ bdrv_refresh_filename(child->bs);
+ }
+
+ if (bs->implicit) {
+ /* For implicit nodes, just copy everything from the single child */
+ child = QLIST_FIRST(&bs->children);
+ assert(QLIST_NEXT(child, next) == NULL);
+
+ pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
+ child->bs->exact_filename);
+ pstrcpy(bs->filename, sizeof(bs->filename), child->bs->filename);
+
+ bs->full_open_options = qobject_ref(child->bs->full_open_options);
+
+ return;
+ }
+
+ backing_overridden = bdrv_backing_overridden(bs);
+
+ if (bs->open_flags & BDRV_O_NO_IO) {
+ /* Without I/O, the backing file does not change anything.
+ * Therefore, in such a case (primarily qemu-img), we can
+ * pretend the backing file has not been overridden even if
+ * it technically has been. */
+ backing_overridden = false;
}
+ /* Gather the options QDict */
+ opts = qdict_new();
+ generate_json_filename = append_strong_runtime_options(opts, bs);
+ generate_json_filename |= backing_overridden;
+
+ if (drv->bdrv_gather_child_options) {
+ /* Some block drivers may not want to present all of their children's
+ * options, or name them differently from BdrvChild.name */
+ drv->bdrv_gather_child_options(bs, opts, backing_overridden);
+ } else {
+ QLIST_FOREACH(child, &bs->children, next) {
+ if (child->role == &child_backing && !backing_overridden) {
+ /* We can skip the backing BDS if it has not been overridden */
+ continue;
+ }
+
+ qdict_put(opts, child->name,
+ qobject_ref(child->bs->full_open_options));
+ }
+
+ if (backing_overridden && !bs->backing) {
+ /* Force no backing file */
+ qdict_put_null(opts, "backing");
+ }
+ }
+
+ qobject_unref(bs->full_open_options);
+ bs->full_open_options = opts;
+
if (drv->bdrv_refresh_filename) {
/* Obsolete information is of no use here, so drop the old file name
* information before refreshing it */
bs->exact_filename[0] = '\0';
- if (bs->full_open_options) {
- qobject_unref(bs->full_open_options);
- bs->full_open_options = NULL;
- }
- opts = qdict_new();
- append_open_options(opts, bs);
- drv->bdrv_refresh_filename(bs, opts);
- qobject_unref(opts);
+ drv->bdrv_refresh_filename(bs);
} else if (bs->file) {
/* Try to reconstruct valid information from the underlying file */
- bool has_open_options;
bs->exact_filename[0] = '\0';
- if (bs->full_open_options) {
- qobject_unref(bs->full_open_options);
- bs->full_open_options = NULL;
- }
-
- opts = qdict_new();
- has_open_options = append_open_options(opts, bs);
- /* If no specific options have been given for this BDS, the filename of
- * the underlying file should suffice for this one as well */
- if (bs->file->bs->exact_filename[0] && !has_open_options) {
+ /*
+ * We can use the underlying file's filename if:
+ * - it has a filename,
+ * - the file is a protocol BDS, and
+ * - opening that file (as this BDS's format) will automatically create
+ * the BDS tree we have right now, that is:
+ * - the user did not significantly change this BDS's behavior with
+ * some explicit (strong) options
+ * - no non-file child of this BDS has been overridden by the user
+ * Both of these conditions are represented by generate_json_filename.
+ */
+ if (bs->file->bs->exact_filename[0] &&
+ bs->file->bs->drv->bdrv_file_open &&
+ !generate_json_filename)
+ {
strcpy(bs->exact_filename, bs->file->bs->exact_filename);
}
- /* Reconstructing the full options QDict is simple for most format block
- * drivers, as long as the full options are known for the underlying
- * file BDS. The full options QDict of that file BDS should somehow
- * contain a representation of the filename, therefore the following
- * suffices without querying the (exact_)filename of this BDS. */
- if (bs->file->bs->full_open_options) {
- qdict_put_str(opts, "driver", drv->format_name);
- qdict_put(opts, "file",
- qobject_ref(bs->file->bs->full_open_options));
-
- bs->full_open_options = opts;
- } else {
- qobject_unref(opts);
- }
- } else if (!bs->full_open_options && qdict_size(bs->options)) {
- /* There is no underlying file BDS (at least referenced by BDS.file),
- * so the full options QDict should be equal to the options given
- * specifically for this block device when it was opened (plus the
- * driver specification).
- * Because those options don't change, there is no need to update
- * full_open_options when it's already set. */
-
- opts = qdict_new();
- append_open_options(opts, bs);
- qdict_put_str(opts, "driver", drv->format_name);
-
- if (bs->exact_filename[0]) {
- /* This may not work for all block protocol drivers (some may
- * require this filename to be parsed), but we have to find some
- * default solution here, so just include it. If some block driver
- * does not support pure options without any filename at all or
- * needs some special format of the options QDict, it needs to
- * implement the driver-specific bdrv_refresh_filename() function.
- */
- qdict_put_str(opts, "filename", bs->exact_filename);
- }
-
- bs->full_open_options = opts;
}
if (bs->exact_filename[0]) {
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
- } else if (bs->full_open_options) {
+ } else {
QString *json = qobject_to_json(QOBJECT(bs->full_open_options));
snprintf(bs->filename, sizeof(bs->filename), "json:%s",
qstring_get_str(json));
}
}
+char *bdrv_dirname(BlockDriverState *bs, Error **errp)
+{
+ BlockDriver *drv = bs->drv;
+
+ if (!drv) {
+ error_setg(errp, "Node '%s' is ejected", bs->node_name);
+ return NULL;
+ }
+
+ if (drv->bdrv_dirname) {
+ return drv->bdrv_dirname(bs, errp);
+ }
+
+ if (bs->file) {
+ return bdrv_dirname(bs->file->bs, errp);
+ }
+
+ bdrv_refresh_filename(bs);
+ if (bs->exact_filename[0] != '\0') {
+ return path_combine(bs->exact_filename, "");
+ }
+
+ error_setg(errp, "Cannot generate a base directory for %s nodes",
+ drv->format_name);
+ return NULL;
+}
+
/*
* Hot add/remove a BDS's child. So the user can take a child offline when
* it is broken and take a new child online
void **bounce_buffer)
{
int ret;
- struct iovec iov;
QEMUIOVector qiov;
BlockBackend *blk = job->common.blk;
int nbytes;
if (!*bounce_buffer) {
*bounce_buffer = blk_blockalign(blk, job->cluster_size);
}
- iov.iov_base = *bounce_buffer;
- iov.iov_len = nbytes;
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, *bounce_buffer, nbytes);
ret = blk_co_preadv(blk, start, qiov.size, &qiov, read_flags);
if (ret < 0) {
return bdrv_getlength(bs->file->bs);
}
-static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
+static void blkdebug_refresh_filename(BlockDriverState *bs)
{
BDRVBlkdebugState *s = bs->opaque;
- QDict *opts;
const QDictEntry *e;
- bool force_json = false;
-
- for (e = qdict_first(options); e; e = qdict_next(options, e)) {
- if (strcmp(qdict_entry_key(e), "config") &&
- strcmp(qdict_entry_key(e), "x-image"))
- {
- force_json = true;
- break;
- }
- }
+ int ret;
- if (force_json && !bs->file->bs->full_open_options) {
- /* The config file cannot be recreated, so creating a plain filename
- * is impossible */
+ if (!bs->file->bs->exact_filename[0]) {
return;
}
- if (!force_json && bs->file->bs->exact_filename[0]) {
- int ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
- "blkdebug:%s:%s", s->config_file ?: "",
- bs->file->bs->exact_filename);
- if (ret >= sizeof(bs->exact_filename)) {
- /* An overflow makes the filename unusable, so do not report any */
- bs->exact_filename[0] = 0;
+ for (e = qdict_first(bs->full_open_options); e;
+ e = qdict_next(bs->full_open_options, e))
+ {
+ /* Real child options are under "image", but "x-image" may
+ * contain a filename */
+ if (strcmp(qdict_entry_key(e), "config") &&
+ strcmp(qdict_entry_key(e), "image") &&
+ strcmp(qdict_entry_key(e), "x-image") &&
+ strcmp(qdict_entry_key(e), "driver"))
+ {
+ return;
}
}
- opts = qdict_new();
- qdict_put_str(opts, "driver", "blkdebug");
-
- qdict_put(opts, "image", qobject_ref(bs->file->bs->full_open_options));
-
- for (e = qdict_first(options); e; e = qdict_next(options, e)) {
- if (strcmp(qdict_entry_key(e), "x-image")) {
- qdict_put_obj(opts, qdict_entry_key(e),
- qobject_ref(qdict_entry_value(e)));
- }
+ ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
+ "blkdebug:%s:%s",
+ s->config_file ?: "", bs->file->bs->exact_filename);
+ if (ret >= sizeof(bs->exact_filename)) {
+ /* An overflow makes the filename unusable, so do not report any */
+ bs->exact_filename[0] = 0;
}
-
- bs->full_open_options = opts;
}
static void blkdebug_refresh_limits(BlockDriverState *bs, Error **errp)
return 0;
}
+static const char *const blkdebug_strong_runtime_opts[] = {
+ "config",
+ "inject-error.",
+ "set-state.",
+ "align",
+ "max-transfer",
+ "opt-write-zero",
+ "max-write-zero",
+ "opt-discard",
+ "max-discard",
+
+ NULL
+};
+
static BlockDriver bdrv_blkdebug = {
.format_name = "blkdebug",
.protocol_name = "blkdebug",
= blkdebug_debug_remove_breakpoint,
.bdrv_debug_resume = blkdebug_debug_resume,
.bdrv_debug_is_suspended = blkdebug_debug_is_suspended,
+
+ .strong_runtime_opts = blkdebug_strong_runtime_opts,
};
static void bdrv_blkdebug_init(void)
return bdrv_getlength(bs->file->bs);
}
-static void blk_log_writes_refresh_filename(BlockDriverState *bs,
- QDict *options)
-{
- BDRVBlkLogWritesState *s = bs->opaque;
-
- /* bs->file->bs has already been refreshed */
- bdrv_refresh_filename(s->log_file->bs);
-
- if (bs->file->bs->full_open_options
- && s->log_file->bs->full_open_options)
- {
- QDict *opts = qdict_new();
- qdict_put_str(opts, "driver", "blklogwrites");
-
- qobject_ref(bs->file->bs->full_open_options);
- qdict_put(opts, "file", bs->file->bs->full_open_options);
- qobject_ref(s->log_file->bs->full_open_options);
- qdict_put(opts, "log", s->log_file->bs->full_open_options);
- qdict_put_int(opts, "log-sector-size", s->sectorsize);
-
- bs->full_open_options = opts;
- }
-}
-
static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
const BdrvChildRole *role,
BlockReopenQueue *ro_q,
LOG_DISCARD_FLAG, false);
}
+static const char *const blk_log_writes_strong_runtime_opts[] = {
+ "log-append",
+ "log-sector-size",
+
+ NULL
+};
+
static BlockDriver bdrv_blk_log_writes = {
.format_name = "blklogwrites",
.instance_size = sizeof(BDRVBlkLogWritesState),
.bdrv_open = blk_log_writes_open,
.bdrv_close = blk_log_writes_close,
.bdrv_getlength = blk_log_writes_getlength,
- .bdrv_refresh_filename = blk_log_writes_refresh_filename,
.bdrv_child_perm = blk_log_writes_child_perm,
.bdrv_refresh_limits = blk_log_writes_refresh_limits,
.bdrv_co_block_status = bdrv_co_block_status_from_file,
.is_filter = true,
+ .strong_runtime_opts = blk_log_writes_strong_runtime_opts,
};
static void bdrv_blk_log_writes_init(void)
return bdrv_recurse_is_first_non_filter(s->test_file->bs, candidate);
}
-static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options)
+static void blkverify_refresh_filename(BlockDriverState *bs)
{
BDRVBlkverifyState *s = bs->opaque;
- /* bs->file->bs has already been refreshed */
- bdrv_refresh_filename(s->test_file->bs);
-
- if (bs->file->bs->full_open_options
- && s->test_file->bs->full_open_options)
- {
- QDict *opts = qdict_new();
- qdict_put_str(opts, "driver", "blkverify");
-
- qdict_put(opts, "raw",
- qobject_ref(bs->file->bs->full_open_options));
- qdict_put(opts, "test",
- qobject_ref(s->test_file->bs->full_open_options));
-
- bs->full_open_options = opts;
- }
-
if (bs->file->bs->exact_filename[0]
&& s->test_file->bs->exact_filename[0])
{
}
}
+static char *blkverify_dirname(BlockDriverState *bs, Error **errp)
+{
+ /* In general, there are two BDSs with different dirnames below this one;
+ * so there is no unique dirname we could return (unless both are equal by
+ * chance). Therefore, to be consistent, just always return NULL. */
+ error_setg(errp, "Cannot generate a base directory for blkverify nodes");
+ return NULL;
+}
+
static BlockDriver bdrv_blkverify = {
.format_name = "blkverify",
.protocol_name = "blkverify",
.bdrv_child_perm = bdrv_filter_default_perms,
.bdrv_getlength = blkverify_getlength,
.bdrv_refresh_filename = blkverify_refresh_filename,
+ .bdrv_dirname = blkverify_dirname,
.bdrv_co_preadv = blkverify_co_preadv,
.bdrv_co_pwritev = blkverify_co_pwritev,
int64_t bytes, CoroutineEntry co_entry,
BdrvRequestFlags flags)
{
- QEMUIOVector qiov;
- struct iovec iov;
- BlkRwCo rwco;
-
- iov = (struct iovec) {
- .iov_base = buf,
- .iov_len = bytes,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
-
- rwco = (BlkRwCo) {
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
+ BlkRwCo rwco = {
.blk = blk,
.offset = offset,
.iobuf = &qiov,
return bdrv_make_zero(blk->root, flags);
}
-static void blk_inc_in_flight(BlockBackend *blk)
+void blk_inc_in_flight(BlockBackend *blk)
{
atomic_inc(&blk->in_flight);
}
-static void blk_dec_in_flight(BlockBackend *blk)
+void blk_dec_in_flight(BlockBackend *blk)
{
atomic_dec(&blk->in_flight);
aio_wait_kick();
void *buf)
{
int ret = 0;
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = buf,
- .iov_len = bytes,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
assert(bytes < SIZE_MAX);
- qemu_iovec_init_external(&qiov, &iov, 1);
ret = blk_co_preadv(bs, offset, qiov.size, &qiov, 0);
if (ret < 0) {
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
}
-static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts)
+static void bdrv_commit_top_refresh_filename(BlockDriverState *bs)
{
- bdrv_refresh_filename(bs->backing->bs);
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
bs->backing->bs->filename);
}
if (s->top) {
blk_unref(s->top);
}
+ job_early_fail(&s->common.job);
+ /* commit_top_bs has to be replaced after deleting the block job,
+ * otherwise this would fail because of lack of permissions. */
if (commit_top_bs) {
bdrv_replace_node(commit_top_bs, top, &error_abort);
}
- job_early_fail(&s->common.job);
}
}
static ImageInfoSpecific *
-block_crypto_get_specific_info_luks(BlockDriverState *bs)
+block_crypto_get_specific_info_luks(BlockDriverState *bs, Error **errp)
{
BlockCrypto *crypto = bs->opaque;
ImageInfoSpecific *spec_info;
QCryptoBlockInfo *info;
- info = qcrypto_block_get_info(crypto->block, NULL);
+ info = qcrypto_block_get_info(crypto->block, errp);
if (!info) {
return NULL;
}
- if (info->format != Q_CRYPTO_BLOCK_FORMAT_LUKS) {
- qapi_free_QCryptoBlockInfo(info);
- return NULL;
- }
+ assert(info->format == Q_CRYPTO_BLOCK_FORMAT_LUKS);
spec_info = g_new(ImageInfoSpecific, 1);
spec_info->type = IMAGE_INFO_SPECIFIC_KIND_LUKS;
return spec_info;
}
+static const char *const block_crypto_strong_runtime_opts[] = {
+ BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
+
+ NULL
+};
+
BlockDriver bdrv_crypto_luks = {
.format_name = "luks",
.instance_size = sizeof(BlockCrypto),
.bdrv_getlength = block_crypto_getlength,
.bdrv_get_info = block_crypto_get_info_luks,
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
+
+ .strong_runtime_opts = block_crypto_strong_runtime_opts,
};
static void block_crypto_init(void)
#define CURL_NUM_STATES 8
#define CURL_NUM_ACB 8
-#define READ_AHEAD_DEFAULT (256 * 1024)
-#define CURL_TIMEOUT_DEFAULT 5
#define CURL_TIMEOUT_MAX 10000
#define CURL_BLOCK_OPT_URL "url"
#define CURL_BLOCK_OPT_PROXY_USERNAME "proxy-username"
#define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret"
+#define CURL_BLOCK_OPT_READAHEAD_DEFAULT (256 * 1024)
+#define CURL_BLOCK_OPT_SSLVERIFY_DEFAULT true
+#define CURL_BLOCK_OPT_TIMEOUT_DEFAULT 5
+
struct BDRVCURLState;
static bool libcurl_initialized;
}
s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD,
- READ_AHEAD_DEFAULT);
+ CURL_BLOCK_OPT_READAHEAD_DEFAULT);
if ((s->readahead_size & 0x1ff) != 0) {
error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512",
s->readahead_size);
}
s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT,
- CURL_TIMEOUT_DEFAULT);
+ CURL_BLOCK_OPT_TIMEOUT_DEFAULT);
if (s->timeout > CURL_TIMEOUT_MAX) {
error_setg(errp, "timeout parameter is too large or negative");
goto out_noclean;
}
- s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true);
+ s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY,
+ CURL_BLOCK_OPT_SSLVERIFY_DEFAULT);
cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE);
cookie_secret = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE_SECRET);
return s->len;
}
+static void curl_refresh_filename(BlockDriverState *bs)
+{
+ BDRVCURLState *s = bs->opaque;
+
+ /* "readahead" and "timeout" do not change the guest-visible data,
+ * so ignore them */
+ if (s->sslverify != CURL_BLOCK_OPT_SSLVERIFY_DEFAULT ||
+ s->cookie || s->username || s->password || s->proxyusername ||
+ s->proxypassword)
+ {
+ return;
+ }
+
+ pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), s->url);
+}
+
+
+static const char *const curl_strong_runtime_opts[] = {
+ CURL_BLOCK_OPT_URL,
+ CURL_BLOCK_OPT_SSLVERIFY,
+ CURL_BLOCK_OPT_COOKIE,
+ CURL_BLOCK_OPT_COOKIE_SECRET,
+ CURL_BLOCK_OPT_USERNAME,
+ CURL_BLOCK_OPT_PASSWORD_SECRET,
+ CURL_BLOCK_OPT_PROXY_USERNAME,
+ CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET,
+
+ NULL
+};
+
static BlockDriver bdrv_http = {
.format_name = "http",
.protocol_name = "http",
.bdrv_detach_aio_context = curl_detach_aio_context,
.bdrv_attach_aio_context = curl_attach_aio_context,
+
+ .bdrv_refresh_filename = curl_refresh_filename,
+ .strong_runtime_opts = curl_strong_runtime_opts,
};
static BlockDriver bdrv_https = {
.bdrv_detach_aio_context = curl_detach_aio_context,
.bdrv_attach_aio_context = curl_attach_aio_context,
+
+ .bdrv_refresh_filename = curl_refresh_filename,
+ .strong_runtime_opts = curl_strong_runtime_opts,
};
static BlockDriver bdrv_ftp = {
.bdrv_detach_aio_context = curl_detach_aio_context,
.bdrv_attach_aio_context = curl_attach_aio_context,
+
+ .bdrv_refresh_filename = curl_refresh_filename,
+ .strong_runtime_opts = curl_strong_runtime_opts,
};
static BlockDriver bdrv_ftps = {
.bdrv_detach_aio_context = curl_detach_aio_context,
.bdrv_attach_aio_context = curl_attach_aio_context,
+
+ .bdrv_refresh_filename = curl_refresh_filename,
+ .strong_runtime_opts = curl_strong_runtime_opts,
};
static void curl_block_init(void)
#include "block/blockjob.h"
/**
- * A BdrvDirtyBitmap can be in three possible states:
- * (1) successor is NULL and disabled is false: full r/w mode
- * (2) successor is NULL and disabled is true: read only mode ("disabled")
- * (3) successor is set: frozen mode.
- * A frozen bitmap cannot be renamed, deleted, anonymized, cleared, set,
- * or enabled. A frozen bitmap can only abdicate() or reclaim().
+ * A BdrvDirtyBitmap can be in four possible user-visible states:
+ * (1) Active: successor is NULL, and disabled is false: full r/w mode
+ * (2) Disabled: successor is NULL, and disabled is true: qualified r/w mode,
+ * guest writes are dropped, but monitor writes are possible,
+ * through commands like merge and clear.
+ * (3) Frozen: successor is not NULL.
+ * A frozen bitmap cannot be renamed, deleted, cleared, set,
+ * enabled, merged to, etc. A frozen bitmap can only abdicate()
+ * or reclaim().
+ * In this state, the anonymous successor bitmap may be either
+ * Active and recording writes from the guest (e.g. backup jobs),
+ * but it can be Disabled and not recording writes.
+ * (4) Locked: Whether Active or Disabled, the user cannot modify this bitmap
+ * in any way from the monitor.
*/
struct BdrvDirtyBitmap {
QemuMutex *mutex;
info->has_name = !!bm->name;
info->name = g_strdup(bm->name);
info->status = bdrv_dirty_bitmap_status(bm);
+ info->persistent = bm->persistent;
entry->value = info;
*plist = entry;
plist = &entry->next;
}
+static const char *const gluster_strong_open_opts[] = {
+ GLUSTER_OPT_VOLUME,
+ GLUSTER_OPT_PATH,
+ GLUSTER_OPT_TYPE,
+ GLUSTER_OPT_SERVER_PATTERN,
+ GLUSTER_OPT_HOST,
+ GLUSTER_OPT_PORT,
+ GLUSTER_OPT_TO,
+ GLUSTER_OPT_IPV4,
+ GLUSTER_OPT_IPV6,
+ GLUSTER_OPT_SOCKET,
+
+ NULL
+};
+
static BlockDriver bdrv_gluster = {
.format_name = "gluster",
.protocol_name = "gluster",
#endif
.bdrv_co_block_status = qemu_gluster_co_block_status,
.create_opts = &qemu_gluster_create_opts,
+ .strong_runtime_opts = gluster_strong_open_opts,
};
static BlockDriver bdrv_gluster_tcp = {
#endif
.bdrv_co_block_status = qemu_gluster_co_block_status,
.create_opts = &qemu_gluster_create_opts,
+ .strong_runtime_opts = gluster_strong_open_opts,
};
static BlockDriver bdrv_gluster_unix = {
#endif
.bdrv_co_block_status = qemu_gluster_co_block_status,
.create_opts = &qemu_gluster_create_opts,
+ .strong_runtime_opts = gluster_strong_open_opts,
};
/* rdma is deprecated (actually never supported for volfile fetch).
#endif
.bdrv_co_block_status = qemu_gluster_co_block_status,
.create_opts = &qemu_gluster_create_opts,
+ .strong_runtime_opts = gluster_strong_open_opts,
};
static void bdrv_gluster_init(void)
static int bdrv_rw_co(BdrvChild *child, int64_t sector_num, uint8_t *buf,
int nb_sectors, bool is_write, BdrvRequestFlags flags)
{
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = (void *)buf,
- .iov_len = nb_sectors * BDRV_SECTOR_SIZE,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf,
+ nb_sectors * BDRV_SECTOR_SIZE);
if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
return -EINVAL;
}
- qemu_iovec_init_external(&qiov, &iov, 1);
return bdrv_prwv_co(child, sector_num << BDRV_SECTOR_BITS,
&qiov, is_write, flags);
}
int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
int bytes, BdrvRequestFlags flags)
{
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = NULL,
- .iov_len = bytes,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, bytes);
- qemu_iovec_init_external(&qiov, &iov, 1);
return bdrv_prwv_co(child, offset, &qiov, true,
BDRV_REQ_ZERO_WRITE | flags);
}
int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int bytes)
{
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = (void *)buf,
- .iov_len = bytes,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
if (bytes < 0) {
return -EINVAL;
}
- qemu_iovec_init_external(&qiov, &iov, 1);
return bdrv_preadv(child, offset, &qiov);
}
int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf, int bytes)
{
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = (void *) buf,
- .iov_len = bytes,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
if (bytes < 0) {
return -EINVAL;
}
- qemu_iovec_init_external(&qiov, &iov, 1);
return bdrv_pwritev(child, offset, &qiov);
}
void *bounce_buffer;
BlockDriver *drv = bs->drv;
- struct iovec iov;
QEMUIOVector local_qiov;
int64_t cluster_offset;
int64_t cluster_bytes;
if (ret <= 0) {
/* Must copy-on-read; use the bounce buffer */
- iov.iov_base = bounce_buffer;
- iov.iov_len = pnum = MIN(pnum, MAX_BOUNCE_BUFFER);
- qemu_iovec_init_external(&local_qiov, &iov, 1);
+ pnum = MIN(pnum, MAX_BOUNCE_BUFFER);
+ qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum);
ret = bdrv_driver_preadv(bs, cluster_offset, pnum,
&local_qiov, 0);
{
BlockDriver *drv = bs->drv;
QEMUIOVector qiov;
- struct iovec iov = {0};
+ void *buf = NULL;
int ret = 0;
bool need_flush = false;
int head = 0;
need_flush = true;
}
num = MIN(num, max_transfer);
- iov.iov_len = num;
- if (iov.iov_base == NULL) {
- iov.iov_base = qemu_try_blockalign(bs, num);
- if (iov.iov_base == NULL) {
+ if (buf == NULL) {
+ buf = qemu_try_blockalign0(bs, num);
+ if (buf == NULL) {
ret = -ENOMEM;
goto fail;
}
- memset(iov.iov_base, 0, num);
}
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, buf, num);
ret = bdrv_driver_pwritev(bs, offset, num, &qiov, write_flags);
* all future requests.
*/
if (num < max_transfer) {
- qemu_vfree(iov.iov_base);
- iov.iov_base = NULL;
+ qemu_vfree(buf);
+ buf = NULL;
}
}
if (ret == 0 && need_flush) {
ret = bdrv_co_flush(bs);
}
- qemu_vfree(iov.iov_base);
+ qemu_vfree(buf);
return ret;
}
BlockDriverState *bs = child->bs;
uint8_t *buf = NULL;
QEMUIOVector local_qiov;
- struct iovec iov;
uint64_t align = bs->bl.request_alignment;
unsigned int head_padding_bytes, tail_padding_bytes;
int ret = 0;
assert(flags & BDRV_REQ_ZERO_WRITE);
if (head_padding_bytes || tail_padding_bytes) {
buf = qemu_blockalign(bs, align);
- iov = (struct iovec) {
- .iov_base = buf,
- .iov_len = align,
- };
- qemu_iovec_init_external(&local_qiov, &iov, 1);
+ qemu_iovec_init_buf(&local_qiov, buf, align);
}
if (head_padding_bytes) {
uint64_t zero_bytes = MIN(bytes, align - head_padding_bytes);
if (offset & (align - 1)) {
QEMUIOVector head_qiov;
- struct iovec head_iov;
mark_request_serialising(&req, align);
wait_serialising_requests(&req);
head_buf = qemu_blockalign(bs, align);
- head_iov = (struct iovec) {
- .iov_base = head_buf,
- .iov_len = align,
- };
- qemu_iovec_init_external(&head_qiov, &head_iov, 1);
+ qemu_iovec_init_buf(&head_qiov, head_buf, align);
bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
ret = bdrv_aligned_preadv(child, &req, offset & ~(align - 1), align,
if ((offset + bytes) & (align - 1)) {
QEMUIOVector tail_qiov;
- struct iovec tail_iov;
size_t tail_bytes;
bool waited;
assert(!waited || !use_local_qiov);
tail_buf = qemu_blockalign(bs, align);
- tail_iov = (struct iovec) {
- .iov_base = tail_buf,
- .iov_len = align,
- };
- qemu_iovec_init_external(&tail_qiov, &tail_iov, 1);
+ qemu_iovec_init_buf(&tail_qiov, tail_buf, align);
bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
ret = bdrv_aligned_preadv(child, &req, (offset + bytes) & ~(align - 1),
int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
int64_t pos, int size)
{
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = (void *) buf,
- .iov_len = size,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, size);
int ret;
- qemu_iovec_init_external(&qiov, &iov, 1);
-
ret = bdrv_writev_vmstate(bs, &qiov, pos);
if (ret < 0) {
return ret;
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
int64_t pos, int size)
{
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = buf,
- .iov_len = size,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, size);
int ret;
- qemu_iovec_init_external(&qiov, &iov, 1);
ret = bdrv_readv_vmstate(bs, &qiov, pos);
if (ret < 0) {
return ret;
}
};
+static const char *const iscsi_strong_runtime_opts[] = {
+ "transport",
+ "portal",
+ "target",
+ "user",
+ "password",
+ "password-secret",
+ "lun",
+ "initiator-name",
+ "header-digest",
+
+ NULL
+};
+
static BlockDriver bdrv_iscsi = {
.format_name = "iscsi",
.protocol_name = "iscsi",
.bdrv_detach_aio_context = iscsi_detach_aio_context,
.bdrv_attach_aio_context = iscsi_attach_aio_context,
+
+ .strong_runtime_opts = iscsi_strong_runtime_opts,
};
#if LIBISCSI_API_VERSION >= (20160603)
.bdrv_detach_aio_context = iscsi_detach_aio_context,
.bdrv_attach_aio_context = iscsi_attach_aio_context,
+
+ .strong_runtime_opts = iscsi_strong_runtime_opts,
};
#endif
NULL, 0);
}
-static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts)
+static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs)
{
if (bs->backing == NULL) {
/* we can be here after failed bdrv_attach_child in
* bdrv_set_backing_hd */
return;
}
- bdrv_refresh_filename(bs->backing->bs);
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
bs->backing->bs->filename);
}
Error *local_err = NULL;
while (!s->quit) {
+ /*
+ * The NBD client can only really be considered idle when it has
+ * yielded from qio_channel_readv_all_eof(), waiting for data. This is
+ * the point where the additional scheduled coroutine entry happens
+ * after nbd_client_attach_aio_context().
+ *
+ * Therefore we keep an additional in_flight reference all the time and
+ * only drop it temporarily here.
+ */
assert(s->reply.handle == 0);
- ret = nbd_receive_reply(s->ioc, &s->reply, &local_err);
+ ret = nbd_receive_reply(s->bs, s->ioc, &s->reply, &local_err);
+
if (local_err) {
trace_nbd_read_reply_entry_fail(ret, error_get_pretty(local_err));
error_free(local_err);
s->quit = true;
nbd_recv_coroutines_wake_all(s);
+ bdrv_dec_in_flight(s->bs);
+
s->connection_co = NULL;
aio_wait_kick();
}
qio_channel_detach_aio_context(QIO_CHANNEL(client->ioc));
}
+static void nbd_client_attach_aio_context_bh(void *opaque)
+{
+ BlockDriverState *bs = opaque;
+ NBDClientSession *client = nbd_get_client_session(bs);
+
+ /* The node is still drained, so we know the coroutine has yielded in
+ * nbd_read_eof(), the only place where bs->in_flight can reach 0, or it is
+ * entered for the first time. Both places are safe for entering the
+ * coroutine.*/
+ qemu_aio_coroutine_enter(bs->aio_context, client->connection_co);
+ bdrv_dec_in_flight(bs);
+}
+
void nbd_client_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
NBDClientSession *client = nbd_get_client_session(bs);
qio_channel_attach_aio_context(QIO_CHANNEL(client->ioc), new_context);
- aio_co_schedule(new_context, client->connection_co);
+
+ bdrv_inc_in_flight(bs);
+
+ /* Need to wait here for the BH to run because the BH must run while the
+ * node is still drained. */
+ aio_wait_bh_oneshot(new_context, nbd_client_attach_aio_context_bh, bs);
}
void nbd_client_close(BlockDriverState *bs)
* kick the reply mechanism. */
qio_channel_set_blocking(QIO_CHANNEL(sioc), false, NULL);
client->connection_co = qemu_coroutine_create(nbd_connection_entry, client);
+ bdrv_inc_in_flight(bs);
nbd_client_attach_aio_context(bs, bdrv_get_aio_context(bs));
logout("Established connection with NBD server\n");
{
NBDClientSession *client = nbd_get_client_session(bs);
+ client->bs = bs;
qemu_co_mutex_init(&client->send_mutex);
qemu_co_queue_init(&client->free_sema);
NBDClientRequest requests[MAX_NBD_REQUESTS];
NBDReply reply;
+ BlockDriverState *bs;
bool quit;
} NBDClientSession;
nbd_client_attach_aio_context(bs, new_context);
}
-static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
+static void nbd_refresh_filename(BlockDriverState *bs)
{
BDRVNBDState *s = bs->opaque;
- QDict *opts = qdict_new();
- QObject *saddr_qdict;
- Visitor *ov;
const char *host = NULL, *port = NULL, *path = NULL;
if (s->saddr->type == SOCKET_ADDRESS_TYPE_INET) {
path = s->saddr->u.q_unix.path;
} /* else can't represent as pseudo-filename */
- qdict_put_str(opts, "driver", "nbd");
-
if (path && s->export) {
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
"nbd+unix:///%s?socket=%s", s->export, path);
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
"nbd://%s:%s", host, port);
}
+}
- ov = qobject_output_visitor_new(&saddr_qdict);
- visit_type_SocketAddress(ov, NULL, &s->saddr, &error_abort);
- visit_complete(ov, &saddr_qdict);
- visit_free(ov);
- qdict_put_obj(opts, "server", saddr_qdict);
+static char *nbd_dirname(BlockDriverState *bs, Error **errp)
+{
+ /* The generic bdrv_dirname() implementation is able to work out some
+ * directory name for NBD nodes, but that would be wrong. So far there is no
+ * specification for how "export paths" would work, so NBD does not have
+ * directory names. */
+ error_setg(errp, "Cannot generate a base directory for NBD nodes");
+ return NULL;
+}
- if (s->export) {
- qdict_put_str(opts, "export", s->export);
- }
- if (s->tlscredsid) {
- qdict_put_str(opts, "tls-creds", s->tlscredsid);
- }
+static const char *const nbd_strong_runtime_opts[] = {
+ "path",
+ "host",
+ "port",
+ "export",
+ "tls-creds",
+ "server.",
- qdict_flatten(opts);
- bs->full_open_options = opts;
-}
+ NULL
+};
static BlockDriver bdrv_nbd = {
.format_name = "nbd",
.bdrv_attach_aio_context = nbd_attach_aio_context,
.bdrv_refresh_filename = nbd_refresh_filename,
.bdrv_co_block_status = nbd_client_co_block_status,
+ .bdrv_dirname = nbd_dirname,
+ .strong_runtime_opts = nbd_strong_runtime_opts,
};
static BlockDriver bdrv_nbd_tcp = {
.bdrv_attach_aio_context = nbd_attach_aio_context,
.bdrv_refresh_filename = nbd_refresh_filename,
.bdrv_co_block_status = nbd_client_co_block_status,
+ .bdrv_dirname = nbd_dirname,
+ .strong_runtime_opts = nbd_strong_runtime_opts,
};
static BlockDriver bdrv_nbd_unix = {
.bdrv_attach_aio_context = nbd_attach_aio_context,
.bdrv_refresh_filename = nbd_refresh_filename,
.bdrv_co_block_status = nbd_client_co_block_status,
+ .bdrv_dirname = nbd_dirname,
+ .strong_runtime_opts = nbd_strong_runtime_opts,
};
static void bdrv_nbd_init(void)
return 0;
}
-static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
+static void nfs_refresh_filename(BlockDriverState *bs)
{
NFSClient *client = bs->opaque;
- QDict *opts = qdict_new();
- QObject *server_qdict;
- Visitor *ov;
-
- qdict_put_str(opts, "driver", "nfs");
if (client->uid && !client->gid) {
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
"nfs://%s%s", client->server->host, client->path);
}
+}
- ov = qobject_output_visitor_new(&server_qdict);
- visit_type_NFSServer(ov, NULL, &client->server, &error_abort);
- visit_complete(ov, &server_qdict);
- qdict_put_obj(opts, "server", server_qdict);
- qdict_put_str(opts, "path", client->path);
+static char *nfs_dirname(BlockDriverState *bs, Error **errp)
+{
+ NFSClient *client = bs->opaque;
- if (client->uid) {
- qdict_put_int(opts, "user", client->uid);
- }
- if (client->gid) {
- qdict_put_int(opts, "group", client->gid);
- }
- if (client->tcp_syncnt) {
- qdict_put_int(opts, "tcp-syn-cnt", client->tcp_syncnt);
- }
- if (client->readahead) {
- qdict_put_int(opts, "readahead-size", client->readahead);
- }
- if (client->pagecache) {
- qdict_put_int(opts, "page-cache-size", client->pagecache);
- }
- if (client->debug) {
- qdict_put_int(opts, "debug", client->debug);
+ if (client->uid || client->gid) {
+ bdrv_refresh_filename(bs);
+ error_setg(errp, "Cannot generate a base directory for NFS node '%s'",
+ bs->filename);
+ return NULL;
}
- visit_free(ov);
- qdict_flatten(opts);
- bs->full_open_options = opts;
+ return g_strdup_printf("nfs://%s%s/", client->server->host, client->path);
}
#ifdef LIBNFS_FEATURE_PAGECACHE
}
#endif
+static const char *nfs_strong_runtime_opts[] = {
+ "path",
+ "user",
+ "group",
+ "server.",
+
+ NULL
+};
+
static BlockDriver bdrv_nfs = {
.format_name = "nfs",
.protocol_name = "nfs",
.bdrv_detach_aio_context = nfs_detach_aio_context,
.bdrv_attach_aio_context = nfs_attach_aio_context,
.bdrv_refresh_filename = nfs_refresh_filename,
+ .bdrv_dirname = nfs_dirname,
+
+ .strong_runtime_opts = nfs_strong_runtime_opts,
#ifdef LIBNFS_FEATURE_PAGECACHE
.bdrv_co_invalidate_cache = nfs_co_invalidate_cache,
return ret;
}
-static void null_refresh_filename(BlockDriverState *bs, QDict *opts)
+static void null_refresh_filename(BlockDriverState *bs)
{
- qdict_del(opts, "filename");
-
- if (!qdict_size(opts)) {
- snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
- bs->drv->format_name);
+ const QDictEntry *e;
+
+ for (e = qdict_first(bs->full_open_options); e;
+ e = qdict_next(bs->full_open_options, e))
+ {
+ /* These options can be ignored */
+ if (strcmp(qdict_entry_key(e), "filename") &&
+ strcmp(qdict_entry_key(e), "driver") &&
+ strcmp(qdict_entry_key(e), NULL_OPT_LATENCY))
+ {
+ return;
+ }
}
- qdict_put_str(opts, "driver", bs->drv->format_name);
- bs->full_open_options = qobject_ref(opts);
+ snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
+ bs->drv->format_name);
}
+static const char *const null_strong_runtime_opts[] = {
+ BLOCK_OPT_SIZE,
+ NULL_OPT_ZEROES,
+
+ NULL
+};
+
static BlockDriver bdrv_null_co = {
.format_name = "null-co",
.protocol_name = "null-co",
.bdrv_co_block_status = null_co_block_status,
.bdrv_refresh_filename = null_refresh_filename,
+ .strong_runtime_opts = null_strong_runtime_opts,
};
static BlockDriver bdrv_null_aio = {
.bdrv_co_block_status = null_co_block_status,
.bdrv_refresh_filename = null_refresh_filename,
+ .strong_runtime_opts = null_strong_runtime_opts,
};
static void bdrv_null_init(void)
uint8_t reserved1[0xec0];
uint8_t cmd_set_specfic[0x100];
uint32_t doorbells[];
-} QEMU_PACKED NVMeRegs;
+} NVMeRegs;
QEMU_BUILD_BUG_ON(offsetof(NVMeRegs, doorbells) != 0x1000);
/* Total size of mapped qiov, accessed under dma_map_lock */
int dma_map_count;
+
+ /* PCI address (required for nvme_refresh_filename()) */
+ char *device;
} BDRVNVMeState;
#define NVME_BLOCK_OPT_DEVICE "device"
qemu_co_mutex_init(&s->dma_map_lock);
qemu_co_queue_init(&s->dma_flush_queue);
+ s->device = g_strdup(device);
s->nsid = namespace;
s->aio_context = bdrv_get_aio_context(bs);
ret = event_notifier_init(&s->irq_notifier, 0);
event_notifier_cleanup(&s->irq_notifier);
qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->regs, 0, NVME_BAR_SIZE);
qemu_vfio_close(s->vfio);
+
+ g_free(s->device);
}
static int nvme_file_open(BlockDriverState *bs, QDict *options, int flags,
return 0;
}
-static void nvme_refresh_filename(BlockDriverState *bs, QDict *opts)
+static void nvme_refresh_filename(BlockDriverState *bs)
{
- qdict_del(opts, "filename");
-
- if (!qdict_size(opts)) {
- snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
- bs->drv->format_name);
- }
+ BDRVNVMeState *s = bs->opaque;
- qdict_put_str(opts, "driver", bs->drv->format_name);
- bs->full_open_options = qobject_ref(opts);
+ snprintf(bs->exact_filename, sizeof(bs->exact_filename), "nvme://%s/%i",
+ s->device, s->nsid);
}
static void nvme_refresh_limits(BlockDriverState *bs, Error **errp)
qemu_vfio_dma_unmap(s->vfio, host);
}
+static const char *const nvme_strong_runtime_opts[] = {
+ NVME_BLOCK_OPT_DEVICE,
+ NVME_BLOCK_OPT_NAMESPACE,
+
+ NULL
+};
+
static BlockDriver bdrv_nvme = {
.format_name = "nvme",
.protocol_name = "nvme",
.bdrv_refresh_filename = nvme_refresh_filename,
.bdrv_refresh_limits = nvme_refresh_limits,
+ .strong_runtime_opts = nvme_strong_runtime_opts,
.bdrv_detach_aio_context = nvme_detach_aio_context,
.bdrv_attach_aio_context = nvme_attach_aio_context,
if (bs->backing) {
int64_t nb_cow_sectors = to_allocate * s->tracks;
int64_t nb_cow_bytes = nb_cow_sectors << BDRV_SECTOR_BITS;
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_len = nb_cow_bytes,
- .iov_base = qemu_blockalign(bs, nb_cow_bytes)
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ QEMUIOVector qiov =
+ QEMU_IOVEC_INIT_BUF(qiov, qemu_blockalign(bs, nb_cow_bytes),
+ nb_cow_bytes);
ret = bdrv_co_preadv(bs->backing, idx * s->tracks * BDRV_SECTOR_SIZE,
nb_cow_bytes, &qiov, 0);
if (ret < 0) {
- qemu_vfree(iov.iov_base);
+ qemu_vfree(qemu_iovec_buf(&qiov));
return ret;
}
ret = bdrv_co_pwritev(bs->file, s->data_end * BDRV_SECTOR_SIZE,
nb_cow_bytes, &qiov, 0);
- qemu_vfree(iov.iov_base);
+ qemu_vfree(qemu_iovec_buf(&qiov));
if (ret < 0) {
return ret;
}
return NULL;
}
+ bdrv_refresh_filename(bs);
+
info = g_malloc0(sizeof(*info));
info->file = g_strdup(bs->filename);
info->ro = bs->read_only;
goto out;
}
+ bdrv_refresh_filename(bs);
+
info = g_new0(ImageInfo, 1);
info->filename = g_strdup(bs->filename);
info->format = g_strdup(bdrv_get_format_name(bs));
info->dirty_flag = bdi.is_dirty;
info->has_dirty_flag = true;
}
- info->format_specific = bdrv_get_specific_info(bs);
+ info->format_specific = bdrv_get_specific_info(bs, &err);
+ if (err) {
+ error_propagate(errp, err);
+ qapi_free_ImageInfo(info);
+ goto out;
+ }
info->has_format_specific = info->format_specific != NULL;
backing_filename = bs->backing_file;
if (backing_filename[0] != '\0') {
- char *backing_filename2 = g_malloc0(PATH_MAX);
+ char *backing_filename2;
info->backing_filename = g_strdup(backing_filename);
info->has_backing_filename = true;
- bdrv_get_full_backing_filename(bs, backing_filename2, PATH_MAX, &err);
- if (err) {
- /* Can't reconstruct the full backing filename, so we must omit
- * this field and apply a Best Effort to this query. */
- g_free(backing_filename2);
- backing_filename2 = NULL;
- error_free(err);
- err = NULL;
- }
+ backing_filename2 = bdrv_get_full_backing_filename(bs, NULL);
/* Always report the full_backing_filename if present, even if it's the
* same as backing_filename. That they are same is useful info. */
#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/bswap.h"
+#include "qemu/cutils.h"
#include <zlib.h>
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
goto fail;
}
ret = bdrv_pread(bs->file, header.backing_file_offset,
- bs->backing_file, len);
+ bs->auto_backing_file, len);
if (ret < 0) {
goto fail;
}
- bs->backing_file[len] = '\0';
+ bs->auto_backing_file[len] = '\0';
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ bs->auto_backing_file);
}
/* Disable migration when qcow images are used */
int offset_in_cluster;
int ret = 0, n;
uint64_t cluster_offset;
- struct iovec hd_iov;
QEMUIOVector hd_qiov;
uint8_t *buf;
void *orig_buf;
if (!cluster_offset) {
if (bs->backing) {
/* read from the base image */
- hd_iov.iov_base = (void *)buf;
- hd_iov.iov_len = n;
- qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
+ qemu_iovec_init_buf(&hd_qiov, buf, n);
qemu_co_mutex_unlock(&s->lock);
/* qcow2 emits this on bs->file instead of bs->backing */
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
ret = -EIO;
break;
}
- hd_iov.iov_base = (void *)buf;
- hd_iov.iov_len = n;
- qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
+ qemu_iovec_init_buf(&hd_qiov, buf, n);
qemu_co_mutex_unlock(&s->lock);
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
ret = bdrv_co_preadv(bs->file, cluster_offset + offset_in_cluster,
int offset_in_cluster;
uint64_t cluster_offset;
int ret = 0, n;
- struct iovec hd_iov;
QEMUIOVector hd_qiov;
uint8_t *buf;
void *orig_buf;
}
}
- hd_iov.iov_base = (void *)buf;
- hd_iov.iov_len = n;
- qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
+ qemu_iovec_init_buf(&hd_qiov, buf, n);
qemu_co_mutex_unlock(&s->lock);
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
ret = bdrv_co_pwritev(bs->file, cluster_offset + offset_in_cluster,
{
BDRVQcowState *s = bs->opaque;
QEMUIOVector hd_qiov;
- struct iovec iov;
z_stream strm;
int ret, out_len;
uint8_t *buf, *out_buf;
}
cluster_offset &= s->cluster_offset_mask;
- iov = (struct iovec) {
- .iov_base = out_buf,
- .iov_len = out_len,
- };
- qemu_iovec_init_external(&hd_qiov, &iov, 1);
+ qemu_iovec_init_buf(&hd_qiov, out_buf, out_len);
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);
if (ret < 0) {
}
};
+static const char *const qcow_strong_runtime_opts[] = {
+ "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET,
+
+ NULL
+};
+
static BlockDriver bdrv_qcow = {
.format_name = "qcow",
.instance_size = sizeof(BDRVQcowState),
.bdrv_get_info = qcow_get_info,
.create_opts = &qcow_create_opts,
+ .strong_runtime_opts = qcow_strong_runtime_opts,
};
static void bdrv_qcow_init(void)
return false;
}
+
+static Qcow2BitmapInfoFlagsList *get_bitmap_info_flags(uint32_t flags)
+{
+ Qcow2BitmapInfoFlagsList *list = NULL;
+ Qcow2BitmapInfoFlagsList **plist = &list;
+ int i;
+
+ static const struct {
+ int bme; /* Bitmap directory entry flags */
+ int info; /* The flags to report to the user */
+ } map[] = {
+ { BME_FLAG_IN_USE, QCOW2_BITMAP_INFO_FLAGS_IN_USE },
+ { BME_FLAG_AUTO, QCOW2_BITMAP_INFO_FLAGS_AUTO },
+ };
+
+ int map_size = ARRAY_SIZE(map);
+
+ for (i = 0; i < map_size; ++i) {
+ if (flags & map[i].bme) {
+ Qcow2BitmapInfoFlagsList *entry =
+ g_new0(Qcow2BitmapInfoFlagsList, 1);
+ entry->value = map[i].info;
+ *plist = entry;
+ plist = &entry->next;
+ flags &= ~map[i].bme;
+ }
+ }
+ /* Check if the BME_* mapping above is complete */
+ assert(!flags);
+
+ return list;
+}
+
+/*
+ * qcow2_get_bitmap_info_list()
+ * Returns a list of QCOW2 bitmap details.
+ * In case of no bitmaps, the function returns NULL and
+ * the @errp parameter is not set.
+ * When bitmap information can not be obtained, the function returns
+ * NULL and the @errp parameter is set.
+ */
+Qcow2BitmapInfoList *qcow2_get_bitmap_info_list(BlockDriverState *bs,
+ Error **errp)
+{
+ BDRVQcow2State *s = bs->opaque;
+ Qcow2BitmapList *bm_list;
+ Qcow2Bitmap *bm;
+ Qcow2BitmapInfoList *list = NULL;
+ Qcow2BitmapInfoList **plist = &list;
+
+ if (s->nb_bitmaps == 0) {
+ return NULL;
+ }
+
+ bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
+ s->bitmap_directory_size, errp);
+ if (bm_list == NULL) {
+ return NULL;
+ }
+
+ QSIMPLEQ_FOREACH(bm, bm_list, entry) {
+ Qcow2BitmapInfo *info = g_new0(Qcow2BitmapInfo, 1);
+ Qcow2BitmapInfoList *obj = g_new0(Qcow2BitmapInfoList, 1);
+ info->granularity = 1U << bm->granularity_bits;
+ info->name = g_strdup(bm->name);
+ info->flags = get_bitmap_info_flags(bm->flags & ~BME_RESERVED_FLAGS);
+ obj->value = info;
+ *plist = obj;
+ plist = &obj->next;
+ }
+
+ bitmap_list_free(bm_list);
+
+ return list;
+}
+
int qcow2_reopen_bitmaps_rw_hint(BlockDriverState *bs, bool *header_updated,
Error **errp)
{
goto fail;
}
+ /* The offset must fit in the offset field of the L1 table entry */
+ assert((l2_offset & L1E_OFFSET_MASK) == l2_offset);
+
/* If we're allocating the table at offset 0 then something is wrong */
if (l2_offset == 0) {
qcow2_signal_corruption(bs, true, -1, -1, "Preventing invalid "
/* Generate an ID */
find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
- /* Check that the ID is unique */
- if (find_snapshot_by_id_and_name(bs, sn_info->id_str, NULL) >= 0) {
- return -EEXIST;
- }
-
/* Populate sn with passed data */
sn->id_str = g_strdup(sn_info->id_str);
sn->name = g_strdup(sn_info->name);
goto fail;
}
ret = bdrv_pread(bs->file, header.backing_file_offset,
- bs->backing_file, len);
+ bs->auto_backing_file, len);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read backing file name");
goto fail;
}
- bs->backing_file[len] = '\0';
- s->image_backing_file = g_strdup(bs->backing_file);
+ bs->auto_backing_file[len] = '\0';
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ bs->auto_backing_file);
+ s->image_backing_file = g_strdup(bs->auto_backing_file);
}
/* Internal snapshots */
return -EINVAL;
}
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
+ backing_file ?: "");
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
{
BDRVQcow2State *s = bs->opaque;
QEMUIOVector hd_qiov;
- struct iovec iov;
int ret;
size_t out_len;
uint8_t *buf, *out_buf;
goto fail;
}
- iov = (struct iovec) {
- .iov_base = out_buf,
- .iov_len = out_len,
- };
- qemu_iovec_init_external(&hd_qiov, &iov, 1);
+ qemu_iovec_init_buf(&hd_qiov, out_buf, out_len);
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);
int ret = 0, csize, nb_csectors;
uint64_t coffset;
uint8_t *buf, *out_buf;
- struct iovec iov;
QEMUIOVector local_qiov;
int offset_in_cluster = offset_into_cluster(s, offset);
if (!buf) {
return -ENOMEM;
}
- iov.iov_base = buf;
- iov.iov_len = csize;
- qemu_iovec_init_external(&local_qiov, &iov, 1);
+ qemu_iovec_init_buf(&local_qiov, buf, csize);
out_buf = qemu_blockalign(bs, s->cluster_size);
return ret;
}
+static ssize_t qcow2_measure_crypto_hdr_init_func(QCryptoBlock *block,
+ size_t headerlen, void *opaque, Error **errp)
+{
+ size_t *headerlenp = opaque;
+
+ /* Stash away the payload size */
+ *headerlenp = headerlen;
+ return 0;
+}
+
+static ssize_t qcow2_measure_crypto_hdr_write_func(QCryptoBlock *block,
+ size_t offset, const uint8_t *buf, size_t buflen,
+ void *opaque, Error **errp)
+{
+ /* Discard the bytes, we're not actually writing to an image */
+ return buflen;
+}
+
+/* Determine the number of bytes for the LUKS payload */
+static bool qcow2_measure_luks_headerlen(QemuOpts *opts, size_t *len,
+ Error **errp)
+{
+ QDict *opts_qdict;
+ QDict *cryptoopts_qdict;
+ QCryptoBlockCreateOptions *cryptoopts;
+ QCryptoBlock *crypto;
+
+ /* Extract "encrypt." options into a qdict */
+ opts_qdict = qemu_opts_to_qdict(opts, NULL);
+ qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, "encrypt.");
+ qobject_unref(opts_qdict);
+
+ /* Build QCryptoBlockCreateOptions object from qdict */
+ qdict_put_str(cryptoopts_qdict, "format", "luks");
+ cryptoopts = block_crypto_create_opts_init(cryptoopts_qdict, errp);
+ qobject_unref(cryptoopts_qdict);
+ if (!cryptoopts) {
+ return false;
+ }
+
+ /* Fake LUKS creation in order to determine the payload size */
+ crypto = qcrypto_block_create(cryptoopts, "encrypt.",
+ qcow2_measure_crypto_hdr_init_func,
+ qcow2_measure_crypto_hdr_write_func,
+ len, errp);
+ qapi_free_QCryptoBlockCreateOptions(cryptoopts);
+ if (!crypto) {
+ return false;
+ }
+
+ qcrypto_block_free(crypto);
+ return true;
+}
+
static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
Error **errp)
{
uint64_t virtual_size; /* disk size as seen by guest */
uint64_t refcount_bits;
uint64_t l2_tables;
+ uint64_t luks_payload_size = 0;
size_t cluster_size;
int version;
char *optstr;
PreallocMode prealloc;
bool has_backing_file;
+ bool has_luks;
/* Parse image creation options */
cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err);
has_backing_file = !!optstr;
g_free(optstr);
+ optstr = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT);
+ has_luks = optstr && strcmp(optstr, "luks") == 0;
+ g_free(optstr);
+
+ if (has_luks) {
+ size_t headerlen;
+
+ if (!qcow2_measure_luks_headerlen(opts, &headerlen, &local_err)) {
+ goto err;
+ }
+
+ luks_payload_size = ROUND_UP(headerlen, cluster_size);
+ }
+
virtual_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
virtual_size = ROUND_UP(virtual_size, cluster_size);
info = g_new(BlockMeasureInfo, 1);
info->fully_allocated =
qcow2_calc_prealloc_size(virtual_size, cluster_size,
- ctz32(refcount_bits));
+ ctz32(refcount_bits)) + luks_payload_size;
/* Remove data clusters that are not required. This overestimates the
* required size because metadata needed for the fully allocated file is
return 0;
}
-static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs)
+static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,
+ Error **errp)
{
BDRVQcow2State *s = bs->opaque;
ImageInfoSpecific *spec_info;
QCryptoBlockInfo *encrypt_info = NULL;
+ Error *local_err = NULL;
if (s->crypto != NULL) {
- encrypt_info = qcrypto_block_get_info(s->crypto, &error_abort);
+ encrypt_info = qcrypto_block_get_info(s->crypto, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return NULL;
+ }
}
spec_info = g_new(ImageInfoSpecific, 1);
*spec_info = (ImageInfoSpecific){
.type = IMAGE_INFO_SPECIFIC_KIND_QCOW2,
- .u.qcow2.data = g_new(ImageInfoSpecificQCow2, 1),
+ .u.qcow2.data = g_new0(ImageInfoSpecificQCow2, 1),
};
if (s->qcow_version == 2) {
*spec_info->u.qcow2.data = (ImageInfoSpecificQCow2){
.refcount_bits = s->refcount_bits,
};
} else if (s->qcow_version == 3) {
+ Qcow2BitmapInfoList *bitmaps;
+ bitmaps = qcow2_get_bitmap_info_list(bs, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ qapi_free_ImageInfoSpecific(spec_info);
+ return NULL;
+ }
*spec_info->u.qcow2.data = (ImageInfoSpecificQCow2){
.compat = g_strdup("1.1"),
.lazy_refcounts = s->compatible_features &
QCOW2_INCOMPAT_CORRUPT,
.has_corrupt = true,
.refcount_bits = s->refcount_bits,
+ .has_bitmaps = !!bitmaps,
+ .bitmaps = bitmaps,
};
} else {
/* if this assertion fails, this probably means a new version was
}
};
+static const char *const qcow2_strong_runtime_opts[] = {
+ "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET,
+
+ NULL
+};
+
BlockDriver bdrv_qcow2 = {
.format_name = "qcow2",
.instance_size = sizeof(BDRVQcow2State),
.bdrv_inactivate = qcow2_inactivate,
.create_opts = &qcow2_create_opts,
+ .strong_runtime_opts = qcow2_strong_runtime_opts,
.bdrv_co_check = qcow2_co_check,
.bdrv_amend_options = qcow2_amend_options,
void **refcount_table,
int64_t *refcount_table_size);
bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error **errp);
+Qcow2BitmapInfoList *qcow2_get_bitmap_info_list(BlockDriverState *bs,
+ Error **errp);
int qcow2_reopen_bitmaps_rw_hint(BlockDriverState *bs, bool *header_updated,
Error **errp);
int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
/* Called with table_lock held. */
static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
{
- QEMUIOVector qiov;
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(
+ qiov, table->offsets, s->header.cluster_size * s->header.table_size);
int noffsets;
int i, ret;
- struct iovec iov = {
- .iov_base = table->offsets,
- .iov_len = s->header.cluster_size * s->header.table_size,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
-
trace_qed_read_table(s, offset, table);
qemu_co_mutex_unlock(&s->table_lock);
unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1;
unsigned int start, end, i;
QEDTable *new_table;
- struct iovec iov;
QEMUIOVector qiov;
size_t len_bytes;
int ret;
len_bytes = (end - start) * sizeof(uint64_t);
new_table = qemu_blockalign(s->bs, len_bytes);
- iov = (struct iovec) {
- .iov_base = new_table->offsets,
- .iov_len = len_bytes,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, new_table->offsets, len_bytes);
/* Byteswap table */
for (i = start; i < end; i++) {
int nsectors = DIV_ROUND_UP(sizeof(QEDHeader), BDRV_SECTOR_SIZE);
size_t len = nsectors * BDRV_SECTOR_SIZE;
uint8_t *buf;
- struct iovec iov;
QEMUIOVector qiov;
int ret;
assert(s->allocating_acb || s->allocating_write_reqs_plugged);
buf = qemu_blockalign(s->bs, len);
- iov = (struct iovec) {
- .iov_base = buf,
- .iov_len = len,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, buf, len);
ret = bdrv_co_preadv(s->bs->file, 0, qiov.size, &qiov, 0);
if (ret < 0) {
}
ret = qed_read_string(bs->file, s->header.backing_filename_offset,
- s->header.backing_filename_size, bs->backing_file,
- sizeof(bs->backing_file));
+ s->header.backing_filename_size,
+ bs->auto_backing_file,
+ sizeof(bs->auto_backing_file));
if (ret < 0) {
return ret;
}
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ bs->auto_backing_file);
if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) {
pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw");
{
QEMUIOVector qiov;
QEMUIOVector *backing_qiov = NULL;
- struct iovec iov;
int ret;
/* Skip copy entirely if there is no work to do */
return 0;
}
- iov = (struct iovec) {
- .iov_base = qemu_blockalign(s->bs, len),
- .iov_len = len,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, qemu_blockalign(s->bs, len), len);
ret = qed_read_backing_file(s, pos, &qiov, &backing_qiov);
}
ret = 0;
out:
- qemu_vfree(iov.iov_base);
+ qemu_vfree(qemu_iovec_buf(&qiov));
return ret;
}
BdrvRequestFlags flags)
{
BDRVQEDState *s = bs->opaque;
- QEMUIOVector qiov;
- struct iovec iov;
+
+ /*
+ * Zero writes start without an I/O buffer. If a buffer becomes necessary
+ * then it will be allocated during request processing.
+ */
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, bytes);
/* Fall back if the request is not aligned */
if (qed_offset_into_cluster(s, offset) ||
return -ENOTSUP;
}
- /* Zero writes start without an I/O buffer. If a buffer becomes necessary
- * then it will be allocated during request processing.
- */
- iov.iov_base = NULL;
- iov.iov_len = bytes;
-
- qemu_iovec_init_external(&qiov, &iov, 1);
return qed_co_request(bs, offset >> BDRV_SECTOR_BITS, &qiov,
bytes >> BDRV_SECTOR_BITS,
QED_AIOCB_WRITE | QED_AIOCB_ZERO);
bdrv_drained_end(bs);
}
-static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
+static void quorum_gather_child_options(BlockDriverState *bs, QDict *target,
+ bool backing_overridden)
{
BDRVQuorumState *s = bs->opaque;
- QDict *opts;
- QList *children;
+ QList *children_list;
int i;
- for (i = 0; i < s->num_children; i++) {
- bdrv_refresh_filename(s->children[i]->bs);
- if (!s->children[i]->bs->full_open_options) {
- return;
- }
- }
+ /*
+ * The generic implementation for gathering child options in
+ * bdrv_refresh_filename() would use the names of the children
+ * as specified for bdrv_open_child() or bdrv_attach_child(),
+ * which is "children.%u" with %u being a value
+ * (s->next_child_index) that is incremented each time a new child
+ * is added (and never decremented). Since children can be
+ * deleted at runtime, there may be gaps in that enumeration.
+ * When creating a new quorum BDS and specifying the children for
+ * it through runtime options, the enumeration used there may not
+ * have any gaps, though.
+ *
+ * Therefore, we have to create a new gap-less enumeration here
+ * (which we can achieve by simply putting all of the children's
+ * full_open_options into a QList).
+ *
+ * XXX: Note that there are issues with the current child option
+ * structure quorum uses (such as the fact that children do
+ * not really have unique permanent names). Therefore, this
+ * is going to have to change in the future and ideally we
+ * want quorum to be covered by the generic implementation.
+ */
+
+ children_list = qlist_new();
+ qdict_put(target, "children", children_list);
- children = qlist_new();
for (i = 0; i < s->num_children; i++) {
- qlist_append(children,
+ qlist_append(children_list,
qobject_ref(s->children[i]->bs->full_open_options));
}
+}
- opts = qdict_new();
- qdict_put_str(opts, "driver", "quorum");
- qdict_put_int(opts, QUORUM_OPT_VOTE_THRESHOLD, s->threshold);
- qdict_put_bool(opts, QUORUM_OPT_BLKVERIFY, s->is_blkverify);
- qdict_put_bool(opts, QUORUM_OPT_REWRITE, s->rewrite_corrupted);
- qdict_put(opts, "children", children);
-
- bs->full_open_options = opts;
+static char *quorum_dirname(BlockDriverState *bs, Error **errp)
+{
+ /* In general, there are multiple BDSs with different dirnames below this
+ * one; so there is no unique dirname we could return (unless all are equal
+ * by chance, or there is only one). Therefore, to be consistent, just
+ * always return NULL. */
+ error_setg(errp, "Cannot generate a base directory for quorum nodes");
+ return NULL;
}
+static const char *const quorum_strong_runtime_opts[] = {
+ QUORUM_OPT_VOTE_THRESHOLD,
+ QUORUM_OPT_BLKVERIFY,
+ QUORUM_OPT_REWRITE,
+ QUORUM_OPT_READ_PATTERN,
+
+ NULL
+};
+
static BlockDriver bdrv_quorum = {
.format_name = "quorum",
.bdrv_open = quorum_open,
.bdrv_close = quorum_close,
- .bdrv_refresh_filename = quorum_refresh_filename,
+ .bdrv_gather_child_options = quorum_gather_child_options,
+ .bdrv_dirname = quorum_dirname,
.bdrv_co_flush_to_disk = quorum_co_flush,
.is_filter = true,
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
+
+ .strong_runtime_opts = quorum_strong_runtime_opts,
};
static void bdrv_quorum_init(void)
bs->file->bs->supported_zero_flags);
if (bs->probed && !bdrv_is_read_only(bs)) {
+ bdrv_refresh_filename(bs->file->bs);
fprintf(stderr,
"WARNING: Image format was not specified for '%s' and probing "
"guessed raw.\n"
read_flags, write_flags);
}
+static const char *const raw_strong_runtime_opts[] = {
+ "offset",
+ "size",
+
+ NULL
+};
+
BlockDriver bdrv_raw = {
.format_name = "raw",
.instance_size = sizeof(BDRVRawState),
.bdrv_lock_medium = &raw_lock_medium,
.bdrv_co_ioctl = &raw_co_ioctl,
.create_opts = &raw_create_opts,
- .bdrv_has_zero_init = &raw_has_zero_init
+ .bdrv_has_zero_init = &raw_has_zero_init,
+ .strong_runtime_opts = raw_strong_runtime_opts,
};
static void bdrv_raw_init(void)
}
};
+static const char *const qemu_rbd_strong_runtime_opts[] = {
+ "pool",
+ "image",
+ "conf",
+ "snapshot",
+ "user",
+ "server.",
+ "password-secret",
+
+ NULL
+};
+
static BlockDriver bdrv_rbd = {
.format_name = "rbd",
.instance_size = sizeof(BDRVRBDState),
#ifdef LIBRBD_SUPPORTS_INVALIDATE
.bdrv_co_invalidate_cache = qemu_rbd_co_invalidate_cache,
#endif
+
+ .strong_runtime_opts = qemu_rbd_strong_runtime_opts,
};
static void bdrv_rbd_init(void)
if (ret == 0) {
s->stage = BLOCK_REPLICATION_DONE;
- /* refresh top bs's filename */
- bdrv_refresh_filename(bs);
s->active_disk = NULL;
s->secondary_disk = NULL;
s->hidden_disk = NULL;
aio_context_release(aio_context);
}
+static const char *const replication_strong_runtime_opts[] = {
+ REPLICATION_MODE,
+ REPLICATION_TOP_ID,
+
+ NULL
+};
+
BlockDriver bdrv_replication = {
.format_name = "replication",
.instance_size = sizeof(BDRVReplicationState),
.bdrv_recurse_is_first_non_filter = replication_recurse_is_first_non_filter,
.has_variable_length = true,
+ .strong_runtime_opts = replication_strong_runtime_opts,
};
static void bdrv_replication_init(void)
}
};
+static const char *const sd_strong_runtime_opts[] = {
+ "vdi",
+ "snap-id",
+ "tag",
+ "server.",
+
+ NULL
+};
+
static BlockDriver bdrv_sheepdog = {
.format_name = "sheepdog",
.protocol_name = "sheepdog",
.bdrv_attach_aio_context = sd_attach_aio_context,
.create_opts = &sd_create_opts,
+ .strong_runtime_opts = sd_strong_runtime_opts,
};
static BlockDriver bdrv_sheepdog_tcp = {
.bdrv_attach_aio_context = sd_attach_aio_context,
.create_opts = &sd_create_opts,
+ .strong_runtime_opts = sd_strong_runtime_opts,
};
static BlockDriver bdrv_sheepdog_unix = {
.bdrv_attach_aio_context = sd_attach_aio_context,
.create_opts = &sd_create_opts,
+ .strong_runtime_opts = sd_strong_runtime_opts,
};
static void bdrv_sheepdog_init(void)
}
for (i = 0; i < nb_sns; i++) {
sn = &sn_tab[i];
- if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
+ if (!strcmp(sn->name, name)) {
*sn_info = *sn;
ret = 0;
break;
return ret;
}
-int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
- const char *id_or_name,
- Error **errp)
-{
- int ret;
- Error *local_err = NULL;
-
- ret = bdrv_snapshot_delete(bs, id_or_name, NULL, &local_err);
- if (ret == -ENOENT || ret == -EINVAL) {
- error_free(local_err);
- local_err = NULL;
- ret = bdrv_snapshot_delete(bs, NULL, id_or_name, &local_err);
- }
-
- if (ret < 0) {
- error_propagate(errp, local_err);
- }
- return ret;
-}
-
int bdrv_snapshot_list(BlockDriverState *bs,
QEMUSnapshotInfo **psn_info)
{
aio_context_acquire(ctx);
if (bdrv_can_snapshot(bs) &&
bdrv_snapshot_find(bs, snapshot, name) >= 0) {
- ret = bdrv_snapshot_delete_by_id_or_name(bs, name, err);
+ ret = bdrv_snapshot_delete(bs, snapshot->id_str,
+ snapshot->name, err);
}
aio_context_release(ctx);
if (ret < 0) {
return ssh_grow_file(s, offset, errp);
}
+static const char *const ssh_strong_runtime_opts[] = {
+ "host",
+ "port",
+ "path",
+ "user",
+ "host_key_check",
+ "server.",
+
+ NULL
+};
+
static BlockDriver bdrv_ssh = {
.format_name = "ssh",
.protocol_name = "ssh",
.bdrv_co_truncate = ssh_co_truncate,
.bdrv_co_flush_to_disk = ssh_co_flush,
.create_opts = &ssh_create_opts,
+ .strong_runtime_opts = ssh_strong_runtime_opts,
};
static void bdrv_ssh_init(void)
int64_t offset, uint64_t bytes,
void *buf)
{
- struct iovec iov = {
- .iov_base = buf,
- .iov_len = bytes,
- };
- QEMUIOVector qiov;
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
assert(bytes < SIZE_MAX);
- qemu_iovec_init_external(&qiov, &iov, 1);
/* Copy-on-read the unallocated clusters */
return blk_co_preadv(blk, offset, qiov.size, &qiov, BDRV_REQ_COPY_ON_READ);
atomic_dec(&tgm->io_limits_disabled);
}
+static const char *const throttle_strong_runtime_opts[] = {
+ QEMU_OPT_THROTTLE_GROUP_NAME,
+
+ NULL
+};
+
static BlockDriver bdrv_throttle = {
.format_name = "throttle",
.instance_size = sizeof(ThrottleGroupMember),
.bdrv_co_drain_end = throttle_co_drain_end,
.is_filter = true,
+ .strong_runtime_opts = throttle_strong_runtime_opts,
};
static void bdrv_throttle_init(void)
if (logs.valid) {
if (bs->read_only) {
+ bdrv_refresh_filename(bs);
ret = -EPERM;
error_setg(errp,
"VHDX image file '%s' opened read-only, but "
#include "qapi/error.h"
#include "block/block_int.h"
#include "sysemu/block-backend.h"
+#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
ret = -EINVAL;
goto out;
}
- if ((end_name - p_name) > sizeof(bs->backing_file) - 1) {
+ if ((end_name - p_name) > sizeof(bs->auto_backing_file) - 1) {
ret = -EINVAL;
goto out;
}
- pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
+ pstrcpy(bs->auto_backing_file, end_name - p_name + 1, p_name);
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ bs->auto_backing_file);
}
out:
extent->l1_table,
l1_size);
if (ret < 0) {
+ bdrv_refresh_filename(extent->file->bs);
error_setg_errno(errp, -ret,
"Could not read l1 table from extent '%s'",
extent->file->bs->filename);
extent->l1_backup_table,
l1_size);
if (ret < 0) {
+ bdrv_refresh_filename(extent->file->bs);
error_setg_errno(errp, -ret,
"Could not read l1 backup table from extent '%s'",
extent->file->bs->filename);
ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
if (ret < 0) {
+ bdrv_refresh_filename(file->bs);
error_setg_errno(errp, -ret,
"Could not read header from file '%s'",
file->bs->filename);
ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
if (ret < 0) {
+ bdrv_refresh_filename(file->bs);
error_setg_errno(errp, -ret,
"Could not read header from file '%s'",
file->bs->filename);
if (!path_is_absolute(fname) && !path_has_protocol(fname) &&
!desc_file_path[0])
{
+ bdrv_refresh_filename(bs->file->bs);
error_setg(errp, "Cannot use relative extent paths with VMDK "
"descriptor file '%s'", bs->file->bs->filename);
return -EINVAL;
}
- extent_path = g_malloc0(PATH_MAX);
- path_combine(extent_path, PATH_MAX, desc_file_path, fname);
+ extent_path = path_combine(desc_file_path, fname);
ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);
assert(ret < 32);
VmdkGrainMarker *data = NULL;
uLongf buf_len;
QEMUIOVector local_qiov;
- struct iovec iov;
int64_t write_offset;
int64_t write_end_sector;
data->size = cpu_to_le32(buf_len);
n_bytes = buf_len + sizeof(VmdkGrainMarker);
- iov = (struct iovec) {
- .iov_base = data,
- .iov_len = n_bytes,
- };
- qemu_iovec_init_external(&local_qiov, &iov, 1);
+ qemu_iovec_init_buf(&local_qiov, data, n_bytes);
BLKDBG_EVENT(extent->file, BLKDBG_WRITE_COMPRESSED);
} else {
if (backing_file) {
BlockBackend *backing;
- char *full_backing = g_new0(char, PATH_MAX);
- bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename, backing_file,
- full_backing, PATH_MAX,
- &local_err);
+ char *full_backing =
+ bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename,
+ backing_file,
+ &local_err);
if (local_err) {
- g_free(full_backing);
error_propagate(errp, local_err);
ret = -ENOENT;
goto exit;
}
+ assert(full_backing);
backing = blk_new_open(full_backing, NULL, NULL,
BDRV_O_NO_BACKING, errp);
compat6 = qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false);
if (strcmp(hw_version, "undefined") == 0) {
g_free(hw_version);
- hw_version = g_strdup("4");
+ hw_version = NULL;
}
fmt = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
zeroed_grain = qemu_opt_get_bool_del(opts, BLOCK_OPT_ZEROED_GRAIN, false);
{
ImageInfo *info = g_new0(ImageInfo, 1);
+ bdrv_refresh_filename(extent->file->bs);
*info = (ImageInfo){
.filename = g_strdup(extent->file->bs->filename),
.format = g_strdup(extent->type),
return ret;
}
-static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs)
+static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs,
+ Error **errp)
{
int i;
BDRVVmdkState *s = bs->opaque;
return 0;
}
+static void vmdk_gather_child_options(BlockDriverState *bs, QDict *target,
+ bool backing_overridden)
+{
+ /* No children but file and backing can be explicitly specified (TODO) */
+ qdict_put(target, "file",
+ qobject_ref(bs->file->bs->full_open_options));
+
+ if (backing_overridden) {
+ if (bs->backing) {
+ qdict_put(target, "backing",
+ qobject_ref(bs->backing->bs->full_open_options));
+ } else {
+ qdict_put_null(target, "backing");
+ }
+ }
+}
+
static QemuOptsList vmdk_create_opts = {
.name = "vmdk-create-opts",
.head = QTAILQ_HEAD_INITIALIZER(vmdk_create_opts.head),
.bdrv_get_specific_info = vmdk_get_specific_info,
.bdrv_refresh_limits = vmdk_refresh_limits,
.bdrv_get_info = vmdk_get_info,
+ .bdrv_gather_child_options = vmdk_gather_child_options,
.supports_backing = true,
.create_opts = &vmdk_create_opts,
}
};
+static const char *const vpc_strong_runtime_opts[] = {
+ VPC_OPT_SIZE_CALC,
+
+ NULL
+};
+
static BlockDriver bdrv_vpc = {
.format_name = "vpc",
.instance_size = sizeof(BDRVVPCState),
.create_opts = &vpc_create_opts,
.bdrv_has_zero_init = vpc_has_zero_init,
+ .strong_runtime_opts = vpc_strong_runtime_opts,
};
static void bdrv_vpc_init(void)
}
}
+static const char *const vvfat_strong_runtime_opts[] = {
+ "dir",
+ "fat-type",
+ "floppy",
+ "label",
+ "rw",
+
+ NULL
+};
+
static BlockDriver bdrv_vvfat = {
.format_name = "vvfat",
.protocol_name = "fat",
.bdrv_co_preadv = vvfat_co_preadv,
.bdrv_co_pwritev = vvfat_co_pwritev,
.bdrv_co_block_status = vvfat_co_block_status,
+
+ .strong_runtime_opts = vvfat_strong_runtime_opts,
};
static void bdrv_vvfat_init(void)
return vdisk_size;
}
+static const char *const vxhs_strong_runtime_opts[] = {
+ VXHS_OPT_VDISK_ID,
+ "tls-creds",
+ VXHS_OPT_HOST,
+ VXHS_OPT_PORT,
+ VXHS_OPT_SERVER".",
+
+ NULL
+};
+
static BlockDriver bdrv_vxhs = {
.format_name = "vxhs",
.protocol_name = "vxhs",
.bdrv_getlength = vxhs_getlength,
.bdrv_aio_preadv = vxhs_aio_preadv,
.bdrv_aio_pwritev = vxhs_aio_pwritev,
+ .strong_runtime_opts = vxhs_strong_runtime_opts,
};
static void bdrv_vxhs_init(void)
error_setg_errno(errp, -size, "bdrv_getlength failed");
goto out;
}
+ bdrv_refresh_filename(state->old_bs);
bdrv_img_create(new_image_file, format,
state->old_bs->filename,
state->old_bs->drv->format_name,
{
BlockDriverState *bs;
BdrvDirtyBitmap *bitmap;
+ AioContext *aio_context = NULL;
if (!name || name[0] == '\0') {
error_setg(errp, "Bitmap name cannot be empty");
disabled = false;
}
- if (persistent &&
- !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
- {
- return;
+ if (persistent) {
+ aio_context = bdrv_get_aio_context(bs);
+ aio_context_acquire(aio_context);
+ if (!bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp)) {
+ goto out;
+ }
}
bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
if (bitmap == NULL) {
- return;
+ goto out;
}
if (disabled) {
}
bdrv_dirty_bitmap_set_persistance(bitmap, persistent);
+ out:
+ if (aio_context) {
+ aio_context_release(aio_context);
+ }
}
void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
BlockDriverState *bs;
BdrvDirtyBitmap *bitmap;
Error *local_err = NULL;
+ AioContext *aio_context = NULL;
bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
if (!bitmap || !bs) {
}
if (bdrv_dirty_bitmap_get_persistance(bitmap)) {
+ aio_context = bdrv_get_aio_context(bs);
+ aio_context_acquire(aio_context);
bdrv_remove_persistent_dirty_bitmap(bs, name, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
- return;
+ goto out;
}
}
bdrv_release_dirty_bitmap(bs, bitmap);
+ out:
+ if (aio_context) {
+ aio_context_release(aio_context);
+ }
}
/**
goto out;
}
assert(bdrv_get_aio_context(base_bs) == aio_context);
+ bdrv_refresh_filename(base_bs);
base_name = base_bs->filename;
}
goto out;
}
} else if (has_top && top) {
+ /* This strcmp() is just a shortcut, there is no need to
+ * refresh @bs's filename. If it mismatches,
+ * bdrv_find_backing_image() will do the refresh and may still
+ * return @bs. */
if (strcmp(bs->filename, top) != 0) {
top_bs = bdrv_find_backing_image(bs, top);
}
if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
assert(backup->format);
if (source) {
+ bdrv_refresh_filename(source);
bdrv_img_create(backup->target, backup->format, source->filename,
source->drv->format_name, NULL,
size, flags, false, &local_err);
break;
case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
/* create new image with backing file */
+ bdrv_refresh_filename(source);
bdrv_img_create(arg->target, format,
source->filename,
source->drv->format_name,
}
}
-void qemu_chr_fe_set_handlers(CharBackend *b,
- IOCanReadHandler *fd_can_read,
- IOReadHandler *fd_read,
- IOEventHandler *fd_event,
- BackendChangeHandler *be_change,
- void *opaque,
- GMainContext *context,
- bool set_open)
+void qemu_chr_fe_set_handlers_full(CharBackend *b,
+ IOCanReadHandler *fd_can_read,
+ IOReadHandler *fd_read,
+ IOEventHandler *fd_event,
+ BackendChangeHandler *be_change,
+ void *opaque,
+ GMainContext *context,
+ bool set_open,
+ bool sync_state)
{
Chardev *s;
int fe_open;
qemu_chr_fe_take_focus(b);
/* We're connecting to an already opened device, so let's make sure we
also get the open event */
- if (s->be_open) {
+ if (sync_state && s->be_open) {
qemu_chr_be_event(s, CHR_EVENT_OPENED);
}
}
+}
- if (CHARDEV_IS_MUX(s)) {
- mux_chr_set_handlers(s, context);
- }
+void qemu_chr_fe_set_handlers(CharBackend *b,
+ IOCanReadHandler *fd_can_read,
+ IOReadHandler *fd_read,
+ IOEventHandler *fd_event,
+ BackendChangeHandler *be_change,
+ void *opaque,
+ GMainContext *context,
+ bool set_open)
+{
+ qemu_chr_fe_set_handlers_full(b, fd_can_read, fd_read, fd_event, be_change,
+ opaque, context, set_open,
+ true);
}
void qemu_chr_fe_take_focus(CharBackend *b)
qemu_chr_fe_deinit(&d->chr, false);
}
-void mux_chr_set_handlers(Chardev *chr, GMainContext *context)
+static void mux_chr_update_read_handlers(Chardev *chr)
{
MuxChardev *d = MUX_CHARDEV(chr);
/* Fix up the real driver with mux routines */
- qemu_chr_fe_set_handlers(&d->chr,
- mux_chr_can_read,
- mux_chr_read,
- mux_chr_event,
- NULL,
- chr,
- context, true);
+ qemu_chr_fe_set_handlers_full(&d->chr,
+ mux_chr_can_read,
+ mux_chr_read,
+ mux_chr_event,
+ NULL,
+ chr,
+ chr->gcontext, true, false);
}
void mux_set_focus(Chardev *chr, int focus)
* mark mux as OPENED so any new FEs will immediately receive
* OPENED event
*/
- qemu_chr_be_event(chr, CHR_EVENT_OPENED);
+ chr->be_open = 1;
return 0;
}
cc->chr_add_watch = mux_chr_add_watch;
cc->chr_be_event = mux_chr_be_event;
cc->chr_machine_done = open_muxes;
+ cc->chr_update_read_handler = mux_chr_update_read_handlers;
}
static const TypeInfo char_mux_type_info = {
QIOChannel *ioc;
int read_bytes;
- /* Protected by the Chardev chr_write_lock. */
int connected;
GSource *timer_src;
- GSource *open_source;
} PtyChardev;
#define PTY_CHARDEV(obj) OBJECT_CHECK(PtyChardev, (obj), TYPE_CHARDEV_PTY)
-static void pty_chr_update_read_handler_locked(Chardev *chr);
static void pty_chr_state(Chardev *chr, int connected);
static void pty_chr_timer_cancel(PtyChardev *s)
}
}
-static void pty_chr_open_src_cancel(PtyChardev *s)
-{
- if (s->open_source) {
- g_source_destroy(s->open_source);
- g_source_unref(s->open_source);
- s->open_source = NULL;
- }
-}
-
static gboolean pty_chr_timer(gpointer opaque)
{
struct Chardev *chr = CHARDEV(opaque);
PtyChardev *s = PTY_CHARDEV(opaque);
- qemu_mutex_lock(&chr->chr_write_lock);
pty_chr_timer_cancel(s);
- pty_chr_open_src_cancel(s);
if (!s->connected) {
/* Next poll ... */
- pty_chr_update_read_handler_locked(chr);
+ qemu_chr_be_update_read_handlers(chr, chr->gcontext);
}
- qemu_mutex_unlock(&chr->chr_write_lock);
return FALSE;
}
-/* Called with chr_write_lock held. */
static void pty_chr_rearm_timer(Chardev *chr, int ms)
{
PtyChardev *s = PTY_CHARDEV(chr);
g_free(name);
}
-/* Called with chr_write_lock held. */
-static void pty_chr_update_read_handler_locked(Chardev *chr)
+static void pty_chr_update_read_handler(Chardev *chr)
{
PtyChardev *s = PTY_CHARDEV(chr);
GPollFD pfd;
}
}
-static void pty_chr_update_read_handler(Chardev *chr)
-{
- qemu_mutex_lock(&chr->chr_write_lock);
- pty_chr_update_read_handler_locked(chr);
- qemu_mutex_unlock(&chr->chr_write_lock);
-}
-
-/* Called with chr_write_lock held. */
static int char_pty_chr_write(Chardev *chr, const uint8_t *buf, int len)
{
PtyChardev *s = PTY_CHARDEV(chr);
if (!s->connected) {
- /* guest sends data, check for (re-)connect */
- pty_chr_update_read_handler_locked(chr);
- if (!s->connected) {
- return len;
- }
+ return len;
}
return io_channel_send(s->ioc, buf, len);
}
return TRUE;
}
-static gboolean qemu_chr_be_generic_open_func(gpointer opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- PtyChardev *s = PTY_CHARDEV(opaque);
-
- s->open_source = NULL;
- qemu_chr_be_event(chr, CHR_EVENT_OPENED);
- return FALSE;
-}
-
-/* Called with chr_write_lock held. */
static void pty_chr_state(Chardev *chr, int connected)
{
PtyChardev *s = PTY_CHARDEV(chr);
if (!connected) {
- pty_chr_open_src_cancel(s);
remove_fd_in_watch(chr);
s->connected = 0;
/* (re-)connect poll interval for idle guests: once per second.
} else {
pty_chr_timer_cancel(s);
if (!s->connected) {
- g_assert(s->open_source == NULL);
- s->open_source = g_idle_source_new();
s->connected = 1;
- g_source_set_callback(s->open_source,
- qemu_chr_be_generic_open_func,
- chr, NULL);
- g_source_attach(s->open_source, chr->gcontext);
+ qemu_chr_be_event(chr, CHR_EVENT_OPENED);
}
if (!chr->gsource) {
chr->gsource = io_add_watch_poll(chr, s->ioc,
Chardev *chr = CHARDEV(obj);
PtyChardev *s = PTY_CHARDEV(obj);
- qemu_mutex_lock(&chr->chr_write_lock);
pty_chr_state(chr, 0);
object_unref(OBJECT(s->ioc));
pty_chr_timer_cancel(s);
- qemu_mutex_unlock(&chr->chr_write_lock);
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
static void tty_serial_init(int fd, int speed,
int parity, int data_bits, int stop_bits)
{
- struct termios tty;
+ struct termios tty = {0};
speed_t spd;
#if 0
size_t buflen;
} TCPChardevTelnetInit;
+typedef enum {
+ TCP_CHARDEV_STATE_DISCONNECTED,
+ TCP_CHARDEV_STATE_CONNECTING,
+ TCP_CHARDEV_STATE_CONNECTED,
+} TCPChardevState;
+
typedef struct {
Chardev parent;
QIOChannel *ioc; /* Client I/O channel */
QIONetListener *listener;
GSource *hup_source;
QCryptoTLSCreds *tls_creds;
- int connected;
+ TCPChardevState state;
int max_size;
int do_telnetopt;
int do_nodelay;
GSource *reconnect_timer;
int64_t reconnect_time;
bool connect_err_reported;
+
+ QIOTask *connect_task;
} SocketChardev;
#define SOCKET_CHARDEV(obj) \
static gboolean socket_reconnect_timeout(gpointer opaque);
static void tcp_chr_telnet_init(Chardev *chr);
+static void tcp_chr_change_state(SocketChardev *s, TCPChardevState state)
+{
+ switch (state) {
+ case TCP_CHARDEV_STATE_DISCONNECTED:
+ break;
+ case TCP_CHARDEV_STATE_CONNECTING:
+ assert(s->state == TCP_CHARDEV_STATE_DISCONNECTED);
+ break;
+ case TCP_CHARDEV_STATE_CONNECTED:
+ assert(s->state == TCP_CHARDEV_STATE_CONNECTING);
+ break;
+ }
+ s->state = state;
+}
+
static void tcp_chr_reconn_timer_cancel(SocketChardev *s)
{
if (s->reconnect_timer) {
SocketChardev *s = SOCKET_CHARDEV(chr);
char *name;
- assert(s->connected == 0);
+ assert(s->state == TCP_CHARDEV_STATE_DISCONNECTED);
+ assert(!s->reconnect_timer);
name = g_strdup_printf("chardev-socket-reconnect-%s", chr->label);
s->reconnect_timer = qemu_chr_timeout_add_ms(chr,
s->reconnect_time * 1000,
{
SocketChardev *s = SOCKET_CHARDEV(chr);
- if (s->connected) {
+ if (s->state == TCP_CHARDEV_STATE_CONNECTED) {
int ret = io_channel_send_full(s->ioc, buf, len,
s->write_msgfds,
s->write_msgfds_num);
{
Chardev *chr = CHARDEV(opaque);
SocketChardev *s = SOCKET_CHARDEV(opaque);
- if (!s->connected) {
+ if (s->state != TCP_CHARDEV_STATE_CONNECTED) {
return 0;
}
s->max_size = qemu_chr_be_can_write(chr);
s->write_msgfds = NULL;
s->write_msgfds_num = 0;
- if (!s->connected ||
+ if ((s->state != TCP_CHARDEV_STATE_CONNECTED) ||
!qio_channel_has_feature(s->ioc,
QIO_CHANNEL_FEATURE_FD_PASS)) {
return -1;
s->ioc = NULL;
g_free(chr->filename);
chr->filename = NULL;
- s->connected = 0;
+ tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
}
static const char *qemu_chr_socket_protocol(SocketChardev *s)
/* NB may be called even if tcp_chr_connect has not been
* reached, due to TLS or telnet initialization failure,
- * so can *not* assume s->connected == true
+ * so can *not* assume s->state == TCP_CHARDEV_STATE_CONNECTED
*/
static void tcp_chr_disconnect(Chardev *chr)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
- bool emit_close = s->connected;
+ bool emit_close = s->state == TCP_CHARDEV_STATE_CONNECTED;
tcp_chr_free_connection(chr);
uint8_t buf[CHR_READ_BUF_LEN];
int len, size;
- if (!s->connected || s->max_size <= 0) {
+ if ((s->state != TCP_CHARDEV_STATE_CONNECTED) ||
+ s->max_size <= 0) {
return TRUE;
}
len = sizeof(buf);
SocketChardev *s = SOCKET_CHARDEV(chr);
int size;
- if (!s->connected) {
+ if (s->state != TCP_CHARDEV_STATE_CONNECTED) {
return 0;
}
{
Chardev *chr = CHARDEV(s);
- if (!s->connected) {
+ if (s->state != TCP_CHARDEV_STATE_CONNECTED) {
return;
}
g_free(chr->filename);
chr->filename = qemu_chr_compute_filename(s);
- s->connected = 1;
+ tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTED);
update_ioc_handlers(s);
qemu_chr_be_event(chr, CHR_EVENT_OPENED);
}
{
SocketChardev *s = SOCKET_CHARDEV(chr);
- if (s->ioc != NULL) {
+ if (s->state != TCP_CHARDEV_STATE_CONNECTING) {
return -1;
}
{
int ret;
QIOChannelSocket *sioc;
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+
+ if (s->state != TCP_CHARDEV_STATE_DISCONNECTED) {
+ return -1;
+ }
sioc = qio_channel_socket_new_fd(fd, NULL);
if (!sioc) {
return -1;
}
+ tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
tcp_chr_set_client_ioc_name(chr, sioc);
ret = tcp_chr_new_client(chr, sioc);
object_unref(OBJECT(sioc));
void *opaque)
{
Chardev *chr = CHARDEV(opaque);
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
tcp_chr_set_client_ioc_name(chr, cioc);
tcp_chr_new_client(chr, cioc);
}
-static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
+
+static int tcp_chr_connect_client_sync(Chardev *chr, Error **errp)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ QIOChannelSocket *sioc = qio_channel_socket_new();
+ tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
+ tcp_chr_set_client_ioc_name(chr, sioc);
+ if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
+ tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
+ object_unref(OBJECT(sioc));
+ return -1;
+ }
+ tcp_chr_new_client(chr, sioc);
+ object_unref(OBJECT(sioc));
+ return 0;
+}
+
+
+static void tcp_chr_accept_server_sync(Chardev *chr)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
QIOChannelSocket *sioc;
+ info_report("QEMU waiting for connection on: %s",
+ chr->filename);
+ tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
+ sioc = qio_net_listener_wait_client(s->listener);
+ tcp_chr_set_client_ioc_name(chr, sioc);
+ tcp_chr_new_client(chr, sioc);
+ object_unref(OBJECT(sioc));
+}
+
- /* It can't wait on s->connected, since it is set asynchronously
- * in TLS and telnet cases, only wait for an accepted socket */
- while (!s->ioc) {
+static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ const char *opts[] = { "telnet", "tn3270", "websock", "tls-creds" };
+ bool optset[] = { s->is_telnet, s->is_tn3270, s->is_websock, s->tls_creds };
+ size_t i;
+
+ QEMU_BUILD_BUG_ON(G_N_ELEMENTS(opts) != G_N_ELEMENTS(optset));
+ for (i = 0; i < G_N_ELEMENTS(opts); i++) {
+ if (optset[i]) {
+ error_setg(errp,
+ "'%s' option is incompatible with waiting for "
+ "connection completion", opts[i]);
+ return -1;
+ }
+ }
+
+ tcp_chr_reconn_timer_cancel(s);
+
+ /*
+ * We expect states to be as follows:
+ *
+ * - server
+ * - wait -> CONNECTED
+ * - nowait -> DISCONNECTED
+ * - client
+ * - reconnect == 0 -> CONNECTED
+ * - reconnect != 0 -> CONNECTING
+ *
+ */
+ if (s->state == TCP_CHARDEV_STATE_CONNECTING) {
+ if (!s->connect_task) {
+ error_setg(errp,
+ "Unexpected 'connecting' state without connect task "
+ "while waiting for connection completion");
+ return -1;
+ }
+ /*
+ * tcp_chr_wait_connected should only ever be run from the
+ * main loop thread associated with chr->gcontext, otherwise
+ * qio_task_wait_thread has a dangerous race condition with
+ * free'ing of the s->connect_task object.
+ *
+ * Acquiring the main context doesn't 100% prove we're in
+ * the main loop thread, but it does at least guarantee
+ * that the main loop won't be executed by another thread
+ * avoiding the race condition with the task idle callback.
+ */
+ g_main_context_acquire(chr->gcontext);
+ qio_task_wait_thread(s->connect_task);
+ g_main_context_release(chr->gcontext);
+
+ /*
+ * The completion callback (qemu_chr_socket_connected) for
+ * s->connect_task should have set this to NULL by the time
+ * qio_task_wait_thread has returned.
+ */
+ assert(!s->connect_task);
+
+ /*
+ * NB we are *not* guaranteed to have "s->state == ..CONNECTED"
+ * at this point as this first connect may be failed, so
+ * allow the next loop to run regardless.
+ */
+ }
+
+ while (s->state != TCP_CHARDEV_STATE_CONNECTED) {
if (s->is_listen) {
- info_report("QEMU waiting for connection on: %s",
- chr->filename);
- sioc = qio_net_listener_wait_client(s->listener);
- tcp_chr_set_client_ioc_name(chr, sioc);
- tcp_chr_new_client(chr, sioc);
- object_unref(OBJECT(sioc));
+ tcp_chr_accept_server_sync(chr);
} else {
- sioc = qio_channel_socket_new();
- tcp_chr_set_client_ioc_name(chr, sioc);
- if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
- object_unref(OBJECT(sioc));
- return -1;
+ Error *err = NULL;
+ if (tcp_chr_connect_client_sync(chr, &err) < 0) {
+ if (s->reconnect_time) {
+ error_free(err);
+ g_usleep(s->reconnect_time * 1000ULL * 1000ULL);
+ } else {
+ error_propagate(errp, err);
+ return -1;
+ }
}
- tcp_chr_new_client(chr, sioc);
- object_unref(OBJECT(sioc));
}
}
SocketChardev *s = SOCKET_CHARDEV(chr);
Error *err = NULL;
+ s->connect_task = NULL;
+
if (qio_task_propagate_error(task, &err)) {
+ tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
check_report_connect_error(chr, err);
error_free(err);
goto cleanup;
object_unref(OBJECT(sioc));
}
-static void tcp_chr_connect_async(Chardev *chr)
+
+static void tcp_chr_connect_client_task(QIOTask *task,
+ gpointer opaque)
+{
+ QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
+ SocketAddress *addr = opaque;
+ Error *err = NULL;
+
+ qio_channel_socket_connect_sync(ioc, addr, &err);
+
+ qio_task_set_error(task, err);
+}
+
+
+static void tcp_chr_connect_client_async(Chardev *chr)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
QIOChannelSocket *sioc;
+ tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
sioc = qio_channel_socket_new();
tcp_chr_set_client_ioc_name(chr, sioc);
- qio_channel_socket_connect_async(sioc, s->addr,
- qemu_chr_socket_connected,
- chr, NULL, chr->gcontext);
+ /*
+ * Normally code would use the qio_channel_socket_connect_async
+ * method which uses a QIOTask + qio_task_set_error internally
+ * to avoid blocking. The tcp_chr_wait_connected method, however,
+ * needs a way to synchronize with completion of the background
+ * connect task which can't be done with the QIOChannelSocket
+ * async APIs. Thus we must use QIOTask directly to implement
+ * the non-blocking concept locally.
+ */
+ s->connect_task = qio_task_new(OBJECT(sioc),
+ qemu_chr_socket_connected,
+ chr, NULL);
+ qio_task_run_in_thread(s->connect_task,
+ tcp_chr_connect_client_task,
+ s->addr,
+ NULL,
+ chr->gcontext);
}
static gboolean socket_reconnect_timeout(gpointer opaque)
return false;
}
- tcp_chr_connect_async(chr);
+ tcp_chr_connect_client_async(chr);
return false;
}
+
+static int qmp_chardev_open_socket_server(Chardev *chr,
+ bool is_telnet,
+ bool is_waitconnect,
+ Error **errp)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ char *name;
+ if (is_telnet) {
+ s->do_telnetopt = 1;
+ }
+ s->listener = qio_net_listener_new();
+
+ name = g_strdup_printf("chardev-tcp-listener-%s", chr->label);
+ qio_net_listener_set_name(s->listener, name);
+ g_free(name);
+
+ if (qio_net_listener_open_sync(s->listener, s->addr, errp) < 0) {
+ object_unref(OBJECT(s->listener));
+ s->listener = NULL;
+ return -1;
+ }
+
+ qapi_free_SocketAddress(s->addr);
+ s->addr = socket_local_address(s->listener->sioc[0]->fd, errp);
+ update_disconnected_filename(s);
+
+ if (is_waitconnect) {
+ tcp_chr_accept_server_sync(chr);
+ } else {
+ qio_net_listener_set_client_func_full(s->listener,
+ tcp_chr_accept,
+ chr, NULL,
+ chr->gcontext);
+ }
+
+ return 0;
+}
+
+
+static int qmp_chardev_open_socket_client(Chardev *chr,
+ int64_t reconnect,
+ Error **errp)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+
+ if (reconnect > 0) {
+ s->reconnect_time = reconnect;
+ tcp_chr_connect_client_async(chr);
+ return 0;
+ } else {
+ return tcp_chr_connect_client_sync(chr, errp);
+ }
+}
+
+
+static bool qmp_chardev_validate_socket(ChardevSocket *sock,
+ SocketAddress *addr,
+ Error **errp)
+{
+ /* Validate any options which have a dependency on address type */
+ switch (addr->type) {
+ case SOCKET_ADDRESS_TYPE_FD:
+ if (sock->has_reconnect) {
+ error_setg(errp,
+ "'reconnect' option is incompatible with "
+ "'fd' address type");
+ return false;
+ }
+ if (sock->has_tls_creds &&
+ !(sock->has_server && sock->server)) {
+ error_setg(errp,
+ "'tls_creds' option is incompatible with "
+ "'fd' address type as client");
+ return false;
+ }
+ break;
+
+ case SOCKET_ADDRESS_TYPE_UNIX:
+ if (sock->has_tls_creds) {
+ error_setg(errp,
+ "'tls_creds' option is incompatible with "
+ "'unix' address type");
+ return false;
+ }
+ break;
+
+ case SOCKET_ADDRESS_TYPE_INET:
+ break;
+
+ case SOCKET_ADDRESS_TYPE_VSOCK:
+ if (sock->has_tls_creds) {
+ error_setg(errp,
+ "'tls_creds' option is incompatible with "
+ "'vsock' address type");
+ return false;
+ }
+
+ default:
+ break;
+ }
+
+ /* Validate any options which have a dependancy on client vs server */
+ if (!sock->has_server || sock->server) {
+ if (sock->has_reconnect) {
+ error_setg(errp,
+ "'reconnect' option is incompatible with "
+ "socket in server listen mode");
+ return false;
+ }
+ } else {
+ if (sock->has_websocket && sock->websocket) {
+ error_setg(errp, "%s", "Websocket client is not implemented");
+ return false;
+ }
+ if (sock->has_wait) {
+ error_setg(errp, "%s",
+ "'wait' option is incompatible with "
+ "socket in client connect mode");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
static void qmp_chardev_open_socket(Chardev *chr,
ChardevBackend *backend,
bool *be_opened,
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;
if (!creds) {
error_setg(errp, "No TLS credentials with id '%s'",
sock->tls_creds);
- goto error;
+ return;
}
s->tls_creds = (QCryptoTLSCreds *)
object_dynamic_cast(creds,
if (!s->tls_creds) {
error_setg(errp, "Object with id '%s' is not TLS credentials",
sock->tls_creds);
- goto error;
+ return;
}
object_ref(OBJECT(s->tls_creds));
if (is_listen) {
if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
error_setg(errp, "%s",
"Expected TLS credentials for server endpoint");
- goto error;
+ return;
}
} else {
if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
error_setg(errp, "%s",
"Expected TLS credentials for client endpoint");
- goto error;
+ return;
}
}
}
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;
+ if (!qmp_chardev_validate_socket(sock, addr, errp)) {
+ return;
}
+
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) {
update_disconnected_filename(s);
- if (is_listen) {
- if (is_telnet || is_tn3270) {
- s->do_telnetopt = 1;
+ if (s->is_listen) {
+ if (qmp_chardev_open_socket_server(chr, is_telnet || is_tn3270,
+ is_waitconnect, errp) < 0) {
+ return;
}
- } else if (reconnect > 0) {
- s->reconnect_time = reconnect;
- }
-
- if (s->reconnect_time) {
- tcp_chr_connect_async(chr);
} else {
- if (s->is_listen) {
- char *name;
- s->listener = qio_net_listener_new();
-
- name = g_strdup_printf("chardev-tcp-listener-%s", chr->label);
- qio_net_listener_set_name(s->listener, name);
- g_free(name);
-
- if (qio_net_listener_open_sync(s->listener, s->addr, errp) < 0) {
- object_unref(OBJECT(s->listener));
- s->listener = NULL;
- goto error;
- }
-
- qapi_free_SocketAddress(s->addr);
- s->addr = socket_local_address(s->listener->sioc[0]->fd, errp);
- update_disconnected_filename(s);
-
- if (is_waitconnect &&
- qemu_chr_wait_connected(chr, errp) < 0) {
- return;
- }
- if (!s->ioc) {
- qio_net_listener_set_client_func_full(s->listener,
- tcp_chr_accept,
- chr, NULL,
- chr->gcontext);
- }
- } else if (qemu_chr_wait_connected(chr, errp) < 0) {
- goto error;
+ if (qmp_chardev_open_socket_client(chr, reconnect, errp) < 0) {
+ return;
}
}
-
- return;
-
-error:
- if (sioc) {
- object_unref(OBJECT(sioc));
- }
}
static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
{
- bool is_listen = qemu_opt_get_bool(opts, "server", false);
- 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");
const char *host = qemu_opt_get(opts, "host");
const char *port = qemu_opt_get(opts, "port");
const char *fd = qemu_opt_get(opts, "fd");
- const char *tls_creds = qemu_opt_get(opts, "tls-creds");
SocketAddressLegacy *addr;
ChardevSocket *sock;
return;
}
- backend->type = CHARDEV_BACKEND_KIND_SOCKET;
- if (path) {
- if (tls_creds) {
- error_setg(errp, "TLS can only be used over TCP socket");
- return;
- }
- } else if (host) {
- if (!port) {
- error_setg(errp, "chardev: socket: no port given");
- return;
- }
- } else if (fd) {
- /* We don't know what host to validate against when in client mode */
- if (tls_creds && !is_listen) {
- error_setg(errp, "TLS can not be used with pre-opened client FD");
- return;
- }
- } else {
- g_assert_not_reached();
+ if (host && !port) {
+ error_setg(errp, "chardev: socket: no port given");
+ return;
}
+ backend->type = CHARDEV_BACKEND_KIND_SOCKET;
sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
- sock->has_nodelay = true;
- sock->nodelay = do_nodelay;
+ sock->has_nodelay = qemu_opt_get(opts, "delay");
+ sock->nodelay = !qemu_opt_get_bool(opts, "delay", true);
+ /*
+ * We have different default to QMP for 'server', hence
+ * we can't just check for existence of 'server'
+ */
sock->has_server = true;
- sock->server = is_listen;
- sock->has_telnet = true;
- 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->server = qemu_opt_get_bool(opts, "server", false);
+ sock->has_telnet = qemu_opt_get(opts, "telnet");
+ sock->telnet = qemu_opt_get_bool(opts, "telnet", false);
+ sock->has_tn3270 = qemu_opt_get(opts, "tn3270");
+ sock->tn3270 = qemu_opt_get_bool(opts, "tn3270", false);
+ sock->has_websocket = qemu_opt_get(opts, "websocket");
+ sock->websocket = qemu_opt_get_bool(opts, "websocket", false);
+ /*
+ * We have different default to QMP for 'wait' when 'server'
+ * is set, hence we can't just check for existence of 'wait'
+ */
+ sock->has_wait = qemu_opt_find(opts, "wait") || sock->server;
+ sock->wait = qemu_opt_get_bool(opts, "wait", true);
sock->has_reconnect = qemu_opt_find(opts, "reconnect");
- sock->reconnect = reconnect;
- sock->tls_creds = g_strdup(tls_creds);
+ sock->reconnect = qemu_opt_get_number(opts, "reconnect", 0);
+ sock->has_tls_creds = qemu_opt_get(opts, "tls-creds");
+ sock->tls_creds = g_strdup(qemu_opt_get(opts, "tls-creds"));
addr = g_new0(SocketAddressLegacy, 1);
if (path) {
{
SocketChardev *s = SOCKET_CHARDEV(obj);
- return s->connected;
+ return s->state == TCP_CHARDEV_STATE_CONNECTED;
}
static void char_socket_class_init(ObjectClass *oc, void *data)
return opts;
}
+ error_report("'%s' is not a valid char driver", filename);
+
fail:
qemu_opts_del(opts);
return NULL;
return backend;
}
-Chardev *qemu_chr_new_from_opts(QemuOpts *opts, Error **errp)
+Chardev *qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context,
+ Error **errp)
{
const ChardevClass *cc;
Chardev *chr = NULL;
chr = qemu_chardev_new(bid ? bid : id,
object_class_get_name(OBJECT_CLASS(cc)),
- backend, errp);
+ backend, context, errp);
if (chr == NULL) {
goto out;
backend->type = CHARDEV_BACKEND_KIND_MUX;
backend->u.mux.data = g_new0(ChardevMux, 1);
backend->u.mux.data->chardev = g_strdup(bid);
- mux = qemu_chardev_new(id, TYPE_CHARDEV_MUX, backend, errp);
+ mux = qemu_chardev_new(id, TYPE_CHARDEV_MUX, backend, context, errp);
if (mux == NULL) {
object_unparent(OBJECT(chr));
chr = NULL;
}
Chardev *qemu_chr_new_noreplay(const char *label, const char *filename,
- bool permit_mux_mon)
+ bool permit_mux_mon, GMainContext *context)
{
const char *p;
Chardev *chr;
if (!opts)
return NULL;
- chr = qemu_chr_new_from_opts(opts, &err);
+ chr = qemu_chr_new_from_opts(opts, context, &err);
if (!chr) {
error_report_err(err);
goto out;
static Chardev *qemu_chr_new_permit_mux_mon(const char *label,
const char *filename,
- bool permit_mux_mon)
+ bool permit_mux_mon,
+ GMainContext *context)
{
Chardev *chr;
- chr = qemu_chr_new_noreplay(label, filename, permit_mux_mon);
+ chr = qemu_chr_new_noreplay(label, filename, permit_mux_mon, context);
if (chr) {
if (replay_mode != REPLAY_MODE_NONE) {
qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_REPLAY);
return chr;
}
-Chardev *qemu_chr_new(const char *label, const char *filename)
+Chardev *qemu_chr_new(const char *label, const char *filename,
+ GMainContext *context)
{
- return qemu_chr_new_permit_mux_mon(label, filename, false);
+ return qemu_chr_new_permit_mux_mon(label, filename, false, context);
}
-Chardev *qemu_chr_new_mux_mon(const char *label, const char *filename)
+Chardev *qemu_chr_new_mux_mon(const char *label, const char *filename,
+ GMainContext *context)
{
- return qemu_chr_new_permit_mux_mon(label, filename, true);
+ return qemu_chr_new_permit_mux_mon(label, filename, true, context);
}
static int qmp_query_chardev_foreach(Object *obj, void *data)
Chardev *qemu_chardev_new(const char *id, const char *typename,
ChardevBackend *backend,
+ GMainContext *gcontext,
Error **errp)
{
Object *obj;
obj = object_new(typename);
chr = CHARDEV(obj);
chr->label = g_strdup(id);
+ chr->gcontext = gcontext;
qemu_char_open(chr, backend, &be_opened, &local_err);
if (local_err) {
}
chr = qemu_chardev_new(id, object_class_get_name(OBJECT_CLASS(cc)),
- backend, errp);
+ backend, NULL, errp);
if (!chr) {
return NULL;
}
}
chr_new = qemu_chardev_new(NULL, object_class_get_name(OBJECT_CLASS(cc)),
- backend, errp);
+ backend, chr->gcontext, errp);
if (!chr_new) {
return NULL;
}
#include "trace.h"
#include "ui/qemu-spice.h"
#include "chardev/char.h"
+#include "chardev/spice.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/option.h"
-#include <spice.h>
#include <spice/protocol.h>
-
-typedef struct SpiceChardev {
- Chardev parent;
-
- SpiceCharDeviceInstance sin;
- bool active;
- bool blocked;
- const uint8_t *datapos;
- int datalen;
- QLIST_ENTRY(SpiceChardev) next;
-} SpiceChardev;
-
-#define TYPE_CHARDEV_SPICE "chardev-spice"
-#define TYPE_CHARDEV_SPICEVMC "chardev-spicevmc"
-#define TYPE_CHARDEV_SPICEPORT "chardev-spiceport"
-
-#define SPICE_CHARDEV(obj) OBJECT_CHECK(SpiceChardev, (obj), TYPE_CHARDEV_SPICE)
-
typedef struct SpiceCharSource {
GSource source;
SpiceChardev *scd;
static gboolean spice_char_source_prepare(GSource *source, gint *timeout)
{
SpiceCharSource *src = (SpiceCharSource *)source;
+ Chardev *chr = CHARDEV(src->scd);
*timeout = -1;
+ if (!chr->be_open) {
+ return true;
+ }
+
return !src->scd->blocked;
}
static gboolean spice_char_source_check(GSource *source)
{
SpiceCharSource *src = (SpiceCharSource *)source;
+ Chardev *chr = CHARDEV(src->scd);
+
+ if (!chr->be_open) {
+ return true;
+ }
return !src->scd->blocked;
}
static gboolean spice_char_source_dispatch(GSource *source,
GSourceFunc callback, gpointer user_data)
{
+ SpiceCharSource *src = (SpiceCharSource *)source;
+ Chardev *chr = CHARDEV(src->scd);
GIOFunc func = (GIOFunc)callback;
+ GIOCondition cond = chr->be_open ? G_IO_OUT : G_IO_HUP;
- return func(NULL, G_IO_OUT, user_data);
+ return func(NULL, cond, user_data);
}
static GSourceFuncs SpiceCharSourceFuncs = {
int read_bytes;
assert(s->datalen == 0);
+
+ if (!chr->be_open) {
+ trace_spice_chr_discard_write(len);
+ return len;
+ }
+
s->datapos = buf;
s->datalen = len;
spice_server_char_device_wakeup(&s->sin);
}
*be_opened = false;
+#if SPICE_SERVER_VERSION < 0x000e02
+ /* Spice < 0.14.2 doesn't explicitly open smartcard chardev */
+ if (strcmp(type, "smartcard") == 0) {
+ *be_opened = true;
+ }
+#endif
chr_open(chr, type);
}
-static void qemu_chr_open_spice_port(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
+void qemu_chr_open_spice_port(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
{
ChardevSpicePort *spiceport = backend->u.spiceport.data;
const char *name = spiceport->fqdn;
*be_opened = false;
s = SPICE_CHARDEV(chr);
s->sin.portname = g_strdup(name);
+
+ if (using_spice) {
+ /* spice server already created */
+ vmc_register_interface(s);
+ }
}
void qemu_spice_register_ports(void)
wct_speed(int speed) "%d"
# chardev/spice.c
+spice_chr_discard_write(int len) "spice chr write discarded %d"
spice_vmc_write(ssize_t out, int len) "spice wrote %zd of requested %d"
spice_vmc_read(int bytes, int len) "spice read %d of requested %d"
spice_vmc_register_interface(void *scd) "spice vmc registered interface %p"
}
static QemuInputHandler wctablet_handler = {
- .name = "QEMU Wacome Pen Tablet",
+ .name = "QEMU Wacom Pen Tablet",
.mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
.event = wctablet_input_event,
.sync = wctablet_input_sync,
nettle=""
gcrypt=""
gcrypt_hmac="no"
+auth_pam=""
vte=""
virglrenderer=""
tpm="yes"
;;
NetBSD)
bsd="yes"
+ hax="yes"
make="${MAKE-gmake}"
audio_drv_list="oss try-sdl"
audio_possible_drivers="oss sdl"
LIBS="-lposix_error_mapper -lnetwork $LIBS"
;;
Linux)
- audio_drv_list="try-pa try-alsa try-sdl oss"
+ audio_drv_list="try-pa oss"
audio_possible_drivers="oss alsa sdl pa"
linux="yes"
linux_user="yes"
;;
--enable-gcrypt) gcrypt="yes"
;;
+ --disable-auth-pam) auth_pam="no"
+ ;;
+ --enable-auth-pam) auth_pam="yes"
+ ;;
--enable-rdma) rdma="yes"
;;
--disable-rdma) rdma="no"
gnutls GNUTLS cryptography support
nettle nettle cryptography support
gcrypt libgcrypt cryptography support
+ auth-pam PAM access control
sdl SDL UI
sdl_image SDL Image support for icons
gtk gtk UI
virglrenderer virgl rendering support
xfsctl xfsctl support
qom-cast-debug cast debugging support
- tools build qemu-io, qemu-nbd and qemu-image tools
+ tools build qemu-io, qemu-nbd and qemu-img tools
vxhs Veritas HyperScale vDisk backend support
bochs bochs image format support
cloop cloop image format support
# Consult white-list to determine whether to enable werror
# by default. Only enable by default for git builds
if test -z "$werror" ; then
- if test -d "$source_path/.git" -a \
- \( "$linux" = "yes" -o "$mingw32" = "yes" \) ; then
+ if test -d "$source_path/.git" && \
+ { test "$linux" = "yes" || test "$mingw32" = "yes"; }; then
werror="yes"
else
werror="no"
gcc_flags="-Wendif-labels -Wno-shift-negative-value $gcc_flags"
gcc_flags="-Wno-initializer-overrides -Wexpansion-to-defined $gcc_flags"
gcc_flags="-Wno-string-plus-int $gcc_flags"
-gcc_flags="-Wno-error=address-of-packed-member $gcc_flags"
# Note that we do not add -Werror to gcc_flags here, because that would
# enable it for all configure tests. If a configure test failed due
# to -Werror this would just silently disable some features,
fi
+##########################################
+# PAM probe
+
+if test "$auth_pam" != "no"; then
+ cat > $TMPC <<EOF
+#include <security/pam_appl.h>
+#include <stdio.h>
+int main(void) {
+ const char *service_name = "qemu";
+ const char *user = "frank";
+ const struct pam_conv *pam_conv = NULL;
+ pam_handle_t *pamh = NULL;
+ pam_start(service_name, user, pam_conv, &pamh);
+ return 0;
+}
+EOF
+ if compile_prog "" "-lpam" ; then
+ auth_pam=yes
+ else
+ if test "$auth_pam" = "yes"; then
+ feature_not_found "PAM" "Install PAM development package"
+ else
+ auth_pam=no
+ fi
+ fi
+fi
+
##########################################
# getifaddrs (for tests/test-io-channel-socket )
sdl=yes
# static link with sdl ? (note: sdl.pc's --static --libs is broken)
- if test "$sdl" = "yes" -a "$static" = "yes" ; then
+ if test "$sdl" = "yes" && test "$static" = "yes" ; then
if test $? = 0 && echo $sdl_libs | grep -- -laa > /dev/null; then
sdl_libs="$sdl_libs $(aalib-config --static-libs 2>/dev/null)"
sdl_cflags="$sdl_cflags $(aalib-config --cflags 2>/dev/null)"
##########################################
# VNC SASL detection
-if test "$vnc" = "yes" -a "$vnc_sasl" != "no" ; then
+if test "$vnc" = "yes" && test "$vnc_sasl" != "no" ; then
cat > $TMPC <<EOF
#include <sasl/sasl.h>
#include <stdio.h>
##########################################
# VNC JPEG detection
-if test "$vnc" = "yes" -a "$vnc_jpeg" != "no" ; then
+if test "$vnc" = "yes" && test "$vnc_jpeg" != "no" ; then
cat > $TMPC <<EOF
#include <stdio.h>
#include <jpeglib.h>
##########################################
# VNC PNG detection
-if test "$vnc" = "yes" -a "$vnc_png" != "no" ; then
+if test "$vnc" = "yes" && test "$vnc_png" != "no" ; then
cat > $TMPC <<EOF
//#include <stdio.h>
#include <png.h>
fi
fi
-##########################################
-# fnmatch() probe, used for ACL routines
-fnmatch="no"
-cat > $TMPC << EOF
-#include <fnmatch.h>
-int main(void)
-{
- fnmatch("foo", "foo", 0);
- return 0;
-}
-EOF
-if compile_prog "" "" ; then
- fnmatch="yes"
-fi
##########################################
# xfsctl() probe, used for file-posix.c
oss_libs="$oss_lib"
;;
- wav)
- # XXX: Probes for CoreAudio, DirectSound
- ;;
-
*)
echo "$audio_possible_drivers" | grep -q "\<$drv\>" || {
error_exit "Unknown driver '$drv' selected" \
# This workaround is required due to a bug in pkg-config file for glib as it
# doesn't define GLIB_STATIC_COMPILATION for pkg-config --static
-if test "$static" = yes -a "$mingw32" = yes; then
+if test "$static" = yes && test "$mingw32" = yes; then
QEMU_CFLAGS="-DGLIB_STATIC_COMPILATION $QEMU_CFLAGS"
fi
fi
done
+if $pkg_config --atleast-version=$glib_req_ver gio-2.0; then
+ gio=yes
+ gio_cflags=$($pkg_config --cflags gio-2.0)
+ gio_libs=$($pkg_config --libs gio-2.0)
+else
+ gio=no
+fi
+
# Sanity check that the current size_t matches the
# size that glib thinks it should be. This catches
# problems on multi-arch where people try to build
##########################################
# pixman support probe
-if test "$want_tools" = "no" -a "$softmmu" = "no"; then
+if test "$want_tools" = "no" && test "$softmmu" = "no"; then
pixman_cflags=
pixman_libs=
elif $pkg_config --atleast-version=0.21.8 pixman-1 > /dev/null 2>&1; then
done
fi
-if test "$mingw32" != yes -a "$pthread" = no; then
+if test "$mingw32" != yes && test "$pthread" = no; then
error_exit "pthread check failed" \
"Make sure to have the pthread libs and headers installed."
fi
##########################################
# TPM passthrough is only on x86 Linux
-if test "$targetos" = Linux && test "$cpu" = i386 -o "$cpu" = x86_64; then
+if test "$targetos" = Linux && { test "$cpu" = i386 || test "$cpu" = x86_64; }; then
tpm_passthrough=$tpm
else
tpm_passthrough=no
fi
fi
-if test "$opengl" = "yes" -a "$have_x11" = "yes"; then
+if test "$opengl" = "yes" && test "$have_x11" = "yes"; then
for target in $target_list; do
case $target in
lm32-softmmu) # milkymist-tmu2 requires X11 and OpenGL
# check for usbfs
have_usbfs=no
if test "$linux_user" = "yes"; then
- if check_include linux/usbdevice_fs.h; then
+ cat > $TMPC << EOF
+#include <linux/usbdevice_fs.h>
+
+#ifndef USBDEVFS_GET_CAPABILITIES
+#error "USBDEVFS_GET_CAPABILITIES undefined"
+#endif
+
+#ifndef USBDEVFS_DISCONNECT_CLAIM
+#error "USBDEVFS_DISCONNECT_CLAIM undefined"
+#endif
+
+int main(void)
+{
+ return 0;
+}
+EOF
+ if compile_prog "" ""; then
have_usbfs=yes
fi
- have_usbfs=yes
fi
# check for fallocate
libs_qga="$libs_qga -lrt"
fi
-if test "$darwin" != "yes" -a "$mingw32" != "yes" -a "$solaris" != yes -a \
- "$haiku" != "yes" ; then
+# Check whether we need to link libutil for openpty()
+cat > $TMPC << EOF
+extern int openpty(int *am, int *as, char *name, void *termp, void *winp);
+int main(void) { return openpty(0, 0, 0, 0, 0); }
+EOF
+
+if ! compile_prog "" "" ; then
+ if compile_prog "" "-lutil" ; then
libs_softmmu="-lutil $libs_softmmu"
+ libs_tools="-lutil $libs_tools"
+ fi
fi
##########################################
##########################################
# check if we have VSS SDK headers for win
-if test "$mingw32" = "yes" -a "$guest_agent" != "no" -a "$vss_win32_sdk" != "no" ; then
+if test "$mingw32" = "yes" && test "$guest_agent" != "no" && \
+ test "$vss_win32_sdk" != "no" ; then
case "$vss_win32_sdk" in
"") vss_win32_include="-isystem $source_path" ;;
*\ *) # The SDK is installed in "Program Files" by default, but we cannot
# VSS provider from the source. It is usually unnecessary because the
# pre-compiled .tlb file is included.
-if test "$mingw32" = "yes" -a "$guest_agent" != "no" -a "$guest_agent_with_vss" = "yes" ; then
+if test "$mingw32" = "yes" && test "$guest_agent" != "no" && \
+ test "$guest_agent_with_vss" = "yes" ; then
if test -z "$win_sdk"; then
programfiles="$PROGRAMFILES"
test -n "$PROGRAMW6432" && programfiles="$PROGRAMW6432"
##########################################
# check if mingw environment provides a recent ntddscsi.h
-if test "$mingw32" = "yes" -a "$guest_agent" != "no"; then
+if test "$mingw32" = "yes" && test "$guest_agent" != "no"; then
cat > $TMPC << EOF
#include <windows.h>
#include <ntddscsi.h>
"" | yes)
if $pkg_config capstone; then
capstone=system
- elif test -e "${source_path}/.git" -a $git_update = 'yes' ; then
+ elif test -e "${source_path}/.git" && test $git_update = 'yes' ; then
capstone=git
elif test -e "${source_path}/capstone/Makefile" ; then
capstone=internal
# 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" -a "$avx2_opt" != "no"; then
+if test "$cpuid_h" = "yes" && test "$avx2_opt" != "no"; then
cat > $TMPC << EOF
#pragma GCC push_options
#pragma GCC target("avx2")
fi
cmpxchg128=no
-if test "$int128" = yes -a "$atomic128" = no; then
+if test "$int128" = yes && test "$atomic128" = no; then
cat > $TMPC << EOF
int main(void)
{
if [ "$ivshmem" = "yes" ]; then
tools="ivshmem-client\$(EXESUF) ivshmem-server\$(EXESUF) $tools"
fi
- if [ "$posix" = "yes" ] && [ "$curl" = "yes" ]; then
- tools="elf2dmp $tools"
+ if [ "$curl" = "yes" ]; then
+ tools="elf2dmp\$(EXESUF) $tools"
fi
fi
if test "$softmmu" = yes ; then
# Mac OS X ships with a broken assembler
roms=
-if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) -a \
- "$targetos" != "Darwin" -a "$targetos" != "SunOS" -a \
- "$softmmu" = yes ; then
+if { test "$cpu" = "i386" || test "$cpu" = "x86_64"; } && \
+ test "$targetos" != "Darwin" && test "$targetos" != "SunOS" && \
+ test "$softmmu" = yes ; then
# Different host OS linkers have different ideas about the name of the ELF
# emulation. Linux and OpenBSD/amd64 use 'elf_i386'; FreeBSD uses the _fbsd
# variant; OpenBSD/i386 uses the _obsd variant; and Windows uses i386pe.
fi
done
fi
-if test "$cpu" = "ppc64" -a "$targetos" != "Darwin" ; then
+if test "$cpu" = "ppc64" && test "$targetos" != "Darwin" ; then
roms="$roms spapr-rtas"
fi
echo "libgcrypt $gcrypt"
echo "nettle $nettle $(echo_version $nettle $nettle_version)"
echo "libtasn1 $tasn1"
+echo "PAM $auth_pam"
echo "curses support $curses"
echo "virgl support $virglrenderer $(echo_version $virglrenderer $virgl_version)"
echo "curl support $curl"
echo "XKBCOMMON_CFLAGS=$xkbcommon_cflags" >> $config_host_mak
echo "XKBCOMMON_LIBS=$xkbcommon_libs" >> $config_host_mak
fi
-if test "$fnmatch" = "yes" ; then
- echo "CONFIG_FNMATCH=y" >> $config_host_mak
-fi
if test "$xfs" = "yes" ; then
echo "CONFIG_XFS=y" >> $config_host_mak
fi
echo "CONFIG_STAMP=_$( (echo $qemu_version; echo $pkgversion; cat $0) | $shacmd - | cut -f1 -d\ )" >> $config_host_mak
echo "CONFIG_MODULES=y" >> $config_host_mak
fi
-if test "$have_x11" = "yes" -a "$need_x11" = "yes"; then
+if test "$have_x11" = "yes" && test "$need_x11" = "yes"; then
echo "CONFIG_X11=y" >> $config_host_mak
echo "X11_CFLAGS=$x11_cflags" >> $config_host_mak
echo "X11_LIBS=$x11_libs" >> $config_host_mak
echo "CONFIG_GTK_GL=y" >> $config_host_mak
fi
fi
+if test "$gio" = "yes" ; then
+ echo "CONFIG_GIO=y" >> $config_host_mak
+ echo "GIO_CFLAGS=$gio_cflags" >> $config_host_mak
+ echo "GIO_LIBS=$gio_libs" >> $config_host_mak
+fi
echo "CONFIG_TLS_PRIORITY=\"$tls_priority\"" >> $config_host_mak
if test "$gnutls" = "yes" ; then
echo "CONFIG_GNUTLS=y" >> $config_host_mak
if test "$tasn1" = "yes" ; then
echo "CONFIG_TASN1=y" >> $config_host_mak
fi
+if test "$auth_pam" = "yes" ; then
+ echo "CONFIG_AUTH_PAM=y" >> $config_host_mak
+fi
if test "$have_ifaddrs_h" = "yes" ; then
echo "HAVE_IFADDRS_H=y" >> $config_host_mak
fi
if test "$vhost_scsi" = "yes" ; then
echo "CONFIG_VHOST_SCSI=y" >> $config_host_mak
fi
-if test "$vhost_net" = "yes" -a "$vhost_user" = "yes"; then
+if test "$vhost_net" = "yes" && test "$vhost_user" = "yes"; then
echo "CONFIG_VHOST_NET_USED=y" >> $config_host_mak
fi
if test "$vhost_crypto" = "yes" ; then
QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/sparc $QEMU_INCLUDES"
elif test "$ARCH" = "s390x" ; then
QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/s390 $QEMU_INCLUDES"
-elif test "$ARCH" = "x86_64" -o "$ARCH" = "x32" ; then
+elif test "$ARCH" = "x86_64" || test "$ARCH" = "x32" ; then
QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/i386 $QEMU_INCLUDES"
elif test "$ARCH" = "ppc64" ; then
QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/ppc $QEMU_INCLUDES"
-elif test "$ARCH" = "riscv32" -o "$ARCH" = "riscv64" ; then
+elif test "$ARCH" = "riscv32" || test "$ARCH" = "riscv64" ; then
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/riscv $QEMU_INCLUDES"
else
QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/\$(ARCH) $QEMU_INCLUDES"
case "$target_name" in
i386)
mttcg="yes"
- gdb_xml_files="i386-32bit.xml i386-32bit-core.xml i386-32bit-sse.xml"
+ gdb_xml_files="i386-32bit.xml"
target_compiler=$cross_cc_i386
target_compiler_cflags=$cross_cc_ccflags_i386
;;
x86_64)
TARGET_BASE_ARCH=i386
mttcg="yes"
- gdb_xml_files="i386-64bit.xml i386-64bit-core.xml i386-64bit-sse.xml"
+ gdb_xml_files="i386-64bit.xml"
target_compiler=$cross_cc_x86_64
;;
alpha)
target_compiler=$cross_cc_microblaze
;;
mips|mipsel)
+ mttcg="yes"
TARGET_ARCH=mips
target_compiler=$cross_cc_mips
echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak
;;
mipsn32|mipsn32el)
+ mttcg="yes"
TARGET_ARCH=mips64
TARGET_BASE_ARCH=mips
target_compiler=$cross_cc_mipsn32
echo "TARGET_ABI32=y" >> $config_target_mak
;;
mips64|mips64el)
+ mttcg="yes"
TARGET_ARCH=mips64
TARGET_BASE_ARCH=mips
target_compiler=$cross_cc_mips64
echo "TARGET_XML_FILES=$list" >> $config_target_mak
fi
-if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
+if test "$target_user_only" = "yes" && test "$bflt" = "yes"; then
echo "TARGET_HAS_BFLT=y" >> $config_target_mak
fi
if test "$target_bsd_user" = "yes" ; then
fi
fi
-if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
+if test "$target_linux_user" = "yes" || test "$target_bsd_user" = "yes" ; then
ldflags="$ldflags $textseg_ldflags"
fi
# - we build the system emulation for s390x (qemu-system-s390x)
# - KVM is enabled
# - the linker supports --s390-pgste
-if test "$TARGET_ARCH" = "s390x" -a "$target_softmmu" = "yes" -a "$ARCH" = "s390x" -a "$kvm" = "yes"; then
+if test "$TARGET_ARCH" = "s390x" && test "$target_softmmu" = "yes" && \
+ test "$ARCH" = "s390x" && test "$kvm" = "yes"; then
if ld_has --s390-pgste ; then
ldflags="-Wl,--s390-pgste $ldflags"
fi
uint64_t DebuggerDataList;
} DBGKD_GET_VERSION64;
+#ifndef _WIN32
+typedef struct LIST_ENTRY64 {
+ struct LIST_ENTRY64 *Flink;
+ struct LIST_ENTRY64 *Blink;
+} LIST_ENTRY64;
+#endif
+
typedef struct DBGKD_DEBUG_DATA_HEADER64 {
- struct LIST_ENTRY64 {
- struct LIST_ENTRY64 *Flink;
- struct LIST_ENTRY64 *Blink;
- } List;
+ LIST_ENTRY64 List;
uint32_t OwnerTag;
uint32_t Size;
} DBGKD_DEBUG_DATA_HEADER64;
*
*/
+#include <inttypes.h>
+
#include "qemu/osdep.h"
#include "err.h"
#include "addrspace.h"
#define KUSD_OFFSET_PRODUCT_TYPE 0x264
#define SYM_RESOLVE(base, r, s) ((s = pdb_resolve(base, r, #s)),\
- s ? printf(#s" = 0x%016lx\n", s) : eprintf("Failed to resolve "#s"\n"), s)
+ s ? printf(#s" = 0x%016"PRIx64"\n", s) :\
+ eprintf("Failed to resolve "#s"\n"), s)
static uint64_t rol(uint64_t x, uint64_t y)
{
return NULL;
}
- printf("[KiWaitNever] = 0x%016lx\n", kwn);
- printf("[KiWaitAlways] = 0x%016lx\n", kwa);
+ printf("[KiWaitNever] = 0x%016"PRIx64"\n", kwn);
+ printf("[KiWaitAlways] = 0x%016"PRIx64"\n", kwa);
/*
* If KDBG header can be decoded, KDBG size is available
if (is_system(s)) {
va_space_set_dtb(vs, s->cr[3]);
- printf("DTB 0x%016lx has been found from CPU #%zu"
+ printf("DTB 0x%016"PRIx64" has been found from CPU #%zu"
" as system task CR3\n", vs->dtb, i);
return !(va_space_resolve(vs, SharedUserData));
}
}
va_space_set_dtb(vs, *cr3);
- printf("DirectoryTableBase = 0x%016lx has been found from CPU #0"
+ printf("DirectoryTableBase = 0x%016"PRIx64" has been found from CPU #0"
" as interrupt handling CR3\n", vs->dtb);
return !(va_space_resolve(vs, SharedUserData));
}
return 1;
}
- printf("Debug Directory RVA = 0x%016x\n",
- data_dir[IMAGE_FILE_DEBUG_DIRECTORY].VirtualAddress);
+ printf("Debug Directory RVA = 0x%08"PRIx32"\n",
+ (uint32_t)data_dir[IMAGE_FILE_DEBUG_DIRECTORY].VirtualAddress);
if (va_space_rw(vs,
base + data_dir[IMAGE_FILE_DEBUG_DIRECTORY].VirtualAddress,
}
state = qemu_elf.state[0];
- printf("CPU #0 CR3 is 0x%016lx\n", state->cr[3]);
+ printf("CPU #0 CR3 is 0x%016"PRIx64"\n", state->cr[3]);
va_space_create(&vs, &ps, state->cr[3]);
if (fix_dtb(&vs, &qemu_elf)) {
goto out_elf;
}
- printf("CPU #0 IDT is at 0x%016lx\n", state->idt.base);
+ printf("CPU #0 IDT is at 0x%016"PRIx64"\n", state->idt.base);
if (va_space_rw(&vs, state->idt.base,
&first_idt_desc, sizeof(first_idt_desc), 0)) {
err = 1;
goto out_ps;
}
- printf("CPU #0 IDT[0] -> 0x%016lx\n", idt_desc_addr(first_idt_desc));
+ printf("CPU #0 IDT[0] -> 0x%016"PRIx64"\n", idt_desc_addr(first_idt_desc));
KernBase = idt_desc_addr(first_idt_desc) & ~(PAGE_SIZE - 1);
- printf("Searching kernel downwards from 0x%16lx...\n", KernBase);
+ printf("Searching kernel downwards from 0x%016"PRIx64"...\n", KernBase);
for (; KernBase >= 0xfffff78000000000; KernBase -= PAGE_SIZE) {
nt_start_addr = va_space_resolve(&vs, KernBase);
}
}
- printf("KernBase = 0x%16lx, signature is \'%.2s\'\n", KernBase,
+ printf("KernBase = 0x%016"PRIx64", signature is \'%.2s\'\n", KernBase,
(char *)nt_start_addr);
if (pe_get_pdb_symstore_hash(KernBase, nt_start_addr, pdb_hash, &vs)) {
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <inttypes.h>
+
#include "qemu/osdep.h"
#include "pdb.h"
#include "err.h"
uint32_t sect_rva = segment->dword[1];
uint64_t rva = sect_rva + sym->public_v3.offset;
- printf("%s: 0x%016x(%d:\'%.8s\') + 0x%08x = 0x%09lx\n", name,
+ printf("%s: 0x%016x(%d:\'%.8s\') + 0x%08x = 0x%09"PRIx64"\n", name,
sect_rva, sym->public_v3.segment,
((char *)segment - 8), sym->public_v3.offset, rva);
return rva;
int pdb_init_from_file(const char *name, struct pdb_reader *reader)
{
+ GError *gerr = NULL;
int err = 0;
- int fd;
void *map;
- struct stat st;
- fd = open(name, O_RDONLY, 0);
- if (fd == -1) {
- eprintf("Failed to open PDB file \'%s\'\n", name);
+ reader->gmf = g_mapped_file_new(name, TRUE, &gerr);
+ if (gerr) {
+ eprintf("Failed to map PDB file \'%s\'\n", name);
return 1;
}
- reader->fd = fd;
-
- fstat(fd, &st);
- reader->file_size = st.st_size;
-
- map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (map == MAP_FAILED) {
- eprintf("Failed to map PDB file\n");
- err = 1;
- goto out_fd;
- }
+ reader->file_size = g_mapped_file_get_length(reader->gmf);
+ map = g_mapped_file_get_contents(reader->gmf);
if (pdb_reader_init(reader, map)) {
err = 1;
goto out_unmap;
return 0;
out_unmap:
- munmap(map, st.st_size);
-out_fd:
- close(fd);
+ g_mapped_file_unref(reader->gmf);
return err;
}
void pdb_exit(struct pdb_reader *reader)
{
- munmap(reader->ds.header, reader->file_size);
- close(reader->fd);
+ g_mapped_file_unref(reader->gmf);
pdb_reader_exit(reader);
}
#define PDB_H
+#ifndef _WIN32
typedef struct GUID {
unsigned int Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[8];
} GUID;
+#endif
struct PDB_FILE {
uint32_t size;
#define IMAGE_FILE_MACHINE_AMD64 0x8664
struct pdb_reader {
- int fd;
+ GMappedFile *gmf;
size_t file_size;
struct {
PDB_DS_HEADER *header;
#define PE_H
+#ifndef _WIN32
typedef struct IMAGE_DOS_HEADER {
uint16_t e_magic; /* 0x00: MZ Header signature */
uint16_t e_cblp; /* 0x02: Bytes on last page of file */
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} __attribute__ ((packed)) IMAGE_NT_HEADERS64;
-#define IMAGE_FILE_DEBUG_DIRECTORY 6
-
typedef struct IMAGE_DEBUG_DIRECTORY {
uint32_t Characteristics;
uint32_t TimeDateStamp;
} __attribute__ ((packed)) IMAGE_DEBUG_DIRECTORY;
#define IMAGE_DEBUG_TYPE_CODEVIEW 2
+#endif
+
+#define IMAGE_FILE_DEBUG_DIRECTORY 6
typedef struct guid_t {
uint32_t a;
int QEMU_Elf_init(QEMU_Elf *qe, const char *filename)
{
+ GError *gerr = NULL;
int err = 0;
- struct stat st;
- qe->fd = open(filename, O_RDONLY, 0);
- if (qe->fd == -1) {
- eprintf("Failed to open ELF dump file \'%s\'\n", filename);
+ qe->gmf = g_mapped_file_new(filename, TRUE, &gerr);
+ if (gerr) {
+ eprintf("Failed to map ELF dump file \'%s\'\n", filename);
return 1;
}
- fstat(qe->fd, &st);
- qe->size = st.st_size;
-
- qe->map = mmap(NULL, qe->size, PROT_READ | PROT_WRITE,
- MAP_PRIVATE, qe->fd, 0);
- if (qe->map == MAP_FAILED) {
- eprintf("Failed to map ELF file\n");
- err = 1;
- goto out_fd;
- }
+ qe->map = g_mapped_file_get_contents(qe->gmf);
+ qe->size = g_mapped_file_get_length(qe->gmf);
if (init_states(qe)) {
eprintf("Failed to extract QEMU CPU states\n");
return 0;
out_unmap:
- munmap(qe->map, qe->size);
-out_fd:
- close(qe->fd);
+ g_mapped_file_unref(qe->gmf);
return err;
}
void QEMU_Elf_exit(QEMU_Elf *qe)
{
exit_states(qe);
- munmap(qe->map, qe->size);
- close(qe->fd);
+ g_mapped_file_unref(qe->gmf);
}
*
*/
-#ifndef QEMU_ELF_H
-#define QEMU_ELF_H
+#ifndef ELF2DMP_ELF_H
+#define ELF2DMP_ELF_H
-#include <elf.h>
+#include "elf.h"
typedef struct QEMUCPUSegment {
uint32_t selector;
int is_system(QEMUCPUState *s);
typedef struct QEMU_Elf {
- int fd;
+ GMappedFile *gmf;
size_t size;
void *map;
QEMUCPUState **state;
Elf64_Phdr *elf64_getphdr(void *map);
Elf64_Half elf_getphdrnum(void *map);
-#endif /* QEMU_ELF_H */
+#endif /* ELF2DMP_ELF_H */
DPRINT("vhost_vring_addr:\n");
DPRINT(" index: %d\n", vra->index);
DPRINT(" flags: %d\n", vra->flags);
- DPRINT(" desc_user_addr: 0x%016llx\n", vra->desc_user_addr);
- DPRINT(" used_user_addr: 0x%016llx\n", vra->used_user_addr);
- DPRINT(" avail_user_addr: 0x%016llx\n", vra->avail_user_addr);
- DPRINT(" log_guest_addr: 0x%016llx\n", vra->log_guest_addr);
+ DPRINT(" desc_user_addr: 0x%016" PRIx64 "\n", vra->desc_user_addr);
+ DPRINT(" used_user_addr: 0x%016" PRIx64 "\n", vra->used_user_addr);
+ DPRINT(" avail_user_addr: 0x%016" PRIx64 "\n", vra->avail_user_addr);
+ DPRINT(" log_guest_addr: 0x%016" PRIx64 "\n", vra->log_guest_addr);
vq->vring.flags = vra->flags;
vq->vring.desc = qva_to_va(dev, vra->desc_user_addr);
#include "contrib/libvhost-user/libvhost-user-glib.h"
#include "contrib/libvhost-user/libvhost-user.h"
+#if defined(__linux__)
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#endif
struct virtio_blk_inhdr {
unsigned char status;
return len;
}
+static size_t vub_iov_to_buf(const struct iovec *iov,
+ const unsigned int iov_cnt, void *buf)
+{
+ size_t len;
+ unsigned int i;
+
+ len = 0;
+ for (i = 0; i < iov_cnt; i++) {
+ memcpy(buf + len, iov[i].iov_base, iov[i].iov_len);
+ len += iov[i].iov_len;
+ }
+ return len;
+}
+
static void vub_panic_cb(VuDev *vu_dev, const char *buf)
{
VugDev *gdev;
return rc;
}
+static int
+vub_discard_write_zeroes(VubReq *req, struct iovec *iov, uint32_t iovcnt,
+ uint32_t type)
+{
+ struct virtio_blk_discard_write_zeroes *desc;
+ ssize_t size;
+ void *buf;
+
+ size = vub_iov_size(iov, iovcnt);
+ if (size != sizeof(*desc)) {
+ fprintf(stderr, "Invalid size %ld, expect %ld\n", size, sizeof(*desc));
+ return -1;
+ }
+ buf = g_new0(char, size);
+ vub_iov_to_buf(iov, iovcnt, buf);
+
+ #if defined(__linux__) && defined(BLKDISCARD) && defined(BLKZEROOUT)
+ VubDev *vdev_blk = req->vdev_blk;
+ desc = (struct virtio_blk_discard_write_zeroes *)buf;
+ uint64_t range[2] = { le64toh(desc->sector) << 9,
+ le32toh(desc->num_sectors) << 9 };
+ if (type == VIRTIO_BLK_T_DISCARD) {
+ if (ioctl(vdev_blk->blk_fd, BLKDISCARD, range) == 0) {
+ g_free(buf);
+ return 0;
+ }
+ } else if (type == VIRTIO_BLK_T_WRITE_ZEROES) {
+ if (ioctl(vdev_blk->blk_fd, BLKZEROOUT, range) == 0) {
+ g_free(buf);
+ return 0;
+ }
+ }
+ #endif
+
+ g_free(buf);
+ return -1;
+}
+
static void
vub_flush(VubReq *req)
{
in_num--;
type = le32toh(req->out->type);
- switch (type & ~(VIRTIO_BLK_T_OUT | VIRTIO_BLK_T_BARRIER)) {
- case VIRTIO_BLK_T_IN: {
- ssize_t ret = 0;
- bool is_write = type & VIRTIO_BLK_T_OUT;
- req->sector_num = le64toh(req->out->sector);
- if (is_write) {
- ret = vub_writev(req, &elem->out_sg[1], out_num);
- } else {
- ret = vub_readv(req, &elem->in_sg[0], in_num);
- }
- if (ret >= 0) {
- req->in->status = VIRTIO_BLK_S_OK;
- } else {
- req->in->status = VIRTIO_BLK_S_IOERR;
- }
- vub_req_complete(req);
- break;
+ switch (type & ~VIRTIO_BLK_T_BARRIER) {
+ case VIRTIO_BLK_T_IN:
+ case VIRTIO_BLK_T_OUT: {
+ ssize_t ret = 0;
+ bool is_write = type & VIRTIO_BLK_T_OUT;
+ req->sector_num = le64toh(req->out->sector);
+ if (is_write) {
+ ret = vub_writev(req, &elem->out_sg[1], out_num);
+ } else {
+ ret = vub_readv(req, &elem->in_sg[0], in_num);
}
- case VIRTIO_BLK_T_FLUSH: {
- vub_flush(req);
+ if (ret >= 0) {
req->in->status = VIRTIO_BLK_S_OK;
- vub_req_complete(req);
- break;
+ } else {
+ req->in->status = VIRTIO_BLK_S_IOERR;
}
- case VIRTIO_BLK_T_GET_ID: {
- size_t size = MIN(vub_iov_size(&elem->in_sg[0], in_num),
- VIRTIO_BLK_ID_BYTES);
- snprintf(elem->in_sg[0].iov_base, size, "%s", "vhost_user_blk");
+ vub_req_complete(req);
+ break;
+ }
+ case VIRTIO_BLK_T_FLUSH:
+ vub_flush(req);
+ req->in->status = VIRTIO_BLK_S_OK;
+ vub_req_complete(req);
+ break;
+ case VIRTIO_BLK_T_GET_ID: {
+ size_t size = MIN(vub_iov_size(&elem->in_sg[0], in_num),
+ VIRTIO_BLK_ID_BYTES);
+ snprintf(elem->in_sg[0].iov_base, size, "%s", "vhost_user_blk");
+ req->in->status = VIRTIO_BLK_S_OK;
+ req->size = elem->in_sg[0].iov_len;
+ vub_req_complete(req);
+ break;
+ }
+ case VIRTIO_BLK_T_DISCARD:
+ case VIRTIO_BLK_T_WRITE_ZEROES: {
+ int rc;
+ rc = vub_discard_write_zeroes(req, &elem->out_sg[1], out_num, type);
+ if (rc == 0) {
req->in->status = VIRTIO_BLK_S_OK;
- req->size = elem->in_sg[0].iov_len;
- vub_req_complete(req);
- break;
- }
- default: {
- req->in->status = VIRTIO_BLK_S_UNSUPP;
- vub_req_complete(req);
- break;
+ } else {
+ req->in->status = VIRTIO_BLK_S_IOERR;
}
+ vub_req_complete(req);
+ break;
+ }
+ default:
+ req->in->status = VIRTIO_BLK_S_UNSUPP;
+ vub_req_complete(req);
+ break;
}
return 0;
1ull << VIRTIO_BLK_F_TOPOLOGY |
1ull << VIRTIO_BLK_F_BLK_SIZE |
1ull << VIRTIO_BLK_F_FLUSH |
+ #if defined(__linux__) && defined(BLKDISCARD) && defined(BLKZEROOUT)
+ 1ull << VIRTIO_BLK_F_DISCARD |
+ 1ull << VIRTIO_BLK_F_WRITE_ZEROES |
+ #endif
1ull << VIRTIO_BLK_F_CONFIG_WCE |
1ull << VIRTIO_F_VERSION_1 |
1ull << VHOST_USER_F_PROTOCOL_FEATURES;
#if defined(__linux__) && defined(BLKSSZGET)
if (ioctl(fd, BLKSSZGET, &blocksize) == 0) {
- return blocklen;
+ return blocksize;
}
#endif
config->min_io_size = 1;
config->opt_io_size = 1;
config->num_queues = 1;
+ #if defined(__linux__) && defined(BLKDISCARD) && defined(BLKZEROOUT)
+ config->max_discard_sectors = 32768;
+ config->max_discard_seg = 1;
+ config->discard_sector_alignment = config->blk_size >> 9;
+ config->max_write_zeroes_sectors = 32768;
+ config->max_write_zeroes_seg = 1;
+ #endif
}
static VubDev *
qemu_wait_io_event(cpu);
} while (!cpu->unplug);
+ qemu_mutex_unlock_iothread();
rcu_unregister_thread();
return NULL;
#endif
}
cpu->thread_kicked = true;
err = pthread_kill(cpu->thread->thread, SIG_IPI);
- if (err) {
+ if (err && err != ESRCH) {
fprintf(stderr, "qemu:%s: %s", __func__, strerror(err));
exit(1);
}
0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
};
static const u32 rcon[] = {
- 0x01000000, 0x02000000, 0x04000000, 0x08000000,
- 0x10000000, 0x20000000, 0x40000000, 0x80000000,
- 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
};
/**
* Expand the cipher key into the encryption key schedule.
*/
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
- AES_KEY *key) {
+ AES_KEY *key) {
- u32 *rk;
- int i = 0;
- u32 temp;
+ u32 *rk;
+ int i = 0;
+ u32 temp;
- if (!userKey || !key)
- return -1;
- if (bits != 128 && bits != 192 && bits != 256)
- return -2;
+ if (!userKey || !key)
+ return -1;
+ if (bits != 128 && bits != 192 && bits != 256)
+ return -2;
- rk = key->rd_key;
+ rk = key->rd_key;
- if (bits==128)
- key->rounds = 10;
- else if (bits==192)
- key->rounds = 12;
- else
- key->rounds = 14;
+ if (bits==128)
+ key->rounds = 10;
+ else if (bits==192)
+ key->rounds = 12;
+ else
+ key->rounds = 14;
- rk[0] = GETU32(userKey );
- rk[1] = GETU32(userKey + 4);
- rk[2] = GETU32(userKey + 8);
- rk[3] = GETU32(userKey + 12);
- if (bits == 128) {
- while (1) {
- temp = rk[3];
- rk[4] = rk[0] ^
+ rk[0] = GETU32(userKey );
+ rk[1] = GETU32(userKey + 4);
+ rk[2] = GETU32(userKey + 8);
+ rk[3] = GETU32(userKey + 12);
+ if (bits == 128) {
+ while (1) {
+ temp = rk[3];
+ rk[4] = rk[0] ^
(AES_Te4[(temp >> 16) & 0xff] & 0xff000000) ^
(AES_Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
(AES_Te4[(temp ) & 0xff] & 0x0000ff00) ^
(AES_Te4[(temp >> 24) ] & 0x000000ff) ^
- rcon[i];
- rk[5] = rk[1] ^ rk[4];
- rk[6] = rk[2] ^ rk[5];
- rk[7] = rk[3] ^ rk[6];
- if (++i == 10) {
- return 0;
- }
- rk += 4;
- }
- }
- rk[4] = GETU32(userKey + 16);
- rk[5] = GETU32(userKey + 20);
- if (bits == 192) {
- while (1) {
- temp = rk[ 5];
- rk[ 6] = rk[ 0] ^
+ rcon[i];
+ rk[5] = rk[1] ^ rk[4];
+ rk[6] = rk[2] ^ rk[5];
+ rk[7] = rk[3] ^ rk[6];
+ if (++i == 10) {
+ return 0;
+ }
+ rk += 4;
+ }
+ }
+ rk[4] = GETU32(userKey + 16);
+ rk[5] = GETU32(userKey + 20);
+ if (bits == 192) {
+ while (1) {
+ temp = rk[ 5];
+ rk[ 6] = rk[ 0] ^
(AES_Te4[(temp >> 16) & 0xff] & 0xff000000) ^
(AES_Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
(AES_Te4[(temp ) & 0xff] & 0x0000ff00) ^
(AES_Te4[(temp >> 24) ] & 0x000000ff) ^
- rcon[i];
- rk[ 7] = rk[ 1] ^ rk[ 6];
- rk[ 8] = rk[ 2] ^ rk[ 7];
- rk[ 9] = rk[ 3] ^ rk[ 8];
- if (++i == 8) {
- return 0;
- }
- rk[10] = rk[ 4] ^ rk[ 9];
- rk[11] = rk[ 5] ^ rk[10];
- rk += 6;
- }
- }
- rk[6] = GETU32(userKey + 24);
- rk[7] = GETU32(userKey + 28);
- if (bits == 256) {
- while (1) {
- temp = rk[ 7];
- rk[ 8] = rk[ 0] ^
+ rcon[i];
+ rk[ 7] = rk[ 1] ^ rk[ 6];
+ rk[ 8] = rk[ 2] ^ rk[ 7];
+ rk[ 9] = rk[ 3] ^ rk[ 8];
+ if (++i == 8) {
+ return 0;
+ }
+ rk[10] = rk[ 4] ^ rk[ 9];
+ rk[11] = rk[ 5] ^ rk[10];
+ rk += 6;
+ }
+ }
+ rk[6] = GETU32(userKey + 24);
+ rk[7] = GETU32(userKey + 28);
+ if (bits == 256) {
+ while (1) {
+ temp = rk[ 7];
+ rk[ 8] = rk[ 0] ^
(AES_Te4[(temp >> 16) & 0xff] & 0xff000000) ^
(AES_Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
(AES_Te4[(temp ) & 0xff] & 0x0000ff00) ^
(AES_Te4[(temp >> 24) ] & 0x000000ff) ^
- rcon[i];
- rk[ 9] = rk[ 1] ^ rk[ 8];
- rk[10] = rk[ 2] ^ rk[ 9];
- rk[11] = rk[ 3] ^ rk[10];
- if (++i == 7) {
- return 0;
- }
- temp = rk[11];
- rk[12] = rk[ 4] ^
+ rcon[i];
+ rk[ 9] = rk[ 1] ^ rk[ 8];
+ rk[10] = rk[ 2] ^ rk[ 9];
+ rk[11] = rk[ 3] ^ rk[10];
+ if (++i == 7) {
+ return 0;
+ }
+ temp = rk[11];
+ rk[12] = rk[ 4] ^
(AES_Te4[(temp >> 24) ] & 0xff000000) ^
(AES_Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
(AES_Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^
(AES_Te4[(temp ) & 0xff] & 0x000000ff);
- rk[13] = rk[ 5] ^ rk[12];
- rk[14] = rk[ 6] ^ rk[13];
- rk[15] = rk[ 7] ^ rk[14];
+ rk[13] = rk[ 5] ^ rk[12];
+ rk[14] = rk[ 6] ^ rk[13];
+ rk[15] = rk[ 7] ^ rk[14];
- rk += 8;
- }
- }
+ rk += 8;
+ }
+ }
abort();
}
* Expand the cipher key into the decryption key schedule.
*/
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
- AES_KEY *key) {
+ AES_KEY *key) {
u32 *rk;
- int i, j, status;
- u32 temp;
+ int i, j, status;
+ u32 temp;
- /* first, start with an encryption schedule */
- status = AES_set_encrypt_key(userKey, bits, key);
- if (status < 0)
- return status;
+ /* first, start with an encryption schedule */
+ status = AES_set_encrypt_key(userKey, bits, key);
+ if (status < 0)
+ return status;
- rk = key->rd_key;
+ rk = key->rd_key;
- /* invert the order of the round keys: */
- for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) {
- temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
- temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
- temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
- temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
- }
- /* apply the inverse MixColumn transform to all round keys but the first and the last: */
- for (i = 1; i < (key->rounds); i++) {
- rk += 4;
- rk[0] =
+ /* invert the order of the round keys: */
+ for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) {
+ temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
+ temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+ temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+ temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+ }
+ /* apply the inverse MixColumn transform to all round keys but the first and the last: */
+ for (i = 1; i < (key->rounds); i++) {
+ rk += 4;
+ rk[0] =
AES_Td0[AES_Te4[(rk[0] >> 24) ] & 0xff] ^
AES_Td1[AES_Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
AES_Td2[AES_Te4[(rk[0] >> 8) & 0xff] & 0xff] ^
AES_Td3[AES_Te4[(rk[0] ) & 0xff] & 0xff];
- rk[1] =
+ rk[1] =
AES_Td0[AES_Te4[(rk[1] >> 24) ] & 0xff] ^
AES_Td1[AES_Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
AES_Td2[AES_Te4[(rk[1] >> 8) & 0xff] & 0xff] ^
AES_Td3[AES_Te4[(rk[1] ) & 0xff] & 0xff];
- rk[2] =
+ rk[2] =
AES_Td0[AES_Te4[(rk[2] >> 24) ] & 0xff] ^
AES_Td1[AES_Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
AES_Td2[AES_Te4[(rk[2] >> 8) & 0xff] & 0xff] ^
AES_Td3[AES_Te4[(rk[2] ) & 0xff] & 0xff];
- rk[3] =
+ rk[3] =
AES_Td0[AES_Te4[(rk[3] >> 24) ] & 0xff] ^
AES_Td1[AES_Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
AES_Td2[AES_Te4[(rk[3] >> 8) & 0xff] & 0xff] ^
AES_Td3[AES_Te4[(rk[3] ) & 0xff] & 0xff];
- }
- return 0;
+ }
+ return 0;
}
#ifndef AES_ASM
* in and out can overlap
*/
void AES_encrypt(const unsigned char *in, unsigned char *out,
- const AES_KEY *key) {
+ const AES_KEY *key) {
- const u32 *rk;
- u32 s0, s1, s2, s3, t0, t1, t2, t3;
+ const u32 *rk;
+ u32 s0, s1, s2, s3, t0, t1, t2, t3;
#ifndef FULL_UNROLL
- int r;
+ int r;
#endif /* ?FULL_UNROLL */
- assert(in && out && key);
- rk = key->rd_key;
+ assert(in && out && key);
+ rk = key->rd_key;
- /*
- * map byte array block to cipher state
- * and add initial round key:
- */
- s0 = GETU32(in ) ^ rk[0];
- s1 = GETU32(in + 4) ^ rk[1];
- s2 = GETU32(in + 8) ^ rk[2];
- s3 = GETU32(in + 12) ^ rk[3];
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ s0 = GETU32(in ) ^ rk[0];
+ s1 = GETU32(in + 4) ^ rk[1];
+ s2 = GETU32(in + 8) ^ rk[2];
+ s3 = GETU32(in + 12) ^ rk[3];
#ifdef FULL_UNROLL
- /* round 1: */
+ /* round 1: */
t0 = AES_Te0[s0 >> 24] ^ AES_Te1[(s1 >> 16) & 0xff] ^ AES_Te2[(s2 >> 8) & 0xff] ^ AES_Te3[s3 & 0xff] ^ rk[ 4];
t1 = AES_Te0[s1 >> 24] ^ AES_Te1[(s2 >> 16) & 0xff] ^ AES_Te2[(s3 >> 8) & 0xff] ^ AES_Te3[s0 & 0xff] ^ rk[ 5];
t2 = AES_Te0[s2 >> 24] ^ AES_Te1[(s3 >> 16) & 0xff] ^ AES_Te2[(s0 >> 8) & 0xff] ^ AES_Te3[s1 & 0xff] ^ rk[ 6];
t3 = AES_Te0[s3 >> 24] ^ AES_Te1[(s0 >> 16) & 0xff] ^ AES_Te2[(s1 >> 8) & 0xff] ^ AES_Te3[s2 & 0xff] ^ rk[ 7];
- /* round 2: */
+ /* round 2: */
s0 = AES_Te0[t0 >> 24] ^ AES_Te1[(t1 >> 16) & 0xff] ^ AES_Te2[(t2 >> 8) & 0xff] ^ AES_Te3[t3 & 0xff] ^ rk[ 8];
s1 = AES_Te0[t1 >> 24] ^ AES_Te1[(t2 >> 16) & 0xff] ^ AES_Te2[(t3 >> 8) & 0xff] ^ AES_Te3[t0 & 0xff] ^ rk[ 9];
s2 = AES_Te0[t2 >> 24] ^ AES_Te1[(t3 >> 16) & 0xff] ^ AES_Te2[(t0 >> 8) & 0xff] ^ AES_Te3[t1 & 0xff] ^ rk[10];
s3 = AES_Te0[t3 >> 24] ^ AES_Te1[(t0 >> 16) & 0xff] ^ AES_Te2[(t1 >> 8) & 0xff] ^ AES_Te3[t2 & 0xff] ^ rk[11];
- /* round 3: */
+ /* round 3: */
t0 = AES_Te0[s0 >> 24] ^ AES_Te1[(s1 >> 16) & 0xff] ^ AES_Te2[(s2 >> 8) & 0xff] ^ AES_Te3[s3 & 0xff] ^ rk[12];
t1 = AES_Te0[s1 >> 24] ^ AES_Te1[(s2 >> 16) & 0xff] ^ AES_Te2[(s3 >> 8) & 0xff] ^ AES_Te3[s0 & 0xff] ^ rk[13];
t2 = AES_Te0[s2 >> 24] ^ AES_Te1[(s3 >> 16) & 0xff] ^ AES_Te2[(s0 >> 8) & 0xff] ^ AES_Te3[s1 & 0xff] ^ rk[14];
t3 = AES_Te0[s3 >> 24] ^ AES_Te1[(s0 >> 16) & 0xff] ^ AES_Te2[(s1 >> 8) & 0xff] ^ AES_Te3[s2 & 0xff] ^ rk[15];
- /* round 4: */
+ /* round 4: */
s0 = AES_Te0[t0 >> 24] ^ AES_Te1[(t1 >> 16) & 0xff] ^ AES_Te2[(t2 >> 8) & 0xff] ^ AES_Te3[t3 & 0xff] ^ rk[16];
s1 = AES_Te0[t1 >> 24] ^ AES_Te1[(t2 >> 16) & 0xff] ^ AES_Te2[(t3 >> 8) & 0xff] ^ AES_Te3[t0 & 0xff] ^ rk[17];
s2 = AES_Te0[t2 >> 24] ^ AES_Te1[(t3 >> 16) & 0xff] ^ AES_Te2[(t0 >> 8) & 0xff] ^ AES_Te3[t1 & 0xff] ^ rk[18];
s3 = AES_Te0[t3 >> 24] ^ AES_Te1[(t0 >> 16) & 0xff] ^ AES_Te2[(t1 >> 8) & 0xff] ^ AES_Te3[t2 & 0xff] ^ rk[19];
- /* round 5: */
+ /* round 5: */
t0 = AES_Te0[s0 >> 24] ^ AES_Te1[(s1 >> 16) & 0xff] ^ AES_Te2[(s2 >> 8) & 0xff] ^ AES_Te3[s3 & 0xff] ^ rk[20];
t1 = AES_Te0[s1 >> 24] ^ AES_Te1[(s2 >> 16) & 0xff] ^ AES_Te2[(s3 >> 8) & 0xff] ^ AES_Te3[s0 & 0xff] ^ rk[21];
t2 = AES_Te0[s2 >> 24] ^ AES_Te1[(s3 >> 16) & 0xff] ^ AES_Te2[(s0 >> 8) & 0xff] ^ AES_Te3[s1 & 0xff] ^ rk[22];
t3 = AES_Te0[s3 >> 24] ^ AES_Te1[(s0 >> 16) & 0xff] ^ AES_Te2[(s1 >> 8) & 0xff] ^ AES_Te3[s2 & 0xff] ^ rk[23];
- /* round 6: */
+ /* round 6: */
s0 = AES_Te0[t0 >> 24] ^ AES_Te1[(t1 >> 16) & 0xff] ^ AES_Te2[(t2 >> 8) & 0xff] ^ AES_Te3[t3 & 0xff] ^ rk[24];
s1 = AES_Te0[t1 >> 24] ^ AES_Te1[(t2 >> 16) & 0xff] ^ AES_Te2[(t3 >> 8) & 0xff] ^ AES_Te3[t0 & 0xff] ^ rk[25];
s2 = AES_Te0[t2 >> 24] ^ AES_Te1[(t3 >> 16) & 0xff] ^ AES_Te2[(t0 >> 8) & 0xff] ^ AES_Te3[t1 & 0xff] ^ rk[26];
s3 = AES_Te0[t3 >> 24] ^ AES_Te1[(t0 >> 16) & 0xff] ^ AES_Te2[(t1 >> 8) & 0xff] ^ AES_Te3[t2 & 0xff] ^ rk[27];
- /* round 7: */
+ /* round 7: */
t0 = AES_Te0[s0 >> 24] ^ AES_Te1[(s1 >> 16) & 0xff] ^ AES_Te2[(s2 >> 8) & 0xff] ^ AES_Te3[s3 & 0xff] ^ rk[28];
t1 = AES_Te0[s1 >> 24] ^ AES_Te1[(s2 >> 16) & 0xff] ^ AES_Te2[(s3 >> 8) & 0xff] ^ AES_Te3[s0 & 0xff] ^ rk[29];
t2 = AES_Te0[s2 >> 24] ^ AES_Te1[(s3 >> 16) & 0xff] ^ AES_Te2[(s0 >> 8) & 0xff] ^ AES_Te3[s1 & 0xff] ^ rk[30];
t3 = AES_Te0[s3 >> 24] ^ AES_Te1[(s0 >> 16) & 0xff] ^ AES_Te2[(s1 >> 8) & 0xff] ^ AES_Te3[s2 & 0xff] ^ rk[31];
- /* round 8: */
+ /* round 8: */
s0 = AES_Te0[t0 >> 24] ^ AES_Te1[(t1 >> 16) & 0xff] ^ AES_Te2[(t2 >> 8) & 0xff] ^ AES_Te3[t3 & 0xff] ^ rk[32];
s1 = AES_Te0[t1 >> 24] ^ AES_Te1[(t2 >> 16) & 0xff] ^ AES_Te2[(t3 >> 8) & 0xff] ^ AES_Te3[t0 & 0xff] ^ rk[33];
s2 = AES_Te0[t2 >> 24] ^ AES_Te1[(t3 >> 16) & 0xff] ^ AES_Te2[(t0 >> 8) & 0xff] ^ AES_Te3[t1 & 0xff] ^ rk[34];
s3 = AES_Te0[t3 >> 24] ^ AES_Te1[(t0 >> 16) & 0xff] ^ AES_Te2[(t1 >> 8) & 0xff] ^ AES_Te3[t2 & 0xff] ^ rk[35];
- /* round 9: */
+ /* round 9: */
t0 = AES_Te0[s0 >> 24] ^ AES_Te1[(s1 >> 16) & 0xff] ^ AES_Te2[(s2 >> 8) & 0xff] ^ AES_Te3[s3 & 0xff] ^ rk[36];
t1 = AES_Te0[s1 >> 24] ^ AES_Te1[(s2 >> 16) & 0xff] ^ AES_Te2[(s3 >> 8) & 0xff] ^ AES_Te3[s0 & 0xff] ^ rk[37];
t2 = AES_Te0[s2 >> 24] ^ AES_Te1[(s3 >> 16) & 0xff] ^ AES_Te2[(s0 >> 8) & 0xff] ^ AES_Te3[s1 & 0xff] ^ rk[38];
}
#endif /* ?FULL_UNROLL */
/*
- * apply last round and
- * map cipher state to byte array block:
- */
- s0 =
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
(AES_Te4[(t0 >> 24) ] & 0xff000000) ^
(AES_Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
(AES_Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
(AES_Te4[(t3 ) & 0xff] & 0x000000ff) ^
- rk[0];
- PUTU32(out , s0);
- s1 =
+ rk[0];
+ PUTU32(out , s0);
+ s1 =
(AES_Te4[(t1 >> 24) ] & 0xff000000) ^
(AES_Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
(AES_Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
(AES_Te4[(t0 ) & 0xff] & 0x000000ff) ^
- rk[1];
- PUTU32(out + 4, s1);
- s2 =
+ rk[1];
+ PUTU32(out + 4, s1);
+ s2 =
(AES_Te4[(t2 >> 24) ] & 0xff000000) ^
(AES_Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
(AES_Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
(AES_Te4[(t1 ) & 0xff] & 0x000000ff) ^
- rk[2];
- PUTU32(out + 8, s2);
- s3 =
+ rk[2];
+ PUTU32(out + 8, s2);
+ s3 =
(AES_Te4[(t3 >> 24) ] & 0xff000000) ^
(AES_Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
(AES_Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
(AES_Te4[(t2 ) & 0xff] & 0x000000ff) ^
- rk[3];
- PUTU32(out + 12, s3);
+ rk[3];
+ PUTU32(out + 12, s3);
}
/*
* in and out can overlap
*/
void AES_decrypt(const unsigned char *in, unsigned char *out,
- const AES_KEY *key) {
+ const AES_KEY *key) {
- const u32 *rk;
- u32 s0, s1, s2, s3, t0, t1, t2, t3;
+ const u32 *rk;
+ u32 s0, s1, s2, s3, t0, t1, t2, t3;
#ifndef FULL_UNROLL
- int r;
+ int r;
#endif /* ?FULL_UNROLL */
- assert(in && out && key);
- rk = key->rd_key;
+ assert(in && out && key);
+ rk = key->rd_key;
- /*
- * map byte array block to cipher state
- * and add initial round key:
- */
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
s0 = GETU32(in ) ^ rk[0];
s1 = GETU32(in + 4) ^ rk[1];
s2 = GETU32(in + 8) ^ rk[2];
t3 = AES_Td0[s3 >> 24] ^ AES_Td1[(s2 >> 16) & 0xff] ^ AES_Td2[(s1 >> 8) & 0xff] ^ AES_Td3[s0 & 0xff] ^ rk[55];
}
}
- rk += key->rounds << 2;
+ rk += key->rounds << 2;
#else /* !FULL_UNROLL */
/*
* Nr - 1 full rounds:
}
#endif /* ?FULL_UNROLL */
/*
- * apply last round and
- * map cipher state to byte array block:
- */
- s0 =
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
(AES_Td4[(t0 >> 24) ] & 0xff000000) ^
(AES_Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
(AES_Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
(AES_Td4[(t1 ) & 0xff] & 0x000000ff) ^
- rk[0];
- PUTU32(out , s0);
- s1 =
+ rk[0];
+ PUTU32(out , s0);
+ s1 =
(AES_Td4[(t1 >> 24) ] & 0xff000000) ^
(AES_Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
(AES_Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
(AES_Td4[(t2 ) & 0xff] & 0x000000ff) ^
- rk[1];
- PUTU32(out + 4, s1);
- s2 =
+ rk[1];
+ PUTU32(out + 4, s1);
+ s2 =
(AES_Td4[(t2 >> 24) ] & 0xff000000) ^
(AES_Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
(AES_Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
(AES_Td4[(t3 ) & 0xff] & 0x000000ff) ^
- rk[2];
- PUTU32(out + 8, s2);
- s3 =
+ rk[2];
+ PUTU32(out + 8, s2);
+ s3 =
(AES_Td4[(t3 >> 24) ] & 0xff000000) ^
(AES_Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
(AES_Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
(AES_Td4[(t0 ) & 0xff] & 0x000000ff) ^
- rk[3];
- PUTU32(out + 12, s3);
+ rk[3];
+ PUTU32(out + 12, s3);
}
#endif /* AES_ASM */
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
- const unsigned long length, const AES_KEY *key,
- unsigned char *ivec, const int enc)
+ const unsigned long length, const AES_KEY *key,
+ unsigned char *ivec, const int enc)
{
- unsigned long n;
- unsigned long len = length;
- unsigned char tmp[AES_BLOCK_SIZE];
+ unsigned long n;
+ unsigned long len = length;
+ unsigned char tmp[AES_BLOCK_SIZE];
- assert(in && out && key && ivec);
+ assert(in && out && key && ivec);
- if (enc) {
- while (len >= AES_BLOCK_SIZE) {
- for(n=0; n < AES_BLOCK_SIZE; ++n)
- tmp[n] = in[n] ^ ivec[n];
- AES_encrypt(tmp, out, key);
- memcpy(ivec, out, AES_BLOCK_SIZE);
- len -= AES_BLOCK_SIZE;
- in += AES_BLOCK_SIZE;
- out += AES_BLOCK_SIZE;
- }
- if (len) {
- for(n=0; n < len; ++n)
- tmp[n] = in[n] ^ ivec[n];
- for(n=len; n < AES_BLOCK_SIZE; ++n)
- tmp[n] = ivec[n];
- AES_encrypt(tmp, tmp, key);
- memcpy(out, tmp, AES_BLOCK_SIZE);
- memcpy(ivec, tmp, AES_BLOCK_SIZE);
- }
- } else {
- while (len >= AES_BLOCK_SIZE) {
- memcpy(tmp, in, AES_BLOCK_SIZE);
- AES_decrypt(in, out, key);
- for(n=0; n < AES_BLOCK_SIZE; ++n)
- out[n] ^= ivec[n];
- memcpy(ivec, tmp, AES_BLOCK_SIZE);
- len -= AES_BLOCK_SIZE;
- in += AES_BLOCK_SIZE;
- out += AES_BLOCK_SIZE;
- }
- if (len) {
- memcpy(tmp, in, AES_BLOCK_SIZE);
- AES_decrypt(tmp, tmp, key);
- for(n=0; n < len; ++n)
- out[n] = tmp[n] ^ ivec[n];
- memcpy(ivec, tmp, AES_BLOCK_SIZE);
- }
- }
+ if (enc) {
+ while (len >= AES_BLOCK_SIZE) {
+ for(n=0; n < AES_BLOCK_SIZE; ++n)
+ tmp[n] = in[n] ^ ivec[n];
+ AES_encrypt(tmp, out, key);
+ memcpy(ivec, out, AES_BLOCK_SIZE);
+ len -= AES_BLOCK_SIZE;
+ in += AES_BLOCK_SIZE;
+ out += AES_BLOCK_SIZE;
+ }
+ if (len) {
+ for(n=0; n < len; ++n)
+ tmp[n] = in[n] ^ ivec[n];
+ for(n=len; n < AES_BLOCK_SIZE; ++n)
+ tmp[n] = ivec[n];
+ AES_encrypt(tmp, tmp, key);
+ memcpy(out, tmp, AES_BLOCK_SIZE);
+ memcpy(ivec, tmp, AES_BLOCK_SIZE);
+ }
+ } else {
+ while (len >= AES_BLOCK_SIZE) {
+ memcpy(tmp, in, AES_BLOCK_SIZE);
+ AES_decrypt(in, out, key);
+ for(n=0; n < AES_BLOCK_SIZE; ++n)
+ out[n] ^= ivec[n];
+ memcpy(ivec, tmp, AES_BLOCK_SIZE);
+ len -= AES_BLOCK_SIZE;
+ in += AES_BLOCK_SIZE;
+ out += AES_BLOCK_SIZE;
+ }
+ if (len) {
+ memcpy(tmp, in, AES_BLOCK_SIZE);
+ AES_decrypt(tmp, tmp, key);
+ for(n=0; n < len; ++n)
+ out[n] = tmp[n] ^ ivec[n];
+ memcpy(ivec, tmp, AES_BLOCK_SIZE);
+ }
+ }
}
static unsigned long KnL[32] = { 0L };
static const unsigned short bytebit[8] = {
- 01, 02, 04, 010, 020, 040, 0100, 0200 };
+ 01, 02, 04, 010, 020, 040, 0100, 0200 };
static const unsigned long bigbyte[24] = {
- 0x800000L, 0x400000L, 0x200000L, 0x100000L,
- 0x80000L, 0x40000L, 0x20000L, 0x10000L,
- 0x8000L, 0x4000L, 0x2000L, 0x1000L,
- 0x800L, 0x400L, 0x200L, 0x100L,
- 0x80L, 0x40L, 0x20L, 0x10L,
- 0x8L, 0x4L, 0x2L, 0x1L };
+ 0x800000L, 0x400000L, 0x200000L, 0x100000L,
+ 0x80000L, 0x40000L, 0x20000L, 0x10000L,
+ 0x8000L, 0x4000L, 0x2000L, 0x1000L,
+ 0x800L, 0x400L, 0x200L, 0x100L,
+ 0x80L, 0x40L, 0x20L, 0x10L,
+ 0x8L, 0x4L, 0x2L, 0x1L };
/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
static const unsigned char pc1[56] = {
- 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
- 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
- 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
- 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
+ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
+ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
+ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
+ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
static const unsigned char totrot[16] = {
- 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
+ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
static const unsigned char pc2[48] = {
- 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
- 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
- 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
- 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
/* Thanks to James Gillogly & Phil Karn! */
void deskey(unsigned char *key, int edf)
{
- register int i, j, l, m, n;
- unsigned char pc1m[56], pcr[56];
- unsigned long kn[32];
-
- for ( j = 0; j < 56; j++ ) {
- l = pc1[j];
- m = l & 07;
- pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
- }
- for( i = 0; i < 16; i++ ) {
- if( edf == DE1 ) m = (15 - i) << 1;
- else m = i << 1;
- n = m + 1;
- kn[m] = kn[n] = 0L;
- for( j = 0; j < 28; j++ ) {
- l = j + totrot[i];
- if( l < 28 ) pcr[j] = pc1m[l];
- else pcr[j] = pc1m[l - 28];
- }
- for( j = 28; j < 56; j++ ) {
- l = j + totrot[i];
- if( l < 56 ) pcr[j] = pc1m[l];
- else pcr[j] = pc1m[l - 28];
- }
- for( j = 0; j < 24; j++ ) {
- if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
- if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
- }
- }
- cookey(kn);
- return;
- }
+ register int i, j, l, m, n;
+ unsigned char pc1m[56], pcr[56];
+ unsigned long kn[32];
+
+ for ( j = 0; j < 56; j++ ) {
+ l = pc1[j];
+ m = l & 07;
+ pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
+ }
+ for( i = 0; i < 16; i++ ) {
+ if( edf == DE1 ) m = (15 - i) << 1;
+ else m = i << 1;
+ n = m + 1;
+ kn[m] = kn[n] = 0L;
+ for( j = 0; j < 28; j++ ) {
+ l = j + totrot[i];
+ if( l < 28 ) pcr[j] = pc1m[l];
+ else pcr[j] = pc1m[l - 28];
+ }
+ for( j = 28; j < 56; j++ ) {
+ l = j + totrot[i];
+ if( l < 56 ) pcr[j] = pc1m[l];
+ else pcr[j] = pc1m[l - 28];
+ }
+ for( j = 0; j < 24; j++ ) {
+ if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
+ if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
+ }
+ }
+ cookey(kn);
+ return;
+ }
static void cookey(register unsigned long *raw1)
{
- register unsigned long *cook, *raw0;
- unsigned long dough[32];
- register int i;
-
- cook = dough;
- for( i = 0; i < 16; i++, raw1++ ) {
- raw0 = raw1++;
- *cook = (*raw0 & 0x00fc0000L) << 6;
- *cook |= (*raw0 & 0x00000fc0L) << 10;
- *cook |= (*raw1 & 0x00fc0000L) >> 10;
- *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
- *cook = (*raw0 & 0x0003f000L) << 12;
- *cook |= (*raw0 & 0x0000003fL) << 16;
- *cook |= (*raw1 & 0x0003f000L) >> 4;
- *cook++ |= (*raw1 & 0x0000003fL);
- }
- usekey(dough);
- return;
- }
+ register unsigned long *cook, *raw0;
+ unsigned long dough[32];
+ register int i;
+
+ cook = dough;
+ for( i = 0; i < 16; i++, raw1++ ) {
+ raw0 = raw1++;
+ *cook = (*raw0 & 0x00fc0000L) << 6;
+ *cook |= (*raw0 & 0x00000fc0L) << 10;
+ *cook |= (*raw1 & 0x00fc0000L) >> 10;
+ *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
+ *cook = (*raw0 & 0x0003f000L) << 12;
+ *cook |= (*raw0 & 0x0000003fL) << 16;
+ *cook |= (*raw1 & 0x0003f000L) >> 4;
+ *cook++ |= (*raw1 & 0x0000003fL);
+ }
+ usekey(dough);
+ return;
+ }
void usekey(register unsigned long *from)
{
- register unsigned long *to, *endp;
+ register unsigned long *to, *endp;
- to = KnL, endp = &KnL[32];
- while( to < endp ) *to++ = *from++;
- return;
- }
+ to = KnL, endp = &KnL[32];
+ while( to < endp ) *to++ = *from++;
+ return;
+ }
void des(unsigned char *inblock, unsigned char *outblock)
{
- unsigned long work[2];
+ unsigned long work[2];
- scrunch(inblock, work);
- desfunc(work, KnL);
- unscrun(work, outblock);
- return;
- }
+ scrunch(inblock, work);
+ desfunc(work, KnL);
+ unscrun(work, outblock);
+ return;
+ }
static void scrunch(register unsigned char *outof, register unsigned long *into)
{
- *into = (*outof++ & 0xffL) << 24;
- *into |= (*outof++ & 0xffL) << 16;
- *into |= (*outof++ & 0xffL) << 8;
- *into++ |= (*outof++ & 0xffL);
- *into = (*outof++ & 0xffL) << 24;
- *into |= (*outof++ & 0xffL) << 16;
- *into |= (*outof++ & 0xffL) << 8;
- *into |= (*outof & 0xffL);
- return;
- }
+ *into = (*outof++ & 0xffL) << 24;
+ *into |= (*outof++ & 0xffL) << 16;
+ *into |= (*outof++ & 0xffL) << 8;
+ *into++ |= (*outof++ & 0xffL);
+ *into = (*outof++ & 0xffL) << 24;
+ *into |= (*outof++ & 0xffL) << 16;
+ *into |= (*outof++ & 0xffL) << 8;
+ *into |= (*outof & 0xffL);
+ return;
+ }
static void unscrun(register unsigned long *outof, register unsigned char *into)
{
- *into++ = (unsigned char)((*outof >> 24) & 0xffL);
- *into++ = (unsigned char)((*outof >> 16) & 0xffL);
- *into++ = (unsigned char)((*outof >> 8) & 0xffL);
- *into++ = (unsigned char)(*outof++ & 0xffL);
- *into++ = (unsigned char)((*outof >> 24) & 0xffL);
- *into++ = (unsigned char)((*outof >> 16) & 0xffL);
- *into++ = (unsigned char)((*outof >> 8) & 0xffL);
- *into = (unsigned char)(*outof & 0xffL);
- return;
- }
+ *into++ = (unsigned char)((*outof >> 24) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 16) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 8) & 0xffL);
+ *into++ = (unsigned char)(*outof++ & 0xffL);
+ *into++ = (unsigned char)((*outof >> 24) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 16) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 8) & 0xffL);
+ *into = (unsigned char)(*outof & 0xffL);
+ return;
+ }
static const unsigned long SP1[64] = {
- 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
- 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
- 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
- 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
- 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
- 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
- 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
- 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
- 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
- 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
- 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
- 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
- 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
- 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
- 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
- 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
+ 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
+ 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
+ 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
+ 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
+ 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
+ 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
+ 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
+ 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
+ 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
+ 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
+ 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
+ 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
+ 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
+ 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
static const unsigned long SP2[64] = {
- 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
- 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
- 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
- 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
- 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
- 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
- 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
- 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
- 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
- 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
- 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
- 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
- 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
- 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
- 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
- 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
+ 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
+ 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
+ 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
+ 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
+ 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
+ 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
+ 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
+ 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
+ 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
+ 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
+ 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
+ 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
+ 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
+ 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
+ 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
+ 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
static const unsigned long SP3[64] = {
- 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
- 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
- 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
- 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
- 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
- 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
- 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
- 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
- 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
- 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
- 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
- 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
- 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
- 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
- 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
- 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
+ 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
+ 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
+ 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
+ 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
+ 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
+ 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
+ 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
+ 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
+ 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
+ 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
+ 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
+ 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
+ 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
+ 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
+ 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
+ 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
static const unsigned long SP4[64] = {
- 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
- 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
- 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
- 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
- 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
- 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
- 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
- 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
- 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
- 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
- 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
- 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
- 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
- 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
- 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
- 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
+ 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
+ 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
+ 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
+ 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
+ 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
+ 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
+ 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
+ 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
+ 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
+ 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
+ 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
+ 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
+ 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
+ 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
static const unsigned long SP5[64] = {
- 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
- 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
- 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
- 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
- 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
- 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
- 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
- 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
- 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
- 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
- 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
- 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
- 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
- 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
- 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
- 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
+ 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
+ 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
+ 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
+ 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
+ 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
+ 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
+ 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
+ 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
+ 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
+ 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
+ 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
+ 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
+ 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
+ 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
+ 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
+ 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
static const unsigned long SP6[64] = {
- 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
- 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
- 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
- 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
- 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
- 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
- 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
- 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
- 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
- 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
- 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
- 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
- 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
- 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
- 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
- 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
+ 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
+ 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
+ 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
+ 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
+ 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
+ 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
+ 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
+ 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
+ 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
+ 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
+ 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
+ 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
+ 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
+ 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
+ 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
+ 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
static const unsigned long SP7[64] = {
- 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
- 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
- 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
- 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
- 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
- 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
- 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
- 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
- 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
- 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
- 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
- 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
- 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
- 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
- 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
- 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
+ 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
+ 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
+ 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
+ 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
+ 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
+ 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
+ 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
+ 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
+ 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
+ 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
+ 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
+ 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
+ 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
+ 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
+ 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
+ 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
static const unsigned long SP8[64] = {
- 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
- 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
- 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
- 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
- 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
- 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
- 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
- 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
- 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
- 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
- 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
- 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
- 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
- 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
- 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
- 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
+ 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
+ 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
+ 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
+ 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
+ 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
+ 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
+ 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
+ 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
+ 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
+ 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
+ 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
+ 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
+ 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
+ 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
+ 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
+ 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
static void desfunc(register unsigned long *block, register unsigned long *keys)
{
- register unsigned long fval, work, right, leftt;
- register int round;
-
- leftt = block[0];
- right = block[1];
- work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
- right ^= work;
- leftt ^= (work << 4);
- work = ((leftt >> 16) ^ right) & 0x0000ffffL;
- right ^= work;
- leftt ^= (work << 16);
- work = ((right >> 2) ^ leftt) & 0x33333333L;
- leftt ^= work;
- right ^= (work << 2);
- work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
- leftt ^= work;
- right ^= (work << 8);
- right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
- work = (leftt ^ right) & 0xaaaaaaaaL;
- leftt ^= work;
- right ^= work;
- leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
-
- for( round = 0; round < 8; round++ ) {
- work = (right << 28) | (right >> 4);
- work ^= *keys++;
- fval = SP7[ work & 0x3fL];
- fval |= SP5[(work >> 8) & 0x3fL];
- fval |= SP3[(work >> 16) & 0x3fL];
- fval |= SP1[(work >> 24) & 0x3fL];
- work = right ^ *keys++;
- fval |= SP8[ work & 0x3fL];
- fval |= SP6[(work >> 8) & 0x3fL];
- fval |= SP4[(work >> 16) & 0x3fL];
- fval |= SP2[(work >> 24) & 0x3fL];
- leftt ^= fval;
- work = (leftt << 28) | (leftt >> 4);
- work ^= *keys++;
- fval = SP7[ work & 0x3fL];
- fval |= SP5[(work >> 8) & 0x3fL];
- fval |= SP3[(work >> 16) & 0x3fL];
- fval |= SP1[(work >> 24) & 0x3fL];
- work = leftt ^ *keys++;
- fval |= SP8[ work & 0x3fL];
- fval |= SP6[(work >> 8) & 0x3fL];
- fval |= SP4[(work >> 16) & 0x3fL];
- fval |= SP2[(work >> 24) & 0x3fL];
- right ^= fval;
- }
-
- right = (right << 31) | (right >> 1);
- work = (leftt ^ right) & 0xaaaaaaaaL;
- leftt ^= work;
- right ^= work;
- leftt = (leftt << 31) | (leftt >> 1);
- work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
- right ^= work;
- leftt ^= (work << 8);
- work = ((leftt >> 2) ^ right) & 0x33333333L;
- right ^= work;
- leftt ^= (work << 2);
- work = ((right >> 16) ^ leftt) & 0x0000ffffL;
- leftt ^= work;
- right ^= (work << 16);
- work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
- leftt ^= work;
- right ^= (work << 4);
- *block++ = right;
- *block = leftt;
- return;
- }
+ register unsigned long fval, work, right, leftt;
+ register int round;
+
+ leftt = block[0];
+ right = block[1];
+ work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
+ right ^= work;
+ leftt ^= (work << 4);
+ work = ((leftt >> 16) ^ right) & 0x0000ffffL;
+ right ^= work;
+ leftt ^= (work << 16);
+ work = ((right >> 2) ^ leftt) & 0x33333333L;
+ leftt ^= work;
+ right ^= (work << 2);
+ work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
+ leftt ^= work;
+ right ^= (work << 8);
+ right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
+ work = (leftt ^ right) & 0xaaaaaaaaL;
+ leftt ^= work;
+ right ^= work;
+ leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
+
+ for( round = 0; round < 8; round++ ) {
+ work = (right << 28) | (right >> 4);
+ work ^= *keys++;
+ fval = SP7[ work & 0x3fL];
+ fval |= SP5[(work >> 8) & 0x3fL];
+ fval |= SP3[(work >> 16) & 0x3fL];
+ fval |= SP1[(work >> 24) & 0x3fL];
+ work = right ^ *keys++;
+ fval |= SP8[ work & 0x3fL];
+ fval |= SP6[(work >> 8) & 0x3fL];
+ fval |= SP4[(work >> 16) & 0x3fL];
+ fval |= SP2[(work >> 24) & 0x3fL];
+ leftt ^= fval;
+ work = (leftt << 28) | (leftt >> 4);
+ work ^= *keys++;
+ fval = SP7[ work & 0x3fL];
+ fval |= SP5[(work >> 8) & 0x3fL];
+ fval |= SP3[(work >> 16) & 0x3fL];
+ fval |= SP1[(work >> 24) & 0x3fL];
+ work = leftt ^ *keys++;
+ fval |= SP8[ work & 0x3fL];
+ fval |= SP6[(work >> 8) & 0x3fL];
+ fval |= SP4[(work >> 16) & 0x3fL];
+ fval |= SP2[(work >> 24) & 0x3fL];
+ right ^= fval;
+ }
+
+ right = (right << 31) | (right >> 1);
+ work = (leftt ^ right) & 0xaaaaaaaaL;
+ leftt ^= work;
+ right ^= work;
+ leftt = (leftt << 31) | (leftt >> 1);
+ work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
+ right ^= work;
+ leftt ^= (work << 8);
+ work = ((leftt >> 2) ^ right) & 0x33333333L;
+ right ^= work;
+ leftt ^= (work << 2);
+ work = ((right >> 16) ^ leftt) & 0x0000ffffL;
+ leftt ^= work;
+ right ^= (work << 16);
+ work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
+ leftt ^= work;
+ right ^= (work << 4);
+ *block++ = right;
+ *block = leftt;
+ return;
+ }
/* Validation sets:
*
#include "crypto/tlscredspsk.h"
#include "crypto/tlscredsx509.h"
#include "qapi/error.h"
-#include "qemu/acl.h"
+#include "authz/base.h"
#include "trace.h"
#ifdef CONFIG_GNUTLS
QCryptoTLSCreds *creds;
gnutls_session_t handle;
char *hostname;
- char *aclname;
+ char *authzid;
bool handshakeComplete;
QCryptoTLSSessionWriteFunc writeFunc;
QCryptoTLSSessionReadFunc readFunc;
gnutls_deinit(session->handle);
g_free(session->hostname);
g_free(session->peername);
- g_free(session->aclname);
+ g_free(session->authzid);
object_unref(OBJECT(session->creds));
g_free(session);
}
QCryptoTLSSession *
qcrypto_tls_session_new(QCryptoTLSCreds *creds,
const char *hostname,
- const char *aclname,
+ const char *authzid,
QCryptoTLSCredsEndpoint endpoint,
Error **errp)
{
session = g_new0(QCryptoTLSSession, 1);
trace_qcrypto_tls_session_new(
session, creds, hostname ? hostname : "<none>",
- aclname ? aclname : "<none>", endpoint);
+ authzid ? authzid : "<none>", endpoint);
if (hostname) {
session->hostname = g_strdup(hostname);
}
- if (aclname) {
- session->aclname = g_strdup(aclname);
+ if (authzid) {
+ session->authzid = g_strdup(authzid);
}
session->creds = creds;
object_ref(OBJECT(creds));
unsigned int nCerts, i;
time_t now;
gnutls_x509_crt_t cert = NULL;
+ Error *err = NULL;
now = time(NULL);
if (now == ((time_t)-1)) {
gnutls_strerror(ret));
goto error;
}
- if (session->aclname) {
- qemu_acl *acl = qemu_acl_find(session->aclname);
- int allow;
- if (!acl) {
- error_setg(errp, "Cannot find ACL %s",
- session->aclname);
+ if (session->authzid) {
+ bool allow;
+
+ allow = qauthz_is_allowed_by_id(session->authzid,
+ session->peername, &err);
+ if (err) {
+ error_propagate(errp, err);
goto error;
}
-
- allow = qemu_acl_party_is_allowed(acl, session->peername);
-
if (!allow) {
- error_setg(errp, "TLS x509 ACL check for %s is denied",
+ error_setg(errp, "TLS x509 authz check for %s is denied",
session->peername);
goto error;
}
QCryptoTLSSession *
qcrypto_tls_session_new(QCryptoTLSCreds *creds G_GNUC_UNUSED,
const char *hostname G_GNUC_UNUSED,
- const char *aclname G_GNUC_UNUSED,
+ const char *authzid G_GNUC_UNUSED,
QCryptoTLSCredsEndpoint endpoint G_GNUC_UNUSED,
Error **errp)
{
qcrypto_tls_creds_x509_load_cert_list(void *creds, const char *file) "TLS creds x509 load cert list creds=%p file=%s"
# crypto/tlssession.c
-qcrypto_tls_session_new(void *session, void *creds, const char *hostname, const char *aclname, int endpoint) "TLS session new session=%p creds=%p hostname=%s aclname=%s endpoint=%d"
+qcrypto_tls_session_new(void *session, void *creds, const char *hostname, const char *authzid, int endpoint) "TLS session new session=%p creds=%p hostname=%s authzid=%s endpoint=%d"
qcrypto_tls_session_check_creds(void *session, const char *status) "TLS session check creds session=%p status=%s"
CONFIG_MC146818RTC=y
CONFIG_ISA_TESTDEV=y
CONFIG_SMC37C669=y
+CONFIG_DP264=y
CONFIG_NAND=y
CONFIG_ECC=y
CONFIG_SERIAL=y
-CONFIG_SERIAL_ISA=y
CONFIG_PTIMER=y
CONFIG_SD=y
CONFIG_MAX7310=y
CONFIG_IMX=y
CONFIG_MAINSTONE=y
CONFIG_MPS2=y
+CONFIG_MUSCA=y
CONFIG_NSERIES=y
CONFIG_RASPI=y
CONFIG_REALVIEW=y
CONFIG_IOTKIT_SYSCTL=y
CONFIG_IOTKIT_SYSINFO=y
CONFIG_ARMSSE_CPUID=y
+CONFIG_ARMSSE_MHU=y
CONFIG_VERSATILE=y
CONFIG_VERSATILE_PCI=y
CONFIG_VERSATILE_I2C=y
-CONFIG_PCI_GENERIC=y
+CONFIG_PCI_EXPRESS_GENERIC_BRIDGE=y
+CONFIG_VFIO=$(CONFIG_LINUX)
+CONFIG_VFIO_PLATFORM=y
CONFIG_VFIO_XGMAC=y
CONFIG_VFIO_AMD_XGBE=y
CONFIG_IOH3420=y
CONFIG_I82801B11=y
CONFIG_ACPI=y
+CONFIG_ARM_VIRT=y
CONFIG_SMBIOS=y
CONFIG_ASPEED_SOC=y
+CONFIG_SMBUS_EEPROM=y
CONFIG_GPIO_KEY=y
CONFIG_MSF2=y
CONFIG_FW_CFG_DMA=y
CONFIG_XILINX_AXI=y
-CONFIG_PCI_DESIGNWARE=y
+CONFIG_PCI_EXPRESS_DESIGNWARE=y
CONFIG_STRONGARM=y
CONFIG_HIGHBANK=y
CONFIG_NAND=y
CONFIG_PTIMER=y
CONFIG_PFLASH_CFI02=y
+CONFIG_AXIS=y
# CONFIG_IDE_MMIO=y
CONFIG_VIRTIO_VGA=y
CONFIG_MC146818RTC=y
+CONFIG_DINO=y
CONFIG_VMPORT=y
CONFIG_SGA=y
CONFIG_LPC_ICH9=y
-CONFIG_PCI_Q35=y
+CONFIG_PCI_EXPRESS_Q35=y
CONFIG_APIC=y
CONFIG_IOAPIC=y
CONFIG_PVPANIC=y
CONFIG_SMBIOS=y
CONFIG_PXB=y
CONFIG_ACPI_VMGENID=y
+CONFIG_ACPI_SMBUS=y
+CONFIG_SMBUS_EEPROM=y
CONFIG_FW_CFG_DMA=y
CONFIG_I2C=y
CONFIG_SEV=$(CONFIG_KVM)
CONFIG_VTD=y
CONFIG_AMD_IOMMU=y
+CONFIG_PAM=y
+CONFIG_I440FX=y
+CONFIG_Q35=y
CONFIG_COLDFIRE=y
CONFIG_PTIMER=y
+CONFIG_AN5206=y
+CONFIG_MCF5208=y
CONFIG_SSI=y
CONFIG_SSI_M25P80=y
CONFIG_XLNX_ZYNQMP=y
+CONFIG_PETALOGIX_S3ADSP1800=y
+CONFIG_PETALOGIX_ML605=y
+CONFIG_XLNX_ZYNQMP_PMU=y
CONFIG_MIPS_CPS=y
CONFIG_MIPS_ITU=y
CONFIG_I2C=y
+CONFIG_R4K=y
+CONFIG_MALTA=y
+CONFIG_MIPSSIM=y
+CONFIG_ACPI_SMBUS=y
+CONFIG_SMBUS_EEPROM=y
CONFIG_VT82C686=y
CONFIG_MIPS_BOSTON=y
CONFIG_FITLOADER=y
-CONFIG_PCI_XILINX=y
+CONFIG_PCI_EXPRESS_XILINX=y
CONFIG_SERIAL=y
CONFIG_SERIAL_ISA=y
CONFIG_VGA=y
+CONFIG_MOXIESIM=y
CONFIG_SERIAL=y
CONFIG_PTIMER=y
CONFIG_ALTERA_TIMER=y
+CONFIG_NIOS2_10M50=y
CONFIG_SERIAL=y
CONFIG_OPENCORES_ETH=y
CONFIG_OMPIC=y
+CONFIG_OR1K_SIM=y
CONFIG_MPTSAS_SCSI_PCI=y
CONFIG_RTL8139_PCI=y
CONFIG_E1000_PCI=y
-CONFIG_E1000E_PCI=y
+CONFIG_E1000E_PCI_EXPRESS=y
CONFIG_IDE_CORE=y
CONFIG_IDE_QDEV=y
CONFIG_IDE_PCI=y
CONFIG_BOCHS_DISPLAY=y
CONFIG_IVSHMEM_DEVICE=$(CONFIG_IVSHMEM)
CONFIG_ROCKER=y
+CONFIG_VFIO=$(CONFIG_LINUX)
+CONFIG_VFIO_PCI=y
CONFIG_OPENPIC_KVM=$(call land,$(CONFIG_E500),$(CONFIG_KVM))
CONFIG_PLATFORM_BUS=y
CONFIG_ETSEC=y
+CONFIG_PPC405=y
+CONFIG_PPC440=y
+CONFIG_VIRTEX=y
+
# For Sam460ex
CONFIG_SAM460EX=y
CONFIG_USB_EHCI_SYSBUS=y
CONFIG_BITBANG_I2C=y
CONFIG_M41T80=y
CONFIG_VGA_CIRRUS=y
+CONFIG_SMBUS_EEPROM=y
# For Macs
-CONFIG_MAC=y
CONFIG_ESCC=y
CONFIG_MACIO=y
CONFIG_MACIO_GPIO=y
CONFIG_UNIN_PCI=y
CONFIG_DEC_PCI=y
CONFIG_IDE_MACIO=y
+CONFIG_MAC_OLDWORLD=y
+CONFIG_MAC_NEWWORLD=y
# For PReP
CONFIG_PREP=y
CONFIG_CADENCE=y
-CONFIG_PCI_GENERIC=y
+CONFIG_PCI_EXPRESS_GENERIC_BRIDGE=y
CONFIG_VGA=y
CONFIG_VGA_PCI=y
+
+CONFIG_SPIKE=y
+CONFIG_HART=y
+CONFIG_SIFIVE_E=y
+CONFIG_SIFIVE=y
+CONFIG_SIFIVE_U=y
+CONFIG_RISCV_VIRT=y
CONFIG_CADENCE=y
-CONFIG_PCI_GENERIC=y
+CONFIG_PCI_EXPRESS_GENERIC_BRIDGE=y
CONFIG_VGA=y
CONFIG_VGA_PCI=y
+
+CONFIG_SPIKE=y
+CONFIG_HART=y
+CONFIG_SIFIVE_E=y
+CONFIG_SIFIVE=y
+CONFIG_SIFIVE_U=y
+CONFIG_RISCV_VIRT=y
CONFIG_TERMINAL3270=y
CONFIG_S390_FLIC=y
CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
-CONFIG_VFIO_CCW=$(CONFIG_LINUX)
CONFIG_WDT_DIAG288=y
-CONFIG_VFIO_AP=$(CONFIG_LINUX)
+CONFIG_S390_CCW_VIRTIO=y
+CONFIG_VFIO=$(CONFIG_LINUX)
+CONFIG_VFIO_CCW=y
+CONFIG_VFIO_AP=y
CONFIG_I82374=y
CONFIG_I8257=y
CONFIG_MC146818RTC=y
+CONFIG_R2D=y
+CONFIG_SHIX=y
CONFIG_I82374=y
CONFIG_I8257=y
CONFIG_MC146818RTC=y
+CONFIG_R2D=y
+CONFIG_SHIX=y
CONFIG_GRLIB=y
CONFIG_STP2000=y
CONFIG_ECCMEMCTL=y
+
CONFIG_SUN4M=y
+CONFIG_LEON3=y
CONFIG_MC146818RTC=y
CONFIG_ISA_TESTDEV=y
CONFIG_SUN4V_RTC=y
+CONFIG_SUN4U=y
+CONFIG_NIAGARA=y
CONFIG_SERIAL=y
CONFIG_OPENCORES_ETH=y
CONFIG_PFLASH_CFI01=y
+
+CONFIG_XTENSA_SIM=y
+CONFIG_XTENSA_FPGA=y
CONFIG_SERIAL=y
CONFIG_OPENCORES_ETH=y
CONFIG_PFLASH_CFI01=y
+
+CONFIG_XTENSA_SIM=y
+CONFIG_XTENSA_FPGA=y
}
-uint64 NMD::extract_ac_13_12(uint64 instruction)
+uint64 NMD::extract_ac_15_14(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 14, 2);
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 size_value = extract_size_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 size_value = extract_size_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 shift_value = extract_shift_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 shift_value = extract_shift_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 shift_value = extract_shift_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 shift_value = extract_shift_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
std::string NMD::MFHI_DSP_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
std::string NMD::MFLO_DSP_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
std::string NMD::MTHI_DSP_(uint64 instruction)
{
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rs = GPR(copy(rs_value));
std::string ac = AC(copy(ac_value));
std::string NMD::MTHLIP(uint64 instruction)
{
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rs = GPR(copy(rs_value));
std::string ac = AC(copy(ac_value));
std::string NMD::MTLO_DSP_(uint64 instruction)
{
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rs = GPR(copy(rs_value));
std::string ac = AC(copy(ac_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
std::string NMD::SHILO(uint64 instruction)
{
int64 shift_value = extract_shift__se5_21_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string shift = IMMEDIATE(copy(shift_value));
std::string ac = AC(copy(ac_value));
std::string NMD::SHILOV(uint64 instruction)
{
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rs = GPR(copy(rs_value));
std::string ac = AC(copy(ac_value));
int64 extract_s__se31_0_11_to_2_20_to_12_s12(uint64 instruction);
int64 extract_shift__se5_21_20_19_18_17_16(uint64 instruction);
- uint64 extract_ac_13_12(uint64 instruction);
+ uint64 extract_ac_15_14(uint64 instruction);
uint64 extract_bit_16_15_14_13_12_11(uint64 instruction);
uint64 extract_bit_23_22_21(uint64 instruction);
uint64 extract_c0s_20_19_18_17_16(uint64 instruction);
[Uninteresting stuff omitted...]
+For a modular QAPI schema (see section Include directives), code for
+each sub-module SUBDIR/SUBMODULE.json is actually generated into
+
+SUBDIR/$(prefix)qapi-types-SUBMODULE.h
+SUBDIR/$(prefix)qapi-types-SUBMODULE.c
+
+If qapi-gen.py is run with option --builtins, additional files are
+created:
+
+qapi-builtin-types.h - C types corresponding to built-in types
+
+qapi-builtin-types.c - Cleanup functions for the above C types
+
=== Code generated for visiting QAPI types ===
These are the visitor functions used to walk through and convert
[Uninteresting stuff omitted...]
+For a modular QAPI schema (see section Include directives), code for
+each sub-module SUBDIR/SUBMODULE.json is actually generated into
+
+SUBDIR/$(prefix)qapi-visit-SUBMODULE.h
+SUBDIR/$(prefix)qapi-visit-SUBMODULE.c
+
+If qapi-gen.py is run with option --builtins, additional files are
+created:
+
+qapi-builtin-visit.h - Visitor functions for built-in types
+
+qapi-builtin-visit.c - Declarations for these visitor functions
+
=== Code generated for commands ===
These are the marshaling/dispatch functions for the commands defined
[Uninteresting stuff omitted...]
+For a modular QAPI schema (see section Include directives), code for
+each sub-module SUBDIR/SUBMODULE.json is actually generated into
+
+SUBDIR/$(prefix)qapi-commands-SUBMODULE.h
+SUBDIR/$(prefix)qapi-commands-SUBMODULE.c
+
=== Code generated for events ===
This is the code related to events defined in the schema, providing
The following files are created:
-$(prefix)qapi-events.h - Function prototypes for each event type, plus an
- enumeration of all event names
+$(prefix)qapi-events.h - Function prototypes for each event type
$(prefix)qapi-events.c - Implementation of functions to send an event
+$(prefix)qapi-emit-events.h - Enumeration of all event names, and
+ common event code declarations
+
+$(prefix)qapi-emit-events.c - Common event code definitions
+
Example:
$ cat qapi-generated/example-qapi-events.h
#include "qapi/util.h"
#include "example-qapi-types.h"
-
void qapi_event_send_my_event(void);
- typedef enum example_QAPIEvent {
- EXAMPLE_QAPI_EVENT_MY_EVENT,
- EXAMPLE_QAPI_EVENT__MAX,
- } example_QAPIEvent;
-
- #define example_QAPIEvent_str(val) \
- qapi_enum_lookup(&example_QAPIEvent_lookup, (val))
-
- extern const QEnumLookup example_QAPIEvent_lookup;
-
#endif /* EXAMPLE_QAPI_EVENTS_H */
$ cat qapi-generated/example-qapi-events.c
[Uninteresting stuff omitted...]
qobject_unref(qmp);
}
+[Uninteresting stuff omitted...]
+ $ cat qapi-generated/example-qapi-emit-events.h
+[Uninteresting stuff omitted...]
+
+ #ifndef EXAMPLE_QAPI_EMIT_EVENTS_H
+ #define EXAMPLE_QAPI_EMIT_EVENTS_H
+
+ #include "qapi/util.h"
+
+ typedef enum example_QAPIEvent {
+ EXAMPLE_QAPI_EVENT_MY_EVENT,
+ EXAMPLE_QAPI_EVENT__MAX,
+ } example_QAPIEvent;
+
+ #define example_QAPIEvent_str(val) \
+ qapi_enum_lookup(&example_QAPIEvent_lookup, (val))
+
+ extern const QEnumLookup example_QAPIEvent_lookup;
+
+ void example_qapi_event_emit(example_QAPIEvent event, QDict *qdict);
+
+ #endif /* EXAMPLE_QAPI_EMIT_EVENTS_H */
+ $ cat qapi-generated/example-qapi-emit-events.c
+[Uninteresting stuff omitted...]
+
const QEnumLookup example_QAPIEvent_lookup = {
.array = (const char *const[]) {
[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
[Uninteresting stuff omitted...]
+For a modular QAPI schema (see section Include directives), code for
+each sub-module SUBDIR/SUBMODULE.json is actually generated into
+
+SUBDIR/$(prefix)qapi-events-SUBMODULE.h
+SUBDIR/$(prefix)qapi-events-SUBMODULE.c
+
=== Code generated for introspection ===
The following files are created:
.. code::
$ sudo groupadd docker
- $ sudo usermod $USER -G docker
+ $ sudo usermod $USER -a -G docker
$ sudo chown :docker /var/run/docker.sock
Note that any one of above configurations makes it possible for the user to
-device usb-braille,chardev=braille -chardev braille,id=braille
-* -virtioconsole becomes
- -device virtio-serial-pci,class=C,vectors=V,ioeventfd=IOEVENTFD,max_ports=N
- -device virtconsole,is_console=NUM,nr=NR,name=NAME
-
LEGACY-CHARDEV translates to -chardev HOST-OPTS... as follows:
* null becomes -chardev null
phdr.p_paddr = cpu_to_dump64(s, memory_mapping->phys_addr);
phdr.p_filesz = cpu_to_dump64(s, filesz);
phdr.p_memsz = cpu_to_dump64(s, memory_mapping->length);
- phdr.p_vaddr = cpu_to_dump64(s, memory_mapping->virt_addr);
+ phdr.p_vaddr = cpu_to_dump64(s, memory_mapping->virt_addr) ?: phdr.p_paddr;
assert(memory_mapping->length >= filesz);
phdr.p_paddr = cpu_to_dump32(s, memory_mapping->phys_addr);
phdr.p_filesz = cpu_to_dump32(s, filesz);
phdr.p_memsz = cpu_to_dump32(s, memory_mapping->length);
- phdr.p_vaddr = cpu_to_dump32(s, memory_mapping->virt_addr);
+ phdr.p_vaddr =
+ cpu_to_dump32(s, memory_mapping->virt_addr) ?: phdr.p_paddr;
assert(memory_mapping->length >= filesz);
};
static MemTxResult flatview_read(FlatView *fv, hwaddr addr,
- MemTxAttrs attrs, uint8_t *buf, int len);
+ MemTxAttrs attrs, uint8_t *buf, hwaddr len);
static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
- const uint8_t *buf, int len);
-static bool flatview_access_valid(FlatView *fv, hwaddr addr, int len,
+ const uint8_t *buf, hwaddr len);
+static bool flatview_access_valid(FlatView *fv, hwaddr addr, hwaddr len,
bool is_write, MemTxAttrs attrs);
static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data,
/* physical memory access (slow version, mainly for debug) */
#if defined(CONFIG_USER_ONLY)
int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
- uint8_t *buf, int len, int is_write)
+ uint8_t *buf, target_ulong len, int is_write)
{
- int l, flags;
- target_ulong page;
+ int flags;
+ target_ulong l, page;
void * p;
while (len > 0) {
static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr,
MemTxAttrs attrs,
const uint8_t *buf,
- int len, hwaddr addr1,
+ hwaddr len, hwaddr addr1,
hwaddr l, MemoryRegion *mr)
{
uint8_t *ptr;
/* Called from RCU critical section. */
static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
- const uint8_t *buf, int len)
+ const uint8_t *buf, hwaddr len)
{
hwaddr l;
hwaddr addr1;
/* Called within RCU critical section. */
MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
MemTxAttrs attrs, uint8_t *buf,
- int len, hwaddr addr1, hwaddr l,
+ hwaddr len, hwaddr addr1, hwaddr l,
MemoryRegion *mr)
{
uint8_t *ptr;
/* Called from RCU critical section. */
static MemTxResult flatview_read(FlatView *fv, hwaddr addr,
- MemTxAttrs attrs, uint8_t *buf, int len)
+ MemTxAttrs attrs, uint8_t *buf, hwaddr len)
{
hwaddr l;
hwaddr addr1;
}
MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr,
- MemTxAttrs attrs, uint8_t *buf, int len)
+ MemTxAttrs attrs, uint8_t *buf, hwaddr len)
{
MemTxResult result = MEMTX_OK;
FlatView *fv;
MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs,
- const uint8_t *buf, int len)
+ const uint8_t *buf, hwaddr len)
{
MemTxResult result = MEMTX_OK;
FlatView *fv;
}
MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
- uint8_t *buf, int len, bool is_write)
+ uint8_t *buf, hwaddr len, bool is_write)
{
if (is_write) {
return address_space_write(as, addr, attrs, buf, len);
}
void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
- int len, int is_write)
+ hwaddr len, int is_write)
{
address_space_rw(&address_space_memory, addr, MEMTXATTRS_UNSPECIFIED,
buf, len, is_write);
hwaddr addr,
MemTxAttrs attrs,
const uint8_t *buf,
- int len,
+ hwaddr len,
enum write_rom_type type)
{
hwaddr l;
/* used for ROM loading : can write in RAM and ROM */
MemTxResult address_space_write_rom(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs,
- const uint8_t *buf, int len)
+ const uint8_t *buf, hwaddr len)
{
return address_space_write_rom_internal(as, addr, attrs,
buf, len, WRITE_DATA);
}
-void cpu_flush_icache_range(hwaddr start, int len)
+void cpu_flush_icache_range(hwaddr start, hwaddr len)
{
/*
* This function should do the same thing as an icache flush that was
qemu_mutex_unlock(&map_client_list_lock);
}
-static bool flatview_access_valid(FlatView *fv, hwaddr addr, int len,
+static bool flatview_access_valid(FlatView *fv, hwaddr addr, hwaddr len,
bool is_write, MemTxAttrs attrs)
{
MemoryRegion *mr;
}
bool address_space_access_valid(AddressSpace *as, hwaddr addr,
- int len, bool is_write,
+ hwaddr len, bool is_write,
MemTxAttrs attrs)
{
FlatView *fv;
*/
void
address_space_read_cached_slow(MemoryRegionCache *cache, hwaddr addr,
- void *buf, int len)
+ void *buf, hwaddr len)
{
hwaddr addr1, l;
MemoryRegion *mr;
*/
void
address_space_write_cached_slow(MemoryRegionCache *cache, hwaddr addr,
- const void *buf, int len)
+ const void *buf, hwaddr len)
{
hwaddr addr1, l;
MemoryRegion *mr;
/* virtual memory access for debug (includes writing to ROM) */
int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
- uint8_t *buf, int len, int is_write)
+ uint8_t *buf, target_ulong len, int is_write)
{
- int l;
hwaddr phys_addr;
- target_ulong page;
+ target_ulong l, page;
cpu_synchronize_state(cpu);
while (len > 0) {
static FloatParts round_canonical(FloatParts p, float_status *s,
const FloatFmt *parm)
{
+ const uint64_t frac_lsb = parm->frac_lsb;
const uint64_t frac_lsbm1 = parm->frac_lsbm1;
const uint64_t round_mask = parm->round_mask;
const uint64_t roundeven_mask = parm->roundeven_mask;
inc = p.sign ? round_mask : 0;
overflow_norm = !p.sign;
break;
+ case float_round_to_odd:
+ overflow_norm = true;
+ inc = frac & frac_lsb ? 0 : round_mask;
+ break;
default:
g_assert_not_reached();
}
shift64RightJamming(frac, 1 - exp, &frac);
if (frac & round_mask) {
/* Need to recompute round-to-even. */
- if (s->float_rounding_mode == float_round_nearest_even) {
+ switch (s->float_rounding_mode) {
+ case float_round_nearest_even:
inc = ((frac & roundeven_mask) != frac_lsbm1
? frac_lsbm1 : 0);
+ break;
+ case float_round_to_odd:
+ inc = frac & frac_lsb ? 0 : round_mask;
+ break;
}
flags |= float_flag_inexact;
frac += inc;
case float_round_down:
one = a.sign;
break;
+ case float_round_to_odd:
+ one = true;
+ break;
default:
g_assert_not_reached();
}
case float_round_down:
inc = a.sign ? rnd_mask : 0;
break;
+ case float_round_to_odd:
+ inc = a.frac & frac_lsb ? 0 : rnd_mask;
+ break;
default:
g_assert_not_reached();
}
case float_round_down:
roundIncrement = zSign ? 0x7f : 0;
break;
+ case float_round_to_odd:
+ roundIncrement = absZ & 0x80 ? 0 : 0x7f;
+ break;
default:
abort();
}
case float_round_down:
increment = zSign && absZ1;
break;
+ case float_round_to_odd:
+ increment = !(absZ0 & 1) && absZ1;
+ break;
default:
abort();
}
case float_round_down:
increment = zSign && absZ1;
break;
+ case float_round_to_odd:
+ increment = !(absZ0 & 1) && absZ1;
+ break;
default:
abort();
}
case float_round_down:
roundIncrement = zSign ? 0x7f : 0;
break;
+ case float_round_to_odd:
+ roundIncrement = zSig & 0x80 ? 0 : 0x7f;
+ break;
default:
abort();
break;
|| ( ( zExp == 0xFD )
&& ( (int32_t) ( zSig + roundIncrement ) < 0 ) )
) {
+ bool overflow_to_inf = roundingMode != float_round_to_odd &&
+ roundIncrement != 0;
float_raise(float_flag_overflow | float_flag_inexact, status);
- return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 ));
+ return packFloat32(zSign, 0xFF, -!overflow_to_inf);
}
if ( zExp < 0 ) {
if (status->flush_to_zero) {
if (isTiny && roundBits) {
float_raise(float_flag_underflow, status);
}
+ if (roundingMode == float_round_to_odd) {
+ /*
+ * For round-to-odd case, the roundIncrement depends on
+ * zSig which just changed.
+ */
+ roundIncrement = zSig & 0x80 ? 0 : 0x7f;
+ }
}
}
if (roundBits) {
return res;
}
+/*----------------------------------------------------------------------------
+| Returns the result of converting the quadruple-precision floating-point value
+| `a' to the 32-bit unsigned integer format. The conversion is
+| performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic---which means in particular that the conversion is rounded
+| according to the current rounding mode. If `a' is a NaN, the largest
+| positive integer is returned. If the conversion overflows, the
+| largest unsigned integer is returned. If 'a' is negative, the value is
+| rounded and zero is returned; negative values that do not round to zero
+| will raise the inexact exception.
+*----------------------------------------------------------------------------*/
+
+uint32_t float128_to_uint32(float128 a, float_status *status)
+{
+ uint64_t v;
+ uint32_t res;
+ int old_exc_flags = get_float_exception_flags(status);
+
+ v = float128_to_uint64(a, status);
+ if (v > 0xffffffff) {
+ res = 0xffffffff;
+ } else {
+ return v;
+ }
+ set_float_exception_flags(old_exc_flags, status);
+ float_raise(float_flag_invalid, status);
+ return res;
+}
+
/*----------------------------------------------------------------------------
| Returns the result of converting the quadruple-precision floating-point
| value `a' to the single-precision floating-point format. The conversion
add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low);
}
break;
+ case float_round_to_odd:
+ /*
+ * Note that if lastBitMask == 0, the last bit is the lsb
+ * of high, and roundBitsMask == -1.
+ */
+ if ((lastBitMask ? z.low & lastBitMask : z.high & 1) == 0) {
+ add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low);
+ }
+ break;
default:
abort();
}
status->float_exception_flags |= float_flag_inexact;
aSign = extractFloat128Sign( a );
switch (status->float_rounding_mode) {
- case float_round_nearest_even:
+ case float_round_nearest_even:
if ( ( aExp == 0x3FFE )
&& ( extractFloat128Frac0( a )
| extractFloat128Frac1( a ) )
return packFloat128(aSign, 0x3FFF, 0, 0);
}
break;
- case float_round_down:
+ case float_round_down:
return
aSign ? packFloat128( 1, 0x3FFF, 0, 0 )
: packFloat128( 0, 0, 0, 0 );
- case float_round_up:
+ case float_round_up:
return
aSign ? packFloat128( 1, 0, 0, 0 )
: packFloat128( 0, 0x3FFF, 0, 0 );
+
+ case float_round_to_odd:
+ return packFloat128(aSign, 0x3FFF, 0, 0);
}
return packFloat128( aSign, 0, 0, 0 );
}
z.high += roundBitsMask;
}
break;
+ case float_round_to_odd:
+ if ((z.high & lastBitMask) == 0) {
+ z.high |= (a.low != 0);
+ z.high += roundBitsMask;
+ }
+ break;
default:
abort();
}
+++ /dev/null
-<?xml version="1.0"?>
-<!-- Copyright (C) 2010-2015 Free Software Foundation, Inc.
-
- Copying and distribution of this file, with or without modification,
- are permitted in any medium without royalty provided the copyright
- notice and this notice are preserved. -->
-
-<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.i386.core">
- <flags id="i386_eflags" size="4">
- <field name="CF" start="0" end="0"/>
- <field name="" start="1" end="1"/>
- <field name="PF" start="2" end="2"/>
- <field name="AF" start="4" end="4"/>
- <field name="ZF" start="6" end="6"/>
- <field name="SF" start="7" end="7"/>
- <field name="TF" start="8" end="8"/>
- <field name="IF" start="9" end="9"/>
- <field name="DF" start="10" end="10"/>
- <field name="OF" start="11" end="11"/>
- <field name="NT" start="14" end="14"/>
- <field name="RF" start="16" end="16"/>
- <field name="VM" start="17" end="17"/>
- <field name="AC" start="18" end="18"/>
- <field name="VIF" start="19" end="19"/>
- <field name="VIP" start="20" end="20"/>
- <field name="ID" start="21" end="21"/>
- </flags>
-
- <reg name="eax" bitsize="32" type="int32"/>
- <reg name="ecx" bitsize="32" type="int32"/>
- <reg name="edx" bitsize="32" type="int32"/>
- <reg name="ebx" bitsize="32" type="int32"/>
- <reg name="esp" bitsize="32" type="data_ptr"/>
- <reg name="ebp" bitsize="32" type="data_ptr"/>
- <reg name="esi" bitsize="32" type="int32"/>
- <reg name="edi" bitsize="32" type="int32"/>
-
- <reg name="eip" bitsize="32" type="code_ptr"/>
- <reg name="eflags" bitsize="32" type="i386_eflags"/>
- <reg name="cs" bitsize="32" type="int32"/>
- <reg name="ss" bitsize="32" type="int32"/>
- <reg name="ds" bitsize="32" type="int32"/>
- <reg name="es" bitsize="32" type="int32"/>
- <reg name="fs" bitsize="32" type="int32"/>
- <reg name="gs" bitsize="32" type="int32"/>
-
- <reg name="st0" bitsize="80" type="i387_ext"/>
- <reg name="st1" bitsize="80" type="i387_ext"/>
- <reg name="st2" bitsize="80" type="i387_ext"/>
- <reg name="st3" bitsize="80" type="i387_ext"/>
- <reg name="st4" bitsize="80" type="i387_ext"/>
- <reg name="st5" bitsize="80" type="i387_ext"/>
- <reg name="st6" bitsize="80" type="i387_ext"/>
- <reg name="st7" bitsize="80" type="i387_ext"/>
-
- <reg name="fctrl" bitsize="32" type="int" group="float"/>
- <reg name="fstat" bitsize="32" type="int" group="float"/>
- <reg name="ftag" bitsize="32" type="int" group="float"/>
- <reg name="fiseg" bitsize="32" type="int" group="float"/>
- <reg name="fioff" bitsize="32" type="int" group="float"/>
- <reg name="foseg" bitsize="32" type="int" group="float"/>
- <reg name="fooff" bitsize="32" type="int" group="float"/>
- <reg name="fop" bitsize="32" type="int" group="float"/>
-</feature>
+++ /dev/null
-<?xml version="1.0"?>
-<!-- Copyright (C) 2010-2017 Free Software Foundation, Inc.
-
- Copying and distribution of this file, with or without modification,
- are permitted in any medium without royalty provided the copyright
- notice and this notice are preserved. -->
-
-<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.i386.32bit.sse">
- <vector id="v4f" type="ieee_single" count="4"/>
- <vector id="v2d" type="ieee_double" count="2"/>
- <vector id="v16i8" type="int8" count="16"/>
- <vector id="v8i16" type="int16" count="8"/>
- <vector id="v4i32" type="int32" count="4"/>
- <vector id="v2i64" type="int64" count="2"/>
- <union id="vec128">
- <field name="v4_float" type="v4f"/>
- <field name="v2_double" type="v2d"/>
- <field name="v16_int8" type="v16i8"/>
- <field name="v8_int16" type="v8i16"/>
- <field name="v4_int32" type="v4i32"/>
- <field name="v2_int64" type="v2i64"/>
- <field name="uint128" type="uint128"/>
- </union>
- <flags id="i386_mxcsr" size="4">
- <field name="IE" start="0" end="0"/>
- <field name="DE" start="1" end="1"/>
- <field name="ZE" start="2" end="2"/>
- <field name="OE" start="3" end="3"/>
- <field name="UE" start="4" end="4"/>
- <field name="PE" start="5" end="5"/>
- <field name="DAZ" start="6" end="6"/>
- <field name="IM" start="7" end="7"/>
- <field name="DM" start="8" end="8"/>
- <field name="ZM" start="9" end="9"/>
- <field name="OM" start="10" end="10"/>
- <field name="UM" start="11" end="11"/>
- <field name="PM" start="12" end="12"/>
- <field name="FZ" start="15" end="15"/>
- </flags>
-
- <reg name="xmm0" bitsize="128" type="vec128" regnum="32"/>
- <reg name="xmm1" bitsize="128" type="vec128"/>
- <reg name="xmm2" bitsize="128" type="vec128"/>
- <reg name="xmm3" bitsize="128" type="vec128"/>
- <reg name="xmm4" bitsize="128" type="vec128"/>
- <reg name="xmm5" bitsize="128" type="vec128"/>
- <reg name="xmm6" bitsize="128" type="vec128"/>
- <reg name="xmm7" bitsize="128" type="vec128"/>
-
- <reg name="mxcsr" bitsize="32" type="i386_mxcsr" group="vector"/>
-</feature>
<!-- I386 with SSE -->
<!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.i386.32bit">
- <xi:include href="i386-32bit-core.xml"/>
- <xi:include href="i386-32bit-sse.xml"/>
+<feature name="org.gnu.gdb.i386.core">
+ <flags id="i386_eflags" size="4">
+ <field name="" start="22" end="31"/>
+ <field name="ID" start="21" end="21"/>
+ <field name="VIP" start="20" end="20"/>
+ <field name="VIF" start="19" end="19"/>
+ <field name="AC" start="18" end="18"/>
+ <field name="VM" start="17" end="17"/>
+ <field name="RF" start="16" end="16"/>
+ <field name="" start="15" end="15"/>
+ <field name="NT" start="14" end="14"/>
+ <field name="IOPL" start="12" end="13"/>
+ <field name="OF" start="11" end="11"/>
+ <field name="DF" start="10" end="10"/>
+ <field name="IF" start="9" end="9"/>
+ <field name="TF" start="8" end="8"/>
+ <field name="SF" start="7" end="7"/>
+ <field name="ZF" start="6" end="6"/>
+ <field name="" start="5" end="5"/>
+ <field name="AF" start="4" end="4"/>
+ <field name="" start="3" end="3"/>
+ <field name="PF" start="2" end="2"/>
+ <field name="" start="1" end="1"/>
+ <field name="CF" start="0" end="0"/>
+ </flags>
+
+ <reg name="eax" bitsize="32" type="int32" regnum="0"/>
+ <reg name="ecx" bitsize="32" type="int32"/>
+ <reg name="edx" bitsize="32" type="int32"/>
+ <reg name="ebx" bitsize="32" type="int32"/>
+ <reg name="esp" bitsize="32" type="data_ptr"/>
+ <reg name="ebp" bitsize="32" type="data_ptr"/>
+ <reg name="esi" bitsize="32" type="int32"/>
+ <reg name="edi" bitsize="32" type="int32"/>
+
+ <reg name="eip" bitsize="32" type="code_ptr"/>
+ <reg name="eflags" bitsize="32" type="i386_eflags"/>
+
+ <reg name="cs" bitsize="32" type="int32"/>
+ <reg name="ss" bitsize="32" type="int32"/>
+ <reg name="ds" bitsize="32" type="int32"/>
+ <reg name="es" bitsize="32" type="int32"/>
+ <reg name="fs" bitsize="32" type="int32"/>
+ <reg name="gs" bitsize="32" type="int32"/>
+
+ <!-- Segment descriptor caches and TLS base MSRs -->
+
+ <!--reg name="cs_base" bitsize="32" type="int32"/>
+ <reg name="ss_base" bitsize="32" type="int32"/>
+ <reg name="ds_base" bitsize="32" type="int32"/>
+ <reg name="es_base" bitsize="32" type="int32"/-->
+ <reg name="fs_base" bitsize="32" type="int32"/>
+ <reg name="gs_base" bitsize="32" type="int32"/>
+ <reg name="k_gs_base" bitsize="32" type="int32"/>
+
+ <flags id="i386_cr0" size="4">
+ <field name="PG" start="31" end="31"/>
+ <field name="CD" start="30" end="30"/>
+ <field name="NW" start="29" end="29"/>
+ <field name="AM" start="18" end="18"/>
+ <field name="WP" start="16" end="16"/>
+ <field name="NE" start="5" end="5"/>
+ <field name="ET" start="4" end="4"/>
+ <field name="TS" start="3" end="3"/>
+ <field name="EM" start="2" end="2"/>
+ <field name="MP" start="1" end="1"/>
+ <field name="PE" start="0" end="0"/>
+ </flags>
+
+ <flags id="i386_cr3" size="4">
+ <field name="PDBR" start="12" end="31"/>
+ <!--field name="" start="3" end="11"/>
+ <field name="WT" start="2" end="2"/>
+ <field name="CD" start="1" end="1"/>
+ <field name="" start="0" end="0"/-->
+ <field name="PCID" start="0" end="11"/>
+ </flags>
+
+ <flags id="i386_cr4" size="4">
+ <field name="VME" start="0" end="0"/>
+ <field name="PVI" start="1" end="1"/>
+ <field name="TSD" start="2" end="2"/>
+ <field name="DE" start="3" end="3"/>
+ <field name="PSE" start="4" end="4"/>
+ <field name="PAE" start="5" end="5"/>
+ <field name="MCE" start="6" end="6"/>
+ <field name="PGE" start="7" end="7"/>
+ <field name="PCE" start="8" end="8"/>
+ <field name="OSFXSR" start="9" end="9"/>
+ <field name="OSXMMEXCPT" start="10" end="10"/>
+ <field name="UMIP" start="11" end="11"/>
+ <field name="LA57" start="12" end="12"/>
+ <field name="VMXE" start="13" end="13"/>
+ <field name="SMXE" start="14" end="14"/>
+ <field name="FSGSBASE" start="16" end="16"/>
+ <field name="PCIDE" start="17" end="17"/>
+ <field name="OSXSAVE" start="18" end="18"/>
+ <field name="SMEP" start="20" end="20"/>
+ <field name="SMAP" start="21" end="21"/>
+ <field name="PKE" start="22" end="22"/>
+ </flags>
+
+ <flags id="i386_efer" size="8">
+ <field name="TCE" start="15" end="15"/>
+ <field name="FFXSR" start="14" end="14"/>
+ <field name="LMSLE" start="13" end="13"/>
+ <field name="SVME" start="12" end="12"/>
+ <field name="NXE" start="11" end="11"/>
+ <field name="LMA" start="10" end="10"/>
+ <field name="LME" start="8" end="8"/>
+ <field name="SCE" start="0" end="0"/>
+ </flags>
+
+ <reg name="cr0" bitsize="32" type="i386_cr0"/>
+ <reg name="cr2" bitsize="32" type="int32"/>
+ <reg name="cr3" bitsize="32" type="i386_cr3"/>
+ <reg name="cr4" bitsize="32" type="i386_cr4"/>
+ <reg name="cr8" bitsize="32" type="int32"/>
+ <reg name="efer" bitsize="32" type="i386_efer"/>
+
+ <reg name="st0" bitsize="80" type="i387_ext"/>
+ <reg name="st1" bitsize="80" type="i387_ext"/>
+ <reg name="st2" bitsize="80" type="i387_ext"/>
+ <reg name="st3" bitsize="80" type="i387_ext"/>
+ <reg name="st4" bitsize="80" type="i387_ext"/>
+ <reg name="st5" bitsize="80" type="i387_ext"/>
+ <reg name="st6" bitsize="80" type="i387_ext"/>
+ <reg name="st7" bitsize="80" type="i387_ext"/>
+
+ <reg name="fctrl" bitsize="32" type="int" group="float"/>
+ <reg name="fstat" bitsize="32" type="int" group="float"/>
+ <reg name="ftag" bitsize="32" type="int" group="float"/>
+ <reg name="fiseg" bitsize="32" type="int" group="float"/>
+ <reg name="fioff" bitsize="32" type="int" group="float"/>
+ <reg name="foseg" bitsize="32" type="int" group="float"/>
+ <reg name="fooff" bitsize="32" type="int" group="float"/>
+ <reg name="fop" bitsize="32" type="int" group="float"/>
+<!--/feature>
+<feature name="org.gnu.gdb.i386.32bit.sse"-->
+ <vector id="v4f" type="ieee_single" count="4"/>
+ <vector id="v2d" type="ieee_double" count="2"/>
+ <vector id="v16i8" type="int8" count="16"/>
+ <vector id="v8i16" type="int16" count="8"/>
+ <vector id="v4i32" type="int32" count="4"/>
+ <vector id="v2i64" type="int64" count="2"/>
+ <union id="vec128">
+ <field name="v4_float" type="v4f"/>
+ <field name="v2_double" type="v2d"/>
+ <field name="v16_int8" type="v16i8"/>
+ <field name="v8_int16" type="v8i16"/>
+ <field name="v4_int32" type="v4i32"/>
+ <field name="v2_int64" type="v2i64"/>
+ <field name="uint128" type="uint128"/>
+ </union>
+ <flags id="i386_mxcsr" size="4">
+ <field name="IE" start="0" end="0"/>
+ <field name="DE" start="1" end="1"/>
+ <field name="ZE" start="2" end="2"/>
+ <field name="OE" start="3" end="3"/>
+ <field name="UE" start="4" end="4"/>
+ <field name="PE" start="5" end="5"/>
+ <field name="DAZ" start="6" end="6"/>
+ <field name="IM" start="7" end="7"/>
+ <field name="DM" start="8" end="8"/>
+ <field name="ZM" start="9" end="9"/>
+ <field name="OM" start="10" end="10"/>
+ <field name="UM" start="11" end="11"/>
+ <field name="PM" start="12" end="12"/>
+ <field name="FZ" start="15" end="15"/>
+ </flags>
+
+ <reg name="xmm0" bitsize="128" type="vec128"/>
+ <reg name="xmm1" bitsize="128" type="vec128"/>
+ <reg name="xmm2" bitsize="128" type="vec128"/>
+ <reg name="xmm3" bitsize="128" type="vec128"/>
+ <reg name="xmm4" bitsize="128" type="vec128"/>
+ <reg name="xmm5" bitsize="128" type="vec128"/>
+ <reg name="xmm6" bitsize="128" type="vec128"/>
+ <reg name="xmm7" bitsize="128" type="vec128"/>
+
+ <reg name="mxcsr" bitsize="32" type="i386_mxcsr" group="vector"/>
</feature>
+++ /dev/null
-<?xml version="1.0"?>
-<!-- Copyright (C) 2010-2015 Free Software Foundation, Inc.
-
- Copying and distribution of this file, with or without modification,
- are permitted in any medium without royalty provided the copyright
- notice and this notice are preserved. -->
-
-<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.i386.core">
- <flags id="i386_eflags" size="4">
- <field name="CF" start="0" end="0"/>
- <field name="" start="1" end="1"/>
- <field name="PF" start="2" end="2"/>
- <field name="AF" start="4" end="4"/>
- <field name="ZF" start="6" end="6"/>
- <field name="SF" start="7" end="7"/>
- <field name="TF" start="8" end="8"/>
- <field name="IF" start="9" end="9"/>
- <field name="DF" start="10" end="10"/>
- <field name="OF" start="11" end="11"/>
- <field name="NT" start="14" end="14"/>
- <field name="RF" start="16" end="16"/>
- <field name="VM" start="17" end="17"/>
- <field name="AC" start="18" end="18"/>
- <field name="VIF" start="19" end="19"/>
- <field name="VIP" start="20" end="20"/>
- <field name="ID" start="21" end="21"/>
- </flags>
-
- <reg name="rax" bitsize="64" type="int64"/>
- <reg name="rbx" bitsize="64" type="int64"/>
- <reg name="rcx" bitsize="64" type="int64"/>
- <reg name="rdx" bitsize="64" type="int64"/>
- <reg name="rsi" bitsize="64" type="int64"/>
- <reg name="rdi" bitsize="64" type="int64"/>
- <reg name="rbp" bitsize="64" type="data_ptr"/>
- <reg name="rsp" bitsize="64" type="data_ptr"/>
- <reg name="r8" bitsize="64" type="int64"/>
- <reg name="r9" bitsize="64" type="int64"/>
- <reg name="r10" bitsize="64" type="int64"/>
- <reg name="r11" bitsize="64" type="int64"/>
- <reg name="r12" bitsize="64" type="int64"/>
- <reg name="r13" bitsize="64" type="int64"/>
- <reg name="r14" bitsize="64" type="int64"/>
- <reg name="r15" bitsize="64" type="int64"/>
-
- <reg name="rip" bitsize="64" type="code_ptr"/>
- <reg name="eflags" bitsize="32" type="i386_eflags"/>
- <reg name="cs" bitsize="32" type="int32"/>
- <reg name="ss" bitsize="32" type="int32"/>
- <reg name="ds" bitsize="32" type="int32"/>
- <reg name="es" bitsize="32" type="int32"/>
- <reg name="fs" bitsize="32" type="int32"/>
- <reg name="gs" bitsize="32" type="int32"/>
-
- <reg name="st0" bitsize="80" type="i387_ext"/>
- <reg name="st1" bitsize="80" type="i387_ext"/>
- <reg name="st2" bitsize="80" type="i387_ext"/>
- <reg name="st3" bitsize="80" type="i387_ext"/>
- <reg name="st4" bitsize="80" type="i387_ext"/>
- <reg name="st5" bitsize="80" type="i387_ext"/>
- <reg name="st6" bitsize="80" type="i387_ext"/>
- <reg name="st7" bitsize="80" type="i387_ext"/>
-
- <reg name="fctrl" bitsize="32" type="int" group="float"/>
- <reg name="fstat" bitsize="32" type="int" group="float"/>
- <reg name="ftag" bitsize="32" type="int" group="float"/>
- <reg name="fiseg" bitsize="32" type="int" group="float"/>
- <reg name="fioff" bitsize="32" type="int" group="float"/>
- <reg name="foseg" bitsize="32" type="int" group="float"/>
- <reg name="fooff" bitsize="32" type="int" group="float"/>
- <reg name="fop" bitsize="32" type="int" group="float"/>
-</feature>
+++ /dev/null
-<?xml version="1.0"?>
-<!-- Copyright (C) 2010-2017 Free Software Foundation, Inc.
-
- Copying and distribution of this file, with or without modification,
- are permitted in any medium without royalty provided the copyright
- notice and this notice are preserved. -->
-
-<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.i386.64bit.sse">
- <vector id="v4f" type="ieee_single" count="4"/>
- <vector id="v2d" type="ieee_double" count="2"/>
- <vector id="v16i8" type="int8" count="16"/>
- <vector id="v8i16" type="int16" count="8"/>
- <vector id="v4i32" type="int32" count="4"/>
- <vector id="v2i64" type="int64" count="2"/>
- <union id="vec128">
- <field name="v4_float" type="v4f"/>
- <field name="v2_double" type="v2d"/>
- <field name="v16_int8" type="v16i8"/>
- <field name="v8_int16" type="v8i16"/>
- <field name="v4_int32" type="v4i32"/>
- <field name="v2_int64" type="v2i64"/>
- <field name="uint128" type="uint128"/>
- </union>
- <flags id="i386_mxcsr" size="4">
- <field name="IE" start="0" end="0"/>
- <field name="DE" start="1" end="1"/>
- <field name="ZE" start="2" end="2"/>
- <field name="OE" start="3" end="3"/>
- <field name="UE" start="4" end="4"/>
- <field name="PE" start="5" end="5"/>
- <field name="DAZ" start="6" end="6"/>
- <field name="IM" start="7" end="7"/>
- <field name="DM" start="8" end="8"/>
- <field name="ZM" start="9" end="9"/>
- <field name="OM" start="10" end="10"/>
- <field name="UM" start="11" end="11"/>
- <field name="PM" start="12" end="12"/>
- <field name="FZ" start="15" end="15"/>
- </flags>
-
- <reg name="xmm0" bitsize="128" type="vec128" regnum="40"/>
- <reg name="xmm1" bitsize="128" type="vec128"/>
- <reg name="xmm2" bitsize="128" type="vec128"/>
- <reg name="xmm3" bitsize="128" type="vec128"/>
- <reg name="xmm4" bitsize="128" type="vec128"/>
- <reg name="xmm5" bitsize="128" type="vec128"/>
- <reg name="xmm6" bitsize="128" type="vec128"/>
- <reg name="xmm7" bitsize="128" type="vec128"/>
- <reg name="xmm8" bitsize="128" type="vec128"/>
- <reg name="xmm9" bitsize="128" type="vec128"/>
- <reg name="xmm10" bitsize="128" type="vec128"/>
- <reg name="xmm11" bitsize="128" type="vec128"/>
- <reg name="xmm12" bitsize="128" type="vec128"/>
- <reg name="xmm13" bitsize="128" type="vec128"/>
- <reg name="xmm14" bitsize="128" type="vec128"/>
- <reg name="xmm15" bitsize="128" type="vec128"/>
-
- <reg name="mxcsr" bitsize="32" type="i386_mxcsr" group="vector"/>
-</feature>
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
-<!-- I386 64bit -->
+<!-- x86_64 64bit -->
<!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.i386.64bit">
- <xi:include href="i386-64bit-core.xml"/>
- <xi:include href="i386-64bit-sse.xml"/>
+
+<feature name="org.gnu.gdb.i386.core">
+ <flags id="x64_eflags" size="4">
+ <field name="" start="22" end="31"/>
+ <field name="ID" start="21" end="21"/>
+ <field name="VIP" start="20" end="20"/>
+ <field name="VIF" start="19" end="19"/>
+ <field name="AC" start="18" end="18"/>
+ <field name="VM" start="17" end="17"/>
+ <field name="RF" start="16" end="16"/>
+ <field name="" start="15" end="15"/>
+ <field name="NT" start="14" end="14"/>
+ <field name="IOPL" start="12" end="13"/>
+ <field name="OF" start="11" end="11"/>
+ <field name="DF" start="10" end="10"/>
+ <field name="IF" start="9" end="9"/>
+ <field name="TF" start="8" end="8"/>
+ <field name="SF" start="7" end="7"/>
+ <field name="ZF" start="6" end="6"/>
+ <field name="" start="5" end="5"/>
+ <field name="AF" start="4" end="4"/>
+ <field name="" start="3" end="3"/>
+ <field name="PF" start="2" end="2"/>
+ <field name="" start="1" end="1"/>
+ <field name="CF" start="0" end="0"/>
+ </flags>
+
+ <!-- General registers -->
+
+ <reg name="rax" bitsize="64" type="int64" regnum="0"/>
+ <reg name="rbx" bitsize="64" type="int64"/>
+ <reg name="rcx" bitsize="64" type="int64"/>
+ <reg name="rdx" bitsize="64" type="int64"/>
+ <reg name="rsi" bitsize="64" type="int64"/>
+ <reg name="rdi" bitsize="64" type="int64"/>
+ <reg name="rbp" bitsize="64" type="data_ptr"/>
+ <reg name="rsp" bitsize="64" type="data_ptr"/>
+ <reg name="r8" bitsize="64" type="int64"/>
+ <reg name="r9" bitsize="64" type="int64"/>
+ <reg name="r10" bitsize="64" type="int64"/>
+ <reg name="r11" bitsize="64" type="int64"/>
+ <reg name="r12" bitsize="64" type="int64"/>
+ <reg name="r13" bitsize="64" type="int64"/>
+ <reg name="r14" bitsize="64" type="int64"/>
+ <reg name="r15" bitsize="64" type="int64"/>
+
+ <reg name="rip" bitsize="64" type="code_ptr"/>
+ <reg name="eflags" bitsize="32" type="x64_eflags"/>
+
+ <!-- Segment registers -->
+
+ <reg name="cs" bitsize="32" type="int32"/>
+ <reg name="ss" bitsize="32" type="int32"/>
+ <reg name="ds" bitsize="32" type="int32"/>
+ <reg name="es" bitsize="32" type="int32"/>
+ <reg name="fs" bitsize="32" type="int32"/>
+ <reg name="gs" bitsize="32" type="int32"/>
+
+ <!-- Segment descriptor caches and TLS base MSRs -->
+
+ <!--reg name="cs_base" bitsize="64" type="int64"/>
+ <reg name="ss_base" bitsize="64" type="int64"/>
+ <reg name="ds_base" bitsize="64" type="int64"/>
+ <reg name="es_base" bitsize="64" type="int64"/-->
+ <reg name="fs_base" bitsize="64" type="int64"/>
+ <reg name="gs_base" bitsize="64" type="int64"/>
+ <reg name="k_gs_base" bitsize="64" type="int64"/>
+
+ <!-- Control registers -->
+
+ <flags id="x64_cr0" size="8">
+ <field name="PG" start="31" end="31"/>
+ <field name="CD" start="30" end="30"/>
+ <field name="NW" start="29" end="29"/>
+ <field name="AM" start="18" end="18"/>
+ <field name="WP" start="16" end="16"/>
+ <field name="NE" start="5" end="5"/>
+ <field name="ET" start="4" end="4"/>
+ <field name="TS" start="3" end="3"/>
+ <field name="EM" start="2" end="2"/>
+ <field name="MP" start="1" end="1"/>
+ <field name="PE" start="0" end="0"/>
+ </flags>
+
+ <flags id="x64_cr3" size="8">
+ <field name="PDBR" start="12" end="63"/>
+ <!--field name="" start="3" end="11"/>
+ <field name="WT" start="2" end="2"/>
+ <field name="CD" start="1" end="1"/>
+ <field name="" start="0" end="0"/-->
+ <field name="PCID" start="0" end="11"/>
+ </flags>
+
+ <flags id="x64_cr4" size="8">
+ <field name="PKE" start="22" end="22"/>
+ <field name="SMAP" start="21" end="21"/>
+ <field name="SMEP" start="20" end="20"/>
+ <field name="OSXSAVE" start="18" end="18"/>
+ <field name="PCIDE" start="17" end="17"/>
+ <field name="FSGSBASE" start="16" end="16"/>
+ <field name="SMXE" start="14" end="14"/>
+ <field name="VMXE" start="13" end="13"/>
+ <field name="LA57" start="12" end="12"/>
+ <field name="UMIP" start="11" end="11"/>
+ <field name="OSXMMEXCPT" start="10" end="10"/>
+ <field name="OSFXSR" start="9" end="9"/>
+ <field name="PCE" start="8" end="8"/>
+ <field name="PGE" start="7" end="7"/>
+ <field name="MCE" start="6" end="6"/>
+ <field name="PAE" start="5" end="5"/>
+ <field name="PSE" start="4" end="4"/>
+ <field name="DE" start="3" end="3"/>
+ <field name="TSD" start="2" end="2"/>
+ <field name="PVI" start="1" end="1"/>
+ <field name="VME" start="0" end="0"/>
+ </flags>
+
+ <flags id="x64_efer" size="8">
+ <field name="TCE" start="15" end="15"/>
+ <field name="FFXSR" start="14" end="14"/>
+ <field name="LMSLE" start="13" end="13"/>
+ <field name="SVME" start="12" end="12"/>
+ <field name="NXE" start="11" end="11"/>
+ <field name="LMA" start="10" end="10"/>
+ <field name="LME" start="8" end="8"/>
+ <field name="SCE" start="0" end="0"/>
+ </flags>
+
+ <reg name="cr0" bitsize="64" type="x64_cr0"/>
+ <reg name="cr2" bitsize="64" type="int64"/>
+ <reg name="cr3" bitsize="64" type="x64_cr3"/>
+ <reg name="cr4" bitsize="64" type="x64_cr4"/>
+ <reg name="cr8" bitsize="64" type="int64"/>
+ <reg name="efer" bitsize="64" type="x64_efer"/>
+
+ <!-- x87 FPU -->
+
+ <reg name="st0" bitsize="80" type="i387_ext"/>
+ <reg name="st1" bitsize="80" type="i387_ext"/>
+ <reg name="st2" bitsize="80" type="i387_ext"/>
+ <reg name="st3" bitsize="80" type="i387_ext"/>
+ <reg name="st4" bitsize="80" type="i387_ext"/>
+ <reg name="st5" bitsize="80" type="i387_ext"/>
+ <reg name="st6" bitsize="80" type="i387_ext"/>
+ <reg name="st7" bitsize="80" type="i387_ext"/>
+
+ <reg name="fctrl" bitsize="32" type="int" group="float"/>
+ <reg name="fstat" bitsize="32" type="int" group="float"/>
+ <reg name="ftag" bitsize="32" type="int" group="float"/>
+ <reg name="fiseg" bitsize="32" type="int" group="float"/>
+ <reg name="fioff" bitsize="32" type="int" group="float"/>
+ <reg name="foseg" bitsize="32" type="int" group="float"/>
+ <reg name="fooff" bitsize="32" type="int" group="float"/>
+ <reg name="fop" bitsize="32" type="int" group="float"/>
+
+ <vector id="v4f" type="ieee_single" count="4"/>
+ <vector id="v2d" type="ieee_double" count="2"/>
+ <vector id="v16i8" type="int8" count="16"/>
+ <vector id="v8i16" type="int16" count="8"/>
+ <vector id="v4i32" type="int32" count="4"/>
+ <vector id="v2i64" type="int64" count="2"/>
+ <union id="vec128">
+ <field name="v4_float" type="v4f"/>
+ <field name="v2_double" type="v2d"/>
+ <field name="v16_int8" type="v16i8"/>
+ <field name="v8_int16" type="v8i16"/>
+ <field name="v4_int32" type="v4i32"/>
+ <field name="v2_int64" type="v2i64"/>
+ <field name="uint128" type="uint128"/>
+ </union>
+ <flags id="x64_mxcsr" size="4">
+ <field name="IE" start="0" end="0"/>
+ <field name="DE" start="1" end="1"/>
+ <field name="ZE" start="2" end="2"/>
+ <field name="OE" start="3" end="3"/>
+ <field name="UE" start="4" end="4"/>
+ <field name="PE" start="5" end="5"/>
+ <field name="DAZ" start="6" end="6"/>
+ <field name="IM" start="7" end="7"/>
+ <field name="DM" start="8" end="8"/>
+ <field name="ZM" start="9" end="9"/>
+ <field name="OM" start="10" end="10"/>
+ <field name="UM" start="11" end="11"/>
+ <field name="PM" start="12" end="12"/>
+ <field name="FZ" start="15" end="15"/>
+ </flags>
+
+ <reg name="xmm0" bitsize="128" type="vec128"/>
+ <reg name="xmm1" bitsize="128" type="vec128"/>
+ <reg name="xmm2" bitsize="128" type="vec128"/>
+ <reg name="xmm3" bitsize="128" type="vec128"/>
+ <reg name="xmm4" bitsize="128" type="vec128"/>
+ <reg name="xmm5" bitsize="128" type="vec128"/>
+ <reg name="xmm6" bitsize="128" type="vec128"/>
+ <reg name="xmm7" bitsize="128" type="vec128"/>
+ <reg name="xmm8" bitsize="128" type="vec128"/>
+ <reg name="xmm9" bitsize="128" type="vec128"/>
+ <reg name="xmm10" bitsize="128" type="vec128"/>
+ <reg name="xmm11" bitsize="128" type="vec128"/>
+ <reg name="xmm12" bitsize="128" type="vec128"/>
+ <reg name="xmm13" bitsize="128" type="vec128"/>
+ <reg name="xmm14" bitsize="128" type="vec128"/>
+ <reg name="xmm15" bitsize="128" type="vec128"/>
+
+ <reg name="mxcsr" bitsize="32" type="x64_mxcsr" group="vector"/>
</feature>
put_packet(s, buf);
break;
+ } else if (strncmp(p, "Kill;", 5) == 0) {
+ /* Kill the target */
+ put_packet(s, "OK");
+ error_report("QEMU: Terminated via GDBstub");
+ exit(0);
} else {
goto unknown_command;
}
* FIXME: it's a bit weird to allow using a mux chardev here
* and implicitly setup a monitor. We may want to break this.
*/
- chr = qemu_chr_new_noreplay("gdb", device, true);
+ chr = qemu_chr_new_noreplay("gdb", device, true, NULL);
if (!chr)
return -1;
}
/* Initialize a monitor terminal for gdb */
mon_chr = qemu_chardev_new(NULL, TYPE_CHARDEV_GDB,
- NULL, &error_abort);
+ NULL, NULL, &error_abort);
monitor_init(mon_chr, 0);
} else {
qemu_chr_fe_deinit(&s->chr, true);
{
.name = "savevm",
.args_type = "name:s?",
- .params = "[tag|id]",
- .help = "save a VM snapshot. If no tag or id are provided, a new snapshot is created",
+ .params = "tag",
+ .help = "save a VM snapshot. If no tag is provided, a new snapshot is created",
.cmd = hmp_savevm,
},
STEXI
-@item savevm [@var{tag}|@var{id}]
+@item savevm @var{tag}
@findex savevm
Create a snapshot of the whole virtual machine. If @var{tag} is
provided, it is used as human readable identifier. If there is already
-a snapshot with the same tag or ID, it is replaced. More info at
+a snapshot with the same tag, it is replaced. More info at
@ref{vm_snapshots}.
+
+Since 4.0, savevm stopped allowing the snapshot id to be set, accepting
+only @var{tag} as parameter.
ETEXI
{
.name = "loadvm",
.args_type = "name:s",
- .params = "tag|id",
- .help = "restore a VM snapshot from its tag or id",
+ .params = "tag",
+ .help = "restore a VM snapshot from its tag",
.cmd = hmp_loadvm,
.command_completion = loadvm_completion,
},
STEXI
-@item loadvm @var{tag}|@var{id}
+@item loadvm @var{tag}
@findex loadvm
Set the whole virtual machine to the snapshot identified by the tag
-@var{tag} or the unique snapshot ID @var{id}.
+@var{tag}.
+
+Since 4.0, loadvm stopped accepting snapshot id as parameter.
ETEXI
{
.name = "delvm",
.args_type = "name:s",
- .params = "tag|id",
- .help = "delete a VM snapshot from its tag or id",
+ .params = "tag",
+ .help = "delete a VM snapshot from its tag",
.cmd = hmp_delvm,
.command_completion = delvm_completion,
},
STEXI
-@item delvm @var{tag}|@var{id}
+@item delvm @var{tag}
@findex delvm
-Delete the snapshot identified by @var{tag} or @var{id}.
+Delete the snapshot identified by @var{tag}.
+
+Since 4.0, delvm stopped deleting snapshots by snapshot id, accepting
+only @var{tag} as parameter.
ETEXI
{
{
assert(errp);
if (*errp) {
- error_report_err(*errp);
+ error_reportf_err(*errp, "Error: ");
}
}
if (opts == NULL) {
error_setg(&err, "Parsing chardev args failed");
} else {
- qemu_chr_new_from_opts(opts, &err);
+ qemu_chr_new_from_opts(opts, NULL, &err);
qemu_opts_del(opts);
}
hmp_handle_error(mon, &err);
devices-dirs-$(CONFIG_SOFTMMU) += timer/
devices-dirs-$(CONFIG_TPM) += tpm/
devices-dirs-$(CONFIG_SOFTMMU) += usb/
-devices-dirs-$(CONFIG_SOFTMMU) += vfio/
+devices-dirs-$(CONFIG_VFIO) += vfio/
devices-dirs-$(CONFIG_SOFTMMU) += virtio/
devices-dirs-$(CONFIG_SOFTMMU) += watchdog/
devices-dirs-$(CONFIG_SOFTMMU) += xen/
object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
PCIBus *sec = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
- qbus_set_hotplug_handler(BUS(sec), DEVICE(hotplug_dev),
+ qbus_set_hotplug_handler(BUS(sec), OBJECT(hotplug_dev),
&error_abort);
/* We don't have to overwrite any other hotplug handler yet */
assert(QLIST_EMPTY(&sec->child));
piix4_acpi_system_hot_add_init(pci_address_space_io(dev),
pci_get_bus(dev), s);
- qbus_set_hotplug_handler(BUS(pci_get_bus(dev)), DEVICE(s), &error_abort);
+ qbus_set_hotplug_handler(BUS(pci_get_bus(dev)), OBJECT(s), &error_abort);
piix4_pm_add_propeties(s);
}
-obj-y += dp264.o pci.o typhoon.o
+obj-$(CONFIG_DP264) += dp264.o pci.o typhoon.o
error_report("no palcode provided");
exit(1);
}
- size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
+ size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys,
NULL, &palcode_entry, &palcode_low, &palcode_high,
0, EM_ALPHA, 0, 0);
if (size < 0) {
if (kernel_filename) {
uint64_t param_offset;
- size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
+ size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys,
NULL, &kernel_entry, &kernel_low, &kernel_high,
0, EM_ALPHA, 0, 0);
if (size < 0) {
-obj-y += boot.o virt.o sysbus-fdt.o
+obj-y += boot.o sysbus-fdt.o
+obj-$(CONFIG_ARM_VIRT) += virt.o
obj-$(CONFIG_ACPI) += virt-acpi-build.o
obj-$(CONFIG_DIGIC) += digic_boards.o
obj-$(CONFIG_EXYNOS4) += exynos4_boards.o
obj-$(CONFIG_MPS2) += mps2.o
obj-$(CONFIG_MPS2) += mps2-tz.o
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
+obj-$(CONFIG_MUSCA) += musca.o
obj-$(CONFIG_ARMSSE) += armsse.o
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
#include "qemu/osdep.h"
#include "qemu/log.h"
+#include "qemu/bitops.h"
#include "qapi/error.h"
#include "trace.h"
#include "hw/sysbus.h"
int sram_banks;
int num_cpus;
uint32_t sys_version;
+ uint32_t cpuwait_rst;
SysConfigFormat sys_config_format;
bool has_mhus;
bool has_ppus;
.sram_banks = 1,
.num_cpus = 1,
.sys_version = 0x41743,
+ .cpuwait_rst = 0,
.sys_config_format = IoTKitFormat,
.has_mhus = false,
.has_ppus = false,
.sram_banks = 4,
.num_cpus = 2,
.sys_version = 0x22041743,
+ .cpuwait_rst = 2,
.sys_config_format = SSE200Format,
.has_mhus = true,
.has_ppus = true,
/* 30, 31: reserved */
};
-/* Create an alias region of @size bytes starting at @base
+/*
+ * Create an alias region in @container of @size bytes starting at @base
* which mirrors the memory starting at @orig.
*/
-static void make_alias(ARMSSE *s, MemoryRegion *mr, const char *name,
- hwaddr base, hwaddr size, hwaddr orig)
+static void make_alias(ARMSSE *s, MemoryRegion *mr, MemoryRegion *container,
+ const char *name, hwaddr base, hwaddr size, hwaddr orig)
{
- memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
+ memory_region_init_alias(mr, NULL, name, container, orig, size);
/* The alias is even lower priority than unimplemented_device regions */
- memory_region_add_subregion_overlap(&s->container, base, mr, -1500);
+ memory_region_add_subregion_overlap(container, base, mr, -1500);
}
static void irq_status_forwarder(void *opaque, int n, int level)
sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO);
if (info->has_mhus) {
sysbus_init_child_obj(obj, "mhu0", &s->mhu[0], sizeof(s->mhu[0]),
- TYPE_UNIMPLEMENTED_DEVICE);
+ TYPE_ARMSSE_MHU);
sysbus_init_child_obj(obj, "mhu1", &s->mhu[1], sizeof(s->mhu[1]),
- TYPE_UNIMPLEMENTED_DEVICE);
+ TYPE_ARMSSE_MHU);
}
if (info->has_ppus) {
for (i = 0; i < info->num_cpus; i++) {
qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + 32);
/*
- * In real hardware the initial Secure VTOR is set from the INITSVTOR0
- * register in the IoT Kit System Control Register block, and the
- * initial value of that is in turn specifiable by the FPGA that
- * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
- * and simply set the CPU's init-svtor to the IoT Kit default value.
- * In SSE-200 the situation is similar, except that the default value
- * is a reset-time signal input. Typically a board using the SSE-200
- * will have a system control processor whose boot firmware initializes
- * the INITSVTOR* registers before powering up the CPUs in any case,
- * so the hardware's default value doesn't matter. QEMU doesn't emulate
+ * In real hardware the initial Secure VTOR is set from the INITSVTOR*
+ * registers in the IoT Kit System Control Register block. In QEMU
+ * we set the initial value here, and also the reset value of the
+ * sysctl register, from this object's QOM init-svtor property.
+ * If the guest changes the INITSVTOR* registers at runtime then the
+ * code in iotkit-sysctl.c will update the CPU init-svtor property
+ * (which will then take effect on the next CPU warm-reset).
+ *
+ * Note that typically a board using the SSE-200 will have a system
+ * control processor whose boot firmware initializes the INITSVTOR*
+ * registers before powering up the CPUs. QEMU doesn't emulate
* the control processor, so instead we behave in the way that the
- * firmware does. All boards currently known about have firmware that
- * sets the INITSVTOR0 and INITSVTOR1 registers to 0x10000000, like the
- * IoTKit default. We can make this more configurable if necessary.
+ * firmware does: the initial value should be set by the board code
+ * (using the init-svtor property on the ARMSSE object) to match
+ * whatever its firmware does.
*/
- qdev_prop_set_uint32(cpudev, "init-svtor", 0x10000000);
+ qdev_prop_set_uint32(cpudev, "init-svtor", s->init_svtor);
/*
- * Start all CPUs except CPU0 powered down. In real hardware it is
- * a configurable property of the SSE-200 which CPUs start powered up
- * (via the CPUWAIT0_RST and CPUWAIT1_RST parameters), but since all
- * the boards we care about start CPU0 and leave CPU1 powered off,
- * we hard-code that for now. We can add QOM properties for this
+ * CPUs start powered down if the corresponding bit in the CPUWAIT
+ * register is 1. In real hardware the CPUWAIT register reset value is
+ * a configurable property of the SSE-200 (via the CPUWAIT0_RST and
+ * CPUWAIT1_RST parameters), but since all the boards we care about
+ * start CPU0 and leave CPU1 powered off, we hard-code that in
+ * info->cpuwait_rst for now. We can add QOM properties for this
* later if necessary.
*/
- if (i > 0) {
+ if (extract32(info->cpuwait_rst, i, 1)) {
object_property_set_bool(cpuobj, true, "start-powered-off", &err);
if (err) {
error_propagate(errp, err);
/* Connect EXP_IRQ/EXP_CPUn_IRQ GPIOs to the NVIC's lines 32 and up */
s->exp_irqs[i] = g_new(qemu_irq, s->exp_numirq);
for (j = 0; j < s->exp_numirq; j++) {
- s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, i + 32);
+ s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, j + 32);
}
if (i == 0) {
gpioname = g_strdup("EXP_IRQ");
}
/* Set up the big aliases first */
- make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
- make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000);
+ make_alias(s, &s->alias1, &s->container, "alias 1",
+ 0x10000000, 0x10000000, 0x00000000);
+ make_alias(s, &s->alias2, &s->container,
+ "alias 2", 0x30000000, 0x10000000, 0x20000000);
/* The 0x50000000..0x5fffffff region is not a pure alias: it has
* a few extra devices that only appear there (generally the
* control interfaces for the protection controllers).
* We implement this by mapping those devices over the top of this
- * alias MR at a higher priority.
+ * alias MR at a higher priority. Some of the devices in this range
+ * are per-CPU, so we must put this alias in the per-cpu containers.
*/
- make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
-
+ for (i = 0; i < info->num_cpus; i++) {
+ make_alias(s, &s->alias3[i], &s->cpu_container[i],
+ "alias 3", 0x50000000, 0x10000000, 0x40000000);
+ }
/* Security controller */
object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
}
if (info->has_mhus) {
+ /*
+ * An SSE-200 with only one CPU should have only one MHU created,
+ * with the region where the second MHU usually is being RAZ/WI.
+ * We don't implement that SSE-200 config; if we want to support
+ * it then this code needs to be enhanced to handle creating the
+ * RAZ/WI region instead of the second MHU.
+ */
+ assert(info->num_cpus == ARRAY_SIZE(s->mhu));
+
for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
- char *name = g_strdup_printf("MHU%d", i);
- char *port = g_strdup_printf("port[%d]", i + 3);
+ char *port;
+ int cpunum;
+ SysBusDevice *mhu_sbd = SYS_BUS_DEVICE(&s->mhu[i]);
- qdev_prop_set_string(DEVICE(&s->mhu[i]), "name", name);
- qdev_prop_set_uint64(DEVICE(&s->mhu[i]), "size", 0x1000);
object_property_set_bool(OBJECT(&s->mhu[i]), true,
"realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mhu[i]), 0);
+ port = g_strdup_printf("port[%d]", i + 3);
+ mr = sysbus_mmio_get_region(mhu_sbd, 0);
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr),
port, &err);
+ g_free(port);
if (err) {
error_propagate(errp, err);
return;
}
- g_free(name);
- g_free(port);
+
+ /*
+ * Each MHU has an irq line for each CPU:
+ * MHU 0 irq line 0 -> CPU 0 IRQ 6
+ * MHU 0 irq line 1 -> CPU 1 IRQ 6
+ * MHU 1 irq line 0 -> CPU 0 IRQ 7
+ * MHU 1 irq line 1 -> CPU 1 IRQ 7
+ */
+ for (cpunum = 0; cpunum < info->num_cpus; cpunum++) {
+ DeviceState *cpudev = DEVICE(&s->armv7m[cpunum]);
+
+ sysbus_connect_irq(mhu_sbd, cpunum,
+ qdev_get_gpio_in(cpudev, 6 + i));
+ }
}
}
/* System information registers */
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000);
/* System control registers */
+ object_property_set_int(OBJECT(&s->sysctl), info->sys_version,
+ "SYS_VERSION", &err);
+ object_property_set_int(OBJECT(&s->sysctl), info->cpuwait_rst,
+ "CPUWAIT_RST", &err);
+ object_property_set_int(OBJECT(&s->sysctl), s->init_svtor,
+ "INITSVTOR0_RST", &err);
+ object_property_set_int(OBJECT(&s->sysctl), s->init_svtor,
+ "INITSVTOR1_RST", &err);
object_property_set_bool(OBJECT(&s->sysctl), true, "realized", &err);
if (err) {
error_propagate(errp, err);
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
+ DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
DEFINE_PROP_END_OF_LIST()
};
as = cpu_get_address_space(cs, asidx);
if (kernel_filename) {
- image_size = load_elf_as(kernel_filename, NULL, NULL, &entry, &lowaddr,
+ image_size = load_elf_as(kernel_filename, NULL, NULL, NULL,
+ &entry, &lowaddr,
NULL, big_endian, EM_ARM, 1, 0, as);
if (image_size < 0) {
image_size = load_image_targphys_as(kernel_filename, 0,
}
}
- ret = load_elf_as(info->kernel_filename, NULL, NULL,
+ ret = load_elf_as(info->kernel_filename, NULL, NULL, NULL,
pentry, lowaddr, highaddr, big_endian, elf_machine,
1, data_swab, as);
if (ret <= 0) {
return size;
}
-void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
+static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
+ struct arm_boot_info *info)
{
+ /* Set up for a direct boot of a kernel image file. */
CPUState *cs;
+ AddressSpace *as = arm_boot_address_space(cpu, info);
int kernel_size;
int initrd_size;
int is_linux = 0;
int elf_machine;
hwaddr entry;
static const ARMInsnFixup *primary_loader;
- AddressSpace *as = arm_boot_address_space(cpu, info);
-
- /* CPU objects (unlike devices) are not automatically reset on system
- * reset, so we must always register a handler to do so. If we're
- * actually loading a kernel, the handler is also responsible for
- * arranging that we start it correctly.
- */
- for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
- qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
- }
-
- /* The board code is not supposed to set secure_board_setup unless
- * running its code in secure mode is actually possible, and KVM
- * doesn't support secure.
- */
- assert(!(info->secure_board_setup && kvm_enabled()));
-
- info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
- info->dtb_limit = 0;
-
- /* Load the kernel. */
- if (!info->kernel_filename || info->firmware_loaded) {
-
- if (have_dtb(info)) {
- /* If we have a device tree blob, but no kernel to supply it to (or
- * the kernel is supposed to be loaded by the bootloader), copy the
- * DTB to the base of RAM for the bootloader to pick up.
- */
- info->dtb_start = info->loader_start;
- }
-
- if (info->kernel_filename) {
- FWCfgState *fw_cfg;
- bool try_decompressing_kernel;
-
- fw_cfg = fw_cfg_find();
- try_decompressing_kernel = arm_feature(&cpu->env,
- ARM_FEATURE_AARCH64);
-
- /* Expose the kernel, the command line, and the initrd in fw_cfg.
- * We don't process them here at all, it's all left to the
- * firmware.
- */
- load_image_to_fw_cfg(fw_cfg,
- FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
- info->kernel_filename,
- try_decompressing_kernel);
- load_image_to_fw_cfg(fw_cfg,
- FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
- info->initrd_filename, false);
-
- if (info->kernel_cmdline) {
- fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
- strlen(info->kernel_cmdline) + 1);
- fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
- info->kernel_cmdline);
- }
- }
-
- /* We will start from address 0 (typically a boot ROM image) in the
- * same way as hardware.
- */
- return;
- }
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
primary_loader = bootloader_aarch64;
if (info->nb_cpus == 0)
info->nb_cpus = 1;
- /* We want to put the initrd far enough into RAM that when the
+ /*
+ * We want to put the initrd far enough into RAM that when the
* kernel is uncompressed it will not clobber the initrd. However
* on boards without much RAM we must ensure that we still leave
* enough room for a decent sized initrd, and on boards with large
kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
&elf_high_addr, elf_machine, as);
if (kernel_size > 0 && have_dtb(info)) {
- /* If there is still some room left at the base of RAM, try and put
+ /*
+ * If there is still some room left at the base of RAM, try and put
* the DTB there like we do for images loaded with -bios or -pflash.
*/
if (elf_low_addr > info->loader_start
|| elf_high_addr < info->loader_start) {
- /* Set elf_low_addr as address limit for arm_load_dtb if it may be
+ /*
+ * Set elf_low_addr as address limit for arm_load_dtb if it may be
* pointing into RAM, otherwise pass '0' (no limit)
*/
if (elf_low_addr < info->loader_start) {
fixupcontext[FIXUP_BOARDID] = info->board_id;
fixupcontext[FIXUP_BOARD_SETUP] = info->board_setup_addr;
- /* for device tree boot, we pass the DTB directly in r2. Otherwise
+ /*
+ * for device tree boot, we pass the DTB directly in r2. Otherwise
* we point to the kernel args.
*/
if (have_dtb(info)) {
info->write_board_setup(cpu, info);
}
- /* Notify devices which need to fake up firmware initialization
+ /*
+ * Notify devices which need to fake up firmware initialization
* that we're doing a direct kernel boot.
*/
object_child_foreach_recursive(object_get_root(),
for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
ARM_CPU(cs)->env.boot_info = info;
}
+}
+
+static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info)
+{
+ /* Set up for booting firmware (which might load a kernel via fw_cfg) */
+
+ if (have_dtb(info)) {
+ /*
+ * If we have a device tree blob, but no kernel to supply it to (or
+ * the kernel is supposed to be loaded by the bootloader), copy the
+ * DTB to the base of RAM for the bootloader to pick up.
+ */
+ info->dtb_start = info->loader_start;
+ }
+
+ if (info->kernel_filename) {
+ FWCfgState *fw_cfg;
+ bool try_decompressing_kernel;
+
+ fw_cfg = fw_cfg_find();
+ try_decompressing_kernel = arm_feature(&cpu->env,
+ ARM_FEATURE_AARCH64);
+
+ /*
+ * Expose the kernel, the command line, and the initrd in fw_cfg.
+ * We don't process them here at all, it's all left to the
+ * firmware.
+ */
+ load_image_to_fw_cfg(fw_cfg,
+ FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
+ info->kernel_filename,
+ try_decompressing_kernel);
+ load_image_to_fw_cfg(fw_cfg,
+ FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
+ info->initrd_filename, false);
+
+ if (info->kernel_cmdline) {
+ fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
+ strlen(info->kernel_cmdline) + 1);
+ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
+ info->kernel_cmdline);
+ }
+ }
+
+ /*
+ * We will start from address 0 (typically a boot ROM image) in the
+ * same way as hardware. Leave env->boot_info NULL, so that
+ * do_cpu_reset() knows it does not need to alter the PC on reset.
+ */
+}
+
+void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
+{
+ CPUState *cs;
+ AddressSpace *as = arm_boot_address_space(cpu, info);
+
+ /*
+ * CPU objects (unlike devices) are not automatically reset on system
+ * reset, so we must always register a handler to do so. If we're
+ * actually loading a kernel, the handler is also responsible for
+ * arranging that we start it correctly.
+ */
+ for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
+ qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
+ }
+
+ /*
+ * The board code is not supposed to set secure_board_setup unless
+ * running its code in secure mode is actually possible, and KVM
+ * doesn't support secure.
+ */
+ assert(!(info->secure_board_setup && kvm_enabled()));
+
+ info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
+ info->dtb_limit = 0;
+
+ /* Load the kernel. */
+ if (!info->kernel_filename || info->firmware_loaded) {
+ arm_setup_firmware_boot(cpu, info);
+ } else {
+ arm_setup_direct_kernel_boot(cpu, info);
+ }
if (!info->skip_dtb_autoload && have_dtb(info)) {
if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as) < 0) {
--- /dev/null
+/*
+ * Arm Musca-B1 test chip board emulation
+ *
+ * Copyright (c) 2019 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * The Musca boards are a reference implementation of a system using
+ * the SSE-200 subsystem for embedded:
+ * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-a-test-chip-board
+ * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-b-test-chip-board
+ * We model the A and B1 variants of this board, as described in the TRMs:
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101107_0000_00_en/index.html
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101312_0000_00_en/index.html
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+#include "hw/arm/arm.h"
+#include "hw/arm/armsse.h"
+#include "hw/boards.h"
+#include "hw/char/pl011.h"
+#include "hw/core/split-irq.h"
+#include "hw/misc/tz-mpc.h"
+#include "hw/misc/tz-ppc.h"
+#include "hw/misc/unimp.h"
+#include "hw/timer/pl031.h"
+
+#define MUSCA_NUMIRQ_MAX 96
+#define MUSCA_PPC_MAX 3
+#define MUSCA_MPC_MAX 5
+
+typedef struct MPCInfo MPCInfo;
+
+typedef enum MuscaType {
+ MUSCA_A,
+ MUSCA_B1,
+} MuscaType;
+
+typedef struct {
+ MachineClass parent;
+ MuscaType type;
+ uint32_t init_svtor;
+ int sram_addr_width;
+ int num_irqs;
+ const MPCInfo *mpc_info;
+ int num_mpcs;
+} MuscaMachineClass;
+
+typedef struct {
+ MachineState parent;
+
+ ARMSSE sse;
+ /* RAM and flash */
+ MemoryRegion ram[MUSCA_MPC_MAX];
+ SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX];
+ SplitIRQ sec_resp_splitter;
+ TZPPC ppc[MUSCA_PPC_MAX];
+ MemoryRegion container;
+ UnimplementedDeviceState eflash[2];
+ UnimplementedDeviceState qspi;
+ TZMPC mpc[MUSCA_MPC_MAX];
+ UnimplementedDeviceState mhu[2];
+ UnimplementedDeviceState pwm[3];
+ UnimplementedDeviceState i2s;
+ PL011State uart[2];
+ UnimplementedDeviceState i2c[2];
+ UnimplementedDeviceState spi;
+ UnimplementedDeviceState scc;
+ UnimplementedDeviceState timer;
+ PL031State rtc;
+ UnimplementedDeviceState pvt;
+ UnimplementedDeviceState sdio;
+ UnimplementedDeviceState gpio;
+ UnimplementedDeviceState cryptoisland;
+} MuscaMachineState;
+
+#define TYPE_MUSCA_MACHINE "musca"
+#define TYPE_MUSCA_A_MACHINE MACHINE_TYPE_NAME("musca-a")
+#define TYPE_MUSCA_B1_MACHINE MACHINE_TYPE_NAME("musca-b1")
+
+#define MUSCA_MACHINE(obj) \
+ OBJECT_CHECK(MuscaMachineState, obj, TYPE_MUSCA_MACHINE)
+#define MUSCA_MACHINE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(MuscaMachineClass, obj, TYPE_MUSCA_MACHINE)
+#define MUSCA_MACHINE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(MuscaMachineClass, klass, TYPE_MUSCA_MACHINE)
+
+/*
+ * Main SYSCLK frequency in Hz
+ * TODO this should really be different for the two cores, but we
+ * don't model that in our SSE-200 model yet.
+ */
+#define SYSCLK_FRQ 40000000
+
+static qemu_irq get_sse_irq_in(MuscaMachineState *mms, int irqno)
+{
+ /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
+ assert(irqno < MUSCA_NUMIRQ_MAX);
+
+ return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
+}
+
+/*
+ * Most of the devices in the Musca board sit behind Peripheral Protection
+ * Controllers. These data structures define the layout of which devices
+ * sit behind which PPCs.
+ * The devfn for each port is a function which creates, configures
+ * and initializes the device, returning the MemoryRegion which
+ * needs to be plugged into the downstream end of the PPC port.
+ */
+typedef MemoryRegion *MakeDevFn(MuscaMachineState *mms, void *opaque,
+ const char *name, hwaddr size);
+
+typedef struct PPCPortInfo {
+ const char *name;
+ MakeDevFn *devfn;
+ void *opaque;
+ hwaddr addr;
+ hwaddr size;
+} PPCPortInfo;
+
+typedef struct PPCInfo {
+ const char *name;
+ PPCPortInfo ports[TZ_NUM_PORTS];
+} PPCInfo;
+
+static MemoryRegion *make_unimp_dev(MuscaMachineState *mms,
+ void *opaque, const char *name, hwaddr size)
+{
+ /*
+ * Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
+ * and return a pointer to its MemoryRegion.
+ */
+ UnimplementedDeviceState *uds = opaque;
+
+ sysbus_init_child_obj(OBJECT(mms), name, uds,
+ sizeof(UnimplementedDeviceState),
+ TYPE_UNIMPLEMENTED_DEVICE);
+ qdev_prop_set_string(DEVICE(uds), "name", name);
+ qdev_prop_set_uint64(DEVICE(uds), "size", size);
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
+}
+
+typedef enum MPCInfoType {
+ MPC_RAM,
+ MPC_ROM,
+ MPC_CRYPTOISLAND,
+} MPCInfoType;
+
+struct MPCInfo {
+ const char *name;
+ hwaddr addr;
+ hwaddr size;
+ MPCInfoType type;
+};
+
+/* Order of the MPCs here must match the order of the bits in SECMPCINTSTATUS */
+static const MPCInfo a_mpc_info[] = { {
+ .name = "qspi",
+ .type = MPC_ROM,
+ .addr = 0x00200000,
+ .size = 0x00800000,
+ }, {
+ .name = "sram",
+ .type = MPC_RAM,
+ .addr = 0x00000000,
+ .size = 0x00200000,
+ }
+};
+
+static const MPCInfo b1_mpc_info[] = { {
+ .name = "qspi",
+ .type = MPC_ROM,
+ .addr = 0x00000000,
+ .size = 0x02000000,
+ }, {
+ .name = "sram",
+ .type = MPC_RAM,
+ .addr = 0x0a400000,
+ .size = 0x00080000,
+ }, {
+ .name = "eflash0",
+ .type = MPC_ROM,
+ .addr = 0x0a000000,
+ .size = 0x00200000,
+ }, {
+ .name = "eflash1",
+ .type = MPC_ROM,
+ .addr = 0x0a200000,
+ .size = 0x00200000,
+ }, {
+ .name = "cryptoisland",
+ .type = MPC_CRYPTOISLAND,
+ .addr = 0x0a000000,
+ .size = 0x00200000,
+ }
+};
+
+static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque,
+ const char *name, hwaddr size)
+{
+ /*
+ * Create an MPC and the RAM or flash behind it.
+ * MPC 0: eFlash 0
+ * MPC 1: eFlash 1
+ * MPC 2: SRAM
+ * MPC 3: QSPI flash
+ * MPC 4: CryptoIsland
+ * For now we implement the flash regions as ROM (ie not programmable)
+ * (with their control interface memory regions being unimplemented
+ * stubs behind the PPCs).
+ * The whole CryptoIsland region behind its MPC is an unimplemented stub.
+ */
+ MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms);
+ TZMPC *mpc = opaque;
+ int i = mpc - &mms->mpc[0];
+ MemoryRegion *downstream;
+ MemoryRegion *upstream;
+ UnimplementedDeviceState *uds;
+ char *mpcname;
+ const MPCInfo *mpcinfo = mmc->mpc_info;
+
+ mpcname = g_strdup_printf("%s-mpc", mpcinfo[i].name);
+
+ switch (mpcinfo[i].type) {
+ case MPC_ROM:
+ downstream = &mms->ram[i];
+ memory_region_init_rom(downstream, NULL, mpcinfo[i].name,
+ mpcinfo[i].size, &error_fatal);
+ break;
+ case MPC_RAM:
+ downstream = &mms->ram[i];
+ memory_region_init_ram(downstream, NULL, mpcinfo[i].name,
+ mpcinfo[i].size, &error_fatal);
+ break;
+ case MPC_CRYPTOISLAND:
+ /* We don't implement the CryptoIsland yet */
+ uds = &mms->cryptoisland;
+ sysbus_init_child_obj(OBJECT(mms), name, uds,
+ sizeof(UnimplementedDeviceState),
+ TYPE_UNIMPLEMENTED_DEVICE);
+ qdev_prop_set_string(DEVICE(uds), "name", mpcinfo[i].name);
+ qdev_prop_set_uint64(DEVICE(uds), "size", mpcinfo[i].size);
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
+ downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ sysbus_init_child_obj(OBJECT(mms), mpcname, mpc, sizeof(mms->mpc[0]),
+ TYPE_TZ_MPC);
+ object_property_set_link(OBJECT(mpc), OBJECT(downstream),
+ "downstream", &error_fatal);
+ object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal);
+ /* Map the upstream end of the MPC into system memory */
+ upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
+ memory_region_add_subregion(get_system_memory(), mpcinfo[i].addr, upstream);
+ /* and connect its interrupt to the SSE-200 */
+ qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0,
+ qdev_get_gpio_in_named(DEVICE(&mms->sse),
+ "mpcexp_status", i));
+
+ g_free(mpcname);
+ /* Return the register interface MR for our caller to map behind the PPC */
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
+}
+
+static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque,
+ const char *name, hwaddr size)
+{
+ PL031State *rtc = opaque;
+
+ sysbus_init_child_obj(OBJECT(mms), name, rtc, sizeof(mms->rtc), TYPE_PL031);
+ object_property_set_bool(OBJECT(rtc), true, "realized", &error_fatal);
+ sysbus_connect_irq(SYS_BUS_DEVICE(rtc), 0, get_sse_irq_in(mms, 39));
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0);
+}
+
+static MemoryRegion *make_uart(MuscaMachineState *mms, void *opaque,
+ const char *name, hwaddr size)
+{
+ PL011State *uart = opaque;
+ int i = uart - &mms->uart[0];
+ int irqbase = 7 + i * 6;
+ SysBusDevice *s;
+
+ sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]),
+ TYPE_PL011);
+ qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
+ object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
+ s = SYS_BUS_DEVICE(uart);
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqbase + 5)); /* combined */
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqbase + 0)); /* RX */
+ sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqbase + 1)); /* TX */
+ sysbus_connect_irq(s, 3, get_sse_irq_in(mms, irqbase + 2)); /* RT */
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqbase + 3)); /* MS */
+ sysbus_connect_irq(s, 5, get_sse_irq_in(mms, irqbase + 4)); /* E */
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
+}
+
+static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
+ const char *name, hwaddr size)
+{
+ /*
+ * Create the container MemoryRegion for all the devices that live
+ * behind the Musca-A PPC's single port. These devices don't have a PPC
+ * port each, but we use the PPCPortInfo struct as a convenient way
+ * to describe them. Note that addresses here are relative to the base
+ * address of the PPC port region: 0x40100000, and devices appear both
+ * at the 0x4... NS region and the 0x5... S region.
+ */
+ int i;
+ MemoryRegion *container = &mms->container;
+
+ const PPCPortInfo devices[] = {
+ { "uart0", make_uart, &mms->uart[0], 0x1000, 0x1000 },
+ { "uart1", make_uart, &mms->uart[1], 0x2000, 0x1000 },
+ { "spi", make_unimp_dev, &mms->spi, 0x3000, 0x1000 },
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x4000, 0x1000 },
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 },
+ { "i2s", make_unimp_dev, &mms->i2s, 0x6000, 0x1000 },
+ { "pwm0", make_unimp_dev, &mms->pwm[0], 0x7000, 0x1000 },
+ { "rtc", make_rtc, &mms->rtc, 0x8000, 0x1000 },
+ { "qspi", make_unimp_dev, &mms->qspi, 0xa000, 0x1000 },
+ { "timer", make_unimp_dev, &mms->timer, 0xb000, 0x1000 },
+ { "scc", make_unimp_dev, &mms->scc, 0xc000, 0x1000 },
+ { "pwm1", make_unimp_dev, &mms->pwm[1], 0xe000, 0x1000 },
+ { "pwm2", make_unimp_dev, &mms->pwm[2], 0xf000, 0x1000 },
+ { "gpio", make_unimp_dev, &mms->gpio, 0x10000, 0x1000 },
+ { "mpc0", make_mpc, &mms->mpc[0], 0x12000, 0x1000 },
+ { "mpc1", make_mpc, &mms->mpc[1], 0x13000, 0x1000 },
+ };
+
+ memory_region_init(container, OBJECT(mms), "musca-device-container", size);
+
+ for (i = 0; i < ARRAY_SIZE(devices); i++) {
+ const PPCPortInfo *pinfo = &devices[i];
+ MemoryRegion *mr;
+
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
+ memory_region_add_subregion(container, pinfo->addr, mr);
+ }
+
+ return &mms->container;
+}
+
+static void musca_init(MachineState *machine)
+{
+ MuscaMachineState *mms = MUSCA_MACHINE(machine);
+ MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms);
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
+ MemoryRegion *system_memory = get_system_memory();
+ DeviceState *ssedev;
+ DeviceState *dev_splitter;
+ const PPCInfo *ppcs;
+ int num_ppcs;
+ int i;
+
+ assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX);
+ assert(mmc->num_mpcs <= MUSCA_MPC_MAX);
+
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
+ error_report("This board can only be used with CPU %s",
+ mc->default_cpu_type);
+ exit(1);
+ }
+
+ sysbus_init_child_obj(OBJECT(machine), "sse-200", &mms->sse,
+ sizeof(mms->sse), TYPE_SSE200);
+ ssedev = DEVICE(&mms->sse);
+ object_property_set_link(OBJECT(&mms->sse), OBJECT(system_memory),
+ "memory", &error_fatal);
+ qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs);
+ qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
+ qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
+ qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ);
+ object_property_set_bool(OBJECT(&mms->sse), true, "realized",
+ &error_fatal);
+
+ /*
+ * We need to create splitters to feed the IRQ inputs
+ * for each CPU in the SSE-200 from each device in the board.
+ */
+ for (i = 0; i < mmc->num_irqs; i++) {
+ char *name = g_strdup_printf("musca-irq-splitter%d", i);
+ SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
+
+ object_initialize_child(OBJECT(machine), name,
+ splitter, sizeof(*splitter),
+ TYPE_SPLIT_IRQ, &error_fatal, NULL);
+ g_free(name);
+
+ object_property_set_int(OBJECT(splitter), 2, "num-lines",
+ &error_fatal);
+ object_property_set_bool(OBJECT(splitter), true, "realized",
+ &error_fatal);
+ qdev_connect_gpio_out(DEVICE(splitter), 0,
+ qdev_get_gpio_in_named(ssedev, "EXP_IRQ", i));
+ qdev_connect_gpio_out(DEVICE(splitter), 1,
+ qdev_get_gpio_in_named(ssedev,
+ "EXP_CPU1_IRQ", i));
+ }
+
+ /*
+ * The sec_resp_cfg output from the SSE-200 must be split into multiple
+ * lines, one for each of the PPCs we create here.
+ */
+ object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter),
+ TYPE_SPLIT_IRQ);
+ object_property_add_child(OBJECT(machine), "sec-resp-splitter",
+ OBJECT(&mms->sec_resp_splitter), &error_fatal);
+ object_property_set_int(OBJECT(&mms->sec_resp_splitter),
+ ARRAY_SIZE(mms->ppc), "num-lines", &error_fatal);
+ object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true,
+ "realized", &error_fatal);
+ dev_splitter = DEVICE(&mms->sec_resp_splitter);
+ qdev_connect_gpio_out_named(ssedev, "sec_resp_cfg", 0,
+ qdev_get_gpio_in(dev_splitter, 0));
+
+ /*
+ * Most of the devices in the board are behind Peripheral Protection
+ * Controllers. The required order for initializing things is:
+ * + initialize the PPC
+ * + initialize, configure and realize downstream devices
+ * + connect downstream device MemoryRegions to the PPC
+ * + realize the PPC
+ * + map the PPC's MemoryRegions to the places in the address map
+ * where the downstream devices should appear
+ * + wire up the PPC's control lines to the SSE object
+ *
+ * The PPC mapping differs for the -A and -B1 variants; the -A version
+ * is much simpler, using only a single port of a single PPC and putting
+ * all the devices behind that.
+ */
+ const PPCInfo a_ppcs[] = { {
+ .name = "ahb_ppcexp0",
+ .ports = {
+ { "musca-devices", make_musca_a_devs, 0, 0x40100000, 0x100000 },
+ },
+ },
+ };
+
+ /*
+ * Devices listed with an 0x4.. address appear in both the NS 0x4.. region
+ * and the 0x5.. S region. Devices listed with an 0x5.. address appear
+ * only in the S region.
+ */
+ const PPCInfo b1_ppcs[] = { {
+ .name = "apb_ppcexp0",
+ .ports = {
+ { "eflash0", make_unimp_dev, &mms->eflash[0],
+ 0x52400000, 0x1000 },
+ { "eflash1", make_unimp_dev, &mms->eflash[1],
+ 0x52500000, 0x1000 },
+ { "qspi", make_unimp_dev, &mms->qspi, 0x42800000, 0x100000 },
+ { "mpc0", make_mpc, &mms->mpc[0], 0x52000000, 0x1000 },
+ { "mpc1", make_mpc, &mms->mpc[1], 0x52100000, 0x1000 },
+ { "mpc2", make_mpc, &mms->mpc[2], 0x52200000, 0x1000 },
+ { "mpc3", make_mpc, &mms->mpc[3], 0x52300000, 0x1000 },
+ { "mhu0", make_unimp_dev, &mms->mhu[0], 0x42600000, 0x100000 },
+ { "mhu1", make_unimp_dev, &mms->mhu[1], 0x42700000, 0x100000 },
+ { }, /* port 9: unused */
+ { }, /* port 10: unused */
+ { }, /* port 11: unused */
+ { }, /* port 12: unused */
+ { }, /* port 13: unused */
+ { "mpc4", make_mpc, &mms->mpc[4], 0x52e00000, 0x1000 },
+ },
+ }, {
+ .name = "apb_ppcexp1",
+ .ports = {
+ { "pwm0", make_unimp_dev, &mms->pwm[0], 0x40101000, 0x1000 },
+ { "pwm1", make_unimp_dev, &mms->pwm[1], 0x40102000, 0x1000 },
+ { "pwm2", make_unimp_dev, &mms->pwm[2], 0x40103000, 0x1000 },
+ { "i2s", make_unimp_dev, &mms->i2s, 0x40104000, 0x1000 },
+ { "uart0", make_uart, &mms->uart[0], 0x40105000, 0x1000 },
+ { "uart1", make_uart, &mms->uart[1], 0x40106000, 0x1000 },
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40108000, 0x1000 },
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40109000, 0x1000 },
+ { "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 },
+ { "scc", make_unimp_dev, &mms->scc, 0x5010b000, 0x1000 },
+ { "timer", make_unimp_dev, &mms->timer, 0x4010c000, 0x1000 },
+ { "rtc", make_rtc, &mms->rtc, 0x4010d000, 0x1000 },
+ { "pvt", make_unimp_dev, &mms->pvt, 0x4010e000, 0x1000 },
+ { "sdio", make_unimp_dev, &mms->sdio, 0x4010f000, 0x1000 },
+ },
+ }, {
+ .name = "ahb_ppcexp0",
+ .ports = {
+ { }, /* port 0: unused */
+ { "gpio", make_unimp_dev, &mms->gpio, 0x41000000, 0x1000 },
+ },
+ },
+ };
+
+ switch (mmc->type) {
+ case MUSCA_A:
+ ppcs = a_ppcs;
+ num_ppcs = ARRAY_SIZE(a_ppcs);
+ break;
+ case MUSCA_B1:
+ ppcs = b1_ppcs;
+ num_ppcs = ARRAY_SIZE(b1_ppcs);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ assert(num_ppcs <= MUSCA_PPC_MAX);
+
+ for (i = 0; i < num_ppcs; i++) {
+ const PPCInfo *ppcinfo = &ppcs[i];
+ TZPPC *ppc = &mms->ppc[i];
+ DeviceState *ppcdev;
+ int port;
+ char *gpioname;
+
+ sysbus_init_child_obj(OBJECT(machine), ppcinfo->name, ppc,
+ sizeof(TZPPC), TYPE_TZ_PPC);
+ ppcdev = DEVICE(ppc);
+
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
+ MemoryRegion *mr;
+ char *portname;
+
+ if (!pinfo->devfn) {
+ continue;
+ }
+
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
+ portname = g_strdup_printf("port[%d]", port);
+ object_property_set_link(OBJECT(ppc), OBJECT(mr),
+ portname, &error_fatal);
+ g_free(portname);
+ }
+
+ object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal);
+
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
+
+ if (!pinfo->devfn) {
+ continue;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr);
+
+ gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name);
+ qdev_connect_gpio_out_named(ssedev, gpioname, port,
+ qdev_get_gpio_in_named(ppcdev,
+ "cfg_nonsec",
+ port));
+ g_free(gpioname);
+ gpioname = g_strdup_printf("%s_ap", ppcinfo->name);
+ qdev_connect_gpio_out_named(ssedev, gpioname, port,
+ qdev_get_gpio_in_named(ppcdev,
+ "cfg_ap", port));
+ g_free(gpioname);
+ }
+
+ gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name);
+ qdev_connect_gpio_out_named(ssedev, gpioname, 0,
+ qdev_get_gpio_in_named(ppcdev,
+ "irq_enable", 0));
+ g_free(gpioname);
+ gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name);
+ qdev_connect_gpio_out_named(ssedev, gpioname, 0,
+ qdev_get_gpio_in_named(ppcdev,
+ "irq_clear", 0));
+ g_free(gpioname);
+ gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name);
+ qdev_connect_gpio_out_named(ppcdev, "irq", 0,
+ qdev_get_gpio_in_named(ssedev,
+ gpioname, 0));
+ g_free(gpioname);
+
+ qdev_connect_gpio_out(dev_splitter, i,
+ qdev_get_gpio_in_named(ppcdev,
+ "cfg_sec_resp", 0));
+ }
+
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000);
+}
+
+static void musca_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ mc->default_cpus = 2;
+ mc->min_cpus = mc->default_cpus;
+ mc->max_cpus = mc->default_cpus;
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
+ mc->init = musca_init;
+}
+
+static void musca_a_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+ MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc);
+
+ mc->desc = "ARM Musca-A board (dual Cortex-M33)";
+ mmc->type = MUSCA_A;
+ mmc->init_svtor = 0x10200000;
+ mmc->sram_addr_width = 15;
+ mmc->num_irqs = 64;
+ mmc->mpc_info = a_mpc_info;
+ mmc->num_mpcs = ARRAY_SIZE(a_mpc_info);
+}
+
+static void musca_b1_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+ MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc);
+
+ mc->desc = "ARM Musca-B1 board (dual Cortex-M33)";
+ mmc->type = MUSCA_B1;
+ /*
+ * This matches the DAPlink firmware which boots from QSPI. There
+ * is also a firmware blob which boots from the eFlash, which
+ * uses init_svtor = 0x1A000000. QEMU doesn't currently support that,
+ * though we could in theory expose a machine property on the command
+ * line to allow the user to request eFlash boot.
+ */
+ mmc->init_svtor = 0x10000000;
+ mmc->sram_addr_width = 17;
+ mmc->num_irqs = 96;
+ mmc->mpc_info = b1_mpc_info;
+ mmc->num_mpcs = ARRAY_SIZE(b1_mpc_info);
+}
+
+static const TypeInfo musca_info = {
+ .name = TYPE_MUSCA_MACHINE,
+ .parent = TYPE_MACHINE,
+ .abstract = true,
+ .instance_size = sizeof(MuscaMachineState),
+ .class_size = sizeof(MuscaMachineClass),
+ .class_init = musca_class_init,
+};
+
+static const TypeInfo musca_a_info = {
+ .name = TYPE_MUSCA_A_MACHINE,
+ .parent = TYPE_MUSCA_MACHINE,
+ .class_init = musca_a_class_init,
+};
+
+static const TypeInfo musca_b1_info = {
+ .name = TYPE_MUSCA_B1_MACHINE,
+ .parent = TYPE_MUSCA_MACHINE,
+ .class_init = musca_b1_class_init,
+};
+
+static void musca_machine_init(void)
+{
+ type_register_static(&musca_info);
+ type_register_static(&musca_a_info);
+ type_register_static(&musca_b1_info);
+}
+
+type_init(musca_machine_init);
s->irq = irq;
omap_sti_reset(s);
- qemu_chr_fe_init(&s->chr, chr ?: qemu_chr_new("null", "null"),
+ qemu_chr_fe_init(&s->chr, chr ?: qemu_chr_new("null", "null", NULL),
&error_abort);
memory_region_init_io(&s->iomem, NULL, &omap_sti_ops, s, "omap.sti",
VIRTIO_BLK_F_RO,
VIRTIO_BLK_F_FLUSH,
VIRTIO_BLK_F_CONFIG_WCE,
+ VIRTIO_BLK_F_DISCARD,
+ VIRTIO_BLK_F_WRITE_ZEROES,
VIRTIO_F_VERSION_1,
VIRTIO_RING_F_INDIRECT_DESC,
VIRTIO_RING_F_EVENT_IDX,
virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE);
virtio_add_feature(&features, VIRTIO_BLK_F_FLUSH);
virtio_add_feature(&features, VIRTIO_BLK_F_RO);
+ virtio_add_feature(&features, VIRTIO_BLK_F_DISCARD);
+ virtio_add_feature(&features, VIRTIO_BLK_F_WRITE_ZEROES);
if (s->config_wce) {
virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE);
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
+/* Config size before the discard support (hide associated config fields) */
+#define VIRTIO_BLK_CFG_SIZE offsetof(struct virtio_blk_config, \
+ max_discard_sectors)
+/*
+ * Starting from the discard feature, we can use this array to properly
+ * set the config size depending on the features enabled.
+ */
+static VirtIOFeature feature_sizes[] = {
+ {.flags = 1ULL << VIRTIO_BLK_F_DISCARD,
+ .end = virtio_endof(struct virtio_blk_config, discard_sector_alignment)},
+ {.flags = 1ULL << VIRTIO_BLK_F_WRITE_ZEROES,
+ .end = virtio_endof(struct virtio_blk_config, write_zeroes_may_unmap)},
+ {}
+};
+
+static void virtio_blk_set_config_size(VirtIOBlock *s, uint64_t host_features)
+{
+ s->config_size = MAX(VIRTIO_BLK_CFG_SIZE,
+ virtio_feature_get_config_size(feature_sizes, host_features));
+
+ assert(s->config_size <= sizeof(struct virtio_blk_config));
+}
+
static void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq,
VirtIOBlockReq *req)
{
}
static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
- bool is_read)
+ bool is_read, bool acct_failed)
{
- BlockErrorAction action = blk_get_error_action(req->dev->blk,
- is_read, error);
VirtIOBlock *s = req->dev;
+ BlockErrorAction action = blk_get_error_action(s->blk, is_read, error);
if (action == BLOCK_ERROR_ACTION_STOP) {
/* Break the link as the next request is going to be parsed from the
s->rq = req;
} else if (action == BLOCK_ERROR_ACTION_REPORT) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
- block_acct_failed(blk_get_stats(s->blk), &req->acct);
+ if (acct_failed) {
+ block_acct_failed(blk_get_stats(s->blk), &req->acct);
+ }
virtio_blk_free_request(req);
}
* the memory until the request is completed (which will
* happen on the other side of the migration).
*/
- if (virtio_blk_handle_rw_error(req, -ret, is_read)) {
+ if (virtio_blk_handle_rw_error(req, -ret, is_read, true)) {
continue;
}
}
aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
if (ret) {
- if (virtio_blk_handle_rw_error(req, -ret, 0)) {
+ if (virtio_blk_handle_rw_error(req, -ret, 0, true)) {
+ goto out;
+ }
+ }
+
+ virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
+ block_acct_done(blk_get_stats(s->blk), &req->acct);
+ virtio_blk_free_request(req);
+
+out:
+ aio_context_release(blk_get_aio_context(s->conf.conf.blk));
+}
+
+static void virtio_blk_discard_write_zeroes_complete(void *opaque, int ret)
+{
+ VirtIOBlockReq *req = opaque;
+ VirtIOBlock *s = req->dev;
+ bool is_write_zeroes = (virtio_ldl_p(VIRTIO_DEVICE(s), &req->out.type) &
+ ~VIRTIO_BLK_T_BARRIER) == VIRTIO_BLK_T_WRITE_ZEROES;
+
+ aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
+ if (ret) {
+ if (virtio_blk_handle_rw_error(req, -ret, false, is_write_zeroes)) {
goto out;
}
}
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
- block_acct_done(blk_get_stats(req->dev->blk), &req->acct);
+ if (is_write_zeroes) {
+ block_acct_done(blk_get_stats(s->blk), &req->acct);
+ }
virtio_blk_free_request(req);
out:
*/
scsi = (void *)elem->in_sg[elem->in_num - 2].iov_base;
- if (!blk->conf.scsi) {
+ if (!virtio_has_feature(blk->host_features, VIRTIO_BLK_F_SCSI)) {
status = VIRTIO_BLK_S_UNSUPP;
goto fail;
}
return true;
}
+static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
+ struct virtio_blk_discard_write_zeroes *dwz_hdr, bool is_write_zeroes)
+{
+ VirtIOBlock *s = req->dev;
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
+ uint64_t sector;
+ uint32_t num_sectors, flags, max_sectors;
+ uint8_t err_status;
+ int bytes;
+
+ sector = virtio_ldq_p(vdev, &dwz_hdr->sector);
+ num_sectors = virtio_ldl_p(vdev, &dwz_hdr->num_sectors);
+ flags = virtio_ldl_p(vdev, &dwz_hdr->flags);
+ max_sectors = is_write_zeroes ? s->conf.max_write_zeroes_sectors :
+ s->conf.max_discard_sectors;
+
+ /*
+ * max_sectors is at most BDRV_REQUEST_MAX_SECTORS, this check
+ * make us sure that "num_sectors << BDRV_SECTOR_BITS" can fit in
+ * the integer variable.
+ */
+ if (unlikely(num_sectors > max_sectors)) {
+ err_status = VIRTIO_BLK_S_IOERR;
+ goto err;
+ }
+
+ bytes = num_sectors << BDRV_SECTOR_BITS;
+
+ if (unlikely(!virtio_blk_sect_range_ok(s, sector, bytes))) {
+ err_status = VIRTIO_BLK_S_IOERR;
+ goto err;
+ }
+
+ /*
+ * The device MUST set the status byte to VIRTIO_BLK_S_UNSUPP for discard
+ * and write zeroes commands if any unknown flag is set.
+ */
+ if (unlikely(flags & ~VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP)) {
+ err_status = VIRTIO_BLK_S_UNSUPP;
+ goto err;
+ }
+
+ if (is_write_zeroes) { /* VIRTIO_BLK_T_WRITE_ZEROES */
+ int blk_aio_flags = 0;
+
+ if (flags & VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP) {
+ blk_aio_flags |= BDRV_REQ_MAY_UNMAP;
+ }
+
+ block_acct_start(blk_get_stats(s->blk), &req->acct, bytes,
+ BLOCK_ACCT_WRITE);
+
+ blk_aio_pwrite_zeroes(s->blk, sector << BDRV_SECTOR_BITS,
+ bytes, blk_aio_flags,
+ virtio_blk_discard_write_zeroes_complete, req);
+ } else { /* VIRTIO_BLK_T_DISCARD */
+ /*
+ * The device MUST set the status byte to VIRTIO_BLK_S_UNSUPP for
+ * discard commands if the unmap flag is set.
+ */
+ if (unlikely(flags & VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP)) {
+ err_status = VIRTIO_BLK_S_UNSUPP;
+ goto err;
+ }
+
+ blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, bytes,
+ virtio_blk_discard_write_zeroes_complete, req);
+ }
+
+ return VIRTIO_BLK_S_OK;
+
+err:
+ if (is_write_zeroes) {
+ block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_WRITE);
+ }
+ return err_status;
+}
+
static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
{
uint32_t type;
- sizeof(struct virtio_blk_inhdr);
iov_discard_back(in_iov, &in_num, sizeof(struct virtio_blk_inhdr));
- type = virtio_ldl_p(VIRTIO_DEVICE(req->dev), &req->out.type);
+ type = virtio_ldl_p(vdev, &req->out.type);
/* VIRTIO_BLK_T_OUT defines the command direction. VIRTIO_BLK_T_BARRIER
* is an optional flag. Although a guest should not send this flag if
case VIRTIO_BLK_T_IN:
{
bool is_write = type & VIRTIO_BLK_T_OUT;
- req->sector_num = virtio_ldq_p(VIRTIO_DEVICE(req->dev),
- &req->out.sector);
+ req->sector_num = virtio_ldq_p(vdev, &req->out.sector);
if (is_write) {
qemu_iovec_init_external(&req->qiov, out_iov, out_num);
req->qiov.size / BDRV_SECTOR_SIZE);
}
- if (!virtio_blk_sect_range_ok(req->dev, req->sector_num,
- req->qiov.size)) {
+ if (!virtio_blk_sect_range_ok(s, req->sector_num, req->qiov.size)) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
- block_acct_invalid(blk_get_stats(req->dev->blk),
+ block_acct_invalid(blk_get_stats(s->blk),
is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ);
virtio_blk_free_request(req);
return 0;
}
- block_acct_start(blk_get_stats(req->dev->blk),
- &req->acct, req->qiov.size,
+ block_acct_start(blk_get_stats(s->blk), &req->acct, req->qiov.size,
is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ);
/* merge would exceed maximum number of requests or IO direction
* changes */
if (mrb->num_reqs > 0 && (mrb->num_reqs == VIRTIO_BLK_MAX_MERGE_REQS ||
is_write != mrb->is_write ||
- !req->dev->conf.request_merging)) {
- virtio_blk_submit_multireq(req->dev->blk, mrb);
+ !s->conf.request_merging)) {
+ virtio_blk_submit_multireq(s->blk, mrb);
}
assert(mrb->num_reqs < VIRTIO_BLK_MAX_MERGE_REQS);
virtio_blk_free_request(req);
break;
}
+ /*
+ * VIRTIO_BLK_T_DISCARD and VIRTIO_BLK_T_WRITE_ZEROES are defined with
+ * VIRTIO_BLK_T_OUT flag set. We masked this flag in the switch statement,
+ * so we must mask it for these requests, then we will check if it is set.
+ */
+ case VIRTIO_BLK_T_DISCARD & ~VIRTIO_BLK_T_OUT:
+ case VIRTIO_BLK_T_WRITE_ZEROES & ~VIRTIO_BLK_T_OUT:
+ {
+ struct virtio_blk_discard_write_zeroes dwz_hdr;
+ size_t out_len = iov_size(out_iov, out_num);
+ bool is_write_zeroes = (type & ~VIRTIO_BLK_T_BARRIER) ==
+ VIRTIO_BLK_T_WRITE_ZEROES;
+ uint8_t err_status;
+
+ /*
+ * Unsupported if VIRTIO_BLK_T_OUT is not set or the request contains
+ * more than one segment.
+ */
+ if (unlikely(!(type & VIRTIO_BLK_T_OUT) ||
+ out_len > sizeof(dwz_hdr))) {
+ virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
+ virtio_blk_free_request(req);
+ return 0;
+ }
+
+ if (unlikely(iov_to_buf(out_iov, out_num, 0, &dwz_hdr,
+ sizeof(dwz_hdr)) != sizeof(dwz_hdr))) {
+ virtio_error(vdev, "virtio-blk discard/write_zeroes header"
+ " too short");
+ return -1;
+ }
+
+ err_status = virtio_blk_handle_discard_write_zeroes(req, &dwz_hdr,
+ is_write_zeroes);
+ if (err_status != VIRTIO_BLK_S_OK) {
+ virtio_blk_req_complete(req, err_status);
+ virtio_blk_free_request(req);
+ }
+
+ break;
+ }
default:
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
virtio_blk_free_request(req);
if (mrb.num_reqs) {
virtio_blk_submit_multireq(s->blk, &mrb);
}
+ blk_dec_in_flight(s->conf.conf.blk);
aio_context_release(blk_get_aio_context(s->conf.conf.blk));
}
}
if (!s->bh) {
+ /* FIXME The data plane is not started yet, so these requests are
+ * processed in the main thread. */
s->bh = aio_bh_new(blk_get_aio_context(s->conf.conf.blk),
virtio_blk_dma_restart_bh, s);
+ blk_inc_in_flight(s->conf.conf.blk);
qemu_bh_schedule(s->bh);
}
}
blkcfg.alignment_offset = 0;
blkcfg.wce = blk_enable_write_cache(s->blk);
virtio_stw_p(vdev, &blkcfg.num_queues, s->conf.num_queues);
- memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_DISCARD)) {
+ virtio_stl_p(vdev, &blkcfg.max_discard_sectors,
+ s->conf.max_discard_sectors);
+ virtio_stl_p(vdev, &blkcfg.discard_sector_alignment,
+ blk_size >> BDRV_SECTOR_BITS);
+ /*
+ * We support only one segment per request since multiple segments
+ * are not widely used and there are no userspace APIs that allow
+ * applications to submit multiple segments in a single call.
+ */
+ virtio_stl_p(vdev, &blkcfg.max_discard_seg, 1);
+ }
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_WRITE_ZEROES)) {
+ virtio_stl_p(vdev, &blkcfg.max_write_zeroes_sectors,
+ s->conf.max_write_zeroes_sectors);
+ blkcfg.write_zeroes_may_unmap = 1;
+ virtio_stl_p(vdev, &blkcfg.max_write_zeroes_seg, 1);
+ }
+ memcpy(config, &blkcfg, s->config_size);
}
static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
VirtIOBlock *s = VIRTIO_BLK(vdev);
struct virtio_blk_config blkcfg;
- memcpy(&blkcfg, config, sizeof(blkcfg));
+ memcpy(&blkcfg, config, s->config_size);
aio_context_acquire(blk_get_aio_context(s->blk));
blk_set_enable_write_cache(s->blk, blkcfg.wce != 0);
{
VirtIOBlock *s = VIRTIO_BLK(vdev);
+ /* Firstly sync all virtio-blk possible supported features */
+ features |= s->host_features;
+
virtio_add_feature(&features, VIRTIO_BLK_F_SEG_MAX);
virtio_add_feature(&features, VIRTIO_BLK_F_GEOMETRY);
virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY);
virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE);
if (virtio_has_feature(features, VIRTIO_F_VERSION_1)) {
- if (s->conf.scsi) {
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_SCSI)) {
error_setg(errp, "Please set scsi=off for virtio-blk devices in order to use virtio 1.0");
return 0;
}
virtio_add_feature(&features, VIRTIO_BLK_F_SCSI);
}
- if (s->conf.config_wce) {
- virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE);
- }
if (blk_enable_write_cache(s->blk)) {
virtio_add_feature(&features, VIRTIO_BLK_F_WCE);
}
return;
}
- virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
- sizeof(struct virtio_blk_config));
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_DISCARD) &&
+ (!conf->max_discard_sectors ||
+ conf->max_discard_sectors > BDRV_REQUEST_MAX_SECTORS)) {
+ error_setg(errp, "invalid max-discard-sectors property (%" PRIu32 ")"
+ ", must be between 1 and %d",
+ conf->max_discard_sectors, (int)BDRV_REQUEST_MAX_SECTORS);
+ return;
+ }
+
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_WRITE_ZEROES) &&
+ (!conf->max_write_zeroes_sectors ||
+ conf->max_write_zeroes_sectors > BDRV_REQUEST_MAX_SECTORS)) {
+ error_setg(errp, "invalid max-write-zeroes-sectors property (%" PRIu32
+ "), must be between 1 and %d",
+ conf->max_write_zeroes_sectors,
+ (int)BDRV_REQUEST_MAX_SECTORS);
+ return;
+ }
+
+ virtio_blk_set_config_size(s, s->host_features);
+
+ virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK, s->config_size);
s->blk = conf->conf.blk;
s->rq = NULL;
DEFINE_BLOCK_ERROR_PROPERTIES(VirtIOBlock, conf.conf),
DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlock, conf.conf),
DEFINE_PROP_STRING("serial", VirtIOBlock, conf.serial),
- DEFINE_PROP_BIT("config-wce", VirtIOBlock, conf.config_wce, 0, true),
+ DEFINE_PROP_BIT64("config-wce", VirtIOBlock, host_features,
+ VIRTIO_BLK_F_CONFIG_WCE, true),
#ifdef __linux__
- DEFINE_PROP_BIT("scsi", VirtIOBlock, conf.scsi, 0, false),
+ DEFINE_PROP_BIT64("scsi", VirtIOBlock, host_features,
+ VIRTIO_BLK_F_SCSI, false),
#endif
DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0,
true),
DEFINE_PROP_UINT16("queue-size", VirtIOBlock, conf.queue_size, 128),
DEFINE_PROP_LINK("iothread", VirtIOBlock, conf.iothread, TYPE_IOTHREAD,
IOThread *),
+ DEFINE_PROP_BIT64("discard", VirtIOBlock, host_features,
+ VIRTIO_BLK_F_DISCARD, true),
+ DEFINE_PROP_BIT64("write-zeroes", VirtIOBlock, host_features,
+ VIRTIO_BLK_F_WRITE_ZEROES, true),
+ DEFINE_PROP_UINT32("max-discard-sectors", VirtIOBlock,
+ conf.max_discard_sectors, BDRV_REQUEST_MAX_SECTORS),
+ DEFINE_PROP_UINT32("max-write-zeroes-sectors", VirtIOBlock,
+ conf.max_write_zeroes_sectors, BDRV_REQUEST_MAX_SECTORS),
DEFINE_PROP_END_OF_LIST(),
};
Chardev *uart_hci_init(void)
{
return qemu_chardev_new(NULL, TYPE_CHARDEV_HCI,
- NULL, &error_abort);
+ NULL, NULL, &error_abort);
}
static void register_types(void)
s->irq = irq;
s->serial = serial_mm_init(get_system_memory(), base, 2, irq,
omap_clk_getrate(fclk)/16,
- chr ?: qemu_chr_new(label, "null"),
+ chr ?: qemu_chr_new(label, "null", NULL),
DEVICE_NATIVE_ENDIAN);
return s;
}
/* TODO: Should reuse or destroy current s->serial */
s->serial = serial_mm_init(get_system_memory(), s->base, 2, s->irq,
omap_clk_getrate(s->fclk) / 16,
- chr ?: qemu_chr_new("null", "null"),
+ chr ?: qemu_chr_new("null", "null", NULL),
DEVICE_NATIVE_ENDIAN);
}
* This code is licensed under the GPL.
*/
+/*
+ * QEMU interface:
+ * + sysbus MMIO region 0: device registers
+ * + sysbus IRQ 0: UARTINTR (combined interrupt line)
+ * + sysbus IRQ 1: UARTRXINTR (receive FIFO interrupt line)
+ * + sysbus IRQ 2: UARTTXINTR (transmit FIFO interrupt line)
+ * + sysbus IRQ 3: UARTRTINTR (receive timeout interrupt line)
+ * + sysbus IRQ 4: UARTMSINTR (momem status interrupt line)
+ * + sysbus IRQ 5: UARTEINTR (error interrupt line)
+ */
+
#include "qemu/osdep.h"
+#include "hw/char/pl011.h"
#include "hw/sysbus.h"
#include "chardev/char-fe.h"
#include "qemu/log.h"
#include "trace.h"
-#define TYPE_PL011 "pl011"
-#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
-
-typedef struct PL011State {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- uint32_t readbuff;
- uint32_t flags;
- uint32_t lcr;
- uint32_t rsr;
- uint32_t cr;
- uint32_t dmacr;
- uint32_t int_enabled;
- uint32_t int_level;
- uint32_t read_fifo[16];
- uint32_t ilpr;
- uint32_t ibrd;
- uint32_t fbrd;
- uint32_t ifl;
- int read_pos;
- int read_count;
- int read_trigger;
- CharBackend chr;
- qemu_irq irq;
- const unsigned char *id;
-} PL011State;
-
#define PL011_INT_TX 0x20
#define PL011_INT_RX 0x10
#define PL011_FLAG_TXFF 0x20
#define PL011_FLAG_RXFE 0x10
+/* Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC */
+#define INT_OE (1 << 10)
+#define INT_BE (1 << 9)
+#define INT_PE (1 << 8)
+#define INT_FE (1 << 7)
+#define INT_RT (1 << 6)
+#define INT_TX (1 << 5)
+#define INT_RX (1 << 4)
+#define INT_DSR (1 << 3)
+#define INT_DCD (1 << 2)
+#define INT_CTS (1 << 1)
+#define INT_RI (1 << 0)
+#define INT_E (INT_OE | INT_BE | INT_PE | INT_FE)
+#define INT_MS (INT_RI | INT_DSR | INT_DCD | INT_CTS)
+
static const unsigned char pl011_id_arm[8] =
{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
static const unsigned char pl011_id_luminary[8] =
{ 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
+/* Which bits in the interrupt status matter for each outbound IRQ line ? */
+static const uint32_t irqmask[] = {
+ INT_E | INT_MS | INT_RT | INT_TX | INT_RX, /* combined IRQ */
+ INT_RX,
+ INT_TX,
+ INT_RT,
+ INT_MS,
+ INT_E,
+};
+
static void pl011_update(PL011State *s)
{
uint32_t flags;
+ int i;
flags = s->int_level & s->int_enabled;
trace_pl011_irq_state(flags != 0);
- qemu_set_irq(s->irq, flags != 0);
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
+ qemu_set_irq(s->irq[i], (flags & irqmask[i]) != 0);
+ }
}
static uint64_t pl011_read(void *opaque, hwaddr offset,
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
- "pl011_read: Bad offset %x\n", (int)offset);
+ "pl011_read: Bad offset 0x%x\n", (int)offset);
r = 0;
break;
}
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
- "pl011_write: Bad offset %x\n", (int)offset);
+ "pl011_write: Bad offset 0x%x\n", (int)offset);
}
}
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
PL011State *s = PL011(obj);
+ int i;
memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
- sysbus_init_irq(sbd, &s->irq);
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
+ sysbus_init_irq(sbd, &s->irq[i]);
+ }
s->read_trigger = 1;
s->ifl = 0x12;
}
static const TypeInfo pl011_luminary_info = {
- .name = "pl011_luminary",
+ .name = TYPE_PL011_LUMINARY,
.parent = TYPE_PL011,
.instance_init = pl011_luminary_init,
};
uint8_t outv[OUTPUT_BUFFER_SIZE];
int in_len;
bool handshake_done;
- GSource *timer_src;
+ guint timer_tag;
} Terminal3270;
#define TYPE_TERMINAL_3270 "x-terminal3270"
static void terminal_timer_cancel(Terminal3270 *t)
{
- if (t->timer_src) {
- g_source_destroy(t->timer_src);
- g_source_unref(t->timer_src);
- t->timer_src = NULL;
+ if (t->timer_tag) {
+ g_source_remove(t->timer_tag);
+ t->timer_tag = 0;
}
}
assert(size <= (INPUT_BUFFER_SIZE - t->in_len));
terminal_timer_cancel(t);
- t->timer_src = qemu_chr_timeout_add_ms(t->chr.chr, 600 * 1000,
- send_timing_mark_cb, t);
+ t->timer_tag = g_timeout_add_seconds(600, send_timing_mark_cb, t);
memcpy(&t->inv[t->in_len], buf, size);
t->in_len += size;
if (t->in_len < 2) {
* char-socket.c. Once qemu receives the terminal-type of the
* client, mark handshake done and trigger everything rolling again.
*/
- t->timer_src = qemu_chr_timeout_add_ms(t->chr.chr, 600 * 1000,
- send_timing_mark_cb, t);
+ t->timer_tag = g_timeout_add_seconds(600, send_timing_mark_cb, t);
break;
case CHR_EVENT_CLOSED:
sch->curr_status.scsw.dstat = SCSW_DSTAT_DEVICE_END;
/* Spawn a new virtio-serial bus on which the ports will ride as devices */
qbus_create_inplace(&vser->bus, sizeof(vser->bus), TYPE_VIRTIO_SERIAL_BUS,
dev, vdev->bus_name);
- qbus_set_hotplug_handler(BUS(&vser->bus), DEVICE(vser), errp);
+ qbus_set_hotplug_handler(BUS(&vser->bus), OBJECT(vser), errp);
vser->bus.vser = vser;
QTAILQ_INIT(&vser->ports);
* FIXME: sure we want to support implicit
* muxed monitors here?
*/
- qemu_chr_new_mux_mon(label, output), &error_abort);
+ qemu_chr_new_mux_mon(label, output, NULL),
+ &error_abort);
}
xenstore_store_pv_console_info(con->xendev.dev,
#include "hw/qdev.h"
#include "qapi/error.h"
-static void qbus_set_hotplug_handler_internal(BusState *bus, Object *handler,
- Error **errp)
+void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp)
{
-
object_property_set_link(OBJECT(bus), OBJECT(handler),
QDEV_HOTPLUG_HANDLER_PROPERTY, errp);
}
-void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, Error **errp)
-{
- qbus_set_hotplug_handler_internal(bus, OBJECT(handler), errp);
-}
-
void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp)
{
- qbus_set_hotplug_handler_internal(bus, OBJECT(bus), errp);
+ qbus_set_hotplug_handler(bus, OBJECT(bus), errp);
}
int qbus_walk_children(BusState *bus,
AddressSpace *as = s->cpu ? s->cpu->as : NULL;
if (!s->force_raw) {
- size = load_elf_as(s->file, NULL, NULL, &entry, NULL, NULL,
+ size = load_elf_as(s->file, NULL, NULL, NULL, &entry, NULL, NULL,
big_endian, 0, 0, 0, as);
if (size < 0) {
ssize_t load_image_size(const char *filename, void *addr, size_t size)
{
int fd;
- ssize_t actsize;
+ ssize_t actsize, l = 0;
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0) {
return -1;
}
- actsize = read(fd, addr, size);
- if (actsize < 0) {
- close(fd);
- return -1;
+ while ((actsize = read(fd, addr + l, size - l)) > 0) {
+ l += actsize;
}
+
close(fd);
- return actsize;
+ return actsize < 0 ? -1 : l;
}
/* read()-like version */
}
/* return < 0 if error, otherwise the number of bytes loaded in memory */
-int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
+int load_elf(const char *filename,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
+ uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
int clear_lsb, int data_swab)
{
- return load_elf_as(filename, translate_fn, translate_opaque, pentry,
- lowaddr, highaddr, big_endian, elf_machine, clear_lsb,
- data_swab, NULL);
+ return load_elf_as(filename, elf_note_fn, translate_fn, translate_opaque,
+ pentry, lowaddr, highaddr, big_endian, elf_machine,
+ clear_lsb, data_swab, NULL);
}
/* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf_as(const char *filename,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
int clear_lsb, int data_swab, AddressSpace *as)
{
- return load_elf_ram(filename, translate_fn, translate_opaque,
+ return load_elf_ram(filename, elf_note_fn, translate_fn, translate_opaque,
pentry, lowaddr, highaddr, big_endian, elf_machine,
clear_lsb, data_swab, as, true);
}
/* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf_ram(const char *filename,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
int clear_lsb, int data_swab, AddressSpace *as,
bool load_rom)
{
- return load_elf_ram_sym(filename, translate_fn, translate_opaque,
+ return load_elf_ram_sym(filename, elf_note_fn,
+ translate_fn, translate_opaque,
pentry, lowaddr, highaddr, big_endian,
elf_machine, clear_lsb, data_swab, as,
load_rom, NULL);
/* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf_ram_sym(const char *filename,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr, int big_endian,
lseek(fd, 0, SEEK_SET);
if (e_ident[EI_CLASS] == ELFCLASS64) {
- ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
+ ret = load_elf64(filename, fd, elf_note_fn,
+ translate_fn, translate_opaque, must_swab,
pentry, lowaddr, highaddr, elf_machine, clear_lsb,
data_swab, as, load_rom, sym_cb);
} else {
- ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
+ ret = load_elf32(filename, fd, elf_note_fn,
+ translate_fn, translate_opaque, must_swab,
pentry, lowaddr, highaddr, elf_machine, clear_lsb,
data_swab, as, load_rom, sym_cb);
}
{ "usb-kbd", "serial", "42" },
{ "usb-mouse", "serial", "42" },
{ "usb-kbd", "serial", "42" },
+ { "virtio-blk-device", "discard", "false" },
+ { "virtio-blk-device", "write-zeroes", "false" },
};
const size_t hw_compat_3_1_len = G_N_ELEMENTS(hw_compat_3_1);
dc->props = cpu_cluster_properties;
dc->realize = cpu_cluster_realize;
+
+ /* This is not directly for users, CPU children must be attached by code */
+ dc->user_creatable = false;
}
static const TypeInfo cpu_cluster_type_info = {
obj-y += boot.o
-obj-y += axis_dev88.o
+obj-$(CONFIG_AXIS) += axis_dev88.o
env->load_info = li;
/* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
devboard SDK. */
- image_size = load_elf(li->image_filename, translate_kernel_address, NULL,
+ image_size = load_elf(li->image_filename, NULL,
+ translate_kernel_address, NULL,
&entry, NULL, &high, 0, EM_CRIS, 0, 0);
li->entry = entry;
if (image_size < 0) {
QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
0));
} else {
-#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
+/* >= release 0.12.6, < release 0.14.2 */
+#if SPICE_SERVER_VERSION >= 0x000c06 && SPICE_SERVER_VERSION < 0x000e02
if (qxl->max_outputs) {
spice_qxl_set_max_monitors(&qxl->ssd.qxl, qxl->max_outputs);
}
SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
return;
}
+
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
+ char device_address[256] = "";
+ if (qemu_spice_fill_device_address(qxl->vga.con, device_address, 256)) {
+ spice_qxl_set_device_info(&qxl->ssd.qxl,
+ device_address,
+ 0,
+ qxl->max_outputs);
+ }
+#endif
+
qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);
# hw/display/virtio-gpu.c
virtio_gpu_features(bool virgl) "virgl %d"
virtio_gpu_cmd_get_display_info(void) ""
+virtio_gpu_cmd_get_edid(uint32_t scanout) "scanout %d"
virtio_gpu_cmd_set_scanout(uint32_t id, uint32_t res, uint32_t w, uint32_t h, uint32_t x, uint32_t y) "id %d, res 0x%x, w %d, h %d, x %d, y %d"
virtio_gpu_cmd_res_create_2d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h) "res 0x%x, fmt 0x%x, w %d, h %d"
virtio_gpu_cmd_res_create_3d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h, uint32_t d) "res 0x%x, fmt 0x%x, w %d, h %d, d %d"
{
VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr);
- cmd->waiting = g->renderer_blocked;
- if (cmd->waiting) {
- return;
- }
-
virgl_renderer_force_ctx_0();
switch (cmd->cmd_hdr.type) {
case VIRTIO_GPU_CMD_CTX_CREATE:
case VIRTIO_GPU_CMD_GET_DISPLAY_INFO:
virtio_gpu_get_display_info(g, cmd);
break;
+ case VIRTIO_GPU_CMD_GET_EDID:
+ virtio_gpu_get_edid(g, cmd);
+ break;
default:
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
break;
}
}
-void virtio_gpu_gl_block(void *opaque, bool block)
-{
- VirtIOGPU *g = opaque;
-
- if (block) {
- g->renderer_blocked++;
- } else {
- g->renderer_blocked--;
- }
- assert(g->renderer_blocked >= 0);
-
- if (g->renderer_blocked == 0) {
- virtio_gpu_process_cmdq(g);
- }
-}
-
int virtio_gpu_virgl_init(VirtIOGPU *g)
{
int ret;
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-gpu.h"
#include "hw/virtio/virtio-bus.h"
+#include "hw/display/edid.h"
#include "migration/blocker.h"
#include "qemu/log.h"
#include "qapi/error.h"
if (virtio_gpu_virgl_enabled(g->conf)) {
features |= (1 << VIRTIO_GPU_F_VIRGL);
}
+ if (virtio_gpu_edid_enabled(g->conf)) {
+ features |= (1 << VIRTIO_GPU_F_EDID);
+ }
return features;
}
sizeof(display_info));
}
+static void
+virtio_gpu_generate_edid(VirtIOGPU *g, int scanout,
+ struct virtio_gpu_resp_edid *edid)
+{
+ qemu_edid_info info = {
+ .prefx = g->req_state[scanout].width,
+ .prefy = g->req_state[scanout].height,
+ };
+
+ edid->size = cpu_to_le32(sizeof(edid->edid));
+ qemu_edid_generate(edid->edid, sizeof(edid->edid), &info);
+}
+
+void virtio_gpu_get_edid(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_resp_edid edid;
+ struct virtio_gpu_cmd_get_edid get_edid;
+
+ VIRTIO_GPU_FILL_CMD(get_edid);
+ virtio_gpu_bswap_32(&get_edid, sizeof(get_edid));
+
+ if (get_edid.scanout >= g->conf.max_outputs) {
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ return;
+ }
+
+ trace_virtio_gpu_cmd_get_edid(get_edid.scanout);
+ memset(&edid, 0, sizeof(edid));
+ edid.hdr.type = VIRTIO_GPU_RESP_OK_EDID;
+ virtio_gpu_generate_edid(g, get_edid.scanout, &edid);
+ virtio_gpu_ctrl_response(g, cmd, &edid.hdr, sizeof(edid));
+}
+
static pixman_format_code_t get_pixman_format(uint32_t virtio_gpu_format)
{
switch (virtio_gpu_format) {
case VIRTIO_GPU_CMD_GET_DISPLAY_INFO:
virtio_gpu_get_display_info(g, cmd);
break;
+ case VIRTIO_GPU_CMD_GET_EDID:
+ virtio_gpu_get_edid(g, cmd);
+ break;
case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D:
virtio_gpu_resource_create_2d(g, cmd);
break;
while (!QTAILQ_EMPTY(&g->cmdq)) {
cmd = QTAILQ_FIRST(&g->cmdq);
+ if (g->renderer_blocked) {
+ break;
+ }
+
/* process command */
VIRGL(g, virtio_gpu_virgl_process_cmd, virtio_gpu_simple_process_cmd,
g, cmd);
- if (cmd->waiting) {
- break;
- }
+
QTAILQ_REMOVE(&g->cmdq, cmd, next);
if (virtio_gpu_stats_enabled(g->conf)) {
g->stats.requests++;
cmd->vq = vq;
cmd->error = 0;
cmd->finished = false;
- cmd->waiting = false;
QTAILQ_INSERT_TAIL(&g->cmdq, cmd, next);
cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
}
return 0;
}
+static void virtio_gpu_gl_block(void *opaque, bool block)
+{
+ VirtIOGPU *g = opaque;
+
+ if (block) {
+ g->renderer_blocked++;
+ } else {
+ g->renderer_blocked--;
+ }
+ assert(g->renderer_blocked >= 0);
+
+ if (g->renderer_blocked == 0) {
+ virtio_gpu_process_cmdq(g);
+ }
+}
+
const GraphicHwOps virtio_gpu_ops = {
.invalidate = virtio_gpu_invalidate_display,
.gfx_update = virtio_gpu_update_display,
.text_update = virtio_gpu_text_update,
.ui_info = virtio_gpu_ui_info,
-#ifdef CONFIG_VIRGL
.gl_block = virtio_gpu_gl_block,
-#endif
};
static const VMStateDescription vmstate_virtio_gpu_scanout = {
}
}
- g->config_size = sizeof(struct virtio_gpu_config);
g->virtio_config.num_scanouts = cpu_to_le32(g->conf.max_outputs);
virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU,
- g->config_size);
+ sizeof(struct virtio_gpu_config));
g->req_state[0].width = g->conf.xres;
g->req_state[0].height = g->conf.yres;
QTAILQ_INIT(&g->fenceq);
g->enabled_output_bitmask = 1;
- g->qdev = qdev;
for (i = 0; i < g->conf.max_outputs; i++) {
g->scanout[i].con =
DEFINE_PROP_BIT("stats", VirtIOGPU, conf.flags,
VIRTIO_GPU_FLAG_STATS_ENABLED, false),
#endif
+ DEFINE_PROP_BIT("edid", VirtIOGPU, conf.flags,
+ VIRTIO_GPU_FLAG_EDID_ENABLED, false),
DEFINE_PROP_UINT32("xres", VirtIOGPU, conf.xres, 1024),
DEFINE_PROP_UINT32("yres", VirtIOGPU, conf.yres, 768),
DEFINE_PROP_END_OF_LIST(),
#include "hw/isa/isa.h"
#include "hw/dma/i8257.h"
#include "qemu/main-loop.h"
+#include "qemu/log.h"
#include "trace.h"
#define I8257(obj) \
switch (iport) {
case 0x00: /* command */
if ((data != 0) && (data & CMD_NOT_SUPPORTED)) {
- dolog("command %"PRIx64" not supported\n", data);
+ qemu_log_mask(LOG_UNIMP, "%s: cmd 0x%02"PRIx64" not supported\n",
+ __func__, data);
return;
}
d->command = data;
-obj-y += machine.o pci.o dino.o
+obj-$(CONFIG_DINO) += pci.o machine.o dino.o
MemoryRegion bm;
MemoryRegion bm_ram_alias;
MemoryRegion bm_pci_alias;
+ MemoryRegion bm_cpu_alias;
MemoryRegion cpu0_eir_mem;
} DinoState;
case DINO_PCI_IO_DATA ... DINO_PCI_IO_DATA + 3:
/* Read from PCI IO space. */
io = &address_space_io;
- ioaddr = s->parent_obj.config_reg;
+ ioaddr = s->parent_obj.config_reg + (addr & 3);
switch (size) {
case 1:
val = address_space_ldub(io, ioaddr, attrs, &ret);
case DINO_IO_DATA ... DINO_PCI_IO_DATA + 3:
/* Write into PCI IO space. */
io = &address_space_io;
- ioaddr = s->parent_obj.config_reg;
+ ioaddr = s->parent_obj.config_reg + (addr & 3);
switch (size) {
case 1:
address_space_stb(io, ioaddr, val, attrs, &ret);
.endianness = DEVICE_LITTLE_ENDIAN,
};
+static uint64_t dino_config_addr_read(void *opaque, hwaddr addr, unsigned len)
+{
+ PCIHostState *s = opaque;
+ return s->config_reg;
+}
+
+static void dino_config_addr_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned len)
+{
+ PCIHostState *s = opaque;
+ s->config_reg = val & ~3U;
+}
+
+static const MemoryRegionOps dino_config_addr_ops = {
+ .read = dino_config_addr_read,
+ .write = dino_config_addr_write,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
static AddressSpace *dino_pcihost_set_iommu(PCIBus *bus, void *opaque,
int devfn)
{
/* Dino PCI config. */
memory_region_init_io(&s->parent_obj.conf_mem, OBJECT(&s->parent_obj),
- &pci_host_conf_be_ops, dev, "pci-conf-idx", 4);
+ &dino_config_addr_ops, dev, "pci-conf-idx", 4);
memory_region_init_io(&s->parent_obj.data_mem, OBJECT(&s->parent_obj),
&dino_config_data_ops, dev, "pci-conf-data", 4);
memory_region_add_subregion(&s->this_mem, DINO_PCI_CONFIG_ADDR,
memory_region_init_alias(&s->bm_pci_alias, OBJECT(s),
"bm-pci", &s->pci_mem,
0xf0000000 + DINO_MEM_CHUNK_SIZE,
- 31 * DINO_MEM_CHUNK_SIZE);
+ 30 * DINO_MEM_CHUNK_SIZE);
+ memory_region_init_alias(&s->bm_cpu_alias, OBJECT(s),
+ "bm-cpu", addr_space, 0xfff00000,
+ 0xfffff);
memory_region_add_subregion(&s->bm, 0,
&s->bm_ram_alias);
memory_region_add_subregion(&s->bm,
0xf0000000 + DINO_MEM_CHUNK_SIZE,
&s->bm_pci_alias);
+ memory_region_add_subregion(&s->bm, 0xfff00000,
+ &s->bm_cpu_alias);
address_space_init(&s->bm_as, &s->bm, "pci-bm");
pci_setup_iommu(b, dino_pcihost_set_iommu, s);
exit(1);
}
- size = load_elf(firmware_filename, NULL,
- NULL, &firmware_entry, &firmware_low, &firmware_high,
+ size = load_elf(firmware_filename, NULL, NULL, NULL,
+ &firmware_entry, &firmware_low, &firmware_high,
true, EM_PARISC, 0, 0);
/* Unfortunately, load_elf sign-extends reading elf32. */
/* Load kernel */
if (kernel_filename) {
- size = load_elf(kernel_filename, &cpu_hppa_to_phys,
+ size = load_elf(kernel_filename, NULL, &cpu_hppa_to_phys,
NULL, &kernel_entry, &kernel_low, &kernel_high,
true, EM_PARISC, 0, 0);
-common-obj-$(CONFIG_I2C) += core.o smbus.o smbus_eeprom.o
+common-obj-$(CONFIG_I2C) += core.o smbus.o
+common-obj-$(CONFIG_SMBUS_EEPROM) += smbus_eeprom.o
common-obj-$(CONFIG_DDC) += i2c-ddc.o
common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
common-obj-$(CONFIG_ACPI_X86) += smbus_ich9.o
-common-obj-$(CONFIG_APM) += pm_smbus.o
+common-obj-$(CONFIG_ACPI_SMBUS) += pm_smbus.o
common-obj-$(CONFIG_BITBANG_I2C) += bitbang_i2c.o
common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o
common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
obj-$(CONFIG_KVM) += kvm/
obj-y += multiboot.o
-obj-y += pc.o pc_piix.o pc_q35.o
+obj-y += pc.o
+obj-$(CONFIG_I440FX) += pc_piix.o
+obj-$(CONFIG_Q35) += pc_q35.o
obj-y += pc_sysfw.o
obj-$(CONFIG_VTD) += x86-iommu.o intel_iommu.o
obj-$(CONFIG_AMD_IOMMU) += x86-iommu.o amd_iommu.o
/* FACS */
static void
-build_facs(GArray *table_data, BIOSLinker *linker)
+build_facs(GArray *table_data)
{
AcpiFacsDescriptorRev1 *facs = acpi_data_push(table_data, sizeof *facs);
memcpy(&facs->signature, "FACS", 4);
build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
if (TPM_IS_TIS(tpm)) {
- dev = aml_device("ISA.TPM");
- aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
+ if (misc->tpm_version == TPM_VERSION_2_0) {
+ dev = aml_device("TPM");
+ aml_append(dev, aml_name_decl("_HID",
+ aml_string("MSFT0101")));
+ } else {
+ dev = aml_device("ISA.TPM");
+ aml_append(dev, aml_name_decl("_HID",
+ aml_eisaid("PNP0C31")));
+ }
+
aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
crs = aml_resource_template();
aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
* requirements.
*/
facs = tables_blob->len;
- build_facs(tables_blob, tables->linker);
+ build_facs(tables_blob);
/* DSDT is pointed to by FADT */
dsdt = tables_blob->len;
assert(as);
- use_iommu = as->iommu_state->dmar_enabled & !vtd_dev_pt_enabled(as);
+ use_iommu = as->iommu_state->dmar_enabled && !vtd_dev_pt_enabled(as);
trace_vtd_switch_address_space(pci_bus_num(as->bus),
VTD_PCI_SLOT(as->devfn),
s->root = 0;
s->root_extended = false;
s->dmar_enabled = false;
+ s->intr_enabled = false;
s->iq_head = 0;
s->iq_tail = 0;
s->iq = 0;
exit(1);
}
- kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
&elf_low, &elf_high, 0, I386_ELF_MACHINE,
0, 0);
if (kernel_size < 0) {
#include "sysemu/qtest.h"
#include "kvm_i386.h"
#include "hw/xen/xen.h"
+#include "hw/xen/start_info.h"
#include "ui/qemu-spice.h"
#include "exec/memory.h"
#include "exec/address-spaces.h"
#include "hw/usb.h"
#include "hw/i386/intel_iommu.h"
#include "hw/net/ne2000-isa.h"
+#include "standard-headers/asm-x86/bootparam.h"
/* debug PC/ISA interrupts */
//#define DEBUG_IRQ
static unsigned e820_entries;
struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
+/* Physical Address of PVH entry point read from kernel ELF NOTE */
+static size_t pvh_start_addr;
+
GlobalProperty pc_compat_3_1[] = {
{ "intel-iommu", "dma-drain", "off" },
{ "Opteron_G3" "-" TYPE_X86_CPU, "rdtscp", "off" },
return size;
}
-/* setup_data types */
-#define SETUP_NONE 0
-#define SETUP_E820_EXT 1
-#define SETUP_DTB 2
-#define SETUP_PCI 3
-#define SETUP_EFI 4
-
struct setup_data {
uint64_t next;
uint32_t type;
uint8_t data[0];
} __attribute__((packed));
+
+/*
+ * The entry point into the kernel for PVH boot is different from
+ * the native entry point. The PVH entry is defined by the x86/HVM
+ * direct boot ABI and is available in an ELFNOTE in the kernel binary.
+ *
+ * This function is passed to load_elf() when it is called from
+ * load_elfboot() which then additionally checks for an ELF Note of
+ * type XEN_ELFNOTE_PHYS32_ENTRY and passes it to this function to
+ * parse the PVH entry address from the ELF Note.
+ *
+ * Due to trickery in elf_opts.h, load_elf() is actually available as
+ * load_elf32() or load_elf64() and this routine needs to be able
+ * to deal with being called as 32 or 64 bit.
+ *
+ * The address of the PVH entry point is saved to the 'pvh_start_addr'
+ * global variable. (although the entry point is 32-bit, the kernel
+ * binary can be either 32-bit or 64-bit).
+ */
+static uint64_t read_pvh_start_addr(void *arg1, void *arg2, bool is64)
+{
+ size_t *elf_note_data_addr;
+
+ /* Check if ELF Note header passed in is valid */
+ if (arg1 == NULL) {
+ return 0;
+ }
+
+ if (is64) {
+ struct elf64_note *nhdr64 = (struct elf64_note *)arg1;
+ uint64_t nhdr_size64 = sizeof(struct elf64_note);
+ uint64_t phdr_align = *(uint64_t *)arg2;
+ uint64_t nhdr_namesz = nhdr64->n_namesz;
+
+ elf_note_data_addr =
+ ((void *)nhdr64) + nhdr_size64 +
+ QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
+ } else {
+ struct elf32_note *nhdr32 = (struct elf32_note *)arg1;
+ uint32_t nhdr_size32 = sizeof(struct elf32_note);
+ uint32_t phdr_align = *(uint32_t *)arg2;
+ uint32_t nhdr_namesz = nhdr32->n_namesz;
+
+ elf_note_data_addr =
+ ((void *)nhdr32) + nhdr_size32 +
+ QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
+ }
+
+ pvh_start_addr = *elf_note_data_addr;
+
+ return pvh_start_addr;
+}
+
+static bool load_elfboot(const char *kernel_filename,
+ int kernel_file_size,
+ uint8_t *header,
+ size_t pvh_xen_start_addr,
+ FWCfgState *fw_cfg)
+{
+ uint32_t flags = 0;
+ uint32_t mh_load_addr = 0;
+ uint32_t elf_kernel_size = 0;
+ uint64_t elf_entry;
+ uint64_t elf_low, elf_high;
+ int kernel_size;
+
+ if (ldl_p(header) != 0x464c457f) {
+ return false; /* no elfboot */
+ }
+
+ bool elf_is64 = header[EI_CLASS] == ELFCLASS64;
+ flags = elf_is64 ?
+ ((Elf64_Ehdr *)header)->e_flags : ((Elf32_Ehdr *)header)->e_flags;
+
+ if (flags & 0x00010004) { /* LOAD_ELF_HEADER_HAS_ADDR */
+ error_report("elfboot unsupported flags = %x", flags);
+ exit(1);
+ }
+
+ uint64_t elf_note_type = XEN_ELFNOTE_PHYS32_ENTRY;
+ kernel_size = load_elf(kernel_filename, read_pvh_start_addr,
+ NULL, &elf_note_type, &elf_entry,
+ &elf_low, &elf_high, 0, I386_ELF_MACHINE,
+ 0, 0);
+
+ if (kernel_size < 0) {
+ error_report("Error while loading elf kernel");
+ exit(1);
+ }
+ mh_load_addr = elf_low;
+ elf_kernel_size = elf_high - elf_low;
+
+ if (pvh_start_addr == 0) {
+ error_report("Error loading uncompressed kernel without PVH ELF Note");
+ exit(1);
+ }
+ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ENTRY, pvh_start_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, mh_load_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, elf_kernel_size);
+
+ return true;
+}
+
static void load_linux(PCMachineState *pcms,
FWCfgState *fw_cfg)
{
if (ldl_p(header+0x202) == 0x53726448) {
protocol = lduw_p(header+0x206);
} else {
+ /*
+ * Check if the file is an uncompressed kernel file (ELF) and load it,
+ * saving the PVH entry point used by the x86/HVM direct boot ABI.
+ * If load_elfboot() is successful, populate the fw_cfg info.
+ */
+ if (pcmc->pvh_enabled &&
+ load_elfboot(kernel_filename, kernel_size,
+ header, pvh_start_addr, fw_cfg)) {
+ fclose(f);
+
+ fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
+ strlen(kernel_cmdline) + 1);
+ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+
+ fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, sizeof(header));
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA,
+ header, sizeof(header));
+
+ /* load initrd */
+ if (initrd_filename) {
+ gsize initrd_size;
+ gchar *initrd_data;
+ GError *gerr = NULL;
+
+ if (!g_file_get_contents(initrd_filename, &initrd_data,
+ &initrd_size, &gerr)) {
+ fprintf(stderr, "qemu: error reading initrd %s: %s\n",
+ initrd_filename, gerr->message);
+ exit(1);
+ }
+
+ initrd_max = pcms->below_4g_mem_size - pcmc->acpi_data_size - 1;
+ if (initrd_size >= initrd_max) {
+ fprintf(stderr, "qemu: initrd is too large, cannot support."
+ "(max: %"PRIu32", need %"PRId64")\n",
+ initrd_max, (uint64_t)initrd_size);
+ exit(1);
+ }
+
+ initrd_addr = (initrd_max - initrd_size) & ~4095;
+
+ fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data,
+ initrd_size);
+ }
+
+ option_rom[nb_option_roms].bootindex = 0;
+ option_rom[nb_option_roms].name = "pvh.bin";
+ nb_option_roms++;
+
+ return;
+ }
/* This looks like a multiboot kernel. If it is, let's stop
treating it like a Linux kernel. */
if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename,
#endif
/* highest address for loading the initrd */
- if (protocol >= 0x203) {
+ if (protocol >= 0x20c &&
+ lduw_p(header+0x236) & XLF_CAN_BE_LOADED_ABOVE_4G) {
+ /*
+ * Linux has supported initrd up to 4 GB for a very long time (2007,
+ * long before XLF_CAN_BE_LOADED_ABOVE_4G which was added in 2013),
+ * though it only sets initrd_max to 2 GB to "work around bootloader
+ * bugs". Luckily, QEMU firmware(which does something like bootloader)
+ * has supported this.
+ *
+ * It's believed that if XLF_CAN_BE_LOADED_ABOVE_4G is set, initrd can
+ * be loaded into any address.
+ *
+ * In addition, initrd_max is uint32_t simply because QEMU doesn't
+ * support the 64-bit boot protocol (specifically the ext_ramdisk_image
+ * field).
+ *
+ * Therefore here just limit initrd_max to UINT32_MAX simply as well.
+ */
+ initrd_max = UINT32_MAX;
+ } else if (protocol >= 0x203) {
initrd_max = ldl_p(header+0x22c);
} else {
initrd_max = 0x37ffffff;
for (i = 0; i < nb_option_roms; i++) {
assert(!strcmp(option_rom[i].name, "linuxboot.bin") ||
!strcmp(option_rom[i].name, "linuxboot_dma.bin") ||
+ !strcmp(option_rom[i].name, "pvh.bin") ||
!strcmp(option_rom[i].name, "multiboot.bin"));
rom_add_option(option_rom[i].name, option_rom[i].bootindex);
}
static void pc_memory_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
- HotplugHandlerClass *hhc;
Error *local_err = NULL;
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
nvdimm_plug(&pcms->acpi_nvdimm_state);
}
- hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
- hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &error_abort);
+ hotplug_handler_plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &error_abort);
out:
error_propagate(errp, local_err);
}
static void pc_memory_unplug_request(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
- HotplugHandlerClass *hhc;
Error *local_err = NULL;
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
goto out;
}
- hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
- hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
-
+ hotplug_handler_unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev,
+ &local_err);
out:
error_propagate(errp, local_err);
}
DeviceState *dev, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
- HotplugHandlerClass *hhc;
Error *local_err = NULL;
- hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
- hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
-
+ hotplug_handler_unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
if (local_err) {
goto out;
}
DeviceState *dev, Error **errp)
{
CPUArchId *found_cpu;
- HotplugHandlerClass *hhc;
Error *local_err = NULL;
X86CPU *cpu = X86_CPU(dev);
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
if (pcms->acpi_dev) {
- hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
- hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
+ hotplug_handler_plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
if (local_err) {
goto out;
}
DeviceState *dev, Error **errp)
{
int idx = -1;
- HotplugHandlerClass *hhc;
Error *local_err = NULL;
X86CPU *cpu = X86_CPU(dev);
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
goto out;
}
- hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
- hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
-
+ hotplug_handler_unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev,
+ &local_err);
if (local_err) {
goto out;
}
DeviceState *dev, Error **errp)
{
CPUArchId *found_cpu;
- HotplugHandlerClass *hhc;
Error *local_err = NULL;
X86CPU *cpu = X86_CPU(dev);
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
- hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
- hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
-
+ hotplug_handler_unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
if (local_err) {
goto out;
}
pcmc->acpi_data_size = 0x20000 + 0x8000;
pcmc->save_tsc_khz = true;
pcmc->linuxboot_dma_enabled = true;
+ pcmc->pvh_enabled = true;
assert(!mc->get_hotplug_handler);
mc->get_hotplug_handler = pc_get_hotplug_handler;
mc->cpu_index_to_instance_props = pc_cpu_index_to_props;
static void pc_i440fx_3_1_machine_options(MachineClass *m)
{
+ PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
+
pc_i440fx_4_0_machine_options(m);
m->is_default = 0;
m->alias = NULL;
+ pcmc->pvh_enabled = false;
compat_props_add(m->compat_props, hw_compat_3_1, hw_compat_3_1_len);
compat_props_add(m->compat_props, pc_compat_3_1, pc_compat_3_1_len);
}
static void pc_q35_3_1_machine_options(MachineClass *m)
{
+ PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
+
pc_q35_4_0_machine_options(m);
m->default_kernel_irqchip_split = false;
m->alias = NULL;
+ pcmc->pvh_enabled = false;
compat_props_add(m->compat_props, hw_compat_3_1, hw_compat_3_1_len);
compat_props_add(m->compat_props, pc_compat_3_1, pc_compat_3_1_len);
}
common-obj-$(CONFIG_IDE_CORE) += core.o atapi.o
common-obj-$(CONFIG_IDE_QDEV) += qdev.o
common-obj-$(CONFIG_IDE_PCI) += pci.o
-common-obj-$(CONFIG_IDE_ISA) += isa.o
-common-obj-$(CONFIG_IDE_PIIX) += piix.o
+common-obj-$(CONFIG_IDE_ISA) += isa.o ioport.o
+common-obj-$(CONFIG_IDE_PIIX) += piix.o ioport.o
common-obj-$(CONFIG_IDE_CMD646) += cmd646.o
common-obj-$(CONFIG_IDE_MACIO) += macio.o
common-obj-$(CONFIG_IDE_MMIO) += mmio.o
static int cd_read_sector(IDEState *s)
{
+ void *buf;
+
if (s->cd_sector_size != 2048 && s->cd_sector_size != 2352) {
block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_READ);
return -EINVAL;
}
- s->iov.iov_base = (s->cd_sector_size == 2352) ?
- s->io_buffer + 16 : s->io_buffer;
-
- s->iov.iov_len = ATAPI_SECTOR_SIZE;
- qemu_iovec_init_external(&s->qiov, &s->iov, 1);
+ buf = (s->cd_sector_size == 2352) ? s->io_buffer + 16 : s->io_buffer;
+ qemu_iovec_init_buf(&s->qiov, buf, ATAPI_SECTOR_SIZE);
trace_cd_read_sector(s->lba);
data_offset = 0;
}
trace_ide_atapi_cmd_read_dma_cb_aio(s, s->lba, n);
- s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset);
- s->bus->dma->iov.iov_len = n * ATAPI_SECTOR_SIZE;
- qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1);
+ qemu_iovec_init_buf(&s->bus->dma->qiov, s->io_buffer + data_offset,
+ n * ATAPI_SECTOR_SIZE);
s->bus->dma->aiocb = ide_buffered_readv(s, (int64_t)s->lba << 2,
&s->bus->dma->qiov, n * 4,
IDEBufferedRequest *req = opaque;
if (!req->orphaned) {
if (!ret) {
- qemu_iovec_from_buf(req->original_qiov, 0, req->iov.iov_base,
+ assert(req->qiov.size == req->original_qiov->size);
+ qemu_iovec_from_buf(req->original_qiov, 0,
+ req->qiov.local_iov.iov_base,
req->original_qiov->size);
}
req->original_cb(req->original_opaque, ret);
}
QLIST_REMOVE(req, list);
- qemu_vfree(req->iov.iov_base);
+ qemu_vfree(qemu_iovec_buf(&req->qiov));
g_free(req);
}
req->original_qiov = iov;
req->original_cb = cb;
req->original_opaque = opaque;
- req->iov.iov_base = qemu_blockalign(blk_bs(s->blk), iov->size);
- req->iov.iov_len = iov->size;
- qemu_iovec_init_external(&req->qiov, &req->iov, 1);
+ qemu_iovec_init_buf(&req->qiov, blk_blockalign(s->blk, iov->size),
+ iov->size);
aioreq = blk_aio_preadv(s->blk, sector_num << BDRV_SECTOR_BITS,
&req->qiov, 0, ide_buffered_readv_cb, req);
return;
}
- s->iov.iov_base = s->io_buffer;
- s->iov.iov_len = n * BDRV_SECTOR_SIZE;
- qemu_iovec_init_external(&s->qiov, &s->iov, 1);
+ qemu_iovec_init_buf(&s->qiov, s->io_buffer, n * BDRV_SECTOR_SIZE);
block_acct_start(blk_get_stats(s->blk), &s->acct,
n * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ);
return;
}
- s->iov.iov_base = s->io_buffer;
- s->iov.iov_len = n * BDRV_SECTOR_SIZE;
- qemu_iovec_init_external(&s->qiov, &s->iov, 1);
+ qemu_iovec_init_buf(&s->qiov, s->io_buffer, n * BDRV_SECTOR_SIZE);
block_acct_start(blk_get_stats(s->blk), &s->acct,
n * BDRV_SECTOR_SIZE, BLOCK_ACCT_WRITE);
qemu_vfree(s->io_buffer);
}
-static const MemoryRegionPortio ide_portio_list[] = {
- { 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write },
- { 0, 1, 2, .read = ide_data_readw, .write = ide_data_writew },
- { 0, 1, 4, .read = ide_data_readl, .write = ide_data_writel },
- PORTIO_END_OF_LIST(),
-};
-
-static const MemoryRegionPortio ide_portio2_list[] = {
- { 0, 1, 1, .read = ide_status_read, .write = ide_cmd_write },
- PORTIO_END_OF_LIST(),
-};
-
-void ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2)
-{
- /* ??? Assume only ISA and PCI configurations, and that the PCI-ISA
- bridge has been setup properly to always register with ISA. */
- isa_register_portio_list(dev, &bus->portio_list,
- iobase, ide_portio_list, bus, "ide");
-
- if (iobase2) {
- isa_register_portio_list(dev, &bus->portio2_list,
- iobase2, ide_portio2_list, bus, "ide");
- }
-}
-
static bool is_identify_set(void *opaque, int version_id)
{
IDEState *s = opaque;
--- /dev/null
+/*
+ * QEMU IDE disk and CD/DVD-ROM Emulator
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ * Copyright (c) 2006 Openedhand Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "hw/isa/isa.h"
+#include "qemu/error-report.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/blockdev.h"
+#include "sysemu/dma.h"
+#include "hw/block/block.h"
+#include "sysemu/block-backend.h"
+#include "qapi/error.h"
+#include "qemu/cutils.h"
+#include "sysemu/replay.h"
+
+#include "hw/ide/internal.h"
+#include "trace.h"
+
+static const MemoryRegionPortio ide_portio_list[] = {
+ { 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write },
+ { 0, 1, 2, .read = ide_data_readw, .write = ide_data_writew },
+ { 0, 1, 4, .read = ide_data_readl, .write = ide_data_writel },
+ PORTIO_END_OF_LIST(),
+};
+
+static const MemoryRegionPortio ide_portio2_list[] = {
+ { 0, 1, 1, .read = ide_status_read, .write = ide_cmd_write },
+ PORTIO_END_OF_LIST(),
+};
+
+void ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2)
+{
+ /* ??? Assume only ISA and PCI configurations, and that the PCI-ISA
+ bridge has been setup properly to always register with ISA. */
+ isa_register_portio_list(dev, &bus->portio_list,
+ iobase, ide_portio_list, bus, "ide");
+
+ if (iobase2) {
+ isa_register_portio_list(dev, &bus->portio2_list,
+ iobase2, ide_portio2_list, bus, "ide");
+ }
+}
#include "hw/input/i8042.h"
#include "sysemu/sysemu.h"
-/* debug PC keyboard */
-//#define DEBUG_KBD
-#ifdef DEBUG_KBD
-#define DPRINTF(fmt, ...) \
- do { printf("KBD: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...)
-#endif
+#include "trace.h"
/* Keyboard Controller Commands */
#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */
KBDState *s = opaque;
int val;
val = s->status;
- DPRINTF("kbd: read status=0x%02x\n", val);
+ trace_pckbd_kbd_read_status(val);
return val;
}
static void outport_write(KBDState *s, uint32_t val)
{
- DPRINTF("kbd: write outport=0x%02x\n", val);
+ trace_pckbd_outport_write(val);
s->outport = val;
qemu_set_irq(s->a20_out, (val >> 1) & 1);
if (!(val & 1)) {
{
KBDState *s = opaque;
- DPRINTF("kbd: write cmd=0x%02" PRIx64 "\n", val);
+ trace_pckbd_kbd_write_command(val);
/* Bits 3-0 of the output port P2 of the keyboard controller may be pulsed
* low for approximately 6 micro seconds. Bits 3-0 of the KBD_CCMD_PULSE
else
val = ps2_read_data(s->kbd);
- DPRINTF("kbd: read data=0x%02x\n", val);
+ trace_pckbd_kbd_read_data(val);
return val;
}
{
KBDState *s = opaque;
- DPRINTF("kbd: write data=0x%02" PRIx64 "\n", val);
+ trace_pckbd_kbd_write_data(val);
switch(s->write_cmd) {
case 0:
adb_mouse_request_change_addr(int devaddr) "change addr to 0x%x"
adb_mouse_request_change_addr_and_handler(int devaddr, int handler) "change addr and handler to 0x%x, 0x%x"
+# hw/input/pckbd.c
+pckbd_kbd_read_data(uint32_t val) "0x%02x"
+pckbd_kbd_read_status(int status) "0x%02x"
+pckbd_outport_write(uint32_t val) "0x%02x"
+pckbd_kbd_write_command(uint64_t val) "0x%02"PRIx64
+pckbd_kbd_write_data(uint64_t val) "0x%02"PRIx64
+
# hw/input/ps2.c
ps2_put_keycode(void *opaque, int keycode) "%p keycode 0x%02x"
ps2_keyboard_event(void *opaque, int qcode, int down, unsigned int modifier, unsigned int modifiers) "%p qcode %d down %d modifier 0x%x modifiers 0x%x"
return;
default:
-#ifdef TSC_VERBOSE
- fprintf(stderr, "tsc2102_data_register_write: "
- "no such register: 0x%02x\n", reg);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR, "tsc2102_data_register_write: "
+ "no such register: 0x%02x\n", reg);
}
}
default:
bad_reg:
-#ifdef TSC_VERBOSE
- fprintf(stderr, "tsc2102_control_register_write: "
- "no such register: 0x%02x\n", reg);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR, "tsc2102_control_register_write: "
+ "no such register: 0x%02x\n", reg);
}
}
return;
default:
-#ifdef TSC_VERBOSE
- fprintf(stderr, "tsc2102_audio_register_write: "
- "no such register: 0x%02x\n", reg);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR, "tsc2102_audio_register_write: "
+ "no such register: 0x%02x\n", reg);
}
}
}
}
break;
- case 0xd18: /* System Handler Priority (SHPR1) */
+ case 0xd18 ... 0xd1b: /* System Handler Priority (SHPR1) */
if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) {
val = 0;
break;
}
nvic_irq_update(s);
return MEMTX_OK;
- case 0xd18: /* System Handler Priority (SHPR1) */
+ case 0xd18 ... 0xd1b: /* System Handler Priority (SHPR1) */
if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) {
return MEMTX_OK;
}
{
sPAPRXive *xive = SPAPR_XIVE(obj);
- object_initialize(&xive->source, sizeof(xive->source), TYPE_XIVE_SOURCE);
- object_property_add_child(obj, "source", OBJECT(&xive->source), NULL);
+ object_initialize_child(obj, "source", &xive->source, sizeof(xive->source),
+ TYPE_XIVE_SOURCE, &error_abort, NULL);
- object_initialize(&xive->end_source, sizeof(xive->end_source),
- TYPE_XIVE_END_SOURCE);
- object_property_add_child(obj, "end_source", OBJECT(&xive->end_source),
- NULL);
+ object_initialize_child(obj, "end_source", &xive->end_source,
+ sizeof(xive->end_source), TYPE_XIVE_END_SOURCE,
+ &error_abort, NULL);
}
static void spapr_xive_realize(DeviceState *dev, Error **errp)
/* Map all regions */
spapr_xive_map_mmio(xive);
+ xive->nodename = g_strdup_printf("interrupt-controller@%" PRIx64,
+ xive->tm_base + XIVE_TM_USER_PAGE * (1 << TM_SHIFT));
+
qemu_register_reset(spapr_xive_reset, dev);
}
}
xive->eat[lisn].w |= cpu_to_be64(EAS_VALID);
- xive_source_irq_set(xsrc, lisn, lsi);
+ if (lsi) {
+ xive_source_irq_set_lsi(xsrc, lisn);
+ }
return true;
}
bool spapr_xive_irq_free(sPAPRXive *xive, uint32_t lisn)
{
- XiveSource *xsrc = &xive->source;
-
if (lisn >= xive->nr_irqs) {
return false;
}
xive->eat[lisn].w &= cpu_to_be64(~EAS_VALID);
- xive_source_irq_set(xsrc, lisn, false);
return true;
}
cpu_to_be32(7), /* start */
cpu_to_be32(0xf8), /* count */
};
- gchar *nodename;
/* Thread Interrupt Management Area : User (ring 3) and OS (ring 2) */
timas[0] = cpu_to_be64(xive->tm_base +
XIVE_TM_OS_PAGE * (1ull << TM_SHIFT));
timas[3] = cpu_to_be64(1ull << TM_SHIFT);
- nodename = g_strdup_printf("interrupt-controller@%" PRIx64,
- xive->tm_base + XIVE_TM_USER_PAGE * (1 << TM_SHIFT));
- _FDT(node = fdt_add_subnode(fdt, 0, nodename));
- g_free(nodename);
+ _FDT(node = fdt_add_subnode(fdt, 0, xive->nodename));
_FDT(fdt_setprop_string(fdt, node, "device_type", "power-ivpe"));
_FDT(fdt_setprop(fdt, node, "reg", timas, sizeof(timas)));
#include "qapi/visitor.h"
#include "monitor/monitor.h"
#include "hw/intc/intc.h"
+#include "sysemu/kvm.h"
void icp_pic_print_info(ICPState *icp, Monitor *mon)
{
- ICPStateClass *icpc = ICP_GET_CLASS(icp);
int cpu_index = icp->cs ? icp->cs->cpu_index : -1;
if (!icp->output) {
return;
}
- if (icpc->synchronize_state) {
- icpc->synchronize_state(icp);
+ if (kvm_irqchip_in_kernel()) {
+ icp_synchronize_state(icp);
}
monitor_printf(mon, "CPU %d XIRR=%08x (%p) PP=%02x MFRR=%02x\n",
void ics_pic_print_info(ICSState *ics, Monitor *mon)
{
- ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics);
uint32_t i;
monitor_printf(mon, "ICS %4x..%4x %p\n",
return;
}
- if (icsc->synchronize_state) {
- icsc->synchronize_state(ics);
+ if (kvm_irqchip_in_kernel()) {
+ ics_synchronize_state(ics);
}
for (i = 0; i < ics->nr_irqs; i++) {
}
}
-static int icp_dispatch_pre_save(void *opaque)
+static int icp_pre_save(void *opaque)
{
ICPState *icp = opaque;
- ICPStateClass *info = ICP_GET_CLASS(icp);
- if (info->pre_save) {
- info->pre_save(icp);
+ if (kvm_irqchip_in_kernel()) {
+ icp_get_kvm_state(icp);
}
return 0;
}
-static int icp_dispatch_post_load(void *opaque, int version_id)
+static int icp_post_load(void *opaque, int version_id)
{
ICPState *icp = opaque;
- ICPStateClass *info = ICP_GET_CLASS(icp);
- if (info->post_load) {
- return info->post_load(icp, version_id);
+ if (kvm_irqchip_in_kernel()) {
+ return icp_set_kvm_state(icp);
}
return 0;
.name = "icp/server",
.version_id = 1,
.minimum_version_id = 1,
- .pre_save = icp_dispatch_pre_save,
- .post_load = icp_dispatch_post_load,
+ .pre_save = icp_pre_save,
+ .post_load = icp_post_load,
.fields = (VMStateField[]) {
/* Sanity check */
VMSTATE_UINT32(xirr, ICPState),
},
};
-static void icp_reset(DeviceState *dev)
+static void icp_reset_handler(void *dev)
{
ICPState *icp = ICP(dev);
/* Make all outputs are deasserted */
qemu_set_irq(icp->output, 0);
-}
-static void icp_reset_handler(void *dev)
-{
- DeviceClass *dc = DEVICE_GET_CLASS(dev);
-
- dc->reset(dev);
+ if (kvm_irqchip_in_kernel()) {
+ icp_set_kvm_state(ICP(dev));
+ }
}
static void icp_realize(DeviceState *dev, Error **errp)
case PPC_FLAGS_INPUT_POWER7:
icp->output = env->irq_inputs[POWER7_INPUT_INT];
break;
+ case PPC_FLAGS_INPUT_POWER9: /* For SPAPR xics emulation */
+ icp->output = env->irq_inputs[POWER9_INPUT_INT];
+ break;
case PPC_FLAGS_INPUT_970:
icp->output = env->irq_inputs[PPC970_INPUT_INT];
return;
}
+ if (kvm_irqchip_in_kernel()) {
+ icp_kvm_realize(dev, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ }
+
qemu_register_reset(icp_reset_handler, dev);
vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp);
}
dc->realize = icp_realize;
dc->unrealize = icp_unrealize;
- dc->reset = icp_reset;
}
static const TypeInfo icp_info = {
{
ICSState *ics = (ICSState *)opaque;
+ if (kvm_irqchip_in_kernel()) {
+ ics_kvm_set_irq(ics, srcno, val);
+ return;
+ }
+
if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
ics_simple_set_irq_lsi(ics, srcno, val);
} else {
ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev);
icsc->parent_reset(dev);
+
+ if (kvm_irqchip_in_kernel()) {
+ ics_set_kvm_state(ICS_BASE(dev));
+ }
}
static void ics_simple_reset_handler(void *dev)
ics->offset = XICS_IRQ_BASE;
}
-static int ics_base_dispatch_pre_save(void *opaque)
+static int ics_base_pre_save(void *opaque)
{
ICSState *ics = opaque;
- ICSStateClass *info = ICS_BASE_GET_CLASS(ics);
- if (info->pre_save) {
- info->pre_save(ics);
+ if (kvm_irqchip_in_kernel()) {
+ ics_get_kvm_state(ics);
}
return 0;
}
-static int ics_base_dispatch_post_load(void *opaque, int version_id)
+static int ics_base_post_load(void *opaque, int version_id)
{
ICSState *ics = opaque;
- ICSStateClass *info = ICS_BASE_GET_CLASS(ics);
- if (info->post_load) {
- return info->post_load(ics, version_id);
+ if (kvm_irqchip_in_kernel()) {
+ return ics_set_kvm_state(ics);
}
return 0;
.name = "ics",
.version_id = 1,
.minimum_version_id = 1,
- .pre_save = ics_base_dispatch_pre_save,
- .post_load = ics_base_dispatch_post_load,
+ .pre_save = ics_base_pre_save,
+ .post_load = ics_base_post_load,
.fields = (VMStateField[]) {
/* Sanity check */
VMSTATE_UINT32_EQUAL(nr_irqs, ICSState, NULL),
ics->irqs[srcno].flags |=
lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI;
+
+ if (kvm_irqchip_in_kernel()) {
+ ics_set_kvm_state_one(ics, srcno);
+ }
}
static void xics_register_types(void)
/*
* ICP-KVM
*/
-static void icp_get_kvm_state(ICPState *icp)
+void icp_get_kvm_state(ICPState *icp)
{
uint64_t state;
int ret;
icp_get_kvm_state(arg.host_ptr);
}
-static void icp_synchronize_state(ICPState *icp)
+void icp_synchronize_state(ICPState *icp)
{
if (icp->cs) {
run_on_cpu(icp->cs, do_icp_synchronize_state, RUN_ON_CPU_HOST_PTR(icp));
}
}
-static int icp_set_kvm_state(ICPState *icp, int version_id)
+int icp_set_kvm_state(ICPState *icp)
{
uint64_t state;
int ret;
return 0;
}
-static void icp_kvm_reset(DeviceState *dev)
-{
- ICPStateClass *icpc = ICP_GET_CLASS(dev);
-
- icpc->parent_reset(dev);
-
- icp_set_kvm_state(ICP(dev), 1);
-}
-
-static void icp_kvm_realize(DeviceState *dev, Error **errp)
+void icp_kvm_realize(DeviceState *dev, Error **errp)
{
ICPState *icp = ICP(dev);
- ICPStateClass *icpc = ICP_GET_CLASS(icp);
- Error *local_err = NULL;
CPUState *cs;
KVMEnabledICP *enabled_icp;
unsigned long vcpu_id;
abort();
}
- icpc->parent_realize(dev, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
cs = icp->cs;
vcpu_id = kvm_arch_vcpu_id(cs);
QLIST_INSERT_HEAD(&kvm_enabled_icps, enabled_icp, node);
}
-static void icp_kvm_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- ICPStateClass *icpc = ICP_CLASS(klass);
-
- device_class_set_parent_realize(dc, icp_kvm_realize,
- &icpc->parent_realize);
- device_class_set_parent_reset(dc, icp_kvm_reset,
- &icpc->parent_reset);
-
- icpc->pre_save = icp_get_kvm_state;
- icpc->post_load = icp_set_kvm_state;
- icpc->synchronize_state = icp_synchronize_state;
-}
-
-static const TypeInfo icp_kvm_info = {
- .name = TYPE_KVM_ICP,
- .parent = TYPE_ICP,
- .instance_size = sizeof(ICPState),
- .class_init = icp_kvm_class_init,
- .class_size = sizeof(ICPStateClass),
-};
-
/*
* ICS-KVM
*/
-static void ics_get_kvm_state(ICSState *ics)
+void ics_get_kvm_state(ICSState *ics)
{
uint64_t state;
int i;
}
}
-static void ics_synchronize_state(ICSState *ics)
+void ics_synchronize_state(ICSState *ics)
{
ics_get_kvm_state(ics);
}
-static int ics_set_kvm_state(ICSState *ics, int version_id)
+int ics_set_kvm_state_one(ICSState *ics, int srcno)
{
uint64_t state;
- int i;
Error *local_err = NULL;
+ ICSIRQState *irq = &ics->irqs[srcno];
+ int ret;
- for (i = 0; i < ics->nr_irqs; i++) {
- ICSIRQState *irq = &ics->irqs[i];
- int ret;
-
- state = irq->server;
- state |= (uint64_t)(irq->saved_priority & KVM_XICS_PRIORITY_MASK)
- << KVM_XICS_PRIORITY_SHIFT;
- if (irq->priority != irq->saved_priority) {
- assert(irq->priority == 0xff);
- state |= KVM_XICS_MASKED;
- }
+ state = irq->server;
+ state |= (uint64_t)(irq->saved_priority & KVM_XICS_PRIORITY_MASK)
+ << KVM_XICS_PRIORITY_SHIFT;
+ if (irq->priority != irq->saved_priority) {
+ assert(irq->priority == 0xff);
+ state |= KVM_XICS_MASKED;
+ }
- if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
- state |= KVM_XICS_LEVEL_SENSITIVE;
- if (irq->status & XICS_STATUS_ASSERTED) {
- state |= KVM_XICS_PENDING;
- }
- } else {
- if (irq->status & XICS_STATUS_MASKED_PENDING) {
- state |= KVM_XICS_PENDING;
- }
+ if (irq->flags & XICS_FLAGS_IRQ_LSI) {
+ state |= KVM_XICS_LEVEL_SENSITIVE;
+ if (irq->status & XICS_STATUS_ASSERTED) {
+ state |= KVM_XICS_PENDING;
}
- if (irq->status & XICS_STATUS_PRESENTED) {
- state |= KVM_XICS_PRESENTED;
- }
- if (irq->status & XICS_STATUS_QUEUED) {
- state |= KVM_XICS_QUEUED;
+ } else {
+ if (irq->status & XICS_STATUS_MASKED_PENDING) {
+ state |= KVM_XICS_PENDING;
}
+ }
+ if (irq->status & XICS_STATUS_PRESENTED) {
+ state |= KVM_XICS_PRESENTED;
+ }
+ if (irq->status & XICS_STATUS_QUEUED) {
+ state |= KVM_XICS_QUEUED;
+ }
- ret = kvm_device_access(kernel_xics_fd, KVM_DEV_XICS_GRP_SOURCES,
- i + ics->offset, &state, true, &local_err);
- if (local_err) {
- error_report_err(local_err);
+ ret = kvm_device_access(kernel_xics_fd, KVM_DEV_XICS_GRP_SOURCES,
+ srcno + ics->offset, &state, true, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ return ret;
+ }
+
+ return 0;
+}
+
+int ics_set_kvm_state(ICSState *ics)
+{
+ int i;
+
+ for (i = 0; i < ics->nr_irqs; i++) {
+ int ret;
+
+ ret = ics_set_kvm_state_one(ics, i);
+ if (ret) {
return ret;
}
}
return 0;
}
-void ics_kvm_set_irq(void *opaque, int srcno, int val)
+void ics_kvm_set_irq(ICSState *ics, int srcno, int val)
{
- ICSState *ics = opaque;
struct kvm_irq_level args;
int rc;
}
}
-static void ics_kvm_reset(DeviceState *dev)
-{
- ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev);
-
- icsc->parent_reset(dev);
-
- ics_set_kvm_state(ICS_KVM(dev), 1);
-}
-
-static void ics_kvm_reset_handler(void *dev)
-{
- ics_kvm_reset(dev);
-}
-
-static void ics_kvm_realize(DeviceState *dev, Error **errp)
-{
- ICSState *ics = ICS_KVM(dev);
- ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics);
- Error *local_err = NULL;
-
- icsc->parent_realize(dev, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- qemu_register_reset(ics_kvm_reset_handler, ics);
-}
-
-static void ics_kvm_class_init(ObjectClass *klass, void *data)
-{
- ICSStateClass *icsc = ICS_BASE_CLASS(klass);
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- device_class_set_parent_realize(dc, ics_kvm_realize,
- &icsc->parent_realize);
- device_class_set_parent_reset(dc, ics_kvm_reset,
- &icsc->parent_reset);
-
- icsc->pre_save = ics_get_kvm_state;
- icsc->post_load = ics_set_kvm_state;
- icsc->synchronize_state = ics_synchronize_state;
-}
-
-static const TypeInfo ics_kvm_info = {
- .name = TYPE_ICS_KVM,
- .parent = TYPE_ICS_BASE,
- .instance_size = sizeof(ICSState),
- .class_init = ics_kvm_class_init,
-};
-
-/*
- * XICS-KVM
- */
-
static void rtas_dummy(PowerPCCPU *cpu, sPAPRMachineState *spapr,
uint32_t token,
uint32_t nargs, target_ulong args,
kvmppc_define_rtas_kernel_token(0, "ibm,int-off");
return -1;
}
-
-static void xics_kvm_register_types(void)
-{
- type_register_static(&ics_kvm_info);
- type_register_static(&icp_kvm_info);
-}
-
-type_init(xics_kvm_register_types)
};
int node;
- _FDT(node = fdt_add_subnode(fdt, 0, "interrupt-controller"));
+ _FDT(node = fdt_add_subnode(fdt, 0, XICS_NODENAME));
_FDT(fdt_setprop_string(fdt, node, "device_type",
"PowerPC-External-Interrupt-Presentation"));
env = &cpu->env;
switch (PPC_INPUT(env)) {
- case PPC_FLAGS_INPUT_POWER7:
- tctx->output = env->irq_inputs[POWER7_INPUT_INT];
+ case PPC_FLAGS_INPUT_POWER9:
+ tctx->output = env->irq_inputs[POWER9_INPUT_INT];
break;
default:
chr = parallel_hds[i];
if (chr == NULL) {
name = g_strdup_printf("discarding-parallel%d", i);
- chr = qemu_chr_new(name, "null");
+ chr = qemu_chr_new(name, "null", NULL);
} else {
name = g_strdup_printf("parallel%d", i);
}
chr = serial_hd(i);
if (chr == NULL) {
name = g_strdup_printf("discarding-serial%d", i);
- chr = qemu_chr_new(name, "null");
+ chr = qemu_chr_new(name, "null", NULL);
} else {
name = g_strdup_printf("serial%d", i);
}
# LM32 boards
-obj-y += lm32_boards.o
-obj-y += milkymist.o
+obj-$(CONFIG_LM32) += lm32_boards.o
+obj-$(CONFIG_MILKYMIST) += milkymist.o
uint64_t entry;
int kernel_size;
- kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
+ &entry, NULL, NULL,
1, EM_LATTICEMICO32, 0, 0);
reset_info->bootstrap_pc = entry;
uint64_t entry;
int kernel_size;
- kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
+ &entry, NULL, NULL,
1, EM_LATTICEMICO32, 0, 0);
reset_info->bootstrap_pc = entry;
uint64_t entry;
/* Boots a kernel elf binary. */
- kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
+ &entry, NULL, NULL,
1, EM_LATTICEMICO32, 0, 0);
reset_info->bootstrap_pc = entry;
-obj-y += an5206.o mcf5208.o
-obj-y += mcf5206.o mcf_intc.o
+obj-$(CONFIG_AN5206) += an5206.o mcf5206.o
+obj-$(CONFIG_MCF5208) += mcf5208.o mcf_intc.o
exit(1);
}
- kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
NULL, NULL, 1, EM_68K, 0, 0);
entry = elf_entry;
if (kernel_size < 0) {
exit(1);
}
- kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
NULL, NULL, 1, EM_68K, 0, 0);
entry = elf_entry;
if (kernel_size < 0) {
-obj-y += petalogix_s3adsp1800_mmu.o
-obj-y += petalogix_ml605_mmu.o
-obj-y += xlnx-zynqmp-pmu.o
+obj-$(CONFIG_PETALOGIX_S3ADSP1800) += petalogix_s3adsp1800_mmu.o
+obj-$(CONFIG_PETALOGIX_ML605) += petalogix_ml605_mmu.o
+obj-$(CONFIG_XLNX_ZYNQMP_PMU) += xlnx-zynqmp-pmu.o
obj-y += boot.o
#endif
/* Boots a kernel elf binary. */
- kernel_size = load_elf(kernel_filename, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&entry, &low, &high,
big_endian, EM_MICROBLAZE, 0, 0);
base32 = entry;
if (base32 == 0xc0000000) {
- kernel_size = load_elf(kernel_filename, translate_kernel_address,
- NULL, &entry, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, NULL,
+ translate_kernel_address, NULL,
+ &entry, NULL, NULL,
big_endian, EM_MICROBLAZE, 0, 0);
}
/* Always boot into physical ram. */
-obj-y += mips_r4k.o mips_malta.o mips_mipssim.o
obj-y += addr.o mips_int.o
+obj-$(CONFIG_R4K) += mips_r4k.o
+obj-$(CONFIG_MALTA) += gt64xxx_pci.o mips_malta.o
+obj-$(CONFIG_MIPSSIM) += mips_mipssim.o
obj-$(CONFIG_JAZZ) += mips_jazz.o
obj-$(CONFIG_FULONG) += mips_fulong2e.o
-obj-y += gt64xxx_pci.o
obj-$(CONFIG_MIPS_CPS) += cps.o
obj-$(CONFIG_MIPS_BOSTON) += boston.o
memory_region_init_io(lcd, NULL, &boston_lcd_ops, s, "boston-lcd", 0x8);
memory_region_add_subregion_overlap(sys_mem, 0x17fff000, lcd, 0);
- chr = qemu_chr_new("lcd", "vc:320x240");
+ chr = qemu_chr_new("lcd", "vc:320x240", NULL);
qemu_chr_fe_init(&s->lcd_display, chr, NULL);
qemu_chr_fe_set_handlers(&s->lcd_display, NULL, NULL,
boston_lcd_event, NULL, s, NULL, true);
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "qapi/error.h"
+#include "cpu.h"
#include "hw/hw.h"
#include "hw/i386/pc.h"
#include "hw/dma/i8257.h"
#include "audio/audio.h"
#include "qemu/log.h"
#include "hw/loader.h"
-#include "hw/mips/bios.h"
#include "hw/ide.h"
#include "elf.h"
#include "hw/isa/vt82c686.h"
#define ENVP_NB_ENTRIES 16
#define ENVP_ENTRY_SIZE 256
+/* fulong 2e has a 512k flash: Winbond W39L040AP70Z */
+#define BIOS_SIZE (512 * KiB)
#define MAX_IDE_BUS 2
/*
uint32_t *prom_buf;
long prom_size;
- kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
- NULL, (uint64_t *)&kernel_entry,
+ kernel_size = load_elf(loaderparams.kernel_filename, NULL,
+ cpu_mips_kseg0_to_phys, NULL,
+ (uint64_t *)&kernel_entry,
(uint64_t *)&kernel_low, (uint64_t *)&kernel_high,
0, EM_MIPS, 1, 0);
if (kernel_size < 0) {
}
}
-static const uint8_t eeprom_spd[0x80] = {
- 0x80,0x08,0x07,0x0d,0x09,0x02,0x40,0x00,0x04,0x70,
- 0x70,0x00,0x82,0x10,0x00,0x01,0x0e,0x04,0x0c,0x01,
- 0x02,0x20,0x80,0x75,0x70,0x00,0x00,0x50,0x3c,0x50,
- 0x2d,0x20,0xb0,0xb0,0x50,0x50,0x00,0x00,0x00,0x00,
- 0x00,0x41,0x48,0x3c,0x32,0x75,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x9c,0x7b,0x07,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x48,0x42,0x35,0x34,0x41,0x32,
- 0x35,0x36,0x38,0x4b,0x4e,0x2d,0x41,0x37,0x35,0x42,
- 0x20,0x30,0x20
-};
-
static void vt82c686b_southbridge_init(PCIBus *pci_bus, int slot, qemu_irq intc,
I2CBus **i2c_bus, ISABus **p_isa_bus)
{
static void mips_fulong2e_init(MachineState *machine)
{
- ram_addr_t ram_size = machine->ram_size;
const char *kernel_filename = machine->kernel_filename;
const char *kernel_cmdline = machine->kernel_cmdline;
const char *initrd_filename = machine->initrd_filename;
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *bios = g_new(MemoryRegion, 1);
+ ram_addr_t ram_size = machine->ram_size;
long bios_size;
+ uint8_t *spd_data;
+ Error *err = NULL;
int64_t kernel_entry;
PCIBus *pci_bus;
ISABus *isa_bus;
qemu_register_reset(main_cpu_reset, cpu);
- /* fulong 2e has 256M ram. */
+ /* TODO: support more than 256M RAM as highmem */
ram_size = 256 * MiB;
- /* fulong 2e has a 1M flash.Winbond W39L040AP70Z */
- bios_size = 1 * MiB;
-
/* allocate RAM */
memory_region_allocate_system_memory(ram, NULL, "fulong2e.ram", ram_size);
- memory_region_init_ram(bios, NULL, "fulong2e.bios", bios_size,
+ memory_region_init_ram(bios, NULL, "fulong2e.bios", BIOS_SIZE,
&error_fatal);
memory_region_set_readonly(bios, true);
vt82c686b_southbridge_init(pci_bus, FULONG2E_VIA_SLOT, env->irq[5],
&smbus, &isa_bus);
- /* TODO: Populate SPD eeprom data. */
- smbus_eeprom_init(smbus, 1, eeprom_spd, sizeof(eeprom_spd));
+ /* Populate SPD eeprom data */
+ spd_data = spd_data_generate(DDR, ram_size, &err);
+ if (err) {
+ warn_report_err(err);
+ }
+ if (spd_data) {
+ smbus_eeprom_init_one(smbus, 0x50, spd_data);
+ }
mc146818_rtc_init(isa_bus, 2000, NULL);
mc->init = mips_fulong2e_init;
mc->block_default_type = IF_IDE;
mc->default_cpu_type = MIPS_CPU_TYPE_NAME("Loongson-2E");
+ mc->default_ram_size = 256 * MiB;
}
DEFINE_MACHINE("fulong2e", mips_fulong2e_machine_init)
*/
#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
#include "hw/hw.h"
#include "hw/mips/cpudevs.h"
#include "cpu.h"
MIPSCPU *cpu = opaque;
CPUMIPSState *env = &cpu->env;
CPUState *cs = CPU(cpu);
+ bool locked = false;
if (irq < 0 || irq > 7)
return;
+ /* Make sure locking works even if BQL is already held by the caller */
+ if (!qemu_mutex_iothread_locked()) {
+ locked = true;
+ qemu_mutex_lock_iothread();
+ }
+
if (level) {
env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
} else {
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
}
+
+ if (locked) {
+ qemu_mutex_unlock_iothread();
+ }
}
void cpu_mips_irq_init_cpu(MIPSCPU *cpu)
memory_region_add_subregion(address_space, base, &s->iomem_lo);
memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
- chr = qemu_chr_new("fpga", "vc:320x200");
+ chr = qemu_chr_new("fpga", "vc:320x200", NULL);
qemu_chr_fe_init(&s->display, chr, NULL);
qemu_chr_fe_set_handlers(&s->display, NULL, NULL,
malta_fgpa_display_event, NULL, s, NULL, true);
big_endian = 0;
#endif
- kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
- NULL, (uint64_t *)&kernel_entry, NULL,
+ kernel_size = load_elf(loaderparams.kernel_filename, NULL,
+ cpu_mips_kseg0_to_phys, NULL,
+ (uint64_t *)&kernel_entry, NULL,
(uint64_t *)&kernel_high, big_endian, EM_MIPS, 1, 0);
if (kernel_size < 0) {
error_report("could not load kernel '%s': %s",
big_endian = 0;
#endif
- kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
- NULL, (uint64_t *)&entry, NULL,
+ kernel_size = load_elf(loaderparams.kernel_filename, NULL,
+ cpu_mips_kseg0_to_phys, NULL,
+ (uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, big_endian,
EM_MIPS, 1, 0);
if (kernel_size >= 0) {
#else
big_endian = 0;
#endif
- kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
- NULL, (uint64_t *)&entry, NULL,
+ kernel_size = load_elf(loaderparams.kernel_filename, NULL,
+ cpu_mips_kseg0_to_phys, NULL,
+ (uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, big_endian,
EM_MIPS, 1, 0);
if (kernel_size >= 0) {
obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o
obj-$(CONFIG_IOTKIT_SYSINFO) += iotkit-sysinfo.o
obj-$(CONFIG_ARMSSE_CPUID) += armsse-cpuid.o
+obj-$(CONFIG_ARMSSE_MHU) += armsse-mhu.o
obj-$(CONFIG_PVPANIC) += pvpanic.o
obj-$(CONFIG_AUX) += auxbus.o
--- /dev/null
+/*
+ * ARM SSE-200 Message Handling Unit (MHU)
+ *
+ * Copyright (c) 2019 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the Message Handling Unit (MHU) which is part of the
+ * Arm SSE-200 and documented in
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "qapi/error.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "hw/misc/armsse-mhu.h"
+
+REG32(CPU0INTR_STAT, 0x0)
+REG32(CPU0INTR_SET, 0x4)
+REG32(CPU0INTR_CLR, 0x8)
+REG32(CPU1INTR_STAT, 0x10)
+REG32(CPU1INTR_SET, 0x14)
+REG32(CPU1INTR_CLR, 0x18)
+REG32(PID4, 0xfd0)
+REG32(PID5, 0xfd4)
+REG32(PID6, 0xfd8)
+REG32(PID7, 0xfdc)
+REG32(PID0, 0xfe0)
+REG32(PID1, 0xfe4)
+REG32(PID2, 0xfe8)
+REG32(PID3, 0xfec)
+REG32(CID0, 0xff0)
+REG32(CID1, 0xff4)
+REG32(CID2, 0xff8)
+REG32(CID3, 0xffc)
+
+/* Valid bits in the interrupt registers. If any are set the IRQ is raised */
+#define INTR_MASK 0xf
+
+/* PID/CID values */
+static const int armsse_mhu_id[] = {
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
+ 0x56, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
+static void armsse_mhu_update(ARMSSEMHU *s)
+{
+ qemu_set_irq(s->cpu0irq, s->cpu0intr != 0);
+ qemu_set_irq(s->cpu1irq, s->cpu1intr != 0);
+}
+
+static uint64_t armsse_mhu_read(void *opaque, hwaddr offset, unsigned size)
+{
+ ARMSSEMHU *s = ARMSSE_MHU(opaque);
+ uint64_t r;
+
+ switch (offset) {
+ case A_CPU0INTR_STAT:
+ r = s->cpu0intr;
+ break;
+
+ case A_CPU1INTR_STAT:
+ r = s->cpu1intr;
+ break;
+
+ case A_PID4 ... A_CID3:
+ r = armsse_mhu_id[(offset - A_PID4) / 4];
+ break;
+
+ case A_CPU0INTR_SET:
+ case A_CPU0INTR_CLR:
+ case A_CPU1INTR_SET:
+ case A_CPU1INTR_CLR:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "SSE MHU: read of write-only register at offset 0x%x\n",
+ (int)offset);
+ r = 0;
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "SSE MHU read: bad offset 0x%x\n", (int)offset);
+ r = 0;
+ break;
+ }
+ trace_armsse_mhu_read(offset, r, size);
+ return r;
+}
+
+static void armsse_mhu_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ ARMSSEMHU *s = ARMSSE_MHU(opaque);
+
+ trace_armsse_mhu_write(offset, value, size);
+
+ switch (offset) {
+ case A_CPU0INTR_SET:
+ s->cpu0intr |= (value & INTR_MASK);
+ break;
+ case A_CPU0INTR_CLR:
+ s->cpu0intr &= ~(value & INTR_MASK);
+ break;
+ case A_CPU1INTR_SET:
+ s->cpu1intr |= (value & INTR_MASK);
+ break;
+ case A_CPU1INTR_CLR:
+ s->cpu1intr &= ~(value & INTR_MASK);
+ break;
+
+ case A_CPU0INTR_STAT:
+ case A_CPU1INTR_STAT:
+ case A_PID4 ... A_CID3:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "SSE MHU: write to read-only register at offset 0x%x\n",
+ (int)offset);
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "SSE MHU write: bad offset 0x%x\n", (int)offset);
+ break;
+ }
+
+ armsse_mhu_update(s);
+}
+
+static const MemoryRegionOps armsse_mhu_ops = {
+ .read = armsse_mhu_read,
+ .write = armsse_mhu_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+};
+
+static void armsse_mhu_reset(DeviceState *dev)
+{
+ ARMSSEMHU *s = ARMSSE_MHU(dev);
+
+ s->cpu0intr = 0;
+ s->cpu1intr = 0;
+}
+
+static const VMStateDescription armsse_mhu_vmstate = {
+ .name = "armsse-mhu",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(cpu0intr, ARMSSEMHU),
+ VMSTATE_UINT32(cpu1intr, ARMSSEMHU),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void armsse_mhu_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ ARMSSEMHU *s = ARMSSE_MHU(obj);
+
+ memory_region_init_io(&s->iomem, obj, &armsse_mhu_ops,
+ s, "armsse-mhu", 0x1000);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->cpu0irq);
+ sysbus_init_irq(sbd, &s->cpu1irq);
+}
+
+static void armsse_mhu_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = armsse_mhu_reset;
+ dc->vmsd = &armsse_mhu_vmstate;
+}
+
+static const TypeInfo armsse_mhu_info = {
+ .name = TYPE_ARMSSE_MHU,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(ARMSSEMHU),
+ .instance_init = armsse_mhu_init,
+ .class_init = armsse_mhu_class_init,
+};
+
+static void armsse_mhu_register_types(void)
+{
+ type_register_static(&armsse_mhu_info);
+}
+
+type_init(armsse_mhu_register_types);
*/
#include "qemu/osdep.h"
+#include "qemu/bitops.h"
#include "qemu/log.h"
#include "trace.h"
#include "qapi/error.h"
#include "hw/sysbus.h"
#include "hw/registerfields.h"
#include "hw/misc/iotkit-sysctl.h"
+#include "target/arm/arm-powerctl.h"
+#include "target/arm/cpu.h"
REG32(SECDBGSTAT, 0x0)
REG32(SECDBGSET, 0x4)
REG32(SECDBGCLR, 0x8)
+REG32(SCSECCTRL, 0xc)
+REG32(FCLK_DIV, 0x10)
+REG32(SYSCLK_DIV, 0x14)
+REG32(CLOCK_FORCE, 0x18)
REG32(RESET_SYNDROME, 0x100)
REG32(RESET_MASK, 0x104)
REG32(SWRESET, 0x108)
FIELD(SWRESET, SWRESETREQ, 9, 1)
REG32(GRETREG, 0x10c)
-REG32(INITSVRTOR0, 0x110)
+REG32(INITSVTOR0, 0x110)
+REG32(INITSVTOR1, 0x114)
REG32(CPUWAIT, 0x118)
-REG32(BUSWAIT, 0x11c)
+REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
REG32(WICCTRL, 0x120)
+REG32(EWCTRL, 0x124)
+REG32(PDCM_PD_SYS_SENSE, 0x200)
+REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
+REG32(PDCM_PD_SRAM1_SENSE, 0x210)
+REG32(PDCM_PD_SRAM2_SENSE, 0x214)
+REG32(PDCM_PD_SRAM3_SENSE, 0x218)
REG32(PID4, 0xfd0)
REG32(PID5, 0xfd4)
REG32(PID6, 0xfd8)
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
};
+/*
+ * Set the initial secure vector table offset address for the core.
+ * This will take effect when the CPU next resets.
+ */
+static void set_init_vtor(uint64_t cpuid, uint32_t vtor)
+{
+ Object *cpuobj = OBJECT(arm_get_cpu_by_id(cpuid));
+
+ if (cpuobj) {
+ if (object_property_find(cpuobj, "init-svtor", NULL)) {
+ object_property_set_uint(cpuobj, vtor, "init-svtor", &error_abort);
+ }
+ }
+}
+
static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
unsigned size)
{
case A_SECDBGSTAT:
r = s->secure_debug;
break;
+ case A_SCSECCTRL:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->scsecctrl;
+ break;
+ case A_FCLK_DIV:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->fclk_div;
+ break;
+ case A_SYSCLK_DIV:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->sysclk_div;
+ break;
+ case A_CLOCK_FORCE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->clock_force;
+ break;
case A_RESET_SYNDROME:
r = s->reset_syndrome;
break;
case A_GRETREG:
r = s->gretreg;
break;
- case A_INITSVRTOR0:
- r = s->initsvrtor0;
+ case A_INITSVTOR0:
+ r = s->initsvtor0;
+ break;
+ case A_INITSVTOR1:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->initsvtor1;
break;
case A_CPUWAIT:
r = s->cpuwait;
break;
- case A_BUSWAIT:
- /* In IoTKit BUSWAIT is reserved, R/O, zero */
- r = 0;
+ case A_NMI_ENABLE:
+ /* In IoTKit this is named BUSWAIT but is marked reserved, R/O, zero */
+ if (!s->is_sse200) {
+ r = 0;
+ break;
+ }
+ r = s->nmi_enable;
break;
case A_WICCTRL:
r = s->wicctrl;
break;
+ case A_EWCTRL:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->ewctrl;
+ break;
+ case A_PDCM_PD_SYS_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->pdcm_pd_sys_sense;
+ break;
+ case A_PDCM_PD_SRAM0_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->pdcm_pd_sram0_sense;
+ break;
+ case A_PDCM_PD_SRAM1_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->pdcm_pd_sram1_sense;
+ break;
+ case A_PDCM_PD_SRAM2_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->pdcm_pd_sram2_sense;
+ break;
+ case A_PDCM_PD_SRAM3_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->pdcm_pd_sram3_sense;
+ break;
case A_PID4 ... A_CID3:
r = sysctl_id[(offset - A_PID4) / 4];
break;
r = 0;
break;
default:
+ bad_offset:
qemu_log_mask(LOG_GUEST_ERROR,
"IoTKit SysCtl read: bad offset %x\n", (int)offset);
r = 0;
*/
s->gretreg = value;
break;
- case A_INITSVRTOR0:
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl INITSVRTOR0 unimplemented\n");
- s->initsvrtor0 = value;
+ case A_INITSVTOR0:
+ s->initsvtor0 = value;
+ set_init_vtor(0, s->initsvtor0);
break;
case A_CPUWAIT:
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CPUWAIT unimplemented\n");
+ if ((s->cpuwait & 1) && !(value & 1)) {
+ /* Powering up CPU 0 */
+ arm_set_cpu_on_and_reset(0);
+ }
+ if ((s->cpuwait & 2) && !(value & 2)) {
+ /* Powering up CPU 1 */
+ arm_set_cpu_on_and_reset(1);
+ }
s->cpuwait = value;
break;
case A_WICCTRL:
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
}
break;
- case A_BUSWAIT: /* In IoTKit BUSWAIT is reserved, R/O, zero */
+ case A_SCSECCTRL:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
+ s->scsecctrl = value;
+ break;
+ case A_FCLK_DIV:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
+ s->fclk_div = value;
+ break;
+ case A_SYSCLK_DIV:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
+ s->sysclk_div = value;
+ break;
+ case A_CLOCK_FORCE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
+ s->clock_force = value;
+ break;
+ case A_INITSVTOR1:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ s->initsvtor1 = value;
+ set_init_vtor(1, s->initsvtor1);
+ break;
+ case A_EWCTRL:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
+ s->ewctrl = value;
+ break;
+ case A_PDCM_PD_SYS_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
+ s->pdcm_pd_sys_sense = value;
+ break;
+ case A_PDCM_PD_SRAM0_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
+ s->pdcm_pd_sram0_sense = value;
+ break;
+ case A_PDCM_PD_SRAM1_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
+ s->pdcm_pd_sram1_sense = value;
+ break;
+ case A_PDCM_PD_SRAM2_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
+ s->pdcm_pd_sram2_sense = value;
+ break;
+ case A_PDCM_PD_SRAM3_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
+ s->pdcm_pd_sram3_sense = value;
+ break;
+ case A_NMI_ENABLE:
+ /* In IoTKit this is BUSWAIT: reserved, R/O, zero */
+ if (!s->is_sse200) {
+ goto ro_offset;
+ }
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
+ s->nmi_enable = value;
+ break;
case A_SECDBGSTAT:
case A_PID4 ... A_CID3:
+ ro_offset:
qemu_log_mask(LOG_GUEST_ERROR,
"IoTKit SysCtl write: write of RO offset %x\n",
(int)offset);
break;
default:
+ bad_offset:
qemu_log_mask(LOG_GUEST_ERROR,
"IoTKit SysCtl write: bad offset %x\n", (int)offset);
break;
s->reset_syndrome = 1;
s->reset_mask = 0;
s->gretreg = 0;
- s->initsvrtor0 = 0x10000000;
- s->cpuwait = 0;
+ s->initsvtor0 = s->initsvtor0_rst;
+ s->initsvtor1 = s->initsvtor1_rst;
+ s->cpuwait = s->cpuwait_rst;
s->wicctrl = 0;
+ s->scsecctrl = 0;
+ s->fclk_div = 0;
+ s->sysclk_div = 0;
+ s->clock_force = 0;
+ s->nmi_enable = 0;
+ s->ewctrl = 0;
+ s->pdcm_pd_sys_sense = 0x7f;
+ s->pdcm_pd_sram0_sense = 0;
+ s->pdcm_pd_sram1_sense = 0;
+ s->pdcm_pd_sram2_sense = 0;
+ s->pdcm_pd_sram3_sense = 0;
}
static void iotkit_sysctl_init(Object *obj)
sysbus_init_mmio(sbd, &s->iomem);
}
+static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
+{
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
+
+ /* The top 4 bits of the SYS_VERSION register tell us if we're an SSE-200 */
+ if (extract32(s->sys_version, 28, 4) == 2) {
+ s->is_sse200 = true;
+ }
+}
+
+static bool sse200_needed(void *opaque)
+{
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
+
+ return s->is_sse200;
+}
+
+static const VMStateDescription iotkit_sysctl_sse200_vmstate = {
+ .name = "iotkit-sysctl/sse-200",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = sse200_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(scsecctrl, IoTKitSysCtl),
+ VMSTATE_UINT32(fclk_div, IoTKitSysCtl),
+ VMSTATE_UINT32(sysclk_div, IoTKitSysCtl),
+ VMSTATE_UINT32(clock_force, IoTKitSysCtl),
+ VMSTATE_UINT32(initsvtor1, IoTKitSysCtl),
+ VMSTATE_UINT32(nmi_enable, IoTKitSysCtl),
+ VMSTATE_UINT32(pdcm_pd_sys_sense, IoTKitSysCtl),
+ VMSTATE_UINT32(pdcm_pd_sram0_sense, IoTKitSysCtl),
+ VMSTATE_UINT32(pdcm_pd_sram1_sense, IoTKitSysCtl),
+ VMSTATE_UINT32(pdcm_pd_sram2_sense, IoTKitSysCtl),
+ VMSTATE_UINT32(pdcm_pd_sram3_sense, IoTKitSysCtl),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription iotkit_sysctl_vmstate = {
.name = "iotkit-sysctl",
.version_id = 1,
VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl),
VMSTATE_UINT32(reset_mask, IoTKitSysCtl),
VMSTATE_UINT32(gretreg, IoTKitSysCtl),
- VMSTATE_UINT32(initsvrtor0, IoTKitSysCtl),
+ VMSTATE_UINT32(initsvtor0, IoTKitSysCtl),
VMSTATE_UINT32(cpuwait, IoTKitSysCtl),
VMSTATE_UINT32(wicctrl, IoTKitSysCtl),
VMSTATE_END_OF_LIST()
+ },
+ .subsections = (const VMStateDescription*[]) {
+ &iotkit_sysctl_sse200_vmstate,
+ NULL
}
};
+static Property iotkit_sysctl_props[] = {
+ DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysCtl, sys_version, 0),
+ DEFINE_PROP_UINT32("CPUWAIT_RST", IoTKitSysCtl, cpuwait_rst, 0),
+ DEFINE_PROP_UINT32("INITSVTOR0_RST", IoTKitSysCtl, initsvtor0_rst,
+ 0x10000000),
+ DEFINE_PROP_UINT32("INITSVTOR1_RST", IoTKitSysCtl, initsvtor1_rst,
+ 0x10000000),
+ DEFINE_PROP_END_OF_LIST()
+};
+
static void iotkit_sysctl_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &iotkit_sysctl_vmstate;
dc->reset = iotkit_sysctl_reset;
+ dc->props = iotkit_sysctl_props;
+ dc->realize = iotkit_sysctl_realize;
}
static const TypeInfo iotkit_sysctl_info = {
static void cuda_delay_set_sr_int(CUDAState *s)
{
- MOS6522CUDAState *mcs = &s->mos6522_cuda;
- MOS6522State *ms = MOS6522(mcs);
- MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms);
int64_t expire;
- if (ms->dirb == 0xff || s->sr_delay_ns == 0) {
- /* Disabled or not in Mac OS, fire the IRQ directly */
- mdc->set_sr_int(ms);
- return;
- }
-
trace_cuda_delay_set_sr_int();
expire = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->sr_delay_ns;
s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
s->sr_delay_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_set_sr_int, s);
- s->sr_delay_ns = 300 * SCALE_US;
+ s->sr_delay_ns = 20 * SCALE_US;
s->adb_poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_adb_poll, s);
s->adb_poll_mask = 0xffff;
return (1ULL << cpc->num_vp) - 1;
}
+static void mips_cpu_reset_async_work(CPUState *cs, run_on_cpu_data data)
+{
+ MIPSCPCState *cpc = (MIPSCPCState *) data.host_ptr;
+
+ cpu_reset(cs);
+ cpc->vp_running |= 1ULL << cs->cpu_index;
+}
+
static void cpc_run_vp(MIPSCPCState *cpc, uint64_t vp_run)
{
CPUState *cs = first_cpu;
CPU_FOREACH(cs) {
uint64_t i = 1ULL << cs->cpu_index;
if (i & vp_run & ~cpc->vp_running) {
- cpu_reset(cs);
- cpc->vp_running |= i;
+ /*
+ * To avoid racing with a CPU we are just kicking off.
+ * We do the final bit of preparation for the work in
+ * the target CPUs context.
+ */
+ async_safe_run_on_cpu(cs, mips_cpu_reset_async_work,
+ RUN_ON_CPU_HOST_PTR(cpc));
}
}
}
if (tag->saar_present) {
address = ((*(uint64_t *) tag->saar) & 0xFFFFFFFFE000ULL) << 4;
- size = 1 << ((*(uint64_t *) tag->saar >> 1) & 0x1f);
+ size = 1ULL << ((*(uint64_t *) tag->saar >> 1) & 0x1f);
is_enabled = *(uint64_t *) tag->saar & 1;
}
# hw/misc/armsse-cpuid.c
armsse_cpuid_read(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
armsse_cpuid_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+
+# hw/misc/armsse-mhu.c
+armsse_mhu_read(uint64_t offset, uint64_t data, unsigned size) "SSE-200 MHU read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+armsse_mhu_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 MHU write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
.endianness = DEVICE_LITTLE_ENDIAN,
};
+static bool tz_ppc_dummy_accepts(void *opaque, hwaddr addr,
+ unsigned size, bool is_write,
+ MemTxAttrs attrs)
+{
+ /*
+ * Board code should never map the upstream end of an unused port,
+ * so we should never try to make a memory access to it.
+ */
+ g_assert_not_reached();
+}
+
+static const MemoryRegionOps tz_ppc_dummy_ops = {
+ .valid.accepts = tz_ppc_dummy_accepts,
+};
+
static void tz_ppc_reset(DeviceState *dev)
{
TZPPC *s = TZ_PPC(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
TZPPC *s = TZ_PPC(dev);
int i;
+ int max_port = 0;
/* We can't create the upstream end of the port until realize,
* as we don't know the size of the MR used as the downstream until then.
*/
for (i = 0; i < TZ_NUM_PORTS; i++) {
+ if (s->port[i].downstream) {
+ max_port = i;
+ }
+ }
+
+ for (i = 0; i <= max_port; i++) {
TZPPCPort *port = &s->port[i];
char *name;
uint64_t size;
if (!port->downstream) {
+ /*
+ * Create dummy sysbus MMIO region so the sysbus region
+ * numbering doesn't get out of sync with the port numbers.
+ * The size is entirely arbitrary.
+ */
+ name = g_strdup_printf("tz-ppc-dummy-port[%d]", i);
+ memory_region_init_io(&port->upstream, obj, &tz_ppc_dummy_ops,
+ port, name, 0x10000);
+ sysbus_init_mmio(sbd, &port->upstream);
+ g_free(name);
continue;
}
# moxie boards
-obj-y += moxiesim.o
+obj-$(CONFIG_MOXIESIM) += moxiesim.o
long kernel_size;
ram_addr_t initrd_offset;
- kernel_size = load_elf(loader_params->kernel_filename, NULL, NULL,
+ kernel_size = load_elf(loader_params->kernel_filename, NULL, NULL, NULL,
&entry, &kernel_low, &kernel_high, 1, EM_MOXIE,
0, 0);
common-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
common-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
common-obj-$(CONFIG_E1000_PCI) += e1000.o e1000x_common.o
-common-obj-$(CONFIG_E1000E_PCI) += net_tx_pkt.o net_rx_pkt.o
-common-obj-$(CONFIG_E1000E_PCI) += e1000e.o e1000e_core.o e1000x_common.o
+common-obj-$(CONFIG_E1000E_PCI_EXPRESS) += net_tx_pkt.o net_rx_pkt.o
+common-obj-$(CONFIG_E1000E_PCI_EXPRESS) += e1000e.o e1000e_core.o e1000x_common.o
common-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
common-obj-$(CONFIG_VMXNET3_PCI) += net_tx_pkt.o net_rx_pkt.o
common-obj-$(CONFIG_VMXNET3_PCI) += vmxnet3.o
#endif
-/*
- * Calculate the number of bytes up to and including the given 'field' of
- * 'container'.
- */
-#define endof(container, field) \
- (offsetof(container, field) + sizeof_field(container, field))
-
-typedef struct VirtIOFeature {
- uint64_t flags;
- size_t end;
-} VirtIOFeature;
-
static VirtIOFeature feature_sizes[] = {
{.flags = 1ULL << VIRTIO_NET_F_MAC,
- .end = endof(struct virtio_net_config, mac)},
+ .end = virtio_endof(struct virtio_net_config, mac)},
{.flags = 1ULL << VIRTIO_NET_F_STATUS,
- .end = endof(struct virtio_net_config, status)},
+ .end = virtio_endof(struct virtio_net_config, status)},
{.flags = 1ULL << VIRTIO_NET_F_MQ,
- .end = endof(struct virtio_net_config, max_virtqueue_pairs)},
+ .end = virtio_endof(struct virtio_net_config, max_virtqueue_pairs)},
{.flags = 1ULL << VIRTIO_NET_F_MTU,
- .end = endof(struct virtio_net_config, mtu)},
+ .end = virtio_endof(struct virtio_net_config, mtu)},
{.flags = 1ULL << VIRTIO_NET_F_SPEED_DUPLEX,
- .end = endof(struct virtio_net_config, duplex)},
+ .end = virtio_endof(struct virtio_net_config, duplex)},
{}
};
static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features)
{
- int i, config_size = 0;
virtio_add_feature(&host_features, VIRTIO_NET_F_MAC);
- for (i = 0; feature_sizes[i].flags != 0; i++) {
- if (host_features & feature_sizes[i].flags) {
- config_size = MAX(feature_sizes[i].end, config_size);
- }
- }
- n->config_size = config_size;
+ n->config_size = virtio_feature_get_config_size(feature_sizes,
+ host_features);
}
void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
-obj-y = boot.o cpu_pic.o 10m50_devboard.o
+obj-y = boot.o cpu_pic.o
+obj-$(CONFIG_NIOS2_10M50) += 10m50_devboard.o
#endif
/* Boots a kernel elf binary. */
- kernel_size = load_elf(kernel_filename, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&entry, &low, &high,
big_endian, EM_ALTERA_NIOS2, 0, 0);
base32 = entry;
if (base32 == 0xc0000000) {
- kernel_size = load_elf(kernel_filename, translate_kernel_address,
- NULL, &entry, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, NULL,
+ translate_kernel_address, NULL,
+ &entry, NULL, NULL,
big_endian, EM_ALTERA_NIOS2, 0, 0);
}
{
const char *boot_splash_filename = NULL;
const char *boot_splash_time = NULL;
- uint8_t qemu_extra_params_fw[2];
char *filename, *file_data;
gsize file_size;
int file_type;
/* insert splash time if user configurated */
if (boot_splash_time) {
int64_t bst_val = qemu_opt_get_number(opts, "splash-time", -1);
+ uint16_t bst_le16;
+
/* validate the input */
if (bst_val < 0 || bst_val > 0xffff) {
error_report("splash-time is invalid,"
exit(1);
}
/* use little endian format */
- qemu_extra_params_fw[0] = (uint8_t)(bst_val & 0xff);
- qemu_extra_params_fw[1] = (uint8_t)((bst_val >> 8) & 0xff);
- fw_cfg_add_file(s, "etc/boot-menu-wait", qemu_extra_params_fw, 2);
+ bst_le16 = cpu_to_le16(bst_val);
+ fw_cfg_add_file(s, "etc/boot-menu-wait",
+ g_memdup(&bst_le16, sizeof bst_le16), sizeof bst_le16);
}
/* insert splash file if user configurated */
obj-y = pic_cpu.o cputimer.o
-obj-y += openrisc_sim.o
+obj-$(CONFIG_OR1K_SIM) += openrisc_sim.o
hwaddr entry;
if (kernel_filename && !qtest_enabled()) {
- kernel_size = load_elf(kernel_filename, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&elf_entry, NULL, NULL, 1, EM_OPENRISC,
1, 0);
entry = elf_entry;
-common-obj-y += pam.o
+common-obj-$(CONFIG_PAM) += pam.o
# PPC devices
common-obj-$(CONFIG_PREP_PCI) += prep.o
common-obj-$(CONFIG_PCI_SABRE) += sabre.o
common-obj-$(CONFIG_FULONG) += bonito.o
common-obj-$(CONFIG_PCI_PIIX) += piix.o
-common-obj-$(CONFIG_PCI_Q35) += q35.o
-common-obj-$(CONFIG_PCI_GENERIC) += gpex.o
-common-obj-$(CONFIG_PCI_XILINX) += xilinx-pcie.o
+common-obj-$(CONFIG_PCI_EXPRESS_Q35) += q35.o
+common-obj-$(CONFIG_PCI_EXPRESS_GENERIC_BRIDGE) += gpex.o
+common-obj-$(CONFIG_PCI_EXPRESS_XILINX) += xilinx-pcie.o
-common-obj-$(CONFIG_PCI_DESIGNWARE) += designware.o
+common-obj-$(CONFIG_PCI_EXPRESS_DESIGNWARE) += designware.o
PCIHostState parent_obj;
qemu_irq *pic;
PCIBonitoState *pci_dev;
+ MemoryRegion pci_mem;
};
#define TYPE_BONITO_PCI_HOST_BRIDGE "Bonito-pcihost"
static void bonito_pcihost_realize(DeviceState *dev, Error **errp)
{
PCIHostState *phb = PCI_HOST_BRIDGE(dev);
+ BonitoState *bs = BONITO_PCI_HOST_BRIDGE(dev);
+ memory_region_init(&bs->pci_mem, OBJECT(dev), "pci.mem", BONITO_PCILO_SIZE);
phb->bus = pci_register_root_bus(DEVICE(dev), "pci",
pci_bonito_set_irq, pci_bonito_map_irq,
- dev, get_system_memory(), get_system_io(),
+ dev, &bs->pci_mem, get_system_io(),
0x28, 32, TYPE_PCI_BUS);
+ memory_region_add_subregion(get_system_memory(), BONITO_PCILO_BASE,
+ &bs->pci_mem);
}
static void bonito_realize(PCIDevice *dev, Error **errp)
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, s->bios_name);
if (filename) {
if (s->elf_machine != EM_NONE) {
- bios_size = load_elf(filename, NULL, NULL, NULL,
+ bios_size = load_elf(filename, NULL, NULL, NULL, NULL,
NULL, NULL, 1, s->elf_machine, 0, 0);
}
if (bios_size < 0) {
MSI_DEV_PRINTF(dev, "reset\n");
}
-static bool msi_is_masked(const PCIDevice *dev, unsigned int vector)
+bool msi_is_masked(const PCIDevice *dev, unsigned int vector)
{
uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
uint32_t mask, data;
dev->exp.hpev_notified = false;
qbus_set_hotplug_handler(BUS(pci_bridge_get_sec_bus(PCI_BRIDGE(dev))),
- DEVICE(dev), NULL);
+ OBJECT(dev), NULL);
}
void pcie_cap_slot_reset(PCIDevice *dev)
shpc_cap_update_dword(d);
memory_region_add_subregion(bar, offset, &shpc->mmio);
- qbus_set_hotplug_handler(BUS(sec_bus), DEVICE(d), NULL);
+ qbus_set_hotplug_handler(BUS(sec_bus), OBJECT(d), NULL);
d->cap_present |= QEMU_PCI_CAP_SHPC;
return 0;
endif
obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
# PowerPC 4xx boards
-obj-$(CONFIG_PPC4XX) += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
-obj-$(CONFIG_PPC4XX) += ppc440_bamboo.o ppc440_pcix.o ppc440_uc.o
+obj-$(CONFIG_PPC405) += ppc405_boards.o ppc405_uc.o
+obj-$(CONFIG_PPC440) += ppc440_bamboo.o ppc440_pcix.o ppc440_uc.o
+obj-$(CONFIG_PPC4XX) += ppc4xx_pci.o ppc4xx_devs.o
obj-$(CONFIG_SAM460EX) += sam460ex.o
# PReP
obj-$(CONFIG_PREP) += prep.o
obj-$(CONFIG_PREP) += prep_systemio.o
obj-${CONFIG_RS6000_MC} += rs6000_mc.o
# OldWorld PowerMac
-obj-$(CONFIG_MAC) += mac_oldworld.o
+obj-$(CONFIG_MAC_OLDWORLD) += mac_oldworld.o
# NewWorld PowerMac
-obj-$(CONFIG_MAC) += mac_newworld.o
+obj-$(CONFIG_MAC_NEWWORLD) += mac_newworld.o
# e500
obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o
obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o
# PowerPC 440 Xilinx ML507 reference board.
-obj-$(CONFIG_XILINX) += virtex_ml507.o
+obj-$(CONFIG_VIRTEX) += virtex_ml507.o
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, payload_name);
- payload_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL,
+ payload_size = load_elf(filename, NULL, NULL, NULL,
+ &bios_entry, &loadaddr, NULL,
1, PPC_ELF_MACHINE, 0, 0);
if (payload_size < 0) {
/*
/* Load OpenBIOS (ELF) */
if (filename) {
- bios_size = load_elf(filename, NULL, NULL, NULL,
+ bios_size = load_elf(filename, NULL, NULL, NULL, NULL,
NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0);
g_free(filename);
#endif
kernel_base = KERNEL_LOAD_ADDR;
- kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+ kernel_size = load_elf(kernel_filename, NULL,
+ translate_kernel_address, NULL,
NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
0, 0);
if (kernel_size < 0)
}
for (i = 0; i < nb_nics; i++) {
- pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL);
+ pci_nic_init_nofail(&nd_table[i], pci_bus, "sungem", NULL);
}
/* The NewWorld NVRAM is not located in the MacIO device */
/* Load OpenBIOS (ELF) */
if (filename) {
- bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
+ bios_size = load_elf(filename, NULL, 0, NULL, NULL, NULL, NULL,
1, PPC_ELF_MACHINE, 0, 0);
g_free(filename);
} else {
bswap_needed = 0;
#endif
kernel_base = KERNEL_LOAD_ADDR;
- kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+ kernel_size = load_elf(kernel_filename, NULL,
+ translate_kernel_address, NULL,
NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
0, 0);
if (kernel_size < 0)
#include <libfdt.h>
-#define FDT_MAX_SIZE 0x00100000
+#define FDT_MAX_SIZE (1 * MiB)
#define FW_FILE_NAME "skiboot.lid"
#define FW_LOAD_ADDR 0x0
-#define FW_MAX_SIZE 0x00400000
+#define FW_MAX_SIZE (4 * MiB)
#define KERNEL_LOAD_ADDR 0x20000000
+#define KERNEL_MAX_SIZE (256 * MiB)
#define INITRD_LOAD_ADDR 0x60000000
+#define INITRD_MAX_SIZE (256 * MiB)
static const char *pnv_chip_core_typename(const PnvChip *o)
{
long kernel_size;
kernel_size = load_image_targphys(machine->kernel_filename,
- KERNEL_LOAD_ADDR, 0x2000000);
+ KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
if (kernel_size < 0) {
error_report("Could not load kernel '%s'",
machine->kernel_filename);
if (machine->initrd_filename) {
pnv->initrd_base = INITRD_LOAD_ADDR;
pnv->initrd_size = load_image_targphys(machine->initrd_filename,
- pnv->initrd_base, 0x10000000); /* 128MB max */
+ pnv->initrd_base, INITRD_MAX_SIZE);
if (pnv->initrd_size < 0) {
error_report("Could not load initial ram disk '%s'",
machine->initrd_filename);
{
Pnv8Chip *chip8 = PNV8_CHIP(obj);
- object_initialize(&chip8->psi, sizeof(chip8->psi), TYPE_PNV_PSI);
- object_property_add_child(obj, "psi", OBJECT(&chip8->psi), NULL);
+ object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi),
+ TYPE_PNV_PSI, &error_abort, NULL);
object_property_add_const_link(OBJECT(&chip8->psi), "xics",
OBJECT(qdev_get_machine()), &error_abort);
- object_initialize(&chip8->lpc, sizeof(chip8->lpc), TYPE_PNV_LPC);
- object_property_add_child(obj, "lpc", OBJECT(&chip8->lpc), NULL);
+ object_initialize_child(obj, "lpc", &chip8->lpc, sizeof(chip8->lpc),
+ TYPE_PNV_LPC, &error_abort, NULL);
object_property_add_const_link(OBJECT(&chip8->lpc), "psi",
OBJECT(&chip8->psi), &error_abort);
- object_initialize(&chip8->occ, sizeof(chip8->occ), TYPE_PNV_OCC);
- object_property_add_child(obj, "occ", OBJECT(&chip8->occ), NULL);
+ object_initialize_child(obj, "occ", &chip8->occ, sizeof(chip8->occ),
+ TYPE_PNV_OCC, &error_abort, NULL);
object_property_add_const_link(OBJECT(&chip8->occ), "psi",
OBJECT(&chip8->psi), &error_abort);
}
{
PnvPsi *psi = PNV_PSI(obj);
- object_initialize(&psi->ics, sizeof(psi->ics), TYPE_ICS_SIMPLE);
- object_property_add_child(obj, "ics-psi", OBJECT(&psi->ics), NULL);
+ object_initialize_child(obj, "ics-psi", &psi->ics, sizeof(psi->ics),
+ TYPE_ICS_SIMPLE, &error_abort, NULL);
}
static const uint8_t irq_to_xivr[] = {
env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu,
POWER7_INPUT_NB);
}
+
+/* POWER9 internal IRQ controller */
+static void power9_set_irq(void *opaque, int pin, int level)
+{
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
+
+ LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
+ env, pin, level);
+
+ switch (pin) {
+ case POWER9_INPUT_INT:
+ /* Level sensitive - active high */
+ LOG_IRQ("%s: set the external IRQ state to %d\n",
+ __func__, level);
+ ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
+ break;
+ case POWER9_INPUT_HINT:
+ /* Level sensitive - active high */
+ LOG_IRQ("%s: set the external IRQ state to %d\n",
+ __func__, level);
+ ppc_set_irq(cpu, PPC_INTERRUPT_HVIRT, level);
+ break;
+ default:
+ /* Unknown pin - do nothing */
+ LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
+ return;
+ }
+ if (level) {
+ env->irq_input_state |= 1 << pin;
+ } else {
+ env->irq_input_state &= ~(1 << pin);
+ }
+}
+
+void ppcPOWER9_irq_init(PowerPCCPU *cpu)
+{
+ CPUPPCState *env = &cpu->env;
+
+ env->irq_inputs = (void **)qemu_allocate_irqs(&power9_set_irq, cpu,
+ POWER9_INPUT_NB);
+}
#endif /* defined(TARGET_PPC64) */
void ppc40x_core_reset(PowerPCCPU *cpu)
* interrupts in a PM state. Not only they don't cause a
* wakeup but they also get effectively discarded.
*/
- if (!env->in_pm_state) {
+ if (!env->resume_as_sreset) {
ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
}
}
success = load_uimage(kernel_filename, &entry, &loadaddr, NULL,
NULL, NULL);
if (success < 0) {
- success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ success = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
&elf_lowaddr, NULL, 1, PPC_ELF_MACHINE,
0, 0);
entry = elf_entry;
#include "cpu.h"
#include "hw/hw.h"
#include "hw/timer/m48t59.h"
-#include "hw/i386/pc.h"
#include "hw/char/serial.h"
#include "hw/block/fdc.h"
#include "net/net.h"
if (success < 0) {
uint64_t elf_entry, elf_lowaddr;
- success = load_elf(machine->kernel_filename, NULL, NULL, &elf_entry,
+ success = load_elf(machine->kernel_filename, NULL,
+ NULL, NULL, &elf_entry,
&elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, 0);
entry = elf_entry;
loadaddr = elf_lowaddr;
#define MIN_RMA_SLOF 128UL
-#define PHANDLE_XICP 0x00001111
+#define PHANDLE_INTC 0x00001111
/* These two functions implement the VCPU id numbering: one to compute them
* all and one to identify thread 0 of a VCORE. Any change to the first one
int offset, MemoryDeviceInfoList *dimms)
{
MachineState *machine = MACHINE(spapr);
- uint8_t *int_buf, *cur_index, buf_len;
+ uint8_t *int_buf, *cur_index;
int ret;
uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
uint64_t addr, cur_addr, size;
uint32_t nr_boot_lmbs = (machine->device_memory->base / lmb_size);
uint64_t mem_end = machine->device_memory->base +
memory_region_size(&machine->device_memory->mr);
- uint32_t node, nr_entries = 0;
+ uint32_t node, buf_len, nr_entries = 0;
sPAPRDRConnector *drc;
DrconfCellQueue *elem, *next;
MemoryDeviceInfoList *info;
* Add info to guest to indentify which host is it being run on
* and what is the uuid of the guest
*/
- if (kvmppc_get_host_model(&buf)) {
- _FDT(fdt_setprop_string(fdt, 0, "host-model", buf));
- g_free(buf);
+ if (spapr->host_model && !g_str_equal(spapr->host_model, "none")) {
+ if (g_str_equal(spapr->host_model, "passthrough")) {
+ /* -M host-model=passthrough */
+ if (kvmppc_get_host_model(&buf)) {
+ _FDT(fdt_setprop_string(fdt, 0, "host-model", buf));
+ g_free(buf);
+ }
+ } else {
+ /* -M host-model=<user-string> */
+ _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model));
+ }
}
- if (kvmppc_get_host_serial(&buf)) {
- _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf));
- g_free(buf);
+
+ if (spapr->host_serial && !g_str_equal(spapr->host_serial, "none")) {
+ if (g_str_equal(spapr->host_serial, "passthrough")) {
+ /* -M host-serial=passthrough */
+ if (kvmppc_get_host_serial(&buf)) {
+ _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf));
+ g_free(buf);
+ }
+ } else {
+ /* -M host-serial=<user-string> */
+ _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial));
+ }
}
buf = qemu_uuid_unparse_strdup(&qemu_uuid);
/* /interrupt controller */
spapr->irq->dt_populate(spapr, spapr_max_server_number(spapr), fdt,
- PHANDLE_XICP);
+ PHANDLE_INTC);
ret = spapr_populate_memory(spapr, fdt);
if (ret < 0) {
}
QLIST_FOREACH(phb, &spapr->phbs, list) {
- ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt,
- spapr->irq->nr_msis);
+ ret = spapr_populate_pci_dt(phb, PHANDLE_INTC, fdt,
+ spapr->irq->nr_msis, NULL);
if (ret < 0) {
error_report("couldn't setup PCI devices in fdt");
exit(1);
exit(1);
}
+ if (smc->dr_phb_enabled) {
+ ret = spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_PHB);
+ if (ret < 0) {
+ error_report("Couldn't set up PHB DR device tree properties");
+ exit(1);
+ }
+ }
+
return fdt;
}
}
}
-static uint64_t spapr_get_patbe(PPCVirtualHypervisor *vhyp)
+struct LPCRSyncState {
+ target_ulong value;
+ target_ulong mask;
+};
+
+static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg)
+{
+ struct LPCRSyncState *s = arg.host_ptr;
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+ target_ulong lpcr;
+
+ cpu_synchronize_state(cs);
+ lpcr = env->spr[SPR_LPCR];
+ lpcr &= ~s->mask;
+ lpcr |= s->value;
+ ppc_store_lpcr(cpu, lpcr);
+}
+
+void spapr_set_all_lpcrs(target_ulong value, target_ulong mask)
+{
+ CPUState *cs;
+ struct LPCRSyncState s = {
+ .value = value,
+ .mask = mask
+ };
+ CPU_FOREACH(cs) {
+ run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s));
+ }
+}
+
+static void spapr_get_pate(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
- return spapr->patb_entry;
+ /* Copy PATE1:GR into PATE0:HR */
+ entry->dw0 = spapr->patb_entry & PATE0_HR;
+ entry->dw1 = spapr->patb_entry;
}
#define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2))
if (!spapr->htab) {
kvmppc_write_hpte(ptex, pte0, pte1);
} else {
- stq_p(spapr->htab + offset, pte0);
- stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1);
+ if (pte0 & HPTE64_V_VALID) {
+ stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1);
+ /*
+ * When setting valid, we write PTE1 first. This ensures
+ * proper synchronization with the reading code in
+ * ppc_hash64_pteg_search()
+ */
+ smp_wmb();
+ stq_p(spapr->htab + offset, pte0);
+ } else {
+ stq_p(spapr->htab + offset, pte0);
+ /*
+ * When clearing it we set PTE0 first. This ensures proper
+ * synchronization with the reading code in
+ * ppc_hash64_pteg_search()
+ */
+ smp_wmb();
+ stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1);
+ }
}
}
}
}
/* We're setting up a hash table, so that means we're not radix */
- spapr->patb_entry = 0;
+ spapr_set_all_lpcrs(0, LPCR_HR | LPCR_UPRT);
}
void spapr_setup_hpt_and_vrma(sPAPRMachineState *spapr)
if (kvm_enabled() && kvmppc_has_cap_mmu_radix() &&
ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0,
spapr->max_compat_pvr)) {
- /* If using KVM with radix mode available, VCPUs can be started
+ /*
+ * If using KVM with radix mode available, VCPUs can be started
* without a HPT because KVM will start them in radix mode.
- * Set the GR bit in PATB so that we know there is no HPT. */
- spapr->patb_entry = PATBE1_GR;
+ * Set the GR bit in PATE so that we know there is no HPT.
+ */
+ spapr->patb_entry = PATE1_GR;
+ spapr_set_all_lpcrs(LPCR_HR | LPCR_UPRT, LPCR_HR | LPCR_UPRT);
} else {
spapr_setup_hpt_and_vrma(spapr);
}
- /* if this reset wasn't generated by CAS, we should reset our
- * negotiated options and start from scratch */
+ /*
+ * If this reset wasn't generated by CAS, we should reset our
+ * negotiated options and start from scratch
+ */
if (!spapr->cas_reboot) {
spapr_ovec_cleanup(spapr->ov5_cas);
spapr->ov5_cas = spapr_ovec_new();
static void spapr_rtc_create(sPAPRMachineState *spapr)
{
- object_initialize(&spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC);
- object_property_add_child(OBJECT(spapr), "rtc", OBJECT(&spapr->rtc),
- &error_fatal);
+ object_initialize_child(OBJECT(spapr), "rtc",
+ &spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC,
+ &error_fatal, NULL);
object_property_set_bool(OBJECT(&spapr->rtc), true, "realized",
&error_fatal);
object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc),
if (kvm_enabled() && spapr->patb_entry) {
PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
- bool radix = !!(spapr->patb_entry & PATBE1_GR);
+ bool radix = !!(spapr->patb_entry & PATE1_GR);
bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE);
+ /*
+ * Update LPCR:HR and UPRT as they may not be set properly in
+ * the stream
+ */
+ spapr_set_all_lpcrs(radix ? (LPCR_HR | LPCR_UPRT) : 0,
+ LPCR_HR | LPCR_UPRT);
+
err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry);
if (err) {
error_report("Process table config unsupported by the host");
/* We always have at least the nvram device on VIO */
spapr_create_nvram(spapr);
+ /*
+ * Setup hotplug / dynamic-reconfiguration connectors. top-level
+ * connectors (described in root DT node's "ibm,drc-types" property)
+ * are pre-initialized here. additional child connectors (such as
+ * connectors for a PHBs PCI slots) are added as needed during their
+ * parent's realization.
+ */
+ if (smc->dr_phb_enabled) {
+ for (i = 0; i < SPAPR_MAX_PHBS; i++) {
+ spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i);
+ }
+ }
+
/* Set up PCI */
spapr_pci_rtas_init();
if (kernel_filename) {
uint64_t lowaddr = 0;
- spapr->kernel_size = load_elf(kernel_filename, translate_kernel_address,
- NULL, NULL, &lowaddr, NULL, 1,
+ spapr->kernel_size = load_elf(kernel_filename, NULL,
+ translate_kernel_address, NULL,
+ NULL, &lowaddr, NULL, 1,
PPC_ELF_MACHINE, 0, 0);
if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) {
- spapr->kernel_size = load_elf(kernel_filename,
+ spapr->kernel_size = load_elf(kernel_filename, NULL,
translate_kernel_address, NULL, NULL,
&lowaddr, NULL, 0, PPC_ELF_MACHINE,
0, 0);
register_savevm_live(NULL, "spapr/htab", -1, 1,
&savevm_htab_handlers, spapr);
+ qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine),
+ &error_fatal);
+
qemu_register_boot_set(spapr_boot_set, spapr);
if (kvm_enabled()) {
}
}
+static char *spapr_get_host_model(Object *obj, Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+
+ return g_strdup(spapr->host_model);
+}
+
+static void spapr_set_host_model(Object *obj, const char *value, Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+
+ g_free(spapr->host_model);
+ spapr->host_model = g_strdup(value);
+}
+
+static char *spapr_get_host_serial(Object *obj, Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+
+ return g_strdup(spapr->host_serial);
+}
+
+static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+
+ g_free(spapr->host_serial);
+ spapr->host_serial = g_strdup(value);
+}
+
static void spapr_instance_init(Object *obj)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
object_property_set_description(obj, "ic-mode",
"Specifies the interrupt controller mode (xics, xive, dual)",
NULL);
+
+ object_property_add_str(obj, "host-model",
+ spapr_get_host_model, spapr_set_host_model,
+ &error_abort);
+ object_property_set_description(obj, "host-model",
+ "Set host's model-id to use - none|passthrough|string", &error_abort);
+ object_property_add_str(obj, "host-serial",
+ spapr_get_host_serial, spapr_set_host_serial,
+ &error_abort);
+ object_property_set_description(obj, "host-serial",
+ "Set host's system-id to use - none|passthrough|string", &error_abort);
}
static void spapr_machine_finalizefn(Object *obj)
}
}
+int spapr_lmb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp)
+{
+ uint64_t addr;
+ uint32_t node;
+
+ addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE;
+ node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP,
+ &error_abort);
+ *fdt_start_offset = spapr_populate_memory_node(fdt, node, addr,
+ SPAPR_MEMORY_BLOCK_SIZE);
+ return 0;
+}
+
static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
- uint32_t node, bool dedicated_hp_event_source,
- Error **errp)
+ bool dedicated_hp_event_source, Error **errp)
{
sPAPRDRConnector *drc;
uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE;
- int i, fdt_offset, fdt_size;
- void *fdt;
+ int i;
uint64_t addr = addr_start;
bool hotplugged = spapr_drc_hotplugged(dev);
Error *local_err = NULL;
addr / SPAPR_MEMORY_BLOCK_SIZE);
g_assert(drc);
- fdt = create_device_tree(&fdt_size);
- fdt_offset = spapr_populate_memory_node(fdt, node, addr,
- SPAPR_MEMORY_BLOCK_SIZE);
-
- spapr_drc_attach(drc, dev, fdt, fdt_offset, &local_err);
+ spapr_drc_attach(drc, dev, &local_err);
if (local_err) {
while (addr > addr_start) {
addr -= SPAPR_MEMORY_BLOCK_SIZE;
addr / SPAPR_MEMORY_BLOCK_SIZE);
spapr_drc_detach(drc);
}
- g_free(fdt);
error_propagate(errp, local_err);
return;
}
sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev);
PCDIMMDevice *dimm = PC_DIMM(dev);
uint64_t size, addr;
- uint32_t node;
size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort);
goto out_unplug;
}
- node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP,
- &error_abort);
- spapr_add_lmbs(dev, addr, size, node,
- spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT),
+ spapr_add_lmbs(dev, addr, size, spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT),
&local_err);
if (local_err) {
goto out_unplug;
error_propagate(errp, local_err);
}
-static void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset,
- sPAPRMachineState *spapr)
-{
- PowerPCCPU *cpu = POWERPC_CPU(cs);
- DeviceClass *dc = DEVICE_GET_CLASS(cs);
- int id = spapr_get_vcpu_id(cpu);
- void *fdt;
- int offset, fdt_size;
- char *nodename;
-
- fdt = create_device_tree(&fdt_size);
- nodename = g_strdup_printf("%s@%x", dc->fw_name, id);
- offset = fdt_add_subnode(fdt, 0, nodename);
-
- spapr_populate_cpu_dt(cs, fdt, offset, spapr);
- g_free(nodename);
-
- *fdt_offset = offset;
- return fdt;
-}
-
/* Callback to be called during DRC release. */
void spapr_core_release(DeviceState *dev)
{
spapr_hotplug_req_remove_by_index(drc);
}
+int spapr_core_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp)
+{
+ sPAPRCPUCore *core = SPAPR_CPU_CORE(drc->dev);
+ CPUState *cs = CPU(core->threads[0]);
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ DeviceClass *dc = DEVICE_GET_CLASS(cs);
+ int id = spapr_get_vcpu_id(cpu);
+ char *nodename;
+ int offset;
+
+ nodename = g_strdup_printf("%s@%x", dc->fw_name, id);
+ offset = fdt_add_subnode(fdt, 0, nodename);
+ g_free(nodename);
+
+ spapr_populate_cpu_dt(cs, fdt, offset, spapr);
+
+ *fdt_start_offset = offset;
+ return 0;
+}
+
static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev));
CPUCore *cc = CPU_CORE(dev);
- CPUState *cs = CPU(core->threads[0]);
+ CPUState *cs;
sPAPRDRConnector *drc;
Error *local_err = NULL;
CPUArchId *core_slot;
g_assert(drc || !mc->has_hotpluggable_cpus);
if (drc) {
- void *fdt;
- int fdt_offset;
-
- fdt = spapr_populate_hotplug_cpu_dt(cs, &fdt_offset, spapr);
-
- spapr_drc_attach(drc, dev, fdt, fdt_offset, &local_err);
+ spapr_drc_attach(drc, dev, &local_err);
if (local_err) {
- g_free(fdt);
error_propagate(errp, local_err);
return;
}
error_propagate(errp, local_err);
}
+int spapr_phb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp)
+{
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev);
+ int intc_phandle;
+
+ intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp);
+ if (intc_phandle <= 0) {
+ return -1;
+ }
+
+ if (spapr_populate_pci_dt(sphb, intc_phandle, fdt, spapr->irq->nr_msis,
+ fdt_start_offset)) {
+ error_setg(errp, "unable to create FDT node for PHB %d", sphb->index);
+ return -1;
+ }
+
+ /* generally SLOF creates these, for hotplug it's up to QEMU */
+ _FDT(fdt_setprop_string(fdt, *fdt_start_offset, "name", "pci"));
+
+ return 0;
+}
+
+static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+ const unsigned windows_supported = spapr_phb_windows_supported(sphb);
+
+ if (dev->hotplugged && !smc->dr_phb_enabled) {
+ error_setg(errp, "PHB hotplug not supported for this machine");
+ return;
+ }
+
+ if (sphb->index == (uint32_t)-1) {
+ error_setg(errp, "\"index\" for PAPR PHB is mandatory");
+ return;
+ }
+
+ /*
+ * This will check that sphb->index doesn't exceed the maximum number of
+ * PHBs for the current machine type.
+ */
+ smc->phb_placement(spapr, sphb->index,
+ &sphb->buid, &sphb->io_win_addr,
+ &sphb->mem_win_addr, &sphb->mem64_win_addr,
+ windows_supported, sphb->dma_liobn, errp);
+}
+
+static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+ sPAPRDRConnector *drc;
+ bool hotplugged = spapr_drc_hotplugged(dev);
+ Error *local_err = NULL;
+
+ if (!smc->dr_phb_enabled) {
+ return;
+ }
+
+ drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
+ /* hotplug hooks should check it's enabled before getting this far */
+ assert(drc);
+
+ spapr_drc_attach(drc, DEVICE(dev), &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ if (hotplugged) {
+ spapr_hotplug_req_add_by_index(drc);
+ } else {
+ spapr_drc_reset(drc);
+ }
+}
+
+void spapr_phb_release(DeviceState *dev)
+{
+ HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
+
+ hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
+}
+
+static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
+{
+ object_unparent(OBJECT(dev));
+}
+
+static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+ sPAPRDRConnector *drc;
+
+ drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
+ assert(drc);
+
+ if (!spapr_drc_unplug_requested(drc)) {
+ spapr_drc_detach(drc);
+ spapr_hotplug_req_remove_by_index(drc);
+ }
+}
+
static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
spapr_memory_plug(hotplug_dev, dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
spapr_core_plug(hotplug_dev, dev, errp);
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
+ spapr_phb_plug(hotplug_dev, dev, errp);
}
}
spapr_memory_unplug(hotplug_dev, dev);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
spapr_core_unplug(hotplug_dev, dev);
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
+ spapr_phb_unplug(hotplug_dev, dev);
}
}
{
sPAPRMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev));
MachineClass *mc = MACHINE_GET_CLASS(sms);
+ sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) {
return;
}
spapr_core_unplug_request(hotplug_dev, dev, errp);
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
+ if (!smc->dr_phb_enabled) {
+ error_setg(errp, "PHB hot unplug not supported on this machine");
+ return;
+ }
+ spapr_phb_unplug_request(hotplug_dev, dev, errp);
}
}
spapr_memory_pre_plug(hotplug_dev, dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
spapr_core_pre_plug(hotplug_dev, dev, errp);
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
+ spapr_phb_pre_plug(hotplug_dev, dev, errp);
}
}
DeviceState *dev)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
- object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
+ object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) ||
+ object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
return HOTPLUG_HANDLER(machine);
}
return NULL;
vhc->map_hptes = spapr_map_hptes;
vhc->unmap_hptes = spapr_unmap_hptes;
vhc->store_hpte = spapr_store_hpte;
- vhc->get_patbe = spapr_get_patbe;
+ vhc->get_pate = spapr_get_pate;
vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr;
xic->ics_get = spapr_ics_get;
xic->ics_resend = spapr_ics_resend;
smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
spapr_caps_add_properties(smc, &error_abort);
smc->irq = &spapr_irq_xics;
+ smc->dr_phb_enabled = true;
}
static const TypeInfo spapr_machine_info = {
static void spapr_machine_3_1_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+ static GlobalProperty compat[] = {
+ { TYPE_SPAPR_MACHINE, "host-model", "passthrough" },
+ { TYPE_SPAPR_MACHINE, "host-serial", "passthrough" },
+ };
spapr_machine_4_0_class_options(mc);
compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len);
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
+
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
smc->update_dt_enabled = false;
+ smc->dr_phb_enabled = false;
}
DEFINE_SPAPR_MACHINE(3_1, "3.1", false);
#include "qemu/error-report.h"
#include "hw/ppc/spapr.h" /* for RTAS return codes */
#include "hw/pci-host/spapr.h" /* spapr_phb_remove_pci_device_cb callback */
+#include "sysemu/device_tree.h"
#include "trace.h"
#define DRC_CONTAINER_PATH "/dr-connector"
} while (fdt_depth != 0);
}
-void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
- int fdt_start_offset, Error **errp)
+void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, Error **errp)
{
trace_spapr_drc_attach(spapr_drc_index(drc));
}
g_assert((drc->state == SPAPR_DRC_STATE_LOGICAL_UNUSABLE)
|| (drc->state == SPAPR_DRC_STATE_PHYSICAL_POWERON));
- g_assert(fdt);
drc->dev = d;
- drc->fdt = fdt;
- drc->fdt_start_offset = fdt_start_offset;
object_property_add_link(OBJECT(drc), "device",
object_get_typename(OBJECT(drc->dev)),
drck->typename = "CPU";
drck->drc_name_prefix = "CPU ";
drck->release = spapr_core_release;
+ drck->dt_populate = spapr_core_dt_populate;
}
static void spapr_drc_pci_class_init(ObjectClass *k, void *data)
drck->typename = "28";
drck->drc_name_prefix = "C";
drck->release = spapr_phb_remove_pci_device_cb;
+ drck->dt_populate = spapr_pci_dt_populate;
}
static void spapr_drc_lmb_class_init(ObjectClass *k, void *data)
drck->typename = "MEM";
drck->drc_name_prefix = "LMB ";
drck->release = spapr_lmb_release;
+ drck->dt_populate = spapr_lmb_dt_populate;
+}
+
+static void spapr_drc_phb_class_init(ObjectClass *k, void *data)
+{
+ sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
+
+ drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PHB;
+ drck->typename = "PHB";
+ drck->drc_name_prefix = "PHB ";
+ drck->release = spapr_phb_release;
+ drck->dt_populate = spapr_phb_dt_populate;
}
static const TypeInfo spapr_dr_connector_info = {
.class_init = spapr_drc_lmb_class_init,
};
+static const TypeInfo spapr_drc_phb_info = {
+ .name = TYPE_SPAPR_DRC_PHB,
+ .parent = TYPE_SPAPR_DRC_LOGICAL,
+ .instance_size = sizeof(sPAPRDRConnector),
+ .class_init = spapr_drc_phb_class_init,
+};
+
/* helper functions for external users */
sPAPRDRConnector *spapr_drc_by_index(uint32_t index)
goto out;
}
- g_assert(drc->fdt);
-
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+ if (!drc->fdt) {
+ Error *local_err = NULL;
+ void *fdt;
+ int fdt_size;
+
+ fdt = create_device_tree(&fdt_size);
+
+ if (drck->dt_populate(drc, spapr, fdt, &drc->fdt_start_offset,
+ &local_err)) {
+ g_free(fdt);
+ error_free(local_err);
+ rc = SPAPR_DR_CC_RESPONSE_ERROR;
+ goto out;
+ }
+
+ drc->fdt = fdt;
+ drc->ccs_offset = drc->fdt_start_offset;
+ drc->ccs_depth = 0;
+ }
+
do {
uint32_t tag;
const char *name;
type_register_static(&spapr_drc_cpu_info);
type_register_static(&spapr_drc_pci_info);
type_register_static(&spapr_drc_lmb_info);
+ type_register_static(&spapr_drc_phb_info);
spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator",
rtas_set_indicator);
continue;
}
- spapr_dt_xics_irq(interrupts, source->irq, false);
+ spapr_dt_irq(interrupts, source->irq, false);
_FDT(node_offset = fdt_add_subnode(fdt, event_sources, source_name));
_FDT(fdt_setprop(fdt, node_offset, "interrupts", interrupts,
case SPAPR_DR_CONNECTOR_TYPE_CPU:
hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_CPU;
break;
+ case SPAPR_DR_CONNECTOR_TYPE_PHB:
+ hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_PHB;
+ break;
default:
/* we shouldn't be signaling hotplug events for resources
* that don't support them
#include "mmu-book3s-v3.h"
#include "hw/mem/memory-device.h"
-struct LPCRSyncState {
- target_ulong value;
- target_ulong mask;
-};
-
-static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg)
-{
- struct LPCRSyncState *s = arg.host_ptr;
- PowerPCCPU *cpu = POWERPC_CPU(cs);
- CPUPPCState *env = &cpu->env;
- target_ulong lpcr;
-
- cpu_synchronize_state(cs);
- lpcr = env->spr[SPR_LPCR];
- lpcr &= ~s->mask;
- lpcr |= s->value;
- ppc_store_lpcr(cpu, lpcr);
-}
-
-static void set_all_lpcrs(target_ulong value, target_ulong mask)
-{
- CPUState *cs;
- struct LPCRSyncState s = {
- .value = value,
- .mask = mask
- };
- CPU_FOREACH(cs) {
- run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s));
- }
-}
-
static bool has_spr(PowerPCCPU *cpu, int spr)
{
/* We can test whether the SPR is defined by checking for a valid name */
switch (mflags) {
case H_SET_MODE_ENDIAN_BIG:
- set_all_lpcrs(0, LPCR_ILE);
+ spapr_set_all_lpcrs(0, LPCR_ILE);
spapr_pci_switch_vga(true);
return H_SUCCESS;
case H_SET_MODE_ENDIAN_LITTLE:
- set_all_lpcrs(LPCR_ILE, LPCR_ILE);
+ spapr_set_all_lpcrs(LPCR_ILE, LPCR_ILE);
spapr_pci_switch_vga(false);
return H_SUCCESS;
}
return H_UNSUPPORTED_FLAG;
}
- set_all_lpcrs(mflags << LPCR_AIL_SHIFT, LPCR_AIL);
+ spapr_set_all_lpcrs(mflags << LPCR_AIL_SHIFT, LPCR_AIL);
return H_SUCCESS;
}
* later and so assumed radix and now it's called H_REG_PROC_TBL
*/
- if ((patbe_old & PATBE1_GR) == (patbe_new & PATBE1_GR)) {
+ if ((patbe_old & PATE1_GR) == (patbe_new & PATE1_GR)) {
/* We assume RADIX, so this catches all the "Do Nothing" cases */
- } else if (!(patbe_old & PATBE1_GR)) {
+ } else if (!(patbe_old & PATE1_GR)) {
/* HASH->RADIX : Free HPT */
spapr_free_hpt(spapr);
- } else if (!(patbe_new & PATBE1_GR)) {
+ } else if (!(patbe_new & PATE1_GR)) {
/* RADIX->HASH || NOTHING->HASH : Allocate HPT */
spapr_setup_hpt_and_vrma(spapr);
}
} else if (table_size > 24) {
return H_P4;
}
- cproc = PATBE1_GR | proc_tbl | table_size;
+ cproc = PATE1_GR | proc_tbl | table_size;
} else { /* Register new HPT process table */
if (flags & FLAG_HASH_PROC_TBL) { /* Hash with Segment Tables */
/* TODO - Not Supported */
}
} else { /* Deregister current process table */
- /* Set to benign value: (current GR) | 0. This allows
- * deregistration in KVM to succeed even if the radix bit in flags
- * doesn't match the radix bit in the old PATB. */
- cproc = spapr->patb_entry & PATBE1_GR;
+ /*
+ * Set to benign value: (current GR) | 0. This allows
+ * deregistration in KVM to succeed even if the radix bit
+ * in flags doesn't match the radix bit in the old PATE.
+ */
+ cproc = spapr->patb_entry & PATE1_GR;
}
} else { /* Maintain current registration */
- if (!(flags & FLAG_RADIX) != !(spapr->patb_entry & PATBE1_GR)) {
+ if (!(flags & FLAG_RADIX) != !(spapr->patb_entry & PATE1_GR)) {
/* Technically caused by flag bits => H_PARAMETER */
return H_PARAMETER; /* Existing Process Table Mismatch */
}
spapr->patb_entry = cproc; /* Save new process table */
- /* Update the UPRT and GTSE bits in the LPCR for all cpus */
- set_all_lpcrs(((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ? LPCR_UPRT : 0) |
- ((flags & FLAG_GTSE) ? LPCR_GTSE : 0),
- LPCR_UPRT | LPCR_GTSE);
+ /* Update the UPRT, HR and GTSE bits in the LPCR for all cpus */
+ spapr_set_all_lpcrs(((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ?
+ (LPCR_UPRT | LPCR_HR) : 0) |
+ ((flags & FLAG_GTSE) ? LPCR_GTSE : 0),
+ LPCR_UPRT | LPCR_HR | LPCR_GTSE);
if (kvm_enabled()) {
return kvmppc_configure_v3_mmu(cpu, flags & FLAG_RADIX,
if (!spapr->cas_reboot) {
/* If spapr_machine_reset() did not set up a HPT but one is necessary
* (because the guest isn't going to use radix) then set it up here. */
- if ((spapr->patb_entry & PATBE1_GR) && !guest_radix) {
+ if ((spapr->patb_entry & PATE1_GR) && !guest_radix) {
/* legacy hash or new hash: */
spapr_setup_hpt_and_vrma(spapr);
}
*/
static ICSState *spapr_ics_create(sPAPRMachineState *spapr,
- const char *type_ics,
int nr_irqs, Error **errp)
{
Error *local_err = NULL;
Object *obj;
- obj = object_new(type_ics);
+ obj = object_new(TYPE_ICS_SIMPLE);
object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort);
object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr),
&error_abort);
return NULL;
}
-static void spapr_irq_init_xics(sPAPRMachineState *spapr, Error **errp)
+static void spapr_irq_init_xics(sPAPRMachineState *spapr, int nr_irqs,
+ Error **errp)
{
MachineState *machine = MACHINE(spapr);
- int nr_irqs = spapr->irq->nr_irqs;
Error *local_err = NULL;
+ bool xics_kvm = false;
if (kvm_enabled()) {
if (machine_kernel_irqchip_allowed(machine) &&
!xics_kvm_init(spapr, &local_err)) {
- spapr->icp_type = TYPE_KVM_ICP;
- spapr->ics = spapr_ics_create(spapr, TYPE_ICS_KVM, nr_irqs,
- &local_err);
+ xics_kvm = true;
}
- if (machine_kernel_irqchip_required(machine) && !spapr->ics) {
+ if (machine_kernel_irqchip_required(machine) && !xics_kvm) {
error_prepend(&local_err,
"kernel_irqchip requested but unavailable: ");
goto error;
local_err = NULL;
}
- if (!spapr->ics) {
+ if (!xics_kvm) {
xics_spapr_init(spapr);
- spapr->icp_type = TYPE_ICP;
- spapr->ics = spapr_ics_create(spapr, TYPE_ICS_SIMPLE, nr_irqs,
- &local_err);
}
+ spapr->ics = spapr_ics_create(spapr, nr_irqs, &local_err);
+
error:
error_propagate(errp, local_err);
}
Object *obj;
sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
- obj = icp_create(OBJECT(cpu), spapr->icp_type, XICS_FABRIC(spapr),
+ obj = icp_create(OBJECT(cpu), TYPE_ICP, XICS_FABRIC(spapr),
&local_err);
if (local_err) {
error_propagate(errp, local_err);
static int spapr_irq_post_load_xics(sPAPRMachineState *spapr, int version_id)
{
- if (!object_dynamic_cast(OBJECT(spapr->ics), TYPE_ICS_KVM)) {
+ if (!kvm_irqchip_in_kernel()) {
CPUState *cs;
CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs);
static void spapr_irq_set_irq_xics(void *opaque, int srcno, int val)
{
sPAPRMachineState *spapr = opaque;
- MachineState *machine = MACHINE(opaque);
- if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) {
- ics_kvm_set_irq(spapr->ics, srcno, val);
- } else {
- ics_simple_set_irq(spapr->ics, srcno, val);
- }
+ ics_simple_set_irq(spapr->ics, srcno, val);
}
static void spapr_irq_reset_xics(sPAPRMachineState *spapr, Error **errp)
/* TODO: create the KVM XICS device */
}
+static const char *spapr_irq_get_nodename_xics(sPAPRMachineState *spapr)
+{
+ return XICS_NODENAME;
+}
+
#define SPAPR_IRQ_XICS_NR_IRQS 0x1000
#define SPAPR_IRQ_XICS_NR_MSIS \
(XICS_IRQ_BASE + SPAPR_IRQ_XICS_NR_IRQS - SPAPR_IRQ_MSI)
.post_load = spapr_irq_post_load_xics,
.reset = spapr_irq_reset_xics,
.set_irq = spapr_irq_set_irq_xics,
+ .get_nodename = spapr_irq_get_nodename_xics,
};
/*
* XIVE IRQ backend.
*/
-static void spapr_irq_init_xive(sPAPRMachineState *spapr, Error **errp)
+static void spapr_irq_init_xive(sPAPRMachineState *spapr, int nr_irqs,
+ Error **errp)
{
MachineState *machine = MACHINE(spapr);
uint32_t nr_servers = spapr_max_server_number(spapr);
}
dev = qdev_create(NULL, TYPE_SPAPR_XIVE);
- qdev_prop_set_uint32(dev, "nr-irqs", spapr->irq->nr_irqs);
+ qdev_prop_set_uint32(dev, "nr-irqs", nr_irqs);
/*
* 8 XIVE END structures per CPU. One for each available priority
*/
xive_source_set_irq(&spapr->xive->source, srcno, val);
}
+static const char *spapr_irq_get_nodename_xive(sPAPRMachineState *spapr)
+{
+ return spapr->xive->nodename;
+}
+
/*
* XIVE uses the full IRQ number space. Set it to 8K to be compatible
* with XICS.
.post_load = spapr_irq_post_load_xive,
.reset = spapr_irq_reset_xive,
.set_irq = spapr_irq_set_irq_xive,
+ .get_nodename = spapr_irq_get_nodename_xive,
};
/*
&spapr_irq_xive : &spapr_irq_xics;
}
-static void spapr_irq_init_dual(sPAPRMachineState *spapr, Error **errp)
+static void spapr_irq_init_dual(sPAPRMachineState *spapr, int nr_irqs,
+ Error **errp)
{
MachineState *machine = MACHINE(spapr);
Error *local_err = NULL;
return;
}
- spapr_irq_xics.init(spapr, &local_err);
+ spapr_irq_xics.init(spapr, spapr_irq_xics.nr_irqs, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
- /*
- * Align the XICS and the XIVE IRQ number space under QEMU.
- *
- * However, the XICS KVM device still considers that the IRQ
- * numbers should start at XICS_IRQ_BASE (0x1000). Either we
- * should introduce a KVM device ioctl to set the offset or ignore
- * the lower 4K numbers when using the get/set ioctl of the XICS
- * KVM device. The second option seems the least intrusive.
- */
- spapr->ics->offset = 0;
-
- spapr_irq_xive.init(spapr, &local_err);
+ spapr_irq_xive.init(spapr, spapr_irq_xive.nr_irqs, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
static qemu_irq spapr_qirq_dual(sPAPRMachineState *spapr, int irq)
{
- sPAPRXive *xive = spapr->xive;
- ICSState *ics = spapr->ics;
-
- if (irq >= spapr->irq->nr_irqs) {
- return NULL;
- }
-
- /*
- * The IRQ number should have been claimed under both interrupt
- * controllers.
- */
- assert(!ICS_IRQ_FREE(ics, irq - ics->offset));
- assert(xive_eas_is_valid(&xive->eat[irq]));
-
- return spapr->qirqs[irq];
+ return spapr_irq_current(spapr)->qirq(spapr, irq);
}
static void spapr_irq_print_info_dual(sPAPRMachineState *spapr, Monitor *mon)
spapr_irq_current(spapr)->set_irq(spapr, srcno, val);
}
+static const char *spapr_irq_get_nodename_dual(sPAPRMachineState *spapr)
+{
+ return spapr_irq_current(spapr)->get_nodename(spapr);
+}
+
/*
* Define values in sync with the XIVE and XICS backend
*/
.cpu_intc_create = spapr_irq_cpu_intc_create_dual,
.post_load = spapr_irq_post_load_dual,
.reset = spapr_irq_reset_dual,
- .set_irq = spapr_irq_set_irq_dual
+ .set_irq = spapr_irq_set_irq_dual,
+ .get_nodename = spapr_irq_get_nodename_dual,
};
/*
*/
void spapr_irq_init(sPAPRMachineState *spapr, Error **errp)
{
+ MachineState *machine = MACHINE(spapr);
+
+ if (machine_kernel_irqchip_split(machine)) {
+ error_setg(errp, "kernel_irqchip split mode not supported on pseries");
+ return;
+ }
+
+ if (!kvm_enabled() && machine_kernel_irqchip_required(machine)) {
+ error_setg(errp,
+ "kernel_irqchip requested but only available with KVM");
+ return;
+ }
+
/* Initialize the MSI IRQ allocator. */
if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
spapr_irq_msi_init(spapr, spapr->irq->nr_msis);
}
- spapr->irq->init(spapr, errp);
+ spapr->irq->init(spapr, spapr->irq->nr_irqs, errp);
spapr->qirqs = qemu_allocate_irqs(spapr->irq->set_irq, spapr,
spapr->irq->nr_irqs);
}
}
+int spapr_irq_get_phandle(sPAPRMachineState *spapr, void *fdt, Error **errp)
+{
+ const char *nodename = spapr->irq->get_nodename(spapr);
+ int offset, phandle;
+
+ offset = fdt_subnode_offset(fdt, 0, nodename);
+ if (offset < 0) {
+ error_setg(errp, "Can't find node \"%s\": %s", nodename,
+ fdt_strerror(offset));
+ return -1;
+ }
+
+ phandle = fdt_get_phandle(fdt, offset);
+ if (!phandle) {
+ error_setg(errp, "Can't get phandle of node \"%s\"", nodename);
+ return -1;
+ }
+
+ return phandle;
+}
+
/*
* XICS legacy routines - to deprecate one day
*/
.cpu_intc_create = spapr_irq_cpu_intc_create_xics,
.post_load = spapr_irq_post_load_xics,
.set_irq = spapr_irq_set_irq_xics,
+ .get_nodename = spapr_irq_get_nodename_xics,
};
#include "qemu/bitmap.h"
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
+#include "sysemu/qtest.h"
#include "trace.h"
#include <libfdt.h>
g_assert(ov);
g_assert(bitnr < OV_MAXBITS);
+ /* support memory unplug for qtest */
+ if (qtest_enabled() && bitnr == OV5_HP_EVT) {
+ return true;
+ }
+
return test_bit(bitnr, ov->bitmap) ? true : false;
}
for (i = 0; i < req_num; i++) {
spapr_irq_claim(spapr, irq + i, false, &err);
if (err) {
+ if (i) {
+ spapr_irq_free(spapr, irq, i);
+ }
+ if (!smc->legacy_irq_allocation) {
+ spapr_irq_msi_free(spapr, irq, req_num);
+ }
error_reportf_err(err, "Can't allocate MSIs for device %x: ",
config_addr);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return spapr_drc_index(drc);
}
+int spapr_pci_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp)
+{
+ HotplugHandler *plug_handler = qdev_get_hotplug_handler(drc->dev);
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(plug_handler);
+ PCIDevice *pdev = PCI_DEVICE(drc->dev);
+
+ *fdt_start_offset = spapr_create_pci_child_dt(sphb, pdev, fdt, 0);
+ return 0;
+}
+
static void spapr_pci_plug(HotplugHandler *plug_handler,
DeviceState *plugged_dev, Error **errp)
{
Error *local_err = NULL;
PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev)));
uint32_t slotnr = PCI_SLOT(pdev->devfn);
- void *fdt = NULL;
- int fdt_start_offset, fdt_size;
/* if DR is disabled we don't need to do anything in the case of
* hotplug or coldplug callbacks
goto out;
}
- fdt = create_device_tree(&fdt_size);
- fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0);
-
- spapr_drc_attach(drc, DEVICE(pdev), fdt, fdt_start_offset, &local_err);
+ spapr_drc_attach(drc, DEVICE(pdev), &local_err);
if (local_err) {
goto out;
}
out:
if (local_err) {
error_propagate(errp, local_err);
- g_free(fdt);
}
}
}
}
+static void spapr_phb_finalizefn(Object *obj)
+{
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(obj);
+
+ g_free(sphb->dtbusname);
+ sphb->dtbusname = NULL;
+}
+
+static void spapr_phb_unrealize(DeviceState *dev, Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+ SysBusDevice *s = SYS_BUS_DEVICE(dev);
+ PCIHostState *phb = PCI_HOST_BRIDGE(s);
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(phb);
+ sPAPRTCETable *tcet;
+ int i;
+ const unsigned windows_supported = spapr_phb_windows_supported(sphb);
+
+ if (sphb->msi) {
+ g_hash_table_unref(sphb->msi);
+ sphb->msi = NULL;
+ }
+
+ /*
+ * Remove IO/MMIO subregions and aliases, rest should get cleaned
+ * via PHB's unrealize->object_finalize
+ */
+ for (i = windows_supported - 1; i >= 0; i--) {
+ tcet = spapr_tce_find_by_liobn(sphb->dma_liobn[i]);
+ if (tcet) {
+ memory_region_del_subregion(&sphb->iommu_root,
+ spapr_tce_get_iommu(tcet));
+ }
+ }
+
+ if (sphb->dr_enabled) {
+ for (i = PCI_SLOT_MAX * 8 - 1; i >= 0; i--) {
+ sPAPRDRConnector *drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PCI,
+ (sphb->index << 16) | i);
+
+ if (drc) {
+ object_unparent(OBJECT(drc));
+ }
+ }
+ }
+
+ for (i = PCI_NUM_PINS - 1; i >= 0; i--) {
+ if (sphb->lsi_table[i].irq) {
+ spapr_irq_free(spapr, sphb->lsi_table[i].irq, 1);
+ sphb->lsi_table[i].irq = 0;
+ }
+ }
+
+ QLIST_REMOVE(sphb, list);
+
+ memory_region_del_subregion(&sphb->iommu_root, &sphb->msiwindow);
+
+ address_space_destroy(&sphb->iommu_as);
+
+ qbus_set_hotplug_handler(BUS(phb->bus), NULL, &error_abort);
+ pci_unregister_root_bus(phb->bus);
+
+ memory_region_del_subregion(get_system_memory(), &sphb->iowindow);
+ if (sphb->mem64_win_pciaddr != (hwaddr)-1) {
+ memory_region_del_subregion(get_system_memory(), &sphb->mem64window);
+ }
+ memory_region_del_subregion(get_system_memory(), &sphb->mem32window);
+}
+
static void spapr_phb_realize(DeviceState *dev, Error **errp)
{
/* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
PCIBus *bus;
uint64_t msi_window_size = 4096;
sPAPRTCETable *tcet;
- const unsigned windows_supported =
- sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1;
+ const unsigned windows_supported = spapr_phb_windows_supported(sphb);
if (!spapr) {
error_setg(errp, TYPE_SPAPR_PCI_HOST_BRIDGE " needs a pseries machine");
return;
}
- if (sphb->index != (uint32_t)-1) {
- Error *local_err = NULL;
-
- smc->phb_placement(spapr, sphb->index,
- &sphb->buid, &sphb->io_win_addr,
- &sphb->mem_win_addr, &sphb->mem64_win_addr,
- windows_supported, sphb->dma_liobn, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- } else {
- error_setg(errp, "\"index\" for PAPR PHB is mandatory");
- return;
- }
+ assert(sphb->index != (uint32_t)-1); /* checked in spapr_phb_pre_plug() */
if (sphb->mem64_win_size != 0) {
if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) {
&sphb->memspace, &sphb->iospace,
PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
phb->bus = bus;
- qbus_set_hotplug_handler(BUS(phb->bus), DEVICE(sphb), NULL);
+ qbus_set_hotplug_handler(BUS(phb->bus), OBJECT(sphb), NULL);
/*
* Initialize PHB address space.
if (local_err) {
error_propagate_prepend(errp, local_err,
"can't allocate LSIs: ");
+ /*
+ * Older machines will never support PHB hotplug, ie, this is an
+ * init only path and QEMU will terminate. No need to rollback.
+ */
return;
}
}
spapr_irq_claim(spapr, irq, true, &local_err);
if (local_err) {
error_propagate_prepend(errp, local_err, "can't allocate LSIs: ");
- return;
+ goto unrealize;
}
sphb->lsi_table[i].irq = irq;
if (!tcet) {
error_setg(errp, "Creating window#%d failed for %s",
i, sphb->dtbusname);
- return;
+ goto unrealize;
}
memory_region_add_subregion(&sphb->iommu_root, 0,
spapr_tce_get_iommu(tcet));
}
sphb->msi = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
+ return;
+
+unrealize:
+ spapr_phb_unrealize(dev, NULL);
}
static int spapr_phb_children_reset(Object *child, void *opaque)
hc->root_bus_path = spapr_phb_root_bus_path;
dc->realize = spapr_phb_realize;
+ dc->unrealize = spapr_phb_unrealize;
dc->props = spapr_phb_properties;
dc->reset = spapr_phb_reset;
dc->vmsd = &vmstate_spapr_pci;
.name = TYPE_SPAPR_PCI_HOST_BRIDGE,
.parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(sPAPRPHBState),
+ .instance_finalize = spapr_phb_finalizefn,
.class_init = spapr_phb_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_HOTPLUG_HANDLER },
}
-int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, void *fdt,
- uint32_t nr_msis)
+int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t intc_phandle, void *fdt,
+ uint32_t nr_msis, int *node_offset)
{
int bus_off, i, j, ret;
gchar *nodename;
sPAPRTCETable *tcet;
PCIBus *bus = PCI_HOST_BRIDGE(phb)->bus;
sPAPRFDT s_fdt;
+ sPAPRDRConnector *drc;
/* Start populating the FDT */
nodename = g_strdup_printf("pci@%" PRIx64, phb->buid);
_FDT(bus_off = fdt_add_subnode(fdt, 0, nodename));
g_free(nodename);
+ if (node_offset) {
+ *node_offset = bus_off;
+ }
/* Write PHB properties */
_FDT(fdt_setprop_string(fdt, bus_off, "device_type", "pci"));
irqmap[1] = 0;
irqmap[2] = 0;
irqmap[3] = cpu_to_be32(j+1);
- irqmap[4] = cpu_to_be32(xics_phandle);
- spapr_dt_xics_irq(&irqmap[5], phb->lsi_table[lsi_num].irq, true);
+ irqmap[4] = cpu_to_be32(intc_phandle);
+ spapr_dt_irq(&irqmap[5], phb->lsi_table[lsi_num].irq, true);
}
}
/* Write interrupt map */
tcet->liobn, tcet->bus_offset,
tcet->nb_table << tcet->page_shift);
+ drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, phb->index);
+ if (drc) {
+ uint32_t drc_index = cpu_to_be32(spapr_drc_index(drc));
+
+ _FDT(fdt_setprop(fdt, bus_off, "ibm,my-drc-index", &drc_index,
+ sizeof(drc_index)));
+ }
+
/* Walk the bridges and program the bus numbers*/
spapr_phb_pci_enumerate(phb);
_FDT(fdt_setprop_cell(fdt, bus_off, "qemu,phb-enumerated", 0x1));
* New cpus are expected to start in the same radix/hash mode
* as the existing CPUs
*/
- if (ppc64_radix_guest(callcpu)) {
- lpcr |= LPCR_UPRT | LPCR_GTSE;
+ if (ppc64_v3_radix(callcpu)) {
+ lpcr |= LPCR_UPRT | LPCR_GTSE | LPCR_HR;
} else {
- lpcr &= ~(LPCR_UPRT | LPCR_GTSE);
+ lpcr &= ~(LPCR_UPRT | LPCR_GTSE | LPCR_HR);
}
}
ppc_store_lpcr(newcpu, lpcr);
#include "sysemu/sysemu.h"
#include "hw/ppc/spapr.h"
#include "qapi/error.h"
-#include "qapi/qapi-events-misc.h"
+#include "qapi/qapi-events-target.h"
#include "qemu/cutils.h"
void spapr_rtc_read(sPAPRRTCState *rtc, struct tm *tm, uint32_t *ns)
if (dev->irq) {
uint32_t ints_prop[2];
- spapr_dt_xics_irq(ints_prop, dev->irq, false);
+ spapr_dt_irq(ints_prop, dev->irq, false);
ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,
sizeof(ints_prop));
if (ret < 0) {
hwaddr boot_offset;
/* Boots a kernel elf binary. */
- kernel_size = load_elf(kernel_filename, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&entry, &low, &high, 1, PPC_ELF_MACHINE,
0, 0);
boot_info.bootstrap_pc = entry & 0x00ffffff;
-obj-y += riscv_htif.o
-obj-y += riscv_hart.o
-obj-y += sifive_e.o
-obj-y += sifive_clint.o
-obj-y += sifive_prci.o
-obj-y += sifive_plic.o
-obj-y += sifive_test.o
-obj-y += sifive_u.o
-obj-y += sifive_uart.o
-obj-y += spike.o
-obj-y += virt.o
+obj-$(CONFIG_SPIKE) += riscv_htif.o
+obj-$(CONFIG_HART) += riscv_hart.o
+obj-$(CONFIG_SIFIVE_E) += sifive_e.o
+obj-$(CONFIG_SIFIVE) += sifive_clint.o
+obj-$(CONFIG_SIFIVE) += sifive_prci.o
+obj-$(CONFIG_SIFIVE) += sifive_plic.o
+obj-$(CONFIG_SIFIVE) += sifive_test.o
+obj-$(CONFIG_SIFIVE_U) += sifive_u.o
+obj-$(CONFIG_SIFIVE) += sifive_uart.o
+obj-$(CONFIG_SPIKE) += spike.o
+obj-$(CONFIG_RISCV_VIRT) += virt.o
[SIFIVE_E_DTIM] = { 0x80000000, 0x4000 }
};
-static uint64_t load_kernel(const char *kernel_filename)
+static target_ulong load_kernel(const char *kernel_filename)
{
uint64_t kernel_entry, kernel_high;
- if (load_elf(kernel_filename, NULL, NULL,
+ if (load_elf(kernel_filename, NULL, NULL, NULL,
&kernel_entry, NULL, &kernel_high,
0, EM_RISCV, 1, 0) < 0) {
error_report("could not load kernel '%s'", kernel_filename);
#define GEM_REVISION 0x10070109
-static uint64_t load_kernel(const char *kernel_filename)
+static target_ulong load_kernel(const char *kernel_filename)
{
uint64_t kernel_entry, kernel_high;
- if (load_elf(kernel_filename, NULL, NULL,
+ if (load_elf(kernel_filename, NULL, NULL, NULL,
&kernel_entry, NULL, &kernel_high,
0, EM_RISCV, 1, 0) < 0) {
error_report("could not load kernel '%s'", kernel_filename);
[SPIKE_DRAM] = { 0x80000000, 0x0 },
};
-static uint64_t load_kernel(const char *kernel_filename)
+static target_ulong load_kernel(const char *kernel_filename)
{
uint64_t kernel_entry, kernel_high;
- if (load_elf_ram_sym(kernel_filename, NULL, NULL,
+ if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL,
&kernel_entry, NULL, &kernel_high, 0, EM_RISCV, 1, 0,
NULL, true, htif_symbol_callback) < 0) {
error_report("could not load kernel '%s'", kernel_filename);
[VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 },
};
-static uint64_t load_kernel(const char *kernel_filename)
+static target_ulong load_kernel(const char *kernel_filename)
{
uint64_t kernel_entry, kernel_high;
- if (load_elf(kernel_filename, NULL, NULL,
+ if (load_elf(kernel_filename, NULL, NULL, NULL,
&kernel_entry, NULL, &kernel_high,
0, EM_RISCV, 1, 0) < 0) {
error_report("could not load kernel '%s'", kernel_filename);
obj-y += sclpcpu.o
obj-y += ipl.o
obj-y += css.o
-obj-y += s390-virtio-ccw.o
+obj-$(CONFIG_S390_CCW_VIRTIO) += s390-virtio-ccw.o
obj-y += 3270-ccw.o
obj-y += virtio-ccw.o
obj-$(CONFIG_VIRTIO_SERIAL) += virtio-ccw-serial.o
obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock-ccw.o
obj-y += css-bridge.o
obj-y += ccw-device.o
-obj-$(CONFIG_PCI) += s390-pci-bus.o s390-pci-inst.o
-obj-$(call lnot,$(CONFIG_PCI)) += s390-pci-stub.o
+obj-y += s390-pci-bus.o s390-pci-inst.o
obj-y += s390-skeys.o
obj-y += s390-stattrib.o
obj-y += tod.o
cbus = VIRTUAL_CSS_BUS(bus);
/* Enable hotplugging */
- qbus_set_hotplug_handler(bus, dev, &error_abort);
+ qbus_set_hotplug_handler(bus, OBJECT(dev), &error_abort);
css_register_io_adapters(CSS_IO_ADAPTER_VIRTIO, true, false,
0, &error_abort);
goto error;
}
- bios_size = load_elf(bios_filename, bios_translate_addr, &fwbase,
+ bios_size = load_elf(bios_filename, NULL,
+ bios_translate_addr, &fwbase,
&ipl->bios_start_addr, NULL, NULL, 1,
EM_S390, 0, 0);
if (bios_size > 0) {
}
if (ipl->kernel) {
- kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL,
+ kernel_size = load_elf(ipl->kernel, NULL, NULL, NULL,
+ &pentry, NULL,
NULL, 1, EM_S390, 0, 0);
if (kernel_size < 0) {
kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
goto unref_mr;
}
- img_size = load_elf_ram(netboot_filename, NULL, NULL, &ipl->start_addr,
+ img_size = load_elf_ram(netboot_filename, NULL, NULL, NULL,
+ &ipl->start_addr,
NULL, NULL, 1, EM_S390, 0, 0, NULL, false);
if (img_size < 0) {
psccb->header.response_code = cpu_to_be16(rc);
}
+static void s390_pci_perform_unplug(S390PCIBusDevice *pbdev)
+{
+ HotplugHandler *hotplug_ctrl;
+
+ /* Unplug the PCI device */
+ if (pbdev->pdev) {
+ hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(pbdev->pdev));
+ hotplug_handler_unplug(hotplug_ctrl, DEVICE(pbdev->pdev),
+ &error_abort);
+ }
+
+ /* Unplug the zPCI device */
+ hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(pbdev));
+ hotplug_handler_unplug(hotplug_ctrl, DEVICE(pbdev), &error_abort);
+}
+
void s390_pci_sclp_deconfigure(SCCB *sccb)
{
IoaCfgSccb *psccb = (IoaCfgSccb *)sccb;
pbdev->state = ZPCI_FS_STANDBY;
rc = SCLP_RC_NORMAL_COMPLETION;
- if (pbdev->release_timer) {
- qdev_unplug(DEVICE(pbdev->pdev), NULL);
+ if (pbdev->unplug_requested) {
+ s390_pci_perform_unplug(pbdev);
}
}
out:
return NULL;
}
+static S390PCIBusDevice *s390_pci_find_dev_by_pci(S390pciState *s,
+ PCIDevice *pci_dev)
+{
+ S390PCIBusDevice *pbdev;
+
+ if (!pci_dev) {
+ return NULL;
+ }
+
+ QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
+ if (pbdev->pdev == pci_dev) {
+ return pbdev;
+ }
+ }
+
+ return NULL;
+}
+
S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx)
{
return g_hash_table_lookup(s->zpci_table, &idx);
pci_setup_iommu(b, s390_pci_dma_iommu, s);
bus = BUS(b);
- qbus_set_hotplug_handler(bus, dev, &local_err);
+ qbus_set_hotplug_handler(bus, OBJECT(dev), &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
phb->bus = b;
s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, dev, NULL));
- qbus_set_hotplug_handler(BUS(s->bus), dev, &local_err);
+ qbus_set_hotplug_handler(BUS(s->bus), OBJECT(dev), &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
{
S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev);
+ if (!s390_has_feat(S390_FEAT_ZPCI)) {
+ warn_report("Plugging a PCI/zPCI device without the 'zpci' CPU "
+ "feature enabled; the guest will not be able to see/use "
+ "this device");
+ }
+
if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
PCIDevice *pdev = PCI_DEVICE(dev);
}
}
+static void s390_pci_update_subordinate(PCIDevice *dev, uint32_t nr)
+{
+ uint32_t old_nr;
+
+ pci_default_write_config(dev, PCI_SUBORDINATE_BUS, nr, 1);
+ while (!pci_bus_is_root(pci_get_bus(dev))) {
+ dev = pci_get_bus(dev)->parent_dev;
+
+ old_nr = pci_default_read_config(dev, PCI_SUBORDINATE_BUS, 1);
+ if (old_nr < nr) {
+ pci_default_write_config(dev, PCI_SUBORDINATE_BUS, nr, 1);
+ }
+ }
+}
+
static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
S390PCIBusDevice *pbdev = NULL;
if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
- BusState *bus;
PCIBridge *pb = PCI_BRIDGE(dev);
- PCIDevice *pdev = PCI_DEVICE(dev);
+ pdev = PCI_DEVICE(dev);
pci_bridge_map_irq(pb, dev->id, s390_pci_map_irq);
pci_setup_iommu(&pb->sec_bus, s390_pci_dma_iommu, s);
- bus = BUS(&pb->sec_bus);
- qbus_set_hotplug_handler(bus, DEVICE(s), errp);
+ qbus_set_hotplug_handler(BUS(&pb->sec_bus), OBJECT(s), errp);
if (dev->hotplugged) {
- pci_default_write_config(pdev, PCI_PRIMARY_BUS, s->bus_no, 1);
+ pci_default_write_config(pdev, PCI_PRIMARY_BUS,
+ pci_dev_bus_num(pdev), 1);
s->bus_no += 1;
pci_default_write_config(pdev, PCI_SECONDARY_BUS, s->bus_no, 1);
- do {
- pdev = pci_get_bus(pdev)->parent_dev;
- pci_default_write_config(pdev, PCI_SUBORDINATE_BUS,
- s->bus_no, 1);
- } while (pci_get_bus(pdev) && pci_dev_bus_num(pdev));
+
+ s390_pci_update_subordinate(pdev, s->bus_no);
}
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
pdev = PCI_DEVICE(dev);
}
}
-static void s390_pcihost_timer_cb(void *opaque)
+static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp)
{
- S390PCIBusDevice *pbdev = opaque;
+ S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev);
+ S390PCIBusDevice *pbdev = NULL;
- if (pbdev->summary_ind) {
- pci_dereg_irqs(pbdev);
- }
- if (pbdev->iommu->enabled) {
- pci_dereg_ioat(pbdev->iommu);
- }
+ if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
+ PCIDevice *pci_dev = PCI_DEVICE(dev);
+ PCIBus *bus;
+ int32_t devfn;
- pbdev->state = ZPCI_FS_STANDBY;
- s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES,
- pbdev->fh, pbdev->fid);
- qdev_unplug(DEVICE(pbdev), NULL);
+ pbdev = s390_pci_find_dev_by_pci(s, PCI_DEVICE(dev));
+ g_assert(pbdev);
+
+ s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED,
+ pbdev->fh, pbdev->fid);
+ bus = pci_get_bus(pci_dev);
+ devfn = pci_dev->devfn;
+ object_unparent(OBJECT(pci_dev));
+
+ s390_pci_msix_free(pbdev);
+ s390_pci_iommu_free(s, bus, devfn);
+ pbdev->pdev = NULL;
+ pbdev->state = ZPCI_FS_RESERVED;
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) {
+ pbdev = S390_PCI_DEVICE(dev);
+ pbdev->fid = 0;
+ QTAILQ_REMOVE(&s->zpci_devs, pbdev, link);
+ g_hash_table_remove(s->zpci_table, &pbdev->idx);
+ object_unparent(OBJECT(pbdev));
+ }
}
-static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
- Error **errp)
+static void s390_pcihost_unplug_request(HotplugHandler *hotplug_dev,
+ DeviceState *dev,
+ Error **errp)
{
S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev);
- PCIDevice *pci_dev = NULL;
- PCIBus *bus;
- int32_t devfn;
- S390PCIBusDevice *pbdev = NULL;
+ S390PCIBusDevice *pbdev;
if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
error_setg(errp, "PCI bridge hot unplug currently not supported");
- return;
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
- pci_dev = PCI_DEVICE(dev);
-
- QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
- if (pbdev->pdev == pci_dev) {
- break;
- }
- }
- assert(pbdev != NULL);
+ /*
+ * Redirect the unplug request to the zPCI device and remember that
+ * we've checked the PCI device already (to prevent endless recursion).
+ */
+ pbdev = s390_pci_find_dev_by_pci(s, PCI_DEVICE(dev));
+ g_assert(pbdev);
+ pbdev->pci_unplug_request_processed = true;
+ qdev_unplug(DEVICE(pbdev), errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) {
pbdev = S390_PCI_DEVICE(dev);
- pci_dev = pbdev->pdev;
- } else {
- g_assert_not_reached();
- }
- switch (pbdev->state) {
- case ZPCI_FS_RESERVED:
- goto out;
- case ZPCI_FS_STANDBY:
- break;
- default:
- if (pbdev->release_timer) {
+ /*
+ * If unplug was initially requested for the zPCI device, we
+ * first have to redirect to the PCI device, which will in return
+ * redirect back to us after performing its checks (if the request
+ * is not blocked, e.g. because it's a PCI bridge).
+ */
+ if (pbdev->pdev && !pbdev->pci_unplug_request_processed) {
+ qdev_unplug(DEVICE(pbdev->pdev), errp);
return;
}
- s390_pci_generate_plug_event(HP_EVENT_DECONFIGURE_REQUEST,
- pbdev->fh, pbdev->fid);
- pbdev->release_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
- s390_pcihost_timer_cb,
- pbdev);
- timer_mod(pbdev->release_timer,
- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + HOT_UNPLUG_TIMEOUT);
- return;
- }
+ pbdev->pci_unplug_request_processed = false;
- if (pbdev->release_timer) {
- timer_del(pbdev->release_timer);
- timer_free(pbdev->release_timer);
- pbdev->release_timer = NULL;
+ switch (pbdev->state) {
+ case ZPCI_FS_STANDBY:
+ case ZPCI_FS_RESERVED:
+ s390_pci_perform_unplug(pbdev);
+ break;
+ default:
+ /*
+ * Allow to send multiple requests, e.g. if the guest crashed
+ * before releasing the device, we would not be able to send
+ * another request to the same VM (e.g. fresh OS).
+ */
+ pbdev->unplug_requested = true;
+ s390_pci_generate_plug_event(HP_EVENT_DECONFIGURE_REQUEST,
+ pbdev->fh, pbdev->fid);
+ }
+ } else {
+ g_assert_not_reached();
}
-
- s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED,
- pbdev->fh, pbdev->fid);
- bus = pci_get_bus(pci_dev);
- devfn = pci_dev->devfn;
- object_unparent(OBJECT(pci_dev));
- fmb_timer_free(pbdev);
- s390_pci_msix_free(pbdev);
- s390_pci_iommu_free(s, bus, devfn);
- pbdev->pdev = NULL;
- pbdev->state = ZPCI_FS_RESERVED;
-out:
- pbdev->fid = 0;
- QTAILQ_REMOVE(&s->zpci_devs, pbdev, link);
- g_hash_table_remove(s->zpci_table, &pbdev->idx);
- object_unparent(OBJECT(pbdev));
}
static void s390_pci_enumerate_bridge(PCIBus *bus, PCIDevice *pdev,
void *opaque)
{
S390pciState *s = opaque;
- unsigned int primary = s->bus_no;
- unsigned int subordinate = 0xff;
PCIBus *sec_bus = NULL;
if ((pci_default_read_config(pdev, PCI_HEADER_TYPE, 1) !=
}
(s->bus_no)++;
- pci_default_write_config(pdev, PCI_PRIMARY_BUS, primary, 1);
+ pci_default_write_config(pdev, PCI_PRIMARY_BUS, pci_dev_bus_num(pdev), 1);
pci_default_write_config(pdev, PCI_SECONDARY_BUS, s->bus_no, 1);
pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, s->bus_no, 1);
return;
}
- pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, subordinate, 1);
+ /* Assign numbers to all child bridges. The last is the highest number. */
pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
s390_pci_enumerate_bridge, s);
pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, s->bus_no, 1);
{
S390pciState *s = S390_PCI_HOST_BRIDGE(dev);
PCIBus *bus = s->parent_obj.bus;
+ S390PCIBusDevice *pbdev, *next;
+
+ /* Process all pending unplug requests */
+ QTAILQ_FOREACH_SAFE(pbdev, &s->zpci_devs, link, next) {
+ if (pbdev->unplug_requested) {
+ if (pbdev->summary_ind) {
+ pci_dereg_irqs(pbdev);
+ }
+ if (pbdev->iommu->enabled) {
+ pci_dereg_ioat(pbdev->iommu);
+ }
+ pbdev->state = ZPCI_FS_STANDBY;
+ s390_pci_perform_unplug(pbdev);
+ }
+ }
+ /*
+ * When resetting a PCI bridge, the assigned numbers are set to 0. So
+ * on every system reset, we also have to reassign numbers.
+ */
s->bus_no = 0;
pci_for_each_device(bus, pci_bus_num(bus), s390_pci_enumerate_bridge, s);
}
dc->realize = s390_pcihost_realize;
hc->pre_plug = s390_pcihost_pre_plug;
hc->plug = s390_pcihost_plug;
+ hc->unplug_request = s390_pcihost_unplug_request;
hc->unplug = s390_pcihost_unplug;
msi_nonbroken = true;
}
DEFINE_PROP_END_OF_LIST(),
};
+static const VMStateDescription s390_pci_device_vmstate = {
+ .name = TYPE_S390_PCI_DEVICE,
+ /*
+ * TODO: add state handling here, so migration works at least with
+ * emulated pci devices on s390x
+ */
+ .unmigratable = 1,
+};
+
static void s390_pci_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->bus_type = TYPE_S390_PCI_BUS;
dc->realize = s390_pci_device_realize;
dc->props = s390_pci_device_properties;
+ dc->vmsd = &s390_pci_device_vmstate;
}
static const TypeInfo s390_pci_device_info = {
#define ZPCI_MAX_UID 0xffff
#define UID_UNDEFINED 0
#define UID_CHECKING_ENABLED 0x01
-#define HOT_UNPLUG_TIMEOUT (NANOSECONDS_PER_SECOND * 60 * 5)
#define S390_PCI_HOST_BRIDGE(obj) \
OBJECT_CHECK(S390pciState, (obj), TYPE_S390_PCI_HOST_BRIDGE)
MemoryRegion msix_notify_mr;
IndAddr *summary_ind;
IndAddr *indicator;
- QEMUTimer *release_timer;
+ bool pci_unplug_request_processed;
+ bool unplug_requested;
QTAILQ_ENTRY(S390PCIBusDevice) link;
};
+++ /dev/null
-/* stubs for non-pci builds */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "cpu.h"
-#include "s390-pci-inst.h"
-#include "s390-pci-bus.h"
-
-/* target/s390x/ioinst.c */
-int pci_chsc_sei_nt2_get_event(void *res)
-{
- return 1;
-}
-
-int pci_chsc_sei_nt2_have_event(void)
-{
- return 0;
-}
-
-/* hw/s390x/sclp.c */
-void s390_pci_sclp_configure(SCCB *sccb)
-{
- sccb->h.response_code = cpu_to_be16(SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED);
-}
-
-void s390_pci_sclp_deconfigure(SCCB *sccb)
-{
- sccb->h.response_code = cpu_to_be16(SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED);
-}
-
-/* target/s390x/kvm.c */
-int clp_service_call(S390CPU *cpu, uint8_t r2)
-{
- return -1;
-}
-
-int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
-{
- return -1;
-}
-
-int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
-{
- return -1;
-}
-
-int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
-{
- return -1;
-}
-
-int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
-{
- return -1;
-}
-
-int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
- uint8_t ar)
-{
- return -1;
-}
-
-int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
-{
- return -1;
-}
-
-S390pciState *s390_get_phb(void)
-{
- return NULL;
-}
-
-S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s,
- const char *target)
-{
- return NULL;
-}
#include "hw/boards.h"
#include "hw/s390x/storage-keys.h"
#include "qapi/error.h"
-#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-commands-target.h"
#include "qapi/qmp/qdict.h"
#include "qemu/error-report.h"
#include "sysemu/kvm.h"
machine->initrd_filename, "s390-ccw.img",
"s390-netboot.img", true);
- /*
- * We cannot easily make the pci host bridge conditional as older QEMUs
- * always created it. Doing so would break migration across QEMU versions.
- */
dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE);
object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE,
OBJECT(dev), NULL);
static void ccw_machine_3_1_instance_options(MachineState *machine)
{
+ static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V3_1 };
ccw_machine_4_0_instance_options(machine);
+ s390_cpudef_featoff_greater(14, 1, S390_FEAT_MULTIPLE_EPOCH);
+ s390_cpudef_group_featoff_greater(14, 1, S390_FEAT_GROUP_MULTIPLE_EPOCH_PTFF);
+ s390_set_qemu_cpu_model(0x2827, 12, 2, qemu_cpu_feat);
}
static void ccw_machine_3_1_class_options(MachineClass *mc)
* the host adapter emulator.
*/
-//#define DEBUG_SCSI
-
-#ifdef DEBUG_SCSI
-#define DPRINTF(fmt, ...) \
-do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#endif
-
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "qapi/error.h"
#include "hw/block/block.h"
#include "sysemu/dma.h"
#include "qemu/cutils.h"
+#include "trace.h"
#ifdef __linux
#include <scsi/sg.h>
/* Helper function for command completion with sense. */
static void scsi_check_condition(SCSIDiskReq *r, SCSISense sense)
{
- DPRINTF("Command complete tag=0x%x sense=%d/%d/%d\n",
- r->req.tag, sense.key, sense.asc, sense.ascq);
+ trace_scsi_disk_check_condition(r->req.tag, sense.key, sense.asc,
+ sense.ascq);
scsi_req_build_sense(&r->req, sense);
scsi_req_complete(&r->req, CHECK_CONDITION);
}
}
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
- DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->qiov.size);
+ trace_scsi_disk_read_complete(r->req.tag, r->qiov.size);
n = r->qiov.size / 512;
r->sector += n;
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
bool first;
- DPRINTF("Read sector_count=%d\n", r->sector_count);
+ trace_scsi_disk_read_data_count(r->sector_count);
if (r->sector_count == 0) {
/* This also clears the sense buffer for REQUEST SENSE. */
scsi_req_complete(&r->req, GOOD);
/* The request is used as the AIO opaque value, so add a ref. */
scsi_req_ref(&r->req);
if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
- DPRINTF("Data transfer direction invalid\n");
+ trace_scsi_disk_read_data_invalid();
scsi_read_complete(r, -EINVAL);
return;
}
return;
} else {
scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
- DPRINTF("Write complete tag=0x%x more=%zd\n", r->req.tag, r->qiov.size);
+ trace_scsi_disk_write_complete_noio(r->req.tag, r->qiov.size);
scsi_req_data(&r->req, r->qiov.size);
}
/* The request is used as the AIO opaque value, so add a ref. */
scsi_req_ref(&r->req);
if (r->req.cmd.mode != SCSI_XFER_TO_DEV) {
- DPRINTF("Data transfer direction invalid\n");
+ trace_scsi_disk_write_data_invalid();
scsi_write_complete_noio(r, -EINVAL);
return;
}
switch (page_code) {
case 0x00: /* Supported page codes, mandatory */
{
- DPRINTF("Inquiry EVPD[Supported pages] "
- "buffer size %zd\n", req->cmd.xfer);
+ trace_scsi_disk_emulate_vpd_page_00(req->cmd.xfer);
outbuf[buflen++] = 0x00; /* list of supported pages (this page) */
if (s->serial) {
outbuf[buflen++] = 0x80; /* unit serial number */
int l;
if (!s->serial) {
- DPRINTF("Inquiry (EVPD[Serial number] not supported\n");
+ trace_scsi_disk_emulate_vpd_page_80_not_supported();
return -1;
}
l = 36;
}
- DPRINTF("Inquiry EVPD[Serial number] "
- "buffer size %zd\n", req->cmd.xfer);
+ trace_scsi_disk_emulate_vpd_page_80(req->cmd.xfer);
memcpy(outbuf + buflen, s->serial, l);
buflen += l;
break;
{
int id_len = s->device_id ? MIN(strlen(s->device_id), 255 - 8) : 0;
- DPRINTF("Inquiry EVPD[Device identification] "
- "buffer size %zd\n", req->cmd.xfer);
+ trace_scsi_disk_emulate_vpd_page_83(req->cmd.xfer);
if (id_len) {
outbuf[buflen++] = 0x2; /* ASCII */
SCSIBlockLimits bl = {};
if (s->qdev.type == TYPE_ROM) {
- DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
- page_code);
+ trace_scsi_disk_emulate_vpd_page_b0_not_supported();
return -1;
}
bl.wsnz = 1;
dbd = (r->req.cmd.buf[1] & 0x8) != 0;
page = r->req.cmd.buf[2] & 0x3f;
page_control = (r->req.cmd.buf[2] & 0xc0) >> 6;
- DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",
- (r->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, r->req.cmd.xfer, page_control);
+
+ trace_scsi_disk_emulate_mode_sense((r->req.cmd.buf[0] == MODE_SENSE) ? 6 :
+ 10, page, r->req.cmd.xfer, page_control);
memset(outbuf, 0, r->req.cmd.xfer);
p = outbuf;
format = req->cmd.buf[2] & 0xf;
start_track = req->cmd.buf[6];
blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
- DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
+ trace_scsi_disk_emulate_read_toc(start_track, format, msf >> 1);
nb_sectors /= s->qdev.blocksize / 512;
switch (format) {
case 0:
int buflen = r->iov.iov_len;
if (buflen) {
- DPRINTF("Read buf_len=%d\n", buflen);
+ trace_scsi_disk_emulate_read_data(buflen);
r->iov.iov_len = 0;
r->started = true;
scsi_req_data(&r->req, buflen);
if (r->iov.iov_len) {
int buflen = r->iov.iov_len;
- DPRINTF("Write buf_len=%d\n", buflen);
+ trace_scsi_disk_emulate_write_data(buflen);
r->iov.iov_len = 0;
scsi_req_data(&r->req, buflen);
return;
case SERVICE_ACTION_IN_16:
/* Service Action In subcommands. */
if ((req->cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
- DPRINTF("SAI READ CAPACITY(16)\n");
+ trace_scsi_disk_emulate_command_SAI_16();
memset(outbuf, 0, req->cmd.xfer);
blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
if (!nb_sectors) {
/* Protection, exponent and lowest lba field left blank. */
break;
}
- DPRINTF("Unsupported Service Action In\n");
+ trace_scsi_disk_emulate_command_SAI_unsupported();
goto illegal_request;
case SYNCHRONIZE_CACHE:
/* The request is used as the AIO opaque value, so add a ref. */
r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_aio_complete, r);
return 0;
case SEEK_10:
- DPRINTF("Seek(10) (sector %" PRId64 ")\n", r->req.cmd.lba);
+ trace_scsi_disk_emulate_command_SEEK_10(r->req.cmd.lba);
if (r->req.cmd.lba > s->qdev.max_lba) {
goto illegal_lba;
}
break;
case MODE_SELECT:
- DPRINTF("Mode Select(6) (len %lu)\n", (unsigned long)r->req.cmd.xfer);
+ trace_scsi_disk_emulate_command_MODE_SELECT(r->req.cmd.xfer);
break;
case MODE_SELECT_10:
- DPRINTF("Mode Select(10) (len %lu)\n", (unsigned long)r->req.cmd.xfer);
+ trace_scsi_disk_emulate_command_MODE_SELECT_10(r->req.cmd.xfer);
break;
case UNMAP:
- DPRINTF("Unmap (len %lu)\n", (unsigned long)r->req.cmd.xfer);
+ trace_scsi_disk_emulate_command_UNMAP(r->req.cmd.xfer);
break;
case VERIFY_10:
case VERIFY_12:
case VERIFY_16:
- DPRINTF("Verify (bytchk %d)\n", (req->cmd.buf[1] >> 1) & 3);
+ trace_scsi_disk_emulate_command_VERIFY((req->cmd.buf[1] >> 1) & 3);
if (req->cmd.buf[1] & 6) {
goto illegal_request;
}
break;
case WRITE_SAME_10:
case WRITE_SAME_16:
- DPRINTF("WRITE SAME %d (len %lu)\n",
- req->cmd.buf[0] == WRITE_SAME_10 ? 10 : 16,
- (unsigned long)r->req.cmd.xfer);
+ trace_scsi_disk_emulate_command_WRITE_SAME(
+ req->cmd.buf[0] == WRITE_SAME_10 ? 10 : 16, r->req.cmd.xfer);
break;
default:
- DPRINTF("Unknown SCSI command (%2.2x=%s)\n", buf[0],
- scsi_command_name(buf[0]));
+ trace_scsi_disk_emulate_command_UNKNOWN(buf[0],
+ scsi_command_name(buf[0]));
scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
return 0;
}
case READ_10:
case READ_12:
case READ_16:
- DPRINTF("Read (sector %" PRId64 ", count %u)\n", r->req.cmd.lba, len);
+ trace_scsi_disk_dma_command_READ(r->req.cmd.lba, len);
/* Protection information is not supported. For SCSI versions 2 and
* older (as determined by snooping the guest's INQUIRY commands),
* there is no RD/WR/VRPROTECT, so skip this check in these versions.
scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
return 0;
}
- DPRINTF("Write %s(sector %" PRId64 ", count %u)\n",
+ trace_scsi_disk_dma_command_WRITE(
(command & 0xe) == 0xe ? "And Verify " : "",
r->req.cmd.lba, len);
/* fall through */
[WRITE_VERIFY_16] = &scsi_disk_dma_reqops,
};
+static void scsi_disk_new_request_dump(uint32_t lun, uint32_t tag, uint8_t *buf)
+{
+ int i;
+ int len = scsi_cdb_length(buf);
+ char *line_buffer, *p;
+
+ line_buffer = g_malloc(len * 5 + 1);
+
+ for (i = 0, p = line_buffer; i < len; i++) {
+ p += sprintf(p, " 0x%02x", buf[i]);
+ }
+ trace_scsi_disk_new_request(lun, tag, line_buffer);
+
+ g_free(line_buffer);
+}
+
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
uint8_t *buf, void *hba_private)
{
}
req = scsi_req_alloc(ops, &s->qdev, tag, lun, hba_private);
-#ifdef DEBUG_SCSI
- DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
- {
- int i;
- for (i = 1; i < scsi_cdb_length(buf); i++) {
- printf(" 0x%02x", buf[i]);
- }
- printf("\n");
+ if (trace_event_get_state_backends(TRACE_SCSI_DISK_NEW_REQUEST)) {
+ scsi_disk_new_request_dump(lun, tag, buf);
}
-#endif
return req;
}
#include "hw/scsi/scsi.h"
#include "hw/scsi/emulation.h"
#include "sysemu/block-backend.h"
+#include "trace.h"
#ifdef __linux__
-//#define DEBUG_SCSI
-
-#ifdef DEBUG_SCSI
-#define DPRINTF(fmt, ...) \
-do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#endif
-
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
-
#include <scsi/sg.h>
#include "scsi/constants.h"
}
}
- DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
- r, r->req.tag, status);
+ trace_scsi_generic_command_complete_noio(r, r->req.tag, status);
scsi_req_complete(&r->req, status);
done:
/* Also take care of the opt xfer len. */
stl_be_p(&r->buf[12],
MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12])));
- } else if (s->needs_vpd_bl_emulation && page == 0x00) {
+ } else if (s->needs_vpd_bl_emulation && page == 0x00 && r->buflen >= 4) {
/*
* Now we're capable of supplying the VPD Block Limits
* response if the hardware can't. Add it in the INQUIRY
* and will use it to proper setup the SCSI device.
*
* VPD page numbers must be sorted, so insert 0xb0 at the
- * right place with an in-place insert. After the initialization
- * part of the for loop is executed, the device response is
- * at r[0] to r[page_idx - 1].
+ * right place with an in-place insert. When the while loop
+ * begins the device response is at r[0] to r[page_idx - 1].
*/
- for (page_idx = lduw_be_p(r->buf + 2) + 4;
- page_idx > 4 && r->buf[page_idx - 1] >= 0xb0;
- page_idx--) {
+ page_idx = lduw_be_p(r->buf + 2) + 4;
+ page_idx = MIN(page_idx, r->buflen);
+ while (page_idx > 4 && r->buf[page_idx - 1] >= 0xb0) {
if (page_idx < r->buflen) {
r->buf[page_idx] = r->buf[page_idx - 1];
}
+ page_idx--;
+ }
+ if (page_idx < r->buflen) {
+ r->buf[page_idx] = 0xb0;
}
- r->buf[page_idx] = 0xb0;
stw_be_p(r->buf + 2, lduw_be_p(r->buf + 2) + 1);
}
}
}
len = r->io_header.dxfer_len - r->io_header.resid;
- DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
+ trace_scsi_generic_read_complete(r->req.tag, len);
r->len = -1;
SCSIDevice *s = r->req.dev;
int ret;
- DPRINTF("scsi_read_data tag=0x%x\n", req->tag);
+ trace_scsi_generic_read_data(req->tag);
/* The request is used as the AIO opaque value, so add a ref. */
scsi_req_ref(&r->req);
SCSIGenericReq *r = (SCSIGenericReq *)opaque;
SCSIDevice *s = r->req.dev;
- DPRINTF("scsi_write_complete() ret = %d\n", ret);
+ trace_scsi_generic_write_complete(ret);
assert(r->req.aiocb != NULL);
r->req.aiocb = NULL;
if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
s->type == TYPE_TAPE) {
s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
- DPRINTF("block size %d\n", s->blocksize);
+ trace_scsi_generic_write_complete_blocksize(s->blocksize);
}
scsi_command_complete_noio(r, ret);
SCSIDevice *s = r->req.dev;
int ret;
- DPRINTF("scsi_write_data tag=0x%x\n", req->tag);
+ trace_scsi_generic_write_data(req->tag);
if (r->len == 0) {
r->len = r->buflen;
scsi_req_data(&r->req, r->len);
return r->buf;
}
+static void scsi_generic_command_dump(uint8_t *cmd, int len)
+{
+ int i;
+ char *line_buffer, *p;
+
+ line_buffer = g_malloc(len * 5 + 1);
+
+ for (i = 0, p = line_buffer; i < len; i++) {
+ p += sprintf(p, " 0x%02x", cmd[i]);
+ }
+ trace_scsi_generic_send_command(line_buffer);
+
+ g_free(line_buffer);
+}
+
/* Execute a scsi command. Returns the length of the data expected by the
command. This will be Positive for data transfers from the device
(eg. disk reads), negative for transfers to the device (eg. disk writes),
SCSIDevice *s = r->req.dev;
int ret;
-#ifdef DEBUG_SCSI
- DPRINTF("Command: data=0x%02x", cmd[0]);
- {
- int i;
- for (i = 1; i < r->req.cmd.len; i++) {
- printf(" 0x%02x", cmd[i]);
- }
- printf("\n");
+ if (trace_event_get_state_backends(TRACE_SCSI_GENERIC_SEND_COMMAND)) {
+ scsi_generic_command_dump(cmd, r->req.cmd.len);
}
-#endif
if (r->req.cmd.xfer == 0) {
g_free(r->buf);
/* define device state */
s->type = scsiid.scsi_type;
- DPRINTF("device type %d\n", s->type);
+ trace_scsi_generic_realize_type(s->type);
switch (s->type) {
case TYPE_TAPE:
break;
}
- DPRINTF("block size %d\n", s->blocksize);
+ trace_scsi_generic_realize_blocksize(s->blocksize);
/* Only used by scsi-block, but initialize it nevertheless to be clean. */
s->default_scsi_version = -1;
lsi_awoken(void) "Woken by SIGP"
lsi_reg_read(const char *name, int offset, uint8_t ret) "Read reg %s 0x%x = 0x%02x"
lsi_reg_write(const char *name, int offset, uint8_t val) "Write reg %s 0x%x = 0x%02x"
+
+# hw/scsi/scsi-disk.c
+scsi_disk_check_condition(uint32_t tag, uint8_t key, uint8_t asc, uint8_t ascq) "Command complete tag=0x%x sense=%d/%d/%d"
+scsi_disk_read_complete(uint32_t tag, size_t size) "Data ready tag=0x%x len=%zd"
+scsi_disk_read_data_count(uint32_t sector_count) "Read sector_count=%d"
+scsi_disk_read_data_invalid(void) "Data transfer direction invalid"
+scsi_disk_write_complete_noio(uint32_t tag, size_t size) "Write complete tag=0x%x more=%zd"
+scsi_disk_write_data_invalid(void) "Data transfer direction invalid"
+scsi_disk_emulate_vpd_page_00(size_t xfer) "Inquiry EVPD[Supported pages] buffer size %zd"
+scsi_disk_emulate_vpd_page_80_not_supported(void) "Inquiry (EVPD[Serial number] not supported"
+scsi_disk_emulate_vpd_page_80(size_t xfer) "Inquiry EVPD[Serial number] buffer size %zd"
+scsi_disk_emulate_vpd_page_83(size_t xfer) "Inquiry EVPD[Device identification] buffer size %zd"
+scsi_disk_emulate_vpd_page_b0_not_supported(void) "Inquiry (EVPD[Block limits] not supported for CDROM"
+scsi_disk_emulate_mode_sense(int cmd, int page, size_t xfer, int control) "Mode Sense(%d) (page %d, xfer %zd, page_control %d)"
+scsi_disk_emulate_read_toc(int start_track, int format, int msf) "Read TOC (track %d format %d msf %d)"
+scsi_disk_emulate_read_data(int buflen) "Read buf_len=%d"
+scsi_disk_emulate_write_data(int buflen) "Write buf_len=%d"
+scsi_disk_emulate_command_SAI_16(void) "SAI READ CAPACITY(16)"
+scsi_disk_emulate_command_SAI_unsupported(void) "Unsupported Service Action In"
+scsi_disk_emulate_command_SEEK_10(uint64_t lba) "Seek(10) (sector %" PRId64 ")"
+scsi_disk_emulate_command_MODE_SELECT(size_t xfer) "Mode Select(6) (len %zd)"
+scsi_disk_emulate_command_MODE_SELECT_10(size_t xfer) "Mode Select(10) (len %zd)"
+scsi_disk_emulate_command_UNMAP(size_t xfer) "Unmap (len %zd)"
+scsi_disk_emulate_command_VERIFY(int bytchk) "Verify (bytchk %d)"
+scsi_disk_emulate_command_WRITE_SAME(int cmd, size_t xfer) "WRITE SAME %d (len %zd)"
+scsi_disk_emulate_command_UNKNOWN(int cmd, const char *name) "Unknown SCSI command (0x%2.2x=%s)"
+scsi_disk_dma_command_READ(uint64_t lba, uint32_t len) "Read (sector %" PRId64 ", count %u)"
+scsi_disk_dma_command_WRITE(const char *cmd, uint64_t lba, int len) "Write %s(sector %" PRId64 ", count %u)"
+scsi_disk_new_request(uint32_t lun, uint32_t tag, const char *line) "Command: lun=%d tag=0x%x data=%s"
+
+# hw/scsi/scsi-generic.c
+scsi_generic_command_complete_noio(void *req, uint32_t tag, int statuc) "Command complete %p tag=0x%x status=%d"
+scsi_generic_read_complete(uint32_t tag, int len) "Data ready tag=0x%x len=%d"
+scsi_generic_read_data(uint32_t tag) "scsi_read_data tag=0x%x"
+scsi_generic_write_complete(int ret) "scsi_write_complete() ret = %d"
+scsi_generic_write_complete_blocksize(int blocksize) "block size %d"
+scsi_generic_write_data(uint32_t tag) "scsi_write_data tag=0x%x"
+scsi_generic_send_command(const char *line) "Command: data=%s"
+scsi_generic_realize_type(int type) "device type %d"
+scsi_generic_realize_blocksize(int blocksize) "block size %d"
scsi_bus_new(&s->bus, sizeof(s->bus), dev,
&virtio_scsi_scsi_info, vdev->bus_name);
/* override default SCSI bus hotplug-handler, with virtio-scsi's one */
- qbus_set_hotplug_handler(BUS(&s->bus), dev, &error_abort);
+ qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev), &error_abort);
virtio_scsi_dataplane_setup(s, errp);
}
scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(pci_dev),
&pvscsi_scsi_info, NULL);
/* override default SCSI bus hotplug-handler, with pvscsi's one */
- qbus_set_hotplug_handler(BUS(&s->bus), DEVICE(s), &error_abort);
+ qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(s), &error_abort);
pvscsi_reset_state(s);
}
-obj-y += shix.o r2d.o
-
obj-y += sh7750.o sh7750_regnames.o
obj-y += sh_pci.o
+obj-$(CONFIG_R2D) += r2d.o
+obj-$(CONFIG_SHIX) += shix.o
char pad[232];
- char kernel_cmdline[256];
+ char kernel_cmdline[256] QEMU_NONSTRING;
} boot_params;
static void r2d_init(MachineState *machine)
-obj-y += sun4m_iommu.o sun4m.o leon3.o
+obj-$(CONFIG_SUN4M) += sun4m_iommu.o
+obj-$(CONFIG_SUN4M) += sun4m.o
+obj-$(CONFIG_LEON3) += leon3.o
long kernel_size;
uint64_t entry;
- kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
+ &entry, NULL, NULL,
1 /* big endian */, EM_SPARC, 0, 0);
if (kernel_size < 0) {
error_report("could not load kernel '%s'", kernel_filename);
static unsigned long sun4m_load_kernel(const char *kernel_filename,
const char *initrd_filename,
- ram_addr_t RAM_size)
+ ram_addr_t RAM_size,
+ uint32_t *initrd_size)
{
int linux_boot;
unsigned int i;
- long initrd_size, kernel_size;
+ long kernel_size;
uint8_t *ptr;
linux_boot = (kernel_filename != NULL);
#else
bswap_needed = 0;
#endif
- kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+ kernel_size = load_elf(kernel_filename, NULL,
+ translate_kernel_address, NULL,
NULL, NULL, NULL, 1, EM_SPARC, 0, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
}
/* load initrd */
- initrd_size = 0;
+ *initrd_size = 0;
if (initrd_filename) {
- initrd_size = load_image_targphys(initrd_filename,
- INITRD_LOAD_ADDR,
- RAM_size - INITRD_LOAD_ADDR);
- if (initrd_size < 0) {
+ *initrd_size = load_image_targphys(initrd_filename,
+ INITRD_LOAD_ADDR,
+ RAM_size - INITRD_LOAD_ADDR);
+ if ((int)*initrd_size < 0) {
error_report("could not load initial ram disk '%s'",
initrd_filename);
exit(1);
}
}
- if (initrd_size > 0) {
+ if (*initrd_size > 0) {
for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
ptr = rom_ptr(KERNEL_LOAD_ADDR + i, 24);
if (ptr && ldl_p(ptr) == 0x48647253) { /* HdrS */
stl_p(ptr + 16, INITRD_LOAD_ADDR);
- stl_p(ptr + 20, initrd_size);
+ stl_p(ptr + 20, *initrd_size);
break;
}
}
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
- ret = load_elf(filename, translate_prom_address, &addr, NULL,
+ ret = load_elf(filename, NULL,
+ translate_prom_address, &addr, NULL,
NULL, NULL, 1, EM_SPARC, 0, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS];
qemu_irq fdc_tc;
unsigned long kernel_size;
+ uint32_t initrd_size;
DriveInfo *fd[MAX_FD];
FWCfgState *fw_cfg;
unsigned int num_vsimms;
empty_slot_init(hwdef->bpp_base, 0x20);
}
+ initrd_size = 0;
kernel_size = sun4m_load_kernel(machine->kernel_filename,
machine->initrd_filename,
- machine->ram_size);
+ machine->ram_size, &initrd_size);
nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, machine->kernel_cmdline,
machine->boot_order, machine->ram_size, kernel_size,
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
}
fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
- fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
+ fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, machine->boot_order[0]);
qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
}
obj-y += sparc64.o
-obj-y += sun4u_iommu.o
-obj-y += sun4u.o
-obj-y += niagara.o
\ No newline at end of file
+obj-$(CONFIG_SUN4U) += sun4u_iommu.o
+obj-$(CONFIG_SUN4U) += sun4u.o
+obj-$(CONFIG_NIAGARA) += niagara.o
#include "hw/pci/pci_bus.h"
#include "hw/pci/pci_host.h"
#include "hw/pci-host/sabre.h"
-#include "hw/i386/pc.h"
#include "hw/char/serial.h"
#include "hw/char/parallel.h"
#include "hw/timer/m48t59.h"
#else
bswap_needed = 0;
#endif
- kernel_size = load_elf(kernel_filename, NULL, NULL, kernel_entry,
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_entry,
kernel_addr, &kernel_top, 1, EM_SPARCV9, 0, 0);
if (kernel_size < 0) {
*kernel_addr = KERNEL_LOAD_ADDR;
} PowerDevice;
/* Power */
+static uint64_t power_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+ return 0;
+}
+
static void power_mem_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
}
static const MemoryRegionOps power_mem_ops = {
+ .read = power_mem_read,
.write = power_mem_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.valid = {
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
- ret = load_elf(filename, translate_prom_address, &addr,
+ ret = load_elf(filename, NULL, translate_prom_address, &addr,
NULL, NULL, NULL, 1, EM_SPARCV9, 0, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 4,
qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_SER_IRQ));
- pci_dev = pci_create_simple(pci_busA, PCI_DEVFN(2, 0), "VGA");
+ switch (vga_interface_type) {
+ case VGA_STD:
+ pci_create_simple(pci_busA, PCI_DEVFN(2, 0), "VGA");
+ break;
+ case VGA_NONE:
+ break;
+ default:
+ abort(); /* Should not happen - types are checked in vl.c already */
+ }
memset(&macaddr, 0, sizeof(MACAddr));
onboard_nic = false;
mc->default_boot_order = "c";
mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-UltraSparc-IIi");
mc->ignore_boot_device_suffixes = true;
+ mc->default_display = "std";
fwc->get_dev_path = sun4u_fw_dev_path;
}
mc->max_cpus = 1; /* XXX for now */
mc->default_boot_order = "c";
mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Sun-UltraSparc-T1");
+ mc->default_display = "std";
}
static const TypeInfo sun4v_type = {
#include "sysemu/replay.h"
#include "hw/timer/mc146818rtc.h"
#include "qapi/error.h"
-#include "qapi/qapi-commands-misc.h"
-#include "qapi/qapi-events-misc.h"
+#include "qapi/qapi-commands-target.h"
+#include "qapi/qapi-events-target.h"
#include "qapi/visitor.h"
#include "exec/address-spaces.h"
*/
#include "qemu/osdep.h"
+#include "hw/timer/pl031.h"
#include "hw/sysbus.h"
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
#include "qemu/cutils.h"
#include "qemu/log.h"
-
-//#define DEBUG_PL031
-
-#ifdef DEBUG_PL031
-#define DPRINTF(fmt, ...) \
-do { printf("pl031: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#endif
+#include "trace.h"
#define RTC_DR 0x00 /* Data read register */
#define RTC_MR 0x04 /* Match register */
#define RTC_MIS 0x18 /* Masked interrupt status register */
#define RTC_ICR 0x1c /* Interrupt clear register */
-#define TYPE_PL031 "pl031"
-#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
-
-typedef struct PL031State {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- QEMUTimer *timer;
- qemu_irq irq;
-
- /* Needed to preserve the tick_count across migration, even if the
- * absolute value of the rtc_clock is different on the source and
- * destination.
- */
- uint32_t tick_offset_vmstate;
- uint32_t tick_offset;
-
- uint32_t mr;
- uint32_t lr;
- uint32_t cr;
- uint32_t im;
- uint32_t is;
-} PL031State;
-
static const unsigned char pl031_id[] = {
0x31, 0x10, 0x14, 0x00, /* Device ID */
0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */
static void pl031_update(PL031State *s)
{
- qemu_set_irq(s->irq, s->is & s->im);
+ uint32_t flags = s->is & s->im;
+
+ trace_pl031_irq_state(flags);
+ qemu_set_irq(s->irq, flags);
}
static void pl031_interrupt(void * opaque)
PL031State *s = (PL031State *)opaque;
s->is = 1;
- DPRINTF("Alarm raised\n");
+ trace_pl031_alarm_raised();
pl031_update(s);
}
/* The timer wraps around. This subtraction also wraps in the same way,
and gives correct results when alarm < now_ticks. */
ticks = s->mr - pl031_get_count(s);
- DPRINTF("Alarm set in %ud ticks\n", ticks);
+ trace_pl031_set_alarm(ticks);
if (ticks == 0) {
timer_del(s->timer);
pl031_interrupt(s);
unsigned size)
{
PL031State *s = (PL031State *)opaque;
-
- if (offset >= 0xfe0 && offset < 0x1000)
- return pl031_id[(offset - 0xfe0) >> 2];
+ uint64_t r;
switch (offset) {
case RTC_DR:
- return pl031_get_count(s);
+ r = pl031_get_count(s);
+ break;
case RTC_MR:
- return s->mr;
+ r = s->mr;
+ break;
case RTC_IMSC:
- return s->im;
+ r = s->im;
+ break;
case RTC_RIS:
- return s->is;
+ r = s->is;
+ break;
case RTC_LR:
- return s->lr;
+ r = s->lr;
+ break;
case RTC_CR:
/* RTC is permanently enabled. */
- return 1;
+ r = 1;
+ break;
case RTC_MIS:
- return s->is & s->im;
+ r = s->is & s->im;
+ break;
+ case 0xfe0 ... 0xfff:
+ r = pl031_id[(offset - 0xfe0) >> 2];
+ break;
case RTC_ICR:
qemu_log_mask(LOG_GUEST_ERROR,
"pl031: read of write-only register at offset 0x%x\n",
(int)offset);
+ r = 0;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"pl031_read: Bad offset 0x%x\n", (int)offset);
+ r = 0;
break;
}
- return 0;
+ trace_pl031_read(offset, r);
+ return r;
}
static void pl031_write(void * opaque, hwaddr offset,
{
PL031State *s = (PL031State *)opaque;
+ trace_pl031_write(offset, value);
switch (offset) {
case RTC_LR:
break;
case RTC_IMSC:
s->im = value & 1;
- DPRINTF("Interrupt mask %d\n", s->im);
pl031_update(s);
break;
case RTC_ICR:
cleared when bit 0 of the written value is set. However the
arm926e documentation (DDI0287B) states that the interrupt is
cleared when any value is written. */
- DPRINTF("Interrupt cleared");
s->is = 0;
pl031_update(s);
break;
nrf51_timer_read(uint64_t addr, uint32_t value, unsigned size) "read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
nrf51_timer_write(uint64_t addr, uint32_t value, unsigned size) "write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
+# hw/timer/pl031.c
+pl031_irq_state(int level) "irq state %d"
+pl031_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
+pl031_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
+pl031_alarm_raised(void) "alarm raised"
+pl031_set_alarm(uint32_t ticks) "alarm set for %u ticks"
-obj-y += tricore_testboard.o
+obj-$(CONFIG_TRICORE) += tricore_testboard.o
long kernel_size;
kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL,
- NULL, &entry, NULL,
+ NULL, NULL, &entry, NULL,
NULL, 0,
EM_TRICORE, 1, 0);
if (kernel_size <= 0) {
#include "ui/console.h"
#include "hw/boards.h"
#include "hw/loader.h"
-#include "hw/i386/pc.h"
#include "sysemu/qtest.h"
#undef DEBUG_PUV3
{
struct USBEndpoint *eps;
- if (dev == NULL) {
- return NULL;
- }
- eps = (pid == USB_TOKEN_IN) ? dev->ep_in : dev->ep_out;
+ assert(dev != NULL);
if (ep == 0) {
return &dev->ep_ctl;
}
assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
assert(ep > 0 && ep <= USB_MAX_ENDPOINTS);
+ eps = (pid == USB_TOKEN_IN) ? dev->ep_in : dev->ep_out;
return eps + ep - 1;
}
#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "qemu/error-report.h"
#include <wchar.h>
#include <dirent.h>
#include <sys/statvfs.h>
-#ifdef CONFIG_INOTIFY1
-#include <sys/inotify.h>
-#include "qemu/main-loop.h"
-#endif
+
#include "qemu-common.h"
#include "qemu/iov.h"
+#include "qemu/filemonitor.h"
#include "trace.h"
#include "hw/usb.h"
#include "desc.h"
EP_EVENT,
};
-#ifdef CONFIG_INOTIFY1
typedef struct MTPMonEntry MTPMonEntry;
struct MTPMonEntry {
QTAILQ_ENTRY(MTPMonEntry) next;
};
-#endif
struct MTPControl {
uint16_t code;
char *name;
char *path;
struct stat stat;
-#ifdef CONFIG_INOTIFY1
- /* inotify watch cookie */
- int watchfd;
-#endif
+ /* file monitor watch id */
+ int watchid;
MTPObject *parent;
uint32_t nchildren;
QLIST_HEAD(, MTPObject) children;
bool readonly;
QTAILQ_HEAD(, MTPObject) objects;
-#ifdef CONFIG_INOTIFY1
- /* inotify descriptor */
- int inotifyfd;
+ QFileMonitor *file_monitor;
QTAILQ_HEAD(, MTPMonEntry) events;
-#endif
/* Responder is expecting a write operation */
bool write_pending;
struct {
/* ----------------------------------------------------------------------- */
static MTPObject *usb_mtp_object_alloc(MTPState *s, uint32_t handle,
- MTPObject *parent, char *name)
+ MTPObject *parent, const char *name)
{
MTPObject *o = g_new0(MTPObject, 1);
goto ignore;
}
+ o->watchid = -1;
o->handle = handle;
o->parent = parent;
o->name = g_strdup(name);
trace_usb_mtp_object_free(s->dev.addr, o->handle, o->path);
+ if (o->watchid != -1 && s->file_monitor) {
+ qemu_file_monitor_remove_watch(s->file_monitor, o->path, o->watchid);
+ }
+
QTAILQ_REMOVE(&s->objects, o, next);
if (o->parent) {
QLIST_REMOVE(o, list);
}
static MTPObject *usb_mtp_add_child(MTPState *s, MTPObject *o,
- char *name)
+ const char *name)
{
MTPObject *child =
usb_mtp_object_alloc(s, s->next_handle++, o, name);
}
static MTPObject *usb_mtp_object_lookup_name(MTPObject *parent,
- char *name, int len)
+ const char *name, int len)
{
MTPObject *iter;
+ if (len == -1) {
+ len = strlen(name);
+ }
+
QLIST_FOREACH(iter, &parent->children, list) {
if (strncmp(iter->name, name, len) == 0) {
return iter;
return NULL;
}
-#ifdef CONFIG_INOTIFY1
-static MTPObject *usb_mtp_object_lookup_wd(MTPState *s, int wd)
+static MTPObject *usb_mtp_object_lookup_id(MTPState *s, int id)
{
MTPObject *iter;
QTAILQ_FOREACH(iter, &s->objects, next) {
- if (iter->watchfd == wd) {
+ if (iter->watchid == id) {
return iter;
}
}
return NULL;
}
-static void inotify_watchfn(void *arg)
+static void file_monitor_event(int id,
+ QFileMonitorEvent ev,
+ const char *name,
+ void *opaque)
{
- MTPState *s = arg;
- ssize_t bytes;
- /* From the man page: atleast one event can be read */
- int pos;
- char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
-
- for (;;) {
- bytes = read(s->inotifyfd, buf, sizeof(buf));
- pos = 0;
-
- if (bytes <= 0) {
- /* Better luck next time */
+ MTPState *s = opaque;
+ MTPObject *parent = usb_mtp_object_lookup_id(s, id);
+ MTPMonEntry *entry = NULL;
+ MTPObject *o;
+
+ if (!parent) {
+ return;
+ }
+
+ switch (ev) {
+ case QFILE_MONITOR_EVENT_CREATED:
+ if (usb_mtp_object_lookup_name(parent, name, -1)) {
+ /* Duplicate create event */
return;
}
+ entry = g_new0(MTPMonEntry, 1);
+ entry->handle = s->next_handle;
+ entry->event = EVT_OBJ_ADDED;
+ o = usb_mtp_add_child(s, parent, name);
+ if (!o) {
+ g_free(entry);
+ return;
+ }
+ trace_usb_mtp_file_monitor_event(s->dev.addr, name, "Obj Added");
+ break;
+ case QFILE_MONITOR_EVENT_DELETED:
/*
- * TODO: Ignore initiator initiated events.
- * For now we are good because the store is RO
+ * The kernel issues a IN_IGNORED event
+ * when a dir containing a watchpoint is
+ * deleted, so we don't have to delete the
+ * watchpoint
*/
- while (bytes > 0) {
- char *p = buf + pos;
- struct inotify_event *event = (struct inotify_event *)p;
- int watchfd = 0;
- uint32_t mask = event->mask & (IN_CREATE | IN_DELETE |
- IN_MODIFY | IN_IGNORED);
- MTPObject *parent = usb_mtp_object_lookup_wd(s, event->wd);
- MTPMonEntry *entry = NULL;
- MTPObject *o;
-
- pos = pos + sizeof(struct inotify_event) + event->len;
- bytes = bytes - pos;
-
- if (!parent) {
- continue;
- }
-
- switch (mask) {
- case IN_CREATE:
- if (usb_mtp_object_lookup_name
- (parent, event->name, event->len)) {
- /* Duplicate create event */
- continue;
- }
- entry = g_new0(MTPMonEntry, 1);
- entry->handle = s->next_handle;
- entry->event = EVT_OBJ_ADDED;
- o = usb_mtp_add_child(s, parent, event->name);
- if (!o) {
- g_free(entry);
- continue;
- }
- o->watchfd = watchfd;
- trace_usb_mtp_inotify_event(s->dev.addr, event->name,
- event->mask, "Obj Added");
- break;
-
- case IN_DELETE:
- /*
- * The kernel issues a IN_IGNORED event
- * when a dir containing a watchpoint is
- * deleted, so we don't have to delete the
- * watchpoint
- */
- o = usb_mtp_object_lookup_name(parent, event->name, event->len);
- if (!o) {
- continue;
- }
- entry = g_new0(MTPMonEntry, 1);
- entry->handle = o->handle;
- entry->event = EVT_OBJ_REMOVED;
- trace_usb_mtp_inotify_event(s->dev.addr, o->path,
- event->mask, "Obj Deleted");
- usb_mtp_object_free(s, o);
- break;
-
- case IN_MODIFY:
- o = usb_mtp_object_lookup_name(parent, event->name, event->len);
- if (!o) {
- continue;
- }
- entry = g_new0(MTPMonEntry, 1);
- entry->handle = o->handle;
- entry->event = EVT_OBJ_INFO_CHANGED;
- trace_usb_mtp_inotify_event(s->dev.addr, o->path,
- event->mask, "Obj Modified");
- break;
-
- case IN_IGNORED:
- trace_usb_mtp_inotify_event(s->dev.addr, parent->path,
- event->mask, "Obj parent dir ignored");
- break;
-
- default:
- fprintf(stderr, "usb-mtp: failed to parse inotify event\n");
- continue;
- }
-
- if (entry) {
- QTAILQ_INSERT_HEAD(&s->events, entry, next);
- }
+ o = usb_mtp_object_lookup_name(parent, name, -1);
+ if (!o) {
+ return;
}
- }
-}
+ entry = g_new0(MTPMonEntry, 1);
+ entry->handle = o->handle;
+ entry->event = EVT_OBJ_REMOVED;
+ trace_usb_mtp_file_monitor_event(s->dev.addr, o->path, "Obj Deleted");
+ usb_mtp_object_free(s, o);
+ break;
-static int usb_mtp_inotify_init(MTPState *s)
-{
- int fd;
+ case QFILE_MONITOR_EVENT_MODIFIED:
+ o = usb_mtp_object_lookup_name(parent, name, -1);
+ if (!o) {
+ return;
+ }
+ entry = g_new0(MTPMonEntry, 1);
+ entry->handle = o->handle;
+ entry->event = EVT_OBJ_INFO_CHANGED;
+ trace_usb_mtp_file_monitor_event(s->dev.addr, o->path, "Obj Modified");
+ break;
- fd = inotify_init1(IN_NONBLOCK);
- if (fd == -1) {
- return 1;
- }
+ case QFILE_MONITOR_EVENT_IGNORED:
+ trace_usb_mtp_file_monitor_event(s->dev.addr, parent->path,
+ "Obj parent dir ignored");
+ break;
- QTAILQ_INIT(&s->events);
- s->inotifyfd = fd;
+ case QFILE_MONITOR_EVENT_ATTRIBUTES:
+ break;
- qemu_set_fd_handler(fd, inotify_watchfn, NULL, s);
+ default:
+ g_assert_not_reached();
+ }
- return 0;
+ if (entry) {
+ QTAILQ_INSERT_HEAD(&s->events, entry, next);
+ }
}
-static void usb_mtp_inotify_cleanup(MTPState *s)
+static void usb_mtp_file_monitor_cleanup(MTPState *s)
{
MTPMonEntry *e, *p;
- if (!s->inotifyfd) {
- return;
- }
-
- qemu_set_fd_handler(s->inotifyfd, NULL, NULL, s);
- close(s->inotifyfd);
-
QTAILQ_FOREACH_SAFE(e, &s->events, next, p) {
QTAILQ_REMOVE(&s->events, e, next);
g_free(e);
}
-}
-static int usb_mtp_add_watch(int inotifyfd, char *path)
-{
- uint32_t mask = IN_CREATE | IN_DELETE | IN_MODIFY |
- IN_ISDIR;
-
- return inotify_add_watch(inotifyfd, path, mask);
+ qemu_file_monitor_free(s->file_monitor);
+ s->file_monitor = NULL;
}
-#endif
+
static void usb_mtp_object_readdir(MTPState *s, MTPObject *o)
{
struct dirent *entry;
DIR *dir;
int fd;
+ Error *err = NULL;
if (o->have_children) {
return;
close(fd);
return;
}
-#ifdef CONFIG_INOTIFY1
- int watchfd = usb_mtp_add_watch(s->inotifyfd, o->path);
- if (watchfd == -1) {
- fprintf(stderr, "usb-mtp: failed to add watch for %s\n", o->path);
- } else {
- trace_usb_mtp_inotify_event(s->dev.addr, o->path,
- 0, "Watch Added");
- o->watchfd = watchfd;
+
+ if (s->file_monitor) {
+ int id = qemu_file_monitor_add_watch(s->file_monitor, o->path, NULL,
+ file_monitor_event, s, &err);
+ if (id == -1) {
+ error_report("usb-mtp: failed to add watch for %s: %s", o->path,
+ error_get_pretty(err));
+ error_free(err);
+ } else {
+ trace_usb_mtp_file_monitor_event(s->dev.addr, o->path,
+ "Watch Added");
+ o->watchid = id;
+ }
}
-#endif
+
while ((entry = readdir(dir)) != NULL) {
usb_mtp_add_child(s, o, entry->d_name);
}
/* Assumes that children, if any, have been already freed */
static void usb_mtp_object_free_one(MTPState *s, MTPObject *o)
{
-#ifndef CONFIG_INOTIFY1
assert(o->nchildren == 0);
QTAILQ_REMOVE(&s->objects, o, next);
g_free(o->name);
g_free(o->path);
g_free(o);
-#endif
}
static int usb_mtp_deletefn(MTPState *s, MTPObject *o, uint32_t trans)
MTPData *data_in = NULL;
MTPObject *o = NULL;
uint32_t nres = 0, res0 = 0;
+ Error *err = NULL;
/* sanity checks */
if (c->code >= CMD_CLOSE_SESSION && s->session == 0) {
trace_usb_mtp_op_open_session(s->dev.addr);
s->session = c->argv[0];
usb_mtp_object_alloc(s, s->next_handle++, NULL, s->root);
-#ifdef CONFIG_INOTIFY1
- if (usb_mtp_inotify_init(s)) {
- fprintf(stderr, "usb-mtp: file monitoring init failed\n");
+
+ s->file_monitor = qemu_file_monitor_new(&err);
+ if (err) {
+ error_report("usb-mtp: file monitoring init failed: %s",
+ error_get_pretty(err));
+ error_free(err);
+ } else {
+ QTAILQ_INIT(&s->events);
}
-#endif
break;
case CMD_CLOSE_SESSION:
trace_usb_mtp_op_close_session(s->dev.addr);
s->session = 0;
s->next_handle = 0;
-#ifdef CONFIG_INOTIFY1
- usb_mtp_inotify_cleanup(s);
-#endif
+ usb_mtp_file_monitor_cleanup(s);
usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects));
assert(QTAILQ_EMPTY(&s->objects));
break;
trace_usb_mtp_reset(s->dev.addr);
-#ifdef CONFIG_INOTIFY1
- usb_mtp_inotify_cleanup(s);
-#endif
+ usb_mtp_file_monitor_cleanup(s);
usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects));
s->session = 0;
usb_mtp_data_free(s->data_in);
}
break;
case EP_EVENT:
-#ifdef CONFIG_INOTIFY1
if (!QTAILQ_EMPTY(&s->events)) {
struct MTPMonEntry *e = QTAILQ_LAST(&s->events);
uint32_t handle;
g_free(e);
return;
}
-#endif
p->status = USB_RET_NAK;
return;
default:
USBDevice *dev;
Chardev *cdrv;
- cdrv = qemu_chr_new("braille", "braille");
+ cdrv = qemu_chr_new("braille", "braille", NULL);
if (!cdrv)
return NULL;
usb_desc_init(dev);
qbus_create_inplace(&s->bus, sizeof(s->bus), TYPE_CCID_BUS, DEVICE(dev),
NULL);
- qbus_set_hotplug_handler(BUS(&s->bus), DEVICE(dev), &error_abort);
+ qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev), &error_abort);
s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
s->bulk = usb_ep_get(dev, USB_TOKEN_IN, CCID_BULK_IN_EP);
s->card = NULL;
qemu_sglist_add(&ehci->isgl, ptr1 + off, len);
}
- pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT;
-
dev = ehci_find_device(ehci, devaddr);
+ if (dev == NULL) {
+ ehci_trace_guest_bug(ehci, "no device found");
+ return -1;
+ }
+ pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT;
ep = usb_ep_get(dev, pid, endp);
if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) {
usb_packet_setup(&ehci->ipacket, pid, ep, 0, addr, false,
/* A wild guess on the FADDR semantics... */
dev = usb_find_device(&s->port, ep->faddr[idx]);
- uep = usb_ep_get(dev, pid, ep->type[idx] & 0xf);
- id = pid;
- if (uep) {
- id |= (dev->addr << 16) | (uep->nr << 8);
+ if (dev == NULL) {
+ return;
}
+ uep = usb_ep_get(dev, pid, ep->type[idx] & 0xf);
+ id = pid | (dev->addr << 16) | (uep->nr << 8);
usb_packet_setup(&ep->packey[dir].p, pid, uep, 0, id, false, true);
usb_packet_addbuf(&ep->packey[dir].p, ep->buf[idx], len);
ep->packey[dir].ep = ep;
bool int_req = relative_frame_number == frame_count &&
OHCI_BM(iso_td.flags, TD_DI) == 0;
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
+ if (dev == NULL) {
+ trace_usb_ohci_td_dev_error();
+ return 1;
+ }
ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, false, int_req);
usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
return 1;
}
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
+ if (dev == NULL) {
+ trace_usb_ohci_td_dev_error();
+ return 1;
+ }
ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r,
OHCI_BM(td.flags, TD_DI) == 0);
/* Allocate new packet */
if (q == NULL) {
- USBDevice *dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
- USBEndpoint *ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);
+ USBDevice *dev;
+ USBEndpoint *ep;
- if (ep == NULL) {
+ dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
+ if (dev == NULL) {
return uhci_handle_td_error(s, td, td_addr, USB_RET_NODEV,
int_mask);
}
+ ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);
q = uhci_queue_new(s, qh_addr, td, ep);
}
async = uhci_async_alloc(q, td_addr);
{
uint32_t pls = PLS_RX_DETECT;
+ assert(port);
port->portsc = PORTSC_PP;
if (!is_detach && xhci_port_have_device(port)) {
port->portsc |= PORTSC_CCS;
XHCIState *xhci = usbport->opaque;
XHCIPort *port = xhci_lookup_port(xhci, usbport);
+ assert(port);
if (get_field(port->portsc, PORTSC_PLS) != PLS_U3) {
return;
}
return NULL;
}
uport = epctx->xhci->slots[epctx->slotid - 1].uport;
- token = (epctx->epid & 1) ? USB_TOKEN_IN : USB_TOKEN_OUT;
- if (!uport) {
+ if (!uport || !uport->dev) {
return NULL;
}
+ token = (epctx->epid & 1) ? USB_TOKEN_IN : USB_TOKEN_OUT;
return usb_ep_get(uport->dev, token, epctx->epid >> 1);
}
USBRedirDevice *dev = priv;
int i;
+ assert(dev != NULL);
for (i = 0; i < MAX_ENDPOINTS; i++) {
dev->endpoint[i].type = ep_info->type[i];
dev->endpoint[i].interval = ep_info->interval[i];
{
USBRedirDevice *dev = priv;
- if (dev->parser == NULL) {
+ if (dev == NULL || dev->parser == NULL) {
return 0;
}
usb_mtp_object_alloc(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
usb_mtp_object_free(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
usb_mtp_add_child(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
-usb_mtp_inotify_event(int dev, const char *path, uint32_t mask, const char *s) "dev %d, path %s mask 0x%x event %s"
+usb_mtp_file_monitor_event(int dev, const char *path, const char *s) "dev %d, path %s event %s"
# hw/usb/host-libusb.c
usb_host_open_started(int bus, int addr) "dev %d:%d"
-ifeq ($(CONFIG_LINUX), y)
-obj-$(CONFIG_SOFTMMU) += common.o
-obj-$(CONFIG_PCI) += pci.o pci-quirks.o display.o
+obj-y += common.o spapr.o
+obj-$(CONFIG_VFIO_PCI) += pci.o pci-quirks.o display.o
obj-$(CONFIG_VFIO_CCW) += ccw.o
-obj-$(CONFIG_SOFTMMU) += platform.o
+obj-$(CONFIG_VFIO_PLATFORM) += platform.o
obj-$(CONFIG_VFIO_XGMAC) += calxeda-xgmac.o
obj-$(CONFIG_VFIO_AMD_XGBE) += amd-xgbe.o
-obj-$(CONFIG_SOFTMMU) += spapr.o
obj-$(CONFIG_VFIO_AP) += ap.o
-endif
.size = size,
};
- if (ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, &unmap)) {
+ while (ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, &unmap)) {
+ /*
+ * The type1 backend has an off-by-one bug in the kernel (71a7d3d78e3c
+ * v4.15) where an overflow in its wrap-around check prevents us from
+ * unmapping the last page of the address space. Test for the error
+ * condition and re-try the unmap excluding the last page. The
+ * expectation is that we've never mapped the last page anyway and this
+ * unmap request comes via vIOMMU support which also makes it unlikely
+ * that this page is used. This bug was introduced well after type1 v2
+ * support was introduced, so we shouldn't need to test for v1. A fix
+ * is queued for kernel v5.0 so this workaround can be removed once
+ * affected kernels are sufficiently deprecated.
+ */
+ if (errno == EINVAL && unmap.size && !(unmap.iova + unmap.size) &&
+ container->iommu_type == VFIO_TYPE1v2_IOMMU) {
+ trace_vfio_dma_unmap_overflow_workaround();
+ unmap.size -= 1ULL << ctz64(container->pgsizes);
+ continue;
+ }
error_report("VFIO_UNMAP_DMA: %d", -errno);
return -errno;
}
}
}
+/*
+ * vfio_get_iommu_type - selects the richest iommu_type (v2 first)
+ */
+static int vfio_get_iommu_type(VFIOContainer *container,
+ Error **errp)
+{
+ int iommu_types[] = { VFIO_TYPE1v2_IOMMU, VFIO_TYPE1_IOMMU,
+ VFIO_SPAPR_TCE_v2_IOMMU, VFIO_SPAPR_TCE_IOMMU };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(iommu_types); i++) {
+ if (ioctl(container->fd, VFIO_CHECK_EXTENSION, iommu_types[i])) {
+ return iommu_types[i];
+ }
+ }
+ error_setg(errp, "No available IOMMU models");
+ return -EINVAL;
+}
+
+static int vfio_init_container(VFIOContainer *container, int group_fd,
+ Error **errp)
+{
+ int iommu_type, ret;
+
+ iommu_type = vfio_get_iommu_type(container, errp);
+ if (iommu_type < 0) {
+ return iommu_type;
+ }
+
+ ret = ioctl(group_fd, VFIO_GROUP_SET_CONTAINER, &container->fd);
+ if (ret) {
+ error_setg_errno(errp, errno, "Failed to set group container");
+ return -errno;
+ }
+
+ while (ioctl(container->fd, VFIO_SET_IOMMU, iommu_type)) {
+ if (iommu_type == VFIO_SPAPR_TCE_v2_IOMMU) {
+ /*
+ * On sPAPR, despite the IOMMU subdriver always advertises v1 and
+ * v2, the running platform may not support v2 and there is no
+ * way to guess it until an IOMMU group gets added to the container.
+ * So in case it fails with v2, try v1 as a fallback.
+ */
+ iommu_type = VFIO_SPAPR_TCE_IOMMU;
+ continue;
+ }
+ error_setg_errno(errp, errno, "Failed to set iommu for container");
+ return -errno;
+ }
+
+ container->iommu_type = iommu_type;
+ return 0;
+}
+
static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
Error **errp)
{
container->fd = fd;
QLIST_INIT(&container->giommu_list);
QLIST_INIT(&container->hostwin_list);
- if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU) ||
- ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU)) {
- bool v2 = !!ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU);
- struct vfio_iommu_type1_info info;
- ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd);
- if (ret) {
- error_setg_errno(errp, errno, "failed to set group container");
- ret = -errno;
- goto free_container_exit;
- }
+ ret = vfio_init_container(container, group->fd, errp);
+ if (ret) {
+ goto free_container_exit;
+ }
- container->iommu_type = v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU;
- ret = ioctl(fd, VFIO_SET_IOMMU, container->iommu_type);
- if (ret) {
- error_setg_errno(errp, errno, "failed to set iommu for container");
- ret = -errno;
- goto free_container_exit;
- }
+ switch (container->iommu_type) {
+ case VFIO_TYPE1v2_IOMMU:
+ case VFIO_TYPE1_IOMMU:
+ {
+ struct vfio_iommu_type1_info info;
/*
* FIXME: This assumes that a Type1 IOMMU can map any 64-bit
}
vfio_host_win_add(container, 0, (hwaddr)-1, info.iova_pgsizes);
container->pgsizes = info.iova_pgsizes;
- } else if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_IOMMU) ||
- ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_v2_IOMMU)) {
+ break;
+ }
+ case VFIO_SPAPR_TCE_v2_IOMMU:
+ case VFIO_SPAPR_TCE_IOMMU:
+ {
struct vfio_iommu_spapr_tce_info info;
- bool v2 = !!ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_v2_IOMMU);
-
- ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd);
- if (ret) {
- error_setg_errno(errp, errno, "failed to set group container");
- ret = -errno;
- goto free_container_exit;
- }
- container->iommu_type =
- v2 ? VFIO_SPAPR_TCE_v2_IOMMU : VFIO_SPAPR_TCE_IOMMU;
- ret = ioctl(fd, VFIO_SET_IOMMU, container->iommu_type);
- if (ret) {
- container->iommu_type = VFIO_SPAPR_TCE_IOMMU;
- v2 = false;
- ret = ioctl(fd, VFIO_SET_IOMMU, container->iommu_type);
- }
- if (ret) {
- error_setg_errno(errp, errno, "failed to set iommu for container");
- ret = -errno;
- goto free_container_exit;
- }
+ bool v2 = container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU;
/*
* The host kernel code implementing VFIO_IOMMU_DISABLE is called
info.dma32_window_size - 1,
0x1000);
}
- } else {
- error_setg(errp, "No available IOMMU models");
- ret = -EINVAL;
- goto free_container_exit;
+ }
}
vfio_kvm_device_add_group(group);
vfio_region_sparse_mmap_header(const char *name, int index, int nr_areas) "Device %s region %d: %d sparse mmap entries"
vfio_region_sparse_mmap_entry(int i, unsigned long start, unsigned long end) "sparse entry %d [0x%lx - 0x%lx]"
vfio_get_dev_region(const char *name, int index, uint32_t type, uint32_t subtype) "%s index %d, %08x/%0x8"
+vfio_dma_unmap_overflow_workaround(void) ""
# hw/vfio/platform.c
vfio_platform_base_device_init(char *name, int groupid) "%s belongs to group #%d"
obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o
obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock.o
-ifeq ($(CONFIG_PCI),y)
+ifeq ($(CONFIG_VIRTIO_PCI),y)
obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock-pci.o
obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk-pci.o
obj-$(CONFIG_VHOST_USER_SCSI) += vhost-user-scsi-pci.o
static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
uint32_t val, int len)
{
- VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+ VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
struct virtio_pci_cfg_cap *cfg;
static uint32_t virtio_read_config(PCIDevice *pci_dev,
uint32_t address, int len)
{
- VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+ VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
struct virtio_pci_cfg_cap *cfg;
if (proxy->config_cap &&
vring_desc_read(vdev, &desc, desc_cache, i);
if (desc.flags & VRING_DESC_F_INDIRECT) {
- if (desc.len % sizeof(VRingDesc)) {
+ if (!desc.len || (desc.len % sizeof(VRingDesc))) {
virtio_error(vdev, "Invalid size for indirect buffer table");
goto err;
}
desc_cache = &caches->desc;
vring_desc_read(vdev, &desc, desc_cache, i);
if (desc.flags & VRING_DESC_F_INDIRECT) {
- if (desc.len % sizeof(VRingDesc)) {
+ if (!desc.len || (desc.len % sizeof(VRingDesc))) {
virtio_error(vdev, "Invalid size for indirect buffer table");
goto done;
}
return ret;
}
+size_t virtio_feature_get_config_size(VirtIOFeature *feature_sizes,
+ uint64_t host_features)
+{
+ size_t config_size = 0;
+ int i;
+
+ for (i = 0; feature_sizes[i].flags != 0; i++) {
+ if (host_features & feature_sizes[i].flags) {
+ config_size = MAX(feature_sizes[i].end, config_size);
+ }
+ }
+
+ return config_size;
+}
+
int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
{
int i, ret;
obj-y += mx_pic.o
obj-y += pic_cpu.o
-obj-y += sim.o
obj-y += xtensa_memory.o
-obj-y += xtfpga.o
+obj-$(CONFIG_XTENSA_SIM) += sim.o
+obj-$(CONFIG_XTENSA_FPGA) += xtfpga.o
uint64_t elf_entry;
uint64_t elf_lowaddr;
#ifdef TARGET_WORDS_BIGENDIAN
- int success = load_elf(kernel_filename, translate_phys_addr, cpu,
- &elf_entry, &elf_lowaddr, NULL, 1, EM_XTENSA, 0, 0);
+ int success = load_elf(kernel_filename, NULL,
+ translate_phys_addr, cpu,
+ &elf_entry, &elf_lowaddr,
+ NULL, 1, EM_XTENSA, 0, 0);
#else
- int success = load_elf(kernel_filename, translate_phys_addr, cpu,
- &elf_entry, &elf_lowaddr, NULL, 0, EM_XTENSA, 0, 0);
+ int success = load_elf(kernel_filename, NULL,
+ translate_phys_addr, cpu,
+ &elf_entry, &elf_lowaddr,
+ NULL, 0, EM_XTENSA, 0, 0);
#endif
if (success > 0) {
env->pc = elf_entry;
uint64_t elf_entry;
uint64_t elf_lowaddr;
- int success = load_elf(kernel_filename, translate_phys_addr, cpu,
+ int success = load_elf(kernel_filename, NULL, translate_phys_addr, cpu,
&elf_entry, &elf_lowaddr, NULL, be, EM_XTENSA, 0, 0);
if (success > 0) {
entry_point = elf_entry;
--- /dev/null
+/*
+ * QEMU authorization framework base class
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef QAUTHZ_BASE_H__
+#define QAUTHZ_BASE_H__
+
+#include "qemu-common.h"
+#include "qapi/error.h"
+#include "qom/object.h"
+
+
+#define TYPE_QAUTHZ "authz"
+
+#define QAUTHZ_CLASS(klass) \
+ OBJECT_CLASS_CHECK(QAuthZClass, (klass), \
+ TYPE_QAUTHZ)
+#define QAUTHZ_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(QAuthZClass, (obj), \
+ TYPE_QAUTHZ)
+#define QAUTHZ(obj) \
+ INTERFACE_CHECK(QAuthZ, (obj), \
+ TYPE_QAUTHZ)
+
+typedef struct QAuthZ QAuthZ;
+typedef struct QAuthZClass QAuthZClass;
+
+/**
+ * QAuthZ:
+ *
+ * The QAuthZ class defines an API contract to be used
+ * for providing an authorization driver for services
+ * with user identities.
+ */
+
+struct QAuthZ {
+ Object parent_obj;
+};
+
+
+struct QAuthZClass {
+ ObjectClass parent_class;
+
+ bool (*is_allowed)(QAuthZ *authz,
+ const char *identity,
+ Error **errp);
+};
+
+
+/**
+ * qauthz_is_allowed:
+ * @authz: the authorization object
+ * @identity: the user identity to authorize
+ * @errp: pointer to a NULL initialized error object
+ *
+ * Check if a user @identity is authorized. If an error
+ * occurs this method will return false to indicate
+ * denial, as well as setting @errp to contain the details.
+ * Callers are recommended to treat the denial and error
+ * scenarios identically. Specifically the error info in
+ * @errp should never be fed back to the user being
+ * authorized, it is merely for benefit of administrator
+ * debugging.
+ *
+ * Returns: true if @identity is authorized, false if denied or if
+ * an error occurred.
+ */
+bool qauthz_is_allowed(QAuthZ *authz,
+ const char *identity,
+ Error **errp);
+
+
+/**
+ * qauthz_is_allowed_by_id:
+ * @authzid: ID of the authorization object
+ * @identity: the user identity to authorize
+ * @errp: pointer to a NULL initialized error object
+ *
+ * Check if a user @identity is authorized. If an error
+ * occurs this method will return false to indicate
+ * denial, as well as setting @errp to contain the details.
+ * Callers are recommended to treat the denial and error
+ * scenarios identically. Specifically the error info in
+ * @errp should never be fed back to the user being
+ * authorized, it is merely for benefit of administrator
+ * debugging.
+ *
+ * Returns: true if @identity is authorized, false if denied or if
+ * an error occurred.
+ */
+bool qauthz_is_allowed_by_id(const char *authzid,
+ const char *identity,
+ Error **errp);
+
+#endif /* QAUTHZ_BASE_H__ */
+
--- /dev/null
+/*
+ * QEMU list authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef QAUTHZ_LIST_H__
+#define QAUTHZ_LIST_H__
+
+#include "authz/base.h"
+#include "qapi/qapi-types-authz.h"
+
+#define TYPE_QAUTHZ_LIST "authz-list"
+
+#define QAUTHZ_LIST_CLASS(klass) \
+ OBJECT_CLASS_CHECK(QAuthZListClass, (klass), \
+ TYPE_QAUTHZ_LIST)
+#define QAUTHZ_LIST_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(QAuthZListClass, (obj), \
+ TYPE_QAUTHZ_LIST)
+#define QAUTHZ_LIST(obj) \
+ INTERFACE_CHECK(QAuthZList, (obj), \
+ TYPE_QAUTHZ_LIST)
+
+typedef struct QAuthZList QAuthZList;
+typedef struct QAuthZListClass QAuthZListClass;
+
+
+/**
+ * QAuthZList:
+ *
+ * This authorization driver provides a list mechanism
+ * for granting access by matching user names against a
+ * list of globs. Each match rule has an associated policy
+ * and a catch all policy applies if no rule matches
+ *
+ * To create an instance of this class via QMP:
+ *
+ * {
+ * "execute": "object-add",
+ * "arguments": {
+ * "qom-type": "authz-list",
+ * "id": "authz0",
+ * "props": {
+ * "rules": [
+ * { "match": "fred", "policy": "allow", "format": "exact" },
+ * { "match": "bob", "policy": "allow", "format": "exact" },
+ * { "match": "danb", "policy": "deny", "format": "exact" },
+ * { "match": "dan*", "policy": "allow", "format": "glob" }
+ * ],
+ * "policy": "deny"
+ * }
+ * }
+ * }
+ *
+ */
+struct QAuthZList {
+ QAuthZ parent_obj;
+
+ QAuthZListPolicy policy;
+ QAuthZListRuleList *rules;
+};
+
+
+struct QAuthZListClass {
+ QAuthZClass parent_class;
+};
+
+
+QAuthZList *qauthz_list_new(const char *id,
+ QAuthZListPolicy policy,
+ Error **errp);
+
+ssize_t qauthz_list_append_rule(QAuthZList *auth,
+ const char *match,
+ QAuthZListPolicy policy,
+ QAuthZListFormat format,
+ Error **errp);
+
+ssize_t qauthz_list_insert_rule(QAuthZList *auth,
+ const char *match,
+ QAuthZListPolicy policy,
+ QAuthZListFormat format,
+ size_t index,
+ Error **errp);
+
+ssize_t qauthz_list_delete_rule(QAuthZList *auth,
+ const char *match);
+
+
+#endif /* QAUTHZ_LIST_H__ */
+
--- /dev/null
+/*
+ * QEMU list file authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef QAUTHZ_LIST_FILE_H__
+#define QAUTHZ_LIST_FILE_H__
+
+#include "authz/list.h"
+#include "qapi/qapi-types-authz.h"
+#include "qemu/filemonitor.h"
+
+#define TYPE_QAUTHZ_LIST_FILE "authz-list-file"
+
+#define QAUTHZ_LIST_FILE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(QAuthZListFileClass, (klass), \
+ TYPE_QAUTHZ_LIST_FILE)
+#define QAUTHZ_LIST_FILE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(QAuthZListFileClass, (obj), \
+ TYPE_QAUTHZ_LIST_FILE)
+#define QAUTHZ_LIST_FILE(obj) \
+ INTERFACE_CHECK(QAuthZListFile, (obj), \
+ TYPE_QAUTHZ_LIST_FILE)
+
+typedef struct QAuthZListFile QAuthZListFile;
+typedef struct QAuthZListFileClass QAuthZListFileClass;
+
+
+/**
+ * QAuthZListFile:
+ *
+ * This authorization driver provides a file mechanism
+ * for granting access by matching user names against a
+ * file of globs. Each match rule has an associated policy
+ * and a catch all policy applies if no rule matches
+ *
+ * To create an instance of this class via QMP:
+ *
+ * {
+ * "execute": "object-add",
+ * "arguments": {
+ * "qom-type": "authz-list-file",
+ * "id": "authz0",
+ * "props": {
+ * "filename": "/etc/qemu/myvm-vnc.acl",
+ * "refresh": true
+ * }
+ * }
+ * }
+ *
+ * If 'refresh' is 'yes', inotify is used to monitor for changes
+ * to the file and auto-reload the rules.
+ *
+ * The myvm-vnc.acl file should contain the parameters for
+ * the QAuthZList object in JSON format:
+ *
+ * {
+ * "rules": [
+ * { "match": "fred", "policy": "allow", "format": "exact" },
+ * { "match": "bob", "policy": "allow", "format": "exact" },
+ * { "match": "danb", "policy": "deny", "format": "exact" },
+ * { "match": "dan*", "policy": "allow", "format": "glob" }
+ * ],
+ * "policy": "deny"
+ * }
+ *
+ * The object can be created on the command line using
+ *
+ * -object authz-list-file,id=authz0,\
+ * filename=/etc/qemu/myvm-vnc.acl,refresh=yes
+ *
+ */
+struct QAuthZListFile {
+ QAuthZ parent_obj;
+
+ QAuthZ *list;
+ char *filename;
+ bool refresh;
+ QFileMonitor *file_monitor;
+ int file_watch;
+};
+
+
+struct QAuthZListFileClass {
+ QAuthZClass parent_class;
+};
+
+
+QAuthZListFile *qauthz_list_file_new(const char *id,
+ const char *filename,
+ bool refresh,
+ Error **errp);
+
+
+#endif /* QAUTHZ_LIST_FILE_H__ */
+
--- /dev/null
+/*
+ * QEMU PAM authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef QAUTHZ_PAM_H__
+#define QAUTHZ_PAM_H__
+
+#include "authz/base.h"
+
+
+#define TYPE_QAUTHZ_PAM "authz-pam"
+
+#define QAUTHZ_PAM_CLASS(klass) \
+ OBJECT_CLASS_CHECK(QAuthZPAMClass, (klass), \
+ TYPE_QAUTHZ_PAM)
+#define QAUTHZ_PAM_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(QAuthZPAMClass, (obj), \
+ TYPE_QAUTHZ_PAM)
+#define QAUTHZ_PAM(obj) \
+ INTERFACE_CHECK(QAuthZPAM, (obj), \
+ TYPE_QAUTHZ_PAM)
+
+typedef struct QAuthZPAM QAuthZPAM;
+typedef struct QAuthZPAMClass QAuthZPAMClass;
+
+
+/**
+ * QAuthZPAM:
+ *
+ * This authorization driver provides a PAM mechanism
+ * for granting access by matching user names against a
+ * list of globs. Each match rule has an associated policy
+ * and a catch all policy applies if no rule matches
+ *
+ * To create an instance of this class via QMP:
+ *
+ * {
+ * "execute": "object-add",
+ * "arguments": {
+ * "qom-type": "authz-pam",
+ * "id": "authz0",
+ * "parameters": {
+ * "service": "qemu-vnc-tls"
+ * }
+ * }
+ * }
+ *
+ * The driver only uses the PAM "account" verification
+ * subsystem. The above config would require a config
+ * file /etc/pam.d/qemu-vnc-tls. For a simple file
+ * lookup it would contain
+ *
+ * account requisite pam_listfile.so item=user sense=allow \
+ * file=/etc/qemu/vnc.allow
+ *
+ * The external file would then contain a list of usernames.
+ * If x509 cert was being used as the username, a suitable
+ * entry would match the distinguish name:
+ *
+ * CN=laptop.berrange.com,O=Berrange Home,L=London,ST=London,C=GB
+ *
+ * On the command line it can be created using
+ *
+ * -object authz-pam,id=authz0,service=qemu-vnc-tls
+ *
+ */
+struct QAuthZPAM {
+ QAuthZ parent_obj;
+
+ char *service;
+};
+
+
+struct QAuthZPAMClass {
+ QAuthZClass parent_class;
+};
+
+
+QAuthZPAM *qauthz_pam_new(const char *id,
+ const char *service,
+ Error **errp);
+
+
+#endif /* QAUTHZ_PAM_H__ */
--- /dev/null
+/*
+ * QEMU simple authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef QAUTHZ_SIMPLE_H__
+#define QAUTHZ_SIMPLE_H__
+
+#include "authz/base.h"
+
+#define TYPE_QAUTHZ_SIMPLE "authz-simple"
+
+#define QAUTHZ_SIMPLE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(QAuthZSimpleClass, (klass), \
+ TYPE_QAUTHZ_SIMPLE)
+#define QAUTHZ_SIMPLE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(QAuthZSimpleClass, (obj), \
+ TYPE_QAUTHZ_SIMPLE)
+#define QAUTHZ_SIMPLE(obj) \
+ INTERFACE_CHECK(QAuthZSimple, (obj), \
+ TYPE_QAUTHZ_SIMPLE)
+
+typedef struct QAuthZSimple QAuthZSimple;
+typedef struct QAuthZSimpleClass QAuthZSimpleClass;
+
+
+/**
+ * QAuthZSimple:
+ *
+ * This authorization driver provides a simple mechanism
+ * for granting access based on an exact matched username.
+ *
+ * To create an instance of this class via QMP:
+ *
+ * {
+ * "execute": "object-add",
+ * "arguments": {
+ * "qom-type": "authz-simple",
+ * "id": "authz0",
+ * "props": {
+ * "identity": "fred"
+ * }
+ * }
+ * }
+ *
+ * Or via the command line
+ *
+ * -object authz-simple,id=authz0,identity=fred
+ *
+ */
+struct QAuthZSimple {
+ QAuthZ parent_obj;
+
+ char *identity;
+};
+
+
+struct QAuthZSimpleClass {
+ QAuthZClass parent_class;
+};
+
+
+QAuthZSimple *qauthz_simple_new(const char *id,
+ const char *identity,
+ Error **errp);
+
+
+#endif /* QAUTHZ_SIMPLE_H__ */
+
const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
int bdrv_get_flags(BlockDriverState *bs);
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
-ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs);
+ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs,
+ Error **errp);
void bdrv_round_to_clusters(BlockDriverState *bs,
int64_t offset, int64_t bytes,
int64_t *cluster_offset,
int64_t *cluster_bytes);
-const char *bdrv_get_encrypted_filename(BlockDriverState *bs);
void bdrv_get_backing_filename(BlockDriverState *bs,
char *filename, int filename_size);
-void bdrv_get_full_backing_filename(BlockDriverState *bs,
- char *dest, size_t sz, Error **errp);
-void bdrv_get_full_backing_filename_from_filename(const char *backed,
- const char *backing,
- char *dest, size_t sz,
- Error **errp);
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
+char *bdrv_get_full_backing_filename_from_filename(const char *backed,
+ const char *backing,
+ Error **errp);
+char *bdrv_dirname(BlockDriverState *bs, Error **errp);
int path_has_protocol(const char *path);
int path_is_absolute(const char *path);
-void path_combine(char *dest, int dest_size,
- const char *base_path,
- const char *filename);
+char *path_combine(const char *base_path, const char *filename);
int bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
Error **errp);
int (*bdrv_make_empty)(BlockDriverState *bs);
- void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
+ /*
+ * Refreshes the bs->exact_filename field. If that is impossible,
+ * bs->exact_filename has to be left empty.
+ */
+ void (*bdrv_refresh_filename)(BlockDriverState *bs);
+
+ /*
+ * Gathers the open options for all children into @target.
+ * A simple format driver (without backing file support) might
+ * implement this function like this:
+ *
+ * QINCREF(bs->file->bs->full_open_options);
+ * qdict_put(target, "file", bs->file->bs->full_open_options);
+ *
+ * If not specified, the generic implementation will simply put
+ * all children's options under their respective name.
+ *
+ * @backing_overridden is true when bs->backing seems not to be
+ * the child that would result from opening bs->backing_file.
+ * Therefore, if it is true, the backing child's options should be
+ * gathered; otherwise, there is no need since the backing child
+ * is the one implied by the image header.
+ *
+ * Note that ideally this function would not be needed. Every
+ * block driver which implements it is probably doing something
+ * shady regarding its runtime option structure.
+ */
+ void (*bdrv_gather_child_options)(BlockDriverState *bs, QDict *target,
+ bool backing_overridden);
+
+ /*
+ * Returns an allocated string which is the directory name of this BDS: It
+ * will be used to make relative filenames absolute by prepending this
+ * function's return value to them.
+ */
+ char *(*bdrv_dirname)(BlockDriverState *bs, Error **errp);
/* aio */
BlockAIOCB *(*bdrv_aio_preadv)(BlockDriverState *bs,
const char *name,
Error **errp);
int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
- ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs);
+ ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs,
+ Error **errp);
int coroutine_fn (*bdrv_save_vmstate)(BlockDriverState *bs,
QEMUIOVector *qiov,
void (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size);
void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host);
QLIST_ENTRY(BlockDriver) list;
+
+ /* Pointer to a NULL-terminated array of names of strong options
+ * that can be specified for bdrv_open(). A strong option is one
+ * that changes the data of a BDS.
+ * If this pointer is NULL, the array is considered empty.
+ * "filename" and "driver" are always considered strong. */
+ const char *const *strong_runtime_opts;
};
typedef struct BlockLimits {
*/
uint64_t shared_perm;
+ /* backup of permissions during permission update procedure */
+ bool has_backup_perm;
+ uint64_t backup_perm;
+ uint64_t backup_shared_perm;
+
QLIST_ENTRY(BdrvChild) next;
QLIST_ENTRY(BdrvChild) next_parent;
};
char filename[PATH_MAX];
char backing_file[PATH_MAX]; /* if non zero, the image is a diff of
this file image */
+ /* The backing filename indicated by the image header; if we ever
+ * open this file, then this is replaced by the resulting BDS's
+ * filename (i.e. after a bdrv_refresh_filename() run). */
+ char auto_backing_file[PATH_MAX];
char backing_format[16]; /* if non-zero and backing_file exists */
QDict *full_open_options;
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
Error **errp);
int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
-int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp);
+int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc,
+ NBDReply *reply, Error **errp);
int nbd_client(int fd);
int nbd_disconnect(int fd);
int nbd_errno_to_system_errno(int err);
const char *snapshot_id,
const char *name,
Error **errp);
-int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
- const char *id_or_name,
- Error **errp);
int bdrv_snapshot_list(BlockDriverState *bs,
QEMUSnapshotInfo **psn_info);
int bdrv_snapshot_load_tmp(BlockDriverState *bs,
bool qemu_chr_fe_backend_open(CharBackend *be);
/**
- * qemu_chr_fe_set_handlers:
+ * qemu_chr_fe_set_handlers_full:
* @b: a CharBackend
* @fd_can_read: callback to get the amount of data the frontend may
* receive
* @context: a main loop context or NULL for the default
* @set_open: whether to call qemu_chr_fe_set_open() implicitely when
* any of the handler is non-NULL
+ * @sync_state: whether to issue event callback with updated state
*
* Set the front end char handlers. The front end takes the focus if
* any of the handler is non-NULL.
*
* Without associated Chardev, nothing is changed.
*/
+void qemu_chr_fe_set_handlers_full(CharBackend *b,
+ IOCanReadHandler *fd_can_read,
+ IOReadHandler *fd_read,
+ IOEventHandler *fd_event,
+ BackendChangeHandler *be_change,
+ void *opaque,
+ GMainContext *context,
+ bool set_open,
+ bool sync_state);
+
+/**
+ * qemu_chr_fe_set_handlers:
+ *
+ * Version of qemu_chr_fe_set_handlers_full() with sync_state = true.
+ */
void qemu_chr_fe_set_handlers(CharBackend *b,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
* is active; return the #GSource's tag. If it is disconnected,
* or without associated Chardev, return 0.
*
+ * Note that you are responsible to update the front-end sources if
+ * you are switching the main context with qemu_chr_fe_set_handlers().
+ *
* Returns: the source tag
*/
guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
#define CHARDEV_IS_MUX(chr) \
object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX)
-void mux_chr_set_handlers(Chardev *chr, GMainContext *context);
void mux_set_focus(Chardev *chr, int focus);
void mux_chr_send_all_event(Chardev *chr, int event);
/**
* qemu_chr_new_from_opts:
* @opts: see qemu-config.c for a list of valid options
+ * @context: the #GMainContext to be used at initialization time
*
* Create a new character backend from a QemuOpts list.
*
* or left untouched in case of help option
*/
Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
+ GMainContext *context,
Error **errp);
/**
* qemu_chr_new:
* @label: the name of the backend
* @filename: the URI
+ * @context: the #GMainContext to be used at initialization time
*
* Create a new character backend from a URI.
* Do not implicitly initialize a monitor if the chardev is muxed.
*
* Returns: a new character backend
*/
-Chardev *qemu_chr_new(const char *label, const char *filename);
+Chardev *qemu_chr_new(const char *label, const char *filename,
+ GMainContext *context);
/**
* qemu_chr_new_mux_mon:
* @label: the name of the backend
* @filename: the URI
+ * @context: the #GMainContext to be used at initialization time
*
* Create a new character backend from a URI.
* Implicitly initialize a monitor if the chardev is muxed.
*
* Returns: a new character backend
*/
-Chardev *qemu_chr_new_mux_mon(const char *label, const char *filename);
+Chardev *qemu_chr_new_mux_mon(const char *label, const char *filename,
+ GMainContext *context);
/**
* qemu_chr_change:
* @label: the name of the backend
* @filename: the URI
* @permit_mux_mon: if chardev is muxed, initialize a monitor
+ * @context: the #GMainContext to be used at initialization time
*
* Create a new character backend from a URI.
* Character device communications are not written
* Returns: a new character backend
*/
Chardev *qemu_chr_new_noreplay(const char *label, const char *filename,
- bool permit_mux_mon);
+ bool permit_mux_mon, GMainContext *context);
/**
* qemu_chr_be_can_write:
} ChardevClass;
Chardev *qemu_chardev_new(const char *id, const char *typename,
- ChardevBackend *backend, Error **errp);
+ ChardevBackend *backend, GMainContext *context,
+ Error **errp);
extern int term_escape_char;
--- /dev/null
+#ifndef CHARDEV_SPICE_H_
+#define CHARDEV_SPICE_H_
+
+#include <spice.h>
+#include "chardev/char-fe.h"
+
+typedef struct SpiceChardev {
+ Chardev parent;
+
+ SpiceCharDeviceInstance sin;
+ bool active;
+ bool blocked;
+ const uint8_t *datapos;
+ int datalen;
+ QLIST_ENTRY(SpiceChardev) next;
+} SpiceChardev;
+
+#define TYPE_CHARDEV_SPICE "chardev-spice"
+#define TYPE_CHARDEV_SPICEVMC "chardev-spicevmc"
+#define TYPE_CHARDEV_SPICEPORT "chardev-spiceport"
+
+#define SPICE_CHARDEV(obj) OBJECT_CHECK(SpiceChardev, (obj), TYPE_CHARDEV_SPICE)
+
+void qemu_chr_open_spice_port(Chardev *chr, ChardevBackend *backend,
+ bool *be_opened, Error **errp);
+
+#endif
#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */
#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
+/*
+ * Physical entry point into the kernel.
+ *
+ * 32bit entry point into the kernel. When requested to launch the
+ * guest kernel, use this entry point to launch the guest in 32-bit
+ * protected mode with paging disabled.
+ *
+ * [ Corresponding definition in Linux kernel: include/xen/interface/elfnote.h ]
+ */
+#define XEN_ELFNOTE_PHYS32_ENTRY 18 /* 0x12 */
/* Note header in a PT_NOTE section */
typedef struct elf32_note {
#endif /* !CONFIG_USER_ONLY */
int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
- uint8_t *buf, int len, int is_write);
+ uint8_t *buf, target_ulong len, int is_write);
int cpu_exec(CPUState *cpu);
size_t qemu_ram_pagesize_largest(void);
void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
- int len, int is_write);
+ hwaddr len, int is_write);
static inline void cpu_physical_memory_read(hwaddr addr,
- void *buf, int len)
+ void *buf, hwaddr len)
{
cpu_physical_memory_rw(addr, buf, len, 0);
}
static inline void cpu_physical_memory_write(hwaddr addr,
- const void *buf, int len)
+ const void *buf, hwaddr len)
{
cpu_physical_memory_rw(addr, (void *)buf, len, 1);
}
*/
void qemu_flush_coalesced_mmio_buffer(void);
-void cpu_flush_icache_range(hwaddr start, int len);
+void cpu_flush_icache_range(hwaddr start, hwaddr len);
extern struct MemoryRegion io_mem_rom;
extern struct MemoryRegion io_mem_notdirty;
struct MemoryRegionSection *iotlb_to_section(CPUState *cpu,
hwaddr index, MemTxAttrs attrs);
+/*
+ * Note: tlb_fill() can trigger a resize of the TLB. This means that all of the
+ * caller's prior references to the TLB table (e.g. CPUTLBEntry pointers) must
+ * be discarded and looked up again (e.g. via tlb_entry()).
+ */
void tlb_fill(CPUState *cpu, target_ulong addr, int size,
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr);
#define dh_alias_f32 i32
#define dh_alias_f64 i64
#define dh_alias_ptr ptr
+#define dh_alias_cptr ptr
#define dh_alias_void void
#define dh_alias_noreturn noreturn
#define dh_alias(t) glue(dh_alias_, t)
#define dh_ctype_f32 float32
#define dh_ctype_f64 float64
#define dh_ctype_ptr void *
+#define dh_ctype_cptr const void *
#define dh_ctype_void void
#define dh_ctype_noreturn void QEMU_NORETURN
#define dh_ctype(t) dh_ctype_##t
#define dh_is_64bit_i32 0
#define dh_is_64bit_i64 1
#define dh_is_64bit_ptr (sizeof(void *) == 8)
+#define dh_is_64bit_cptr dh_is_64bit_ptr
#define dh_is_64bit(t) glue(dh_is_64bit_, dh_alias(t))
#define dh_is_signed_void 0
extension instructions that may be required, e.g. ia64's addp4. But
for now we don't support any 64-bit targets with 32-bit pointers. */
#define dh_is_signed_ptr 0
+#define dh_is_signed_cptr dh_is_signed_ptr
#define dh_is_signed_env dh_is_signed_ptr
#define dh_is_signed(t) dh_is_signed_##t
#define dh_callflag_f32 0
#define dh_callflag_f64 0
#define dh_callflag_ptr 0
+#define dh_callflag_cptr dh_callflag_ptr
#define dh_callflag_void 0
#define dh_callflag_noreturn TCG_CALL_NO_RETURN
#define dh_callflag(t) glue(dh_callflag_, dh_alias(t))
unsigned int user:1;
/* Requester ID (for MSI for example) */
unsigned int requester_id:16;
+ /*
+ * The following are target-specific page-table bits. These are not
+ * related to actual memory transactions at all. However, this structure
+ * is part of the tlb_fill interface, cached in the cputlb structure,
+ * and has unused bits. These fields will be read by target-specific
+ * helpers using env->iotlb[mmu_idx][tlb_index()].attrs.target_tlb_bitN.
+ */
+ unsigned int target_tlb_bit0 : 1;
+ unsigned int target_tlb_bit1 : 1;
+ unsigned int target_tlb_bit2 : 1;
} MemTxAttrs;
/* Bus masters which don't specify any attributes will get this,
*/
MemTxResult address_space_rw(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, uint8_t *buf,
- int len, bool is_write);
+ hwaddr len, bool is_write);
/**
* address_space_write: write to address space.
*/
MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs,
- const uint8_t *buf, int len);
+ const uint8_t *buf, hwaddr len);
/**
* address_space_write_rom: write to address space, including ROM.
*/
MemTxResult address_space_write_rom(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs,
- const uint8_t *buf, int len);
+ const uint8_t *buf, hwaddr len);
/* address_space_ld*: load from an address space
* address_space_st*: store to an address space
* @is_write: indicates the transfer direction
* @attrs: memory attributes
*/
-bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len,
+bool address_space_access_valid(AddressSpace *as, hwaddr addr, hwaddr len,
bool is_write, MemTxAttrs attrs);
/* address_space_map: map a physical memory region into a host virtual address
/* Internal functions, part of the implementation of address_space_read. */
MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr,
- MemTxAttrs attrs, uint8_t *buf, int len);
+ MemTxAttrs attrs, uint8_t *buf, hwaddr len);
MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
MemTxAttrs attrs, uint8_t *buf,
- int len, hwaddr addr1, hwaddr l,
+ hwaddr len, hwaddr addr1, hwaddr l,
MemoryRegion *mr);
void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr);
/* Internal functions, part of the implementation of address_space_read_cached
* and address_space_write_cached. */
void address_space_read_cached_slow(MemoryRegionCache *cache,
- hwaddr addr, void *buf, int len);
+ hwaddr addr, void *buf, hwaddr len);
void address_space_write_cached_slow(MemoryRegionCache *cache,
- hwaddr addr, const void *buf, int len);
+ hwaddr addr, const void *buf, hwaddr len);
static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)
{
static inline __attribute__((__always_inline__))
MemTxResult address_space_read(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, uint8_t *buf,
- int len)
+ hwaddr len)
{
MemTxResult result = MEMTX_OK;
hwaddr l, addr1;
*/
static inline void
address_space_read_cached(MemoryRegionCache *cache, hwaddr addr,
- void *buf, int len)
+ void *buf, hwaddr len)
{
assert(addr < cache->len && len <= cache->len - addr);
if (likely(cache->ptr)) {
*/
static inline void
address_space_write_cached(MemoryRegionCache *cache, hwaddr addr,
- void *buf, int len)
+ void *buf, hwaddr len)
{
assert(addr < cache->len && len <= cache->len - addr);
if (likely(cache->ptr)) {
cpu_get_tb_cpu_state(env, pc, cs_base, flags);
hash = tb_jmp_cache_hash_func(*pc);
tb = atomic_rcu_read(&cpu->tb_jmp_cache[hash]);
+
+ cf_mask &= ~CF_CLUSTER_MASK;
+ cf_mask |= cpu->cluster_index << CF_CLUSTER_SHIFT;
+
if (likely(tb &&
tb->pc == *pc &&
tb->cs_base == *cs_base &&
static inline bool float32_is_normal(float32 a)
{
- return ((float32_val(a) + 0x00800000) & 0x7fffffff) >= 0x01000000;
+ return (((float32_val(a) >> 23) + 1) & 0xff) >= 2;
}
static inline bool float32_is_denormal(float32 a)
static inline bool float64_is_normal(float64 a)
{
- return ((float64_val(a) + (1ULL << 52)) & -1ULL >> 1) >= 1ULL << 53;
+ return (((float64_val(a) >> 52) + 1) & 0x7ff) >= 2;
}
static inline bool float64_is_denormal(float64 a)
int64_t float128_to_int64_round_to_zero(float128, float_status *status);
uint64_t float128_to_uint64(float128, float_status *status);
uint64_t float128_to_uint64_round_to_zero(float128, float_status *status);
+uint32_t float128_to_uint32(float128, float_status *status);
uint32_t float128_to_uint32_round_to_zero(float128, float_status *status);
float32 float128_to_float32(float128, float_status *status);
float64 float128_to_float64(float128, float_status *status);
return (a.high & 0x7fff000000000000LL) == 0;
}
+static inline bool float128_is_normal(float128 a)
+{
+ return (((a.high >> 48) + 1) & 0x7fff) >= 2;
+}
+
+static inline bool float128_is_denormal(float128 a)
+{
+ return float128_is_zero_or_denormal(a) && !float128_is_zero(a);
+}
+
static inline int float128_is_any_nan(float128 a)
{
return ((a.high >> 48) & 0x7fff) == 0x7fff &&
}
#define g_strv_contains(a, b) g_strv_contains_qemu(a, b)
-#if !GLIB_CHECK_VERSION(2, 58, 0)
-typedef struct QemuGSpawnFds {
- GSpawnChildSetupFunc child_setup;
- gpointer user_data;
- gint stdin_fd;
- gint stdout_fd;
- gint stderr_fd;
-} QemuGSpawnFds;
-
-static inline void
-qemu_gspawn_fds_setup(gpointer user_data)
-{
- QemuGSpawnFds *q = (QemuGSpawnFds *)user_data;
-
- dup2(q->stdin_fd, 0);
- dup2(q->stdout_fd, 1);
- dup2(q->stderr_fd, 2);
- q->child_setup(q->user_data);
-}
-#endif
-
-static inline gboolean
-g_spawn_async_with_fds_qemu(const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_pid,
- gint stdin_fd,
- gint stdout_fd,
- gint stderr_fd,
- GError **error)
-{
-#if GLIB_CHECK_VERSION(2, 58, 0)
- return g_spawn_async_with_fds(working_directory, argv, envp, flags,
- child_setup, user_data,
- child_pid, stdin_fd, stdout_fd, stderr_fd,
- error);
-#else
- QemuGSpawnFds setup = {
- .child_setup = child_setup,
- .user_data = user_data,
- .stdin_fd = stdin_fd,
- .stdout_fd = stdout_fd,
- .stderr_fd = stderr_fd,
- };
-
- return g_spawn_async(working_directory, argv, envp, flags,
- qemu_gspawn_fds_setup, &setup,
- child_pid, error);
-#endif
-}
-
-#define g_spawn_async_with_fds(wd, argv, env, f, c, d, p, ifd, ofd, efd, err) \
- g_spawn_async_with_fds_qemu(wd, argv, env, f, c, d, p, ifd, ofd, efd, err)
-
#if defined(_WIN32) && !GLIB_CHECK_VERSION(2, 50, 0)
/*
* g_poll has a problem on Windows when using
* being the same for both, to avoid having to have separate Property
* lists for different variants. This restriction can be relaxed later
* if necessary.)
+ * + QOM property "SRAM_ADDR_WIDTH" sets the number of bits used for the
+ * address of each SRAM bank (and thus the total amount of internal SRAM)
+ * + QOM property "init-svtor" sets the initial value of the CPU SVTOR register
+ * (where it expects to load the PC and SP from the vector table on reset)
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
* which are wired to its NVIC lines 32 .. n+32
* + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
#include "hw/misc/iotkit-sysctl.h"
#include "hw/misc/iotkit-sysinfo.h"
#include "hw/misc/armsse-cpuid.h"
+#include "hw/misc/armsse-mhu.h"
#include "hw/misc/unimp.h"
#include "hw/or-irq.h"
#include "hw/core/split-irq.h"
IoTKitSysCtl sysctl;
IoTKitSysCtl sysinfo;
- UnimplementedDeviceState mhu[2];
+ ARMSSEMHU mhu[2];
UnimplementedDeviceState ppu[NUM_PPUS];
UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
UnimplementedDeviceState cpusecctrl[SSE_MAX_CPUS];
MemoryRegion cpu_container[SSE_MAX_CPUS];
MemoryRegion alias1;
MemoryRegion alias2;
- MemoryRegion alias3;
+ MemoryRegion alias3[SSE_MAX_CPUS];
MemoryRegion sram[MAX_SRAM_BANKS];
qemu_irq *exp_irqs[SSE_MAX_CPUS];
uint32_t exp_numirq;
uint32_t mainclk_frq;
uint32_t sram_addr_width;
+ uint32_t init_svtor;
} ARMSSE;
typedef struct ARMSSEInfo ARMSSEInfo;
int default_cpus;
unsigned int no_serial:1,
no_parallel:1,
- use_virtcon:1,
no_floppy:1,
no_cdrom:1,
no_sdcard:1,
#ifndef HW_PL011_H
#define HW_PL011_H
+#include "hw/sysbus.h"
+#include "chardev/char-fe.h"
+
+#define TYPE_PL011 "pl011"
+#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
+
+/* This shares the same struct (and cast macro) as the base pl011 device */
+#define TYPE_PL011_LUMINARY "pl011_luminary"
+
+typedef struct PL011State {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ uint32_t readbuff;
+ uint32_t flags;
+ uint32_t lcr;
+ uint32_t rsr;
+ uint32_t cr;
+ uint32_t dmacr;
+ uint32_t int_enabled;
+ uint32_t int_level;
+ uint32_t read_fifo[16];
+ uint32_t ilpr;
+ uint32_t ibrd;
+ uint32_t fbrd;
+ uint32_t ifl;
+ int read_pos;
+ int read_count;
+ int read_trigger;
+ CharBackend chr;
+ qemu_irq irq[6];
+ const unsigned char *id;
+} PL011State;
+
static inline DeviceState *pl011_create(hwaddr addr,
qemu_irq irq,
Chardev *chr)
return ret;
}
+/*
+ * Given 'nhdr', a pointer to a range of ELF Notes, search through them
+ * for a note matching type 'elf_note_type' and return a pointer to
+ * the matching ELF note.
+ */
+static struct elf_note *glue(get_elf_note_type, SZ)(struct elf_note *nhdr,
+ elf_word note_size,
+ elf_word phdr_align,
+ elf_word elf_note_type)
+{
+ elf_word nhdr_size = sizeof(struct elf_note);
+ elf_word elf_note_entry_offset = 0;
+ elf_word note_type;
+ elf_word nhdr_namesz;
+ elf_word nhdr_descsz;
+
+ if (nhdr == NULL) {
+ return NULL;
+ }
+
+ note_type = nhdr->n_type;
+ while (note_type != elf_note_type) {
+ nhdr_namesz = nhdr->n_namesz;
+ nhdr_descsz = nhdr->n_descsz;
+
+ elf_note_entry_offset = nhdr_size +
+ QEMU_ALIGN_UP(nhdr_namesz, phdr_align) +
+ QEMU_ALIGN_UP(nhdr_descsz, phdr_align);
+
+ /*
+ * If the offset calculated in this iteration exceeds the
+ * supplied size, we are done and no matching note was found.
+ */
+ if (elf_note_entry_offset > note_size) {
+ return NULL;
+ }
+
+ /* skip to the next ELF Note entry */
+ nhdr = (void *)nhdr + elf_note_entry_offset;
+ note_type = nhdr->n_type;
+ }
+
+ return nhdr;
+}
+
static int glue(load_elf, SZ)(const char *name, int fd,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque,
int must_swab, uint64_t *pentry,
high = addr + mem_size;
data = NULL;
+
+ } else if (ph->p_type == PT_NOTE && elf_note_fn) {
+ struct elf_note *nhdr = NULL;
+
+ file_size = ph->p_filesz; /* Size of the range of ELF notes */
+ data = g_malloc0(file_size);
+ if (ph->p_filesz > 0) {
+ if (lseek(fd, ph->p_offset, SEEK_SET) < 0) {
+ goto fail;
+ }
+ if (read(fd, data, file_size) != file_size) {
+ goto fail;
+ }
+ }
+
+ /*
+ * Search the ELF notes to find one with a type matching the
+ * value passed in via 'translate_opaque'
+ */
+ nhdr = (struct elf_note *)data;
+ assert(translate_opaque != NULL);
+ nhdr = glue(get_elf_note_type, SZ)(nhdr, file_size, ph->p_align,
+ *(uint64_t *)translate_opaque);
+ if (nhdr != NULL) {
+ bool is64 =
+ sizeof(struct elf_note) == sizeof(struct elf64_note);
+ elf_note_fn((void *)nhdr, (void *)&ph->p_align, is64);
+ }
+ g_free(data);
+ data = NULL;
}
}
+
g_free(phdr);
if (lowaddr)
*lowaddr = (uint64_t)(elf_sword)low;
/* use DMA capable linuxboot option rom */
bool linuxboot_dma_enabled;
+
+ /* use PVH to load kernels that support this feature */
+ bool pvh_enabled;
} PCMachineClass;
#define TYPE_PC_MACHINE "generic-pc-machine"
typedef struct IDEBufferedRequest {
QLIST_ENTRY(IDEBufferedRequest) list;
- struct iovec iov;
QEMUIOVector qiov;
QEMUIOVector *original_qiov;
BlockCompletionFunc *original_cb;
int atapi_dma; /* true if dma is requested for the packet cmd */
BlockAcctCookie acct;
BlockAIOCB *pio_aiocb;
- struct iovec iov;
QEMUIOVector qiov;
QLIST_HEAD(, IDEBufferedRequest) buffered_requests;
/* ATA DMA state */
struct IDEDMA {
const struct IDEDMAOps *ops;
- struct iovec iov;
QEMUIOVector qiov;
BlockAIOCB *aiocb;
};
/** load_elf_ram_sym:
* @filename: Path of ELF file
+ * @elf_note_fn: optional function to parse ELF Note type
+ * passed via @translate_opaque
* @translate_fn: optional function to translate load addresses
* @translate_opaque: opaque data passed to @translate_fn
* @pentry: Populated with program entry point. Ignored if NULL.
uint64_t st_value, uint64_t st_size);
int load_elf_ram_sym(const char *filename,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr, int big_endian,
* symbol callback function
*/
int load_elf_ram(const char *filename,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
* Same as load_elf_ram(), but always loads the elf as ROM
*/
int load_elf_as(const char *filename,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
* Same as load_elf_as(), but doesn't allow the caller to specify an
* AddressSpace.
*/
-int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
+int load_elf(const char *filename,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
+ uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
int clear_lsb, int data_swab);
--- /dev/null
+/*
+ * ARM SSE-200 Message Handling Unit (MHU)
+ *
+ * Copyright (c) 2019 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the Message Handling Unit (MHU) which is part of the
+ * Arm SSE-200 and documented in
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
+ *
+ * QEMU interface:
+ * + sysbus MMIO region 0: the system information register bank
+ * + sysbus IRQ 0: interrupt for CPU 0
+ * + sysbus IRQ 1: interrupt for CPU 1
+ */
+
+#ifndef HW_MISC_SSE_MHU_H
+#define HW_MISC_SSE_MHU_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_ARMSSE_MHU "armsse-mhu"
+#define ARMSSE_MHU(obj) OBJECT_CHECK(ARMSSEMHU, (obj), TYPE_ARMSSE_MHU)
+
+typedef struct ARMSSEMHU {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ qemu_irq cpu0irq;
+ qemu_irq cpu1irq;
+
+ uint32_t cpu0intr;
+ uint32_t cpu1intr;
+} ARMSSEMHU;
+
+#endif
* "system control register" blocks.
*
* QEMU interface:
+ * + QOM property "SYS_VERSION": value of the SYS_VERSION register of the
+ * system information block of the SSE
+ * (used to identify whether to provide SSE-200-only registers)
* + sysbus MMIO region 0: the system information register bank
* + sysbus MMIO region 1: the system control register bank
*/
uint32_t reset_syndrome;
uint32_t reset_mask;
uint32_t gretreg;
- uint32_t initsvrtor0;
+ uint32_t initsvtor0;
uint32_t cpuwait;
uint32_t wicctrl;
+ uint32_t scsecctrl;
+ uint32_t fclk_div;
+ uint32_t sysclk_div;
+ uint32_t clock_force;
+ uint32_t initsvtor1;
+ uint32_t nmi_enable;
+ uint32_t ewctrl;
+ uint32_t pdcm_pd_sys_sense;
+ uint32_t pdcm_pd_sram0_sense;
+ uint32_t pdcm_pd_sram1_sense;
+ uint32_t pdcm_pd_sram2_sense;
+ uint32_t pdcm_pd_sram3_sense;
+
+ /* Properties */
+ uint32_t sys_version;
+ uint32_t cpuwait_rst;
+ uint32_t initsvtor0_rst;
+ uint32_t initsvtor1_rst;
+
+ bool is_sse200;
} IoTKitSysCtl;
#endif
*
* QEMU interface:
* + sysbus MMIO regions 0..15: MemoryRegions defining the upstream end
- * of each of the 16 ports of the PPC
+ * of each of the 16 ports of the PPC. When a port is unused (i.e. no
+ * downstream MemoryRegion is connected to it) at the end of the 0..15
+ * range then no sysbus MMIO region is created for its upstream. When an
+ * unused port lies in the middle of the range with other used ports at
+ * higher port numbers, a dummy MMIO region is created to ensure that
+ * port N's upstream is always sysbus MMIO region N. Dummy regions should
+ * not be mapped, and will assert if any access is made to them.
* + Property "port[0..15]": MemoryRegion defining the downstream device(s)
* for each of the 16 ports of the PPC
* + Named GPIO inputs "cfg_nonsec[0..15]": set to 1 if the port should be
return spapr_qirq(spapr, phb->lsi_table[pin].irq);
}
-int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, void *fdt,
- uint32_t nr_msis);
+int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t intc_phandle, void *fdt,
+ uint32_t nr_msis, int *node_offset);
void spapr_pci_rtas_init(void);
PCIDevice *spapr_pci_find_dev(sPAPRMachineState *spapr, uint64_t buid,
uint32_t config_addr);
-/* PCI release callback. */
+/* DRC callbacks */
void spapr_phb_remove_pci_device_cb(DeviceState *dev);
+int spapr_pci_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
/* VFIO EEH hooks */
#ifdef CONFIG_LINUX
void spapr_phb_dma_reset(sPAPRPHBState *sphb);
+static inline unsigned spapr_phb_windows_supported(sPAPRPHBState *sphb)
+{
+ return sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1;
+}
+
#endif /* PCI_HOST_SPAPR_H */
bool msi_per_vector_mask, Error **errp);
void msi_uninit(struct PCIDevice *dev);
void msi_reset(PCIDevice *dev);
+bool msi_is_masked(const PCIDevice *dev, unsigned int vector);
void msi_notify(PCIDevice *dev, unsigned int vector);
void msi_send_message(PCIDevice *dev, MSIMessage msg);
void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len);
static inline void ppc6xx_irq_init(PowerPCCPU *cpu) {}
static inline void ppc970_irq_init(PowerPCCPU *cpu) {}
static inline void ppcPOWER7_irq_init(PowerPCCPU *cpu) {}
+static inline void ppcPOWER9_irq_init(PowerPCCPU *cpu) {}
static inline void ppce500_irq_init(PowerPCCPU *cpu) {}
#else
void ppc40x_irq_init(PowerPCCPU *cpu);
void ppc6xx_irq_init(PowerPCCPU *cpu);
void ppc970_irq_init(PowerPCCPU *cpu);
void ppcPOWER7_irq_init(PowerPCCPU *cpu);
+void ppcPOWER9_irq_init(PowerPCCPU *cpu);
#endif
/* PPC machines for OpenBIOS */
/*< public >*/
bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */
+ bool dr_phb_enabled; /* enable dynamic-reconfig/hotplug of PHBs */
bool update_dt_enabled; /* enable KVMPPC_H_UPDATE_DT */
bool use_ohci_by_default; /* use USB-OHCI instead of XHCI */
bool pre_2_10_has_unused_icps;
/*< public >*/
char *kvm_type;
+ char *host_model;
+ char *host_serial;
- const char *icp_type;
int32_t irq_map_nr;
unsigned long *irq_map;
sPAPRXive *xive;
* "interrupt-controller" node has its "#interrupt-cells" property set to 2 (ie,
* VIO devices, RTAS event sources and PHBs).
*/
-static inline void spapr_dt_xics_irq(uint32_t *intspec, int irq, bool is_lsi)
+static inline void spapr_dt_irq(uint32_t *intspec, int irq, bool is_lsi)
{
intspec[0] = cpu_to_be32(irq);
intspec[1] = is_lsi ? cpu_to_be32(1) : 0;
void spapr_clear_pending_events(sPAPRMachineState *spapr);
int spapr_max_server_number(sPAPRMachineState *spapr);
-/* CPU and LMB DRC release callbacks. */
+/* DRC callbacks. */
void spapr_core_release(DeviceState *dev);
+int spapr_core_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
void spapr_lmb_release(DeviceState *dev);
+int spapr_lmb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
+void spapr_phb_release(DeviceState *dev);
+int spapr_phb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
void spapr_rtc_read(sPAPRRTCState *rtc, struct tm *tm, uint32_t *ns);
int spapr_rtc_import_offset(sPAPRRTCState *rtc, int64_t legacy_offset);
#define SPAPR_OV5_XIVE_EXPLOIT 0x40
#define SPAPR_OV5_XIVE_BOTH 0x80 /* Only to advertise on the platform */
+void spapr_set_all_lpcrs(target_ulong value, target_ulong mask);
#endif /* HW_SPAPR_H */
#include "qom/object.h"
#include "sysemu/sysemu.h"
#include "hw/qdev.h"
+#include "qapi/error.h"
#define TYPE_SPAPR_DR_CONNECTOR "spapr-dr-connector"
#define SPAPR_DR_CONNECTOR_GET_CLASS(obj) \
#define SPAPR_DRC_LMB(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
TYPE_SPAPR_DRC_LMB)
+#define TYPE_SPAPR_DRC_PHB "spapr-drc-phb"
+#define SPAPR_DRC_PHB_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_PHB)
+#define SPAPR_DRC_PHB_CLASS(klass) \
+ OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, TYPE_SPAPR_DRC_PHB)
+#define SPAPR_DRC_PHB(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
+ TYPE_SPAPR_DRC_PHB)
+
/*
* Various hotplug types managed by sPAPRDRConnector
*
int fdt_start_offset;
} sPAPRDRConnector;
+struct sPAPRMachineState;
+
typedef struct sPAPRDRConnectorClass {
/*< private >*/
DeviceClass parent;
uint32_t (*isolate)(sPAPRDRConnector *drc);
uint32_t (*unisolate)(sPAPRDRConnector *drc);
void (*release)(DeviceState *dev);
+
+ int (*dt_populate)(sPAPRDRConnector *drc, struct sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
} sPAPRDRConnectorClass;
typedef struct sPAPRDRCPhysical {
int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
uint32_t drc_type_mask);
-void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
- int fdt_start_offset, Error **errp);
+void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, Error **errp);
void spapr_drc_detach(sPAPRDRConnector *drc);
bool spapr_drc_needed(void *opaque);
uint32_t nr_msis;
uint8_t ov5;
- void (*init)(sPAPRMachineState *spapr, Error **errp);
+ void (*init)(sPAPRMachineState *spapr, int nr_irqs, Error **errp);
int (*claim)(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp);
void (*free)(sPAPRMachineState *spapr, int irq, int num);
qemu_irq (*qirq)(sPAPRMachineState *spapr, int irq);
int (*post_load)(sPAPRMachineState *spapr, int version_id);
void (*reset)(sPAPRMachineState *spapr, Error **errp);
void (*set_irq)(void *opaque, int srcno, int val);
+ const char *(*get_nodename)(sPAPRMachineState *spapr);
} sPAPRIrq;
extern sPAPRIrq spapr_irq_xics;
qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq);
int spapr_irq_post_load(sPAPRMachineState *spapr, int version_id);
void spapr_irq_reset(sPAPRMachineState *spapr, Error **errp);
+int spapr_irq_get_phandle(sPAPRMachineState *spapr, void *fdt, Error **errp);
/*
* XICS legacy routines
XiveENDSource end_source;
hwaddr end_base;
+ /* DT */
+ gchar *nodename;
+
/* Routing table */
XiveEAS *eat;
uint32_t nr_irqs;
#define TYPE_ICP "icp"
#define ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_ICP)
-#define TYPE_KVM_ICP "icp-kvm"
-#define KVM_ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_KVM_ICP)
-
#define TYPE_PNV_ICP "pnv-icp"
#define PNV_ICP(obj) OBJECT_CHECK(PnvICPState, (obj), TYPE_PNV_ICP)
DeviceClass parent_class;
DeviceRealize parent_realize;
- DeviceReset parent_reset;
-
- void (*pre_save)(ICPState *icp);
- int (*post_load)(ICPState *icp, int version_id);
- void (*synchronize_state)(ICPState *icp);
};
struct ICPState {
#define TYPE_ICS_SIMPLE "ics"
#define ICS_SIMPLE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
-#define TYPE_ICS_KVM "icskvm"
-#define ICS_KVM(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_KVM)
-
#define ICS_BASE_CLASS(klass) \
OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_BASE)
#define ICS_BASE_GET_CLASS(obj) \
DeviceRealize parent_realize;
DeviceReset parent_reset;
- void (*pre_save)(ICSState *s);
- int (*post_load)(ICSState *s, int version_id);
void (*reject)(ICSState *s, uint32_t irq);
void (*resend)(ICSState *s);
void (*eoi)(ICSState *s, uint32_t irq);
- void (*synchronize_state)(ICSState *s);
};
struct ICSState {
void ics_simple_write_xive(ICSState *ics, int nr, int server,
uint8_t priority, uint8_t saved_priority);
void ics_simple_set_irq(void *opaque, int srcno, int val);
-void ics_kvm_set_irq(void *opaque, int srcno, int val);
void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
void icp_pic_print_info(ICPState *icp, Monitor *mon);
Object *icp_create(Object *cpu, const char *type, XICSFabric *xi,
Error **errp);
+/* KVM */
+void icp_get_kvm_state(ICPState *icp);
+int icp_set_kvm_state(ICPState *icp);
+void icp_synchronize_state(ICPState *icp);
+void icp_kvm_realize(DeviceState *dev, Error **errp);
+
+void ics_get_kvm_state(ICSState *ics);
+int ics_set_kvm_state_one(ICSState *ics, int srcno);
+int ics_set_kvm_state(ICSState *ics);
+void ics_synchronize_state(ICSState *ics);
+void ics_kvm_set_irq(ICSState *ics, int srcno, int val);
+
#endif /* XICS_H */
#include "hw/ppc/spapr.h"
+#define XICS_NODENAME "interrupt-controller"
+
void spapr_dt_xics(sPAPRMachineState *spapr, uint32_t nr_servers, void *fdt,
uint32_t phandle);
int xics_kvm_init(sPAPRMachineState *spapr, Error **errp);
return test_bit(srcno, xsrc->lsi_map);
}
-static inline void xive_source_irq_set(XiveSource *xsrc, uint32_t srcno,
- bool lsi)
+static inline void xive_source_irq_set_lsi(XiveSource *xsrc, uint32_t srcno)
{
assert(srcno < xsrc->nr_irqs);
- if (lsi) {
- bitmap_set(xsrc->lsi_map, srcno, 1);
- }
+ bitmap_set(xsrc->lsi_map, srcno, 1);
}
void xive_source_set_irq(void *opaque, int srcno, int val);
GSList *qdev_build_hotpluggable_device_list(Object *peripheral);
-void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler,
- Error **errp);
+void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp);
void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp);
#define HW_S390_TOD_H
#include "hw/qdev.h"
+#include "s390-tod.h"
typedef struct S390TOD {
uint8_t high;
void (*set)(S390TODState *td, const S390TOD *tod, Error **errp);
} S390TODClass;
-/* The value of the TOD clock for 1.1.1970. */
-#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
-
-/* Converts ns to s390's clock format */
-static inline uint64_t time2tod(uint64_t ns)
-{
- return (ns << 9) / 125 + (((ns & 0xff80000000000000ull) / 125) << 9);
-}
-
-/* Converts s390's clock format to ns */
-static inline uint64_t tod2time(uint64_t t)
-{
- return ((t >> 9) * 125) + (((t & 0x1ff) * 125) >> 9);
-}
-
void s390_init_tod(void);
S390TODState *s390_get_todstate(void);
--- /dev/null
+/*
+ * ARM AMBA PrimeCell PL031 RTC
+ *
+ * Copyright (c) 2007 CodeSourcery
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#ifndef HW_TIMER_PL031
+#define HW_TIMER_PL031
+
+#include "hw/sysbus.h"
+
+#define TYPE_PL031 "pl031"
+#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
+
+typedef struct PL031State {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ QEMUTimer *timer;
+ qemu_irq irq;
+
+ /*
+ * Needed to preserve the tick_count across migration, even if the
+ * absolute value of the rtc_clock is different on the source and
+ * destination.
+ */
+ uint32_t tick_offset_vmstate;
+ uint32_t tick_offset;
+
+ uint32_t mr;
+ uint32_t lr;
+ uint32_t cr;
+ uint32_t im;
+ uint32_t is;
+} PL031State;
+
+#endif
BlockConf conf;
IOThread *iothread;
char *serial;
- uint32_t scsi;
- uint32_t config_wce;
uint32_t request_merging;
uint16_t num_queues;
uint16_t queue_size;
+ uint32_t max_discard_sectors;
+ uint32_t max_write_zeroes_sectors;
};
struct VirtIOBlockDataPlane;
bool dataplane_disabled;
bool dataplane_started;
struct VirtIOBlockDataPlane *dataplane;
+ uint64_t host_features;
+ size_t config_size;
} VirtIOBlock;
typedef struct VirtIOBlockReq {
enum virtio_gpu_conf_flags {
VIRTIO_GPU_FLAG_VIRGL_ENABLED = 1,
VIRTIO_GPU_FLAG_STATS_ENABLED,
+ VIRTIO_GPU_FLAG_EDID_ENABLED,
};
#define virtio_gpu_virgl_enabled(_cfg) \
(_cfg.flags & (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED))
#define virtio_gpu_stats_enabled(_cfg) \
(_cfg.flags & (1 << VIRTIO_GPU_FLAG_STATS_ENABLED))
+#define virtio_gpu_edid_enabled(_cfg) \
+ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_EDID_ENABLED))
struct virtio_gpu_conf {
uint64_t max_hostmem;
VirtQueue *vq;
struct virtio_gpu_ctrl_hdr cmd_hdr;
uint32_t error;
- bool waiting;
bool finished;
QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
};
int enable;
- int config_size;
- DeviceState *qdev;
-
QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist;
QTAILQ_HEAD(, virtio_gpu_ctrl_command) cmdq;
QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq;
enum virtio_gpu_ctrl_type type);
void virtio_gpu_get_display_info(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd);
+void virtio_gpu_get_edid(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd);
int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
struct virtio_gpu_resource_attach_backing *ab,
struct virtio_gpu_ctrl_command *cmd,
struct virtio_gpu_ctrl_command *cmd);
void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
void virtio_gpu_virgl_reset(VirtIOGPU *g);
-void virtio_gpu_gl_block(void *opaque, bool block);
int virtio_gpu_virgl_init(VirtIOGPU *g);
int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
#endif
return QEMU_ALIGN_UP(addr, align);
}
+/*
+ * Calculate the number of bytes up to and including the given 'field' of
+ * 'container'.
+ */
+#define virtio_endof(container, field) \
+ (offsetof(container, field) + sizeof_field(container, field))
+
+typedef struct VirtIOFeature {
+ uint64_t flags;
+ size_t end;
+} VirtIOFeature;
+
+size_t virtio_feature_get_config_size(VirtIOFeature *features,
+ uint64_t host_features);
+
typedef struct VirtQueue VirtQueue;
#define VIRTQUEUE_MAX_SIZE 1024
--- /dev/null
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2016, Citrix Systems, Inc.
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_X86_HVM_START_INFO_H__
+#define __XEN_PUBLIC_ARCH_X86_HVM_START_INFO_H__
+
+/*
+ * Start of day structure passed to PVH guests and to HVM guests in %ebx.
+ *
+ * NOTE: nothing will be loaded at physical address 0, so a 0 value in any
+ * of the address fields should be treated as not present.
+ *
+ * 0 +----------------+
+ * | magic | Contains the magic value XEN_HVM_START_MAGIC_VALUE
+ * | | ("xEn3" with the 0x80 bit of the "E" set).
+ * 4 +----------------+
+ * | version | Version of this structure. Current version is 1. New
+ * | | versions are guaranteed to be backwards-compatible.
+ * 8 +----------------+
+ * | flags | SIF_xxx flags.
+ * 12 +----------------+
+ * | nr_modules | Number of modules passed to the kernel.
+ * 16 +----------------+
+ * | modlist_paddr | Physical address of an array of modules
+ * | | (layout of the structure below).
+ * 24 +----------------+
+ * | cmdline_paddr | Physical address of the command line,
+ * | | a zero-terminated ASCII string.
+ * 32 +----------------+
+ * | rsdp_paddr | Physical address of the RSDP ACPI data structure.
+ * 40 +----------------+
+ * | memmap_paddr | Physical address of the (optional) memory map. Only
+ * | | present in version 1 and newer of the structure.
+ * 48 +----------------+
+ * | memmap_entries | Number of entries in the memory map table. Only
+ * | | present in version 1 and newer of the structure.
+ * | | Zero if there is no memory map being provided.
+ * 52 +----------------+
+ * | reserved | Version 1 and newer only.
+ * 56 +----------------+
+ *
+ * The layout of each entry in the module structure is the following:
+ *
+ * 0 +----------------+
+ * | paddr | Physical address of the module.
+ * 8 +----------------+
+ * | size | Size of the module in bytes.
+ * 16 +----------------+
+ * | cmdline_paddr | Physical address of the command line,
+ * | | a zero-terminated ASCII string.
+ * 24 +----------------+
+ * | reserved |
+ * 32 +----------------+
+ *
+ * The layout of each entry in the memory map table is as follows:
+ *
+ * 0 +----------------+
+ * | addr | Base address
+ * 8 +----------------+
+ * | size | Size of mapping in bytes
+ * 16 +----------------+
+ * | type | Type of mapping as defined between the hypervisor
+ * | | and guest it's starting. E820_TYPE_xxx, for example.
+ * 20 +----------------|
+ * | reserved |
+ * 24 +----------------+
+ *
+ * The address and sizes are always a 64bit little endian unsigned integer.
+ *
+ * NB: Xen on x86 will always try to place all the data below the 4GiB
+ * boundary.
+ *
+ * Version numbers of the hvm_start_info structure have evolved like this:
+ *
+ * Version 0:
+ *
+ * Version 1: Added the memmap_paddr/memmap_entries fields (plus 4 bytes of
+ * padding) to the end of the hvm_start_info struct. These new
+ * fields can be used to pass a memory map to the guest. The
+ * memory map is optional and so guests that understand version 1
+ * of the structure must check that memmap_entries is non-zero
+ * before trying to read the memory map.
+ */
+#define XEN_HVM_START_MAGIC_VALUE 0x336ec578
+
+/*
+ * C representation of the x86/HVM start info layout.
+ *
+ * The canonical definition of this layout is above, this is just a way to
+ * represent the layout described there using C types.
+ */
+struct hvm_start_info {
+ uint32_t magic; /* Contains the magic value 0x336ec578 */
+ /* ("xEn3" with the 0x80 bit of the "E" set).*/
+ uint32_t version; /* Version of this structure. */
+ uint32_t flags; /* SIF_xxx flags. */
+ uint32_t nr_modules; /* Number of modules passed to the kernel. */
+ uint64_t modlist_paddr; /* Physical address of an array of */
+ /* hvm_modlist_entry. */
+ uint64_t cmdline_paddr; /* Physical address of the command line. */
+ uint64_t rsdp_paddr; /* Physical address of the RSDP ACPI data */
+ /* structure. */
+ uint64_t memmap_paddr; /* Physical address of an array of */
+ /* hvm_memmap_table_entry. Only present in */
+ /* version 1 and newer of the structure */
+ uint32_t memmap_entries; /* Number of entries in the memmap table. */
+ /* Only present in version 1 and newer of */
+ /* the structure. Value will be zero if */
+ /* there is no memory map being provided. */
+ uint32_t reserved;
+};
+
+struct hvm_modlist_entry {
+ uint64_t paddr; /* Physical address of the module. */
+ uint64_t size; /* Size of the module in bytes. */
+ uint64_t cmdline_paddr; /* Physical address of the command line. */
+ uint64_t reserved;
+};
+
+struct hvm_memmap_table_entry {
+ uint64_t addr; /* Base address of the memory region */
+ uint64_t size; /* Size of the memory region in bytes */
+ uint32_t type; /* Mapping type */
+ uint32_t reserved;
+};
+
+#endif /* __XEN_PUBLIC_ARCH_X86_HVM_START_INFO_H__ */
* addition, no two coroutine can be waiting on the same condition
* and channel at the same time.
*
- * This must only be called from coroutine context
+ * This must only be called from coroutine context. It is safe to
+ * reenter the coroutine externally while it is waiting; in this
+ * case the function will return even if @condition is not yet
+ * available.
*/
-void qio_channel_yield(QIOChannel *ioc,
- GIOCondition condition);
+void coroutine_fn qio_channel_yield(QIOChannel *ioc,
+ GIOCondition condition);
/**
* qio_channel_wait:
*
* Run a task in a background thread. When @worker
* returns it will call qio_task_complete() in
- * the event thread context that provided.
+ * the thread that is running the main loop associated
+ * with @context.
*/
void qio_task_run_in_thread(QIOTask *task,
QIOTaskWorker worker,
GDestroyNotify destroy,
GMainContext *context);
+
+/**
+ * qio_task_wait_thread:
+ * @task: the task struct
+ *
+ * Wait for completion of a task that was previously
+ * invoked using qio_task_run_in_thread. This MUST
+ * ONLY be invoked if the task has not already
+ * completed, since after the completion callback
+ * is invoked, @task will have been freed.
+ *
+ * To avoid racing with execution of the completion
+ * callback provided with qio_task_new, this method
+ * MUST ONLY be invoked from the thread that is
+ * running the main loop associated with @context
+ * parameter to qio_task_run_in_thread.
+ *
+ * When the thread has completed, the completion
+ * callback provided to qio_task_new will be invoked.
+ * When that callback returns @task will be freed,
+ * so @task must not be referenced after this
+ * method completes.
+ */
+void qio_task_wait_thread(QIOTask *task);
+
+
/**
* qio_task_complete:
* @task: the task struct
int iovcnt);
ssize_t qemu_sendv_packet_async(NetClientState *nc, const struct iovec *iov,
int iovcnt, NetPacketSent *sent_cb);
-void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size);
+ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size);
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size);
ssize_t qemu_send_packet_async(NetClientState *nc, const uint8_t *buf,
int size, NetPacketSent *sent_cb);
void qmp_register_command(QmpCommandList *cmds, const char *name,
QmpCommandFunc *fn, QmpCommandOptions options);
-void qmp_unregister_command(QmpCommandList *cmds, const char *name);
QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name);
void qmp_disable_command(QmpCommandList *cmds, const char *name);
void qmp_enable_command(QmpCommandList *cmds, const char *name);
#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
/* Copyright string for -version arguments, About dialogs, etc */
-#define QEMU_COPYRIGHT "Copyright (c) 2003-2018 " \
+#define QEMU_COPYRIGHT "Copyright (c) 2003-2019 " \
"Fabrice Bellard and the QEMU Project developers"
/* Bug reporting information for --help arguments, About dialogs, etc */
+++ /dev/null
-/*
- * QEMU access control list management
- *
- * Copyright (C) 2009 Red Hat, Inc
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#ifndef QEMU_ACL_H
-#define QEMU_ACL_H
-
-#include "qemu/queue.h"
-
-typedef struct qemu_acl_entry qemu_acl_entry;
-typedef struct qemu_acl qemu_acl;
-
-struct qemu_acl_entry {
- char *match;
- int deny;
-
- QTAILQ_ENTRY(qemu_acl_entry) next;
-};
-
-struct qemu_acl {
- char *aclname;
- unsigned int nentries;
- QTAILQ_HEAD(,qemu_acl_entry) entries;
- int defaultDeny;
-};
-
-qemu_acl *qemu_acl_init(const char *aclname);
-
-qemu_acl *qemu_acl_find(const char *aclname);
-
-int qemu_acl_party_is_allowed(qemu_acl *acl,
- const char *party);
-
-void qemu_acl_reset(qemu_acl *acl);
-
-int qemu_acl_append(qemu_acl *acl,
- int deny,
- const char *match);
-int qemu_acl_insert(qemu_acl *acl,
- int deny,
- const char *match,
- int index);
-int qemu_acl_remove(qemu_acl *acl,
- const char *match);
-
-#endif /* QEMU_ACL_H */
"cbnz %w[tmp], 0b\n"
"1:"
: [mem] "+m"(*ptr), [tmp] "=&r"(tmp),
- [oldl] "=&r"(oldl), [oldh] "=r"(oldh)
+ [oldl] "=&r"(oldl), [oldh] "=&r"(oldh)
: [cmpl] "r"(cmpl), [cmph] "r"(cmph),
[newl] "r"(newl), [newh] "r"(newh)
: "memory", "cc");
--- /dev/null
+/*
+ * QEMU file monitor helper
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef QEMU_FILE_MONITOR_H
+#define QEMU_FILE_MONITOR_H
+
+#include "qemu-common.h"
+
+
+typedef struct QFileMonitor QFileMonitor;
+
+typedef enum {
+ /* File has been created in a dir */
+ QFILE_MONITOR_EVENT_CREATED,
+ /* File has been modified in a dir */
+ QFILE_MONITOR_EVENT_MODIFIED,
+ /* File has been deleted in a dir */
+ QFILE_MONITOR_EVENT_DELETED,
+ /* File has attributes changed */
+ QFILE_MONITOR_EVENT_ATTRIBUTES,
+ /* Dir is no longer being monitored (due to deletion) */
+ QFILE_MONITOR_EVENT_IGNORED,
+} QFileMonitorEvent;
+
+
+/**
+ * QFileMonitorHandler:
+ * @id: id from qemu_file_monitor_add_watch()
+ * @event: the file change that occurred
+ * @filename: the name of the file affected
+ * @opaque: opaque data provided to qemu_file_monitor_add_watch()
+ *
+ * Invoked whenever a file changes. If @event is
+ * QFILE_MONITOR_EVENT_IGNORED, @filename will be
+ * empty.
+ *
+ */
+typedef void (*QFileMonitorHandler)(int id,
+ QFileMonitorEvent event,
+ const char *filename,
+ void *opaque);
+
+/**
+ * qemu_file_monitor_new:
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Create a handle for a file monitoring object.
+ *
+ * This object does locking internally to enable it to be
+ * safe to use from multiple threads
+ *
+ * If the platform does not support file monitoring, an
+ * error will be reported. Likewise if file monitoring
+ * is supported, but cannot be initialized
+ *
+ * Currently this is implemented on Linux platforms with
+ * the inotify subsystem.
+ *
+ * Returns: the new monitoring object, or NULL on error
+ */
+QFileMonitor *qemu_file_monitor_new(Error **errp);
+
+/**
+ * qemu_file_monitor_free:
+ * @mon: the file monitor context
+ *
+ * Free resources associated with the file monitor,
+ * including any currently registered watches.
+ */
+void qemu_file_monitor_free(QFileMonitor *mon);
+
+/**
+ * qemu_file_monitor_add_watch:
+ * @mon: the file monitor context
+ * @dirpath: the directory whose contents to watch
+ * @filename: optional filename to filter on
+ * @cb: the function to invoke when @dirpath has changes
+ * @opaque: data to pass to @cb
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Register to receive notifications of changes
+ * in the directory @dirpath. All files in the
+ * directory will be monitored. If the caller is
+ * only interested in one specific file, @filename
+ * can be used to filter events.
+ *
+ * Returns: a positive integer watch ID, or -1 on error
+ */
+int qemu_file_monitor_add_watch(QFileMonitor *mon,
+ const char *dirpath,
+ const char *filename,
+ QFileMonitorHandler cb,
+ void *opaque,
+ Error **errp);
+
+/**
+ * qemu_file_monitor_remove_watch:
+ * @mon: the file monitor context
+ * @dirpath: the directory whose contents to unwatch
+ * @id: id of the watch to remove
+ *
+ * Removes the file monitoring watch @id, associated
+ * with the directory @dirpath. This must never be
+ * called from a QFileMonitorHandler callback, or a
+ * deadlock will result.
+ */
+void qemu_file_monitor_remove_watch(QFileMonitor *mon,
+ const char *dirpath,
+ int id);
+
+#endif /* QEMU_FILE_MONITOR_H */
typedef struct QEMUIOVector {
struct iovec *iov;
int niov;
- int nalloc;
- size_t size;
+
+ /*
+ * For external @iov (qemu_iovec_init_external()) or allocated @iov
+ * (qemu_iovec_init()), @size is the cumulative size of iovecs and
+ * @local_iov is invalid and unused.
+ *
+ * For embedded @iov (QEMU_IOVEC_INIT_BUF() or qemu_iovec_init_buf()),
+ * @iov is equal to &@local_iov, and @size is valid, as it has same
+ * offset and type as @local_iov.iov_len, which is guaranteed by
+ * static assertion below.
+ *
+ * @nalloc is always valid and is -1 both for embedded and external
+ * cases. It is included in the union only to ensure the padding prior
+ * to the @size field will not result in a 0-length array.
+ */
+ union {
+ struct {
+ int nalloc;
+ struct iovec local_iov;
+ };
+ struct {
+ char __pad[sizeof(int) + offsetof(struct iovec, iov_len)];
+ size_t size;
+ };
+ };
} QEMUIOVector;
+QEMU_BUILD_BUG_ON(offsetof(QEMUIOVector, size) !=
+ offsetof(QEMUIOVector, local_iov.iov_len));
+
+#define QEMU_IOVEC_INIT_BUF(self, buf, len) \
+{ \
+ .iov = &(self).local_iov, \
+ .niov = 1, \
+ .nalloc = -1, \
+ .local_iov = { \
+ .iov_base = (void *)(buf), /* cast away const */ \
+ .iov_len = (len), \
+ }, \
+}
+
+/*
+ * qemu_iovec_init_buf
+ *
+ * Initialize embedded QEMUIOVector.
+ *
+ * Note: "const" is used over @buf pointer to make it simple to pass
+ * const pointers, appearing in read functions. Then this "const" is
+ * cast away by QEMU_IOVEC_INIT_BUF().
+ */
+static inline void qemu_iovec_init_buf(QEMUIOVector *qiov,
+ const void *buf, size_t len)
+{
+ *qiov = (QEMUIOVector) QEMU_IOVEC_INIT_BUF(*qiov, buf, len);
+}
+
+static inline void *qemu_iovec_buf(QEMUIOVector *qiov)
+{
+ /* Only supports embedded iov */
+ assert(qiov->nalloc == -1 && qiov->iov == &qiov->local_iov);
+
+ return qiov->local_iov.iov_base;
+}
+
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint);
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
void qemu_bh_schedule_idle(QEMUBH *bh);
+enum {
+ MAIN_LOOP_POLL_FILL,
+ MAIN_LOOP_POLL_ERR,
+ MAIN_LOOP_POLL_OK,
+};
+
+typedef struct MainLoopPoll {
+ int state;
+ uint32_t timeout;
+ GArray *pollfds;
+} MainLoopPoll;
+
+void main_loop_poll_add_notifier(Notifier *notify);
+void main_loop_poll_remove_notifier(Notifier *notify);
+
#endif
#define QTAILQ_FOREACH_REVERSE_SAFE(var, head, field, prev_var) \
for ((var) = QTAILQ_LAST(head); \
- (var) && ((prev_var) = QTAILQ_PREV(var, field)); \
+ (var) && ((prev_var) = QTAILQ_PREV(var, field), 1); \
(var) = (prev_var))
/*
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _ASM_X86_BOOTPARAM_H
+#define _ASM_X86_BOOTPARAM_H
+
+/* setup_data types */
+#define SETUP_NONE 0
+#define SETUP_E820_EXT 1
+#define SETUP_DTB 2
+#define SETUP_PCI 3
+#define SETUP_EFI 4
+#define SETUP_APPLE_PROPERTIES 5
+#define SETUP_JAILHOUSE 6
+
+/* ram_size flags */
+#define RAMDISK_IMAGE_START_MASK 0x07FF
+#define RAMDISK_PROMPT_FLAG 0x8000
+#define RAMDISK_LOAD_FLAG 0x4000
+
+/* loadflags */
+#define LOADED_HIGH (1<<0)
+#define KASLR_FLAG (1<<1)
+#define QUIET_FLAG (1<<5)
+#define KEEP_SEGMENTS (1<<6)
+#define CAN_USE_HEAP (1<<7)
+
+/* xloadflags */
+#define XLF_KERNEL_64 (1<<0)
+#define XLF_CAN_BE_LOADED_ABOVE_4G (1<<1)
+#define XLF_EFI_HANDOVER_32 (1<<2)
+#define XLF_EFI_HANDOVER_64 (1<<3)
+#define XLF_EFI_KEXEC (1<<4)
+
+
+#endif /* _ASM_X86_BOOTPARAM_H */
extern "C" {
#endif
+/**
+ * DOC: overview
+ *
+ * In the DRM subsystem, framebuffer pixel formats are described using the
+ * fourcc codes defined in `include/uapi/drm/drm_fourcc.h`. In addition to the
+ * fourcc code, a Format Modifier may optionally be provided, in order to
+ * further describe the buffer's format - for example tiling or compression.
+ *
+ * Format Modifiers
+ * ----------------
+ *
+ * Format modifiers are used in conjunction with a fourcc code, forming a
+ * unique fourcc:modifier pair. This format:modifier pair must fully define the
+ * format and data layout of the buffer, and should be the only way to describe
+ * that particular buffer.
+ *
+ * Having multiple fourcc:modifier pairs which describe the same layout should
+ * be avoided, as such aliases run the risk of different drivers exposing
+ * different names for the same data format, forcing userspace to understand
+ * that they are aliases.
+ *
+ * Format modifiers may change any property of the buffer, including the number
+ * of planes and/or the required allocation size. Format modifiers are
+ * vendor-namespaced, and as such the relationship between a fourcc code and a
+ * modifier is specific to the modifer being used. For example, some modifiers
+ * may preserve meaning - such as number of planes - from the fourcc code,
+ * whereas others may not.
+ *
+ * Vendors should document their modifier usage in as much detail as
+ * possible, to ensure maximum compatibility across devices, drivers and
+ * applications.
+ *
+ * The authoritative list of format modifier codes is found in
+ * `include/uapi/drm/drm_fourcc.h`
+ */
+
#define fourcc_code(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \
((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
#define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */
+/* Reserve 0 for the invalid format specifier */
+#define DRM_FORMAT_INVALID 0
+
/* color index */
#define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */
#define DRM_FORMAT_VYUY fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */
#define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
+#define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */
+
+/*
+ * packed YCbCr420 2x2 tiled formats
+ * first 64 bits will contain Y,Cb,Cr components for a 2x2 tile
+ */
+/* [63:0] A3:A2:Y3:0:Cr0:0:Y2:0:A1:A0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian */
+#define DRM_FORMAT_Y0L0 fourcc_code('Y', '0', 'L', '0')
+/* [63:0] X3:X2:Y3:0:Cr0:0:Y2:0:X1:X0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian */
+#define DRM_FORMAT_X0L0 fourcc_code('X', '0', 'L', '0')
+
+/* [63:0] A3:A2:Y3:Cr0:Y2:A1:A0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian */
+#define DRM_FORMAT_Y0L2 fourcc_code('Y', '0', 'L', '2')
+/* [63:0] X3:X2:Y3:Cr0:Y2:X1:X0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian */
+#define DRM_FORMAT_X0L2 fourcc_code('X', '0', 'L', '2')
/*
* 2 plane RGB + A
*/
#define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1)
+/*
+ * Tiled, 16 (pixels) x 16 (lines) - sized macroblocks
+ *
+ * This is a simple tiled layout using tiles of 16x16 pixels in a row-major
+ * layout. For YCbCr formats Cb/Cr components are taken in such a way that
+ * they correspond to their 16x16 luma block.
+ */
+#define DRM_FORMAT_MOD_SAMSUNG_16_16_TILE fourcc_mod_code(SAMSUNG, 2)
+
/*
* Qualcomm Compressed Format
*
* %ETHTOOL_GSET to get the current values before making specific
* changes and then applying them with %ETHTOOL_SSET.
*
- * Drivers that implement set_settings() should validate all fields
- * other than @cmd that are not described as read-only or deprecated,
- * and must ignore all fields described as read-only.
- *
* Deprecated fields should be ignored by both users and drivers.
*/
struct ethtool_cmd {
uint32_t location;
};
-/* How rings are layed out when accessing virtual functions or
+/* How rings are laid out when accessing virtual functions or
* offloaded queues is device specific. To allow users to do flow
* steering and specify these queues the ring cookie is partitioned
* into a 32bit queue index with an 8 bit virtual function id.
* devices start supporting PCIe w/ARI. However at the moment I
* do not know of any devices that support this so I do not reserve
* space for this at this time. If a future patch consumes the next
- * byte it should be aware of this possiblity.
+ * byte it should be aware of this possibility.
*/
#define ETHTOOL_RX_FLOW_SPEC_RING 0x00000000FFFFFFFFLL
#define ETHTOOL_RX_FLOW_SPEC_RING_VF 0x000000FF00000000LL
* rejected.
*
* Deprecated %ethtool_cmd fields transceiver, maxtxpkt and maxrxpkt
- * are not available in %ethtool_link_settings. Until all drivers are
- * converted to ignore them or to the new %ethtool_link_settings API,
- * for both queries and changes, users should always try
- * %ETHTOOL_GLINKSETTINGS first, and if it fails with -ENOTSUPP stick
- * only to %ETHTOOL_GSET and %ETHTOOL_SSET consistently. If it
- * succeeds, then users should stick to %ETHTOOL_GLINKSETTINGS and
- * %ETHTOOL_SLINKSETTINGS (which would support drivers implementing
- * either %ethtool_cmd or %ethtool_link_settings).
+ * are not available in %ethtool_link_settings. These fields will be
+ * always set to zero in %ETHTOOL_GSET reply and %ETHTOOL_SSET will
+ * fail if any of them is set to non-zero value.
*
* Users should assume that all fields not marked read-only are
* writable and subject to validation by the driver. They should use
#define REL_DIAL 0x07
#define REL_WHEEL 0x08
#define REL_MISC 0x09
+/*
+ * 0x0a is reserved and should not be used in input drivers.
+ * It was used by HID as REL_MISC+1 and userspace needs to detect if
+ * the next REL_* event is correct or is just REL_MISC + n.
+ * We define here REL_RESERVED so userspace can rely on it and detect
+ * the situation described above.
+ */
+#define REL_RESERVED 0x0a
#define REL_MAX 0x0f
#define REL_CNT (REL_MAX+1)
#define ABS_MISC 0x28
+/*
+ * 0x2e is reserved and should not be used in input drivers.
+ * It was used by HID as ABS_MISC+6 and userspace needs to detect if
+ * the next ABS_* event is correct or is just ABS_MISC + n.
+ * We define here ABS_RESERVED so userspace can rely on it and detect
+ * the situation described above.
+ */
+#define ABS_RESERVED 0x2e
+
#define ABS_MT_SLOT 0x2f /* MT slot being modified */
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
#define PCI_STATUS 0x06 /* 16 bits */
+#define PCI_STATUS_IMM_READY 0x01 /* Immediate Readiness */
#define PCI_STATUS_INTERRUPT 0x08 /* Interrupt status */
#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
#define PCI_STATUS_66MHZ 0x20 /* Support 66 MHz PCI 2.1 bus */
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_VHOST_TYPES_H
+#define _LINUX_VHOST_TYPES_H
+/* Userspace interface for in-kernel virtio accelerators. */
+
+/* vhost is used to reduce the number of system calls involved in virtio.
+ *
+ * Existing virtio net code is used in the guest without modification.
+ *
+ * This header includes interface used by userspace hypervisor for
+ * device configuration.
+ */
+
+#include "standard-headers/linux/types.h"
+
+#include "standard-headers/linux/virtio_config.h"
+#include "standard-headers/linux/virtio_ring.h"
+
+struct vhost_vring_state {
+ unsigned int index;
+ unsigned int num;
+};
+
+struct vhost_vring_file {
+ unsigned int index;
+ int fd; /* Pass -1 to unbind from file. */
+
+};
+
+struct vhost_vring_addr {
+ unsigned int index;
+ /* Option flags. */
+ unsigned int flags;
+ /* Flag values: */
+ /* Whether log address is valid. If set enables logging. */
+#define VHOST_VRING_F_LOG 0
+
+ /* Start of array of descriptors (virtually contiguous) */
+ uint64_t desc_user_addr;
+ /* Used structure address. Must be 32 bit aligned */
+ uint64_t used_user_addr;
+ /* Available structure address. Must be 16 bit aligned */
+ uint64_t avail_user_addr;
+ /* Logging support. */
+ /* Log writes to used structure, at offset calculated from specified
+ * address. Address must be 32 bit aligned. */
+ uint64_t log_guest_addr;
+};
+
+/* no alignment requirement */
+struct vhost_iotlb_msg {
+ uint64_t iova;
+ uint64_t size;
+ uint64_t uaddr;
+#define VHOST_ACCESS_RO 0x1
+#define VHOST_ACCESS_WO 0x2
+#define VHOST_ACCESS_RW 0x3
+ uint8_t perm;
+#define VHOST_IOTLB_MISS 1
+#define VHOST_IOTLB_UPDATE 2
+#define VHOST_IOTLB_INVALIDATE 3
+#define VHOST_IOTLB_ACCESS_FAIL 4
+ uint8_t type;
+};
+
+#define VHOST_IOTLB_MSG 0x1
+#define VHOST_IOTLB_MSG_V2 0x2
+
+struct vhost_msg {
+ int type;
+ union {
+ struct vhost_iotlb_msg iotlb;
+ uint8_t padding[64];
+ };
+};
+
+struct vhost_msg_v2 {
+ uint32_t type;
+ uint32_t reserved;
+ union {
+ struct vhost_iotlb_msg iotlb;
+ uint8_t padding[64];
+ };
+};
+
+struct vhost_memory_region {
+ uint64_t guest_phys_addr;
+ uint64_t memory_size; /* bytes */
+ uint64_t userspace_addr;
+ uint64_t flags_padding; /* No flags are currently specified. */
+};
+
+/* All region addresses and sizes must be 4K aligned. */
+#define VHOST_PAGE_SIZE 0x1000
+
+struct vhost_memory {
+ uint32_t nregions;
+ uint32_t padding;
+ struct vhost_memory_region regions[0];
+};
+
+/* VHOST_SCSI specific definitions */
+
+/*
+ * Used by QEMU userspace to ensure a consistent vhost-scsi ABI.
+ *
+ * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate +
+ * RFC-v2 vhost-scsi userspace. Add GET_ABI_VERSION ioctl usage
+ * ABI Rev 1: January 2013. Ignore vhost_tpgt field in struct vhost_scsi_target.
+ * All the targets under vhost_wwpn can be seen and used by guset.
+ */
+
+#define VHOST_SCSI_ABI_VERSION 1
+
+struct vhost_scsi_target {
+ int abi_version;
+ char vhost_wwpn[224]; /* TRANSPORT_IQN_LEN */
+ unsigned short vhost_tpgt;
+ unsigned short reserved;
+};
+
+/* Feature bits */
+/* Log all write descriptors. Can be changed while device is active. */
+#define VHOST_F_LOG_ALL 26
+/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
+#define VHOST_NET_F_VIRTIO_NET_HDR 27
+
+#endif
#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */
#define VIRTIO_BALLOON_F_STATS_VQ 1 /* Memory Stats virtqueue */
#define VIRTIO_BALLOON_F_DEFLATE_ON_OOM 2 /* Deflate balloon on OOM */
+#define VIRTIO_BALLOON_F_FREE_PAGE_HINT 3 /* VQ to report free pages */
+#define VIRTIO_BALLOON_F_PAGE_POISON 4 /* Guest is using page poisoning */
/* Size of a PFN in the balloon interface. */
#define VIRTIO_BALLOON_PFN_SHIFT 12
+#define VIRTIO_BALLOON_CMD_ID_STOP 0
+#define VIRTIO_BALLOON_CMD_ID_DONE 1
struct virtio_balloon_config {
/* Number of pages host wants Guest to give up. */
uint32_t num_pages;
/* Number of pages we've actually got in balloon. */
uint32_t actual;
+ /* Free page report command id, readonly by guest */
+ uint32_t free_page_report_cmd_id;
+ /* Stores PAGE_POISON if page poisoning is in use */
+ uint32_t poison_val;
};
#define VIRTIO_BALLOON_S_SWAP_IN 0 /* Amount of memory swapped in */
#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/
#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */
#define VIRTIO_BLK_F_MQ 12 /* support more than one vq */
+#define VIRTIO_BLK_F_DISCARD 13 /* DISCARD is supported */
+#define VIRTIO_BLK_F_WRITE_ZEROES 14 /* WRITE ZEROES is supported */
/* Legacy feature bits */
#ifndef VIRTIO_BLK_NO_LEGACY
/* number of vqs, only available when VIRTIO_BLK_F_MQ is set */
uint16_t num_queues;
+
+ /* the next 3 entries are guarded by VIRTIO_BLK_F_DISCARD */
+ /*
+ * The maximum discard sectors (in 512-byte sectors) for
+ * one segment.
+ */
+ uint32_t max_discard_sectors;
+ /*
+ * The maximum number of discard segments in a
+ * discard command.
+ */
+ uint32_t max_discard_seg;
+ /* Discard commands must be aligned to this number of sectors. */
+ uint32_t discard_sector_alignment;
+
+ /* the next 3 entries are guarded by VIRTIO_BLK_F_WRITE_ZEROES */
+ /*
+ * The maximum number of write zeroes sectors (in 512-byte sectors) in
+ * one segment.
+ */
+ uint32_t max_write_zeroes_sectors;
+ /*
+ * The maximum number of segments in a write zeroes
+ * command.
+ */
+ uint32_t max_write_zeroes_seg;
+ /*
+ * Set if a VIRTIO_BLK_T_WRITE_ZEROES request may result in the
+ * deallocation of one or more of the sectors.
+ */
+ uint8_t write_zeroes_may_unmap;
+
+ uint8_t unused1[3];
} QEMU_PACKED;
/*
/* Get device ID command */
#define VIRTIO_BLK_T_GET_ID 8
+/* Discard command */
+#define VIRTIO_BLK_T_DISCARD 11
+
+/* Write zeroes command */
+#define VIRTIO_BLK_T_WRITE_ZEROES 13
+
#ifndef VIRTIO_BLK_NO_LEGACY
/* Barrier before this op. */
#define VIRTIO_BLK_T_BARRIER 0x80000000
__virtio64 sector;
};
+/* Unmap this range (only valid for write zeroes command) */
+#define VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP 0x00000001
+
+/* Discard/write zeroes range for each request. */
+struct virtio_blk_discard_write_zeroes {
+ /* discard/write zeroes start sector */
+ uint64_t sector;
+ /* number of discard/write zeroes sectors */
+ uint32_t num_sectors;
+ /* flags for this range */
+ uint32_t flags;
+};
+
#ifndef VIRTIO_BLK_NO_LEGACY
struct virtio_scsi_inhdr {
__virtio32 errors;
*/
#define VIRTIO_F_IOMMU_PLATFORM 33
+/* This feature indicates support for the packed virtqueue layout. */
+#define VIRTIO_F_RING_PACKED 34
+
/*
* Does the device support Single Root I/O Virtualization?
*/
#include "standard-headers/linux/types.h"
#define VIRTIO_GPU_F_VIRGL 0
+#define VIRTIO_GPU_F_EDID 1
enum virtio_gpu_ctrl_type {
VIRTIO_GPU_UNDEFINED = 0,
VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING,
VIRTIO_GPU_CMD_GET_CAPSET_INFO,
VIRTIO_GPU_CMD_GET_CAPSET,
+ VIRTIO_GPU_CMD_GET_EDID,
/* 3d commands */
VIRTIO_GPU_CMD_CTX_CREATE = 0x0200,
VIRTIO_GPU_RESP_OK_DISPLAY_INFO,
VIRTIO_GPU_RESP_OK_CAPSET_INFO,
VIRTIO_GPU_RESP_OK_CAPSET,
+ VIRTIO_GPU_RESP_OK_EDID,
/* error responses */
VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200,
uint8_t capset_data[];
};
+/* VIRTIO_GPU_CMD_GET_EDID */
+struct virtio_gpu_cmd_get_edid {
+ struct virtio_gpu_ctrl_hdr hdr;
+ uint32_t scanout;
+ uint32_t padding;
+};
+
+/* VIRTIO_GPU_RESP_OK_EDID */
+struct virtio_gpu_resp_edid {
+ struct virtio_gpu_ctrl_hdr hdr;
+ uint32_t size;
+ uint32_t padding;
+ uint8_t edid[1024];
+};
+
#define VIRTIO_GPU_EVENT_DISPLAY (1 << 0)
struct virtio_gpu_config {
/* This means the buffer contains a list of buffer descriptors. */
#define VRING_DESC_F_INDIRECT 4
+/*
+ * Mark a descriptor as available or used in packed ring.
+ * Notice: they are defined as shifts instead of shifted values.
+ */
+#define VRING_PACKED_DESC_F_AVAIL 7
+#define VRING_PACKED_DESC_F_USED 15
+
/* The Host uses this in used->flags to advise the Guest: don't kick me when
* you add a buffer. It's unreliable, so it's simply an optimization. Guest
* will still kick if it's out of buffers. */
* optimization. */
#define VRING_AVAIL_F_NO_INTERRUPT 1
+/* Enable events in packed ring. */
+#define VRING_PACKED_EVENT_FLAG_ENABLE 0x0
+/* Disable events in packed ring. */
+#define VRING_PACKED_EVENT_FLAG_DISABLE 0x1
+/*
+ * Enable events for a specific descriptor in packed ring.
+ * (as specified by Descriptor Ring Change Event Offset/Wrap Counter).
+ * Only valid if VIRTIO_RING_F_EVENT_IDX has been negotiated.
+ */
+#define VRING_PACKED_EVENT_FLAG_DESC 0x2
+
+/*
+ * Wrap counter bit shift in event suppression structure
+ * of packed ring.
+ */
+#define VRING_PACKED_EVENT_F_WRAP_CTR 15
+
/* We support indirect buffer descriptors */
#define VIRTIO_RING_F_INDIRECT_DESC 28
return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old);
}
+struct vring_packed_desc_event {
+ /* Descriptor Ring Change Event Offset/Wrap Counter. */
+ uint16_t off_wrap;
+ /* Descriptor Ring Change Event Flags. */
+ uint16_t flags;
+};
+
+struct vring_packed_desc {
+ /* Buffer Address. */
+ uint64_t addr;
+ /* Buffer Length. */
+ uint32_t len;
+ /* Buffer ID. */
+ uint16_t id;
+ /* The flags depending on descriptor type. */
+ uint16_t flags;
+};
+
+struct vring_packed {
+ unsigned int num;
+
+ struct vring_packed_desc *desc;
+
+ struct vring_packed_desc_event *driver;
+
+ struct vring_packed_desc_event *device;
+};
+
#endif /* _LINUX_VIRTIO_RING_H */
int kvm_available(void);
int xen_available(void);
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp);
-CpuModelExpansionInfo *arch_query_cpu_model_expansion(CpuModelExpansionType type,
- CpuModelInfo *mode,
- Error **errp);
-CpuModelCompareInfo *arch_query_cpu_model_comparison(CpuModelInfo *modela,
- CpuModelInfo *modelb,
- Error **errp);
-CpuModelBaselineInfo *arch_query_cpu_model_baseline(CpuModelInfo *modela,
- CpuModelInfo *modelb,
- Error **errp);
-
#endif
int blk_co_flush(BlockBackend *blk);
int blk_flush(BlockBackend *blk);
int blk_commit_all(void);
+void blk_inc_in_flight(BlockBackend *blk);
+void blk_dec_in_flight(BlockBackend *blk);
void blk_drain(BlockBackend *blk);
void blk_drain_all(void);
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
extern int win2k_install_hack;
extern int alt_grab;
extern int ctrl_grab;
-extern int no_frame;
extern int smp_cpus;
extern unsigned int max_cpus;
extern int cursor_hide;
void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip);
void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip,
- int x, int y);
+ int x, int y, double scale_x, double scale_y);
#ifdef CONFIG_OPENGL_DMABUF
#include <gdk/gdkwayland.h>
#endif
+#include "ui/kbd-state.h"
#if defined(CONFIG_OPENGL)
#include "ui/egl-helpers.h"
#include "ui/egl-context.h"
typedef struct VirtualGfxConsole {
GtkWidget *drawing_area;
DisplayChangeListener dcl;
+ QKbdState *kbd;
DisplaySurface *ds;
pixman_image_t *convert;
cairo_surface_t *surface;
--- /dev/null
+/*
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+#ifndef QEMU_UI_KBD_STATE_H
+#define QEMU_UI_KBD_STATE_H 1
+
+#include "qapi/qapi-types-ui.h"
+
+typedef enum QKbdModifier QKbdModifier;
+
+enum QKbdModifier {
+ QKBD_MOD_NONE = 0,
+
+ QKBD_MOD_SHIFT,
+ QKBD_MOD_CTRL,
+ QKBD_MOD_ALT,
+ QKBD_MOD_ALTGR,
+
+ QKBD_MOD_NUMLOCK,
+ QKBD_MOD_CAPSLOCK,
+
+ QKBD_MOD__MAX
+};
+
+typedef struct QKbdState QKbdState;
+
+/**
+ * qkbd_state_init: init keyboard state tracker.
+ *
+ * Allocates and initializes keyboard state struct.
+ *
+ * @con: QemuConsole for this state tracker. Gets passed down to
+ * qemu_input_*() functions when sending key events to the guest.
+ */
+QKbdState *qkbd_state_init(QemuConsole *con);
+
+/**
+ * qkbd_state_free: free keyboard tracker state.
+ *
+ * @kbd: state tracker state.
+ */
+void qkbd_state_free(QKbdState *kbd);
+
+/**
+ * qkbd_state_key_event: process key event.
+ *
+ * Update keyboard state, send event to the guest.
+ *
+ * This function takes care to not send suspious events (keyup event
+ * for a key not pressed for example).
+ *
+ * @kbd: state tracker state.
+ * @qcode: the key pressed or released.
+ * @down: true for key down events, false otherwise.
+ */
+void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down);
+
+/**
+ * qkbd_state_set_delay: set key press delay.
+ *
+ * When set the specified delay will be added after each key event,
+ * using qemu_input_event_send_key_delay().
+ *
+ * @kbd: state tracker state.
+ * @delay_ms: the delay in miliseconds.
+ */
+void qkbd_state_set_delay(QKbdState *kbd, int delay_ms);
+
+/**
+ * qkbd_state_key_get: get key state.
+ *
+ * Returns true when the key is down.
+ *
+ * @kbd: state tracker state.
+ * @qcode: the key to query.
+ */
+bool qkbd_state_key_get(QKbdState *kbd, QKeyCode qcode);
+
+/**
+ * qkbd_state_modifier_get: get modifier state.
+ *
+ * Returns true when the modifier is active.
+ *
+ * @kbd: state tracker state.
+ * @mod: the modifier to query.
+ */
+bool qkbd_state_modifier_get(QKbdState *kbd, QKbdModifier mod);
+
+/**
+ * qkbd_state_lift_all_keys: lift all pressed keys.
+ *
+ * This sends key up events to the guest for all keys which are in
+ * down state.
+ *
+ * @kbd: state tracker state.
+ */
+void qkbd_state_lift_all_keys(QKbdState *kbd);
+
+#endif /* QEMU_UI_KBD_STATE_H */
# include <SDL_image.h>
#endif
+#include "ui/kbd-state.h"
#ifdef CONFIG_OPENGL
# include "ui/egl-helpers.h"
#endif
int idle_counter;
int ignore_hotkeys;
SDL_GLContext winctx;
+ QKbdState *kbd;
#ifdef CONFIG_OPENGL
QemuGLShader *gls;
egl_fb guest_fb;
void sdl2_window_resize(struct sdl2_console *scon);
void sdl2_poll_events(struct sdl2_console *scon);
-void sdl2_reset_keys(struct sdl2_console *scon);
void sdl2_process_key(struct sdl2_console *scon,
SDL_KeyboardEvent *ev);
void qemu_spice_display_start(void);
void qemu_spice_display_stop(void);
int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd);
+
+bool qemu_spice_fill_device_address(QemuConsole *con,
+ char *device_address,
+ size_t size);
}
-static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc);
-
static void qio_channel_restart_read(void *opaque)
{
QIOChannel *ioc = opaque;
Coroutine *co = ioc->read_coroutine;
- ioc->read_coroutine = NULL;
- qio_channel_set_aio_fd_handlers(ioc);
+ /* Assert that aio_co_wake() reenters the coroutine directly */
+ assert(qemu_get_current_aio_context() ==
+ qemu_coroutine_get_aio_context(co));
aio_co_wake(co);
}
QIOChannel *ioc = opaque;
Coroutine *co = ioc->write_coroutine;
- ioc->write_coroutine = NULL;
- qio_channel_set_aio_fd_handlers(ioc);
+ /* Assert that aio_co_wake() reenters the coroutine directly */
+ assert(qemu_get_current_aio_context() ==
+ qemu_coroutine_get_aio_context(co));
aio_co_wake(co);
}
}
qio_channel_set_aio_fd_handlers(ioc);
qemu_coroutine_yield();
+
+ /* Allow interrupting the operation by reentering the coroutine other than
+ * through the aio_fd_handlers. */
+ if (condition == G_IO_IN && ioc->read_coroutine) {
+ ioc->read_coroutine = NULL;
+ qio_channel_set_aio_fd_handlers(ioc);
+ } else if (condition == G_IO_OUT && ioc->write_coroutine) {
+ ioc->write_coroutine = NULL;
+ qio_channel_set_aio_fd_handlers(ioc);
+ }
}
#include "qemu/thread.h"
#include "trace.h"
+struct QIOTaskThreadData {
+ QIOTaskWorker worker;
+ gpointer opaque;
+ GDestroyNotify destroy;
+ GMainContext *context;
+ GSource *completion;
+};
+
+
struct QIOTask {
Object *source;
QIOTaskFunc func;
Error *err;
gpointer result;
GDestroyNotify destroyResult;
+ QemuMutex thread_lock;
+ QemuCond thread_cond;
+ struct QIOTaskThreadData *thread;
};
task->func = func;
task->opaque = opaque;
task->destroy = destroy;
+ qemu_mutex_init(&task->thread_lock);
+ qemu_cond_init(&task->thread_cond);
trace_qio_task_new(task, source, func, opaque);
static void qio_task_free(QIOTask *task)
{
+ qemu_mutex_lock(&task->thread_lock);
+ if (task->thread) {
+ if (task->thread->destroy) {
+ task->thread->destroy(task->thread->opaque);
+ }
+
+ if (task->thread->context) {
+ g_main_context_unref(task->thread->context);
+ }
+
+ g_free(task->thread);
+ }
+
if (task->destroy) {
task->destroy(task->opaque);
}
}
object_unref(task->source);
+ qemu_mutex_unlock(&task->thread_lock);
+ qemu_mutex_destroy(&task->thread_lock);
+ qemu_cond_destroy(&task->thread_cond);
+
g_free(task);
}
-struct QIOTaskThreadData {
- QIOTask *task;
- QIOTaskWorker worker;
- gpointer opaque;
- GDestroyNotify destroy;
- GMainContext *context;
-};
-
-
static gboolean qio_task_thread_result(gpointer opaque)
{
- struct QIOTaskThreadData *data = opaque;
-
- trace_qio_task_thread_result(data->task);
- qio_task_complete(data->task);
-
- if (data->destroy) {
- data->destroy(data->opaque);
- }
-
- if (data->context) {
- g_main_context_unref(data->context);
- }
+ QIOTask *task = opaque;
- g_free(data);
+ trace_qio_task_thread_result(task);
+ qio_task_complete(task);
return FALSE;
}
static gpointer qio_task_thread_worker(gpointer opaque)
{
- struct QIOTaskThreadData *data = opaque;
- GSource *idle;
+ QIOTask *task = opaque;
- trace_qio_task_thread_run(data->task);
- data->worker(data->task, data->opaque);
+ trace_qio_task_thread_run(task);
+
+ task->thread->worker(task, task->thread->opaque);
/* We're running in the background thread, and must only
* ever report the task results in the main event loop
* thread. So we schedule an idle callback to report
* the worker results
*/
- trace_qio_task_thread_exit(data->task);
+ trace_qio_task_thread_exit(task);
+
+ qemu_mutex_lock(&task->thread_lock);
- idle = g_idle_source_new();
- g_source_set_callback(idle, qio_task_thread_result, data, NULL);
- g_source_attach(idle, data->context);
+ task->thread->completion = g_idle_source_new();
+ g_source_set_callback(task->thread->completion,
+ qio_task_thread_result, task, NULL);
+ g_source_attach(task->thread->completion,
+ task->thread->context);
+ trace_qio_task_thread_source_attach(task, task->thread->completion);
+
+ qemu_cond_signal(&task->thread_cond);
+ qemu_mutex_unlock(&task->thread_lock);
return NULL;
}
g_main_context_ref(context);
}
- data->task = task;
data->worker = worker;
data->opaque = opaque;
data->destroy = destroy;
data->context = context;
+ task->thread = data;
+
trace_qio_task_thread_start(task, worker, opaque);
qemu_thread_create(&thread,
"io-task-worker",
qio_task_thread_worker,
- data,
+ task,
QEMU_THREAD_DETACHED);
}
+void qio_task_wait_thread(QIOTask *task)
+{
+ qemu_mutex_lock(&task->thread_lock);
+ g_assert(task->thread != NULL);
+ while (task->thread->completion == NULL) {
+ qemu_cond_wait(&task->thread_cond, &task->thread_lock);
+ }
+
+ trace_qio_task_thread_source_cancel(task, task->thread->completion);
+ g_source_destroy(task->thread->completion);
+ qemu_mutex_unlock(&task->thread_lock);
+
+ qio_task_thread_result(task);
+}
+
+
void qio_task_complete(QIOTask *task)
{
task->func(task, task->opaque);
qio_task_thread_run(void *task) "Task thread run task=%p"
qio_task_thread_exit(void *task) "Task thread exit task=%p"
qio_task_thread_result(void *task) "Task thread result task=%p"
+qio_task_thread_source_attach(void *task, void *source) "Task thread source attach task=%p source=%p"
+qio_task_thread_source_cancel(void *task, void *source) "Task thread source cancel task=%p source=%p"
# io/channel-socket.c
qio_channel_socket_new(void *ioc) "Socket new ioc=%p"
while (iothread->running) {
aio_poll(iothread->ctx, true);
- if (atomic_read(&iothread->worker_context)) {
+ /*
+ * We must check the running state again in case it was
+ * changed in previous aio_poll()
+ */
+ if (iothread->running && atomic_read(&iothread->worker_context)) {
GMainLoop *loop;
g_main_context_push_thread_default(iothread->worker_context);
#define __NR_pkey_free (__NR_SYSCALL_BASE + 396)
#define __NR_statx (__NR_SYSCALL_BASE + 397)
#define __NR_rseq (__NR_SYSCALL_BASE + 398)
+#define __NR_io_pgetevents (__NR_SYSCALL_BASE + 399)
#endif /* _ASM_ARM_UNISTD_COMMON_H */
*/
#define __ARCH_WANT_RENAMEAT
+#define __ARCH_WANT_NEW_STAT
#include <asm-generic/unistd.h>
/* fs/stat.c */
#define __NR_readlinkat 78
__SYSCALL(__NR_readlinkat, sys_readlinkat)
+#if defined(__ARCH_WANT_NEW_STAT) || defined(__ARCH_WANT_STAT64)
#define __NR3264_fstatat 79
__SC_3264(__NR3264_fstatat, sys_fstatat64, sys_newfstatat)
#define __NR3264_fstat 80
__SC_3264(__NR3264_fstat, sys_fstat64, sys_newfstat)
+#endif
/* fs/sync.c */
#define __NR_sync 81
__SC_COMP(__NR_io_pgetevents, sys_io_pgetevents, compat_sys_io_pgetevents)
#define __NR_rseq 293
__SYSCALL(__NR_rseq, sys_rseq)
+#define __NR_kexec_file_load 294
+__SYSCALL(__NR_kexec_file_load, sys_kexec_file_load)
#undef __NR_syscalls
-#define __NR_syscalls 294
+#define __NR_syscalls 295
/*
* 32 bit systems traditionally used different
#define __NR_ftruncate __NR3264_ftruncate
#define __NR_lseek __NR3264_lseek
#define __NR_sendfile __NR3264_sendfile
+#if defined(__ARCH_WANT_NEW_STAT) || defined(__ARCH_WANT_STAT64)
#define __NR_newfstatat __NR3264_fstatat
#define __NR_fstat __NR3264_fstat
+#endif
#define __NR_mmap __NR3264_mmap
#define __NR_fadvise64 __NR3264_fadvise64
#ifdef __NR3264_stat
#define __NR_ftruncate64 __NR3264_ftruncate
#define __NR_llseek __NR3264_lseek
#define __NR_sendfile64 __NR3264_sendfile
+#if defined(__ARCH_WANT_NEW_STAT) || defined(__ARCH_WANT_STAT64)
#define __NR_fstatat64 __NR3264_fstatat
#define __NR_fstat64 __NR3264_fstat
+#endif
#define __NR_mmap2 __NR3264_mmap
#define __NR_fadvise64_64 __NR3264_fadvise64
#ifdef __NR3264_stat
#ifndef __ASM_SGIDEFS_H
#define __ASM_SGIDEFS_H
-/*
- * Using a Linux compiler for building Linux seems logic but not to
- * everybody.
- */
-#ifndef __linux__
-#error Use a Linux compiler or give up.
-#endif
-
/*
* Definitions for the ISA levels
*
#if _MIPS_SIM == _MIPS_SIM_ABI32
-/*
- * Linux o32 style syscalls are in the range from 4000 to 4999.
- */
-#define __NR_Linux 4000
-#define __NR_syscall (__NR_Linux + 0)
-#define __NR_exit (__NR_Linux + 1)
-#define __NR_fork (__NR_Linux + 2)
-#define __NR_read (__NR_Linux + 3)
-#define __NR_write (__NR_Linux + 4)
-#define __NR_open (__NR_Linux + 5)
-#define __NR_close (__NR_Linux + 6)
-#define __NR_waitpid (__NR_Linux + 7)
-#define __NR_creat (__NR_Linux + 8)
-#define __NR_link (__NR_Linux + 9)
-#define __NR_unlink (__NR_Linux + 10)
-#define __NR_execve (__NR_Linux + 11)
-#define __NR_chdir (__NR_Linux + 12)
-#define __NR_time (__NR_Linux + 13)
-#define __NR_mknod (__NR_Linux + 14)
-#define __NR_chmod (__NR_Linux + 15)
-#define __NR_lchown (__NR_Linux + 16)
-#define __NR_break (__NR_Linux + 17)
-#define __NR_unused18 (__NR_Linux + 18)
-#define __NR_lseek (__NR_Linux + 19)
-#define __NR_getpid (__NR_Linux + 20)
-#define __NR_mount (__NR_Linux + 21)
-#define __NR_umount (__NR_Linux + 22)
-#define __NR_setuid (__NR_Linux + 23)
-#define __NR_getuid (__NR_Linux + 24)
-#define __NR_stime (__NR_Linux + 25)
-#define __NR_ptrace (__NR_Linux + 26)
-#define __NR_alarm (__NR_Linux + 27)
-#define __NR_unused28 (__NR_Linux + 28)
-#define __NR_pause (__NR_Linux + 29)
-#define __NR_utime (__NR_Linux + 30)
-#define __NR_stty (__NR_Linux + 31)
-#define __NR_gtty (__NR_Linux + 32)
-#define __NR_access (__NR_Linux + 33)
-#define __NR_nice (__NR_Linux + 34)
-#define __NR_ftime (__NR_Linux + 35)
-#define __NR_sync (__NR_Linux + 36)
-#define __NR_kill (__NR_Linux + 37)
-#define __NR_rename (__NR_Linux + 38)
-#define __NR_mkdir (__NR_Linux + 39)
-#define __NR_rmdir (__NR_Linux + 40)
-#define __NR_dup (__NR_Linux + 41)
-#define __NR_pipe (__NR_Linux + 42)
-#define __NR_times (__NR_Linux + 43)
-#define __NR_prof (__NR_Linux + 44)
-#define __NR_brk (__NR_Linux + 45)
-#define __NR_setgid (__NR_Linux + 46)
-#define __NR_getgid (__NR_Linux + 47)
-#define __NR_signal (__NR_Linux + 48)
-#define __NR_geteuid (__NR_Linux + 49)
-#define __NR_getegid (__NR_Linux + 50)
-#define __NR_acct (__NR_Linux + 51)
-#define __NR_umount2 (__NR_Linux + 52)
-#define __NR_lock (__NR_Linux + 53)
-#define __NR_ioctl (__NR_Linux + 54)
-#define __NR_fcntl (__NR_Linux + 55)
-#define __NR_mpx (__NR_Linux + 56)
-#define __NR_setpgid (__NR_Linux + 57)
-#define __NR_ulimit (__NR_Linux + 58)
-#define __NR_unused59 (__NR_Linux + 59)
-#define __NR_umask (__NR_Linux + 60)
-#define __NR_chroot (__NR_Linux + 61)
-#define __NR_ustat (__NR_Linux + 62)
-#define __NR_dup2 (__NR_Linux + 63)
-#define __NR_getppid (__NR_Linux + 64)
-#define __NR_getpgrp (__NR_Linux + 65)
-#define __NR_setsid (__NR_Linux + 66)
-#define __NR_sigaction (__NR_Linux + 67)
-#define __NR_sgetmask (__NR_Linux + 68)
-#define __NR_ssetmask (__NR_Linux + 69)
-#define __NR_setreuid (__NR_Linux + 70)
-#define __NR_setregid (__NR_Linux + 71)
-#define __NR_sigsuspend (__NR_Linux + 72)
-#define __NR_sigpending (__NR_Linux + 73)
-#define __NR_sethostname (__NR_Linux + 74)
-#define __NR_setrlimit (__NR_Linux + 75)
-#define __NR_getrlimit (__NR_Linux + 76)
-#define __NR_getrusage (__NR_Linux + 77)
-#define __NR_gettimeofday (__NR_Linux + 78)
-#define __NR_settimeofday (__NR_Linux + 79)
-#define __NR_getgroups (__NR_Linux + 80)
-#define __NR_setgroups (__NR_Linux + 81)
-#define __NR_reserved82 (__NR_Linux + 82)
-#define __NR_symlink (__NR_Linux + 83)
-#define __NR_unused84 (__NR_Linux + 84)
-#define __NR_readlink (__NR_Linux + 85)
-#define __NR_uselib (__NR_Linux + 86)
-#define __NR_swapon (__NR_Linux + 87)
-#define __NR_reboot (__NR_Linux + 88)
-#define __NR_readdir (__NR_Linux + 89)
-#define __NR_mmap (__NR_Linux + 90)
-#define __NR_munmap (__NR_Linux + 91)
-#define __NR_truncate (__NR_Linux + 92)
-#define __NR_ftruncate (__NR_Linux + 93)
-#define __NR_fchmod (__NR_Linux + 94)
-#define __NR_fchown (__NR_Linux + 95)
-#define __NR_getpriority (__NR_Linux + 96)
-#define __NR_setpriority (__NR_Linux + 97)
-#define __NR_profil (__NR_Linux + 98)
-#define __NR_statfs (__NR_Linux + 99)
-#define __NR_fstatfs (__NR_Linux + 100)
-#define __NR_ioperm (__NR_Linux + 101)
-#define __NR_socketcall (__NR_Linux + 102)
-#define __NR_syslog (__NR_Linux + 103)
-#define __NR_setitimer (__NR_Linux + 104)
-#define __NR_getitimer (__NR_Linux + 105)
-#define __NR_stat (__NR_Linux + 106)
-#define __NR_lstat (__NR_Linux + 107)
-#define __NR_fstat (__NR_Linux + 108)
-#define __NR_unused109 (__NR_Linux + 109)
-#define __NR_iopl (__NR_Linux + 110)
-#define __NR_vhangup (__NR_Linux + 111)
-#define __NR_idle (__NR_Linux + 112)
-#define __NR_vm86 (__NR_Linux + 113)
-#define __NR_wait4 (__NR_Linux + 114)
-#define __NR_swapoff (__NR_Linux + 115)
-#define __NR_sysinfo (__NR_Linux + 116)
-#define __NR_ipc (__NR_Linux + 117)
-#define __NR_fsync (__NR_Linux + 118)
-#define __NR_sigreturn (__NR_Linux + 119)
-#define __NR_clone (__NR_Linux + 120)
-#define __NR_setdomainname (__NR_Linux + 121)
-#define __NR_uname (__NR_Linux + 122)
-#define __NR_modify_ldt (__NR_Linux + 123)
-#define __NR_adjtimex (__NR_Linux + 124)
-#define __NR_mprotect (__NR_Linux + 125)
-#define __NR_sigprocmask (__NR_Linux + 126)
-#define __NR_create_module (__NR_Linux + 127)
-#define __NR_init_module (__NR_Linux + 128)
-#define __NR_delete_module (__NR_Linux + 129)
-#define __NR_get_kernel_syms (__NR_Linux + 130)
-#define __NR_quotactl (__NR_Linux + 131)
-#define __NR_getpgid (__NR_Linux + 132)
-#define __NR_fchdir (__NR_Linux + 133)
-#define __NR_bdflush (__NR_Linux + 134)
-#define __NR_sysfs (__NR_Linux + 135)
-#define __NR_personality (__NR_Linux + 136)
-#define __NR_afs_syscall (__NR_Linux + 137) /* Syscall for Andrew File System */
-#define __NR_setfsuid (__NR_Linux + 138)
-#define __NR_setfsgid (__NR_Linux + 139)
-#define __NR__llseek (__NR_Linux + 140)
-#define __NR_getdents (__NR_Linux + 141)
-#define __NR__newselect (__NR_Linux + 142)
-#define __NR_flock (__NR_Linux + 143)
-#define __NR_msync (__NR_Linux + 144)
-#define __NR_readv (__NR_Linux + 145)
-#define __NR_writev (__NR_Linux + 146)
-#define __NR_cacheflush (__NR_Linux + 147)
-#define __NR_cachectl (__NR_Linux + 148)
-#define __NR_sysmips (__NR_Linux + 149)
-#define __NR_unused150 (__NR_Linux + 150)
-#define __NR_getsid (__NR_Linux + 151)
-#define __NR_fdatasync (__NR_Linux + 152)
-#define __NR__sysctl (__NR_Linux + 153)
-#define __NR_mlock (__NR_Linux + 154)
-#define __NR_munlock (__NR_Linux + 155)
-#define __NR_mlockall (__NR_Linux + 156)
-#define __NR_munlockall (__NR_Linux + 157)
-#define __NR_sched_setparam (__NR_Linux + 158)
-#define __NR_sched_getparam (__NR_Linux + 159)
-#define __NR_sched_setscheduler (__NR_Linux + 160)
-#define __NR_sched_getscheduler (__NR_Linux + 161)
-#define __NR_sched_yield (__NR_Linux + 162)
-#define __NR_sched_get_priority_max (__NR_Linux + 163)
-#define __NR_sched_get_priority_min (__NR_Linux + 164)
-#define __NR_sched_rr_get_interval (__NR_Linux + 165)
-#define __NR_nanosleep (__NR_Linux + 166)
-#define __NR_mremap (__NR_Linux + 167)
-#define __NR_accept (__NR_Linux + 168)
-#define __NR_bind (__NR_Linux + 169)
-#define __NR_connect (__NR_Linux + 170)
-#define __NR_getpeername (__NR_Linux + 171)
-#define __NR_getsockname (__NR_Linux + 172)
-#define __NR_getsockopt (__NR_Linux + 173)
-#define __NR_listen (__NR_Linux + 174)
-#define __NR_recv (__NR_Linux + 175)
-#define __NR_recvfrom (__NR_Linux + 176)
-#define __NR_recvmsg (__NR_Linux + 177)
-#define __NR_send (__NR_Linux + 178)
-#define __NR_sendmsg (__NR_Linux + 179)
-#define __NR_sendto (__NR_Linux + 180)
-#define __NR_setsockopt (__NR_Linux + 181)
-#define __NR_shutdown (__NR_Linux + 182)
-#define __NR_socket (__NR_Linux + 183)
-#define __NR_socketpair (__NR_Linux + 184)
-#define __NR_setresuid (__NR_Linux + 185)
-#define __NR_getresuid (__NR_Linux + 186)
-#define __NR_query_module (__NR_Linux + 187)
-#define __NR_poll (__NR_Linux + 188)
-#define __NR_nfsservctl (__NR_Linux + 189)
-#define __NR_setresgid (__NR_Linux + 190)
-#define __NR_getresgid (__NR_Linux + 191)
-#define __NR_prctl (__NR_Linux + 192)
-#define __NR_rt_sigreturn (__NR_Linux + 193)
-#define __NR_rt_sigaction (__NR_Linux + 194)
-#define __NR_rt_sigprocmask (__NR_Linux + 195)
-#define __NR_rt_sigpending (__NR_Linux + 196)
-#define __NR_rt_sigtimedwait (__NR_Linux + 197)
-#define __NR_rt_sigqueueinfo (__NR_Linux + 198)
-#define __NR_rt_sigsuspend (__NR_Linux + 199)
-#define __NR_pread64 (__NR_Linux + 200)
-#define __NR_pwrite64 (__NR_Linux + 201)
-#define __NR_chown (__NR_Linux + 202)
-#define __NR_getcwd (__NR_Linux + 203)
-#define __NR_capget (__NR_Linux + 204)
-#define __NR_capset (__NR_Linux + 205)
-#define __NR_sigaltstack (__NR_Linux + 206)
-#define __NR_sendfile (__NR_Linux + 207)
-#define __NR_getpmsg (__NR_Linux + 208)
-#define __NR_putpmsg (__NR_Linux + 209)
-#define __NR_mmap2 (__NR_Linux + 210)
-#define __NR_truncate64 (__NR_Linux + 211)
-#define __NR_ftruncate64 (__NR_Linux + 212)
-#define __NR_stat64 (__NR_Linux + 213)
-#define __NR_lstat64 (__NR_Linux + 214)
-#define __NR_fstat64 (__NR_Linux + 215)
-#define __NR_pivot_root (__NR_Linux + 216)
-#define __NR_mincore (__NR_Linux + 217)
-#define __NR_madvise (__NR_Linux + 218)
-#define __NR_getdents64 (__NR_Linux + 219)
-#define __NR_fcntl64 (__NR_Linux + 220)
-#define __NR_reserved221 (__NR_Linux + 221)
-#define __NR_gettid (__NR_Linux + 222)
-#define __NR_readahead (__NR_Linux + 223)
-#define __NR_setxattr (__NR_Linux + 224)
-#define __NR_lsetxattr (__NR_Linux + 225)
-#define __NR_fsetxattr (__NR_Linux + 226)
-#define __NR_getxattr (__NR_Linux + 227)
-#define __NR_lgetxattr (__NR_Linux + 228)
-#define __NR_fgetxattr (__NR_Linux + 229)
-#define __NR_listxattr (__NR_Linux + 230)
-#define __NR_llistxattr (__NR_Linux + 231)
-#define __NR_flistxattr (__NR_Linux + 232)
-#define __NR_removexattr (__NR_Linux + 233)
-#define __NR_lremovexattr (__NR_Linux + 234)
-#define __NR_fremovexattr (__NR_Linux + 235)
-#define __NR_tkill (__NR_Linux + 236)
-#define __NR_sendfile64 (__NR_Linux + 237)
-#define __NR_futex (__NR_Linux + 238)
-#define __NR_sched_setaffinity (__NR_Linux + 239)
-#define __NR_sched_getaffinity (__NR_Linux + 240)
-#define __NR_io_setup (__NR_Linux + 241)
-#define __NR_io_destroy (__NR_Linux + 242)
-#define __NR_io_getevents (__NR_Linux + 243)
-#define __NR_io_submit (__NR_Linux + 244)
-#define __NR_io_cancel (__NR_Linux + 245)
-#define __NR_exit_group (__NR_Linux + 246)
-#define __NR_lookup_dcookie (__NR_Linux + 247)
-#define __NR_epoll_create (__NR_Linux + 248)
-#define __NR_epoll_ctl (__NR_Linux + 249)
-#define __NR_epoll_wait (__NR_Linux + 250)
-#define __NR_remap_file_pages (__NR_Linux + 251)
-#define __NR_set_tid_address (__NR_Linux + 252)
-#define __NR_restart_syscall (__NR_Linux + 253)
-#define __NR_fadvise64 (__NR_Linux + 254)
-#define __NR_statfs64 (__NR_Linux + 255)
-#define __NR_fstatfs64 (__NR_Linux + 256)
-#define __NR_timer_create (__NR_Linux + 257)
-#define __NR_timer_settime (__NR_Linux + 258)
-#define __NR_timer_gettime (__NR_Linux + 259)
-#define __NR_timer_getoverrun (__NR_Linux + 260)
-#define __NR_timer_delete (__NR_Linux + 261)
-#define __NR_clock_settime (__NR_Linux + 262)
-#define __NR_clock_gettime (__NR_Linux + 263)
-#define __NR_clock_getres (__NR_Linux + 264)
-#define __NR_clock_nanosleep (__NR_Linux + 265)
-#define __NR_tgkill (__NR_Linux + 266)
-#define __NR_utimes (__NR_Linux + 267)
-#define __NR_mbind (__NR_Linux + 268)
-#define __NR_get_mempolicy (__NR_Linux + 269)
-#define __NR_set_mempolicy (__NR_Linux + 270)
-#define __NR_mq_open (__NR_Linux + 271)
-#define __NR_mq_unlink (__NR_Linux + 272)
-#define __NR_mq_timedsend (__NR_Linux + 273)
-#define __NR_mq_timedreceive (__NR_Linux + 274)
-#define __NR_mq_notify (__NR_Linux + 275)
-#define __NR_mq_getsetattr (__NR_Linux + 276)
-#define __NR_vserver (__NR_Linux + 277)
-#define __NR_waitid (__NR_Linux + 278)
-/* #define __NR_sys_setaltroot (__NR_Linux + 279) */
-#define __NR_add_key (__NR_Linux + 280)
-#define __NR_request_key (__NR_Linux + 281)
-#define __NR_keyctl (__NR_Linux + 282)
-#define __NR_set_thread_area (__NR_Linux + 283)
-#define __NR_inotify_init (__NR_Linux + 284)
-#define __NR_inotify_add_watch (__NR_Linux + 285)
-#define __NR_inotify_rm_watch (__NR_Linux + 286)
-#define __NR_migrate_pages (__NR_Linux + 287)
-#define __NR_openat (__NR_Linux + 288)
-#define __NR_mkdirat (__NR_Linux + 289)
-#define __NR_mknodat (__NR_Linux + 290)
-#define __NR_fchownat (__NR_Linux + 291)
-#define __NR_futimesat (__NR_Linux + 292)
-#define __NR_fstatat64 (__NR_Linux + 293)
-#define __NR_unlinkat (__NR_Linux + 294)
-#define __NR_renameat (__NR_Linux + 295)
-#define __NR_linkat (__NR_Linux + 296)
-#define __NR_symlinkat (__NR_Linux + 297)
-#define __NR_readlinkat (__NR_Linux + 298)
-#define __NR_fchmodat (__NR_Linux + 299)
-#define __NR_faccessat (__NR_Linux + 300)
-#define __NR_pselect6 (__NR_Linux + 301)
-#define __NR_ppoll (__NR_Linux + 302)
-#define __NR_unshare (__NR_Linux + 303)
-#define __NR_splice (__NR_Linux + 304)
-#define __NR_sync_file_range (__NR_Linux + 305)
-#define __NR_tee (__NR_Linux + 306)
-#define __NR_vmsplice (__NR_Linux + 307)
-#define __NR_move_pages (__NR_Linux + 308)
-#define __NR_set_robust_list (__NR_Linux + 309)
-#define __NR_get_robust_list (__NR_Linux + 310)
-#define __NR_kexec_load (__NR_Linux + 311)
-#define __NR_getcpu (__NR_Linux + 312)
-#define __NR_epoll_pwait (__NR_Linux + 313)
-#define __NR_ioprio_set (__NR_Linux + 314)
-#define __NR_ioprio_get (__NR_Linux + 315)
-#define __NR_utimensat (__NR_Linux + 316)
-#define __NR_signalfd (__NR_Linux + 317)
-#define __NR_timerfd (__NR_Linux + 318)
-#define __NR_eventfd (__NR_Linux + 319)
-#define __NR_fallocate (__NR_Linux + 320)
-#define __NR_timerfd_create (__NR_Linux + 321)
-#define __NR_timerfd_gettime (__NR_Linux + 322)
-#define __NR_timerfd_settime (__NR_Linux + 323)
-#define __NR_signalfd4 (__NR_Linux + 324)
-#define __NR_eventfd2 (__NR_Linux + 325)
-#define __NR_epoll_create1 (__NR_Linux + 326)
-#define __NR_dup3 (__NR_Linux + 327)
-#define __NR_pipe2 (__NR_Linux + 328)
-#define __NR_inotify_init1 (__NR_Linux + 329)
-#define __NR_preadv (__NR_Linux + 330)
-#define __NR_pwritev (__NR_Linux + 331)
-#define __NR_rt_tgsigqueueinfo (__NR_Linux + 332)
-#define __NR_perf_event_open (__NR_Linux + 333)
-#define __NR_accept4 (__NR_Linux + 334)
-#define __NR_recvmmsg (__NR_Linux + 335)
-#define __NR_fanotify_init (__NR_Linux + 336)
-#define __NR_fanotify_mark (__NR_Linux + 337)
-#define __NR_prlimit64 (__NR_Linux + 338)
-#define __NR_name_to_handle_at (__NR_Linux + 339)
-#define __NR_open_by_handle_at (__NR_Linux + 340)
-#define __NR_clock_adjtime (__NR_Linux + 341)
-#define __NR_syncfs (__NR_Linux + 342)
-#define __NR_sendmmsg (__NR_Linux + 343)
-#define __NR_setns (__NR_Linux + 344)
-#define __NR_process_vm_readv (__NR_Linux + 345)
-#define __NR_process_vm_writev (__NR_Linux + 346)
-#define __NR_kcmp (__NR_Linux + 347)
-#define __NR_finit_module (__NR_Linux + 348)
-#define __NR_sched_setattr (__NR_Linux + 349)
-#define __NR_sched_getattr (__NR_Linux + 350)
-#define __NR_renameat2 (__NR_Linux + 351)
-#define __NR_seccomp (__NR_Linux + 352)
-#define __NR_getrandom (__NR_Linux + 353)
-#define __NR_memfd_create (__NR_Linux + 354)
-#define __NR_bpf (__NR_Linux + 355)
-#define __NR_execveat (__NR_Linux + 356)
-#define __NR_userfaultfd (__NR_Linux + 357)
-#define __NR_membarrier (__NR_Linux + 358)
-#define __NR_mlock2 (__NR_Linux + 359)
-#define __NR_copy_file_range (__NR_Linux + 360)
-#define __NR_preadv2 (__NR_Linux + 361)
-#define __NR_pwritev2 (__NR_Linux + 362)
-#define __NR_pkey_mprotect (__NR_Linux + 363)
-#define __NR_pkey_alloc (__NR_Linux + 364)
-#define __NR_pkey_free (__NR_Linux + 365)
-#define __NR_statx (__NR_Linux + 366)
-#define __NR_rseq (__NR_Linux + 367)
-#define __NR_io_pgetevents (__NR_Linux + 368)
-
-
-/*
- * Offset of the last Linux o32 flavoured syscall
- */
-#define __NR_Linux_syscalls 368
+#define __NR_Linux 4000
+#include <asm/unistd_o32.h>
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
-#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 368
-
#if _MIPS_SIM == _MIPS_SIM_ABI64
-/*
- * Linux 64-bit syscalls are in the range from 5000 to 5999.
- */
-#define __NR_Linux 5000
-#define __NR_read (__NR_Linux + 0)
-#define __NR_write (__NR_Linux + 1)
-#define __NR_open (__NR_Linux + 2)
-#define __NR_close (__NR_Linux + 3)
-#define __NR_stat (__NR_Linux + 4)
-#define __NR_fstat (__NR_Linux + 5)
-#define __NR_lstat (__NR_Linux + 6)
-#define __NR_poll (__NR_Linux + 7)
-#define __NR_lseek (__NR_Linux + 8)
-#define __NR_mmap (__NR_Linux + 9)
-#define __NR_mprotect (__NR_Linux + 10)
-#define __NR_munmap (__NR_Linux + 11)
-#define __NR_brk (__NR_Linux + 12)
-#define __NR_rt_sigaction (__NR_Linux + 13)
-#define __NR_rt_sigprocmask (__NR_Linux + 14)
-#define __NR_ioctl (__NR_Linux + 15)
-#define __NR_pread64 (__NR_Linux + 16)
-#define __NR_pwrite64 (__NR_Linux + 17)
-#define __NR_readv (__NR_Linux + 18)
-#define __NR_writev (__NR_Linux + 19)
-#define __NR_access (__NR_Linux + 20)
-#define __NR_pipe (__NR_Linux + 21)
-#define __NR__newselect (__NR_Linux + 22)
-#define __NR_sched_yield (__NR_Linux + 23)
-#define __NR_mremap (__NR_Linux + 24)
-#define __NR_msync (__NR_Linux + 25)
-#define __NR_mincore (__NR_Linux + 26)
-#define __NR_madvise (__NR_Linux + 27)
-#define __NR_shmget (__NR_Linux + 28)
-#define __NR_shmat (__NR_Linux + 29)
-#define __NR_shmctl (__NR_Linux + 30)
-#define __NR_dup (__NR_Linux + 31)
-#define __NR_dup2 (__NR_Linux + 32)
-#define __NR_pause (__NR_Linux + 33)
-#define __NR_nanosleep (__NR_Linux + 34)
-#define __NR_getitimer (__NR_Linux + 35)
-#define __NR_setitimer (__NR_Linux + 36)
-#define __NR_alarm (__NR_Linux + 37)
-#define __NR_getpid (__NR_Linux + 38)
-#define __NR_sendfile (__NR_Linux + 39)
-#define __NR_socket (__NR_Linux + 40)
-#define __NR_connect (__NR_Linux + 41)
-#define __NR_accept (__NR_Linux + 42)
-#define __NR_sendto (__NR_Linux + 43)
-#define __NR_recvfrom (__NR_Linux + 44)
-#define __NR_sendmsg (__NR_Linux + 45)
-#define __NR_recvmsg (__NR_Linux + 46)
-#define __NR_shutdown (__NR_Linux + 47)
-#define __NR_bind (__NR_Linux + 48)
-#define __NR_listen (__NR_Linux + 49)
-#define __NR_getsockname (__NR_Linux + 50)
-#define __NR_getpeername (__NR_Linux + 51)
-#define __NR_socketpair (__NR_Linux + 52)
-#define __NR_setsockopt (__NR_Linux + 53)
-#define __NR_getsockopt (__NR_Linux + 54)
-#define __NR_clone (__NR_Linux + 55)
-#define __NR_fork (__NR_Linux + 56)
-#define __NR_execve (__NR_Linux + 57)
-#define __NR_exit (__NR_Linux + 58)
-#define __NR_wait4 (__NR_Linux + 59)
-#define __NR_kill (__NR_Linux + 60)
-#define __NR_uname (__NR_Linux + 61)
-#define __NR_semget (__NR_Linux + 62)
-#define __NR_semop (__NR_Linux + 63)
-#define __NR_semctl (__NR_Linux + 64)
-#define __NR_shmdt (__NR_Linux + 65)
-#define __NR_msgget (__NR_Linux + 66)
-#define __NR_msgsnd (__NR_Linux + 67)
-#define __NR_msgrcv (__NR_Linux + 68)
-#define __NR_msgctl (__NR_Linux + 69)
-#define __NR_fcntl (__NR_Linux + 70)
-#define __NR_flock (__NR_Linux + 71)
-#define __NR_fsync (__NR_Linux + 72)
-#define __NR_fdatasync (__NR_Linux + 73)
-#define __NR_truncate (__NR_Linux + 74)
-#define __NR_ftruncate (__NR_Linux + 75)
-#define __NR_getdents (__NR_Linux + 76)
-#define __NR_getcwd (__NR_Linux + 77)
-#define __NR_chdir (__NR_Linux + 78)
-#define __NR_fchdir (__NR_Linux + 79)
-#define __NR_rename (__NR_Linux + 80)
-#define __NR_mkdir (__NR_Linux + 81)
-#define __NR_rmdir (__NR_Linux + 82)
-#define __NR_creat (__NR_Linux + 83)
-#define __NR_link (__NR_Linux + 84)
-#define __NR_unlink (__NR_Linux + 85)
-#define __NR_symlink (__NR_Linux + 86)
-#define __NR_readlink (__NR_Linux + 87)
-#define __NR_chmod (__NR_Linux + 88)
-#define __NR_fchmod (__NR_Linux + 89)
-#define __NR_chown (__NR_Linux + 90)
-#define __NR_fchown (__NR_Linux + 91)
-#define __NR_lchown (__NR_Linux + 92)
-#define __NR_umask (__NR_Linux + 93)
-#define __NR_gettimeofday (__NR_Linux + 94)
-#define __NR_getrlimit (__NR_Linux + 95)
-#define __NR_getrusage (__NR_Linux + 96)
-#define __NR_sysinfo (__NR_Linux + 97)
-#define __NR_times (__NR_Linux + 98)
-#define __NR_ptrace (__NR_Linux + 99)
-#define __NR_getuid (__NR_Linux + 100)
-#define __NR_syslog (__NR_Linux + 101)
-#define __NR_getgid (__NR_Linux + 102)
-#define __NR_setuid (__NR_Linux + 103)
-#define __NR_setgid (__NR_Linux + 104)
-#define __NR_geteuid (__NR_Linux + 105)
-#define __NR_getegid (__NR_Linux + 106)
-#define __NR_setpgid (__NR_Linux + 107)
-#define __NR_getppid (__NR_Linux + 108)
-#define __NR_getpgrp (__NR_Linux + 109)
-#define __NR_setsid (__NR_Linux + 110)
-#define __NR_setreuid (__NR_Linux + 111)
-#define __NR_setregid (__NR_Linux + 112)
-#define __NR_getgroups (__NR_Linux + 113)
-#define __NR_setgroups (__NR_Linux + 114)
-#define __NR_setresuid (__NR_Linux + 115)
-#define __NR_getresuid (__NR_Linux + 116)
-#define __NR_setresgid (__NR_Linux + 117)
-#define __NR_getresgid (__NR_Linux + 118)
-#define __NR_getpgid (__NR_Linux + 119)
-#define __NR_setfsuid (__NR_Linux + 120)
-#define __NR_setfsgid (__NR_Linux + 121)
-#define __NR_getsid (__NR_Linux + 122)
-#define __NR_capget (__NR_Linux + 123)
-#define __NR_capset (__NR_Linux + 124)
-#define __NR_rt_sigpending (__NR_Linux + 125)
-#define __NR_rt_sigtimedwait (__NR_Linux + 126)
-#define __NR_rt_sigqueueinfo (__NR_Linux + 127)
-#define __NR_rt_sigsuspend (__NR_Linux + 128)
-#define __NR_sigaltstack (__NR_Linux + 129)
-#define __NR_utime (__NR_Linux + 130)
-#define __NR_mknod (__NR_Linux + 131)
-#define __NR_personality (__NR_Linux + 132)
-#define __NR_ustat (__NR_Linux + 133)
-#define __NR_statfs (__NR_Linux + 134)
-#define __NR_fstatfs (__NR_Linux + 135)
-#define __NR_sysfs (__NR_Linux + 136)
-#define __NR_getpriority (__NR_Linux + 137)
-#define __NR_setpriority (__NR_Linux + 138)
-#define __NR_sched_setparam (__NR_Linux + 139)
-#define __NR_sched_getparam (__NR_Linux + 140)
-#define __NR_sched_setscheduler (__NR_Linux + 141)
-#define __NR_sched_getscheduler (__NR_Linux + 142)
-#define __NR_sched_get_priority_max (__NR_Linux + 143)
-#define __NR_sched_get_priority_min (__NR_Linux + 144)
-#define __NR_sched_rr_get_interval (__NR_Linux + 145)
-#define __NR_mlock (__NR_Linux + 146)
-#define __NR_munlock (__NR_Linux + 147)
-#define __NR_mlockall (__NR_Linux + 148)
-#define __NR_munlockall (__NR_Linux + 149)
-#define __NR_vhangup (__NR_Linux + 150)
-#define __NR_pivot_root (__NR_Linux + 151)
-#define __NR__sysctl (__NR_Linux + 152)
-#define __NR_prctl (__NR_Linux + 153)
-#define __NR_adjtimex (__NR_Linux + 154)
-#define __NR_setrlimit (__NR_Linux + 155)
-#define __NR_chroot (__NR_Linux + 156)
-#define __NR_sync (__NR_Linux + 157)
-#define __NR_acct (__NR_Linux + 158)
-#define __NR_settimeofday (__NR_Linux + 159)
-#define __NR_mount (__NR_Linux + 160)
-#define __NR_umount2 (__NR_Linux + 161)
-#define __NR_swapon (__NR_Linux + 162)
-#define __NR_swapoff (__NR_Linux + 163)
-#define __NR_reboot (__NR_Linux + 164)
-#define __NR_sethostname (__NR_Linux + 165)
-#define __NR_setdomainname (__NR_Linux + 166)
-#define __NR_create_module (__NR_Linux + 167)
-#define __NR_init_module (__NR_Linux + 168)
-#define __NR_delete_module (__NR_Linux + 169)
-#define __NR_get_kernel_syms (__NR_Linux + 170)
-#define __NR_query_module (__NR_Linux + 171)
-#define __NR_quotactl (__NR_Linux + 172)
-#define __NR_nfsservctl (__NR_Linux + 173)
-#define __NR_getpmsg (__NR_Linux + 174)
-#define __NR_putpmsg (__NR_Linux + 175)
-#define __NR_afs_syscall (__NR_Linux + 176)
-#define __NR_reserved177 (__NR_Linux + 177)
-#define __NR_gettid (__NR_Linux + 178)
-#define __NR_readahead (__NR_Linux + 179)
-#define __NR_setxattr (__NR_Linux + 180)
-#define __NR_lsetxattr (__NR_Linux + 181)
-#define __NR_fsetxattr (__NR_Linux + 182)
-#define __NR_getxattr (__NR_Linux + 183)
-#define __NR_lgetxattr (__NR_Linux + 184)
-#define __NR_fgetxattr (__NR_Linux + 185)
-#define __NR_listxattr (__NR_Linux + 186)
-#define __NR_llistxattr (__NR_Linux + 187)
-#define __NR_flistxattr (__NR_Linux + 188)
-#define __NR_removexattr (__NR_Linux + 189)
-#define __NR_lremovexattr (__NR_Linux + 190)
-#define __NR_fremovexattr (__NR_Linux + 191)
-#define __NR_tkill (__NR_Linux + 192)
-#define __NR_reserved193 (__NR_Linux + 193)
-#define __NR_futex (__NR_Linux + 194)
-#define __NR_sched_setaffinity (__NR_Linux + 195)
-#define __NR_sched_getaffinity (__NR_Linux + 196)
-#define __NR_cacheflush (__NR_Linux + 197)
-#define __NR_cachectl (__NR_Linux + 198)
-#define __NR_sysmips (__NR_Linux + 199)
-#define __NR_io_setup (__NR_Linux + 200)
-#define __NR_io_destroy (__NR_Linux + 201)
-#define __NR_io_getevents (__NR_Linux + 202)
-#define __NR_io_submit (__NR_Linux + 203)
-#define __NR_io_cancel (__NR_Linux + 204)
-#define __NR_exit_group (__NR_Linux + 205)
-#define __NR_lookup_dcookie (__NR_Linux + 206)
-#define __NR_epoll_create (__NR_Linux + 207)
-#define __NR_epoll_ctl (__NR_Linux + 208)
-#define __NR_epoll_wait (__NR_Linux + 209)
-#define __NR_remap_file_pages (__NR_Linux + 210)
-#define __NR_rt_sigreturn (__NR_Linux + 211)
-#define __NR_set_tid_address (__NR_Linux + 212)
-#define __NR_restart_syscall (__NR_Linux + 213)
-#define __NR_semtimedop (__NR_Linux + 214)
-#define __NR_fadvise64 (__NR_Linux + 215)
-#define __NR_timer_create (__NR_Linux + 216)
-#define __NR_timer_settime (__NR_Linux + 217)
-#define __NR_timer_gettime (__NR_Linux + 218)
-#define __NR_timer_getoverrun (__NR_Linux + 219)
-#define __NR_timer_delete (__NR_Linux + 220)
-#define __NR_clock_settime (__NR_Linux + 221)
-#define __NR_clock_gettime (__NR_Linux + 222)
-#define __NR_clock_getres (__NR_Linux + 223)
-#define __NR_clock_nanosleep (__NR_Linux + 224)
-#define __NR_tgkill (__NR_Linux + 225)
-#define __NR_utimes (__NR_Linux + 226)
-#define __NR_mbind (__NR_Linux + 227)
-#define __NR_get_mempolicy (__NR_Linux + 228)
-#define __NR_set_mempolicy (__NR_Linux + 229)
-#define __NR_mq_open (__NR_Linux + 230)
-#define __NR_mq_unlink (__NR_Linux + 231)
-#define __NR_mq_timedsend (__NR_Linux + 232)
-#define __NR_mq_timedreceive (__NR_Linux + 233)
-#define __NR_mq_notify (__NR_Linux + 234)
-#define __NR_mq_getsetattr (__NR_Linux + 235)
-#define __NR_vserver (__NR_Linux + 236)
-#define __NR_waitid (__NR_Linux + 237)
-/* #define __NR_sys_setaltroot (__NR_Linux + 238) */
-#define __NR_add_key (__NR_Linux + 239)
-#define __NR_request_key (__NR_Linux + 240)
-#define __NR_keyctl (__NR_Linux + 241)
-#define __NR_set_thread_area (__NR_Linux + 242)
-#define __NR_inotify_init (__NR_Linux + 243)
-#define __NR_inotify_add_watch (__NR_Linux + 244)
-#define __NR_inotify_rm_watch (__NR_Linux + 245)
-#define __NR_migrate_pages (__NR_Linux + 246)
-#define __NR_openat (__NR_Linux + 247)
-#define __NR_mkdirat (__NR_Linux + 248)
-#define __NR_mknodat (__NR_Linux + 249)
-#define __NR_fchownat (__NR_Linux + 250)
-#define __NR_futimesat (__NR_Linux + 251)
-#define __NR_newfstatat (__NR_Linux + 252)
-#define __NR_unlinkat (__NR_Linux + 253)
-#define __NR_renameat (__NR_Linux + 254)
-#define __NR_linkat (__NR_Linux + 255)
-#define __NR_symlinkat (__NR_Linux + 256)
-#define __NR_readlinkat (__NR_Linux + 257)
-#define __NR_fchmodat (__NR_Linux + 258)
-#define __NR_faccessat (__NR_Linux + 259)
-#define __NR_pselect6 (__NR_Linux + 260)
-#define __NR_ppoll (__NR_Linux + 261)
-#define __NR_unshare (__NR_Linux + 262)
-#define __NR_splice (__NR_Linux + 263)
-#define __NR_sync_file_range (__NR_Linux + 264)
-#define __NR_tee (__NR_Linux + 265)
-#define __NR_vmsplice (__NR_Linux + 266)
-#define __NR_move_pages (__NR_Linux + 267)
-#define __NR_set_robust_list (__NR_Linux + 268)
-#define __NR_get_robust_list (__NR_Linux + 269)
-#define __NR_kexec_load (__NR_Linux + 270)
-#define __NR_getcpu (__NR_Linux + 271)
-#define __NR_epoll_pwait (__NR_Linux + 272)
-#define __NR_ioprio_set (__NR_Linux + 273)
-#define __NR_ioprio_get (__NR_Linux + 274)
-#define __NR_utimensat (__NR_Linux + 275)
-#define __NR_signalfd (__NR_Linux + 276)
-#define __NR_timerfd (__NR_Linux + 277)
-#define __NR_eventfd (__NR_Linux + 278)
-#define __NR_fallocate (__NR_Linux + 279)
-#define __NR_timerfd_create (__NR_Linux + 280)
-#define __NR_timerfd_gettime (__NR_Linux + 281)
-#define __NR_timerfd_settime (__NR_Linux + 282)
-#define __NR_signalfd4 (__NR_Linux + 283)
-#define __NR_eventfd2 (__NR_Linux + 284)
-#define __NR_epoll_create1 (__NR_Linux + 285)
-#define __NR_dup3 (__NR_Linux + 286)
-#define __NR_pipe2 (__NR_Linux + 287)
-#define __NR_inotify_init1 (__NR_Linux + 288)
-#define __NR_preadv (__NR_Linux + 289)
-#define __NR_pwritev (__NR_Linux + 290)
-#define __NR_rt_tgsigqueueinfo (__NR_Linux + 291)
-#define __NR_perf_event_open (__NR_Linux + 292)
-#define __NR_accept4 (__NR_Linux + 293)
-#define __NR_recvmmsg (__NR_Linux + 294)
-#define __NR_fanotify_init (__NR_Linux + 295)
-#define __NR_fanotify_mark (__NR_Linux + 296)
-#define __NR_prlimit64 (__NR_Linux + 297)
-#define __NR_name_to_handle_at (__NR_Linux + 298)
-#define __NR_open_by_handle_at (__NR_Linux + 299)
-#define __NR_clock_adjtime (__NR_Linux + 300)
-#define __NR_syncfs (__NR_Linux + 301)
-#define __NR_sendmmsg (__NR_Linux + 302)
-#define __NR_setns (__NR_Linux + 303)
-#define __NR_process_vm_readv (__NR_Linux + 304)
-#define __NR_process_vm_writev (__NR_Linux + 305)
-#define __NR_kcmp (__NR_Linux + 306)
-#define __NR_finit_module (__NR_Linux + 307)
-#define __NR_getdents64 (__NR_Linux + 308)
-#define __NR_sched_setattr (__NR_Linux + 309)
-#define __NR_sched_getattr (__NR_Linux + 310)
-#define __NR_renameat2 (__NR_Linux + 311)
-#define __NR_seccomp (__NR_Linux + 312)
-#define __NR_getrandom (__NR_Linux + 313)
-#define __NR_memfd_create (__NR_Linux + 314)
-#define __NR_bpf (__NR_Linux + 315)
-#define __NR_execveat (__NR_Linux + 316)
-#define __NR_userfaultfd (__NR_Linux + 317)
-#define __NR_membarrier (__NR_Linux + 318)
-#define __NR_mlock2 (__NR_Linux + 319)
-#define __NR_copy_file_range (__NR_Linux + 320)
-#define __NR_preadv2 (__NR_Linux + 321)
-#define __NR_pwritev2 (__NR_Linux + 322)
-#define __NR_pkey_mprotect (__NR_Linux + 323)
-#define __NR_pkey_alloc (__NR_Linux + 324)
-#define __NR_pkey_free (__NR_Linux + 325)
-#define __NR_statx (__NR_Linux + 326)
-#define __NR_rseq (__NR_Linux + 327)
-#define __NR_io_pgetevents (__NR_Linux + 328)
-
-/*
- * Offset of the last Linux 64-bit flavoured syscall
- */
-#define __NR_Linux_syscalls 328
+#define __NR_Linux 5000
+#include <asm/unistd_n64.h>
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
-#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 328
-
#if _MIPS_SIM == _MIPS_SIM_NABI32
-/*
- * Linux N32 syscalls are in the range from 6000 to 6999.
- */
-#define __NR_Linux 6000
-#define __NR_read (__NR_Linux + 0)
-#define __NR_write (__NR_Linux + 1)
-#define __NR_open (__NR_Linux + 2)
-#define __NR_close (__NR_Linux + 3)
-#define __NR_stat (__NR_Linux + 4)
-#define __NR_fstat (__NR_Linux + 5)
-#define __NR_lstat (__NR_Linux + 6)
-#define __NR_poll (__NR_Linux + 7)
-#define __NR_lseek (__NR_Linux + 8)
-#define __NR_mmap (__NR_Linux + 9)
-#define __NR_mprotect (__NR_Linux + 10)
-#define __NR_munmap (__NR_Linux + 11)
-#define __NR_brk (__NR_Linux + 12)
-#define __NR_rt_sigaction (__NR_Linux + 13)
-#define __NR_rt_sigprocmask (__NR_Linux + 14)
-#define __NR_ioctl (__NR_Linux + 15)
-#define __NR_pread64 (__NR_Linux + 16)
-#define __NR_pwrite64 (__NR_Linux + 17)
-#define __NR_readv (__NR_Linux + 18)
-#define __NR_writev (__NR_Linux + 19)
-#define __NR_access (__NR_Linux + 20)
-#define __NR_pipe (__NR_Linux + 21)
-#define __NR__newselect (__NR_Linux + 22)
-#define __NR_sched_yield (__NR_Linux + 23)
-#define __NR_mremap (__NR_Linux + 24)
-#define __NR_msync (__NR_Linux + 25)
-#define __NR_mincore (__NR_Linux + 26)
-#define __NR_madvise (__NR_Linux + 27)
-#define __NR_shmget (__NR_Linux + 28)
-#define __NR_shmat (__NR_Linux + 29)
-#define __NR_shmctl (__NR_Linux + 30)
-#define __NR_dup (__NR_Linux + 31)
-#define __NR_dup2 (__NR_Linux + 32)
-#define __NR_pause (__NR_Linux + 33)
-#define __NR_nanosleep (__NR_Linux + 34)
-#define __NR_getitimer (__NR_Linux + 35)
-#define __NR_setitimer (__NR_Linux + 36)
-#define __NR_alarm (__NR_Linux + 37)
-#define __NR_getpid (__NR_Linux + 38)
-#define __NR_sendfile (__NR_Linux + 39)
-#define __NR_socket (__NR_Linux + 40)
-#define __NR_connect (__NR_Linux + 41)
-#define __NR_accept (__NR_Linux + 42)
-#define __NR_sendto (__NR_Linux + 43)
-#define __NR_recvfrom (__NR_Linux + 44)
-#define __NR_sendmsg (__NR_Linux + 45)
-#define __NR_recvmsg (__NR_Linux + 46)
-#define __NR_shutdown (__NR_Linux + 47)
-#define __NR_bind (__NR_Linux + 48)
-#define __NR_listen (__NR_Linux + 49)
-#define __NR_getsockname (__NR_Linux + 50)
-#define __NR_getpeername (__NR_Linux + 51)
-#define __NR_socketpair (__NR_Linux + 52)
-#define __NR_setsockopt (__NR_Linux + 53)
-#define __NR_getsockopt (__NR_Linux + 54)
-#define __NR_clone (__NR_Linux + 55)
-#define __NR_fork (__NR_Linux + 56)
-#define __NR_execve (__NR_Linux + 57)
-#define __NR_exit (__NR_Linux + 58)
-#define __NR_wait4 (__NR_Linux + 59)
-#define __NR_kill (__NR_Linux + 60)
-#define __NR_uname (__NR_Linux + 61)
-#define __NR_semget (__NR_Linux + 62)
-#define __NR_semop (__NR_Linux + 63)
-#define __NR_semctl (__NR_Linux + 64)
-#define __NR_shmdt (__NR_Linux + 65)
-#define __NR_msgget (__NR_Linux + 66)
-#define __NR_msgsnd (__NR_Linux + 67)
-#define __NR_msgrcv (__NR_Linux + 68)
-#define __NR_msgctl (__NR_Linux + 69)
-#define __NR_fcntl (__NR_Linux + 70)
-#define __NR_flock (__NR_Linux + 71)
-#define __NR_fsync (__NR_Linux + 72)
-#define __NR_fdatasync (__NR_Linux + 73)
-#define __NR_truncate (__NR_Linux + 74)
-#define __NR_ftruncate (__NR_Linux + 75)
-#define __NR_getdents (__NR_Linux + 76)
-#define __NR_getcwd (__NR_Linux + 77)
-#define __NR_chdir (__NR_Linux + 78)
-#define __NR_fchdir (__NR_Linux + 79)
-#define __NR_rename (__NR_Linux + 80)
-#define __NR_mkdir (__NR_Linux + 81)
-#define __NR_rmdir (__NR_Linux + 82)
-#define __NR_creat (__NR_Linux + 83)
-#define __NR_link (__NR_Linux + 84)
-#define __NR_unlink (__NR_Linux + 85)
-#define __NR_symlink (__NR_Linux + 86)
-#define __NR_readlink (__NR_Linux + 87)
-#define __NR_chmod (__NR_Linux + 88)
-#define __NR_fchmod (__NR_Linux + 89)
-#define __NR_chown (__NR_Linux + 90)
-#define __NR_fchown (__NR_Linux + 91)
-#define __NR_lchown (__NR_Linux + 92)
-#define __NR_umask (__NR_Linux + 93)
-#define __NR_gettimeofday (__NR_Linux + 94)
-#define __NR_getrlimit (__NR_Linux + 95)
-#define __NR_getrusage (__NR_Linux + 96)
-#define __NR_sysinfo (__NR_Linux + 97)
-#define __NR_times (__NR_Linux + 98)
-#define __NR_ptrace (__NR_Linux + 99)
-#define __NR_getuid (__NR_Linux + 100)
-#define __NR_syslog (__NR_Linux + 101)
-#define __NR_getgid (__NR_Linux + 102)
-#define __NR_setuid (__NR_Linux + 103)
-#define __NR_setgid (__NR_Linux + 104)
-#define __NR_geteuid (__NR_Linux + 105)
-#define __NR_getegid (__NR_Linux + 106)
-#define __NR_setpgid (__NR_Linux + 107)
-#define __NR_getppid (__NR_Linux + 108)
-#define __NR_getpgrp (__NR_Linux + 109)
-#define __NR_setsid (__NR_Linux + 110)
-#define __NR_setreuid (__NR_Linux + 111)
-#define __NR_setregid (__NR_Linux + 112)
-#define __NR_getgroups (__NR_Linux + 113)
-#define __NR_setgroups (__NR_Linux + 114)
-#define __NR_setresuid (__NR_Linux + 115)
-#define __NR_getresuid (__NR_Linux + 116)
-#define __NR_setresgid (__NR_Linux + 117)
-#define __NR_getresgid (__NR_Linux + 118)
-#define __NR_getpgid (__NR_Linux + 119)
-#define __NR_setfsuid (__NR_Linux + 120)
-#define __NR_setfsgid (__NR_Linux + 121)
-#define __NR_getsid (__NR_Linux + 122)
-#define __NR_capget (__NR_Linux + 123)
-#define __NR_capset (__NR_Linux + 124)
-#define __NR_rt_sigpending (__NR_Linux + 125)
-#define __NR_rt_sigtimedwait (__NR_Linux + 126)
-#define __NR_rt_sigqueueinfo (__NR_Linux + 127)
-#define __NR_rt_sigsuspend (__NR_Linux + 128)
-#define __NR_sigaltstack (__NR_Linux + 129)
-#define __NR_utime (__NR_Linux + 130)
-#define __NR_mknod (__NR_Linux + 131)
-#define __NR_personality (__NR_Linux + 132)
-#define __NR_ustat (__NR_Linux + 133)
-#define __NR_statfs (__NR_Linux + 134)
-#define __NR_fstatfs (__NR_Linux + 135)
-#define __NR_sysfs (__NR_Linux + 136)
-#define __NR_getpriority (__NR_Linux + 137)
-#define __NR_setpriority (__NR_Linux + 138)
-#define __NR_sched_setparam (__NR_Linux + 139)
-#define __NR_sched_getparam (__NR_Linux + 140)
-#define __NR_sched_setscheduler (__NR_Linux + 141)
-#define __NR_sched_getscheduler (__NR_Linux + 142)
-#define __NR_sched_get_priority_max (__NR_Linux + 143)
-#define __NR_sched_get_priority_min (__NR_Linux + 144)
-#define __NR_sched_rr_get_interval (__NR_Linux + 145)
-#define __NR_mlock (__NR_Linux + 146)
-#define __NR_munlock (__NR_Linux + 147)
-#define __NR_mlockall (__NR_Linux + 148)
-#define __NR_munlockall (__NR_Linux + 149)
-#define __NR_vhangup (__NR_Linux + 150)
-#define __NR_pivot_root (__NR_Linux + 151)
-#define __NR__sysctl (__NR_Linux + 152)
-#define __NR_prctl (__NR_Linux + 153)
-#define __NR_adjtimex (__NR_Linux + 154)
-#define __NR_setrlimit (__NR_Linux + 155)
-#define __NR_chroot (__NR_Linux + 156)
-#define __NR_sync (__NR_Linux + 157)
-#define __NR_acct (__NR_Linux + 158)
-#define __NR_settimeofday (__NR_Linux + 159)
-#define __NR_mount (__NR_Linux + 160)
-#define __NR_umount2 (__NR_Linux + 161)
-#define __NR_swapon (__NR_Linux + 162)
-#define __NR_swapoff (__NR_Linux + 163)
-#define __NR_reboot (__NR_Linux + 164)
-#define __NR_sethostname (__NR_Linux + 165)
-#define __NR_setdomainname (__NR_Linux + 166)
-#define __NR_create_module (__NR_Linux + 167)
-#define __NR_init_module (__NR_Linux + 168)
-#define __NR_delete_module (__NR_Linux + 169)
-#define __NR_get_kernel_syms (__NR_Linux + 170)
-#define __NR_query_module (__NR_Linux + 171)
-#define __NR_quotactl (__NR_Linux + 172)
-#define __NR_nfsservctl (__NR_Linux + 173)
-#define __NR_getpmsg (__NR_Linux + 174)
-#define __NR_putpmsg (__NR_Linux + 175)
-#define __NR_afs_syscall (__NR_Linux + 176)
-#define __NR_reserved177 (__NR_Linux + 177)
-#define __NR_gettid (__NR_Linux + 178)
-#define __NR_readahead (__NR_Linux + 179)
-#define __NR_setxattr (__NR_Linux + 180)
-#define __NR_lsetxattr (__NR_Linux + 181)
-#define __NR_fsetxattr (__NR_Linux + 182)
-#define __NR_getxattr (__NR_Linux + 183)
-#define __NR_lgetxattr (__NR_Linux + 184)
-#define __NR_fgetxattr (__NR_Linux + 185)
-#define __NR_listxattr (__NR_Linux + 186)
-#define __NR_llistxattr (__NR_Linux + 187)
-#define __NR_flistxattr (__NR_Linux + 188)
-#define __NR_removexattr (__NR_Linux + 189)
-#define __NR_lremovexattr (__NR_Linux + 190)
-#define __NR_fremovexattr (__NR_Linux + 191)
-#define __NR_tkill (__NR_Linux + 192)
-#define __NR_reserved193 (__NR_Linux + 193)
-#define __NR_futex (__NR_Linux + 194)
-#define __NR_sched_setaffinity (__NR_Linux + 195)
-#define __NR_sched_getaffinity (__NR_Linux + 196)
-#define __NR_cacheflush (__NR_Linux + 197)
-#define __NR_cachectl (__NR_Linux + 198)
-#define __NR_sysmips (__NR_Linux + 199)
-#define __NR_io_setup (__NR_Linux + 200)
-#define __NR_io_destroy (__NR_Linux + 201)
-#define __NR_io_getevents (__NR_Linux + 202)
-#define __NR_io_submit (__NR_Linux + 203)
-#define __NR_io_cancel (__NR_Linux + 204)
-#define __NR_exit_group (__NR_Linux + 205)
-#define __NR_lookup_dcookie (__NR_Linux + 206)
-#define __NR_epoll_create (__NR_Linux + 207)
-#define __NR_epoll_ctl (__NR_Linux + 208)
-#define __NR_epoll_wait (__NR_Linux + 209)
-#define __NR_remap_file_pages (__NR_Linux + 210)
-#define __NR_rt_sigreturn (__NR_Linux + 211)
-#define __NR_fcntl64 (__NR_Linux + 212)
-#define __NR_set_tid_address (__NR_Linux + 213)
-#define __NR_restart_syscall (__NR_Linux + 214)
-#define __NR_semtimedop (__NR_Linux + 215)
-#define __NR_fadvise64 (__NR_Linux + 216)
-#define __NR_statfs64 (__NR_Linux + 217)
-#define __NR_fstatfs64 (__NR_Linux + 218)
-#define __NR_sendfile64 (__NR_Linux + 219)
-#define __NR_timer_create (__NR_Linux + 220)
-#define __NR_timer_settime (__NR_Linux + 221)
-#define __NR_timer_gettime (__NR_Linux + 222)
-#define __NR_timer_getoverrun (__NR_Linux + 223)
-#define __NR_timer_delete (__NR_Linux + 224)
-#define __NR_clock_settime (__NR_Linux + 225)
-#define __NR_clock_gettime (__NR_Linux + 226)
-#define __NR_clock_getres (__NR_Linux + 227)
-#define __NR_clock_nanosleep (__NR_Linux + 228)
-#define __NR_tgkill (__NR_Linux + 229)
-#define __NR_utimes (__NR_Linux + 230)
-#define __NR_mbind (__NR_Linux + 231)
-#define __NR_get_mempolicy (__NR_Linux + 232)
-#define __NR_set_mempolicy (__NR_Linux + 233)
-#define __NR_mq_open (__NR_Linux + 234)
-#define __NR_mq_unlink (__NR_Linux + 235)
-#define __NR_mq_timedsend (__NR_Linux + 236)
-#define __NR_mq_timedreceive (__NR_Linux + 237)
-#define __NR_mq_notify (__NR_Linux + 238)
-#define __NR_mq_getsetattr (__NR_Linux + 239)
-#define __NR_vserver (__NR_Linux + 240)
-#define __NR_waitid (__NR_Linux + 241)
-/* #define __NR_sys_setaltroot (__NR_Linux + 242) */
-#define __NR_add_key (__NR_Linux + 243)
-#define __NR_request_key (__NR_Linux + 244)
-#define __NR_keyctl (__NR_Linux + 245)
-#define __NR_set_thread_area (__NR_Linux + 246)
-#define __NR_inotify_init (__NR_Linux + 247)
-#define __NR_inotify_add_watch (__NR_Linux + 248)
-#define __NR_inotify_rm_watch (__NR_Linux + 249)
-#define __NR_migrate_pages (__NR_Linux + 250)
-#define __NR_openat (__NR_Linux + 251)
-#define __NR_mkdirat (__NR_Linux + 252)
-#define __NR_mknodat (__NR_Linux + 253)
-#define __NR_fchownat (__NR_Linux + 254)
-#define __NR_futimesat (__NR_Linux + 255)
-#define __NR_newfstatat (__NR_Linux + 256)
-#define __NR_unlinkat (__NR_Linux + 257)
-#define __NR_renameat (__NR_Linux + 258)
-#define __NR_linkat (__NR_Linux + 259)
-#define __NR_symlinkat (__NR_Linux + 260)
-#define __NR_readlinkat (__NR_Linux + 261)
-#define __NR_fchmodat (__NR_Linux + 262)
-#define __NR_faccessat (__NR_Linux + 263)
-#define __NR_pselect6 (__NR_Linux + 264)
-#define __NR_ppoll (__NR_Linux + 265)
-#define __NR_unshare (__NR_Linux + 266)
-#define __NR_splice (__NR_Linux + 267)
-#define __NR_sync_file_range (__NR_Linux + 268)
-#define __NR_tee (__NR_Linux + 269)
-#define __NR_vmsplice (__NR_Linux + 270)
-#define __NR_move_pages (__NR_Linux + 271)
-#define __NR_set_robust_list (__NR_Linux + 272)
-#define __NR_get_robust_list (__NR_Linux + 273)
-#define __NR_kexec_load (__NR_Linux + 274)
-#define __NR_getcpu (__NR_Linux + 275)
-#define __NR_epoll_pwait (__NR_Linux + 276)
-#define __NR_ioprio_set (__NR_Linux + 277)
-#define __NR_ioprio_get (__NR_Linux + 278)
-#define __NR_utimensat (__NR_Linux + 279)
-#define __NR_signalfd (__NR_Linux + 280)
-#define __NR_timerfd (__NR_Linux + 281)
-#define __NR_eventfd (__NR_Linux + 282)
-#define __NR_fallocate (__NR_Linux + 283)
-#define __NR_timerfd_create (__NR_Linux + 284)
-#define __NR_timerfd_gettime (__NR_Linux + 285)
-#define __NR_timerfd_settime (__NR_Linux + 286)
-#define __NR_signalfd4 (__NR_Linux + 287)
-#define __NR_eventfd2 (__NR_Linux + 288)
-#define __NR_epoll_create1 (__NR_Linux + 289)
-#define __NR_dup3 (__NR_Linux + 290)
-#define __NR_pipe2 (__NR_Linux + 291)
-#define __NR_inotify_init1 (__NR_Linux + 292)
-#define __NR_preadv (__NR_Linux + 293)
-#define __NR_pwritev (__NR_Linux + 294)
-#define __NR_rt_tgsigqueueinfo (__NR_Linux + 295)
-#define __NR_perf_event_open (__NR_Linux + 296)
-#define __NR_accept4 (__NR_Linux + 297)
-#define __NR_recvmmsg (__NR_Linux + 298)
-#define __NR_getdents64 (__NR_Linux + 299)
-#define __NR_fanotify_init (__NR_Linux + 300)
-#define __NR_fanotify_mark (__NR_Linux + 301)
-#define __NR_prlimit64 (__NR_Linux + 302)
-#define __NR_name_to_handle_at (__NR_Linux + 303)
-#define __NR_open_by_handle_at (__NR_Linux + 304)
-#define __NR_clock_adjtime (__NR_Linux + 305)
-#define __NR_syncfs (__NR_Linux + 306)
-#define __NR_sendmmsg (__NR_Linux + 307)
-#define __NR_setns (__NR_Linux + 308)
-#define __NR_process_vm_readv (__NR_Linux + 309)
-#define __NR_process_vm_writev (__NR_Linux + 310)
-#define __NR_kcmp (__NR_Linux + 311)
-#define __NR_finit_module (__NR_Linux + 312)
-#define __NR_sched_setattr (__NR_Linux + 313)
-#define __NR_sched_getattr (__NR_Linux + 314)
-#define __NR_renameat2 (__NR_Linux + 315)
-#define __NR_seccomp (__NR_Linux + 316)
-#define __NR_getrandom (__NR_Linux + 317)
-#define __NR_memfd_create (__NR_Linux + 318)
-#define __NR_bpf (__NR_Linux + 319)
-#define __NR_execveat (__NR_Linux + 320)
-#define __NR_userfaultfd (__NR_Linux + 321)
-#define __NR_membarrier (__NR_Linux + 322)
-#define __NR_mlock2 (__NR_Linux + 323)
-#define __NR_copy_file_range (__NR_Linux + 324)
-#define __NR_preadv2 (__NR_Linux + 325)
-#define __NR_pwritev2 (__NR_Linux + 326)
-#define __NR_pkey_mprotect (__NR_Linux + 327)
-#define __NR_pkey_alloc (__NR_Linux + 328)
-#define __NR_pkey_free (__NR_Linux + 329)
-#define __NR_statx (__NR_Linux + 330)
-#define __NR_rseq (__NR_Linux + 331)
-#define __NR_io_pgetevents (__NR_Linux + 332)
-
-/*
- * Offset of the last N32 flavoured syscall
- */
-#define __NR_Linux_syscalls 332
+#define __NR_Linux 6000
+#include <asm/unistd_n32.h>
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
-#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 332
-
#endif /* _ASM_UNISTD_H */
--- /dev/null
+#ifndef _ASM_MIPS_UNISTD_N32_H
+#define _ASM_MIPS_UNISTD_N32_H
+
+#define __NR_read (__NR_Linux + 0)
+#define __NR_write (__NR_Linux + 1)
+#define __NR_open (__NR_Linux + 2)
+#define __NR_close (__NR_Linux + 3)
+#define __NR_stat (__NR_Linux + 4)
+#define __NR_fstat (__NR_Linux + 5)
+#define __NR_lstat (__NR_Linux + 6)
+#define __NR_poll (__NR_Linux + 7)
+#define __NR_lseek (__NR_Linux + 8)
+#define __NR_mmap (__NR_Linux + 9)
+#define __NR_mprotect (__NR_Linux + 10)
+#define __NR_munmap (__NR_Linux + 11)
+#define __NR_brk (__NR_Linux + 12)
+#define __NR_rt_sigaction (__NR_Linux + 13)
+#define __NR_rt_sigprocmask (__NR_Linux + 14)
+#define __NR_ioctl (__NR_Linux + 15)
+#define __NR_pread64 (__NR_Linux + 16)
+#define __NR_pwrite64 (__NR_Linux + 17)
+#define __NR_readv (__NR_Linux + 18)
+#define __NR_writev (__NR_Linux + 19)
+#define __NR_access (__NR_Linux + 20)
+#define __NR_pipe (__NR_Linux + 21)
+#define __NR__newselect (__NR_Linux + 22)
+#define __NR_sched_yield (__NR_Linux + 23)
+#define __NR_mremap (__NR_Linux + 24)
+#define __NR_msync (__NR_Linux + 25)
+#define __NR_mincore (__NR_Linux + 26)
+#define __NR_madvise (__NR_Linux + 27)
+#define __NR_shmget (__NR_Linux + 28)
+#define __NR_shmat (__NR_Linux + 29)
+#define __NR_shmctl (__NR_Linux + 30)
+#define __NR_dup (__NR_Linux + 31)
+#define __NR_dup2 (__NR_Linux + 32)
+#define __NR_pause (__NR_Linux + 33)
+#define __NR_nanosleep (__NR_Linux + 34)
+#define __NR_getitimer (__NR_Linux + 35)
+#define __NR_setitimer (__NR_Linux + 36)
+#define __NR_alarm (__NR_Linux + 37)
+#define __NR_getpid (__NR_Linux + 38)
+#define __NR_sendfile (__NR_Linux + 39)
+#define __NR_socket (__NR_Linux + 40)
+#define __NR_connect (__NR_Linux + 41)
+#define __NR_accept (__NR_Linux + 42)
+#define __NR_sendto (__NR_Linux + 43)
+#define __NR_recvfrom (__NR_Linux + 44)
+#define __NR_sendmsg (__NR_Linux + 45)
+#define __NR_recvmsg (__NR_Linux + 46)
+#define __NR_shutdown (__NR_Linux + 47)
+#define __NR_bind (__NR_Linux + 48)
+#define __NR_listen (__NR_Linux + 49)
+#define __NR_getsockname (__NR_Linux + 50)
+#define __NR_getpeername (__NR_Linux + 51)
+#define __NR_socketpair (__NR_Linux + 52)
+#define __NR_setsockopt (__NR_Linux + 53)
+#define __NR_getsockopt (__NR_Linux + 54)
+#define __NR_clone (__NR_Linux + 55)
+#define __NR_fork (__NR_Linux + 56)
+#define __NR_execve (__NR_Linux + 57)
+#define __NR_exit (__NR_Linux + 58)
+#define __NR_wait4 (__NR_Linux + 59)
+#define __NR_kill (__NR_Linux + 60)
+#define __NR_uname (__NR_Linux + 61)
+#define __NR_semget (__NR_Linux + 62)
+#define __NR_semop (__NR_Linux + 63)
+#define __NR_semctl (__NR_Linux + 64)
+#define __NR_shmdt (__NR_Linux + 65)
+#define __NR_msgget (__NR_Linux + 66)
+#define __NR_msgsnd (__NR_Linux + 67)
+#define __NR_msgrcv (__NR_Linux + 68)
+#define __NR_msgctl (__NR_Linux + 69)
+#define __NR_fcntl (__NR_Linux + 70)
+#define __NR_flock (__NR_Linux + 71)
+#define __NR_fsync (__NR_Linux + 72)
+#define __NR_fdatasync (__NR_Linux + 73)
+#define __NR_truncate (__NR_Linux + 74)
+#define __NR_ftruncate (__NR_Linux + 75)
+#define __NR_getdents (__NR_Linux + 76)
+#define __NR_getcwd (__NR_Linux + 77)
+#define __NR_chdir (__NR_Linux + 78)
+#define __NR_fchdir (__NR_Linux + 79)
+#define __NR_rename (__NR_Linux + 80)
+#define __NR_mkdir (__NR_Linux + 81)
+#define __NR_rmdir (__NR_Linux + 82)
+#define __NR_creat (__NR_Linux + 83)
+#define __NR_link (__NR_Linux + 84)
+#define __NR_unlink (__NR_Linux + 85)
+#define __NR_symlink (__NR_Linux + 86)
+#define __NR_readlink (__NR_Linux + 87)
+#define __NR_chmod (__NR_Linux + 88)
+#define __NR_fchmod (__NR_Linux + 89)
+#define __NR_chown (__NR_Linux + 90)
+#define __NR_fchown (__NR_Linux + 91)
+#define __NR_lchown (__NR_Linux + 92)
+#define __NR_umask (__NR_Linux + 93)
+#define __NR_gettimeofday (__NR_Linux + 94)
+#define __NR_getrlimit (__NR_Linux + 95)
+#define __NR_getrusage (__NR_Linux + 96)
+#define __NR_sysinfo (__NR_Linux + 97)
+#define __NR_times (__NR_Linux + 98)
+#define __NR_ptrace (__NR_Linux + 99)
+#define __NR_getuid (__NR_Linux + 100)
+#define __NR_syslog (__NR_Linux + 101)
+#define __NR_getgid (__NR_Linux + 102)
+#define __NR_setuid (__NR_Linux + 103)
+#define __NR_setgid (__NR_Linux + 104)
+#define __NR_geteuid (__NR_Linux + 105)
+#define __NR_getegid (__NR_Linux + 106)
+#define __NR_setpgid (__NR_Linux + 107)
+#define __NR_getppid (__NR_Linux + 108)
+#define __NR_getpgrp (__NR_Linux + 109)
+#define __NR_setsid (__NR_Linux + 110)
+#define __NR_setreuid (__NR_Linux + 111)
+#define __NR_setregid (__NR_Linux + 112)
+#define __NR_getgroups (__NR_Linux + 113)
+#define __NR_setgroups (__NR_Linux + 114)
+#define __NR_setresuid (__NR_Linux + 115)
+#define __NR_getresuid (__NR_Linux + 116)
+#define __NR_setresgid (__NR_Linux + 117)
+#define __NR_getresgid (__NR_Linux + 118)
+#define __NR_getpgid (__NR_Linux + 119)
+#define __NR_setfsuid (__NR_Linux + 120)
+#define __NR_setfsgid (__NR_Linux + 121)
+#define __NR_getsid (__NR_Linux + 122)
+#define __NR_capget (__NR_Linux + 123)
+#define __NR_capset (__NR_Linux + 124)
+#define __NR_rt_sigpending (__NR_Linux + 125)
+#define __NR_rt_sigtimedwait (__NR_Linux + 126)
+#define __NR_rt_sigqueueinfo (__NR_Linux + 127)
+#define __NR_rt_sigsuspend (__NR_Linux + 128)
+#define __NR_sigaltstack (__NR_Linux + 129)
+#define __NR_utime (__NR_Linux + 130)
+#define __NR_mknod (__NR_Linux + 131)
+#define __NR_personality (__NR_Linux + 132)
+#define __NR_ustat (__NR_Linux + 133)
+#define __NR_statfs (__NR_Linux + 134)
+#define __NR_fstatfs (__NR_Linux + 135)
+#define __NR_sysfs (__NR_Linux + 136)
+#define __NR_getpriority (__NR_Linux + 137)
+#define __NR_setpriority (__NR_Linux + 138)
+#define __NR_sched_setparam (__NR_Linux + 139)
+#define __NR_sched_getparam (__NR_Linux + 140)
+#define __NR_sched_setscheduler (__NR_Linux + 141)
+#define __NR_sched_getscheduler (__NR_Linux + 142)
+#define __NR_sched_get_priority_max (__NR_Linux + 143)
+#define __NR_sched_get_priority_min (__NR_Linux + 144)
+#define __NR_sched_rr_get_interval (__NR_Linux + 145)
+#define __NR_mlock (__NR_Linux + 146)
+#define __NR_munlock (__NR_Linux + 147)
+#define __NR_mlockall (__NR_Linux + 148)
+#define __NR_munlockall (__NR_Linux + 149)
+#define __NR_vhangup (__NR_Linux + 150)
+#define __NR_pivot_root (__NR_Linux + 151)
+#define __NR__sysctl (__NR_Linux + 152)
+#define __NR_prctl (__NR_Linux + 153)
+#define __NR_adjtimex (__NR_Linux + 154)
+#define __NR_setrlimit (__NR_Linux + 155)
+#define __NR_chroot (__NR_Linux + 156)
+#define __NR_sync (__NR_Linux + 157)
+#define __NR_acct (__NR_Linux + 158)
+#define __NR_settimeofday (__NR_Linux + 159)
+#define __NR_mount (__NR_Linux + 160)
+#define __NR_umount2 (__NR_Linux + 161)
+#define __NR_swapon (__NR_Linux + 162)
+#define __NR_swapoff (__NR_Linux + 163)
+#define __NR_reboot (__NR_Linux + 164)
+#define __NR_sethostname (__NR_Linux + 165)
+#define __NR_setdomainname (__NR_Linux + 166)
+#define __NR_create_module (__NR_Linux + 167)
+#define __NR_init_module (__NR_Linux + 168)
+#define __NR_delete_module (__NR_Linux + 169)
+#define __NR_get_kernel_syms (__NR_Linux + 170)
+#define __NR_query_module (__NR_Linux + 171)
+#define __NR_quotactl (__NR_Linux + 172)
+#define __NR_nfsservctl (__NR_Linux + 173)
+#define __NR_getpmsg (__NR_Linux + 174)
+#define __NR_putpmsg (__NR_Linux + 175)
+#define __NR_afs_syscall (__NR_Linux + 176)
+#define __NR_reserved177 (__NR_Linux + 177)
+#define __NR_gettid (__NR_Linux + 178)
+#define __NR_readahead (__NR_Linux + 179)
+#define __NR_setxattr (__NR_Linux + 180)
+#define __NR_lsetxattr (__NR_Linux + 181)
+#define __NR_fsetxattr (__NR_Linux + 182)
+#define __NR_getxattr (__NR_Linux + 183)
+#define __NR_lgetxattr (__NR_Linux + 184)
+#define __NR_fgetxattr (__NR_Linux + 185)
+#define __NR_listxattr (__NR_Linux + 186)
+#define __NR_llistxattr (__NR_Linux + 187)
+#define __NR_flistxattr (__NR_Linux + 188)
+#define __NR_removexattr (__NR_Linux + 189)
+#define __NR_lremovexattr (__NR_Linux + 190)
+#define __NR_fremovexattr (__NR_Linux + 191)
+#define __NR_tkill (__NR_Linux + 192)
+#define __NR_reserved193 (__NR_Linux + 193)
+#define __NR_futex (__NR_Linux + 194)
+#define __NR_sched_setaffinity (__NR_Linux + 195)
+#define __NR_sched_getaffinity (__NR_Linux + 196)
+#define __NR_cacheflush (__NR_Linux + 197)
+#define __NR_cachectl (__NR_Linux + 198)
+#define __NR_sysmips (__NR_Linux + 199)
+#define __NR_io_setup (__NR_Linux + 200)
+#define __NR_io_destroy (__NR_Linux + 201)
+#define __NR_io_getevents (__NR_Linux + 202)
+#define __NR_io_submit (__NR_Linux + 203)
+#define __NR_io_cancel (__NR_Linux + 204)
+#define __NR_exit_group (__NR_Linux + 205)
+#define __NR_lookup_dcookie (__NR_Linux + 206)
+#define __NR_epoll_create (__NR_Linux + 207)
+#define __NR_epoll_ctl (__NR_Linux + 208)
+#define __NR_epoll_wait (__NR_Linux + 209)
+#define __NR_remap_file_pages (__NR_Linux + 210)
+#define __NR_rt_sigreturn (__NR_Linux + 211)
+#define __NR_fcntl64 (__NR_Linux + 212)
+#define __NR_set_tid_address (__NR_Linux + 213)
+#define __NR_restart_syscall (__NR_Linux + 214)
+#define __NR_semtimedop (__NR_Linux + 215)
+#define __NR_fadvise64 (__NR_Linux + 216)
+#define __NR_statfs64 (__NR_Linux + 217)
+#define __NR_fstatfs64 (__NR_Linux + 218)
+#define __NR_sendfile64 (__NR_Linux + 219)
+#define __NR_timer_create (__NR_Linux + 220)
+#define __NR_timer_settime (__NR_Linux + 221)
+#define __NR_timer_gettime (__NR_Linux + 222)
+#define __NR_timer_getoverrun (__NR_Linux + 223)
+#define __NR_timer_delete (__NR_Linux + 224)
+#define __NR_clock_settime (__NR_Linux + 225)
+#define __NR_clock_gettime (__NR_Linux + 226)
+#define __NR_clock_getres (__NR_Linux + 227)
+#define __NR_clock_nanosleep (__NR_Linux + 228)
+#define __NR_tgkill (__NR_Linux + 229)
+#define __NR_utimes (__NR_Linux + 230)
+#define __NR_mbind (__NR_Linux + 231)
+#define __NR_get_mempolicy (__NR_Linux + 232)
+#define __NR_set_mempolicy (__NR_Linux + 233)
+#define __NR_mq_open (__NR_Linux + 234)
+#define __NR_mq_unlink (__NR_Linux + 235)
+#define __NR_mq_timedsend (__NR_Linux + 236)
+#define __NR_mq_timedreceive (__NR_Linux + 237)
+#define __NR_mq_notify (__NR_Linux + 238)
+#define __NR_mq_getsetattr (__NR_Linux + 239)
+#define __NR_vserver (__NR_Linux + 240)
+#define __NR_waitid (__NR_Linux + 241)
+#define __NR_add_key (__NR_Linux + 243)
+#define __NR_request_key (__NR_Linux + 244)
+#define __NR_keyctl (__NR_Linux + 245)
+#define __NR_set_thread_area (__NR_Linux + 246)
+#define __NR_inotify_init (__NR_Linux + 247)
+#define __NR_inotify_add_watch (__NR_Linux + 248)
+#define __NR_inotify_rm_watch (__NR_Linux + 249)
+#define __NR_migrate_pages (__NR_Linux + 250)
+#define __NR_openat (__NR_Linux + 251)
+#define __NR_mkdirat (__NR_Linux + 252)
+#define __NR_mknodat (__NR_Linux + 253)
+#define __NR_fchownat (__NR_Linux + 254)
+#define __NR_futimesat (__NR_Linux + 255)
+#define __NR_newfstatat (__NR_Linux + 256)
+#define __NR_unlinkat (__NR_Linux + 257)
+#define __NR_renameat (__NR_Linux + 258)
+#define __NR_linkat (__NR_Linux + 259)
+#define __NR_symlinkat (__NR_Linux + 260)
+#define __NR_readlinkat (__NR_Linux + 261)
+#define __NR_fchmodat (__NR_Linux + 262)
+#define __NR_faccessat (__NR_Linux + 263)
+#define __NR_pselect6 (__NR_Linux + 264)
+#define __NR_ppoll (__NR_Linux + 265)
+#define __NR_unshare (__NR_Linux + 266)
+#define __NR_splice (__NR_Linux + 267)
+#define __NR_sync_file_range (__NR_Linux + 268)
+#define __NR_tee (__NR_Linux + 269)
+#define __NR_vmsplice (__NR_Linux + 270)
+#define __NR_move_pages (__NR_Linux + 271)
+#define __NR_set_robust_list (__NR_Linux + 272)
+#define __NR_get_robust_list (__NR_Linux + 273)
+#define __NR_kexec_load (__NR_Linux + 274)
+#define __NR_getcpu (__NR_Linux + 275)
+#define __NR_epoll_pwait (__NR_Linux + 276)
+#define __NR_ioprio_set (__NR_Linux + 277)
+#define __NR_ioprio_get (__NR_Linux + 278)
+#define __NR_utimensat (__NR_Linux + 279)
+#define __NR_signalfd (__NR_Linux + 280)
+#define __NR_timerfd (__NR_Linux + 281)
+#define __NR_eventfd (__NR_Linux + 282)
+#define __NR_fallocate (__NR_Linux + 283)
+#define __NR_timerfd_create (__NR_Linux + 284)
+#define __NR_timerfd_gettime (__NR_Linux + 285)
+#define __NR_timerfd_settime (__NR_Linux + 286)
+#define __NR_signalfd4 (__NR_Linux + 287)
+#define __NR_eventfd2 (__NR_Linux + 288)
+#define __NR_epoll_create1 (__NR_Linux + 289)
+#define __NR_dup3 (__NR_Linux + 290)
+#define __NR_pipe2 (__NR_Linux + 291)
+#define __NR_inotify_init1 (__NR_Linux + 292)
+#define __NR_preadv (__NR_Linux + 293)
+#define __NR_pwritev (__NR_Linux + 294)
+#define __NR_rt_tgsigqueueinfo (__NR_Linux + 295)
+#define __NR_perf_event_open (__NR_Linux + 296)
+#define __NR_accept4 (__NR_Linux + 297)
+#define __NR_recvmmsg (__NR_Linux + 298)
+#define __NR_getdents64 (__NR_Linux + 299)
+#define __NR_fanotify_init (__NR_Linux + 300)
+#define __NR_fanotify_mark (__NR_Linux + 301)
+#define __NR_prlimit64 (__NR_Linux + 302)
+#define __NR_name_to_handle_at (__NR_Linux + 303)
+#define __NR_open_by_handle_at (__NR_Linux + 304)
+#define __NR_clock_adjtime (__NR_Linux + 305)
+#define __NR_syncfs (__NR_Linux + 306)
+#define __NR_sendmmsg (__NR_Linux + 307)
+#define __NR_setns (__NR_Linux + 308)
+#define __NR_process_vm_readv (__NR_Linux + 309)
+#define __NR_process_vm_writev (__NR_Linux + 310)
+#define __NR_kcmp (__NR_Linux + 311)
+#define __NR_finit_module (__NR_Linux + 312)
+#define __NR_sched_setattr (__NR_Linux + 313)
+#define __NR_sched_getattr (__NR_Linux + 314)
+#define __NR_renameat2 (__NR_Linux + 315)
+#define __NR_seccomp (__NR_Linux + 316)
+#define __NR_getrandom (__NR_Linux + 317)
+#define __NR_memfd_create (__NR_Linux + 318)
+#define __NR_bpf (__NR_Linux + 319)
+#define __NR_execveat (__NR_Linux + 320)
+#define __NR_userfaultfd (__NR_Linux + 321)
+#define __NR_membarrier (__NR_Linux + 322)
+#define __NR_mlock2 (__NR_Linux + 323)
+#define __NR_copy_file_range (__NR_Linux + 324)
+#define __NR_preadv2 (__NR_Linux + 325)
+#define __NR_pwritev2 (__NR_Linux + 326)
+#define __NR_pkey_mprotect (__NR_Linux + 327)
+#define __NR_pkey_alloc (__NR_Linux + 328)
+#define __NR_pkey_free (__NR_Linux + 329)
+#define __NR_statx (__NR_Linux + 330)
+#define __NR_rseq (__NR_Linux + 331)
+#define __NR_io_pgetevents (__NR_Linux + 332)
+
+
+#endif /* _ASM_MIPS_UNISTD_N32_H */
--- /dev/null
+#ifndef _ASM_MIPS_UNISTD_N64_H
+#define _ASM_MIPS_UNISTD_N64_H
+
+#define __NR_read (__NR_Linux + 0)
+#define __NR_write (__NR_Linux + 1)
+#define __NR_open (__NR_Linux + 2)
+#define __NR_close (__NR_Linux + 3)
+#define __NR_stat (__NR_Linux + 4)
+#define __NR_fstat (__NR_Linux + 5)
+#define __NR_lstat (__NR_Linux + 6)
+#define __NR_poll (__NR_Linux + 7)
+#define __NR_lseek (__NR_Linux + 8)
+#define __NR_mmap (__NR_Linux + 9)
+#define __NR_mprotect (__NR_Linux + 10)
+#define __NR_munmap (__NR_Linux + 11)
+#define __NR_brk (__NR_Linux + 12)
+#define __NR_rt_sigaction (__NR_Linux + 13)
+#define __NR_rt_sigprocmask (__NR_Linux + 14)
+#define __NR_ioctl (__NR_Linux + 15)
+#define __NR_pread64 (__NR_Linux + 16)
+#define __NR_pwrite64 (__NR_Linux + 17)
+#define __NR_readv (__NR_Linux + 18)
+#define __NR_writev (__NR_Linux + 19)
+#define __NR_access (__NR_Linux + 20)
+#define __NR_pipe (__NR_Linux + 21)
+#define __NR__newselect (__NR_Linux + 22)
+#define __NR_sched_yield (__NR_Linux + 23)
+#define __NR_mremap (__NR_Linux + 24)
+#define __NR_msync (__NR_Linux + 25)
+#define __NR_mincore (__NR_Linux + 26)
+#define __NR_madvise (__NR_Linux + 27)
+#define __NR_shmget (__NR_Linux + 28)
+#define __NR_shmat (__NR_Linux + 29)
+#define __NR_shmctl (__NR_Linux + 30)
+#define __NR_dup (__NR_Linux + 31)
+#define __NR_dup2 (__NR_Linux + 32)
+#define __NR_pause (__NR_Linux + 33)
+#define __NR_nanosleep (__NR_Linux + 34)
+#define __NR_getitimer (__NR_Linux + 35)
+#define __NR_setitimer (__NR_Linux + 36)
+#define __NR_alarm (__NR_Linux + 37)
+#define __NR_getpid (__NR_Linux + 38)
+#define __NR_sendfile (__NR_Linux + 39)
+#define __NR_socket (__NR_Linux + 40)
+#define __NR_connect (__NR_Linux + 41)
+#define __NR_accept (__NR_Linux + 42)
+#define __NR_sendto (__NR_Linux + 43)
+#define __NR_recvfrom (__NR_Linux + 44)
+#define __NR_sendmsg (__NR_Linux + 45)
+#define __NR_recvmsg (__NR_Linux + 46)
+#define __NR_shutdown (__NR_Linux + 47)
+#define __NR_bind (__NR_Linux + 48)
+#define __NR_listen (__NR_Linux + 49)
+#define __NR_getsockname (__NR_Linux + 50)
+#define __NR_getpeername (__NR_Linux + 51)
+#define __NR_socketpair (__NR_Linux + 52)
+#define __NR_setsockopt (__NR_Linux + 53)
+#define __NR_getsockopt (__NR_Linux + 54)
+#define __NR_clone (__NR_Linux + 55)
+#define __NR_fork (__NR_Linux + 56)
+#define __NR_execve (__NR_Linux + 57)
+#define __NR_exit (__NR_Linux + 58)
+#define __NR_wait4 (__NR_Linux + 59)
+#define __NR_kill (__NR_Linux + 60)
+#define __NR_uname (__NR_Linux + 61)
+#define __NR_semget (__NR_Linux + 62)
+#define __NR_semop (__NR_Linux + 63)
+#define __NR_semctl (__NR_Linux + 64)
+#define __NR_shmdt (__NR_Linux + 65)
+#define __NR_msgget (__NR_Linux + 66)
+#define __NR_msgsnd (__NR_Linux + 67)
+#define __NR_msgrcv (__NR_Linux + 68)
+#define __NR_msgctl (__NR_Linux + 69)
+#define __NR_fcntl (__NR_Linux + 70)
+#define __NR_flock (__NR_Linux + 71)
+#define __NR_fsync (__NR_Linux + 72)
+#define __NR_fdatasync (__NR_Linux + 73)
+#define __NR_truncate (__NR_Linux + 74)
+#define __NR_ftruncate (__NR_Linux + 75)
+#define __NR_getdents (__NR_Linux + 76)
+#define __NR_getcwd (__NR_Linux + 77)
+#define __NR_chdir (__NR_Linux + 78)
+#define __NR_fchdir (__NR_Linux + 79)
+#define __NR_rename (__NR_Linux + 80)
+#define __NR_mkdir (__NR_Linux + 81)
+#define __NR_rmdir (__NR_Linux + 82)
+#define __NR_creat (__NR_Linux + 83)
+#define __NR_link (__NR_Linux + 84)
+#define __NR_unlink (__NR_Linux + 85)
+#define __NR_symlink (__NR_Linux + 86)
+#define __NR_readlink (__NR_Linux + 87)
+#define __NR_chmod (__NR_Linux + 88)
+#define __NR_fchmod (__NR_Linux + 89)
+#define __NR_chown (__NR_Linux + 90)
+#define __NR_fchown (__NR_Linux + 91)
+#define __NR_lchown (__NR_Linux + 92)
+#define __NR_umask (__NR_Linux + 93)
+#define __NR_gettimeofday (__NR_Linux + 94)
+#define __NR_getrlimit (__NR_Linux + 95)
+#define __NR_getrusage (__NR_Linux + 96)
+#define __NR_sysinfo (__NR_Linux + 97)
+#define __NR_times (__NR_Linux + 98)
+#define __NR_ptrace (__NR_Linux + 99)
+#define __NR_getuid (__NR_Linux + 100)
+#define __NR_syslog (__NR_Linux + 101)
+#define __NR_getgid (__NR_Linux + 102)
+#define __NR_setuid (__NR_Linux + 103)
+#define __NR_setgid (__NR_Linux + 104)
+#define __NR_geteuid (__NR_Linux + 105)
+#define __NR_getegid (__NR_Linux + 106)
+#define __NR_setpgid (__NR_Linux + 107)
+#define __NR_getppid (__NR_Linux + 108)
+#define __NR_getpgrp (__NR_Linux + 109)
+#define __NR_setsid (__NR_Linux + 110)
+#define __NR_setreuid (__NR_Linux + 111)
+#define __NR_setregid (__NR_Linux + 112)
+#define __NR_getgroups (__NR_Linux + 113)
+#define __NR_setgroups (__NR_Linux + 114)
+#define __NR_setresuid (__NR_Linux + 115)
+#define __NR_getresuid (__NR_Linux + 116)
+#define __NR_setresgid (__NR_Linux + 117)
+#define __NR_getresgid (__NR_Linux + 118)
+#define __NR_getpgid (__NR_Linux + 119)
+#define __NR_setfsuid (__NR_Linux + 120)
+#define __NR_setfsgid (__NR_Linux + 121)
+#define __NR_getsid (__NR_Linux + 122)
+#define __NR_capget (__NR_Linux + 123)
+#define __NR_capset (__NR_Linux + 124)
+#define __NR_rt_sigpending (__NR_Linux + 125)
+#define __NR_rt_sigtimedwait (__NR_Linux + 126)
+#define __NR_rt_sigqueueinfo (__NR_Linux + 127)
+#define __NR_rt_sigsuspend (__NR_Linux + 128)
+#define __NR_sigaltstack (__NR_Linux + 129)
+#define __NR_utime (__NR_Linux + 130)
+#define __NR_mknod (__NR_Linux + 131)
+#define __NR_personality (__NR_Linux + 132)
+#define __NR_ustat (__NR_Linux + 133)
+#define __NR_statfs (__NR_Linux + 134)
+#define __NR_fstatfs (__NR_Linux + 135)
+#define __NR_sysfs (__NR_Linux + 136)
+#define __NR_getpriority (__NR_Linux + 137)
+#define __NR_setpriority (__NR_Linux + 138)
+#define __NR_sched_setparam (__NR_Linux + 139)
+#define __NR_sched_getparam (__NR_Linux + 140)
+#define __NR_sched_setscheduler (__NR_Linux + 141)
+#define __NR_sched_getscheduler (__NR_Linux + 142)
+#define __NR_sched_get_priority_max (__NR_Linux + 143)
+#define __NR_sched_get_priority_min (__NR_Linux + 144)
+#define __NR_sched_rr_get_interval (__NR_Linux + 145)
+#define __NR_mlock (__NR_Linux + 146)
+#define __NR_munlock (__NR_Linux + 147)
+#define __NR_mlockall (__NR_Linux + 148)
+#define __NR_munlockall (__NR_Linux + 149)
+#define __NR_vhangup (__NR_Linux + 150)
+#define __NR_pivot_root (__NR_Linux + 151)
+#define __NR__sysctl (__NR_Linux + 152)
+#define __NR_prctl (__NR_Linux + 153)
+#define __NR_adjtimex (__NR_Linux + 154)
+#define __NR_setrlimit (__NR_Linux + 155)
+#define __NR_chroot (__NR_Linux + 156)
+#define __NR_sync (__NR_Linux + 157)
+#define __NR_acct (__NR_Linux + 158)
+#define __NR_settimeofday (__NR_Linux + 159)
+#define __NR_mount (__NR_Linux + 160)
+#define __NR_umount2 (__NR_Linux + 161)
+#define __NR_swapon (__NR_Linux + 162)
+#define __NR_swapoff (__NR_Linux + 163)
+#define __NR_reboot (__NR_Linux + 164)
+#define __NR_sethostname (__NR_Linux + 165)
+#define __NR_setdomainname (__NR_Linux + 166)
+#define __NR_create_module (__NR_Linux + 167)
+#define __NR_init_module (__NR_Linux + 168)
+#define __NR_delete_module (__NR_Linux + 169)
+#define __NR_get_kernel_syms (__NR_Linux + 170)
+#define __NR_query_module (__NR_Linux + 171)
+#define __NR_quotactl (__NR_Linux + 172)
+#define __NR_nfsservctl (__NR_Linux + 173)
+#define __NR_getpmsg (__NR_Linux + 174)
+#define __NR_putpmsg (__NR_Linux + 175)
+#define __NR_afs_syscall (__NR_Linux + 176)
+#define __NR_reserved177 (__NR_Linux + 177)
+#define __NR_gettid (__NR_Linux + 178)
+#define __NR_readahead (__NR_Linux + 179)
+#define __NR_setxattr (__NR_Linux + 180)
+#define __NR_lsetxattr (__NR_Linux + 181)
+#define __NR_fsetxattr (__NR_Linux + 182)
+#define __NR_getxattr (__NR_Linux + 183)
+#define __NR_lgetxattr (__NR_Linux + 184)
+#define __NR_fgetxattr (__NR_Linux + 185)
+#define __NR_listxattr (__NR_Linux + 186)
+#define __NR_llistxattr (__NR_Linux + 187)
+#define __NR_flistxattr (__NR_Linux + 188)
+#define __NR_removexattr (__NR_Linux + 189)
+#define __NR_lremovexattr (__NR_Linux + 190)
+#define __NR_fremovexattr (__NR_Linux + 191)
+#define __NR_tkill (__NR_Linux + 192)
+#define __NR_reserved193 (__NR_Linux + 193)
+#define __NR_futex (__NR_Linux + 194)
+#define __NR_sched_setaffinity (__NR_Linux + 195)
+#define __NR_sched_getaffinity (__NR_Linux + 196)
+#define __NR_cacheflush (__NR_Linux + 197)
+#define __NR_cachectl (__NR_Linux + 198)
+#define __NR_sysmips (__NR_Linux + 199)
+#define __NR_io_setup (__NR_Linux + 200)
+#define __NR_io_destroy (__NR_Linux + 201)
+#define __NR_io_getevents (__NR_Linux + 202)
+#define __NR_io_submit (__NR_Linux + 203)
+#define __NR_io_cancel (__NR_Linux + 204)
+#define __NR_exit_group (__NR_Linux + 205)
+#define __NR_lookup_dcookie (__NR_Linux + 206)
+#define __NR_epoll_create (__NR_Linux + 207)
+#define __NR_epoll_ctl (__NR_Linux + 208)
+#define __NR_epoll_wait (__NR_Linux + 209)
+#define __NR_remap_file_pages (__NR_Linux + 210)
+#define __NR_rt_sigreturn (__NR_Linux + 211)
+#define __NR_set_tid_address (__NR_Linux + 212)
+#define __NR_restart_syscall (__NR_Linux + 213)
+#define __NR_semtimedop (__NR_Linux + 214)
+#define __NR_fadvise64 (__NR_Linux + 215)
+#define __NR_timer_create (__NR_Linux + 216)
+#define __NR_timer_settime (__NR_Linux + 217)
+#define __NR_timer_gettime (__NR_Linux + 218)
+#define __NR_timer_getoverrun (__NR_Linux + 219)
+#define __NR_timer_delete (__NR_Linux + 220)
+#define __NR_clock_settime (__NR_Linux + 221)
+#define __NR_clock_gettime (__NR_Linux + 222)
+#define __NR_clock_getres (__NR_Linux + 223)
+#define __NR_clock_nanosleep (__NR_Linux + 224)
+#define __NR_tgkill (__NR_Linux + 225)
+#define __NR_utimes (__NR_Linux + 226)
+#define __NR_mbind (__NR_Linux + 227)
+#define __NR_get_mempolicy (__NR_Linux + 228)
+#define __NR_set_mempolicy (__NR_Linux + 229)
+#define __NR_mq_open (__NR_Linux + 230)
+#define __NR_mq_unlink (__NR_Linux + 231)
+#define __NR_mq_timedsend (__NR_Linux + 232)
+#define __NR_mq_timedreceive (__NR_Linux + 233)
+#define __NR_mq_notify (__NR_Linux + 234)
+#define __NR_mq_getsetattr (__NR_Linux + 235)
+#define __NR_vserver (__NR_Linux + 236)
+#define __NR_waitid (__NR_Linux + 237)
+#define __NR_add_key (__NR_Linux + 239)
+#define __NR_request_key (__NR_Linux + 240)
+#define __NR_keyctl (__NR_Linux + 241)
+#define __NR_set_thread_area (__NR_Linux + 242)
+#define __NR_inotify_init (__NR_Linux + 243)
+#define __NR_inotify_add_watch (__NR_Linux + 244)
+#define __NR_inotify_rm_watch (__NR_Linux + 245)
+#define __NR_migrate_pages (__NR_Linux + 246)
+#define __NR_openat (__NR_Linux + 247)
+#define __NR_mkdirat (__NR_Linux + 248)
+#define __NR_mknodat (__NR_Linux + 249)
+#define __NR_fchownat (__NR_Linux + 250)
+#define __NR_futimesat (__NR_Linux + 251)
+#define __NR_newfstatat (__NR_Linux + 252)
+#define __NR_unlinkat (__NR_Linux + 253)
+#define __NR_renameat (__NR_Linux + 254)
+#define __NR_linkat (__NR_Linux + 255)
+#define __NR_symlinkat (__NR_Linux + 256)
+#define __NR_readlinkat (__NR_Linux + 257)
+#define __NR_fchmodat (__NR_Linux + 258)
+#define __NR_faccessat (__NR_Linux + 259)
+#define __NR_pselect6 (__NR_Linux + 260)
+#define __NR_ppoll (__NR_Linux + 261)
+#define __NR_unshare (__NR_Linux + 262)
+#define __NR_splice (__NR_Linux + 263)
+#define __NR_sync_file_range (__NR_Linux + 264)
+#define __NR_tee (__NR_Linux + 265)
+#define __NR_vmsplice (__NR_Linux + 266)
+#define __NR_move_pages (__NR_Linux + 267)
+#define __NR_set_robust_list (__NR_Linux + 268)
+#define __NR_get_robust_list (__NR_Linux + 269)
+#define __NR_kexec_load (__NR_Linux + 270)
+#define __NR_getcpu (__NR_Linux + 271)
+#define __NR_epoll_pwait (__NR_Linux + 272)
+#define __NR_ioprio_set (__NR_Linux + 273)
+#define __NR_ioprio_get (__NR_Linux + 274)
+#define __NR_utimensat (__NR_Linux + 275)
+#define __NR_signalfd (__NR_Linux + 276)
+#define __NR_timerfd (__NR_Linux + 277)
+#define __NR_eventfd (__NR_Linux + 278)
+#define __NR_fallocate (__NR_Linux + 279)
+#define __NR_timerfd_create (__NR_Linux + 280)
+#define __NR_timerfd_gettime (__NR_Linux + 281)
+#define __NR_timerfd_settime (__NR_Linux + 282)
+#define __NR_signalfd4 (__NR_Linux + 283)
+#define __NR_eventfd2 (__NR_Linux + 284)
+#define __NR_epoll_create1 (__NR_Linux + 285)
+#define __NR_dup3 (__NR_Linux + 286)
+#define __NR_pipe2 (__NR_Linux + 287)
+#define __NR_inotify_init1 (__NR_Linux + 288)
+#define __NR_preadv (__NR_Linux + 289)
+#define __NR_pwritev (__NR_Linux + 290)
+#define __NR_rt_tgsigqueueinfo (__NR_Linux + 291)
+#define __NR_perf_event_open (__NR_Linux + 292)
+#define __NR_accept4 (__NR_Linux + 293)
+#define __NR_recvmmsg (__NR_Linux + 294)
+#define __NR_fanotify_init (__NR_Linux + 295)
+#define __NR_fanotify_mark (__NR_Linux + 296)
+#define __NR_prlimit64 (__NR_Linux + 297)
+#define __NR_name_to_handle_at (__NR_Linux + 298)
+#define __NR_open_by_handle_at (__NR_Linux + 299)
+#define __NR_clock_adjtime (__NR_Linux + 300)
+#define __NR_syncfs (__NR_Linux + 301)
+#define __NR_sendmmsg (__NR_Linux + 302)
+#define __NR_setns (__NR_Linux + 303)
+#define __NR_process_vm_readv (__NR_Linux + 304)
+#define __NR_process_vm_writev (__NR_Linux + 305)
+#define __NR_kcmp (__NR_Linux + 306)
+#define __NR_finit_module (__NR_Linux + 307)
+#define __NR_getdents64 (__NR_Linux + 308)
+#define __NR_sched_setattr (__NR_Linux + 309)
+#define __NR_sched_getattr (__NR_Linux + 310)
+#define __NR_renameat2 (__NR_Linux + 311)
+#define __NR_seccomp (__NR_Linux + 312)
+#define __NR_getrandom (__NR_Linux + 313)
+#define __NR_memfd_create (__NR_Linux + 314)
+#define __NR_bpf (__NR_Linux + 315)
+#define __NR_execveat (__NR_Linux + 316)
+#define __NR_userfaultfd (__NR_Linux + 317)
+#define __NR_membarrier (__NR_Linux + 318)
+#define __NR_mlock2 (__NR_Linux + 319)
+#define __NR_copy_file_range (__NR_Linux + 320)
+#define __NR_preadv2 (__NR_Linux + 321)
+#define __NR_pwritev2 (__NR_Linux + 322)
+#define __NR_pkey_mprotect (__NR_Linux + 323)
+#define __NR_pkey_alloc (__NR_Linux + 324)
+#define __NR_pkey_free (__NR_Linux + 325)
+#define __NR_statx (__NR_Linux + 326)
+#define __NR_rseq (__NR_Linux + 327)
+#define __NR_io_pgetevents (__NR_Linux + 328)
+
+
+#endif /* _ASM_MIPS_UNISTD_N64_H */
--- /dev/null
+#ifndef _ASM_MIPS_UNISTD_O32_H
+#define _ASM_MIPS_UNISTD_O32_H
+
+#define __NR_syscall (__NR_Linux + 0)
+#define __NR_exit (__NR_Linux + 1)
+#define __NR_fork (__NR_Linux + 2)
+#define __NR_read (__NR_Linux + 3)
+#define __NR_write (__NR_Linux + 4)
+#define __NR_open (__NR_Linux + 5)
+#define __NR_close (__NR_Linux + 6)
+#define __NR_waitpid (__NR_Linux + 7)
+#define __NR_creat (__NR_Linux + 8)
+#define __NR_link (__NR_Linux + 9)
+#define __NR_unlink (__NR_Linux + 10)
+#define __NR_execve (__NR_Linux + 11)
+#define __NR_chdir (__NR_Linux + 12)
+#define __NR_time (__NR_Linux + 13)
+#define __NR_mknod (__NR_Linux + 14)
+#define __NR_chmod (__NR_Linux + 15)
+#define __NR_lchown (__NR_Linux + 16)
+#define __NR_break (__NR_Linux + 17)
+#define __NR_unused18 (__NR_Linux + 18)
+#define __NR_lseek (__NR_Linux + 19)
+#define __NR_getpid (__NR_Linux + 20)
+#define __NR_mount (__NR_Linux + 21)
+#define __NR_umount (__NR_Linux + 22)
+#define __NR_setuid (__NR_Linux + 23)
+#define __NR_getuid (__NR_Linux + 24)
+#define __NR_stime (__NR_Linux + 25)
+#define __NR_ptrace (__NR_Linux + 26)
+#define __NR_alarm (__NR_Linux + 27)
+#define __NR_unused28 (__NR_Linux + 28)
+#define __NR_pause (__NR_Linux + 29)
+#define __NR_utime (__NR_Linux + 30)
+#define __NR_stty (__NR_Linux + 31)
+#define __NR_gtty (__NR_Linux + 32)
+#define __NR_access (__NR_Linux + 33)
+#define __NR_nice (__NR_Linux + 34)
+#define __NR_ftime (__NR_Linux + 35)
+#define __NR_sync (__NR_Linux + 36)
+#define __NR_kill (__NR_Linux + 37)
+#define __NR_rename (__NR_Linux + 38)
+#define __NR_mkdir (__NR_Linux + 39)
+#define __NR_rmdir (__NR_Linux + 40)
+#define __NR_dup (__NR_Linux + 41)
+#define __NR_pipe (__NR_Linux + 42)
+#define __NR_times (__NR_Linux + 43)
+#define __NR_prof (__NR_Linux + 44)
+#define __NR_brk (__NR_Linux + 45)
+#define __NR_setgid (__NR_Linux + 46)
+#define __NR_getgid (__NR_Linux + 47)
+#define __NR_signal (__NR_Linux + 48)
+#define __NR_geteuid (__NR_Linux + 49)
+#define __NR_getegid (__NR_Linux + 50)
+#define __NR_acct (__NR_Linux + 51)
+#define __NR_umount2 (__NR_Linux + 52)
+#define __NR_lock (__NR_Linux + 53)
+#define __NR_ioctl (__NR_Linux + 54)
+#define __NR_fcntl (__NR_Linux + 55)
+#define __NR_mpx (__NR_Linux + 56)
+#define __NR_setpgid (__NR_Linux + 57)
+#define __NR_ulimit (__NR_Linux + 58)
+#define __NR_unused59 (__NR_Linux + 59)
+#define __NR_umask (__NR_Linux + 60)
+#define __NR_chroot (__NR_Linux + 61)
+#define __NR_ustat (__NR_Linux + 62)
+#define __NR_dup2 (__NR_Linux + 63)
+#define __NR_getppid (__NR_Linux + 64)
+#define __NR_getpgrp (__NR_Linux + 65)
+#define __NR_setsid (__NR_Linux + 66)
+#define __NR_sigaction (__NR_Linux + 67)
+#define __NR_sgetmask (__NR_Linux + 68)
+#define __NR_ssetmask (__NR_Linux + 69)
+#define __NR_setreuid (__NR_Linux + 70)
+#define __NR_setregid (__NR_Linux + 71)
+#define __NR_sigsuspend (__NR_Linux + 72)
+#define __NR_sigpending (__NR_Linux + 73)
+#define __NR_sethostname (__NR_Linux + 74)
+#define __NR_setrlimit (__NR_Linux + 75)
+#define __NR_getrlimit (__NR_Linux + 76)
+#define __NR_getrusage (__NR_Linux + 77)
+#define __NR_gettimeofday (__NR_Linux + 78)
+#define __NR_settimeofday (__NR_Linux + 79)
+#define __NR_getgroups (__NR_Linux + 80)
+#define __NR_setgroups (__NR_Linux + 81)
+#define __NR_reserved82 (__NR_Linux + 82)
+#define __NR_symlink (__NR_Linux + 83)
+#define __NR_unused84 (__NR_Linux + 84)
+#define __NR_readlink (__NR_Linux + 85)
+#define __NR_uselib (__NR_Linux + 86)
+#define __NR_swapon (__NR_Linux + 87)
+#define __NR_reboot (__NR_Linux + 88)
+#define __NR_readdir (__NR_Linux + 89)
+#define __NR_mmap (__NR_Linux + 90)
+#define __NR_munmap (__NR_Linux + 91)
+#define __NR_truncate (__NR_Linux + 92)
+#define __NR_ftruncate (__NR_Linux + 93)
+#define __NR_fchmod (__NR_Linux + 94)
+#define __NR_fchown (__NR_Linux + 95)
+#define __NR_getpriority (__NR_Linux + 96)
+#define __NR_setpriority (__NR_Linux + 97)
+#define __NR_profil (__NR_Linux + 98)
+#define __NR_statfs (__NR_Linux + 99)
+#define __NR_fstatfs (__NR_Linux + 100)
+#define __NR_ioperm (__NR_Linux + 101)
+#define __NR_socketcall (__NR_Linux + 102)
+#define __NR_syslog (__NR_Linux + 103)
+#define __NR_setitimer (__NR_Linux + 104)
+#define __NR_getitimer (__NR_Linux + 105)
+#define __NR_stat (__NR_Linux + 106)
+#define __NR_lstat (__NR_Linux + 107)
+#define __NR_fstat (__NR_Linux + 108)
+#define __NR_unused109 (__NR_Linux + 109)
+#define __NR_iopl (__NR_Linux + 110)
+#define __NR_vhangup (__NR_Linux + 111)
+#define __NR_idle (__NR_Linux + 112)
+#define __NR_vm86 (__NR_Linux + 113)
+#define __NR_wait4 (__NR_Linux + 114)
+#define __NR_swapoff (__NR_Linux + 115)
+#define __NR_sysinfo (__NR_Linux + 116)
+#define __NR_ipc (__NR_Linux + 117)
+#define __NR_fsync (__NR_Linux + 118)
+#define __NR_sigreturn (__NR_Linux + 119)
+#define __NR_clone (__NR_Linux + 120)
+#define __NR_setdomainname (__NR_Linux + 121)
+#define __NR_uname (__NR_Linux + 122)
+#define __NR_modify_ldt (__NR_Linux + 123)
+#define __NR_adjtimex (__NR_Linux + 124)
+#define __NR_mprotect (__NR_Linux + 125)
+#define __NR_sigprocmask (__NR_Linux + 126)
+#define __NR_create_module (__NR_Linux + 127)
+#define __NR_init_module (__NR_Linux + 128)
+#define __NR_delete_module (__NR_Linux + 129)
+#define __NR_get_kernel_syms (__NR_Linux + 130)
+#define __NR_quotactl (__NR_Linux + 131)
+#define __NR_getpgid (__NR_Linux + 132)
+#define __NR_fchdir (__NR_Linux + 133)
+#define __NR_bdflush (__NR_Linux + 134)
+#define __NR_sysfs (__NR_Linux + 135)
+#define __NR_personality (__NR_Linux + 136)
+#define __NR_afs_syscall (__NR_Linux + 137)
+#define __NR_setfsuid (__NR_Linux + 138)
+#define __NR_setfsgid (__NR_Linux + 139)
+#define __NR__llseek (__NR_Linux + 140)
+#define __NR_getdents (__NR_Linux + 141)
+#define __NR__newselect (__NR_Linux + 142)
+#define __NR_flock (__NR_Linux + 143)
+#define __NR_msync (__NR_Linux + 144)
+#define __NR_readv (__NR_Linux + 145)
+#define __NR_writev (__NR_Linux + 146)
+#define __NR_cacheflush (__NR_Linux + 147)
+#define __NR_cachectl (__NR_Linux + 148)
+#define __NR_sysmips (__NR_Linux + 149)
+#define __NR_unused150 (__NR_Linux + 150)
+#define __NR_getsid (__NR_Linux + 151)
+#define __NR_fdatasync (__NR_Linux + 152)
+#define __NR__sysctl (__NR_Linux + 153)
+#define __NR_mlock (__NR_Linux + 154)
+#define __NR_munlock (__NR_Linux + 155)
+#define __NR_mlockall (__NR_Linux + 156)
+#define __NR_munlockall (__NR_Linux + 157)
+#define __NR_sched_setparam (__NR_Linux + 158)
+#define __NR_sched_getparam (__NR_Linux + 159)
+#define __NR_sched_setscheduler (__NR_Linux + 160)
+#define __NR_sched_getscheduler (__NR_Linux + 161)
+#define __NR_sched_yield (__NR_Linux + 162)
+#define __NR_sched_get_priority_max (__NR_Linux + 163)
+#define __NR_sched_get_priority_min (__NR_Linux + 164)
+#define __NR_sched_rr_get_interval (__NR_Linux + 165)
+#define __NR_nanosleep (__NR_Linux + 166)
+#define __NR_mremap (__NR_Linux + 167)
+#define __NR_accept (__NR_Linux + 168)
+#define __NR_bind (__NR_Linux + 169)
+#define __NR_connect (__NR_Linux + 170)
+#define __NR_getpeername (__NR_Linux + 171)
+#define __NR_getsockname (__NR_Linux + 172)
+#define __NR_getsockopt (__NR_Linux + 173)
+#define __NR_listen (__NR_Linux + 174)
+#define __NR_recv (__NR_Linux + 175)
+#define __NR_recvfrom (__NR_Linux + 176)
+#define __NR_recvmsg (__NR_Linux + 177)
+#define __NR_send (__NR_Linux + 178)
+#define __NR_sendmsg (__NR_Linux + 179)
+#define __NR_sendto (__NR_Linux + 180)
+#define __NR_setsockopt (__NR_Linux + 181)
+#define __NR_shutdown (__NR_Linux + 182)
+#define __NR_socket (__NR_Linux + 183)
+#define __NR_socketpair (__NR_Linux + 184)
+#define __NR_setresuid (__NR_Linux + 185)
+#define __NR_getresuid (__NR_Linux + 186)
+#define __NR_query_module (__NR_Linux + 187)
+#define __NR_poll (__NR_Linux + 188)
+#define __NR_nfsservctl (__NR_Linux + 189)
+#define __NR_setresgid (__NR_Linux + 190)
+#define __NR_getresgid (__NR_Linux + 191)
+#define __NR_prctl (__NR_Linux + 192)
+#define __NR_rt_sigreturn (__NR_Linux + 193)
+#define __NR_rt_sigaction (__NR_Linux + 194)
+#define __NR_rt_sigprocmask (__NR_Linux + 195)
+#define __NR_rt_sigpending (__NR_Linux + 196)
+#define __NR_rt_sigtimedwait (__NR_Linux + 197)
+#define __NR_rt_sigqueueinfo (__NR_Linux + 198)
+#define __NR_rt_sigsuspend (__NR_Linux + 199)
+#define __NR_pread64 (__NR_Linux + 200)
+#define __NR_pwrite64 (__NR_Linux + 201)
+#define __NR_chown (__NR_Linux + 202)
+#define __NR_getcwd (__NR_Linux + 203)
+#define __NR_capget (__NR_Linux + 204)
+#define __NR_capset (__NR_Linux + 205)
+#define __NR_sigaltstack (__NR_Linux + 206)
+#define __NR_sendfile (__NR_Linux + 207)
+#define __NR_getpmsg (__NR_Linux + 208)
+#define __NR_putpmsg (__NR_Linux + 209)
+#define __NR_mmap2 (__NR_Linux + 210)
+#define __NR_truncate64 (__NR_Linux + 211)
+#define __NR_ftruncate64 (__NR_Linux + 212)
+#define __NR_stat64 (__NR_Linux + 213)
+#define __NR_lstat64 (__NR_Linux + 214)
+#define __NR_fstat64 (__NR_Linux + 215)
+#define __NR_pivot_root (__NR_Linux + 216)
+#define __NR_mincore (__NR_Linux + 217)
+#define __NR_madvise (__NR_Linux + 218)
+#define __NR_getdents64 (__NR_Linux + 219)
+#define __NR_fcntl64 (__NR_Linux + 220)
+#define __NR_reserved221 (__NR_Linux + 221)
+#define __NR_gettid (__NR_Linux + 222)
+#define __NR_readahead (__NR_Linux + 223)
+#define __NR_setxattr (__NR_Linux + 224)
+#define __NR_lsetxattr (__NR_Linux + 225)
+#define __NR_fsetxattr (__NR_Linux + 226)
+#define __NR_getxattr (__NR_Linux + 227)
+#define __NR_lgetxattr (__NR_Linux + 228)
+#define __NR_fgetxattr (__NR_Linux + 229)
+#define __NR_listxattr (__NR_Linux + 230)
+#define __NR_llistxattr (__NR_Linux + 231)
+#define __NR_flistxattr (__NR_Linux + 232)
+#define __NR_removexattr (__NR_Linux + 233)
+#define __NR_lremovexattr (__NR_Linux + 234)
+#define __NR_fremovexattr (__NR_Linux + 235)
+#define __NR_tkill (__NR_Linux + 236)
+#define __NR_sendfile64 (__NR_Linux + 237)
+#define __NR_futex (__NR_Linux + 238)
+#define __NR_sched_setaffinity (__NR_Linux + 239)
+#define __NR_sched_getaffinity (__NR_Linux + 240)
+#define __NR_io_setup (__NR_Linux + 241)
+#define __NR_io_destroy (__NR_Linux + 242)
+#define __NR_io_getevents (__NR_Linux + 243)
+#define __NR_io_submit (__NR_Linux + 244)
+#define __NR_io_cancel (__NR_Linux + 245)
+#define __NR_exit_group (__NR_Linux + 246)
+#define __NR_lookup_dcookie (__NR_Linux + 247)
+#define __NR_epoll_create (__NR_Linux + 248)
+#define __NR_epoll_ctl (__NR_Linux + 249)
+#define __NR_epoll_wait (__NR_Linux + 250)
+#define __NR_remap_file_pages (__NR_Linux + 251)
+#define __NR_set_tid_address (__NR_Linux + 252)
+#define __NR_restart_syscall (__NR_Linux + 253)
+#define __NR_fadvise64 (__NR_Linux + 254)
+#define __NR_statfs64 (__NR_Linux + 255)
+#define __NR_fstatfs64 (__NR_Linux + 256)
+#define __NR_timer_create (__NR_Linux + 257)
+#define __NR_timer_settime (__NR_Linux + 258)
+#define __NR_timer_gettime (__NR_Linux + 259)
+#define __NR_timer_getoverrun (__NR_Linux + 260)
+#define __NR_timer_delete (__NR_Linux + 261)
+#define __NR_clock_settime (__NR_Linux + 262)
+#define __NR_clock_gettime (__NR_Linux + 263)
+#define __NR_clock_getres (__NR_Linux + 264)
+#define __NR_clock_nanosleep (__NR_Linux + 265)
+#define __NR_tgkill (__NR_Linux + 266)
+#define __NR_utimes (__NR_Linux + 267)
+#define __NR_mbind (__NR_Linux + 268)
+#define __NR_get_mempolicy (__NR_Linux + 269)
+#define __NR_set_mempolicy (__NR_Linux + 270)
+#define __NR_mq_open (__NR_Linux + 271)
+#define __NR_mq_unlink (__NR_Linux + 272)
+#define __NR_mq_timedsend (__NR_Linux + 273)
+#define __NR_mq_timedreceive (__NR_Linux + 274)
+#define __NR_mq_notify (__NR_Linux + 275)
+#define __NR_mq_getsetattr (__NR_Linux + 276)
+#define __NR_vserver (__NR_Linux + 277)
+#define __NR_waitid (__NR_Linux + 278)
+#define __NR_add_key (__NR_Linux + 280)
+#define __NR_request_key (__NR_Linux + 281)
+#define __NR_keyctl (__NR_Linux + 282)
+#define __NR_set_thread_area (__NR_Linux + 283)
+#define __NR_inotify_init (__NR_Linux + 284)
+#define __NR_inotify_add_watch (__NR_Linux + 285)
+#define __NR_inotify_rm_watch (__NR_Linux + 286)
+#define __NR_migrate_pages (__NR_Linux + 287)
+#define __NR_openat (__NR_Linux + 288)
+#define __NR_mkdirat (__NR_Linux + 289)
+#define __NR_mknodat (__NR_Linux + 290)
+#define __NR_fchownat (__NR_Linux + 291)
+#define __NR_futimesat (__NR_Linux + 292)
+#define __NR_fstatat64 (__NR_Linux + 293)
+#define __NR_unlinkat (__NR_Linux + 294)
+#define __NR_renameat (__NR_Linux + 295)
+#define __NR_linkat (__NR_Linux + 296)
+#define __NR_symlinkat (__NR_Linux + 297)
+#define __NR_readlinkat (__NR_Linux + 298)
+#define __NR_fchmodat (__NR_Linux + 299)
+#define __NR_faccessat (__NR_Linux + 300)
+#define __NR_pselect6 (__NR_Linux + 301)
+#define __NR_ppoll (__NR_Linux + 302)
+#define __NR_unshare (__NR_Linux + 303)
+#define __NR_splice (__NR_Linux + 304)
+#define __NR_sync_file_range (__NR_Linux + 305)
+#define __NR_tee (__NR_Linux + 306)
+#define __NR_vmsplice (__NR_Linux + 307)
+#define __NR_move_pages (__NR_Linux + 308)
+#define __NR_set_robust_list (__NR_Linux + 309)
+#define __NR_get_robust_list (__NR_Linux + 310)
+#define __NR_kexec_load (__NR_Linux + 311)
+#define __NR_getcpu (__NR_Linux + 312)
+#define __NR_epoll_pwait (__NR_Linux + 313)
+#define __NR_ioprio_set (__NR_Linux + 314)
+#define __NR_ioprio_get (__NR_Linux + 315)
+#define __NR_utimensat (__NR_Linux + 316)
+#define __NR_signalfd (__NR_Linux + 317)
+#define __NR_timerfd (__NR_Linux + 318)
+#define __NR_eventfd (__NR_Linux + 319)
+#define __NR_fallocate (__NR_Linux + 320)
+#define __NR_timerfd_create (__NR_Linux + 321)
+#define __NR_timerfd_gettime (__NR_Linux + 322)
+#define __NR_timerfd_settime (__NR_Linux + 323)
+#define __NR_signalfd4 (__NR_Linux + 324)
+#define __NR_eventfd2 (__NR_Linux + 325)
+#define __NR_epoll_create1 (__NR_Linux + 326)
+#define __NR_dup3 (__NR_Linux + 327)
+#define __NR_pipe2 (__NR_Linux + 328)
+#define __NR_inotify_init1 (__NR_Linux + 329)
+#define __NR_preadv (__NR_Linux + 330)
+#define __NR_pwritev (__NR_Linux + 331)
+#define __NR_rt_tgsigqueueinfo (__NR_Linux + 332)
+#define __NR_perf_event_open (__NR_Linux + 333)
+#define __NR_accept4 (__NR_Linux + 334)
+#define __NR_recvmmsg (__NR_Linux + 335)
+#define __NR_fanotify_init (__NR_Linux + 336)
+#define __NR_fanotify_mark (__NR_Linux + 337)
+#define __NR_prlimit64 (__NR_Linux + 338)
+#define __NR_name_to_handle_at (__NR_Linux + 339)
+#define __NR_open_by_handle_at (__NR_Linux + 340)
+#define __NR_clock_adjtime (__NR_Linux + 341)
+#define __NR_syncfs (__NR_Linux + 342)
+#define __NR_sendmmsg (__NR_Linux + 343)
+#define __NR_setns (__NR_Linux + 344)
+#define __NR_process_vm_readv (__NR_Linux + 345)
+#define __NR_process_vm_writev (__NR_Linux + 346)
+#define __NR_kcmp (__NR_Linux + 347)
+#define __NR_finit_module (__NR_Linux + 348)
+#define __NR_sched_setattr (__NR_Linux + 349)
+#define __NR_sched_getattr (__NR_Linux + 350)
+#define __NR_renameat2 (__NR_Linux + 351)
+#define __NR_seccomp (__NR_Linux + 352)
+#define __NR_getrandom (__NR_Linux + 353)
+#define __NR_memfd_create (__NR_Linux + 354)
+#define __NR_bpf (__NR_Linux + 355)
+#define __NR_execveat (__NR_Linux + 356)
+#define __NR_userfaultfd (__NR_Linux + 357)
+#define __NR_membarrier (__NR_Linux + 358)
+#define __NR_mlock2 (__NR_Linux + 359)
+#define __NR_copy_file_range (__NR_Linux + 360)
+#define __NR_preadv2 (__NR_Linux + 361)
+#define __NR_pwritev2 (__NR_Linux + 362)
+#define __NR_pkey_mprotect (__NR_Linux + 363)
+#define __NR_pkey_alloc (__NR_Linux + 364)
+#define __NR_pkey_free (__NR_Linux + 365)
+#define __NR_statx (__NR_Linux + 366)
+#define __NR_rseq (__NR_Linux + 367)
+#define __NR_io_pgetevents (__NR_Linux + 368)
+
+
+#endif /* _ASM_MIPS_UNISTD_O32_H */
#ifndef _ASM_POWERPC_UNISTD_H_
#define _ASM_POWERPC_UNISTD_H_
-
-#define __NR_restart_syscall 0
-#define __NR_exit 1
-#define __NR_fork 2
-#define __NR_read 3
-#define __NR_write 4
-#define __NR_open 5
-#define __NR_close 6
-#define __NR_waitpid 7
-#define __NR_creat 8
-#define __NR_link 9
-#define __NR_unlink 10
-#define __NR_execve 11
-#define __NR_chdir 12
-#define __NR_time 13
-#define __NR_mknod 14
-#define __NR_chmod 15
-#define __NR_lchown 16
-#define __NR_break 17
-#define __NR_oldstat 18
-#define __NR_lseek 19
-#define __NR_getpid 20
-#define __NR_mount 21
-#define __NR_umount 22
-#define __NR_setuid 23
-#define __NR_getuid 24
-#define __NR_stime 25
-#define __NR_ptrace 26
-#define __NR_alarm 27
-#define __NR_oldfstat 28
-#define __NR_pause 29
-#define __NR_utime 30
-#define __NR_stty 31
-#define __NR_gtty 32
-#define __NR_access 33
-#define __NR_nice 34
-#define __NR_ftime 35
-#define __NR_sync 36
-#define __NR_kill 37
-#define __NR_rename 38
-#define __NR_mkdir 39
-#define __NR_rmdir 40
-#define __NR_dup 41
-#define __NR_pipe 42
-#define __NR_times 43
-#define __NR_prof 44
-#define __NR_brk 45
-#define __NR_setgid 46
-#define __NR_getgid 47
-#define __NR_signal 48
-#define __NR_geteuid 49
-#define __NR_getegid 50
-#define __NR_acct 51
-#define __NR_umount2 52
-#define __NR_lock 53
-#define __NR_ioctl 54
-#define __NR_fcntl 55
-#define __NR_mpx 56
-#define __NR_setpgid 57
-#define __NR_ulimit 58
-#define __NR_oldolduname 59
-#define __NR_umask 60
-#define __NR_chroot 61
-#define __NR_ustat 62
-#define __NR_dup2 63
-#define __NR_getppid 64
-#define __NR_getpgrp 65
-#define __NR_setsid 66
-#define __NR_sigaction 67
-#define __NR_sgetmask 68
-#define __NR_ssetmask 69
-#define __NR_setreuid 70
-#define __NR_setregid 71
-#define __NR_sigsuspend 72
-#define __NR_sigpending 73
-#define __NR_sethostname 74
-#define __NR_setrlimit 75
-#define __NR_getrlimit 76
-#define __NR_getrusage 77
-#define __NR_gettimeofday 78
-#define __NR_settimeofday 79
-#define __NR_getgroups 80
-#define __NR_setgroups 81
-#define __NR_select 82
-#define __NR_symlink 83
-#define __NR_oldlstat 84
-#define __NR_readlink 85
-#define __NR_uselib 86
-#define __NR_swapon 87
-#define __NR_reboot 88
-#define __NR_readdir 89
-#define __NR_mmap 90
-#define __NR_munmap 91
-#define __NR_truncate 92
-#define __NR_ftruncate 93
-#define __NR_fchmod 94
-#define __NR_fchown 95
-#define __NR_getpriority 96
-#define __NR_setpriority 97
-#define __NR_profil 98
-#define __NR_statfs 99
-#define __NR_fstatfs 100
-#define __NR_ioperm 101
-#define __NR_socketcall 102
-#define __NR_syslog 103
-#define __NR_setitimer 104
-#define __NR_getitimer 105
-#define __NR_stat 106
-#define __NR_lstat 107
-#define __NR_fstat 108
-#define __NR_olduname 109
-#define __NR_iopl 110
-#define __NR_vhangup 111
-#define __NR_idle 112
-#define __NR_vm86 113
-#define __NR_wait4 114
-#define __NR_swapoff 115
-#define __NR_sysinfo 116
-#define __NR_ipc 117
-#define __NR_fsync 118
-#define __NR_sigreturn 119
-#define __NR_clone 120
-#define __NR_setdomainname 121
-#define __NR_uname 122
-#define __NR_modify_ldt 123
-#define __NR_adjtimex 124
-#define __NR_mprotect 125
-#define __NR_sigprocmask 126
-#define __NR_create_module 127
-#define __NR_init_module 128
-#define __NR_delete_module 129
-#define __NR_get_kernel_syms 130
-#define __NR_quotactl 131
-#define __NR_getpgid 132
-#define __NR_fchdir 133
-#define __NR_bdflush 134
-#define __NR_sysfs 135
-#define __NR_personality 136
-#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
-#define __NR_setfsuid 138
-#define __NR_setfsgid 139
-#define __NR__llseek 140
-#define __NR_getdents 141
-#define __NR__newselect 142
-#define __NR_flock 143
-#define __NR_msync 144
-#define __NR_readv 145
-#define __NR_writev 146
-#define __NR_getsid 147
-#define __NR_fdatasync 148
-#define __NR__sysctl 149
-#define __NR_mlock 150
-#define __NR_munlock 151
-#define __NR_mlockall 152
-#define __NR_munlockall 153
-#define __NR_sched_setparam 154
-#define __NR_sched_getparam 155
-#define __NR_sched_setscheduler 156
-#define __NR_sched_getscheduler 157
-#define __NR_sched_yield 158
-#define __NR_sched_get_priority_max 159
-#define __NR_sched_get_priority_min 160
-#define __NR_sched_rr_get_interval 161
-#define __NR_nanosleep 162
-#define __NR_mremap 163
-#define __NR_setresuid 164
-#define __NR_getresuid 165
-#define __NR_query_module 166
-#define __NR_poll 167
-#define __NR_nfsservctl 168
-#define __NR_setresgid 169
-#define __NR_getresgid 170
-#define __NR_prctl 171
-#define __NR_rt_sigreturn 172
-#define __NR_rt_sigaction 173
-#define __NR_rt_sigprocmask 174
-#define __NR_rt_sigpending 175
-#define __NR_rt_sigtimedwait 176
-#define __NR_rt_sigqueueinfo 177
-#define __NR_rt_sigsuspend 178
-#define __NR_pread64 179
-#define __NR_pwrite64 180
-#define __NR_chown 181
-#define __NR_getcwd 182
-#define __NR_capget 183
-#define __NR_capset 184
-#define __NR_sigaltstack 185
-#define __NR_sendfile 186
-#define __NR_getpmsg 187 /* some people actually want streams */
-#define __NR_putpmsg 188 /* some people actually want streams */
-#define __NR_vfork 189
-#define __NR_ugetrlimit 190 /* SuS compliant getrlimit */
-#define __NR_readahead 191
-#ifndef __powerpc64__ /* these are 32-bit only */
-#define __NR_mmap2 192
-#define __NR_truncate64 193
-#define __NR_ftruncate64 194
-#define __NR_stat64 195
-#define __NR_lstat64 196
-#define __NR_fstat64 197
-#endif
-#define __NR_pciconfig_read 198
-#define __NR_pciconfig_write 199
-#define __NR_pciconfig_iobase 200
-#define __NR_multiplexer 201
-#define __NR_getdents64 202
-#define __NR_pivot_root 203
-#ifndef __powerpc64__
-#define __NR_fcntl64 204
-#endif
-#define __NR_madvise 205
-#define __NR_mincore 206
-#define __NR_gettid 207
-#define __NR_tkill 208
-#define __NR_setxattr 209
-#define __NR_lsetxattr 210
-#define __NR_fsetxattr 211
-#define __NR_getxattr 212
-#define __NR_lgetxattr 213
-#define __NR_fgetxattr 214
-#define __NR_listxattr 215
-#define __NR_llistxattr 216
-#define __NR_flistxattr 217
-#define __NR_removexattr 218
-#define __NR_lremovexattr 219
-#define __NR_fremovexattr 220
-#define __NR_futex 221
-#define __NR_sched_setaffinity 222
-#define __NR_sched_getaffinity 223
-/* 224 currently unused */
-#define __NR_tuxcall 225
#ifndef __powerpc64__
-#define __NR_sendfile64 226
-#endif
-#define __NR_io_setup 227
-#define __NR_io_destroy 228
-#define __NR_io_getevents 229
-#define __NR_io_submit 230
-#define __NR_io_cancel 231
-#define __NR_set_tid_address 232
-#define __NR_fadvise64 233
-#define __NR_exit_group 234
-#define __NR_lookup_dcookie 235
-#define __NR_epoll_create 236
-#define __NR_epoll_ctl 237
-#define __NR_epoll_wait 238
-#define __NR_remap_file_pages 239
-#define __NR_timer_create 240
-#define __NR_timer_settime 241
-#define __NR_timer_gettime 242
-#define __NR_timer_getoverrun 243
-#define __NR_timer_delete 244
-#define __NR_clock_settime 245
-#define __NR_clock_gettime 246
-#define __NR_clock_getres 247
-#define __NR_clock_nanosleep 248
-#define __NR_swapcontext 249
-#define __NR_tgkill 250
-#define __NR_utimes 251
-#define __NR_statfs64 252
-#define __NR_fstatfs64 253
-#ifndef __powerpc64__
-#define __NR_fadvise64_64 254
-#endif
-#define __NR_rtas 255
-#define __NR_sys_debug_setcontext 256
-/* Number 257 is reserved for vserver */
-#define __NR_migrate_pages 258
-#define __NR_mbind 259
-#define __NR_get_mempolicy 260
-#define __NR_set_mempolicy 261
-#define __NR_mq_open 262
-#define __NR_mq_unlink 263
-#define __NR_mq_timedsend 264
-#define __NR_mq_timedreceive 265
-#define __NR_mq_notify 266
-#define __NR_mq_getsetattr 267
-#define __NR_kexec_load 268
-#define __NR_add_key 269
-#define __NR_request_key 270
-#define __NR_keyctl 271
-#define __NR_waitid 272
-#define __NR_ioprio_set 273
-#define __NR_ioprio_get 274
-#define __NR_inotify_init 275
-#define __NR_inotify_add_watch 276
-#define __NR_inotify_rm_watch 277
-#define __NR_spu_run 278
-#define __NR_spu_create 279
-#define __NR_pselect6 280
-#define __NR_ppoll 281
-#define __NR_unshare 282
-#define __NR_splice 283
-#define __NR_tee 284
-#define __NR_vmsplice 285
-#define __NR_openat 286
-#define __NR_mkdirat 287
-#define __NR_mknodat 288
-#define __NR_fchownat 289
-#define __NR_futimesat 290
-#ifdef __powerpc64__
-#define __NR_newfstatat 291
+#include <asm/unistd_32.h>
#else
-#define __NR_fstatat64 291
+#include <asm/unistd_64.h>
#endif
-#define __NR_unlinkat 292
-#define __NR_renameat 293
-#define __NR_linkat 294
-#define __NR_symlinkat 295
-#define __NR_readlinkat 296
-#define __NR_fchmodat 297
-#define __NR_faccessat 298
-#define __NR_get_robust_list 299
-#define __NR_set_robust_list 300
-#define __NR_move_pages 301
-#define __NR_getcpu 302
-#define __NR_epoll_pwait 303
-#define __NR_utimensat 304
-#define __NR_signalfd 305
-#define __NR_timerfd_create 306
-#define __NR_eventfd 307
-#define __NR_sync_file_range2 308
-#define __NR_fallocate 309
-#define __NR_subpage_prot 310
-#define __NR_timerfd_settime 311
-#define __NR_timerfd_gettime 312
-#define __NR_signalfd4 313
-#define __NR_eventfd2 314
-#define __NR_epoll_create1 315
-#define __NR_dup3 316
-#define __NR_pipe2 317
-#define __NR_inotify_init1 318
-#define __NR_perf_event_open 319
-#define __NR_preadv 320
-#define __NR_pwritev 321
-#define __NR_rt_tgsigqueueinfo 322
-#define __NR_fanotify_init 323
-#define __NR_fanotify_mark 324
-#define __NR_prlimit64 325
-#define __NR_socket 326
-#define __NR_bind 327
-#define __NR_connect 328
-#define __NR_listen 329
-#define __NR_accept 330
-#define __NR_getsockname 331
-#define __NR_getpeername 332
-#define __NR_socketpair 333
-#define __NR_send 334
-#define __NR_sendto 335
-#define __NR_recv 336
-#define __NR_recvfrom 337
-#define __NR_shutdown 338
-#define __NR_setsockopt 339
-#define __NR_getsockopt 340
-#define __NR_sendmsg 341
-#define __NR_recvmsg 342
-#define __NR_recvmmsg 343
-#define __NR_accept4 344
-#define __NR_name_to_handle_at 345
-#define __NR_open_by_handle_at 346
-#define __NR_clock_adjtime 347
-#define __NR_syncfs 348
-#define __NR_sendmmsg 349
-#define __NR_setns 350
-#define __NR_process_vm_readv 351
-#define __NR_process_vm_writev 352
-#define __NR_finit_module 353
-#define __NR_kcmp 354
-#define __NR_sched_setattr 355
-#define __NR_sched_getattr 356
-#define __NR_renameat2 357
-#define __NR_seccomp 358
-#define __NR_getrandom 359
-#define __NR_memfd_create 360
-#define __NR_bpf 361
-#define __NR_execveat 362
-#define __NR_switch_endian 363
-#define __NR_userfaultfd 364
-#define __NR_membarrier 365
-#define __NR_mlock2 378
-#define __NR_copy_file_range 379
-#define __NR_preadv2 380
-#define __NR_pwritev2 381
-#define __NR_kexec_file_load 382
-#define __NR_statx 383
-#define __NR_pkey_alloc 384
-#define __NR_pkey_free 385
-#define __NR_pkey_mprotect 386
-#define __NR_rseq 387
-#define __NR_io_pgetevents 388
#endif /* _ASM_POWERPC_UNISTD_H_ */
--- /dev/null
+#ifndef _ASM_POWERPC_UNISTD_32_H
+#define _ASM_POWERPC_UNISTD_32_H
+
+#define __NR_restart_syscall 0
+#define __NR_exit 1
+#define __NR_fork 2
+#define __NR_read 3
+#define __NR_write 4
+#define __NR_open 5
+#define __NR_close 6
+#define __NR_waitpid 7
+#define __NR_creat 8
+#define __NR_link 9
+#define __NR_unlink 10
+#define __NR_execve 11
+#define __NR_chdir 12
+#define __NR_time 13
+#define __NR_mknod 14
+#define __NR_chmod 15
+#define __NR_lchown 16
+#define __NR_break 17
+#define __NR_oldstat 18
+#define __NR_lseek 19
+#define __NR_getpid 20
+#define __NR_mount 21
+#define __NR_umount 22
+#define __NR_setuid 23
+#define __NR_getuid 24
+#define __NR_stime 25
+#define __NR_ptrace 26
+#define __NR_alarm 27
+#define __NR_oldfstat 28
+#define __NR_pause 29
+#define __NR_utime 30
+#define __NR_stty 31
+#define __NR_gtty 32
+#define __NR_access 33
+#define __NR_nice 34
+#define __NR_ftime 35
+#define __NR_sync 36
+#define __NR_kill 37
+#define __NR_rename 38
+#define __NR_mkdir 39
+#define __NR_rmdir 40
+#define __NR_dup 41
+#define __NR_pipe 42
+#define __NR_times 43
+#define __NR_prof 44
+#define __NR_brk 45
+#define __NR_setgid 46
+#define __NR_getgid 47
+#define __NR_signal 48
+#define __NR_geteuid 49
+#define __NR_getegid 50
+#define __NR_acct 51
+#define __NR_umount2 52
+#define __NR_lock 53
+#define __NR_ioctl 54
+#define __NR_fcntl 55
+#define __NR_mpx 56
+#define __NR_setpgid 57
+#define __NR_ulimit 58
+#define __NR_oldolduname 59
+#define __NR_umask 60
+#define __NR_chroot 61
+#define __NR_ustat 62
+#define __NR_dup2 63
+#define __NR_getppid 64
+#define __NR_getpgrp 65
+#define __NR_setsid 66
+#define __NR_sigaction 67
+#define __NR_sgetmask 68
+#define __NR_ssetmask 69
+#define __NR_setreuid 70
+#define __NR_setregid 71
+#define __NR_sigsuspend 72
+#define __NR_sigpending 73
+#define __NR_sethostname 74
+#define __NR_setrlimit 75
+#define __NR_getrlimit 76
+#define __NR_getrusage 77
+#define __NR_gettimeofday 78
+#define __NR_settimeofday 79
+#define __NR_getgroups 80
+#define __NR_setgroups 81
+#define __NR_select 82
+#define __NR_symlink 83
+#define __NR_oldlstat 84
+#define __NR_readlink 85
+#define __NR_uselib 86
+#define __NR_swapon 87
+#define __NR_reboot 88
+#define __NR_readdir 89
+#define __NR_mmap 90
+#define __NR_munmap 91
+#define __NR_truncate 92
+#define __NR_ftruncate 93
+#define __NR_fchmod 94
+#define __NR_fchown 95
+#define __NR_getpriority 96
+#define __NR_setpriority 97
+#define __NR_profil 98
+#define __NR_statfs 99
+#define __NR_fstatfs 100
+#define __NR_ioperm 101
+#define __NR_socketcall 102
+#define __NR_syslog 103
+#define __NR_setitimer 104
+#define __NR_getitimer 105
+#define __NR_stat 106
+#define __NR_lstat 107
+#define __NR_fstat 108
+#define __NR_olduname 109
+#define __NR_iopl 110
+#define __NR_vhangup 111
+#define __NR_idle 112
+#define __NR_vm86 113
+#define __NR_wait4 114
+#define __NR_swapoff 115
+#define __NR_sysinfo 116
+#define __NR_ipc 117
+#define __NR_fsync 118
+#define __NR_sigreturn 119
+#define __NR_clone 120
+#define __NR_setdomainname 121
+#define __NR_uname 122
+#define __NR_modify_ldt 123
+#define __NR_adjtimex 124
+#define __NR_mprotect 125
+#define __NR_sigprocmask 126
+#define __NR_create_module 127
+#define __NR_init_module 128
+#define __NR_delete_module 129
+#define __NR_get_kernel_syms 130
+#define __NR_quotactl 131
+#define __NR_getpgid 132
+#define __NR_fchdir 133
+#define __NR_bdflush 134
+#define __NR_sysfs 135
+#define __NR_personality 136
+#define __NR_afs_syscall 137
+#define __NR_setfsuid 138
+#define __NR_setfsgid 139
+#define __NR__llseek 140
+#define __NR_getdents 141
+#define __NR__newselect 142
+#define __NR_flock 143
+#define __NR_msync 144
+#define __NR_readv 145
+#define __NR_writev 146
+#define __NR_getsid 147
+#define __NR_fdatasync 148
+#define __NR__sysctl 149
+#define __NR_mlock 150
+#define __NR_munlock 151
+#define __NR_mlockall 152
+#define __NR_munlockall 153
+#define __NR_sched_setparam 154
+#define __NR_sched_getparam 155
+#define __NR_sched_setscheduler 156
+#define __NR_sched_getscheduler 157
+#define __NR_sched_yield 158
+#define __NR_sched_get_priority_max 159
+#define __NR_sched_get_priority_min 160
+#define __NR_sched_rr_get_interval 161
+#define __NR_nanosleep 162
+#define __NR_mremap 163
+#define __NR_setresuid 164
+#define __NR_getresuid 165
+#define __NR_query_module 166
+#define __NR_poll 167
+#define __NR_nfsservctl 168
+#define __NR_setresgid 169
+#define __NR_getresgid 170
+#define __NR_prctl 171
+#define __NR_rt_sigreturn 172
+#define __NR_rt_sigaction 173
+#define __NR_rt_sigprocmask 174
+#define __NR_rt_sigpending 175
+#define __NR_rt_sigtimedwait 176
+#define __NR_rt_sigqueueinfo 177
+#define __NR_rt_sigsuspend 178
+#define __NR_pread64 179
+#define __NR_pwrite64 180
+#define __NR_chown 181
+#define __NR_getcwd 182
+#define __NR_capget 183
+#define __NR_capset 184
+#define __NR_sigaltstack 185
+#define __NR_sendfile 186
+#define __NR_getpmsg 187
+#define __NR_putpmsg 188
+#define __NR_vfork 189
+#define __NR_ugetrlimit 190
+#define __NR_readahead 191
+#define __NR_mmap2 192
+#define __NR_truncate64 193
+#define __NR_ftruncate64 194
+#define __NR_stat64 195
+#define __NR_lstat64 196
+#define __NR_fstat64 197
+#define __NR_pciconfig_read 198
+#define __NR_pciconfig_write 199
+#define __NR_pciconfig_iobase 200
+#define __NR_multiplexer 201
+#define __NR_getdents64 202
+#define __NR_pivot_root 203
+#define __NR_fcntl64 204
+#define __NR_madvise 205
+#define __NR_mincore 206
+#define __NR_gettid 207
+#define __NR_tkill 208
+#define __NR_setxattr 209
+#define __NR_lsetxattr 210
+#define __NR_fsetxattr 211
+#define __NR_getxattr 212
+#define __NR_lgetxattr 213
+#define __NR_fgetxattr 214
+#define __NR_listxattr 215
+#define __NR_llistxattr 216
+#define __NR_flistxattr 217
+#define __NR_removexattr 218
+#define __NR_lremovexattr 219
+#define __NR_fremovexattr 220
+#define __NR_futex 221
+#define __NR_sched_setaffinity 222
+#define __NR_sched_getaffinity 223
+#define __NR_tuxcall 225
+#define __NR_sendfile64 226
+#define __NR_io_setup 227
+#define __NR_io_destroy 228
+#define __NR_io_getevents 229
+#define __NR_io_submit 230
+#define __NR_io_cancel 231
+#define __NR_set_tid_address 232
+#define __NR_fadvise64 233
+#define __NR_exit_group 234
+#define __NR_lookup_dcookie 235
+#define __NR_epoll_create 236
+#define __NR_epoll_ctl 237
+#define __NR_epoll_wait 238
+#define __NR_remap_file_pages 239
+#define __NR_timer_create 240
+#define __NR_timer_settime 241
+#define __NR_timer_gettime 242
+#define __NR_timer_getoverrun 243
+#define __NR_timer_delete 244
+#define __NR_clock_settime 245
+#define __NR_clock_gettime 246
+#define __NR_clock_getres 247
+#define __NR_clock_nanosleep 248
+#define __NR_swapcontext 249
+#define __NR_tgkill 250
+#define __NR_utimes 251
+#define __NR_statfs64 252
+#define __NR_fstatfs64 253
+#define __NR_fadvise64_64 254
+#define __NR_rtas 255
+#define __NR_sys_debug_setcontext 256
+#define __NR_migrate_pages 258
+#define __NR_mbind 259
+#define __NR_get_mempolicy 260
+#define __NR_set_mempolicy 261
+#define __NR_mq_open 262
+#define __NR_mq_unlink 263
+#define __NR_mq_timedsend 264
+#define __NR_mq_timedreceive 265
+#define __NR_mq_notify 266
+#define __NR_mq_getsetattr 267
+#define __NR_kexec_load 268
+#define __NR_add_key 269
+#define __NR_request_key 270
+#define __NR_keyctl 271
+#define __NR_waitid 272
+#define __NR_ioprio_set 273
+#define __NR_ioprio_get 274
+#define __NR_inotify_init 275
+#define __NR_inotify_add_watch 276
+#define __NR_inotify_rm_watch 277
+#define __NR_spu_run 278
+#define __NR_spu_create 279
+#define __NR_pselect6 280
+#define __NR_ppoll 281
+#define __NR_unshare 282
+#define __NR_splice 283
+#define __NR_tee 284
+#define __NR_vmsplice 285
+#define __NR_openat 286
+#define __NR_mkdirat 287
+#define __NR_mknodat 288
+#define __NR_fchownat 289
+#define __NR_futimesat 290
+#define __NR_fstatat64 291
+#define __NR_unlinkat 292
+#define __NR_renameat 293
+#define __NR_linkat 294
+#define __NR_symlinkat 295
+#define __NR_readlinkat 296
+#define __NR_fchmodat 297
+#define __NR_faccessat 298
+#define __NR_get_robust_list 299
+#define __NR_set_robust_list 300
+#define __NR_move_pages 301
+#define __NR_getcpu 302
+#define __NR_epoll_pwait 303
+#define __NR_utimensat 304
+#define __NR_signalfd 305
+#define __NR_timerfd_create 306
+#define __NR_eventfd 307
+#define __NR_sync_file_range2 308
+#define __NR_fallocate 309
+#define __NR_subpage_prot 310
+#define __NR_timerfd_settime 311
+#define __NR_timerfd_gettime 312
+#define __NR_signalfd4 313
+#define __NR_eventfd2 314
+#define __NR_epoll_create1 315
+#define __NR_dup3 316
+#define __NR_pipe2 317
+#define __NR_inotify_init1 318
+#define __NR_perf_event_open 319
+#define __NR_preadv 320
+#define __NR_pwritev 321
+#define __NR_rt_tgsigqueueinfo 322
+#define __NR_fanotify_init 323
+#define __NR_fanotify_mark 324
+#define __NR_prlimit64 325
+#define __NR_socket 326
+#define __NR_bind 327
+#define __NR_connect 328
+#define __NR_listen 329
+#define __NR_accept 330
+#define __NR_getsockname 331
+#define __NR_getpeername 332
+#define __NR_socketpair 333
+#define __NR_send 334
+#define __NR_sendto 335
+#define __NR_recv 336
+#define __NR_recvfrom 337
+#define __NR_shutdown 338
+#define __NR_setsockopt 339
+#define __NR_getsockopt 340
+#define __NR_sendmsg 341
+#define __NR_recvmsg 342
+#define __NR_recvmmsg 343
+#define __NR_accept4 344
+#define __NR_name_to_handle_at 345
+#define __NR_open_by_handle_at 346
+#define __NR_clock_adjtime 347
+#define __NR_syncfs 348
+#define __NR_sendmmsg 349
+#define __NR_setns 350
+#define __NR_process_vm_readv 351
+#define __NR_process_vm_writev 352
+#define __NR_finit_module 353
+#define __NR_kcmp 354
+#define __NR_sched_setattr 355
+#define __NR_sched_getattr 356
+#define __NR_renameat2 357
+#define __NR_seccomp 358
+#define __NR_getrandom 359
+#define __NR_memfd_create 360
+#define __NR_bpf 361
+#define __NR_execveat 362
+#define __NR_switch_endian 363
+#define __NR_userfaultfd 364
+#define __NR_membarrier 365
+#define __NR_mlock2 378
+#define __NR_copy_file_range 379
+#define __NR_preadv2 380
+#define __NR_pwritev2 381
+#define __NR_kexec_file_load 382
+#define __NR_statx 383
+#define __NR_pkey_alloc 384
+#define __NR_pkey_free 385
+#define __NR_pkey_mprotect 386
+#define __NR_rseq 387
+#define __NR_io_pgetevents 388
+
+
+#endif /* _ASM_POWERPC_UNISTD_32_H */
--- /dev/null
+#ifndef _ASM_POWERPC_UNISTD_64_H
+#define _ASM_POWERPC_UNISTD_64_H
+
+#define __NR_restart_syscall 0
+#define __NR_exit 1
+#define __NR_fork 2
+#define __NR_read 3
+#define __NR_write 4
+#define __NR_open 5
+#define __NR_close 6
+#define __NR_waitpid 7
+#define __NR_creat 8
+#define __NR_link 9
+#define __NR_unlink 10
+#define __NR_execve 11
+#define __NR_chdir 12
+#define __NR_time 13
+#define __NR_mknod 14
+#define __NR_chmod 15
+#define __NR_lchown 16
+#define __NR_break 17
+#define __NR_oldstat 18
+#define __NR_lseek 19
+#define __NR_getpid 20
+#define __NR_mount 21
+#define __NR_umount 22
+#define __NR_setuid 23
+#define __NR_getuid 24
+#define __NR_stime 25
+#define __NR_ptrace 26
+#define __NR_alarm 27
+#define __NR_oldfstat 28
+#define __NR_pause 29
+#define __NR_utime 30
+#define __NR_stty 31
+#define __NR_gtty 32
+#define __NR_access 33
+#define __NR_nice 34
+#define __NR_ftime 35
+#define __NR_sync 36
+#define __NR_kill 37
+#define __NR_rename 38
+#define __NR_mkdir 39
+#define __NR_rmdir 40
+#define __NR_dup 41
+#define __NR_pipe 42
+#define __NR_times 43
+#define __NR_prof 44
+#define __NR_brk 45
+#define __NR_setgid 46
+#define __NR_getgid 47
+#define __NR_signal 48
+#define __NR_geteuid 49
+#define __NR_getegid 50
+#define __NR_acct 51
+#define __NR_umount2 52
+#define __NR_lock 53
+#define __NR_ioctl 54
+#define __NR_fcntl 55
+#define __NR_mpx 56
+#define __NR_setpgid 57
+#define __NR_ulimit 58
+#define __NR_oldolduname 59
+#define __NR_umask 60
+#define __NR_chroot 61
+#define __NR_ustat 62
+#define __NR_dup2 63
+#define __NR_getppid 64
+#define __NR_getpgrp 65
+#define __NR_setsid 66
+#define __NR_sigaction 67
+#define __NR_sgetmask 68
+#define __NR_ssetmask 69
+#define __NR_setreuid 70
+#define __NR_setregid 71
+#define __NR_sigsuspend 72
+#define __NR_sigpending 73
+#define __NR_sethostname 74
+#define __NR_setrlimit 75
+#define __NR_getrlimit 76
+#define __NR_getrusage 77
+#define __NR_gettimeofday 78
+#define __NR_settimeofday 79
+#define __NR_getgroups 80
+#define __NR_setgroups 81
+#define __NR_select 82
+#define __NR_symlink 83
+#define __NR_oldlstat 84
+#define __NR_readlink 85
+#define __NR_uselib 86
+#define __NR_swapon 87
+#define __NR_reboot 88
+#define __NR_readdir 89
+#define __NR_mmap 90
+#define __NR_munmap 91
+#define __NR_truncate 92
+#define __NR_ftruncate 93
+#define __NR_fchmod 94
+#define __NR_fchown 95
+#define __NR_getpriority 96
+#define __NR_setpriority 97
+#define __NR_profil 98
+#define __NR_statfs 99
+#define __NR_fstatfs 100
+#define __NR_ioperm 101
+#define __NR_socketcall 102
+#define __NR_syslog 103
+#define __NR_setitimer 104
+#define __NR_getitimer 105
+#define __NR_stat 106
+#define __NR_lstat 107
+#define __NR_fstat 108
+#define __NR_olduname 109
+#define __NR_iopl 110
+#define __NR_vhangup 111
+#define __NR_idle 112
+#define __NR_vm86 113
+#define __NR_wait4 114
+#define __NR_swapoff 115
+#define __NR_sysinfo 116
+#define __NR_ipc 117
+#define __NR_fsync 118
+#define __NR_sigreturn 119
+#define __NR_clone 120
+#define __NR_setdomainname 121
+#define __NR_uname 122
+#define __NR_modify_ldt 123
+#define __NR_adjtimex 124
+#define __NR_mprotect 125
+#define __NR_sigprocmask 126
+#define __NR_create_module 127
+#define __NR_init_module 128
+#define __NR_delete_module 129
+#define __NR_get_kernel_syms 130
+#define __NR_quotactl 131
+#define __NR_getpgid 132
+#define __NR_fchdir 133
+#define __NR_bdflush 134
+#define __NR_sysfs 135
+#define __NR_personality 136
+#define __NR_afs_syscall 137
+#define __NR_setfsuid 138
+#define __NR_setfsgid 139
+#define __NR__llseek 140
+#define __NR_getdents 141
+#define __NR__newselect 142
+#define __NR_flock 143
+#define __NR_msync 144
+#define __NR_readv 145
+#define __NR_writev 146
+#define __NR_getsid 147
+#define __NR_fdatasync 148
+#define __NR__sysctl 149
+#define __NR_mlock 150
+#define __NR_munlock 151
+#define __NR_mlockall 152
+#define __NR_munlockall 153
+#define __NR_sched_setparam 154
+#define __NR_sched_getparam 155
+#define __NR_sched_setscheduler 156
+#define __NR_sched_getscheduler 157
+#define __NR_sched_yield 158
+#define __NR_sched_get_priority_max 159
+#define __NR_sched_get_priority_min 160
+#define __NR_sched_rr_get_interval 161
+#define __NR_nanosleep 162
+#define __NR_mremap 163
+#define __NR_setresuid 164
+#define __NR_getresuid 165
+#define __NR_query_module 166
+#define __NR_poll 167
+#define __NR_nfsservctl 168
+#define __NR_setresgid 169
+#define __NR_getresgid 170
+#define __NR_prctl 171
+#define __NR_rt_sigreturn 172
+#define __NR_rt_sigaction 173
+#define __NR_rt_sigprocmask 174
+#define __NR_rt_sigpending 175
+#define __NR_rt_sigtimedwait 176
+#define __NR_rt_sigqueueinfo 177
+#define __NR_rt_sigsuspend 178
+#define __NR_pread64 179
+#define __NR_pwrite64 180
+#define __NR_chown 181
+#define __NR_getcwd 182
+#define __NR_capget 183
+#define __NR_capset 184
+#define __NR_sigaltstack 185
+#define __NR_sendfile 186
+#define __NR_getpmsg 187
+#define __NR_putpmsg 188
+#define __NR_vfork 189
+#define __NR_ugetrlimit 190
+#define __NR_readahead 191
+#define __NR_pciconfig_read 198
+#define __NR_pciconfig_write 199
+#define __NR_pciconfig_iobase 200
+#define __NR_multiplexer 201
+#define __NR_getdents64 202
+#define __NR_pivot_root 203
+#define __NR_madvise 205
+#define __NR_mincore 206
+#define __NR_gettid 207
+#define __NR_tkill 208
+#define __NR_setxattr 209
+#define __NR_lsetxattr 210
+#define __NR_fsetxattr 211
+#define __NR_getxattr 212
+#define __NR_lgetxattr 213
+#define __NR_fgetxattr 214
+#define __NR_listxattr 215
+#define __NR_llistxattr 216
+#define __NR_flistxattr 217
+#define __NR_removexattr 218
+#define __NR_lremovexattr 219
+#define __NR_fremovexattr 220
+#define __NR_futex 221
+#define __NR_sched_setaffinity 222
+#define __NR_sched_getaffinity 223
+#define __NR_tuxcall 225
+#define __NR_io_setup 227
+#define __NR_io_destroy 228
+#define __NR_io_getevents 229
+#define __NR_io_submit 230
+#define __NR_io_cancel 231
+#define __NR_set_tid_address 232
+#define __NR_fadvise64 233
+#define __NR_exit_group 234
+#define __NR_lookup_dcookie 235
+#define __NR_epoll_create 236
+#define __NR_epoll_ctl 237
+#define __NR_epoll_wait 238
+#define __NR_remap_file_pages 239
+#define __NR_timer_create 240
+#define __NR_timer_settime 241
+#define __NR_timer_gettime 242
+#define __NR_timer_getoverrun 243
+#define __NR_timer_delete 244
+#define __NR_clock_settime 245
+#define __NR_clock_gettime 246
+#define __NR_clock_getres 247
+#define __NR_clock_nanosleep 248
+#define __NR_swapcontext 249
+#define __NR_tgkill 250
+#define __NR_utimes 251
+#define __NR_statfs64 252
+#define __NR_fstatfs64 253
+#define __NR_rtas 255
+#define __NR_sys_debug_setcontext 256
+#define __NR_migrate_pages 258
+#define __NR_mbind 259
+#define __NR_get_mempolicy 260
+#define __NR_set_mempolicy 261
+#define __NR_mq_open 262
+#define __NR_mq_unlink 263
+#define __NR_mq_timedsend 264
+#define __NR_mq_timedreceive 265
+#define __NR_mq_notify 266
+#define __NR_mq_getsetattr 267
+#define __NR_kexec_load 268
+#define __NR_add_key 269
+#define __NR_request_key 270
+#define __NR_keyctl 271
+#define __NR_waitid 272
+#define __NR_ioprio_set 273
+#define __NR_ioprio_get 274
+#define __NR_inotify_init 275
+#define __NR_inotify_add_watch 276
+#define __NR_inotify_rm_watch 277
+#define __NR_spu_run 278
+#define __NR_spu_create 279
+#define __NR_pselect6 280
+#define __NR_ppoll 281
+#define __NR_unshare 282
+#define __NR_splice 283
+#define __NR_tee 284
+#define __NR_vmsplice 285
+#define __NR_openat 286
+#define __NR_mkdirat 287
+#define __NR_mknodat 288
+#define __NR_fchownat 289
+#define __NR_futimesat 290
+#define __NR_newfstatat 291
+#define __NR_unlinkat 292
+#define __NR_renameat 293
+#define __NR_linkat 294
+#define __NR_symlinkat 295
+#define __NR_readlinkat 296
+#define __NR_fchmodat 297
+#define __NR_faccessat 298
+#define __NR_get_robust_list 299
+#define __NR_set_robust_list 300
+#define __NR_move_pages 301
+#define __NR_getcpu 302
+#define __NR_epoll_pwait 303
+#define __NR_utimensat 304
+#define __NR_signalfd 305
+#define __NR_timerfd_create 306
+#define __NR_eventfd 307
+#define __NR_sync_file_range2 308
+#define __NR_fallocate 309
+#define __NR_subpage_prot 310
+#define __NR_timerfd_settime 311
+#define __NR_timerfd_gettime 312
+#define __NR_signalfd4 313
+#define __NR_eventfd2 314
+#define __NR_epoll_create1 315
+#define __NR_dup3 316
+#define __NR_pipe2 317
+#define __NR_inotify_init1 318
+#define __NR_perf_event_open 319
+#define __NR_preadv 320
+#define __NR_pwritev 321
+#define __NR_rt_tgsigqueueinfo 322
+#define __NR_fanotify_init 323
+#define __NR_fanotify_mark 324
+#define __NR_prlimit64 325
+#define __NR_socket 326
+#define __NR_bind 327
+#define __NR_connect 328
+#define __NR_listen 329
+#define __NR_accept 330
+#define __NR_getsockname 331
+#define __NR_getpeername 332
+#define __NR_socketpair 333
+#define __NR_send 334
+#define __NR_sendto 335
+#define __NR_recv 336
+#define __NR_recvfrom 337
+#define __NR_shutdown 338
+#define __NR_setsockopt 339
+#define __NR_getsockopt 340
+#define __NR_sendmsg 341
+#define __NR_recvmsg 342
+#define __NR_recvmmsg 343
+#define __NR_accept4 344
+#define __NR_name_to_handle_at 345
+#define __NR_open_by_handle_at 346
+#define __NR_clock_adjtime 347
+#define __NR_syncfs 348
+#define __NR_sendmmsg 349
+#define __NR_setns 350
+#define __NR_process_vm_readv 351
+#define __NR_process_vm_writev 352
+#define __NR_finit_module 353
+#define __NR_kcmp 354
+#define __NR_sched_setattr 355
+#define __NR_sched_getattr 356
+#define __NR_renameat2 357
+#define __NR_seccomp 358
+#define __NR_getrandom 359
+#define __NR_memfd_create 360
+#define __NR_bpf 361
+#define __NR_execveat 362
+#define __NR_switch_endian 363
+#define __NR_userfaultfd 364
+#define __NR_membarrier 365
+#define __NR_mlock2 378
+#define __NR_copy_file_range 379
+#define __NR_preadv2 380
+#define __NR_pwritev2 381
+#define __NR_kexec_file_load 382
+#define __NR_statx 383
+#define __NR_pkey_alloc 384
+#define __NR_pkey_free 385
+#define __NR_pkey_mprotect 386
+#define __NR_rseq 387
+#define __NR_io_pgetevents 388
+
+
+#endif /* _ASM_POWERPC_UNISTD_64_H */
};
};
+/* for KVM_CLEAR_DIRTY_LOG */
+struct kvm_clear_dirty_log {
+ __u32 slot;
+ __u32 num_pages;
+ __u64 first_page;
+ union {
+ void *dirty_bitmap; /* one bit per page */
+ __u64 padding2;
+ };
+};
+
/* for KVM_SET_SIGNAL_MASK */
struct kvm_signal_mask {
__u32 len;
#define KVM_S390_SIE_PAGE_OFFSET 1
+/*
+ * On arm64, machine type can be used to request the physical
+ * address size for the VM. Bits[7-0] are reserved for the guest
+ * PA size shift (i.e, log2(PA_Size)). For backward compatibility,
+ * value 0 implies the default IPA size, 40bits.
+ */
+#define KVM_VM_TYPE_ARM_IPA_SIZE_MASK 0xffULL
+#define KVM_VM_TYPE_ARM_IPA_SIZE(x) \
+ ((x) & KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
/*
* ioctls for /dev/kvm fds:
*/
#define KVM_CAP_COALESCED_PIO 162
#define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163
#define KVM_CAP_EXCEPTION_PAYLOAD 164
+#define KVM_CAP_ARM_VM_IPA_SIZE 165
+#define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166
+#define KVM_CAP_HYPERV_CPUID 167
#ifdef KVM_CAP_IRQ_ROUTING
#define KVM_GET_NESTED_STATE _IOWR(KVMIO, 0xbe, struct kvm_nested_state)
#define KVM_SET_NESTED_STATE _IOW(KVMIO, 0xbf, struct kvm_nested_state)
+/* Available with KVM_CAP_MANUAL_DIRTY_LOG_PROTECT */
+#define KVM_CLEAR_DIRTY_LOG _IOWR(KVMIO, 0xc0, struct kvm_clear_dirty_log)
+
+/* Available with KVM_CAP_HYPERV_CPUID */
+#define KVM_GET_SUPPORTED_HV_CPUID _IOWR(KVMIO, 0xc1, struct kvm_cpuid2)
+
/* Secure Encrypted Virtualization command */
enum sev_cmd_id {
/* Guest initialization commands */
#define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2)
#define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3)
+#define VFIO_REGION_TYPE_GFX (1)
+#define VFIO_REGION_SUBTYPE_GFX_EDID (1)
+
+/**
+ * struct vfio_region_gfx_edid - EDID region layout.
+ *
+ * Set display link state and EDID blob.
+ *
+ * The EDID blob has monitor information such as brand, name, serial
+ * number, physical size, supported video modes and more.
+ *
+ * This special region allows userspace (typically qemu) set a virtual
+ * EDID for the virtual monitor, which allows a flexible display
+ * configuration.
+ *
+ * For the edid blob spec look here:
+ * https://en.wikipedia.org/wiki/Extended_Display_Identification_Data
+ *
+ * On linux systems you can find the EDID blob in sysfs:
+ * /sys/class/drm/${card}/${connector}/edid
+ *
+ * You can use the edid-decode ulility (comes with xorg-x11-utils) to
+ * decode the EDID blob.
+ *
+ * @edid_offset: location of the edid blob, relative to the
+ * start of the region (readonly).
+ * @edid_max_size: max size of the edid blob (readonly).
+ * @edid_size: actual edid size (read/write).
+ * @link_state: display link state (read/write).
+ * VFIO_DEVICE_GFX_LINK_STATE_UP: Monitor is turned on.
+ * VFIO_DEVICE_GFX_LINK_STATE_DOWN: Monitor is turned off.
+ * @max_xres: max display width (0 == no limitation, readonly).
+ * @max_yres: max display height (0 == no limitation, readonly).
+ *
+ * EDID update protocol:
+ * (1) set link-state to down.
+ * (2) update edid blob and size.
+ * (3) set link-state to up.
+ */
+struct vfio_region_gfx_edid {
+ __u32 edid_offset;
+ __u32 edid_max_size;
+ __u32 edid_size;
+ __u32 max_xres;
+ __u32 max_yres;
+ __u32 link_state;
+#define VFIO_DEVICE_GFX_LINK_STATE_UP 1
+#define VFIO_DEVICE_GFX_LINK_STATE_DOWN 2
+};
+
+/*
+ * 10de vendor sub-type
+ *
+ * NVIDIA GPU NVlink2 RAM is coherent RAM mapped onto the host address space.
+ */
+#define VFIO_REGION_SUBTYPE_NVIDIA_NVLINK2_RAM (1)
+
+/*
+ * 1014 vendor sub-type
+ *
+ * IBM NPU NVlink2 ATSD (Address Translation Shootdown) register of NPU
+ * to do TLB invalidation on a GPU.
+ */
+#define VFIO_REGION_SUBTYPE_IBM_NVLINK2_ATSD (1)
+
/*
* The MSIX mappable capability informs that MSIX data of a BAR can be mmapped
* which allows direct access to non-MSIX registers which happened to be within
*/
#define VFIO_REGION_INFO_CAP_MSIX_MAPPABLE 3
+/*
+ * Capability with compressed real address (aka SSA - small system address)
+ * where GPU RAM is mapped on a system bus. Used by a GPU for DMA routing
+ * and by the userspace to associate a NVLink bridge with a GPU.
+ */
+#define VFIO_REGION_INFO_CAP_NVLINK2_SSATGT 4
+
+struct vfio_region_info_cap_nvlink2_ssatgt {
+ struct vfio_info_cap_header header;
+ __u64 tgt;
+};
+
+/*
+ * Capability with an NVLink link speed. The value is read by
+ * the NVlink2 bridge driver from the bridge's "ibm,nvlink-speed"
+ * property in the device tree. The value is fixed in the hardware
+ * and failing to provide the correct value results in the link
+ * not working with no indication from the driver why.
+ */
+#define VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD 5
+
+struct vfio_region_info_cap_nvlink2_lnkspd {
+ struct vfio_info_cap_header header;
+ __u32 link_speed;
+ __u32 __pad;
+};
+
/**
* VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9,
* struct vfio_irq_info)
* device configuration.
*/
+#include <linux/vhost_types.h>
#include <linux/types.h>
-
#include <linux/ioctl.h>
-#include <linux/virtio_config.h>
-#include <linux/virtio_ring.h>
-
-struct vhost_vring_state {
- unsigned int index;
- unsigned int num;
-};
-
-struct vhost_vring_file {
- unsigned int index;
- int fd; /* Pass -1 to unbind from file. */
-
-};
-
-struct vhost_vring_addr {
- unsigned int index;
- /* Option flags. */
- unsigned int flags;
- /* Flag values: */
- /* Whether log address is valid. If set enables logging. */
-#define VHOST_VRING_F_LOG 0
-
- /* Start of array of descriptors (virtually contiguous) */
- __u64 desc_user_addr;
- /* Used structure address. Must be 32 bit aligned */
- __u64 used_user_addr;
- /* Available structure address. Must be 16 bit aligned */
- __u64 avail_user_addr;
- /* Logging support. */
- /* Log writes to used structure, at offset calculated from specified
- * address. Address must be 32 bit aligned. */
- __u64 log_guest_addr;
-};
-
-/* no alignment requirement */
-struct vhost_iotlb_msg {
- __u64 iova;
- __u64 size;
- __u64 uaddr;
-#define VHOST_ACCESS_RO 0x1
-#define VHOST_ACCESS_WO 0x2
-#define VHOST_ACCESS_RW 0x3
- __u8 perm;
-#define VHOST_IOTLB_MISS 1
-#define VHOST_IOTLB_UPDATE 2
-#define VHOST_IOTLB_INVALIDATE 3
-#define VHOST_IOTLB_ACCESS_FAIL 4
- __u8 type;
-};
-
-#define VHOST_IOTLB_MSG 0x1
-#define VHOST_IOTLB_MSG_V2 0x2
-
-struct vhost_msg {
- int type;
- union {
- struct vhost_iotlb_msg iotlb;
- __u8 padding[64];
- };
-};
-
-struct vhost_msg_v2 {
- __u32 type;
- __u32 reserved;
- union {
- struct vhost_iotlb_msg iotlb;
- __u8 padding[64];
- };
-};
-
-struct vhost_memory_region {
- __u64 guest_phys_addr;
- __u64 memory_size; /* bytes */
- __u64 userspace_addr;
- __u64 flags_padding; /* No flags are currently specified. */
-};
-
-/* All region addresses and sizes must be 4K aligned. */
-#define VHOST_PAGE_SIZE 0x1000
-
-struct vhost_memory {
- __u32 nregions;
- __u32 padding;
- struct vhost_memory_region regions[0];
-};
/* ioctls */
* device. This can be used to stop the ring (e.g. for migration). */
#define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
-/* Feature bits */
-/* Log all write descriptors. Can be changed while device is active. */
-#define VHOST_F_LOG_ALL 26
-/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
-#define VHOST_NET_F_VIRTIO_NET_HDR 27
-
-/* VHOST_SCSI specific definitions */
-
-/*
- * Used by QEMU userspace to ensure a consistent vhost-scsi ABI.
- *
- * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate +
- * RFC-v2 vhost-scsi userspace. Add GET_ABI_VERSION ioctl usage
- * ABI Rev 1: January 2013. Ignore vhost_tpgt filed in struct vhost_scsi_target.
- * All the targets under vhost_wwpn can be seen and used by guset.
- */
-
-#define VHOST_SCSI_ABI_VERSION 1
-
-struct vhost_scsi_target {
- int abi_version;
- char vhost_wwpn[224]; /* TRANSPORT_IQN_LEN */
- unsigned short vhost_tpgt;
- unsigned short reserved;
-};
+/* VHOST_SCSI specific defines */
#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
--- /dev/null
+#include "standard-headers/linux/vhost_types.h"
#define TARGET_PR_SVE_SET_VL 50
#define TARGET_PR_SVE_GET_VL 51
+#define TARGET_PR_PAC_RESET_KEYS 54
+# define TARGET_PR_PAC_APIAKEY (1 << 0)
+# define TARGET_PR_PAC_APIBKEY (1 << 1)
+# define TARGET_PR_PAC_APDAKEY (1 << 2)
+# define TARGET_PR_PAC_APDBKEY (1 << 3)
+# define TARGET_PR_PAC_APGAKEY (1 << 4)
+
void arm_init_pauth_key(ARMPACKey *key);
#endif /* AARCH64_TARGET_SYSCALL_H */
hwcaps |= ARM_HWCAP_A64_FP;
hwcaps |= ARM_HWCAP_A64_ASIMD;
+ hwcaps |= ARM_HWCAP_A64_CPUID;
/* probe for the extra features */
#define GET_FEATURE_ID(feat, hwcap) \
GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA);
GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE);
GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG);
+ GET_FEATURE_ID(aa64_fhm, ARM_HWCAP_A64_ASIMDFHM);
+ GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT);
#undef GET_FEATURE_ID
QEMU_IFLA_CARRIER_UP_COUNT,
QEMU_IFLA_CARRIER_DOWN_COUNT,
QEMU_IFLA_NEW_IFINDEX,
+ QEMU_IFLA_MIN_MTU,
+ QEMU_IFLA_MAX_MTU,
QEMU___IFLA_MAX
};
QEMU_IFLA_BRPORT_BCAST_FLOOD,
QEMU_IFLA_BRPORT_GROUP_FWD_MASK,
QEMU_IFLA_BRPORT_NEIGH_SUPPRESS,
+ QEMU_IFLA_BRPORT_ISOLATED,
+ QEMU_IFLA_BRPORT_BACKUP_PORT,
QEMU___IFLA_BRPORT_MAX
};
case QEMU_IFLA_BRPORT_VLAN_TUNNEL:
case QEMU_IFLA_BRPORT_BCAST_FLOOD:
case QEMU_IFLA_BRPORT_NEIGH_SUPPRESS:
+ case QEMU_IFLA_BRPORT_ISOLATED:
break;
/* uint16_t */
case QEMU_IFLA_BRPORT_PRIORITY:
break;
/* uin32_t */
case QEMU_IFLA_BRPORT_COST:
+ case QEMU_IFLA_BRPORT_BACKUP_PORT:
u32 = NLA_DATA(nlattr);
*u32 = tswap32(*u32);
break;
case QEMU_IFLA_GSO_MAX_SIZE:
case QEMU_IFLA_CARRIER_UP_COUNT:
case QEMU_IFLA_CARRIER_DOWN_COUNT:
+ case QEMU_IFLA_MIN_MTU:
+ case QEMU_IFLA_MAX_MTU:
u32 = RTA_DATA(rtattr);
*u32 = tswap32(*u32);
break;
# undef MIPS_SYS
# endif /* O32 */
-static int do_store_exclusive(CPUMIPSState *env)
-{
- target_ulong addr;
- target_ulong page_addr;
- target_ulong val;
- uint32_t val_wp = 0;
- uint32_t llnewval_wp = 0;
- int flags;
- int segv = 0;
- int reg;
- int d;
- int wp;
-
- addr = env->lladdr;
- page_addr = addr & TARGET_PAGE_MASK;
- start_exclusive();
- mmap_lock();
- flags = page_get_flags(page_addr);
- if ((flags & PAGE_READ) == 0) {
- segv = 1;
- } else {
- reg = env->llreg & 0x1f;
- d = (env->llreg & 0x20) != 0;
- wp = (env->llreg & 0x40) != 0;
- if (!wp) {
- if (d) {
- segv = get_user_s64(val, addr);
- } else {
- segv = get_user_s32(val, addr);
- }
- } else {
- segv = get_user_s32(val, addr);
- segv |= get_user_s32(val_wp, addr);
- llnewval_wp = env->llnewval_wp;
- }
- if (!segv) {
- if (val != env->llval && val_wp == llnewval_wp) {
- env->active_tc.gpr[reg] = 0;
- } else {
- if (!wp) {
- if (d) {
- segv = put_user_u64(env->llnewval, addr);
- } else {
- segv = put_user_u32(env->llnewval, addr);
- }
- } else {
- segv = put_user_u32(env->llnewval, addr);
- segv |= put_user_u32(env->llnewval_wp, addr + 4);
- }
- if (!segv) {
- env->active_tc.gpr[reg] = 1;
- }
- }
- }
- }
- env->lladdr = -1;
- if (!segv) {
- env->active_tc.PC += 4;
- }
- mmap_unlock();
- end_exclusive();
- return segv;
-}
-
/* Break codes */
enum {
BRK_OVERFLOW = 6,
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
- case EXCP_SC:
- if (do_store_exclusive(env)) {
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- info.si_code = TARGET_SEGV_MAPERR;
- info._sifields._sigfault._addr = env->active_tc.PC;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- }
- break;
case EXCP_DSPDIS:
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
__put_user(env->fpr[i], &sc->fpr[i]);
}
- uint32_t fcsr = csr_read_helper(env, CSR_FCSR); /*riscv_get_fcsr(env);*/
+ uint32_t fcsr = riscv_csr_read(env, CSR_FCSR);
__put_user(fcsr, &sc->fcsr);
}
uint32_t fcsr;
__get_user(fcsr, &sc->fcsr);
- csr_write_helper(env, fcsr, CSR_FCSR);
+ riscv_csr_write(env, CSR_FCSR, fcsr);
}
static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
*
* Copyright (c) 2009 Ulrich Hecht
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * This library is distributed in the hope that it will be useful,
+ * 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
- * Lesser General Public License for more details.
+ * General Public License for more details.
*
- * Contributions after 2012-10-29 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- *
- * You should have received a copy of the GNU (Lesser) General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef S390X_TARGET_CPU_H
#define S390X_TARGET_CPU_H
unlock_user(argptr, arg, 0);
host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
- target_ifc_len = host_ifconf->ifc_len;
target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
-
target_ifreq_size = thunk_type_size(ifreq_arg_type, 0);
- nb_ifreq = target_ifc_len / target_ifreq_size;
- host_ifc_len = nb_ifreq * sizeof(struct ifreq);
- outbufsz = sizeof(*host_ifconf) + host_ifc_len;
- if (outbufsz > MAX_STRUCT_SIZE) {
- /* We can't fit all the extents into the fixed size buffer.
- * Allocate one that is large enough and use it instead.
- */
- host_ifconf = malloc(outbufsz);
- if (!host_ifconf) {
- return -TARGET_ENOMEM;
+ if (target_ifc_buf != 0) {
+ target_ifc_len = host_ifconf->ifc_len;
+ nb_ifreq = target_ifc_len / target_ifreq_size;
+ host_ifc_len = nb_ifreq * sizeof(struct ifreq);
+
+ outbufsz = sizeof(*host_ifconf) + host_ifc_len;
+ if (outbufsz > MAX_STRUCT_SIZE) {
+ /*
+ * We can't fit all the extents into the fixed size buffer.
+ * Allocate one that is large enough and use it instead.
+ */
+ host_ifconf = malloc(outbufsz);
+ if (!host_ifconf) {
+ return -TARGET_ENOMEM;
+ }
+ memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
+ free_buf = 1;
}
- memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
- free_buf = 1;
- }
- host_ifc_buf = (char*)host_ifconf + sizeof(*host_ifconf);
+ host_ifc_buf = (char *)host_ifconf + sizeof(*host_ifconf);
- host_ifconf->ifc_len = host_ifc_len;
+ host_ifconf->ifc_len = host_ifc_len;
+ } else {
+ host_ifc_buf = NULL;
+ }
host_ifconf->ifc_buf = host_ifc_buf;
ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_ifconf));
thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
unlock_user(argptr, arg, target_size);
- /* copy ifreq[] to target user */
-
- argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
- for (i = 0; i < nb_ifreq ; i++) {
- thunk_convert(argptr + i * target_ifreq_size,
- host_ifc_buf + i * sizeof(struct ifreq),
- ifreq_arg_type, THUNK_TARGET);
+ if (target_ifc_buf != 0) {
+ /* copy ifreq[] to target user */
+ argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
+ for (i = 0; i < nb_ifreq ; i++) {
+ thunk_convert(argptr + i * target_ifreq_size,
+ host_ifc_buf + i * sizeof(struct ifreq),
+ ifreq_arg_type, THUNK_TARGET);
+ }
+ unlock_user(argptr, target_ifc_buf, target_ifc_len);
}
- unlock_user(argptr, target_ifc_buf, target_ifc_len);
}
if (free_buf) {
char iface[16];
uint32_t dest, gw, mask;
unsigned int flags, refcnt, use, metric, mtu, window, irtt;
- sscanf(line, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
- iface, &dest, &gw, &flags, &refcnt, &use, &metric,
- &mask, &mtu, &window, &irtt);
+ int fields;
+
+ fields = sscanf(line,
+ "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
+ iface, &dest, &gw, &flags, &refcnt, &use, &metric,
+ &mask, &mtu, &window, &irtt);
+ if (fields != 11) {
+ continue;
+ }
dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
metric, tswap32(mask), mtu, window, irtt);
}
}
return ret;
+ case TARGET_PR_PAC_RESET_KEYS:
+ {
+ CPUARMState *env = cpu_env;
+ ARMCPU *cpu = arm_env_get_cpu(env);
+
+ if (arg3 || arg4 || arg5) {
+ return -TARGET_EINVAL;
+ }
+ if (cpu_isar_feature(aa64_pauth, cpu)) {
+ int all = (TARGET_PR_PAC_APIAKEY | TARGET_PR_PAC_APIBKEY |
+ TARGET_PR_PAC_APDAKEY | TARGET_PR_PAC_APDBKEY |
+ TARGET_PR_PAC_APGAKEY);
+ if (arg2 == 0) {
+ arg2 = all;
+ } else if (arg2 & ~all) {
+ return -TARGET_EINVAL;
+ }
+ if (arg2 & TARGET_PR_PAC_APIAKEY) {
+ arm_init_pauth_key(&env->apia_key);
+ }
+ if (arg2 & TARGET_PR_PAC_APIBKEY) {
+ arm_init_pauth_key(&env->apib_key);
+ }
+ if (arg2 & TARGET_PR_PAC_APDAKEY) {
+ arm_init_pauth_key(&env->apda_key);
+ }
+ if (arg2 & TARGET_PR_PAC_APDBKEY) {
+ arm_init_pauth_key(&env->apdb_key);
+ }
+ if (arg2 & TARGET_PR_PAC_APGAKEY) {
+ arm_init_pauth_key(&env->apga_key);
+ }
+ return 0;
+ }
+ }
+ return -TARGET_EINVAL;
#endif /* AARCH64 */
case PR_GET_SECCOMP:
case PR_SET_SECCOMP:
BlkMigDevState *bmds;
int64_t sector;
int nr_sectors;
- struct iovec iov;
QEMUIOVector qiov;
BlockAIOCB *aiocb;
blk->sector = cur_sector;
blk->nr_sectors = nr_sectors;
- blk->iov.iov_base = blk->buf;
- blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
- qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
+ qemu_iovec_init_buf(&blk->qiov, blk->buf, nr_sectors * BDRV_SECTOR_SIZE);
blk_mig_lock();
block_mig_state.submitted++;
blk->nr_sectors = nr_sectors;
if (is_async) {
- blk->iov.iov_base = blk->buf;
- blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
- qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
+ qemu_iovec_init_buf(&blk->qiov, blk->buf,
+ nr_sectors * BDRV_SECTOR_SIZE);
blk->aiocb = blk_aio_preadv(bmds->blk,
sector * BDRV_SECTOR_SIZE,
#include "sysemu/balloon.h"
#include "qemu/timer.h"
#include "sysemu/hw_accel.h"
-#include "qemu/acl.h"
+#include "authz/list.h"
+#include "qapi/util.h"
#include "sysemu/tpm.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h"
#include "qemu/thread.h"
#include "block/qapi.h"
#include "qapi/qapi-commands.h"
-#include "qapi/qapi-events.h"
+#include "qapi/qapi-emit-events.h"
#include "qapi/error.h"
#include "qapi/qmp-event.h"
#include "qapi/qapi-introspect.h"
EventInfoList *qmp_query_events(Error **errp)
{
+ /*
+ * TODO This deprecated command is the only user of
+ * QAPIEvent_str() and QAPIEvent_lookup[]. When the command goes,
+ * they should go, too.
+ */
EventInfoList *info, *ev_list = NULL;
QAPIEvent e;
*ret_data = qobject_from_qlit(&qmp_schema_qlit);
}
-/*
- * We used to define commands in qmp-commands.hx in addition to the
- * QAPI schema. This permitted defining some of them only in certain
- * configurations. query-commands has always reflected that (good,
- * because it lets QMP clients figure out what's actually available),
- * while query-qmp-schema never did (not so good). This function is a
- * hack to keep the configuration-specific commands defined exactly as
- * before, even though qmp-commands.hx is gone.
- *
- * FIXME Educate the QAPI schema on configuration-specific commands,
- * and drop this hack.
- */
-static void qmp_unregister_commands_hack(void)
-{
-#ifndef TARGET_I386
- qmp_unregister_command(&qmp_commands, "rtc-reset-reinjection");
- qmp_unregister_command(&qmp_commands, "query-sev");
- qmp_unregister_command(&qmp_commands, "query-sev-launch-measure");
- qmp_unregister_command(&qmp_commands, "query-sev-capabilities");
-#endif
-#ifndef TARGET_S390X
- qmp_unregister_command(&qmp_commands, "dump-skeys");
-#endif
-#ifndef TARGET_ARM
- qmp_unregister_command(&qmp_commands, "query-gic-capabilities");
-#endif
-#if !defined(TARGET_S390X) && !defined(TARGET_I386)
- qmp_unregister_command(&qmp_commands, "query-cpu-model-expansion");
-#endif
-#if !defined(TARGET_S390X)
- qmp_unregister_command(&qmp_commands, "query-cpu-model-baseline");
- qmp_unregister_command(&qmp_commands, "query-cpu-model-comparison");
-#endif
-#if !defined(TARGET_PPC) && !defined(TARGET_ARM) && !defined(TARGET_I386) \
- && !defined(TARGET_S390X)
- qmp_unregister_command(&qmp_commands, "query-cpu-definitions");
-#endif
-}
-
static void monitor_init_qmp_commands(void)
{
/*
qmp_register_command(&qmp_commands, "netdev_add", qmp_netdev_add,
QCO_NO_OPTIONS);
- qmp_unregister_commands_hack();
-
QTAILQ_INIT(&qmp_cap_negotiation_commands);
qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG);
QLIST_INSERT_HEAD (&capture_head, s, entries);
}
-static qemu_acl *find_acl(Monitor *mon, const char *name)
+static QAuthZList *find_auth(Monitor *mon, const char *name)
{
- qemu_acl *acl = qemu_acl_find(name);
+ Object *obj;
+ Object *container;
- if (!acl) {
+ container = object_get_objects_root();
+ obj = object_resolve_path_component(container, name);
+ if (!obj) {
monitor_printf(mon, "acl: unknown list '%s'\n", name);
+ return NULL;
}
- return acl;
+
+ return QAUTHZ_LIST(obj);
}
static void hmp_acl_show(Monitor *mon, const QDict *qdict)
{
const char *aclname = qdict_get_str(qdict, "aclname");
- qemu_acl *acl = find_acl(mon, aclname);
- qemu_acl_entry *entry;
- int i = 0;
-
- if (acl) {
- monitor_printf(mon, "policy: %s\n",
- acl->defaultDeny ? "deny" : "allow");
- QTAILQ_FOREACH(entry, &acl->entries, next) {
- i++;
- monitor_printf(mon, "%d: %s %s\n", i,
- entry->deny ? "deny" : "allow", entry->match);
- }
+ QAuthZList *auth = find_auth(mon, aclname);
+ QAuthZListRuleList *rules;
+ size_t i = 0;
+
+ if (!auth) {
+ return;
+ }
+
+ monitor_printf(mon, "policy: %s\n",
+ QAuthZListPolicy_str(auth->policy));
+
+ rules = auth->rules;
+ while (rules) {
+ QAuthZListRule *rule = rules->value;
+ i++;
+ monitor_printf(mon, "%zu: %s %s\n", i,
+ QAuthZListPolicy_str(rule->policy),
+ rule->match);
+ rules = rules->next;
}
}
static void hmp_acl_reset(Monitor *mon, const QDict *qdict)
{
const char *aclname = qdict_get_str(qdict, "aclname");
- qemu_acl *acl = find_acl(mon, aclname);
+ QAuthZList *auth = find_auth(mon, aclname);
- if (acl) {
- qemu_acl_reset(acl);
- monitor_printf(mon, "acl: removed all rules\n");
+ if (!auth) {
+ return;
}
+
+ auth->policy = QAUTHZ_LIST_POLICY_DENY;
+ qapi_free_QAuthZListRuleList(auth->rules);
+ auth->rules = NULL;
+ monitor_printf(mon, "acl: removed all rules\n");
}
static void hmp_acl_policy(Monitor *mon, const QDict *qdict)
{
const char *aclname = qdict_get_str(qdict, "aclname");
const char *policy = qdict_get_str(qdict, "policy");
- qemu_acl *acl = find_acl(mon, aclname);
+ QAuthZList *auth = find_auth(mon, aclname);
+ int val;
+ Error *err = NULL;
+
+ if (!auth) {
+ return;
+ }
- if (acl) {
- if (strcmp(policy, "allow") == 0) {
- acl->defaultDeny = 0;
+ val = qapi_enum_parse(&QAuthZListPolicy_lookup,
+ policy,
+ QAUTHZ_LIST_POLICY_DENY,
+ &err);
+ if (err) {
+ error_free(err);
+ monitor_printf(mon, "acl: unknown policy '%s', "
+ "expected 'deny' or 'allow'\n", policy);
+ } else {
+ auth->policy = val;
+ if (auth->policy == QAUTHZ_LIST_POLICY_ALLOW) {
monitor_printf(mon, "acl: policy set to 'allow'\n");
- } else if (strcmp(policy, "deny") == 0) {
- acl->defaultDeny = 1;
- monitor_printf(mon, "acl: policy set to 'deny'\n");
} else {
- monitor_printf(mon, "acl: unknown policy '%s', "
- "expected 'deny' or 'allow'\n", policy);
+ monitor_printf(mon, "acl: policy set to 'deny'\n");
}
}
}
+static QAuthZListFormat hmp_acl_get_format(const char *match)
+{
+ if (strchr(match, '*')) {
+ return QAUTHZ_LIST_FORMAT_GLOB;
+ } else {
+ return QAUTHZ_LIST_FORMAT_EXACT;
+ }
+}
+
static void hmp_acl_add(Monitor *mon, const QDict *qdict)
{
const char *aclname = qdict_get_str(qdict, "aclname");
const char *match = qdict_get_str(qdict, "match");
- const char *policy = qdict_get_str(qdict, "policy");
+ const char *policystr = qdict_get_str(qdict, "policy");
int has_index = qdict_haskey(qdict, "index");
int index = qdict_get_try_int(qdict, "index", -1);
- qemu_acl *acl = find_acl(mon, aclname);
- int deny, ret;
-
- if (acl) {
- if (strcmp(policy, "allow") == 0) {
- deny = 0;
- } else if (strcmp(policy, "deny") == 0) {
- deny = 1;
- } else {
- monitor_printf(mon, "acl: unknown policy '%s', "
- "expected 'deny' or 'allow'\n", policy);
- return;
- }
- if (has_index)
- ret = qemu_acl_insert(acl, deny, match, index);
- else
- ret = qemu_acl_append(acl, deny, match);
- if (ret < 0)
- monitor_printf(mon, "acl: unable to add acl entry\n");
- else
- monitor_printf(mon, "acl: added rule at position %d\n", ret);
+ QAuthZList *auth = find_auth(mon, aclname);
+ Error *err = NULL;
+ QAuthZListPolicy policy;
+ QAuthZListFormat format;
+ size_t i = 0;
+
+ if (!auth) {
+ return;
+ }
+
+ policy = qapi_enum_parse(&QAuthZListPolicy_lookup,
+ policystr,
+ QAUTHZ_LIST_POLICY_DENY,
+ &err);
+ if (err) {
+ error_free(err);
+ monitor_printf(mon, "acl: unknown policy '%s', "
+ "expected 'deny' or 'allow'\n", policystr);
+ return;
+ }
+
+ format = hmp_acl_get_format(match);
+
+ if (has_index && index == 0) {
+ monitor_printf(mon, "acl: unable to add acl entry\n");
+ return;
+ }
+
+ if (has_index) {
+ i = qauthz_list_insert_rule(auth, match, policy,
+ format, index - 1, &err);
+ } else {
+ i = qauthz_list_append_rule(auth, match, policy,
+ format, &err);
+ }
+ if (err) {
+ monitor_printf(mon, "acl: unable to add rule: %s",
+ error_get_pretty(err));
+ error_free(err);
+ } else {
+ monitor_printf(mon, "acl: added rule at position %zu\n", i + 1);
}
}
{
const char *aclname = qdict_get_str(qdict, "aclname");
const char *match = qdict_get_str(qdict, "match");
- qemu_acl *acl = find_acl(mon, aclname);
- int ret;
+ QAuthZList *auth = find_auth(mon, aclname);
+ ssize_t i = 0;
- if (acl) {
- ret = qemu_acl_remove(acl, match);
- if (ret < 0)
- monitor_printf(mon, "acl: no matching acl entry\n");
- else
- monitor_printf(mon, "acl: removed rule at position %d\n", ret);
+ if (!auth) {
+ return;
+ }
+
+ i = qauthz_list_delete_rule(auth, match);
+ if (i >= 0) {
+ monitor_printf(mon, "acl: removed rule at position %zu\n", i + 1);
+ } else {
+ monitor_printf(mon, "acl: no matching acl entry\n");
}
}
void monitor_cleanup(void)
{
- Monitor *mon, *next;
-
/*
* We need to explicitly stop the I/O thread (but not destroy it),
* clean up the monitor resources, then destroy the I/O thread since
/* Flush output buffers and destroy monitors */
qemu_mutex_lock(&monitor_lock);
monitor_destroyed = true;
- QTAILQ_FOREACH_SAFE(mon, &mon_list, entry, next) {
+ while (!QTAILQ_EMPTY(&mon_list)) {
+ Monitor *mon = QTAILQ_FIRST(&mon_list);
QTAILQ_REMOVE(&mon_list, mon, entry);
/* Permit QAPI event emission from character frontend release */
qemu_mutex_unlock(&monitor_lock);
},
};
-#ifndef TARGET_I386
-void qmp_rtc_reset_reinjection(Error **errp)
-{
- error_setg(errp, QERR_FEATURE_DISABLED, "rtc-reset-reinjection");
-}
-
-SevInfo *qmp_query_sev(Error **errp)
-{
- error_setg(errp, QERR_FEATURE_DISABLED, "query-sev");
- return NULL;
-}
-
-SevLaunchMeasureInfo *qmp_query_sev_launch_measure(Error **errp)
-{
- error_setg(errp, QERR_FEATURE_DISABLED, "query-sev-launch-measure");
- return NULL;
-}
-
-SevCapability *qmp_query_sev_capabilities(Error **errp)
-{
- error_setg(errp, QERR_FEATURE_DISABLED, "query-sev-capabilities");
- return NULL;
-}
-#endif
-
-#ifndef TARGET_S390X
-void qmp_dump_skeys(const char *filename, Error **errp)
-{
- error_setg(errp, QERR_FEATURE_DISABLED, "dump-skeys");
-}
-#endif
-
-#ifndef TARGET_ARM
-GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
-{
- error_setg(errp, QERR_FEATURE_DISABLED, "query-gic-capabilities");
- return NULL;
-}
-#endif
-
HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
{
MachineState *ms = MACHINE(qdev_get_machine());
return 0;
}
+/* nbd_read_eof
+ * Tries to read @size bytes from @ioc.
+ * Returns 1 on success
+ * 0 on eof, when no data was read (errp is not set)
+ * negative errno on failure (errp is set)
+ */
+static inline int coroutine_fn
+nbd_read_eof(BlockDriverState *bs, QIOChannel *ioc, void *buffer, size_t size,
+ Error **errp)
+{
+ bool partial = false;
+
+ assert(size);
+ while (size > 0) {
+ struct iovec iov = { .iov_base = buffer, .iov_len = size };
+ ssize_t len;
+
+ len = qio_channel_readv(ioc, &iov, 1, errp);
+ if (len == QIO_CHANNEL_ERR_BLOCK) {
+ bdrv_dec_in_flight(bs);
+ qio_channel_yield(ioc, G_IO_IN);
+ bdrv_inc_in_flight(bs);
+ continue;
+ } else if (len < 0) {
+ return -EIO;
+ } else if (len == 0) {
+ if (partial) {
+ error_setg(errp,
+ "Unexpected end-of-file before all bytes were read");
+ return -EIO;
+ } else {
+ return 0;
+ }
+ }
+
+ partial = true;
+ size -= len;
+ buffer = (uint8_t*) buffer + len;
+ }
+ return 1;
+}
+
/* nbd_receive_reply
+ *
+ * Decreases bs->in_flight while waiting for a new reply. This yield is where
+ * we wait indefinitely and the coroutine must be able to be safely reentered
+ * for nbd_client_attach_aio_context().
+ *
* Returns 1 on success
* 0 on eof, when no data was read (errp is not set)
* negative errno on failure (errp is set)
*/
-int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp)
+int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc,
+ NBDReply *reply, Error **errp)
{
int ret;
const char *type;
- ret = nbd_read_eof(ioc, &reply->magic, sizeof(reply->magic), errp);
+ ret = nbd_read_eof(bs, ioc, &reply->magic, sizeof(reply->magic), errp);
if (ret <= 0) {
return ret;
}
#define NBD_SET_TIMEOUT _IO(0xab, 9)
#define NBD_SET_FLAGS _IO(0xab, 10)
-/* nbd_read_eof
- * Tries to read @size bytes from @ioc.
- * Returns 1 on success
- * 0 on eof, when no data was read (errp is not set)
- * negative errno on failure (errp is set)
- */
-static inline int nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size,
- Error **errp)
-{
- int ret;
-
- assert(size);
- ret = qio_channel_read_all_eof(ioc, buffer, size, errp);
- if (ret < 0) {
- ret = -EIO;
- }
- return ret;
-}
-
/* nbd_write
* Writes @size bytes to @ioc. Returns 0 on success.
*/
if (bitmap) {
BdrvDirtyBitmap *bm = NULL;
- BlockDriverState *bs = blk_bs(blk);
while (true) {
bm = bdrv_find_dirty_bitmap(bs, bitmap);
buf, size, sent_cb);
}
-void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
+ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
{
- qemu_send_packet_async(nc, buf, size, NULL);
+ return qemu_send_packet_async(nc, buf, size, NULL);
}
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
char str[1024];
};
+struct GuestFwd {
+ CharBackend hd;
+ struct in_addr server;
+ int port;
+ Slirp *slirp;
+};
+
typedef struct SlirpState {
NetClientState nc;
QTAILQ_ENTRY(SlirpState) entry;
Slirp *slirp;
+ Notifier poll_notifier;
Notifier exit_notifier;
#ifndef _WIN32
gchar *smb_dir;
#endif
+ GSList *fwd;
} SlirpState;
static struct slirp_config_str *slirp_configs;
static inline void slirp_smb_cleanup(SlirpState *s) { }
#endif
-static void net_slirp_output(void *opaque, const uint8_t *pkt, int pkt_len)
+static ssize_t net_slirp_send_packet(const void *pkt, size_t pkt_len,
+ void *opaque)
{
SlirpState *s = opaque;
- qemu_send_packet(&s->nc, pkt, pkt_len);
+ return qemu_send_packet(&s->nc, pkt, pkt_len);
}
static ssize_t net_slirp_receive(NetClientState *nc, const uint8_t *buf, size_t size)
slirp_smb_cleanup(s);
}
+static void slirp_free_fwd(gpointer data)
+{
+ struct GuestFwd *fwd = data;
+
+ qemu_chr_fe_deinit(&fwd->hd, true);
+ g_free(data);
+}
+
static void net_slirp_cleanup(NetClientState *nc)
{
SlirpState *s = DO_UPCAST(SlirpState, nc, nc);
+ g_slist_free_full(s->fwd, slirp_free_fwd);
+ main_loop_poll_remove_notifier(&s->poll_notifier);
slirp_cleanup(s->slirp);
if (s->exit_notifier.notify) {
qemu_remove_exit_notifier(&s->exit_notifier);
.cleanup = net_slirp_cleanup,
};
-static void net_slirp_guest_error(const char *msg)
+static void net_slirp_guest_error(const char *msg, void *opaque)
{
qemu_log_mask(LOG_GUEST_ERROR, "%s", msg);
}
-static int64_t net_slirp_clock_get_ns(void)
+static int64_t net_slirp_clock_get_ns(void *opaque)
{
return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
+static void *net_slirp_timer_new(SlirpTimerCb cb,
+ void *cb_opaque, void *opaque)
+{
+ return timer_new_full(NULL, QEMU_CLOCK_VIRTUAL,
+ SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
+ cb, cb_opaque);
+}
+
+static void net_slirp_timer_free(void *timer, void *opaque)
+{
+ timer_del(timer);
+ timer_free(timer);
+}
+
+static void net_slirp_timer_mod(void *timer, int64_t expire_timer,
+ void *opaque)
+{
+ timer_mod(timer, expire_timer);
+}
+
+static void net_slirp_register_poll_fd(int fd, void *opaque)
+{
+ qemu_fd_register(fd);
+}
+
+static void net_slirp_unregister_poll_fd(int fd, void *opaque)
+{
+ /* no qemu_fd_unregister */
+}
+
+static void net_slirp_notify(void *opaque)
+{
+ qemu_notify_event();
+}
+
static const SlirpCb slirp_cb = {
- .output = net_slirp_output,
+ .send_packet = net_slirp_send_packet,
.guest_error = net_slirp_guest_error,
.clock_get_ns = net_slirp_clock_get_ns,
+ .timer_new = net_slirp_timer_new,
+ .timer_free = net_slirp_timer_free,
+ .timer_mod = net_slirp_timer_mod,
+ .register_poll_fd = net_slirp_register_poll_fd,
+ .unregister_poll_fd = net_slirp_unregister_poll_fd,
+ .notify = net_slirp_notify,
};
+static int slirp_poll_to_gio(int events)
+{
+ int ret = 0;
+
+ if (events & SLIRP_POLL_IN) {
+ ret |= G_IO_IN;
+ }
+ if (events & SLIRP_POLL_OUT) {
+ ret |= G_IO_OUT;
+ }
+ if (events & SLIRP_POLL_PRI) {
+ ret |= G_IO_PRI;
+ }
+ if (events & SLIRP_POLL_ERR) {
+ ret |= G_IO_ERR;
+ }
+ if (events & SLIRP_POLL_HUP) {
+ ret |= G_IO_HUP;
+ }
+
+ return ret;
+}
+
+static int net_slirp_add_poll(int fd, int events, void *opaque)
+{
+ GArray *pollfds = opaque;
+ GPollFD pfd = {
+ .fd = fd,
+ .events = slirp_poll_to_gio(events),
+ };
+ int idx = pollfds->len;
+ g_array_append_val(pollfds, pfd);
+ return idx;
+}
+
+static int slirp_gio_to_poll(int events)
+{
+ int ret = 0;
+
+ if (events & G_IO_IN) {
+ ret |= SLIRP_POLL_IN;
+ }
+ if (events & G_IO_OUT) {
+ ret |= SLIRP_POLL_OUT;
+ }
+ if (events & G_IO_PRI) {
+ ret |= SLIRP_POLL_PRI;
+ }
+ if (events & G_IO_ERR) {
+ ret |= SLIRP_POLL_ERR;
+ }
+ if (events & G_IO_HUP) {
+ ret |= SLIRP_POLL_HUP;
+ }
+
+ return ret;
+}
+
+static int net_slirp_get_revents(int idx, void *opaque)
+{
+ GArray *pollfds = opaque;
+
+ return slirp_gio_to_poll(g_array_index(pollfds, GPollFD, idx).revents);
+}
+
+static void net_slirp_poll_notify(Notifier *notifier, void *data)
+{
+ MainLoopPoll *poll = data;
+ SlirpState *s = container_of(notifier, SlirpState, poll_notifier);
+
+ switch (poll->state) {
+ case MAIN_LOOP_POLL_FILL:
+ slirp_pollfds_fill(s->slirp, &poll->timeout,
+ net_slirp_add_poll, poll->pollfds);
+ break;
+ case MAIN_LOOP_POLL_OK:
+ case MAIN_LOOP_POLL_ERR:
+ slirp_pollfds_poll(s->slirp, poll->state == MAIN_LOOP_POLL_ERR,
+ net_slirp_get_revents, poll->pollfds);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
static int net_slirp_init(NetClientState *peer, const char *model,
const char *name, int restricted,
bool ipv4, const char *vnetwork, const char *vhost,
&slirp_cb, s);
QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
+ s->poll_notifier.notify = net_slirp_poll_notify;
+ main_loop_poll_add_notifier(&s->poll_notifier);
+
for (config = slirp_configs; config; config = config->next) {
if (config->flags & SLIRP_CFG_HOSTFWD) {
if (slirp_hostfwd(s, config->str, errp) < 0) {
CONFIG_SMBD_COMMAND, s->smb_dir, smb_conf);
g_free(smb_conf);
- if (slirp_add_exec(s->slirp, NULL, smb_cmdline, &vserver_addr, 139) < 0 ||
- slirp_add_exec(s->slirp, NULL, smb_cmdline, &vserver_addr, 445) < 0) {
+ if (slirp_add_exec(s->slirp, smb_cmdline, &vserver_addr, 139) < 0 ||
+ slirp_add_exec(s->slirp, smb_cmdline, &vserver_addr, 445) < 0) {
slirp_smb_cleanup(s);
g_free(smb_cmdline);
error_setg(errp, "Conflicting/invalid smbserver address");
#endif /* !defined(_WIN32) */
-struct GuestFwd {
- CharBackend hd;
- struct in_addr server;
- int port;
- Slirp *slirp;
-};
-
static int guestfwd_can_read(void *opaque)
{
struct GuestFwd *fwd = opaque;
slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
}
+static ssize_t guestfwd_write(const void *buf, size_t len, void *chr)
+{
+ return qemu_chr_fe_write_all(chr, buf, len);
+}
+
static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
{
struct in_addr server = { .s_addr = 0 };
snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port);
- if ((strlen(p) > 4) && !strncmp(p, "cmd:", 4)) {
- if (slirp_add_exec(s->slirp, NULL, &p[4], &server, port) < 0) {
+ if (g_str_has_prefix(p, "cmd:")) {
+ if (slirp_add_exec(s->slirp, &p[4], &server, port) < 0) {
error_setg(errp, "Conflicting/invalid host:port in guest "
"forwarding rule '%s'", config_str);
return -1;
* FIXME: sure we want to support implicit
* muxed monitors here?
*/
- Chardev *chr = qemu_chr_new_mux_mon(buf, p);
+ Chardev *chr = qemu_chr_new_mux_mon(buf, p, NULL);
if (!chr) {
error_setg(errp, "Could not open guest forwarding device '%s'",
qemu_chr_fe_init(&fwd->hd, chr, &err);
if (err) {
error_propagate(errp, err);
+ object_unparent(OBJECT(chr));
g_free(fwd);
return -1;
}
- if (slirp_add_exec(s->slirp, &fwd->hd, NULL, &server, port) < 0) {
+ if (slirp_add_guestfwd(s->slirp, guestfwd_write, &fwd->hd,
+ &server, port) < 0) {
error_setg(errp, "Conflicting/invalid host:port in guest "
"forwarding rule '%s'", config_str);
+ qemu_chr_fe_deinit(&fwd->hd, true);
g_free(fwd);
return -1;
}
qemu_chr_fe_set_handlers(&fwd->hd, guestfwd_can_read, guestfwd_read,
NULL, NULL, fwd, NULL, true);
+ s->fwd = g_slist_append(s->fwd, fwd);
}
return 0;
ASFLAGS += -32
QEMU_CFLAGS += $(call cc-c-option, $(QEMU_CFLAGS), $(Wa)-32)
-build-all: multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin
+build-all: multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin
# suppress auto-removal of intermediate files
.SECONDARY:
%.o: %.S
$(call quiet-command,$(CPP) $(QEMU_INCLUDES) $(QEMU_DGFLAGS) -c -o - $< | $(AS) $(ASFLAGS) -o $@,"AS","$(TARGET_DIR)$@")
+pvh.img: pvh.o pvh_main.o
+ $(call quiet-command,$(LD) $(LDFLAGS_NOPIE) -m $(LD_I386_EMULATION) -T $(SRC_PATH)/pc-bios/optionrom/flat.lds -s -o $@ $^,"BUILD","$(TARGET_DIR)$@")
+
%.img: %.o
$(call quiet-command,$(LD) $(LDFLAGS_NOPIE) -m $(LD_I386_EMULATION) -T $(SRC_PATH)/pc-bios/optionrom/flat.lds -s -o $@ $<,"BUILD","$(TARGET_DIR)$@")
" jmp load_kernel\n"
);
-/* QEMU_CFG_DMA_CONTROL bits */
-#define BIOS_CFG_DMA_CTL_ERROR 0x01
-#define BIOS_CFG_DMA_CTL_READ 0x02
-#define BIOS_CFG_DMA_CTL_SKIP 0x04
-#define BIOS_CFG_DMA_CTL_SELECT 0x08
-
-#define BIOS_CFG_DMA_ADDR_HIGH 0x514
-#define BIOS_CFG_DMA_ADDR_LOW 0x518
-
-#define uint64_t unsigned long long
-#define uint32_t unsigned int
-#define uint16_t unsigned short
-
-#include "../../include/standard-headers/linux/qemu_fw_cfg.h"
-
-#define barrier() asm("" : : : "memory")
-
-typedef struct FWCfgDmaAccess {
- uint32_t control;
- uint32_t length;
- uint64_t address;
-} __attribute__((packed)) FWCfgDmaAccess;
-
-static inline void outl(uint32_t value, uint16_t port)
-{
- asm("outl %0, %w1" : : "a"(value), "Nd"(port));
-}
+/*
+ * The includes of C headers must be after the asm block to avoid compiler
+ * errors.
+ */
+#include <stdint.h>
+#include "optrom.h"
+#include "optrom_fw_cfg.h"
static inline void set_es(void *addr)
{
asm("movl %0, %%es" : : "r"(seg));
}
-#ifdef __clang__
-#define ADDR32
-#else
-#define ADDR32 "addr32 "
-#endif
-
static inline uint16_t readw_es(uint16_t offset)
{
uint16_t val;
asm(ADDR32 "movl %0, %%es:(%1)" : : "r"(val), "r"((uint32_t)offset));
}
-static inline uint32_t bswap32(uint32_t x)
-{
- asm("bswapl %0" : "=r" (x) : "0" (x));
- return x;
-}
-
-static inline uint64_t bswap64(uint64_t x)
-{
- asm("bswapl %%eax; bswapl %%edx; xchg %%eax, %%edx" : "=A" (x) : "0" (x));
- return x;
-}
-
-static inline uint64_t cpu_to_be64(uint64_t x)
-{
- return bswap64(x);
-}
-
-static inline uint32_t cpu_to_be32(uint32_t x)
-{
- return bswap32(x);
-}
-
-static inline uint32_t be32_to_cpu(uint32_t x)
-{
- return bswap32(x);
-}
-
-/* clang is happy to inline this function, and bloats the
- * ROM.
- */
-static __attribute__((__noinline__))
-void bios_cfg_read_entry(void *buf, uint16_t entry, uint32_t len)
-{
- FWCfgDmaAccess access;
- uint32_t control = (entry << 16) | BIOS_CFG_DMA_CTL_SELECT
- | BIOS_CFG_DMA_CTL_READ;
-
- access.address = cpu_to_be64((uint64_t)(uint32_t)buf);
- access.length = cpu_to_be32(len);
- access.control = cpu_to_be32(control);
-
- barrier();
-
- outl(cpu_to_be32((uint32_t)&access), BIOS_CFG_DMA_ADDR_LOW);
-
- while (be32_to_cpu(access.control) & ~BIOS_CFG_DMA_CTL_ERROR) {
- barrier();
- }
-}
-
/* Return top of memory using BIOS function E801. */
static uint32_t get_e801_addr(void)
{
uint32_t initrd_end_page, max_allowed_page;
uint32_t segment_addr, stack_addr;
- bios_cfg_read_entry(&setup_addr, FW_CFG_SETUP_ADDR, 4);
- bios_cfg_read_entry(&setup_size, FW_CFG_SETUP_SIZE, 4);
- bios_cfg_read_entry(setup_addr, FW_CFG_SETUP_DATA, setup_size);
+ bios_cfg_read_entry_dma(&setup_addr, FW_CFG_SETUP_ADDR, 4);
+ bios_cfg_read_entry_dma(&setup_size, FW_CFG_SETUP_SIZE, 4);
+ bios_cfg_read_entry_dma(setup_addr, FW_CFG_SETUP_DATA, setup_size);
set_es(setup_addr);
writel_es(0x22c, 0x37ffffff);
}
- bios_cfg_read_entry(&initrd_addr, FW_CFG_INITRD_ADDR, 4);
- bios_cfg_read_entry(&initrd_size, FW_CFG_INITRD_SIZE, 4);
+ bios_cfg_read_entry_dma(&initrd_addr, FW_CFG_INITRD_ADDR, 4);
+ bios_cfg_read_entry_dma(&initrd_size, FW_CFG_INITRD_SIZE, 4);
initrd_end_page = ((uint32_t)(initrd_addr + initrd_size) & -4096);
max_allowed_page = (readl_es(0x22c) & -4096);
}
- bios_cfg_read_entry(initrd_addr, FW_CFG_INITRD_DATA, initrd_size);
+ bios_cfg_read_entry_dma(initrd_addr, FW_CFG_INITRD_DATA, initrd_size);
- bios_cfg_read_entry(&kernel_addr, FW_CFG_KERNEL_ADDR, 4);
- bios_cfg_read_entry(&kernel_size, FW_CFG_KERNEL_SIZE, 4);
- bios_cfg_read_entry(kernel_addr, FW_CFG_KERNEL_DATA, kernel_size);
+ bios_cfg_read_entry_dma(&kernel_addr, FW_CFG_KERNEL_ADDR, 4);
+ bios_cfg_read_entry_dma(&kernel_size, FW_CFG_KERNEL_SIZE, 4);
+ bios_cfg_read_entry_dma(kernel_addr, FW_CFG_KERNEL_DATA, kernel_size);
- bios_cfg_read_entry(&cmdline_addr, FW_CFG_CMDLINE_ADDR, 4);
- bios_cfg_read_entry(&cmdline_size, FW_CFG_CMDLINE_SIZE, 4);
- bios_cfg_read_entry(cmdline_addr, FW_CFG_CMDLINE_DATA, cmdline_size);
+ bios_cfg_read_entry_dma(&cmdline_addr, FW_CFG_CMDLINE_ADDR, 4);
+ bios_cfg_read_entry_dma(&cmdline_size, FW_CFG_CMDLINE_SIZE, 4);
+ bios_cfg_read_entry_dma(cmdline_addr, FW_CFG_CMDLINE_DATA, cmdline_size);
/* Boot linux */
segment_addr = ((uint32_t)setup_addr >> 4);
--- /dev/null
+/*
+ * Common Option ROM Functions for C code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (c) 2015-2019 Red Hat Inc.
+ * Authors:
+ * Marc Marà <marc.mari.barcelo@gmail.com>
+ * Richard W.M. Jones <rjones@redhat.com>
+ * Stefano Garzarella <sgarzare@redhat.com>
+ */
+
+#ifndef OPTROM_H
+#define OPTROM_H
+
+#include <stdint.h>
+#include "../../include/standard-headers/linux/qemu_fw_cfg.h"
+
+#define barrier() asm("" : : : "memory")
+
+#ifdef __clang__
+#define ADDR32
+#else
+#define ADDR32 "addr32 "
+#endif
+
+static inline void outb(uint8_t value, uint16_t port)
+{
+ asm volatile("outb %0, %w1" : : "a"(value), "Nd"(port));
+}
+
+static inline void outw(uint16_t value, uint16_t port)
+{
+ asm volatile("outw %0, %w1" : : "a"(value), "Nd"(port));
+}
+
+static inline void outl(uint32_t value, uint16_t port)
+{
+ asm volatile("outl %0, %w1" : : "a"(value), "Nd"(port));
+}
+
+static inline uint8_t inb(uint16_t port)
+{
+ uint8_t value;
+
+ asm volatile("inb %w1, %0" : "=a"(value) : "Nd"(port));
+ return value;
+}
+
+static inline uint16_t inw(uint16_t port)
+{
+ uint16_t value;
+
+ asm volatile("inw %w1, %0" : "=a"(value) : "Nd"(port));
+ return value;
+}
+
+static inline uint32_t inl(uint16_t port)
+{
+ uint32_t value;
+
+ asm volatile("inl %w1, %0" : "=a"(value) : "Nd"(port));
+ return value;
+}
+
+static inline void insb(uint16_t port, uint8_t *buf, uint32_t len)
+{
+ asm volatile("rep insb %%dx, %%es:(%%edi)"
+ : "+c"(len), "+D"(buf) : "d"(port) : "memory");
+}
+
+static inline uint32_t bswap32(uint32_t x)
+{
+ asm("bswapl %0" : "=r" (x) : "0" (x));
+ return x;
+}
+
+static inline uint64_t bswap64(uint64_t x)
+{
+ asm("bswapl %%eax; bswapl %%edx; xchg %%eax, %%edx" : "=A" (x) : "0" (x));
+ return x;
+}
+
+static inline uint64_t cpu_to_be64(uint64_t x)
+{
+ return bswap64(x);
+}
+
+static inline uint32_t cpu_to_be32(uint32_t x)
+{
+ return bswap32(x);
+}
+
+static inline uint32_t be32_to_cpu(uint32_t x)
+{
+ return bswap32(x);
+}
+
+#endif /* OPTROM_H */
--- /dev/null
+/*
+ * Common Option ROM Functions for fw_cfg
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (c) 2015-2019 Red Hat Inc.
+ * Authors:
+ * Marc Marà <marc.mari.barcelo@gmail.com>
+ * Richard W.M. Jones <rjones@redhat.com>
+ * Stefano Garzarella <sgarzare@redhat.com>
+ */
+
+#ifndef OPTROM_FW_CFG_H
+#define OPTROM_FW_CFG_H
+
+#include "../../include/standard-headers/linux/qemu_fw_cfg.h"
+
+#define BIOS_CFG_IOPORT_CFG 0x510
+#define BIOS_CFG_IOPORT_DATA 0x511
+#define BIOS_CFG_DMA_ADDR_HIGH 0x514
+#define BIOS_CFG_DMA_ADDR_LOW 0x518
+
+static __attribute__((unused))
+void bios_cfg_select(uint16_t key)
+{
+ outw(key, BIOS_CFG_IOPORT_CFG);
+}
+
+static __attribute__((unused))
+void bios_cfg_read_entry_io(void *buf, uint16_t entry, uint32_t len)
+{
+ bios_cfg_select(entry);
+ insb(BIOS_CFG_IOPORT_DATA, buf, len);
+}
+
+/*
+ * clang is happy to inline this function, and bloats the
+ * ROM.
+ */
+static __attribute__((__noinline__)) __attribute__((unused))
+void bios_cfg_read_entry_dma(void *buf, uint16_t entry, uint32_t len)
+{
+ struct fw_cfg_dma_access access;
+ uint32_t control = (entry << 16) | FW_CFG_DMA_CTL_SELECT
+ | FW_CFG_DMA_CTL_READ;
+
+ access.address = cpu_to_be64((uint64_t)(uint32_t)buf);
+ access.length = cpu_to_be32(len);
+ access.control = cpu_to_be32(control);
+
+ barrier();
+
+ outl(cpu_to_be32((uint32_t)&access), BIOS_CFG_DMA_ADDR_LOW);
+
+ while (be32_to_cpu(access.control) & ~FW_CFG_DMA_CTL_ERROR) {
+ barrier();
+ }
+}
+
+static __attribute__((unused))
+void bios_cfg_read_entry(void *buf, uint16_t entry, uint32_t len,
+ uint32_t version)
+{
+ if (version & FW_CFG_VERSION_DMA) {
+ bios_cfg_read_entry_dma(buf, entry, len);
+ } else {
+ bios_cfg_read_entry_io(buf, entry, len);
+ }
+}
+
+static __attribute__((unused))
+uint32_t bios_cfg_version(void)
+{
+ uint32_t version;
+
+ bios_cfg_read_entry_io(&version, FW_CFG_ID, sizeof(version));
+
+ return version;
+}
+
+#endif /* OPTROM_FW_CFG_H */
--- /dev/null
+/*
+ * PVH Option ROM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright Novell Inc, 2009
+ * Authors: Alexander Graf <agraf@suse.de>
+ *
+ * Copyright (c) 2019 Red Hat Inc.
+ * Authors: Stefano Garzarella <sgarzare@redhat.com>
+ */
+
+#include "optionrom.h"
+
+#define BOOT_ROM_PRODUCT "PVH loader"
+
+#define GS_PROT_JUMP 0
+#define GS_GDT_DESC 6
+
+#ifdef OPTION_ROM_START
+#undef OPTION_ROM_START
+#endif
+#ifdef OPTION_ROM_END
+#undef OPTION_ROM_END
+#endif
+
+/*
+ * Redefine OPTION_ROM_START and OPTION_ROM_END, because this rom is produced
+ * linking multiple objects.
+ * signrom.py will add padding.
+ */
+#define OPTION_ROM_START \
+ .code16; \
+ .text; \
+ .global _start; \
+ _start:; \
+ .short 0xaa55; \
+ .byte 3; /* desired size in 512 units */
+
+#define OPTION_ROM_END \
+ _end:
+
+BOOT_ROM_START
+
+run_pvhboot:
+
+ cli
+ cld
+
+ mov %cs, %eax
+ shl $0x4, %eax
+
+ /* set up a long jump descriptor that is PC relative */
+
+ /* move stack memory to %gs */
+ mov %ss, %ecx
+ shl $0x4, %ecx
+ mov %esp, %ebx
+ add %ebx, %ecx
+ sub $0x20, %ecx
+ sub $0x30, %esp
+ shr $0x4, %ecx
+ mov %cx, %gs
+
+ /* now push the indirect jump descriptor there */
+ mov (prot_jump), %ebx
+ add %eax, %ebx
+ movl %ebx, %gs:GS_PROT_JUMP
+ mov $8, %bx
+ movw %bx, %gs:GS_PROT_JUMP + 4
+
+ /* fix the gdt descriptor to be PC relative */
+ movw (gdt_desc), %bx
+ movw %bx, %gs:GS_GDT_DESC
+ movl (gdt_desc+2), %ebx
+ add %eax, %ebx
+ movl %ebx, %gs:GS_GDT_DESC + 2
+
+ /* initialize HVM memmap table using int 0x15(e820) */
+
+ /* ES = pvh_e820 struct */
+ mov $pvh_e820, %eax
+ shr $4, %eax
+ mov %ax, %es
+
+ /* start storing memmap table at %es:8 (pvh_e820.table) */
+ mov $8,%edi
+ xor %ebx, %ebx
+ jmp memmap_loop
+
+memmap_loop_check:
+ /* pvh_e820 can contains up to 128 entries */
+ cmp $128, %ebx
+ je memmap_done
+
+memmap_loop:
+ /* entry size (hvm_memmap_table_entry) & max buffer size (int15) */
+ movl $24, %ecx
+ /* e820 */
+ movl $0x0000e820, %eax
+ /* 'SMAP' magic */
+ movl $0x534d4150, %edx
+ /* store counter value at %es:0 (pvh_e820.entries) */
+ movl %ebx, %es:0
+
+ int $0x15
+ /* error or last entry already done? */
+ jb memmap_err
+
+ /* %edi += entry size (hvm_memmap_table_entry) */
+ add $24, %edi
+
+ /* continuation value 0 means last entry */
+ test %ebx, %ebx
+ jnz memmap_loop_check
+
+ /* increase pvh_e820.entries to save the last entry */
+ movl %es:0, %ebx
+ inc %ebx
+
+memmap_done:
+ movl %ebx, %es:0
+
+memmap_err:
+
+ /* load the GDT before going into protected mode */
+lgdt:
+ data32 lgdt %gs:GS_GDT_DESC
+
+ /* get us to protected mode now */
+ movl $1, %eax
+ movl %eax, %cr0
+
+ /* the LJMP sets CS for us and gets us to 32-bit */
+ljmp:
+ data32 ljmp *%gs:GS_PROT_JUMP
+
+prot_mode:
+.code32
+
+ /* initialize all other segments */
+ movl $0x10, %eax
+ movl %eax, %ss
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %fs
+ movl %eax, %gs
+
+ jmp pvh_load_kernel
+
+/* Variables */
+.align 4, 0
+prot_jump: .long prot_mode
+ .short 8
+
+.align 4, 0
+gdt:
+ /* 0x00 */
+.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+ /*
+ * 0x08: code segment
+ * (base=0, limit=0xfffff, type=32bit code exec/read, DPL=0, 4k)
+ */
+.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00
+
+ /*
+ * 0x10: data segment
+ * (base=0, limit=0xfffff, type=32bit data read/write, DPL=0, 4k)
+ */
+.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00
+
+ /*
+ * 0x18: code segment
+ * (base=0, limit=0x0ffff, type=16bit code exec/read/conf, DPL=0, 1b)
+ */
+.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00
+
+ /*
+ * 0x20: data segment
+ * (base=0, limit=0x0ffff, type=16bit data read/write, DPL=0, 1b)
+ */
+.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00
+
+gdt_desc:
+.short (5 * 8) - 1
+.long gdt
+
+BOOT_ROM_END
--- /dev/null
+/*
+ * PVH Option ROM for fw_cfg DMA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (c) 2019 Red Hat Inc.
+ * Authors:
+ * Stefano Garzarella <sgarzare@redhat.com>
+ */
+
+asm (".code32"); /* this code will be executed in protected mode */
+
+#include <stddef.h>
+#include <stdint.h>
+#include "optrom.h"
+#include "optrom_fw_cfg.h"
+#include "../../include/hw/xen/start_info.h"
+
+#define RSDP_SIGNATURE 0x2052545020445352LL /* "RSD PTR " */
+#define RSDP_AREA_ADDR 0x000E0000
+#define RSDP_AREA_SIZE 2048
+#define EBDA_BASE_ADDR 0x0000040E
+#define EBDA_SIZE 1024
+
+#define E820_MAXENTRIES 128
+#define CMDLINE_BUFSIZE 4096
+
+/* e820 table filled in pvh.S using int 0x15 */
+struct pvh_e820_table {
+ uint32_t entries;
+ uint32_t reserved;
+ struct hvm_memmap_table_entry table[E820_MAXENTRIES];
+};
+
+struct pvh_e820_table pvh_e820 asm("pvh_e820") __attribute__ ((aligned));
+
+static struct hvm_start_info start_info;
+static struct hvm_modlist_entry ramdisk_mod;
+static uint8_t cmdline_buffer[CMDLINE_BUFSIZE];
+
+
+/* Search RSDP signature. */
+static uintptr_t search_rsdp(uint32_t start_addr, uint32_t end_addr)
+{
+ uint64_t *rsdp_p;
+
+ /* RSDP signature is always on a 16 byte boundary */
+ for (rsdp_p = (uint64_t *)start_addr; rsdp_p < (uint64_t *)end_addr;
+ rsdp_p += 2) {
+ if (*rsdp_p == RSDP_SIGNATURE) {
+ return (uintptr_t)rsdp_p;
+ }
+ }
+
+ return 0;
+}
+
+/* Force the asm name without leading underscore, even on Win32. */
+extern void pvh_load_kernel(void) asm("pvh_load_kernel");
+
+void pvh_load_kernel(void)
+{
+ void *cmdline_addr = &cmdline_buffer;
+ void *kernel_entry, *initrd_addr;
+ uint32_t cmdline_size, initrd_size, fw_cfg_version = bios_cfg_version();
+
+ start_info.magic = XEN_HVM_START_MAGIC_VALUE;
+ start_info.version = 1;
+
+ /*
+ * pvh_e820 is filled in the pvh.S before to switch in protected mode,
+ * because we can use int 0x15 only in real mode.
+ */
+ start_info.memmap_entries = pvh_e820.entries;
+ start_info.memmap_paddr = (uintptr_t)pvh_e820.table;
+
+ /*
+ * Search RSDP in the main BIOS area below 1 MB.
+ * SeaBIOS store the RSDP in this area, so we try it first.
+ */
+ start_info.rsdp_paddr = search_rsdp(RSDP_AREA_ADDR,
+ RSDP_AREA_ADDR + RSDP_AREA_SIZE);
+
+ /* Search RSDP in the EBDA if it is not found */
+ if (!start_info.rsdp_paddr) {
+ /*
+ * Th EBDA address is stored at EBDA_BASE_ADDR. It contains 2 bytes
+ * segment pointer to EBDA, so we must convert it to a linear address.
+ */
+ uint32_t ebda_paddr = ((uint32_t)*((uint16_t *)EBDA_BASE_ADDR)) << 4;
+ if (ebda_paddr > 0x400) {
+ uint32_t *ebda = (uint32_t *)ebda_paddr;
+
+ start_info.rsdp_paddr = search_rsdp(*ebda, *ebda + EBDA_SIZE);
+ }
+ }
+
+ bios_cfg_read_entry(&cmdline_size, FW_CFG_CMDLINE_SIZE, 4, fw_cfg_version);
+ bios_cfg_read_entry(cmdline_addr, FW_CFG_CMDLINE_DATA, cmdline_size,
+ fw_cfg_version);
+ start_info.cmdline_paddr = (uintptr_t)cmdline_addr;
+
+ /* Check if we have the initrd to load */
+ bios_cfg_read_entry(&initrd_size, FW_CFG_INITRD_SIZE, 4, fw_cfg_version);
+ if (initrd_size) {
+ bios_cfg_read_entry(&initrd_addr, FW_CFG_INITRD_ADDR, 4,
+ fw_cfg_version);
+ bios_cfg_read_entry(initrd_addr, FW_CFG_INITRD_DATA, initrd_size,
+ fw_cfg_version);
+
+ ramdisk_mod.paddr = (uintptr_t)initrd_addr;
+ ramdisk_mod.size = initrd_size;
+
+ /* The first module is always ramdisk. */
+ start_info.modlist_paddr = (uintptr_t)&ramdisk_mod;
+ start_info.nr_modules = 1;
+ }
+
+ bios_cfg_read_entry(&kernel_entry, FW_CFG_KERNEL_ENTRY, 4, fw_cfg_version);
+
+ asm volatile("jmp *%1" : : "b"(&start_info), "c"(kernel_entry));
+}
util-obj-y += opts-visitor.o qapi-clone-visitor.o
util-obj-y += qmp-event.o
util-obj-y += qapi-util.o
+
+QAPI_COMMON_MODULES = authz block-core block char common crypto introspect
+QAPI_COMMON_MODULES += job migration misc net rdma rocker run-state
+QAPI_COMMON_MODULES += sockets tpm trace transaction ui
+QAPI_TARGET_MODULES = target
+QAPI_MODULES = $(QAPI_COMMON_MODULES) $(QAPI_TARGET_MODULES)
+
+util-obj-y += qapi-builtin-types.o
+util-obj-y += $(QAPI_COMMON_MODULES:%=qapi-types-%.o)
+util-obj-y += qapi-builtin-visit.o
+util-obj-y += $(QAPI_COMMON_MODULES:%=qapi-visit-%.o)
+util-obj-y += qapi-emit-events.o
+util-obj-y += $(QAPI_COMMON_MODULES:%=qapi-events-%.o)
+
+common-obj-y = $(QAPI_COMMON_MODULES:%=qapi-commands-%.o)
+
+obj-y = qapi-introspect.o
+obj-y += $(QAPI_TARGET_MODULES:%=qapi-types-%.o)
+obj-y += qapi-types.o
+obj-y += $(QAPI_TARGET_MODULES:%=qapi-visit-%.o)
+obj-y += qapi-visit.o
+obj-y += $(QAPI_TARGET_MODULES:%=qapi-events-%.o)
+obj-y += qapi-events.o
+obj-y += $(QAPI_TARGET_MODULES:%=qapi-commands-%.o)
+obj-y += qapi-commands.o
--- /dev/null
+# -*- Mode: Python -*-
+#
+# QAPI authz definitions
+
+##
+# @QAuthZListPolicy:
+#
+# The authorization policy result
+#
+# @deny: deny access
+# @allow: allow access
+#
+# Since: 4.0
+##
+{ 'enum': 'QAuthZListPolicy',
+ 'prefix': 'QAUTHZ_LIST_POLICY',
+ 'data': ['deny', 'allow']}
+
+##
+# @QAuthZListFormat:
+#
+# The authorization policy match format
+#
+# @exact: an exact string match
+# @glob: string with ? and * shell wildcard support
+#
+# Since: 4.0
+##
+{ 'enum': 'QAuthZListFormat',
+ 'prefix': 'QAUTHZ_LIST_FORMAT',
+ 'data': ['exact', 'glob']}
+
+##
+# @QAuthZListRule:
+#
+# A single authorization rule.
+#
+# @match: a string or glob to match against a user identity
+# @policy: the result to return if @match evaluates to true
+# @format: the format of the @match rule (default 'exact')
+#
+# Since: 4.0
+##
+{ 'struct': 'QAuthZListRule',
+ 'data': {'match': 'str',
+ 'policy': 'QAuthZListPolicy',
+ '*format': 'QAuthZListFormat'}}
+
+##
+# @QAuthZListRuleListHack:
+#
+# Not exposed via QMP; hack to generate QAuthZListRuleList
+# for use internally by the code.
+#
+# Since: 4.0
+##
+{ 'struct': 'QAuthZListRuleListHack',
+ 'data': { 'unused': ['QAuthZListRule'] } }
# @encrypt: details about encryption parameters; only set if image
# is encrypted (since 2.10)
#
+# @bitmaps: A list of qcow2 bitmap details (since 4.0)
+#
# Since: 1.7
##
{ 'struct': 'ImageInfoSpecificQCow2',
'*lazy-refcounts': 'bool',
'*corrupt': 'bool',
'refcount-bits': 'int',
- '*encrypt': 'ImageInfoSpecificQCow2Encryption'
+ '*encrypt': 'ImageInfoSpecificQCow2Encryption',
+ '*bitmaps': ['Qcow2BitmapInfo']
} }
##
#
# An enumeration of possible states that a dirty bitmap can report to the user.
#
-# @frozen: The bitmap is currently in-use by a backup operation or block job,
-# and is immutable.
+# @frozen: The bitmap is currently in-use by some operation and is immutable.
+# If the bitmap was @active prior to the operation, new writes by the
+# guest are being recorded in a temporary buffer, and will not be lost.
+# Generally, bitmaps are cleared on successful use in an operation and
+# the temporary buffer is committed into the bitmap. On failure, the
+# temporary buffer is merged back into the bitmap without first
+# clearing it.
+# Please refer to the documentation for each bitmap-using operation,
+# See also @blockdev-backup, @drive-backup.
#
-# @disabled: The bitmap is currently in-use by an internal operation and is
-# read-only. It can still be deleted.
+# @disabled: The bitmap is not currently recording new writes by the guest.
+# This is requested explicitly via @block-dirty-bitmap-disable.
+# It can still be cleared, deleted, or used for backup operations.
#
# @active: The bitmap is actively monitoring for new writes, and can be cleared,
# deleted, or used for backup operations.
#
-# @locked: The bitmap is currently in-use by some operation and can not be
-# cleared, deleted, or used for backup operations. (Since 2.12)
+# @locked: The bitmap is currently in-use by some operation and is immutable.
+# If the bitmap was @active prior to the operation, it is still
+# recording new writes. If the bitmap was @disabled, it is not
+# recording new writes. (Since 2.12)
#
# Since: 2.4
##
#
# @status: current status of the dirty bitmap (since 2.4)
#
+# @persistent: true if the bitmap will eventually be flushed to persistent
+# storage (since 4.0)
+#
# Since: 1.3
##
{ 'struct': 'BlockDirtyInfo',
'data': {'*name': 'str', 'count': 'int', 'granularity': 'uint32',
- 'status': 'DirtyBitmapStatus'} }
+ 'status': 'DirtyBitmapStatus', 'persistent': 'bool' } }
+
+##
+# @Qcow2BitmapInfoFlags:
+#
+# An enumeration of flags that a bitmap can report to the user.
+#
+# @in-use: This flag is set by any process actively modifying the qcow2 file,
+# and cleared when the updated bitmap is flushed to the qcow2 image.
+# The presence of this flag in an offline image means that the bitmap
+# was not saved correctly after its last usage, and may contain
+# inconsistent data.
+#
+# @auto: The bitmap must reflect all changes of the virtual disk by any
+# application that would write to this qcow2 file.
+#
+# Since: 4.0
+##
+{ 'enum': 'Qcow2BitmapInfoFlags',
+ 'data': ['in-use', 'auto'] }
+
+##
+# @Qcow2BitmapInfo:
+#
+# Qcow2 bitmap information.
+#
+# @name: the name of the bitmap
+#
+# @granularity: granularity of the bitmap in bytes
+#
+# @flags: flags of the bitmap
+#
+# Since: 4.0
+##
+{ 'struct': 'Qcow2BitmapInfo',
+ 'data': {'name': 'str', 'granularity': 'uint32',
+ 'flags': ['Qcow2BitmapInfoFlags'] } }
##
# @BlockLatencyHistogramInfo:
# @block-dirty-bitmap-merge:
#
# Merge dirty bitmaps listed in @bitmaps to the @target dirty bitmap.
-# The @bitmaps dirty bitmaps are unchanged.
+# Dirty bitmaps in @bitmaps will be unchanged, except if it also appears
+# as the @target bitmap. Any bits already set in @target will still be
+# set after the merge, i.e., this operation does not clear the target.
# On error, @target is unchanged.
#
+# The resulting bitmap will count as dirty any clusters that were dirty in any
+# of the source bitmaps. This can be used to achieve backup checkpoints, or in
+# simpler usages, to copy bitmaps.
+#
# Returns: nothing on success
# If @node is not a valid block device, DeviceNotFound
# If any bitmap in @bitmaps or @target is not found, GenericError
##
# @x-debug-block-dirty-bitmap-sha256:
#
-# Get bitmap SHA256
+# Get bitmap SHA256.
#
# Returns: BlockDirtyBitmapSha256 on success
# If @node is not a valid block device, DeviceNotFound
##
# @BlockdevQcow2EncryptionFormat:
-# @aes: AES-CBC with plain64 initialization venctors
+# @aes: AES-CBC with plain64 initialization vectors
#
# Since: 2.10
##
##
# @query-events:
#
-# Return a list of supported QMP events by this server
+# Return information on QMP events.
#
-# Returns: A list of @EventInfo for all supported events
+# Returns: A list of @EventInfo.
#
# Since: 1.2.0
#
+# Note: This command is deprecated, because its output doesn't reflect
+# compile-time configuration. Use query-qmp-schema instead.
+#
# Example:
#
# -> { "execute": "query-events" }
{ 'command': 'query-dump-guest-memory-capability',
'returns': 'DumpGuestMemoryCapability' }
-##
-# @dump-skeys:
-#
-# Dump guest's storage keys
-#
-# @filename: the path to the file to dump to
-#
-# This command is only supported on s390 architecture.
-#
-# Since: 2.5
-#
-# Example:
-#
-# -> { "execute": "dump-skeys",
-# "arguments": { "filename": "/tmp/skeys" } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'dump-skeys',
- 'data': { 'filename': 'str' } }
-
##
# @object-add:
#
##
{ 'command': 'query-current-machine', 'returns': 'CurrentMachineParams' }
-##
-# @CpuDefinitionInfo:
-#
-# Virtual CPU definition.
-#
-# @name: the name of the CPU definition
-#
-# @migration-safe: whether a CPU definition can be safely used for
-# migration in combination with a QEMU compatibility machine
-# when migrating between different QEMU versions and between
-# hosts with different sets of (hardware or software)
-# capabilities. If not provided, information is not available
-# and callers should not assume the CPU definition to be
-# migration-safe. (since 2.8)
-#
-# @static: whether a CPU definition is static and will not change depending on
-# QEMU version, machine type, machine options and accelerator options.
-# A static model is always migration-safe. (since 2.8)
-#
-# @unavailable-features: List of properties that prevent
-# the CPU model from running in the current
-# host. (since 2.8)
-# @typename: Type name that can be used as argument to @device-list-properties,
-# to introspect properties configurable using -cpu or -global.
-# (since 2.9)
-#
-# @unavailable-features is a list of QOM property names that
-# represent CPU model attributes that prevent the CPU from running.
-# If the QOM property is read-only, that means there's no known
-# way to make the CPU model run in the current host. Implementations
-# that choose not to provide specific information return the
-# property name "type".
-# If the property is read-write, it means that it MAY be possible
-# to run the CPU model in the current host if that property is
-# changed. Management software can use it as hints to suggest or
-# choose an alternative for the user, or just to generate meaningful
-# error messages explaining why the CPU model can't be used.
-# If @unavailable-features is an empty list, the CPU model is
-# runnable using the current host and machine-type.
-# If @unavailable-features is not present, runnability
-# information for the CPU is not available.
-#
-# Since: 1.2.0
-##
-{ 'struct': 'CpuDefinitionInfo',
- 'data': { 'name': 'str', '*migration-safe': 'bool', 'static': 'bool',
- '*unavailable-features': [ 'str' ], 'typename': 'str' } }
-
##
# @MemoryInfo:
#
##
{ 'command': 'query-memory-size-summary', 'returns': 'MemoryInfo' }
-##
-# @query-cpu-definitions:
-#
-# Return a list of supported virtual CPU definitions
-#
-# Returns: a list of CpuDefInfo
-#
-# Since: 1.2.0
-##
-{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] }
##
# @CpuModelInfo:
'data': [ 'static', 'full' ] }
-##
-# @CpuModelExpansionInfo:
-#
-# The result of a cpu model expansion.
-#
-# @model: the expanded CpuModelInfo.
-#
-# Since: 2.8.0
-##
-{ 'struct': 'CpuModelExpansionInfo',
- 'data': { 'model': 'CpuModelInfo' } }
-
-
-##
-# @query-cpu-model-expansion:
-#
-# Expands a given CPU model (or a combination of CPU model + additional options)
-# to different granularities, allowing tooling to get an understanding what a
-# specific CPU model looks like in QEMU under a certain configuration.
-#
-# This interface can be used to query the "host" CPU model.
-#
-# The data returned by this command may be affected by:
-#
-# * QEMU version: CPU models may look different depending on the QEMU version.
-# (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine-type: CPU model may look different depending on the machine-type.
-# (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine options (including accelerator): in some architectures, CPU models
-# may look different depending on machine and accelerator options. (Except for
-# CPU models reported as "static" in query-cpu-definitions.)
-# * "-cpu" arguments and global properties: arguments to the -cpu option and
-# global properties may affect expansion of CPU models. Using
-# query-cpu-model-expansion while using these is not advised.
-#
-# Some architectures may not support all expansion types. s390x supports
-# "full" and "static".
-#
-# Returns: a CpuModelExpansionInfo. Returns an error if expanding CPU models is
-# not supported, if the model cannot be expanded, if the model contains
-# an unknown CPU definition name, unknown properties or properties
-# with a wrong type. Also returns an error if an expansion type is
-# not supported.
-#
-# Since: 2.8.0
-##
-{ 'command': 'query-cpu-model-expansion',
- 'data': { 'type': 'CpuModelExpansionType',
- 'model': 'CpuModelInfo' },
- 'returns': 'CpuModelExpansionInfo' }
-
##
# @CpuModelCompareResult:
#
{ 'enum': 'CpuModelCompareResult',
'data': [ 'incompatible', 'identical', 'superset', 'subset' ] }
-##
-# @CpuModelCompareInfo:
-#
-# The result of a CPU model comparison.
-#
-# @result: The result of the compare operation.
-# @responsible-properties: List of properties that led to the comparison result
-# not being identical.
-#
-# @responsible-properties is a list of QOM property names that led to
-# both CPUs not being detected as identical. For identical models, this
-# list is empty.
-# If a QOM property is read-only, that means there's no known way to make the
-# CPU models identical. If the special property name "type" is included, the
-# models are by definition not identical and cannot be made identical.
-#
-# Since: 2.8.0
-##
-{ 'struct': 'CpuModelCompareInfo',
- 'data': {'result': 'CpuModelCompareResult',
- 'responsible-properties': ['str']
- }
-}
-
-##
-# @query-cpu-model-comparison:
-#
-# Compares two CPU models, returning how they compare in a specific
-# configuration. The results indicates how both models compare regarding
-# runnability. This result can be used by tooling to make decisions if a
-# certain CPU model will run in a certain configuration or if a compatible
-# CPU model has to be created by baselining.
-#
-# Usually, a CPU model is compared against the maximum possible CPU model
-# of a certain configuration (e.g. the "host" model for KVM). If that CPU
-# model is identical or a subset, it will run in that configuration.
-#
-# The result returned by this command may be affected by:
-#
-# * QEMU version: CPU models may look different depending on the QEMU version.
-# (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine-type: CPU model may look different depending on the machine-type.
-# (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine options (including accelerator): in some architectures, CPU models
-# may look different depending on machine and accelerator options. (Except for
-# CPU models reported as "static" in query-cpu-definitions.)
-# * "-cpu" arguments and global properties: arguments to the -cpu option and
-# global properties may affect expansion of CPU models. Using
-# query-cpu-model-expansion while using these is not advised.
-#
-# Some architectures may not support comparing CPU models. s390x supports
-# comparing CPU models.
-#
-# Returns: a CpuModelBaselineInfo. Returns an error if comparing CPU models is
-# not supported, if a model cannot be used, if a model contains
-# an unknown cpu definition name, unknown properties or properties
-# with wrong types.
-#
-# Since: 2.8.0
-##
-{ 'command': 'query-cpu-model-comparison',
- 'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
- 'returns': 'CpuModelCompareInfo' }
-
-##
-# @CpuModelBaselineInfo:
-#
-# The result of a CPU model baseline.
-#
-# @model: the baselined CpuModelInfo.
-#
-# Since: 2.8.0
-##
-{ 'struct': 'CpuModelBaselineInfo',
- 'data': { 'model': 'CpuModelInfo' } }
-
-##
-# @query-cpu-model-baseline:
-#
-# Baseline two CPU models, creating a compatible third model. The created
-# model will always be a static, migration-safe CPU model (see "static"
-# CPU model expansion for details).
-#
-# This interface can be used by tooling to create a compatible CPU model out
-# two CPU models. The created CPU model will be identical to or a subset of
-# both CPU models when comparing them. Therefore, the created CPU model is
-# guaranteed to run where the given CPU models run.
-#
-# The result returned by this command may be affected by:
-#
-# * QEMU version: CPU models may look different depending on the QEMU version.
-# (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine-type: CPU model may look different depending on the machine-type.
-# (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine options (including accelerator): in some architectures, CPU models
-# may look different depending on machine and accelerator options. (Except for
-# CPU models reported as "static" in query-cpu-definitions.)
-# * "-cpu" arguments and global properties: arguments to the -cpu option and
-# global properties may affect expansion of CPU models. Using
-# query-cpu-model-expansion while using these is not advised.
-#
-# Some architectures may not support baselining CPU models. s390x supports
-# baselining CPU models.
-#
-# Returns: a CpuModelBaselineInfo. Returns an error if baselining CPU models is
-# not supported, if a model cannot be used, if a model contains
-# an unknown cpu definition name, unknown properties or properties
-# with wrong types.
-#
-# Since: 2.8.0
-##
-{ 'command': 'query-cpu-model-baseline',
- 'data': { 'modela': 'CpuModelInfo',
- 'modelb': 'CpuModelInfo' },
- 'returns': 'CpuModelBaselineInfo' }
-
##
# @AddfdInfo:
#
{ 'event': 'ACPI_DEVICE_OST',
'data': { 'info': 'ACPIOSTInfo' } }
-##
-# @rtc-reset-reinjection:
-#
-# This command will reset the RTC interrupt reinjection backlog.
-# Can be used if another mechanism to synchronize guest time
-# is in effect, for example QEMU guest agent's guest-set-time
-# command.
-#
-# Since: 2.1
-#
-# Example:
-#
-# -> { "execute": "rtc-reset-reinjection" }
-# <- { "return": {} }
-#
-##
-{ 'command': 'rtc-reset-reinjection' }
-
-##
-# @RTC_CHANGE:
-#
-# Emitted when the guest changes the RTC time.
-#
-# @offset: offset between base RTC clock (as specified by -rtc base), and
-# new RTC clock value. Note that value will be different depending
-# on clock chosen to drive RTC (specified by -rtc clock).
-#
-# Note: This event is rate-limited.
-#
-# Since: 0.13.0
-#
-# Example:
-#
-# <- { "event": "RTC_CHANGE",
-# "data": { "offset": 78 },
-# "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
-#
-##
-{ 'event': 'RTC_CHANGE',
- 'data': { 'offset': 'int' } }
-
##
# @ReplayMode:
#
##
{ 'command': 'xen-load-devices-state', 'data': {'filename': 'str'} }
-##
-# @GICCapability:
-#
-# The struct describes capability for a specific GIC (Generic
-# Interrupt Controller) version. These bits are not only decided by
-# QEMU/KVM software version, but also decided by the hardware that
-# the program is running upon.
-#
-# @version: version of GIC to be described. Currently, only 2 and 3
-# are supported.
-#
-# @emulated: whether current QEMU/hardware supports emulated GIC
-# device in user space.
-#
-# @kernel: whether current QEMU/hardware supports hardware
-# accelerated GIC device in kernel.
-#
-# Since: 2.6
-##
-{ 'struct': 'GICCapability',
- 'data': { 'version': 'int',
- 'emulated': 'bool',
- 'kernel': 'bool' } }
-
-##
-# @query-gic-capabilities:
-#
-# This command is ARM-only. It will return a list of GICCapability
-# objects that describe its capability bits.
-#
-# Returns: a list of GICCapability objects.
-#
-# Since: 2.6
-#
-# Example:
-#
-# -> { "execute": "query-gic-capabilities" }
-# <- { "return": [{ "version": 2, "emulated": true, "kernel": false },
-# { "version": 3, "emulated": false, "kernel": true } ] }
-#
-##
-{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'] }
-
##
# @CpuInstanceProperties:
#
##
{ 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
-
-##
-# @SevState:
-#
-# An enumeration of SEV state information used during @query-sev.
-#
-# @uninit: The guest is uninitialized.
-#
-# @launch-update: The guest is currently being launched; plaintext data and
-# register state is being imported.
-#
-# @launch-secret: The guest is currently being launched; ciphertext data
-# is being imported.
-#
-# @running: The guest is fully launched or migrated in.
-#
-# @send-update: The guest is currently being migrated out to another machine.
-#
-# @receive-update: The guest is currently being migrated from another machine.
-#
-# Since: 2.12
-##
-{ 'enum': 'SevState',
- 'data': ['uninit', 'launch-update', 'launch-secret', 'running',
- 'send-update', 'receive-update' ] }
-
-##
-# @SevInfo:
-#
-# Information about Secure Encrypted Virtualization (SEV) support
-#
-# @enabled: true if SEV is active
-#
-# @api-major: SEV API major version
-#
-# @api-minor: SEV API minor version
-#
-# @build-id: SEV FW build id
-#
-# @policy: SEV policy value
-#
-# @state: SEV guest state
-#
-# @handle: SEV firmware handle
-#
-# Since: 2.12
-##
-{ 'struct': 'SevInfo',
- 'data': { 'enabled': 'bool',
- 'api-major': 'uint8',
- 'api-minor' : 'uint8',
- 'build-id' : 'uint8',
- 'policy' : 'uint32',
- 'state' : 'SevState',
- 'handle' : 'uint32'
- }
-}
-
-##
-# @query-sev:
-#
-# Returns information about SEV
-#
-# Returns: @SevInfo
-#
-# Since: 2.12
-#
-# Example:
-#
-# -> { "execute": "query-sev" }
-# <- { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0,
-# "build-id" : 0, "policy" : 0, "state" : "running",
-# "handle" : 1 } }
-#
-##
-{ 'command': 'query-sev', 'returns': 'SevInfo' }
-
-##
-# @SevLaunchMeasureInfo:
-#
-# SEV Guest Launch measurement information
-#
-# @data: the measurement value encoded in base64
-#
-# Since: 2.12
-#
-##
-{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'} }
-
-##
-# @query-sev-launch-measure:
-#
-# Query the SEV guest launch information.
-#
-# Returns: The @SevLaunchMeasureInfo for the guest
-#
-# Since: 2.12
-#
-# Example:
-#
-# -> { "execute": "query-sev-launch-measure" }
-# <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
-#
-##
-{ 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo' }
-
-##
-# @SevCapability:
-#
-# The struct describes capability for a Secure Encrypted Virtualization
-# feature.
-#
-# @pdh: Platform Diffie-Hellman key (base64 encoded)
-#
-# @cert-chain: PDH certificate chain (base64 encoded)
-#
-# @cbitpos: C-bit location in page table entry
-#
-# @reduced-phys-bits: Number of physical Address bit reduction when SEV is
-# enabled
-#
-# Since: 2.12
-##
-{ 'struct': 'SevCapability',
- 'data': { 'pdh': 'str',
- 'cert-chain': 'str',
- 'cbitpos': 'int',
- 'reduced-phys-bits': 'int'} }
-
-##
-# @query-sev-capabilities:
-#
-# This command is used to get the SEV capabilities, and is supported on AMD
-# X86 platforms only.
-#
-# Returns: SevCapability objects.
-#
-# Since: 2.12
-#
-# Example:
-#
-# -> { "execute": "query-sev-capabilities" }
-# <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE",
-# "cbitpos": 47, "reduced-phys-bits": 5}}
-#
-##
-{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability' }
-
##
# @set-numa-node:
#
{ 'include': 'rocker.json' }
{ 'include': 'tpm.json' }
{ 'include': 'ui.json' }
+{ 'include': 'authz.json' }
{ 'include': 'migration.json' }
{ 'include': 'transaction.json' }
{ 'include': 'trace.json' }
{ 'include': 'introspect.json' }
{ 'include': 'misc.json' }
+{ 'include': 'target.json' }
QTAILQ_INSERT_TAIL(cmds, cmd, node);
}
-void qmp_unregister_command(QmpCommandList *cmds, const char *name)
-{
- QmpCommand *cmd = qmp_find_command(cmds, name);
-
- QTAILQ_REMOVE(cmds, cmd, node);
- g_free(cmd);
-}
-
QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name)
{
QmpCommand *cmd;
--- /dev/null
+# -*- Mode: Python -*-
+#
+
+##
+# = Target-specific commands & events
+##
+
+{ 'include': 'misc.json' }
+
+##
+# @RTC_CHANGE:
+#
+# Emitted when the guest changes the RTC time.
+#
+# @offset: offset between base RTC clock (as specified by -rtc base), and
+# new RTC clock value
+#
+# Note: This event is rate-limited.
+#
+# Since: 0.13.0
+#
+# Example:
+#
+# <- { "event": "RTC_CHANGE",
+# "data": { "offset": 78 },
+# "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
+#
+##
+{ 'event': 'RTC_CHANGE',
+ 'data': { 'offset': 'int' },
+ 'if': 'defined(TARGET_ALPHA) || defined(TARGET_ARM) || defined(TARGET_HPPA) || defined(TARGET_I386) || defined(TARGET_MIPS) || defined(TARGET_MIPS64) || defined(TARGET_MOXIE) || defined(TARGET_PPC) || defined(TARGET_PPC64) || defined(TARGET_S390X) || defined(TARGET_SH4) || defined(TARGET_SPARC)' }
+
+##
+# @rtc-reset-reinjection:
+#
+# This command will reset the RTC interrupt reinjection backlog.
+# Can be used if another mechanism to synchronize guest time
+# is in effect, for example QEMU guest agent's guest-set-time
+# command.
+#
+# Since: 2.1
+#
+# Example:
+#
+# -> { "execute": "rtc-reset-reinjection" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'rtc-reset-reinjection',
+ 'if': 'defined(TARGET_I386)' }
+
+
+##
+# @SevState:
+#
+# An enumeration of SEV state information used during @query-sev.
+#
+# @uninit: The guest is uninitialized.
+#
+# @launch-update: The guest is currently being launched; plaintext data and
+# register state is being imported.
+#
+# @launch-secret: The guest is currently being launched; ciphertext data
+# is being imported.
+#
+# @running: The guest is fully launched or migrated in.
+#
+# @send-update: The guest is currently being migrated out to another machine.
+#
+# @receive-update: The guest is currently being migrated from another machine.
+#
+# Since: 2.12
+##
+{ 'enum': 'SevState',
+ 'data': ['uninit', 'launch-update', 'launch-secret', 'running',
+ 'send-update', 'receive-update' ],
+ 'if': 'defined(TARGET_I386)' }
+
+##
+# @SevInfo:
+#
+# Information about Secure Encrypted Virtualization (SEV) support
+#
+# @enabled: true if SEV is active
+#
+# @api-major: SEV API major version
+#
+# @api-minor: SEV API minor version
+#
+# @build-id: SEV FW build id
+#
+# @policy: SEV policy value
+#
+# @state: SEV guest state
+#
+# @handle: SEV firmware handle
+#
+# Since: 2.12
+##
+{ 'struct': 'SevInfo',
+ 'data': { 'enabled': 'bool',
+ 'api-major': 'uint8',
+ 'api-minor' : 'uint8',
+ 'build-id' : 'uint8',
+ 'policy' : 'uint32',
+ 'state' : 'SevState',
+ 'handle' : 'uint32'
+ },
+ 'if': 'defined(TARGET_I386)'
+}
+
+##
+# @query-sev:
+#
+# Returns information about SEV
+#
+# Returns: @SevInfo
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "query-sev" }
+# <- { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0,
+# "build-id" : 0, "policy" : 0, "state" : "running",
+# "handle" : 1 } }
+#
+##
+{ 'command': 'query-sev', 'returns': 'SevInfo',
+ 'if': 'defined(TARGET_I386)' }
+
+
+##
+# @SevLaunchMeasureInfo:
+#
+# SEV Guest Launch measurement information
+#
+# @data: the measurement value encoded in base64
+#
+# Since: 2.12
+#
+##
+{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'},
+ 'if': 'defined(TARGET_I386)' }
+
+##
+# @query-sev-launch-measure:
+#
+# Query the SEV guest launch information.
+#
+# Returns: The @SevLaunchMeasureInfo for the guest
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "query-sev-launch-measure" }
+# <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
+#
+##
+{ 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo',
+ 'if': 'defined(TARGET_I386)' }
+
+
+##
+# @SevCapability:
+#
+# The struct describes capability for a Secure Encrypted Virtualization
+# feature.
+#
+# @pdh: Platform Diffie-Hellman key (base64 encoded)
+#
+# @cert-chain: PDH certificate chain (base64 encoded)
+#
+# @cbitpos: C-bit location in page table entry
+#
+# @reduced-phys-bits: Number of physical Address bit reduction when SEV is
+# enabled
+#
+# Since: 2.12
+##
+{ 'struct': 'SevCapability',
+ 'data': { 'pdh': 'str',
+ 'cert-chain': 'str',
+ 'cbitpos': 'int',
+ 'reduced-phys-bits': 'int'},
+ 'if': 'defined(TARGET_I386)' }
+
+##
+# @query-sev-capabilities:
+#
+# This command is used to get the SEV capabilities, and is supported on AMD
+# X86 platforms only.
+#
+# Returns: SevCapability objects.
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "query-sev-capabilities" }
+# <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE",
+# "cbitpos": 47, "reduced-phys-bits": 5}}
+#
+##
+{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
+ 'if': 'defined(TARGET_I386)' }
+
+##
+# @dump-skeys:
+#
+# Dump guest's storage keys
+#
+# @filename: the path to the file to dump to
+#
+# This command is only supported on s390 architecture.
+#
+# Since: 2.5
+#
+# Example:
+#
+# -> { "execute": "dump-skeys",
+# "arguments": { "filename": "/tmp/skeys" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'dump-skeys',
+ 'data': { 'filename': 'str' },
+ 'if': 'defined(TARGET_S390X)' }
+
+##
+# @CpuModelBaselineInfo:
+#
+# The result of a CPU model baseline.
+#
+# @model: the baselined CpuModelInfo.
+#
+# Since: 2.8.0
+##
+{ 'struct': 'CpuModelBaselineInfo',
+ 'data': { 'model': 'CpuModelInfo' },
+ 'if': 'defined(TARGET_S390X)' }
+
+##
+# @CpuModelCompareInfo:
+#
+# The result of a CPU model comparison.
+#
+# @result: The result of the compare operation.
+# @responsible-properties: List of properties that led to the comparison result
+# not being identical.
+#
+# @responsible-properties is a list of QOM property names that led to
+# both CPUs not being detected as identical. For identical models, this
+# list is empty.
+# If a QOM property is read-only, that means there's no known way to make the
+# CPU models identical. If the special property name "type" is included, the
+# models are by definition not identical and cannot be made identical.
+#
+# Since: 2.8.0
+##
+{ 'struct': 'CpuModelCompareInfo',
+ 'data': { 'result': 'CpuModelCompareResult',
+ 'responsible-properties': ['str'] },
+ 'if': 'defined(TARGET_S390X)' }
+
+##
+# @query-cpu-model-comparison:
+#
+# Compares two CPU models, returning how they compare in a specific
+# configuration. The results indicates how both models compare regarding
+# runnability. This result can be used by tooling to make decisions if a
+# certain CPU model will run in a certain configuration or if a compatible
+# CPU model has to be created by baselining.
+#
+# Usually, a CPU model is compared against the maximum possible CPU model
+# of a certain configuration (e.g. the "host" model for KVM). If that CPU
+# model is identical or a subset, it will run in that configuration.
+#
+# The result returned by this command may be affected by:
+#
+# * QEMU version: CPU models may look different depending on the QEMU version.
+# (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine-type: CPU model may look different depending on the machine-type.
+# (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine options (including accelerator): in some architectures, CPU models
+# may look different depending on machine and accelerator options. (Except for
+# CPU models reported as "static" in query-cpu-definitions.)
+# * "-cpu" arguments and global properties: arguments to the -cpu option and
+# global properties may affect expansion of CPU models. Using
+# query-cpu-model-expansion while using these is not advised.
+#
+# Some architectures may not support comparing CPU models. s390x supports
+# comparing CPU models.
+#
+# Returns: a CpuModelBaselineInfo. Returns an error if comparing CPU models is
+# not supported, if a model cannot be used, if a model contains
+# an unknown cpu definition name, unknown properties or properties
+# with wrong types.
+#
+# Note: this command isn't specific to s390x, but is only implemented
+# on this architecture currently.
+#
+# Since: 2.8.0
+##
+{ 'command': 'query-cpu-model-comparison',
+ 'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
+ 'returns': 'CpuModelCompareInfo',
+ 'if': 'defined(TARGET_S390X)' }
+
+##
+# @query-cpu-model-baseline:
+#
+# Baseline two CPU models, creating a compatible third model. The created
+# model will always be a static, migration-safe CPU model (see "static"
+# CPU model expansion for details).
+#
+# This interface can be used by tooling to create a compatible CPU model out
+# two CPU models. The created CPU model will be identical to or a subset of
+# both CPU models when comparing them. Therefore, the created CPU model is
+# guaranteed to run where the given CPU models run.
+#
+# The result returned by this command may be affected by:
+#
+# * QEMU version: CPU models may look different depending on the QEMU version.
+# (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine-type: CPU model may look different depending on the machine-type.
+# (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine options (including accelerator): in some architectures, CPU models
+# may look different depending on machine and accelerator options. (Except for
+# CPU models reported as "static" in query-cpu-definitions.)
+# * "-cpu" arguments and global properties: arguments to the -cpu option and
+# global properties may affect expansion of CPU models. Using
+# query-cpu-model-expansion while using these is not advised.
+#
+# Some architectures may not support baselining CPU models. s390x supports
+# baselining CPU models.
+#
+# Returns: a CpuModelBaselineInfo. Returns an error if baselining CPU models is
+# not supported, if a model cannot be used, if a model contains
+# an unknown cpu definition name, unknown properties or properties
+# with wrong types.
+#
+# Note: this command isn't specific to s390x, but is only implemented
+# on this architecture currently.
+#
+# Since: 2.8.0
+##
+{ 'command': 'query-cpu-model-baseline',
+ 'data': { 'modela': 'CpuModelInfo',
+ 'modelb': 'CpuModelInfo' },
+ 'returns': 'CpuModelBaselineInfo',
+ 'if': 'defined(TARGET_S390X)' }
+
+##
+# @GICCapability:
+#
+# The struct describes capability for a specific GIC (Generic
+# Interrupt Controller) version. These bits are not only decided by
+# QEMU/KVM software version, but also decided by the hardware that
+# the program is running upon.
+#
+# @version: version of GIC to be described. Currently, only 2 and 3
+# are supported.
+#
+# @emulated: whether current QEMU/hardware supports emulated GIC
+# device in user space.
+#
+# @kernel: whether current QEMU/hardware supports hardware
+# accelerated GIC device in kernel.
+#
+# Since: 2.6
+##
+{ 'struct': 'GICCapability',
+ 'data': { 'version': 'int',
+ 'emulated': 'bool',
+ 'kernel': 'bool' },
+ 'if': 'defined(TARGET_ARM)' }
+
+##
+# @query-gic-capabilities:
+#
+# This command is ARM-only. It will return a list of GICCapability
+# objects that describe its capability bits.
+#
+# Returns: a list of GICCapability objects.
+#
+# Since: 2.6
+#
+# Example:
+#
+# -> { "execute": "query-gic-capabilities" }
+# <- { "return": [{ "version": 2, "emulated": true, "kernel": false },
+# { "version": 3, "emulated": false, "kernel": true } ] }
+#
+##
+{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
+ 'if': 'defined(TARGET_ARM)' }
+
+##
+# @CpuModelExpansionInfo:
+#
+# The result of a cpu model expansion.
+#
+# @model: the expanded CpuModelInfo.
+#
+# Since: 2.8.0
+##
+{ 'struct': 'CpuModelExpansionInfo',
+ 'data': { 'model': 'CpuModelInfo' },
+ 'if': 'defined(TARGET_S390X) || defined(TARGET_I386)' }
+
+##
+# @query-cpu-model-expansion:
+#
+# Expands a given CPU model (or a combination of CPU model + additional options)
+# to different granularities, allowing tooling to get an understanding what a
+# specific CPU model looks like in QEMU under a certain configuration.
+#
+# This interface can be used to query the "host" CPU model.
+#
+# The data returned by this command may be affected by:
+#
+# * QEMU version: CPU models may look different depending on the QEMU version.
+# (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine-type: CPU model may look different depending on the machine-type.
+# (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine options (including accelerator): in some architectures, CPU models
+# may look different depending on machine and accelerator options. (Except for
+# CPU models reported as "static" in query-cpu-definitions.)
+# * "-cpu" arguments and global properties: arguments to the -cpu option and
+# global properties may affect expansion of CPU models. Using
+# query-cpu-model-expansion while using these is not advised.
+#
+# Some architectures may not support all expansion types. s390x supports
+# "full" and "static".
+#
+# Returns: a CpuModelExpansionInfo. Returns an error if expanding CPU models is
+# not supported, if the model cannot be expanded, if the model contains
+# an unknown CPU definition name, unknown properties or properties
+# with a wrong type. Also returns an error if an expansion type is
+# not supported.
+#
+# Since: 2.8.0
+##
+{ 'command': 'query-cpu-model-expansion',
+ 'data': { 'type': 'CpuModelExpansionType',
+ 'model': 'CpuModelInfo' },
+ 'returns': 'CpuModelExpansionInfo',
+ 'if': 'defined(TARGET_S390X) || defined(TARGET_I386)' }
+
+##
+# @CpuDefinitionInfo:
+#
+# Virtual CPU definition.
+#
+# @name: the name of the CPU definition
+#
+# @migration-safe: whether a CPU definition can be safely used for
+# migration in combination with a QEMU compatibility machine
+# when migrating between different QEMU versions and between
+# hosts with different sets of (hardware or software)
+# capabilities. If not provided, information is not available
+# and callers should not assume the CPU definition to be
+# migration-safe. (since 2.8)
+#
+# @static: whether a CPU definition is static and will not change depending on
+# QEMU version, machine type, machine options and accelerator options.
+# A static model is always migration-safe. (since 2.8)
+#
+# @unavailable-features: List of properties that prevent
+# the CPU model from running in the current
+# host. (since 2.8)
+# @typename: Type name that can be used as argument to @device-list-properties,
+# to introspect properties configurable using -cpu or -global.
+# (since 2.9)
+#
+# @unavailable-features is a list of QOM property names that
+# represent CPU model attributes that prevent the CPU from running.
+# If the QOM property is read-only, that means there's no known
+# way to make the CPU model run in the current host. Implementations
+# that choose not to provide specific information return the
+# property name "type".
+# If the property is read-write, it means that it MAY be possible
+# to run the CPU model in the current host if that property is
+# changed. Management software can use it as hints to suggest or
+# choose an alternative for the user, or just to generate meaningful
+# error messages explaining why the CPU model can't be used.
+# If @unavailable-features is an empty list, the CPU model is
+# runnable using the current host and machine-type.
+# If @unavailable-features is not present, runnability
+# information for the CPU is not available.
+#
+# Since: 1.2.0
+##
+{ 'struct': 'CpuDefinitionInfo',
+ 'data': { 'name': 'str',
+ '*migration-safe': 'bool',
+ 'static': 'bool',
+ '*unavailable-features': [ 'str' ],
+ 'typename': 'str' },
+ 'if': 'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386) || defined(TARGET_S390X) || defined(TARGET_MIPS)' }
+
+##
+# @query-cpu-definitions:
+#
+# Return a list of supported virtual CPU definitions
+#
+# Returns: a list of CpuDefInfo
+#
+# Since: 1.2.0
+##
+{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'],
+ 'if': 'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386) || defined(TARGET_S390X) || defined(TARGET_MIPS)' }
#
# Display (user interface) type.
#
+# @default: The default user interface, selecting from the first available
+# of gtk, sdl, cocoa, and vnc.
+#
+# @none: No user interface or video output display. The guest will
+# still see an emulated graphics card, but its output will not
+# be displayed to the QEMU user.
+#
+# @gtk: The GTK user interface.
+#
+# @sdl: The SDL user interface.
+#
+# @egl-headless: No user interface, offload GL operations to a local
+# DRI device. Graphical display need to be paired with
+# VNC or Spice. (Since 3.1)
+#
+# @curses: Display video output via curses. For graphics device
+# models which support a text mode, QEMU can display this
+# output using a curses/ncurses interface. Nothing is
+# displayed when the graphics device is in graphical mode or
+# if the graphics device does not support a text
+# mode. Generally only the VGA device models support text
+# mode.
+#
+# @cocoa: The Cocoa user interface.
+#
+# @spice-app: Set up a Spice server and run the default associated
+# application to connect to it. The server will redirect
+# the serial console and QEMU monitors. (Since 4.0)
+#
# Since: 2.12
#
##
{ 'enum' : 'DisplayType',
'data' : [ 'default', 'none', 'gtk', 'sdl',
- 'egl-headless', 'curses', 'cocoa' ] }
+ 'egl-headless', 'curses', 'cocoa',
+ 'spice-app'] }
##
# @DisplayOptions:
If using the new syntax, USB support must be explicitly
enabled via the ``-machine usb=on'' argument.
-@subsection -no-frame (since 2.12.0)
-
-The @code{--no-frame} argument works with SDL 1.2 only. The other user
-interfaces never implemented this in the first place. So this will be
-removed together with SDL 1.2 support.
-
-@subsection -virtioconsole (since 3.0.0)
-
-Option @option{-virtioconsole} has been replaced by
-@option{-device virtconsole}.
-
-@subsection -clock (since 3.0.0)
-
-The @code{-clock} option is ignored since QEMU version 1.7.0. There is no
-replacement since it is not needed anymore.
-
-@subsection -enable-hax (since 3.0.0)
-
-The @option{-enable-hax} option has been replaced by @option{-accel hax}.
-Both options have been introduced in QEMU version 2.9.0.
-
@subsection -drive file=json:@{...@{'driver':'file'@}@} (since 3.0)
The 'file' driver for drives is no longer appropriate for character or host
documentation of ``query-hotpluggable-cpus'' for additional
details.
+@subsection query-events (since 4.0)
+
+The ``query-events'' command has been superseded by the more powerful
+and accurate ``query-qmp-schema'' command.
+
@section Human Monitor Protocol (HMP) commands
@subsection The hub_id parameter of 'hostfwd_add' / 'hostfwd_remove' (since 3.1)
Cirrus (default) or any other PCI VGA graphics card
@end itemize
+The Boston board emulation supports the following devices:
+
+@itemize @minus
+@item
+Xilinx FPGA, which includes a PCIe root port and an UART
+@item
+Intel EG20T PCH connects the I/O peripherals, but only the SATA bus is emulated
+@end itemize
+
The ACER Pica emulation supports:
@itemize @minus
IDE controller
@end itemize
-The mipssim pseudo board emulation provides an environment similar
-to what the proprietary MIPS emulator uses for running Linux.
-It supports:
+The MIPS Magnum R4000 emulation supports:
@itemize @minus
@item
-A range of MIPS CPUs, default is the 24Kf
+MIPS R4000 CPU
@item
-PC style serial port
+PC-style IRQ controller
@item
-MIPSnet network emulation
+PC Keyboard
+@item
+SCSI controller
+@item
+G364 framebuffer
@end itemize
-The MIPS Magnum R4000 emulation supports:
+The Fulong 2E emulation supports:
@itemize @minus
@item
-MIPS R4000 CPU
+Loongson 2E CPU
@item
-PC-style IRQ controller
+Bonito64 system controller as North Bridge
@item
-PC Keyboard
+VT82C686 chipset as South Bridge
@item
-SCSI controller
+RTL8139D as a network card chipset
+@end itemize
+
+The mipssim pseudo board emulation provides an environment similar
+to what the proprietary MIPS emulator uses for running Linux.
+It supports:
+
+@itemize @minus
@item
-G364 framebuffer
+A range of MIPS CPUs, default is the 24Kf
+@item
+PC style serial port
+@item
+MIPSnet network emulation
@end itemize
@node nanoMIPS System emulator
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
goto fail;
}
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
ret = 2;
goto out4;
}
{
int n, ret;
QEMUIOVector qiov;
- struct iovec iov;
assert(nb_sectors <= s->buf_sectors);
while (nb_sectors > 0) {
bs_sectors = s->src_sectors[src_cur];
n = MIN(nb_sectors, bs_sectors - (sector_num - src_cur_offset));
- iov.iov_base = buf;
- iov.iov_len = n << BDRV_SECTOR_BITS;
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, buf, n << BDRV_SECTOR_BITS);
ret = blk_co_preadv(
blk, (sector_num - src_cur_offset) << BDRV_SECTOR_BITS,
{
int ret;
QEMUIOVector qiov;
- struct iovec iov;
while (nb_sectors > 0) {
int n = nb_sectors;
(s->compressed &&
!buffer_is_zero(buf, n * BDRV_SECTOR_SIZE)))
{
- iov.iov_base = buf;
- iov.iov_len = n << BDRV_SECTOR_BITS;
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, buf, n << BDRV_SECTOR_BITS);
ret = blk_co_pwritev(s->target, sector_num << BDRV_SECTOR_BITS,
n << BDRV_SECTOR_BITS, &qiov, flags);
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
goto fail_getopt;
}
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
BlockDriverState *file;
bool has_offset;
int64_t map;
+ char *filename = NULL;
/* As an optimization, we could cache the current range of unallocated
* clusters in each file of the chain, and avoid querying the same
has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID);
+ if (file && has_offset) {
+ bdrv_refresh_filename(file);
+ filename = file->filename;
+ }
+
*e = (MapEntry) {
.start = offset,
.length = bytes,
.offset = map,
.has_offset = has_offset,
.depth = depth,
- .has_filename = file && has_offset,
- .filename = file && has_offset ? file->filename : NULL,
+ .has_filename = filename,
+ .filename = filename,
};
return 0;
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
break;
case SNAPSHOT_DELETE:
- bdrv_snapshot_delete_by_id_or_name(bs, snapshot_name, &err);
- if (err) {
- error_reportf_err(err, "Could not delete snapshot '%s': ",
- snapshot_name);
+ ret = bdrv_snapshot_find(bs, &sn, snapshot_name);
+ if (ret < 0) {
+ error_report("Could not delete snapshot '%s': snapshot not "
+ "found", snapshot_name);
ret = 1;
+ } else {
+ ret = bdrv_snapshot_delete(bs, sn.id_str, sn.name, &err);
+ if (ret < 0) {
+ error_reportf_err(err, "Could not delete snapshot '%s': ",
+ snapshot_name);
+ ret = 1;
+ }
}
break;
}
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true);
}
+ bdrv_refresh_filename(bs);
overlay_filename = bs->exact_filename[0] ? bs->exact_filename
: bs->filename;
- out_real_path = g_malloc(PATH_MAX);
-
- bdrv_get_full_backing_filename_from_filename(overlay_filename,
- out_baseimg,
- out_real_path,
- PATH_MAX,
- &local_err);
+ out_real_path =
+ bdrv_get_full_backing_filename_from_filename(overlay_filename,
+ out_baseimg,
+ &local_err);
if (local_err) {
error_reportf_err(local_err,
"Could not resolve backing filename: ");
ret = -1;
- g_free(out_real_path);
goto out;
}
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
ret = -1;
goto out_no_progress;
}
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
ret = -1;
goto out;
}
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
goto out;
}
BlockDriverState *bs = blk_bs(blk);
BlockDriverInfo bdi;
ImageInfoSpecific *spec_info;
+ Error *local_err = NULL;
char s1[64], s2[64];
int ret;
printf("cluster size: %s\n", s1);
printf("vm state offset: %s\n", s2);
- spec_info = bdrv_get_specific_info(bs);
+ spec_info = bdrv_get_specific_info(bs, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ return -EIO;
+ }
if (spec_info) {
printf("Format specific information:\n");
bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
ETEXI
DEF("display", HAS_ARG, QEMU_OPTION_display,
+ "-display spice-app[,gl=on|off]\n"
"-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n"
" [,window_close=on|off][,gl=on|core|es|off]\n"
"-display gtk[,grab_on_hover=on|off][,gl=on|off]|\n"
@item egl-headless
Offload all OpenGL operations to a local DRI device. For any graphical display,
this display needs to be paired with either VNC or SPICE displays.
+@item spice-app
+Start QEMU as a Spice server and launch the default Spice client
+application. The Spice server will redirect the serial consoles and
+QEMU monitors. (Since 4.0)
@end table
ETEXI
mode.
ETEXI
-DEF("no-frame", 0, QEMU_OPTION_no_frame,
- "-no-frame open SDL window without a frame and window decorations\n",
- QEMU_ARCH_ALL)
-STEXI
-@item -no-frame
-@findex -no-frame
-Do not use decorations for SDL windows and start them using the whole
-available screen space. This makes the using QEMU in a dedicated desktop
-workspace more convenient.
-ETEXI
-
DEF("alt-grab", 0, QEMU_OPTION_alt_grab,
"-alt-grab use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt)\n",
QEMU_ARCH_ALL)
if KVM support is enabled when compiling.
ETEXI
-DEF("enable-hax", 0, QEMU_OPTION_enable_hax, \
- "-enable-hax enable HAX virtualization support\n", QEMU_ARCH_I386)
-STEXI
-@item -enable-hax
-@findex -enable-hax
-Enable HAX (Hardware-based Acceleration eXecution) support. This option
-is only available if HAX support is enabled when compiling. HAX is only
-applicable to MAC and Windows platform, and thus does not conflict with
-KVM. This option is deprecated, use @option{-accel hax} instead.
-ETEXI
-
DEF("xen-domid", HAS_ARG, QEMU_OPTION_xen_domid,
"-xen-domid id specify xen guest domain id\n", QEMU_ARCH_ALL)
DEF("xen-attach", 0, QEMU_OPTION_xen_attach,
This option is useful to load things like EtherBoot.
ETEXI
-HXCOMM Silently ignored for compatibility
-DEF("clock", HAS_ARG, QEMU_OPTION_clock, "", QEMU_ARCH_ALL)
-
DEF("rtc", HAS_ARG, QEMU_OPTION_rtc, \
"-rtc [base=utc|localtime|<datetime>][,clock=host|rt|vm][,driftfix=none|slew]\n" \
" set the RTC base and clock, enable drift fix for clock ticks (x86 only)\n",
@end table
ETEXI
-DEF("virtioconsole", HAS_ARG, QEMU_OPTION_virtiocon, \
- "-virtioconsole c\n" \
- " set virtio console\n", QEMU_ARCH_ALL)
-STEXI
-@item -virtioconsole @var{c}
-@findex -virtioconsole
-Set virtio console.
-This option is deprecated, please use @option{-device virtconsole} instead.
-ETEXI
-
DEF("show-cursor", 0, QEMU_OPTION_show_cursor, \
"-show-cursor show cursor\n", QEMU_ARCH_ALL)
STEXI
.....
@end example
+
+
+@item -object authz-simple,id=@var{id},identity=@var{string}
+
+Create an authorization object that will control access to network services.
+
+The @option{identity} parameter is identifies the user and its format
+depends on the network service that authorization object is associated
+with. For authorizing based on TLS x509 certificates, the identity must
+be the x509 distinguished name. Note that care must be taken to escape
+any commas in the distinguished name.
+
+An example authorization object to validate a x509 distinguished name
+would look like:
+@example
+ # $QEMU \
+ ...
+ -object 'authz-simple,id=auth0,identity=CN=laptop.example.com,,O=Example Org,,L=London,,ST=London,,C=GB' \
+ ...
+@end example
+
+Note the use of quotes due to the x509 distinguished name containing
+whitespace, and escaping of ','.
+
+@item -object authz-listfile,id=@var{id},filename=@var{path},refresh=@var{yes|no}
+
+Create an authorization object that will control access to network services.
+
+The @option{filename} parameter is the fully qualified path to a file
+containing the access control list rules in JSON format.
+
+An example set of rules that match against SASL usernames might look
+like:
+
+@example
+ @{
+ "rules": [
+ @{ "match": "fred", "policy": "allow", "format": "exact" @},
+ @{ "match": "bob", "policy": "allow", "format": "exact" @},
+ @{ "match": "danb", "policy": "deny", "format": "glob" @},
+ @{ "match": "dan*", "policy": "allow", "format": "exact" @},
+ ],
+ "policy": "deny"
+ @}
+@end example
+
+When checking access the object will iterate over all the rules and
+the first rule to match will have its @option{policy} value returned
+as the result. If no rules match, then the default @option{policy}
+value is returned.
+
+The rules can either be an exact string match, or they can use the
+simple UNIX glob pattern matching to allow wildcards to be used.
+
+If @option{refresh} is set to true the file will be monitored
+and automatically reloaded whenever its content changes.
+
+As with the @code{authz-simple} object, the format of the identity
+strings being matched depends on the network service, but is usually
+a TLS x509 distinguished name, or a SASL username.
+
+An example authorization object to validate a SASL username
+would look like:
+@example
+ # $QEMU \
+ ...
+ -object authz-simple,id=auth0,filename=/etc/qemu/vnc-sasl.acl,refresh=yes
+ ...
+@end example
+
+@item -object authz-pam,id=@var{id},service=@var{string}
+
+Create an authorization object that will control access to network services.
+
+The @option{service} parameter provides the name of a PAM service to use
+for authorization. It requires that a file @code{/etc/pam.d/@var{service}}
+exist to provide the configuration for the @code{account} subsystem.
+
+An example authorization object to validate a TLS x509 distinguished
+name would look like:
+
+@example
+ # $QEMU \
+ ...
+ -object authz-pam,id=auth0,service=qemu-vnc
+ ...
+@end example
+
+There would then be a corresponding config file for PAM at
+@code{/etc/pam.d/qemu-vnc} that contains:
+
+@example
+account requisite pam_listfile.so item=user sense=allow \
+ file=/etc/qemu/vnc.allow
+@end example
+
+Finally the @code{/etc/qemu/vnc.allow} file would contain
+the list of x509 distingished names that are permitted
+access
+
+@example
+CN=laptop.example.com,O=Example Home,L=London,ST=London,C=GB
+@end example
+
+
@end table
ETEXI
return prop_list;
}
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
-{
- return arch_query_cpu_definitions(errp);
-}
-
-CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
- CpuModelInfo *model,
- Error **errp)
-{
- return arch_query_cpu_model_expansion(type, model, errp);
-}
-
-CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *modela,
- CpuModelInfo *modelb,
- Error **errp)
-{
- return arch_query_cpu_model_comparison(modela, modelb, errp);
-}
-
-CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *modela,
- CpuModelInfo *modelb,
- Error **errp)
-{
- return arch_query_cpu_model_baseline(modela, modelb, errp);
-}
-
void qmp_add_client(const char *protocol, const char *fdname,
bool has_skipauth, bool skipauth, bool has_tls, bool tls,
Error **errp)
goto error;
}
- object_property_add_child(parent, id, obj, &local_err);
- if (local_err) {
- goto error;
+ if (id != NULL) {
+ object_property_add_child(parent, id, obj, &local_err);
+ if (local_err) {
+ goto error;
+ }
}
uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
if (uc) {
user_creatable_complete(uc, &local_err);
if (local_err) {
- object_unparent(obj);
+ if (id != NULL) {
+ object_unparent(obj);
+ }
goto error;
}
}
goto out;
}
- object_property_add_child(object_get_objects_root(),
- id, obj, &local_err);
- if (local_err) {
- goto out;
+ if (id != NULL) {
+ object_property_add_child(object_get_objects_root(),
+ id, obj, &local_err);
+ if (local_err) {
+ goto out;
+ }
}
user_creatable_complete(USER_CREATABLE(obj), &local_err);
if (local_err) {
- object_property_del(object_get_objects_root(),
- id, &error_abort);
+ if (id != NULL) {
+ object_property_del(object_get_objects_root(),
+ id, &error_abort);
+ }
goto out;
}
out:
{
Chardev *chr;
- chr = qemu_chr_new("qtest", qtest_chrdev);
+ chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
if (chr == NULL) {
error_setg(errp, "Failed to initialize device for qtest: \"%s\"",
-Subproject commit 441a84d3a642a10b948369c63f32367e8ff6395b
+Subproject commit 3464681b2b5983df80086a40179d324102347da3
fi
git clone --shared . "$vroot_dir"
test $? -ne 0 && error "failed to clone into '$vroot_dir'"
+for sm in $submodules; do
+ if test -d "$sm/.git"
+ then
+ git clone --shared "$sm" "$vroot_dir/$sm"
+ test $? -ne 0 && error "failed to clone submodule $sm"
+ fi
+done
cd "$vroot_dir"
test $? -ne 0 && error "failed to change into '$vroot_dir'"
phdr = get_arch_phdr(self.endianness, self.elfclass)
phdr.p_type = p_type
phdr.p_paddr = p_paddr
+ phdr.p_vaddr = p_paddr
phdr.p_filesz = p_size
phdr.p_memsz = p_size
self.segments.append(phdr)
self._regy = QAPIGenCCode()
self._visited_ret_types = {}
- def _begin_module(self, name):
+ def _begin_user_module(self, name):
self._visited_ret_types[self._genc] = set()
commands = self._module_basename('qapi-commands', name)
types = self._module_basename('qapi-types', name)
def visit(self, visitor):
visitor.visit_begin(self)
module = None
+ visitor.visit_module(module)
for entity in self._entity_list:
if visitor.visit_needed(entity):
if entity.module != module:
self._what = what
self._blurb = blurb
self._pydoc = pydoc
+ self._genc = None
+ self._genh = None
self._module = {}
self._main_module = None
+ @staticmethod
+ def _is_user_module(name):
+ return name and not name.startswith('./')
+
+ @staticmethod
+ def _is_builtin_module(name):
+ return not name
+
def _module_basename(self, what, name):
- if name is None:
- return re.sub(r'-', '-builtin-', what)
- basename = os.path.join(os.path.dirname(name),
- self._prefix + what)
- if name == self._main_module:
- return basename
- return basename + '-' + os.path.splitext(os.path.basename(name))[0]
+ ret = '' if self._is_builtin_module(name) else self._prefix
+ if self._is_user_module(name):
+ dirname, basename = os.path.split(name)
+ ret += what
+ if name != self._main_module:
+ ret += '-' + os.path.splitext(basename)[0]
+ ret = os.path.join(dirname, ret)
+ else:
+ name = name[2:] if name else 'builtin'
+ ret += re.sub(r'-', '-' + name + '-', what)
+ return ret
def _add_module(self, name, blurb):
- if self._main_module is None and name is not None:
- self._main_module = name
genc = QAPIGenC(blurb, self._pydoc)
genh = QAPIGenH(blurb, self._pydoc)
self._module[name] = (genc, genh)
self._set_module(name)
+ def _add_user_module(self, name, blurb):
+ assert self._is_user_module(name)
+ if self._main_module is None:
+ self._main_module = name
+ self._add_module(name, blurb)
+
+ def _add_system_module(self, name, blurb):
+ self._add_module(name and './' + name, blurb)
+
def _set_module(self, name):
self._genc, self._genh = self._module[name]
def write(self, output_dir, opt_builtins=False):
for name in self._module:
- if name is None and not opt_builtins:
+ if self._is_builtin_module(name) and not opt_builtins:
continue
basename = self._module_basename(self._what, name)
(genc, genh) = self._module[name]
genc.write(output_dir, basename + '.c')
genh.write(output_dir, basename + '.h')
- def _begin_module(self, name):
+ def _begin_user_module(self, name):
pass
def visit_module(self, name):
if name in self._module:
self._set_module(name)
- return
- self._add_module(name, self._blurb)
- self._begin_module(name)
+ elif self._is_builtin_module(name):
+ # The built-in module has not been created. No code may
+ # be generated.
+ self._genc = None
+ self._genh = None
+ else:
+ self._add_user_module(name, self._blurb)
+ self._begin_user_module(name)
def visit_include(self, name, info):
basename = self._module_basename(self._what, name)
self._event_enum_members = []
self._event_emit_name = c_name(prefix + 'qapi_event_emit')
- def _begin_module(self, name):
+ def _begin_user_module(self, name):
+ events = self._module_basename('qapi-events', name)
types = self._module_basename('qapi-types', name)
visit = self._module_basename('qapi-visit', name)
self._genc.add(mcgen('''
#include "qemu/osdep.h"
#include "qemu-common.h"
-#include "%(prefix)sqapi-events.h"
+#include "%(prefix)sqapi-emit-events.h"
+#include "%(events)s.h"
#include "%(visit)s.h"
#include "qapi/error.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp-event.h"
''',
- visit=visit, prefix=self._prefix))
+ events=events, visit=visit,
+ prefix=self._prefix))
self._genh.add(mcgen('''
#include "qapi/util.h"
#include "%(types)s.h"
-
''',
types=types))
def visit_end(self):
- (genc, genh) = self._module[self._main_module]
- genh.add(gen_enum(self._event_enum_name,
- self._event_enum_members))
- genc.add(gen_enum_lookup(self._event_enum_name,
- self._event_enum_members))
- genh.add(mcgen('''
+ self._add_system_module('emit', ' * QAPI Events emission')
+ self._genc.preamble_add(mcgen('''
+#include "qemu/osdep.h"
+#include "%(prefix)sqapi-emit-events.h"
+''',
+ prefix=self._prefix))
+ self._genh.preamble_add(mcgen('''
+#include "qapi/util.h"
+'''))
+ self._genh.add(gen_enum(self._event_enum_name,
+ self._event_enum_members))
+ self._genc.add(gen_enum_lookup(self._event_enum_name,
+ self._event_enum_members))
+ self._genh.add(mcgen('''
void %(event_emit)s(%(event_enum)s event, QDict *qdict);
''',
- event_emit=self._event_emit_name,
- event_enum=self._event_enum_name))
+ event_emit=self._event_emit_name,
+ event_enum=self._event_enum_name))
def visit_event(self, name, info, ifcond, arg_type, boxed):
with ifcontext(ifcond, self._genh, self._genc):
self._genc.add(gen_event_send(name, arg_type, boxed,
self._event_enum_name,
self._event_emit_name))
- self._event_enum_members.append(QAPISchemaMember(name, ifcond))
+ # Note: we generate the enum member regardless of @ifcond, to
+ # keep the enumeration usable in target-independent code.
+ self._event_enum_members.append(QAPISchemaMember(name))
def gen_events(schema, output_dir, prefix):
QAPISchemaModularCVisitor.__init__(
self, prefix, 'qapi-types', ' * Schema-defined QAPI types',
__doc__)
- self._add_module(None, ' * Built-in QAPI types')
+ self._add_system_module(None, ' * Built-in QAPI types')
self._genc.preamble_add(mcgen('''
#include "qemu/osdep.h"
#include "qapi/dealloc-visitor.h"
#include "qapi/util.h"
'''))
- def _begin_module(self, name):
+ def _begin_user_module(self, name):
types = self._module_basename('qapi-types', name)
visit = self._module_basename('qapi-visit', name)
self._genc.preamble_add(mcgen('''
QAPISchemaModularCVisitor.__init__(
self, prefix, 'qapi-visit', ' * Schema-defined QAPI visitors',
__doc__)
- self._add_module(None, ' * Built-in QAPI visitors')
+ self._add_system_module(None, ' * Built-in QAPI visitors')
self._genc.preamble_add(mcgen('''
#include "qemu/osdep.h"
#include "qemu-common.h"
''',
prefix=prefix))
- def _begin_module(self, name):
+ def _begin_user_module(self, name):
types = self._module_basename('qapi-types', name)
visit = self._module_basename('qapi-visit', name)
self._genc.preamble_add(mcgen('''
LOG = logging.getLogger(__name__)
+# Mapping host architecture to any additional architectures it can
+# support which often includes its 32 bit cousin.
+ADDITIONAL_ARCHES = {
+ "x86_64" : "i386",
+ "aarch64" : "armhf"
+}
def kvm_available(target_arch=None):
- if target_arch and target_arch != os.uname()[4]:
- return False
+ host_arch = os.uname()[4]
+ if target_arch and target_arch != host_arch:
+ if target_arch != ADDITIONAL_ARCHES.get(host_arch):
+ return False
return os.access("/dev/kvm", os.R_OK | os.W_OK)
return False
# This can be used to add an unused monitor instance.
- def add_monitor_telnet(self, ip, port):
- args = 'tcp:%s:%d,server,nowait,telnet' % (ip, port)
+ def add_monitor_null(self):
self._args.append('-monitor')
- self._args.append(args)
+ self._args.append('null')
def add_fd(self, fd, fdset, opaque, opts=''):
"""
pthread_self().'''
# %rsp - 120 is scratch space according to the SystemV ABI
old = gdb.parse_and_eval('*(uint64_t*)($rsp - 120)')
- gdb.execute('call arch_prctl(0x1003, $rsp - 120)', False, True)
+ gdb.execute('call (int)arch_prctl(0x1003, $rsp - 120)', False, True)
fs_base = gdb.parse_and_eval('*(uint64_t*)($rsp - 120)')
gdb.execute('set *(uint64_t*)($rsp - 120) = %s' % old, False, True)
return fs_base
my $iterator = TAP::Parser::Iterator::Stream->new(\*STDIN);
my $parser = TAP::Parser->new ({iterator => $iterator });
+ STDOUT->autoflush(1);
while (defined (my $cur = $parser->next))
{
# Parsing of TAP input should stop after a "Bail out!" directive.
my $testno = 0; # Number of test results seen so far.
my $bailed_out = 0; # Whether a "Bail out!" directive has been seen.
+ STDOUT->autoflush(1);
while (defined (my $cur = $parser->next))
{
if ($cur->is_bailout)
if [ $arch = mips ]; then
cp "$tmpdir/include/asm/sgidefs.h" "$output/linux-headers/asm-mips/"
+ cp "$tmpdir/include/asm/unistd_o32.h" "$output/linux-headers/asm-mips/"
+ cp "$tmpdir/include/asm/unistd_n32.h" "$output/linux-headers/asm-mips/"
+ cp "$tmpdir/include/asm/unistd_n64.h" "$output/linux-headers/asm-mips/"
+ fi
+ if [ $arch = powerpc ]; then
+ cp "$tmpdir/include/asm/unistd_32.h" "$output/linux-headers/asm-powerpc/"
+ cp "$tmpdir/include/asm/unistd_64.h" "$output/linux-headers/asm-powerpc/"
fi
rm -rf "$output/include/standard-headers/asm-$arch"
cp "$tmpdir/include/asm/unistd_x32.h" "$output/linux-headers/asm-x86/"
cp "$tmpdir/include/asm/unistd_64.h" "$output/linux-headers/asm-x86/"
cp_portable "$tmpdir/include/asm/kvm_para.h" "$output/include/standard-headers/asm-$arch"
+ # Remove everything except the macros from bootparam.h avoiding the
+ # unnecessary import of several video/ist/etc headers
+ sed -e '/__ASSEMBLY__/,/__ASSEMBLY__/d' \
+ "$tmpdir/include/asm/bootparam.h" > "$tmpdir/bootparam.h"
+ cp_portable "$tmpdir/bootparam.h" \
+ "$output/include/standard-headers/asm-$arch"
fi
done
cat <<EOF >$output/linux-headers/linux/virtio_ring.h
#include "standard-headers/linux/virtio_ring.h"
EOF
+cat <<EOF >$output/linux-headers/linux/vhost_types.h
+#include "standard-headers/linux/vhost_types.h"
+EOF
rm -rf "$output/include/standard-headers/linux"
mkdir -p "$output/include/standard-headers/linux"
"$tmpdir/include/linux/input-event-codes.h" \
"$tmpdir/include/linux/pci_regs.h" \
"$tmpdir/include/linux/ethtool.h" "$tmpdir/include/linux/kernel.h" \
+ "$tmpdir/include/linux/vhost_types.h" \
"$tmpdir/include/linux/sysinfo.h"; do
cp_portable "$i" "$output/include/standard-headers/linux"
done
sbuf.o \
slirp.o \
socket.o \
+ state.o \
tcp_input.o \
tcp_output.o \
tcp_subr.o \
tftp.o \
udp.o \
udp6.o \
+ util.o \
$(NULL)
-slirp.mo-cflags = -DG_LOG_DOMAIN=\"Slirp\"
+slirp.mo-cflags = -DG_LOG_DOMAIN=\"Slirp\" -DWITH_QEMU
* THE SOFTWARE.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
+#include <string.h>
+
void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN])
{
const uint32_t broadcast_addr =
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
#if defined(_WIN32)
* in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp
*/
-#include "qemu/osdep.h"
#include "slirp.h"
/*
#ifndef DEBUG_H_
#define DEBUG_H_
-#define DBG_CALL 0x1
-#define DBG_MISC 0x2
-#define DBG_ERROR 0x4
+#define DBG_CALL (1 << 0)
+#define DBG_MISC (1 << 1)
+#define DBG_ERROR (1 << 2)
+#define DBG_TFTP (1 << 3)
extern int slirp_debug;
} \
} while (0)
+#define DEBUG_TFTP(fmt, ...) do { \
+ if (G_UNLIKELY(slirp_debug & DBG_TFTP)) { \
+ g_debug(fmt, ##__VA_ARGS__); \
+ } \
+} while (0)
+
#endif /* DEBUG_H_ */
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "qemu/osdep.h"
-#include "qemu/log.h"
#include "slirp.h"
#include "dhcpv6.h"
int len = odata[2] << 8 | odata[3];
if (len + 4 > olen) {
- slirp->cb->guest_error("Guest sent bad DHCPv6 packet!");
+ slirp->cb->guest_error("Guest sent bad DHCPv6 packet!", slirp->opaque);
return -E2BIG;
}
* THE SOFTWARE.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
static const uint8_t RFC3397_OPT_DOMAIN_SEARCH = 119;
* terms and conditions of the copyright.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
-#include "qemu/timer.h"
static void
ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead)
*/
void if_start(Slirp *slirp)
{
- uint64_t now = slirp->cb->clock_get_ns();
+ uint64_t now = slirp->cb->clock_get_ns(slirp->opaque);
bool from_batchq = false;
struct mbuf *ifm, *ifm_next, *ifqt;
uint8_t ip_p; /* protocol */
uint16_t ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
-} QEMU_PACKED;
+} SLIRP_PACKED;
#define IP_MAXPACKET 65535 /* maximum packet size */
n_long ipt_time;
} ipt_ta[1];
} ipt_timestamp;
-} QEMU_PACKED;
+} SLIRP_PACKED;
/* flag bits for ipt_flg */
#define IPOPT_TS_TSONLY 0 /* timestamps only */
struct mbuf_ptr {
struct mbuf *mptr;
uint32_t dummy;
-} QEMU_PACKED;
+} SLIRP_PACKED;
#else
struct mbuf_ptr {
struct mbuf *mptr;
-} QEMU_PACKED;
+} SLIRP_PACKED;
#endif
struct qlink {
void *next, *prev;
uint16_t ih_len; /* protocol length */
struct in_addr ih_src; /* source internet address */
struct in_addr ih_dst; /* destination internet address */
-} QEMU_PACKED;
+} SLIRP_PACKED;
/*
* Ip reassembly queue structure. Each fragment
uint8_t ipq_p; /* protocol of this fragment */
uint16_t ipq_id; /* sequence id for reassembly */
struct in_addr ipq_src,ipq_dst;
-} QEMU_PACKED;
+};
/*
* Ip header, when holding a fragment.
struct ipasfrag {
struct qlink ipf_link;
struct ip ipf_ip;
-} QEMU_PACKED;
+};
+
+G_STATIC_ASSERT(offsetof(struct ipq, frag_link) ==
+ offsetof(struct ipasfrag, ipf_link));
#define ipf_off ipf_ip.ip_off
#define ipf_tos ipf_ip.ip_tos
#define SLIRP_IP6_H
#include <glib.h>
-#include "net/eth.h"
+#include <string.h>
#define ALLNODES_MULTICAST { .s6_addr = \
{ 0xff, 0x02, 0x00, 0x00,\
uint8_t ip_nh; /* next header */
uint8_t ip_hl; /* hop limit */
struct in6_addr ip_src, ip_dst; /* source and dest address */
-} QEMU_PACKED;
+};
/*
* IPv6 pseudo-header used by upper-layer protocols
uint16_t ih_zero_hi; /* zero */
uint8_t ih_zero_lo; /* zero */
uint8_t ih_nh; /* next header */
-} QEMU_PACKED;
+};
+/*
+ * We don't want to mark these ip6 structs as packed as they are naturally
+ * correctly aligned; instead assert that there is no stray padding.
+ * If we marked the struct as packed then we would be unable to take
+ * the address of any of the fields in it.
+ */
+G_STATIC_ASSERT(sizeof(struct ip6) == 40);
+G_STATIC_ASSERT(sizeof(struct ip6_pseudohdr) == 40);
#endif
* Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
#include "ip6_icmp.h"
-#include "qemu/timer.h"
-#include "qemu/error-report.h"
-#include "qemu/log.h"
#define NDP_Interval g_rand_int_range(slirp->grand, \
NDP_MinRtrAdvInterval, NDP_MaxRtrAdvInterval)
static void ra_timer_handler(void *opaque)
{
Slirp *slirp = opaque;
- timer_mod(slirp->ra_timer,
- slirp->cb->clock_get_ns() / SCALE_MS + NDP_Interval);
+
+ slirp->cb->timer_mod(slirp->ra_timer,
+ slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS + NDP_Interval,
+ slirp->opaque);
ndp_send_ra(slirp);
}
return;
}
- slirp->ra_timer = timer_new_full(NULL, QEMU_CLOCK_VIRTUAL,
- SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
- ra_timer_handler, slirp);
- timer_mod(slirp->ra_timer,
- slirp->cb->clock_get_ns() / SCALE_MS + NDP_Interval);
+ slirp->ra_timer = slirp->cb->timer_new(ra_timer_handler, slirp, slirp->opaque);
+ slirp->cb->timer_mod(slirp->ra_timer,
+ slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS + NDP_Interval,
+ slirp->opaque);
}
void icmp6_cleanup(Slirp *slirp)
return;
}
- timer_del(slirp->ra_timer);
- timer_free(slirp->ra_timer);
+ slirp->cb->timer_free(slirp->ra_timer, slirp->opaque);
}
static void icmp6_send_echoreply(struct mbuf *m, Slirp *slirp, struct ip6 *ip,
case ICMP6_NDP_RA:
DEBUG_CALL(" type = Router Advertisement");
- slirp->cb->guest_error("Warning: guest sent NDP RA, but shouldn't");
+ slirp->cb->guest_error("Warning: guest sent NDP RA, but shouldn't",
+ slirp->opaque);
break;
case ICMP6_NDP_NS:
case ICMP6_NDP_REDIRECT:
DEBUG_CALL(" type = Redirect");
slirp->cb->guest_error(
- "Warning: guest sent NDP REDIRECT, but shouldn't");
+ "Warning: guest sent NDP REDIRECT, but shouldn't", slirp->opaque);
break;
}
}
uint16_t lifetime; /* Router Lifetime */
uint32_t reach_time; /* Reachable Time */
uint32_t retrans_time; /* Retrans Timer */
-} QEMU_PACKED;
+};
+
+G_STATIC_ASSERT(sizeof(struct ndp_ra) == 12);
struct ndp_ns { /* Neighbor Solicitation Message */
uint32_t reserved;
struct in6_addr target; /* Target Address */
-} QEMU_PACKED;
+};
+
+G_STATIC_ASSERT(sizeof(struct ndp_ns) == 20);
struct ndp_na { /* Neighbor Advertisement Message */
#if G_BYTE_ORDER == G_BIG_ENDIAN
reserved_lo:24;
#endif
struct in6_addr target; /* Target Address */
-} QEMU_PACKED;
+};
+
+G_STATIC_ASSERT(sizeof(struct ndp_na) == 20);
struct ndp_redirect {
uint32_t reserved;
struct in6_addr target; /* Target Address */
struct in6_addr dest; /* Destination Address */
-} QEMU_PACKED;
+};
+
+G_STATIC_ASSERT(sizeof(struct ndp_redirect) == 36);
/*
* Structure of an icmpv6 header.
#define icmp6_nns icmp6_body.ndp_ns
#define icmp6_nna icmp6_body.ndp_na
#define icmp6_redirect icmp6_body.ndp_redirect
-} QEMU_PACKED;
+};
+
+G_STATIC_ASSERT(sizeof(struct icmp6) == 40);
#define ICMP6_MINLEN 4
#define ICMP6_ERROR_MINLEN 8
uint32_t pref_lt; /* Preferred Lifetime */
uint32_t reserved2;
struct in6_addr prefix;
- } QEMU_PACKED prefixinfo;
+ } SLIRP_PACKED prefixinfo;
#define ndpopt_prefixinfo ndpopt_body.prefixinfo
struct rdnss {
uint16_t reserved;
uint32_t lifetime;
struct in6_addr addr;
- } QEMU_PACKED rdnss;
+ } SLIRP_PACKED rdnss;
#define ndpopt_rdnss ndpopt_body.rdnss
} ndpopt_body;
-} QEMU_PACKED;
+} SLIRP_PACKED;
/* NDP options type */
#define NDPOPT_LINKLAYER_SOURCE 1 /* Source Link-Layer Address */
* Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
#include "ip6_icmp.h"
* Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
*/
-#include "qemu/osdep.h"
-#include "qemu-common.h"
#include "slirp.h"
/* Number of packets queued before we start sending
* ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp
*/
-#include "qemu/osdep.h"
#include "slirp.h"
#include "ip_icmp.h"
struct ip *ip = mtod(m, struct ip *);
struct sockaddr_in addr;
- so->s = qemu_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
+ so->s = slirp_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
if (so->s == -1) {
return -1;
}
void icmp_detach(struct socket *so)
{
+ so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque);
closesocket(so->s);
sofree(so);
}
#define ICMP_MAXDATALEN (IP_MSS-28)
void
-icmp_send_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
+icmp_send_error(struct mbuf *msrc, uint8_t type, uint8_t code, int minsize,
const char *message)
{
unsigned hlen, shlen, s_ip_len;
* Strip out original options by copying rest of first
* mbuf's data back, and adjust the IP length.
*/
- memmove((caddr_t)(ip + 1), (caddr_t)ip + hlen,
+ memmove((char *)(ip + 1), (char *)ip + hlen,
(unsigned )(m->m_len - hlen));
hlen -= optlen;
ip->ip_hl = hlen >> 2;
struct mbuf *m = so->so_m;
struct ip *ip = mtod(m, struct ip *);
int hlen = ip->ip_hl << 2;
- u_char error_code;
+ uint8_t error_code;
struct icmp *icp;
int id, len;
icp = mtod(m, struct icmp *);
id = icp->icmp_id;
- len = qemu_recv(so->s, icp, M_ROOM(m), 0);
+ len = recv(so->s, icp, M_ROOM(m), 0);
/*
* The behavior of reading SOCK_DGRAM+IPPROTO_ICMP sockets is inconsistent
* between host OSes. On Linux, only the ICMP header and payload is
* Structure of an icmp header.
*/
struct icmp {
- u_char icmp_type; /* type of message, see below */
- u_char icmp_code; /* type sub code */
- u_short icmp_cksum; /* ones complement cksum of struct */
+ uint8_t icmp_type; /* type of message, see below */
+ uint8_t icmp_code; /* type sub code */
+ uint16_t icmp_cksum; /* ones complement cksum of struct */
union {
- u_char ih_pptr; /* ICMP_PARAMPROB */
+ uint8_t ih_pptr; /* ICMP_PARAMPROB */
struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
struct ih_idseq {
- u_short icd_id;
- u_short icd_seq;
+ uint16_t icd_id;
+ uint16_t icd_seq;
} ih_idseq;
int ih_void;
/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
struct ih_pmtu {
- u_short ipm_void;
- u_short ipm_nextmtu;
+ uint16_t ipm_void;
+ uint16_t ipm_nextmtu;
} ih_pmtu;
} icmp_hun;
#define icmp_pptr icmp_hun.ih_pptr
void icmp_init(Slirp *slirp);
void icmp_cleanup(Slirp *slirp);
void icmp_input(struct mbuf *, int);
-void icmp_send_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
+void icmp_send_error(struct mbuf *msrc, uint8_t type, uint8_t code, int minsize,
const char *message);
void icmp_reflect(struct mbuf *);
void icmp_receive(struct socket *so);
* terms and conditions of the copyright.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
#include "ip_icmp.h"
{
register int i;
struct ip *ip = mtod(m, struct ip *);
- register caddr_t opts;
+ register char *opts;
int olen;
olen = (ip->ip_hl<<2) - sizeof (struct ip);
- opts = (caddr_t)(ip + 1);
+ opts = (char *)(ip + 1);
i = m->m_len - (sizeof (struct ip) + olen);
memcpy(opts, opts + olen, (unsigned)i);
m->m_len -= olen;
* terms and conditions of the copyright.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
/* Number of packets queued before we start sending
#ifndef LIBSLIRP_H
#define LIBSLIRP_H
-#include "qemu-common.h"
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <in6addr.h>
+#else
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
typedef struct Slirp Slirp;
+enum {
+ SLIRP_POLL_IN = 1 << 0,
+ SLIRP_POLL_OUT = 1 << 1,
+ SLIRP_POLL_PRI = 1 << 2,
+ SLIRP_POLL_ERR = 1 << 3,
+ SLIRP_POLL_HUP = 1 << 4,
+};
+
+typedef ssize_t (*SlirpWriteCb)(const void *buf, size_t len, void *opaque);
+typedef void (*SlirpTimerCb)(void *opaque);
+typedef int (*SlirpAddPollCb)(int fd, int events, void *opaque);
+typedef int (*SlirpGetREventsCb)(int idx, void *opaque);
+
/*
* Callbacks from slirp
- *
- * The opaque parameter comes from the opaque parameter given to slirp_init().
*/
typedef struct SlirpCb {
- /* Send an ethernet frame to the guest network. */
- void (*output)(void *opaque, const uint8_t *pkt, int pkt_len);
+ /*
+ * Send an ethernet frame to the guest network. The opaque
+ * parameter is the one given to slirp_init(). The function
+ * doesn't need to send all the data and may return <len (no
+ * buffering is done on libslirp side, so the data will be dropped
+ * in this case). <0 reports an IO error.
+ */
+ SlirpWriteCb send_packet;
/* Print a message for an error due to guest misbehavior. */
- void (*guest_error)(const char *msg);
+ void (*guest_error)(const char *msg, void *opaque);
/* Return the virtual clock value in nanoseconds */
- int64_t (*clock_get_ns)(void);
+ int64_t (*clock_get_ns)(void *opaque);
+ /* Create a new timer with the given callback and opaque data */
+ void *(*timer_new)(SlirpTimerCb cb, void *cb_opaque, void *opaque);
+ /* Remove and free a timer */
+ void (*timer_free)(void *timer, void *opaque);
+ /* Modify a timer to expire at @expire_time */
+ void (*timer_mod)(void *timer, int64_t expire_time, void *opaque);
+ /* Register a fd for future polling */
+ void (*register_poll_fd)(int fd, void *opaque);
+ /* Unregister a fd */
+ void (*unregister_poll_fd)(int fd, void *opaque);
+ /* Kick the io-thread, to signal that new events may be processed */
+ void (*notify)(void *opaque);
} SlirpCb;
void *opaque);
void slirp_cleanup(Slirp *slirp);
-void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout);
+void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout,
+ SlirpAddPollCb add_poll, void *opaque);
-void slirp_pollfds_poll(GArray *pollfds, int select_error);
+void slirp_pollfds_poll(Slirp *slirp, int select_error,
+ SlirpGetREventsCb get_revents, void *opaque);
void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);
struct in_addr guest_addr, int guest_port);
int slirp_remove_hostfwd(Slirp *slirp, int is_udp,
struct in_addr host_addr, int host_port);
-int slirp_add_exec(Slirp *slirp, void *chardev, const char *cmdline,
+int slirp_add_exec(Slirp *slirp, const char *cmdline,
+ struct in_addr *guest_addr, int guest_port);
+int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque,
struct in_addr *guest_addr, int guest_port);
char *slirp_connection_info(Slirp *slirp);
int guest_port, const uint8_t *buf, int size);
size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
int guest_port);
-
+#ifdef __cplusplus
+} /* extern "C" */
#endif
+
+#endif /* LIBSLIRP_H */
#ifndef SLIRP_MAIN_H
#define SLIRP_MAIN_H
-extern u_int curtime;
+extern unsigned curtime;
extern struct in_addr loopback_addr;
extern unsigned long loopback_mask;
* the flags
*/
-#include "qemu/osdep.h"
#include "slirp.h"
#define MBUF_THRESH 30
int m_size; /* Size of mbuf, from m_dat or m_ext */
struct socket *m_so;
- caddr_t m_data; /* Current location of data */
+ char *m_data; /* Current location of data */
int m_len; /* Amount of data in this mbuf, from m_data */
Slirp *slirp;
* terms and conditions of the copyright.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
-#include "libslirp.h"
-#include "qemu/error-report.h"
-#include "qemu/main-loop.h"
inline void
insque(void *a, void *b)
element->qh_rlink = NULL;
}
-int add_exec(struct gfwd_list **ex_ptr, void *chardev, const char *cmdline,
+struct gfwd_list *
+add_guestfwd(struct gfwd_list **ex_ptr,
+ SlirpWriteCb write_cb, void *opaque,
struct in_addr addr, int port)
{
- struct gfwd_list *tmp_ptr;
-
- tmp_ptr = *ex_ptr;
- *ex_ptr = g_new0(struct gfwd_list, 1);
- (*ex_ptr)->ex_fport = port;
- (*ex_ptr)->ex_addr = addr;
- if (chardev) {
- (*ex_ptr)->ex_chardev = chardev;
- } else {
- (*ex_ptr)->ex_exec = g_strdup(cmdline);
- }
- (*ex_ptr)->ex_next = tmp_ptr;
- return 0;
+ struct gfwd_list *f = g_new0(struct gfwd_list, 1);
+
+ f->write_cb = write_cb;
+ f->opaque = opaque;
+ f->ex_fport = port;
+ f->ex_addr = addr;
+ f->ex_next = *ex_ptr;
+ *ex_ptr = f;
+
+ return f;
}
+struct gfwd_list *
+add_exec(struct gfwd_list **ex_ptr, const char *cmdline,
+ struct in_addr addr, int port)
+{
+ struct gfwd_list *f = add_guestfwd(ex_ptr, NULL, NULL, addr, port);
+
+ f->ex_exec = g_strdup(cmdline);
+
+ return f;
+}
static int
slirp_socketpair_with_oob(int sv[2])
int ret, s;
sv[1] = -1;
- s = qemu_socket(AF_INET, SOCK_STREAM, 0);
+ s = slirp_socket(AF_INET, SOCK_STREAM, 0);
if (s < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
listen(s, 1) < 0 ||
getsockname(s, (struct sockaddr *)&addr, &addrlen) < 0) {
goto err;
}
- sv[1] = qemu_socket(AF_INET, SOCK_STREAM, 0);
+ sv[1] = slirp_socket(AF_INET, SOCK_STREAM, 0);
if (sv[1] < 0) {
goto err;
}
#endif
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+#if !GLIB_CHECK_VERSION(2, 58, 0)
+typedef struct SlirpGSpawnFds {
+ GSpawnChildSetupFunc child_setup;
+ gpointer user_data;
+ gint stdin_fd;
+ gint stdout_fd;
+ gint stderr_fd;
+} SlirpGSpawnFds;
+
+static inline void
+slirp_gspawn_fds_setup(gpointer user_data)
+{
+ SlirpGSpawnFds *q = (SlirpGSpawnFds *)user_data;
+
+ dup2(q->stdin_fd, 0);
+ dup2(q->stdout_fd, 1);
+ dup2(q->stderr_fd, 2);
+ q->child_setup(q->user_data);
+}
+#endif
+
+static inline gboolean
+g_spawn_async_with_fds_slirp(const gchar *working_directory,
+ gchar **argv,
+ gchar **envp,
+ GSpawnFlags flags,
+ GSpawnChildSetupFunc child_setup,
+ gpointer user_data,
+ GPid *child_pid,
+ gint stdin_fd,
+ gint stdout_fd,
+ gint stderr_fd,
+ GError **error)
+{
+#if GLIB_CHECK_VERSION(2, 58, 0)
+ return g_spawn_async_with_fds(working_directory, argv, envp, flags,
+ child_setup, user_data,
+ child_pid, stdin_fd, stdout_fd, stderr_fd,
+ error);
+#else
+ SlirpGSpawnFds setup = {
+ .child_setup = child_setup,
+ .user_data = user_data,
+ .stdin_fd = stdin_fd,
+ .stdout_fd = stdout_fd,
+ .stderr_fd = stderr_fd,
+ };
+
+ return g_spawn_async(working_directory, argv, envp, flags,
+ slirp_gspawn_fds_setup, &setup,
+ child_pid, error);
+#endif
+}
+
+#define g_spawn_async_with_fds(wd, argv, env, f, c, d, p, ifd, ofd, efd, err) \
+ g_spawn_async_with_fds_slirp(wd, argv, env, f, c, d, p, ifd, ofd, efd, err)
+
+#pragma GCC diagnostic pop
+
int
fork_exec(struct socket *so, const char *ex)
{
so->s = sp[0];
closesocket(sp[1]);
- socket_set_fast_reuse(so->s);
+ slirp_socket_set_fast_reuse(so->s);
opt = 1;
- qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
- qemu_set_nonblock(so->s);
+ setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
+ slirp_set_nonblock(so->s);
+ so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque);
return 1;
}
#ifndef MISC_H
#define MISC_H
+#include "libslirp.h"
+
struct gfwd_list {
- void *ex_chardev;
+ SlirpWriteCb write_cb;
+ void *opaque;
struct in_addr ex_addr; /* Server address */
int ex_fport; /* Port to telnet to */
char *ex_exec; /* Command line of what to exec */
void slirp_insque(void *, void *);
void slirp_remque(void *);
-int add_exec(struct gfwd_list **, void *, const char *, struct in_addr, int);
int fork_exec(struct socket *so, const char *ex);
+struct gfwd_list *
+add_guestfwd(struct gfwd_list **ex_ptr,
+ SlirpWriteCb write_cb, void *opaque,
+ struct in_addr addr, int port);
+
+struct gfwd_list *
+add_exec(struct gfwd_list **ex_ptr, const char *cmdline,
+ struct in_addr addr, int port);
+
#endif
* This code is licensed under the GPL version 2 or later. See the
* COPYING file in the top-level directory.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
#include "ncsi-pkt.h"
*pchecksum = htonl(checksum);
ncsi_rsp_len += 4;
- slirp->cb->output(slirp->opaque, ncsi_reply, ETH_HLEN + ncsi_rsp_len);
+ slirp_send_packet_all(slirp, ncsi_reply, ETH_HLEN + ncsi_rsp_len);
}
* Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
*/
-#include "qemu/osdep.h"
-#include "qemu-common.h"
#include "slirp.h"
void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr,
--- /dev/null
+/* $NetBSD: queue.h,v 1.52 2009/04/20 09:56:08 mschuett Exp $ */
+
+/*
+ * slirp version: Copy from QEMU, removed all but tail queues.
+ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef QTAILQ_H
+#define QTAILQ_H
+
+/*
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ */
+typedef struct QTailQLink {
+ void *tql_next;
+ struct QTailQLink *tql_prev;
+} QTailQLink;
+
+/*
+ * Tail queue definitions. The union acts as a poor man template, as if
+ * it were QTailQLink<type>.
+ */
+#define QTAILQ_HEAD(name, type) \
+ union name { \
+ struct type *tqh_first; /* first element */ \
+ QTailQLink tqh_circ; /* link for circular backwards list */ \
+ }
+
+#define QTAILQ_HEAD_INITIALIZER(head) \
+ { .tqh_circ = { NULL, &(head).tqh_circ } }
+
+#define QTAILQ_ENTRY(type) \
+ union { \
+ struct type *tqe_next; /* next element */ \
+ QTailQLink tqe_circ; /* link for circular backwards list */ \
+ }
+
+#define QTAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_circ.tql_prev = &(head)->tqh_circ; \
+} while (/*CONSTCOND*/0)
+
+#define QTAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_circ.tql_prev = \
+ &(elm)->field.tqe_circ; \
+ else \
+ (head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_circ.tql_prev = &(head)->tqh_circ; \
+} while (/*CONSTCOND*/0)
+
+#define QTAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_circ.tql_prev = (head)->tqh_circ.tql_prev; \
+ (head)->tqh_circ.tql_prev->tql_next = (elm); \
+ (head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \
+} while (/*CONSTCOND*/0)
+
+#define QTAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_circ.tql_prev = \
+ &(elm)->field.tqe_circ; \
+ else \
+ (head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_circ.tql_prev = &(listelm)->field.tqe_circ; \
+} while (/*CONSTCOND*/0)
+
+#define QTAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_circ.tql_prev = (listelm)->field.tqe_circ.tql_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ (listelm)->field.tqe_circ.tql_prev->tql_next = (elm); \
+ (listelm)->field.tqe_circ.tql_prev = &(elm)->field.tqe_circ; \
+} while (/*CONSTCOND*/0)
+
+#define QTAILQ_REMOVE(head, elm, field) do { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_circ.tql_prev = \
+ (elm)->field.tqe_circ.tql_prev; \
+ else \
+ (head)->tqh_circ.tql_prev = (elm)->field.tqe_circ.tql_prev; \
+ (elm)->field.tqe_circ.tql_prev->tql_next = (elm)->field.tqe_next; \
+ (elm)->field.tqe_circ.tql_prev = NULL; \
+} while (/*CONSTCOND*/0)
+
+#define QTAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->tqh_first); \
+ (var); \
+ (var) = ((var)->field.tqe_next))
+
+#define QTAILQ_FOREACH_SAFE(var, head, field, next_var) \
+ for ((var) = ((head)->tqh_first); \
+ (var) && ((next_var) = ((var)->field.tqe_next), 1); \
+ (var) = (next_var))
+
+#define QTAILQ_FOREACH_REVERSE(var, head, field) \
+ for ((var) = QTAILQ_LAST(head); \
+ (var); \
+ (var) = QTAILQ_PREV(var, field))
+
+#define QTAILQ_FOREACH_REVERSE_SAFE(var, head, field, prev_var) \
+ for ((var) = QTAILQ_LAST(head); \
+ (var) && ((prev_var) = QTAILQ_PREV(var, field)); \
+ (var) = (prev_var))
+
+/*
+ * Tail queue access methods.
+ */
+#define QTAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+#define QTAILQ_FIRST(head) ((head)->tqh_first)
+#define QTAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+#define QTAILQ_IN_USE(elm, field) ((elm)->field.tqe_circ.tql_prev != NULL)
+
+#define QTAILQ_LINK_PREV(link) \
+ ((link).tql_prev->tql_prev->tql_next)
+#define QTAILQ_LAST(head) \
+ ((typeof((head)->tqh_first)) QTAILQ_LINK_PREV((head)->tqh_circ))
+#define QTAILQ_PREV(elm, field) \
+ ((typeof((elm)->field.tqe_next)) QTAILQ_LINK_PREV((elm)->field.tqe_circ))
+
+#define field_at_offset(base, offset, type) \
+ ((type *) (((char *) (base)) + (offset)))
+
+/*
+ * Raw access of elements of a tail queue head. Offsets are all zero
+ * because it's a union.
+ */
+#define QTAILQ_RAW_FIRST(head) \
+ field_at_offset(head, 0, void *)
+#define QTAILQ_RAW_TQH_CIRC(head) \
+ field_at_offset(head, 0, QTailQLink)
+
+/*
+ * Raw access of elements of a tail entry
+ */
+#define QTAILQ_RAW_NEXT(elm, entry) \
+ field_at_offset(elm, entry, void *)
+#define QTAILQ_RAW_TQE_CIRC(elm, entry) \
+ field_at_offset(elm, entry, QTailQLink)
+/*
+ * Tail queue traversal using pointer arithmetic.
+ */
+#define QTAILQ_RAW_FOREACH(elm, head, entry) \
+ for ((elm) = *QTAILQ_RAW_FIRST(head); \
+ (elm); \
+ (elm) = *QTAILQ_RAW_NEXT(elm, entry))
+/*
+ * Tail queue insertion using pointer arithmetic.
+ */
+#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) do { \
+ *QTAILQ_RAW_NEXT(elm, entry) = NULL; \
+ QTAILQ_RAW_TQE_CIRC(elm, entry)->tql_prev = QTAILQ_RAW_TQH_CIRC(head)->tql_prev; \
+ QTAILQ_RAW_TQH_CIRC(head)->tql_prev->tql_next = (elm); \
+ QTAILQ_RAW_TQH_CIRC(head)->tql_prev = QTAILQ_RAW_TQE_CIRC(elm, entry); \
+} while (/*CONSTCOND*/0)
+
+#endif /* QTAILQ_H */
* terms and conditions of the copyright.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
-#include "qemu/main-loop.h"
static void sbappendsb(struct sbuf *sb, struct mbuf *m);
free(sb->sb_data);
}
-void
+bool
sbdrop(struct sbuf *sb, int num)
{
int limit = sb->sb_datalen / 2;
sb->sb_rptr -= sb->sb_datalen;
if (sb->sb_cc < limit && sb->sb_cc + num >= limit) {
- qemu_notify_event();
+ return true;
}
+
+ return false;
}
void
};
void sbfree(struct sbuf *);
-void sbdrop(struct sbuf *, int);
+bool sbdrop(struct sbuf *, int);
void sbreserve(struct sbuf *, int);
void sbappend(struct socket *, struct mbuf *);
void sbcopy(struct sbuf *, int, int, char *);
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/timer.h"
-#include "qemu/error-report.h"
-#include "chardev/char-fe.h"
-#include "migration/register.h"
#include "slirp.h"
-#include "hw/hw.h"
-#include "qemu/cutils.h"
+
+#ifdef WITH_QEMU
+#include "state.h"
+#endif
#ifndef _WIN32
#include <net/if.h>
0x52, 0x55, 0x00, 0x00, 0x00, 0x00
};
-u_int curtime;
-
-static QTAILQ_HEAD(, Slirp) slirp_instances =
- QTAILQ_HEAD_INITIALIZER(slirp_instances);
+unsigned curtime;
static struct in_addr dns_addr;
#ifndef _WIN32
static struct in6_addr dns6_addr;
#endif
-static u_int dns_addr_time;
+static unsigned dns_addr_time;
#ifndef _WIN32
-static u_int dns6_addr_time;
+static unsigned dns6_addr_time;
#endif
#define TIMEOUT_FAST 2 /* milliseconds */
}
if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
- printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
+ printf("GetNetworkParams failed. ret = %08x\n", (unsigned)ret );
if (FixedInfo) {
GlobalFree(FixedInfo);
FixedInfo = NULL;
static int get_dns_addr_cached(void *pdns_addr, void *cached_addr,
socklen_t addrlen,
- struct stat *cached_stat, u_int *cached_time)
+ struct stat *cached_stat, unsigned *cached_time)
{
struct stat old_stat;
if (curtime - *cached_time < TIMEOUT_DEFAULT) {
static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr,
socklen_t addrlen, uint32_t *scope_id,
- u_int *cached_time)
+ unsigned *cached_time)
{
char buff[512];
char buff2[257];
{ "call", DBG_CALL },
{ "misc", DBG_MISC },
{ "error", DBG_ERROR },
+ { "tftp", DBG_TFTP },
};
slirp_debug = g_parse_debug_string(debug, keys, G_N_ELEMENTS(keys));
}
}
-static void slirp_state_save(QEMUFile *f, void *opaque);
-static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
-
-static SaveVMHandlers savevm_slirp_state = {
- .save_state = slirp_state_save,
- .load_state = slirp_state_load,
-};
-
Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
struct in_addr vnetmask, struct in_addr vhost,
bool in6_enabled,
slirp_init_once();
+ slirp->opaque = opaque;
slirp->cb = callbacks;
slirp->grand = g_rand_new();
slirp->restricted = restricted;
slirp->vprefix_len = vprefix_len;
slirp->vhost_addr6 = vhost6;
if (vhostname) {
- pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
- vhostname);
+ slirp_pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
+ vhostname);
}
slirp->tftp_prefix = g_strdup(tftp_path);
slirp->bootp_filename = g_strdup(bootfile);
translate_dnssearch(slirp, vdnssearch);
}
- slirp->opaque = opaque;
-
- register_savevm_live(NULL, "slirp", 0, 4, &savevm_slirp_state, slirp);
-
- QTAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
-
+#ifdef WITH_QEMU
+ slirp_state_register(slirp);
+#endif
return slirp;
}
g_free(e);
}
- QTAILQ_REMOVE(&slirp_instances, slirp, entry);
-
- unregister_savevm(NULL, "slirp", slirp);
-
+#ifdef WITH_QEMU
+ slirp_state_unregister(slirp);
+#endif
ip_cleanup(slirp);
ip6_cleanup(slirp);
m_cleanup(slirp);
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
-static void slirp_update_timeout(uint32_t *timeout)
+static void slirp_update_timeout(Slirp *slirp, uint32_t *timeout)
{
- Slirp *slirp;
uint32_t t;
if (*timeout <= TIMEOUT_FAST) {
/* If we have tcp timeout with slirp, then we will fill @timeout with
* more precise value.
*/
- QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
- if (slirp->time_fasttimo) {
- *timeout = TIMEOUT_FAST;
- return;
- }
- if (slirp->do_slowtimo) {
- t = MIN(TIMEOUT_SLOW, t);
- }
+ if (slirp->time_fasttimo) {
+ *timeout = TIMEOUT_FAST;
+ return;
+ }
+ if (slirp->do_slowtimo) {
+ t = MIN(TIMEOUT_SLOW, t);
}
*timeout = t;
}
-void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout)
+void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout,
+ SlirpAddPollCb add_poll, void *opaque)
{
- Slirp *slirp;
struct socket *so, *so_next;
- if (QTAILQ_EMPTY(&slirp_instances)) {
- return;
- }
-
/*
* First, TCP sockets
*/
- QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
- /*
- * *_slowtimo needs calling if there are IP fragments
- * in the fragment queue, or there are TCP connections active
- */
- slirp->do_slowtimo = ((slirp->tcb.so_next != &slirp->tcb) ||
- (&slirp->ipq.ip_link != slirp->ipq.ip_link.next));
+ /*
+ * *_slowtimo needs calling if there are IP fragments
+ * in the fragment queue, or there are TCP connections active
+ */
+ slirp->do_slowtimo = ((slirp->tcb.so_next != &slirp->tcb) ||
+ (&slirp->ipq.ip_link != slirp->ipq.ip_link.next));
- for (so = slirp->tcb.so_next; so != &slirp->tcb;
- so = so_next) {
- int events = 0;
+ for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so_next) {
+ int events = 0;
- so_next = so->so_next;
+ so_next = so->so_next;
- so->pollfds_idx = -1;
+ so->pollfds_idx = -1;
- /*
- * See if we need a tcp_fasttimo
- */
- if (slirp->time_fasttimo == 0 &&
- so->so_tcpcb->t_flags & TF_DELACK) {
- slirp->time_fasttimo = curtime; /* Flag when want a fasttimo */
- }
-
- /*
- * NOFDREF can include still connecting to local-host,
- * newly socreated() sockets etc. Don't want to select these.
- */
- if (so->so_state & SS_NOFDREF || so->s == -1) {
- continue;
- }
-
- /*
- * Set for reading sockets which are accepting
- */
- if (so->so_state & SS_FACCEPTCONN) {
- GPollFD pfd = {
- .fd = so->s,
- .events = G_IO_IN | G_IO_HUP | G_IO_ERR,
- };
- so->pollfds_idx = pollfds->len;
- g_array_append_val(pollfds, pfd);
- continue;
- }
+ /*
+ * See if we need a tcp_fasttimo
+ */
+ if (slirp->time_fasttimo == 0 &&
+ so->so_tcpcb->t_flags & TF_DELACK) {
+ slirp->time_fasttimo = curtime; /* Flag when want a fasttimo */
+ }
- /*
- * Set for writing sockets which are connecting
- */
- if (so->so_state & SS_ISFCONNECTING) {
- GPollFD pfd = {
- .fd = so->s,
- .events = G_IO_OUT | G_IO_ERR,
- };
- so->pollfds_idx = pollfds->len;
- g_array_append_val(pollfds, pfd);
- continue;
- }
+ /*
+ * NOFDREF can include still connecting to local-host,
+ * newly socreated() sockets etc. Don't want to select these.
+ */
+ if (so->so_state & SS_NOFDREF || so->s == -1) {
+ continue;
+ }
- /*
- * Set for writing if we are connected, can send more, and
- * we have something to send
- */
- if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
- events |= G_IO_OUT | G_IO_ERR;
- }
+ /*
+ * Set for reading sockets which are accepting
+ */
+ if (so->so_state & SS_FACCEPTCONN) {
+ so->pollfds_idx = add_poll(so->s,
+ SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
+ continue;
+ }
- /*
- * Set for reading (and urgent data) if we are connected, can
- * receive more, and we have room for it XXX /2 ?
- */
- if (CONN_CANFRCV(so) &&
- (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
- events |= G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI;
- }
+ /*
+ * Set for writing sockets which are connecting
+ */
+ if (so->so_state & SS_ISFCONNECTING) {
+ so->pollfds_idx = add_poll(so->s,
+ SLIRP_POLL_OUT | SLIRP_POLL_ERR, opaque);
+ continue;
+ }
- if (events) {
- GPollFD pfd = {
- .fd = so->s,
- .events = events,
- };
- so->pollfds_idx = pollfds->len;
- g_array_append_val(pollfds, pfd);
- }
+ /*
+ * Set for writing if we are connected, can send more, and
+ * we have something to send
+ */
+ if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
+ events |= SLIRP_POLL_OUT | SLIRP_POLL_ERR;
}
/*
- * UDP sockets
+ * Set for reading (and urgent data) if we are connected, can
+ * receive more, and we have room for it XXX /2 ?
*/
- for (so = slirp->udb.so_next; so != &slirp->udb;
- so = so_next) {
- so_next = so->so_next;
+ if (CONN_CANFRCV(so) &&
+ (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
+ events |= SLIRP_POLL_IN | SLIRP_POLL_HUP |
+ SLIRP_POLL_ERR | SLIRP_POLL_PRI;
+ }
- so->pollfds_idx = -1;
+ if (events) {
+ so->pollfds_idx = add_poll(so->s, events, opaque);
+ }
+ }
- /*
- * See if it's timed out
- */
- if (so->so_expire) {
- if (so->so_expire <= curtime) {
- udp_detach(so);
- continue;
- } else {
- slirp->do_slowtimo = true; /* Let socket expire */
- }
- }
+ /*
+ * UDP sockets
+ */
+ for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) {
+ so_next = so->so_next;
- /*
- * When UDP packets are received from over the
- * link, they're sendto()'d straight away, so
- * no need for setting for writing
- * Limit the number of packets queued by this session
- * to 4. Note that even though we try and limit this
- * to 4 packets, the session could have more queued
- * if the packets needed to be fragmented
- * (XXX <= 4 ?)
- */
- if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
- GPollFD pfd = {
- .fd = so->s,
- .events = G_IO_IN | G_IO_HUP | G_IO_ERR,
- };
- so->pollfds_idx = pollfds->len;
- g_array_append_val(pollfds, pfd);
+ so->pollfds_idx = -1;
+
+ /*
+ * See if it's timed out
+ */
+ if (so->so_expire) {
+ if (so->so_expire <= curtime) {
+ udp_detach(so);
+ continue;
+ } else {
+ slirp->do_slowtimo = true; /* Let socket expire */
}
}
/*
- * ICMP sockets
+ * When UDP packets are received from over the
+ * link, they're sendto()'d straight away, so
+ * no need for setting for writing
+ * Limit the number of packets queued by this session
+ * to 4. Note that even though we try and limit this
+ * to 4 packets, the session could have more queued
+ * if the packets needed to be fragmented
+ * (XXX <= 4 ?)
*/
- for (so = slirp->icmp.so_next; so != &slirp->icmp;
- so = so_next) {
- so_next = so->so_next;
+ if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
+ so->pollfds_idx = add_poll(so->s,
+ SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
+ }
+ }
- so->pollfds_idx = -1;
+ /*
+ * ICMP sockets
+ */
+ for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) {
+ so_next = so->so_next;
- /*
- * See if it's timed out
- */
- if (so->so_expire) {
- if (so->so_expire <= curtime) {
- icmp_detach(so);
- continue;
- } else {
- slirp->do_slowtimo = true; /* Let socket expire */
- }
- }
+ so->pollfds_idx = -1;
- if (so->so_state & SS_ISFCONNECTED) {
- GPollFD pfd = {
- .fd = so->s,
- .events = G_IO_IN | G_IO_HUP | G_IO_ERR,
- };
- so->pollfds_idx = pollfds->len;
- g_array_append_val(pollfds, pfd);
+ /*
+ * See if it's timed out
+ */
+ if (so->so_expire) {
+ if (so->so_expire <= curtime) {
+ icmp_detach(so);
+ continue;
+ } else {
+ slirp->do_slowtimo = true; /* Let socket expire */
}
}
+
+ if (so->so_state & SS_ISFCONNECTED) {
+ so->pollfds_idx = add_poll(so->s,
+ SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
+ }
}
- slirp_update_timeout(timeout);
+
+ slirp_update_timeout(slirp, timeout);
}
-void slirp_pollfds_poll(GArray *pollfds, int select_error)
+void slirp_pollfds_poll(Slirp *slirp, int select_error,
+ SlirpGetREventsCb get_revents, void *opaque)
{
- Slirp *slirp = QTAILQ_FIRST(&slirp_instances);
struct socket *so, *so_next;
int ret;
- if (!slirp) {
- return;
- }
+ curtime = slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS;
- curtime = slirp->cb->clock_get_ns() / SCALE_MS;
+ /*
+ * See if anything has timed out
+ */
+ if (slirp->time_fasttimo &&
+ ((curtime - slirp->time_fasttimo) >= TIMEOUT_FAST)) {
+ tcp_fasttimo(slirp);
+ slirp->time_fasttimo = 0;
+ }
+ if (slirp->do_slowtimo &&
+ ((curtime - slirp->last_slowtimo) >= TIMEOUT_SLOW)) {
+ ip_slowtimo(slirp);
+ tcp_slowtimo(slirp);
+ slirp->last_slowtimo = curtime;
+ }
- QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
+ /*
+ * Check sockets
+ */
+ if (!select_error) {
/*
- * See if anything has timed out
+ * Check TCP sockets
*/
- if (slirp->time_fasttimo &&
- ((curtime - slirp->time_fasttimo) >= TIMEOUT_FAST)) {
- tcp_fasttimo(slirp);
- slirp->time_fasttimo = 0;
- }
- if (slirp->do_slowtimo &&
- ((curtime - slirp->last_slowtimo) >= TIMEOUT_SLOW)) {
- ip_slowtimo(slirp);
- tcp_slowtimo(slirp);
- slirp->last_slowtimo = curtime;
- }
+ for (so = slirp->tcb.so_next; so != &slirp->tcb;
+ so = so_next) {
+ int revents;
- /*
- * Check sockets
- */
- if (!select_error) {
- /*
- * Check TCP sockets
- */
- for (so = slirp->tcb.so_next; so != &slirp->tcb;
- so = so_next) {
- int revents;
+ so_next = so->so_next;
- so_next = so->so_next;
+ revents = 0;
+ if (so->pollfds_idx != -1) {
+ revents = get_revents(so->pollfds_idx, opaque);
+ }
- revents = 0;
- if (so->pollfds_idx != -1) {
- revents = g_array_index(pollfds, GPollFD,
- so->pollfds_idx).revents;
- }
+ if (so->so_state & SS_NOFDREF || so->s == -1) {
+ continue;
+ }
- if (so->so_state & SS_NOFDREF || so->s == -1) {
+ /*
+ * Check for URG data
+ * This will soread as well, so no need to
+ * test for SLIRP_POLL_IN below if this succeeds
+ */
+ if (revents & SLIRP_POLL_PRI) {
+ ret = sorecvoob(so);
+ if (ret < 0) {
+ /* Socket error might have resulted in the socket being
+ * removed, do not try to do anything more with it. */
continue;
}
-
+ }
+ /*
+ * Check sockets for reading
+ */
+ else if (revents &
+ (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR)) {
/*
- * Check for URG data
- * This will soread as well, so no need to
- * test for G_IO_IN below if this succeeds
+ * Check for incoming connections
*/
- if (revents & G_IO_PRI) {
- ret = sorecvoob(so);
- if (ret < 0) {
- /* Socket error might have resulted in the socket being
- * removed, do not try to do anything more with it. */
- continue;
- }
+ if (so->so_state & SS_FACCEPTCONN) {
+ tcp_connect(so);
+ continue;
+ } /* else */
+ ret = soread(so);
+
+ /* Output it if we read something */
+ if (ret > 0) {
+ tcp_output(sototcpcb(so));
+ }
+ if (ret < 0) {
+ /* Socket error might have resulted in the socket being
+ * removed, do not try to do anything more with it. */
+ continue;
}
+ }
+
+ /*
+ * Check sockets for writing
+ */
+ if (!(so->so_state & SS_NOFDREF) &&
+ (revents & (SLIRP_POLL_OUT | SLIRP_POLL_ERR))) {
/*
- * Check sockets for reading
+ * Check for non-blocking, still-connecting sockets
*/
- else if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) {
- /*
- * Check for incoming connections
- */
- if (so->so_state & SS_FACCEPTCONN) {
- tcp_connect(so);
- continue;
- } /* else */
- ret = soread(so);
+ if (so->so_state & SS_ISFCONNECTING) {
+ /* Connected */
+ so->so_state &= ~SS_ISFCONNECTING;
- /* Output it if we read something */
- if (ret > 0) {
- tcp_output(sototcpcb(so));
- }
+ ret = send(so->s, (const void *) &ret, 0, 0);
if (ret < 0) {
- /* Socket error might have resulted in the socket being
- * removed, do not try to do anything more with it. */
- continue;
+ /* XXXXX Must fix, zero bytes is a NOP */
+ if (errno == EAGAIN || errno == EWOULDBLOCK ||
+ errno == EINPROGRESS || errno == ENOTCONN) {
+ continue;
+ }
+
+ /* else failed */
+ so->so_state &= SS_PERSISTENT_MASK;
+ so->so_state |= SS_NOFDREF;
}
- }
+ /* else so->so_state &= ~SS_ISFCONNECTING; */
- /*
- * Check sockets for writing
- */
- if (!(so->so_state & SS_NOFDREF) &&
- (revents & (G_IO_OUT | G_IO_ERR))) {
/*
- * Check for non-blocking, still-connecting sockets
+ * Continue tcp_input
*/
- if (so->so_state & SS_ISFCONNECTING) {
- /* Connected */
- so->so_state &= ~SS_ISFCONNECTING;
-
- ret = send(so->s, (const void *) &ret, 0, 0);
- if (ret < 0) {
- /* XXXXX Must fix, zero bytes is a NOP */
- if (errno == EAGAIN || errno == EWOULDBLOCK ||
- errno == EINPROGRESS || errno == ENOTCONN) {
- continue;
- }
-
- /* else failed */
- so->so_state &= SS_PERSISTENT_MASK;
- so->so_state |= SS_NOFDREF;
- }
- /* else so->so_state &= ~SS_ISFCONNECTING; */
-
- /*
- * Continue tcp_input
- */
- tcp_input((struct mbuf *)NULL, sizeof(struct ip), so,
- so->so_ffamily);
- /* continue; */
- } else {
- ret = sowrite(so);
- if (ret > 0) {
- /* Call tcp_output in case we need to send a window
- * update to the guest, otherwise it will be stuck
- * until it sends a window probe. */
- tcp_output(sototcpcb(so));
- }
+ tcp_input((struct mbuf *)NULL, sizeof(struct ip), so,
+ so->so_ffamily);
+ /* continue; */
+ } else {
+ ret = sowrite(so);
+ if (ret > 0) {
+ /* Call tcp_output in case we need to send a window
+ * update to the guest, otherwise it will be stuck
+ * until it sends a window probe. */
+ tcp_output(sototcpcb(so));
}
}
}
+ }
- /*
- * Now UDP sockets.
- * Incoming packets are sent straight away, they're not buffered.
- * Incoming UDP data isn't buffered either.
- */
- for (so = slirp->udb.so_next; so != &slirp->udb;
- so = so_next) {
- int revents;
+ /*
+ * Now UDP sockets.
+ * Incoming packets are sent straight away, they're not buffered.
+ * Incoming UDP data isn't buffered either.
+ */
+ for (so = slirp->udb.so_next; so != &slirp->udb;
+ so = so_next) {
+ int revents;
- so_next = so->so_next;
+ so_next = so->so_next;
- revents = 0;
- if (so->pollfds_idx != -1) {
- revents = g_array_index(pollfds, GPollFD,
- so->pollfds_idx).revents;
- }
+ revents = 0;
+ if (so->pollfds_idx != -1) {
+ revents = get_revents(so->pollfds_idx, opaque);
+ }
- if (so->s != -1 &&
- (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) {
- sorecvfrom(so);
- }
+ if (so->s != -1 &&
+ (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) {
+ sorecvfrom(so);
}
+ }
- /*
- * Check incoming ICMP relies.
- */
- for (so = slirp->icmp.so_next; so != &slirp->icmp;
- so = so_next) {
- int revents;
+ /*
+ * Check incoming ICMP relies.
+ */
+ for (so = slirp->icmp.so_next; so != &slirp->icmp;
+ so = so_next) {
+ int revents;
- so_next = so->so_next;
+ so_next = so->so_next;
- revents = 0;
- if (so->pollfds_idx != -1) {
- revents = g_array_index(pollfds, GPollFD,
- so->pollfds_idx).revents;
- }
+ revents = 0;
+ if (so->pollfds_idx != -1) {
+ revents = get_revents(so->pollfds_idx, opaque);
+ }
- if (so->s != -1 &&
- (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) {
- icmp_receive(so);
- }
+ if (so->s != -1 &&
+ (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) {
+ icmp_receive(so);
}
}
-
- if_start(slirp);
}
+
+ if_start(slirp);
}
static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
rah->ar_sip = ah->ar_tip;
memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
rah->ar_tip = ah->ar_sip;
- slirp->cb->output(slirp->opaque, arp_reply, sizeof(arp_reply));
+ slirp_send_packet_all(slirp, arp_reply, sizeof(arp_reply));
}
break;
case ARPOP_REPLY:
if (pkt_len < ETH_HLEN)
return;
- proto = ntohs(*(uint16_t *)(pkt + 12));
+ proto = (((uint16_t) pkt[12]) << 8) + pkt[13];
switch(proto) {
case ETH_P_ARP:
arp_input(slirp, pkt, pkt_len);
/* target IP */
rah->ar_tip = iph->ip_dst.s_addr;
slirp->client_ipaddr = iph->ip_dst;
- slirp->cb->output(slirp->opaque, arp_req, sizeof(arp_req));
+ slirp_send_packet_all(slirp, arp_req, sizeof(arp_req));
ifm->resolution_requested = true;
/* Expire request and drop outgoing packet after 1 second */
- ifm->expiration_date = slirp->cb->clock_get_ns() + 1000000000ULL;
+ ifm->expiration_date =
+ slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL;
}
return 0;
} else {
if (!ifm->resolution_requested) {
ndp_send_ns(slirp, ip6h->ip_dst);
ifm->resolution_requested = true;
- ifm->expiration_date = slirp->cb->clock_get_ns() + 1000000000ULL;
+ ifm->expiration_date = slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL;
}
return 0;
} else {
eh->h_dest[0], eh->h_dest[1], eh->h_dest[2],
eh->h_dest[3], eh->h_dest[4], eh->h_dest[5]);
memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
- slirp->cb->output(slirp->opaque, buf, ifm->m_len + ETH_HLEN);
+ slirp_send_packet_all(slirp, buf, ifm->m_len + ETH_HLEN);
return 1;
}
getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
addr.sin_addr.s_addr == host_addr.s_addr &&
addr.sin_port == port) {
- close(so->s);
+ so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque);
+ closesocket(so->s);
sofree(so);
return 0;
}
return true;
}
-int slirp_add_exec(Slirp *slirp, void *chardev, const char *cmdline,
+int slirp_add_exec(Slirp *slirp, const char *cmdline,
struct in_addr *guest_addr, int guest_port)
{
if (!check_guestfwd(slirp, guest_addr, guest_port)) {
return -1;
}
- return add_exec(&slirp->guestfwd_list, chardev, cmdline, *guest_addr,
- htons(guest_port));
+ add_exec(&slirp->guestfwd_list, cmdline, *guest_addr, htons(guest_port));
+ return 0;
+}
+
+int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque,
+ struct in_addr *guest_addr, int guest_port)
+{
+ if (!check_guestfwd(slirp, guest_addr, guest_port)) {
+ return -1;
+ }
+
+ add_guestfwd(&slirp->guestfwd_list, write_cb, opaque,
+ *guest_addr, htons(guest_port));
+ return 0;
}
ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
{
- if (so->s == -1 && so->chardev) {
+ if (so->s == -1 && so->guestfwd) {
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
- qemu_chr_fe_write_all(so->chardev, buf, len);
+ so->guestfwd->write_cb(buf, len, so->guestfwd->opaque);
return len;
}
return send(so->s, buf, len, flags);
}
-static struct socket *
+struct socket *
slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port)
{
struct socket *so;
tcp_output(sototcpcb(so));
}
-static int slirp_tcp_post_load(void *opaque, int version)
+void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len)
{
- tcp_template((struct tcpcb *)opaque);
-
- return 0;
-}
+ ssize_t ret = slirp->cb->send_packet(buf, len, slirp->opaque);
-static const VMStateDescription vmstate_slirp_tcp = {
- .name = "slirp-tcp",
- .version_id = 0,
- .post_load = slirp_tcp_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_INT16(t_state, struct tcpcb),
- VMSTATE_INT16_ARRAY(t_timer, struct tcpcb, TCPT_NTIMERS),
- VMSTATE_INT16(t_rxtshift, struct tcpcb),
- VMSTATE_INT16(t_rxtcur, struct tcpcb),
- VMSTATE_INT16(t_dupacks, struct tcpcb),
- VMSTATE_UINT16(t_maxseg, struct tcpcb),
- VMSTATE_UINT8(t_force, struct tcpcb),
- VMSTATE_UINT16(t_flags, struct tcpcb),
- VMSTATE_UINT32(snd_una, struct tcpcb),
- VMSTATE_UINT32(snd_nxt, struct tcpcb),
- VMSTATE_UINT32(snd_up, struct tcpcb),
- VMSTATE_UINT32(snd_wl1, struct tcpcb),
- VMSTATE_UINT32(snd_wl2, struct tcpcb),
- VMSTATE_UINT32(iss, struct tcpcb),
- VMSTATE_UINT32(snd_wnd, struct tcpcb),
- VMSTATE_UINT32(rcv_wnd, struct tcpcb),
- VMSTATE_UINT32(rcv_nxt, struct tcpcb),
- VMSTATE_UINT32(rcv_up, struct tcpcb),
- VMSTATE_UINT32(irs, struct tcpcb),
- VMSTATE_UINT32(rcv_adv, struct tcpcb),
- VMSTATE_UINT32(snd_max, struct tcpcb),
- VMSTATE_UINT32(snd_cwnd, struct tcpcb),
- VMSTATE_UINT32(snd_ssthresh, struct tcpcb),
- VMSTATE_INT16(t_idle, struct tcpcb),
- VMSTATE_INT16(t_rtt, struct tcpcb),
- VMSTATE_UINT32(t_rtseq, struct tcpcb),
- VMSTATE_INT16(t_srtt, struct tcpcb),
- VMSTATE_INT16(t_rttvar, struct tcpcb),
- VMSTATE_UINT16(t_rttmin, struct tcpcb),
- VMSTATE_UINT32(max_sndwnd, struct tcpcb),
- VMSTATE_UINT8(t_oobflags, struct tcpcb),
- VMSTATE_UINT8(t_iobc, struct tcpcb),
- VMSTATE_INT16(t_softerror, struct tcpcb),
- VMSTATE_UINT8(snd_scale, struct tcpcb),
- VMSTATE_UINT8(rcv_scale, struct tcpcb),
- VMSTATE_UINT8(request_r_scale, struct tcpcb),
- VMSTATE_UINT8(requested_s_scale, struct tcpcb),
- VMSTATE_UINT32(ts_recent, struct tcpcb),
- VMSTATE_UINT32(ts_recent_age, struct tcpcb),
- VMSTATE_UINT32(last_ack_sent, struct tcpcb),
- VMSTATE_END_OF_LIST()
+ if (ret < 0) {
+ g_critical("Failed to send packet, ret: %ld", (long) ret);
+ } else if (ret < len) {
+ DEBUG_ERROR("send_packet() didn't send all data: %ld < %lu",
+ (long) ret, (unsigned long) len);
}
-};
-
-/* The sbuf has a pair of pointers that are migrated as offsets;
- * we calculate the offsets and restore the pointers using
- * pre_save/post_load on a tmp structure.
- */
-struct sbuf_tmp {
- struct sbuf *parent;
- uint32_t roff, woff;
-};
-
-static int sbuf_tmp_pre_save(void *opaque)
-{
- struct sbuf_tmp *tmp = opaque;
- tmp->woff = tmp->parent->sb_wptr - tmp->parent->sb_data;
- tmp->roff = tmp->parent->sb_rptr - tmp->parent->sb_data;
-
- return 0;
-}
-
-static int sbuf_tmp_post_load(void *opaque, int version)
-{
- struct sbuf_tmp *tmp = opaque;
- uint32_t requested_len = tmp->parent->sb_datalen;
-
- /* Allocate the buffer space used by the field after the tmp */
- sbreserve(tmp->parent, tmp->parent->sb_datalen);
-
- if (tmp->parent->sb_datalen != requested_len) {
- return -ENOMEM;
- }
- if (tmp->woff >= requested_len ||
- tmp->roff >= requested_len) {
- g_critical("invalid sbuf offsets r/w=%u/%u len=%u",
- tmp->roff, tmp->woff, requested_len);
- return -EINVAL;
- }
-
- tmp->parent->sb_wptr = tmp->parent->sb_data + tmp->woff;
- tmp->parent->sb_rptr = tmp->parent->sb_data + tmp->roff;
-
- return 0;
-}
-
-
-static const VMStateDescription vmstate_slirp_sbuf_tmp = {
- .name = "slirp-sbuf-tmp",
- .post_load = sbuf_tmp_post_load,
- .pre_save = sbuf_tmp_pre_save,
- .version_id = 0,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(woff, struct sbuf_tmp),
- VMSTATE_UINT32(roff, struct sbuf_tmp),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_slirp_sbuf = {
- .name = "slirp-sbuf",
- .version_id = 0,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(sb_cc, struct sbuf),
- VMSTATE_UINT32(sb_datalen, struct sbuf),
- VMSTATE_WITH_TMP(struct sbuf, struct sbuf_tmp, vmstate_slirp_sbuf_tmp),
- VMSTATE_VBUFFER_UINT32(sb_data, struct sbuf, 0, NULL, sb_datalen),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool slirp_older_than_v4(void *opaque, int version_id)
-{
- return version_id < 4;
-}
-
-static bool slirp_family_inet(void *opaque, int version_id)
-{
- union slirp_sockaddr *ssa = (union slirp_sockaddr *)opaque;
- return ssa->ss.ss_family == AF_INET;
-}
-
-static int slirp_socket_pre_load(void *opaque)
-{
- struct socket *so = opaque;
- if (tcp_attach(so) < 0) {
- return -ENOMEM;
- }
- /* Older versions don't load these fields */
- so->so_ffamily = AF_INET;
- so->so_lfamily = AF_INET;
- return 0;
-}
-
-#ifndef _WIN32
-#define VMSTATE_SIN4_ADDR(f, s, t) VMSTATE_UINT32_TEST(f, s, t)
-#else
-/* Win uses u_long rather than uint32_t - but it's still 32bits long */
-#define VMSTATE_SIN4_ADDR(f, s, t) VMSTATE_SINGLE_TEST(f, s, t, 0, \
- vmstate_info_uint32, u_long)
-#endif
-
-/* The OS provided ss_family field isn't that portable; it's size
- * and type varies (16/8 bit, signed, unsigned)
- * and the values it contains aren't fully portable.
- */
-typedef struct SS_FamilyTmpStruct {
- union slirp_sockaddr *parent;
- uint16_t portable_family;
-} SS_FamilyTmpStruct;
-
-#define SS_FAMILY_MIG_IPV4 2 /* Linux, BSD, Win... */
-#define SS_FAMILY_MIG_IPV6 10 /* Linux */
-#define SS_FAMILY_MIG_OTHER 0xffff
-
-static int ss_family_pre_save(void *opaque)
-{
- SS_FamilyTmpStruct *tss = opaque;
-
- tss->portable_family = SS_FAMILY_MIG_OTHER;
-
- if (tss->parent->ss.ss_family == AF_INET) {
- tss->portable_family = SS_FAMILY_MIG_IPV4;
- } else if (tss->parent->ss.ss_family == AF_INET6) {
- tss->portable_family = SS_FAMILY_MIG_IPV6;
- }
-
- return 0;
-}
-
-static int ss_family_post_load(void *opaque, int version_id)
-{
- SS_FamilyTmpStruct *tss = opaque;
-
- switch (tss->portable_family) {
- case SS_FAMILY_MIG_IPV4:
- tss->parent->ss.ss_family = AF_INET;
- break;
- case SS_FAMILY_MIG_IPV6:
- case 23: /* compatibility: AF_INET6 from mingw */
- case 28: /* compatibility: AF_INET6 from FreeBSD sys/socket.h */
- tss->parent->ss.ss_family = AF_INET6;
- break;
- default:
- g_critical("invalid ss_family type %x", tss->portable_family);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static const VMStateDescription vmstate_slirp_ss_family = {
- .name = "slirp-socket-addr/ss_family",
- .pre_save = ss_family_pre_save,
- .post_load = ss_family_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_UINT16(portable_family, SS_FamilyTmpStruct),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_slirp_socket_addr = {
- .name = "slirp-socket-addr",
- .version_id = 4,
- .fields = (VMStateField[]) {
- VMSTATE_WITH_TMP(union slirp_sockaddr, SS_FamilyTmpStruct,
- vmstate_slirp_ss_family),
- VMSTATE_SIN4_ADDR(sin.sin_addr.s_addr, union slirp_sockaddr,
- slirp_family_inet),
- VMSTATE_UINT16_TEST(sin.sin_port, union slirp_sockaddr,
- slirp_family_inet),
-
-#if 0
- /* Untested: Needs checking by someone with IPv6 test */
- VMSTATE_BUFFER_TEST(sin6.sin6_addr, union slirp_sockaddr,
- slirp_family_inet6),
- VMSTATE_UINT16_TEST(sin6.sin6_port, union slirp_sockaddr,
- slirp_family_inet6),
- VMSTATE_UINT32_TEST(sin6.sin6_flowinfo, union slirp_sockaddr,
- slirp_family_inet6),
- VMSTATE_UINT32_TEST(sin6.sin6_scope_id, union slirp_sockaddr,
- slirp_family_inet6),
-#endif
-
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_slirp_socket = {
- .name = "slirp-socket",
- .version_id = 4,
- .pre_load = slirp_socket_pre_load,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(so_urgc, struct socket),
- /* Pre-v4 versions */
- VMSTATE_SIN4_ADDR(so_faddr.s_addr, struct socket,
- slirp_older_than_v4),
- VMSTATE_SIN4_ADDR(so_laddr.s_addr, struct socket,
- slirp_older_than_v4),
- VMSTATE_UINT16_TEST(so_fport, struct socket, slirp_older_than_v4),
- VMSTATE_UINT16_TEST(so_lport, struct socket, slirp_older_than_v4),
- /* v4 and newer */
- VMSTATE_STRUCT(fhost, struct socket, 4, vmstate_slirp_socket_addr,
- union slirp_sockaddr),
- VMSTATE_STRUCT(lhost, struct socket, 4, vmstate_slirp_socket_addr,
- union slirp_sockaddr),
-
- VMSTATE_UINT8(so_iptos, struct socket),
- VMSTATE_UINT8(so_emu, struct socket),
- VMSTATE_UINT8(so_type, struct socket),
- VMSTATE_INT32(so_state, struct socket),
- VMSTATE_STRUCT(so_rcv, struct socket, 0, vmstate_slirp_sbuf,
- struct sbuf),
- VMSTATE_STRUCT(so_snd, struct socket, 0, vmstate_slirp_sbuf,
- struct sbuf),
- VMSTATE_STRUCT_POINTER(so_tcpcb, struct socket, vmstate_slirp_tcp,
- struct tcpcb),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_slirp_bootp_client = {
- .name = "slirp_bootpclient",
- .fields = (VMStateField[]) {
- VMSTATE_UINT16(allocated, BOOTPClient),
- VMSTATE_BUFFER(macaddr, BOOTPClient),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_slirp = {
- .name = "slirp",
- .version_id = 4,
- .fields = (VMStateField[]) {
- VMSTATE_UINT16_V(ip_id, Slirp, 2),
- VMSTATE_STRUCT_ARRAY(bootp_clients, Slirp, NB_BOOTP_CLIENTS, 3,
- vmstate_slirp_bootp_client, BOOTPClient),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void slirp_state_save(QEMUFile *f, void *opaque)
-{
- Slirp *slirp = opaque;
- struct gfwd_list *ex_ptr;
-
- for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
- if (ex_ptr->ex_chardev) {
- struct socket *so;
- so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
- ntohs(ex_ptr->ex_fport));
- if (!so)
- continue;
-
- qemu_put_byte(f, 42);
- vmstate_save_state(f, &vmstate_slirp_socket, so, NULL);
- }
- qemu_put_byte(f, 0);
-
- vmstate_save_state(f, &vmstate_slirp, slirp, NULL);
-}
-
-
-static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
-{
- Slirp *slirp = opaque;
- struct gfwd_list *ex_ptr;
-
- while (qemu_get_byte(f)) {
- int ret;
- struct socket *so = socreate(slirp);
-
- ret = vmstate_load_state(f, &vmstate_slirp_socket, so, version_id);
-
- if (ret < 0)
- return ret;
-
- if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) !=
- slirp->vnetwork_addr.s_addr) {
- return -EINVAL;
- }
- for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
- if (ex_ptr->ex_chardev &&
- so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
- so->so_fport == ex_ptr->ex_fport) {
- break;
- }
- }
- if (!ex_ptr)
- return -EINVAL;
- }
-
- return vmstate_load_state(f, &vmstate_slirp, slirp, version_id);
}
#ifdef _WIN32
-typedef char *caddr_t;
+/* as defined in sdkddkver.h */
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600 /* Vista */
+#endif
+/* reduces the number of implicitly included headers */
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
-# include <windows.h>
# include <winsock2.h>
+# include <windows.h>
# include <ws2tcpip.h>
# include <sys/timeb.h>
# include <iphlpapi.h>
#ifndef _WIN32
#include <sys/uio.h>
-#endif
-
-#ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
-#endif
-
-#ifndef _WIN32
#include <sys/socket.h>
-#endif
-
-#ifndef _WIN32
-# include <sys/ioctl.h>
+#include <sys/ioctl.h>
#endif
#ifdef __APPLE__
#define quehead slirp_quehead
#include "debug.h"
-
-#include "qemu/queue.h"
-#include "qemu/sockets.h"
-#include "net/eth.h"
+#include "util.h"
+#include "qtailq.h"
#include "libslirp.h"
#include "ip.h"
uint32_t ar_sip; /* sender IP address */
unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
uint32_t ar_tip; /* target IP address */
-} QEMU_PACKED;
+} SLIRP_PACKED;
#define ARP_TABLE_SIZE 16
struct ndpentry {
unsigned char eth_addr[ETH_ALEN]; /* sender hardware address */
struct in6_addr ip_addr; /* sender IP address */
-} QEMU_PACKED;
+} SLIRP_PACKED;
#define NDP_TABLE_SIZE 16
struct Slirp {
QTAILQ_ENTRY(Slirp) entry;
- u_int time_fasttimo;
- u_int last_slowtimo;
+ unsigned time_fasttimo;
+ unsigned last_slowtimo;
bool do_slowtimo;
bool in_enabled, in6_enabled;
NdpTable ndp_table;
GRand *grand;
- QEMUTimer *ra_timer;
+ void *ra_timer;
const SlirpCb *cb;
void *opaque;
/* tcp_input.c */
void tcp_input(register struct mbuf *, int, struct socket *, unsigned short af);
-int tcp_mss(register struct tcpcb *, u_int);
+int tcp_mss(register struct tcpcb *, unsigned);
/* tcp_output.c */
int tcp_output(register struct tcpcb *);
int tcp_ctl(struct socket *);
struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
+struct socket *
+slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port);
+
+void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len);
+
#endif
* terms and conditions of the copyright.
*/
-#include "qemu/osdep.h"
-#include "qemu-common.h"
#include "slirp.h"
#include "ip_icmp.h"
#ifdef __sun__
*/
sopreprbuf(so, iov, &n);
- nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
+ nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
if (nn <= 0) {
if (nn < 0 && (errno == EINTR || errno == EAGAIN))
return 0;
*/
if (n == 2 && nn == iov[0].iov_len) {
int ret;
- ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
+ ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
if (ret > 0)
nn += ret;
}
/* XXX Check if reply is "correct"? */
if(len == -1 || len == 0) {
- u_char code=ICMP_UNREACH_PORT;
+ uint8_t code=ICMP_UNREACH_PORT;
if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
* Listen for incoming TCP connections
*/
struct socket *
-tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
- u_int lport, int flags)
+tcp_listen(Slirp *slirp, uint32_t haddr, unsigned hport, uint32_t laddr,
+ unsigned lport, int flags)
{
struct sockaddr_in addr;
struct socket *so;
addr.sin_addr.s_addr = haddr;
addr.sin_port = hport;
- if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) ||
- (socket_set_fast_reuse(s) < 0) ||
+ if (((s = slirp_socket(AF_INET,SOCK_STREAM,0)) < 0) ||
+ (slirp_socket_set_fast_reuse(s) < 0) ||
(bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
(listen(s,1) < 0)) {
int tmperrno = errno; /* Don't clobber the real reason we failed */
#endif
return NULL;
}
- qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
+ setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
opt = 1;
- qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int));
+ setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int));
getsockname(s,(struct sockaddr *)&addr,&addrlen);
so->so_ffamily = AF_INET;
break;
}
}
+
+void sodrop(struct socket *s, int num)
+{
+ if (sbdrop(&s->so_snd, num)) {
+ s->slirp->cb->notify(s->slirp->opaque);
+ }
+}
#ifndef SLIRP_SOCKET_H
#define SLIRP_SOCKET_H
+#include "misc.h"
+
#define SO_EXPIRE 240000
#define SO_EXPIREFAST 10000
struct socket *so_next,*so_prev; /* For a linked list of sockets */
int s; /* The actual socket */
+ struct gfwd_list *guestfwd;
int pollfds_idx; /* GPollFD GArray index */
int32_t so_state; /* internal state flags SS_*, below */
struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */
- u_int so_expire; /* When the socket will expire */
+ unsigned so_expire; /* When the socket will expire */
int so_queued; /* Number of packets queued from this socket */
int so_nqueued; /* Number of packets queued in a row
struct sbuf so_rcv; /* Receive buffer */
struct sbuf so_snd; /* Send buffer */
- void * chardev;
};
int sowrite(struct socket *);
void sorecvfrom(struct socket *);
int sosendto(struct socket *, struct mbuf *);
-struct socket * tcp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int,
+struct socket * tcp_listen(Slirp *, uint32_t, unsigned, uint32_t, unsigned,
int);
void soisfconnecting(register struct socket *);
void soisfconnected(register struct socket *);
void sotranslate_out(struct socket *, struct sockaddr_storage *);
void sotranslate_in(struct socket *, struct sockaddr_storage *);
void sotranslate_accept(struct socket *);
+void sodrop(struct socket *, int num);
#endif /* SLIRP_SOCKET_H */
--- /dev/null
+/*
+ * libslirp
+ *
+ * Copyright (c) 2004-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+
+#include "slirp.h"
+#include "state.h"
+#include "migration/vmstate.h"
+#include "migration/qemu-file-types.h"
+#include "migration/register.h"
+
+static int slirp_tcp_post_load(void *opaque, int version)
+{
+ tcp_template((struct tcpcb *)opaque);
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_slirp_tcp = {
+ .name = "slirp-tcp",
+ .version_id = 0,
+ .post_load = slirp_tcp_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT16(t_state, struct tcpcb),
+ VMSTATE_INT16_ARRAY(t_timer, struct tcpcb, TCPT_NTIMERS),
+ VMSTATE_INT16(t_rxtshift, struct tcpcb),
+ VMSTATE_INT16(t_rxtcur, struct tcpcb),
+ VMSTATE_INT16(t_dupacks, struct tcpcb),
+ VMSTATE_UINT16(t_maxseg, struct tcpcb),
+ VMSTATE_UINT8(t_force, struct tcpcb),
+ VMSTATE_UINT16(t_flags, struct tcpcb),
+ VMSTATE_UINT32(snd_una, struct tcpcb),
+ VMSTATE_UINT32(snd_nxt, struct tcpcb),
+ VMSTATE_UINT32(snd_up, struct tcpcb),
+ VMSTATE_UINT32(snd_wl1, struct tcpcb),
+ VMSTATE_UINT32(snd_wl2, struct tcpcb),
+ VMSTATE_UINT32(iss, struct tcpcb),
+ VMSTATE_UINT32(snd_wnd, struct tcpcb),
+ VMSTATE_UINT32(rcv_wnd, struct tcpcb),
+ VMSTATE_UINT32(rcv_nxt, struct tcpcb),
+ VMSTATE_UINT32(rcv_up, struct tcpcb),
+ VMSTATE_UINT32(irs, struct tcpcb),
+ VMSTATE_UINT32(rcv_adv, struct tcpcb),
+ VMSTATE_UINT32(snd_max, struct tcpcb),
+ VMSTATE_UINT32(snd_cwnd, struct tcpcb),
+ VMSTATE_UINT32(snd_ssthresh, struct tcpcb),
+ VMSTATE_INT16(t_idle, struct tcpcb),
+ VMSTATE_INT16(t_rtt, struct tcpcb),
+ VMSTATE_UINT32(t_rtseq, struct tcpcb),
+ VMSTATE_INT16(t_srtt, struct tcpcb),
+ VMSTATE_INT16(t_rttvar, struct tcpcb),
+ VMSTATE_UINT16(t_rttmin, struct tcpcb),
+ VMSTATE_UINT32(max_sndwnd, struct tcpcb),
+ VMSTATE_UINT8(t_oobflags, struct tcpcb),
+ VMSTATE_UINT8(t_iobc, struct tcpcb),
+ VMSTATE_INT16(t_softerror, struct tcpcb),
+ VMSTATE_UINT8(snd_scale, struct tcpcb),
+ VMSTATE_UINT8(rcv_scale, struct tcpcb),
+ VMSTATE_UINT8(request_r_scale, struct tcpcb),
+ VMSTATE_UINT8(requested_s_scale, struct tcpcb),
+ VMSTATE_UINT32(ts_recent, struct tcpcb),
+ VMSTATE_UINT32(ts_recent_age, struct tcpcb),
+ VMSTATE_UINT32(last_ack_sent, struct tcpcb),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+/* The sbuf has a pair of pointers that are migrated as offsets;
+ * we calculate the offsets and restore the pointers using
+ * pre_save/post_load on a tmp structure.
+ */
+struct sbuf_tmp {
+ struct sbuf *parent;
+ uint32_t roff, woff;
+};
+
+static int sbuf_tmp_pre_save(void *opaque)
+{
+ struct sbuf_tmp *tmp = opaque;
+ tmp->woff = tmp->parent->sb_wptr - tmp->parent->sb_data;
+ tmp->roff = tmp->parent->sb_rptr - tmp->parent->sb_data;
+
+ return 0;
+}
+
+static int sbuf_tmp_post_load(void *opaque, int version)
+{
+ struct sbuf_tmp *tmp = opaque;
+ uint32_t requested_len = tmp->parent->sb_datalen;
+
+ /* Allocate the buffer space used by the field after the tmp */
+ sbreserve(tmp->parent, tmp->parent->sb_datalen);
+
+ if (tmp->parent->sb_datalen != requested_len) {
+ return -ENOMEM;
+ }
+ if (tmp->woff >= requested_len ||
+ tmp->roff >= requested_len) {
+ g_critical("invalid sbuf offsets r/w=%u/%u len=%u",
+ tmp->roff, tmp->woff, requested_len);
+ return -EINVAL;
+ }
+
+ tmp->parent->sb_wptr = tmp->parent->sb_data + tmp->woff;
+ tmp->parent->sb_rptr = tmp->parent->sb_data + tmp->roff;
+
+ return 0;
+}
+
+
+static const VMStateDescription vmstate_slirp_sbuf_tmp = {
+ .name = "slirp-sbuf-tmp",
+ .post_load = sbuf_tmp_post_load,
+ .pre_save = sbuf_tmp_pre_save,
+ .version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(woff, struct sbuf_tmp),
+ VMSTATE_UINT32(roff, struct sbuf_tmp),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_slirp_sbuf = {
+ .name = "slirp-sbuf",
+ .version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(sb_cc, struct sbuf),
+ VMSTATE_UINT32(sb_datalen, struct sbuf),
+ VMSTATE_WITH_TMP(struct sbuf, struct sbuf_tmp, vmstate_slirp_sbuf_tmp),
+ VMSTATE_VBUFFER_UINT32(sb_data, struct sbuf, 0, NULL, sb_datalen),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static bool slirp_older_than_v4(void *opaque, int version_id)
+{
+ return version_id < 4;
+}
+
+static bool slirp_family_inet(void *opaque, int version_id)
+{
+ union slirp_sockaddr *ssa = (union slirp_sockaddr *)opaque;
+ return ssa->ss.ss_family == AF_INET;
+}
+
+static int slirp_socket_pre_load(void *opaque)
+{
+ struct socket *so = opaque;
+ if (tcp_attach(so) < 0) {
+ return -ENOMEM;
+ }
+ /* Older versions don't load these fields */
+ so->so_ffamily = AF_INET;
+ so->so_lfamily = AF_INET;
+ return 0;
+}
+
+#ifndef _WIN32
+#define VMSTATE_SIN4_ADDR(f, s, t) VMSTATE_UINT32_TEST(f, s, t)
+#else
+/* Win uses u_long rather than uint32_t - but it's still 32bits long */
+#define VMSTATE_SIN4_ADDR(f, s, t) VMSTATE_SINGLE_TEST(f, s, t, 0, \
+ vmstate_info_uint32, u_long)
+#endif
+
+/* The OS provided ss_family field isn't that portable; it's size
+ * and type varies (16/8 bit, signed, unsigned)
+ * and the values it contains aren't fully portable.
+ */
+typedef struct SS_FamilyTmpStruct {
+ union slirp_sockaddr *parent;
+ uint16_t portable_family;
+} SS_FamilyTmpStruct;
+
+#define SS_FAMILY_MIG_IPV4 2 /* Linux, BSD, Win... */
+#define SS_FAMILY_MIG_IPV6 10 /* Linux */
+#define SS_FAMILY_MIG_OTHER 0xffff
+
+static int ss_family_pre_save(void *opaque)
+{
+ SS_FamilyTmpStruct *tss = opaque;
+
+ tss->portable_family = SS_FAMILY_MIG_OTHER;
+
+ if (tss->parent->ss.ss_family == AF_INET) {
+ tss->portable_family = SS_FAMILY_MIG_IPV4;
+ } else if (tss->parent->ss.ss_family == AF_INET6) {
+ tss->portable_family = SS_FAMILY_MIG_IPV6;
+ }
+
+ return 0;
+}
+
+static int ss_family_post_load(void *opaque, int version_id)
+{
+ SS_FamilyTmpStruct *tss = opaque;
+
+ switch (tss->portable_family) {
+ case SS_FAMILY_MIG_IPV4:
+ tss->parent->ss.ss_family = AF_INET;
+ break;
+ case SS_FAMILY_MIG_IPV6:
+ case 23: /* compatibility: AF_INET6 from mingw */
+ case 28: /* compatibility: AF_INET6 from FreeBSD sys/socket.h */
+ tss->parent->ss.ss_family = AF_INET6;
+ break;
+ default:
+ g_critical("invalid ss_family type %x", tss->portable_family);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_slirp_ss_family = {
+ .name = "slirp-socket-addr/ss_family",
+ .pre_save = ss_family_pre_save,
+ .post_load = ss_family_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT16(portable_family, SS_FamilyTmpStruct),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_slirp_socket_addr = {
+ .name = "slirp-socket-addr",
+ .version_id = 4,
+ .fields = (VMStateField[]) {
+ VMSTATE_WITH_TMP(union slirp_sockaddr, SS_FamilyTmpStruct,
+ vmstate_slirp_ss_family),
+ VMSTATE_SIN4_ADDR(sin.sin_addr.s_addr, union slirp_sockaddr,
+ slirp_family_inet),
+ VMSTATE_UINT16_TEST(sin.sin_port, union slirp_sockaddr,
+ slirp_family_inet),
+
+#if 0
+ /* Untested: Needs checking by someone with IPv6 test */
+ VMSTATE_BUFFER_TEST(sin6.sin6_addr, union slirp_sockaddr,
+ slirp_family_inet6),
+ VMSTATE_UINT16_TEST(sin6.sin6_port, union slirp_sockaddr,
+ slirp_family_inet6),
+ VMSTATE_UINT32_TEST(sin6.sin6_flowinfo, union slirp_sockaddr,
+ slirp_family_inet6),
+ VMSTATE_UINT32_TEST(sin6.sin6_scope_id, union slirp_sockaddr,
+ slirp_family_inet6),
+#endif
+
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_slirp_socket = {
+ .name = "slirp-socket",
+ .version_id = 4,
+ .pre_load = slirp_socket_pre_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(so_urgc, struct socket),
+ /* Pre-v4 versions */
+ VMSTATE_SIN4_ADDR(so_faddr.s_addr, struct socket,
+ slirp_older_than_v4),
+ VMSTATE_SIN4_ADDR(so_laddr.s_addr, struct socket,
+ slirp_older_than_v4),
+ VMSTATE_UINT16_TEST(so_fport, struct socket, slirp_older_than_v4),
+ VMSTATE_UINT16_TEST(so_lport, struct socket, slirp_older_than_v4),
+ /* v4 and newer */
+ VMSTATE_STRUCT(fhost, struct socket, 4, vmstate_slirp_socket_addr,
+ union slirp_sockaddr),
+ VMSTATE_STRUCT(lhost, struct socket, 4, vmstate_slirp_socket_addr,
+ union slirp_sockaddr),
+
+ VMSTATE_UINT8(so_iptos, struct socket),
+ VMSTATE_UINT8(so_emu, struct socket),
+ VMSTATE_UINT8(so_type, struct socket),
+ VMSTATE_INT32(so_state, struct socket),
+ VMSTATE_STRUCT(so_rcv, struct socket, 0, vmstate_slirp_sbuf,
+ struct sbuf),
+ VMSTATE_STRUCT(so_snd, struct socket, 0, vmstate_slirp_sbuf,
+ struct sbuf),
+ VMSTATE_STRUCT_POINTER(so_tcpcb, struct socket, vmstate_slirp_tcp,
+ struct tcpcb),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_slirp_bootp_client = {
+ .name = "slirp_bootpclient",
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT16(allocated, BOOTPClient),
+ VMSTATE_BUFFER(macaddr, BOOTPClient),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_slirp = {
+ .name = "slirp",
+ .version_id = 4,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT16_V(ip_id, Slirp, 2),
+ VMSTATE_STRUCT_ARRAY(bootp_clients, Slirp, NB_BOOTP_CLIENTS, 3,
+ vmstate_slirp_bootp_client, BOOTPClient),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void slirp_state_save(QEMUFile *f, void *opaque)
+{
+ Slirp *slirp = opaque;
+ struct gfwd_list *ex_ptr;
+
+ for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+ if (ex_ptr->write_cb) {
+ struct socket *so;
+ so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
+ ntohs(ex_ptr->ex_fport));
+ if (!so) {
+ continue;
+ }
+
+ qemu_put_byte(f, 42);
+ vmstate_save_state(f, &vmstate_slirp_socket, so, NULL);
+ }
+ qemu_put_byte(f, 0);
+
+ vmstate_save_state(f, &vmstate_slirp, slirp, NULL);
+}
+
+
+static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
+{
+ Slirp *slirp = opaque;
+ struct gfwd_list *ex_ptr;
+
+ while (qemu_get_byte(f)) {
+ int ret;
+ struct socket *so = socreate(slirp);
+
+ ret = vmstate_load_state(f, &vmstate_slirp_socket, so, version_id);
+ if (ret < 0) {
+ return ret;
+ }
+
+ if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) !=
+ slirp->vnetwork_addr.s_addr) {
+ return -EINVAL;
+ }
+ for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+ if (ex_ptr->write_cb &&
+ so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
+ so->so_fport == ex_ptr->ex_fport) {
+ break;
+ }
+ }
+ if (!ex_ptr) {
+ return -EINVAL;
+ }
+ }
+
+ return vmstate_load_state(f, &vmstate_slirp, slirp, version_id);
+}
+
+void slirp_state_register(Slirp *slirp)
+{
+ static SaveVMHandlers savevm_slirp_state = {
+ .save_state = slirp_state_save,
+ .load_state = slirp_state_load,
+ };
+
+ register_savevm_live(NULL, "slirp", 0, 4, &savevm_slirp_state, slirp);
+}
+
+void slirp_state_unregister(Slirp *slirp)
+{
+ unregister_savevm(NULL, "slirp", slirp);
+}
--- /dev/null
+#ifndef SLIRP_STATE_H_
+#define SLIRP_STATE_H_
+
+#include "libslirp.h"
+
+void slirp_state_register(Slirp *slirp);
+void slirp_state_unregister(Slirp *slirp);
+
+#endif /* SLIRP_STATE_H_ */
* terms and conditions of the copyright.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
#include "ip_icmp.h"
} \
}
-static void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt,
+static void tcp_dooptions(struct tcpcb *tp, uint8_t *cp, int cnt,
struct tcpiphdr *ti);
static void tcp_xmit_timer(register struct tcpcb *tp, int rtt);
struct ip save_ip, *ip;
struct ip6 save_ip6, *ip6;
register struct tcpiphdr *ti;
- caddr_t optp = NULL;
+ char *optp = NULL;
int optlen = 0;
int len, tlen, off;
register struct tcpcb *tp = NULL;
struct socket *so = NULL;
int todrop, acked, ourfinisacked, needoutput = 0;
int iss = 0;
- u_long tiwin;
+ uint32_t tiwin;
int ret;
struct sockaddr_storage lhost, fhost;
struct sockaddr_in *lhost4, *fhost4;
ti->ti_len = tlen;
if (off > sizeof (struct tcphdr)) {
optlen = off - sizeof (struct tcphdr);
- optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
+ optp = mtod(m, char *) + sizeof (struct tcpiphdr);
}
tiflags = ti->ti_flags;
* else do it below (after getting remote address).
*/
if (optp && tp->t_state != TCPS_LISTEN)
- tcp_dooptions(tp, (u_char *)optp, optlen, ti);
+ tcp_dooptions(tp, (uint8_t *)optp, optlen, ti);
/*
* Header prediction: check for the two common cases
SEQ_GT(ti->ti_ack, tp->t_rtseq))
tcp_xmit_timer(tp, tp->t_rtt);
acked = ti->ti_ack - tp->snd_una;
- sbdrop(&so->so_snd, acked);
+ sodrop(so, acked);
tp->snd_una = ti->ti_ack;
m_free(m);
tcp_template(tp);
if (optp)
- tcp_dooptions(tp, (u_char *)optp, optlen, ti);
+ tcp_dooptions(tp, (uint8_t *)optp, optlen, ti);
if (iss)
tp->iss = iss;
tp->t_dupacks = 0;
else if (++tp->t_dupacks == TCPREXMTTHRESH) {
tcp_seq onxt = tp->snd_nxt;
- u_int win =
+ unsigned win =
MIN(tp->snd_wnd, tp->snd_cwnd) /
2 / tp->t_maxseg;
* (maxseg^2 / cwnd per packet).
*/
{
- register u_int cw = tp->snd_cwnd;
- register u_int incr = tp->t_maxseg;
+ register unsigned cw = tp->snd_cwnd;
+ register unsigned incr = tp->t_maxseg;
if (cw > tp->snd_ssthresh)
incr = incr * incr / cw;
}
if (acked > so->so_snd.sb_cc) {
tp->snd_wnd -= so->so_snd.sb_cc;
- sbdrop(&so->so_snd, (int )so->so_snd.sb_cc);
+ sodrop(so, (int)so->so_snd.sb_cc);
ourfinisacked = 1;
} else {
- sbdrop(&so->so_snd, acked);
+ sodrop(so, acked);
tp->snd_wnd -= acked;
ourfinisacked = 0;
}
}
static void
-tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)
+tcp_dooptions(struct tcpcb *tp, uint8_t *cp, int cnt, struct tcpiphdr *ti)
{
uint16_t mss;
int opt, optlen;
*/
int
-tcp_mss(struct tcpcb *tp, u_int offer)
+tcp_mss(struct tcpcb *tp, unsigned offer)
{
struct socket *so = tp->t_socket;
int mss;
* terms and conditions of the copyright.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
-static const u_char tcp_outflags[TCP_NSTATES] = {
+static const uint8_t tcp_outflags[TCP_NSTATES] = {
TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
TH_FIN|TH_ACK, TH_ACK, TH_ACK,
register struct tcpiphdr *ti, tcpiph_save;
struct ip *ip;
struct ip6 *ip6;
- u_char opt[MAX_TCPOPTLEN];
+ uint8_t opt[MAX_TCPOPTLEN];
unsigned optlen, hdrlen;
int idle, sendalot;
opt[0] = TCPOPT_MAXSEG;
opt[1] = 4;
mss = htons((uint16_t) tcp_mss(tp, 0));
- memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss));
+ memcpy((char *)(opt + 2), (char *)&mss, sizeof(mss));
optlen = 4;
}
}
m->m_data += IF_MAXLINKHDR;
m->m_len = hdrlen;
- sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
+ sbcopy(&so->so_snd, off, (int) len, mtod(m, char *) + hdrlen);
m->m_len += len;
/*
ti = mtod(m, struct tcpiphdr *);
- memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));
+ memcpy((char *)ti, &tp->t_template, sizeof (struct tcpiphdr));
/*
* Fill in fields, remembering maximum advertised
ti->ti_seq = htonl(tp->snd_max);
ti->ti_ack = htonl(tp->rcv_nxt);
if (optlen) {
- memcpy((caddr_t)(ti + 1), (caddr_t)opt, optlen);
+ memcpy((char *)(ti + 1), (char *)opt, optlen);
ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;
}
ti->ti_flags = flags;
* terms and conditions of the copyright.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
/* patchable/settable parameters for tcp */
* ti points into m so the next line is just making
* the mbuf point to ti
*/
- m->m_data = (caddr_t)ti;
+ m->m_data = (char *)ti;
m->m_len = sizeof (struct tcpiphdr);
tlen = 0;
}
#undef xchg
}
- ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
+ ti->ti_len = htons((uint16_t)(sizeof (struct tcphdr) + tlen));
tlen += sizeof (struct tcpiphdr);
m->m_len = tlen;
/* clobber input socket cache if we're closing the cached connection */
if (so == slirp->tcp_last_so)
slirp->tcp_last_so = &slirp->tcb;
+ so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque);
closesocket(so->s);
sbfree(&so->so_rcv);
sbfree(&so->so_snd);
DEBUG_CALL("tcp_fconnect");
DEBUG_ARG("so = %p", so);
- ret = so->s = qemu_socket(af, SOCK_STREAM, 0);
+ ret = so->s = slirp_socket(af, SOCK_STREAM, 0);
if (ret >= 0) {
int opt, s=so->s;
struct sockaddr_storage addr;
- qemu_set_nonblock(s);
- socket_set_fast_reuse(s);
+ slirp_set_nonblock(s);
+ so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque);
+ slirp_socket_set_fast_reuse(s);
opt = 1;
- qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
+ setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
opt = 1;
- qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
+ setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
addr = so->fhost.ss;
DEBUG_CALL(" connect()ing");
tcp_close(sototcpcb(so)); /* This will sofree() as well */
return;
}
- qemu_set_nonblock(s);
- socket_set_fast_reuse(s);
+ slirp_set_nonblock(s);
+ so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque);
+ slirp_socket_set_fast_reuse(s);
opt = 1;
- qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
- socket_set_nodelay(s);
+ setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
+ slirp_socket_set_nodelay(s);
so->fhost.ss = addr;
sotranslate_accept(so);
/* Close the accept() socket, set right state */
if (inso->so_state & SS_FACCEPTONCE) {
/* If we only accept once, close the accept() socket */
+ so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque);
closesocket(so->s);
/* Don't select it yet, even though we have an FD */
tcp_emu(struct socket *so, struct mbuf *m)
{
Slirp *slirp = so->slirp;
- u_int n1, n2, n3, n4, n5, n6;
+ unsigned n1, n2, n3, n4, n5, n6;
char buff[257];
uint32_t laddr;
- u_int lport;
+ unsigned lport;
char *bptr;
DEBUG_CALL("tcp_emu");
bptr = m->m_data;
while (bptr < m->m_data + m->m_len) {
- u_short p;
+ uint16_t p;
static int ra = 0;
char ra_tbl[4];
/* This is the field containing the port
* number that RA-player is listening to.
*/
- lport = (((u_char*)bptr)[0] << 8)
- + ((u_char *)bptr)[1];
+ lport = (((uint8_t*)bptr)[0] << 8)
+ + ((uint8_t *)bptr)[1];
if (lport < 6970)
lport += 256; /* don't know why */
if (lport < 6970 || lport > 7170)
}
if (p == 7071)
p = 0;
- *(u_char *)bptr++ = (p >> 8) & 0xff;
- *(u_char *)bptr = p & 0xff;
+ *(uint8_t *)bptr++ = (p >> 8) & 0xff;
+ *(uint8_t *)bptr = p & 0xff;
ra = 0;
return 1; /* port redirected, we're done */
break;
for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
if (ex_ptr->ex_fport == so->so_fport &&
so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
- if (ex_ptr->ex_chardev) {
+ if (ex_ptr->write_cb) {
so->s = -1;
- so->chardev = ex_ptr->ex_chardev;
+ so->guestfwd = ex_ptr;
return 1;
}
DEBUG_MISC(" executing %s", ex_ptr->ex_exec);
* tcp_timer.c,v 1.2 1994/08/02 07:49:10 davidg Exp
*/
-#include "qemu/osdep.h"
#include "slirp.h"
static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer);
* to go below this.)
*/
{
- u_int win = MIN(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
+ unsigned win = MIN(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
if (win < 2)
win = 2;
tp->snd_cwnd = tp->t_maxseg;
short t_rxtshift; /* log(2) of rexmt exp. backoff */
short t_rxtcur; /* current retransmit value */
short t_dupacks; /* consecutive dup acks recd */
- u_short t_maxseg; /* maximum segment size */
+ uint16_t t_maxseg; /* maximum segment size */
uint8_t t_force; /* 1 if forcing out a byte */
- u_short t_flags;
+ uint16_t t_flags;
#define TF_ACKNOW 0x0001 /* ack peer immediately */
#define TF_DELACK 0x0002 /* ack, but try to delay it */
#define TF_NODELAY 0x0004 /* don't delay packets to coalesce */
tcp_seq t_rtseq; /* sequence number being timed */
short t_srtt; /* smoothed round-trip time */
short t_rttvar; /* variance in round-trip time */
- u_short t_rttmin; /* minimum rtt allowed */
+ uint16_t t_rttmin; /* minimum rtt allowed */
uint32_t max_sndwnd; /* largest window peer has offered */
/* out-of-band data */
short t_softerror; /* possible error not yet reported */
/* RFC 1323 variables */
- u_char snd_scale; /* window scaling for send window */
- u_char rcv_scale; /* window scaling for recv window */
- u_char request_r_scale; /* pending window scaling */
- u_char requested_s_scale;
+ uint8_t snd_scale; /* window scaling for send window */
+ uint8_t rcv_scale; /* window scaling for recv window */
+ uint8_t request_r_scale; /* pending window scaling */
+ uint8_t requested_s_scale;
uint32_t ts_recent; /* timestamp echo data */
uint32_t ts_recent_age; /* when last updated */
tcp_seq last_ack_sent;
* THE SOFTWARE.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
-#include "qemu-common.h"
-#include "qemu/cutils.h"
-#include "trace.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
static inline int tftp_session_in_use(struct tftp_session *spt)
{
struct mbuf *m;
struct tftp_t *tp;
- trace_slirp_tftp_error(msg);
+ DEBUG_TFTP("tftp error msg: %s", msg);
+
m = m_get(spt->slirp);
if (!m) {
tp->tp_op = htons(TFTP_ERROR);
tp->x.tp_error.tp_error_code = htons(errorcode);
- pstrcpy((char *)tp->x.tp_error.tp_msg, sizeof(tp->x.tp_error.tp_msg), msg);
+ slirp_pstrcpy((char *)tp->x.tp_error.tp_msg, sizeof(tp->x.tp_error.tp_msg), msg);
m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX + 2) + 3 + strlen(msg)
- sizeof(struct udphdr);
break;
}
}
- trace_slirp_tftp_rrq(req_fname);
+
+ DEBUG_TFTP("tftp rrq file: %s", req_fname);
/* check mode */
if ((pktlen - k) < 6) {
+++ /dev/null
-# See docs/devel/tracing.txt for syntax documentation.
-
-# slirp/tftp.c
-slirp_tftp_rrq(const char *file) "file: %s"
-slirp_tftp_error(const char *file) "msg: %s"
* terms and conditions of the copyright.
*/
-#include "qemu/osdep.h"
#include "slirp.h"
#include "ip_icmp.h"
* Get IP and UDP header together in first mbuf.
*/
ip = mtod(m, struct ip *);
- uh = (struct udphdr *)((caddr_t)ip + iphlen);
+ uh = (struct udphdr *)((char *)ip + iphlen);
/*
* Make mbuf data length reflect UDP length.
int
udp_attach(struct socket *so, unsigned short af)
{
- so->s = qemu_socket(af, SOCK_DGRAM, 0);
+ so->s = slirp_socket(af, SOCK_DGRAM, 0);
if (so->s != -1) {
so->so_expire = curtime + SO_EXPIRE;
insque(so, &so->slirp->udb);
void
udp_detach(struct socket *so)
{
+ so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque);
closesocket(so->s);
sofree(so);
}
}
struct socket *
-udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
- u_int lport, int flags)
+udp_listen(Slirp *slirp, uint32_t haddr, unsigned hport, uint32_t laddr,
+ unsigned lport, int flags)
{
struct sockaddr_in addr;
struct socket *so;
socklen_t addrlen = sizeof(struct sockaddr_in);
so = socreate(slirp);
- so->s = qemu_socket(AF_INET,SOCK_DGRAM,0);
+ so->s = slirp_socket(AF_INET,SOCK_DGRAM,0);
if (so->s < 0) {
sofree(so);
return NULL;
udp_detach(so);
return NULL;
}
- socket_set_fast_reuse(so->s);
+ slirp_socket_set_fast_reuse(so->s);
getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
so->fhost.sin = addr;
void udp_input(register struct mbuf *, int);
int udp_attach(struct socket *, unsigned short af);
void udp_detach(struct socket *);
-struct socket * udp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int,
+struct socket * udp_listen(Slirp *, uint32_t, unsigned, uint32_t, unsigned,
int);
int udp_output(struct socket *so, struct mbuf *m,
struct sockaddr_in *saddr, struct sockaddr_in *daddr,
* Guillaume Subiron
*/
-#include "qemu/osdep.h"
-#include "qemu-common.h"
#include "slirp.h"
#include "udp.h"
#include "dhcpv6.h"
--- /dev/null
+/*
+ * util.c (mostly based on QEMU os-win32.c)
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010-2016 Red Hat, Inc.
+ *
+ * QEMU library functions for win32 which are shared between QEMU and
+ * the QEMU tools.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "util.h"
+
+#include <glib.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+#if defined(_WIN32) && !defined(WITH_QEMU)
+int inet_aton(const char *cp, struct in_addr *ia)
+{
+ uint32_t addr = inet_addr(cp);
+ if (addr == 0xffffffff) {
+ return 0;
+ }
+ ia->s_addr = addr;
+ return 1;
+}
+#endif
+
+void slirp_set_nonblock(int fd)
+{
+#ifndef _WIN32
+ int f;
+ f = fcntl(fd, F_GETFL);
+ assert(f != -1);
+ f = fcntl(fd, F_SETFL, f | O_NONBLOCK);
+ assert(f != -1);
+#else
+ unsigned long opt = 1;
+ ioctlsocket(fd, FIONBIO, &opt);
+#endif
+}
+
+static void slirp_set_cloexec(int fd)
+{
+#ifndef _WIN32
+ int f;
+ f = fcntl(fd, F_GETFD);
+ assert(f != -1);
+ f = fcntl(fd, F_SETFD, f | FD_CLOEXEC);
+ assert(f != -1);
+#endif
+}
+
+/*
+ * Opens a socket with FD_CLOEXEC set
+ */
+int slirp_socket(int domain, int type, int protocol)
+{
+ int ret;
+
+#ifdef SOCK_CLOEXEC
+ ret = socket(domain, type | SOCK_CLOEXEC, protocol);
+ if (ret != -1 || errno != EINVAL) {
+ return ret;
+ }
+#endif
+ ret = socket(domain, type, protocol);
+ if (ret >= 0) {
+ slirp_set_cloexec(ret);
+ }
+
+ return ret;
+}
+
+#ifdef _WIN32
+static int socket_error(void)
+{
+ switch (WSAGetLastError()) {
+ case 0:
+ return 0;
+ case WSAEINTR:
+ return EINTR;
+ case WSAEINVAL:
+ return EINVAL;
+ case WSA_INVALID_HANDLE:
+ return EBADF;
+ case WSA_NOT_ENOUGH_MEMORY:
+ return ENOMEM;
+ case WSA_INVALID_PARAMETER:
+ return EINVAL;
+ case WSAENAMETOOLONG:
+ return ENAMETOOLONG;
+ case WSAENOTEMPTY:
+ return ENOTEMPTY;
+ case WSAEWOULDBLOCK:
+ /* not using EWOULDBLOCK as we don't want code to have
+ * to check both EWOULDBLOCK and EAGAIN */
+ return EAGAIN;
+ case WSAEINPROGRESS:
+ return EINPROGRESS;
+ case WSAEALREADY:
+ return EALREADY;
+ case WSAENOTSOCK:
+ return ENOTSOCK;
+ case WSAEDESTADDRREQ:
+ return EDESTADDRREQ;
+ case WSAEMSGSIZE:
+ return EMSGSIZE;
+ case WSAEPROTOTYPE:
+ return EPROTOTYPE;
+ case WSAENOPROTOOPT:
+ return ENOPROTOOPT;
+ case WSAEPROTONOSUPPORT:
+ return EPROTONOSUPPORT;
+ case WSAEOPNOTSUPP:
+ return EOPNOTSUPP;
+ case WSAEAFNOSUPPORT:
+ return EAFNOSUPPORT;
+ case WSAEADDRINUSE:
+ return EADDRINUSE;
+ case WSAEADDRNOTAVAIL:
+ return EADDRNOTAVAIL;
+ case WSAENETDOWN:
+ return ENETDOWN;
+ case WSAENETUNREACH:
+ return ENETUNREACH;
+ case WSAENETRESET:
+ return ENETRESET;
+ case WSAECONNABORTED:
+ return ECONNABORTED;
+ case WSAECONNRESET:
+ return ECONNRESET;
+ case WSAENOBUFS:
+ return ENOBUFS;
+ case WSAEISCONN:
+ return EISCONN;
+ case WSAENOTCONN:
+ return ENOTCONN;
+ case WSAETIMEDOUT:
+ return ETIMEDOUT;
+ case WSAECONNREFUSED:
+ return ECONNREFUSED;
+ case WSAELOOP:
+ return ELOOP;
+ case WSAEHOSTUNREACH:
+ return EHOSTUNREACH;
+ default:
+ return EIO;
+ }
+}
+
+#undef ioctlsocket
+int slirp_ioctlsocket_wrap(int fd, int req, void *val)
+{
+ int ret;
+ ret = ioctlsocket(fd, req, val);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef closesocket
+int slirp_closesocket_wrap(int fd)
+{
+ int ret;
+ ret = closesocket(fd);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef connect
+int slirp_connect_wrap(int sockfd, const struct sockaddr *addr, int addrlen)
+{
+ int ret;
+ ret = connect(sockfd, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef listen
+int slirp_listen_wrap(int sockfd, int backlog)
+{
+ int ret;
+ ret = listen(sockfd, backlog);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef bind
+int slirp_bind_wrap(int sockfd, const struct sockaddr *addr, int addrlen)
+{
+ int ret;
+ ret = bind(sockfd, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef socket
+int slirp_socket_wrap(int domain, int type, int protocol)
+{
+ int ret;
+ ret = socket(domain, type, protocol);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef accept
+int slirp_accept_wrap(int sockfd, struct sockaddr *addr, int *addrlen)
+{
+ int ret;
+ ret = accept(sockfd, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef shutdown
+int slirp_shutdown_wrap(int sockfd, int how)
+{
+ int ret;
+ ret = shutdown(sockfd, how);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef getsockopt
+int slirp_getsockopt_wrap(int sockfd, int level, int optname,
+ void *optval, int *optlen)
+{
+ int ret;
+ ret = getsockopt(sockfd, level, optname, optval, optlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef setsockopt
+int slirp_setsockopt_wrap(int sockfd, int level, int optname,
+ const void *optval, int optlen)
+{
+ int ret;
+ ret = setsockopt(sockfd, level, optname, optval, optlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef getpeername
+int slirp_getpeername_wrap(int sockfd, struct sockaddr *addr,
+ int *addrlen)
+{
+ int ret;
+ ret = getpeername(sockfd, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef getsockname
+int slirp_getsockname_wrap(int sockfd, struct sockaddr *addr,
+ int *addrlen)
+{
+ int ret;
+ ret = getsockname(sockfd, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef send
+ssize_t slirp_send_wrap(int sockfd, const void *buf, size_t len, int flags)
+{
+ int ret;
+ ret = send(sockfd, buf, len, flags);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef sendto
+ssize_t slirp_sendto_wrap(int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *addr, int addrlen)
+{
+ int ret;
+ ret = sendto(sockfd, buf, len, flags, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef recv
+ssize_t slirp_recv_wrap(int sockfd, void *buf, size_t len, int flags)
+{
+ int ret;
+ ret = recv(sockfd, buf, len, flags);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+#undef recvfrom
+ssize_t slirp_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags,
+ struct sockaddr *addr, int *addrlen)
+{
+ int ret;
+ ret = recvfrom(sockfd, buf, len, flags, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+#endif /* WIN32 */
+
+void slirp_pstrcpy(char *buf, int buf_size, const char *str)
+{
+ int c;
+ char *q = buf;
+
+ if (buf_size <= 0)
+ return;
+
+ for(;;) {
+ c = *str++;
+ if (c == 0 || q >= buf + buf_size - 1)
+ break;
+ *q++ = c;
+ }
+ *q = '\0';
+}
--- /dev/null
+/*
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010-2019 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef UTIL_H_
+#define UTIL_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <windows.h>
+#else
+#include <sys/socket.h>
+#include <netinet/tcp.h>
+#include <netinet/in.h>
+#endif
+
+#if defined(_WIN32)
+# define SLIRP_PACKED __attribute__((gcc_struct, packed))
+#else
+# define SLIRP_PACKED __attribute__((packed))
+#endif
+
+#ifndef DIV_ROUND_UP
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+#endif
+
+#ifndef container_of
+#define container_of(ptr, type, member) __extension__ ({ \
+ void *__mptr = (void *)(ptr); \
+ ((type *)(__mptr - offsetof(type, member))); })
+#endif
+
+#if defined(_WIN32) /* CONFIG_IOVEC */
+# if !defined(IOV_MAX) /* XXX: to avoid duplicate with QEMU osdep.h */
+struct iovec {
+ void *iov_base;
+ size_t iov_len;
+};
+# endif
+#else
+#include <sys/uio.h>
+#endif
+
+#define SCALE_MS 1000000
+
+#define ETH_ALEN 6
+#define ETH_HLEN 14
+#define ETH_P_IP (0x0800) /* Internet Protocol packet */
+#define ETH_P_ARP (0x0806) /* Address Resolution packet */
+#define ETH_P_IPV6 (0x86dd)
+#define ETH_P_VLAN (0x8100)
+#define ETH_P_DVLAN (0x88a8)
+#define ETH_P_NCSI (0x88f8)
+#define ETH_P_UNKNOWN (0xffff)
+
+/* FIXME: remove me when made standalone */
+#ifdef _WIN32
+#undef accept
+#undef bind
+#undef closesocket
+#undef connect
+#undef getpeername
+#undef getsockname
+#undef getsockopt
+#undef ioctlsocket
+#undef listen
+#undef recv
+#undef recvfrom
+#undef send
+#undef sendto
+#undef setsockopt
+#undef shutdown
+#undef socket
+#endif
+
+#ifdef _WIN32
+#define connect slirp_connect_wrap
+int slirp_connect_wrap(int fd, const struct sockaddr *addr, int addrlen);
+#define listen slirp_listen_wrap
+int slirp_listen_wrap(int fd, int backlog);
+#define bind slirp_bind_wrap
+int slirp_bind_wrap(int fd, const struct sockaddr *addr, int addrlen);
+#define socket slirp_socket_wrap
+int slirp_socket_wrap(int domain, int type, int protocol);
+#define accept slirp_accept_wrap
+int slirp_accept_wrap(int fd, struct sockaddr *addr, int *addrlen);
+#define shutdown slirp_shutdown_wrap
+int slirp_shutdown_wrap(int fd, int how);
+#define getpeername slirp_getpeername_wrap
+int slirp_getpeername_wrap(int fd, struct sockaddr *addr, int *addrlen);
+#define getsockname slirp_getsockname_wrap
+int slirp_getsockname_wrap(int fd, struct sockaddr *addr, int *addrlen);
+#define send slirp_send_wrap
+ssize_t slirp_send_wrap(int fd, const void *buf, size_t len, int flags);
+#define sendto slirp_sendto_wrap
+ssize_t slirp_sendto_wrap(int fd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, int addrlen);
+#define recv slirp_recv_wrap
+ssize_t slirp_recv_wrap(int fd, void *buf, size_t len, int flags);
+#define recvfrom slirp_recvfrom_wrap
+ssize_t slirp_recvfrom_wrap(int fd, void *buf, size_t len, int flags,
+ struct sockaddr *src_addr, int *addrlen);
+#define closesocket slirp_closesocket_wrap
+int slirp_closesocket_wrap(int fd);
+#define ioctlsocket slirp_ioctlsocket_wrap
+int slirp_ioctlsocket_wrap(int fd, int req, void *val);
+#define getsockopt slirp_getsockopt_wrap
+int slirp_getsockopt_wrap(int sockfd, int level, int optname,
+ void *optval, int *optlen);
+#define setsockopt slirp_setsockopt_wrap
+int slirp_setsockopt_wrap(int sockfd, int level, int optname,
+ const void *optval, int optlen);
+
+int inet_aton(const char *cp, struct in_addr *ia);
+#else
+#define closesocket(s) close(s)
+#define ioctlsocket(s, r, v) ioctl(s, r, v)
+#endif
+
+int slirp_socket(int domain, int type, int protocol);
+void slirp_set_nonblock(int fd);
+
+static inline int slirp_socket_set_nodelay(int fd)
+{
+ int v = 1;
+ return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
+}
+
+static inline int slirp_socket_set_fast_reuse(int fd)
+{
+#ifndef _WIN32
+ int v = 1;
+ return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v));
+#else
+ /* Enabling the reuse of an endpoint that was used by a socket still in
+ * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows
+ * fast reuse is the default and SO_REUSEADDR does strange things. So we
+ * don't have to do anything here. More info can be found at:
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */
+ return 0;
+#endif
+}
+
+void slirp_pstrcpy(char *buf, int buf_size, const char *str);
+
+#endif
-stub-obj-y += arch-query-cpu-def.o
-stub-obj-y += arch-query-cpu-model-expansion.o
-stub-obj-y += arch-query-cpu-model-comparison.o
-stub-obj-y += arch-query-cpu-model-baseline.o
stub-obj-y += bdrv-next-monitor-owned.o
stub-obj-y += blk-commit-all.o
stub-obj-y += blockdev-close-all-bdrv-states.o
stub-obj-y += replay.o
stub-obj-y += runstate-check.o
stub-obj-y += set-fd-handler.o
-stub-obj-y += slirp.o
stub-obj-y += sysbus.o
stub-obj-y += tpm.o
stub-obj-y += trace-control.o
stub-obj-y += uuid.o
stub-obj-y += vm-stop.o
stub-obj-y += vmstate.o
-stub-obj-$(CONFIG_WIN32) += fd-register.o
+stub-obj-y += fd-register.o
stub-obj-y += qmp_memory_device.o
stub-obj-y += target-monitor-defs.o
stub-obj-y += target-get-monitor-def.o
+++ /dev/null
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/arch_init.h"
-#include "qapi/error.h"
-#include "qapi/qmp/qerror.h"
-
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
-{
- error_setg(errp, QERR_UNSUPPORTED);
- return NULL;
-}
+++ /dev/null
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/arch_init.h"
-#include "qapi/error.h"
-#include "qapi/qmp/qerror.h"
-
-CpuModelBaselineInfo *arch_query_cpu_model_baseline(CpuModelInfo *modela,
- CpuModelInfo *modelb,
- Error **errp)
-{
- error_setg(errp, QERR_UNSUPPORTED);
- return NULL;
-}
+++ /dev/null
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/arch_init.h"
-#include "qapi/error.h"
-#include "qapi/qmp/qerror.h"
-
-CpuModelCompareInfo *arch_query_cpu_model_comparison(CpuModelInfo *modela,
- CpuModelInfo *modelb,
- Error **errp)
-{
- error_setg(errp, QERR_UNSUPPORTED);
- return NULL;
-}
+++ /dev/null
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/arch_init.h"
-#include "qapi/error.h"
-#include "qapi/qmp/qerror.h"
-
-CpuModelExpansionInfo *arch_query_cpu_model_expansion(CpuModelExpansionType type,
- CpuModelInfo *mode,
- Error **errp)
-{
- error_setg(errp, QERR_UNSUPPORTED);
- return NULL;
-}
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qapi/qapi-events.h"
+#include "qapi/qapi-emit-events.h"
#include "qemu-common.h"
#include "monitor/monitor.h"
+++ /dev/null
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/host-utils.h"
-#include "slirp/libslirp.h"
-
-void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout)
-{
-}
-
-void slirp_pollfds_poll(GArray *pollfds, int select_error)
-{
-}
-
obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
obj-y += translate.o op_helper.o helper.o cpu.o
-obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o
+obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o vfp_helper.o
obj-y += gdbstub.o
obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
obj-$(TARGET_AARCH64) += pauth_helper.o
return QEMU_ARM_POWERCTL_RET_SUCCESS;
}
+static void arm_set_cpu_on_and_reset_async_work(CPUState *target_cpu_state,
+ run_on_cpu_data data)
+{
+ ARMCPU *target_cpu = ARM_CPU(target_cpu_state);
+
+ /* Initialize the cpu we are turning on */
+ cpu_reset(target_cpu_state);
+ target_cpu_state->halted = 0;
+
+ /* Finally set the power status */
+ assert(qemu_mutex_iothread_locked());
+ target_cpu->power_state = PSCI_ON;
+}
+
+int arm_set_cpu_on_and_reset(uint64_t cpuid)
+{
+ CPUState *target_cpu_state;
+ ARMCPU *target_cpu;
+
+ assert(qemu_mutex_iothread_locked());
+
+ /* Retrieve the cpu we are powering up */
+ target_cpu_state = arm_get_cpu_by_id(cpuid);
+ if (!target_cpu_state) {
+ /* The cpu was not found */
+ return QEMU_ARM_POWERCTL_INVALID_PARAM;
+ }
+
+ target_cpu = ARM_CPU(target_cpu_state);
+ if (target_cpu->power_state == PSCI_ON) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "[ARM]%s: CPU %" PRId64 " is already on\n",
+ __func__, cpuid);
+ return QEMU_ARM_POWERCTL_ALREADY_ON;
+ }
+
+ /*
+ * If another CPU has powered the target on we are in the state
+ * ON_PENDING and additional attempts to power on the CPU should
+ * fail (see 6.6 Implementation CPU_ON/CPU_OFF races in the PSCI
+ * spec)
+ */
+ if (target_cpu->power_state == PSCI_ON_PENDING) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "[ARM]%s: CPU %" PRId64 " is already powering on\n",
+ __func__, cpuid);
+ return QEMU_ARM_POWERCTL_ON_PENDING;
+ }
+
+ async_run_on_cpu(target_cpu_state, arm_set_cpu_on_and_reset_async_work,
+ RUN_ON_CPU_NULL);
+
+ /* We are good to go */
+ return QEMU_ARM_POWERCTL_RET_SUCCESS;
+}
+
static void arm_set_cpu_off_async_work(CPUState *target_cpu_state,
run_on_cpu_data data)
{
*/
int arm_reset_cpu(uint64_t cpuid);
+/*
+ * arm_set_cpu_on_and_reset:
+ * @cpuid: the id of the CPU we want to star
+ *
+ * Start the cpu designated by @cpuid and put it through its normal
+ * CPU reset process. The CPU will start in the way it is architected
+ * to start after a power-on reset.
+ *
+ * Returns: QEMU_ARM_POWERCTL_RET_SUCCESS on success.
+ * QEMU_ARM_POWERCTL_INVALID_PARAM if there is no CPU with that ID.
+ * QEMU_ARM_POWERCTL_ALREADY_ON if the CPU is already on.
+ * QEMU_ARM_POWERCTL_ON_PENDING if the CPU is already partway through
+ * powering on.
+ */
+int arm_set_cpu_on_and_reset(uint64_t cpuid);
+
#endif
#include "target/arm/idau.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
+#include "qapi/visitor.h"
#include "cpu.h"
#include "internals.h"
#include "qemu-common.h"
env->vfp.zcr_el[1] = cpu->sve_max_vq - 1;
env->vfp.zcr_el[2] = env->vfp.zcr_el[1];
env->vfp.zcr_el[3] = env->vfp.zcr_el[1];
+ /*
+ * Enable TBI0 and TBI1. While the real kernel only enables TBI0,
+ * turning on both here will produce smaller code and otherwise
+ * make no difference to the user-level emulation.
+ */
+ env->cp15.tcr_el[1].raw_tcr = (3ULL << 37);
#else
/* Reset into the highest available EL */
if (arm_feature(env, ARM_FEATURE_EL3)) {
pmsav7_dregion,
qdev_prop_uint32, uint32_t);
-/* M profile: initial value of the Secure VTOR */
-static Property arm_cpu_initsvtor_property =
- DEFINE_PROP_UINT32("init-svtor", ARMCPU, init_svtor, 0);
+static void arm_get_init_svtor(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+
+ visit_type_uint32(v, name, &cpu->init_svtor, errp);
+}
+
+static void arm_set_init_svtor(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+
+ visit_type_uint32(v, name, &cpu->init_svtor, errp);
+}
void arm_cpu_post_init(Object *obj)
{
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_STRONG,
&error_abort);
- qdev_property_add_static(DEVICE(obj), &arm_cpu_initsvtor_property,
- &error_abort);
+ /*
+ * M profile: initial value of the Secure VTOR. We can't just use
+ * a simple DEFINE_PROP_UINT32 for this because we want to permit
+ * the property to be set after realize.
+ */
+ object_property_add(obj, "init-svtor", "uint32",
+ arm_get_init_svtor, arm_set_init_svtor,
+ NULL, NULL, &error_abort);
}
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
}
if (arm_feature(env, ARM_FEATURE_VFP4)) {
set_feature(env, ARM_FEATURE_VFP3);
- set_feature(env, ARM_FEATURE_VFP_FP16);
}
if (arm_feature(env, ARM_FEATURE_VFP3)) {
set_feature(env, ARM_FEATURE_VFP);
cpu->dtb_compatible = "arm,cortex-a9";
set_feature(&cpu->env, ARM_FEATURE_V7);
set_feature(&cpu->env, ARM_FEATURE_VFP3);
- set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
set_feature(&cpu->env, ARM_FEATURE_NEON);
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
set_feature(&cpu->env, ARM_FEATURE_EL3);
cpu->isar.id_isar5 = t;
t = cpu->isar.id_isar6;
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
t = FIELD_DP32(t, ID_ISAR6, DP, 1);
+ t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
cpu->isar.id_isar6 = t;
t = cpu->id_mmfr4;
* semantics as for AArch32, as described in the comments on each field)
* nRW (also known as M[4]) is kept, inverted, in env->aarch64
* DAIF (exception masks) are kept in env->daif
+ * BTYPE is kept in env->btype
* all other bits are stored in their correct places in env->pstate
*/
uint32_t pstate;
uint32_t GE; /* cpsr[19:16] */
uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */
uint32_t condexec_bits; /* IT bits. cpsr[15:10,26:25]. */
+ uint32_t btype; /* BTI branch type. spsr[11:10]. */
uint64_t daif; /* exception masks, in the bits they are in PSTATE */
uint64_t elr_el[4]; /* AArch64 exception link regs */
ARMPredicateReg preg_tmp;
#endif
- uint32_t xregs[16];
/* We store these fpcsr fields separately for convenience. */
+ uint32_t qc[4] QEMU_ALIGNED(16);
int vec_len;
int vec_stride;
+ uint32_t xregs[16];
+
/* Scratch space for aa32 neon expansion. */
uint32_t scratch[8];
#define PSTATE_I (1U << 7)
#define PSTATE_A (1U << 8)
#define PSTATE_D (1U << 9)
+#define PSTATE_BTYPE (3U << 10)
#define PSTATE_IL (1U << 20)
#define PSTATE_SS (1U << 21)
#define PSTATE_V (1U << 28)
#define PSTATE_N (1U << 31)
#define PSTATE_NZCV (PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V)
#define PSTATE_DAIF (PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F)
-#define CACHED_PSTATE_BITS (PSTATE_NZCV | PSTATE_DAIF)
+#define CACHED_PSTATE_BITS (PSTATE_NZCV | PSTATE_DAIF | PSTATE_BTYPE)
/* Mode values for AArch64 */
#define PSTATE_MODE_EL3h 13
#define PSTATE_MODE_EL3t 12
ZF = (env->ZF == 0);
return (env->NF & 0x80000000) | (ZF << 30)
| (env->CF << 29) | ((env->VF & 0x80000000) >> 3)
- | env->pstate | env->daif;
+ | env->pstate | env->daif | (env->btype << 10);
}
static inline void pstate_write(CPUARMState *env, uint32_t val)
env->CF = (val >> 29) & 1;
env->VF = (val << 3) & 0x80000000;
env->daif = val & PSTATE_DAIF;
+ env->btype = (val >> 10) & 3;
env->pstate = val & ~CACHED_PSTATE_BITS;
}
#define FPSR_MASK 0xf800009f
#define FPCR_MASK 0x07ff9f00
+#define FPCR_IOE (1 << 8) /* Invalid Operation exception trap enable */
+#define FPCR_DZE (1 << 9) /* Divide by Zero exception trap enable */
+#define FPCR_OFE (1 << 10) /* Overflow exception trap enable */
+#define FPCR_UFE (1 << 11) /* Underflow exception trap enable */
+#define FPCR_IXE (1 << 12) /* Inexact exception trap enable */
+#define FPCR_IDE (1 << 15) /* Input Denormal exception trap enable */
#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
+#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
static inline uint32_t vfp_get_fpsr(CPUARMState *env)
{
FIELD(ID_AA64PFR0, RAS, 28, 4)
FIELD(ID_AA64PFR0, SVE, 32, 4)
+FIELD(ID_AA64PFR1, BT, 0, 4)
+FIELD(ID_AA64PFR1, SBSS, 4, 4)
+FIELD(ID_AA64PFR1, MTE, 8, 4)
+FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
+
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
FIELD(ID_AA64MMFR0, BIGEND, 8, 4)
FIELD(ID_DFR0, PERFMON, 24, 4)
FIELD(ID_DFR0, TRACEFILT, 28, 4)
+FIELD(MVFR0, SIMDREG, 0, 4)
+FIELD(MVFR0, FPSP, 4, 4)
+FIELD(MVFR0, FPDP, 8, 4)
+FIELD(MVFR0, FPTRAP, 12, 4)
+FIELD(MVFR0, FPDIVIDE, 16, 4)
+FIELD(MVFR0, FPSQRT, 20, 4)
+FIELD(MVFR0, FPSHVEC, 24, 4)
+FIELD(MVFR0, FPROUND, 28, 4)
+
+FIELD(MVFR1, FPFTZ, 0, 4)
+FIELD(MVFR1, FPDNAN, 4, 4)
+FIELD(MVFR1, SIMDLS, 8, 4)
+FIELD(MVFR1, SIMDINT, 12, 4)
+FIELD(MVFR1, SIMDSP, 16, 4)
+FIELD(MVFR1, SIMDHP, 20, 4)
+FIELD(MVFR1, FPHP, 24, 4)
+FIELD(MVFR1, SIMDFMAC, 28, 4)
+
+FIELD(MVFR2, SIMDMISC, 0, 4)
+FIELD(MVFR2, FPMISC, 4, 4)
+
QEMU_BUILD_BUG_ON(ARRAY_SIZE(((ARMCPU *)0)->ccsidr) <= R_V7M_CSSELR_INDEX_MASK);
/* If adding a feature bit which corresponds to a Linux ELF
ARM_FEATURE_THUMB2,
ARM_FEATURE_PMSA, /* no MMU; may have Memory Protection Unit */
ARM_FEATURE_VFP3,
- ARM_FEATURE_VFP_FP16,
ARM_FEATURE_NEON,
ARM_FEATURE_M, /* Microcontroller profile. */
ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. */
#define PL0_R (0x02 | PL1_R)
#define PL0_W (0x01 | PL1_W)
+/*
+ * For user-mode some registers are accessible to EL0 via a kernel
+ * trap-and-emulate ABI. In this case we define the read permissions
+ * as actually being PL0_R. However some bits of any given register
+ * may still be masked.
+ */
+#ifdef CONFIG_USER_ONLY
+#define PL0U_R PL0_R
+#else
+#define PL0U_R PL1_R
+#endif
+
#define PL3_RW (PL3_R | PL3_W)
#define PL2_RW (PL2_R | PL2_W)
#define PL1_RW (PL1_R | PL1_W)
}
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
+/*
+ * Definition of an ARM co-processor register as viewed from
+ * userspace. This is used for presenting sanitised versions of
+ * registers to userspace when emulating the Linux AArch64 CPU
+ * ID/feature ABI (advertised as HWCAP_CPUID).
+ */
+typedef struct ARMCPRegUserSpaceInfo {
+ /* Name of register */
+ const char *name;
+
+ /* Is the name actually a glob pattern */
+ bool is_glob;
+
+ /* Only some bits are exported to user space */
+ uint64_t exported_bits;
+
+ /* Fixed bits are applied after the mask */
+ uint64_t fixed_bits;
+} ARMCPRegUserSpaceInfo;
+
+#define REGUSERINFO_SENTINEL { .name = NULL }
+
+void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
+
/* CPWriteFn that can be used to implement writes-ignored behaviour */
void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value);
FIELD(TBFLAG_A64, SVEEXC_EL, 2, 2)
FIELD(TBFLAG_A64, ZCR_LEN, 4, 4)
FIELD(TBFLAG_A64, PAUTH_ACTIVE, 8, 1)
+FIELD(TBFLAG_A64, BT, 9, 1)
+FIELD(TBFLAG_A64, BTYPE, 10, 2)
+FIELD(TBFLAG_A64, TBID, 12, 2)
static inline bool bswap_code(bool sctlr_b)
{
return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0;
}
+static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id)
+{
+ return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0;
+}
+
static inline bool isar_feature_aa32_dp(const ARMISARegisters *id)
{
return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0;
}
+static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id)
+{
+ return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0;
+}
+
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
{
/*
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
}
+/*
+ * We always set the FP and SIMD FP16 fields to indicate identical
+ * levels of support (assuming SIMD is implemented at all), so
+ * we only need one set of accessors.
+ */
+static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 0;
+}
+
+static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 1;
+}
+
+static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 1;
+}
+
+static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 2;
+}
+
+static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 3;
+}
+
+static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 4;
+}
+
/*
* 64-bit feature tests via id registers.
*/
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0;
}
+static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0;
+}
+
+static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;
+}
+
static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0;
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;
}
+static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
+}
+
/*
* Forward to the above feature tests given an ARMCPU pointer.
*/
t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 1);
t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 1);
t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1);
+ t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1);
cpu->isar.id_aa64isar0 = t;
t = cpu->isar.id_aa64isar1;
+ t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1);
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1);
t = FIELD_DP64(t, ID_AA64ISAR1, APA, 1); /* PAuth, architected only */
t = FIELD_DP64(t, ID_AA64ISAR1, API, 0);
t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1);
cpu->isar.id_aa64pfr0 = t;
+ t = cpu->isar.id_aa64pfr1;
+ t = FIELD_DP64(t, ID_AA64PFR1, BT, 1);
+ cpu->isar.id_aa64pfr1 = t;
+
t = cpu->isar.id_aa64mmfr1;
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1);
cpu->isar.id_isar5 = u;
u = cpu->isar.id_isar6;
+ u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1);
u = FIELD_DP32(u, ID_ISAR6, DP, 1);
+ u = FIELD_DP32(u, ID_ISAR6, FHM, 1);
cpu->isar.id_isar6 = u;
/*
* High and low need to be switched here because this is not actually a
* 128bit store but two doublewords stored consecutively
*/
- Int128 cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
- Int128 newv = int128_make128(new_lo, new_hi);
+ Int128 cmpv = int128_make128(env->exclusive_high, env->exclusive_val);
+ Int128 newv = int128_make128(new_hi, new_lo);
Int128 oldv;
uintptr_t ra = GETPC();
uint64_t o0, o1;
#include "sysemu/kvm.h"
#include "fpu/softfloat.h"
#include "qemu/range.h"
+#include "qapi/qapi-commands-target.h"
#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
}
switch (reg - nregs) {
case 0: stl_p(buf, env->vfp.xregs[ARM_VFP_FPSID]); return 4;
- case 1: stl_p(buf, env->vfp.xregs[ARM_VFP_FPSCR]); return 4;
+ case 1: stl_p(buf, vfp_get_fpscr(env)); return 4;
case 2: stl_p(buf, env->vfp.xregs[ARM_VFP_FPEXC]); return 4;
}
return 0;
}
switch (reg - nregs) {
case 0: env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); return 4;
- case 1: env->vfp.xregs[ARM_VFP_FPSCR] = ldl_p(buf); return 4;
+ case 1: vfp_set_fpscr(env, ldl_p(buf)); return 4;
case 2: env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); return 4;
}
return 0;
if (cnt->supported(&cpu->env)) {
supported_event_map[cnt->number] = i;
- uint64_t event_mask = 1 << (cnt->number & 0x1f);
+ uint64_t event_mask = 1ULL << (cnt->number & 0x1f);
if (cnt->number & 0x20) {
cpu->pmceid1 |= event_mask;
} else {
return mpidr_read_val(env);
}
-static const ARMCPRegInfo mpidr_cp_reginfo[] = {
- { .name = "MPIDR", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
- .access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
- REGINFO_SENTINEL
-};
-
static const ARMCPRegInfo lpae_cp_reginfo[] = {
/* NOP AMAIR0/1 */
{ .name = "AMAIR0", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
.access = PL2_RW,
.type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "HACR_EL2", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 7,
+ .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "ESR_EL2", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0,
.access = PL2_RW,
.cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
.writefn = hcr_writelow },
+ { .name = "HACR_EL2", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 7,
+ .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "ELR_EL2", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_ALIAS,
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
char *pmevtyper_name = g_strdup_printf("PMEVTYPER%d", i);
char *pmevtyper_el0_name = g_strdup_printf("PMEVTYPER%d_EL0", i);
ARMCPRegInfo pmev_regs[] = {
- { .name = pmevcntr_name, .cp = 15, .crn = 15,
+ { .name = pmevcntr_name, .cp = 15, .crn = 14,
.crm = 8 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
.access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
.readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
.accessfn = pmreg_access },
{ .name = pmevcntr_el0_name, .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 3, .crn = 15, .crm = 8 | (3 & (i >> 3)),
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 8 | (3 & (i >> 3)),
.opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
.type = ARM_CP_IO,
.readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
.raw_readfn = pmevcntr_rawread,
.raw_writefn = pmevcntr_rawwrite },
- { .name = pmevtyper_name, .cp = 15, .crn = 15,
+ { .name = pmevtyper_name, .cp = 15, .crn = 14,
.crm = 12 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
.access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
.readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
.accessfn = pmreg_access },
{ .name = pmevtyper_el0_name, .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 3, .crn = 15, .crm = 12 | (3 & (i >> 3)),
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 12 | (3 & (i >> 3)),
.opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
.type = ARM_CP_IO,
.readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
.resetvalue = cpu->pmceid1 },
REGINFO_SENTINEL
};
+#ifdef CONFIG_USER_ONLY
+ ARMCPRegUserSpaceInfo v8_user_idregs[] = {
+ { .name = "ID_AA64PFR0_EL1",
+ .exported_bits = 0x000f000f00ff0000,
+ .fixed_bits = 0x0000000000000011 },
+ { .name = "ID_AA64PFR1_EL1",
+ .exported_bits = 0x00000000000000f0 },
+ { .name = "ID_AA64PFR*_EL1_RESERVED",
+ .is_glob = true },
+ { .name = "ID_AA64ZFR0_EL1" },
+ { .name = "ID_AA64MMFR0_EL1",
+ .fixed_bits = 0x00000000ff000000 },
+ { .name = "ID_AA64MMFR1_EL1" },
+ { .name = "ID_AA64MMFR*_EL1_RESERVED",
+ .is_glob = true },
+ { .name = "ID_AA64DFR0_EL1",
+ .fixed_bits = 0x0000000000000006 },
+ { .name = "ID_AA64DFR1_EL1" },
+ { .name = "ID_AA64DFR*_EL1_RESERVED",
+ .is_glob = true },
+ { .name = "ID_AA64AFR*",
+ .is_glob = true },
+ { .name = "ID_AA64ISAR0_EL1",
+ .exported_bits = 0x00fffffff0fffff0 },
+ { .name = "ID_AA64ISAR1_EL1",
+ .exported_bits = 0x000000f0ffffffff },
+ { .name = "ID_AA64ISAR*_EL1_RESERVED",
+ .is_glob = true },
+ REGUSERINFO_SENTINEL
+ };
+ modify_arm_cp_regs(v8_idregs, v8_user_idregs);
+#endif
/* RVBAR_EL1 is only implemented if EL1 is the highest EL */
if (!arm_feature(env, ARM_FEATURE_EL3) &&
!arm_feature(env, ARM_FEATURE_EL2)) {
.opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
.type = ARM_CP_NOP | ARM_CP_OVERRIDE
};
+#ifdef CONFIG_USER_ONLY
+ ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
+ { .name = "MIDR_EL1",
+ .exported_bits = 0x00000000ffffffff },
+ { .name = "REVIDR_EL1" },
+ REGUSERINFO_SENTINEL
+ };
+ modify_arm_cp_regs(id_v8_midr_cp_reginfo, id_v8_user_midr_cp_reginfo);
+#endif
if (arm_feature(env, ARM_FEATURE_OMAPCP) ||
arm_feature(env, ARM_FEATURE_STRONGARM)) {
ARMCPRegInfo *r;
}
if (arm_feature(env, ARM_FEATURE_MPIDR)) {
+ ARMCPRegInfo mpidr_cp_reginfo[] = {
+ { .name = "MPIDR_EL1", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
+ .access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
+ REGINFO_SENTINEL
+ };
+#ifdef CONFIG_USER_ONLY
+ ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
+ { .name = "MPIDR_EL1",
+ .fixed_bits = 0x0000000080000000 },
+ REGUSERINFO_SENTINEL
+ };
+ modify_arm_cp_regs(mpidr_cp_reginfo, mpidr_user_cp_reginfo);
+#endif
define_arm_cp_regs(cpu, mpidr_cp_reginfo);
}
*cpu_list = entry;
}
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
{
CpuDefinitionInfoList *cpu_list = NULL;
GSList *list;
if (r->state != ARM_CP_STATE_AA32) {
int mask = 0;
switch (r->opc1) {
- case 0: case 1: case 2:
+ case 0:
+ /* min_EL EL1, but some accessible to EL0 via kernel ABI */
+ mask = PL0U_R | PL1_RW;
+ break;
+ case 1: case 2:
/* min_EL EL1 */
mask = PL1_RW;
break;
}
}
+/*
+ * Modify ARMCPRegInfo for access from userspace.
+ *
+ * This is a data driven modification directed by
+ * ARMCPRegUserSpaceInfo. All registers become ARM_CP_CONST as
+ * user-space cannot alter any values and dynamic values pertaining to
+ * execution state are hidden from user space view anyway.
+ */
+void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods)
+{
+ const ARMCPRegUserSpaceInfo *m;
+ ARMCPRegInfo *r;
+
+ for (m = mods; m->name; m++) {
+ GPatternSpec *pat = NULL;
+ if (m->is_glob) {
+ pat = g_pattern_spec_new(m->name);
+ }
+ for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
+ if (pat && g_pattern_match_string(pat, r->name)) {
+ r->type = ARM_CP_CONST;
+ r->access = PL0U_R;
+ r->resetvalue = 0;
+ /* continue */
+ } else if (strcmp(r->name, m->name) == 0) {
+ r->type = ARM_CP_CONST;
+ r->access = PL0U_R;
+ r->resetvalue &= m->exported_bits;
+ r->resetvalue |= m->fixed_bits;
+ break;
+ }
+ }
+ if (pat) {
+ g_pattern_spec_free(pat);
+ }
+ }
+}
+
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp)
{
return g_hash_table_lookup(cpregs, &encoded_cp);
return revbit32(x);
}
-#if defined(CONFIG_USER_ONLY)
+#ifdef CONFIG_USER_ONLY
/* These should probably raise undefined insn exceptions. */
void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
}
}
+#endif /* !CONFIG_USER_ONLY */
/* Return the exception level which controls this address translation regime */
static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
}
}
+#ifndef CONFIG_USER_ONLY
+
/* Return the SCTLR value which controls this address translation regime */
static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
{
return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
}
+/* Return the TTBR associated with this translation regime */
+static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
+ int ttbrn)
+{
+ if (mmu_idx == ARMMMUIdx_S2NS) {
+ return env->cp15.vttbr_el2;
+ }
+ if (ttbrn == 0) {
+ return env->cp15.ttbr0_el[regime_el(env, mmu_idx)];
+ } else {
+ return env->cp15.ttbr1_el[regime_el(env, mmu_idx)];
+ }
+}
+
+#endif /* !CONFIG_USER_ONLY */
+
/* Return the TCR controlling this translation regime */
static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
{
return mmu_idx;
}
-/* Return the TTBR associated with this translation regime */
-static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
- int ttbrn)
-{
- if (mmu_idx == ARMMMUIdx_S2NS) {
- return env->cp15.vttbr_el2;
- }
- if (ttbrn == 0) {
- return env->cp15.ttbr0_el[regime_el(env, mmu_idx)];
- } else {
- return env->cp15.ttbr1_el[regime_el(env, mmu_idx)];
- }
-}
-
/* Return true if the translation regime is using LPAE format page tables */
static inline bool regime_using_lpae_format(CPUARMState *env,
ARMMMUIdx mmu_idx)
return regime_using_lpae_format(env, mmu_idx);
}
+#ifndef CONFIG_USER_ONLY
static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
return (hiattr << 6) | (hihint << 4) | (loattr << 2) | lohint;
}
+#endif /* !CONFIG_USER_ONLY */
ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
ARMMMUIdx mmu_idx)
return ret;
}
+#ifndef CONFIG_USER_ONLY
static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
ARMMMUIdx mmu_idx)
{
bool ttbr1_valid;
uint64_t descaddrmask;
bool aarch64 = arm_el_is_aa64(env, el);
+ bool guarded = false;
/* TODO:
* This code does not handle the different format TCR for VTCR_EL2.
}
/* Merge in attributes from table descriptors */
attrs |= nstable << 3; /* NS */
+ guarded = extract64(descriptor, 50, 1); /* GP */
if (param.hpd) {
/* HPD disables all the table attributes except NSTable. */
break;
*/
txattrs->secure = false;
}
+ /* When in aarch64 mode, and BTI is enabled, remember GP in the IOTLB. */
+ if (aarch64 && guarded && cpu_isar_feature(aa64_bti, cpu)) {
+ txattrs->target_tlb_bit0 = true;
+ }
if (cacheattrs != NULL) {
if (mmu_idx == ARMMMUIdx_S2NS) {
hit = true;
} else if (m_is_ppb_region(env, address)) {
hit = true;
- } else if (pmsav7_use_background_region(cpu, mmu_idx, is_user)) {
- hit = true;
} else {
+ if (pmsav7_use_background_region(cpu, mmu_idx, is_user)) {
+ hit = true;
+ }
+
for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
/* region search */
/* Note that the base address is bits [31:5] from the register
*is_subpage = true;
}
- if (hit) {
+ if (matchregion != -1) {
/* Multiple regions match -- always a failure (unlike
* PMSAv7 where highest-numbered-region wins)
*/
return (a & mask) | (b & ~mask);
}
-/* VFP support. We follow the convention used for VFP instructions:
- Single precision routines have a "s" suffix, double precision a
- "d" suffix. */
-
-/* Convert host exception flags to vfp form. */
-static inline int vfp_exceptbits_from_host(int host_bits)
-{
- int target_bits = 0;
-
- if (host_bits & float_flag_invalid)
- target_bits |= 1;
- if (host_bits & float_flag_divbyzero)
- target_bits |= 2;
- if (host_bits & float_flag_overflow)
- target_bits |= 4;
- if (host_bits & (float_flag_underflow | float_flag_output_denormal))
- target_bits |= 8;
- if (host_bits & float_flag_inexact)
- target_bits |= 0x10;
- if (host_bits & float_flag_input_denormal)
- target_bits |= 0x80;
- return target_bits;
-}
-
-uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
-{
- int i;
- uint32_t fpscr;
-
- fpscr = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff)
- | (env->vfp.vec_len << 16)
- | (env->vfp.vec_stride << 20);
-
- i = get_float_exception_flags(&env->vfp.fp_status);
- i |= get_float_exception_flags(&env->vfp.standard_fp_status);
- /* FZ16 does not generate an input denormal exception. */
- i |= (get_float_exception_flags(&env->vfp.fp_status_f16)
- & ~float_flag_input_denormal);
-
- fpscr |= vfp_exceptbits_from_host(i);
- return fpscr;
-}
-
-uint32_t vfp_get_fpscr(CPUARMState *env)
-{
- return HELPER(vfp_get_fpscr)(env);
-}
-
-/* Convert vfp exception flags to target form. */
-static inline int vfp_exceptbits_to_host(int target_bits)
-{
- int host_bits = 0;
-
- if (target_bits & 1)
- host_bits |= float_flag_invalid;
- if (target_bits & 2)
- host_bits |= float_flag_divbyzero;
- if (target_bits & 4)
- host_bits |= float_flag_overflow;
- if (target_bits & 8)
- host_bits |= float_flag_underflow;
- if (target_bits & 0x10)
- host_bits |= float_flag_inexact;
- if (target_bits & 0x80)
- host_bits |= float_flag_input_denormal;
- return host_bits;
-}
-
-void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
-{
- int i;
- uint32_t changed;
-
- /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
- if (!cpu_isar_feature(aa64_fp16, arm_env_get_cpu(env))) {
- val &= ~FPCR_FZ16;
- }
-
- changed = env->vfp.xregs[ARM_VFP_FPSCR];
- env->vfp.xregs[ARM_VFP_FPSCR] = (val & 0xffc8ffff);
- env->vfp.vec_len = (val >> 16) & 7;
- env->vfp.vec_stride = (val >> 20) & 3;
-
- changed ^= val;
- if (changed & (3 << 22)) {
- i = (val >> 22) & 3;
- switch (i) {
- case FPROUNDING_TIEEVEN:
- i = float_round_nearest_even;
- break;
- case FPROUNDING_POSINF:
- i = float_round_up;
- break;
- case FPROUNDING_NEGINF:
- i = float_round_down;
- break;
- case FPROUNDING_ZERO:
- i = float_round_to_zero;
- break;
- }
- set_float_rounding_mode(i, &env->vfp.fp_status);
- set_float_rounding_mode(i, &env->vfp.fp_status_f16);
- }
- if (changed & FPCR_FZ16) {
- bool ftz_enabled = val & FPCR_FZ16;
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
- }
- if (changed & FPCR_FZ) {
- bool ftz_enabled = val & FPCR_FZ;
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status);
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status);
- }
- if (changed & FPCR_DN) {
- bool dnan_enabled = val & FPCR_DN;
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status);
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16);
- }
-
- /* The exception flags are ORed together when we read fpscr so we
- * only need to preserve the current state in one of our
- * float_status values.
- */
- i = vfp_exceptbits_to_host(val);
- set_float_exception_flags(i, &env->vfp.fp_status);
- set_float_exception_flags(0, &env->vfp.fp_status_f16);
- set_float_exception_flags(0, &env->vfp.standard_fp_status);
-}
-
-void vfp_set_fpscr(CPUARMState *env, uint32_t val)
-{
- HELPER(vfp_set_fpscr)(env, val);
-}
-
-#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
-
-#define VFP_BINOP(name) \
-float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
-{ \
- float_status *fpst = fpstp; \
- return float32_ ## name(a, b, fpst); \
-} \
-float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
-{ \
- float_status *fpst = fpstp; \
- return float64_ ## name(a, b, fpst); \
-}
-VFP_BINOP(add)
-VFP_BINOP(sub)
-VFP_BINOP(mul)
-VFP_BINOP(div)
-VFP_BINOP(min)
-VFP_BINOP(max)
-VFP_BINOP(minnum)
-VFP_BINOP(maxnum)
-#undef VFP_BINOP
-
-float32 VFP_HELPER(neg, s)(float32 a)
-{
- return float32_chs(a);
-}
-
-float64 VFP_HELPER(neg, d)(float64 a)
-{
- return float64_chs(a);
-}
-
-float32 VFP_HELPER(abs, s)(float32 a)
-{
- return float32_abs(a);
-}
-
-float64 VFP_HELPER(abs, d)(float64 a)
-{
- return float64_abs(a);
-}
-
-float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
-{
- return float32_sqrt(a, &env->vfp.fp_status);
-}
-
-float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env)
-{
- return float64_sqrt(a, &env->vfp.fp_status);
-}
-
-/* XXX: check quiet/signaling case */
-#define DO_VFP_cmp(p, type) \
-void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \
-{ \
- uint32_t flags; \
- switch(type ## _compare_quiet(a, b, &env->vfp.fp_status)) { \
- case 0: flags = 0x6; break; \
- case -1: flags = 0x8; break; \
- case 1: flags = 0x2; break; \
- default: case 2: flags = 0x3; break; \
- } \
- env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
- | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
-} \
-void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
-{ \
- uint32_t flags; \
- switch(type ## _compare(a, b, &env->vfp.fp_status)) { \
- case 0: flags = 0x6; break; \
- case -1: flags = 0x8; break; \
- case 1: flags = 0x2; break; \
- default: case 2: flags = 0x3; break; \
- } \
- env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
- | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
-}
-DO_VFP_cmp(s, float32)
-DO_VFP_cmp(d, float64)
-#undef DO_VFP_cmp
-
-/* Integer to float and float to integer conversions */
-
-#define CONV_ITOF(name, ftype, fsz, sign) \
-ftype HELPER(name)(uint32_t x, void *fpstp) \
-{ \
- float_status *fpst = fpstp; \
- return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
-}
-
-#define CONV_FTOI(name, ftype, fsz, sign, round) \
-sign##int32_t HELPER(name)(ftype x, void *fpstp) \
-{ \
- float_status *fpst = fpstp; \
- if (float##fsz##_is_any_nan(x)) { \
- float_raise(float_flag_invalid, fpst); \
- return 0; \
- } \
- return float##fsz##_to_##sign##int32##round(x, fpst); \
-}
-
-#define FLOAT_CONVS(name, p, ftype, fsz, sign) \
- CONV_ITOF(vfp_##name##to##p, ftype, fsz, sign) \
- CONV_FTOI(vfp_to##name##p, ftype, fsz, sign, ) \
- CONV_FTOI(vfp_to##name##z##p, ftype, fsz, sign, _round_to_zero)
-
-FLOAT_CONVS(si, h, uint32_t, 16, )
-FLOAT_CONVS(si, s, float32, 32, )
-FLOAT_CONVS(si, d, float64, 64, )
-FLOAT_CONVS(ui, h, uint32_t, 16, u)
-FLOAT_CONVS(ui, s, float32, 32, u)
-FLOAT_CONVS(ui, d, float64, 64, u)
-
-#undef CONV_ITOF
-#undef CONV_FTOI
-#undef FLOAT_CONVS
-
-/* floating point conversion */
-float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
-{
- return float32_to_float64(x, &env->vfp.fp_status);
-}
-
-float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
-{
- return float64_to_float32(x, &env->vfp.fp_status);
-}
-
-/* VFP3 fixed point conversion. */
-#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
-float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
- void *fpstp) \
-{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
-
-#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
-uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
- void *fpst) \
-{ \
- if (unlikely(float##fsz##_is_any_nan(x))) { \
- float_raise(float_flag_invalid, fpst); \
- return 0; \
- } \
- return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
-}
-
-#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
- float_round_to_zero, _round_to_zero) \
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
- get_float_rounding_mode(fpst), )
-
-#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
- get_float_rounding_mode(fpst), )
-
-VFP_CONV_FIX(sh, d, 64, 64, int16)
-VFP_CONV_FIX(sl, d, 64, 64, int32)
-VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
-VFP_CONV_FIX(uh, d, 64, 64, uint16)
-VFP_CONV_FIX(ul, d, 64, 64, uint32)
-VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
-VFP_CONV_FIX(sh, s, 32, 32, int16)
-VFP_CONV_FIX(sl, s, 32, 32, int32)
-VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
-VFP_CONV_FIX(uh, s, 32, 32, uint16)
-VFP_CONV_FIX(ul, s, 32, 32, uint32)
-VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
-
-#undef VFP_CONV_FIX
-#undef VFP_CONV_FIX_FLOAT
-#undef VFP_CONV_FLOAT_FIX_ROUND
-#undef VFP_CONV_FIX_A64
-
-uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
-{
- return int32_to_float16_scalbn(x, -shift, fpst);
-}
-
-uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
-{
- return uint32_to_float16_scalbn(x, -shift, fpst);
-}
-
-uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
-{
- return int64_to_float16_scalbn(x, -shift, fpst);
-}
-
-uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
-{
- return uint64_to_float16_scalbn(x, -shift, fpst);
-}
-
-uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
-{
- if (unlikely(float16_is_any_nan(x))) {
- float_raise(float_flag_invalid, fpst);
- return 0;
- }
- return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
- shift, fpst);
-}
-
-uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
-{
- if (unlikely(float16_is_any_nan(x))) {
- float_raise(float_flag_invalid, fpst);
- return 0;
- }
- return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
- shift, fpst);
-}
-
-uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
-{
- if (unlikely(float16_is_any_nan(x))) {
- float_raise(float_flag_invalid, fpst);
- return 0;
- }
- return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
- shift, fpst);
-}
-
-uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
-{
- if (unlikely(float16_is_any_nan(x))) {
- float_raise(float_flag_invalid, fpst);
- return 0;
- }
- return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
- shift, fpst);
-}
-
-uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
-{
- if (unlikely(float16_is_any_nan(x))) {
- float_raise(float_flag_invalid, fpst);
- return 0;
- }
- return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
- shift, fpst);
-}
-
-uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
-{
- if (unlikely(float16_is_any_nan(x))) {
- float_raise(float_flag_invalid, fpst);
- return 0;
- }
- return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
- shift, fpst);
-}
-
-/* Set the current fp rounding mode and return the old one.
- * The argument is a softfloat float_round_ value.
- */
-uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp)
-{
- float_status *fp_status = fpstp;
-
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
- set_float_rounding_mode(rmode, fp_status);
-
- return prev_rmode;
-}
-
-/* Set the current fp rounding mode in the standard fp status and return
- * the old one. This is for NEON instructions that need to change the
- * rounding mode but wish to use the standard FPSCR values for everything
- * else. Always set the rounding mode back to the correct value after
- * modifying it.
- * The argument is a softfloat float_round_ value.
- */
-uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
-{
- float_status *fp_status = &env->vfp.standard_fp_status;
-
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
- set_float_rounding_mode(rmode, fp_status);
-
- return prev_rmode;
-}
-
-/* Half precision conversions. */
-float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode)
-{
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
- * it would affect flushing input denormals.
- */
- float_status *fpst = fpstp;
- flag save = get_flush_inputs_to_zero(fpst);
- set_flush_inputs_to_zero(false, fpst);
- float32 r = float16_to_float32(a, !ahp_mode, fpst);
- set_flush_inputs_to_zero(save, fpst);
- return r;
-}
-
-uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, void *fpstp, uint32_t ahp_mode)
-{
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
- * it would affect flushing output denormals.
- */
- float_status *fpst = fpstp;
- flag save = get_flush_to_zero(fpst);
- set_flush_to_zero(false, fpst);
- float16 r = float32_to_float16(a, !ahp_mode, fpst);
- set_flush_to_zero(save, fpst);
- return r;
-}
-
-float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, void *fpstp, uint32_t ahp_mode)
-{
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
- * it would affect flushing input denormals.
- */
- float_status *fpst = fpstp;
- flag save = get_flush_inputs_to_zero(fpst);
- set_flush_inputs_to_zero(false, fpst);
- float64 r = float16_to_float64(a, !ahp_mode, fpst);
- set_flush_inputs_to_zero(save, fpst);
- return r;
-}
-
-uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
-{
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
- * it would affect flushing output denormals.
- */
- float_status *fpst = fpstp;
- flag save = get_flush_to_zero(fpst);
- set_flush_to_zero(false, fpst);
- float16 r = float64_to_float16(a, !ahp_mode, fpst);
- set_flush_to_zero(save, fpst);
- return r;
-}
-
-#define float32_two make_float32(0x40000000)
-#define float32_three make_float32(0x40400000)
-#define float32_one_point_five make_float32(0x3fc00000)
-
-float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
-{
- float_status *s = &env->vfp.standard_fp_status;
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
- float_raise(float_flag_input_denormal, s);
- }
- return float32_two;
- }
- return float32_sub(float32_two, float32_mul(a, b, s), s);
-}
-
-float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
-{
- float_status *s = &env->vfp.standard_fp_status;
- float32 product;
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
- float_raise(float_flag_input_denormal, s);
- }
- return float32_one_point_five;
- }
- product = float32_mul(a, b, s);
- return float32_div(float32_sub(float32_three, product, s), float32_two, s);
-}
-
-/* NEON helpers. */
-
-/* Constants 256 and 512 are used in some helpers; we avoid relying on
- * int->float conversions at run-time. */
-#define float64_256 make_float64(0x4070000000000000LL)
-#define float64_512 make_float64(0x4080000000000000LL)
-#define float16_maxnorm make_float16(0x7bff)
-#define float32_maxnorm make_float32(0x7f7fffff)
-#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
-
-/* Reciprocal functions
- *
- * The algorithm that must be used to calculate the estimate
- * is specified by the ARM ARM, see FPRecipEstimate()/RecipEstimate
- */
-
-/* See RecipEstimate()
- *
- * input is a 9 bit fixed point number
- * input range 256 .. 511 for a number from 0.5 <= x < 1.0.
- * result range 256 .. 511 for a number from 1.0 to 511/256.
- */
-
-static int recip_estimate(int input)
-{
- int a, b, r;
- assert(256 <= input && input < 512);
- a = (input * 2) + 1;
- b = (1 << 19) / a;
- r = (b + 1) >> 1;
- assert(256 <= r && r < 512);
- return r;
-}
-
-/*
- * Common wrapper to call recip_estimate
- *
- * The parameters are exponent and 64 bit fraction (without implicit
- * bit) where the binary point is nominally at bit 52. Returns a
- * float64 which can then be rounded to the appropriate size by the
- * callee.
- */
-
-static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac)
-{
- uint32_t scaled, estimate;
- uint64_t result_frac;
- int result_exp;
-
- /* Handle sub-normals */
- if (*exp == 0) {
- if (extract64(frac, 51, 1) == 0) {
- *exp = -1;
- frac <<= 2;
- } else {
- frac <<= 1;
- }
- }
-
- /* scaled = UInt('1':fraction<51:44>) */
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
- estimate = recip_estimate(scaled);
-
- result_exp = exp_off - *exp;
- result_frac = deposit64(0, 44, 8, estimate);
- if (result_exp == 0) {
- result_frac = deposit64(result_frac >> 1, 51, 1, 1);
- } else if (result_exp == -1) {
- result_frac = deposit64(result_frac >> 2, 50, 2, 1);
- result_exp = 0;
- }
-
- *exp = result_exp;
-
- return result_frac;
-}
-
-static bool round_to_inf(float_status *fpst, bool sign_bit)
-{
- switch (fpst->float_rounding_mode) {
- case float_round_nearest_even: /* Round to Nearest */
- return true;
- case float_round_up: /* Round to +Inf */
- return !sign_bit;
- case float_round_down: /* Round to -Inf */
- return sign_bit;
- case float_round_to_zero: /* Round to Zero */
- return false;
- }
-
- g_assert_not_reached();
-}
-
-uint32_t HELPER(recpe_f16)(uint32_t input, void *fpstp)
-{
- float_status *fpst = fpstp;
- float16 f16 = float16_squash_input_denormal(input, fpst);
- uint32_t f16_val = float16_val(f16);
- uint32_t f16_sign = float16_is_neg(f16);
- int f16_exp = extract32(f16_val, 10, 5);
- uint32_t f16_frac = extract32(f16_val, 0, 10);
- uint64_t f64_frac;
-
- if (float16_is_any_nan(f16)) {
- float16 nan = f16;
- if (float16_is_signaling_nan(f16, fpst)) {
- float_raise(float_flag_invalid, fpst);
- nan = float16_silence_nan(f16, fpst);
- }
- if (fpst->default_nan_mode) {
- nan = float16_default_nan(fpst);
- }
- return nan;
- } else if (float16_is_infinity(f16)) {
- return float16_set_sign(float16_zero, float16_is_neg(f16));
- } else if (float16_is_zero(f16)) {
- float_raise(float_flag_divbyzero, fpst);
- return float16_set_sign(float16_infinity, float16_is_neg(f16));
- } else if (float16_abs(f16) < (1 << 8)) {
- /* Abs(value) < 2.0^-16 */
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
- if (round_to_inf(fpst, f16_sign)) {
- return float16_set_sign(float16_infinity, f16_sign);
- } else {
- return float16_set_sign(float16_maxnorm, f16_sign);
- }
- } else if (f16_exp >= 29 && fpst->flush_to_zero) {
- float_raise(float_flag_underflow, fpst);
- return float16_set_sign(float16_zero, float16_is_neg(f16));
- }
-
- f64_frac = call_recip_estimate(&f16_exp, 29,
- ((uint64_t) f16_frac) << (52 - 10));
-
- /* result = sign : result_exp<4:0> : fraction<51:42> */
- f16_val = deposit32(0, 15, 1, f16_sign);
- f16_val = deposit32(f16_val, 10, 5, f16_exp);
- f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
- return make_float16(f16_val);
-}
-
-float32 HELPER(recpe_f32)(float32 input, void *fpstp)
-{
- float_status *fpst = fpstp;
- float32 f32 = float32_squash_input_denormal(input, fpst);
- uint32_t f32_val = float32_val(f32);
- bool f32_sign = float32_is_neg(f32);
- int f32_exp = extract32(f32_val, 23, 8);
- uint32_t f32_frac = extract32(f32_val, 0, 23);
- uint64_t f64_frac;
-
- if (float32_is_any_nan(f32)) {
- float32 nan = f32;
- if (float32_is_signaling_nan(f32, fpst)) {
- float_raise(float_flag_invalid, fpst);
- nan = float32_silence_nan(f32, fpst);
- }
- if (fpst->default_nan_mode) {
- nan = float32_default_nan(fpst);
- }
- return nan;
- } else if (float32_is_infinity(f32)) {
- return float32_set_sign(float32_zero, float32_is_neg(f32));
- } else if (float32_is_zero(f32)) {
- float_raise(float_flag_divbyzero, fpst);
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
- } else if (float32_abs(f32) < (1ULL << 21)) {
- /* Abs(value) < 2.0^-128 */
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
- if (round_to_inf(fpst, f32_sign)) {
- return float32_set_sign(float32_infinity, f32_sign);
- } else {
- return float32_set_sign(float32_maxnorm, f32_sign);
- }
- } else if (f32_exp >= 253 && fpst->flush_to_zero) {
- float_raise(float_flag_underflow, fpst);
- return float32_set_sign(float32_zero, float32_is_neg(f32));
- }
-
- f64_frac = call_recip_estimate(&f32_exp, 253,
- ((uint64_t) f32_frac) << (52 - 23));
-
- /* result = sign : result_exp<7:0> : fraction<51:29> */
- f32_val = deposit32(0, 31, 1, f32_sign);
- f32_val = deposit32(f32_val, 23, 8, f32_exp);
- f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
- return make_float32(f32_val);
-}
-
-float64 HELPER(recpe_f64)(float64 input, void *fpstp)
-{
- float_status *fpst = fpstp;
- float64 f64 = float64_squash_input_denormal(input, fpst);
- uint64_t f64_val = float64_val(f64);
- bool f64_sign = float64_is_neg(f64);
- int f64_exp = extract64(f64_val, 52, 11);
- uint64_t f64_frac = extract64(f64_val, 0, 52);
-
- /* Deal with any special cases */
- if (float64_is_any_nan(f64)) {
- float64 nan = f64;
- if (float64_is_signaling_nan(f64, fpst)) {
- float_raise(float_flag_invalid, fpst);
- nan = float64_silence_nan(f64, fpst);
- }
- if (fpst->default_nan_mode) {
- nan = float64_default_nan(fpst);
- }
- return nan;
- } else if (float64_is_infinity(f64)) {
- return float64_set_sign(float64_zero, float64_is_neg(f64));
- } else if (float64_is_zero(f64)) {
- float_raise(float_flag_divbyzero, fpst);
- return float64_set_sign(float64_infinity, float64_is_neg(f64));
- } else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
- /* Abs(value) < 2.0^-1024 */
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
- if (round_to_inf(fpst, f64_sign)) {
- return float64_set_sign(float64_infinity, f64_sign);
- } else {
- return float64_set_sign(float64_maxnorm, f64_sign);
- }
- } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
- float_raise(float_flag_underflow, fpst);
- return float64_set_sign(float64_zero, float64_is_neg(f64));
- }
-
- f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac);
-
- /* result = sign : result_exp<10:0> : fraction<51:0>; */
- f64_val = deposit64(0, 63, 1, f64_sign);
- f64_val = deposit64(f64_val, 52, 11, f64_exp);
- f64_val = deposit64(f64_val, 0, 52, f64_frac);
- return make_float64(f64_val);
-}
-
-/* The algorithm that must be used to calculate the estimate
- * is specified by the ARM ARM.
- */
-
-static int do_recip_sqrt_estimate(int a)
-{
- int b, estimate;
-
- assert(128 <= a && a < 512);
- if (a < 256) {
- a = a * 2 + 1;
- } else {
- a = (a >> 1) << 1;
- a = (a + 1) * 2;
- }
- b = 512;
- while (a * (b + 1) * (b + 1) < (1 << 28)) {
- b += 1;
- }
- estimate = (b + 1) / 2;
- assert(256 <= estimate && estimate < 512);
-
- return estimate;
-}
-
-
-static uint64_t recip_sqrt_estimate(int *exp , int exp_off, uint64_t frac)
-{
- int estimate;
- uint32_t scaled;
-
- if (*exp == 0) {
- while (extract64(frac, 51, 1) == 0) {
- frac = frac << 1;
- *exp -= 1;
- }
- frac = extract64(frac, 0, 51) << 1;
- }
-
- if (*exp & 1) {
- /* scaled = UInt('01':fraction<51:45>) */
- scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
- } else {
- /* scaled = UInt('1':fraction<51:44>) */
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
- }
- estimate = do_recip_sqrt_estimate(scaled);
-
- *exp = (exp_off - *exp) / 2;
- return extract64(estimate, 0, 8) << 44;
-}
-
-uint32_t HELPER(rsqrte_f16)(uint32_t input, void *fpstp)
-{
- float_status *s = fpstp;
- float16 f16 = float16_squash_input_denormal(input, s);
- uint16_t val = float16_val(f16);
- bool f16_sign = float16_is_neg(f16);
- int f16_exp = extract32(val, 10, 5);
- uint16_t f16_frac = extract32(val, 0, 10);
- uint64_t f64_frac;
-
- if (float16_is_any_nan(f16)) {
- float16 nan = f16;
- if (float16_is_signaling_nan(f16, s)) {
- float_raise(float_flag_invalid, s);
- nan = float16_silence_nan(f16, s);
- }
- if (s->default_nan_mode) {
- nan = float16_default_nan(s);
- }
- return nan;
- } else if (float16_is_zero(f16)) {
- float_raise(float_flag_divbyzero, s);
- return float16_set_sign(float16_infinity, f16_sign);
- } else if (f16_sign) {
- float_raise(float_flag_invalid, s);
- return float16_default_nan(s);
- } else if (float16_is_infinity(f16)) {
- return float16_zero;
- }
-
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
- * preserving the parity of the exponent. */
-
- f64_frac = ((uint64_t) f16_frac) << (52 - 10);
-
- f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac);
-
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
- val = deposit32(0, 15, 1, f16_sign);
- val = deposit32(val, 10, 5, f16_exp);
- val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
- return make_float16(val);
-}
-
-float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
-{
- float_status *s = fpstp;
- float32 f32 = float32_squash_input_denormal(input, s);
- uint32_t val = float32_val(f32);
- uint32_t f32_sign = float32_is_neg(f32);
- int f32_exp = extract32(val, 23, 8);
- uint32_t f32_frac = extract32(val, 0, 23);
- uint64_t f64_frac;
-
- if (float32_is_any_nan(f32)) {
- float32 nan = f32;
- if (float32_is_signaling_nan(f32, s)) {
- float_raise(float_flag_invalid, s);
- nan = float32_silence_nan(f32, s);
- }
- if (s->default_nan_mode) {
- nan = float32_default_nan(s);
- }
- return nan;
- } else if (float32_is_zero(f32)) {
- float_raise(float_flag_divbyzero, s);
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
- } else if (float32_is_neg(f32)) {
- float_raise(float_flag_invalid, s);
- return float32_default_nan(s);
- } else if (float32_is_infinity(f32)) {
- return float32_zero;
- }
-
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
- * preserving the parity of the exponent. */
-
- f64_frac = ((uint64_t) f32_frac) << 29;
-
- f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac);
-
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(15) */
- val = deposit32(0, 31, 1, f32_sign);
- val = deposit32(val, 23, 8, f32_exp);
- val = deposit32(val, 15, 8, extract64(f64_frac, 52 - 8, 8));
- return make_float32(val);
-}
-
-float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
-{
- float_status *s = fpstp;
- float64 f64 = float64_squash_input_denormal(input, s);
- uint64_t val = float64_val(f64);
- bool f64_sign = float64_is_neg(f64);
- int f64_exp = extract64(val, 52, 11);
- uint64_t f64_frac = extract64(val, 0, 52);
-
- if (float64_is_any_nan(f64)) {
- float64 nan = f64;
- if (float64_is_signaling_nan(f64, s)) {
- float_raise(float_flag_invalid, s);
- nan = float64_silence_nan(f64, s);
- }
- if (s->default_nan_mode) {
- nan = float64_default_nan(s);
- }
- return nan;
- } else if (float64_is_zero(f64)) {
- float_raise(float_flag_divbyzero, s);
- return float64_set_sign(float64_infinity, float64_is_neg(f64));
- } else if (float64_is_neg(f64)) {
- float_raise(float_flag_invalid, s);
- return float64_default_nan(s);
- } else if (float64_is_infinity(f64)) {
- return float64_zero;
- }
-
- f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac);
-
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
- val = deposit64(0, 61, 1, f64_sign);
- val = deposit64(val, 52, 11, f64_exp);
- val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
- return make_float64(val);
-}
-
-uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
-{
- /* float_status *s = fpstp; */
- int input, estimate;
-
- if ((a & 0x80000000) == 0) {
- return 0xffffffff;
- }
-
- input = extract32(a, 23, 9);
- estimate = recip_estimate(input);
-
- return deposit32(0, (32 - 9), 9, estimate);
-}
-
-uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
-{
- int estimate;
-
- if ((a & 0xc0000000) == 0) {
- return 0xffffffff;
- }
-
- estimate = do_recip_sqrt_estimate(extract32(a, 23, 9));
-
- return deposit32(0, 23, 9, estimate);
-}
-
-/* VFPv4 fused multiply-accumulate */
-float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
-{
- float_status *fpst = fpstp;
- return float32_muladd(a, b, c, 0, fpst);
-}
-
-float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
-{
- float_status *fpst = fpstp;
- return float64_muladd(a, b, c, 0, fpst);
-}
-
-/* ARMv8 round to integral */
-float32 HELPER(rints_exact)(float32 x, void *fp_status)
-{
- return float32_round_to_int(x, fp_status);
-}
-
-float64 HELPER(rintd_exact)(float64 x, void *fp_status)
-{
- return float64_round_to_int(x, fp_status);
-}
-
-float32 HELPER(rints)(float32 x, void *fp_status)
-{
- int old_flags = get_float_exception_flags(fp_status), new_flags;
- float32 ret;
-
- ret = float32_round_to_int(x, fp_status);
-
- /* Suppress any inexact exceptions the conversion produced */
- if (!(old_flags & float_flag_inexact)) {
- new_flags = get_float_exception_flags(fp_status);
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
- }
-
- return ret;
-}
-
-float64 HELPER(rintd)(float64 x, void *fp_status)
-{
- int old_flags = get_float_exception_flags(fp_status), new_flags;
- float64 ret;
-
- ret = float64_round_to_int(x, fp_status);
-
- new_flags = get_float_exception_flags(fp_status);
-
- /* Suppress any inexact exceptions the conversion produced */
- if (!(old_flags & float_flag_inexact)) {
- new_flags = get_float_exception_flags(fp_status);
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
- }
-
- return ret;
-}
-
-/* Convert ARM rounding mode to softfloat */
-int arm_rmode_to_sf(int rmode)
-{
- switch (rmode) {
- case FPROUNDING_TIEAWAY:
- rmode = float_round_ties_away;
- break;
- case FPROUNDING_ODD:
- /* FIXME: add support for TIEAWAY and ODD */
- qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
- rmode);
- /* fall through for now */
- case FPROUNDING_TIEEVEN:
- default:
- rmode = float_round_nearest_even;
- break;
- case FPROUNDING_POSINF:
- rmode = float_round_up;
- break;
- case FPROUNDING_NEGINF:
- rmode = float_round_down;
- break;
- case FPROUNDING_ZERO:
- rmode = float_round_to_zero;
- break;
- }
- return rmode;
-}
-
/* CRC helpers.
* The upper bytes of val (above the number specified by 'bytes') must have
* been zeroed out by the caller.
if (is_a64(env)) {
ARMCPU *cpu = arm_env_get_cpu(env);
+ uint64_t sctlr;
*pc = env->pc;
flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
-#ifndef CONFIG_USER_ONLY
- /*
- * Get control bits for tagged addresses. Note that the
- * translator only uses this for instruction addresses.
- */
+ /* Get control bits for tagged addresses. */
{
ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
}
flags = FIELD_DP32(flags, TBFLAG_A64, TBII, tbii);
+ flags = FIELD_DP32(flags, TBFLAG_A64, TBID, tbid);
}
-#endif
if (cpu_isar_feature(aa64_sve, cpu)) {
int sve_el = sve_exception_el(env, current_el);
flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len);
}
+ if (current_el == 0) {
+ /* FIXME: ARMv8.1-VHE S2 translation regime. */
+ sctlr = env->cp15.sctlr_el[1];
+ } else {
+ sctlr = env->cp15.sctlr_el[current_el];
+ }
if (cpu_isar_feature(aa64_pauth, cpu)) {
/*
* In order to save space in flags, we record only whether
* a nop, or "active" when some action must be performed.
* The decision of which action to take is left to a helper.
*/
- uint64_t sctlr;
- if (current_el == 0) {
- /* FIXME: ARMv8.1-VHE S2 translation regime. */
- sctlr = env->cp15.sctlr_el[1];
- } else {
- sctlr = env->cp15.sctlr_el[current_el];
- }
if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) {
flags = FIELD_DP32(flags, TBFLAG_A64, PAUTH_ACTIVE, 1);
}
}
+
+ if (cpu_isar_feature(aa64_bti, cpu)) {
+ /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */
+ if (sctlr & (current_el == 0 ? SCTLR_BT0 : SCTLR_BT1)) {
+ flags = FIELD_DP32(flags, TBFLAG_A64, BT, 1);
+ }
+ flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
+ }
} else {
*pc = env->regs[15];
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
DEF_HELPER_FLAGS_2(rints, TCG_CALL_NO_RWG, f32, f32, ptr)
DEF_HELPER_FLAGS_2(rintd, TCG_CALL_NO_RWG, f64, f64, ptr)
+DEF_HELPER_FLAGS_2(vjcvt, TCG_CALL_NO_RWG, i32, f64, env)
+DEF_HELPER_FLAGS_2(fjcvtzs, TCG_CALL_NO_RWG, i64, f64, ptr)
+
/* neon_helper.c */
DEF_HELPER_FLAGS_3(neon_qadd_u8, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_qadd_s8, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_2(neon_cge_u32, i32, i32, i32)
DEF_HELPER_2(neon_cge_s32, i32, i32, i32)
-DEF_HELPER_2(neon_min_u8, i32, i32, i32)
-DEF_HELPER_2(neon_min_s8, i32, i32, i32)
-DEF_HELPER_2(neon_min_u16, i32, i32, i32)
-DEF_HELPER_2(neon_min_s16, i32, i32, i32)
-DEF_HELPER_2(neon_min_u32, i32, i32, i32)
-DEF_HELPER_2(neon_min_s32, i32, i32, i32)
-DEF_HELPER_2(neon_max_u8, i32, i32, i32)
-DEF_HELPER_2(neon_max_s8, i32, i32, i32)
-DEF_HELPER_2(neon_max_u16, i32, i32, i32)
-DEF_HELPER_2(neon_max_s16, i32, i32, i32)
-DEF_HELPER_2(neon_max_u32, i32, i32, i32)
-DEF_HELPER_2(neon_max_s32, i32, i32, i32)
DEF_HELPER_2(neon_pmin_u8, i32, i32, i32)
DEF_HELPER_2(neon_pmin_s8, i32, i32, i32)
DEF_HELPER_2(neon_pmin_u16, i32, i32, i32)
DEF_HELPER_FLAGS_6(gvec_fmla_idx_d, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_uqadd_b, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_uqadd_h, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_uqadd_s, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_uqadd_d, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_sqadd_b, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_sqadd_h, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_sqadd_s, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_sqadd_d, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_uqsub_b, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_uqsub_h, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_uqsub_s, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_uqsub_d, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_sqsub_b, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_sqsub_h, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_sqsub_s, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_sqsub_d, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_5(gvec_fmlal_a32, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_fmlal_a64, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_fmlal_idx_a32, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_fmlal_idx_a64, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+
#ifdef TARGET_AARCH64
#include "helper-a64.h"
#include "helper-sve.h"
EC_FPIDTRAP = 0x08,
EC_PACTRAP = 0x09,
EC_CP14RRTTRAP = 0x0c,
+ EC_BTITRAP = 0x0d,
EC_ILLEGALSTATE = 0x0e,
EC_AA32_SVC = 0x11,
EC_AA32_HVC = 0x12,
return EC_PACTRAP << ARM_EL_EC_SHIFT;
}
+static inline uint32_t syn_btitrap(int btype)
+{
+ return (EC_BTITRAP << ARM_EL_EC_SHIFT) | btype;
+}
+
static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
{
return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
bool using64k : 1;
} ARMVAParameters;
-#ifdef CONFIG_USER_ONLY
-static inline ARMVAParameters aa64_va_parameters_both(CPUARMState *env,
- uint64_t va,
- ARMMMUIdx mmu_idx)
-{
- return (ARMVAParameters) {
- /* 48-bit address space */
- .tsz = 16,
- /* We can't handle tagged addresses properly in user-only mode */
- .tbi = false,
- };
-}
-
-static inline ARMVAParameters aa64_va_parameters(CPUARMState *env,
- uint64_t va,
- ARMMMUIdx mmu_idx, bool data)
-{
- return aa64_va_parameters_both(env, va, mmu_idx);
-}
-#else
ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
ARMMMUIdx mmu_idx);
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
ARMMMUIdx mmu_idx, bool data);
-#endif
#endif
if (extract32(id_pfr0, 12, 4) == 1) {
set_feature(&features, ARM_FEATURE_THUMB2EE);
}
- if (extract32(ahcf->isar.mvfr1, 20, 4) == 1) {
- set_feature(&features, ARM_FEATURE_VFP_FP16);
- }
if (extract32(ahcf->isar.mvfr1, 12, 4) == 1) {
set_feature(&features, ARM_FEATURE_NEON);
}
#include "qemu/osdep.h"
#include "hw/boards.h"
#include "kvm_arm.h"
-#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-commands-target.h"
static GICCapability *gic_cap_new(int version)
{
#define SIGNBIT (uint32_t)0x80000000
#define SIGNBIT64 ((uint64_t)1 << 63)
-#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
+#define SET_QC() env->vfp.qc[0] = 1
#define NEON_TYPE1(name, type) \
typedef struct \
#undef NEON_FN
#define NEON_FN(dest, src1, src2) dest = (src1 < src2) ? src1 : src2
-NEON_VOP(min_s8, neon_s8, 4)
-NEON_VOP(min_u8, neon_u8, 4)
-NEON_VOP(min_s16, neon_s16, 2)
-NEON_VOP(min_u16, neon_u16, 2)
-NEON_VOP(min_s32, neon_s32, 1)
-NEON_VOP(min_u32, neon_u32, 1)
NEON_POP(pmin_s8, neon_s8, 4)
NEON_POP(pmin_u8, neon_u8, 4)
NEON_POP(pmin_s16, neon_s16, 2)
#undef NEON_FN
#define NEON_FN(dest, src1, src2) dest = (src1 > src2) ? src1 : src2
-NEON_VOP(max_s8, neon_s8, 4)
-NEON_VOP(max_u8, neon_u8, 4)
-NEON_VOP(max_s16, neon_s16, 2)
-NEON_VOP(max_u16, neon_u16, 2)
-NEON_VOP(max_s32, neon_s32, 1)
-NEON_VOP(max_u32, neon_u32, 1)
NEON_POP(pmax_s8, neon_s8, 4)
NEON_POP(pmax_u8, neon_u8, 4)
NEON_POP(pmax_s16, neon_s16, 2)
return arm_to_core_mmu_idx(useridx);
}
+static void reset_btype(DisasContext *s)
+{
+ if (s->btype != 0) {
+ TCGv_i32 zero = tcg_const_i32(0);
+ tcg_gen_st_i32(zero, cpu_env, offsetof(CPUARMState, btype));
+ tcg_temp_free_i32(zero);
+ s->btype = 0;
+ }
+}
+
+static void set_btype(DisasContext *s, int val)
+{
+ TCGv_i32 tcg_val;
+
+ /* BTYPE is a 2-bit field, and 0 should be done with reset_btype. */
+ tcg_debug_assert(val >= 1 && val <= 3);
+
+ tcg_val = tcg_const_i32(val);
+ tcg_gen_st_i32(tcg_val, cpu_env, offsetof(CPUARMState, btype));
+ tcg_temp_free_i32(tcg_val);
+ s->btype = -1;
+}
+
void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
fprintf_function cpu_fprintf, int flags)
{
el,
psr & PSTATE_SP ? 'h' : 't');
+ if (cpu_isar_feature(aa64_bti, cpu)) {
+ cpu_fprintf(f, " BTYPE=%d", (psr & PSTATE_BTYPE) >> 10);
+ }
if (!(flags & CPU_DUMP_FPU)) {
cpu_fprintf(f, "\n");
return;
tcg_gen_movi_i64(cpu_pc, val);
}
-/* Load the PC from a generic TCG variable.
+/*
+ * Handle Top Byte Ignore (TBI) bits.
*
- * If address tagging is enabled via the TCR TBI bits, then loading
- * an address into the PC will clear out any tag in it:
+ * If address tagging is enabled via the TCR TBI bits:
* + for EL2 and EL3 there is only one TBI bit, and if it is set
* then the address is zero-extended, clearing bits [63:56]
* + for EL0 and EL1, TBI0 controls addresses with bit 55 == 0
* If the appropriate TBI bit is set for the address then
* the address is sign-extended from bit 55 into bits [63:56]
*
- * We can avoid doing this for relative-branches, because the
- * PC + offset can never overflow into the tag bits (assuming
- * that virtual addresses are less than 56 bits wide, as they
- * are currently), but we must handle it for branch-to-register.
+ * Here We have concatenated TBI{1,0} into tbi.
*/
-static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
+static void gen_top_byte_ignore(DisasContext *s, TCGv_i64 dst,
+ TCGv_i64 src, int tbi)
{
- /* Note that TBII is TBI1:TBI0. */
- int tbi = s->tbii;
-
- if (s->current_el <= 1) {
- if (tbi != 0) {
- /* Sign-extend from bit 55. */
- tcg_gen_sextract_i64(cpu_pc, src, 0, 56);
+ if (tbi == 0) {
+ /* Load unmodified address */
+ tcg_gen_mov_i64(dst, src);
+ } else if (s->current_el >= 2) {
+ /* FIXME: ARMv8.1-VHE S2 translation regime. */
+ /* Force tag byte to all zero */
+ tcg_gen_extract_i64(dst, src, 0, 56);
+ } else {
+ /* Sign-extend from bit 55. */
+ tcg_gen_sextract_i64(dst, src, 0, 56);
- if (tbi != 3) {
- TCGv_i64 tcg_zero = tcg_const_i64(0);
+ if (tbi != 3) {
+ TCGv_i64 tcg_zero = tcg_const_i64(0);
- /*
- * The two TBI bits differ.
- * If tbi0, then !tbi1: only use the extension if positive.
- * if !tbi0, then tbi1: only use the extension if negative.
- */
- tcg_gen_movcond_i64(tbi == 1 ? TCG_COND_GE : TCG_COND_LT,
- cpu_pc, cpu_pc, tcg_zero, cpu_pc, src);
- tcg_temp_free_i64(tcg_zero);
- }
- return;
- }
- } else {
- if (tbi != 0) {
- /* Force tag byte to all zero */
- tcg_gen_extract_i64(cpu_pc, src, 0, 56);
- return;
+ /*
+ * The two TBI bits differ.
+ * If tbi0, then !tbi1: only use the extension if positive.
+ * if !tbi0, then tbi1: only use the extension if negative.
+ */
+ tcg_gen_movcond_i64(tbi == 1 ? TCG_COND_GE : TCG_COND_LT,
+ dst, dst, tcg_zero, dst, src);
+ tcg_temp_free_i64(tcg_zero);
}
}
+}
- /* Load unmodified address */
- tcg_gen_mov_i64(cpu_pc, src);
+static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
+{
+ /*
+ * If address tagging is enabled for instructions via the TCR TBI bits,
+ * then loading an address into the PC will clear out any tag.
+ */
+ gen_top_byte_ignore(s, cpu_pc, src, s->tbii);
+}
+
+/*
+ * Return a "clean" address for ADDR according to TBID.
+ * This is always a fresh temporary, as we need to be able to
+ * increment this independently of a dirty write-back address.
+ */
+static TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr)
+{
+ TCGv_i64 clean = new_tmp_a64(s);
+ gen_top_byte_ignore(s, clean, addr, s->tbid);
+ return clean;
}
typedef struct DisasCompare64 {
}
/* B Branch / BL Branch with link */
+ reset_btype(s);
gen_goto_tb(s, 0, addr);
}
tcg_cmp = read_cpu_reg(s, rt, sf);
label_match = gen_new_label();
+ reset_btype(s);
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
tcg_cmp, 0, label_match);
tcg_cmp = tcg_temp_new_i64();
tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
label_match = gen_new_label();
+
+ reset_btype(s);
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
tcg_cmp, 0, label_match);
tcg_temp_free_i64(tcg_cmp);
addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
cond = extract32(insn, 0, 4);
+ reset_btype(s);
if (cond < 0x0e) {
/* genuinely conditional branches */
TCGLabel *label_match = gen_new_label();
* a self-modified code correctly and also to take
* any pending interrupts immediately.
*/
+ reset_btype(s);
gen_goto_tb(s, 0, s->pc);
return;
default:
static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
{
unsigned int opc, op2, op3, rn, op4;
+ unsigned btype_mod = 2; /* 0: BR, 1: BLR, 2: other */
TCGv_i64 dst;
TCGv_i64 modifier;
case 0: /* BR */
case 1: /* BLR */
case 2: /* RET */
+ btype_mod = opc;
switch (op3) {
case 0:
/* BR, BLR, RET */
default:
goto do_unallocated;
}
-
gen_a64_set_pc(s, dst);
/* BLR also needs to load return address */
if (opc == 1) {
if ((op3 & ~1) != 2) {
goto do_unallocated;
}
+ btype_mod = opc & 1;
if (s->pauth_active) {
dst = new_tmp_a64(s);
modifier = cpu_reg_sp(s, op4);
return;
}
+ switch (btype_mod) {
+ case 0: /* BR */
+ if (dc_isar_feature(aa64_bti, s)) {
+ /* BR to {x16,x17} or !guard -> 1, else 3. */
+ set_btype(s, rn == 16 || rn == 17 || !s->guarded_page ? 1 : 3);
+ }
+ break;
+
+ case 1: /* BLR */
+ if (dc_isar_feature(aa64_bti, s)) {
+ /* BLR sets BTYPE to 2, regardless of source guarded page. */
+ set_btype(s, 2);
+ }
+ break;
+
+ default: /* RET or none of the above. */
+ /* BTYPE will be set to 0 by normal end-of-insn processing. */
+ break;
+ }
+
s->base.is_jmp = DISAS_JUMP;
}
TCGv_i64 tcg_rs = cpu_reg(s, rs);
TCGv_i64 tcg_rt = cpu_reg(s, rt);
int memidx = get_mem_index(s);
- TCGv_i64 addr = cpu_reg_sp(s, rn);
+ TCGv_i64 clean_addr;
if (rn == 31) {
gen_check_sp_alignment(s);
}
- tcg_gen_atomic_cmpxchg_i64(tcg_rs, addr, tcg_rs, tcg_rt, memidx,
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
+ tcg_gen_atomic_cmpxchg_i64(tcg_rs, clean_addr, tcg_rs, tcg_rt, memidx,
size | MO_ALIGN | s->be_data);
}
TCGv_i64 s2 = cpu_reg(s, rs + 1);
TCGv_i64 t1 = cpu_reg(s, rt);
TCGv_i64 t2 = cpu_reg(s, rt + 1);
- TCGv_i64 addr = cpu_reg_sp(s, rn);
+ TCGv_i64 clean_addr;
int memidx = get_mem_index(s);
if (rn == 31) {
gen_check_sp_alignment(s);
}
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
if (size == 2) {
TCGv_i64 cmp = tcg_temp_new_i64();
tcg_gen_concat32_i64(cmp, s2, s1);
}
- tcg_gen_atomic_cmpxchg_i64(cmp, addr, cmp, val, memidx,
+ tcg_gen_atomic_cmpxchg_i64(cmp, clean_addr, cmp, val, memidx,
MO_64 | MO_ALIGN | s->be_data);
tcg_temp_free_i64(val);
if (HAVE_CMPXCHG128) {
TCGv_i32 tcg_rs = tcg_const_i32(rs);
if (s->be_data == MO_LE) {
- gen_helper_casp_le_parallel(cpu_env, tcg_rs, addr, t1, t2);
+ gen_helper_casp_le_parallel(cpu_env, tcg_rs,
+ clean_addr, t1, t2);
} else {
- gen_helper_casp_be_parallel(cpu_env, tcg_rs, addr, t1, t2);
+ gen_helper_casp_be_parallel(cpu_env, tcg_rs,
+ clean_addr, t1, t2);
}
tcg_temp_free_i32(tcg_rs);
} else {
TCGv_i64 zero = tcg_const_i64(0);
/* Load the two words, in memory order. */
- tcg_gen_qemu_ld_i64(d1, addr, memidx,
+ tcg_gen_qemu_ld_i64(d1, clean_addr, memidx,
MO_64 | MO_ALIGN_16 | s->be_data);
- tcg_gen_addi_i64(a2, addr, 8);
- tcg_gen_qemu_ld_i64(d2, addr, memidx, MO_64 | s->be_data);
+ tcg_gen_addi_i64(a2, clean_addr, 8);
+ tcg_gen_qemu_ld_i64(d2, clean_addr, memidx, MO_64 | s->be_data);
/* Compare the two words, also in memory order. */
tcg_gen_setcond_i64(TCG_COND_EQ, c1, d1, s1);
/* If compare equal, write back new data, else write back old data. */
tcg_gen_movcond_i64(TCG_COND_NE, c1, c2, zero, t1, d1);
tcg_gen_movcond_i64(TCG_COND_NE, c2, c2, zero, t2, d2);
- tcg_gen_qemu_st_i64(c1, addr, memidx, MO_64 | s->be_data);
+ tcg_gen_qemu_st_i64(c1, clean_addr, memidx, MO_64 | s->be_data);
tcg_gen_qemu_st_i64(c2, a2, memidx, MO_64 | s->be_data);
tcg_temp_free_i64(a2);
tcg_temp_free_i64(c1);
int is_lasr = extract32(insn, 15, 1);
int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
int size = extract32(insn, 30, 2);
- TCGv_i64 tcg_addr;
+ TCGv_i64 clean_addr;
switch (o2_L_o1_o0) {
case 0x0: /* STXR */
if (is_lasr) {
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
}
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
- gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, false);
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
+ gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, false);
return;
case 0x4: /* LDXR */
if (rn == 31) {
gen_check_sp_alignment(s);
}
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
s->is_ldex = true;
- gen_load_exclusive(s, rt, rt2, tcg_addr, size, false);
+ gen_load_exclusive(s, rt, rt2, clean_addr, size, false);
if (is_lasr) {
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
}
gen_check_sp_alignment(s);
}
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
- do_gpr_st(s, cpu_reg(s, rt), tcg_addr, size, true, rt,
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
+ do_gpr_st(s, cpu_reg(s, rt), clean_addr, size, true, rt,
disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
return;
if (rn == 31) {
gen_check_sp_alignment(s);
}
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
- do_gpr_ld(s, cpu_reg(s, rt), tcg_addr, size, false, false, true, rt,
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
+ do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, false, false, true, rt,
disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
return;
if (is_lasr) {
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
}
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
- gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, true);
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
+ gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, true);
return;
}
if (rt2 == 31
if (rn == 31) {
gen_check_sp_alignment(s);
}
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
s->is_ldex = true;
- gen_load_exclusive(s, rt, rt2, tcg_addr, size, true);
+ gen_load_exclusive(s, rt, rt2, clean_addr, size, true);
if (is_lasr) {
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
}
int opc = extract32(insn, 30, 2);
bool is_signed = false;
int size = 2;
- TCGv_i64 tcg_rt, tcg_addr;
+ TCGv_i64 tcg_rt, clean_addr;
if (is_vector) {
if (opc == 3) {
tcg_rt = cpu_reg(s, rt);
- tcg_addr = tcg_const_i64((s->pc - 4) + imm);
+ clean_addr = tcg_const_i64((s->pc - 4) + imm);
if (is_vector) {
- do_fp_ld(s, rt, tcg_addr, size);
+ do_fp_ld(s, rt, clean_addr, size);
} else {
/* Only unsigned 32bit loads target 32bit registers. */
bool iss_sf = opc != 0;
- do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false,
+ do_gpr_ld(s, tcg_rt, clean_addr, size, is_signed, false,
true, rt, iss_sf, false);
}
- tcg_temp_free_i64(tcg_addr);
+ tcg_temp_free_i64(clean_addr);
}
/*
bool postindex = false;
bool wback = false;
- TCGv_i64 tcg_addr; /* calculated address */
+ TCGv_i64 clean_addr, dirty_addr;
+
int size;
if (opc == 3) {
gen_check_sp_alignment(s);
}
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
-
+ dirty_addr = read_cpu_reg_sp(s, rn, 1);
if (!postindex) {
- tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
}
+ clean_addr = clean_data_tbi(s, dirty_addr);
if (is_vector) {
if (is_load) {
- do_fp_ld(s, rt, tcg_addr, size);
+ do_fp_ld(s, rt, clean_addr, size);
} else {
- do_fp_st(s, rt, tcg_addr, size);
+ do_fp_st(s, rt, clean_addr, size);
}
- tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
+ tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
if (is_load) {
- do_fp_ld(s, rt2, tcg_addr, size);
+ do_fp_ld(s, rt2, clean_addr, size);
} else {
- do_fp_st(s, rt2, tcg_addr, size);
+ do_fp_st(s, rt2, clean_addr, size);
}
} else {
TCGv_i64 tcg_rt = cpu_reg(s, rt);
/* Do not modify tcg_rt before recognizing any exception
* from the second load.
*/
- do_gpr_ld(s, tmp, tcg_addr, size, is_signed, false,
+ do_gpr_ld(s, tmp, clean_addr, size, is_signed, false,
false, 0, false, false);
- tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
- do_gpr_ld(s, tcg_rt2, tcg_addr, size, is_signed, false,
+ tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
+ do_gpr_ld(s, tcg_rt2, clean_addr, size, is_signed, false,
false, 0, false, false);
tcg_gen_mov_i64(tcg_rt, tmp);
tcg_temp_free_i64(tmp);
} else {
- do_gpr_st(s, tcg_rt, tcg_addr, size,
+ do_gpr_st(s, tcg_rt, clean_addr, size,
false, 0, false, false);
- tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
- do_gpr_st(s, tcg_rt2, tcg_addr, size,
+ tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
+ do_gpr_st(s, tcg_rt2, clean_addr, size,
false, 0, false, false);
}
}
if (wback) {
if (postindex) {
- tcg_gen_addi_i64(tcg_addr, tcg_addr, offset - (1 << size));
- } else {
- tcg_gen_subi_i64(tcg_addr, tcg_addr, 1 << size);
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
}
- tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr);
+ tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
}
}
bool post_index;
bool writeback;
- TCGv_i64 tcg_addr;
+ TCGv_i64 clean_addr, dirty_addr;
if (is_vector) {
size |= (opc & 2) << 1;
if (rn == 31) {
gen_check_sp_alignment(s);
}
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
+ dirty_addr = read_cpu_reg_sp(s, rn, 1);
if (!post_index) {
- tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
}
+ clean_addr = clean_data_tbi(s, dirty_addr);
if (is_vector) {
if (is_store) {
- do_fp_st(s, rt, tcg_addr, size);
+ do_fp_st(s, rt, clean_addr, size);
} else {
- do_fp_ld(s, rt, tcg_addr, size);
+ do_fp_ld(s, rt, clean_addr, size);
}
} else {
TCGv_i64 tcg_rt = cpu_reg(s, rt);
bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
if (is_store) {
- do_gpr_st_memidx(s, tcg_rt, tcg_addr, size, memidx,
+ do_gpr_st_memidx(s, tcg_rt, clean_addr, size, memidx,
iss_valid, rt, iss_sf, false);
} else {
- do_gpr_ld_memidx(s, tcg_rt, tcg_addr, size,
+ do_gpr_ld_memidx(s, tcg_rt, clean_addr, size,
is_signed, is_extended, memidx,
iss_valid, rt, iss_sf, false);
}
if (writeback) {
TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
if (post_index) {
- tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
}
- tcg_gen_mov_i64(tcg_rn, tcg_addr);
+ tcg_gen_mov_i64(tcg_rn, dirty_addr);
}
}
bool is_store = false;
bool is_extended = false;
- TCGv_i64 tcg_rm;
- TCGv_i64 tcg_addr;
+ TCGv_i64 tcg_rm, clean_addr, dirty_addr;
if (extract32(opt, 1, 1) == 0) {
unallocated_encoding(s);
if (rn == 31) {
gen_check_sp_alignment(s);
}
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
+ dirty_addr = read_cpu_reg_sp(s, rn, 1);
tcg_rm = read_cpu_reg(s, rm, 1);
ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
- tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_rm);
+ tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm);
+ clean_addr = clean_data_tbi(s, dirty_addr);
if (is_vector) {
if (is_store) {
- do_fp_st(s, rt, tcg_addr, size);
+ do_fp_st(s, rt, clean_addr, size);
} else {
- do_fp_ld(s, rt, tcg_addr, size);
+ do_fp_ld(s, rt, clean_addr, size);
}
} else {
TCGv_i64 tcg_rt = cpu_reg(s, rt);
bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
if (is_store) {
- do_gpr_st(s, tcg_rt, tcg_addr, size,
+ do_gpr_st(s, tcg_rt, clean_addr, size,
true, rt, iss_sf, false);
} else {
- do_gpr_ld(s, tcg_rt, tcg_addr, size,
+ do_gpr_ld(s, tcg_rt, clean_addr, size,
is_signed, is_extended,
true, rt, iss_sf, false);
}
unsigned int imm12 = extract32(insn, 10, 12);
unsigned int offset;
- TCGv_i64 tcg_addr;
+ TCGv_i64 clean_addr, dirty_addr;
bool is_store;
bool is_signed = false;
if (rn == 31) {
gen_check_sp_alignment(s);
}
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
+ dirty_addr = read_cpu_reg_sp(s, rn, 1);
offset = imm12 << size;
- tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
+ clean_addr = clean_data_tbi(s, dirty_addr);
if (is_vector) {
if (is_store) {
- do_fp_st(s, rt, tcg_addr, size);
+ do_fp_st(s, rt, clean_addr, size);
} else {
- do_fp_ld(s, rt, tcg_addr, size);
+ do_fp_ld(s, rt, clean_addr, size);
}
} else {
TCGv_i64 tcg_rt = cpu_reg(s, rt);
bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
if (is_store) {
- do_gpr_st(s, tcg_rt, tcg_addr, size,
+ do_gpr_st(s, tcg_rt, clean_addr, size,
true, rt, iss_sf, false);
} else {
- do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended,
+ do_gpr_ld(s, tcg_rt, clean_addr, size, is_signed, is_extended,
true, rt, iss_sf, false);
}
}
int rs = extract32(insn, 16, 5);
int rn = extract32(insn, 5, 5);
int o3_opc = extract32(insn, 12, 4);
- TCGv_i64 tcg_rn, tcg_rs;
+ TCGv_i64 tcg_rs, clean_addr;
AtomicThreeOpFn *fn;
if (is_vector || !dc_isar_feature(aa64_atomics, s)) {
if (rn == 31) {
gen_check_sp_alignment(s);
}
- tcg_rn = cpu_reg_sp(s, rn);
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
tcg_rs = read_cpu_reg(s, rs, true);
if (o3_opc == 1) { /* LDCLR */
/* The tcg atomic primitives are all full barriers. Therefore we
* can ignore the Acquire and Release bits of this instruction.
*/
- fn(cpu_reg(s, rt), tcg_rn, tcg_rs, get_mem_index(s),
+ fn(cpu_reg(s, rt), clean_addr, tcg_rs, get_mem_index(s),
s->be_data | size | MO_ALIGN);
}
bool is_wback = extract32(insn, 11, 1);
bool use_key_a = !extract32(insn, 23, 1);
int offset;
- TCGv_i64 tcg_addr, tcg_rt;
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt;
if (size != 3 || is_vector || !dc_isar_feature(aa64_pauth, s)) {
unallocated_encoding(s);
if (rn == 31) {
gen_check_sp_alignment(s);
}
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
+ dirty_addr = read_cpu_reg_sp(s, rn, 1);
if (s->pauth_active) {
if (use_key_a) {
- gen_helper_autda(tcg_addr, cpu_env, tcg_addr, cpu_X[31]);
+ gen_helper_autda(dirty_addr, cpu_env, dirty_addr, cpu_X[31]);
} else {
- gen_helper_autdb(tcg_addr, cpu_env, tcg_addr, cpu_X[31]);
+ gen_helper_autdb(dirty_addr, cpu_env, dirty_addr, cpu_X[31]);
}
}
/* Form the 10-bit signed, scaled offset. */
offset = (extract32(insn, 22, 1) << 9) | extract32(insn, 12, 9);
offset = sextract32(offset << size, 0, 10 + size);
- tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
- tcg_rt = cpu_reg(s, rt);
+ /* Note that "clean" and "dirty" here refer to TBI not PAC. */
+ clean_addr = clean_data_tbi(s, dirty_addr);
- do_gpr_ld(s, tcg_rt, tcg_addr, size, /* is_signed */ false,
+ tcg_rt = cpu_reg(s, rt);
+ do_gpr_ld(s, tcg_rt, clean_addr, size, /* is_signed */ false,
/* extend */ false, /* iss_valid */ !is_wback,
/* iss_srt */ rt, /* iss_sf */ true, /* iss_ar */ false);
if (is_wback) {
- tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr);
+ tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
}
}
bool is_store = !extract32(insn, 22, 1);
bool is_postidx = extract32(insn, 23, 1);
bool is_q = extract32(insn, 30, 1);
- TCGv_i64 tcg_addr, tcg_rn, tcg_ebytes;
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
TCGMemOp endian = s->be_data;
int ebytes; /* bytes per element */
elements = (is_q ? 16 : 8) / ebytes;
tcg_rn = cpu_reg_sp(s, rn);
- tcg_addr = tcg_temp_new_i64();
- tcg_gen_mov_i64(tcg_addr, tcg_rn);
+ clean_addr = clean_data_tbi(s, tcg_rn);
tcg_ebytes = tcg_const_i64(ebytes);
for (r = 0; r < rpt; r++) {
for (xs = 0; xs < selem; xs++) {
int tt = (rt + r + xs) % 32;
if (is_store) {
- do_vec_st(s, tt, e, tcg_addr, size, endian);
+ do_vec_st(s, tt, e, clean_addr, size, endian);
} else {
- do_vec_ld(s, tt, e, tcg_addr, size, endian);
+ do_vec_ld(s, tt, e, clean_addr, size, endian);
}
- tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_ebytes);
+ tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
}
}
}
+ tcg_temp_free_i64(tcg_ebytes);
if (!is_store) {
/* For non-quad operations, setting a slice of the low
if (is_postidx) {
if (rm == 31) {
- tcg_gen_mov_i64(tcg_rn, tcg_addr);
+ tcg_gen_addi_i64(tcg_rn, tcg_rn, rpt * elements * selem * ebytes);
} else {
tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
}
}
- tcg_temp_free_i64(tcg_ebytes);
- tcg_temp_free_i64(tcg_addr);
}
/* AdvSIMD load/store single structure
bool replicate = false;
int index = is_q << 3 | S << 2 | size;
int ebytes, xs;
- TCGv_i64 tcg_addr, tcg_rn, tcg_ebytes;
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
if (extract32(insn, 31, 1)) {
unallocated_encoding(s);
}
tcg_rn = cpu_reg_sp(s, rn);
- tcg_addr = tcg_temp_new_i64();
- tcg_gen_mov_i64(tcg_addr, tcg_rn);
+ clean_addr = clean_data_tbi(s, tcg_rn);
tcg_ebytes = tcg_const_i64(ebytes);
for (xs = 0; xs < selem; xs++) {
/* Load and replicate to all elements */
TCGv_i64 tcg_tmp = tcg_temp_new_i64();
- tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr,
+ tcg_gen_qemu_ld_i64(tcg_tmp, clean_addr,
get_mem_index(s), s->be_data + scale);
tcg_gen_gvec_dup_i64(scale, vec_full_reg_offset(s, rt),
(is_q + 1) * 8, vec_full_reg_size(s),
} else {
/* Load/store one element per register */
if (is_load) {
- do_vec_ld(s, rt, index, tcg_addr, scale, s->be_data);
+ do_vec_ld(s, rt, index, clean_addr, scale, s->be_data);
} else {
- do_vec_st(s, rt, index, tcg_addr, scale, s->be_data);
+ do_vec_st(s, rt, index, clean_addr, scale, s->be_data);
}
}
- tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_ebytes);
+ tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
rt = (rt + 1) % 32;
}
+ tcg_temp_free_i64(tcg_ebytes);
if (is_postidx) {
if (rm == 31) {
- tcg_gen_mov_i64(tcg_rn, tcg_addr);
+ tcg_gen_addi_i64(tcg_rn, tcg_rn, selem * ebytes);
} else {
tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
}
}
- tcg_temp_free_i64(tcg_ebytes);
- tcg_temp_free_i64(tcg_addr);
}
/* Loads and stores */
}
}
+static void handle_fjcvtzs(DisasContext *s, int rd, int rn)
+{
+ TCGv_i64 t = read_fp_dreg(s, rn);
+ TCGv_ptr fpstatus = get_fpstatus_ptr(false);
+
+ gen_helper_fjcvtzs(t, t, fpstatus);
+
+ tcg_temp_free_ptr(fpstatus);
+
+ tcg_gen_ext32u_i64(cpu_reg(s, rd), t);
+ tcg_gen_extrh_i64_i32(cpu_ZF, t);
+ tcg_gen_movi_i32(cpu_CF, 0);
+ tcg_gen_movi_i32(cpu_NF, 0);
+ tcg_gen_movi_i32(cpu_VF, 0);
+
+ tcg_temp_free_i64(t);
+}
+
/* Floating point <-> integer conversions
* 31 30 29 28 24 23 22 21 20 19 18 16 15 10 9 5 4 0
* +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
int type = extract32(insn, 22, 2);
bool sbit = extract32(insn, 29, 1);
bool sf = extract32(insn, 31, 1);
+ bool itof = false;
if (sbit) {
- unallocated_encoding(s);
- return;
+ goto do_unallocated;
}
- if (opcode > 5) {
- /* FMOV */
- bool itof = opcode & 1;
-
- if (rmode >= 2) {
- unallocated_encoding(s);
- return;
+ switch (opcode) {
+ case 2: /* SCVTF */
+ case 3: /* UCVTF */
+ itof = true;
+ /* fallthru */
+ case 4: /* FCVTAS */
+ case 5: /* FCVTAU */
+ if (rmode != 0) {
+ goto do_unallocated;
}
-
- switch (sf << 3 | type << 1 | rmode) {
- case 0x0: /* 32 bit */
- case 0xa: /* 64 bit */
- case 0xd: /* 64 bit to top half of quad */
+ /* fallthru */
+ case 0: /* FCVT[NPMZ]S */
+ case 1: /* FCVT[NPMZ]U */
+ switch (type) {
+ case 0: /* float32 */
+ case 1: /* float64 */
break;
- case 0x6: /* 16-bit float, 32-bit int */
- case 0xe: /* 16-bit float, 64-bit int */
- if (dc_isar_feature(aa64_fp16, s)) {
- break;
+ case 3: /* float16 */
+ if (!dc_isar_feature(aa64_fp16, s)) {
+ goto do_unallocated;
}
- /* fallthru */
+ break;
default:
- /* all other sf/type/rmode combinations are invalid */
- unallocated_encoding(s);
- return;
+ goto do_unallocated;
}
-
if (!fp_access_check(s)) {
return;
}
- handle_fmov(s, rd, rn, type, itof);
- } else {
- /* actual FP conversions */
- bool itof = extract32(opcode, 1, 1);
+ handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
+ break;
- if (rmode != 0 && opcode > 1) {
- unallocated_encoding(s);
- return;
- }
- switch (type) {
- case 0: /* float32 */
- case 1: /* float64 */
- break;
- case 3: /* float16 */
- if (dc_isar_feature(aa64_fp16, s)) {
- break;
+ default:
+ switch (sf << 7 | type << 5 | rmode << 3 | opcode) {
+ case 0b01100110: /* FMOV half <-> 32-bit int */
+ case 0b01100111:
+ case 0b11100110: /* FMOV half <-> 64-bit int */
+ case 0b11100111:
+ if (!dc_isar_feature(aa64_fp16, s)) {
+ goto do_unallocated;
}
/* fallthru */
+ case 0b00000110: /* FMOV 32-bit */
+ case 0b00000111:
+ case 0b10100110: /* FMOV 64-bit */
+ case 0b10100111:
+ case 0b11001110: /* FMOV top half of 128-bit */
+ case 0b11001111:
+ if (!fp_access_check(s)) {
+ return;
+ }
+ itof = opcode & 1;
+ handle_fmov(s, rd, rn, type, itof);
+ break;
+
+ case 0b00111110: /* FJCVTZS */
+ if (!dc_isar_feature(aa64_jscvt, s)) {
+ goto do_unallocated;
+ } else if (fp_access_check(s)) {
+ handle_fjcvtzs(s, rd, rn);
+ }
+ break;
+
default:
+ do_unallocated:
unallocated_encoding(s);
return;
}
-
- if (!fp_access_check(s)) {
- return;
- }
- handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
+ break;
}
}
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_andc, 0);
return;
case 2: /* ORR */
- if (rn == rm) { /* MOV */
- gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_mov, 0);
- } else {
- gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_or, 0);
- }
+ gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_or, 0);
return;
case 3: /* ORN */
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_orc, 0);
if (!fp_access_check(s)) {
return;
}
-
handle_3same_float(s, size, elements, fpopcode, rd, rn, rm);
return;
+
+ case 0x1d: /* FMLAL */
+ case 0x3d: /* FMLSL */
+ case 0x59: /* FMLAL2 */
+ case 0x79: /* FMLSL2 */
+ if (size & 1 || !dc_isar_feature(aa64_fhm, s)) {
+ unallocated_encoding(s);
+ return;
+ }
+ if (fp_access_check(s)) {
+ int is_s = extract32(insn, 23, 1);
+ int is_2 = extract32(insn, 29, 1);
+ int data = (is_2 << 1) | is_s;
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
+ vec_full_reg_offset(s, rn),
+ vec_full_reg_offset(s, rm), cpu_env,
+ is_q ? 16 : 8, vec_full_reg_size(s),
+ data, gen_helper_gvec_fmlal_a64);
+ }
+ return;
+
default:
unallocated_encoding(s);
return;
}
switch (opcode) {
+ case 0x01: /* SQADD, UQADD */
+ tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
+ offsetof(CPUARMState, vfp.qc),
+ vec_full_reg_offset(s, rn),
+ vec_full_reg_offset(s, rm),
+ is_q ? 16 : 8, vec_full_reg_size(s),
+ (u ? uqadd_op : sqadd_op) + size);
+ return;
+ case 0x05: /* SQSUB, UQSUB */
+ tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
+ offsetof(CPUARMState, vfp.qc),
+ vec_full_reg_offset(s, rn),
+ vec_full_reg_offset(s, rm),
+ is_q ? 16 : 8, vec_full_reg_size(s),
+ (u ? uqsub_op : sqsub_op) + size);
+ return;
+ case 0x0c: /* SMAX, UMAX */
+ if (u) {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_umax, size);
+ } else {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_smax, size);
+ }
+ return;
+ case 0x0d: /* SMIN, UMIN */
+ if (u) {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_umin, size);
+ } else {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_smin, size);
+ }
+ return;
case 0x10: /* ADD, SUB */
if (u) {
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size);
genfn = fns[size][u];
break;
}
- case 0x1: /* SQADD, UQADD */
- {
- static NeonGenTwoOpEnvFn * const fns[3][2] = {
- { gen_helper_neon_qadd_s8, gen_helper_neon_qadd_u8 },
- { gen_helper_neon_qadd_s16, gen_helper_neon_qadd_u16 },
- { gen_helper_neon_qadd_s32, gen_helper_neon_qadd_u32 },
- };
- genenvfn = fns[size][u];
- break;
- }
case 0x2: /* SRHADD, URHADD */
{
static NeonGenTwoOpFn * const fns[3][2] = {
genfn = fns[size][u];
break;
}
- case 0x5: /* SQSUB, UQSUB */
- {
- static NeonGenTwoOpEnvFn * const fns[3][2] = {
- { gen_helper_neon_qsub_s8, gen_helper_neon_qsub_u8 },
- { gen_helper_neon_qsub_s16, gen_helper_neon_qsub_u16 },
- { gen_helper_neon_qsub_s32, gen_helper_neon_qsub_u32 },
- };
- genenvfn = fns[size][u];
- break;
- }
case 0x8: /* SSHL, USHL */
{
static NeonGenTwoOpFn * const fns[3][2] = {
genenvfn = fns[size][u];
break;
}
- case 0xc: /* SMAX, UMAX */
- {
- static NeonGenTwoOpFn * const fns[3][2] = {
- { gen_helper_neon_max_s8, gen_helper_neon_max_u8 },
- { gen_helper_neon_max_s16, gen_helper_neon_max_u16 },
- { tcg_gen_smax_i32, tcg_gen_umax_i32 },
- };
- genfn = fns[size][u];
- break;
- }
-
- case 0xd: /* SMIN, UMIN */
- {
- static NeonGenTwoOpFn * const fns[3][2] = {
- { gen_helper_neon_min_s8, gen_helper_neon_min_u8 },
- { gen_helper_neon_min_s16, gen_helper_neon_min_u16 },
- { tcg_gen_smin_i32, tcg_gen_umin_i32 },
- };
- genfn = fns[size][u];
- break;
- }
case 0xe: /* SABD, UABD */
case 0xf: /* SABA, UABA */
{
}
is_fp = 2;
break;
+ case 0x00: /* FMLAL */
+ case 0x04: /* FMLSL */
+ case 0x18: /* FMLAL2 */
+ case 0x1c: /* FMLSL2 */
+ if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_fhm, s)) {
+ unallocated_encoding(s);
+ return;
+ }
+ size = MO_16;
+ /* is_fp, but we pass cpu_env not fp_status. */
+ break;
default:
unallocated_encoding(s);
return;
tcg_temp_free_ptr(fpst);
}
return;
+
+ case 0x00: /* FMLAL */
+ case 0x04: /* FMLSL */
+ case 0x18: /* FMLAL2 */
+ case 0x1c: /* FMLSL2 */
+ {
+ int is_s = extract32(opcode, 2, 1);
+ int is_2 = u;
+ int data = (index << 2) | (is_2 << 1) | is_s;
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
+ vec_full_reg_offset(s, rn),
+ vec_full_reg_offset(s, rm), cpu_env,
+ is_q ? 16 : 8, vec_full_reg_size(s),
+ data, gen_helper_gvec_fmlal_idx_a64);
+ }
+ return;
}
if (size == 3) {
}
}
+/**
+ * is_guarded_page:
+ * @env: The cpu environment
+ * @s: The DisasContext
+ *
+ * Return true if the page is guarded.
+ */
+static bool is_guarded_page(CPUARMState *env, DisasContext *s)
+{
+#ifdef CONFIG_USER_ONLY
+ return false; /* FIXME */
+#else
+ uint64_t addr = s->base.pc_first;
+ int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
+ unsigned int index = tlb_index(env, mmu_idx, addr);
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
+
+ /*
+ * We test this immediately after reading an insn, which means
+ * that any normal page must be in the TLB. The only exception
+ * would be for executing from flash or device memory, which
+ * does not retain the TLB entry.
+ *
+ * FIXME: Assume false for those, for now. We could use
+ * arm_cpu_get_phys_page_attrs_debug to re-read the page
+ * table entry even for that case.
+ */
+ return (tlb_hit(entry->addr_code, addr) &&
+ env->iotlb[mmu_idx][index].attrs.target_tlb_bit0);
+#endif
+}
+
+/**
+ * btype_destination_ok:
+ * @insn: The instruction at the branch destination
+ * @bt: SCTLR_ELx.BT
+ * @btype: PSTATE.BTYPE, and is non-zero
+ *
+ * On a guarded page, there are a limited number of insns
+ * that may be present at the branch target:
+ * - branch target identifiers,
+ * - paciasp, pacibsp,
+ * - BRK insn
+ * - HLT insn
+ * Anything else causes a Branch Target Exception.
+ *
+ * Return true if the branch is compatible, false to raise BTITRAP.
+ */
+static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
+{
+ if ((insn & 0xfffff01fu) == 0xd503201fu) {
+ /* HINT space */
+ switch (extract32(insn, 5, 7)) {
+ case 0b011001: /* PACIASP */
+ case 0b011011: /* PACIBSP */
+ /*
+ * If SCTLR_ELx.BT, then PACI*SP are not compatible
+ * with btype == 3. Otherwise all btype are ok.
+ */
+ return !bt || btype != 3;
+ case 0b100000: /* BTI */
+ /* Not compatible with any btype. */
+ return false;
+ case 0b100010: /* BTI c */
+ /* Not compatible with btype == 3 */
+ return btype != 3;
+ case 0b100100: /* BTI j */
+ /* Not compatible with btype == 2 */
+ return btype != 2;
+ case 0b100110: /* BTI jc */
+ /* Compatible with any btype. */
+ return true;
+ }
+ } else {
+ switch (insn & 0xffe0001fu) {
+ case 0xd4200000u: /* BRK */
+ case 0xd4400000u: /* HLT */
+ /* Give priority to the breakpoint exception. */
+ return true;
+ }
+ }
+ return false;
+}
+
/* C3.1 A64 instruction index by encoding */
static void disas_a64_insn(CPUARMState *env, DisasContext *s)
{
s->fp_access_checked = false;
+ if (dc_isar_feature(aa64_bti, s)) {
+ if (s->base.num_insns == 1) {
+ /*
+ * At the first insn of the TB, compute s->guarded_page.
+ * We delayed computing this until successfully reading
+ * the first insn of the TB, above. This (mostly) ensures
+ * that the softmmu tlb entry has been populated, and the
+ * page table GP bit is available.
+ *
+ * Note that we need to compute this even if btype == 0,
+ * because this value is used for BR instructions later
+ * where ENV is not available.
+ */
+ s->guarded_page = is_guarded_page(env, s);
+
+ /* First insn can have btype set to non-zero. */
+ tcg_debug_assert(s->btype >= 0);
+
+ /*
+ * Note that the Branch Target Exception has fairly high
+ * priority -- below debugging exceptions but above most
+ * everything else. This allows us to handle this now
+ * instead of waiting until the insn is otherwise decoded.
+ */
+ if (s->btype != 0
+ && s->guarded_page
+ && !btype_destination_ok(insn, s->bt, s->btype)) {
+ gen_exception_insn(s, 4, EXCP_UDEF, syn_btitrap(s->btype),
+ default_exception_el(s));
+ return;
+ }
+ } else {
+ /* Not the first insn: btype must be 0. */
+ tcg_debug_assert(s->btype == 0);
+ }
+ }
+
switch (extract32(insn, 25, 4)) {
case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
unallocated_encoding(s);
/* if we allocated any temporaries, free them here */
free_tmp_a64(s);
+
+ /*
+ * After execution of most insns, btype is reset to 0.
+ * Note that we set btype == -1 when the insn sets btype.
+ */
+ if (s->btype > 0 && s->base.is_jmp != DISAS_NORETURN) {
+ reset_btype(s);
+ }
}
static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
dc->tbii = FIELD_EX32(tb_flags, TBFLAG_A64, TBII);
+ dc->tbid = FIELD_EX32(tb_flags, TBFLAG_A64, TBID);
dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
#if !defined(CONFIG_USER_ONLY)
dc->user = (dc->current_el == 0);
dc->sve_excp_el = FIELD_EX32(tb_flags, TBFLAG_A64, SVEEXC_EL);
dc->sve_len = (FIELD_EX32(tb_flags, TBFLAG_A64, ZCR_LEN) + 1) * 16;
dc->pauth_active = FIELD_EX32(tb_flags, TBFLAG_A64, PAUTH_ACTIVE);
+ dc->bt = FIELD_EX32(tb_flags, TBFLAG_A64, BT);
+ dc->btype = FIELD_EX32(tb_flags, TBFLAG_A64, BTYPE);
dc->vec_len = 0;
dc->vec_stride = 0;
dc->cp_regs = arm_cpu->cp_regs;
static bool trans_ORR_zzz(DisasContext *s, arg_rrr_esz *a)
{
- if (a->rn == a->rm) { /* MOV */
- return do_mov_z(s, a->rd, a->rn);
- } else {
- return do_vector3_z(s, tcg_gen_gvec_or, 0, a->rd, a->rn, a->rm);
- }
+ return do_vector3_z(s, tcg_gen_gvec_or, 0, a->rd, a->rn, a->rm);
}
static bool trans_EOR_zzz(DisasContext *s, arg_rrr_esz *a)
FPROUNDING_NEGINF,
};
-static int disas_vfp_v8_insn(DisasContext *s, uint32_t insn)
+static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn)
{
uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
- if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
- return 1;
- }
-
if (dp) {
VFP_DREG_D(rd, insn);
VFP_DREG_N(rn, insn);
rm = VFP_SREG_M(insn);
}
- if ((insn & 0x0f800e50) == 0x0e000a00) {
+ if ((insn & 0x0f800e50) == 0x0e000a00 && dc_isar_feature(aa32_vsel, s)) {
return handle_vsel(insn, rd, rn, rm, dp);
- } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
+ } else if ((insn & 0x0fb00e10) == 0x0e800a00 &&
+ dc_isar_feature(aa32_vminmaxnm, s)) {
return handle_vminmaxnm(insn, rd, rn, rm, dp);
- } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
+ } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40 &&
+ dc_isar_feature(aa32_vrint, s)) {
/* VRINTA, VRINTN, VRINTP, VRINTM */
int rounding = fp_decode_rm[extract32(insn, 16, 2)];
return handle_vrint(insn, rd, rm, dp, rounding);
- } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
+ } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40 &&
+ dc_isar_feature(aa32_vcvt_dr, s)) {
/* VCVTA, VCVTN, VCVTP, VCVTM */
int rounding = fp_decode_rm[extract32(insn, 16, 2)];
return handle_vcvt(insn, rd, rm, dp, rounding);
}
if (extract32(insn, 28, 4) == 0xf) {
- /* Encodings with T=1 (Thumb) or unconditional (ARM):
- * only used in v8 and above.
+ /*
+ * Encodings with T=1 (Thumb) or unconditional (ARM):
+ * only used for the "miscellaneous VFP features" added in v8A
+ * and v7M (and gated on the MVFR2.FPMisc field).
*/
- return disas_vfp_v8_insn(s, insn);
+ return disas_vfp_misc_insn(s, insn);
}
dp = ((insn & 0xf00) == 0xb00);
}
} else {
/* data processing */
+ bool rd_is_dp = dp;
+ bool rm_is_dp = dp;
+ bool no_output = false;
+
/* The opcode is in bits 23, 21, 20 and 6. */
op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
- if (dp) {
- if (op == 15) {
- /* rn is opcode */
- rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
- } else {
- /* rn is register number */
- VFP_DREG_N(rn, insn);
- }
+ rn = VFP_SREG_N(insn);
- if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
- ((rn & 0x1e) == 0x6))) {
- /* Integer or single/half precision destination. */
- rd = VFP_SREG_D(insn);
- } else {
- VFP_DREG_D(rd, insn);
- }
- if (op == 15 &&
- (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
- ((rn & 0x1e) == 0x4))) {
- /* VCVT from int or half precision is always from S reg
- * regardless of dp bit. VCVT with immediate frac_bits
- * has same format as SREG_M.
+ if (op == 15) {
+ /* rn is opcode, encoded as per VFP_SREG_N. */
+ switch (rn) {
+ case 0x00: /* vmov */
+ case 0x01: /* vabs */
+ case 0x02: /* vneg */
+ case 0x03: /* vsqrt */
+ break;
+
+ case 0x04: /* vcvtb.f64.f16, vcvtb.f32.f16 */
+ case 0x05: /* vcvtt.f64.f16, vcvtt.f32.f16 */
+ /*
+ * VCVTB, VCVTT: only present with the halfprec extension
+ * UNPREDICTABLE if bit 8 is set prior to ARMv8
+ * (we choose to UNDEF)
*/
- rm = VFP_SREG_M(insn);
- } else {
- VFP_DREG_M(rm, insn);
+ if (dp) {
+ if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
+ return 1;
+ }
+ } else {
+ if (!dc_isar_feature(aa32_fp16_spconv, s)) {
+ return 1;
+ }
+ }
+ rm_is_dp = false;
+ break;
+ case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
+ case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
+ if (dp) {
+ if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
+ return 1;
+ }
+ } else {
+ if (!dc_isar_feature(aa32_fp16_spconv, s)) {
+ return 1;
+ }
+ }
+ rd_is_dp = false;
+ break;
+
+ case 0x08: case 0x0a: /* vcmp, vcmpz */
+ case 0x09: case 0x0b: /* vcmpe, vcmpez */
+ no_output = true;
+ break;
+
+ case 0x0c: /* vrintr */
+ case 0x0d: /* vrintz */
+ case 0x0e: /* vrintx */
+ break;
+
+ case 0x0f: /* vcvt double<->single */
+ rd_is_dp = !dp;
+ break;
+
+ case 0x10: /* vcvt.fxx.u32 */
+ case 0x11: /* vcvt.fxx.s32 */
+ rm_is_dp = false;
+ break;
+ case 0x18: /* vcvtr.u32.fxx */
+ case 0x19: /* vcvtz.u32.fxx */
+ case 0x1a: /* vcvtr.s32.fxx */
+ case 0x1b: /* vcvtz.s32.fxx */
+ rd_is_dp = false;
+ break;
+
+ case 0x14: /* vcvt fp <-> fixed */
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f:
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
+ return 1;
+ }
+ /* Immediate frac_bits has same format as SREG_M. */
+ rm_is_dp = false;
+ break;
+
+ case 0x13: /* vjcvt */
+ if (!dp || !dc_isar_feature(aa32_jscvt, s)) {
+ return 1;
+ }
+ rd_is_dp = false;
+ break;
+
+ default:
+ return 1;
}
+ } else if (dp) {
+ /* rn is register number */
+ VFP_DREG_N(rn, insn);
+ }
+
+ if (rd_is_dp) {
+ VFP_DREG_D(rd, insn);
+ } else {
+ rd = VFP_SREG_D(insn);
+ }
+ if (rm_is_dp) {
+ VFP_DREG_M(rm, insn);
} else {
- rn = VFP_SREG_N(insn);
- if (op == 15 && rn == 15) {
- /* Double precision destination. */
- VFP_DREG_D(rd, insn);
- } else {
- rd = VFP_SREG_D(insn);
- }
- /* NB that we implicitly rely on the encoding for the frac_bits
- * in VCVT of fixed to float being the same as that of an SREG_M
- */
rm = VFP_SREG_M(insn);
}
veclen = s->vec_len;
- if (op == 15 && rn > 3)
+ if (op == 15 && rn > 3) {
veclen = 0;
+ }
/* Shut up compiler warnings. */
delta_m = 0;
/* Load the initial operands. */
if (op == 15) {
switch (rn) {
- case 16:
- case 17:
- /* Integer source */
- gen_mov_F0_vreg(0, rm);
- break;
- case 8:
- case 9:
- /* Compare */
+ case 0x08: case 0x09: /* Compare */
gen_mov_F0_vreg(dp, rd);
gen_mov_F1_vreg(dp, rm);
break;
- case 10:
- case 11:
- /* Compare with zero */
+ case 0x0a: case 0x0b: /* Compare with zero */
gen_mov_F0_vreg(dp, rd);
gen_vfp_F1_ld0(dp);
break;
- case 20:
- case 21:
- case 22:
- case 23:
- case 28:
- case 29:
- case 30:
- case 31:
+ case 0x14: /* vcvt fp <-> fixed */
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f:
/* Source and destination the same. */
gen_mov_F0_vreg(dp, rd);
break;
- case 4:
- case 5:
- case 6:
- case 7:
- /* VCVTB, VCVTT: only present with the halfprec extension
- * UNPREDICTABLE if bit 8 is set prior to ARMv8
- * (we choose to UNDEF)
- */
- if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
- !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
- return 1;
- }
- if (!extract32(rn, 1, 1)) {
- /* Half precision source. */
- gen_mov_F0_vreg(0, rm);
- break;
- }
- /* Otherwise fall through */
default:
/* One source operand. */
- gen_mov_F0_vreg(dp, rm);
+ gen_mov_F0_vreg(rm_is_dp, rm);
break;
}
} else {
break;
}
case 15: /* single<->double conversion */
- if (dp)
+ if (dp) {
gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
- else
+ } else {
gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
+ }
break;
case 16: /* fuito */
gen_vfp_uito(dp, 0);
case 17: /* fsito */
gen_vfp_sito(dp, 0);
break;
+ case 19: /* vjcvt */
+ gen_helper_vjcvt(cpu_F0s, cpu_F0d, cpu_env);
+ break;
case 20: /* fshto */
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
- return 1;
- }
gen_vfp_shto(dp, 16 - rm, 0);
break;
case 21: /* fslto */
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
- return 1;
- }
gen_vfp_slto(dp, 32 - rm, 0);
break;
case 22: /* fuhto */
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
- return 1;
- }
gen_vfp_uhto(dp, 16 - rm, 0);
break;
case 23: /* fulto */
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
- return 1;
- }
gen_vfp_ulto(dp, 32 - rm, 0);
break;
case 24: /* ftoui */
gen_vfp_tosiz(dp, 0);
break;
case 28: /* ftosh */
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
- return 1;
- }
gen_vfp_tosh(dp, 16 - rm, 0);
break;
case 29: /* ftosl */
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
- return 1;
- }
gen_vfp_tosl(dp, 32 - rm, 0);
break;
case 30: /* ftouh */
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
- return 1;
- }
gen_vfp_touh(dp, 16 - rm, 0);
break;
case 31: /* ftoul */
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
- return 1;
- }
gen_vfp_toul(dp, 32 - rm, 0);
break;
default: /* undefined */
- return 1;
+ g_assert_not_reached();
}
break;
default: /* undefined */
return 1;
}
- /* Write back the result. */
- if (op == 15 && (rn >= 8 && rn <= 11)) {
- /* Comparison, do nothing. */
- } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
- (rn & 0x1e) == 0x6)) {
- /* VCVT double to int: always integer result.
- * VCVT double to half precision is always a single
- * precision result.
- */
- gen_mov_vreg_F0(0, rd);
- } else if (op == 15 && rn == 15) {
- /* conversion */
- gen_mov_vreg_F0(!dp, rd);
- } else {
- gen_mov_vreg_F0(dp, rd);
+ /* Write back the result, if any. */
+ if (!no_output) {
+ gen_mov_vreg_F0(rd_is_dp, rd);
}
/* break out of the loop if we have finished */
- if (veclen == 0)
+ if (veclen == 0) {
break;
+ }
if (op == 15 && delta_m == 0) {
/* single source one-many */
}
/* 32-bit pairwise ops end up the same as the elementwise versions. */
-#define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
-#define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
-#define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
-#define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
+#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
+#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
+#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
+#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
#define GEN_NEON_INTEGER_OP_ENV(name) do { \
switch ((size << 1) | u) { \
.vece = MO_64 },
};
+static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
+ TCGv_vec a, TCGv_vec b)
+{
+ TCGv_vec x = tcg_temp_new_vec_matching(t);
+ tcg_gen_add_vec(vece, x, a, b);
+ tcg_gen_usadd_vec(vece, t, a, b);
+ tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
+ tcg_gen_or_vec(vece, sat, sat, x);
+ tcg_temp_free_vec(x);
+}
+
+const GVecGen4 uqadd_op[4] = {
+ { .fniv = gen_uqadd_vec,
+ .fno = gen_helper_gvec_uqadd_b,
+ .opc = INDEX_op_usadd_vec,
+ .write_aofs = true,
+ .vece = MO_8 },
+ { .fniv = gen_uqadd_vec,
+ .fno = gen_helper_gvec_uqadd_h,
+ .opc = INDEX_op_usadd_vec,
+ .write_aofs = true,
+ .vece = MO_16 },
+ { .fniv = gen_uqadd_vec,
+ .fno = gen_helper_gvec_uqadd_s,
+ .opc = INDEX_op_usadd_vec,
+ .write_aofs = true,
+ .vece = MO_32 },
+ { .fniv = gen_uqadd_vec,
+ .fno = gen_helper_gvec_uqadd_d,
+ .opc = INDEX_op_usadd_vec,
+ .write_aofs = true,
+ .vece = MO_64 },
+};
+
+static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
+ TCGv_vec a, TCGv_vec b)
+{
+ TCGv_vec x = tcg_temp_new_vec_matching(t);
+ tcg_gen_add_vec(vece, x, a, b);
+ tcg_gen_ssadd_vec(vece, t, a, b);
+ tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
+ tcg_gen_or_vec(vece, sat, sat, x);
+ tcg_temp_free_vec(x);
+}
+
+const GVecGen4 sqadd_op[4] = {
+ { .fniv = gen_sqadd_vec,
+ .fno = gen_helper_gvec_sqadd_b,
+ .opc = INDEX_op_ssadd_vec,
+ .write_aofs = true,
+ .vece = MO_8 },
+ { .fniv = gen_sqadd_vec,
+ .fno = gen_helper_gvec_sqadd_h,
+ .opc = INDEX_op_ssadd_vec,
+ .write_aofs = true,
+ .vece = MO_16 },
+ { .fniv = gen_sqadd_vec,
+ .fno = gen_helper_gvec_sqadd_s,
+ .opc = INDEX_op_ssadd_vec,
+ .write_aofs = true,
+ .vece = MO_32 },
+ { .fniv = gen_sqadd_vec,
+ .fno = gen_helper_gvec_sqadd_d,
+ .opc = INDEX_op_ssadd_vec,
+ .write_aofs = true,
+ .vece = MO_64 },
+};
+
+static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
+ TCGv_vec a, TCGv_vec b)
+{
+ TCGv_vec x = tcg_temp_new_vec_matching(t);
+ tcg_gen_sub_vec(vece, x, a, b);
+ tcg_gen_ussub_vec(vece, t, a, b);
+ tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
+ tcg_gen_or_vec(vece, sat, sat, x);
+ tcg_temp_free_vec(x);
+}
+
+const GVecGen4 uqsub_op[4] = {
+ { .fniv = gen_uqsub_vec,
+ .fno = gen_helper_gvec_uqsub_b,
+ .opc = INDEX_op_ussub_vec,
+ .write_aofs = true,
+ .vece = MO_8 },
+ { .fniv = gen_uqsub_vec,
+ .fno = gen_helper_gvec_uqsub_h,
+ .opc = INDEX_op_ussub_vec,
+ .write_aofs = true,
+ .vece = MO_16 },
+ { .fniv = gen_uqsub_vec,
+ .fno = gen_helper_gvec_uqsub_s,
+ .opc = INDEX_op_ussub_vec,
+ .write_aofs = true,
+ .vece = MO_32 },
+ { .fniv = gen_uqsub_vec,
+ .fno = gen_helper_gvec_uqsub_d,
+ .opc = INDEX_op_ussub_vec,
+ .write_aofs = true,
+ .vece = MO_64 },
+};
+
+static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
+ TCGv_vec a, TCGv_vec b)
+{
+ TCGv_vec x = tcg_temp_new_vec_matching(t);
+ tcg_gen_sub_vec(vece, x, a, b);
+ tcg_gen_sssub_vec(vece, t, a, b);
+ tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
+ tcg_gen_or_vec(vece, sat, sat, x);
+ tcg_temp_free_vec(x);
+}
+
+const GVecGen4 sqsub_op[4] = {
+ { .fniv = gen_sqsub_vec,
+ .fno = gen_helper_gvec_sqsub_b,
+ .opc = INDEX_op_sssub_vec,
+ .write_aofs = true,
+ .vece = MO_8 },
+ { .fniv = gen_sqsub_vec,
+ .fno = gen_helper_gvec_sqsub_h,
+ .opc = INDEX_op_sssub_vec,
+ .write_aofs = true,
+ .vece = MO_16 },
+ { .fniv = gen_sqsub_vec,
+ .fno = gen_helper_gvec_sqsub_s,
+ .opc = INDEX_op_sssub_vec,
+ .write_aofs = true,
+ .vece = MO_32 },
+ { .fniv = gen_sqsub_vec,
+ .fno = gen_helper_gvec_sqsub_d,
+ .opc = INDEX_op_sssub_vec,
+ .write_aofs = true,
+ .vece = MO_64 },
+};
+
/* Translate a NEON data processing instruction. Return nonzero if the
instruction is invalid.
We process data in a mixture of 32-bit and 64-bit chunks.
tcg_gen_gvec_andc(0, rd_ofs, rn_ofs, rm_ofs,
vec_size, vec_size);
break;
- case 2:
- if (rn == rm) {
- /* VMOV */
- tcg_gen_gvec_mov(0, rd_ofs, rn_ofs, vec_size, vec_size);
- } else {
- /* VORR */
- tcg_gen_gvec_or(0, rd_ofs, rn_ofs, rm_ofs,
- vec_size, vec_size);
- }
+ case 2: /* VORR */
+ tcg_gen_gvec_or(0, rd_ofs, rn_ofs, rm_ofs,
+ vec_size, vec_size);
break;
case 3: /* VORN */
tcg_gen_gvec_orc(0, rd_ofs, rn_ofs, rm_ofs,
}
return 0;
+ case NEON_3R_VQADD:
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
+ rn_ofs, rm_ofs, vec_size, vec_size,
+ (u ? uqadd_op : sqadd_op) + size);
+ break;
+
+ case NEON_3R_VQSUB:
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
+ rn_ofs, rm_ofs, vec_size, vec_size,
+ (u ? uqsub_op : sqsub_op) + size);
+ break;
+
case NEON_3R_VMUL: /* VMUL */
if (u) {
/* Polynomial case allows only P8 and is handled below. */
tcg_gen_gvec_cmp(u ? TCG_COND_GEU : TCG_COND_GE, size,
rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
return 0;
+
+ case NEON_3R_VMAX:
+ if (u) {
+ tcg_gen_gvec_umax(size, rd_ofs, rn_ofs, rm_ofs,
+ vec_size, vec_size);
+ } else {
+ tcg_gen_gvec_smax(size, rd_ofs, rn_ofs, rm_ofs,
+ vec_size, vec_size);
+ }
+ return 0;
+ case NEON_3R_VMIN:
+ if (u) {
+ tcg_gen_gvec_umin(size, rd_ofs, rn_ofs, rm_ofs,
+ vec_size, vec_size);
+ } else {
+ tcg_gen_gvec_smin(size, rd_ofs, rn_ofs, rm_ofs,
+ vec_size, vec_size);
+ }
+ return 0;
}
if (size == 3) {
neon_load_reg64(cpu_V0, rn + pass);
neon_load_reg64(cpu_V1, rm + pass);
switch (op) {
- case NEON_3R_VQADD:
- if (u) {
- gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
- cpu_V0, cpu_V1);
- } else {
- gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
- cpu_V0, cpu_V1);
- }
- break;
- case NEON_3R_VQSUB:
- if (u) {
- gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
- cpu_V0, cpu_V1);
- } else {
- gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
- cpu_V0, cpu_V1);
- }
- break;
case NEON_3R_VSHL:
if (u) {
gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
case NEON_3R_VHADD:
GEN_NEON_INTEGER_OP(hadd);
break;
- case NEON_3R_VQADD:
- GEN_NEON_INTEGER_OP_ENV(qadd);
- break;
case NEON_3R_VRHADD:
GEN_NEON_INTEGER_OP(rhadd);
break;
case NEON_3R_VHSUB:
GEN_NEON_INTEGER_OP(hsub);
break;
- case NEON_3R_VQSUB:
- GEN_NEON_INTEGER_OP_ENV(qsub);
- break;
case NEON_3R_VSHL:
GEN_NEON_INTEGER_OP(shl);
break;
case NEON_3R_VQRSHL:
GEN_NEON_INTEGER_OP_ENV(qrshl);
break;
- case NEON_3R_VMAX:
- GEN_NEON_INTEGER_OP(max);
- break;
- case NEON_3R_VMIN:
- GEN_NEON_INTEGER_OP(min);
- break;
case NEON_3R_VABD:
GEN_NEON_INTEGER_OP(abd);
break;
TCGv_ptr fpst;
TCGv_i32 ahp;
- if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
+ if (!dc_isar_feature(aa32_fp16_spconv, s) ||
q || (rm & 1)) {
return 1;
}
{
TCGv_ptr fpst;
TCGv_i32 ahp;
- if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
+ if (!dc_isar_feature(aa32_fp16_spconv, s) ||
q || (rd & 1)) {
return 1;
}
gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
int rd, rn, rm, opr_sz;
int data = 0;
- bool q;
-
- q = extract32(insn, 6, 1);
- VFP_DREG_D(rd, insn);
- VFP_DREG_N(rn, insn);
- VFP_DREG_M(rm, insn);
- if ((rd | rn | rm) & q) {
- return 1;
- }
+ int off_rn, off_rm;
+ bool is_long = false, q = extract32(insn, 6, 1);
+ bool ptr_is_env = false;
if ((insn & 0xfe200f10) == 0xfc200800) {
/* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
return 1;
}
fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
+ } else if ((insn & 0xff300f10) == 0xfc200810) {
+ /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
+ int is_s = extract32(insn, 23, 1);
+ if (!dc_isar_feature(aa32_fhm, s)) {
+ return 1;
+ }
+ is_long = true;
+ data = is_s; /* is_2 == 0 */
+ fn_gvec_ptr = gen_helper_gvec_fmlal_a32;
+ ptr_is_env = true;
} else {
return 1;
}
+ VFP_DREG_D(rd, insn);
+ if (rd & q) {
+ return 1;
+ }
+ if (q || !is_long) {
+ VFP_DREG_N(rn, insn);
+ VFP_DREG_M(rm, insn);
+ if ((rn | rm) & q & !is_long) {
+ return 1;
+ }
+ off_rn = vfp_reg_offset(1, rn);
+ off_rm = vfp_reg_offset(1, rm);
+ } else {
+ rn = VFP_SREG_N(insn);
+ rm = VFP_SREG_M(insn);
+ off_rn = vfp_reg_offset(0, rn);
+ off_rm = vfp_reg_offset(0, rm);
+ }
+
if (s->fp_excp_el) {
gen_exception_insn(s, 4, EXCP_UDEF,
syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
opr_sz = (1 + q) * 8;
if (fn_gvec_ptr) {
- TCGv_ptr fpst = get_fpstatus_ptr(1);
- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
- vfp_reg_offset(1, rn),
- vfp_reg_offset(1, rm), fpst,
+ TCGv_ptr ptr;
+ if (ptr_is_env) {
+ ptr = cpu_env;
+ } else {
+ ptr = get_fpstatus_ptr(1);
+ }
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
opr_sz, opr_sz, data, fn_gvec_ptr);
- tcg_temp_free_ptr(fpst);
+ if (!ptr_is_env) {
+ tcg_temp_free_ptr(ptr);
+ }
} else {
- tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
- vfp_reg_offset(1, rn),
- vfp_reg_offset(1, rm),
+ tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
opr_sz, opr_sz, data, fn_gvec);
}
return 0;
gen_helper_gvec_3 *fn_gvec = NULL;
gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
int rd, rn, rm, opr_sz, data;
- bool q;
-
- q = extract32(insn, 6, 1);
- VFP_DREG_D(rd, insn);
- VFP_DREG_N(rn, insn);
- if ((rd | rn) & q) {
- return 1;
- }
+ int off_rn, off_rm;
+ bool is_long = false, q = extract32(insn, 6, 1);
+ bool ptr_is_env = false;
if ((insn & 0xff000f10) == 0xfe000800) {
/* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
} else if ((insn & 0xffb00f00) == 0xfe200d00) {
/* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
int u = extract32(insn, 4, 1);
+
if (!dc_isar_feature(aa32_dp, s)) {
return 1;
}
/* rm is just Vm, and index is M. */
data = extract32(insn, 5, 1); /* index */
rm = extract32(insn, 0, 4);
+ } else if ((insn & 0xffa00f10) == 0xfe000810) {
+ /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
+ int is_s = extract32(insn, 20, 1);
+ int vm20 = extract32(insn, 0, 3);
+ int vm3 = extract32(insn, 3, 1);
+ int m = extract32(insn, 5, 1);
+ int index;
+
+ if (!dc_isar_feature(aa32_fhm, s)) {
+ return 1;
+ }
+ if (q) {
+ rm = vm20;
+ index = m * 2 + vm3;
+ } else {
+ rm = vm20 * 2 + m;
+ index = vm3;
+ }
+ is_long = true;
+ data = (index << 2) | is_s; /* is_2 == 0 */
+ fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32;
+ ptr_is_env = true;
} else {
return 1;
}
+ VFP_DREG_D(rd, insn);
+ if (rd & q) {
+ return 1;
+ }
+ if (q || !is_long) {
+ VFP_DREG_N(rn, insn);
+ if (rn & q & !is_long) {
+ return 1;
+ }
+ off_rn = vfp_reg_offset(1, rn);
+ off_rm = vfp_reg_offset(1, rm);
+ } else {
+ rn = VFP_SREG_N(insn);
+ off_rn = vfp_reg_offset(0, rn);
+ off_rm = vfp_reg_offset(0, rm);
+ }
if (s->fp_excp_el) {
gen_exception_insn(s, 4, EXCP_UDEF,
syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
opr_sz = (1 + q) * 8;
if (fn_gvec_ptr) {
- TCGv_ptr fpst = get_fpstatus_ptr(1);
- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
- vfp_reg_offset(1, rn),
- vfp_reg_offset(1, rm), fpst,
+ TCGv_ptr ptr;
+ if (ptr_is_env) {
+ ptr = cpu_env;
+ } else {
+ ptr = get_fpstatus_ptr(1);
+ }
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
opr_sz, opr_sz, data, fn_gvec_ptr);
- tcg_temp_free_ptr(fpst);
+ if (!ptr_is_env) {
+ tcg_temp_free_ptr(ptr);
+ }
} else {
- tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
- vfp_reg_offset(1, rn),
- vfp_reg_offset(1, rm),
+ tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
opr_sz, opr_sz, data, fn_gvec);
}
return 0;
i * 2 + 1, (uint32_t)(v >> 32),
i, v);
}
- cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
+ cpu_fprintf(f, "FPSCR: %08x\n", vfp_get_fpscr(env));
}
}
int user;
#endif
ARMMMUIdx mmu_idx; /* MMU index to use for normal loads/stores */
- uint8_t tbii; /* TBI1|TBI0 for EL0/1 or TBI for EL2/3 */
+ uint8_t tbii; /* TBI1|TBI0 for insns */
+ uint8_t tbid; /* TBI1|TBI0 for data */
bool ns; /* Use non-secure CPREG bank on access */
int fp_excp_el; /* FP exception EL or 0 if enabled */
int sve_excp_el; /* SVE exception EL or 0 if enabled */
bool ss_same_el;
/* True if v8.3-PAuth is active. */
bool pauth_active;
+ /* True with v8.5-BTI and SCTLR_ELx.BT* set. */
+ bool bt;
+ /*
+ * >= 0, a copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI.
+ * < 0, set by the current instruction.
+ */
+ int8_t btype;
+ /* True if this page is guarded. */
+ bool guarded_page;
/* Bottom two bits of XScale c15_cpar coprocessor access control reg */
int c15_cpar;
/* TCG op of the current insn_start. */
extern const GVecGen2i usra_op[4];
extern const GVecGen2i sri_op[4];
extern const GVecGen2i sli_op[4];
+extern const GVecGen4 uqadd_op[4];
+extern const GVecGen4 sqadd_op[4];
+extern const GVecGen4 uqsub_op[4];
+extern const GVecGen4 sqsub_op[4];
void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
/*
#define H4(x) (x)
#endif
-#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
+#define SET_QC() env->vfp.qc[0] = 1
static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
{
for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
d[i] = FUNC(n[i], stat); \
} \
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
}
DO_2OP(gvec_frecpe_h, helper_recpe_f16, float16)
for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
d[i] = FUNC(n[i], m[i], stat); \
} \
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
}
DO_3OP(gvec_fadd_h, float16_add, float16)
DO_FMLA_IDX(gvec_fmla_idx_d, float64, )
#undef DO_FMLA_IDX
+
+#define DO_SAT(NAME, WTYPE, TYPEN, TYPEM, OP, MIN, MAX) \
+void HELPER(NAME)(void *vd, void *vq, void *vn, void *vm, uint32_t desc) \
+{ \
+ intptr_t i, oprsz = simd_oprsz(desc); \
+ TYPEN *d = vd, *n = vn; TYPEM *m = vm; \
+ bool q = false; \
+ for (i = 0; i < oprsz / sizeof(TYPEN); i++) { \
+ WTYPE dd = (WTYPE)n[i] OP m[i]; \
+ if (dd < MIN) { \
+ dd = MIN; \
+ q = true; \
+ } else if (dd > MAX) { \
+ dd = MAX; \
+ q = true; \
+ } \
+ d[i] = dd; \
+ } \
+ if (q) { \
+ uint32_t *qc = vq; \
+ qc[0] = 1; \
+ } \
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
+}
+
+DO_SAT(gvec_uqadd_b, int, uint8_t, uint8_t, +, 0, UINT8_MAX)
+DO_SAT(gvec_uqadd_h, int, uint16_t, uint16_t, +, 0, UINT16_MAX)
+DO_SAT(gvec_uqadd_s, int64_t, uint32_t, uint32_t, +, 0, UINT32_MAX)
+
+DO_SAT(gvec_sqadd_b, int, int8_t, int8_t, +, INT8_MIN, INT8_MAX)
+DO_SAT(gvec_sqadd_h, int, int16_t, int16_t, +, INT16_MIN, INT16_MAX)
+DO_SAT(gvec_sqadd_s, int64_t, int32_t, int32_t, +, INT32_MIN, INT32_MAX)
+
+DO_SAT(gvec_uqsub_b, int, uint8_t, uint8_t, -, 0, UINT8_MAX)
+DO_SAT(gvec_uqsub_h, int, uint16_t, uint16_t, -, 0, UINT16_MAX)
+DO_SAT(gvec_uqsub_s, int64_t, uint32_t, uint32_t, -, 0, UINT32_MAX)
+
+DO_SAT(gvec_sqsub_b, int, int8_t, int8_t, -, INT8_MIN, INT8_MAX)
+DO_SAT(gvec_sqsub_h, int, int16_t, int16_t, -, INT16_MIN, INT16_MAX)
+DO_SAT(gvec_sqsub_s, int64_t, int32_t, int32_t, -, INT32_MIN, INT32_MAX)
+
+#undef DO_SAT
+
+void HELPER(gvec_uqadd_d)(void *vd, void *vq, void *vn,
+ void *vm, uint32_t desc)
+{
+ intptr_t i, oprsz = simd_oprsz(desc);
+ uint64_t *d = vd, *n = vn, *m = vm;
+ bool q = false;
+
+ for (i = 0; i < oprsz / 8; i++) {
+ uint64_t nn = n[i], mm = m[i], dd = nn + mm;
+ if (dd < nn) {
+ dd = UINT64_MAX;
+ q = true;
+ }
+ d[i] = dd;
+ }
+ if (q) {
+ uint32_t *qc = vq;
+ qc[0] = 1;
+ }
+ clear_tail(d, oprsz, simd_maxsz(desc));
+}
+
+void HELPER(gvec_uqsub_d)(void *vd, void *vq, void *vn,
+ void *vm, uint32_t desc)
+{
+ intptr_t i, oprsz = simd_oprsz(desc);
+ uint64_t *d = vd, *n = vn, *m = vm;
+ bool q = false;
+
+ for (i = 0; i < oprsz / 8; i++) {
+ uint64_t nn = n[i], mm = m[i], dd = nn - mm;
+ if (nn < mm) {
+ dd = 0;
+ q = true;
+ }
+ d[i] = dd;
+ }
+ if (q) {
+ uint32_t *qc = vq;
+ qc[0] = 1;
+ }
+ clear_tail(d, oprsz, simd_maxsz(desc));
+}
+
+void HELPER(gvec_sqadd_d)(void *vd, void *vq, void *vn,
+ void *vm, uint32_t desc)
+{
+ intptr_t i, oprsz = simd_oprsz(desc);
+ int64_t *d = vd, *n = vn, *m = vm;
+ bool q = false;
+
+ for (i = 0; i < oprsz / 8; i++) {
+ int64_t nn = n[i], mm = m[i], dd = nn + mm;
+ if (((dd ^ nn) & ~(nn ^ mm)) & INT64_MIN) {
+ dd = (nn >> 63) ^ ~INT64_MIN;
+ q = true;
+ }
+ d[i] = dd;
+ }
+ if (q) {
+ uint32_t *qc = vq;
+ qc[0] = 1;
+ }
+ clear_tail(d, oprsz, simd_maxsz(desc));
+}
+
+void HELPER(gvec_sqsub_d)(void *vd, void *vq, void *vn,
+ void *vm, uint32_t desc)
+{
+ intptr_t i, oprsz = simd_oprsz(desc);
+ int64_t *d = vd, *n = vn, *m = vm;
+ bool q = false;
+
+ for (i = 0; i < oprsz / 8; i++) {
+ int64_t nn = n[i], mm = m[i], dd = nn - mm;
+ if (((dd ^ nn) & (nn ^ mm)) & INT64_MIN) {
+ dd = (nn >> 63) ^ ~INT64_MIN;
+ q = true;
+ }
+ d[i] = dd;
+ }
+ if (q) {
+ uint32_t *qc = vq;
+ qc[0] = 1;
+ }
+ clear_tail(d, oprsz, simd_maxsz(desc));
+}
+
+/*
+ * Convert float16 to float32, raising no exceptions and
+ * preserving exceptional values, including SNaN.
+ * This is effectively an unpack+repack operation.
+ */
+static float32 float16_to_float32_by_bits(uint32_t f16, bool fz16)
+{
+ const int f16_bias = 15;
+ const int f32_bias = 127;
+ uint32_t sign = extract32(f16, 15, 1);
+ uint32_t exp = extract32(f16, 10, 5);
+ uint32_t frac = extract32(f16, 0, 10);
+
+ if (exp == 0x1f) {
+ /* Inf or NaN */
+ exp = 0xff;
+ } else if (exp == 0) {
+ /* Zero or denormal. */
+ if (frac != 0) {
+ if (fz16) {
+ frac = 0;
+ } else {
+ /*
+ * Denormal; these are all normal float32.
+ * Shift the fraction so that the msb is at bit 11,
+ * then remove bit 11 as the implicit bit of the
+ * normalized float32. Note that we still go through
+ * the shift for normal numbers below, to put the
+ * float32 fraction at the right place.
+ */
+ int shift = clz32(frac) - 21;
+ frac = (frac << shift) & 0x3ff;
+ exp = f32_bias - f16_bias - shift + 1;
+ }
+ }
+ } else {
+ /* Normal number; adjust the bias. */
+ exp += f32_bias - f16_bias;
+ }
+ sign <<= 31;
+ exp <<= 23;
+ frac <<= 23 - 10;
+
+ return sign | exp | frac;
+}
+
+static uint64_t load4_f16(uint64_t *ptr, int is_q, int is_2)
+{
+ /*
+ * Branchless load of u32[0], u64[0], u32[1], or u64[1].
+ * Load the 2nd qword iff is_q & is_2.
+ * Shift to the 2nd dword iff !is_q & is_2.
+ * For !is_q & !is_2, the upper bits of the result are garbage.
+ */
+ return ptr[is_q & is_2] >> ((is_2 & ~is_q) << 5);
+}
+
+/*
+ * Note that FMLAL requires oprsz == 8 or oprsz == 16,
+ * as there is not yet SVE versions that might use blocking.
+ */
+
+static void do_fmlal(float32 *d, void *vn, void *vm, float_status *fpst,
+ uint32_t desc, bool fz16)
+{
+ intptr_t i, oprsz = simd_oprsz(desc);
+ int is_s = extract32(desc, SIMD_DATA_SHIFT, 1);
+ int is_2 = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
+ int is_q = oprsz == 16;
+ uint64_t n_4, m_4;
+
+ /* Pre-load all of the f16 data, avoiding overlap issues. */
+ n_4 = load4_f16(vn, is_q, is_2);
+ m_4 = load4_f16(vm, is_q, is_2);
+
+ /* Negate all inputs for FMLSL at once. */
+ if (is_s) {
+ n_4 ^= 0x8000800080008000ull;
+ }
+
+ for (i = 0; i < oprsz / 4; i++) {
+ float32 n_1 = float16_to_float32_by_bits(n_4 >> (i * 16), fz16);
+ float32 m_1 = float16_to_float32_by_bits(m_4 >> (i * 16), fz16);
+ d[H4(i)] = float32_muladd(n_1, m_1, d[H4(i)], 0, fpst);
+ }
+ clear_tail(d, oprsz, simd_maxsz(desc));
+}
+
+void HELPER(gvec_fmlal_a32)(void *vd, void *vn, void *vm,
+ void *venv, uint32_t desc)
+{
+ CPUARMState *env = venv;
+ do_fmlal(vd, vn, vm, &env->vfp.standard_fp_status, desc,
+ get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
+}
+
+void HELPER(gvec_fmlal_a64)(void *vd, void *vn, void *vm,
+ void *venv, uint32_t desc)
+{
+ CPUARMState *env = venv;
+ do_fmlal(vd, vn, vm, &env->vfp.fp_status, desc,
+ get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
+}
+
+static void do_fmlal_idx(float32 *d, void *vn, void *vm, float_status *fpst,
+ uint32_t desc, bool fz16)
+{
+ intptr_t i, oprsz = simd_oprsz(desc);
+ int is_s = extract32(desc, SIMD_DATA_SHIFT, 1);
+ int is_2 = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
+ int index = extract32(desc, SIMD_DATA_SHIFT + 2, 3);
+ int is_q = oprsz == 16;
+ uint64_t n_4;
+ float32 m_1;
+
+ /* Pre-load all of the f16 data, avoiding overlap issues. */
+ n_4 = load4_f16(vn, is_q, is_2);
+
+ /* Negate all inputs for FMLSL at once. */
+ if (is_s) {
+ n_4 ^= 0x8000800080008000ull;
+ }
+
+ m_1 = float16_to_float32_by_bits(((float16 *)vm)[H2(index)], fz16);
+
+ for (i = 0; i < oprsz / 4; i++) {
+ float32 n_1 = float16_to_float32_by_bits(n_4 >> (i * 16), fz16);
+ d[H4(i)] = float32_muladd(n_1, m_1, d[H4(i)], 0, fpst);
+ }
+ clear_tail(d, oprsz, simd_maxsz(desc));
+}
+
+void HELPER(gvec_fmlal_idx_a32)(void *vd, void *vn, void *vm,
+ void *venv, uint32_t desc)
+{
+ CPUARMState *env = venv;
+ do_fmlal_idx(vd, vn, vm, &env->vfp.standard_fp_status, desc,
+ get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
+}
+
+void HELPER(gvec_fmlal_idx_a64)(void *vd, void *vn, void *vm,
+ void *venv, uint32_t desc)
+{
+ CPUARMState *env = venv;
+ do_fmlal_idx(vd, vn, vm, &env->vfp.fp_status, desc,
+ get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
+}
--- /dev/null
+/*
+ * ARM VFP floating-point operations
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "cpu.h"
+#include "exec/helper-proto.h"
+#include "fpu/softfloat.h"
+#include "internals.h"
+
+
+/* VFP support. We follow the convention used for VFP instructions:
+ Single precision routines have a "s" suffix, double precision a
+ "d" suffix. */
+
+/* Convert host exception flags to vfp form. */
+static inline int vfp_exceptbits_from_host(int host_bits)
+{
+ int target_bits = 0;
+
+ if (host_bits & float_flag_invalid)
+ target_bits |= 1;
+ if (host_bits & float_flag_divbyzero)
+ target_bits |= 2;
+ if (host_bits & float_flag_overflow)
+ target_bits |= 4;
+ if (host_bits & (float_flag_underflow | float_flag_output_denormal))
+ target_bits |= 8;
+ if (host_bits & float_flag_inexact)
+ target_bits |= 0x10;
+ if (host_bits & float_flag_input_denormal)
+ target_bits |= 0x80;
+ return target_bits;
+}
+
+uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
+{
+ uint32_t i, fpscr;
+
+ fpscr = env->vfp.xregs[ARM_VFP_FPSCR]
+ | (env->vfp.vec_len << 16)
+ | (env->vfp.vec_stride << 20);
+
+ i = get_float_exception_flags(&env->vfp.fp_status);
+ i |= get_float_exception_flags(&env->vfp.standard_fp_status);
+ /* FZ16 does not generate an input denormal exception. */
+ i |= (get_float_exception_flags(&env->vfp.fp_status_f16)
+ & ~float_flag_input_denormal);
+ fpscr |= vfp_exceptbits_from_host(i);
+
+ i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
+ fpscr |= i ? FPCR_QC : 0;
+
+ return fpscr;
+}
+
+uint32_t vfp_get_fpscr(CPUARMState *env)
+{
+ return HELPER(vfp_get_fpscr)(env);
+}
+
+/* Convert vfp exception flags to target form. */
+static inline int vfp_exceptbits_to_host(int target_bits)
+{
+ int host_bits = 0;
+
+ if (target_bits & 1)
+ host_bits |= float_flag_invalid;
+ if (target_bits & 2)
+ host_bits |= float_flag_divbyzero;
+ if (target_bits & 4)
+ host_bits |= float_flag_overflow;
+ if (target_bits & 8)
+ host_bits |= float_flag_underflow;
+ if (target_bits & 0x10)
+ host_bits |= float_flag_inexact;
+ if (target_bits & 0x80)
+ host_bits |= float_flag_input_denormal;
+ return host_bits;
+}
+
+void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
+{
+ int i;
+ uint32_t changed = env->vfp.xregs[ARM_VFP_FPSCR];
+
+ /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
+ if (!cpu_isar_feature(aa64_fp16, arm_env_get_cpu(env))) {
+ val &= ~FPCR_FZ16;
+ }
+
+ /*
+ * We don't implement trapped exception handling, so the
+ * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
+ *
+ * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
+ * (which are stored in fp_status), and the other RES0 bits
+ * in between, then we clear all of the low 16 bits.
+ */
+ env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
+ env->vfp.vec_len = (val >> 16) & 7;
+ env->vfp.vec_stride = (val >> 20) & 3;
+
+ /*
+ * The bit we set within fpscr_q is arbitrary; the register as a
+ * whole being zero/non-zero is what counts.
+ */
+ env->vfp.qc[0] = val & FPCR_QC;
+ env->vfp.qc[1] = 0;
+ env->vfp.qc[2] = 0;
+ env->vfp.qc[3] = 0;
+
+ changed ^= val;
+ if (changed & (3 << 22)) {
+ i = (val >> 22) & 3;
+ switch (i) {
+ case FPROUNDING_TIEEVEN:
+ i = float_round_nearest_even;
+ break;
+ case FPROUNDING_POSINF:
+ i = float_round_up;
+ break;
+ case FPROUNDING_NEGINF:
+ i = float_round_down;
+ break;
+ case FPROUNDING_ZERO:
+ i = float_round_to_zero;
+ break;
+ }
+ set_float_rounding_mode(i, &env->vfp.fp_status);
+ set_float_rounding_mode(i, &env->vfp.fp_status_f16);
+ }
+ if (changed & FPCR_FZ16) {
+ bool ftz_enabled = val & FPCR_FZ16;
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
+ }
+ if (changed & FPCR_FZ) {
+ bool ftz_enabled = val & FPCR_FZ;
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status);
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status);
+ }
+ if (changed & FPCR_DN) {
+ bool dnan_enabled = val & FPCR_DN;
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status);
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16);
+ }
+
+ /* The exception flags are ORed together when we read fpscr so we
+ * only need to preserve the current state in one of our
+ * float_status values.
+ */
+ i = vfp_exceptbits_to_host(val);
+ set_float_exception_flags(i, &env->vfp.fp_status);
+ set_float_exception_flags(0, &env->vfp.fp_status_f16);
+ set_float_exception_flags(0, &env->vfp.standard_fp_status);
+}
+
+void vfp_set_fpscr(CPUARMState *env, uint32_t val)
+{
+ HELPER(vfp_set_fpscr)(env, val);
+}
+
+#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
+
+#define VFP_BINOP(name) \
+float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
+{ \
+ float_status *fpst = fpstp; \
+ return float32_ ## name(a, b, fpst); \
+} \
+float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
+{ \
+ float_status *fpst = fpstp; \
+ return float64_ ## name(a, b, fpst); \
+}
+VFP_BINOP(add)
+VFP_BINOP(sub)
+VFP_BINOP(mul)
+VFP_BINOP(div)
+VFP_BINOP(min)
+VFP_BINOP(max)
+VFP_BINOP(minnum)
+VFP_BINOP(maxnum)
+#undef VFP_BINOP
+
+float32 VFP_HELPER(neg, s)(float32 a)
+{
+ return float32_chs(a);
+}
+
+float64 VFP_HELPER(neg, d)(float64 a)
+{
+ return float64_chs(a);
+}
+
+float32 VFP_HELPER(abs, s)(float32 a)
+{
+ return float32_abs(a);
+}
+
+float64 VFP_HELPER(abs, d)(float64 a)
+{
+ return float64_abs(a);
+}
+
+float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
+{
+ return float32_sqrt(a, &env->vfp.fp_status);
+}
+
+float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env)
+{
+ return float64_sqrt(a, &env->vfp.fp_status);
+}
+
+static void softfloat_to_vfp_compare(CPUARMState *env, int cmp)
+{
+ uint32_t flags;
+ switch (cmp) {
+ case float_relation_equal:
+ flags = 0x6;
+ break;
+ case float_relation_less:
+ flags = 0x8;
+ break;
+ case float_relation_greater:
+ flags = 0x2;
+ break;
+ case float_relation_unordered:
+ flags = 0x3;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ env->vfp.xregs[ARM_VFP_FPSCR] =
+ deposit32(env->vfp.xregs[ARM_VFP_FPSCR], 28, 4, flags);
+}
+
+/* XXX: check quiet/signaling case */
+#define DO_VFP_cmp(p, type) \
+void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \
+{ \
+ softfloat_to_vfp_compare(env, \
+ type ## _compare_quiet(a, b, &env->vfp.fp_status)); \
+} \
+void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
+{ \
+ softfloat_to_vfp_compare(env, \
+ type ## _compare(a, b, &env->vfp.fp_status)); \
+}
+DO_VFP_cmp(s, float32)
+DO_VFP_cmp(d, float64)
+#undef DO_VFP_cmp
+
+/* Integer to float and float to integer conversions */
+
+#define CONV_ITOF(name, ftype, fsz, sign) \
+ftype HELPER(name)(uint32_t x, void *fpstp) \
+{ \
+ float_status *fpst = fpstp; \
+ return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
+}
+
+#define CONV_FTOI(name, ftype, fsz, sign, round) \
+sign##int32_t HELPER(name)(ftype x, void *fpstp) \
+{ \
+ float_status *fpst = fpstp; \
+ if (float##fsz##_is_any_nan(x)) { \
+ float_raise(float_flag_invalid, fpst); \
+ return 0; \
+ } \
+ return float##fsz##_to_##sign##int32##round(x, fpst); \
+}
+
+#define FLOAT_CONVS(name, p, ftype, fsz, sign) \
+ CONV_ITOF(vfp_##name##to##p, ftype, fsz, sign) \
+ CONV_FTOI(vfp_to##name##p, ftype, fsz, sign, ) \
+ CONV_FTOI(vfp_to##name##z##p, ftype, fsz, sign, _round_to_zero)
+
+FLOAT_CONVS(si, h, uint32_t, 16, )
+FLOAT_CONVS(si, s, float32, 32, )
+FLOAT_CONVS(si, d, float64, 64, )
+FLOAT_CONVS(ui, h, uint32_t, 16, u)
+FLOAT_CONVS(ui, s, float32, 32, u)
+FLOAT_CONVS(ui, d, float64, 64, u)
+
+#undef CONV_ITOF
+#undef CONV_FTOI
+#undef FLOAT_CONVS
+
+/* floating point conversion */
+float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
+{
+ return float32_to_float64(x, &env->vfp.fp_status);
+}
+
+float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
+{
+ return float64_to_float32(x, &env->vfp.fp_status);
+}
+
+/* VFP3 fixed point conversion. */
+#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
+float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
+ void *fpstp) \
+{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
+
+#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
+uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
+ void *fpst) \
+{ \
+ if (unlikely(float##fsz##_is_any_nan(x))) { \
+ float_raise(float_flag_invalid, fpst); \
+ return 0; \
+ } \
+ return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
+}
+
+#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
+VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
+ float_round_to_zero, _round_to_zero) \
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
+ get_float_rounding_mode(fpst), )
+
+#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
+VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
+ get_float_rounding_mode(fpst), )
+
+VFP_CONV_FIX(sh, d, 64, 64, int16)
+VFP_CONV_FIX(sl, d, 64, 64, int32)
+VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
+VFP_CONV_FIX(uh, d, 64, 64, uint16)
+VFP_CONV_FIX(ul, d, 64, 64, uint32)
+VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
+VFP_CONV_FIX(sh, s, 32, 32, int16)
+VFP_CONV_FIX(sl, s, 32, 32, int32)
+VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
+VFP_CONV_FIX(uh, s, 32, 32, uint16)
+VFP_CONV_FIX(ul, s, 32, 32, uint32)
+VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
+
+#undef VFP_CONV_FIX
+#undef VFP_CONV_FIX_FLOAT
+#undef VFP_CONV_FLOAT_FIX_ROUND
+#undef VFP_CONV_FIX_A64
+
+uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
+{
+ return int32_to_float16_scalbn(x, -shift, fpst);
+}
+
+uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
+{
+ return uint32_to_float16_scalbn(x, -shift, fpst);
+}
+
+uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
+{
+ return int64_to_float16_scalbn(x, -shift, fpst);
+}
+
+uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
+{
+ return uint64_to_float16_scalbn(x, -shift, fpst);
+}
+
+uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
+{
+ if (unlikely(float16_is_any_nan(x))) {
+ float_raise(float_flag_invalid, fpst);
+ return 0;
+ }
+ return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
+ shift, fpst);
+}
+
+uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
+{
+ if (unlikely(float16_is_any_nan(x))) {
+ float_raise(float_flag_invalid, fpst);
+ return 0;
+ }
+ return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
+ shift, fpst);
+}
+
+uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
+{
+ if (unlikely(float16_is_any_nan(x))) {
+ float_raise(float_flag_invalid, fpst);
+ return 0;
+ }
+ return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
+ shift, fpst);
+}
+
+uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
+{
+ if (unlikely(float16_is_any_nan(x))) {
+ float_raise(float_flag_invalid, fpst);
+ return 0;
+ }
+ return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
+ shift, fpst);
+}
+
+uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
+{
+ if (unlikely(float16_is_any_nan(x))) {
+ float_raise(float_flag_invalid, fpst);
+ return 0;
+ }
+ return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
+ shift, fpst);
+}
+
+uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
+{
+ if (unlikely(float16_is_any_nan(x))) {
+ float_raise(float_flag_invalid, fpst);
+ return 0;
+ }
+ return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
+ shift, fpst);
+}
+
+/* Set the current fp rounding mode and return the old one.
+ * The argument is a softfloat float_round_ value.
+ */
+uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp)
+{
+ float_status *fp_status = fpstp;
+
+ uint32_t prev_rmode = get_float_rounding_mode(fp_status);
+ set_float_rounding_mode(rmode, fp_status);
+
+ return prev_rmode;
+}
+
+/* Set the current fp rounding mode in the standard fp status and return
+ * the old one. This is for NEON instructions that need to change the
+ * rounding mode but wish to use the standard FPSCR values for everything
+ * else. Always set the rounding mode back to the correct value after
+ * modifying it.
+ * The argument is a softfloat float_round_ value.
+ */
+uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
+{
+ float_status *fp_status = &env->vfp.standard_fp_status;
+
+ uint32_t prev_rmode = get_float_rounding_mode(fp_status);
+ set_float_rounding_mode(rmode, fp_status);
+
+ return prev_rmode;
+}
+
+/* Half precision conversions. */
+float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode)
+{
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
+ * it would affect flushing input denormals.
+ */
+ float_status *fpst = fpstp;
+ flag save = get_flush_inputs_to_zero(fpst);
+ set_flush_inputs_to_zero(false, fpst);
+ float32 r = float16_to_float32(a, !ahp_mode, fpst);
+ set_flush_inputs_to_zero(save, fpst);
+ return r;
+}
+
+uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, void *fpstp, uint32_t ahp_mode)
+{
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
+ * it would affect flushing output denormals.
+ */
+ float_status *fpst = fpstp;
+ flag save = get_flush_to_zero(fpst);
+ set_flush_to_zero(false, fpst);
+ float16 r = float32_to_float16(a, !ahp_mode, fpst);
+ set_flush_to_zero(save, fpst);
+ return r;
+}
+
+float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, void *fpstp, uint32_t ahp_mode)
+{
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
+ * it would affect flushing input denormals.
+ */
+ float_status *fpst = fpstp;
+ flag save = get_flush_inputs_to_zero(fpst);
+ set_flush_inputs_to_zero(false, fpst);
+ float64 r = float16_to_float64(a, !ahp_mode, fpst);
+ set_flush_inputs_to_zero(save, fpst);
+ return r;
+}
+
+uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
+{
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
+ * it would affect flushing output denormals.
+ */
+ float_status *fpst = fpstp;
+ flag save = get_flush_to_zero(fpst);
+ set_flush_to_zero(false, fpst);
+ float16 r = float64_to_float16(a, !ahp_mode, fpst);
+ set_flush_to_zero(save, fpst);
+ return r;
+}
+
+#define float32_two make_float32(0x40000000)
+#define float32_three make_float32(0x40400000)
+#define float32_one_point_five make_float32(0x3fc00000)
+
+float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
+{
+ float_status *s = &env->vfp.standard_fp_status;
+ if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
+ (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
+ if (!(float32_is_zero(a) || float32_is_zero(b))) {
+ float_raise(float_flag_input_denormal, s);
+ }
+ return float32_two;
+ }
+ return float32_sub(float32_two, float32_mul(a, b, s), s);
+}
+
+float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
+{
+ float_status *s = &env->vfp.standard_fp_status;
+ float32 product;
+ if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
+ (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
+ if (!(float32_is_zero(a) || float32_is_zero(b))) {
+ float_raise(float_flag_input_denormal, s);
+ }
+ return float32_one_point_five;
+ }
+ product = float32_mul(a, b, s);
+ return float32_div(float32_sub(float32_three, product, s), float32_two, s);
+}
+
+/* NEON helpers. */
+
+/* Constants 256 and 512 are used in some helpers; we avoid relying on
+ * int->float conversions at run-time. */
+#define float64_256 make_float64(0x4070000000000000LL)
+#define float64_512 make_float64(0x4080000000000000LL)
+#define float16_maxnorm make_float16(0x7bff)
+#define float32_maxnorm make_float32(0x7f7fffff)
+#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
+
+/* Reciprocal functions
+ *
+ * The algorithm that must be used to calculate the estimate
+ * is specified by the ARM ARM, see FPRecipEstimate()/RecipEstimate
+ */
+
+/* See RecipEstimate()
+ *
+ * input is a 9 bit fixed point number
+ * input range 256 .. 511 for a number from 0.5 <= x < 1.0.
+ * result range 256 .. 511 for a number from 1.0 to 511/256.
+ */
+
+static int recip_estimate(int input)
+{
+ int a, b, r;
+ assert(256 <= input && input < 512);
+ a = (input * 2) + 1;
+ b = (1 << 19) / a;
+ r = (b + 1) >> 1;
+ assert(256 <= r && r < 512);
+ return r;
+}
+
+/*
+ * Common wrapper to call recip_estimate
+ *
+ * The parameters are exponent and 64 bit fraction (without implicit
+ * bit) where the binary point is nominally at bit 52. Returns a
+ * float64 which can then be rounded to the appropriate size by the
+ * callee.
+ */
+
+static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac)
+{
+ uint32_t scaled, estimate;
+ uint64_t result_frac;
+ int result_exp;
+
+ /* Handle sub-normals */
+ if (*exp == 0) {
+ if (extract64(frac, 51, 1) == 0) {
+ *exp = -1;
+ frac <<= 2;
+ } else {
+ frac <<= 1;
+ }
+ }
+
+ /* scaled = UInt('1':fraction<51:44>) */
+ scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
+ estimate = recip_estimate(scaled);
+
+ result_exp = exp_off - *exp;
+ result_frac = deposit64(0, 44, 8, estimate);
+ if (result_exp == 0) {
+ result_frac = deposit64(result_frac >> 1, 51, 1, 1);
+ } else if (result_exp == -1) {
+ result_frac = deposit64(result_frac >> 2, 50, 2, 1);
+ result_exp = 0;
+ }
+
+ *exp = result_exp;
+
+ return result_frac;
+}
+
+static bool round_to_inf(float_status *fpst, bool sign_bit)
+{
+ switch (fpst->float_rounding_mode) {
+ case float_round_nearest_even: /* Round to Nearest */
+ return true;
+ case float_round_up: /* Round to +Inf */
+ return !sign_bit;
+ case float_round_down: /* Round to -Inf */
+ return sign_bit;
+ case float_round_to_zero: /* Round to Zero */
+ return false;
+ }
+
+ g_assert_not_reached();
+}
+
+uint32_t HELPER(recpe_f16)(uint32_t input, void *fpstp)
+{
+ float_status *fpst = fpstp;
+ float16 f16 = float16_squash_input_denormal(input, fpst);
+ uint32_t f16_val = float16_val(f16);
+ uint32_t f16_sign = float16_is_neg(f16);
+ int f16_exp = extract32(f16_val, 10, 5);
+ uint32_t f16_frac = extract32(f16_val, 0, 10);
+ uint64_t f64_frac;
+
+ if (float16_is_any_nan(f16)) {
+ float16 nan = f16;
+ if (float16_is_signaling_nan(f16, fpst)) {
+ float_raise(float_flag_invalid, fpst);
+ nan = float16_silence_nan(f16, fpst);
+ }
+ if (fpst->default_nan_mode) {
+ nan = float16_default_nan(fpst);
+ }
+ return nan;
+ } else if (float16_is_infinity(f16)) {
+ return float16_set_sign(float16_zero, float16_is_neg(f16));
+ } else if (float16_is_zero(f16)) {
+ float_raise(float_flag_divbyzero, fpst);
+ return float16_set_sign(float16_infinity, float16_is_neg(f16));
+ } else if (float16_abs(f16) < (1 << 8)) {
+ /* Abs(value) < 2.0^-16 */
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
+ if (round_to_inf(fpst, f16_sign)) {
+ return float16_set_sign(float16_infinity, f16_sign);
+ } else {
+ return float16_set_sign(float16_maxnorm, f16_sign);
+ }
+ } else if (f16_exp >= 29 && fpst->flush_to_zero) {
+ float_raise(float_flag_underflow, fpst);
+ return float16_set_sign(float16_zero, float16_is_neg(f16));
+ }
+
+ f64_frac = call_recip_estimate(&f16_exp, 29,
+ ((uint64_t) f16_frac) << (52 - 10));
+
+ /* result = sign : result_exp<4:0> : fraction<51:42> */
+ f16_val = deposit32(0, 15, 1, f16_sign);
+ f16_val = deposit32(f16_val, 10, 5, f16_exp);
+ f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
+ return make_float16(f16_val);
+}
+
+float32 HELPER(recpe_f32)(float32 input, void *fpstp)
+{
+ float_status *fpst = fpstp;
+ float32 f32 = float32_squash_input_denormal(input, fpst);
+ uint32_t f32_val = float32_val(f32);
+ bool f32_sign = float32_is_neg(f32);
+ int f32_exp = extract32(f32_val, 23, 8);
+ uint32_t f32_frac = extract32(f32_val, 0, 23);
+ uint64_t f64_frac;
+
+ if (float32_is_any_nan(f32)) {
+ float32 nan = f32;
+ if (float32_is_signaling_nan(f32, fpst)) {
+ float_raise(float_flag_invalid, fpst);
+ nan = float32_silence_nan(f32, fpst);
+ }
+ if (fpst->default_nan_mode) {
+ nan = float32_default_nan(fpst);
+ }
+ return nan;
+ } else if (float32_is_infinity(f32)) {
+ return float32_set_sign(float32_zero, float32_is_neg(f32));
+ } else if (float32_is_zero(f32)) {
+ float_raise(float_flag_divbyzero, fpst);
+ return float32_set_sign(float32_infinity, float32_is_neg(f32));
+ } else if (float32_abs(f32) < (1ULL << 21)) {
+ /* Abs(value) < 2.0^-128 */
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
+ if (round_to_inf(fpst, f32_sign)) {
+ return float32_set_sign(float32_infinity, f32_sign);
+ } else {
+ return float32_set_sign(float32_maxnorm, f32_sign);
+ }
+ } else if (f32_exp >= 253 && fpst->flush_to_zero) {
+ float_raise(float_flag_underflow, fpst);
+ return float32_set_sign(float32_zero, float32_is_neg(f32));
+ }
+
+ f64_frac = call_recip_estimate(&f32_exp, 253,
+ ((uint64_t) f32_frac) << (52 - 23));
+
+ /* result = sign : result_exp<7:0> : fraction<51:29> */
+ f32_val = deposit32(0, 31, 1, f32_sign);
+ f32_val = deposit32(f32_val, 23, 8, f32_exp);
+ f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
+ return make_float32(f32_val);
+}
+
+float64 HELPER(recpe_f64)(float64 input, void *fpstp)
+{
+ float_status *fpst = fpstp;
+ float64 f64 = float64_squash_input_denormal(input, fpst);
+ uint64_t f64_val = float64_val(f64);
+ bool f64_sign = float64_is_neg(f64);
+ int f64_exp = extract64(f64_val, 52, 11);
+ uint64_t f64_frac = extract64(f64_val, 0, 52);
+
+ /* Deal with any special cases */
+ if (float64_is_any_nan(f64)) {
+ float64 nan = f64;
+ if (float64_is_signaling_nan(f64, fpst)) {
+ float_raise(float_flag_invalid, fpst);
+ nan = float64_silence_nan(f64, fpst);
+ }
+ if (fpst->default_nan_mode) {
+ nan = float64_default_nan(fpst);
+ }
+ return nan;
+ } else if (float64_is_infinity(f64)) {
+ return float64_set_sign(float64_zero, float64_is_neg(f64));
+ } else if (float64_is_zero(f64)) {
+ float_raise(float_flag_divbyzero, fpst);
+ return float64_set_sign(float64_infinity, float64_is_neg(f64));
+ } else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
+ /* Abs(value) < 2.0^-1024 */
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
+ if (round_to_inf(fpst, f64_sign)) {
+ return float64_set_sign(float64_infinity, f64_sign);
+ } else {
+ return float64_set_sign(float64_maxnorm, f64_sign);
+ }
+ } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
+ float_raise(float_flag_underflow, fpst);
+ return float64_set_sign(float64_zero, float64_is_neg(f64));
+ }
+
+ f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac);
+
+ /* result = sign : result_exp<10:0> : fraction<51:0>; */
+ f64_val = deposit64(0, 63, 1, f64_sign);
+ f64_val = deposit64(f64_val, 52, 11, f64_exp);
+ f64_val = deposit64(f64_val, 0, 52, f64_frac);
+ return make_float64(f64_val);
+}
+
+/* The algorithm that must be used to calculate the estimate
+ * is specified by the ARM ARM.
+ */
+
+static int do_recip_sqrt_estimate(int a)
+{
+ int b, estimate;
+
+ assert(128 <= a && a < 512);
+ if (a < 256) {
+ a = a * 2 + 1;
+ } else {
+ a = (a >> 1) << 1;
+ a = (a + 1) * 2;
+ }
+ b = 512;
+ while (a * (b + 1) * (b + 1) < (1 << 28)) {
+ b += 1;
+ }
+ estimate = (b + 1) / 2;
+ assert(256 <= estimate && estimate < 512);
+
+ return estimate;
+}
+
+
+static uint64_t recip_sqrt_estimate(int *exp , int exp_off, uint64_t frac)
+{
+ int estimate;
+ uint32_t scaled;
+
+ if (*exp == 0) {
+ while (extract64(frac, 51, 1) == 0) {
+ frac = frac << 1;
+ *exp -= 1;
+ }
+ frac = extract64(frac, 0, 51) << 1;
+ }
+
+ if (*exp & 1) {
+ /* scaled = UInt('01':fraction<51:45>) */
+ scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
+ } else {
+ /* scaled = UInt('1':fraction<51:44>) */
+ scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
+ }
+ estimate = do_recip_sqrt_estimate(scaled);
+
+ *exp = (exp_off - *exp) / 2;
+ return extract64(estimate, 0, 8) << 44;
+}
+
+uint32_t HELPER(rsqrte_f16)(uint32_t input, void *fpstp)
+{
+ float_status *s = fpstp;
+ float16 f16 = float16_squash_input_denormal(input, s);
+ uint16_t val = float16_val(f16);
+ bool f16_sign = float16_is_neg(f16);
+ int f16_exp = extract32(val, 10, 5);
+ uint16_t f16_frac = extract32(val, 0, 10);
+ uint64_t f64_frac;
+
+ if (float16_is_any_nan(f16)) {
+ float16 nan = f16;
+ if (float16_is_signaling_nan(f16, s)) {
+ float_raise(float_flag_invalid, s);
+ nan = float16_silence_nan(f16, s);
+ }
+ if (s->default_nan_mode) {
+ nan = float16_default_nan(s);
+ }
+ return nan;
+ } else if (float16_is_zero(f16)) {
+ float_raise(float_flag_divbyzero, s);
+ return float16_set_sign(float16_infinity, f16_sign);
+ } else if (f16_sign) {
+ float_raise(float_flag_invalid, s);
+ return float16_default_nan(s);
+ } else if (float16_is_infinity(f16)) {
+ return float16_zero;
+ }
+
+ /* Scale and normalize to a double-precision value between 0.25 and 1.0,
+ * preserving the parity of the exponent. */
+
+ f64_frac = ((uint64_t) f16_frac) << (52 - 10);
+
+ f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac);
+
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
+ val = deposit32(0, 15, 1, f16_sign);
+ val = deposit32(val, 10, 5, f16_exp);
+ val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
+ return make_float16(val);
+}
+
+float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
+{
+ float_status *s = fpstp;
+ float32 f32 = float32_squash_input_denormal(input, s);
+ uint32_t val = float32_val(f32);
+ uint32_t f32_sign = float32_is_neg(f32);
+ int f32_exp = extract32(val, 23, 8);
+ uint32_t f32_frac = extract32(val, 0, 23);
+ uint64_t f64_frac;
+
+ if (float32_is_any_nan(f32)) {
+ float32 nan = f32;
+ if (float32_is_signaling_nan(f32, s)) {
+ float_raise(float_flag_invalid, s);
+ nan = float32_silence_nan(f32, s);
+ }
+ if (s->default_nan_mode) {
+ nan = float32_default_nan(s);
+ }
+ return nan;
+ } else if (float32_is_zero(f32)) {
+ float_raise(float_flag_divbyzero, s);
+ return float32_set_sign(float32_infinity, float32_is_neg(f32));
+ } else if (float32_is_neg(f32)) {
+ float_raise(float_flag_invalid, s);
+ return float32_default_nan(s);
+ } else if (float32_is_infinity(f32)) {
+ return float32_zero;
+ }
+
+ /* Scale and normalize to a double-precision value between 0.25 and 1.0,
+ * preserving the parity of the exponent. */
+
+ f64_frac = ((uint64_t) f32_frac) << 29;
+
+ f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac);
+
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(15) */
+ val = deposit32(0, 31, 1, f32_sign);
+ val = deposit32(val, 23, 8, f32_exp);
+ val = deposit32(val, 15, 8, extract64(f64_frac, 52 - 8, 8));
+ return make_float32(val);
+}
+
+float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
+{
+ float_status *s = fpstp;
+ float64 f64 = float64_squash_input_denormal(input, s);
+ uint64_t val = float64_val(f64);
+ bool f64_sign = float64_is_neg(f64);
+ int f64_exp = extract64(val, 52, 11);
+ uint64_t f64_frac = extract64(val, 0, 52);
+
+ if (float64_is_any_nan(f64)) {
+ float64 nan = f64;
+ if (float64_is_signaling_nan(f64, s)) {
+ float_raise(float_flag_invalid, s);
+ nan = float64_silence_nan(f64, s);
+ }
+ if (s->default_nan_mode) {
+ nan = float64_default_nan(s);
+ }
+ return nan;
+ } else if (float64_is_zero(f64)) {
+ float_raise(float_flag_divbyzero, s);
+ return float64_set_sign(float64_infinity, float64_is_neg(f64));
+ } else if (float64_is_neg(f64)) {
+ float_raise(float_flag_invalid, s);
+ return float64_default_nan(s);
+ } else if (float64_is_infinity(f64)) {
+ return float64_zero;
+ }
+
+ f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac);
+
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
+ val = deposit64(0, 61, 1, f64_sign);
+ val = deposit64(val, 52, 11, f64_exp);
+ val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
+ return make_float64(val);
+}
+
+uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
+{
+ /* float_status *s = fpstp; */
+ int input, estimate;
+
+ if ((a & 0x80000000) == 0) {
+ return 0xffffffff;
+ }
+
+ input = extract32(a, 23, 9);
+ estimate = recip_estimate(input);
+
+ return deposit32(0, (32 - 9), 9, estimate);
+}
+
+uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
+{
+ int estimate;
+
+ if ((a & 0xc0000000) == 0) {
+ return 0xffffffff;
+ }
+
+ estimate = do_recip_sqrt_estimate(extract32(a, 23, 9));
+
+ return deposit32(0, 23, 9, estimate);
+}
+
+/* VFPv4 fused multiply-accumulate */
+float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
+{
+ float_status *fpst = fpstp;
+ return float32_muladd(a, b, c, 0, fpst);
+}
+
+float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
+{
+ float_status *fpst = fpstp;
+ return float64_muladd(a, b, c, 0, fpst);
+}
+
+/* ARMv8 round to integral */
+float32 HELPER(rints_exact)(float32 x, void *fp_status)
+{
+ return float32_round_to_int(x, fp_status);
+}
+
+float64 HELPER(rintd_exact)(float64 x, void *fp_status)
+{
+ return float64_round_to_int(x, fp_status);
+}
+
+float32 HELPER(rints)(float32 x, void *fp_status)
+{
+ int old_flags = get_float_exception_flags(fp_status), new_flags;
+ float32 ret;
+
+ ret = float32_round_to_int(x, fp_status);
+
+ /* Suppress any inexact exceptions the conversion produced */
+ if (!(old_flags & float_flag_inexact)) {
+ new_flags = get_float_exception_flags(fp_status);
+ set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
+ }
+
+ return ret;
+}
+
+float64 HELPER(rintd)(float64 x, void *fp_status)
+{
+ int old_flags = get_float_exception_flags(fp_status), new_flags;
+ float64 ret;
+
+ ret = float64_round_to_int(x, fp_status);
+
+ new_flags = get_float_exception_flags(fp_status);
+
+ /* Suppress any inexact exceptions the conversion produced */
+ if (!(old_flags & float_flag_inexact)) {
+ new_flags = get_float_exception_flags(fp_status);
+ set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
+ }
+
+ return ret;
+}
+
+/* Convert ARM rounding mode to softfloat */
+int arm_rmode_to_sf(int rmode)
+{
+ switch (rmode) {
+ case FPROUNDING_TIEAWAY:
+ rmode = float_round_ties_away;
+ break;
+ case FPROUNDING_ODD:
+ /* FIXME: add support for TIEAWAY and ODD */
+ qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
+ rmode);
+ /* fall through for now */
+ case FPROUNDING_TIEEVEN:
+ default:
+ rmode = float_round_nearest_even;
+ break;
+ case FPROUNDING_POSINF:
+ rmode = float_round_up;
+ break;
+ case FPROUNDING_NEGINF:
+ rmode = float_round_down;
+ break;
+ case FPROUNDING_ZERO:
+ rmode = float_round_to_zero;
+ break;
+ }
+ return rmode;
+}
+
+/*
+ * Implement float64 to int32_t conversion without saturation;
+ * the result is supplied modulo 2^32.
+ */
+uint64_t HELPER(fjcvtzs)(float64 value, void *vstatus)
+{
+ float_status *status = vstatus;
+ uint32_t exp, sign;
+ uint64_t frac;
+ uint32_t inexact = 1; /* !Z */
+
+ sign = extract64(value, 63, 1);
+ exp = extract64(value, 52, 11);
+ frac = extract64(value, 0, 52);
+
+ if (exp == 0) {
+ /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */
+ inexact = sign;
+ if (frac != 0) {
+ if (status->flush_inputs_to_zero) {
+ float_raise(float_flag_input_denormal, status);
+ } else {
+ float_raise(float_flag_inexact, status);
+ inexact = 1;
+ }
+ }
+ frac = 0;
+ } else if (exp == 0x7ff) {
+ /* This operation raises Invalid for both NaN and overflow (Inf). */
+ float_raise(float_flag_invalid, status);
+ frac = 0;
+ } else {
+ int true_exp = exp - 1023;
+ int shift = true_exp - 52;
+
+ /* Restore implicit bit. */
+ frac |= 1ull << 52;
+
+ /* Shift the fraction into place. */
+ if (shift >= 0) {
+ /* The number is so large we must shift the fraction left. */
+ if (shift >= 64) {
+ /* The fraction is shifted out entirely. */
+ frac = 0;
+ } else {
+ frac <<= shift;
+ }
+ } else if (shift > -64) {
+ /* Normal case -- shift right and notice if bits shift out. */
+ inexact = (frac << (64 + shift)) != 0;
+ frac >>= -shift;
+ } else {
+ /* The fraction is shifted out entirely. */
+ frac = 0;
+ }
+
+ /* Notice overflow or inexact exceptions. */
+ if (true_exp > 31 || frac > (sign ? 0x80000000ull : 0x7fffffff)) {
+ /* Overflow, for which this operation raises invalid. */
+ float_raise(float_flag_invalid, status);
+ inexact = 1;
+ } else if (inexact) {
+ float_raise(float_flag_inexact, status);
+ }
+
+ /* Honor the sign. */
+ if (sign) {
+ frac = -frac;
+ }
+ }
+
+ /* Pack the result and the env->ZF representation of Z together. */
+ return deposit64(frac, 32, 32, inexact);
+}
+
+uint32_t HELPER(vjcvt)(float64 value, CPUARMState *env)
+{
+ uint64_t pair = HELPER(fjcvtzs)(value, &env->vfp.fp_status);
+ uint32_t result = pair;
+ uint32_t z = (pair >> 32) == 0;
+
+ /* Store Z, clear NCV, in FPSCR.NZCV. */
+ env->vfp.xregs[ARM_VFP_FPSCR]
+ = (env->vfp.xregs[ARM_VFP_FPSCR] & ~CPSR_NZCV) | (z * CPSR_Z);
+
+ return result;
+}
obj-y += translate.o helper.o cpu.o op_helper.o gdbstub.o mem_helper.o
obj-y += int_helper.o
obj-$(CONFIG_SOFTMMU) += machine.o
+
+DECODETREE = $(SRC_PATH)/scripts/decodetree.py
+
+target/hppa/decode.inc.c: $(SRC_PATH)/target/hppa/insns.decode $(DECODETREE)
+ $(call quiet-command,\
+ $(PYTHON) $(DECODETREE) -o $@ $<, "GEN", $(TARGET_DIR)$@)
+
+target/hppa/translate.o: target/hppa/decode.inc.c
case 65 ... 127:
{
uint64_t *fr = &env->fr[(n - 64) / 2];
- *fr = deposit64(*fr, val, (n & 1 ? 0 : 32), 32);
+ *fr = deposit64(*fr, (n & 1 ? 0 : 32), 32, val);
}
break;
default:
--- /dev/null
+#
+# HPPA instruction decode definitions.
+#
+# Copyright (c) 2018 Richard Henderson <rth@twiddle.net>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+####
+# Field definitions
+####
+
+%assemble_sr3 13:1 14:2
+%assemble_sr3x 13:1 14:2 !function=expand_sr3x
+
+%assemble_11a 0:s1 4:10 !function=expand_shl3
+%assemble_12 0:s1 2:1 3:10 !function=expand_shl2
+%assemble_12a 0:s1 3:11 !function=expand_shl2
+%assemble_17 0:s1 16:5 2:1 3:10 !function=expand_shl2
+%assemble_22 0:s1 16:10 2:1 3:10 !function=expand_shl2
+
+%assemble_21 0:s1 1:11 14:2 16:5 12:2 !function=expand_shl11
+
+%lowsign_11 0:s1 1:10
+%lowsign_14 0:s1 1:13
+
+%sm_imm 16:10 !function=expand_sm_imm
+
+%rm64 1:1 16:5
+%rt64 6:1 0:5
+%ra64 7:1 21:5
+%rb64 12:1 16:5
+%rc64 8:1 13:3 9:2
+%rc32 13:3 9:2
+
+%im5_0 0:s1 1:4
+%im5_16 16:s1 17:4
+%ma_to_m 5:1 13:1 !function=ma_to_m
+%ma2_to_m 2:2 !function=ma_to_m
+%pos_to_m 0:1 !function=pos_to_m
+%neg_to_m 0:1 !function=neg_to_m
+%a_to_m 2:1 !function=neg_to_m
+
+####
+# Argument set definitions
+####
+
+# All insns that need to form a virtual address should use this set.
+&ldst t b x disp sp m scale size
+
+&rr_cf t r cf
+&rrr_cf t r1 r2 cf
+&rrr_cf_sh t r1 r2 cf sh
+&rri_cf t r i cf
+
+&rrb_c_f disp n c f r1 r2
+&rib_c_f disp n c f r i
+
+####
+# Format definitions
+####
+
+@rr_cf ...... r:5 ..... cf:4 ....... t:5 &rr_cf
+@rrr_cf ...... r2:5 r1:5 cf:4 ....... t:5 &rrr_cf
+@rrr_cf_sh ...... r2:5 r1:5 cf:4 .... sh:2 . t:5 &rrr_cf_sh
+@rrr_cf_sh0 ...... r2:5 r1:5 cf:4 ....... t:5 &rrr_cf_sh sh=0
+@rri_cf ...... r:5 t:5 cf:4 . ........... &rri_cf i=%lowsign_11
+
+@rrb_cf ...... r2:5 r1:5 c:3 ........... n:1 . \
+ &rrb_c_f disp=%assemble_12
+@rib_cf ...... r:5 ..... c:3 ........... n:1 . \
+ &rib_c_f disp=%assemble_12 i=%im5_16
+
+####
+# System
+####
+
+break 000000 ----- ----- --- 00000000 -----
+
+mtsp 000000 ----- r:5 ... 11000001 00000 sp=%assemble_sr3
+mtctl 000000 t:5 r:5 --- 11000010 00000
+mtsarcm 000000 01011 r:5 --- 11000110 00000
+mtsm 000000 00000 r:5 000 11000011 00000
+
+mfia 000000 ----- 00000 --- 10100101 t:5
+mfsp 000000 ----- 00000 ... 00100101 t:5 sp=%assemble_sr3
+mfctl 000000 r:5 00000- e:1 -01000101 t:5
+
+sync 000000 ----- ----- 000 00100000 00000 # sync, syncdma
+
+ldsid 000000 b:5 ----- sp:2 0 10000101 t:5
+
+rsm 000000 .......... 000 01110011 t:5 i=%sm_imm
+ssm 000000 .......... 000 01101011 t:5 i=%sm_imm
+
+rfi 000000 ----- ----- --- 01100000 00000
+rfi_r 000000 ----- ----- --- 01100101 00000
+
+# These are artificial instructions used by QEMU firmware.
+# They are allocated from the unassigned instruction space.
+halt 1111 1111 1111 1101 1110 1010 1101 0000
+reset 1111 1111 1111 1101 1110 1010 1101 0001
+
+####
+# Memory Management
+####
+
+@addrx ...... b:5 x:5 .. ........ m:1 ..... \
+ &ldst disp=0 scale=0 t=0 sp=0 size=0
+
+nop 000001 ----- ----- -- 11001010 0 ----- # fdc, disp
+nop_addrx 000001 ..... ..... -- 01001010 . ----- @addrx # fdc, index
+nop_addrx 000001 ..... ..... -- 01001011 . ----- @addrx # fdce
+nop_addrx 000001 ..... ..... --- 0001010 . ----- @addrx # fic 0x0a
+nop_addrx 000001 ..... ..... -- 01001111 . 00000 @addrx # fic 0x4f
+nop_addrx 000001 ..... ..... --- 0001011 . ----- @addrx # fice
+nop_addrx 000001 ..... ..... -- 01001110 . 00000 @addrx # pdc
+
+probe 000001 b:5 ri:5 sp:2 imm:1 100011 write:1 0 t:5
+
+ixtlbx 000001 b:5 r:5 sp:2 0100000 addr:1 0 00000 data=1
+ixtlbx 000001 b:5 r:5 ... 000000 addr:1 0 00000 \
+ sp=%assemble_sr3x data=0
+
+pxtlbx 000001 b:5 x:5 sp:2 0100100 local:1 m:1 ----- data=1
+pxtlbx 000001 b:5 x:5 ... 000100 local:1 m:1 ----- \
+ sp=%assemble_sr3x data=0
+
+lpa 000001 b:5 x:5 sp:2 01001101 m:1 t:5 \
+ &ldst disp=0 scale=0 size=0
+
+lci 000001 ----- ----- -- 01001100 0 t:5
+
+####
+# Arith/Log
+####
+
+andcm 000010 ..... ..... .... 000000 0 ..... @rrr_cf
+and 000010 ..... ..... .... 001000 0 ..... @rrr_cf
+or 000010 ..... ..... .... 001001 0 ..... @rrr_cf
+xor 000010 ..... ..... .... 001010 0 ..... @rrr_cf
+uxor 000010 ..... ..... .... 001110 0 ..... @rrr_cf
+ds 000010 ..... ..... .... 010001 0 ..... @rrr_cf
+cmpclr 000010 ..... ..... .... 100010 0 ..... @rrr_cf
+uaddcm 000010 ..... ..... .... 100110 0 ..... @rrr_cf
+uaddcm_tc 000010 ..... ..... .... 100111 0 ..... @rrr_cf
+dcor 000010 ..... 00000 .... 101110 0 ..... @rr_cf
+dcor_i 000010 ..... 00000 .... 101111 0 ..... @rr_cf
+
+add 000010 ..... ..... .... 0110.. 0 ..... @rrr_cf_sh
+add_l 000010 ..... ..... .... 1010.. 0 ..... @rrr_cf_sh
+add_tsv 000010 ..... ..... .... 1110.. 0 ..... @rrr_cf_sh
+add_c 000010 ..... ..... .... 011100 0 ..... @rrr_cf_sh0
+add_c_tsv 000010 ..... ..... .... 111100 0 ..... @rrr_cf_sh0
+
+sub 000010 ..... ..... .... 010000 0 ..... @rrr_cf
+sub_tsv 000010 ..... ..... .... 110000 0 ..... @rrr_cf
+sub_tc 000010 ..... ..... .... 010011 0 ..... @rrr_cf
+sub_tsv_tc 000010 ..... ..... .... 110011 0 ..... @rrr_cf
+sub_b 000010 ..... ..... .... 010100 0 ..... @rrr_cf
+sub_b_tsv 000010 ..... ..... .... 110100 0 ..... @rrr_cf
+
+ldil 001000 t:5 ..................... i=%assemble_21
+addil 001010 r:5 ..................... i=%assemble_21
+ldo 001101 b:5 t:5 -- .............. i=%lowsign_14
+
+addi 101101 ..... ..... .... 0 ........... @rri_cf
+addi_tsv 101101 ..... ..... .... 1 ........... @rri_cf
+addi_tc 101100 ..... ..... .... 0 ........... @rri_cf
+addi_tc_tsv 101100 ..... ..... .... 1 ........... @rri_cf
+
+subi 100101 ..... ..... .... 0 ........... @rri_cf
+subi_tsv 100101 ..... ..... .... 1 ........... @rri_cf
+
+cmpiclr 100100 ..... ..... .... 0 ........... @rri_cf
+
+####
+# Index Mem
+####
+
+@ldstx ...... b:5 x:5 sp:2 scale:1 ....... m:1 t:5 &ldst disp=0
+@ldim5 ...... b:5 ..... sp:2 ......... t:5 \
+ &ldst disp=%im5_16 x=0 scale=0 m=%ma_to_m
+@stim5 ...... b:5 t:5 sp:2 ......... ..... \
+ &ldst disp=%im5_0 x=0 scale=0 m=%ma_to_m
+
+ld 000011 ..... ..... .. . 1 -- 00 size:2 ...... @ldim5
+ld 000011 ..... ..... .. . 0 -- 00 size:2 ...... @ldstx
+st 000011 ..... ..... .. . 1 -- 10 size:2 ...... @stim5
+ldc 000011 ..... ..... .. . 1 -- 0111 ...... @ldim5 size=2
+ldc 000011 ..... ..... .. . 0 -- 0111 ...... @ldstx size=2
+lda 000011 ..... ..... .. . 1 -- 0110 ...... @ldim5 size=2
+lda 000011 ..... ..... .. . 0 -- 0110 ...... @ldstx size=2
+sta 000011 ..... ..... .. . 1 -- 1110 ...... @stim5 size=2
+stby 000011 b:5 r:5 sp:2 a:1 1 -- 1100 m:1 ..... disp=%im5_0
+
+@fldstwx ...... b:5 x:5 sp:2 scale:1 ....... m:1 ..... \
+ &ldst t=%rt64 disp=0 size=2
+@fldstwi ...... b:5 ..... sp:2 . ....... . ..... \
+ &ldst t=%rt64 disp=%im5_16 m=%ma_to_m x=0 scale=0 size=2
+
+fldw 001001 ..... ..... .. . 0 -- 000 . . ..... @fldstwx
+fldw 001001 ..... ..... .. . 1 -- 000 . . ..... @fldstwi
+fstw 001001 ..... ..... .. . 0 -- 100 . . ..... @fldstwx
+fstw 001001 ..... ..... .. . 1 -- 100 . . ..... @fldstwi
+
+@fldstdx ...... b:5 x:5 sp:2 scale:1 ....... m:1 t:5 \
+ &ldst disp=0 size=3
+@fldstdi ...... b:5 ..... sp:2 . ....... . t:5 \
+ &ldst disp=%im5_16 m=%ma_to_m x=0 scale=0 size=3
+
+fldd 001011 ..... ..... .. . 0 -- 000 0 . ..... @fldstdx
+fldd 001011 ..... ..... .. . 1 -- 000 0 . ..... @fldstdi
+fstd 001011 ..... ..... .. . 0 -- 100 0 . ..... @fldstdx
+fstd 001011 ..... ..... .. . 1 -- 100 0 . ..... @fldstdi
+
+####
+# Offset Mem
+####
+
+@ldstim14 ...... b:5 t:5 sp:2 .............. \
+ &ldst disp=%lowsign_14 x=0 scale=0 m=0
+@ldstim14m ...... b:5 t:5 sp:2 .............. \
+ &ldst disp=%lowsign_14 x=0 scale=0 m=%neg_to_m
+@ldstim12m ...... b:5 t:5 sp:2 .............. \
+ &ldst disp=%assemble_12a x=0 scale=0 m=%pos_to_m
+
+# LDB, LDH, LDW, LDWM
+ld 010000 ..... ..... .. .............. @ldstim14 size=0
+ld 010001 ..... ..... .. .............. @ldstim14 size=1
+ld 010010 ..... ..... .. .............. @ldstim14 size=2
+ld 010011 ..... ..... .. .............. @ldstim14m size=2
+ld 010111 ..... ..... .. ...........10. @ldstim12m size=2
+
+# STB, STH, STW, STWM
+st 011000 ..... ..... .. .............. @ldstim14 size=0
+st 011001 ..... ..... .. .............. @ldstim14 size=1
+st 011010 ..... ..... .. .............. @ldstim14 size=2
+st 011011 ..... ..... .. .............. @ldstim14m size=2
+st 011111 ..... ..... .. ...........10. @ldstim12m size=2
+
+fldw 010110 b:5 ..... sp:2 .............. \
+ &ldst disp=%assemble_12a t=%rm64 m=%a_to_m x=0 scale=0 size=2
+fldw 010111 b:5 ..... sp:2 ...........0.. \
+ &ldst disp=%assemble_12a t=%rm64 m=0 x=0 scale=0 size=2
+
+fstw 011110 b:5 ..... sp:2 .............. \
+ &ldst disp=%assemble_12a t=%rm64 m=%a_to_m x=0 scale=0 size=2
+fstw 011111 b:5 ..... sp:2 ...........0.. \
+ &ldst disp=%assemble_12a t=%rm64 m=0 x=0 scale=0 size=2
+
+fldd 010100 b:5 t:5 sp:2 .......... .. 1 . \
+ &ldst disp=%assemble_11a m=%ma2_to_m x=0 scale=0 size=3
+
+fstd 011100 b:5 t:5 sp:2 .......... .. 1 . \
+ &ldst disp=%assemble_11a m=%ma2_to_m x=0 scale=0 size=3
+
+####
+# Floating-point Multiply Add
+####
+
+&mpyadd rm1 rm2 ta ra tm
+@mpyadd ...... rm1:5 rm2:5 ta:5 ra:5 . tm:5 &mpyadd
+
+fmpyadd_f 000110 ..... ..... ..... ..... 0 ..... @mpyadd
+fmpyadd_d 000110 ..... ..... ..... ..... 1 ..... @mpyadd
+fmpysub_f 100110 ..... ..... ..... ..... 0 ..... @mpyadd
+fmpysub_d 100110 ..... ..... ..... ..... 1 ..... @mpyadd
+
+####
+# Conditional Branches
+####
+
+bb_sar 110000 00000 r:5 c:1 10 ........... n:1 . disp=%assemble_12
+bb_imm 110001 p:5 r:5 c:1 10 ........... n:1 . disp=%assemble_12
+
+movb 110010 ..... ..... ... ........... . . @rrb_cf f=0
+movbi 110011 ..... ..... ... ........... . . @rib_cf f=0
+
+cmpb 100000 ..... ..... ... ........... . . @rrb_cf f=0
+cmpb 100010 ..... ..... ... ........... . . @rrb_cf f=1
+cmpbi 100001 ..... ..... ... ........... . . @rib_cf f=0
+cmpbi 100011 ..... ..... ... ........... . . @rib_cf f=1
+
+addb 101000 ..... ..... ... ........... . . @rrb_cf f=0
+addb 101010 ..... ..... ... ........... . . @rrb_cf f=1
+addbi 101001 ..... ..... ... ........... . . @rib_cf f=0
+addbi 101011 ..... ..... ... ........... . . @rib_cf f=1
+
+####
+# Shift, Extract, Deposit
+####
+
+shrpw_sar 110100 r2:5 r1:5 c:3 00 0 00000 t:5
+shrpw_imm 110100 r2:5 r1:5 c:3 01 0 cpos:5 t:5
+
+extrw_sar 110100 r:5 t:5 c:3 10 se:1 00000 clen:5
+extrw_imm 110100 r:5 t:5 c:3 11 se:1 pos:5 clen:5
+
+depw_sar 110101 t:5 r:5 c:3 00 nz:1 00000 clen:5
+depw_imm 110101 t:5 r:5 c:3 01 nz:1 cpos:5 clen:5
+depwi_sar 110101 t:5 ..... c:3 10 nz:1 00000 clen:5 i=%im5_16
+depwi_imm 110101 t:5 ..... c:3 11 nz:1 cpos:5 clen:5 i=%im5_16
+
+####
+# Branch External
+####
+
+&BE b l n disp sp
+@be ...... b:5 ..... ... ........... n:1 . \
+ &BE disp=%assemble_17 sp=%assemble_sr3
+
+be 111000 ..... ..... ... ........... . . @be l=0
+be 111001 ..... ..... ... ........... . . @be l=31
+
+####
+# Branch
+####
+
+&BL l n disp
+@bl ...... l:5 ..... ... ........... n:1 . &BL disp=%assemble_17
+
+# B,L and B,L,PUSH
+bl 111010 ..... ..... 000 ........... . . @bl
+bl 111010 ..... ..... 100 ........... . . @bl
+# B,L (long displacement)
+bl 111010 ..... ..... 101 ........... n:1 . &BL l=2 \
+ disp=%assemble_22
+b_gate 111010 ..... ..... 001 ........... . . @bl
+blr 111010 l:5 x:5 010 00000000000 n:1 0
+bv 111010 b:5 x:5 110 00000000000 n:1 0
+bve 111010 b:5 00000 110 10000000000 n:1 - l=0
+bve 111010 b:5 00000 111 10000000000 n:1 - l=2
+
+####
+# FP Fused Multiple-Add
+####
+
+fmpyfadd_f 101110 ..... ..... ... . 0 ... . . neg:1 ..... \
+ rm1=%ra64 rm2=%rb64 ra3=%rc64 t=%rt64
+fmpyfadd_d 101110 rm1:5 rm2:5 ... 0 1 ..0 0 0 neg:1 t:5 ra3=%rc32
+
+####
+# FP operations
+####
+
+&fclass01 r t
+&fclass2 r1 r2 c y
+&fclass3 r1 r2 t
+
+@f0c_0 ...... r:5 00000 ..... 00 000 0 t:5 &fclass01
+@f0c_1 ...... r:5 000.. ..... 01 000 0 t:5 &fclass01
+@f0c_2 ...... r1:5 r2:5 y:3 .. 10 000 . c:5 &fclass2
+@f0c_3 ...... r1:5 r2:5 ..... 11 000 0 t:5 &fclass3
+
+@f0e_f_0 ...... ..... 00000 ... 0 0 000 .. 0 ..... \
+ &fclass01 r=%ra64 t=%rt64
+@f0e_d_0 ...... r:5 00000 ... 0 1 000 00 0 t:5 &fclass01
+
+@f0e_ff_1 ...... ..... 000 ... 0000 010 .. 0 ..... \
+ &fclass01 r=%ra64 t=%rt64
+@f0e_fd_1 ...... ..... 000 ... 0100 010 .0 0 t:5 &fclass01 r=%ra64
+@f0e_df_1 ...... r:5 000 ... 0001 010 0. 0 ..... &fclass01 t=%rt64
+@f0e_dd_1 ...... r:5 000 ... 0101 010 00 0 t:5 &fclass01
+
+@f0e_f_2 ...... ..... ..... y:3 .0 100 .00 c:5 \
+ &fclass2 r1=%ra64 r2=%rb64
+@f0e_d_2 ...... r1:5 r2:5 y:3 01 100 000 c:5 &fclass2
+
+@f0e_f_3 ...... ..... ..... ... .0 110 ..0 ..... \
+ &fclass3 r1=%ra64 r2=%rb64 t=%rt64
+@f0e_d_3 ...... r1:5 r2:5 ... 01 110 000 t:5
+
+# Floating point class 0
+
+# FID. With r = t = 0, which via fcpy puts 0 into fr0.
+# This is machine/revision = 0, which is reserved for simulator.
+fcpy_f 001100 00000 00000 00000 000000 00000 \
+ &fclass01 r=0 t=0
+
+fcpy_f 001100 ..... ..... 010 00 ...... ..... @f0c_0
+fabs_f 001100 ..... ..... 011 00 ...... ..... @f0c_0
+fsqrt_f 001100 ..... ..... 100 00 ...... ..... @f0c_0
+frnd_f 001100 ..... ..... 101 00 ...... ..... @f0c_0
+fneg_f 001100 ..... ..... 110 00 ...... ..... @f0c_0
+fnegabs_f 001100 ..... ..... 111 00 ...... ..... @f0c_0
+
+fcpy_d 001100 ..... ..... 010 01 ...... ..... @f0c_0
+fabs_d 001100 ..... ..... 011 01 ...... ..... @f0c_0
+fsqrt_d 001100 ..... ..... 100 01 ...... ..... @f0c_0
+frnd_d 001100 ..... ..... 101 01 ...... ..... @f0c_0
+fneg_d 001100 ..... ..... 110 01 ...... ..... @f0c_0
+fnegabs_d 001100 ..... ..... 111 01 ...... ..... @f0c_0
+
+fcpy_f 001110 ..... ..... 010 ........ ..... @f0e_f_0
+fabs_f 001110 ..... ..... 011 ........ ..... @f0e_f_0
+fsqrt_f 001110 ..... ..... 100 ........ ..... @f0e_f_0
+frnd_f 001110 ..... ..... 101 ........ ..... @f0e_f_0
+fneg_f 001110 ..... ..... 110 ........ ..... @f0e_f_0
+fnegabs_f 001110 ..... ..... 111 ........ ..... @f0e_f_0
+
+fcpy_d 001110 ..... ..... 010 ........ ..... @f0e_d_0
+fabs_d 001110 ..... ..... 011 ........ ..... @f0e_d_0
+fsqrt_d 001110 ..... ..... 100 ........ ..... @f0e_d_0
+frnd_d 001110 ..... ..... 101 ........ ..... @f0e_d_0
+fneg_d 001110 ..... ..... 110 ........ ..... @f0e_d_0
+fnegabs_d 001110 ..... ..... 111 ........ ..... @f0e_d_0
+
+# Floating point class 1
+
+# float/float
+fcnv_d_f 001100 ..... ... 000 00 01 ...... ..... @f0c_1
+fcnv_f_d 001100 ..... ... 000 01 00 ...... ..... @f0c_1
+
+fcnv_d_f 001110 ..... ... 000 .......... ..... @f0e_df_1
+fcnv_f_d 001110 ..... ... 000 .......... ..... @f0e_fd_1
+
+# int/float
+fcnv_w_f 001100 ..... ... 001 00 00 ...... ..... @f0c_1
+fcnv_q_f 001100 ..... ... 001 00 01 ...... ..... @f0c_1
+fcnv_w_d 001100 ..... ... 001 01 00 ...... ..... @f0c_1
+fcnv_q_d 001100 ..... ... 001 01 01 ...... ..... @f0c_1
+
+fcnv_w_f 001110 ..... ... 001 .......... ..... @f0e_ff_1
+fcnv_q_f 001110 ..... ... 001 .......... ..... @f0e_df_1
+fcnv_w_d 001110 ..... ... 001 .......... ..... @f0e_fd_1
+fcnv_q_d 001110 ..... ... 001 .......... ..... @f0e_dd_1
+
+# float/int
+fcnv_f_w 001100 ..... ... 010 00 00 ...... ..... @f0c_1
+fcnv_d_w 001100 ..... ... 010 00 01 ...... ..... @f0c_1
+fcnv_f_q 001100 ..... ... 010 01 00 ...... ..... @f0c_1
+fcnv_d_q 001100 ..... ... 010 01 01 ...... ..... @f0c_1
+
+fcnv_f_w 001110 ..... ... 010 .......... ..... @f0e_ff_1
+fcnv_d_w 001110 ..... ... 010 .......... ..... @f0e_df_1
+fcnv_f_q 001110 ..... ... 010 .......... ..... @f0e_fd_1
+fcnv_d_q 001110 ..... ... 010 .......... ..... @f0e_dd_1
+
+# float/int truncate
+fcnv_t_f_w 001100 ..... ... 011 00 00 ...... ..... @f0c_1
+fcnv_t_d_w 001100 ..... ... 011 00 01 ...... ..... @f0c_1
+fcnv_t_f_q 001100 ..... ... 011 01 00 ...... ..... @f0c_1
+fcnv_t_d_q 001100 ..... ... 011 01 01 ...... ..... @f0c_1
+
+fcnv_t_f_w 001110 ..... ... 011 .......... ..... @f0e_ff_1
+fcnv_t_d_w 001110 ..... ... 011 .......... ..... @f0e_df_1
+fcnv_t_f_q 001110 ..... ... 011 .......... ..... @f0e_fd_1
+fcnv_t_d_q 001110 ..... ... 011 .......... ..... @f0e_dd_1
+
+# uint/float
+fcnv_uw_f 001100 ..... ... 101 00 00 ...... ..... @f0c_1
+fcnv_uq_f 001100 ..... ... 101 00 01 ...... ..... @f0c_1
+fcnv_uw_d 001100 ..... ... 101 01 00 ...... ..... @f0c_1
+fcnv_uq_d 001100 ..... ... 101 01 01 ...... ..... @f0c_1
+
+fcnv_uw_f 001110 ..... ... 101 .......... ..... @f0e_ff_1
+fcnv_uq_f 001110 ..... ... 101 .......... ..... @f0e_df_1
+fcnv_uw_d 001110 ..... ... 101 .......... ..... @f0e_fd_1
+fcnv_uq_d 001110 ..... ... 101 .......... ..... @f0e_dd_1
+
+# float/int
+fcnv_f_uw 001100 ..... ... 110 00 00 ...... ..... @f0c_1
+fcnv_d_uw 001100 ..... ... 110 00 01 ...... ..... @f0c_1
+fcnv_f_uq 001100 ..... ... 110 01 00 ...... ..... @f0c_1
+fcnv_d_uq 001100 ..... ... 110 01 01 ...... ..... @f0c_1
+
+fcnv_f_uw 001110 ..... ... 110 .......... ..... @f0e_ff_1
+fcnv_d_uw 001110 ..... ... 110 .......... ..... @f0e_df_1
+fcnv_f_uq 001110 ..... ... 110 .......... ..... @f0e_fd_1
+fcnv_d_uq 001110 ..... ... 110 .......... ..... @f0e_dd_1
+
+# float/int truncate
+fcnv_t_f_uw 001100 ..... ... 111 00 00 ...... ..... @f0c_1
+fcnv_t_d_uw 001100 ..... ... 111 00 01 ...... ..... @f0c_1
+fcnv_t_f_uq 001100 ..... ... 111 01 00 ...... ..... @f0c_1
+fcnv_t_d_uq 001100 ..... ... 111 01 01 ...... ..... @f0c_1
+
+fcnv_t_f_uw 001110 ..... ... 111 .......... ..... @f0e_ff_1
+fcnv_t_d_uw 001110 ..... ... 111 .......... ..... @f0e_df_1
+fcnv_t_f_uq 001110 ..... ... 111 .......... ..... @f0e_fd_1
+fcnv_t_d_uq 001110 ..... ... 111 .......... ..... @f0e_dd_1
+
+# Floating point class 2
+
+ftest 001100 00000 00000 y:3 00 10000 1 c:5
+
+fcmp_f 001100 ..... ..... ... 00 ..... 0 ..... @f0c_2
+fcmp_d 001100 ..... ..... ... 01 ..... 0 ..... @f0c_2
+
+fcmp_f 001110 ..... ..... ... ..... ... ..... @f0e_f_2
+fcmp_d 001110 ..... ..... ... ..... ... ..... @f0e_d_2
+
+# Floating point class 3
+
+fadd_f 001100 ..... ..... 000 00 ...... ..... @f0c_3
+fsub_f 001100 ..... ..... 001 00 ...... ..... @f0c_3
+fmpy_f 001100 ..... ..... 010 00 ...... ..... @f0c_3
+fdiv_f 001100 ..... ..... 011 00 ...... ..... @f0c_3
+
+fadd_d 001100 ..... ..... 000 01 ...... ..... @f0c_3
+fsub_d 001100 ..... ..... 001 01 ...... ..... @f0c_3
+fmpy_d 001100 ..... ..... 010 01 ...... ..... @f0c_3
+fdiv_d 001100 ..... ..... 011 01 ...... ..... @f0c_3
+
+fadd_f 001110 ..... ..... 000 ..... ... ..... @f0e_f_3
+fsub_f 001110 ..... ..... 001 ..... ... ..... @f0e_f_3
+fmpy_f 001110 ..... ..... 010 ..... ... ..... @f0e_f_3
+fdiv_f 001110 ..... ..... 011 ..... ... ..... @f0e_f_3
+
+fadd_d 001110 ..... ..... 000 ..... ... ..... @f0e_d_3
+fsub_d 001110 ..... ..... 001 ..... ... ..... @f0e_d_3
+fmpy_d 001110 ..... ..... 010 ..... ... ..... @f0e_d_3
+fdiv_d 001110 ..... ..... 011 ..... ... ..... @f0e_d_3
+
+xmpyu 001110 ..... ..... 010 .0111 .00 t:5 r1=%ra64 r2=%rb64
}
static void do_stby_b(CPUHPPAState *env, target_ulong addr, target_ureg val,
- bool parallel)
+ bool parallel, uintptr_t ra)
{
- uintptr_t ra = GETPC();
-
switch (addr & 3) {
case 3:
cpu_stb_data_ra(env, addr, val, ra);
void HELPER(stby_b)(CPUHPPAState *env, target_ulong addr, target_ureg val)
{
- do_stby_b(env, addr, val, false);
+ do_stby_b(env, addr, val, false, GETPC());
}
void HELPER(stby_b_parallel)(CPUHPPAState *env, target_ulong addr,
target_ureg val)
{
- do_stby_b(env, addr, val, true);
+ do_stby_b(env, addr, val, true, GETPC());
}
static void do_stby_e(CPUHPPAState *env, target_ulong addr, target_ureg val,
- bool parallel)
+ bool parallel, uintptr_t ra)
{
- uintptr_t ra = GETPC();
-
switch (addr & 3) {
case 3:
/* The 3 byte store must appear atomic. */
void HELPER(stby_e)(CPUHPPAState *env, target_ulong addr, target_ureg val)
{
- do_stby_e(env, addr, val, false);
+ do_stby_e(env, addr, val, false, GETPC());
}
void HELPER(stby_e_parallel)(CPUHPPAState *env, target_ulong addr,
target_ureg val)
{
- do_stby_e(env, addr, val, true);
+ do_stby_e(env, addr, val, true, GETPC());
}
target_ureg HELPER(probe)(CPUHPPAState *env, target_ulong addr,
target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm)
{
target_ulong psw = env->psw;
- /* ??? On second reading this condition simply seems
- to be undefined rather than a diagnosed trap. */
- if (nsm & ~psw & PSW_Q) {
- hppa_dynamic_excp(env, EXCP_ILL, GETPC());
- }
+ /*
+ * Setting the PSW Q bit to 1, if it was not already 1, is an
+ * undefined operation.
+ *
+ * However, HP-UX 10.20 does this with the SSM instruction.
+ * Tested this on HP9000/712 and HP9000/785/C3750 and both
+ * machines set the Q bit from 0 to 1 without an exception,
+ * so let this go without comment.
+ */
env->psw = (psw & ~PSW_SM) | (nsm & PSW_SM);
return psw & PSW_SM;
}
bool psw_n_nonzero;
} DisasContext;
-/* Target-specific return values from translate_one, indicating the
- state of the TB. Note that DISAS_NEXT indicates that we are not
- exiting the TB. */
+/* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */
+static int expand_sm_imm(int val)
+{
+ if (val & PSW_SM_E) {
+ val = (val & ~PSW_SM_E) | PSW_E;
+ }
+ if (val & PSW_SM_W) {
+ val = (val & ~PSW_SM_W) | PSW_W;
+ }
+ return val;
+}
+
+/* Inverted space register indicates 0 means sr0 not inferred from base. */
+static int expand_sr3x(int val)
+{
+ return ~val;
+}
+
+/* Convert the M:A bits within a memory insn to the tri-state value
+ we use for the final M. */
+static int ma_to_m(int val)
+{
+ return val & 2 ? (val & 1 ? -1 : 1) : 0;
+}
+
+/* Convert the sign of the displacement to a pre or post-modify. */
+static int pos_to_m(int val)
+{
+ return val ? 1 : -1;
+}
+
+static int neg_to_m(int val)
+{
+ return val ? -1 : 1;
+}
+
+/* Used for branch targets and fp memory ops. */
+static int expand_shl2(int val)
+{
+ return val << 2;
+}
+
+/* Used for fp memory ops. */
+static int expand_shl3(int val)
+{
+ return val << 3;
+}
+
+/* Used for assemble_21. */
+static int expand_shl11(int val)
+{
+ return val << 11;
+}
+
+
+/* Include the auto-generated decoder. */
+#include "decode.inc.c"
/* We are not using a goto_tb (for whatever reason), but have updated
the iaq (for whatever reason), so don't do it again on exit. */
to recognize unmasked interrupts. */
#define DISAS_IAQ_N_STALE_EXIT DISAS_TARGET_2
-typedef struct DisasInsn {
- uint32_t insn, mask;
- DisasJumpType (*trans)(DisasContext *ctx, uint32_t insn,
- const struct DisasInsn *f);
- union {
- void (*ttt)(TCGv_reg, TCGv_reg, TCGv_reg);
- void (*weww)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32);
- void (*dedd)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64);
- void (*wew)(TCGv_i32, TCGv_env, TCGv_i32);
- void (*ded)(TCGv_i64, TCGv_env, TCGv_i64);
- void (*wed)(TCGv_i32, TCGv_env, TCGv_i64);
- void (*dew)(TCGv_i64, TCGv_env, TCGv_i32);
- } f;
-} DisasInsn;
-
/* global register indexes */
static TCGv_reg cpu_gr[32];
static TCGv_i64 cpu_sr[4];
};
}
+static DisasCond cond_make_t(void)
+{
+ return (DisasCond){
+ .c = TCG_COND_ALWAYS,
+ .a0 = NULL,
+ .a1 = NULL,
+ };
+}
+
static DisasCond cond_make_n(void)
{
return (DisasCond){
};
}
-static DisasCond cond_make_0(TCGCond c, TCGv_reg a0)
+static DisasCond cond_make_0_tmp(TCGCond c, TCGv_reg a0)
{
- DisasCond r = { .c = c, .a1 = NULL, .a1_is_0 = true };
-
assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
- r.a0 = tcg_temp_new();
- tcg_gen_mov_reg(r.a0, a0);
+ return (DisasCond){
+ .c = c, .a0 = a0, .a1_is_0 = true
+ };
+}
- return r;
+static DisasCond cond_make_0(TCGCond c, TCGv_reg a0)
+{
+ TCGv_reg tmp = tcg_temp_new();
+ tcg_gen_mov_reg(tmp, a0);
+ return cond_make_0_tmp(c, tmp);
}
static DisasCond cond_make(TCGCond c, TCGv_reg a0, TCGv_reg a1)
}
/* Mark the end of an instruction that may have been nullified.
- This is the pair to nullify_over. */
-static DisasJumpType nullify_end(DisasContext *ctx, DisasJumpType status)
+ This is the pair to nullify_over. Always returns true so that
+ it may be tail-called from a translate function. */
+static bool nullify_end(DisasContext *ctx)
{
TCGLabel *null_lab = ctx->null_lab;
+ DisasJumpType status = ctx->base.is_jmp;
/* For NEXT, NORETURN, STALE, we can easily continue (or exit).
For UPDATED, we cannot update on the nullified path. */
/* The current insn wasn't conditional or handled the condition
applied to it without a branch, so the (new) setting of
NULL_COND can be applied directly to the next insn. */
- return status;
+ return true;
}
ctx->null_lab = NULL;
ctx->null_cond = cond_make_n();
}
if (status == DISAS_NORETURN) {
- status = DISAS_NEXT;
+ ctx->base.is_jmp = DISAS_NEXT;
}
- return status;
+ return true;
}
static void copy_iaoq_entry(TCGv_reg dest, target_ureg ival, TCGv_reg vval)
tcg_temp_free_i32(t);
}
-static DisasJumpType gen_excp(DisasContext *ctx, int exception)
+static void gen_excp(DisasContext *ctx, int exception)
{
copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
nullify_save(ctx);
gen_excp_1(exception);
- return DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
}
-static DisasJumpType gen_excp_iir(DisasContext *ctx, int exc)
+static bool gen_excp_iir(DisasContext *ctx, int exc)
{
- TCGv_reg tmp = tcg_const_reg(ctx->insn);
+ TCGv_reg tmp;
+
+ nullify_over(ctx);
+ tmp = tcg_const_reg(ctx->insn);
tcg_gen_st_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[CR_IIR]));
tcg_temp_free(tmp);
- return gen_excp(ctx, exc);
+ gen_excp(ctx, exc);
+ return nullify_end(ctx);
}
-static DisasJumpType gen_illegal(DisasContext *ctx)
+static bool gen_illegal(DisasContext *ctx)
{
- nullify_over(ctx);
- return nullify_end(ctx, gen_excp_iir(ctx, EXCP_ILL));
+ return gen_excp_iir(ctx, EXCP_ILL);
}
-#define CHECK_MOST_PRIVILEGED(EXCP) \
- do { \
- if (ctx->privilege != 0) { \
- nullify_over(ctx); \
- return nullify_end(ctx, gen_excp_iir(ctx, EXCP)); \
- } \
+#ifdef CONFIG_USER_ONLY
+#define CHECK_MOST_PRIVILEGED(EXCP) \
+ return gen_excp_iir(ctx, EXCP)
+#else
+#define CHECK_MOST_PRIVILEGED(EXCP) \
+ do { \
+ if (ctx->privilege != 0) { \
+ return gen_excp_iir(ctx, EXCP); \
+ } \
} while (0)
+#endif
static bool use_goto_tb(DisasContext *ctx, target_ureg dest)
{
/* Suppress goto_tb in the case of single-steping and IO. */
- if ((tb_cflags(ctx->base.tb) & CF_LAST_IO) || ctx->base.singlestep_enabled) {
+ if ((tb_cflags(ctx->base.tb) & CF_LAST_IO)
+ || ctx->base.singlestep_enabled) {
return false;
}
return true;
}
}
-/* PA has a habit of taking the LSB of a field and using that as the sign,
- with the rest of the field becoming the least significant bits. */
-static target_sreg low_sextract(uint32_t val, int pos, int len)
-{
- target_ureg x = -(target_ureg)extract32(val, pos, 1);
- x = (x << (len - 1)) | extract32(val, pos + 1, len - 1);
- return x;
-}
-
-static unsigned assemble_rt64(uint32_t insn)
-{
- unsigned r1 = extract32(insn, 6, 1);
- unsigned r0 = extract32(insn, 0, 5);
- return r1 * 32 + r0;
-}
-
-static unsigned assemble_ra64(uint32_t insn)
-{
- unsigned r1 = extract32(insn, 7, 1);
- unsigned r0 = extract32(insn, 21, 5);
- return r1 * 32 + r0;
-}
-
-static unsigned assemble_rb64(uint32_t insn)
-{
- unsigned r1 = extract32(insn, 12, 1);
- unsigned r0 = extract32(insn, 16, 5);
- return r1 * 32 + r0;
-}
-
-static unsigned assemble_rc64(uint32_t insn)
-{
- unsigned r2 = extract32(insn, 8, 1);
- unsigned r1 = extract32(insn, 13, 3);
- unsigned r0 = extract32(insn, 9, 2);
- return r2 * 32 + r1 * 4 + r0;
-}
-
-static unsigned assemble_sr3(uint32_t insn)
-{
- unsigned s2 = extract32(insn, 13, 1);
- unsigned s0 = extract32(insn, 14, 2);
- return s2 * 4 + s0;
-}
-
-static target_sreg assemble_12(uint32_t insn)
-{
- target_ureg x = -(target_ureg)(insn & 1);
- x = (x << 1) | extract32(insn, 2, 1);
- x = (x << 10) | extract32(insn, 3, 10);
- return x;
-}
-
-static target_sreg assemble_16(uint32_t insn)
-{
- /* Take the name from PA2.0, which produces a 16-bit number
- only with wide mode; otherwise a 14-bit number. Since we don't
- implement wide mode, this is always the 14-bit number. */
- return low_sextract(insn, 0, 14);
-}
-
-static target_sreg assemble_16a(uint32_t insn)
-{
- /* Take the name from PA2.0, which produces a 14-bit shifted number
- only with wide mode; otherwise a 12-bit shifted number. Since we
- don't implement wide mode, this is always the 12-bit number. */
- target_ureg x = -(target_ureg)(insn & 1);
- x = (x << 11) | extract32(insn, 2, 11);
- return x << 2;
-}
-
-static target_sreg assemble_17(uint32_t insn)
-{
- target_ureg x = -(target_ureg)(insn & 1);
- x = (x << 5) | extract32(insn, 16, 5);
- x = (x << 1) | extract32(insn, 2, 1);
- x = (x << 10) | extract32(insn, 3, 10);
- return x << 2;
-}
-
-static target_sreg assemble_21(uint32_t insn)
+static bool cond_need_sv(int c)
{
- target_ureg x = -(target_ureg)(insn & 1);
- x = (x << 11) | extract32(insn, 1, 11);
- x = (x << 2) | extract32(insn, 14, 2);
- x = (x << 5) | extract32(insn, 16, 5);
- x = (x << 2) | extract32(insn, 12, 2);
- return x << 11;
+ return c == 2 || c == 3 || c == 6;
}
-static target_sreg assemble_22(uint32_t insn)
+static bool cond_need_cb(int c)
{
- target_ureg x = -(target_ureg)(insn & 1);
- x = (x << 10) | extract32(insn, 16, 10);
- x = (x << 1) | extract32(insn, 2, 1);
- x = (x << 10) | extract32(insn, 3, 10);
- return x << 2;
+ return c == 4 || c == 5;
}
-/* The parisc documentation describes only the general interpretation of
- the conditions, without describing their exact implementation. The
- interpretations do not stand up well when considering ADD,C and SUB,B.
- However, considering the Addition, Subtraction and Logical conditions
- as a whole it would appear that these relations are similar to what
- a traditional NZCV set of flags would produce. */
+/*
+ * Compute conditional for arithmetic. See Page 5-3, Table 5-1, of
+ * the Parisc 1.1 Architecture Reference Manual for details.
+ */
static DisasCond do_cond(unsigned cf, TCGv_reg res,
TCGv_reg cb_msb, TCGv_reg sv)
TCGv_reg tmp;
switch (cf >> 1) {
- case 0: /* Never / TR */
+ case 0: /* Never / TR (0 / 1) */
cond = cond_make_f();
break;
case 1: /* = / <> (Z / !Z) */
cond = cond_make_0(TCG_COND_EQ, res);
break;
- case 2: /* < / >= (N / !N) */
- cond = cond_make_0(TCG_COND_LT, res);
+ case 2: /* < / >= (N ^ V / !(N ^ V) */
+ tmp = tcg_temp_new();
+ tcg_gen_xor_reg(tmp, res, sv);
+ cond = cond_make_0_tmp(TCG_COND_LT, tmp);
break;
- case 3: /* <= / > (N | Z / !N & !Z) */
- cond = cond_make_0(TCG_COND_LE, res);
+ case 3: /* <= / > (N ^ V) | Z / !((N ^ V) | Z) */
+ /*
+ * Simplify:
+ * (N ^ V) | Z
+ * ((res < 0) ^ (sv < 0)) | !res
+ * ((res ^ sv) < 0) | !res
+ * (~(res ^ sv) >= 0) | !res
+ * !(~(res ^ sv) >> 31) | !res
+ * !(~(res ^ sv) >> 31 & res)
+ */
+ tmp = tcg_temp_new();
+ tcg_gen_eqv_reg(tmp, res, sv);
+ tcg_gen_sari_reg(tmp, tmp, TARGET_REGISTER_BITS - 1);
+ tcg_gen_and_reg(tmp, tmp, res);
+ cond = cond_make_0_tmp(TCG_COND_EQ, tmp);
break;
case 4: /* NUV / UV (!C / C) */
cond = cond_make_0(TCG_COND_EQ, cb_msb);
tmp = tcg_temp_new();
tcg_gen_neg_reg(tmp, cb_msb);
tcg_gen_and_reg(tmp, tmp, res);
- cond = cond_make_0(TCG_COND_EQ, tmp);
- tcg_temp_free(tmp);
+ cond = cond_make_0_tmp(TCG_COND_EQ, tmp);
break;
case 6: /* SV / NSV (V / !V) */
cond = cond_make_0(TCG_COND_LT, sv);
case 7: /* OD / EV */
tmp = tcg_temp_new();
tcg_gen_andi_reg(tmp, res, 1);
- cond = cond_make_0(TCG_COND_NE, tmp);
- tcg_temp_free(tmp);
+ cond = cond_make_0_tmp(TCG_COND_NE, tmp);
break;
default:
g_assert_not_reached();
cond = cond_make(TCG_COND_LEU, in1, in2);
break;
default:
- return do_cond(cf, res, sv, sv);
+ return do_cond(cf, res, NULL, sv);
}
if (cf & 1) {
cond.c = tcg_invert_cond(cond.c);
return cond;
}
-/* Similar, but for logicals, where the carry and overflow bits are not
- computed, and use of them is undefined. */
+/*
+ * Similar, but for logicals, where the carry and overflow bits are not
+ * computed, and use of them is undefined.
+ *
+ * Undefined or not, hardware does not trap. It seems reasonable to
+ * assume hardware treats cases c={4,5,6} as if C=0 & V=0, since that's
+ * how cases c={2,3} are treated.
+ */
static DisasCond do_log_cond(unsigned cf, TCGv_reg res)
{
- switch (cf >> 1) {
- case 4: case 5: case 6:
- cf &= 1;
- break;
+ switch (cf) {
+ case 0: /* never */
+ case 9: /* undef, C */
+ case 11: /* undef, C & !Z */
+ case 12: /* undef, V */
+ return cond_make_f();
+
+ case 1: /* true */
+ case 8: /* undef, !C */
+ case 10: /* undef, !C | Z */
+ case 13: /* undef, !V */
+ return cond_make_t();
+
+ case 2: /* == */
+ return cond_make_0(TCG_COND_EQ, res);
+ case 3: /* <> */
+ return cond_make_0(TCG_COND_NE, res);
+ case 4: /* < */
+ return cond_make_0(TCG_COND_LT, res);
+ case 5: /* >= */
+ return cond_make_0(TCG_COND_GE, res);
+ case 6: /* <= */
+ return cond_make_0(TCG_COND_LE, res);
+ case 7: /* > */
+ return cond_make_0(TCG_COND_GT, res);
+
+ case 14: /* OD */
+ case 15: /* EV */
+ return do_cond(cf, res, NULL, NULL);
+
+ default:
+ g_assert_not_reached();
}
- return do_cond(cf, res, res, res);
}
/* Similar, but for shift/extract/deposit conditions. */
return sv;
}
-static DisasJumpType do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1,
- TCGv_reg in2, unsigned shift, bool is_l,
- bool is_tsv, bool is_tc, bool is_c, unsigned cf)
+static void do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1,
+ TCGv_reg in2, unsigned shift, bool is_l,
+ bool is_tsv, bool is_tc, bool is_c, unsigned cf)
{
TCGv_reg dest, cb, cb_msb, sv, tmp;
unsigned c = cf >> 1;
in1 = tmp;
}
- if (!is_l || c == 4 || c == 5) {
+ if (!is_l || cond_need_cb(c)) {
TCGv_reg zero = tcg_const_reg(0);
cb_msb = get_temp(ctx);
tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero);
/* Compute signed overflow if required. */
sv = NULL;
- if (is_tsv || c == 6) {
+ if (is_tsv || cond_need_sv(c)) {
sv = do_add_sv(ctx, dest, in1, in2);
if (is_tsv) {
/* ??? Need to include overflow from shift. */
/* Install the new nullification. */
cond_free(&ctx->null_cond);
ctx->null_cond = cond;
- return DISAS_NEXT;
}
-static DisasJumpType do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1,
- TCGv_reg in2, bool is_tsv, bool is_b,
- bool is_tc, unsigned cf)
+static bool do_add_reg(DisasContext *ctx, arg_rrr_cf_sh *a,
+ bool is_l, bool is_tsv, bool is_tc, bool is_c)
+{
+ TCGv_reg tcg_r1, tcg_r2;
+
+ if (a->cf) {
+ nullify_over(ctx);
+ }
+ tcg_r1 = load_gpr(ctx, a->r1);
+ tcg_r2 = load_gpr(ctx, a->r2);
+ do_add(ctx, a->t, tcg_r1, tcg_r2, a->sh, is_l, is_tsv, is_tc, is_c, a->cf);
+ return nullify_end(ctx);
+}
+
+static bool do_add_imm(DisasContext *ctx, arg_rri_cf *a,
+ bool is_tsv, bool is_tc)
+{
+ TCGv_reg tcg_im, tcg_r2;
+
+ if (a->cf) {
+ nullify_over(ctx);
+ }
+ tcg_im = load_const(ctx, a->i);
+ tcg_r2 = load_gpr(ctx, a->r);
+ do_add(ctx, a->t, tcg_im, tcg_r2, 0, 0, is_tsv, is_tc, 0, a->cf);
+ return nullify_end(ctx);
+}
+
+static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1,
+ TCGv_reg in2, bool is_tsv, bool is_b,
+ bool is_tc, unsigned cf)
{
TCGv_reg dest, sv, cb, cb_msb, zero, tmp;
unsigned c = cf >> 1;
/* Compute signed overflow if required. */
sv = NULL;
- if (is_tsv || c == 6) {
+ if (is_tsv || cond_need_sv(c)) {
sv = do_sub_sv(ctx, dest, in1, in2);
if (is_tsv) {
gen_helper_tsv(cpu_env, sv);
/* Install the new nullification. */
cond_free(&ctx->null_cond);
ctx->null_cond = cond;
- return DISAS_NEXT;
}
-static DisasJumpType do_cmpclr(DisasContext *ctx, unsigned rt, TCGv_reg in1,
- TCGv_reg in2, unsigned cf)
+static bool do_sub_reg(DisasContext *ctx, arg_rrr_cf *a,
+ bool is_tsv, bool is_b, bool is_tc)
+{
+ TCGv_reg tcg_r1, tcg_r2;
+
+ if (a->cf) {
+ nullify_over(ctx);
+ }
+ tcg_r1 = load_gpr(ctx, a->r1);
+ tcg_r2 = load_gpr(ctx, a->r2);
+ do_sub(ctx, a->t, tcg_r1, tcg_r2, is_tsv, is_b, is_tc, a->cf);
+ return nullify_end(ctx);
+}
+
+static bool do_sub_imm(DisasContext *ctx, arg_rri_cf *a, bool is_tsv)
+{
+ TCGv_reg tcg_im, tcg_r2;
+
+ if (a->cf) {
+ nullify_over(ctx);
+ }
+ tcg_im = load_const(ctx, a->i);
+ tcg_r2 = load_gpr(ctx, a->r);
+ do_sub(ctx, a->t, tcg_im, tcg_r2, is_tsv, 0, 0, a->cf);
+ return nullify_end(ctx);
+}
+
+static void do_cmpclr(DisasContext *ctx, unsigned rt, TCGv_reg in1,
+ TCGv_reg in2, unsigned cf)
{
TCGv_reg dest, sv;
DisasCond cond;
/* Compute signed overflow if required. */
sv = NULL;
- if ((cf >> 1) == 6) {
+ if (cond_need_sv(cf >> 1)) {
sv = do_sub_sv(ctx, dest, in1, in2);
}
/* Install the new nullification. */
cond_free(&ctx->null_cond);
ctx->null_cond = cond;
- return DISAS_NEXT;
}
-static DisasJumpType do_log(DisasContext *ctx, unsigned rt, TCGv_reg in1,
- TCGv_reg in2, unsigned cf,
- void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
+static void do_log(DisasContext *ctx, unsigned rt, TCGv_reg in1,
+ TCGv_reg in2, unsigned cf,
+ void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
{
TCGv_reg dest = dest_gpr(ctx, rt);
if (cf) {
ctx->null_cond = do_log_cond(cf, dest);
}
- return DISAS_NEXT;
}
-static DisasJumpType do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1,
- TCGv_reg in2, unsigned cf, bool is_tc,
- void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
+static bool do_log_reg(DisasContext *ctx, arg_rrr_cf *a,
+ void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
+{
+ TCGv_reg tcg_r1, tcg_r2;
+
+ if (a->cf) {
+ nullify_over(ctx);
+ }
+ tcg_r1 = load_gpr(ctx, a->r1);
+ tcg_r2 = load_gpr(ctx, a->r2);
+ do_log(ctx, a->t, tcg_r1, tcg_r2, a->cf, fn);
+ return nullify_end(ctx);
+}
+
+static void do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1,
+ TCGv_reg in2, unsigned cf, bool is_tc,
+ void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
{
TCGv_reg dest;
DisasCond cond;
cond_free(&ctx->null_cond);
ctx->null_cond = cond;
}
- return DISAS_NEXT;
}
#ifndef CONFIG_USER_ONLY
#define do_store_reg do_store_32
#endif
-static DisasJumpType do_load(DisasContext *ctx, unsigned rt, unsigned rb,
- unsigned rx, int scale, target_sreg disp,
- unsigned sp, int modify, TCGMemOp mop)
+static bool do_load(DisasContext *ctx, unsigned rt, unsigned rb,
+ unsigned rx, int scale, target_sreg disp,
+ unsigned sp, int modify, TCGMemOp mop)
{
TCGv_reg dest;
do_load_reg(ctx, dest, rb, rx, scale, disp, sp, modify, mop);
save_gpr(ctx, rt, dest);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType do_floadw(DisasContext *ctx, unsigned rt, unsigned rb,
- unsigned rx, int scale, target_sreg disp,
- unsigned sp, int modify)
+static bool do_floadw(DisasContext *ctx, unsigned rt, unsigned rb,
+ unsigned rx, int scale, target_sreg disp,
+ unsigned sp, int modify)
{
TCGv_i32 tmp;
gen_helper_loaded_fr0(cpu_env);
}
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
+}
+
+static bool trans_fldw(DisasContext *ctx, arg_ldst *a)
+{
+ return do_floadw(ctx, a->t, a->b, a->x, a->scale ? 2 : 0,
+ a->disp, a->sp, a->m);
}
-static DisasJumpType do_floadd(DisasContext *ctx, unsigned rt, unsigned rb,
- unsigned rx, int scale, target_sreg disp,
- unsigned sp, int modify)
+static bool do_floadd(DisasContext *ctx, unsigned rt, unsigned rb,
+ unsigned rx, int scale, target_sreg disp,
+ unsigned sp, int modify)
{
TCGv_i64 tmp;
gen_helper_loaded_fr0(cpu_env);
}
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
+}
+
+static bool trans_fldd(DisasContext *ctx, arg_ldst *a)
+{
+ return do_floadd(ctx, a->t, a->b, a->x, a->scale ? 3 : 0,
+ a->disp, a->sp, a->m);
}
-static DisasJumpType do_store(DisasContext *ctx, unsigned rt, unsigned rb,
- target_sreg disp, unsigned sp,
- int modify, TCGMemOp mop)
+static bool do_store(DisasContext *ctx, unsigned rt, unsigned rb,
+ target_sreg disp, unsigned sp,
+ int modify, TCGMemOp mop)
{
nullify_over(ctx);
do_store_reg(ctx, load_gpr(ctx, rt), rb, 0, 0, disp, sp, modify, mop);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb,
- unsigned rx, int scale, target_sreg disp,
- unsigned sp, int modify)
+static bool do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb,
+ unsigned rx, int scale, target_sreg disp,
+ unsigned sp, int modify)
{
TCGv_i32 tmp;
do_store_32(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUL);
tcg_temp_free_i32(tmp);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
+}
+
+static bool trans_fstw(DisasContext *ctx, arg_ldst *a)
+{
+ return do_fstorew(ctx, a->t, a->b, a->x, a->scale ? 2 : 0,
+ a->disp, a->sp, a->m);
}
-static DisasJumpType do_fstored(DisasContext *ctx, unsigned rt, unsigned rb,
- unsigned rx, int scale, target_sreg disp,
- unsigned sp, int modify)
+static bool do_fstored(DisasContext *ctx, unsigned rt, unsigned rb,
+ unsigned rx, int scale, target_sreg disp,
+ unsigned sp, int modify)
{
TCGv_i64 tmp;
do_store_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ);
tcg_temp_free_i64(tmp);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
+}
+
+static bool trans_fstd(DisasContext *ctx, arg_ldst *a)
+{
+ return do_fstored(ctx, a->t, a->b, a->x, a->scale ? 3 : 0,
+ a->disp, a->sp, a->m);
}
-static DisasJumpType do_fop_wew(DisasContext *ctx, unsigned rt, unsigned ra,
- void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
+static bool do_fop_wew(DisasContext *ctx, unsigned rt, unsigned ra,
+ void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
{
TCGv_i32 tmp;
save_frw_i32(rt, tmp);
tcg_temp_free_i32(tmp);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType do_fop_wed(DisasContext *ctx, unsigned rt, unsigned ra,
- void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
+static bool do_fop_wed(DisasContext *ctx, unsigned rt, unsigned ra,
+ void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
{
TCGv_i32 dst;
TCGv_i64 src;
tcg_temp_free_i64(src);
save_frw_i32(rt, dst);
tcg_temp_free_i32(dst);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType do_fop_ded(DisasContext *ctx, unsigned rt, unsigned ra,
- void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
+static bool do_fop_ded(DisasContext *ctx, unsigned rt, unsigned ra,
+ void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
{
TCGv_i64 tmp;
save_frd(rt, tmp);
tcg_temp_free_i64(tmp);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType do_fop_dew(DisasContext *ctx, unsigned rt, unsigned ra,
- void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
+static bool do_fop_dew(DisasContext *ctx, unsigned rt, unsigned ra,
+ void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
{
TCGv_i32 src;
TCGv_i64 dst;
tcg_temp_free_i32(src);
save_frd(rt, dst);
tcg_temp_free_i64(dst);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType do_fop_weww(DisasContext *ctx, unsigned rt,
- unsigned ra, unsigned rb,
- void (*func)(TCGv_i32, TCGv_env,
- TCGv_i32, TCGv_i32))
+static bool do_fop_weww(DisasContext *ctx, unsigned rt,
+ unsigned ra, unsigned rb,
+ void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
{
TCGv_i32 a, b;
tcg_temp_free_i32(b);
save_frw_i32(rt, a);
tcg_temp_free_i32(a);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType do_fop_dedd(DisasContext *ctx, unsigned rt,
- unsigned ra, unsigned rb,
- void (*func)(TCGv_i64, TCGv_env,
- TCGv_i64, TCGv_i64))
+static bool do_fop_dedd(DisasContext *ctx, unsigned rt,
+ unsigned ra, unsigned rb,
+ void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
{
TCGv_i64 a, b;
tcg_temp_free_i64(b);
save_frd(rt, a);
tcg_temp_free_i64(a);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
/* Emit an unconditional branch to a direct target, which may or may not
have already had nullification handled. */
-static DisasJumpType do_dbranch(DisasContext *ctx, target_ureg dest,
- unsigned link, bool is_n)
+static bool do_dbranch(DisasContext *ctx, target_ureg dest,
+ unsigned link, bool is_n)
{
if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
if (link != 0) {
if (is_n) {
ctx->null_cond.c = TCG_COND_ALWAYS;
}
- return DISAS_NEXT;
} else {
nullify_over(ctx);
gen_goto_tb(ctx, 0, ctx->iaoq_b, dest);
}
- nullify_end(ctx, DISAS_NEXT);
+ nullify_end(ctx);
nullify_set(ctx, 0);
gen_goto_tb(ctx, 1, ctx->iaoq_b, ctx->iaoq_n);
- return DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
}
+ return true;
}
/* Emit a conditional branch to a direct target. If the branch itself
is nullified, we should have already used nullify_over. */
-static DisasJumpType do_cbranch(DisasContext *ctx, target_sreg disp, bool is_n,
- DisasCond *cond)
+static bool do_cbranch(DisasContext *ctx, target_sreg disp, bool is_n,
+ DisasCond *cond)
{
target_ureg dest = iaoq_dest(ctx, disp);
TCGLabel *taken = NULL;
if (ctx->null_lab) {
gen_set_label(ctx->null_lab);
ctx->null_lab = NULL;
- return DISAS_IAQ_N_STALE;
+ ctx->base.is_jmp = DISAS_IAQ_N_STALE;
} else {
- return DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
}
+ return true;
}
/* Emit an unconditional branch to an indirect target. This handles
nullification of the branch itself. */
-static DisasJumpType do_ibranch(DisasContext *ctx, TCGv_reg dest,
- unsigned link, bool is_n)
+static bool do_ibranch(DisasContext *ctx, TCGv_reg dest,
+ unsigned link, bool is_n)
{
TCGv_reg a0, a1, next, tmp;
TCGCond c;
tcg_gen_mov_reg(cpu_iaoq_f, next);
tcg_gen_addi_reg(cpu_iaoq_b, next, 4);
nullify_set(ctx, 0);
- return DISAS_IAQ_N_UPDATED;
+ ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
+ return true;
}
ctx->null_cond.c = TCG_COND_ALWAYS;
}
tcg_gen_movi_reg(cpu_gr[link], ctx->iaoq_n);
}
tcg_gen_lookup_and_goto_ptr();
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
} else {
cond_prep(&ctx->null_cond);
c = ctx->null_cond.c;
cond_free(&ctx->null_cond);
}
}
-
- return DISAS_NEXT;
+ return true;
}
/* Implement
in than the "be disp(sr2,r0)" instruction that probably sent us
here, is the easiest way to handle the branch delay slot on the
aforementioned BE. */
-static DisasJumpType do_page_zero(DisasContext *ctx)
+static void do_page_zero(DisasContext *ctx)
{
/* If by some means we get here with PSW[N]=1, that implies that
the B,GATE instruction would be skipped, and we'd fault on the
switch (ctx->iaoq_f & -4) {
case 0x00: /* Null pointer call */
gen_excp_1(EXCP_IMP);
- return DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
+ break;
case 0xb0: /* LWS */
gen_excp_1(EXCP_SYSCALL_LWS);
- return DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
+ break;
case 0xe0: /* SET_THREAD_POINTER */
tcg_gen_st_reg(cpu_gr[26], cpu_env, offsetof(CPUHPPAState, cr[27]));
tcg_gen_ori_reg(cpu_iaoq_f, cpu_gr[31], 3);
tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4);
- return DISAS_IAQ_N_UPDATED;
+ ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
+ break;
case 0x100: /* SYSCALL */
gen_excp_1(EXCP_SYSCALL);
- return DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
+ break;
default:
do_sigill:
gen_excp_1(EXCP_ILL);
- return DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
+ break;
}
}
#endif
-static DisasJumpType trans_nop(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_nop(DisasContext *ctx, arg_nop *a)
{
cond_free(&ctx->null_cond);
- return DISAS_NEXT;
+ return true;
}
-static DisasJumpType trans_break(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_break(DisasContext *ctx, arg_break *a)
{
- nullify_over(ctx);
- return nullify_end(ctx, gen_excp_iir(ctx, EXCP_BREAK));
+ return gen_excp_iir(ctx, EXCP_BREAK);
}
-static DisasJumpType trans_sync(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_sync(DisasContext *ctx, arg_sync *a)
{
/* No point in nullifying the memory barrier. */
tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
cond_free(&ctx->null_cond);
- return DISAS_NEXT;
+ return true;
}
-static DisasJumpType trans_mfia(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_mfia(DisasContext *ctx, arg_mfia *a)
{
- unsigned rt = extract32(insn, 0, 5);
+ unsigned rt = a->t;
TCGv_reg tmp = dest_gpr(ctx, rt);
tcg_gen_movi_reg(tmp, ctx->iaoq_f);
save_gpr(ctx, rt, tmp);
cond_free(&ctx->null_cond);
- return DISAS_NEXT;
+ return true;
}
-static DisasJumpType trans_mfsp(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_mfsp(DisasContext *ctx, arg_mfsp *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned rs = assemble_sr3(insn);
+ unsigned rt = a->t;
+ unsigned rs = a->sp;
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_reg t1 = tcg_temp_new();
tcg_temp_free_i64(t0);
cond_free(&ctx->null_cond);
- return DISAS_NEXT;
+ return true;
}
-static DisasJumpType trans_mfctl(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_mfctl(DisasContext *ctx, arg_mfctl *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned ctl = extract32(insn, 21, 5);
+ unsigned rt = a->t;
+ unsigned ctl = a->r;
TCGv_reg tmp;
- DisasJumpType ret;
switch (ctl) {
case CR_SAR:
#ifdef TARGET_HPPA64
- if (extract32(insn, 14, 1) == 0) {
+ if (a->e == 0) {
/* MFSAR without ,W masks low 5 bits. */
tmp = dest_gpr(ctx, rt);
tcg_gen_andi_reg(tmp, cpu_sar, 31);
/* FIXME: Respect PSW_S bit. */
nullify_over(ctx);
tmp = dest_gpr(ctx, rt);
- if (ctx->base.tb->cflags & CF_USE_ICOUNT) {
+ if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
gen_helper_read_interval_timer(tmp);
gen_io_end();
- ret = DISAS_IAQ_N_STALE;
+ ctx->base.is_jmp = DISAS_IAQ_N_STALE;
} else {
gen_helper_read_interval_timer(tmp);
- ret = DISAS_NEXT;
}
save_gpr(ctx, rt, tmp);
- return nullify_end(ctx, ret);
+ return nullify_end(ctx);
case 26:
case 27:
break;
done:
cond_free(&ctx->null_cond);
- return DISAS_NEXT;
+ return true;
}
-static DisasJumpType trans_mtsp(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_mtsp(DisasContext *ctx, arg_mtsp *a)
{
- unsigned rr = extract32(insn, 16, 5);
- unsigned rs = assemble_sr3(insn);
+ unsigned rr = a->r;
+ unsigned rs = a->sp;
TCGv_i64 t64;
if (rs >= 5) {
}
tcg_temp_free_i64(t64);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType trans_mtctl(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_mtctl(DisasContext *ctx, arg_mtctl *a)
{
- unsigned rin = extract32(insn, 16, 5);
- unsigned ctl = extract32(insn, 21, 5);
- TCGv_reg reg = load_gpr(ctx, rin);
+ unsigned ctl = a->t;
+ TCGv_reg reg = load_gpr(ctx, a->r);
TCGv_reg tmp;
if (ctl == CR_SAR) {
tcg_temp_free(tmp);
cond_free(&ctx->null_cond);
- return DISAS_NEXT;
+ return true;
}
/* All other control registers are privileged or read-only. */
CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
-#ifdef CONFIG_USER_ONLY
- g_assert_not_reached();
-#else
- DisasJumpType ret = DISAS_NEXT;
-
+#ifndef CONFIG_USER_ONLY
nullify_over(ctx);
switch (ctl) {
case CR_IT:
break;
case CR_EIEM:
gen_helper_write_eiem(cpu_env, reg);
- ret = DISAS_IAQ_N_STALE_EXIT;
+ ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
break;
case CR_IIASQ:
tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
break;
}
- return nullify_end(ctx, ret);
+ return nullify_end(ctx);
#endif
}
-static DisasJumpType trans_mtsarcm(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_mtsarcm(DisasContext *ctx, arg_mtsarcm *a)
{
- unsigned rin = extract32(insn, 16, 5);
TCGv_reg tmp = tcg_temp_new();
- tcg_gen_not_reg(tmp, load_gpr(ctx, rin));
+ tcg_gen_not_reg(tmp, load_gpr(ctx, a->r));
tcg_gen_andi_reg(tmp, tmp, TARGET_REGISTER_BITS - 1);
save_or_nullify(ctx, cpu_sar, tmp);
tcg_temp_free(tmp);
cond_free(&ctx->null_cond);
- return DISAS_NEXT;
+ return true;
}
-static DisasJumpType trans_ldsid(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_ldsid(DisasContext *ctx, arg_ldsid *a)
{
- unsigned rt = extract32(insn, 0, 5);
- TCGv_reg dest = dest_gpr(ctx, rt);
+ TCGv_reg dest = dest_gpr(ctx, a->t);
#ifdef CONFIG_USER_ONLY
/* We don't implement space registers in user mode. */
tcg_gen_movi_reg(dest, 0);
#else
- unsigned rb = extract32(insn, 21, 5);
- unsigned sp = extract32(insn, 14, 2);
TCGv_i64 t0 = tcg_temp_new_i64();
- tcg_gen_mov_i64(t0, space_select(ctx, sp, load_gpr(ctx, rb)));
+ tcg_gen_mov_i64(t0, space_select(ctx, a->sp, load_gpr(ctx, a->b)));
tcg_gen_shri_i64(t0, t0, 32);
tcg_gen_trunc_i64_reg(dest, t0);
tcg_temp_free_i64(t0);
#endif
- save_gpr(ctx, rt, dest);
+ save_gpr(ctx, a->t, dest);
cond_free(&ctx->null_cond);
- return DISAS_NEXT;
-}
-
-#ifndef CONFIG_USER_ONLY
-/* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */
-static target_ureg extract_sm_imm(uint32_t insn)
-{
- target_ureg val = extract32(insn, 16, 10);
-
- if (val & PSW_SM_E) {
- val = (val & ~PSW_SM_E) | PSW_E;
- }
- if (val & PSW_SM_W) {
- val = (val & ~PSW_SM_W) | PSW_W;
- }
- return val;
+ return true;
}
-static DisasJumpType trans_rsm(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_rsm(DisasContext *ctx, arg_rsm *a)
{
- unsigned rt = extract32(insn, 0, 5);
- target_ureg sm = extract_sm_imm(insn);
+ CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+#ifndef CONFIG_USER_ONLY
TCGv_reg tmp;
- CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
nullify_over(ctx);
tmp = get_temp(ctx);
tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw));
- tcg_gen_andi_reg(tmp, tmp, ~sm);
+ tcg_gen_andi_reg(tmp, tmp, ~a->i);
gen_helper_swap_system_mask(tmp, cpu_env, tmp);
- save_gpr(ctx, rt, tmp);
+ save_gpr(ctx, a->t, tmp);
/* Exit the TB to recognize new interrupts, e.g. PSW_M. */
- return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT);
+ ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
+ return nullify_end(ctx);
+#endif
}
-static DisasJumpType trans_ssm(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_ssm(DisasContext *ctx, arg_ssm *a)
{
- unsigned rt = extract32(insn, 0, 5);
- target_ureg sm = extract_sm_imm(insn);
+ CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+#ifndef CONFIG_USER_ONLY
TCGv_reg tmp;
- CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
nullify_over(ctx);
tmp = get_temp(ctx);
tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw));
- tcg_gen_ori_reg(tmp, tmp, sm);
+ tcg_gen_ori_reg(tmp, tmp, a->i);
gen_helper_swap_system_mask(tmp, cpu_env, tmp);
- save_gpr(ctx, rt, tmp);
+ save_gpr(ctx, a->t, tmp);
/* Exit the TB to recognize new interrupts, e.g. PSW_I. */
- return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT);
+ ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
+ return nullify_end(ctx);
+#endif
}
-static DisasJumpType trans_mtsm(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_mtsm(DisasContext *ctx, arg_mtsm *a)
{
- unsigned rr = extract32(insn, 16, 5);
- TCGv_reg tmp, reg;
-
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+#ifndef CONFIG_USER_ONLY
+ TCGv_reg tmp, reg;
nullify_over(ctx);
- reg = load_gpr(ctx, rr);
+ reg = load_gpr(ctx, a->r);
tmp = get_temp(ctx);
gen_helper_swap_system_mask(tmp, cpu_env, reg);
/* Exit the TB to recognize new interrupts. */
- return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT);
+ ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
+ return nullify_end(ctx);
+#endif
}
-static DisasJumpType trans_rfi(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool do_rfi(DisasContext *ctx, bool rfi_r)
{
- unsigned comp = extract32(insn, 5, 4);
-
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+#ifndef CONFIG_USER_ONLY
nullify_over(ctx);
- if (comp == 5) {
+ if (rfi_r) {
gen_helper_rfi_r(cpu_env);
} else {
gen_helper_rfi(cpu_env);
}
+ /* Exit the TB to recognize new interrupts. */
if (ctx->base.singlestep_enabled) {
gen_excp_1(EXCP_DEBUG);
} else {
tcg_gen_exit_tb(NULL, 0);
}
+ ctx->base.is_jmp = DISAS_NORETURN;
- /* Exit the TB to recognize new interrupts. */
- return nullify_end(ctx, DISAS_NORETURN);
+ return nullify_end(ctx);
+#endif
+}
+
+static bool trans_rfi(DisasContext *ctx, arg_rfi *a)
+{
+ return do_rfi(ctx, false);
+}
+
+static bool trans_rfi_r(DisasContext *ctx, arg_rfi_r *a)
+{
+ return do_rfi(ctx, true);
}
-static DisasJumpType gen_hlt(DisasContext *ctx, int reset)
+static bool trans_halt(DisasContext *ctx, arg_halt *a)
{
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
- nullify_over(ctx);
- if (reset) {
- gen_helper_reset(cpu_env);
- } else {
- gen_helper_halt(cpu_env);
- }
- return nullify_end(ctx, DISAS_NORETURN);
-}
-#endif /* !CONFIG_USER_ONLY */
-
-static const DisasInsn table_system[] = {
- { 0x00000000u, 0xfc001fe0u, trans_break },
- { 0x00001820u, 0xffe01fffu, trans_mtsp },
- { 0x00001840u, 0xfc00ffffu, trans_mtctl },
- { 0x016018c0u, 0xffe0ffffu, trans_mtsarcm },
- { 0x000014a0u, 0xffffffe0u, trans_mfia },
- { 0x000004a0u, 0xffff1fe0u, trans_mfsp },
- { 0x000008a0u, 0xfc1fbfe0u, trans_mfctl },
- { 0x00000400u, 0xffffffffu, trans_sync }, /* sync */
- { 0x00100400u, 0xffffffffu, trans_sync }, /* syncdma */
- { 0x000010a0u, 0xfc1f3fe0u, trans_ldsid },
#ifndef CONFIG_USER_ONLY
- { 0x00000e60u, 0xfc00ffe0u, trans_rsm },
- { 0x00000d60u, 0xfc00ffe0u, trans_ssm },
- { 0x00001860u, 0xffe0ffffu, trans_mtsm },
- { 0x00000c00u, 0xfffffe1fu, trans_rfi },
+ nullify_over(ctx);
+ gen_helper_halt(cpu_env);
+ ctx->base.is_jmp = DISAS_NORETURN;
+ return nullify_end(ctx);
#endif
-};
+}
-static DisasJumpType trans_base_idx_mod(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_reset(DisasContext *ctx, arg_reset *a)
{
- unsigned rb = extract32(insn, 21, 5);
- unsigned rx = extract32(insn, 16, 5);
- TCGv_reg dest = dest_gpr(ctx, rb);
- TCGv_reg src1 = load_gpr(ctx, rb);
- TCGv_reg src2 = load_gpr(ctx, rx);
+ CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+#ifndef CONFIG_USER_ONLY
+ nullify_over(ctx);
+ gen_helper_reset(cpu_env);
+ ctx->base.is_jmp = DISAS_NORETURN;
+ return nullify_end(ctx);
+#endif
+}
- /* The only thing we need to do is the base register modification. */
- tcg_gen_add_reg(dest, src1, src2);
- save_gpr(ctx, rb, dest);
+static bool trans_nop_addrx(DisasContext *ctx, arg_ldst *a)
+{
+ if (a->m) {
+ TCGv_reg dest = dest_gpr(ctx, a->b);
+ TCGv_reg src1 = load_gpr(ctx, a->b);
+ TCGv_reg src2 = load_gpr(ctx, a->x);
+ /* The only thing we need to do is the base register modification. */
+ tcg_gen_add_reg(dest, src1, src2);
+ save_gpr(ctx, a->b, dest);
+ }
cond_free(&ctx->null_cond);
- return DISAS_NEXT;
+ return true;
}
-static DisasJumpType trans_probe(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_probe(DisasContext *ctx, arg_probe *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned sp = extract32(insn, 14, 2);
- unsigned rr = extract32(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
- unsigned is_write = extract32(insn, 6, 1);
- unsigned is_imm = extract32(insn, 13, 1);
TCGv_reg dest, ofs;
TCGv_i32 level, want;
TCGv_tl addr;
nullify_over(ctx);
- dest = dest_gpr(ctx, rt);
- form_gva(ctx, &addr, &ofs, rb, 0, 0, 0, sp, 0, false);
+ dest = dest_gpr(ctx, a->t);
+ form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
- if (is_imm) {
- level = tcg_const_i32(extract32(insn, 16, 2));
+ if (a->imm) {
+ level = tcg_const_i32(a->ri);
} else {
level = tcg_temp_new_i32();
- tcg_gen_trunc_reg_i32(level, load_gpr(ctx, rr));
+ tcg_gen_trunc_reg_i32(level, load_gpr(ctx, a->ri));
tcg_gen_andi_i32(level, level, 3);
}
- want = tcg_const_i32(is_write ? PAGE_WRITE : PAGE_READ);
+ want = tcg_const_i32(a->write ? PAGE_WRITE : PAGE_READ);
gen_helper_probe(dest, cpu_env, addr, level, want);
tcg_temp_free_i32(want);
tcg_temp_free_i32(level);
- save_gpr(ctx, rt, dest);
- return nullify_end(ctx, DISAS_NEXT);
+ save_gpr(ctx, a->t, dest);
+ return nullify_end(ctx);
}
+static bool trans_ixtlbx(DisasContext *ctx, arg_ixtlbx *a)
+{
+ CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
#ifndef CONFIG_USER_ONLY
-static DisasJumpType trans_ixtlbx(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
-{
- unsigned sp;
- unsigned rr = extract32(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
- unsigned is_data = insn & 0x1000;
- unsigned is_addr = insn & 0x40;
TCGv_tl addr;
TCGv_reg ofs, reg;
- if (is_data) {
- sp = extract32(insn, 14, 2);
- } else {
- sp = ~assemble_sr3(insn);
- }
-
- CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
nullify_over(ctx);
- form_gva(ctx, &addr, &ofs, rb, 0, 0, 0, sp, 0, false);
- reg = load_gpr(ctx, rr);
- if (is_addr) {
+ form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
+ reg = load_gpr(ctx, a->r);
+ if (a->addr) {
gen_helper_itlba(cpu_env, addr, reg);
} else {
gen_helper_itlbp(cpu_env, addr, reg);
/* Exit TB for ITLB change if mmu is enabled. This *should* not be
the case, since the OS TLB fill handler runs with mmu disabled. */
- return nullify_end(ctx, !is_data && (ctx->tb_flags & PSW_C)
- ? DISAS_IAQ_N_STALE : DISAS_NEXT);
+ if (!a->data && (ctx->tb_flags & PSW_C)) {
+ ctx->base.is_jmp = DISAS_IAQ_N_STALE;
+ }
+ return nullify_end(ctx);
+#endif
}
-static DisasJumpType trans_pxtlbx(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_pxtlbx(DisasContext *ctx, arg_pxtlbx *a)
{
- unsigned m = extract32(insn, 5, 1);
- unsigned sp;
- unsigned rx = extract32(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
- unsigned is_data = insn & 0x1000;
- unsigned is_local = insn & 0x40;
+ CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+#ifndef CONFIG_USER_ONLY
TCGv_tl addr;
TCGv_reg ofs;
- if (is_data) {
- sp = extract32(insn, 14, 2);
- } else {
- sp = ~assemble_sr3(insn);
- }
-
- CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
nullify_over(ctx);
- form_gva(ctx, &addr, &ofs, rb, rx, 0, 0, sp, m, false);
- if (m) {
- save_gpr(ctx, rb, ofs);
+ form_gva(ctx, &addr, &ofs, a->b, a->x, 0, 0, a->sp, a->m, false);
+ if (a->m) {
+ save_gpr(ctx, a->b, ofs);
}
- if (is_local) {
+ if (a->local) {
gen_helper_ptlbe(cpu_env);
} else {
gen_helper_ptlb(cpu_env, addr);
}
/* Exit TB for TLB change if mmu is enabled. */
- return nullify_end(ctx, !is_data && (ctx->tb_flags & PSW_C)
- ? DISAS_IAQ_N_STALE : DISAS_NEXT);
+ if (!a->data && (ctx->tb_flags & PSW_C)) {
+ ctx->base.is_jmp = DISAS_IAQ_N_STALE;
+ }
+ return nullify_end(ctx);
+#endif
}
-static DisasJumpType trans_lpa(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_lpa(DisasContext *ctx, arg_ldst *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned m = extract32(insn, 5, 1);
- unsigned sp = extract32(insn, 14, 2);
- unsigned rx = extract32(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
+ CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+#ifndef CONFIG_USER_ONLY
TCGv_tl vaddr;
TCGv_reg ofs, paddr;
- CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
nullify_over(ctx);
- form_gva(ctx, &vaddr, &ofs, rb, rx, 0, 0, sp, m, false);
+ form_gva(ctx, &vaddr, &ofs, a->b, a->x, 0, 0, a->sp, a->m, false);
paddr = tcg_temp_new();
gen_helper_lpa(paddr, cpu_env, vaddr);
/* Note that physical address result overrides base modification. */
- if (m) {
- save_gpr(ctx, rb, ofs);
+ if (a->m) {
+ save_gpr(ctx, a->b, ofs);
}
- save_gpr(ctx, rt, paddr);
+ save_gpr(ctx, a->t, paddr);
tcg_temp_free(paddr);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
+#endif
}
-static DisasJumpType trans_lci(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_lci(DisasContext *ctx, arg_lci *a)
{
- unsigned rt = extract32(insn, 0, 5);
TCGv_reg ci;
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
view of the cache. Our implementation is to return 0 for all,
since the entire address space is coherent. */
ci = tcg_const_reg(0);
- save_gpr(ctx, rt, ci);
+ save_gpr(ctx, a->t, ci);
tcg_temp_free(ci);
- return DISAS_NEXT;
-}
-#endif /* !CONFIG_USER_ONLY */
-
-static const DisasInsn table_mem_mgmt[] = {
- { 0x04003280u, 0xfc003fffu, trans_nop }, /* fdc, disp */
- { 0x04001280u, 0xfc003fffu, trans_nop }, /* fdc, index */
- { 0x040012a0u, 0xfc003fffu, trans_base_idx_mod }, /* fdc, index, base mod */
- { 0x040012c0u, 0xfc003fffu, trans_nop }, /* fdce */
- { 0x040012e0u, 0xfc003fffu, trans_base_idx_mod }, /* fdce, base mod */
- { 0x04000280u, 0xfc001fffu, trans_nop }, /* fic 0a */
- { 0x040002a0u, 0xfc001fffu, trans_base_idx_mod }, /* fic 0a, base mod */
- { 0x040013c0u, 0xfc003fffu, trans_nop }, /* fic 4f */
- { 0x040013e0u, 0xfc003fffu, trans_base_idx_mod }, /* fic 4f, base mod */
- { 0x040002c0u, 0xfc001fffu, trans_nop }, /* fice */
- { 0x040002e0u, 0xfc001fffu, trans_base_idx_mod }, /* fice, base mod */
- { 0x04002700u, 0xfc003fffu, trans_nop }, /* pdc */
- { 0x04002720u, 0xfc003fffu, trans_base_idx_mod }, /* pdc, base mod */
- { 0x04001180u, 0xfc003fa0u, trans_probe }, /* probe */
- { 0x04003180u, 0xfc003fa0u, trans_probe }, /* probei */
-#ifndef CONFIG_USER_ONLY
- { 0x04000000u, 0xfc001fffu, trans_ixtlbx }, /* iitlbp */
- { 0x04000040u, 0xfc001fffu, trans_ixtlbx }, /* iitlba */
- { 0x04001000u, 0xfc001fffu, trans_ixtlbx }, /* idtlbp */
- { 0x04001040u, 0xfc001fffu, trans_ixtlbx }, /* idtlba */
- { 0x04000200u, 0xfc001fdfu, trans_pxtlbx }, /* pitlb */
- { 0x04000240u, 0xfc001fdfu, trans_pxtlbx }, /* pitlbe */
- { 0x04001200u, 0xfc001fdfu, trans_pxtlbx }, /* pdtlb */
- { 0x04001240u, 0xfc001fdfu, trans_pxtlbx }, /* pdtlbe */
- { 0x04001340u, 0xfc003fc0u, trans_lpa },
- { 0x04001300u, 0xfc003fe0u, trans_lci },
-#endif
-};
+ cond_free(&ctx->null_cond);
+ return true;
+}
-static DisasJumpType trans_add(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_add(DisasContext *ctx, arg_rrr_cf_sh *a)
{
- unsigned r2 = extract32(insn, 21, 5);
- unsigned r1 = extract32(insn, 16, 5);
- unsigned cf = extract32(insn, 12, 4);
- unsigned ext = extract32(insn, 8, 4);
- unsigned shift = extract32(insn, 6, 2);
- unsigned rt = extract32(insn, 0, 5);
- TCGv_reg tcg_r1, tcg_r2;
- bool is_c = false;
- bool is_l = false;
- bool is_tc = false;
- bool is_tsv = false;
- DisasJumpType ret;
+ return do_add_reg(ctx, a, false, false, false, false);
+}
- switch (ext) {
- case 0x6: /* ADD, SHLADD */
- break;
- case 0xa: /* ADD,L, SHLADD,L */
- is_l = true;
- break;
- case 0xe: /* ADD,TSV, SHLADD,TSV (1) */
- is_tsv = true;
- break;
- case 0x7: /* ADD,C */
- is_c = true;
- break;
- case 0xf: /* ADD,C,TSV */
- is_c = is_tsv = true;
- break;
- default:
- return gen_illegal(ctx);
- }
+static bool trans_add_l(DisasContext *ctx, arg_rrr_cf_sh *a)
+{
+ return do_add_reg(ctx, a, true, false, false, false);
+}
- if (cf) {
- nullify_over(ctx);
- }
- tcg_r1 = load_gpr(ctx, r1);
- tcg_r2 = load_gpr(ctx, r2);
- ret = do_add(ctx, rt, tcg_r1, tcg_r2, shift, is_l, is_tsv, is_tc, is_c, cf);
- return nullify_end(ctx, ret);
+static bool trans_add_tsv(DisasContext *ctx, arg_rrr_cf_sh *a)
+{
+ return do_add_reg(ctx, a, false, true, false, false);
}
-static DisasJumpType trans_sub(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_add_c(DisasContext *ctx, arg_rrr_cf_sh *a)
{
- unsigned r2 = extract32(insn, 21, 5);
- unsigned r1 = extract32(insn, 16, 5);
- unsigned cf = extract32(insn, 12, 4);
- unsigned ext = extract32(insn, 6, 6);
- unsigned rt = extract32(insn, 0, 5);
- TCGv_reg tcg_r1, tcg_r2;
- bool is_b = false;
- bool is_tc = false;
- bool is_tsv = false;
- DisasJumpType ret;
+ return do_add_reg(ctx, a, false, false, false, true);
+}
- switch (ext) {
- case 0x10: /* SUB */
- break;
- case 0x30: /* SUB,TSV */
- is_tsv = true;
- break;
- case 0x14: /* SUB,B */
- is_b = true;
- break;
- case 0x34: /* SUB,B,TSV */
- is_b = is_tsv = true;
- break;
- case 0x13: /* SUB,TC */
- is_tc = true;
- break;
- case 0x33: /* SUB,TSV,TC */
- is_tc = is_tsv = true;
- break;
- default:
- return gen_illegal(ctx);
- }
+static bool trans_add_c_tsv(DisasContext *ctx, arg_rrr_cf_sh *a)
+{
+ return do_add_reg(ctx, a, false, true, false, true);
+}
- if (cf) {
- nullify_over(ctx);
- }
- tcg_r1 = load_gpr(ctx, r1);
- tcg_r2 = load_gpr(ctx, r2);
- ret = do_sub(ctx, rt, tcg_r1, tcg_r2, is_tsv, is_b, is_tc, cf);
- return nullify_end(ctx, ret);
+static bool trans_sub(DisasContext *ctx, arg_rrr_cf *a)
+{
+ return do_sub_reg(ctx, a, false, false, false);
}
-static DisasJumpType trans_log(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_sub_tsv(DisasContext *ctx, arg_rrr_cf *a)
{
- unsigned r2 = extract32(insn, 21, 5);
- unsigned r1 = extract32(insn, 16, 5);
- unsigned cf = extract32(insn, 12, 4);
- unsigned rt = extract32(insn, 0, 5);
- TCGv_reg tcg_r1, tcg_r2;
- DisasJumpType ret;
+ return do_sub_reg(ctx, a, true, false, false);
+}
- if (cf) {
- nullify_over(ctx);
- }
- tcg_r1 = load_gpr(ctx, r1);
- tcg_r2 = load_gpr(ctx, r2);
- ret = do_log(ctx, rt, tcg_r1, tcg_r2, cf, di->f.ttt);
- return nullify_end(ctx, ret);
+static bool trans_sub_tc(DisasContext *ctx, arg_rrr_cf *a)
+{
+ return do_sub_reg(ctx, a, false, false, true);
}
-/* OR r,0,t -> COPY (according to gas) */
-static DisasJumpType trans_copy(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_sub_tsv_tc(DisasContext *ctx, arg_rrr_cf *a)
{
- unsigned r1 = extract32(insn, 16, 5);
- unsigned rt = extract32(insn, 0, 5);
+ return do_sub_reg(ctx, a, true, false, true);
+}
- if (r1 == 0) {
- TCGv_reg dest = dest_gpr(ctx, rt);
- tcg_gen_movi_reg(dest, 0);
- save_gpr(ctx, rt, dest);
- } else {
- save_gpr(ctx, rt, cpu_gr[r1]);
+static bool trans_sub_b(DisasContext *ctx, arg_rrr_cf *a)
+{
+ return do_sub_reg(ctx, a, false, true, false);
+}
+
+static bool trans_sub_b_tsv(DisasContext *ctx, arg_rrr_cf *a)
+{
+ return do_sub_reg(ctx, a, true, true, false);
+}
+
+static bool trans_andcm(DisasContext *ctx, arg_rrr_cf *a)
+{
+ return do_log_reg(ctx, a, tcg_gen_andc_reg);
+}
+
+static bool trans_and(DisasContext *ctx, arg_rrr_cf *a)
+{
+ return do_log_reg(ctx, a, tcg_gen_and_reg);
+}
+
+static bool trans_or(DisasContext *ctx, arg_rrr_cf *a)
+{
+ if (a->cf == 0) {
+ unsigned r2 = a->r2;
+ unsigned r1 = a->r1;
+ unsigned rt = a->t;
+
+ if (rt == 0) { /* NOP */
+ cond_free(&ctx->null_cond);
+ return true;
+ }
+ if (r2 == 0) { /* COPY */
+ if (r1 == 0) {
+ TCGv_reg dest = dest_gpr(ctx, rt);
+ tcg_gen_movi_reg(dest, 0);
+ save_gpr(ctx, rt, dest);
+ } else {
+ save_gpr(ctx, rt, cpu_gr[r1]);
+ }
+ cond_free(&ctx->null_cond);
+ return true;
+ }
+#ifndef CONFIG_USER_ONLY
+ /* These are QEMU extensions and are nops in the real architecture:
+ *
+ * or %r10,%r10,%r10 -- idle loop; wait for interrupt
+ * or %r31,%r31,%r31 -- death loop; offline cpu
+ * currently implemented as idle.
+ */
+ if ((rt == 10 || rt == 31) && r1 == rt && r2 == rt) { /* PAUSE */
+ TCGv_i32 tmp;
+
+ /* No need to check for supervisor, as userland can only pause
+ until the next timer interrupt. */
+ nullify_over(ctx);
+
+ /* Advance the instruction queue. */
+ copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
+ copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
+ nullify_set(ctx, 0);
+
+ /* Tell the qemu main loop to halt until this cpu has work. */
+ tmp = tcg_const_i32(1);
+ tcg_gen_st_i32(tmp, cpu_env, -offsetof(HPPACPU, env) +
+ offsetof(CPUState, halted));
+ tcg_temp_free_i32(tmp);
+ gen_excp_1(EXCP_HALTED);
+ ctx->base.is_jmp = DISAS_NORETURN;
+
+ return nullify_end(ctx);
+ }
+#endif
}
- cond_free(&ctx->null_cond);
- return DISAS_NEXT;
+ return do_log_reg(ctx, a, tcg_gen_or_reg);
}
-static DisasJumpType trans_cmpclr(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_xor(DisasContext *ctx, arg_rrr_cf *a)
+{
+ return do_log_reg(ctx, a, tcg_gen_xor_reg);
+}
+
+static bool trans_cmpclr(DisasContext *ctx, arg_rrr_cf *a)
{
- unsigned r2 = extract32(insn, 21, 5);
- unsigned r1 = extract32(insn, 16, 5);
- unsigned cf = extract32(insn, 12, 4);
- unsigned rt = extract32(insn, 0, 5);
TCGv_reg tcg_r1, tcg_r2;
- DisasJumpType ret;
- if (cf) {
+ if (a->cf) {
nullify_over(ctx);
}
- tcg_r1 = load_gpr(ctx, r1);
- tcg_r2 = load_gpr(ctx, r2);
- ret = do_cmpclr(ctx, rt, tcg_r1, tcg_r2, cf);
- return nullify_end(ctx, ret);
+ tcg_r1 = load_gpr(ctx, a->r1);
+ tcg_r2 = load_gpr(ctx, a->r2);
+ do_cmpclr(ctx, a->t, tcg_r1, tcg_r2, a->cf);
+ return nullify_end(ctx);
}
-static DisasJumpType trans_uxor(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_uxor(DisasContext *ctx, arg_rrr_cf *a)
{
- unsigned r2 = extract32(insn, 21, 5);
- unsigned r1 = extract32(insn, 16, 5);
- unsigned cf = extract32(insn, 12, 4);
- unsigned rt = extract32(insn, 0, 5);
TCGv_reg tcg_r1, tcg_r2;
- DisasJumpType ret;
- if (cf) {
+ if (a->cf) {
nullify_over(ctx);
}
- tcg_r1 = load_gpr(ctx, r1);
- tcg_r2 = load_gpr(ctx, r2);
- ret = do_unit(ctx, rt, tcg_r1, tcg_r2, cf, false, tcg_gen_xor_reg);
- return nullify_end(ctx, ret);
+ tcg_r1 = load_gpr(ctx, a->r1);
+ tcg_r2 = load_gpr(ctx, a->r2);
+ do_unit(ctx, a->t, tcg_r1, tcg_r2, a->cf, false, tcg_gen_xor_reg);
+ return nullify_end(ctx);
}
-static DisasJumpType trans_uaddcm(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool do_uaddcm(DisasContext *ctx, arg_rrr_cf *a, bool is_tc)
{
- unsigned r2 = extract32(insn, 21, 5);
- unsigned r1 = extract32(insn, 16, 5);
- unsigned cf = extract32(insn, 12, 4);
- unsigned is_tc = extract32(insn, 6, 1);
- unsigned rt = extract32(insn, 0, 5);
TCGv_reg tcg_r1, tcg_r2, tmp;
- DisasJumpType ret;
- if (cf) {
+ if (a->cf) {
nullify_over(ctx);
}
- tcg_r1 = load_gpr(ctx, r1);
- tcg_r2 = load_gpr(ctx, r2);
+ tcg_r1 = load_gpr(ctx, a->r1);
+ tcg_r2 = load_gpr(ctx, a->r2);
tmp = get_temp(ctx);
tcg_gen_not_reg(tmp, tcg_r2);
- ret = do_unit(ctx, rt, tcg_r1, tmp, cf, is_tc, tcg_gen_add_reg);
- return nullify_end(ctx, ret);
+ do_unit(ctx, a->t, tcg_r1, tmp, a->cf, is_tc, tcg_gen_add_reg);
+ return nullify_end(ctx);
}
-static DisasJumpType trans_dcor(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_uaddcm(DisasContext *ctx, arg_rrr_cf *a)
+{
+ return do_uaddcm(ctx, a, false);
+}
+
+static bool trans_uaddcm_tc(DisasContext *ctx, arg_rrr_cf *a)
+{
+ return do_uaddcm(ctx, a, true);
+}
+
+static bool do_dcor(DisasContext *ctx, arg_rr_cf *a, bool is_i)
{
- unsigned r2 = extract32(insn, 21, 5);
- unsigned cf = extract32(insn, 12, 4);
- unsigned is_i = extract32(insn, 6, 1);
- unsigned rt = extract32(insn, 0, 5);
TCGv_reg tmp;
- DisasJumpType ret;
nullify_over(ctx);
}
tcg_gen_andi_reg(tmp, tmp, 0x11111111);
tcg_gen_muli_reg(tmp, tmp, 6);
- ret = do_unit(ctx, rt, tmp, load_gpr(ctx, r2), cf, false,
- is_i ? tcg_gen_add_reg : tcg_gen_sub_reg);
+ do_unit(ctx, a->t, load_gpr(ctx, a->r), tmp, a->cf, false,
+ is_i ? tcg_gen_add_reg : tcg_gen_sub_reg);
+ return nullify_end(ctx);
+}
+
+static bool trans_dcor(DisasContext *ctx, arg_rr_cf *a)
+{
+ return do_dcor(ctx, a, false);
+}
- return nullify_end(ctx, ret);
+static bool trans_dcor_i(DisasContext *ctx, arg_rr_cf *a)
+{
+ return do_dcor(ctx, a, true);
}
-static DisasJumpType trans_ds(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a)
{
- unsigned r2 = extract32(insn, 21, 5);
- unsigned r1 = extract32(insn, 16, 5);
- unsigned cf = extract32(insn, 12, 4);
- unsigned rt = extract32(insn, 0, 5);
TCGv_reg dest, add1, add2, addc, zero, in1, in2;
nullify_over(ctx);
- in1 = load_gpr(ctx, r1);
- in2 = load_gpr(ctx, r2);
+ in1 = load_gpr(ctx, a->r1);
+ in2 = load_gpr(ctx, a->r2);
add1 = tcg_temp_new();
add2 = tcg_temp_new();
tcg_temp_free(zero);
/* Write back the result register. */
- save_gpr(ctx, rt, dest);
+ save_gpr(ctx, a->t, dest);
/* Write back PSW[CB]. */
tcg_gen_xor_reg(cpu_psw_cb, add1, add2);
tcg_gen_xor_reg(cpu_psw_v, cpu_psw_v, in2);
/* Install the new nullification. */
- if (cf) {
+ if (a->cf) {
TCGv_reg sv = NULL;
- if (cf >> 1 == 6) {
+ if (cond_need_sv(a->cf >> 1)) {
/* ??? The lshift is supposed to contribute to overflow. */
sv = do_add_sv(ctx, dest, add1, add2);
}
- ctx->null_cond = do_cond(cf, dest, cpu_psw_cb_msb, sv);
+ ctx->null_cond = do_cond(a->cf, dest, cpu_psw_cb_msb, sv);
}
tcg_temp_free(add1);
tcg_temp_free(add2);
tcg_temp_free(dest);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-#ifndef CONFIG_USER_ONLY
-/* These are QEMU extensions and are nops in the real architecture:
- *
- * or %r10,%r10,%r10 -- idle loop; wait for interrupt
- * or %r31,%r31,%r31 -- death loop; offline cpu
- * currently implemented as idle.
- */
-static DisasJumpType trans_pause(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_addi(DisasContext *ctx, arg_rri_cf *a)
{
- TCGv_i32 tmp;
-
- /* No need to check for supervisor, as userland can only pause
- until the next timer interrupt. */
- nullify_over(ctx);
-
- /* Advance the instruction queue. */
- copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
- copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
- nullify_set(ctx, 0);
-
- /* Tell the qemu main loop to halt until this cpu has work. */
- tmp = tcg_const_i32(1);
- tcg_gen_st_i32(tmp, cpu_env, -offsetof(HPPACPU, env) +
- offsetof(CPUState, halted));
- tcg_temp_free_i32(tmp);
- gen_excp_1(EXCP_HALTED);
-
- return nullify_end(ctx, DISAS_NORETURN);
+ return do_add_imm(ctx, a, false, false);
}
-#endif
-
-static const DisasInsn table_arith_log[] = {
- { 0x08000240u, 0xfc00ffffu, trans_nop }, /* or x,y,0 */
- { 0x08000240u, 0xffe0ffe0u, trans_copy }, /* or x,0,t */
-#ifndef CONFIG_USER_ONLY
- { 0x094a024au, 0xffffffffu, trans_pause }, /* or r10,r10,r10 */
- { 0x0bff025fu, 0xffffffffu, trans_pause }, /* or r31,r31,r31 */
-#endif
- { 0x08000000u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_andc_reg },
- { 0x08000200u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_and_reg },
- { 0x08000240u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_or_reg },
- { 0x08000280u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_xor_reg },
- { 0x08000880u, 0xfc000fe0u, trans_cmpclr },
- { 0x08000380u, 0xfc000fe0u, trans_uxor },
- { 0x08000980u, 0xfc000fa0u, trans_uaddcm },
- { 0x08000b80u, 0xfc1f0fa0u, trans_dcor },
- { 0x08000440u, 0xfc000fe0u, trans_ds },
- { 0x08000700u, 0xfc0007e0u, trans_add }, /* add */
- { 0x08000400u, 0xfc0006e0u, trans_sub }, /* sub; sub,b; sub,tsv */
- { 0x080004c0u, 0xfc0007e0u, trans_sub }, /* sub,tc; sub,tsv,tc */
- { 0x08000200u, 0xfc000320u, trans_add }, /* shladd */
-};
-static DisasJumpType trans_addi(DisasContext *ctx, uint32_t insn)
+static bool trans_addi_tsv(DisasContext *ctx, arg_rri_cf *a)
{
- target_sreg im = low_sextract(insn, 0, 11);
- unsigned e1 = extract32(insn, 11, 1);
- unsigned cf = extract32(insn, 12, 4);
- unsigned rt = extract32(insn, 16, 5);
- unsigned r2 = extract32(insn, 21, 5);
- unsigned o1 = extract32(insn, 26, 1);
- TCGv_reg tcg_im, tcg_r2;
- DisasJumpType ret;
-
- if (cf) {
- nullify_over(ctx);
- }
-
- tcg_im = load_const(ctx, im);
- tcg_r2 = load_gpr(ctx, r2);
- ret = do_add(ctx, rt, tcg_im, tcg_r2, 0, false, e1, !o1, false, cf);
-
- return nullify_end(ctx, ret);
+ return do_add_imm(ctx, a, true, false);
}
-static DisasJumpType trans_subi(DisasContext *ctx, uint32_t insn)
+static bool trans_addi_tc(DisasContext *ctx, arg_rri_cf *a)
{
- target_sreg im = low_sextract(insn, 0, 11);
- unsigned e1 = extract32(insn, 11, 1);
- unsigned cf = extract32(insn, 12, 4);
- unsigned rt = extract32(insn, 16, 5);
- unsigned r2 = extract32(insn, 21, 5);
- TCGv_reg tcg_im, tcg_r2;
- DisasJumpType ret;
+ return do_add_imm(ctx, a, false, true);
+}
- if (cf) {
- nullify_over(ctx);
- }
+static bool trans_addi_tc_tsv(DisasContext *ctx, arg_rri_cf *a)
+{
+ return do_add_imm(ctx, a, true, true);
+}
- tcg_im = load_const(ctx, im);
- tcg_r2 = load_gpr(ctx, r2);
- ret = do_sub(ctx, rt, tcg_im, tcg_r2, e1, false, false, cf);
+static bool trans_subi(DisasContext *ctx, arg_rri_cf *a)
+{
+ return do_sub_imm(ctx, a, false);
+}
- return nullify_end(ctx, ret);
+static bool trans_subi_tsv(DisasContext *ctx, arg_rri_cf *a)
+{
+ return do_sub_imm(ctx, a, true);
}
-static DisasJumpType trans_cmpiclr(DisasContext *ctx, uint32_t insn)
+static bool trans_cmpiclr(DisasContext *ctx, arg_rri_cf *a)
{
- target_sreg im = low_sextract(insn, 0, 11);
- unsigned cf = extract32(insn, 12, 4);
- unsigned rt = extract32(insn, 16, 5);
- unsigned r2 = extract32(insn, 21, 5);
TCGv_reg tcg_im, tcg_r2;
- DisasJumpType ret;
- if (cf) {
+ if (a->cf) {
nullify_over(ctx);
}
- tcg_im = load_const(ctx, im);
- tcg_r2 = load_gpr(ctx, r2);
- ret = do_cmpclr(ctx, rt, tcg_im, tcg_r2, cf);
+ tcg_im = load_const(ctx, a->i);
+ tcg_r2 = load_gpr(ctx, a->r);
+ do_cmpclr(ctx, a->t, tcg_im, tcg_r2, a->cf);
- return nullify_end(ctx, ret);
+ return nullify_end(ctx);
}
-static DisasJumpType trans_ld_idx_i(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_ld(DisasContext *ctx, arg_ldst *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned m = extract32(insn, 5, 1);
- unsigned sz = extract32(insn, 6, 2);
- unsigned a = extract32(insn, 13, 1);
- unsigned sp = extract32(insn, 14, 2);
- int disp = low_sextract(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
- int modify = (m ? (a ? -1 : 1) : 0);
- TCGMemOp mop = MO_TE | sz;
-
- return do_load(ctx, rt, rb, 0, 0, disp, sp, modify, mop);
+ return do_load(ctx, a->t, a->b, a->x, a->scale ? a->size : 0,
+ a->disp, a->sp, a->m, a->size | MO_TE);
}
-static DisasJumpType trans_ld_idx_x(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_st(DisasContext *ctx, arg_ldst *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned m = extract32(insn, 5, 1);
- unsigned sz = extract32(insn, 6, 2);
- unsigned u = extract32(insn, 13, 1);
- unsigned sp = extract32(insn, 14, 2);
- unsigned rx = extract32(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
- TCGMemOp mop = MO_TE | sz;
-
- return do_load(ctx, rt, rb, rx, u ? sz : 0, 0, sp, m, mop);
-}
-
-static DisasJumpType trans_st_idx_i(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
-{
- int disp = low_sextract(insn, 0, 5);
- unsigned m = extract32(insn, 5, 1);
- unsigned sz = extract32(insn, 6, 2);
- unsigned a = extract32(insn, 13, 1);
- unsigned sp = extract32(insn, 14, 2);
- unsigned rr = extract32(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
- int modify = (m ? (a ? -1 : 1) : 0);
- TCGMemOp mop = MO_TE | sz;
-
- return do_store(ctx, rr, rb, disp, sp, modify, mop);
+ assert(a->x == 0 && a->scale == 0);
+ return do_store(ctx, a->t, a->b, a->disp, a->sp, a->m, a->size | MO_TE);
}
-static DisasJumpType trans_ldcw(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_ldc(DisasContext *ctx, arg_ldst *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned m = extract32(insn, 5, 1);
- unsigned i = extract32(insn, 12, 1);
- unsigned au = extract32(insn, 13, 1);
- unsigned sp = extract32(insn, 14, 2);
- unsigned rx = extract32(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
- TCGMemOp mop = MO_TEUL | MO_ALIGN_16;
+ TCGMemOp mop = MO_TEUL | MO_ALIGN_16 | a->size;
TCGv_reg zero, dest, ofs;
TCGv_tl addr;
- int modify, disp = 0, scale = 0;
nullify_over(ctx);
- if (i) {
- modify = (m ? (au ? -1 : 1) : 0);
- disp = low_sextract(rx, 0, 5);
- rx = 0;
- } else {
- modify = m;
- if (au) {
- scale = mop & MO_SIZE;
- }
- }
- if (modify) {
+ if (a->m) {
/* Base register modification. Make sure if RT == RB,
we see the result of the load. */
dest = get_temp(ctx);
} else {
- dest = dest_gpr(ctx, rt);
+ dest = dest_gpr(ctx, a->t);
}
- form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
- ctx->mmu_idx == MMU_PHYS_IDX);
+ form_gva(ctx, &addr, &ofs, a->b, a->x, a->scale ? a->size : 0,
+ a->disp, a->sp, a->m, ctx->mmu_idx == MMU_PHYS_IDX);
zero = tcg_const_reg(0);
tcg_gen_atomic_xchg_reg(dest, addr, zero, ctx->mmu_idx, mop);
- if (modify) {
- save_gpr(ctx, rb, ofs);
+ if (a->m) {
+ save_gpr(ctx, a->b, ofs);
}
- save_gpr(ctx, rt, dest);
+ save_gpr(ctx, a->t, dest);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType trans_stby(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_stby(DisasContext *ctx, arg_stby *a)
{
- target_sreg disp = low_sextract(insn, 0, 5);
- unsigned m = extract32(insn, 5, 1);
- unsigned a = extract32(insn, 13, 1);
- unsigned sp = extract32(insn, 14, 2);
- unsigned rt = extract32(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
TCGv_reg ofs, val;
TCGv_tl addr;
nullify_over(ctx);
- form_gva(ctx, &addr, &ofs, rb, 0, 0, disp, sp, m,
+ form_gva(ctx, &addr, &ofs, a->b, 0, 0, a->disp, a->sp, a->m,
ctx->mmu_idx == MMU_PHYS_IDX);
- val = load_gpr(ctx, rt);
- if (a) {
+ val = load_gpr(ctx, a->r);
+ if (a->a) {
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
gen_helper_stby_e_parallel(cpu_env, addr, val);
} else {
gen_helper_stby_b(cpu_env, addr, val);
}
}
-
- if (m) {
+ if (a->m) {
tcg_gen_andi_reg(ofs, ofs, ~3);
- save_gpr(ctx, rb, ofs);
+ save_gpr(ctx, a->b, ofs);
}
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-#ifndef CONFIG_USER_ONLY
-static DisasJumpType trans_ldwa_idx_i(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_lda(DisasContext *ctx, arg_ldst *a)
{
int hold_mmu_idx = ctx->mmu_idx;
- DisasJumpType ret;
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
-
- /* ??? needs fixing for hppa64 -- ldda does not follow the same
- format wrt the sub-opcode in bits 6:9. */
ctx->mmu_idx = MMU_PHYS_IDX;
- ret = trans_ld_idx_i(ctx, insn, di);
+ trans_ld(ctx, a);
ctx->mmu_idx = hold_mmu_idx;
- return ret;
-}
-
-static DisasJumpType trans_ldwa_idx_x(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
-{
- int hold_mmu_idx = ctx->mmu_idx;
- DisasJumpType ret;
-
- CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
-
- /* ??? needs fixing for hppa64 -- ldda does not follow the same
- format wrt the sub-opcode in bits 6:9. */
- ctx->mmu_idx = MMU_PHYS_IDX;
- ret = trans_ld_idx_x(ctx, insn, di);
- ctx->mmu_idx = hold_mmu_idx;
- return ret;
+ return true;
}
-static DisasJumpType trans_stwa_idx_i(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_sta(DisasContext *ctx, arg_ldst *a)
{
int hold_mmu_idx = ctx->mmu_idx;
- DisasJumpType ret;
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
-
- /* ??? needs fixing for hppa64 -- ldda does not follow the same
- format wrt the sub-opcode in bits 6:9. */
ctx->mmu_idx = MMU_PHYS_IDX;
- ret = trans_st_idx_i(ctx, insn, di);
+ trans_st(ctx, a);
ctx->mmu_idx = hold_mmu_idx;
- return ret;
+ return true;
}
-#endif
-
-static const DisasInsn table_index_mem[] = {
- { 0x0c001000u, 0xfc001300, trans_ld_idx_i }, /* LD[BHWD], im */
- { 0x0c000000u, 0xfc001300, trans_ld_idx_x }, /* LD[BHWD], rx */
- { 0x0c001200u, 0xfc001300, trans_st_idx_i }, /* ST[BHWD] */
- { 0x0c0001c0u, 0xfc0003c0, trans_ldcw },
- { 0x0c001300u, 0xfc0013c0, trans_stby },
-#ifndef CONFIG_USER_ONLY
- { 0x0c000180u, 0xfc00d3c0, trans_ldwa_idx_x }, /* LDWA, rx */
- { 0x0c001180u, 0xfc00d3c0, trans_ldwa_idx_i }, /* LDWA, im */
- { 0x0c001380u, 0xfc00d3c0, trans_stwa_idx_i }, /* STWA, im */
-#endif
-};
-static DisasJumpType trans_ldil(DisasContext *ctx, uint32_t insn)
+static bool trans_ldil(DisasContext *ctx, arg_ldil *a)
{
- unsigned rt = extract32(insn, 21, 5);
- target_sreg i = assemble_21(insn);
- TCGv_reg tcg_rt = dest_gpr(ctx, rt);
+ TCGv_reg tcg_rt = dest_gpr(ctx, a->t);
- tcg_gen_movi_reg(tcg_rt, i);
- save_gpr(ctx, rt, tcg_rt);
+ tcg_gen_movi_reg(tcg_rt, a->i);
+ save_gpr(ctx, a->t, tcg_rt);
cond_free(&ctx->null_cond);
-
- return DISAS_NEXT;
+ return true;
}
-static DisasJumpType trans_addil(DisasContext *ctx, uint32_t insn)
+static bool trans_addil(DisasContext *ctx, arg_addil *a)
{
- unsigned rt = extract32(insn, 21, 5);
- target_sreg i = assemble_21(insn);
- TCGv_reg tcg_rt = load_gpr(ctx, rt);
+ TCGv_reg tcg_rt = load_gpr(ctx, a->r);
TCGv_reg tcg_r1 = dest_gpr(ctx, 1);
- tcg_gen_addi_reg(tcg_r1, tcg_rt, i);
+ tcg_gen_addi_reg(tcg_r1, tcg_rt, a->i);
save_gpr(ctx, 1, tcg_r1);
cond_free(&ctx->null_cond);
-
- return DISAS_NEXT;
+ return true;
}
-static DisasJumpType trans_ldo(DisasContext *ctx, uint32_t insn)
+static bool trans_ldo(DisasContext *ctx, arg_ldo *a)
{
- unsigned rb = extract32(insn, 21, 5);
- unsigned rt = extract32(insn, 16, 5);
- target_sreg i = assemble_16(insn);
- TCGv_reg tcg_rt = dest_gpr(ctx, rt);
+ TCGv_reg tcg_rt = dest_gpr(ctx, a->t);
/* Special case rb == 0, for the LDI pseudo-op.
The COPY pseudo-op is handled for free within tcg_gen_addi_tl. */
- if (rb == 0) {
- tcg_gen_movi_reg(tcg_rt, i);
+ if (a->b == 0) {
+ tcg_gen_movi_reg(tcg_rt, a->i);
} else {
- tcg_gen_addi_reg(tcg_rt, cpu_gr[rb], i);
+ tcg_gen_addi_reg(tcg_rt, cpu_gr[a->b], a->i);
}
- save_gpr(ctx, rt, tcg_rt);
+ save_gpr(ctx, a->t, tcg_rt);
cond_free(&ctx->null_cond);
-
- return DISAS_NEXT;
+ return true;
}
-static DisasJumpType trans_load(DisasContext *ctx, uint32_t insn,
- bool is_mod, TCGMemOp mop)
+static bool do_cmpb(DisasContext *ctx, unsigned r, TCGv_reg in1,
+ unsigned c, unsigned f, unsigned n, int disp)
{
- unsigned rb = extract32(insn, 21, 5);
- unsigned rt = extract32(insn, 16, 5);
- unsigned sp = extract32(insn, 14, 2);
- target_sreg i = assemble_16(insn);
+ TCGv_reg dest, in2, sv;
+ DisasCond cond;
- return do_load(ctx, rt, rb, 0, 0, i, sp,
- is_mod ? (i < 0 ? -1 : 1) : 0, mop);
-}
+ in2 = load_gpr(ctx, r);
+ dest = get_temp(ctx);
-static DisasJumpType trans_load_w(DisasContext *ctx, uint32_t insn)
-{
- unsigned rb = extract32(insn, 21, 5);
- unsigned rt = extract32(insn, 16, 5);
- unsigned sp = extract32(insn, 14, 2);
- target_sreg i = assemble_16a(insn);
- unsigned ext2 = extract32(insn, 1, 2);
+ tcg_gen_sub_reg(dest, in1, in2);
- switch (ext2) {
- case 0:
- case 1:
- /* FLDW without modification. */
- return do_floadw(ctx, ext2 * 32 + rt, rb, 0, 0, i, sp, 0);
- case 2:
- /* LDW with modification. Note that the sign of I selects
- post-dec vs pre-inc. */
- return do_load(ctx, rt, rb, 0, 0, i, sp, (i < 0 ? 1 : -1), MO_TEUL);
- default:
- return gen_illegal(ctx);
+ sv = NULL;
+ if (cond_need_sv(c)) {
+ sv = do_sub_sv(ctx, dest, in1, in2);
}
+
+ cond = do_sub_cond(c * 2 + f, dest, in1, in2, sv);
+ return do_cbranch(ctx, disp, n, &cond);
}
-static DisasJumpType trans_fload_mod(DisasContext *ctx, uint32_t insn)
+static bool trans_cmpb(DisasContext *ctx, arg_cmpb *a)
{
- target_sreg i = assemble_16a(insn);
- unsigned t1 = extract32(insn, 1, 1);
- unsigned a = extract32(insn, 2, 1);
- unsigned sp = extract32(insn, 14, 2);
- unsigned t0 = extract32(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
-
- /* FLDW with modification. */
- return do_floadw(ctx, t1 * 32 + t0, rb, 0, 0, i, sp, (a ? -1 : 1));
+ nullify_over(ctx);
+ return do_cmpb(ctx, a->r2, load_gpr(ctx, a->r1), a->c, a->f, a->n, a->disp);
}
-static DisasJumpType trans_store(DisasContext *ctx, uint32_t insn,
- bool is_mod, TCGMemOp mop)
+static bool trans_cmpbi(DisasContext *ctx, arg_cmpbi *a)
{
- unsigned rb = extract32(insn, 21, 5);
- unsigned rt = extract32(insn, 16, 5);
- unsigned sp = extract32(insn, 14, 2);
- target_sreg i = assemble_16(insn);
-
- return do_store(ctx, rt, rb, i, sp, is_mod ? (i < 0 ? -1 : 1) : 0, mop);
+ nullify_over(ctx);
+ return do_cmpb(ctx, a->r, load_const(ctx, a->i), a->c, a->f, a->n, a->disp);
}
-static DisasJumpType trans_store_w(DisasContext *ctx, uint32_t insn)
+static bool do_addb(DisasContext *ctx, unsigned r, TCGv_reg in1,
+ unsigned c, unsigned f, unsigned n, int disp)
{
- unsigned rb = extract32(insn, 21, 5);
- unsigned rt = extract32(insn, 16, 5);
- unsigned sp = extract32(insn, 14, 2);
- target_sreg i = assemble_16a(insn);
- unsigned ext2 = extract32(insn, 1, 2);
+ TCGv_reg dest, in2, sv, cb_msb;
+ DisasCond cond;
- switch (ext2) {
- case 0:
- case 1:
- /* FSTW without modification. */
- return do_fstorew(ctx, ext2 * 32 + rt, rb, 0, 0, i, sp, 0);
- case 2:
- /* STW with modification. */
- return do_store(ctx, rt, rb, i, sp, (i < 0 ? 1 : -1), MO_TEUL);
- default:
- return gen_illegal(ctx);
+ in2 = load_gpr(ctx, r);
+ dest = dest_gpr(ctx, r);
+ sv = NULL;
+ cb_msb = NULL;
+
+ if (cond_need_cb(c)) {
+ cb_msb = get_temp(ctx);
+ tcg_gen_movi_reg(cb_msb, 0);
+ tcg_gen_add2_reg(dest, cb_msb, in1, cb_msb, in2, cb_msb);
+ } else {
+ tcg_gen_add_reg(dest, in1, in2);
}
+ if (cond_need_sv(c)) {
+ sv = do_add_sv(ctx, dest, in1, in2);
+ }
+
+ cond = do_cond(c * 2 + f, dest, cb_msb, sv);
+ return do_cbranch(ctx, disp, n, &cond);
}
-static DisasJumpType trans_fstore_mod(DisasContext *ctx, uint32_t insn)
+static bool trans_addb(DisasContext *ctx, arg_addb *a)
{
- target_sreg i = assemble_16a(insn);
- unsigned t1 = extract32(insn, 1, 1);
- unsigned a = extract32(insn, 2, 1);
- unsigned sp = extract32(insn, 14, 2);
- unsigned t0 = extract32(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
-
- /* FSTW with modification. */
- return do_fstorew(ctx, t1 * 32 + t0, rb, 0, 0, i, sp, (a ? -1 : 1));
+ nullify_over(ctx);
+ return do_addb(ctx, a->r2, load_gpr(ctx, a->r1), a->c, a->f, a->n, a->disp);
}
-static DisasJumpType trans_copr_w(DisasContext *ctx, uint32_t insn)
+static bool trans_addbi(DisasContext *ctx, arg_addbi *a)
{
- unsigned t0 = extract32(insn, 0, 5);
- unsigned m = extract32(insn, 5, 1);
- unsigned t1 = extract32(insn, 6, 1);
- unsigned ext3 = extract32(insn, 7, 3);
- /* unsigned cc = extract32(insn, 10, 2); */
- unsigned i = extract32(insn, 12, 1);
- unsigned ua = extract32(insn, 13, 1);
- unsigned sp = extract32(insn, 14, 2);
- unsigned rx = extract32(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
- unsigned rt = t1 * 32 + t0;
- int modify = (m ? (ua ? -1 : 1) : 0);
- int disp, scale;
-
- if (i == 0) {
- scale = (ua ? 2 : 0);
- disp = 0;
- modify = m;
- } else {
- disp = low_sextract(rx, 0, 5);
- scale = 0;
- rx = 0;
- modify = (m ? (ua ? -1 : 1) : 0);
- }
-
- switch (ext3) {
- case 0: /* FLDW */
- return do_floadw(ctx, rt, rb, rx, scale, disp, sp, modify);
- case 4: /* FSTW */
- return do_fstorew(ctx, rt, rb, rx, scale, disp, sp, modify);
- }
- return gen_illegal(ctx);
-}
-
-static DisasJumpType trans_copr_dw(DisasContext *ctx, uint32_t insn)
-{
- unsigned rt = extract32(insn, 0, 5);
- unsigned m = extract32(insn, 5, 1);
- unsigned ext4 = extract32(insn, 6, 4);
- /* unsigned cc = extract32(insn, 10, 2); */
- unsigned i = extract32(insn, 12, 1);
- unsigned ua = extract32(insn, 13, 1);
- unsigned sp = extract32(insn, 14, 2);
- unsigned rx = extract32(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
- int modify = (m ? (ua ? -1 : 1) : 0);
- int disp, scale;
-
- if (i == 0) {
- scale = (ua ? 3 : 0);
- disp = 0;
- modify = m;
- } else {
- disp = low_sextract(rx, 0, 5);
- scale = 0;
- rx = 0;
- modify = (m ? (ua ? -1 : 1) : 0);
- }
-
- switch (ext4) {
- case 0: /* FLDD */
- return do_floadd(ctx, rt, rb, rx, scale, disp, sp, modify);
- case 8: /* FSTD */
- return do_fstored(ctx, rt, rb, rx, scale, disp, sp, modify);
- default:
- return gen_illegal(ctx);
- }
+ nullify_over(ctx);
+ return do_addb(ctx, a->r, load_const(ctx, a->i), a->c, a->f, a->n, a->disp);
}
-static DisasJumpType trans_cmpb(DisasContext *ctx, uint32_t insn,
- bool is_true, bool is_imm, bool is_dw)
+static bool trans_bb_sar(DisasContext *ctx, arg_bb_sar *a)
{
- target_sreg disp = assemble_12(insn) * 4;
- unsigned n = extract32(insn, 1, 1);
- unsigned c = extract32(insn, 13, 3);
- unsigned r = extract32(insn, 21, 5);
- unsigned cf = c * 2 + !is_true;
- TCGv_reg dest, in1, in2, sv;
+ TCGv_reg tmp, tcg_r;
DisasCond cond;
nullify_over(ctx);
- if (is_imm) {
- in1 = load_const(ctx, low_sextract(insn, 16, 5));
- } else {
- in1 = load_gpr(ctx, extract32(insn, 16, 5));
- }
- in2 = load_gpr(ctx, r);
- dest = get_temp(ctx);
-
- tcg_gen_sub_reg(dest, in1, in2);
-
- sv = NULL;
- if (c == 6) {
- sv = do_sub_sv(ctx, dest, in1, in2);
- }
+ tmp = tcg_temp_new();
+ tcg_r = load_gpr(ctx, a->r);
+ tcg_gen_shl_reg(tmp, tcg_r, cpu_sar);
- cond = do_sub_cond(cf, dest, in1, in2, sv);
- return do_cbranch(ctx, disp, n, &cond);
+ cond = cond_make_0(a->c ? TCG_COND_GE : TCG_COND_LT, tmp);
+ tcg_temp_free(tmp);
+ return do_cbranch(ctx, a->disp, a->n, &cond);
}
-static DisasJumpType trans_addb(DisasContext *ctx, uint32_t insn,
- bool is_true, bool is_imm)
+static bool trans_bb_imm(DisasContext *ctx, arg_bb_imm *a)
{
- target_sreg disp = assemble_12(insn) * 4;
- unsigned n = extract32(insn, 1, 1);
- unsigned c = extract32(insn, 13, 3);
- unsigned r = extract32(insn, 21, 5);
- unsigned cf = c * 2 + !is_true;
- TCGv_reg dest, in1, in2, sv, cb_msb;
+ TCGv_reg tmp, tcg_r;
DisasCond cond;
nullify_over(ctx);
- if (is_imm) {
- in1 = load_const(ctx, low_sextract(insn, 16, 5));
- } else {
- in1 = load_gpr(ctx, extract32(insn, 16, 5));
- }
- in2 = load_gpr(ctx, r);
- dest = dest_gpr(ctx, r);
- sv = NULL;
- cb_msb = NULL;
-
- switch (c) {
- default:
- tcg_gen_add_reg(dest, in1, in2);
- break;
- case 4: case 5:
- cb_msb = get_temp(ctx);
- tcg_gen_movi_reg(cb_msb, 0);
- tcg_gen_add2_reg(dest, cb_msb, in1, cb_msb, in2, cb_msb);
- break;
- case 6:
- tcg_gen_add_reg(dest, in1, in2);
- sv = do_add_sv(ctx, dest, in1, in2);
- break;
- }
+ tmp = tcg_temp_new();
+ tcg_r = load_gpr(ctx, a->r);
+ tcg_gen_shli_reg(tmp, tcg_r, a->p);
- cond = do_cond(cf, dest, cb_msb, sv);
- return do_cbranch(ctx, disp, n, &cond);
+ cond = cond_make_0(a->c ? TCG_COND_GE : TCG_COND_LT, tmp);
+ tcg_temp_free(tmp);
+ return do_cbranch(ctx, a->disp, a->n, &cond);
}
-static DisasJumpType trans_bb(DisasContext *ctx, uint32_t insn)
+static bool trans_movb(DisasContext *ctx, arg_movb *a)
{
- target_sreg disp = assemble_12(insn) * 4;
- unsigned n = extract32(insn, 1, 1);
- unsigned c = extract32(insn, 15, 1);
- unsigned r = extract32(insn, 16, 5);
- unsigned p = extract32(insn, 21, 5);
- unsigned i = extract32(insn, 26, 1);
- TCGv_reg tmp, tcg_r;
+ TCGv_reg dest;
DisasCond cond;
nullify_over(ctx);
- tmp = tcg_temp_new();
- tcg_r = load_gpr(ctx, r);
- if (i) {
- tcg_gen_shli_reg(tmp, tcg_r, p);
+ dest = dest_gpr(ctx, a->r2);
+ if (a->r1 == 0) {
+ tcg_gen_movi_reg(dest, 0);
} else {
- tcg_gen_shl_reg(tmp, tcg_r, cpu_sar);
+ tcg_gen_mov_reg(dest, cpu_gr[a->r1]);
}
- cond = cond_make_0(c ? TCG_COND_GE : TCG_COND_LT, tmp);
- tcg_temp_free(tmp);
- return do_cbranch(ctx, disp, n, &cond);
+ cond = do_sed_cond(a->c, dest);
+ return do_cbranch(ctx, a->disp, a->n, &cond);
}
-static DisasJumpType trans_movb(DisasContext *ctx, uint32_t insn, bool is_imm)
+static bool trans_movbi(DisasContext *ctx, arg_movbi *a)
{
- target_sreg disp = assemble_12(insn) * 4;
- unsigned n = extract32(insn, 1, 1);
- unsigned c = extract32(insn, 13, 3);
- unsigned t = extract32(insn, 16, 5);
- unsigned r = extract32(insn, 21, 5);
TCGv_reg dest;
DisasCond cond;
nullify_over(ctx);
- dest = dest_gpr(ctx, r);
- if (is_imm) {
- tcg_gen_movi_reg(dest, low_sextract(t, 0, 5));
- } else if (t == 0) {
- tcg_gen_movi_reg(dest, 0);
- } else {
- tcg_gen_mov_reg(dest, cpu_gr[t]);
- }
+ dest = dest_gpr(ctx, a->r);
+ tcg_gen_movi_reg(dest, a->i);
- cond = do_sed_cond(c, dest);
- return do_cbranch(ctx, disp, n, &cond);
+ cond = do_sed_cond(a->c, dest);
+ return do_cbranch(ctx, a->disp, a->n, &cond);
}
-static DisasJumpType trans_shrpw_sar(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_shrpw_sar(DisasContext *ctx, arg_shrpw_sar *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned c = extract32(insn, 13, 3);
- unsigned r1 = extract32(insn, 16, 5);
- unsigned r2 = extract32(insn, 21, 5);
TCGv_reg dest;
- if (c) {
+ if (a->c) {
nullify_over(ctx);
}
- dest = dest_gpr(ctx, rt);
- if (r1 == 0) {
- tcg_gen_ext32u_reg(dest, load_gpr(ctx, r2));
+ dest = dest_gpr(ctx, a->t);
+ if (a->r1 == 0) {
+ tcg_gen_ext32u_reg(dest, load_gpr(ctx, a->r2));
tcg_gen_shr_reg(dest, dest, cpu_sar);
- } else if (r1 == r2) {
+ } else if (a->r1 == a->r2) {
TCGv_i32 t32 = tcg_temp_new_i32();
- tcg_gen_trunc_reg_i32(t32, load_gpr(ctx, r2));
+ tcg_gen_trunc_reg_i32(t32, load_gpr(ctx, a->r2));
tcg_gen_rotr_i32(t32, t32, cpu_sar);
tcg_gen_extu_i32_reg(dest, t32);
tcg_temp_free_i32(t32);
TCGv_i64 t = tcg_temp_new_i64();
TCGv_i64 s = tcg_temp_new_i64();
- tcg_gen_concat_reg_i64(t, load_gpr(ctx, r2), load_gpr(ctx, r1));
+ tcg_gen_concat_reg_i64(t, load_gpr(ctx, a->r2), load_gpr(ctx, a->r1));
tcg_gen_extu_reg_i64(s, cpu_sar);
tcg_gen_shr_i64(t, t, s);
tcg_gen_trunc_i64_reg(dest, t);
tcg_temp_free_i64(t);
tcg_temp_free_i64(s);
}
- save_gpr(ctx, rt, dest);
+ save_gpr(ctx, a->t, dest);
/* Install the new nullification. */
cond_free(&ctx->null_cond);
- if (c) {
- ctx->null_cond = do_sed_cond(c, dest);
+ if (a->c) {
+ ctx->null_cond = do_sed_cond(a->c, dest);
}
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType trans_shrpw_imm(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_shrpw_imm(DisasContext *ctx, arg_shrpw_imm *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned cpos = extract32(insn, 5, 5);
- unsigned c = extract32(insn, 13, 3);
- unsigned r1 = extract32(insn, 16, 5);
- unsigned r2 = extract32(insn, 21, 5);
- unsigned sa = 31 - cpos;
+ unsigned sa = 31 - a->cpos;
TCGv_reg dest, t2;
- if (c) {
+ if (a->c) {
nullify_over(ctx);
}
- dest = dest_gpr(ctx, rt);
- t2 = load_gpr(ctx, r2);
- if (r1 == r2) {
+ dest = dest_gpr(ctx, a->t);
+ t2 = load_gpr(ctx, a->r2);
+ if (a->r1 == a->r2) {
TCGv_i32 t32 = tcg_temp_new_i32();
tcg_gen_trunc_reg_i32(t32, t2);
tcg_gen_rotri_i32(t32, t32, sa);
tcg_gen_extu_i32_reg(dest, t32);
tcg_temp_free_i32(t32);
- } else if (r1 == 0) {
+ } else if (a->r1 == 0) {
tcg_gen_extract_reg(dest, t2, sa, 32 - sa);
} else {
TCGv_reg t0 = tcg_temp_new();
tcg_gen_extract_reg(t0, t2, sa, 32 - sa);
- tcg_gen_deposit_reg(dest, t0, cpu_gr[r1], 32 - sa, sa);
+ tcg_gen_deposit_reg(dest, t0, cpu_gr[a->r1], 32 - sa, sa);
tcg_temp_free(t0);
}
- save_gpr(ctx, rt, dest);
+ save_gpr(ctx, a->t, dest);
/* Install the new nullification. */
cond_free(&ctx->null_cond);
- if (c) {
- ctx->null_cond = do_sed_cond(c, dest);
+ if (a->c) {
+ ctx->null_cond = do_sed_cond(a->c, dest);
}
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType trans_extrw_sar(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_extrw_sar(DisasContext *ctx, arg_extrw_sar *a)
{
- unsigned clen = extract32(insn, 0, 5);
- unsigned is_se = extract32(insn, 10, 1);
- unsigned c = extract32(insn, 13, 3);
- unsigned rt = extract32(insn, 16, 5);
- unsigned rr = extract32(insn, 21, 5);
- unsigned len = 32 - clen;
+ unsigned len = 32 - a->clen;
TCGv_reg dest, src, tmp;
- if (c) {
+ if (a->c) {
nullify_over(ctx);
}
- dest = dest_gpr(ctx, rt);
- src = load_gpr(ctx, rr);
+ dest = dest_gpr(ctx, a->t);
+ src = load_gpr(ctx, a->r);
tmp = tcg_temp_new();
/* Recall that SAR is using big-endian bit numbering. */
tcg_gen_xori_reg(tmp, cpu_sar, TARGET_REGISTER_BITS - 1);
- if (is_se) {
+ if (a->se) {
tcg_gen_sar_reg(dest, src, tmp);
tcg_gen_sextract_reg(dest, dest, 0, len);
} else {
tcg_gen_extract_reg(dest, dest, 0, len);
}
tcg_temp_free(tmp);
- save_gpr(ctx, rt, dest);
+ save_gpr(ctx, a->t, dest);
/* Install the new nullification. */
cond_free(&ctx->null_cond);
- if (c) {
- ctx->null_cond = do_sed_cond(c, dest);
+ if (a->c) {
+ ctx->null_cond = do_sed_cond(a->c, dest);
}
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType trans_extrw_imm(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_extrw_imm(DisasContext *ctx, arg_extrw_imm *a)
{
- unsigned clen = extract32(insn, 0, 5);
- unsigned pos = extract32(insn, 5, 5);
- unsigned is_se = extract32(insn, 10, 1);
- unsigned c = extract32(insn, 13, 3);
- unsigned rt = extract32(insn, 16, 5);
- unsigned rr = extract32(insn, 21, 5);
- unsigned len = 32 - clen;
- unsigned cpos = 31 - pos;
+ unsigned len = 32 - a->clen;
+ unsigned cpos = 31 - a->pos;
TCGv_reg dest, src;
- if (c) {
+ if (a->c) {
nullify_over(ctx);
}
- dest = dest_gpr(ctx, rt);
- src = load_gpr(ctx, rr);
- if (is_se) {
+ dest = dest_gpr(ctx, a->t);
+ src = load_gpr(ctx, a->r);
+ if (a->se) {
tcg_gen_sextract_reg(dest, src, cpos, len);
} else {
tcg_gen_extract_reg(dest, src, cpos, len);
}
- save_gpr(ctx, rt, dest);
+ save_gpr(ctx, a->t, dest);
/* Install the new nullification. */
cond_free(&ctx->null_cond);
- if (c) {
- ctx->null_cond = do_sed_cond(c, dest);
+ if (a->c) {
+ ctx->null_cond = do_sed_cond(a->c, dest);
}
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static const DisasInsn table_sh_ex[] = {
- { 0xd0000000u, 0xfc001fe0u, trans_shrpw_sar },
- { 0xd0000800u, 0xfc001c00u, trans_shrpw_imm },
- { 0xd0001000u, 0xfc001be0u, trans_extrw_sar },
- { 0xd0001800u, 0xfc001800u, trans_extrw_imm },
-};
-
-static DisasJumpType trans_depw_imm_c(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_depwi_imm(DisasContext *ctx, arg_depwi_imm *a)
{
- unsigned clen = extract32(insn, 0, 5);
- unsigned cpos = extract32(insn, 5, 5);
- unsigned nz = extract32(insn, 10, 1);
- unsigned c = extract32(insn, 13, 3);
- target_sreg val = low_sextract(insn, 16, 5);
- unsigned rt = extract32(insn, 21, 5);
- unsigned len = 32 - clen;
+ unsigned len = 32 - a->clen;
target_sreg mask0, mask1;
TCGv_reg dest;
- if (c) {
+ if (a->c) {
nullify_over(ctx);
}
- if (cpos + len > 32) {
- len = 32 - cpos;
+ if (a->cpos + len > 32) {
+ len = 32 - a->cpos;
}
- dest = dest_gpr(ctx, rt);
- mask0 = deposit64(0, cpos, len, val);
- mask1 = deposit64(-1, cpos, len, val);
+ dest = dest_gpr(ctx, a->t);
+ mask0 = deposit64(0, a->cpos, len, a->i);
+ mask1 = deposit64(-1, a->cpos, len, a->i);
- if (nz) {
- TCGv_reg src = load_gpr(ctx, rt);
+ if (a->nz) {
+ TCGv_reg src = load_gpr(ctx, a->t);
if (mask1 != -1) {
tcg_gen_andi_reg(dest, src, mask1);
src = dest;
} else {
tcg_gen_movi_reg(dest, mask0);
}
- save_gpr(ctx, rt, dest);
+ save_gpr(ctx, a->t, dest);
/* Install the new nullification. */
cond_free(&ctx->null_cond);
- if (c) {
- ctx->null_cond = do_sed_cond(c, dest);
+ if (a->c) {
+ ctx->null_cond = do_sed_cond(a->c, dest);
}
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType trans_depw_imm(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_depw_imm(DisasContext *ctx, arg_depw_imm *a)
{
- unsigned clen = extract32(insn, 0, 5);
- unsigned cpos = extract32(insn, 5, 5);
- unsigned nz = extract32(insn, 10, 1);
- unsigned c = extract32(insn, 13, 3);
- unsigned rr = extract32(insn, 16, 5);
- unsigned rt = extract32(insn, 21, 5);
- unsigned rs = nz ? rt : 0;
- unsigned len = 32 - clen;
+ unsigned rs = a->nz ? a->t : 0;
+ unsigned len = 32 - a->clen;
TCGv_reg dest, val;
- if (c) {
+ if (a->c) {
nullify_over(ctx);
}
- if (cpos + len > 32) {
- len = 32 - cpos;
+ if (a->cpos + len > 32) {
+ len = 32 - a->cpos;
}
- dest = dest_gpr(ctx, rt);
- val = load_gpr(ctx, rr);
+ dest = dest_gpr(ctx, a->t);
+ val = load_gpr(ctx, a->r);
if (rs == 0) {
- tcg_gen_deposit_z_reg(dest, val, cpos, len);
+ tcg_gen_deposit_z_reg(dest, val, a->cpos, len);
} else {
- tcg_gen_deposit_reg(dest, cpu_gr[rs], val, cpos, len);
+ tcg_gen_deposit_reg(dest, cpu_gr[rs], val, a->cpos, len);
}
- save_gpr(ctx, rt, dest);
+ save_gpr(ctx, a->t, dest);
/* Install the new nullification. */
cond_free(&ctx->null_cond);
- if (c) {
- ctx->null_cond = do_sed_cond(c, dest);
+ if (a->c) {
+ ctx->null_cond = do_sed_cond(a->c, dest);
}
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType trans_depw_sar(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool do_depw_sar(DisasContext *ctx, unsigned rt, unsigned c,
+ unsigned nz, unsigned clen, TCGv_reg val)
{
- unsigned clen = extract32(insn, 0, 5);
- unsigned nz = extract32(insn, 10, 1);
- unsigned i = extract32(insn, 12, 1);
- unsigned c = extract32(insn, 13, 3);
- unsigned rt = extract32(insn, 21, 5);
unsigned rs = nz ? rt : 0;
unsigned len = 32 - clen;
- TCGv_reg val, mask, tmp, shift, dest;
+ TCGv_reg mask, tmp, shift, dest;
unsigned msb = 1U << (len - 1);
if (c) {
nullify_over(ctx);
}
- if (i) {
- val = load_const(ctx, low_sextract(insn, 16, 5));
- } else {
- val = load_gpr(ctx, extract32(insn, 16, 5));
- }
dest = dest_gpr(ctx, rt);
shift = tcg_temp_new();
tmp = tcg_temp_new();
if (c) {
ctx->null_cond = do_sed_cond(c, dest);
}
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static const DisasInsn table_depw[] = {
- { 0xd4000000u, 0xfc000be0u, trans_depw_sar },
- { 0xd4000800u, 0xfc001800u, trans_depw_imm },
- { 0xd4001800u, 0xfc001800u, trans_depw_imm_c },
-};
+static bool trans_depw_sar(DisasContext *ctx, arg_depw_sar *a)
+{
+ return do_depw_sar(ctx, a->t, a->c, a->nz, a->clen, load_gpr(ctx, a->r));
+}
-static DisasJumpType trans_be(DisasContext *ctx, uint32_t insn, bool is_l)
+static bool trans_depwi_sar(DisasContext *ctx, arg_depwi_sar *a)
+{
+ return do_depw_sar(ctx, a->t, a->c, a->nz, a->clen, load_const(ctx, a->i));
+}
+
+static bool trans_be(DisasContext *ctx, arg_be *a)
{
- unsigned n = extract32(insn, 1, 1);
- unsigned b = extract32(insn, 21, 5);
- target_sreg disp = assemble_17(insn);
TCGv_reg tmp;
#ifdef CONFIG_USER_ONLY
/* Since we don't implement spaces, just branch. Do notice the special
case of "be disp(*,r0)" using a direct branch to disp, so that we can
goto_tb to the TB containing the syscall. */
- if (b == 0) {
- return do_dbranch(ctx, disp, is_l ? 31 : 0, n);
+ if (a->b == 0) {
+ return do_dbranch(ctx, a->disp, a->l, a->n);
}
#else
- int sp = assemble_sr3(insn);
nullify_over(ctx);
#endif
tmp = get_temp(ctx);
- tcg_gen_addi_reg(tmp, load_gpr(ctx, b), disp);
+ tcg_gen_addi_reg(tmp, load_gpr(ctx, a->b), a->disp);
tmp = do_ibranch_priv(ctx, tmp);
#ifdef CONFIG_USER_ONLY
- return do_ibranch(ctx, tmp, is_l ? 31 : 0, n);
+ return do_ibranch(ctx, tmp, a->l, a->n);
#else
TCGv_i64 new_spc = tcg_temp_new_i64();
- load_spr(ctx, new_spc, sp);
- if (is_l) {
+ load_spr(ctx, new_spc, a->sp);
+ if (a->l) {
copy_iaoq_entry(cpu_gr[31], ctx->iaoq_n, ctx->iaoq_n_var);
tcg_gen_mov_i64(cpu_sr[0], cpu_iasq_f);
}
- if (n && use_nullify_skip(ctx)) {
+ if (a->n && use_nullify_skip(ctx)) {
tcg_gen_mov_reg(cpu_iaoq_f, tmp);
tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4);
tcg_gen_mov_i64(cpu_iasq_f, new_spc);
}
tcg_gen_mov_reg(cpu_iaoq_b, tmp);
tcg_gen_mov_i64(cpu_iasq_b, new_spc);
- nullify_set(ctx, n);
+ nullify_set(ctx, a->n);
}
tcg_temp_free_i64(new_spc);
tcg_gen_lookup_and_goto_ptr();
- return nullify_end(ctx, DISAS_NORETURN);
+ ctx->base.is_jmp = DISAS_NORETURN;
+ return nullify_end(ctx);
#endif
}
-static DisasJumpType trans_bl(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_bl(DisasContext *ctx, arg_bl *a)
{
- unsigned n = extract32(insn, 1, 1);
- unsigned link = extract32(insn, 21, 5);
- target_sreg disp = assemble_17(insn);
-
- return do_dbranch(ctx, iaoq_dest(ctx, disp), link, n);
+ return do_dbranch(ctx, iaoq_dest(ctx, a->disp), a->l, a->n);
}
-static DisasJumpType trans_b_gate(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
{
- unsigned n = extract32(insn, 1, 1);
- unsigned link = extract32(insn, 21, 5);
- target_sreg disp = assemble_17(insn);
- target_ureg dest = iaoq_dest(ctx, disp);
+ target_ureg dest = iaoq_dest(ctx, a->disp);
/* Make sure the caller hasn't done something weird with the queue.
* ??? This is not quite the same as the PSW[B] bit, which would be
we will re-translate, at which point we *will* be able to find
the TLB entry and determine if this is in fact a gateway page. */
if (type < 0) {
- return gen_excp(ctx, EXCP_ITLB_MISS);
+ gen_excp(ctx, EXCP_ITLB_MISS);
+ return true;
}
/* No change for non-gateway pages or for priv decrease. */
if (type >= 4 && type - 4 < ctx->privilege) {
}
#endif
- return do_dbranch(ctx, dest, link, n);
-}
-
-static DisasJumpType trans_bl_long(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
-{
- unsigned n = extract32(insn, 1, 1);
- target_sreg disp = assemble_22(insn);
-
- return do_dbranch(ctx, iaoq_dest(ctx, disp), 2, n);
+ return do_dbranch(ctx, dest, a->l, a->n);
}
-static DisasJumpType trans_blr(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_blr(DisasContext *ctx, arg_blr *a)
{
- unsigned n = extract32(insn, 1, 1);
- unsigned rx = extract32(insn, 16, 5);
- unsigned link = extract32(insn, 21, 5);
TCGv_reg tmp = get_temp(ctx);
- tcg_gen_shli_reg(tmp, load_gpr(ctx, rx), 3);
+ tcg_gen_shli_reg(tmp, load_gpr(ctx, a->x), 3);
tcg_gen_addi_reg(tmp, tmp, ctx->iaoq_f + 8);
/* The computation here never changes privilege level. */
- return do_ibranch(ctx, tmp, link, n);
+ return do_ibranch(ctx, tmp, a->l, a->n);
}
-static DisasJumpType trans_bv(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_bv(DisasContext *ctx, arg_bv *a)
{
- unsigned n = extract32(insn, 1, 1);
- unsigned rx = extract32(insn, 16, 5);
- unsigned rb = extract32(insn, 21, 5);
TCGv_reg dest;
- if (rx == 0) {
- dest = load_gpr(ctx, rb);
+ if (a->x == 0) {
+ dest = load_gpr(ctx, a->b);
} else {
dest = get_temp(ctx);
- tcg_gen_shli_reg(dest, load_gpr(ctx, rx), 3);
- tcg_gen_add_reg(dest, dest, load_gpr(ctx, rb));
+ tcg_gen_shli_reg(dest, load_gpr(ctx, a->x), 3);
+ tcg_gen_add_reg(dest, dest, load_gpr(ctx, a->b));
}
dest = do_ibranch_priv(ctx, dest);
- return do_ibranch(ctx, dest, 0, n);
+ return do_ibranch(ctx, dest, 0, a->n);
}
-static DisasJumpType trans_bve(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_bve(DisasContext *ctx, arg_bve *a)
{
- unsigned n = extract32(insn, 1, 1);
- unsigned rb = extract32(insn, 21, 5);
- unsigned link = extract32(insn, 13, 1) ? 2 : 0;
TCGv_reg dest;
#ifdef CONFIG_USER_ONLY
- dest = do_ibranch_priv(ctx, load_gpr(ctx, rb));
- return do_ibranch(ctx, dest, link, n);
+ dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
+ return do_ibranch(ctx, dest, a->l, a->n);
#else
nullify_over(ctx);
- dest = do_ibranch_priv(ctx, load_gpr(ctx, rb));
+ dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
if (ctx->iaoq_b == -1) {
}
copy_iaoq_entry(cpu_iaoq_b, -1, dest);
tcg_gen_mov_i64(cpu_iasq_b, space_select(ctx, 0, dest));
- if (link) {
- copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
+ if (a->l) {
+ copy_iaoq_entry(cpu_gr[a->l], ctx->iaoq_n, ctx->iaoq_n_var);
}
- nullify_set(ctx, n);
+ nullify_set(ctx, a->n);
tcg_gen_lookup_and_goto_ptr();
- return nullify_end(ctx, DISAS_NORETURN);
+ ctx->base.is_jmp = DISAS_NORETURN;
+ return nullify_end(ctx);
#endif
}
-static const DisasInsn table_branch[] = {
- { 0xe8000000u, 0xfc006000u, trans_bl }, /* B,L and B,L,PUSH */
- { 0xe800a000u, 0xfc00e000u, trans_bl_long },
- { 0xe8004000u, 0xfc00fffdu, trans_blr },
- { 0xe800c000u, 0xfc00fffdu, trans_bv },
- { 0xe800d000u, 0xfc00dffcu, trans_bve },
- { 0xe8002000u, 0xfc00e000u, trans_b_gate },
-};
+/*
+ * Float class 0
+ */
-static DisasJumpType trans_fop_wew_0c(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static void gen_fcpy_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned ra = extract32(insn, 21, 5);
- return do_fop_wew(ctx, rt, ra, di->f.wew);
+ tcg_gen_mov_i32(dst, src);
}
-static DisasJumpType trans_fop_wew_0e(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_fcpy_f(DisasContext *ctx, arg_fclass01 *a)
{
- unsigned rt = assemble_rt64(insn);
- unsigned ra = assemble_ra64(insn);
- return do_fop_wew(ctx, rt, ra, di->f.wew);
+ return do_fop_wew(ctx, a->t, a->r, gen_fcpy_f);
}
-static DisasJumpType trans_fop_ded(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static void gen_fcpy_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned ra = extract32(insn, 21, 5);
- return do_fop_ded(ctx, rt, ra, di->f.ded);
+ tcg_gen_mov_i64(dst, src);
}
-static DisasJumpType trans_fop_wed_0c(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_fcpy_d(DisasContext *ctx, arg_fclass01 *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned ra = extract32(insn, 21, 5);
- return do_fop_wed(ctx, rt, ra, di->f.wed);
+ return do_fop_ded(ctx, a->t, a->r, gen_fcpy_d);
}
-static DisasJumpType trans_fop_wed_0e(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static void gen_fabs_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
{
- unsigned rt = assemble_rt64(insn);
- unsigned ra = extract32(insn, 21, 5);
- return do_fop_wed(ctx, rt, ra, di->f.wed);
+ tcg_gen_andi_i32(dst, src, INT32_MAX);
}
-static DisasJumpType trans_fop_dew_0c(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_fabs_f(DisasContext *ctx, arg_fclass01 *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned ra = extract32(insn, 21, 5);
- return do_fop_dew(ctx, rt, ra, di->f.dew);
+ return do_fop_wew(ctx, a->t, a->r, gen_fabs_f);
}
-static DisasJumpType trans_fop_dew_0e(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static void gen_fabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned ra = assemble_ra64(insn);
- return do_fop_dew(ctx, rt, ra, di->f.dew);
+ tcg_gen_andi_i64(dst, src, INT64_MAX);
}
-static DisasJumpType trans_fop_weww_0c(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_fabs_d(DisasContext *ctx, arg_fclass01 *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned rb = extract32(insn, 16, 5);
- unsigned ra = extract32(insn, 21, 5);
- return do_fop_weww(ctx, rt, ra, rb, di->f.weww);
+ return do_fop_ded(ctx, a->t, a->r, gen_fabs_d);
}
-static DisasJumpType trans_fop_weww_0e(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_fsqrt_f(DisasContext *ctx, arg_fclass01 *a)
{
- unsigned rt = assemble_rt64(insn);
- unsigned rb = assemble_rb64(insn);
- unsigned ra = assemble_ra64(insn);
- return do_fop_weww(ctx, rt, ra, rb, di->f.weww);
+ return do_fop_wew(ctx, a->t, a->r, gen_helper_fsqrt_s);
}
-static DisasJumpType trans_fop_dedd(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_fsqrt_d(DisasContext *ctx, arg_fclass01 *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned rb = extract32(insn, 16, 5);
- unsigned ra = extract32(insn, 21, 5);
- return do_fop_dedd(ctx, rt, ra, rb, di->f.dedd);
+ return do_fop_ded(ctx, a->t, a->r, gen_helper_fsqrt_d);
}
-static void gen_fcpy_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
+static bool trans_frnd_f(DisasContext *ctx, arg_fclass01 *a)
{
- tcg_gen_mov_i32(dst, src);
+ return do_fop_wew(ctx, a->t, a->r, gen_helper_frnd_s);
}
-static void gen_fcpy_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
+static bool trans_frnd_d(DisasContext *ctx, arg_fclass01 *a)
{
- tcg_gen_mov_i64(dst, src);
+ return do_fop_ded(ctx, a->t, a->r, gen_helper_frnd_d);
}
-static void gen_fabs_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
+static void gen_fneg_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
{
- tcg_gen_andi_i32(dst, src, INT32_MAX);
+ tcg_gen_xori_i32(dst, src, INT32_MIN);
}
-static void gen_fabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
+static bool trans_fneg_f(DisasContext *ctx, arg_fclass01 *a)
{
- tcg_gen_andi_i64(dst, src, INT64_MAX);
+ return do_fop_wew(ctx, a->t, a->r, gen_fneg_f);
}
-static void gen_fneg_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
+static void gen_fneg_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
{
- tcg_gen_xori_i32(dst, src, INT32_MIN);
+ tcg_gen_xori_i64(dst, src, INT64_MIN);
}
-static void gen_fneg_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
+static bool trans_fneg_d(DisasContext *ctx, arg_fclass01 *a)
{
- tcg_gen_xori_i64(dst, src, INT64_MIN);
+ return do_fop_ded(ctx, a->t, a->r, gen_fneg_d);
}
-static void gen_fnegabs_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
+static void gen_fnegabs_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
{
tcg_gen_ori_i32(dst, src, INT32_MIN);
}
+static bool trans_fnegabs_f(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wew(ctx, a->t, a->r, gen_fnegabs_f);
+}
+
static void gen_fnegabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
{
tcg_gen_ori_i64(dst, src, INT64_MIN);
}
-static DisasJumpType do_fcmp_s(DisasContext *ctx, unsigned ra, unsigned rb,
- unsigned y, unsigned c)
+static bool trans_fnegabs_d(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_ded(ctx, a->t, a->r, gen_fnegabs_d);
+}
+
+/*
+ * Float class 1
+ */
+
+static bool trans_fcnv_d_f(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_s);
+}
+
+static bool trans_fcnv_f_d(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_d);
+}
+
+static bool trans_fcnv_w_f(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_w_s);
+}
+
+static bool trans_fcnv_q_f(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_dw_s);
+}
+
+static bool trans_fcnv_w_d(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_w_d);
+}
+
+static bool trans_fcnv_q_d(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_dw_d);
+}
+
+static bool trans_fcnv_f_w(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_s_w);
+}
+
+static bool trans_fcnv_d_w(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_w);
+}
+
+static bool trans_fcnv_f_q(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_dw);
+}
+
+static bool trans_fcnv_d_q(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_d_dw);
+}
+
+static bool trans_fcnv_t_f_w(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_t_s_w);
+}
+
+static bool trans_fcnv_t_d_w(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_t_d_w);
+}
+
+static bool trans_fcnv_t_f_q(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_t_s_dw);
+}
+
+static bool trans_fcnv_t_d_q(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_t_d_dw);
+}
+
+static bool trans_fcnv_uw_f(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_uw_s);
+}
+
+static bool trans_fcnv_uq_f(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_udw_s);
+}
+
+static bool trans_fcnv_uw_d(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_uw_d);
+}
+
+static bool trans_fcnv_uq_d(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_udw_d);
+}
+
+static bool trans_fcnv_f_uw(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_s_uw);
+}
+
+static bool trans_fcnv_d_uw(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_uw);
+}
+
+static bool trans_fcnv_f_uq(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_udw);
+}
+
+static bool trans_fcnv_d_uq(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_d_udw);
+}
+
+static bool trans_fcnv_t_f_uw(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_t_s_uw);
+}
+
+static bool trans_fcnv_t_d_uw(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_t_d_uw);
+}
+
+static bool trans_fcnv_t_f_uq(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_t_s_udw);
+}
+
+static bool trans_fcnv_t_d_uq(DisasContext *ctx, arg_fclass01 *a)
+{
+ return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_t_d_udw);
+}
+
+/*
+ * Float class 2
+ */
+
+static bool trans_fcmp_f(DisasContext *ctx, arg_fclass2 *a)
{
TCGv_i32 ta, tb, tc, ty;
nullify_over(ctx);
- ta = load_frw0_i32(ra);
- tb = load_frw0_i32(rb);
- ty = tcg_const_i32(y);
- tc = tcg_const_i32(c);
+ ta = load_frw0_i32(a->r1);
+ tb = load_frw0_i32(a->r2);
+ ty = tcg_const_i32(a->y);
+ tc = tcg_const_i32(a->c);
gen_helper_fcmp_s(cpu_env, ta, tb, ty, tc);
tcg_temp_free_i32(ty);
tcg_temp_free_i32(tc);
- return nullify_end(ctx, DISAS_NEXT);
-}
-
-static DisasJumpType trans_fcmp_s_0c(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
-{
- unsigned c = extract32(insn, 0, 5);
- unsigned y = extract32(insn, 13, 3);
- unsigned rb = extract32(insn, 16, 5);
- unsigned ra = extract32(insn, 21, 5);
- return do_fcmp_s(ctx, ra, rb, y, c);
-}
-
-static DisasJumpType trans_fcmp_s_0e(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
-{
- unsigned c = extract32(insn, 0, 5);
- unsigned y = extract32(insn, 13, 3);
- unsigned rb = assemble_rb64(insn);
- unsigned ra = assemble_ra64(insn);
- return do_fcmp_s(ctx, ra, rb, y, c);
+ return nullify_end(ctx);
}
-static DisasJumpType trans_fcmp_d(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_fcmp_d(DisasContext *ctx, arg_fclass2 *a)
{
- unsigned c = extract32(insn, 0, 5);
- unsigned y = extract32(insn, 13, 3);
- unsigned rb = extract32(insn, 16, 5);
- unsigned ra = extract32(insn, 21, 5);
TCGv_i64 ta, tb;
TCGv_i32 tc, ty;
nullify_over(ctx);
- ta = load_frd0(ra);
- tb = load_frd0(rb);
- ty = tcg_const_i32(y);
- tc = tcg_const_i32(c);
+ ta = load_frd0(a->r1);
+ tb = load_frd0(a->r2);
+ ty = tcg_const_i32(a->y);
+ tc = tcg_const_i32(a->c);
gen_helper_fcmp_d(cpu_env, ta, tb, ty, tc);
tcg_temp_free_i32(ty);
tcg_temp_free_i32(tc);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
}
-static DisasJumpType trans_ftest_t(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_ftest(DisasContext *ctx, arg_ftest *a)
{
- unsigned y = extract32(insn, 13, 3);
- unsigned cbit = (y ^ 1) - 1;
TCGv_reg t;
nullify_over(ctx);
- t = tcg_temp_new();
+ t = get_temp(ctx);
tcg_gen_ld32u_reg(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow));
- tcg_gen_extract_reg(t, t, 21 - cbit, 1);
- ctx->null_cond = cond_make_0(TCG_COND_NE, t);
- tcg_temp_free(t);
- return nullify_end(ctx, DISAS_NEXT);
+ if (a->y == 1) {
+ int mask;
+ bool inv = false;
+
+ switch (a->c) {
+ case 0: /* simple */
+ tcg_gen_andi_reg(t, t, 0x4000000);
+ ctx->null_cond = cond_make_0(TCG_COND_NE, t);
+ goto done;
+ case 2: /* rej */
+ inv = true;
+ /* fallthru */
+ case 1: /* acc */
+ mask = 0x43ff800;
+ break;
+ case 6: /* rej8 */
+ inv = true;
+ /* fallthru */
+ case 5: /* acc8 */
+ mask = 0x43f8000;
+ break;
+ case 9: /* acc6 */
+ mask = 0x43e0000;
+ break;
+ case 13: /* acc4 */
+ mask = 0x4380000;
+ break;
+ case 17: /* acc2 */
+ mask = 0x4200000;
+ break;
+ default:
+ gen_illegal(ctx);
+ return true;
+ }
+ if (inv) {
+ TCGv_reg c = load_const(ctx, mask);
+ tcg_gen_or_reg(t, t, c);
+ ctx->null_cond = cond_make(TCG_COND_EQ, t, c);
+ } else {
+ tcg_gen_andi_reg(t, t, mask);
+ ctx->null_cond = cond_make_0(TCG_COND_EQ, t);
+ }
+ } else {
+ unsigned cbit = (a->y ^ 1) - 1;
+
+ tcg_gen_extract_reg(t, t, 21 - cbit, 1);
+ ctx->null_cond = cond_make_0(TCG_COND_NE, t);
+ tcg_temp_free(t);
+ }
+
+ done:
+ return nullify_end(ctx);
}
-static DisasJumpType trans_ftest_q(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+/*
+ * Float class 2
+ */
+
+static bool trans_fadd_f(DisasContext *ctx, arg_fclass3 *a)
{
- unsigned c = extract32(insn, 0, 5);
- int mask;
- bool inv = false;
- TCGv_reg t;
+ return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fadd_s);
+}
- nullify_over(ctx);
+static bool trans_fadd_d(DisasContext *ctx, arg_fclass3 *a)
+{
+ return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fadd_d);
+}
- t = tcg_temp_new();
- tcg_gen_ld32u_reg(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow));
+static bool trans_fsub_f(DisasContext *ctx, arg_fclass3 *a)
+{
+ return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fsub_s);
+}
- switch (c) {
- case 0: /* simple */
- tcg_gen_andi_reg(t, t, 0x4000000);
- ctx->null_cond = cond_make_0(TCG_COND_NE, t);
- goto done;
- case 2: /* rej */
- inv = true;
- /* fallthru */
- case 1: /* acc */
- mask = 0x43ff800;
- break;
- case 6: /* rej8 */
- inv = true;
- /* fallthru */
- case 5: /* acc8 */
- mask = 0x43f8000;
- break;
- case 9: /* acc6 */
- mask = 0x43e0000;
- break;
- case 13: /* acc4 */
- mask = 0x4380000;
- break;
- case 17: /* acc2 */
- mask = 0x4200000;
- break;
- default:
- return gen_illegal(ctx);
- }
- if (inv) {
- TCGv_reg c = load_const(ctx, mask);
- tcg_gen_or_reg(t, t, c);
- ctx->null_cond = cond_make(TCG_COND_EQ, t, c);
- } else {
- tcg_gen_andi_reg(t, t, mask);
- ctx->null_cond = cond_make_0(TCG_COND_EQ, t);
- }
- done:
- return nullify_end(ctx, DISAS_NEXT);
+static bool trans_fsub_d(DisasContext *ctx, arg_fclass3 *a)
+{
+ return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fsub_d);
}
-static DisasJumpType trans_xmpyu(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_fmpy_f(DisasContext *ctx, arg_fclass3 *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned rb = assemble_rb64(insn);
- unsigned ra = assemble_ra64(insn);
- TCGv_i64 a, b;
+ return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fmpy_s);
+}
- nullify_over(ctx);
+static bool trans_fmpy_d(DisasContext *ctx, arg_fclass3 *a)
+{
+ return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fmpy_d);
+}
- a = load_frw0_i64(ra);
- b = load_frw0_i64(rb);
- tcg_gen_mul_i64(a, a, b);
- save_frd(rt, a);
- tcg_temp_free_i64(a);
- tcg_temp_free_i64(b);
+static bool trans_fdiv_f(DisasContext *ctx, arg_fclass3 *a)
+{
+ return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fdiv_s);
+}
- return nullify_end(ctx, DISAS_NEXT);
-}
-
-#define FOP_DED trans_fop_ded, .f.ded
-#define FOP_DEDD trans_fop_dedd, .f.dedd
-
-#define FOP_WEW trans_fop_wew_0c, .f.wew
-#define FOP_DEW trans_fop_dew_0c, .f.dew
-#define FOP_WED trans_fop_wed_0c, .f.wed
-#define FOP_WEWW trans_fop_weww_0c, .f.weww
-
-static const DisasInsn table_float_0c[] = {
- /* floating point class zero */
- { 0x30004000, 0xfc1fffe0, FOP_WEW = gen_fcpy_s },
- { 0x30006000, 0xfc1fffe0, FOP_WEW = gen_fabs_s },
- { 0x30008000, 0xfc1fffe0, FOP_WEW = gen_helper_fsqrt_s },
- { 0x3000a000, 0xfc1fffe0, FOP_WEW = gen_helper_frnd_s },
- { 0x3000c000, 0xfc1fffe0, FOP_WEW = gen_fneg_s },
- { 0x3000e000, 0xfc1fffe0, FOP_WEW = gen_fnegabs_s },
-
- { 0x30004800, 0xfc1fffe0, FOP_DED = gen_fcpy_d },
- { 0x30006800, 0xfc1fffe0, FOP_DED = gen_fabs_d },
- { 0x30008800, 0xfc1fffe0, FOP_DED = gen_helper_fsqrt_d },
- { 0x3000a800, 0xfc1fffe0, FOP_DED = gen_helper_frnd_d },
- { 0x3000c800, 0xfc1fffe0, FOP_DED = gen_fneg_d },
- { 0x3000e800, 0xfc1fffe0, FOP_DED = gen_fnegabs_d },
-
- /* floating point class three */
- { 0x30000600, 0xfc00ffe0, FOP_WEWW = gen_helper_fadd_s },
- { 0x30002600, 0xfc00ffe0, FOP_WEWW = gen_helper_fsub_s },
- { 0x30004600, 0xfc00ffe0, FOP_WEWW = gen_helper_fmpy_s },
- { 0x30006600, 0xfc00ffe0, FOP_WEWW = gen_helper_fdiv_s },
-
- { 0x30000e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fadd_d },
- { 0x30002e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fsub_d },
- { 0x30004e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fmpy_d },
- { 0x30006e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fdiv_d },
-
- /* floating point class one */
- /* float/float */
- { 0x30000a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_s },
- { 0x30002200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_d },
- /* int/float */
- { 0x30008200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_w_s },
- { 0x30008a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_dw_s },
- { 0x3000a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_w_d },
- { 0x3000aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_dw_d },
- /* float/int */
- { 0x30010200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_s_w },
- { 0x30010a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_w },
- { 0x30012200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_dw },
- { 0x30012a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_dw },
- /* float/int truncate */
- { 0x30018200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_t_s_w },
- { 0x30018a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_t_d_w },
- { 0x3001a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_t_s_dw },
- { 0x3001aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_dw },
- /* uint/float */
- { 0x30028200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_uw_s },
- { 0x30028a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_udw_s },
- { 0x3002a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_uw_d },
- { 0x3002aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_udw_d },
- /* float/uint */
- { 0x30030200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_s_uw },
- { 0x30030a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_uw },
- { 0x30032200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_udw },
- { 0x30032a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_udw },
- /* float/uint truncate */
- { 0x30038200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_t_s_uw },
- { 0x30038a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_t_d_uw },
- { 0x3003a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_t_s_udw },
- { 0x3003aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_udw },
-
- /* floating point class two */
- { 0x30000400, 0xfc001fe0, trans_fcmp_s_0c },
- { 0x30000c00, 0xfc001fe0, trans_fcmp_d },
- { 0x30002420, 0xffffffe0, trans_ftest_q },
- { 0x30000420, 0xffff1fff, trans_ftest_t },
-
- /* FID. Note that ra == rt == 0, which via fcpy puts 0 into fr0.
- This is machine/revision == 0, which is reserved for simulator. */
- { 0x30000000, 0xffffffff, FOP_WEW = gen_fcpy_s },
-};
+static bool trans_fdiv_d(DisasContext *ctx, arg_fclass3 *a)
+{
+ return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fdiv_d);
+}
-#undef FOP_WEW
-#undef FOP_DEW
-#undef FOP_WED
-#undef FOP_WEWW
-#define FOP_WEW trans_fop_wew_0e, .f.wew
-#define FOP_DEW trans_fop_dew_0e, .f.dew
-#define FOP_WED trans_fop_wed_0e, .f.wed
-#define FOP_WEWW trans_fop_weww_0e, .f.weww
-
-static const DisasInsn table_float_0e[] = {
- /* floating point class zero */
- { 0x38004000, 0xfc1fff20, FOP_WEW = gen_fcpy_s },
- { 0x38006000, 0xfc1fff20, FOP_WEW = gen_fabs_s },
- { 0x38008000, 0xfc1fff20, FOP_WEW = gen_helper_fsqrt_s },
- { 0x3800a000, 0xfc1fff20, FOP_WEW = gen_helper_frnd_s },
- { 0x3800c000, 0xfc1fff20, FOP_WEW = gen_fneg_s },
- { 0x3800e000, 0xfc1fff20, FOP_WEW = gen_fnegabs_s },
-
- { 0x38004800, 0xfc1fffe0, FOP_DED = gen_fcpy_d },
- { 0x38006800, 0xfc1fffe0, FOP_DED = gen_fabs_d },
- { 0x38008800, 0xfc1fffe0, FOP_DED = gen_helper_fsqrt_d },
- { 0x3800a800, 0xfc1fffe0, FOP_DED = gen_helper_frnd_d },
- { 0x3800c800, 0xfc1fffe0, FOP_DED = gen_fneg_d },
- { 0x3800e800, 0xfc1fffe0, FOP_DED = gen_fnegabs_d },
-
- /* floating point class three */
- { 0x38000600, 0xfc00ef20, FOP_WEWW = gen_helper_fadd_s },
- { 0x38002600, 0xfc00ef20, FOP_WEWW = gen_helper_fsub_s },
- { 0x38004600, 0xfc00ef20, FOP_WEWW = gen_helper_fmpy_s },
- { 0x38006600, 0xfc00ef20, FOP_WEWW = gen_helper_fdiv_s },
-
- { 0x38000e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fadd_d },
- { 0x38002e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fsub_d },
- { 0x38004e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fmpy_d },
- { 0x38006e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fdiv_d },
-
- { 0x38004700, 0xfc00ef60, trans_xmpyu },
-
- /* floating point class one */
- /* float/float */
- { 0x38000a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_s },
- { 0x38002200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_d },
- /* int/float */
- { 0x38008200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_w_s },
- { 0x38008a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_dw_s },
- { 0x3800a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_w_d },
- { 0x3800aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_dw_d },
- /* float/int */
- { 0x38010200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_s_w },
- { 0x38010a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_w },
- { 0x38012200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_dw },
- { 0x38012a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_dw },
- /* float/int truncate */
- { 0x38018200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_t_s_w },
- { 0x38018a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_w },
- { 0x3801a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_dw },
- { 0x3801aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_dw },
- /* uint/float */
- { 0x38028200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_uw_s },
- { 0x38028a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_udw_s },
- { 0x3802a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_uw_d },
- { 0x3802aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_udw_d },
- /* float/uint */
- { 0x38030200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_s_uw },
- { 0x38030a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_uw },
- { 0x38032200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_udw },
- { 0x38032a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_udw },
- /* float/uint truncate */
- { 0x38038200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_t_s_uw },
- { 0x38038a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_uw },
- { 0x3803a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_udw },
- { 0x3803aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_udw },
-
- /* floating point class two */
- { 0x38000400, 0xfc000f60, trans_fcmp_s_0e },
- { 0x38000c00, 0xfc001fe0, trans_fcmp_d },
-};
+static bool trans_xmpyu(DisasContext *ctx, arg_xmpyu *a)
+{
+ TCGv_i64 x, y;
+
+ nullify_over(ctx);
+
+ x = load_frw0_i64(a->r1);
+ y = load_frw0_i64(a->r2);
+ tcg_gen_mul_i64(x, x, y);
+ save_frd(a->t, x);
+ tcg_temp_free_i64(x);
+ tcg_temp_free_i64(y);
-#undef FOP_WEW
-#undef FOP_DEW
-#undef FOP_WED
-#undef FOP_WEWW
-#undef FOP_DED
-#undef FOP_DEDD
+ return nullify_end(ctx);
+}
/* Convert the fmpyadd single-precision register encodings to standard. */
static inline int fmpyadd_s_reg(unsigned r)
return (r & 16) * 2 + 16 + (r & 15);
}
-static DisasJumpType trans_fmpyadd(DisasContext *ctx,
- uint32_t insn, bool is_sub)
+static bool do_fmpyadd_s(DisasContext *ctx, arg_mpyadd *a, bool is_sub)
{
- unsigned tm = extract32(insn, 0, 5);
- unsigned f = extract32(insn, 5, 1);
- unsigned ra = extract32(insn, 6, 5);
- unsigned ta = extract32(insn, 11, 5);
- unsigned rm2 = extract32(insn, 16, 5);
- unsigned rm1 = extract32(insn, 21, 5);
+ int tm = fmpyadd_s_reg(a->tm);
+ int ra = fmpyadd_s_reg(a->ra);
+ int ta = fmpyadd_s_reg(a->ta);
+ int rm2 = fmpyadd_s_reg(a->rm2);
+ int rm1 = fmpyadd_s_reg(a->rm1);
nullify_over(ctx);
- /* Independent multiply & add/sub, with undefined behaviour
- if outputs overlap inputs. */
- if (f == 0) {
- tm = fmpyadd_s_reg(tm);
- ra = fmpyadd_s_reg(ra);
- ta = fmpyadd_s_reg(ta);
- rm2 = fmpyadd_s_reg(rm2);
- rm1 = fmpyadd_s_reg(rm1);
- do_fop_weww(ctx, tm, rm1, rm2, gen_helper_fmpy_s);
- do_fop_weww(ctx, ta, ta, ra,
- is_sub ? gen_helper_fsub_s : gen_helper_fadd_s);
- } else {
- do_fop_dedd(ctx, tm, rm1, rm2, gen_helper_fmpy_d);
- do_fop_dedd(ctx, ta, ta, ra,
- is_sub ? gen_helper_fsub_d : gen_helper_fadd_d);
- }
+ do_fop_weww(ctx, tm, rm1, rm2, gen_helper_fmpy_s);
+ do_fop_weww(ctx, ta, ta, ra,
+ is_sub ? gen_helper_fsub_s : gen_helper_fadd_s);
+
+ return nullify_end(ctx);
+}
- return nullify_end(ctx, DISAS_NEXT);
+static bool trans_fmpyadd_f(DisasContext *ctx, arg_mpyadd *a)
+{
+ return do_fmpyadd_s(ctx, a, false);
}
-static DisasJumpType trans_fmpyfadd_s(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_fmpysub_f(DisasContext *ctx, arg_mpyadd *a)
{
- unsigned rt = assemble_rt64(insn);
- unsigned neg = extract32(insn, 5, 1);
- unsigned rm1 = assemble_ra64(insn);
- unsigned rm2 = assemble_rb64(insn);
- unsigned ra3 = assemble_rc64(insn);
- TCGv_i32 a, b, c;
+ return do_fmpyadd_s(ctx, a, true);
+}
+static bool do_fmpyadd_d(DisasContext *ctx, arg_mpyadd *a, bool is_sub)
+{
nullify_over(ctx);
- a = load_frw0_i32(rm1);
- b = load_frw0_i32(rm2);
- c = load_frw0_i32(ra3);
- if (neg) {
- gen_helper_fmpynfadd_s(a, cpu_env, a, b, c);
- } else {
- gen_helper_fmpyfadd_s(a, cpu_env, a, b, c);
- }
+ do_fop_dedd(ctx, a->tm, a->rm1, a->rm2, gen_helper_fmpy_d);
+ do_fop_dedd(ctx, a->ta, a->ta, a->ra,
+ is_sub ? gen_helper_fsub_d : gen_helper_fadd_d);
- tcg_temp_free_i32(b);
- tcg_temp_free_i32(c);
- save_frw_i32(rt, a);
- tcg_temp_free_i32(a);
- return nullify_end(ctx, DISAS_NEXT);
+ return nullify_end(ctx);
+}
+
+static bool trans_fmpyadd_d(DisasContext *ctx, arg_mpyadd *a)
+{
+ return do_fmpyadd_d(ctx, a, false);
}
-static DisasJumpType trans_fmpyfadd_d(DisasContext *ctx, uint32_t insn,
- const DisasInsn *di)
+static bool trans_fmpysub_d(DisasContext *ctx, arg_mpyadd *a)
{
- unsigned rt = extract32(insn, 0, 5);
- unsigned neg = extract32(insn, 5, 1);
- unsigned rm1 = extract32(insn, 21, 5);
- unsigned rm2 = extract32(insn, 16, 5);
- unsigned ra3 = assemble_rc64(insn);
- TCGv_i64 a, b, c;
+ return do_fmpyadd_d(ctx, a, true);
+}
+
+static bool trans_fmpyfadd_f(DisasContext *ctx, arg_fmpyfadd_f *a)
+{
+ TCGv_i32 x, y, z;
nullify_over(ctx);
- a = load_frd0(rm1);
- b = load_frd0(rm2);
- c = load_frd0(ra3);
+ x = load_frw0_i32(a->rm1);
+ y = load_frw0_i32(a->rm2);
+ z = load_frw0_i32(a->ra3);
- if (neg) {
- gen_helper_fmpynfadd_d(a, cpu_env, a, b, c);
+ if (a->neg) {
+ gen_helper_fmpynfadd_s(x, cpu_env, x, y, z);
} else {
- gen_helper_fmpyfadd_d(a, cpu_env, a, b, c);
+ gen_helper_fmpyfadd_s(x, cpu_env, x, y, z);
}
- tcg_temp_free_i64(b);
- tcg_temp_free_i64(c);
- save_frd(rt, a);
- tcg_temp_free_i64(a);
- return nullify_end(ctx, DISAS_NEXT);
+ tcg_temp_free_i32(y);
+ tcg_temp_free_i32(z);
+ save_frw_i32(a->t, x);
+ tcg_temp_free_i32(x);
+ return nullify_end(ctx);
}
-static const DisasInsn table_fp_fused[] = {
- { 0xb8000000u, 0xfc000800u, trans_fmpyfadd_s },
- { 0xb8000800u, 0xfc0019c0u, trans_fmpyfadd_d }
-};
-
-static DisasJumpType translate_table_int(DisasContext *ctx, uint32_t insn,
- const DisasInsn table[], size_t n)
+static bool trans_fmpyfadd_d(DisasContext *ctx, arg_fmpyfadd_d *a)
{
- size_t i;
- for (i = 0; i < n; ++i) {
- if ((insn & table[i].mask) == table[i].insn) {
- return table[i].trans(ctx, insn, &table[i]);
- }
- }
- qemu_log_mask(LOG_UNIMP, "UNIMP insn %08x @ " TARGET_FMT_lx "\n",
- insn, ctx->base.pc_next);
- return gen_illegal(ctx);
-}
-
-#define translate_table(ctx, insn, table) \
- translate_table_int(ctx, insn, table, ARRAY_SIZE(table))
-
-static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
-{
- uint32_t opc = extract32(insn, 26, 6);
-
- switch (opc) {
- case 0x00: /* system op */
- return translate_table(ctx, insn, table_system);
- case 0x01:
- return translate_table(ctx, insn, table_mem_mgmt);
- case 0x02:
- return translate_table(ctx, insn, table_arith_log);
- case 0x03:
- return translate_table(ctx, insn, table_index_mem);
- case 0x06:
- return trans_fmpyadd(ctx, insn, false);
- case 0x08:
- return trans_ldil(ctx, insn);
- case 0x09:
- return trans_copr_w(ctx, insn);
- case 0x0A:
- return trans_addil(ctx, insn);
- case 0x0B:
- return trans_copr_dw(ctx, insn);
- case 0x0C:
- return translate_table(ctx, insn, table_float_0c);
- case 0x0D:
- return trans_ldo(ctx, insn);
- case 0x0E:
- return translate_table(ctx, insn, table_float_0e);
-
- case 0x10:
- return trans_load(ctx, insn, false, MO_UB);
- case 0x11:
- return trans_load(ctx, insn, false, MO_TEUW);
- case 0x12:
- return trans_load(ctx, insn, false, MO_TEUL);
- case 0x13:
- return trans_load(ctx, insn, true, MO_TEUL);
- case 0x16:
- return trans_fload_mod(ctx, insn);
- case 0x17:
- return trans_load_w(ctx, insn);
- case 0x18:
- return trans_store(ctx, insn, false, MO_UB);
- case 0x19:
- return trans_store(ctx, insn, false, MO_TEUW);
- case 0x1A:
- return trans_store(ctx, insn, false, MO_TEUL);
- case 0x1B:
- return trans_store(ctx, insn, true, MO_TEUL);
- case 0x1E:
- return trans_fstore_mod(ctx, insn);
- case 0x1F:
- return trans_store_w(ctx, insn);
-
- case 0x20:
- return trans_cmpb(ctx, insn, true, false, false);
- case 0x21:
- return trans_cmpb(ctx, insn, true, true, false);
- case 0x22:
- return trans_cmpb(ctx, insn, false, false, false);
- case 0x23:
- return trans_cmpb(ctx, insn, false, true, false);
- case 0x24:
- return trans_cmpiclr(ctx, insn);
- case 0x25:
- return trans_subi(ctx, insn);
- case 0x26:
- return trans_fmpyadd(ctx, insn, true);
- case 0x27:
- return trans_cmpb(ctx, insn, true, false, true);
- case 0x28:
- return trans_addb(ctx, insn, true, false);
- case 0x29:
- return trans_addb(ctx, insn, true, true);
- case 0x2A:
- return trans_addb(ctx, insn, false, false);
- case 0x2B:
- return trans_addb(ctx, insn, false, true);
- case 0x2C:
- case 0x2D:
- return trans_addi(ctx, insn);
- case 0x2E:
- return translate_table(ctx, insn, table_fp_fused);
- case 0x2F:
- return trans_cmpb(ctx, insn, false, false, true);
-
- case 0x30:
- case 0x31:
- return trans_bb(ctx, insn);
- case 0x32:
- return trans_movb(ctx, insn, false);
- case 0x33:
- return trans_movb(ctx, insn, true);
- case 0x34:
- return translate_table(ctx, insn, table_sh_ex);
- case 0x35:
- return translate_table(ctx, insn, table_depw);
- case 0x38:
- return trans_be(ctx, insn, false);
- case 0x39:
- return trans_be(ctx, insn, true);
- case 0x3A:
- return translate_table(ctx, insn, table_branch);
-
- case 0x04: /* spopn */
- case 0x05: /* diag */
- case 0x0F: /* product specific */
- break;
+ TCGv_i64 x, y, z;
- case 0x07: /* unassigned */
- case 0x15: /* unassigned */
- case 0x1D: /* unassigned */
- case 0x37: /* unassigned */
- break;
- case 0x3F:
-#ifndef CONFIG_USER_ONLY
- /* Unassigned, but use as system-halt. */
- if (insn == 0xfffdead0) {
- return gen_hlt(ctx, 0); /* halt system */
- }
- if (insn == 0xfffdead1) {
- return gen_hlt(ctx, 1); /* reset system */
- }
-#endif
- break;
- default:
- break;
+ nullify_over(ctx);
+ x = load_frd0(a->rm1);
+ y = load_frd0(a->rm2);
+ z = load_frd0(a->ra3);
+
+ if (a->neg) {
+ gen_helper_fmpynfadd_d(x, cpu_env, x, y, z);
+ } else {
+ gen_helper_fmpyfadd_d(x, cpu_env, x, y, z);
}
- return gen_illegal(ctx);
+
+ tcg_temp_free_i64(y);
+ tcg_temp_free_i64(z);
+ save_frd(a->t, x);
+ tcg_temp_free_i64(x);
+ return nullify_end(ctx);
}
static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
{
DisasContext *ctx = container_of(dcbase, DisasContext, base);
- ctx->base.is_jmp = gen_excp(ctx, EXCP_DEBUG);
+ gen_excp(ctx, EXCP_DEBUG);
ctx->base.pc_next += 4;
return true;
}
/* Execute one insn. */
#ifdef CONFIG_USER_ONLY
if (ctx->base.pc_next < TARGET_PAGE_SIZE) {
- ret = do_page_zero(ctx);
+ do_page_zero(ctx);
+ ret = ctx->base.is_jmp;
assert(ret != DISAS_NEXT);
} else
#endif
ret = DISAS_NEXT;
} else {
ctx->insn = insn;
- ret = translate_one(ctx, insn);
+ if (!decode(ctx, insn)) {
+ gen_illegal(ctx);
+ }
+ ret = ctx->base.is_jmp;
assert(ctx->null_lab == NULL);
}
}
|| ctx->null_cond.c == TCG_COND_ALWAYS)) {
nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
- ret = DISAS_NORETURN;
+ ctx->base.is_jmp = ret = DISAS_NORETURN;
} else {
- ret = DISAS_IAQ_N_STALE;
+ ctx->base.is_jmp = ret = DISAS_IAQ_N_STALE;
}
}
ctx->iaoq_f = ctx->iaoq_b;
ctx->iaoq_b = ctx->iaoq_n;
- ctx->base.is_jmp = ret;
ctx->base.pc_next += 4;
if (ret == DISAS_NORETURN || ret == DISAS_IAQ_N_UPDATED) {
#include "qapi/visitor.h"
#include "qom/qom-qobject.h"
#include "sysemu/arch_init.h"
+#include "qapi/qapi-commands-target.h"
#include "standard-headers/asm-x86/kvm_para.h"
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
- NULL, NULL, "pconfig", NULL,
+ NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, "spec-ctrl", "stibp",
NULL, "arch-capabilities", NULL, "ssbd",
CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLWB |
CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ |
CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD |
- CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT |
- CPUID_7_0_EBX_INTEL_PT,
+ CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT,
.features[FEAT_7_0_ECX] =
CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE |
CPUID_7_0_ECX_AVX512VNNI,
CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
- CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_INTEL_PT,
+ CPUID_7_0_EBX_SMAP,
.features[FEAT_7_0_ECX] =
CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU |
CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI |
CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLWB |
CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ |
CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD |
- CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT |
- CPUID_7_0_EBX_INTEL_PT,
+ CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT,
.features[FEAT_7_0_ECX] =
CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU |
CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI |
CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG |
CPUID_7_0_ECX_AVX512_VPOPCNTDQ | CPUID_7_0_ECX_LA57,
.features[FEAT_7_0_EDX] =
- CPUID_7_0_EDX_PCONFIG | CPUID_7_0_EDX_SPEC_CTRL |
- CPUID_7_0_EDX_SPEC_CTRL_SSBD,
+ CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD,
/* Missing: XSAVES (not supported by some Linux versions,
* including v4.1 to v4.12).
* KVM doesn't yet expose any XSAVES state save component,
*cpu_list = entry;
}
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
{
CpuDefinitionInfoList *cpu_list = NULL;
GSList *list = get_sorted_cpu_model_list();
}
+#ifndef CONFIG_USER_ONLY
/* Return a QDict containing keys for all properties that can be included
* in static expansion of CPU models. All properties set by x86_cpu_load_def()
* must be included in the dictionary.
}
CpuModelExpansionInfo *
-arch_query_cpu_model_expansion(CpuModelExpansionType type,
+qmp_query_cpu_model_expansion(CpuModelExpansionType type,
CpuModelInfo *model,
Error **errp)
{
}
return ret;
}
+#endif /* !CONFIG_USER_ONLY */
static gchar *x86_gdb_arch_name(CPUState *cs)
{
cc->gdb_arch_name = x86_gdb_arch_name;
#ifdef TARGET_X86_64
cc->gdb_core_xml_file = "i386-64bit.xml";
- cc->gdb_num_core_regs = 57;
+ cc->gdb_num_core_regs = 66;
#else
cc->gdb_core_xml_file = "i386-32bit.xml";
- cc->gdb_num_core_regs = 41;
+ cc->gdb_num_core_regs = 50;
#endif
#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
cc->debug_excp_handler = breakpoint_handler;
#define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network Instructions */
#define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */
-#define CPUID_7_0_EDX_PCONFIG (1U << 18) /* Platform Configuration */
#define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Speculation Control */
#define CPUID_7_0_EDX_ARCH_CAPABILITIES (1U << 29) /*Arch Capabilities*/
#define CPUID_7_0_EDX_SPEC_CTRL_SSBD (1U << 31) /* Speculative Store Bypass Disable */
#endif
static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+/*
+ * Keep these in sync with assignment to
+ * gdb_num_core_regs in target/i386/cpu.c
+ * and with the machine description
+ */
+
+/*
+ * SEG: 6 segments, plus fs_base, gs_base, kernel_gs_base
+ */
+
+/*
+ * general regs -----> 8 or 16
+ */
+#define IDX_NB_IP 1
+#define IDX_NB_FLAGS 1
+#define IDX_NB_SEG (6 + 3)
+#define IDX_NB_CTL 6
+#define IDX_NB_FP 16
+/*
+ * fpu regs ----------> 8 or 16
+ */
+#define IDX_NB_MXCSR 1
+/*
+ * total ----> 8+1+1+9+6+16+8+1=50 or 16+1+1+9+6+16+16+1=66
+ */
+
#define IDX_IP_REG CPU_NB_REGS
-#define IDX_FLAGS_REG (IDX_IP_REG + 1)
-#define IDX_SEG_REGS (IDX_FLAGS_REG + 1)
-#define IDX_FP_REGS (IDX_SEG_REGS + 6)
-#define IDX_XMM_REGS (IDX_FP_REGS + 16)
+#define IDX_FLAGS_REG (IDX_IP_REG + IDX_NB_IP)
+#define IDX_SEG_REGS (IDX_FLAGS_REG + IDX_NB_FLAGS)
+#define IDX_CTL_REGS (IDX_SEG_REGS + IDX_NB_SEG)
+#define IDX_FP_REGS (IDX_CTL_REGS + IDX_NB_CTL)
+#define IDX_XMM_REGS (IDX_FP_REGS + IDX_NB_FP)
#define IDX_MXCSR_REG (IDX_XMM_REGS + CPU_NB_REGS)
+#define IDX_CTL_CR0_REG (IDX_CTL_REGS + 0)
+#define IDX_CTL_CR2_REG (IDX_CTL_REGS + 1)
+#define IDX_CTL_CR3_REG (IDX_CTL_REGS + 2)
+#define IDX_CTL_CR4_REG (IDX_CTL_REGS + 3)
+#define IDX_CTL_CR8_REG (IDX_CTL_REGS + 4)
+#define IDX_CTL_EFER_REG (IDX_CTL_REGS + 5)
+
+#ifdef TARGET_X86_64
+#define GDB_FORCE_64 1
+#else
+#define GDB_FORCE_64 0
+#endif
+
+
int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
{
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;
+ uint64_t tpr;
+
/* N.B. GDB can't deal with changes in registers or sizes in the middle
of a session. So if we're in 32-bit mode on a 64-bit cpu, still act
as if we're on a 64-bit cpu. */
case IDX_SEG_REGS + 5:
return gdb_get_reg32(mem_buf, env->segs[R_GS].selector);
+ case IDX_SEG_REGS + 6:
+ if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+ return gdb_get_reg64(mem_buf, env->segs[R_FS].base);
+ }
+ return gdb_get_reg32(mem_buf, env->segs[R_FS].base);
+
+ case IDX_SEG_REGS + 7:
+ if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+ return gdb_get_reg64(mem_buf, env->segs[R_GS].base);
+ }
+ return gdb_get_reg32(mem_buf, env->segs[R_GS].base);
+
+ case IDX_SEG_REGS + 8:
+#ifdef TARGET_X86_64
+ if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+ return gdb_get_reg64(mem_buf, env->kernelgsbase);
+ }
+ return gdb_get_reg32(mem_buf, env->kernelgsbase);
+#else
+ return gdb_get_reg32(mem_buf, 0);
+#endif
+
case IDX_FP_REGS + 8:
return gdb_get_reg32(mem_buf, env->fpuc);
case IDX_FP_REGS + 9:
case IDX_MXCSR_REG:
return gdb_get_reg32(mem_buf, env->mxcsr);
+
+ case IDX_CTL_CR0_REG:
+ if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+ return gdb_get_reg64(mem_buf, env->cr[0]);
+ }
+ return gdb_get_reg32(mem_buf, env->cr[0]);
+
+ case IDX_CTL_CR2_REG:
+ if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+ return gdb_get_reg64(mem_buf, env->cr[2]);
+ }
+ return gdb_get_reg32(mem_buf, env->cr[2]);
+
+ case IDX_CTL_CR3_REG:
+ if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+ return gdb_get_reg64(mem_buf, env->cr[3]);
+ }
+ return gdb_get_reg32(mem_buf, env->cr[3]);
+
+ case IDX_CTL_CR4_REG:
+ if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+ return gdb_get_reg64(mem_buf, env->cr[4]);
+ }
+ return gdb_get_reg32(mem_buf, env->cr[4]);
+
+ case IDX_CTL_CR8_REG:
+#ifdef CONFIG_SOFTMMU
+ tpr = cpu_get_apic_tpr(cpu->apic_state);
+#else
+ tpr = 0;
+#endif
+ if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+ return gdb_get_reg64(mem_buf, tpr);
+ }
+ return gdb_get_reg32(mem_buf, tpr);
+
+ case IDX_CTL_EFER_REG:
+ if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+ return gdb_get_reg64(mem_buf, env->efer);
+ }
+ return gdb_get_reg32(mem_buf, env->efer);
}
}
return 0;
case IDX_SEG_REGS + 5:
return x86_cpu_gdb_load_seg(cpu, R_GS, mem_buf);
+ case IDX_SEG_REGS + 6:
+ if (env->hflags & HF_CS64_MASK) {
+ env->segs[R_FS].base = ldq_p(mem_buf);
+ return 8;
+ }
+ env->segs[R_FS].base = ldl_p(mem_buf);
+ return 4;
+
+ case IDX_SEG_REGS + 7:
+ if (env->hflags & HF_CS64_MASK) {
+ env->segs[R_GS].base = ldq_p(mem_buf);
+ return 8;
+ }
+ env->segs[R_GS].base = ldl_p(mem_buf);
+ return 4;
+
+#ifdef TARGET_X86_64
+ case IDX_SEG_REGS + 8:
+ if (env->hflags & HF_CS64_MASK) {
+ env->kernelgsbase = ldq_p(mem_buf);
+ return 8;
+ }
+ env->kernelgsbase = ldl_p(mem_buf);
+ return 4;
+#endif
+
case IDX_FP_REGS + 8:
cpu_set_fpuc(env, ldl_p(mem_buf));
return 4;
case IDX_MXCSR_REG:
cpu_set_mxcsr(env, ldl_p(mem_buf));
return 4;
+
+ case IDX_CTL_CR0_REG:
+ if (env->hflags & HF_CS64_MASK) {
+ cpu_x86_update_cr0(env, ldq_p(mem_buf));
+ return 8;
+ }
+ cpu_x86_update_cr0(env, ldl_p(mem_buf));
+ return 4;
+
+ case IDX_CTL_CR2_REG:
+ if (env->hflags & HF_CS64_MASK) {
+ env->cr[2] = ldq_p(mem_buf);
+ return 8;
+ }
+ env->cr[2] = ldl_p(mem_buf);
+ return 4;
+
+ case IDX_CTL_CR3_REG:
+ if (env->hflags & HF_CS64_MASK) {
+ cpu_x86_update_cr3(env, ldq_p(mem_buf));
+ return 8;
+ }
+ cpu_x86_update_cr3(env, ldl_p(mem_buf));
+ return 4;
+
+ case IDX_CTL_CR4_REG:
+ if (env->hflags & HF_CS64_MASK) {
+ cpu_x86_update_cr4(env, ldq_p(mem_buf));
+ return 8;
+ }
+ cpu_x86_update_cr4(env, ldl_p(mem_buf));
+ return 4;
+
+ case IDX_CTL_CR8_REG:
+ if (env->hflags & HF_CS64_MASK) {
+#ifdef CONFIG_SOFTMMU
+ cpu_set_apic_tpr(cpu->apic_state, ldq_p(mem_buf));
+#endif
+ return 8;
+ }
+#ifdef CONFIG_SOFTMMU
+ cpu_set_apic_tpr(cpu->apic_state, ldl_p(mem_buf));
+#endif
+ return 4;
+
+ case IDX_CTL_EFER_REG:
+ if (env->hflags & HF_CS64_MASK) {
+ cpu_load_efer(env, ldq_p(mem_buf));
+ return 8;
+ }
+ cpu_load_efer(env, ldl_p(mem_buf));
+ return 4;
+
}
}
/* Unrecognised register. */
}
hv_vm_sync_tsc(0);
- cpu->halted = 0;
hv_vcpu_invalidate_tlb(cpu->hvf_fd);
hv_vcpu_flush(cpu->hvf_fd);
}
wvmcs(cpu->hvf_fd, VMCS_TPR_THRESHOLD, 0);
- hvf_reset_vcpu(cpu);
-
x86cpu = X86_CPU(cpu);
x86cpu->env.xsave_buf = qemu_memalign(4096, 4096);
int ret = 0;
uint64_t rip = 0;
- cpu->halted = 0;
-
if (hvf_process_events(cpu)) {
return EXCP_HLT;
}
return (((uint64_t)edx) << 32) | eax;
}
-static bool vmx_mpx_supported()
-{
- uint64_t cap_exit, cap_entry;
-
- hv_vmx_read_capability(HV_VMX_CAP_ENTRY, &cap_entry);
- hv_vmx_read_capability(HV_VMX_CAP_EXIT, &cap_exit);
-
- return ((cap_exit & (1 << 23)) && (cap_entry & (1 << 16)));
-}
-
uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
int reg)
{
CPUID_7_0_EBX_CLFLUSHOPT | CPUID_7_0_EBX_CLWB |
CPUID_7_0_EBX_AVX512DQ | CPUID_7_0_EBX_SHA_NI |
CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512VL |
- CPUID_7_0_EBX_INVPCID | CPUID_7_0_EBX_MPX;
+ CPUID_7_0_EBX_INVPCID;
- if (!vmx_mpx_supported()) {
- ebx &= ~CPUID_7_0_EBX_MPX;
- }
hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
if (!(cap & CPU_BASED2_INVPCID)) {
ebx &= ~CPUID_7_0_EBX_INVPCID;
XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK |
XSTATE_ZMM_Hi256_MASK | XSTATE_Hi16_ZMM_MASK);
eax &= supp_xcr0;
- if (!vmx_mpx_supported()) {
- eax &= ~(XSTATE_BNDREGS_MASK | XSTATE_BNDCSR_MASK);
- }
} else if (idx == 1) {
hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
eax &= CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1;
X86Seg seg = R_DS;
if (!decode->modrm.mod && 6 == decode->modrm.rm) {
- op->ptr = (uint16_t)decode->displacement;
+ ptr = decode->displacement;
goto calc_addr;
}
static void kvm_update_msi_routes_all(void *private, bool global,
uint32_t index, uint32_t mask)
{
- int cnt = 0;
+ int cnt = 0, vector;
MSIRouteEntry *entry;
MSIMessage msg;
PCIDevice *dev;
/* TODO: explicit route update */
QLIST_FOREACH(entry, &msi_route_list, list) {
cnt++;
+ vector = entry->vector;
dev = entry->dev;
- if (!msix_enabled(dev) && !msi_enabled(dev)) {
+ if (msix_enabled(dev) && !msix_is_masked(dev, vector)) {
+ msg = msix_get_message(dev, vector);
+ } else if (msi_enabled(dev) && !msi_is_masked(dev, vector)) {
+ msg = msi_get_message(dev, vector);
+ } else {
+ /*
+ * Either MSI/MSIX is disabled for the device, or the
+ * specific message was masked out. Skip this one.
+ */
continue;
}
- msg = pci_get_msi_message(dev, entry->vector);
kvm_irqchip_update_msi_route(kvm_state, entry->virq, msg, dev);
}
kvm_irqchip_commit_routes(kvm_state);
#include "sysemu/kvm.h"
#include "sysemu/sev.h"
#include "qemu/error-report.h"
-#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-commands-target.h"
#define SEV_POLICY_NODBG 0x1
#define SEV_POLICY_NOKS 0x2
#include "exec/cpu-defs.h"
#include "fpu/softfloat.h"
+#define TCG_GUEST_DEFAULT_MO (0)
+
struct CPUMIPSState;
typedef struct CPUMIPSTLBContext CPUMIPSTLBContext;
#define CP0C5_NFExists 0
int32_t CP0_Config6;
int32_t CP0_Config7;
+ uint64_t CP0_LLAddr;
uint64_t CP0_MAAR[MIPS_MAAR_MAX];
int32_t CP0_MAARI;
/* XXX: Maybe make LLAddr per-TC? */
/*
* CP0 Register 17
*/
- uint64_t lladdr;
+ target_ulong lladdr; /* LL virtual address compared against SC */
target_ulong llval;
- target_ulong llnewval;
uint64_t llval_wp;
uint32_t llnewval_wp;
- target_ulong llreg;
uint64_t CP0_LLAddr_rw_bitmask;
int CP0_LLAddr_shift;
/*
EXCP_LAST = EXCP_TLBRI,
};
-/* Dummy exception for conditional stores. */
-#define EXCP_SC 0x100
/*
* This is an internally generated WAKE request line.
#include "exec/cpu_ldst.h"
#include "exec/log.h"
#include "hw/mips/cpudevs.h"
+#include "qapi/qapi-commands-target.h"
enum {
TLBRET_XI = -6,
{
CPUState *cs = CPU(mips_env_get_cpu(env));
- if (exception < EXCP_SC) {
- qemu_log_mask(CPU_LOG_INT, "%s: %d %d\n",
- __func__, exception, error_code);
- }
+ qemu_log_mask(CPU_LOG_INT, "%s: %d %d\n",
+ __func__, exception, error_code);
cs->exception_index = exception;
env->error_code = error_code;
cpu_loop_exit_restore(cs, pc);
}
+
+static void mips_cpu_add_definition(gpointer data, gpointer user_data)
+{
+ ObjectClass *oc = data;
+ CpuDefinitionInfoList **cpu_list = user_data;
+ CpuDefinitionInfoList *entry;
+ CpuDefinitionInfo *info;
+ const char *typename;
+
+ typename = object_class_get_name(oc);
+ info = g_malloc0(sizeof(*info));
+ info->name = g_strndup(typename,
+ strlen(typename) - strlen("-" TYPE_MIPS_CPU));
+ info->q_typename = g_strdup(typename);
+
+ entry = g_malloc0(sizeof(*entry));
+ entry->value = info;
+ entry->next = *cpu_list;
+ *cpu_list = entry;
+}
+
+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+{
+ CpuDefinitionInfoList *cpu_list = NULL;
+ GSList *list;
+
+ list = object_class_get_list(TYPE_MIPS_CPU, false);
+ g_slist_foreach(list, mips_cpu_add_definition, &cpu_list);
+ g_slist_free(list);
+
+ return cpu_list;
+}
#ifndef CONFIG_USER_ONLY
DEF_HELPER_3(ll, tl, env, tl, int)
-DEF_HELPER_4(sc, tl, env, tl, tl, int)
#ifdef TARGET_MIPS64
DEF_HELPER_3(lld, tl, env, tl, int)
-DEF_HELPER_4(scd, tl, env, tl, tl, int)
#endif
#endif
const VMStateDescription vmstate_mips_cpu = {
.name = "cpu",
- .version_id = 17,
- .minimum_version_id = 17,
+ .version_id = 18,
+ .minimum_version_id = 18,
.post_load = cpu_post_load,
.fields = (VMStateField[]) {
/* Active TC */
VMSTATE_INT32(env.CP0_Config3, MIPSCPU),
VMSTATE_INT32(env.CP0_Config6, MIPSCPU),
VMSTATE_INT32(env.CP0_Config7, MIPSCPU),
+ VMSTATE_UINT64(env.CP0_LLAddr, MIPSCPU),
VMSTATE_UINT64_ARRAY(env.CP0_MAAR, MIPSCPU, MIPS_MAAR_MAX),
VMSTATE_INT32(env.CP0_MAARI, MIPSCPU),
- VMSTATE_UINT64(env.lladdr, MIPSCPU),
+ VMSTATE_UINTTL(env.lladdr, MIPSCPU),
VMSTATE_UINTTL_ARRAY(env.CP0_WatchLo, MIPSCPU, 8),
VMSTATE_INT32_ARRAY(env.CP0_WatchHi, MIPSCPU, 8),
VMSTATE_UINTTL(env.CP0_XContext, MIPSCPU),
target_ulong address,
int rw, uintptr_t retaddr)
{
- hwaddr lladdr;
+ hwaddr paddr;
CPUState *cs = CPU(mips_env_get_cpu(env));
- lladdr = cpu_mips_translate_address(env, address, rw);
+ paddr = cpu_mips_translate_address(env, address, rw);
- if (lladdr == -1LL) {
+ if (paddr == -1LL) {
cpu_loop_exit_restore(cs, retaddr);
} else {
- return lladdr;
+ return paddr;
}
}
} \
do_raise_exception(env, EXCP_AdEL, GETPC()); \
} \
- env->lladdr = do_translate_address(env, arg, 0, GETPC()); \
+ env->CP0_LLAddr = do_translate_address(env, arg, 0, GETPC()); \
+ env->lladdr = arg; \
env->llval = do_##insn(env, arg, mem_idx, GETPC()); \
return env->llval; \
}
HELPER_LD_ATOMIC(lld, ld, 0x7)
#endif
#undef HELPER_LD_ATOMIC
-
-#define HELPER_ST_ATOMIC(name, ld_insn, st_insn, almask) \
-target_ulong helper_##name(CPUMIPSState *env, target_ulong arg1, \
- target_ulong arg2, int mem_idx) \
-{ \
- target_long tmp; \
- \
- if (arg2 & almask) { \
- if (!(env->hflags & MIPS_HFLAG_DM)) { \
- env->CP0_BadVAddr = arg2; \
- } \
- do_raise_exception(env, EXCP_AdES, GETPC()); \
- } \
- if (do_translate_address(env, arg2, 1, GETPC()) == env->lladdr) { \
- tmp = do_##ld_insn(env, arg2, mem_idx, GETPC()); \
- if (tmp == env->llval) { \
- do_##st_insn(env, arg2, arg1, mem_idx, GETPC()); \
- return 1; \
- } \
- } \
- return 0; \
-}
-HELPER_ST_ATOMIC(sc, lw, sw, 0x3)
-#ifdef TARGET_MIPS64
-HELPER_ST_ATOMIC(scd, ld, sd, 0x7)
-#endif
-#undef HELPER_ST_ATOMIC
#endif
#ifdef TARGET_WORDS_BIGENDIAN
/* Don't set ->halted = 0 directly, let it be done via cpu_has_work
because there might be other conditions that state that c should
be sleeping. */
+ qemu_mutex_lock_iothread();
cpu_interrupt(CPU(c), CPU_INTERRUPT_WAKE);
+ qemu_mutex_unlock_iothread();
}
static inline void mips_vpe_sleep(MIPSCPU *cpu)
target_ulong helper_mfc0_count(CPUMIPSState *env)
{
- int32_t count;
- qemu_mutex_lock_iothread();
- count = (int32_t) cpu_mips_get_count(env);
- qemu_mutex_unlock_iothread();
- return count;
+ return (int32_t)cpu_mips_get_count(env);
}
target_ulong helper_mfc0_saar(CPUMIPSState *env)
target_ulong helper_mfc0_lladdr(CPUMIPSState *env)
{
- return (int32_t)(env->lladdr >> env->CP0_LLAddr_shift);
+ return (int32_t)(env->CP0_LLAddr >> env->CP0_LLAddr_shift);
}
target_ulong helper_mfc0_maar(CPUMIPSState *env)
target_ulong helper_dmfc0_lladdr(CPUMIPSState *env)
{
- return env->lladdr >> env->CP0_LLAddr_shift;
+ return env->CP0_LLAddr >> env->CP0_LLAddr_shift;
}
target_ulong helper_dmfc0_maar(CPUMIPSState *env)
{
env->active_tc.PC = arg1;
env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
- env->lladdr = 0ULL;
+ env->CP0_LLAddr = 0;
+ env->lladdr = 0;
/* MIPS16 not implemented. */
}
if (other_tc == other->current_tc) {
other->active_tc.PC = arg1;
other->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
- other->lladdr = 0ULL;
+ other->CP0_LLAddr = 0;
+ other->lladdr = 0;
/* MIPS16 not implemented. */
} else {
other->tcs[other_tc].PC = arg1;
other->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
- other->lladdr = 0ULL;
+ other->CP0_LLAddr = 0;
+ other->lladdr = 0;
/* MIPS16 not implemented. */
}
}
void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1)
{
- qemu_mutex_lock_iothread();
cpu_mips_store_count(env, arg1);
- qemu_mutex_unlock_iothread();
}
void helper_mtc0_saari(CPUMIPSState *env, target_ulong arg1)
void helper_mtc0_compare(CPUMIPSState *env, target_ulong arg1)
{
- qemu_mutex_lock_iothread();
cpu_mips_store_compare(env, arg1);
- qemu_mutex_unlock_iothread();
}
void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1)
void helper_mtc0_cause(CPUMIPSState *env, target_ulong arg1)
{
- qemu_mutex_lock_iothread();
cpu_mips_store_cause(env, arg1);
- qemu_mutex_unlock_iothread();
}
void helper_mttc0_cause(CPUMIPSState *env, target_ulong arg1)
{
target_long mask = env->CP0_LLAddr_rw_bitmask;
arg1 = arg1 << env->CP0_LLAddr_shift;
- env->lladdr = (env->lladdr & ~mask) | (arg1 & mask);
+ env->CP0_LLAddr = (env->CP0_LLAddr & ~mask) | (arg1 & mask);
}
#define MTC0_MAAR_MASK(env) \
void helper_eret(CPUMIPSState *env)
{
exception_return(env);
+ env->CP0_LLAddr = 1;
env->lladdr = 1;
}
target_ulong helper_rdhwr_cc(CPUMIPSState *env)
{
- int32_t count;
check_hwrena(env, 2, GETPC());
#ifdef CONFIG_USER_ONLY
- count = env->CP0_Count;
+ return env->CP0_Count;
#else
- qemu_mutex_lock_iothread();
- count = (int32_t)cpu_mips_get_count(env);
- qemu_mutex_unlock_iothread();
+ return (int32_t)cpu_mips_get_count(env);
#endif
- return count;
}
target_ulong helper_rdhwr_ccres(CPUMIPSState *env)
static TCGv cpu_gpr[32], cpu_PC;
static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
static TCGv cpu_dspctrl, btarget, bcond;
+static TCGv cpu_lladdr, cpu_llval;
static TCGv_i32 hflags;
static TCGv_i32 fpu_fcr0, fpu_fcr31;
static TCGv_i64 fpu_f64[32];
#endif
#undef OP_LD_ATOMIC
-#ifdef CONFIG_USER_ONLY
-#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
-static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
- DisasContext *ctx) \
-{ \
- TCGv t0 = tcg_temp_new(); \
- TCGLabel *l1 = gen_new_label(); \
- TCGLabel *l2 = gen_new_label(); \
- \
- tcg_gen_andi_tl(t0, arg2, almask); \
- tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
- tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
- generate_exception(ctx, EXCP_AdES); \
- gen_set_label(l1); \
- tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
- tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
- tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
- tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
- tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
- generate_exception_end(ctx, EXCP_SC); \
- gen_set_label(l2); \
- tcg_gen_movi_tl(t0, 0); \
- gen_store_gpr(t0, rt); \
- tcg_temp_free(t0); \
-}
-#else
-#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
-static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
- DisasContext *ctx) \
-{ \
- TCGv t0 = tcg_temp_new(); \
- gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
- gen_store_gpr(t0, rt); \
- tcg_temp_free(t0); \
-}
-#endif
-OP_ST_ATOMIC(sc,st32,ld32s,0x3);
-#if defined(TARGET_MIPS64)
-OP_ST_ATOMIC(scd,st64,ld64,0x7);
-#endif
-#undef OP_ST_ATOMIC
-
static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
int base, int offset)
{
/* Store conditional */
-static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
- int base, int16_t offset)
+static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
+ TCGMemOp tcg_mo, bool eva)
{
- TCGv t0, t1;
- int mem_idx = ctx->mem_idx;
+ TCGv addr, t0, val;
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *done = gen_new_label();
-#ifdef CONFIG_USER_ONLY
- t0 = tcg_temp_local_new();
- t1 = tcg_temp_local_new();
-#else
t0 = tcg_temp_new();
- t1 = tcg_temp_new();
-#endif
- gen_base_offset_addr(ctx, t0, base, offset);
- gen_load_gpr(t1, rt);
- switch (opc) {
-#if defined(TARGET_MIPS64)
- case OPC_SCD:
- case R6_OPC_SCD:
- op_st_scd(t1, t0, rt, mem_idx, ctx);
- break;
-#endif
- case OPC_SCE:
- mem_idx = MIPS_HFLAG_UM;
- /* fall through */
- case OPC_SC:
- case R6_OPC_SC:
- op_st_sc(t1, t0, rt, mem_idx, ctx);
- break;
- }
- tcg_temp_free(t1);
+ addr = tcg_temp_new();
+ /* compare the address against that of the preceeding LL */
+ gen_base_offset_addr(ctx, addr, base, offset);
+ tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
+ tcg_temp_free(addr);
+ tcg_gen_movi_tl(t0, 0);
+ gen_store_gpr(t0, rt);
+ tcg_gen_br(done);
+
+ gen_set_label(l1);
+ /* generate cmpxchg */
+ val = tcg_temp_new();
+ gen_load_gpr(val, rt);
+ tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
+ eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
+ tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
+ gen_store_gpr(t0, rt);
+ tcg_temp_free(val);
+
+ gen_set_label(done);
tcg_temp_free(t0);
}
+
static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
uint32_t reg1, uint32_t reg2, bool eva)
{
tcg_temp_free(t1);
}
+#if defined(TARGET_MIPS64)
/* Copy GPR to and from TX79 HI1/LO1 register. */
static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
{
break;
}
}
+#endif
/* Arithmetic on HI/LO registers */
static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
tcg_temp_free(t1);
}
+#if defined(TARGET_MIPS64)
static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
{
TCGv t0, t1;
tcg_temp_free(t0);
tcg_temp_free(t1);
}
+#endif
static void gen_muldiv(DisasContext *ctx, uint32_t opc,
int acc, int rs, int rt)
case CP0_REGISTER_17:
switch (sel) {
case 0:
- gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
+ gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
ctx->CP0_LLAddr_shift);
register_name = "LLAddr";
break;
gen_st(ctx, mips32_op, rt, rs, offset);
break;
case SC:
- gen_st_cond(ctx, OPC_SC, rt, rs, offset);
+ gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
break;
#if defined(TARGET_MIPS64)
case SCD:
check_insn(ctx, ISA_MIPS3);
check_mips_64(ctx);
- gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
+ gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
break;
#endif
case LD_EVA:
mips32_op = OPC_SHE;
goto do_st_lr;
case SCE:
- gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
+ gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
break;
case SWE:
mips32_op = OPC_SWE;
case NM_P_SC:
switch (ctx->opcode & 0x03) {
case NM_SC:
- gen_st_cond(ctx, OPC_SC, rt, rs, s);
+ gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
break;
case NM_SCWP:
check_xnp(ctx);
check_xnp(ctx);
check_eva(ctx);
check_cp0_enabled(ctx);
- gen_st_cond(ctx, OPC_SCE, rt, rs, s);
+ gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
break;
case NM_SCWPE:
check_xnp(ctx);
}
+#if defined(TARGET_MIPS64)
+
+/*
+ *
+ * MMI (MultiMedia Interface) ASE instructions
+ * ===========================================
+ */
+
+/*
+ * MMI instructions category: data communication
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
+ * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
+ * PCPYUD PEXEH PEXTLW PPACW
+ * PEXEW PEXTUB
+ * PEXTUH
+ * PEXTUW
+ */
+
+#endif
+
+
#if !defined(TARGET_MIPS64)
/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
}
break;
case R6_OPC_SC:
- gen_st_cond(ctx, op1, rt, rs, imm);
+ gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
break;
case R6_OPC_LL:
gen_ld(ctx, op1, rt, rs, imm);
break;
#if defined(TARGET_MIPS64)
case R6_OPC_SCD:
- gen_st_cond(ctx, op1, rt, rs, imm);
+ gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
break;
case R6_OPC_LLD:
gen_ld(ctx, op1, rt, rs, imm);
}
}
+
+#if defined(TARGET_MIPS64)
+
static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
{
uint32_t opc = MASK_MMI0(ctx->opcode);
gen_mmi_sq(ctx, base, rt, offset);
}
+#endif
+
static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
{
int rs, rt, rd, sa;
return;
case OPC_SCE:
check_cp0_enabled(ctx);
- gen_st_cond(ctx, op1, rt, rs, imm);
+ gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
return;
case OPC_CACHEE:
check_cp0_enabled(ctx);
decode_opc_special(env, ctx);
break;
case OPC_SPECIAL2:
+#if defined(TARGET_MIPS64)
if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
decode_mmi(env, ctx);
-#if !defined(TARGET_MIPS64)
- } else if (ctx->insn_flags & ASE_MXU) {
+#else
+ if (ctx->insn_flags & ASE_MXU) {
decode_opc_mxu(env, ctx);
#endif
} else {
}
break;
case OPC_SPECIAL3:
+#if defined(TARGET_MIPS64)
if (ctx->insn_flags & INSN_R5900) {
decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
} else {
decode_opc_special3(env, ctx);
}
+#else
+ decode_opc_special3(env, ctx);
+#endif
break;
case OPC_REGIMM:
op1 = MASK_REGIMM(ctx->opcode);
if (ctx->insn_flags & INSN_R5900) {
check_insn_opc_user_only(ctx, INSN_R5900);
}
- gen_st_cond(ctx, op, rt, rs, imm);
- break;
+ gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
+ break;
case OPC_CACHE:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
check_cp0_enabled(ctx);
check_insn_opc_user_only(ctx, INSN_R5900);
}
check_mips_64(ctx);
- gen_st_cond(ctx, op, rt, rs, imm);
+ gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
break;
case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
if (ctx->insn_flags & ISA_MIPS32R6) {
break;
case OPC_MSA: /* OPC_MDMX */
if (ctx->insn_flags & INSN_R5900) {
+#if defined(TARGET_MIPS64)
gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
+#endif
} else {
/* MDMX: Not implemented. */
gen_msa(env, ctx);
env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
PRIx64 "\n",
- env->CP0_Config0, env->CP0_Config1, env->lladdr);
+ env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
env->CP0_Config2, env->CP0_Config3);
cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUMIPSState, active_fpu.fcr31),
"fcr31");
+ cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
+ "lladdr");
+ cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
+ "llval");
#if defined(TARGET_MIPS64)
cpu_mmr[0] = NULL;
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
+ * You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
+ * You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
+ * You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
+ * You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2 of
+ * as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
+ * You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "elf.h"
#include "sysemu/dump.h"
#include "sysemu/kvm.h"
+#include "exec/helper-proto.h"
#ifdef TARGET_PPC64
#define ELFCLASS ELFCLASS64
vmxregset->avr[i].u64[1] = avr->u64[1];
}
}
- vmxregset->vscr.u32[3] = cpu_to_dump32(s, cpu->env.vscr);
+ vmxregset->vscr.u32[3] = cpu_to_dump32(s, helper_mfvscr(&cpu->env));
}
static void ppc_write_elf_vsxregset(NoteFuncArg *arg, PowerPCCPU *cpu)
POWERPC_EXCP_POWER7,
/* POWER8 exception model */
POWERPC_EXCP_POWER8,
+ /* POWER9 exception model */
+ POWERPC_EXCP_POWER9,
};
/*****************************************************************************/
PPC_PM_NAP,
PPC_PM_SLEEP,
PPC_PM_RVWINKLE,
+ PPC_PM_STOP,
} powerpc_pm_insn_t;
/*****************************************************************************/
PPC_FLAGS_INPUT_970,
/* PowerPC POWER7 bus */
PPC_FLAGS_INPUT_POWER7,
+ /* PowerPC POWER9 bus */
+ PPC_FLAGS_INPUT_POWER9,
/* PowerPC 401 bus */
PPC_FLAGS_INPUT_401,
/* Freescale RCPU bus */
uint32_t flags;
int bfd_mach;
uint32_t l1_dcache_size, l1_icache_size;
+#ifndef CONFIG_USER_ONLY
+ unsigned int gdb_num_sprs;
+ const char *gdb_spr_xml;
+#endif
const PPCHash64Options *hash64_opts;
struct ppc_radix_page_info *radix_page_info;
void (*init_proc)(CPUPPCState *env);
/* Server doorbell variants */
POWERPC_EXCP_SDOOR = 99,
POWERPC_EXCP_SDOOR_HV = 100,
+ /* ISA 3.00 additions */
+ POWERPC_EXCP_HVIRT = 101,
/* EOL */
- POWERPC_EXCP_NB = 101,
+ POWERPC_EXCP_NB = 102,
/* QEMU exceptions: used internally during code translation */
POWERPC_EXCP_STOP = 0x200, /* stop translation */
POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */
void (*oea_write)(DisasContext *ctx, int spr_num, int gpr_num);
void (*hea_read)(DisasContext *ctx, int gpr_num, int spr_num);
void (*hea_write)(DisasContext *ctx, int spr_num, int gpr_num);
+ unsigned int gdb_id;
#endif
const char *name;
target_ulong default_value;
#define SEGMENT_SHIFT_1T 40
#define SEGMENT_MASK_1T (~((1ULL << SEGMENT_SHIFT_1T) - 1))
+typedef struct ppc_v3_pate_t {
+ uint64_t dw0;
+ uint64_t dw1;
+} ppc_v3_pate_t;
/*****************************************************************************/
/* Machine state register bits definition */
#define LPCR_AIL (3ull << LPCR_AIL_SHIFT)
#define LPCR_UPRT PPC_BIT(41) /* Use Process Table */
#define LPCR_EVIRT PPC_BIT(42) /* Enhanced Virtualisation */
+#define LPCR_HR PPC_BIT(43) /* Host Radix */
#define LPCR_ONL PPC_BIT(45)
#define LPCR_LD PPC_BIT(46) /* Large Decrementer */
#define LPCR_P7_PECE0 PPC_BIT(49)
#define LPCR_HVICE PPC_BIT(62) /* HV Virtualisation Int Enable */
#define LPCR_HDICE PPC_BIT(63)
+/* PSSCR bits */
+#define PSSCR_ESL PPC_BIT(42) /* Enable State Loss */
+#define PSSCR_EC PPC_BIT(43) /* Exit Criterion */
+
#define msr_sf ((env->msr >> MSR_SF) & 1)
#define msr_isf ((env->msr >> MSR_ISF) & 1)
#define msr_shv ((env->msr >> MSR_SHV) & 1)
/* Vector status and control register */
#define VSCR_NJ 16 /* Vector non-java */
#define VSCR_SAT 0 /* Vector saturation */
-#define vscr_nj (((env->vscr) >> VSCR_NJ) & 0x1)
-#define vscr_sat (((env->vscr) >> VSCR_SAT) & 0x1)
/*****************************************************************************/
/* BookE e500 MMU registers */
/* Special purpose registers */
target_ulong spr[1024];
ppc_spr_t spr_cb[1024];
- /* Vector status and control register */
+ /* Vector status and control register, minus VSCR_SAT. */
uint32_t vscr;
/* VSX registers (including FP and AVR) */
ppc_vsr_t vsr[64] QEMU_ALIGNED(16);
+ /* Non-zero if and only if VSCR_SAT should be set. */
+ ppc_vsr_t vscr_sat QEMU_ALIGNED(16);
/* SPE registers */
uint64_t spe_acc;
uint32_t spe_fscr;
* instructions and SPRs are diallowed if MSR:HV is 0
*/
bool has_hv_mode;
- /* On P7/P8, set when in PM state, we need to handle resume
- * in a special way (such as routing some resume causes to
- * 0x100), so flag this here.
+
+ /*
+ * On P7/P8/P9, set when in PM state, we need to handle resume in
+ * a special way (such as routing some resume causes to 0x100, ie,
+ * sreset), so flag this here.
*/
- bool in_pm_state;
+ bool resume_as_sreset;
#endif
/* Those resources are used only during code translation */
hwaddr ptex, int n);
void (*store_hpte)(PPCVirtualHypervisor *vhyp, hwaddr ptex,
uint64_t pte0, uint64_t pte1);
- uint64_t (*get_patbe)(PPCVirtualHypervisor *vhyp);
+ void (*get_pate)(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry);
target_ulong (*encode_hpt_for_kvm_pr)(PPCVirtualHypervisor *vhyp);
};
int ppc_cpu_gdb_read_register_apple(CPUState *cpu, uint8_t *buf, int reg);
int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
int ppc_cpu_gdb_write_register_apple(CPUState *cpu, uint8_t *buf, int reg);
+#ifndef CONFIG_USER_ONLY
+void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu);
+const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name);
+#endif
int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
int cpuid, void *opaque);
int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
* them */
POWER7_INPUT_NB,
};
+
+enum {
+ /* POWER9 input pins */
+ POWER9_INPUT_INT = 0,
+ POWER9_INPUT_HINT = 1,
+ POWER9_INPUT_NB,
+};
#endif
/* Hardware exceptions definitions */
PPC_INTERRUPT_PERFM, /* Performance monitor interrupt */
PPC_INTERRUPT_HMI, /* Hypervisor Maintainance interrupt */
PPC_INTERRUPT_HDOORBELL, /* Hypervisor Doorbell interrupt */
+ PPC_INTERRUPT_HVIRT, /* Hypervisor virtualization interrupt */
};
/* Processor Compatibility mask (PCR) */
ppc_dump_gpr(env, 6), env->nip);
}
+static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
+ target_ulong *msr)
+{
+ /* We no longer are in a PM state */
+ env->resume_as_sreset = false;
+
+ /* Pretend to be returning from doze always as we don't lose state */
+ *msr |= (0x1ull << (63 - 47));
+
+ /* Machine checks are sent normally */
+ if (excp == POWERPC_EXCP_MCHECK) {
+ return excp;
+ }
+ switch (excp) {
+ case POWERPC_EXCP_RESET:
+ *msr |= 0x4ull << (63 - 45);
+ break;
+ case POWERPC_EXCP_EXTERNAL:
+ *msr |= 0x8ull << (63 - 45);
+ break;
+ case POWERPC_EXCP_DECR:
+ *msr |= 0x6ull << (63 - 45);
+ break;
+ case POWERPC_EXCP_SDOOR:
+ *msr |= 0x5ull << (63 - 45);
+ break;
+ case POWERPC_EXCP_SDOOR_HV:
+ *msr |= 0x3ull << (63 - 45);
+ break;
+ case POWERPC_EXCP_HV_MAINT:
+ *msr |= 0xaull << (63 - 45);
+ break;
+ case POWERPC_EXCP_HVIRT:
+ *msr |= 0x9ull << (63 - 45);
+ break;
+ default:
+ cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
+ excp);
+ }
+ return POWERPC_EXCP_RESET;
+}
+
+
/* Note that this function should be greatly optimized
* when called with a constant excp, from ppc_hw_interrupt
*/
asrr0 = -1;
asrr1 = -1;
- /* check for special resume at 0x100 from doze/nap/sleep/winkle on P7/P8 */
- if (env->in_pm_state) {
- env->in_pm_state = false;
-
- /* Pretend to be returning from doze always as we don't lose state */
- msr |= (0x1ull << (63 - 47));
-
- /* Non-machine check are routed to 0x100 with a wakeup cause
- * encoded in SRR1
- */
- if (excp != POWERPC_EXCP_MCHECK) {
- switch (excp) {
- case POWERPC_EXCP_RESET:
- msr |= 0x4ull << (63 - 45);
- break;
- case POWERPC_EXCP_EXTERNAL:
- msr |= 0x8ull << (63 - 45);
- break;
- case POWERPC_EXCP_DECR:
- msr |= 0x6ull << (63 - 45);
- break;
- case POWERPC_EXCP_SDOOR:
- msr |= 0x5ull << (63 - 45);
- break;
- case POWERPC_EXCP_SDOOR_HV:
- msr |= 0x3ull << (63 - 45);
- break;
- case POWERPC_EXCP_HV_MAINT:
- msr |= 0xaull << (63 - 45);
- break;
- default:
- cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
- excp);
- }
- excp = POWERPC_EXCP_RESET;
- }
+ /*
+ * check for special resume at 0x100 from doze/nap/sleep/winkle on
+ * P7/P8/P9
+ */
+ if (env->resume_as_sreset) {
+ excp = powerpc_reset_wakeup(cs, env, excp, &msr);
}
/* Exception targetting modifiers
*
- * LPES0 is supported on POWER7/8
+ * LPES0 is supported on POWER7/8/9
* LPES1 is not supported (old iSeries mode)
*
* On anything else, we behave as if LPES0 is 1
*/
#if defined(TARGET_PPC64)
if (excp_model == POWERPC_EXCP_POWER7 ||
- excp_model == POWERPC_EXCP_POWER8) {
+ excp_model == POWERPC_EXCP_POWER8 ||
+ excp_model == POWERPC_EXCP_POWER9) {
lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
- if (excp_model == POWERPC_EXCP_POWER8) {
+ if (excp_model != POWERPC_EXCP_POWER7) {
ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
} else {
ail = 0;
case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */
case POWERPC_EXCP_HV_EMU:
+ case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */
srr0 = SPR_HSRR0;
srr1 = SPR_HSRR1;
new_msr |= (target_ulong)MSR_HVB;
}
} else if (excp_model == POWERPC_EXCP_POWER8) {
if (new_msr & MSR_HVB) {
- if (env->spr[SPR_HID0] & (HID0_HILE | HID0_POWER9_HILE)) {
+ if (env->spr[SPR_HID0] & HID0_HILE) {
+ new_msr |= (target_ulong)1 << MSR_LE;
+ }
+ } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
+ new_msr |= (target_ulong)1 << MSR_LE;
+ }
+ } else if (excp_model == POWERPC_EXCP_POWER9) {
+ if (new_msr & MSR_HVB) {
+ if (env->spr[SPR_HID0] & HID0_POWER9_HILE) {
new_msr |= (target_ulong)1 << MSR_LE;
}
} else if (env->spr[SPR_LPCR] & LPCR_ILE) {
static void ppc_hw_interrupt(CPUPPCState *env)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
-#if 0
- CPUState *cs = CPU(cpu);
+ bool async_deliver;
- qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
- __func__, env, env->pending_interrupts,
- cs->interrupt_request, (int)msr_me, (int)msr_ee);
-#endif
/* External reset */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
return;
}
#endif
+
+ /*
+ * For interrupts that gate on MSR:EE, we need to do something a
+ * bit more subtle, as we need to let them through even when EE is
+ * clear when coming out of some power management states (in order
+ * for them to become a 0x100).
+ */
+ async_deliver = (msr_ee != 0) || env->resume_as_sreset;
+
/* Hypervisor decrementer exception */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
/* LPCR will be clear when not supported so this will work */
bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
- if ((msr_ee != 0 || msr_hv == 0) && hdice) {
+ if ((async_deliver || msr_hv == 0) && hdice) {
/* HDEC clears on delivery */
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
return;
}
}
- /* Extermal interrupt can ignore MSR:EE under some circumstances */
+
+ /* Hypervisor virtualization interrupt */
+ if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) {
+ /* LPCR will be clear when not supported so this will work */
+ bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
+ if ((async_deliver || msr_hv == 0) && hvice) {
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT);
+ return;
+ }
+ }
+
+ /* External interrupt can ignore MSR:EE under some circumstances */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
- if (msr_ee != 0 || (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
+ bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
+ /* HEIC blocks delivery to the hypervisor */
+ if ((async_deliver && !(heic && msr_hv && !msr_pr)) ||
+ (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
return;
}
if (msr_ce != 0) {
/* External critical interrupt */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
- /* Taking a critical external interrupt does not clear the external
- * critical interrupt status
- */
-#if 0
- env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
-#endif
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
return;
}
}
- if (msr_ee != 0) {
+ if (async_deliver != 0) {
/* Watchdog timer on embedded PowerPC */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
return;
}
}
+
+ if (env->resume_as_sreset) {
+ /*
+ * This is a bug ! It means that has_work took us out of halt without
+ * anything to deliver while in a PM state that requires getting
+ * out via a 0x100
+ *
+ * This means we will incorrectly execute past the power management
+ * instruction instead of triggering a reset.
+ *
+ * It generally means a discrepancy between the wakup conditions in the
+ * processor has_work implementation and the logic in this function.
+ */
+ cpu_abort(CPU(ppc_env_get_cpu(env)),
+ "Wakeup from PM state but interrupt Undelivered");
+ }
}
void ppc_cpu_do_system_reset(CPUState *cs)
cs = CPU(ppc_env_get_cpu(env));
cs->halted = 1;
- env->in_pm_state = true;
/* The architecture specifies that HDEC interrupts are
* discarded in PM states
*/
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
- /* Technically, nap doesn't set EE, but if we don't set it
- * then ppc_hw_interrupt() won't deliver. We could add some
- * other tests there based on LPCR but it's simpler to just
- * whack EE in. It will be cleared by the 0x100 at wakeup
- * anyway. It will still be observable by the guest in SRR1
- * but this doesn't seem to be a problem.
- */
- env->msr |= (1ull << MSR_EE);
- raise_exception(env, EXCP_HLT);
+ /* Condition for waking up at 0x100 */
+ env->resume_as_sreset = (insn != PPC_PM_STOP) ||
+ (env->spr[SPR_PSSCR] & PSSCR_EC);
}
#endif /* defined(TARGET_PPC64) */
}
return r;
}
+
+#ifndef CONFIG_USER_ONLY
+void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu)
+{
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ CPUPPCState *env = &cpu->env;
+ GString *xml;
+ char *spr_name;
+ unsigned int num_regs = 0;
+ int i;
+
+ if (pcc->gdb_spr_xml) {
+ return;
+ }
+
+ xml = g_string_new("<?xml version=\"1.0\"?>");
+ g_string_append(xml, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
+ g_string_append(xml, "<feature name=\"org.qemu.power.spr\">");
+
+ for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
+ ppc_spr_t *spr = &env->spr_cb[i];
+
+ if (!spr->name) {
+ continue;
+ }
+
+ spr_name = g_ascii_strdown(spr->name, -1);
+ g_string_append_printf(xml, "<reg name=\"%s\"", spr_name);
+ g_free(spr_name);
+
+ g_string_append_printf(xml, " bitsize=\"%d\"", TARGET_LONG_BITS);
+ g_string_append(xml, " group=\"spr\"/>");
+
+ /*
+ * GDB identifies registers based on the order they are
+ * presented in the XML. These ids will not match QEMU's
+ * representation (which follows the PowerISA).
+ *
+ * Store the position of the current register description so
+ * we can make the correspondence later.
+ */
+ spr->gdb_id = num_regs;
+ num_regs++;
+ }
+
+ g_string_append(xml, "</feature>");
+
+ pcc->gdb_num_sprs = num_regs;
+ pcc->gdb_spr_xml = g_string_free(xml, false);
+}
+
+const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name)
+{
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
+
+ if (strcmp(xml_name, "power-spr.xml") == 0) {
+ return pcc->gdb_spr_xml;
+ }
+ return NULL;
+}
+#endif
#define dh_ctype_avr ppc_avr_t *
#define dh_is_signed_avr dh_is_signed_ptr
-DEF_HELPER_3(vaddubm, void, avr, avr, avr)
-DEF_HELPER_3(vadduhm, void, avr, avr, avr)
-DEF_HELPER_3(vadduwm, void, avr, avr, avr)
-DEF_HELPER_3(vaddudm, void, avr, avr, avr)
-DEF_HELPER_3(vsububm, void, avr, avr, avr)
-DEF_HELPER_3(vsubuhm, void, avr, avr, avr)
-DEF_HELPER_3(vsubuwm, void, avr, avr, avr)
-DEF_HELPER_3(vsubudm, void, avr, avr, avr)
DEF_HELPER_3(vavgub, void, avr, avr, avr)
DEF_HELPER_3(vavguh, void, avr, avr, avr)
DEF_HELPER_3(vavguw, void, avr, avr, avr)
DEF_HELPER_3(vavgsb, void, avr, avr, avr)
DEF_HELPER_3(vavgsh, void, avr, avr, avr)
DEF_HELPER_3(vavgsw, void, avr, avr, avr)
-DEF_HELPER_3(vminsb, void, avr, avr, avr)
-DEF_HELPER_3(vminsh, void, avr, avr, avr)
-DEF_HELPER_3(vminsw, void, avr, avr, avr)
-DEF_HELPER_3(vminsd, void, avr, avr, avr)
-DEF_HELPER_3(vmaxsb, void, avr, avr, avr)
-DEF_HELPER_3(vmaxsh, void, avr, avr, avr)
-DEF_HELPER_3(vmaxsw, void, avr, avr, avr)
-DEF_HELPER_3(vmaxsd, void, avr, avr, avr)
-DEF_HELPER_3(vminub, void, avr, avr, avr)
-DEF_HELPER_3(vminuh, void, avr, avr, avr)
-DEF_HELPER_3(vminuw, void, avr, avr, avr)
-DEF_HELPER_3(vminud, void, avr, avr, avr)
-DEF_HELPER_3(vmaxub, void, avr, avr, avr)
-DEF_HELPER_3(vmaxuh, void, avr, avr, avr)
-DEF_HELPER_3(vmaxuw, void, avr, avr, avr)
-DEF_HELPER_3(vmaxud, void, avr, avr, avr)
DEF_HELPER_4(vcmpequb, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpequh, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpequw, void, env, avr, avr, avr)
DEF_HELPER_3(vsubcuw, void, avr, avr, avr)
DEF_HELPER_2(lvsl, void, avr, tl)
DEF_HELPER_2(lvsr, void, avr, tl)
-DEF_HELPER_4(vaddsbs, void, env, avr, avr, avr)
-DEF_HELPER_4(vaddshs, void, env, avr, avr, avr)
-DEF_HELPER_4(vaddsws, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubsbs, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubshs, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubsws, void, env, avr, avr, avr)
-DEF_HELPER_4(vaddubs, void, env, avr, avr, avr)
-DEF_HELPER_4(vadduhs, void, env, avr, avr, avr)
-DEF_HELPER_4(vadduws, void, env, avr, avr, avr)
-DEF_HELPER_4(vsububs, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubuhs, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubuws, void, env, avr, avr, avr)
+DEF_HELPER_FLAGS_5(vaddsbs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vaddshs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vaddsws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubsbs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubshs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubsws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vaddubs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vadduhs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vadduws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsububs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubuhs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubuws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
DEF_HELPER_3(vadduqm, void, avr, avr, avr)
DEF_HELPER_4(vaddecuq, void, avr, avr, avr, avr)
DEF_HELPER_4(vaddeuqm, void, avr, avr, avr, avr)
DEF_HELPER_3(vsl, void, avr, avr, avr)
DEF_HELPER_3(vsr, void, avr, avr, avr)
DEF_HELPER_4(vsldoi, void, avr, avr, avr, i32)
-DEF_HELPER_2(vspltisb, void, avr, i32)
-DEF_HELPER_2(vspltish, void, avr, i32)
-DEF_HELPER_2(vspltisw, void, avr, i32)
-DEF_HELPER_3(vspltb, void, avr, avr, i32)
-DEF_HELPER_3(vsplth, void, avr, avr, i32)
-DEF_HELPER_3(vspltw, void, avr, avr, i32)
DEF_HELPER_3(vextractub, void, avr, avr, i32)
DEF_HELPER_3(vextractuh, void, avr, avr, i32)
DEF_HELPER_3(vextractuw, void, avr, avr, i32)
DEF_HELPER_5(vmsumshm, void, env, avr, avr, avr, avr)
DEF_HELPER_5(vmsumshs, void, env, avr, avr, avr, avr)
DEF_HELPER_4(vmladduhm, void, avr, avr, avr, avr)
-DEF_HELPER_2(mtvscr, void, env, avr)
+DEF_HELPER_FLAGS_2(mtvscr, TCG_CALL_NO_RWG, void, env, i32)
+DEF_HELPER_FLAGS_1(mfvscr, TCG_CALL_NO_RWG, i32, env)
DEF_HELPER_3(lvebx, void, env, avr, tl)
DEF_HELPER_3(lvehx, void, env, avr, tl)
DEF_HELPER_3(lvewx, void, env, avr, tl)
#endif
DEF_HELPER_2(store_sdr1, void, env, tl)
DEF_HELPER_2(store_pidr, void, env, tl)
+DEF_HELPER_2(store_lpidr, void, env, tl)
DEF_HELPER_FLAGS_2(store_tbl, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_tbu, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_atbl, TCG_CALL_NO_RWG, void, env, tl)
static inline void check_tlb_flush(CPUPPCState *env, bool global)
{
CPUState *cs = CPU(ppc_env_get_cpu(env));
- if (env->tlb_need_flush & TLB_NEED_LOCAL_FLUSH) {
- tlb_flush(cs);
- env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
- }
- /* Propagate TLB invalidations to other CPUs when the guest uses broadcast
- * TLB invalidation instructions.
- */
+ /* Handle global flushes first */
if (global && (env->tlb_need_flush & TLB_NEED_GLOBAL_FLUSH)) {
- CPUState *other_cs;
- CPU_FOREACH(other_cs) {
- if (other_cs != cs) {
- PowerPCCPU *cpu = POWERPC_CPU(other_cs);
- CPUPPCState *other_env = &cpu->env;
-
- other_env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
- tlb_flush(other_cs);
- }
- }
env->tlb_need_flush &= ~TLB_NEED_GLOBAL_FLUSH;
+ env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
+ tlb_flush_all_cpus_synced(cs);
+ return;
+ }
+
+ /* Then handle local ones */
+ if (env->tlb_need_flush & TLB_NEED_LOCAL_FLUSH) {
+ env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
+ tlb_flush(cs);
}
}
#else
}
}
-void helper_mtvscr(CPUPPCState *env, ppc_avr_t *r)
+void helper_mtvscr(CPUPPCState *env, uint32_t vscr)
{
- env->vscr = r->VsrW(3);
- set_flush_to_zero(vscr_nj, &env->vec_status);
+ env->vscr = vscr & ~(1u << VSCR_SAT);
+ /* Which bit we set is completely arbitrary, but clear the rest. */
+ env->vscr_sat.u64[0] = vscr & (1u << VSCR_SAT);
+ env->vscr_sat.u64[1] = 0;
+ set_flush_to_zero((vscr >> VSCR_NJ) & 1, &env->vec_status);
+}
+
+uint32_t helper_mfvscr(CPUPPCState *env)
+{
+ uint32_t sat = (env->vscr_sat.u64[0] | env->vscr_sat.u64[1]) != 0;
+ return env->vscr | (sat << VSCR_SAT);
+}
+
+static inline void set_vscr_sat(CPUPPCState *env)
+{
+ /* The choice of non-zero value is arbitrary. */
+ env->vscr_sat.u32[0] = 1;
}
void helper_vaddcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
r->element[i] = a->element[i] op b->element[i]; \
} \
}
-#define VARITH(suffix, element) \
- VARITH_DO(add##suffix, +, element) \
- VARITH_DO(sub##suffix, -, element)
-VARITH(ubm, u8)
-VARITH(uhm, u16)
-VARITH(uwm, u32)
-VARITH(udm, u64)
VARITH_DO(muluwm, *, u32)
#undef VARITH_DO
#undef VARITH
}
#define VARITHSAT_DO(name, op, optype, cvt, element) \
- void helper_v##name(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
- ppc_avr_t *b) \
+ void helper_v##name(ppc_avr_t *r, ppc_avr_t *vscr_sat, \
+ ppc_avr_t *a, ppc_avr_t *b, uint32_t desc) \
{ \
int sat = 0; \
int i; \
\
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
- switch (sizeof(r->element[0])) { \
- case 1: \
- VARITHSAT_CASE(optype, op, cvt, element); \
- break; \
- case 2: \
- VARITHSAT_CASE(optype, op, cvt, element); \
- break; \
- case 4: \
- VARITHSAT_CASE(optype, op, cvt, element); \
- break; \
- } \
+ VARITHSAT_CASE(optype, op, cvt, element); \
} \
if (sat) { \
- env->vscr |= (1 << VSCR_SAT); \
+ vscr_sat->u32[0] = 1; \
} \
}
#define VARITHSAT_SIGNED(suffix, element, optype, cvt) \
} \
} \
if (sat) { \
- env->vscr |= (1 << VSCR_SAT); \
+ set_vscr_sat(env); \
} \
}
VCT(uxs, cvtsduw, u32)
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
-#define VMINMAX_DO(name, compare, element) \
- void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
- { \
- int i; \
- \
- for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
- if (a->element[i] compare b->element[i]) { \
- r->element[i] = b->element[i]; \
- } else { \
- r->element[i] = a->element[i]; \
- } \
- } \
- }
-#define VMINMAX(suffix, element) \
- VMINMAX_DO(min##suffix, >, element) \
- VMINMAX_DO(max##suffix, <, element)
-VMINMAX(sb, s8)
-VMINMAX(sh, s16)
-VMINMAX(sw, s32)
-VMINMAX(sd, s64)
-VMINMAX(ub, u8)
-VMINMAX(uh, u16)
-VMINMAX(uw, u32)
-VMINMAX(ud, u64)
-#undef VMINMAX_DO
-#undef VMINMAX
-
void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
int i;
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
} \
*r = result; \
if (dosat && sat) { \
- env->vscr |= (1 << VSCR_SAT); \
+ set_vscr_sat(env); \
} \
}
#define I(x, y) (x)
#endif
}
-/* Experimental testing shows that hardware masks the immediate. */
-#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
-#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
-#define VSPLT(suffix, element, access) \
- void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
- { \
- uint32_t s = b->access(SPLAT_ELEMENT(element)); \
- int i; \
- \
- for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
- r->access(i) = s; \
- } \
- }
-VSPLT(b, u8, VsrB)
-VSPLT(h, u16, VsrH)
-VSPLT(w, u32, VsrW)
-#undef VSPLT
-#undef SPLAT_ELEMENT
-#undef _SPLAT_MASKED
#if defined(HOST_WORDS_BIGENDIAN)
#define VINSERT(suffix, element) \
void helper_vinsert##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
VNEG(vnegd, s64)
#undef VNEG
-#define VSPLTI(suffix, element, splat_type) \
- void helper_vspltis##suffix(ppc_avr_t *r, uint32_t splat) \
- { \
- splat_type x = (int8_t)(splat << 3) >> 3; \
- int i; \
- \
- for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
- r->element[i] = x; \
- } \
- }
-VSPLTI(b, s8, int8_t)
-VSPLTI(h, s16, int16_t)
-VSPLTI(w, s32, int32_t)
-#undef VSPLTI
-
#define VSR(suffix, element, mask) \
void helper_vsr##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \
*r = result;
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
*r = result;
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
#include "migration/cpu.h"
#include "qapi/error.h"
#include "kvm_ppc.h"
+#include "exec/helper-proto.h"
static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
{
CPUPPCState *env = &cpu->env;
unsigned int i, j;
target_ulong sdr1;
- uint32_t fpscr;
+ uint32_t fpscr, vscr;
#if defined(TARGET_PPC64)
int32_t slb_nr;
#endif
if (!cpu->vhyp) {
ppc_store_sdr1(env, sdr1);
}
- qemu_get_be32s(f, &env->vscr);
+ qemu_get_be32s(f, &vscr);
+ helper_mtvscr(env, vscr);
qemu_get_be64s(f, &env->spe_acc);
qemu_get_be32s(f, &env->spe_fscr);
qemu_get_betls(f, &env->msr_mask);
return (cpu->env.insns_flags & PPC_ALTIVEC);
}
+static int get_vscr(QEMUFile *f, void *opaque, size_t size,
+ const VMStateField *field)
+{
+ PowerPCCPU *cpu = opaque;
+ helper_mtvscr(&cpu->env, qemu_get_be32(f));
+ return 0;
+}
+
+static int put_vscr(QEMUFile *f, void *opaque, size_t size,
+ const VMStateField *field, QJSON *vmdesc)
+{
+ PowerPCCPU *cpu = opaque;
+ qemu_put_be32(f, helper_mfvscr(&cpu->env));
+ return 0;
+}
+
+static const VMStateInfo vmstate_vscr = {
+ .name = "cpu/altivec/vscr",
+ .get = get_vscr,
+ .put = put_vscr,
+};
+
static const VMStateDescription vmstate_altivec = {
.name = "cpu/altivec",
.version_id = 1,
.needed = altivec_needed,
.fields = (VMStateField[]) {
VMSTATE_AVR_ARRAY(env.vsr, PowerPCCPU, 32),
- VMSTATE_UINT32(env.vscr, PowerPCCPU),
+ /*
+ * Save the architecture value of the vscr, not the internally
+ * expanded version. Since this architecture value does not
+ * exist in memory to be stored, this requires a but of hoop
+ * jumping. We want OFFSET=0 so that we effectively pass CPU
+ * to the helper functions.
+ */
+ {
+ .name = "vscr",
+ .version_id = 0,
+ .size = sizeof(uint32_t),
+ .info = &vmstate_vscr,
+ .flags = VMS_SINGLE,
+ .offset = 0
+ },
VMSTATE_END_OF_LIST()
},
};
tlb_flush(CPU(cpu));
}
+void helper_store_lpidr(CPUPPCState *env, target_ulong val)
+{
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+ env->spr[SPR_LPIDR] = val;
+
+ /*
+ * We need to flush the TLB on LPID changes as we only tag HV vs
+ * guest in TCG TLB. Also the quadrants means the HV will
+ * potentially access and cache entries for the current LPID as
+ * well.
+ */
+ tlb_flush(CPU(cpu));
+}
+
void helper_store_hid0_601(CPUPPCState *env, target_ulong val)
{
target_ulong hid0;
int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
int mmu_idx)
{
- if (ppc64_radix_guest(cpu)) { /* Guest uses radix */
+ if (ppc64_v3_radix(cpu)) { /* Guest uses radix */
return ppc_radix64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx);
} else { /* Guest uses hash */
return ppc_hash64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx);
}
}
+
+hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr)
+{
+ if (ppc64_v3_radix(cpu)) {
+ return ppc_radix64_get_phys_page_debug(cpu, eaddr);
+ } else {
+ return ppc_hash64_get_phys_page_debug(cpu, eaddr);
+ }
+}
+
+bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid, ppc_v3_pate_t *entry)
+{
+ uint64_t patb = cpu->env.spr[SPR_PTCR] & PTCR_PATB;
+ uint64_t pats = cpu->env.spr[SPR_PTCR] & PTCR_PATS;
+
+ /* Calculate number of entries */
+ pats = 1ull << (pats + 12 - 4);
+ if (pats <= lpid) {
+ return false;
+ }
+
+ /* Grab entry */
+ patb += 16 * lpid;
+ entry->dw0 = ldq_phys(CPU(cpu)->as, patb);
+ entry->dw1 = ldq_phys(CPU(cpu)->as, patb + 8);
+ return true;
+}
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef MMU_H
-#define MMU_H
+#ifndef MMU_BOOOK3S_V3_H
+#define MMU_BOOOK3S_V3_H
+
+#include "mmu-hash64.h"
#ifndef CONFIG_USER_ONLY
#define PTCR_PATS 0x000000000000001FULL /* Partition Table Size */
/* Partition Table Entry Fields */
-#define PATBE1_GR 0x8000000000000000
+#define PATE0_HR 0x8000000000000000
+
+/*
+ * WARNING: This field doesn't actually exist in the final version of
+ * the architecture and is unused by hardware. However, qemu uses it
+ * as an indication of a radix guest in the pseudo-PATB entry that it
+ * maintains for SPAPR guests and in the migration stream, so we need
+ * to keep it around
+ */
+#define PATE1_GR 0x8000000000000000
/* Process Table Entry */
struct prtb_entry {
return !!(cpu->env.spr[SPR_LPCR] & LPCR_UPRT);
}
-static inline bool ppc64_radix_guest(PowerPCCPU *cpu)
-{
- PPCVirtualHypervisorClass *vhc =
- PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid,
+ ppc_v3_pate_t *entry);
- return !!(vhc->get_patbe(cpu->vhyp) & PATBE1_GR);
+/*
+ * The LPCR:HR bit is a shortcut that avoids having to
+ * dig out the partition table in the fast path. This is
+ * also how the HW uses it.
+ */
+static inline bool ppc64_v3_radix(PowerPCCPU *cpu)
+{
+ return !!(cpu->env.spr[SPR_LPCR] & LPCR_HR);
}
+hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr);
+
int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
int mmu_idx);
+static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
+{
+ uint64_t base;
+
+ if (cpu->vhyp) {
+ return 0;
+ }
+ if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
+ ppc_v3_pate_t pate;
+
+ if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) {
+ return 0;
+ }
+ base = pate.dw0;
+ } else {
+ base = cpu->env.spr[SPR_SDR1];
+ }
+ return base & SDR_64_HTABORG;
+}
+
+static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
+{
+ uint64_t base;
+
+ if (cpu->vhyp) {
+ PPCVirtualHypervisorClass *vhc =
+ PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ return vhc->hpt_mask(cpu->vhyp);
+ }
+ if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
+ ppc_v3_pate_t pate;
+
+ if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) {
+ return 0;
+ }
+ base = pate.dw0;
+ } else {
+ base = cpu->env.spr[SPR_SDR1];
+ }
+ return (1ULL << ((base & SDR_64_HTABSIZE) + 18 - 7)) - 1;
+}
+
#endif /* TARGET_PPC64 */
#endif /* CONFIG_USER_ONLY */
-#endif /* MMU_H */
+#endif /* MMU_BOOOK3S_V3_H */
for (i = 0; i < HPTES_PER_GROUP; i++) {
pte0 = ppc_hash32_load_hpte0(cpu, pte_offset);
+ /*
+ * pte0 contains the valid bit and must be read before pte1,
+ * otherwise we might see an old pte1 with a new valid bit and
+ * thus an inconsistent hpte value
+ */
+ smp_rmb();
pte1 = ppc_hash32_load_hpte1(cpu, pte_offset);
if ((pte0 & HPTE32_V_VALID)
hwaddr ptex, int n)
{
hwaddr pte_offset = ptex * HASH_PTE_SIZE_64;
- hwaddr base = ppc_hash64_hpt_base(cpu);
+ hwaddr base;
hwaddr plen = n * HASH_PTE_SIZE_64;
const ppc_hash_pte64_t *hptes;
PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
return vhc->map_hptes(cpu->vhyp, ptex, n);
}
+ base = ppc_hash64_hpt_base(cpu);
if (!base) {
return NULL;
return 0; /* Bad page size encoding */
}
+static void ppc64_v3_new_to_old_hpte(target_ulong *pte0, target_ulong *pte1)
+{
+ /* Insert B into pte0 */
+ *pte0 = (*pte0 & HPTE64_V_COMMON_BITS) |
+ ((*pte1 & HPTE64_R_3_0_SSIZE_MASK) <<
+ (HPTE64_V_SSIZE_SHIFT - HPTE64_R_3_0_SSIZE_SHIFT));
+
+ /* Remove B from pte1 */
+ *pte1 = *pte1 & ~HPTE64_R_3_0_SSIZE_MASK;
+}
+
+
static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash,
const PPCHash64SegmentPageSizes *sps,
target_ulong ptem,
}
for (i = 0; i < HPTES_PER_GROUP; i++) {
pte0 = ppc_hash64_hpte0(cpu, pteg, i);
+ /*
+ * pte0 contains the valid bit and must be read before pte1,
+ * otherwise we might see an old pte1 with a new valid bit and
+ * thus an inconsistent hpte value
+ */
+ smp_rmb();
pte1 = ppc_hash64_hpte1(cpu, pteg, i);
+ /* Convert format if necessary */
+ if (cpu->env.mmu_model == POWERPC_MMU_3_00 && !cpu->vhyp) {
+ ppc64_v3_new_to_old_hpte(&pte0, &pte1);
+ }
+
/* This compares V, B, H (secondary) and the AVPN */
if (HPTE64_V_COMPARE(pte0, ptem)) {
*pshift = hpte_page_shift(sps, pte0, pte1);
void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
uint64_t pte0, uint64_t pte1)
{
- hwaddr base = ppc_hash64_hpt_base(cpu);
+ hwaddr base;
hwaddr offset = ptex * HASH_PTE_SIZE_64;
if (cpu->vhyp) {
vhc->store_hpte(cpu->vhyp, ptex, pte0, pte1);
return;
}
+ base = ppc_hash64_hpt_base(cpu);
stq_phys(CPU(cpu)->as, base + offset, pte0);
stq_phys(CPU(cpu)->as, base + offset + HASH_PTE_SIZE_64 / 2, pte1);
case POWERPC_MMU_3_00: /* P9 */
lpcr = val & (LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD |
(LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL |
- LPCR_UPRT | LPCR_EVIRT | LPCR_ONL |
+ LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR |
(LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE |
LPCR_DEE | LPCR_OEE)) | LPCR_MER | LPCR_GTSE | LPCR_TC |
LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE);
+ /*
+ * If we have a virtual hypervisor, we need to bring back RMLS. It
+ * doesn't exist on an actual P9 but that's all we know how to
+ * configure with softmmu at the moment
+ */
+ if (cpu->vhyp) {
+ lpcr |= (val & LPCR_RMLS);
+ }
break;
default:
;
#define SDR_64_HTABORG 0x0FFFFFFFFFFC0000ULL
#define SDR_64_HTABSIZE 0x000000000000001FULL
+#define PATE0_HTABORG 0x0FFFFFFFFFFC0000ULL
#define HPTES_PER_GROUP 8
#define HASH_PTE_SIZE_64 16
#define HASH_PTEG_SIZE_64 (HASH_PTE_SIZE_64 * HPTES_PER_GROUP)
#define HPTE64_V_1TB_SEG 0x4000000000000000ULL
#define HPTE64_V_VRMA_MASK 0x4001ffffff000000ULL
-static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
-{
- if (cpu->vhyp) {
- return 0;
- }
- return cpu->env.spr[SPR_SDR1] & SDR_64_HTABORG;
-}
-
-static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
-{
- if (cpu->vhyp) {
- PPCVirtualHypervisorClass *vhc =
- PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
- return vhc->hpt_mask(cpu->vhyp);
- }
- return (1ULL << ((cpu->env.spr[SPR_SDR1] & SDR_64_HTABSIZE) + 18 - 7)) - 1;
-}
+/* Format changes for ARCH v3 */
+#define HPTE64_V_COMMON_BITS 0x000fffffffffffffULL
+#define HPTE64_R_3_0_SSIZE_SHIFT 58
+#define HPTE64_R_3_0_SSIZE_MASK (3ULL << HPTE64_R_3_0_SSIZE_SHIFT)
struct ppc_hash_pte64 {
uint64_t pte0, pte1;
static bool ppc_radix64_get_fully_qualified_addr(CPUPPCState *env, vaddr eaddr,
uint64_t *lpid, uint64_t *pid)
{
- /* We don't have HV support yet and shouldn't get here with it set anyway */
- assert(!msr_hv);
-
- if (!msr_hv) { /* !MSR[HV] -> Guest */
+ if (msr_hv) { /* MSR[HV] -> Hypervisor/bare metal */
+ switch (eaddr & R_EADDR_QUADRANT) {
+ case R_EADDR_QUADRANT0:
+ *lpid = 0;
+ *pid = env->spr[SPR_BOOKS_PID];
+ break;
+ case R_EADDR_QUADRANT1:
+ *lpid = env->spr[SPR_LPIDR];
+ *pid = env->spr[SPR_BOOKS_PID];
+ break;
+ case R_EADDR_QUADRANT2:
+ *lpid = env->spr[SPR_LPIDR];
+ *pid = 0;
+ break;
+ case R_EADDR_QUADRANT3:
+ *lpid = 0;
+ *pid = 0;
+ break;
+ }
+ } else { /* !MSR[HV] -> Guest */
switch (eaddr & R_EADDR_QUADRANT) {
case R_EADDR_QUADRANT0: /* Guest application */
*lpid = env->spr[SPR_LPIDR];
raddr, psize, fault_cause, pte_addr);
}
+static bool validate_pate(PowerPCCPU *cpu, uint64_t lpid, ppc_v3_pate_t *pate)
+{
+ CPUPPCState *env = &cpu->env;
+
+ if (!(pate->dw0 & PATE0_HR)) {
+ return false;
+ }
+ if (lpid == 0 && !msr_hv) {
+ return false;
+ }
+ /* More checks ... */
+ return true;
+}
+
int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
int mmu_idx)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
- PPCVirtualHypervisorClass *vhc =
- PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ PPCVirtualHypervisorClass *vhc;
hwaddr raddr, pte_addr;
- uint64_t lpid = 0, pid = 0, offset, size, patbe, prtbe0, pte;
+ uint64_t lpid = 0, pid = 0, offset, size, prtbe0, pte;
int page_size, prot, fault_cause = 0;
+ ppc_v3_pate_t pate;
assert((rwx == 0) || (rwx == 1) || (rwx == 2));
- assert(!msr_hv); /* For now there is no Radix PowerNV Support */
- assert(cpu->vhyp);
assert(ppc64_use_proc_tbl(cpu));
/* Real Mode Access */
}
/* Get Process Table */
- patbe = vhc->get_patbe(cpu->vhyp);
+ if (cpu->vhyp) {
+ vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ vhc->get_pate(cpu->vhyp, &pate);
+ } else {
+ if (!ppc64_v3_get_pate(cpu, lpid, &pate)) {
+ ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
+ return 1;
+ }
+ if (!validate_pate(cpu, lpid, &pate)) {
+ ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_R_BADCONFIG);
+ }
+ /* We don't support guest mode yet */
+ if (lpid != 0) {
+ error_report("PowerNV guest support Unimplemented");
+ exit(1);
+ }
+ }
/* Index Process Table by PID to Find Corresponding Process Table Entry */
offset = pid * sizeof(struct prtb_entry);
- size = 1ULL << ((patbe & PATBE1_R_PRTS) + 12);
+ size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
if (offset >= size) {
/* offset exceeds size of the process table */
ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
return 1;
}
- prtbe0 = ldq_phys(cs->as, (patbe & PATBE1_R_PRTB) + offset);
+ prtbe0 = ldq_phys(cs->as, (pate.dw1 & PATE1_R_PRTB) + offset);
/* Walk Radix Tree from Process Table Entry to Convert EA to RA */
page_size = PRTBE_R_GET_RTS(prtbe0);
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
- PPCVirtualHypervisorClass *vhc =
- PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ PPCVirtualHypervisorClass *vhc;
hwaddr raddr, pte_addr;
- uint64_t lpid = 0, pid = 0, offset, size, patbe, prtbe0, pte;
+ uint64_t lpid = 0, pid = 0, offset, size, prtbe0, pte;
int page_size, fault_cause = 0;
+ ppc_v3_pate_t pate;
/* Handle Real Mode */
if (msr_dr == 0) {
}
/* Get Process Table */
- patbe = vhc->get_patbe(cpu->vhyp);
+ if (cpu->vhyp) {
+ vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ vhc->get_pate(cpu->vhyp, &pate);
+ } else {
+ if (!ppc64_v3_get_pate(cpu, lpid, &pate)) {
+ return -1;
+ }
+ if (!validate_pate(cpu, lpid, &pate)) {
+ return -1;
+ }
+ /* We don't support guest mode yet */
+ if (lpid != 0) {
+ error_report("PowerNV guest support Unimplemented");
+ exit(1);
+ }
+ }
/* Index Process Table by PID to Find Corresponding Process Table Entry */
offset = pid * sizeof(struct prtb_entry);
- size = 1ULL << ((patbe & PATBE1_R_PRTS) + 12);
+ size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
if (offset >= size) {
/* offset exceeds size of the process table */
return -1;
}
- prtbe0 = ldq_phys(cs->as, (patbe & PATBE1_R_PRTB) + offset);
+ prtbe0 = ldq_phys(cs->as, (pate.dw1 & PATE1_R_PRTB) + offset);
/* Walk Radix Tree from Process Table Entry to Convert EA to RA */
page_size = PRTBE_R_GET_RTS(prtbe0);
#define R_EADDR_QUADRANT3 0xC000000000000000
/* Radix Partition Table Entry Fields */
-#define PATBE1_R_PRTB 0x0FFFFFFFFFFFF000
-#define PATBE1_R_PRTS 0x000000000000001F
+#define PATE1_R_PRTB 0x0FFFFFFFFFFFF000
+#define PATE1_R_PRTS 0x000000000000001F
/* Radix Process Table Entry Fields */
#define PRTBE_R_GET_RTS(rts) \
dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env));
break;
case POWERPC_MMU_3_00:
- if (ppc64_radix_guest(ppc_env_get_cpu(env))) {
+ if (ppc64_v3_radix(ppc_env_get_cpu(env))) {
/* TODO - Unsupported */
} else {
dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env));
bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
|| (access_type != ACCESS_CODE && msr_dr == 0);
-#if 0
- qemu_log("%s\n", __func__);
-#endif
-
switch (env->mmu_model) {
case POWERPC_MMU_SOFT_6xx:
case POWERPC_MMU_SOFT_74xx:
cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n");
return -1;
}
-#if 0
- qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
- __func__, eaddr, ret, ctx->raddr);
-#endif
return ret;
}
case POWERPC_MMU_2_07:
return ppc_hash64_get_phys_page_debug(cpu, addr);
case POWERPC_MMU_3_00:
- if (ppc64_radix_guest(ppc_env_get_cpu(env))) {
- return ppc_radix64_get_phys_page_debug(cpu, addr);
- } else {
- return ppc_hash64_get_phys_page_debug(cpu, addr);
- }
- break;
+ return ppc64_v3_get_phys_page_debug(cpu, addr);
#endif
case POWERPC_MMU_32B:
break;
}
}
-#if 0
- printf("%s: set exception to %d %02x\n", __func__,
- cs->exception, env->error_code);
-#endif
ret = 1;
}
#include "disas/disas.h"
#include "exec/exec-all.h"
#include "tcg-op.h"
+#include "tcg-op-gvec.h"
#include "qemu/host-utils.h"
#include "exec/cpu_ldst.h"
ctx->exception = (excp);
}
-/* Translates the EXCP_TRACE/BRANCH exceptions used on most PowerPCs to
- * EXCP_DEBUG, if we are running on cores using the debug enable bit (e.g.
- * BookE).
+/*
+ * Tells the caller what is the appropriate exception to generate and prepares
+ * SPR registers for this exception.
+ *
+ * The exception can be either POWERPC_EXCP_TRACE (on most PowerPCs) or
+ * POWERPC_EXCP_DEBUG (on BookE).
*/
-static uint32_t gen_prep_dbgex(DisasContext *ctx, uint32_t excp)
+static uint32_t gen_prep_dbgex(DisasContext *ctx)
{
- if ((ctx->singlestep_enabled & CPU_SINGLE_STEP)
- && (excp == POWERPC_EXCP_BRANCH)) {
- /* Trace excpt. has priority */
- excp = POWERPC_EXCP_TRACE;
- }
if (ctx->flags & POWERPC_FLAG_DE) {
target_ulong dbsr = 0;
- switch (excp) {
- case POWERPC_EXCP_TRACE:
+ if (ctx->singlestep_enabled & CPU_SINGLE_STEP) {
dbsr = DBCR0_ICMP;
- break;
- case POWERPC_EXCP_BRANCH:
+ } else {
+ /* Must have been branch */
dbsr = DBCR0_BRT;
- break;
}
TCGv t0 = tcg_temp_new();
gen_load_spr(t0, SPR_BOOKE_DBSR);
tcg_temp_free(t0);
return POWERPC_EXCP_DEBUG;
} else {
- return excp;
+ return POWERPC_EXCP_TRACE;
}
}
t = tcg_const_i32(PPC_PM_DOZE);
gen_helper_pminsn(cpu_env, t);
tcg_temp_free_i32(t);
- gen_stop_exception(ctx);
+ /* Stop translation, as the CPU is supposed to sleep from now */
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
#endif /* defined(CONFIG_USER_ONLY) */
}
t = tcg_const_i32(PPC_PM_NAP);
gen_helper_pminsn(cpu_env, t);
tcg_temp_free_i32(t);
- gen_stop_exception(ctx);
+ /* Stop translation, as the CPU is supposed to sleep from now */
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
#endif /* defined(CONFIG_USER_ONLY) */
}
static void gen_stop(DisasContext *ctx)
{
- gen_nap(ctx);
+#if defined(CONFIG_USER_ONLY)
+ GEN_PRIV;
+#else
+ TCGv_i32 t;
+
+ CHK_HV;
+ t = tcg_const_i32(PPC_PM_STOP);
+ gen_helper_pminsn(cpu_env, t);
+ tcg_temp_free_i32(t);
+ /* Stop translation, as the CPU is supposed to sleep from now */
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
+#endif /* defined(CONFIG_USER_ONLY) */
}
static void gen_sleep(DisasContext *ctx)
t = tcg_const_i32(PPC_PM_SLEEP);
gen_helper_pminsn(cpu_env, t);
tcg_temp_free_i32(t);
- gen_stop_exception(ctx);
+ /* Stop translation, as the CPU is supposed to sleep from now */
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
#endif /* defined(CONFIG_USER_ONLY) */
}
t = tcg_const_i32(PPC_PM_RVWINKLE);
gen_helper_pminsn(cpu_env, t);
tcg_temp_free_i32(t);
- gen_stop_exception(ctx);
+ /* Stop translation, as the CPU is supposed to sleep from now */
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
#endif /* defined(CONFIG_USER_ONLY) */
}
#endif /* #if defined(TARGET_PPC64) */
if (sse & GDBSTUB_SINGLE_STEP) {
gen_debug_exception(ctx);
} else if (sse & (CPU_SINGLE_STEP | CPU_BRANCH_STEP)) {
- uint32_t excp = gen_prep_dbgex(ctx, POWERPC_EXCP_BRANCH);
- if (excp != POWERPC_EXCP_NONE) {
- gen_exception(ctx, excp);
- }
+ uint32_t excp = gen_prep_dbgex(ctx);
+ gen_exception(ctx, excp);
}
tcg_gen_exit_tb(NULL, 0);
} else {
/* msync replaces sync on 440 */
static void gen_msync_4xx(DisasContext *ctx)
{
- /* interpreted as no-op */
+ /* Only e500 seems to treat reserved bits as invalid */
+ if ((ctx->insns_flags2 & PPC2_BOOKE206) &&
+ (ctx->opcode & 0x03FFF801)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
+ }
+ /* otherwise interpreted as no-op */
}
/* icbt */
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
PPC_BOOKE, PPC2_BOOKE206),
-GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
+GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x039FF801, PPC_BOOKE),
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
PPC_BOOKE, PPC2_BOOKE206),
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x06, 0x08, 0x03E00001,
- PPC_440_SPEC),
+ PPC_440_SPEC),
GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
#if defined(TARGET_PPC64)
if (env->excp_model == POWERPC_EXCP_POWER7 ||
- env->excp_model == POWERPC_EXCP_POWER8) {
+ env->excp_model == POWERPC_EXCP_POWER8 ||
+ env->excp_model == POWERPC_EXCP_POWER9) {
cpu_fprintf(f, "HSRR0 " TARGET_FMT_lx " HSRR1 " TARGET_FMT_lx "\n",
env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
}
ctx->exception != POWERPC_SYSCALL &&
ctx->exception != POWERPC_EXCP_TRAP &&
ctx->exception != POWERPC_EXCP_BRANCH)) {
- uint32_t excp = gen_prep_dbgex(ctx, POWERPC_EXCP_TRACE);
- if (excp != POWERPC_EXCP_NONE)
- gen_exception_nip(ctx, excp, ctx->base.pc_next);
+ uint32_t excp = gen_prep_dbgex(ctx);
+ gen_exception_nip(ctx, excp, ctx->base.pc_next);
}
if (tcg_check_temp_count()) {
tcg_gen_movi_i64(avr, 0);
set_avr64(rD(ctx->opcode), avr, true);
t = tcg_temp_new_i32();
- tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
+ gen_helper_mfvscr(t, cpu_env);
tcg_gen_extu_i32_i64(avr, t);
set_avr64(rD(ctx->opcode), avr, false);
tcg_temp_free_i32(t);
static void gen_mtvscr(DisasContext *ctx)
{
- TCGv_ptr p;
+ TCGv_i32 val;
+ int bofs;
+
if (unlikely(!ctx->altivec_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VPU);
return;
}
- p = gen_avr_ptr(rB(ctx->opcode));
- gen_helper_mtvscr(cpu_env, p);
- tcg_temp_free_ptr(p);
+
+ val = tcg_temp_new_i32();
+ bofs = avr64_offset(rB(ctx->opcode), true);
+#ifdef HOST_WORDS_BIGENDIAN
+ bofs += 3 * 4;
+#endif
+
+ tcg_gen_ld_i32(val, cpu_env, bofs);
+ gen_helper_mtvscr(cpu_env, val);
+ tcg_temp_free_i32(val);
}
#define GEN_VX_VMUL10(name, add_cin, ret_carry) \
GEN_VX_VMUL10(vmul10cuq, 0, 1);
GEN_VX_VMUL10(vmul10ecuq, 1, 1);
-/* Logical operations */
-#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
-static void glue(gen_, name)(DisasContext *ctx) \
+#define GEN_VXFORM_V(name, vece, tcg_op, opc2, opc3) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
- TCGv_i64 t0; \
- TCGv_i64 t1; \
- TCGv_i64 avr; \
- \
if (unlikely(!ctx->altivec_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VPU); \
return; \
} \
- t0 = tcg_temp_new_i64(); \
- t1 = tcg_temp_new_i64(); \
- avr = tcg_temp_new_i64(); \
- \
- get_avr64(t0, rA(ctx->opcode), true); \
- get_avr64(t1, rB(ctx->opcode), true); \
- tcg_op(avr, t0, t1); \
- set_avr64(rD(ctx->opcode), avr, true); \
\
- get_avr64(t0, rA(ctx->opcode), false); \
- get_avr64(t1, rB(ctx->opcode), false); \
- tcg_op(avr, t0, t1); \
- set_avr64(rD(ctx->opcode), avr, false); \
- \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
- tcg_temp_free_i64(avr); \
+ tcg_op(vece, \
+ avr64_offset(rD(ctx->opcode), true), \
+ avr64_offset(rA(ctx->opcode), true), \
+ avr64_offset(rB(ctx->opcode), true), \
+ 16, 16); \
}
-GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
-GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
-GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
-GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
-GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
-GEN_VX_LOGICAL(veqv, tcg_gen_eqv_i64, 2, 26);
-GEN_VX_LOGICAL(vnand, tcg_gen_nand_i64, 2, 22);
-GEN_VX_LOGICAL(vorc, tcg_gen_orc_i64, 2, 21);
+/* Logical operations */
+GEN_VXFORM_V(vand, MO_64, tcg_gen_gvec_and, 2, 16);
+GEN_VXFORM_V(vandc, MO_64, tcg_gen_gvec_andc, 2, 17);
+GEN_VXFORM_V(vor, MO_64, tcg_gen_gvec_or, 2, 18);
+GEN_VXFORM_V(vxor, MO_64, tcg_gen_gvec_xor, 2, 19);
+GEN_VXFORM_V(vnor, MO_64, tcg_gen_gvec_nor, 2, 20);
+GEN_VXFORM_V(veqv, MO_64, tcg_gen_gvec_eqv, 2, 26);
+GEN_VXFORM_V(vnand, MO_64, tcg_gen_gvec_nand, 2, 22);
+GEN_VXFORM_V(vorc, MO_64, tcg_gen_gvec_orc, 2, 21);
#define GEN_VXFORM(name, opc2, opc3) \
static void glue(gen_, name)(DisasContext *ctx) \
tcg_temp_free_ptr(rb); \
}
-GEN_VXFORM(vaddubm, 0, 0);
+GEN_VXFORM_V(vaddubm, MO_8, tcg_gen_gvec_add, 0, 0);
GEN_VXFORM_DUAL_EXT(vaddubm, PPC_ALTIVEC, PPC_NONE, 0, \
vmul10cuq, PPC_NONE, PPC2_ISA300, 0x0000F800)
-GEN_VXFORM(vadduhm, 0, 1);
+GEN_VXFORM_V(vadduhm, MO_16, tcg_gen_gvec_add, 0, 1);
GEN_VXFORM_DUAL(vadduhm, PPC_ALTIVEC, PPC_NONE, \
vmul10ecuq, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM(vadduwm, 0, 2);
-GEN_VXFORM(vaddudm, 0, 3);
-GEN_VXFORM(vsububm, 0, 16);
-GEN_VXFORM(vsubuhm, 0, 17);
-GEN_VXFORM(vsubuwm, 0, 18);
-GEN_VXFORM(vsubudm, 0, 19);
-GEN_VXFORM(vmaxub, 1, 0);
-GEN_VXFORM(vmaxuh, 1, 1);
-GEN_VXFORM(vmaxuw, 1, 2);
-GEN_VXFORM(vmaxud, 1, 3);
-GEN_VXFORM(vmaxsb, 1, 4);
-GEN_VXFORM(vmaxsh, 1, 5);
-GEN_VXFORM(vmaxsw, 1, 6);
-GEN_VXFORM(vmaxsd, 1, 7);
-GEN_VXFORM(vminub, 1, 8);
-GEN_VXFORM(vminuh, 1, 9);
-GEN_VXFORM(vminuw, 1, 10);
-GEN_VXFORM(vminud, 1, 11);
-GEN_VXFORM(vminsb, 1, 12);
-GEN_VXFORM(vminsh, 1, 13);
-GEN_VXFORM(vminsw, 1, 14);
-GEN_VXFORM(vminsd, 1, 15);
+GEN_VXFORM_V(vadduwm, MO_32, tcg_gen_gvec_add, 0, 2);
+GEN_VXFORM_V(vaddudm, MO_64, tcg_gen_gvec_add, 0, 3);
+GEN_VXFORM_V(vsububm, MO_8, tcg_gen_gvec_sub, 0, 16);
+GEN_VXFORM_V(vsubuhm, MO_16, tcg_gen_gvec_sub, 0, 17);
+GEN_VXFORM_V(vsubuwm, MO_32, tcg_gen_gvec_sub, 0, 18);
+GEN_VXFORM_V(vsubudm, MO_64, tcg_gen_gvec_sub, 0, 19);
+GEN_VXFORM_V(vmaxub, MO_8, tcg_gen_gvec_umax, 1, 0);
+GEN_VXFORM_V(vmaxuh, MO_16, tcg_gen_gvec_umax, 1, 1);
+GEN_VXFORM_V(vmaxuw, MO_32, tcg_gen_gvec_umax, 1, 2);
+GEN_VXFORM_V(vmaxud, MO_64, tcg_gen_gvec_umax, 1, 3);
+GEN_VXFORM_V(vmaxsb, MO_8, tcg_gen_gvec_smax, 1, 4);
+GEN_VXFORM_V(vmaxsh, MO_16, tcg_gen_gvec_smax, 1, 5);
+GEN_VXFORM_V(vmaxsw, MO_32, tcg_gen_gvec_smax, 1, 6);
+GEN_VXFORM_V(vmaxsd, MO_64, tcg_gen_gvec_smax, 1, 7);
+GEN_VXFORM_V(vminub, MO_8, tcg_gen_gvec_umin, 1, 8);
+GEN_VXFORM_V(vminuh, MO_16, tcg_gen_gvec_umin, 1, 9);
+GEN_VXFORM_V(vminuw, MO_32, tcg_gen_gvec_umin, 1, 10);
+GEN_VXFORM_V(vminud, MO_64, tcg_gen_gvec_umin, 1, 11);
+GEN_VXFORM_V(vminsb, MO_8, tcg_gen_gvec_smin, 1, 12);
+GEN_VXFORM_V(vminsh, MO_16, tcg_gen_gvec_smin, 1, 13);
+GEN_VXFORM_V(vminsw, MO_32, tcg_gen_gvec_smin, 1, 14);
+GEN_VXFORM_V(vminsd, MO_64, tcg_gen_gvec_smin, 1, 15);
GEN_VXFORM(vavgub, 1, 16);
GEN_VXFORM(vabsdub, 1, 16);
GEN_VXFORM_DUAL(vavgub, PPC_ALTIVEC, PPC_NONE, \
GEN_VXFORM(vsro, 6, 17);
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
-GEN_VXFORM_ENV(vaddubs, 0, 8);
+
+#define GEN_VXFORM_SAT(NAME, VECE, NORM, SAT, OPC2, OPC3) \
+static void glue(glue(gen_, NAME), _vec)(unsigned vece, TCGv_vec t, \
+ TCGv_vec sat, TCGv_vec a, \
+ TCGv_vec b) \
+{ \
+ TCGv_vec x = tcg_temp_new_vec_matching(t); \
+ glue(glue(tcg_gen_, NORM), _vec)(VECE, x, a, b); \
+ glue(glue(tcg_gen_, SAT), _vec)(VECE, t, a, b); \
+ tcg_gen_cmp_vec(TCG_COND_NE, VECE, x, x, t); \
+ tcg_gen_or_vec(VECE, sat, sat, x); \
+ tcg_temp_free_vec(x); \
+} \
+static void glue(gen_, NAME)(DisasContext *ctx) \
+{ \
+ static const GVecGen4 g = { \
+ .fniv = glue(glue(gen_, NAME), _vec), \
+ .fno = glue(gen_helper_, NAME), \
+ .opc = glue(glue(INDEX_op_, SAT), _vec), \
+ .write_aofs = true, \
+ .vece = VECE, \
+ }; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ tcg_gen_gvec_4(avr64_offset(rD(ctx->opcode), true), \
+ offsetof(CPUPPCState, vscr_sat), \
+ avr64_offset(rA(ctx->opcode), true), \
+ avr64_offset(rB(ctx->opcode), true), \
+ 16, 16, &g); \
+}
+
+GEN_VXFORM_SAT(vaddubs, MO_8, add, usadd, 0, 8);
GEN_VXFORM_DUAL_EXT(vaddubs, PPC_ALTIVEC, PPC_NONE, 0, \
vmul10uq, PPC_NONE, PPC2_ISA300, 0x0000F800)
-GEN_VXFORM_ENV(vadduhs, 0, 9);
+GEN_VXFORM_SAT(vadduhs, MO_16, add, usadd, 0, 9);
GEN_VXFORM_DUAL(vadduhs, PPC_ALTIVEC, PPC_NONE, \
vmul10euq, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM_ENV(vadduws, 0, 10);
-GEN_VXFORM_ENV(vaddsbs, 0, 12);
-GEN_VXFORM_ENV(vaddshs, 0, 13);
-GEN_VXFORM_ENV(vaddsws, 0, 14);
-GEN_VXFORM_ENV(vsububs, 0, 24);
-GEN_VXFORM_ENV(vsubuhs, 0, 25);
-GEN_VXFORM_ENV(vsubuws, 0, 26);
-GEN_VXFORM_ENV(vsubsbs, 0, 28);
-GEN_VXFORM_ENV(vsubshs, 0, 29);
-GEN_VXFORM_ENV(vsubsws, 0, 30);
+GEN_VXFORM_SAT(vadduws, MO_32, add, usadd, 0, 10);
+GEN_VXFORM_SAT(vaddsbs, MO_8, add, ssadd, 0, 12);
+GEN_VXFORM_SAT(vaddshs, MO_16, add, ssadd, 0, 13);
+GEN_VXFORM_SAT(vaddsws, MO_32, add, ssadd, 0, 14);
+GEN_VXFORM_SAT(vsububs, MO_8, sub, ussub, 0, 24);
+GEN_VXFORM_SAT(vsubuhs, MO_16, sub, ussub, 0, 25);
+GEN_VXFORM_SAT(vsubuws, MO_32, sub, ussub, 0, 26);
+GEN_VXFORM_SAT(vsubsbs, MO_8, sub, sssub, 0, 28);
+GEN_VXFORM_SAT(vsubshs, MO_16, sub, sssub, 0, 29);
+GEN_VXFORM_SAT(vsubsws, MO_32, sub, sssub, 0, 30);
GEN_VXFORM(vadduqm, 0, 4);
GEN_VXFORM(vaddcuq, 0, 5);
GEN_VXFORM3(vaddeuqm, 30, 0);
GEN_VXRFORM_DUAL(vcmpgtfp, PPC_ALTIVEC, PPC_NONE, \
vcmpgtud, PPC_NONE, PPC2_ALTIVEC_207)
-#define GEN_VXFORM_SIMM(name, opc2, opc3) \
+#define GEN_VXFORM_DUPI(name, tcg_op, opc2, opc3) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
- TCGv_ptr rd; \
- TCGv_i32 simm; \
+ int simm; \
if (unlikely(!ctx->altivec_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VPU); \
return; \
} \
- simm = tcg_const_i32(SIMM5(ctx->opcode)); \
- rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name (rd, simm); \
- tcg_temp_free_i32(simm); \
- tcg_temp_free_ptr(rd); \
+ simm = SIMM5(ctx->opcode); \
+ tcg_op(avr64_offset(rD(ctx->opcode), true), 16, 16, simm); \
}
-GEN_VXFORM_SIMM(vspltisb, 6, 12);
-GEN_VXFORM_SIMM(vspltish, 6, 13);
-GEN_VXFORM_SIMM(vspltisw, 6, 14);
+GEN_VXFORM_DUPI(vspltisb, tcg_gen_gvec_dup8i, 6, 12);
+GEN_VXFORM_DUPI(vspltish, tcg_gen_gvec_dup16i, 6, 13);
+GEN_VXFORM_DUPI(vspltisw, tcg_gen_gvec_dup32i, 6, 14);
#define GEN_VXFORM_NOA(name, opc2, opc3) \
static void glue(gen_, name)(DisasContext *ctx) \
GEN_VXFORM_NOA(vprtybd, 1, 24);
GEN_VXFORM_NOA(vprtybq, 1, 24);
-#define GEN_VXFORM_SIMM(name, opc2, opc3) \
-static void glue(gen_, name)(DisasContext *ctx) \
- { \
- TCGv_ptr rd; \
- TCGv_i32 simm; \
- if (unlikely(!ctx->altivec_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VPU); \
- return; \
- } \
- simm = tcg_const_i32(SIMM5(ctx->opcode)); \
- rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name (rd, simm); \
- tcg_temp_free_i32(simm); \
- tcg_temp_free_ptr(rd); \
- }
+static void gen_vsplt(DisasContext *ctx, int vece)
+{
+ int uimm, dofs, bofs;
-#define GEN_VXFORM_UIMM(name, opc2, opc3) \
-static void glue(gen_, name)(DisasContext *ctx) \
- { \
- TCGv_ptr rb, rd; \
- TCGv_i32 uimm; \
- if (unlikely(!ctx->altivec_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VPU); \
- return; \
- } \
- uimm = tcg_const_i32(UIMM5(ctx->opcode)); \
- rb = gen_avr_ptr(rB(ctx->opcode)); \
- rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name (rd, rb, uimm); \
- tcg_temp_free_i32(uimm); \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(rd); \
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
}
+ uimm = UIMM5(ctx->opcode);
+ bofs = avr64_offset(rB(ctx->opcode), true);
+ dofs = avr64_offset(rD(ctx->opcode), true);
+
+ /* Experimental testing shows that hardware masks the immediate. */
+ bofs += (uimm << vece) & 15;
+#ifndef HOST_WORDS_BIGENDIAN
+ bofs ^= 15;
+ bofs &= ~((1 << vece) - 1);
+#endif
+
+ tcg_gen_gvec_dup_mem(vece, dofs, bofs, 16, 16);
+}
+
+#define GEN_VXFORM_VSPLT(name, vece, opc2, opc3) \
+static void glue(gen_, name)(DisasContext *ctx) { gen_vsplt(ctx, vece); }
+
#define GEN_VXFORM_UIMM_ENV(name, opc2, opc3) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
tcg_temp_free_ptr(rd); \
}
-GEN_VXFORM_UIMM(vspltb, 6, 8);
-GEN_VXFORM_UIMM(vsplth, 6, 9);
-GEN_VXFORM_UIMM(vspltw, 6, 10);
+GEN_VXFORM_VSPLT(vspltb, MO_8, 6, 8);
+GEN_VXFORM_VSPLT(vsplth, MO_16, 6, 9);
+GEN_VXFORM_VSPLT(vspltw, MO_32, 6, 10);
GEN_VXFORM_UIMM_SPLAT(vextractub, 6, 8, 15);
GEN_VXFORM_UIMM_SPLAT(vextractuh, 6, 9, 14);
GEN_VXFORM_UIMM_SPLAT(vextractuw, 6, 10, 12);
#undef GEN_VXRFORM_DUAL
#undef GEN_VXRFORM1
#undef GEN_VXRFORM
-#undef GEN_VXFORM_SIMM
+#undef GEN_VXFORM_DUPI
#undef GEN_VXFORM_NOA
#undef GEN_VXFORM_UIMM
#undef GEN_VAFORM_PAIRED
tcg_gen_st_i64(src, cpu_env, offsetof(CPUPPCState, vsr[n].u64[1]));
}
+static inline int vsr_full_offset(int n)
+{
+ return offsetof(CPUPPCState, vsr[n].u64[0]);
+}
+
static inline void get_cpu_vsrh(TCGv_i64 dst, int n)
{
if (n < 32) {
tcg_temp_free_i64(xbl);
}
-#define VSX_LOGICAL(name, tcg_op) \
+#define VSX_LOGICAL(name, vece, tcg_op) \
static void glue(gen_, name)(DisasContext * ctx) \
{ \
- TCGv_i64 t0; \
- TCGv_i64 t1; \
- TCGv_i64 t2; \
if (unlikely(!ctx->vsx_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
- t0 = tcg_temp_new_i64(); \
- t1 = tcg_temp_new_i64(); \
- t2 = tcg_temp_new_i64(); \
- get_cpu_vsrh(t0, xA(ctx->opcode)); \
- get_cpu_vsrh(t1, xB(ctx->opcode)); \
- tcg_op(t2, t0, t1); \
- set_cpu_vsrh(xT(ctx->opcode), t2); \
- get_cpu_vsrl(t0, xA(ctx->opcode)); \
- get_cpu_vsrl(t1, xB(ctx->opcode)); \
- tcg_op(t2, t0, t1); \
- set_cpu_vsrl(xT(ctx->opcode), t2); \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
- tcg_temp_free_i64(t2); \
+ tcg_op(vece, vsr_full_offset(xT(ctx->opcode)), \
+ vsr_full_offset(xA(ctx->opcode)), \
+ vsr_full_offset(xB(ctx->opcode)), 16, 16); \
}
-VSX_LOGICAL(xxland, tcg_gen_and_i64)
-VSX_LOGICAL(xxlandc, tcg_gen_andc_i64)
-VSX_LOGICAL(xxlor, tcg_gen_or_i64)
-VSX_LOGICAL(xxlxor, tcg_gen_xor_i64)
-VSX_LOGICAL(xxlnor, tcg_gen_nor_i64)
-VSX_LOGICAL(xxleqv, tcg_gen_eqv_i64)
-VSX_LOGICAL(xxlnand, tcg_gen_nand_i64)
-VSX_LOGICAL(xxlorc, tcg_gen_orc_i64)
+VSX_LOGICAL(xxland, MO_64, tcg_gen_gvec_and)
+VSX_LOGICAL(xxlandc, MO_64, tcg_gen_gvec_andc)
+VSX_LOGICAL(xxlor, MO_64, tcg_gen_gvec_or)
+VSX_LOGICAL(xxlxor, MO_64, tcg_gen_gvec_xor)
+VSX_LOGICAL(xxlnor, MO_64, tcg_gen_gvec_nor)
+VSX_LOGICAL(xxleqv, MO_64, tcg_gen_gvec_eqv)
+VSX_LOGICAL(xxlnand, MO_64, tcg_gen_gvec_nand)
+VSX_LOGICAL(xxlorc, MO_64, tcg_gen_gvec_orc)
#define VSX_XXMRG(name, high) \
static void glue(gen_, name)(DisasContext * ctx) \
VSX_XXMRG(xxmrghw, 1)
VSX_XXMRG(xxmrglw, 0)
-static void gen_xxsel(DisasContext * ctx)
+static void xxsel_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, TCGv_i64 c)
{
- TCGv_i64 a, b, c, tmp;
- if (unlikely(!ctx->vsx_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_VSXU);
- return;
- }
- a = tcg_temp_new_i64();
- b = tcg_temp_new_i64();
- c = tcg_temp_new_i64();
- tmp = tcg_temp_new_i64();
-
- get_cpu_vsrh(a, xA(ctx->opcode));
- get_cpu_vsrh(b, xB(ctx->opcode));
- get_cpu_vsrh(c, xC(ctx->opcode));
-
tcg_gen_and_i64(b, b, c);
tcg_gen_andc_i64(a, a, c);
- tcg_gen_or_i64(tmp, a, b);
- set_cpu_vsrh(xT(ctx->opcode), tmp);
-
- get_cpu_vsrl(a, xA(ctx->opcode));
- get_cpu_vsrl(b, xB(ctx->opcode));
- get_cpu_vsrl(c, xC(ctx->opcode));
-
- tcg_gen_and_i64(b, b, c);
- tcg_gen_andc_i64(a, a, c);
- tcg_gen_or_i64(tmp, a, b);
- set_cpu_vsrl(xT(ctx->opcode), tmp);
+ tcg_gen_or_i64(t, a, b);
+}
- tcg_temp_free_i64(a);
- tcg_temp_free_i64(b);
- tcg_temp_free_i64(c);
- tcg_temp_free_i64(tmp);
+static void xxsel_vec(unsigned vece, TCGv_vec t, TCGv_vec a,
+ TCGv_vec b, TCGv_vec c)
+{
+ tcg_gen_and_vec(vece, b, b, c);
+ tcg_gen_andc_vec(vece, a, a, c);
+ tcg_gen_or_vec(vece, t, a, b);
}
-static void gen_xxspltw(DisasContext *ctx)
+static void gen_xxsel(DisasContext *ctx)
{
- TCGv_i64 b, b2;
- TCGv_i64 vsr;
+ static const GVecGen4 g = {
+ .fni8 = xxsel_i64,
+ .fniv = xxsel_vec,
+ .vece = MO_64,
+ };
+ int rt = xT(ctx->opcode);
+ int ra = xA(ctx->opcode);
+ int rb = xB(ctx->opcode);
+ int rc = xC(ctx->opcode);
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
+ tcg_gen_gvec_4(vsr_full_offset(rt), vsr_full_offset(ra),
+ vsr_full_offset(rb), vsr_full_offset(rc), 16, 16, &g);
+}
- vsr = tcg_temp_new_i64();
- if (UIM(ctx->opcode) & 2) {
- get_cpu_vsrl(vsr, xB(ctx->opcode));
- } else {
- get_cpu_vsrh(vsr, xB(ctx->opcode));
- }
-
- b = tcg_temp_new_i64();
- b2 = tcg_temp_new_i64();
+static void gen_xxspltw(DisasContext *ctx)
+{
+ int rt = xT(ctx->opcode);
+ int rb = xB(ctx->opcode);
+ int uim = UIM(ctx->opcode);
+ int tofs, bofs;
- if (UIM(ctx->opcode) & 1) {
- tcg_gen_ext32u_i64(b, vsr);
- } else {
- tcg_gen_shri_i64(b, vsr, 32);
+ if (unlikely(!ctx->vsx_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VSXU);
+ return;
}
- tcg_gen_shli_i64(b2, b, 32);
- tcg_gen_or_i64(vsr, b, b2);
- set_cpu_vsrh(xT(ctx->opcode), vsr);
- set_cpu_vsrl(xT(ctx->opcode), vsr);
+ tofs = vsr_full_offset(rt);
+ bofs = vsr_full_offset(rb);
+ bofs += uim << MO_32;
+#ifndef HOST_WORDS_BIG_ENDIAN
+ bofs ^= 8 | 4;
+#endif
- tcg_temp_free_i64(vsr);
- tcg_temp_free_i64(b);
- tcg_temp_free_i64(b2);
+ tcg_gen_gvec_dup_mem(MO_32, tofs, bofs, 16, 16);
}
#define pattern(x) (((x) & 0xff) * (~(uint64_t)0 / 0xff))
static void gen_xxspltib(DisasContext *ctx)
{
- unsigned char uim8 = IMM8(ctx->opcode);
- TCGv_i64 vsr;
- if (xS(ctx->opcode) < 32) {
+ uint8_t uim8 = IMM8(ctx->opcode);
+ int rt = xT(ctx->opcode);
+
+ if (rt < 32) {
if (unlikely(!ctx->altivec_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VPU);
return;
return;
}
}
- vsr = tcg_temp_new_i64();
- tcg_gen_movi_i64(vsr, pattern(uim8));
- set_cpu_vsrh(xT(ctx->opcode), vsr);
- set_cpu_vsrl(xT(ctx->opcode), vsr);
- tcg_temp_free_i64(vsr);
+ tcg_gen_gvec_dup8i(vsr_full_offset(rt), 16, 16, uim8);
}
static void gen_xxsldwi(DisasContext *ctx)
#include "qemu/cutils.h"
#include "disas/capstone.h"
#include "fpu/softfloat.h"
+#include "qapi/qapi-commands-target.h"
//#define PPC_DUMP_CPU
//#define PPC_DEBUG_SPR
gen_helper_store_pidr(cpu_env, cpu_gpr[gprn]);
}
+static void spr_write_lpidr(DisasContext *ctx, int sprn, int gprn)
+{
+ gen_helper_store_lpidr(cpu_env, cpu_gpr[gprn]);
+}
+
static void spr_read_hior(DisasContext *ctx, int gprn, int sprn)
{
tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, excp_prefix));
static inline void vscr_init(CPUPPCState *env, uint32_t val)
{
- env->vscr = val;
/* Altivec always uses round-to-nearest */
set_float_rounding_mode(float_round_nearest_even, &env->vec_status);
- set_flush_to_zero(vscr_nj, &env->vec_status);
+ helper_mtvscr(env, val);
}
#ifdef CONFIG_USER_ONLY
#endif
}
+static void init_excp_POWER9(CPUPPCState *env)
+{
+ init_excp_POWER8(env);
+
+#if !defined(CONFIG_USER_ONLY)
+ env->excp_vectors[POWERPC_EXCP_HVIRT] = 0x00000EA0;
+#endif
+}
+
#endif
/*****************************************************************************/
spr_register_hv(env, SPR_LPIDR, "LPIDR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_lpidr,
0x00000000);
spr_register_hv(env, SPR_HFSCR, "HFSCR",
SPR_NOACCESS, SPR_NOACCESS,
env->icache_line_size = 128;
/* Allocate hardware IRQ controller */
- init_excp_POWER8(env);
- ppcPOWER7_irq_init(ppc_env_get_cpu(env));
+ init_excp_POWER9(env);
+ ppcPOWER9_irq_init(ppc_env_get_cpu(env));
}
static bool ppc_pvr_match_power9(PowerPCCPUClass *pcc, uint32_t pvr)
CPUPPCState *env = &cpu->env;
if (cs->halted) {
+ uint64_t psscr = env->spr[SPR_PSSCR];
+
if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
return false;
}
+
+ /* If EC is clear, just return true on any pending interrupt */
+ if (!(psscr & PSSCR_EC)) {
+ return true;
+ }
/* External Exception */
if ((env->pending_interrupts & (1u << PPC_INTERRUPT_EXT)) &&
(env->spr[SPR_LPCR] & LPCR_EEE)) {
- return true;
+ bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
+ if (heic == 0 || !msr_hv || msr_pr) {
+ return true;
+ }
}
/* Decrementer Exception */
if ((env->pending_interrupts & (1u << PPC_INTERRUPT_DECR)) &&
(env->spr[SPR_LPCR] & LPCR_HDEE)) {
return true;
}
+ /* Hypervisor virtualization exception */
+ if ((env->pending_interrupts & (1u << PPC_INTERRUPT_HVIRT)) &&
+ (env->spr[SPR_LPCR] & LPCR_HVEE)) {
+ return true;
+ }
if (env->pending_interrupts & (1u << PPC_INTERRUPT_RESET)) {
return true;
}
PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
- PPC2_TM | PPC2_PM_ISA206 | PPC2_ISA300 | PPC2_PRCNTL;
+ PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_TM) |
(1ull << MSR_VR) |
pcc->hash64_opts = &ppc_hash64_opts_POWER7;
pcc->radix_page_info = &POWER9_radix_page_info;
#endif
- pcc->excp_model = POWERPC_EXCP_POWER8;
- pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
+ pcc->excp_model = POWERPC_EXCP_POWER9;
+ pcc->bus_model = PPC_FLAGS_INPUT_POWER9;
pcc->bfd_mach = bfd_mach_ppc64;
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
/* PowerPC implementation specific initialisations (SPRs, timers, ...) */
(*pcc->init_proc)(env);
+#if !defined(CONFIG_USER_ONLY)
+ ppc_gdb_gen_spr_xml(cpu);
+#endif
+
/* MSR bits & flags consistency checks */
if (env->msr_mask & (1 << 25)) {
switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
#endif
}
+#if !defined(CONFIG_USER_ONLY)
+static int gdb_find_spr_idx(CPUPPCState *env, int n)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
+ ppc_spr_t *spr = &env->spr_cb[i];
+
+ if (spr->name && spr->gdb_id == n) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static int gdb_get_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
+{
+ int reg;
+ int len;
+
+ reg = gdb_find_spr_idx(env, n);
+ if (reg < 0) {
+ return 0;
+ }
+
+ len = TARGET_LONG_SIZE;
+ stn_p(mem_buf, len, env->spr[reg]);
+ ppc_maybe_bswap_register(env, mem_buf, len);
+ return len;
+}
+
+static int gdb_set_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
+{
+ int reg;
+ int len;
+
+ reg = gdb_find_spr_idx(env, n);
+ if (reg < 0) {
+ return 0;
+ }
+
+ len = TARGET_LONG_SIZE;
+ ppc_maybe_bswap_register(env, mem_buf, len);
+ env->spr[reg] = ldn_p(mem_buf, len);
+
+ return len;
+}
+#endif
+
static int gdb_get_float_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
{
if (n < 32) {
return 16;
}
if (n == 32) {
- stl_p(mem_buf, env->vscr);
+ stl_p(mem_buf, helper_mfvscr(env));
ppc_maybe_bswap_register(env, mem_buf, 4);
return 4;
}
}
if (n == 32) {
ppc_maybe_bswap_register(env, mem_buf, 4);
- env->vscr = ldl_p(mem_buf);
+ helper_mtvscr(env, ldl_p(mem_buf));
return 4;
}
if (n == 33) {
gdb_register_coprocessor(cs, gdb_get_vsx_reg, gdb_set_vsx_reg,
32, "power-vsx.xml", 0);
}
-
+#ifndef CONFIG_USER_ONLY
+ gdb_register_coprocessor(cs, gdb_get_spr_reg, gdb_set_spr_reg,
+ pcc->gdb_num_sprs, "power-spr.xml", 0);
+#endif
qemu_init_vcpu(cs);
pcc->parent_realize(dev, errp);
*first = entry;
}
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
{
CpuDefinitionInfoList *cpu_list = NULL;
GSList *list;
#endif
cc->gdb_num_core_regs = 71;
-
+#ifndef CONFIG_USER_ONLY
+ cc->gdb_get_dynamic_xml = ppc_gdb_get_dynamic_xml;
+#endif
#ifdef USE_APPLE_GDB
cc->gdb_read_register = ppc_cpu_gdb_read_register_apple;
cc->gdb_write_register = ppc_cpu_gdb_write_register_apple;
static void set_misa(CPURISCVState *env, target_ulong misa)
{
- env->misa = misa;
+ env->misa_mask = env->misa = misa;
}
static void set_versions(CPURISCVState *env, int user_ver, int priv_ver)
so a cpu features bitfield is required, likewise for optional PMP support */
enum {
RISCV_FEATURE_MMU,
- RISCV_FEATURE_PMP
+ RISCV_FEATURE_PMP,
+ RISCV_FEATURE_MISA
};
#define USER_VERSION_2_02_0 0x00020200
target_ulong user_ver;
target_ulong priv_ver;
target_ulong misa;
+ target_ulong misa_mask;
uint32_t features;
char *riscv_isa_string(RISCVCPU *cpu);
void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf);
-#define cpu_signal_handler cpu_riscv_signal_handler
+#define cpu_signal_handler riscv_cpu_signal_handler
#define cpu_list riscv_cpu_list
#define cpu_mmu_index riscv_cpu_mmu_index
uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value);
#define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
#endif
-void riscv_set_mode(CPURISCVState *env, target_ulong newpriv);
+void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
void riscv_translate_init(void);
-RISCVCPU *cpu_riscv_init(const char *cpu_model);
-int cpu_riscv_signal_handler(int host_signum, void *pinfo, void *puc);
-void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
- uint32_t exception, uintptr_t pc);
+int riscv_cpu_signal_handler(int host_signum, void *pinfo, void *puc);
+void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
+ uint32_t exception, uintptr_t pc);
-target_ulong cpu_riscv_get_fflags(CPURISCVState *env);
-void cpu_riscv_set_fflags(CPURISCVState *env, target_ulong);
+target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
+void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
-#define TB_FLAGS_MMU_MASK 3
-#define TB_FLAGS_FP_ENABLE MSTATUS_FS
+#define TB_FLAGS_MMU_MASK 3
+#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *flags)
*pc = env->pc;
*cs_base = 0;
#ifdef CONFIG_USER_ONLY
- *flags = TB_FLAGS_FP_ENABLE;
+ *flags = TB_FLAGS_MSTATUS_FS;
#else
*flags = cpu_mmu_index(env, 0) | (env->mstatus & MSTATUS_FS);
#endif
int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask);
-static inline void csr_write_helper(CPURISCVState *env, target_ulong val,
- int csrno)
+static inline void riscv_csr_write(CPURISCVState *env, int csrno,
+ target_ulong val)
{
riscv_csrrw(env, csrno, NULL, val, MAKE_64BIT_MASK(0, TARGET_LONG_BITS));
}
-static inline target_ulong csr_read_helper(CPURISCVState *env, int csrno)
+static inline target_ulong riscv_csr_read(CPURISCVState *env, int csrno)
{
target_ulong val = 0;
riscv_csrrw(env, csrno, &val, 0, 0);
#define MSTATUS32_SD 0x80000000
#define MSTATUS64_SD 0x8000000000000000ULL
+#define MISA32_MXL 0xC0000000
+#define MISA64_MXL 0xC000000000000000ULL
+
+#define MXL_RV32 1
+#define MXL_RV64 2
+#define MXL_RV128 3
+
#if defined(TARGET_RISCV32)
#define MSTATUS_SD MSTATUS32_SD
+#define MISA_MXL MISA32_MXL
+#define MXL_VAL MXL_RV32
#elif defined(TARGET_RISCV64)
#define MSTATUS_SD MSTATUS64_SD
+#define MISA_MXL MISA64_MXL
+#define MXL_VAL MXL_RV64
#endif
/* sstatus CSR bits */
return old;
}
-void riscv_set_mode(CPURISCVState *env, target_ulong newpriv)
+void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
{
if (newpriv > PRV_M) {
g_assert_not_reached();
g_assert_not_reached();
}
env->badaddr = addr;
- do_raise_exception_err(env, cs->exception_index, retaddr);
+ riscv_raise_exception(env, cs->exception_index, retaddr);
}
/* called by qemu's softmmu to fill the qemu tlb */
if (ret == TRANSLATE_FAIL) {
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
- do_raise_exception_err(env, cs->exception_index, retaddr);
+ riscv_raise_exception(env, cs->exception_index, retaddr);
}
}
s = set_field(s, MSTATUS_SPP, env->priv);
s = set_field(s, MSTATUS_SIE, 0);
env->mstatus = s;
- riscv_set_mode(env, PRV_S);
+ riscv_cpu_set_mode(env, PRV_S);
} else {
/* No need to check MTVEC for misaligned - lower 2 bits cannot be set */
env->pc = env->mtvec;
s = set_field(s, MSTATUS_MPP, env->priv);
s = set_field(s, MSTATUS_MIE, 0);
env->mstatus = s;
- riscv_set_mode(env, PRV_M);
+ riscv_cpu_set_mode(env, PRV_M);
}
/* TODO yield load reservation */
#endif
static int ctr(CPURISCVState *env, int csrno)
{
#if !defined(CONFIG_USER_ONLY)
- target_ulong ctr_en = env->priv == PRV_U ? env->scounteren :
- env->priv == PRV_S ? env->mcounteren : -1U;
- if (!(ctr_en & (1 << (csrno & 31)))) {
+ uint32_t ctr_en = ~0u;
+
+ if (env->priv < PRV_M) {
+ ctr_en &= env->mcounteren;
+ }
+ if (env->priv < PRV_S) {
+ ctr_en &= env->scounteren;
+ }
+ if (!(ctr_en & (1u << (csrno & 31)))) {
return -1;
}
#endif
return -1;
}
#endif
- *val = cpu_riscv_get_fflags(env);
+ *val = riscv_cpu_get_fflags(env);
return 0;
}
}
env->mstatus |= MSTATUS_FS;
#endif
- cpu_riscv_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
+ riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
return 0;
}
return -1;
}
#endif
- *val = (cpu_riscv_get_fflags(env) << FSR_AEXC_SHIFT)
+ *val = (riscv_cpu_get_fflags(env) << FSR_AEXC_SHIFT)
| (env->frm << FSR_RD_SHIFT);
return 0;
}
env->mstatus |= MSTATUS_FS;
#endif
env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
- cpu_riscv_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
+ riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
return 0;
}
}
mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
- MSTATUS_MPP | MSTATUS_MXR;
+ MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
+ MSTATUS_TW;
}
/* silenty discard mstatus.mpp writes for unsupported modes */
mstatus = (mstatus & ~mask) | (val & mask);
- /* Note: this is a workaround for an issue where mstatus.FS
- does not report dirty after floating point operations
- that modify floating point state. This workaround is
- technically compliant with the RISC-V Privileged
- specification as it is legal to return only off, or dirty.
- at the expense of extra floating point save/restore. */
-
- /* FP is always dirty or off */
- if (mstatus & MSTATUS_FS) {
- mstatus |= MSTATUS_FS;
- }
-
int dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) |
((mstatus & MSTATUS_XS) == MSTATUS_XS);
mstatus = set_field(mstatus, MSTATUS_SD, dirty);
return 0;
}
+static int write_misa(CPURISCVState *env, int csrno, target_ulong val)
+{
+ if (!riscv_feature(env, RISCV_FEATURE_MISA)) {
+ /* drop write to misa */
+ return 0;
+ }
+
+ /* 'I' or 'E' must be present */
+ if (!(val & (RVI | RVE))) {
+ /* It is not, drop write to misa */
+ return 0;
+ }
+
+ /* 'E' excludes all other extensions */
+ if (val & RVE) {
+ /* when we support 'E' we can do "val = RVE;" however
+ * for now we just drop writes if 'E' is present.
+ */
+ return 0;
+ }
+
+ /* Mask extensions that are not supported by this hart */
+ val &= env->misa_mask;
+
+ /* Mask extensions that are not supported by QEMU */
+ val &= (RVI | RVE | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+
+ /* 'D' depends on 'F', so clear 'D' if 'F' is not present */
+ if ((val & RVD) && !(val & RVF)) {
+ val &= ~RVD;
+ }
+
+ /* Suppress 'C' if next instruction is not aligned
+ * TODO: this should check next_pc
+ */
+ if ((val & RVC) && (GETPC() & ~3) != 0) {
+ val &= ~RVC;
+ }
+
+ /* misa.MXL writes are not supported by QEMU */
+ val = (env->misa & MISA_MXL) | (val & ~MISA_MXL);
+
+ /* flush translation cache */
+ if (val != env->misa) {
+ tb_flush(CPU(riscv_env_get_cpu(env)));
+ }
+
+ env->misa = val;
+
+ return 0;
+}
+
static int read_medeleg(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->medeleg;
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
*val = 0;
} else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
- *val = env->satp;
+ if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
+ return -1;
+ } else {
+ *val = env->satp;
+ }
} else {
*val = env->sptbr;
}
validate_vm(env, get_field(val, SATP_MODE)) &&
((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
{
- tlb_flush(CPU(riscv_env_get_cpu(env)));
- env->satp = val;
+ if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
+ return -1;
+ } else {
+ tlb_flush(CPU(riscv_env_get_cpu(env)));
+ env->satp = val;
+ }
}
return 0;
}
/* Machine Trap Setup */
[CSR_MSTATUS] = { any, read_mstatus, write_mstatus },
- [CSR_MISA] = { any, read_misa },
+ [CSR_MISA] = { any, read_misa, write_misa },
[CSR_MIDELEG] = { any, read_mideleg, write_mideleg },
[CSR_MEDELEG] = { any, read_medeleg, write_medeleg },
[CSR_MIE] = { any, read_mie, write_mie },
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
-target_ulong cpu_riscv_get_fflags(CPURISCVState *env)
+target_ulong riscv_cpu_get_fflags(CPURISCVState *env)
{
int soft = get_float_exception_flags(&env->fp_status);
target_ulong hard = 0;
return hard;
}
-void cpu_riscv_set_fflags(CPURISCVState *env, target_ulong hard)
+void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong hard)
{
int soft = 0;
softrm = float_round_ties_away;
break;
default:
- do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
}
set_float_rounding_mode(softrm, &env->fp_status);
#include "exec/helper-proto.h"
/* Exceptions processing helpers */
-void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
+void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
uint32_t exception, uintptr_t pc)
{
CPUState *cs = CPU(riscv_env_get_cpu(env));
void helper_raise_exception(CPURISCVState *env, uint32_t exception)
{
- do_raise_exception_err(env, exception, 0);
+ riscv_raise_exception(env, exception, 0);
}
target_ulong helper_csrrw(CPURISCVState *env, target_ulong src,
{
target_ulong val = 0;
if (riscv_csrrw(env, csr, &val, src, -1) < 0) {
- do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
}
return val;
}
{
target_ulong val = 0;
if (riscv_csrrw(env, csr, &val, -1, rs1_pass ? src : 0) < 0) {
- do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
}
return val;
}
{
target_ulong val = 0;
if (riscv_csrrw(env, csr, &val, 0, rs1_pass ? src : 0) < 0) {
- do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
}
return val;
}
target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
{
if (!(env->priv >= PRV_S)) {
- do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
}
target_ulong retpc = env->sepc;
if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) {
- do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
+ riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
+ }
+
+ if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
+ get_field(env->mstatus, MSTATUS_TSR)) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
}
target_ulong mstatus = env->mstatus;
get_field(mstatus, MSTATUS_SPIE));
mstatus = set_field(mstatus, MSTATUS_SPIE, 0);
mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
- riscv_set_mode(env, prev_priv);
+ riscv_cpu_set_mode(env, prev_priv);
env->mstatus = mstatus;
return retpc;
target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
{
if (!(env->priv >= PRV_M)) {
- do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
}
target_ulong retpc = env->mepc;
if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) {
- do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
+ riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
}
target_ulong mstatus = env->mstatus;
get_field(mstatus, MSTATUS_MPIE));
mstatus = set_field(mstatus, MSTATUS_MPIE, 0);
mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
- riscv_set_mode(env, prev_priv);
+ riscv_cpu_set_mode(env, prev_priv);
env->mstatus = mstatus;
return retpc;
{
CPUState *cs = CPU(riscv_env_get_cpu(env));
- cs->halted = 1;
- cs->exception_index = EXCP_HLT;
- cpu_loop_exit(cs);
+ if (env->priv == PRV_S &&
+ env->priv_ver >= PRIV_VERSION_1_10_0 &&
+ get_field(env->mstatus, MSTATUS_TW)) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ } else {
+ cs->halted = 1;
+ cs->exception_index = EXCP_HLT;
+ cpu_loop_exit(cs);
+ }
}
void helper_tlb_flush(CPURISCVState *env)
{
RISCVCPU *cpu = riscv_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- tlb_flush(cs);
+ if (env->priv == PRV_S &&
+ env->priv_ver >= PRIV_VERSION_1_10_0 &&
+ get_field(env->mstatus, MSTATUS_TVM)) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ } else {
+ tlb_flush(cs);
+ }
}
#endif /* !CONFIG_USER_ONLY */
DisasContextBase base;
/* pc_succ_insn points to the instruction following base.pc_next */
target_ulong pc_succ_insn;
+ target_ulong priv_ver;
uint32_t opcode;
- uint32_t flags;
+ uint32_t mstatus_fs;
+ uint32_t misa;
uint32_t mem_idx;
/* Remember the rounding mode encoded in the previous fp instruction,
which we have already installed into env->fp_status. Or -1 for
#define CASE_OP_32_64(X) case X
#endif
+static inline bool has_ext(DisasContext *ctx, uint32_t ext)
+{
+ return ctx->misa & ext;
+}
+
static void generate_exception(DisasContext *ctx, int excp)
{
tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
tcg_gen_and_tl(source1, source1, source2);
break;
CASE_OP_32_64(OPC_RISC_MUL):
+ if (!has_ext(ctx, RVM)) {
+ goto do_illegal;
+ }
tcg_gen_mul_tl(source1, source1, source2);
break;
case OPC_RISC_MULH:
+ if (!has_ext(ctx, RVM)) {
+ goto do_illegal;
+ }
tcg_gen_muls2_tl(source2, source1, source1, source2);
break;
case OPC_RISC_MULHSU:
+ if (!has_ext(ctx, RVM)) {
+ goto do_illegal;
+ }
gen_mulhsu(source1, source1, source2);
break;
case OPC_RISC_MULHU:
+ if (!has_ext(ctx, RVM)) {
+ goto do_illegal;
+ }
tcg_gen_mulu2_tl(source2, source1, source1, source2);
break;
#if defined(TARGET_RISCV64)
case OPC_RISC_DIVW:
+ if (!has_ext(ctx, RVM)) {
+ goto do_illegal;
+ }
tcg_gen_ext32s_tl(source1, source1);
tcg_gen_ext32s_tl(source2, source2);
/* fall through to DIV */
#endif
case OPC_RISC_DIV:
+ if (!has_ext(ctx, RVM)) {
+ goto do_illegal;
+ }
/* Handle by altering args to tcg_gen_div to produce req'd results:
* For overflow: want source1 in source1 and 1 in source2
* For div by zero: want -1 in source1 and 1 in source2 -> -1 result */
break;
#if defined(TARGET_RISCV64)
case OPC_RISC_DIVUW:
+ if (!has_ext(ctx, RVM)) {
+ goto do_illegal;
+ }
tcg_gen_ext32u_tl(source1, source1);
tcg_gen_ext32u_tl(source2, source2);
/* fall through to DIVU */
#endif
case OPC_RISC_DIVU:
+ if (!has_ext(ctx, RVM)) {
+ goto do_illegal;
+ }
cond1 = tcg_temp_new();
zeroreg = tcg_const_tl(0);
resultopt1 = tcg_temp_new();
break;
#if defined(TARGET_RISCV64)
case OPC_RISC_REMW:
+ if (!has_ext(ctx, RVM)) {
+ goto do_illegal;
+ }
tcg_gen_ext32s_tl(source1, source1);
tcg_gen_ext32s_tl(source2, source2);
/* fall through to REM */
#endif
case OPC_RISC_REM:
+ if (!has_ext(ctx, RVM)) {
+ goto do_illegal;
+ }
cond1 = tcg_temp_new();
cond2 = tcg_temp_new();
zeroreg = tcg_const_tl(0);
break;
#if defined(TARGET_RISCV64)
case OPC_RISC_REMUW:
+ if (!has_ext(ctx, RVM)) {
+ goto do_illegal;
+ }
tcg_gen_ext32u_tl(source1, source1);
tcg_gen_ext32u_tl(source2, source2);
/* fall through to REMU */
#endif
case OPC_RISC_REMU:
+ if (!has_ext(ctx, RVM)) {
+ goto do_illegal;
+ }
cond1 = tcg_temp_new();
zeroreg = tcg_const_tl(0);
resultopt1 = tcg_temp_new();
tcg_temp_free(zeroreg);
tcg_temp_free(resultopt1);
break;
+ do_illegal:
default:
gen_exception_illegal(ctx);
return;
tcg_temp_free(source1);
}
-static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd,
- target_ulong imm)
+static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
{
target_ulong next_pc;
/* check misaligned: */
next_pc = ctx->base.pc_next + imm;
- if (!riscv_has_ext(env, RVC)) {
+ if (!has_ext(ctx, RVC)) {
if ((next_pc & 0x3) != 0) {
gen_exception_inst_addr_mis(ctx);
return;
ctx->base.is_jmp = DISAS_NORETURN;
}
-static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
- int rd, int rs1, target_long imm)
+static void gen_jalr(DisasContext *ctx, uint32_t opc, int rd, int rs1,
+ target_long imm)
{
/* no chaining with JALR */
TCGLabel *misaligned = NULL;
tcg_gen_addi_tl(cpu_pc, cpu_pc, imm);
tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2);
- if (!riscv_has_ext(env, RVC)) {
+ if (!has_ext(ctx, RVC)) {
misaligned = gen_new_label();
tcg_gen_andi_tl(t0, cpu_pc, 0x2);
tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
tcg_temp_free(t0);
}
-static void gen_branch(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
- int rs1, int rs2, target_long bimm)
+static void gen_branch(DisasContext *ctx, uint32_t opc, int rs1, int rs2,
+ target_long bimm)
{
TCGLabel *l = gen_new_label();
TCGv source1, source2;
gen_goto_tb(ctx, 1, ctx->pc_succ_insn);
gen_set_label(l); /* branch taken */
- if (!riscv_has_ext(env, RVC) && ((ctx->base.pc_next + bimm) & 0x3)) {
+ if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + bimm) & 0x3)) {
/* misaligned */
gen_exception_inst_addr_mis(ctx);
} else {
tcg_temp_free(dat);
}
+#ifndef CONFIG_USER_ONLY
+/* The states of mstatus_fs are:
+ * 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
+ * We will have already diagnosed disabled state,
+ * and need to turn initial/clean into dirty.
+ */
+static void mark_fs_dirty(DisasContext *ctx)
+{
+ TCGv tmp;
+ if (ctx->mstatus_fs == MSTATUS_FS) {
+ return;
+ }
+ /* Remember the state change for the rest of the TB. */
+ ctx->mstatus_fs = MSTATUS_FS;
+
+ tmp = tcg_temp_new();
+ tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
+ tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
+ tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
+ tcg_temp_free(tmp);
+}
+#else
+static inline void mark_fs_dirty(DisasContext *ctx) { }
+#endif
+
static void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd,
int rs1, target_long imm)
{
TCGv t0;
- if (!(ctx->flags & TB_FLAGS_FP_ENABLE)) {
+ if (ctx->mstatus_fs == 0) {
gen_exception_illegal(ctx);
return;
}
switch (opc) {
case OPC_RISC_FLW:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
tcg_gen_qemu_ld_i64(cpu_fpr[rd], t0, ctx->mem_idx, MO_TEUL);
/* RISC-V requires NaN-boxing of narrower width floating point values */
tcg_gen_ori_i64(cpu_fpr[rd], cpu_fpr[rd], 0xffffffff00000000ULL);
break;
case OPC_RISC_FLD:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
tcg_gen_qemu_ld_i64(cpu_fpr[rd], t0, ctx->mem_idx, MO_TEQ);
break;
+ do_illegal:
default:
gen_exception_illegal(ctx);
break;
}
tcg_temp_free(t0);
+
+ mark_fs_dirty(ctx);
}
static void gen_fp_store(DisasContext *ctx, uint32_t opc, int rs1,
{
TCGv t0;
- if (!(ctx->flags & TB_FLAGS_FP_ENABLE)) {
+ if (ctx->mstatus_fs == 0) {
gen_exception_illegal(ctx);
return;
}
switch (opc) {
case OPC_RISC_FSW:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
tcg_gen_qemu_st_i64(cpu_fpr[rs2], t0, ctx->mem_idx, MO_TEUL);
break;
case OPC_RISC_FSD:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
tcg_gen_qemu_st_i64(cpu_fpr[rs2], t0, ctx->mem_idx, MO_TEQ);
break;
+ do_illegal:
default:
gen_exception_illegal(ctx);
break;
{
switch (opc) {
case OPC_RISC_FMADD_S:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fmadd_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
cpu_fpr[rs2], cpu_fpr[rs3]);
break;
case OPC_RISC_FMADD_D:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fmadd_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
cpu_fpr[rs2], cpu_fpr[rs3]);
break;
+ do_illegal:
default:
gen_exception_illegal(ctx);
break;
{
switch (opc) {
case OPC_RISC_FMSUB_S:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fmsub_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
cpu_fpr[rs2], cpu_fpr[rs3]);
break;
case OPC_RISC_FMSUB_D:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fmsub_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
cpu_fpr[rs2], cpu_fpr[rs3]);
break;
+ do_illegal:
default:
gen_exception_illegal(ctx);
break;
{
switch (opc) {
case OPC_RISC_FNMSUB_S:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fnmsub_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
cpu_fpr[rs2], cpu_fpr[rs3]);
break;
case OPC_RISC_FNMSUB_D:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fnmsub_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
cpu_fpr[rs2], cpu_fpr[rs3]);
break;
+ do_illegal:
default:
gen_exception_illegal(ctx);
break;
{
switch (opc) {
case OPC_RISC_FNMADD_S:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fnmadd_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
cpu_fpr[rs2], cpu_fpr[rs3]);
break;
case OPC_RISC_FNMADD_D:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fnmadd_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1],
cpu_fpr[rs2], cpu_fpr[rs3]);
break;
+ do_illegal:
default:
gen_exception_illegal(ctx);
break;
int rs1, int rs2, int rm)
{
TCGv t0 = NULL;
+ bool fp_output = true;
- if (!(ctx->flags & TB_FLAGS_FP_ENABLE)) {
+ if (ctx->mstatus_fs == 0) {
goto do_illegal;
}
switch (opc) {
case OPC_RISC_FADD_S:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fadd_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
break;
case OPC_RISC_FSUB_S:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fsub_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
break;
case OPC_RISC_FMUL_S:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fmul_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
break;
case OPC_RISC_FDIV_S:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fdiv_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
break;
case OPC_RISC_FSQRT_S:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fsqrt_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1]);
break;
case OPC_RISC_FSGNJ_S:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
gen_fsgnj(ctx, rd, rs1, rs2, rm, INT32_MIN);
break;
case OPC_RISC_FMIN_S:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
/* also handles: OPC_RISC_FMAX_S */
switch (rm) {
case 0x0:
case OPC_RISC_FEQ_S:
/* also handles: OPC_RISC_FLT_S, OPC_RISC_FLE_S */
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
t0 = tcg_temp_new();
switch (rm) {
case 0x0:
}
gen_set_gpr(rd, t0);
tcg_temp_free(t0);
+ fp_output = false;
break;
case OPC_RISC_FCVT_W_S:
/* also OPC_RISC_FCVT_WU_S, OPC_RISC_FCVT_L_S, OPC_RISC_FCVT_LU_S */
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
t0 = tcg_temp_new();
switch (rs2) {
case 0: /* FCVT_W_S */
}
gen_set_gpr(rd, t0);
tcg_temp_free(t0);
+ fp_output = false;
break;
case OPC_RISC_FCVT_S_W:
/* also OPC_RISC_FCVT_S_WU, OPC_RISC_FCVT_S_L, OPC_RISC_FCVT_S_LU */
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
t0 = tcg_temp_new();
gen_get_gpr(t0, rs1);
switch (rs2) {
case OPC_RISC_FMV_X_S:
/* also OPC_RISC_FCLASS_S */
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
t0 = tcg_temp_new();
switch (rm) {
case 0: /* FMV */
}
gen_set_gpr(rd, t0);
tcg_temp_free(t0);
+ fp_output = false;
break;
case OPC_RISC_FMV_S_X:
+ if (!has_ext(ctx, RVF)) {
+ goto do_illegal;
+ }
t0 = tcg_temp_new();
gen_get_gpr(t0, rs1);
#if defined(TARGET_RISCV64)
/* double */
case OPC_RISC_FADD_D:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fadd_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
break;
case OPC_RISC_FSUB_D:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fsub_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
break;
case OPC_RISC_FMUL_D:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fmul_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
break;
case OPC_RISC_FDIV_D:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fdiv_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
break;
case OPC_RISC_FSQRT_D:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
gen_set_rm(ctx, rm);
gen_helper_fsqrt_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1]);
break;
case OPC_RISC_FMIN_D:
/* also OPC_RISC_FMAX_D */
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
switch (rm) {
case 0:
gen_helper_fmin_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
break;
case OPC_RISC_FCVT_S_D:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
switch (rs2) {
case 1:
gen_set_rm(ctx, rm);
break;
case OPC_RISC_FCVT_D_S:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
switch (rs2) {
case 0:
gen_set_rm(ctx, rm);
case OPC_RISC_FEQ_D:
/* also OPC_RISC_FLT_D, OPC_RISC_FLE_D */
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
t0 = tcg_temp_new();
switch (rm) {
case 0:
}
gen_set_gpr(rd, t0);
tcg_temp_free(t0);
+ fp_output = false;
break;
case OPC_RISC_FCVT_W_D:
/* also OPC_RISC_FCVT_WU_D, OPC_RISC_FCVT_L_D, OPC_RISC_FCVT_LU_D */
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
t0 = tcg_temp_new();
switch (rs2) {
case 0:
}
gen_set_gpr(rd, t0);
tcg_temp_free(t0);
+ fp_output = false;
break;
case OPC_RISC_FCVT_D_W:
/* also OPC_RISC_FCVT_D_WU, OPC_RISC_FCVT_D_L, OPC_RISC_FCVT_D_LU */
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
t0 = tcg_temp_new();
gen_get_gpr(t0, rs1);
switch (rs2) {
case OPC_RISC_FMV_X_D:
/* also OPC_RISC_FCLASS_D */
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
switch (rm) {
#if defined(TARGET_RISCV64)
case 0: /* FMV */
default:
goto do_illegal;
}
+ fp_output = false;
break;
#if defined(TARGET_RISCV64)
case OPC_RISC_FMV_D_X:
+ if (!has_ext(ctx, RVD)) {
+ goto do_illegal;
+ }
t0 = tcg_temp_new();
gen_get_gpr(t0, rs1);
tcg_gen_mov_tl(cpu_fpr[rd], t0);
tcg_temp_free(t0);
}
gen_exception_illegal(ctx);
- break;
+ return;
+ }
+
+ if (fp_output) {
+ mark_fs_dirty(ctx);
}
}
-static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
- int rd, int rs1, int csr)
+static void gen_system(DisasContext *ctx, uint32_t opc, int rd, int rs1,
+ int csr)
{
TCGv source1, csr_store, dest, rs1_pass, imm_rs1;
source1 = tcg_temp_new();
#ifndef CONFIG_USER_ONLY
/* Extract funct7 value and check whether it matches SFENCE.VMA */
if ((opc == OPC_RISC_ECALL) && ((csr >> 5) == 9)) {
- if (env->priv_ver == PRIV_VERSION_1_10_0) {
+ if (ctx->priv_ver == PRIV_VERSION_1_10_0) {
/* sfence.vma */
/* TODO: handle ASID specific fences */
gen_helper_tlb_flush(cpu_env);
gen_exception_illegal(ctx);
break;
case 0x102: /* SRET */
- if (riscv_has_ext(env, RVS)) {
+ if (has_ext(ctx, RVS)) {
gen_helper_sret(cpu_pc, cpu_env, cpu_pc);
tcg_gen_exit_tb(NULL, 0); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
gen_helper_wfi(cpu_env);
break;
case 0x104: /* SFENCE.VM */
- if (env->priv_ver <= PRIV_VERSION_1_09_1) {
+ if (ctx->priv_ver <= PRIV_VERSION_1_09_1) {
gen_helper_tlb_flush(cpu_env);
} else {
gen_exception_illegal(ctx);
}
}
-static void decode_RV32_64C1(CPURISCVState *env, DisasContext *ctx)
+static void decode_RV32_64C1(DisasContext *ctx)
{
uint8_t funct3 = extract32(ctx->opcode, 13, 3);
uint8_t rd_rs1 = GET_C_RS1(ctx->opcode);
GET_C_IMM(ctx->opcode));
#else
/* C.JAL(RV32) -> jal x1, offset[11:1] */
- gen_jal(env, ctx, 1, GET_C_J_IMM(ctx->opcode));
+ gen_jal(ctx, 1, GET_C_J_IMM(ctx->opcode));
#endif
break;
case 2:
break;
case 5:
/* C.J -> jal x0, offset[11:1]*/
- gen_jal(env, ctx, 0, GET_C_J_IMM(ctx->opcode));
+ gen_jal(ctx, 0, GET_C_J_IMM(ctx->opcode));
break;
case 6:
/* C.BEQZ -> beq rs1', x0, offset[8:1]*/
rs1s = GET_C_RS1S(ctx->opcode);
- gen_branch(env, ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode));
+ gen_branch(ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode));
break;
case 7:
/* C.BNEZ -> bne rs1', x0, offset[8:1]*/
rs1s = GET_C_RS1S(ctx->opcode);
- gen_branch(env, ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode));
+ gen_branch(ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode));
break;
}
}
-static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
+static void decode_RV32_64C2(DisasContext *ctx)
{
uint8_t rd, rs2;
uint8_t funct3 = extract32(ctx->opcode, 13, 3);
if (extract32(ctx->opcode, 12, 1) == 0) {
if (rs2 == 0) {
/* C.JR -> jalr x0, rs1, 0*/
- gen_jalr(env, ctx, OPC_RISC_JALR, 0, rd, 0);
+ gen_jalr(ctx, OPC_RISC_JALR, 0, rd, 0);
} else {
/* C.MV -> add rd, x0, rs2 */
gen_arith(ctx, OPC_RISC_ADD, rd, 0, rs2);
} else {
if (rd == 0) {
/* C.EBREAK -> ebreak*/
- gen_system(env, ctx, OPC_RISC_ECALL, 0, 0, 0x1);
+ gen_system(ctx, OPC_RISC_ECALL, 0, 0, 0x1);
} else {
if (rs2 == 0) {
/* C.JALR -> jalr x1, rs1, 0*/
- gen_jalr(env, ctx, OPC_RISC_JALR, 1, rd, 0);
+ gen_jalr(ctx, OPC_RISC_JALR, 1, rd, 0);
} else {
/* C.ADD -> add rd, rd, rs2 */
gen_arith(ctx, OPC_RISC_ADD, rd, rd, rs2);
}
}
-static void decode_RV32_64C(CPURISCVState *env, DisasContext *ctx)
+static void decode_RV32_64C(DisasContext *ctx)
{
uint8_t op = extract32(ctx->opcode, 0, 2);
decode_RV32_64C0(ctx);
break;
case 1:
- decode_RV32_64C1(env, ctx);
+ decode_RV32_64C1(ctx);
break;
case 2:
- decode_RV32_64C2(env, ctx);
+ decode_RV32_64C2(ctx);
break;
}
}
-static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
+static void decode_RV32_64G(DisasContext *ctx)
{
int rs1;
int rs2;
break;
case OPC_RISC_JAL:
imm = GET_JAL_IMM(ctx->opcode);
- gen_jal(env, ctx, rd, imm);
+ gen_jal(ctx, rd, imm);
break;
case OPC_RISC_JALR:
- gen_jalr(env, ctx, MASK_OP_JALR(ctx->opcode), rd, rs1, imm);
+ gen_jalr(ctx, MASK_OP_JALR(ctx->opcode), rd, rs1, imm);
break;
case OPC_RISC_BRANCH:
- gen_branch(env, ctx, MASK_OP_BRANCH(ctx->opcode), rs1, rs2,
+ gen_branch(ctx, MASK_OP_BRANCH(ctx->opcode), rs1, rs2,
GET_B_IMM(ctx->opcode));
break;
case OPC_RISC_LOAD:
GET_STORE_IMM(ctx->opcode));
break;
case OPC_RISC_ATOMIC:
+ if (!has_ext(ctx, RVA)) {
+ goto do_illegal;
+ }
gen_atomic(ctx, MASK_OP_ATOMIC(ctx->opcode), rd, rs1, rs2);
break;
case OPC_RISC_FMADD:
}
break;
case OPC_RISC_SYSTEM:
- gen_system(env, ctx, MASK_OP_SYSTEM(ctx->opcode), rd, rs1,
+ gen_system(ctx, MASK_OP_SYSTEM(ctx->opcode), rd, rs1,
(ctx->opcode & 0xFFF00000) >> 20);
break;
+ do_illegal:
default:
gen_exception_illegal(ctx);
break;
}
}
-static void decode_opc(CPURISCVState *env, DisasContext *ctx)
+static void decode_opc(DisasContext *ctx)
{
/* check for compressed insn */
if (extract32(ctx->opcode, 0, 2) != 3) {
- if (!riscv_has_ext(env, RVC)) {
+ if (!has_ext(ctx, RVC)) {
gen_exception_illegal(ctx);
} else {
ctx->pc_succ_insn = ctx->base.pc_next + 2;
- decode_RV32_64C(env, ctx);
+ decode_RV32_64C(ctx);
}
} else {
ctx->pc_succ_insn = ctx->base.pc_next + 4;
- decode_RV32_64G(env, ctx);
+ decode_RV32_64G(ctx);
}
}
static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
{
DisasContext *ctx = container_of(dcbase, DisasContext, base);
+ CPURISCVState *env = cs->env_ptr;
ctx->pc_succ_insn = ctx->base.pc_first;
- ctx->flags = ctx->base.tb->flags;
ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK;
+ ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
+ ctx->priv_ver = env->priv_ver;
+ ctx->misa = env->misa;
ctx->frm = -1; /* unknown rounding mode */
}
return true;
}
-
static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
{
DisasContext *ctx = container_of(dcbase, DisasContext, base);
CPURISCVState *env = cpu->env_ptr;
ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
- decode_opc(env, ctx);
+ decode_opc(ctx);
ctx->base.pc_next = ctx->pc_succ_insn;
if (ctx->base.is_jmp == DISAS_NEXT) {
* Copyright (c) 2012 SUSE LINUX Products GmbH
* Copyright (c) 2012 IBM Corp.
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * This library is distributed in the hope that it will be useful,
+ * 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
- * Lesser General Public License for more details.
+ * General Public License for more details.
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/lgpl-2.1.html>
- * Contributions after 2012-12-11 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
* Copyright (c) 2009 Ulrich Hecht
* Copyright IBM Corp. 2012, 2018
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * This library is distributed in the hope that it will be useful,
+ * 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
- * Lesser General Public License for more details.
+ * General Public License for more details.
*
- * Contributions after 2012-10-29 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- *
- * You should have received a copy of the GNU (Lesser) General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef S390X_CPU_H
#define CPUArchState struct CPUS390XState
#include "exec/cpu-defs.h"
+
+/* The z/Architecture has a strong memory model with some store-after-load re-ordering */
+#define TCG_GUEST_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD)
+
#define TARGET_PAGE_BITS 12
#define TARGET_PHYS_ADDR_SPACE_BITS 64
FEAT_GROUP_INIT("plo", PLO, "Perform-locked-operation facility"),
FEAT_GROUP_INIT("tods", TOD_CLOCK_STEERING, "Tod-clock-steering facility"),
FEAT_GROUP_INIT("gen13ptff", GEN13_PTFF, "PTFF enhancements introduced with z13"),
- FEAT_GROUP_INIT("mepochptff", MULTIPLE_EPOCH_PTFF, "PTFF enhancements introduced with Multiple-epoch facility"),
FEAT_GROUP_INIT("msa", MSA, "Message-security-assist facility"),
FEAT_GROUP_INIT("msa1", MSA_EXT_1, "Message-security-assist-extension 1 facility"),
FEAT_GROUP_INIT("msa2", MSA_EXT_2, "Message-security-assist-extension 2 facility"),
FEAT_GROUP_INIT("msa6", MSA_EXT_6, "Message-security-assist-extension 6 facility"),
FEAT_GROUP_INIT("msa7", MSA_EXT_7, "Message-security-assist-extension 7 facility"),
FEAT_GROUP_INIT("msa8", MSA_EXT_8, "Message-security-assist-extension 8 facility"),
+ FEAT_GROUP_INIT("mepochptff", MULTIPLE_EPOCH_PTFF, "PTFF enhancements introduced with Multiple-epoch facility"),
};
const S390FeatGroupDef *s390_feat_group_def(S390FeatGroup group)
#include "sysemu/arch_init.h"
#include "hw/pci/pci.h"
#endif
+#include "qapi/qapi-commands-target.h"
#define CPUDEF_INIT(_type, _gen, _ec_ga, _mha_pow, _hmfai, _name, _desc) \
{ \
CPUDEF_INIT(0x2964, 13, 2, 47, 0x08000000U, "z13.2", "IBM z13 GA2"),
CPUDEF_INIT(0x2965, 13, 2, 47, 0x08000000U, "z13s", "IBM z13s GA1"),
CPUDEF_INIT(0x3906, 14, 1, 47, 0x08000000U, "z14", "IBM z14 GA1"),
+ CPUDEF_INIT(0x3906, 14, 2, 47, 0x08000000U, "z14.2", "IBM z14 GA2"),
CPUDEF_INIT(0x3907, 14, 1, 47, 0x08000000U, "z14ZR1", "IBM z14 Model ZR1 GA1"),
};
}
}
+void s390_cpudef_group_featoff_greater(uint8_t gen, uint8_t ec_ga,
+ S390FeatGroup group)
+{
+ const S390FeatGroupDef *group_def = s390_feat_group_def(group);
+ S390FeatBitmap group_def_off;
+ int i;
+
+ bitmap_complement(group_def_off, group_def->feat, S390_FEAT_MAX);
+
+ for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) {
+ const S390CPUDef *cpu_def = &s390_cpu_defs[i];
+
+ if (cpu_def->gen < gen) {
+ continue;
+ }
+ if (cpu_def->gen == gen && cpu_def->ec_ga < ec_ga) {
+ continue;
+ }
+
+ bitmap_and((unsigned long *)&cpu_def->default_feat,
+ cpu_def->default_feat, group_def_off, S390_FEAT_MAX);
+ }
+}
+
uint32_t s390_get_hmfai(void)
{
static S390CPU *cpu;
*cpu_list = entry;
}
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
{
struct CpuDefinitionInfoListData list_data = {
.list = NULL,
}
}
-CpuModelExpansionInfo *arch_query_cpu_model_expansion(CpuModelExpansionType type,
+CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
CpuModelInfo *model,
Error **errp)
{
*last = entry;
}
-CpuModelCompareInfo *arch_query_cpu_model_comparison(CpuModelInfo *infoa,
+CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *infoa,
CpuModelInfo *infob,
Error **errp)
{
return compare_info;
}
-CpuModelBaselineInfo *arch_query_cpu_model_baseline(CpuModelInfo *infoa,
+CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *infoa,
CpuModelInfo *infob,
Error **errp)
{
{ S390_FEAT_SIE_KSS, S390_FEAT_SIE_F2 },
{ S390_FEAT_AP_QUERY_CONFIG_INFO, S390_FEAT_AP },
{ S390_FEAT_AP_FACILITIES_TEST, S390_FEAT_AP },
+ { S390_FEAT_PTFF_QSIE, S390_FEAT_MULTIPLE_EPOCH },
+ { S390_FEAT_PTFF_QTOUE, S390_FEAT_MULTIPLE_EPOCH },
+ { S390_FEAT_PTFF_STOE, S390_FEAT_MULTIPLE_EPOCH },
+ { S390_FEAT_PTFF_STOUE, S390_FEAT_MULTIPLE_EPOCH },
};
int i;
/* init all bitmaps from gnerated data initially */
s390_init_feat_bitmap(qemu_max_cpu_feat_init, qemu_max_cpu_feat);
-#ifndef CONFIG_USER_ONLY
- if (!pci_available) {
- clear_bit(S390_FEAT_ZPCI, qemu_max_cpu_feat);
- }
-#endif
for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) {
s390_init_feat_bitmap(s390_cpu_defs[i].base_init,
s390_cpu_defs[i].base_feat);
void s390_cpudef_featoff(uint8_t gen, uint8_t ec_ga, S390Feat feat);
void s390_cpudef_featoff_greater(uint8_t gen, uint8_t ec_ga, S390Feat feat);
+void s390_cpudef_group_featoff_greater(uint8_t gen, uint8_t ec_ga,
+ S390FeatGroup group);
uint32_t s390_get_hmfai(void);
uint8_t s390_get_mha_pow(void);
uint32_t s390_get_ibc_val(void);
S390_FEAT_ORDER_PRESERVING_COMPRESSION,
};
+#define base_GEN14_GA2 EmptyFeat
+
/* Full features (in order of release)
* Automatically includes corresponding base features.
* Full features are all features this hardware supports even if kvm/QEMU do not
S390_FEAT_GROUP_MULTIPLE_EPOCH_PTFF,
};
+#define full_GEN14_GA2 EmptyFeat
+
/* Default features (in order of release)
* Automatically includes corresponding base features.
* Default features are all features this version of QEMU supports for this
S390_FEAT_GROUP_MSA_EXT_6,
S390_FEAT_GROUP_MSA_EXT_7,
S390_FEAT_GROUP_MSA_EXT_8,
+ S390_FEAT_MULTIPLE_EPOCH,
+ S390_FEAT_GROUP_MULTIPLE_EPOCH_PTFF,
};
+#define default_GEN14_GA2 EmptyFeat
+
/* QEMU (CPU model) features */
static uint16_t qemu_V2_11[] = {
S390_FEAT_ZARCH,
};
-static uint16_t qemu_LATEST[] = {
+static uint16_t qemu_V3_1[] = {
S390_FEAT_DAT_ENH,
S390_FEAT_IDTE_SEGMENT,
S390_FEAT_STFLE,
S390_FEAT_MSA_EXT_4,
};
+static uint16_t qemu_LATEST[] = {
+ S390_FEAT_ZPCI,
+};
+
/* add all new definitions before this point */
static uint16_t qemu_MAX[] = {
/* z13+ features */
S390_FEAT_STFLE_53,
/* generates a dependency warning, leave it out for now */
S390_FEAT_MSA_EXT_5,
- /* only with CONFIG_PCI */
- S390_FEAT_ZPCI,
};
/****** END FEATURE DEFS ******/
CPU_FEAT_INITIALIZER(GEN13_GA1),
CPU_FEAT_INITIALIZER(GEN13_GA2),
CPU_FEAT_INITIALIZER(GEN14_GA1),
+ CPU_FEAT_INITIALIZER(GEN14_GA2),
};
#define FEAT_GROUP_INITIALIZER(_name) \
*******************************/
static FeatGroupDefSpec QemuFeatDef[] = {
QEMU_FEAT_INITIALIZER(V2_11),
+ QEMU_FEAT_INITIALIZER(V3_1),
QEMU_FEAT_INITIALIZER(LATEST),
QEMU_FEAT_INITIALIZER(MAX),
};
DEF_HELPER_4(cu42, i32, env, i32, i32, i32)
DEF_HELPER_5(msa, i32, env, i32, i32, i32, i32)
DEF_HELPER_FLAGS_1(stpt, TCG_CALL_NO_RWG, i64, env)
+DEF_HELPER_FLAGS_1(stck, TCG_CALL_NO_RWG_SE, i64, env)
#ifndef CONFIG_USER_ONLY
DEF_HELPER_3(servc, i32, env, i64, i64)
DEF_HELPER_4(diag, void, env, i32, i32, i32)
DEF_HELPER_3(load_psw, noreturn, env, i64, i64)
DEF_HELPER_FLAGS_2(spx, TCG_CALL_NO_RWG, void, env, i64)
-DEF_HELPER_FLAGS_1(stck, TCG_CALL_NO_RWG_SE, i64, env)
DEF_HELPER_FLAGS_2(sck, TCG_CALL_NO_RWG, i32, env, i64)
DEF_HELPER_FLAGS_2(sckc, TCG_CALL_NO_RWG, void, env, i64)
DEF_HELPER_FLAGS_2(sckpf, TCG_CALL_NO_RWG, void, env, i64)
C(0xe308, AG, RXY_a, Z, r1, m2_64, r1, 0, add, adds64)
C(0xe318, AGF, RXY_a, Z, r1, m2_32s, r1, 0, add, adds64)
F(0xb30a, AEBR, RRE, Z, e1, e2, new, e1, aeb, f32, IF_BFP)
- F(0xb31a, ADBR, RRE, Z, f1_o, f2_o, f1, 0, adb, f64, IF_BFP)
- F(0xb34a, AXBR, RRE, Z, 0, x2_o, x1, 0, axb, f128, IF_BFP)
+ F(0xb31a, ADBR, RRE, Z, f1, f2, new, f1, adb, f64, IF_BFP)
+ F(0xb34a, AXBR, RRE, Z, x2h, x2l, x1, x1, axb, f128, IF_BFP)
F(0xed0a, AEB, RXE, Z, e1, m2_32u, new, e1, aeb, f32, IF_BFP)
- F(0xed1a, ADB, RXE, Z, f1_o, m2_64, f1, 0, adb, f64, IF_BFP)
+ F(0xed1a, ADB, RXE, Z, f1, m2_64, new, f1, adb, f64, IF_BFP)
/* ADD HIGH */
C(0xb9c8, AHHHR, RRF_a, HW, r2_sr32, r3_sr32, new, r1_32h, add, adds32)
C(0xb9d8, AHHLR, RRF_a, HW, r2_sr32, r3, new, r1_32h, add, adds32)
C(0xb241, CKSM, RRE, Z, r1_o, ra2, new, r1_32, cksm, 0)
/* COPY SIGN */
- F(0xb372, CPSDR, RRF_b, FPSSH, f3_o, f2_o, f1, 0, cps, 0, IF_AFP1 | IF_AFP2 | IF_AFP3)
+ F(0xb372, CPSDR, RRF_b, FPSSH, f3, f2, new, f1, cps, 0, IF_AFP1 | IF_AFP2 | IF_AFP3)
/* COMPARE */
C(0x1900, CR, RR_a, Z, r1_o, r2_o, 0, 0, 0, cmps32)
C(0xe320, CG, RXY_a, Z, r1_o, m2_64, 0, 0, 0, cmps64)
C(0xe330, CGF, RXY_a, Z, r1_o, m2_32s, 0, 0, 0, cmps64)
F(0xb309, CEBR, RRE, Z, e1, e2, 0, 0, ceb, 0, IF_BFP)
- F(0xb319, CDBR, RRE, Z, f1_o, f2_o, 0, 0, cdb, 0, IF_BFP)
- F(0xb349, CXBR, RRE, Z, x1_o, x2_o, 0, 0, cxb, 0, IF_BFP)
+ F(0xb319, CDBR, RRE, Z, f1, f2, 0, 0, cdb, 0, IF_BFP)
+ F(0xb349, CXBR, RRE, Z, x2h, x2l, x1, 0, cxb, 0, IF_BFP)
F(0xed09, CEB, RXE, Z, e1, m2_32u, 0, 0, ceb, 0, IF_BFP)
- F(0xed19, CDB, RXE, Z, f1_o, m2_64, 0, 0, cdb, 0, IF_BFP)
+ F(0xed19, CDB, RXE, Z, f1, m2_64, 0, 0, cdb, 0, IF_BFP)
/* COMPARE AND SIGNAL */
F(0xb308, KEBR, RRE, Z, e1, e2, 0, 0, keb, 0, IF_BFP)
- F(0xb318, KDBR, RRE, Z, f1_o, f2_o, 0, 0, kdb, 0, IF_BFP)
- F(0xb348, KXBR, RRE, Z, x1_o, x2_o, 0, 0, kxb, 0, IF_BFP)
+ F(0xb318, KDBR, RRE, Z, f1, f2, 0, 0, kdb, 0, IF_BFP)
+ F(0xb348, KXBR, RRE, Z, x2h, x2l, x1, 0, kxb, 0, IF_BFP)
F(0xed08, KEB, RXE, Z, e1, m2_32u, 0, 0, keb, 0, IF_BFP)
- F(0xed18, KDB, RXE, Z, f1_o, m2_64, 0, 0, kdb, 0, IF_BFP)
+ F(0xed18, KDB, RXE, Z, f1, m2_64, 0, 0, kdb, 0, IF_BFP)
/* COMPARE IMMEDIATE */
C(0xc20d, CFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps32)
C(0xc20c, CGFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps64)
C(0xe326, CVDY, RXY_a, LD, r1_o, a2, 0, 0, cvd, 0)
/* CONVERT TO FIXED */
F(0xb398, CFEBR, RRF_e, Z, 0, e2, new, r1_32, cfeb, 0, IF_BFP)
- F(0xb399, CFDBR, RRF_e, Z, 0, f2_o, new, r1_32, cfdb, 0, IF_BFP)
- F(0xb39a, CFXBR, RRF_e, Z, 0, x2_o, new, r1_32, cfxb, 0, IF_BFP)
+ F(0xb399, CFDBR, RRF_e, Z, 0, f2, new, r1_32, cfdb, 0, IF_BFP)
+ F(0xb39a, CFXBR, RRF_e, Z, x2h, x2l, new, r1_32, cfxb, 0, IF_BFP)
F(0xb3a8, CGEBR, RRF_e, Z, 0, e2, r1, 0, cgeb, 0, IF_BFP)
- F(0xb3a9, CGDBR, RRF_e, Z, 0, f2_o, r1, 0, cgdb, 0, IF_BFP)
- F(0xb3aa, CGXBR, RRF_e, Z, 0, x2_o, r1, 0, cgxb, 0, IF_BFP)
+ F(0xb3a9, CGDBR, RRF_e, Z, 0, f2, r1, 0, cgdb, 0, IF_BFP)
+ F(0xb3aa, CGXBR, RRF_e, Z, x2h, x2l, r1, 0, cgxb, 0, IF_BFP)
/* CONVERT FROM FIXED */
F(0xb394, CEFBR, RRF_e, Z, 0, r2_32s, new, e1, cegb, 0, IF_BFP)
- F(0xb395, CDFBR, RRF_e, Z, 0, r2_32s, f1, 0, cdgb, 0, IF_BFP)
- F(0xb396, CXFBR, RRF_e, Z, 0, r2_32s, x1, 0, cxgb, 0, IF_BFP)
+ F(0xb395, CDFBR, RRF_e, Z, 0, r2_32s, new, f1, cdgb, 0, IF_BFP)
+ F(0xb396, CXFBR, RRF_e, Z, 0, r2_32s, new_P, x1, cxgb, 0, IF_BFP)
F(0xb3a4, CEGBR, RRF_e, Z, 0, r2_o, new, e1, cegb, 0, IF_BFP)
- F(0xb3a5, CDGBR, RRF_e, Z, 0, r2_o, f1, 0, cdgb, 0, IF_BFP)
- F(0xb3a6, CXGBR, RRF_e, Z, 0, r2_o, x1, 0, cxgb, 0, IF_BFP)
+ F(0xb3a5, CDGBR, RRF_e, Z, 0, r2_o, new, f1, cdgb, 0, IF_BFP)
+ F(0xb3a6, CXGBR, RRF_e, Z, 0, r2_o, new_P, x1, cxgb, 0, IF_BFP)
/* CONVERT TO LOGICAL */
F(0xb39c, CLFEBR, RRF_e, FPE, 0, e2, new, r1_32, clfeb, 0, IF_BFP)
- F(0xb39d, CLFDBR, RRF_e, FPE, 0, f2_o, new, r1_32, clfdb, 0, IF_BFP)
- F(0xb39e, CLFXBR, RRF_e, FPE, 0, x2_o, new, r1_32, clfxb, 0, IF_BFP)
+ F(0xb39d, CLFDBR, RRF_e, FPE, 0, f2, new, r1_32, clfdb, 0, IF_BFP)
+ F(0xb39e, CLFXBR, RRF_e, FPE, x2h, x2l, new, r1_32, clfxb, 0, IF_BFP)
F(0xb3ac, CLGEBR, RRF_e, FPE, 0, e2, r1, 0, clgeb, 0, IF_BFP)
- F(0xb3ad, CLGDBR, RRF_e, FPE, 0, f2_o, r1, 0, clgdb, 0, IF_BFP)
- F(0xb3ae, CLGXBR, RRF_e, FPE, 0, x2_o, r1, 0, clgxb, 0, IF_BFP)
+ F(0xb3ad, CLGDBR, RRF_e, FPE, 0, f2, r1, 0, clgdb, 0, IF_BFP)
+ F(0xb3ae, CLGXBR, RRF_e, FPE, x2h, x2l, r1, 0, clgxb, 0, IF_BFP)
/* CONVERT FROM LOGICAL */
F(0xb390, CELFBR, RRF_e, FPE, 0, r2_32u, new, e1, celgb, 0, IF_BFP)
- F(0xb391, CDLFBR, RRF_e, FPE, 0, r2_32u, f1, 0, cdlgb, 0, IF_BFP)
- F(0xb392, CXLFBR, RRF_e, FPE, 0, r2_32u, x1, 0, cxlgb, 0, IF_BFP)
+ F(0xb391, CDLFBR, RRF_e, FPE, 0, r2_32u, new, f1, cdlgb, 0, IF_BFP)
+ F(0xb392, CXLFBR, RRF_e, FPE, 0, r2_32u, new_P, x1, cxlgb, 0, IF_BFP)
F(0xb3a0, CELGBR, RRF_e, FPE, 0, r2_o, new, e1, celgb, 0, IF_BFP)
- F(0xb3a1, CDLGBR, RRF_e, FPE, 0, r2_o, f1, 0, cdlgb, 0, IF_BFP)
- F(0xb3a2, CXLGBR, RRF_e, FPE, 0, r2_o, x1, 0, cxlgb, 0, IF_BFP)
+ F(0xb3a1, CDLGBR, RRF_e, FPE, 0, r2_o, new, f1, cdlgb, 0, IF_BFP)
+ F(0xb3a2, CXLGBR, RRF_e, FPE, 0, r2_o, new_P, x1, cxlgb, 0, IF_BFP)
/* CONVERT UTF-8 TO UTF-16 */
D(0xb2a7, CU12, RRF_c, Z, 0, 0, 0, 0, cuXX, 0, 12)
C(0x1d00, DR, RR_a, Z, r1_D32, r2_32s, new_P, r1_P32, divs32, 0)
C(0x5d00, D, RX_a, Z, r1_D32, m2_32s, new_P, r1_P32, divs32, 0)
F(0xb30d, DEBR, RRE, Z, e1, e2, new, e1, deb, 0, IF_BFP)
- F(0xb31d, DDBR, RRE, Z, f1_o, f2_o, f1, 0, ddb, 0, IF_BFP)
- F(0xb34d, DXBR, RRE, Z, 0, x2_o, x1, 0, dxb, 0, IF_BFP)
+ F(0xb31d, DDBR, RRE, Z, f1, f2, new, f1, ddb, 0, IF_BFP)
+ F(0xb34d, DXBR, RRE, Z, x2h, x2l, x1, x1, dxb, 0, IF_BFP)
F(0xed0d, DEB, RXE, Z, e1, m2_32u, new, e1, deb, 0, IF_BFP)
- F(0xed1d, DDB, RXE, Z, f1_o, m2_64, f1, 0, ddb, 0, IF_BFP)
+ F(0xed1d, DDB, RXE, Z, f1, m2_64, new, f1, ddb, 0, IF_BFP)
/* DIVIDE LOGICAL */
C(0xb997, DLR, RRE, Z, r1_D32, r2_32u, new_P, r1_P32, divu32, 0)
C(0xe397, DL, RXY_a, Z, r1_D32, m2_32u, new_P, r1_P32, divu32, 0)
C(0xb914, LGFR, RRE, Z, 0, r2_32s, 0, r1, mov2, 0)
C(0xe304, LG, RXY_a, Z, 0, a2, r1, 0, ld64, 0)
C(0xe314, LGF, RXY_a, Z, 0, a2, r1, 0, ld32s, 0)
- F(0x2800, LDR, RR_a, Z, 0, f2_o, 0, f1, mov2, 0, IF_AFP1 | IF_AFP2)
+ F(0x2800, LDR, RR_a, Z, 0, f2, 0, f1, mov2, 0, IF_AFP1 | IF_AFP2)
F(0x6800, LD, RX_a, Z, 0, m2_64, 0, f1, mov2, 0, IF_AFP1)
F(0xed65, LDY, RXY_a, LD, 0, m2_64, 0, f1, mov2, 0, IF_AFP1)
F(0x3800, LER, RR_a, Z, 0, e2, 0, cond_e1e2, mov2, 0, IF_AFP1 | IF_AFP2)
F(0x7800, LE, RX_a, Z, 0, m2_32u, 0, e1, mov2, 0, IF_AFP1)
F(0xed64, LEY, RXY_a, LD, 0, m2_32u, 0, e1, mov2, 0, IF_AFP1)
- F(0xb365, LXR, RRE, Z, 0, x2_o, 0, x1, movx, 0, IF_AFP1)
+ F(0xb365, LXR, RRE, Z, x2h, x2l, 0, x1, movx, 0, IF_AFP1)
/* LOAD IMMEDIATE */
C(0xc001, LGFI, RIL_a, EI, 0, i2, 0, r1, mov2, 0)
/* LOAD RELATIVE LONG */
C(0xe302, LTG, RXY_a, EI, 0, a2, r1, 0, ld64, s64)
C(0xe332, LTGF, RXY_a, GIE, 0, a2, r1, 0, ld32s, s64)
F(0xb302, LTEBR, RRE, Z, 0, e2, 0, cond_e1e2, mov2, f32, IF_BFP)
- F(0xb312, LTDBR, RRE, Z, 0, f2_o, 0, f1, mov2, f64, IF_BFP)
- F(0xb342, LTXBR, RRE, Z, 0, x2_o, 0, x1, movx, f128, IF_BFP)
+ F(0xb312, LTDBR, RRE, Z, 0, f2, 0, f1, mov2, f64, IF_BFP)
+ F(0xb342, LTXBR, RRE, Z, x2h, x2l, 0, x1, movx, f128, IF_BFP)
/* LOAD AND TRAP */
C(0xe39f, LAT, RXY_a, LAT, 0, m2_32u, r1, 0, lat, 0)
C(0xe385, LGAT, RXY_a, LAT, 0, a2, r1, 0, lgat, 0)
C(0xb903, LCGR, RRE, Z, 0, r2, r1, 0, neg, neg64)
C(0xb913, LCGFR, RRE, Z, 0, r2_32s, r1, 0, neg, neg64)
F(0xb303, LCEBR, RRE, Z, 0, e2, new, e1, negf32, f32, IF_BFP)
- F(0xb313, LCDBR, RRE, Z, 0, f2_o, f1, 0, negf64, f64, IF_BFP)
- F(0xb343, LCXBR, RRE, Z, 0, x2_o, x1, 0, negf128, f128, IF_BFP)
- F(0xb373, LCDFR, RRE, FPSSH, 0, f2_o, f1, 0, negf64, 0, IF_AFP1 | IF_AFP2)
+ F(0xb313, LCDBR, RRE, Z, 0, f2, new, f1, negf64, f64, IF_BFP)
+ F(0xb343, LCXBR, RRE, Z, x2h, x2l, new_P, x1, negf128, f128, IF_BFP)
+ F(0xb373, LCDFR, RRE, FPSSH, 0, f2, new, f1, negf64, 0, IF_AFP1 | IF_AFP2)
/* LOAD HALFWORD */
C(0xb927, LHR, RRE, EI, 0, r2_16s, 0, r1_32, mov2, 0)
C(0xb907, LGHR, RRE, EI, 0, r2_16s, 0, r1, mov2, 0)
/* LOAD FPR FROM GR */
F(0xb3c1, LDGR, RRE, FPRGR, 0, r2_o, 0, f1, mov2, 0, IF_AFP1)
/* LOAD GR FROM FPR */
- F(0xb3cd, LGDR, RRE, FPRGR, 0, f2_o, 0, r1, mov2, 0, IF_AFP2)
+ F(0xb3cd, LGDR, RRE, FPRGR, 0, f2, 0, r1, mov2, 0, IF_AFP2)
/* LOAD NEGATIVE */
C(0x1100, LNR, RR_a, Z, 0, r2_32s, new, r1_32, nabs, nabs32)
C(0xb901, LNGR, RRE, Z, 0, r2, r1, 0, nabs, nabs64)
C(0xb911, LNGFR, RRE, Z, 0, r2_32s, r1, 0, nabs, nabs64)
F(0xb301, LNEBR, RRE, Z, 0, e2, new, e1, nabsf32, f32, IF_BFP)
- F(0xb311, LNDBR, RRE, Z, 0, f2_o, f1, 0, nabsf64, f64, IF_BFP)
- F(0xb341, LNXBR, RRE, Z, 0, x2_o, x1, 0, nabsf128, f128, IF_BFP)
- F(0xb371, LNDFR, RRE, FPSSH, 0, f2_o, f1, 0, nabsf64, 0, IF_AFP1 | IF_AFP2)
+ F(0xb311, LNDBR, RRE, Z, 0, f2, new, f1, nabsf64, f64, IF_BFP)
+ F(0xb341, LNXBR, RRE, Z, x2h, x2l, new_P, x1, nabsf128, f128, IF_BFP)
+ F(0xb371, LNDFR, RRE, FPSSH, 0, f2, new, f1, nabsf64, 0, IF_AFP1 | IF_AFP2)
/* LOAD ON CONDITION */
C(0xb9f2, LOCR, RRF_c, LOC, r1, r2, new, r1_32, loc, 0)
C(0xb9e2, LOCGR, RRF_c, LOC, r1, r2, r1, 0, loc, 0)
C(0xb900, LPGR, RRE, Z, 0, r2, r1, 0, abs, abs64)
C(0xb910, LPGFR, RRE, Z, 0, r2_32s, r1, 0, abs, abs64)
F(0xb300, LPEBR, RRE, Z, 0, e2, new, e1, absf32, f32, IF_BFP)
- F(0xb310, LPDBR, RRE, Z, 0, f2_o, f1, 0, absf64, f64, IF_BFP)
- F(0xb340, LPXBR, RRE, Z, 0, x2_o, x1, 0, absf128, f128, IF_BFP)
- F(0xb370, LPDFR, RRE, FPSSH, 0, f2_o, f1, 0, absf64, 0, IF_AFP1 | IF_AFP2)
+ F(0xb310, LPDBR, RRE, Z, 0, f2, new, f1, absf64, f64, IF_BFP)
+ F(0xb340, LPXBR, RRE, Z, x2h, x2l, new_P, x1, absf128, f128, IF_BFP)
+ F(0xb370, LPDFR, RRE, FPSSH, 0, f2, new, f1, absf64, 0, IF_AFP1 | IF_AFP2)
/* LOAD REVERSED */
C(0xb91f, LRVR, RRE, Z, 0, r2_32u, new, r1_32, rev32, 0)
C(0xb90f, LRVGR, RRE, Z, 0, r2_o, r1, 0, rev64, 0)
F(0xb2bd, LFAS, S, IEEEE_SIM, 0, m2_32u, 0, 0, sfas, 0, IF_DFP)
/* LOAD FP INTEGER */
F(0xb357, FIEBR, RRF_e, Z, 0, e2, new, e1, fieb, 0, IF_BFP)
- F(0xb35f, FIDBR, RRF_e, Z, 0, f2_o, f1, 0, fidb, 0, IF_BFP)
- F(0xb347, FIXBR, RRF_e, Z, 0, x2_o, x1, 0, fixb, 0, IF_BFP)
+ F(0xb35f, FIDBR, RRF_e, Z, 0, f2, new, f1, fidb, 0, IF_BFP)
+ F(0xb347, FIXBR, RRF_e, Z, x2h, x2l, new_P, x1, fixb, 0, IF_BFP)
/* LOAD LENGTHENED */
- F(0xb304, LDEBR, RRE, Z, 0, e2, f1, 0, ldeb, 0, IF_BFP)
- F(0xb305, LXDBR, RRE, Z, 0, f2_o, x1, 0, lxdb, 0, IF_BFP)
- F(0xb306, LXEBR, RRE, Z, 0, e2, x1, 0, lxeb, 0, IF_BFP)
- F(0xed04, LDEB, RXE, Z, 0, m2_32u, f1, 0, ldeb, 0, IF_BFP)
- F(0xed05, LXDB, RXE, Z, 0, m2_64, x1, 0, lxdb, 0, IF_BFP)
- F(0xed06, LXEB, RXE, Z, 0, m2_32u, x1, 0, lxeb, 0, IF_BFP)
+ F(0xb304, LDEBR, RRE, Z, 0, e2, new, f1, ldeb, 0, IF_BFP)
+ F(0xb305, LXDBR, RRE, Z, 0, f2, new_P, x1, lxdb, 0, IF_BFP)
+ F(0xb306, LXEBR, RRE, Z, 0, e2, new_P, x1, lxeb, 0, IF_BFP)
+ F(0xed04, LDEB, RXE, Z, 0, m2_32u, new, f1, ldeb, 0, IF_BFP)
+ F(0xed05, LXDB, RXE, Z, 0, m2_64, new_P, x1, lxdb, 0, IF_BFP)
+ F(0xed06, LXEB, RXE, Z, 0, m2_32u, new_P, x1, lxeb, 0, IF_BFP)
/* LOAD ROUNDED */
- F(0xb344, LEDBR, RRE, Z, 0, f2_o, new, e1, ledb, 0, IF_BFP)
- F(0xb345, LDXBR, RRE, Z, 0, x2_o, f1, 0, ldxb, 0, IF_BFP)
- F(0xb346, LEXBR, RRE, Z, 0, x2_o, new, e1, lexb, 0, IF_BFP)
+ F(0xb344, LEDBR, RRE, Z, 0, f2, new, e1, ledb, 0, IF_BFP)
+ F(0xb345, LDXBR, RRE, Z, x2h, x2l, new, f1, ldxb, 0, IF_BFP)
+ F(0xb346, LEXBR, RRE, Z, x2h, x2l, new, e1, lexb, 0, IF_BFP)
/* LOAD MULTIPLE */
C(0x9800, LM, RS_a, Z, 0, a2, 0, 0, lm32, 0)
C(0x5c00, M, RX_a, Z, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
C(0xe35c, MFY, RXY_a, GIE, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
F(0xb317, MEEBR, RRE, Z, e1, e2, new, e1, meeb, 0, IF_BFP)
- F(0xb31c, MDBR, RRE, Z, f1_o, f2_o, f1, 0, mdb, 0, IF_BFP)
- F(0xb34c, MXBR, RRE, Z, 0, x2_o, x1, 0, mxb, 0, IF_BFP)
- F(0xb30c, MDEBR, RRE, Z, f1_o, e2, f1, 0, mdeb, 0, IF_BFP)
- F(0xb307, MXDBR, RRE, Z, 0, f2_o, x1, 0, mxdb, 0, IF_BFP)
+ F(0xb31c, MDBR, RRE, Z, f1, f2, new, f1, mdb, 0, IF_BFP)
+ F(0xb34c, MXBR, RRE, Z, x2h, x2l, x1, x1, mxb, 0, IF_BFP)
+ F(0xb30c, MDEBR, RRE, Z, f1, e2, new, f1, mdeb, 0, IF_BFP)
+ F(0xb307, MXDBR, RRE, Z, 0, f2, x1, x1, mxdb, 0, IF_BFP)
F(0xed17, MEEB, RXE, Z, e1, m2_32u, new, e1, meeb, 0, IF_BFP)
- F(0xed1c, MDB, RXE, Z, f1_o, m2_64, f1, 0, mdb, 0, IF_BFP)
- F(0xed0c, MDEB, RXE, Z, f1_o, m2_32u, f1, 0, mdeb, 0, IF_BFP)
- F(0xed07, MXDB, RXE, Z, 0, m2_64, x1, 0, mxdb, 0, IF_BFP)
+ F(0xed1c, MDB, RXE, Z, f1, m2_64, new, f1, mdb, 0, IF_BFP)
+ F(0xed0c, MDEB, RXE, Z, f1, m2_32u, new, f1, mdeb, 0, IF_BFP)
+ F(0xed07, MXDB, RXE, Z, 0, m2_64, x1, x1, mxdb, 0, IF_BFP)
/* MULTIPLY HALFWORD */
C(0x4c00, MH, RX_a, Z, r1_o, m2_16s, new, r1_32, mul, 0)
C(0xe37c, MHY, RXY_a, GIE, r1_o, m2_16s, new, r1_32, mul, 0)
/* MULTIPLY AND ADD */
F(0xb30e, MAEBR, RRD, Z, e1, e2, new, e1, maeb, 0, IF_BFP)
- F(0xb31e, MADBR, RRD, Z, f1_o, f2_o, f1, 0, madb, 0, IF_BFP)
+ F(0xb31e, MADBR, RRD, Z, f1, f2, new, f1, madb, 0, IF_BFP)
F(0xed0e, MAEB, RXF, Z, e1, m2_32u, new, e1, maeb, 0, IF_BFP)
- F(0xed1e, MADB, RXF, Z, f1_o, m2_64, f1, 0, madb, 0, IF_BFP)
+ F(0xed1e, MADB, RXF, Z, f1, m2_64, new, f1, madb, 0, IF_BFP)
/* MULTIPLY AND SUBTRACT */
F(0xb30f, MSEBR, RRD, Z, e1, e2, new, e1, mseb, 0, IF_BFP)
- F(0xb31f, MSDBR, RRD, Z, f1_o, f2_o, f1, 0, msdb, 0, IF_BFP)
+ F(0xb31f, MSDBR, RRD, Z, f1, f2, new, f1, msdb, 0, IF_BFP)
F(0xed0f, MSEB, RXF, Z, e1, m2_32u, new, e1, mseb, 0, IF_BFP)
- F(0xed1f, MSDB, RXF, Z, f1_o, m2_64, f1, 0, msdb, 0, IF_BFP)
+ F(0xed1f, MSDB, RXF, Z, f1, m2_64, new, f1, msdb, 0, IF_BFP)
/* OR */
C(0x1600, OR, RR_a, Z, r1, r2, new, r1_32, or, nz32)
/* SQUARE ROOT */
F(0xb314, SQEBR, RRE, Z, 0, e2, new, e1, sqeb, 0, IF_BFP)
- F(0xb315, SQDBR, RRE, Z, 0, f2_o, f1, 0, sqdb, 0, IF_BFP)
- F(0xb316, SQXBR, RRE, Z, 0, x2_o, x1, 0, sqxb, 0, IF_BFP)
+ F(0xb315, SQDBR, RRE, Z, 0, f2, new, f1, sqdb, 0, IF_BFP)
+ F(0xb316, SQXBR, RRE, Z, x2h, x2l, new, x1, sqxb, 0, IF_BFP)
F(0xed14, SQEB, RXE, Z, 0, m2_32u, new, e1, sqeb, 0, IF_BFP)
- F(0xed15, SQDB, RXE, Z, 0, m2_64, f1, 0, sqdb, 0, IF_BFP)
+ F(0xed15, SQDB, RXE, Z, 0, m2_64, new, f1, sqdb, 0, IF_BFP)
/* STORE */
C(0x5000, ST, RX_a, Z, r1_o, a2, 0, 0, st32, 0)
C(0xe350, STY, RXY_a, LD, r1_o, a2, 0, 0, st32, 0)
C(0xe324, STG, RXY_a, Z, r1_o, a2, 0, 0, st64, 0)
- F(0x6000, STD, RX_a, Z, f1_o, a2, 0, 0, st64, 0, IF_AFP1)
- F(0xed67, STDY, RXY_a, LD, f1_o, a2, 0, 0, st64, 0, IF_AFP1)
+ F(0x6000, STD, RX_a, Z, f1, a2, 0, 0, st64, 0, IF_AFP1)
+ F(0xed67, STDY, RXY_a, LD, f1, a2, 0, 0, st64, 0, IF_AFP1)
F(0x7000, STE, RX_a, Z, e1, a2, 0, 0, st32, 0, IF_AFP1)
F(0xed66, STEY, RXY_a, LD, e1, a2, 0, 0, st32, 0, IF_AFP1)
/* STORE RELATIVE LONG */
C(0xe33e, STRV, RXY_a, Z, la2, r1_32u, new, m1_32, rev32, 0)
C(0xe32f, STRVG, RXY_a, Z, la2, r1_o, new, m1_64, rev64, 0)
+/* STORE CLOCK */
+ C(0xb205, STCK, S, Z, la2, 0, new, m1_64, stck, 0)
+ C(0xb27c, STCKF, S, SCF, la2, 0, new, m1_64, stck, 0)
+/* STORE CLOCK EXTENDED */
+ C(0xb278, STCKE, S, Z, 0, a2, 0, 0, stcke, 0)
+
/* STORE FACILITY LIST EXTENDED */
C(0xb2b0, STFLE, S, SFLE, 0, a2, 0, 0, stfle, 0)
/* STORE FPC */
C(0xe309, SG, RXY_a, Z, r1, m2_64, r1, 0, sub, subs64)
C(0xe319, SGF, RXY_a, Z, r1, m2_32s, r1, 0, sub, subs64)
F(0xb30b, SEBR, RRE, Z, e1, e2, new, e1, seb, f32, IF_BFP)
- F(0xb31b, SDBR, RRE, Z, f1_o, f2_o, f1, 0, sdb, f64, IF_BFP)
- F(0xb34b, SXBR, RRE, Z, 0, x2_o, x1, 0, sxb, f128, IF_BFP)
+ F(0xb31b, SDBR, RRE, Z, f1, f2, new, f1, sdb, f64, IF_BFP)
+ F(0xb34b, SXBR, RRE, Z, x2h, x2l, x1, x1, sxb, f128, IF_BFP)
F(0xed0b, SEB, RXE, Z, e1, m2_32u, new, e1, seb, f32, IF_BFP)
- F(0xed1b, SDB, RXE, Z, f1_o, m2_64, f1, 0, sdb, f64, IF_BFP)
+ F(0xed1b, SDB, RXE, Z, f1, m2_64, new, f1, sdb, f64, IF_BFP)
/* SUBTRACT HALFWORD */
C(0x4b00, SH, RX_a, Z, r1, m2_16s, new, r1_32, sub, subs32)
C(0xe37b, SHY, RXY_a, LD, r1, m2_16s, new, r1_32, sub, subs32)
/* TEST DATA CLASS */
F(0xed10, TCEB, RXE, Z, e1, a2, 0, 0, tceb, 0, IF_BFP)
- F(0xed11, TCDB, RXE, Z, f1_o, a2, 0, 0, tcdb, 0, IF_BFP)
- F(0xed12, TCXB, RXE, Z, x1_o, a2, 0, 0, tcxb, 0, IF_BFP)
+ F(0xed11, TCDB, RXE, Z, f1, a2, 0, 0, tcdb, 0, IF_BFP)
+ F(0xed12, TCXB, RXE, Z, 0, a2, x1, 0, tcxb, 0, IF_BFP)
/* TEST DECIMAL */
C(0xebc0, TP, RSL, E2, la1, 0, 0, 0, tp, 0)
F(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0, IF_PRIV)
/* SIGNAL PROCESSOR */
F(0xae00, SIGP, RS_a, Z, 0, a2, 0, 0, sigp, 0, IF_PRIV)
-/* STORE CLOCK */
- C(0xb205, STCK, S, Z, la2, 0, new, m1_64, stck, 0)
- C(0xb27c, STCKF, S, SCF, la2, 0, new, m1_64, stck, 0)
-/* STORE CLOCK EXTENDED */
- C(0xb278, STCKE, S, Z, 0, a2, 0, 0, stcke, 0)
/* STORE CLOCK COMPARATOR */
F(0xb207, STCKC, S, Z, la2, 0, new, m1_64a, stckc, 0, IF_PRIV)
/* STORE CONTROL */
* Copyright (c) 2009 Alexander Graf <agraf@suse.de>
* Copyright IBM Corp. 2012
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * This library is distributed in the hope that it will be useful,
+ * 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
- * Lesser General Public License for more details.
+ * General Public License for more details.
*
- * Contributions after 2012-10-29 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- *
- * You should have received a copy of the GNU (Lesser) General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "sysemu/device_tree.h"
#include "exec/gdbstub.h"
+#include "exec/ram_addr.h"
#include "trace.h"
#include "hw/s390x/s390-pci-inst.h"
#include "hw/s390x/s390-pci-bus.h"
static int kvm_s390_configure_mempath_backing(KVMState *s)
{
- size_t path_psize = qemu_mempath_getpagesize(mem_path);
+ size_t path_psize = qemu_getrampagesize();
if (path_psize == 4 * KiB) {
return 0;
{
MachineClass *mc = MACHINE_GET_CLASS(ms);
- if (mem_path && kvm_s390_configure_mempath_backing(s)) {
+ if (kvm_s390_configure_mempath_backing(s)) {
return -EINVAL;
}
.addr = sch,
.len = 8,
};
+ trace_kvm_assign_subch_ioeventfd(kick.fd, kick.addr, assign,
+ kick.datamatch);
if (!kvm_check_extension(kvm_state, KVM_CAP_IOEVENTFD)) {
return -ENOSYS;
}
}
/* We emulate a zPCI bus and AEN, therefore we don't need HW support */
- if (pci_available) {
- set_bit(S390_FEAT_ZPCI, model->features);
- }
+ set_bit(S390_FEAT_ZPCI, model->features);
set_bit(S390_FEAT_ADAPTER_EVENT_NOTIFICATION, model->features);
if (s390_known_cpu_type(cpu_type)) {
#include "exec/cpu_ldst.h"
#include "qapi/error.h"
#include "tcg_s390x.h"
+#include "s390-tod.h"
#if !defined(CONFIG_USER_ONLY)
#include "sysemu/cpus.h"
#endif
}
-#ifndef CONFIG_USER_ONLY
+/* Store Clock */
+uint64_t HELPER(stck)(CPUS390XState *env)
+{
+#ifdef CONFIG_USER_ONLY
+ struct timespec ts;
+ uint64_t ns;
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ns = ts.tv_sec * NANOSECONDS_PER_SECOND + ts.tv_nsec;
+
+ return TOD_UNIX_EPOCH + time2tod(ns);
+#else
+ S390TODState *td = s390_get_todstate();
+ S390TODClass *tdc = S390_TOD_GET_CLASS(td);
+ S390TOD tod;
+ tdc->get(td, &tod, &error_abort);
+ return tod.low;
+#endif
+}
+
+#ifndef CONFIG_USER_ONLY
/* SCLP service call */
uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2)
{
tlb_flush_page(cs, TARGET_PAGE_SIZE);
}
-/* Store Clock */
-uint64_t HELPER(stck)(CPUS390XState *env)
-{
- S390TODState *td = s390_get_todstate();
- S390TODClass *tdc = S390_TOD_GET_CLASS(td);
- S390TOD tod;
-
- tdc->get(td, &tod, &error_abort);
- return tod.low;
-}
-
static void update_ckc_timer(CPUS390XState *env)
{
S390TODState *td = s390_get_todstate();
--- /dev/null
+/*
+ * TOD (Time Of Day) clock
+ *
+ * Copyright 2018 Red Hat, Inc.
+ * Author(s): David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef TARGET_S390_TOD_H
+#define TARGET_S390_TOD_H
+
+/* The value of the TOD clock for 1.1.1970. */
+#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
+
+/* Converts ns to s390's clock format */
+static inline uint64_t time2tod(uint64_t ns)
+{
+ return (ns << 9) / 125 + (((ns & 0xff80000000000000ull) / 125) << 9);
+}
+
+/* Converts s390's clock format to ns */
+static inline uint64_t tod2time(uint64_t t)
+{
+ return ((t >> 9) * 125) + (((t & 0x1ff) * 125) >> 9);
+}
+
+#endif
kvm_enable_cmma(int rc) "CMMA: enabling with result code %d"
kvm_clear_cmma(int rc) "CMMA: clearing with result code %d"
kvm_failed_cpu_state_set(int cpu_index, uint8_t state, const char *msg) "Warning: Unable to set cpu %d state %" PRIu8 " to KVM: %s"
+kvm_assign_subch_ioeventfd(int fd, uint32_t addr, bool assign, int datamatch) "fd: %d sch: @0x%x assign: %d vq: %d"
# target/s390x/cpu.c
cpu_set_state(int cpu_index, uint8_t state) "setting cpu %d state to %" PRIu8
static TCGv_i64 cc_dst;
static TCGv_i64 cc_vr;
-static char cpu_reg_names[32][4];
+static char cpu_reg_names[16][4];
static TCGv_i64 regs[16];
-static TCGv_i64 fregs[16];
void s390x_translate_init(void)
{
offsetof(CPUS390XState, regs[i]),
cpu_reg_names[i]);
}
+}
- for (i = 0; i < 16; i++) {
- snprintf(cpu_reg_names[i + 16], sizeof(cpu_reg_names[0]), "f%d", i);
- fregs[i] = tcg_global_mem_new(cpu_env,
- offsetof(CPUS390XState, vregs[i][0].d),
- cpu_reg_names[i + 16]);
- }
+static inline int vec_reg_offset(uint8_t reg, uint8_t enr, TCGMemOp size)
+{
+ const uint8_t es = 1 << size;
+ int offs = enr * es;
+
+ g_assert(reg < 32);
+ /*
+ * vregs[n][0] is the lowest 8 byte and vregs[n][1] the highest 8 byte
+ * of the 16 byte vector, on both, little and big endian systems.
+ *
+ * Big Endian (target/possible host)
+ * B: [ 0][ 1][ 2][ 3][ 4][ 5][ 6][ 7] - [ 8][ 9][10][11][12][13][14][15]
+ * HW: [ 0][ 1][ 2][ 3] - [ 4][ 5][ 6][ 7]
+ * W: [ 0][ 1] - [ 2][ 3]
+ * DW: [ 0] - [ 1]
+ *
+ * Little Endian (possible host)
+ * B: [ 7][ 6][ 5][ 4][ 3][ 2][ 1][ 0] - [15][14][13][12][11][10][ 9][ 8]
+ * HW: [ 3][ 2][ 1][ 0] - [ 7][ 6][ 5][ 4]
+ * W: [ 1][ 0] - [ 3][ 2]
+ * DW: [ 0] - [ 1]
+ *
+ * For 16 byte elements, the two 8 byte halves will not form a host
+ * int128 if the host is little endian, since they're in the wrong order.
+ * Some operations (e.g. xor) do not care. For operations like addition,
+ * the two 8 byte elements have to be loaded separately. Let's force all
+ * 16 byte operations to handle it in a special way.
+ */
+ g_assert(size <= MO_64);
+#ifndef HOST_WORDS_BIGENDIAN
+ offs ^= (8 - es);
+#endif
+ return offs + offsetof(CPUS390XState, vregs[reg][0].d);
+}
+
+static inline int freg64_offset(uint8_t reg)
+{
+ g_assert(reg < 16);
+ return vec_reg_offset(reg, 0, MO_64);
+}
+
+static inline int freg32_offset(uint8_t reg)
+{
+ g_assert(reg < 16);
+ return vec_reg_offset(reg, 0, MO_32);
}
static TCGv_i64 load_reg(int reg)
return r;
}
+static TCGv_i64 load_freg(int reg)
+{
+ TCGv_i64 r = tcg_temp_new_i64();
+
+ tcg_gen_ld_i64(r, cpu_env, freg64_offset(reg));
+ return r;
+}
+
static TCGv_i64 load_freg32_i64(int reg)
{
TCGv_i64 r = tcg_temp_new_i64();
- tcg_gen_shri_i64(r, fregs[reg], 32);
+
+ tcg_gen_ld32u_i64(r, cpu_env, freg32_offset(reg));
return r;
}
static void store_freg(int reg, TCGv_i64 v)
{
- tcg_gen_mov_i64(fregs[reg], v);
+ tcg_gen_st_i64(v, cpu_env, freg64_offset(reg));
}
static void store_reg32_i64(int reg, TCGv_i64 v)
static void store_freg32_i64(int reg, TCGv_i64 v)
{
- tcg_gen_deposit_i64(fregs[reg], fregs[reg], v, 32, 32);
+ tcg_gen_st32_i64(v, cpu_env, freg32_offset(reg));
}
static void return_low128(TCGv_i64 dest)
static DisasJumpType op_madb(DisasContext *s, DisasOps *o)
{
- int r3 = get_field(s->fields, r3);
- gen_helper_madb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
+ TCGv_i64 r3 = load_freg(get_field(s->fields, r3));
+ gen_helper_madb(o->out, cpu_env, o->in1, o->in2, r3);
+ tcg_temp_free_i64(r3);
return DISAS_NEXT;
}
static DisasJumpType op_msdb(DisasContext *s, DisasOps *o)
{
- int r3 = get_field(s->fields, r3);
- gen_helper_msdb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
+ TCGv_i64 r3 = load_freg(get_field(s->fields, r3));
+ gen_helper_msdb(o->out, cpu_env, o->in1, o->in2, r3);
+ tcg_temp_free_i64(r3);
return DISAS_NEXT;
}
tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, core_id));
return DISAS_NEXT;
}
+#endif
static DisasJumpType op_stck(DisasContext *s, DisasOps *o)
{
return DISAS_NEXT;
}
+#ifndef CONFIG_USER_ONLY
static DisasJumpType op_sck(DisasContext *s, DisasOps *o)
{
tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TEQ | MO_ALIGN);
}
#define SPEC_prep_r1_P SPEC_r1_even
-static void prep_f1(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->out = fregs[get_field(f, r1)];
- o->g_out = true;
-}
-#define SPEC_prep_f1 0
-
+/* Whenever we need x1 in addition to other inputs, we'll load it to out/out2 */
static void prep_x1(DisasContext *s, DisasFields *f, DisasOps *o)
{
- int r1 = get_field(f, r1);
- o->out = fregs[r1];
- o->out2 = fregs[r1 + 2];
- o->g_out = o->g_out2 = true;
+ o->out = load_freg(get_field(f, r1));
+ o->out2 = load_freg(get_field(f, r1) + 2);
}
#define SPEC_prep_x1 SPEC_r1_f128
}
#define SPEC_in1_e1 0
-static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
+static void in1_f1(DisasContext *s, DisasFields *f, DisasOps *o)
{
- o->in1 = fregs[get_field(f, r1)];
- o->g_in1 = true;
+ o->in1 = load_freg(get_field(f, r1));
}
-#define SPEC_in1_f1_o 0
+#define SPEC_in1_f1 0
-static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o)
+/* Load the high double word of an extended (128-bit) format FP number */
+static void in1_x2h(DisasContext *s, DisasFields *f, DisasOps *o)
{
- int r1 = get_field(f, r1);
- o->out = fregs[r1];
- o->out2 = fregs[r1 + 2];
- o->g_out = o->g_out2 = true;
+ o->in1 = load_freg(get_field(f, r2));
}
-#define SPEC_in1_x1_o SPEC_r1_f128
+#define SPEC_in1_x2h SPEC_r2_f128
-static void in1_f3_o(DisasContext *s, DisasFields *f, DisasOps *o)
+static void in1_f3(DisasContext *s, DisasFields *f, DisasOps *o)
{
- o->in1 = fregs[get_field(f, r3)];
- o->g_in1 = true;
+ o->in1 = load_freg(get_field(f, r3));
}
-#define SPEC_in1_f3_o 0
+#define SPEC_in1_f3 0
static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
{
}
#define SPEC_in2_e2 0
-static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
+static void in2_f2(DisasContext *s, DisasFields *f, DisasOps *o)
{
- o->in2 = fregs[get_field(f, r2)];
- o->g_in2 = true;
+ o->in2 = load_freg(get_field(f, r2));
}
-#define SPEC_in2_f2_o 0
+#define SPEC_in2_f2 0
-static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
+/* Load the low double word of an extended (128-bit) format FP number */
+static void in2_x2l(DisasContext *s, DisasFields *f, DisasOps *o)
{
- int r2 = get_field(f, r2);
- o->in1 = fregs[r2];
- o->in2 = fregs[r2 + 2];
- o->g_in1 = o->g_in2 = true;
+ o->in2 = load_freg(get_field(f, r2) + 2);
}
-#define SPEC_in2_x2_o SPEC_r2_f128
+#define SPEC_in2_x2l SPEC_r2_f128
static void in2_ra2(DisasContext *s, DisasFields *f, DisasOps *o)
{
+++ /dev/null
-- Add new instructions such as: clz, ctz, popcnt.
-
-- See if it is worth exporting mul2, mulu2, div2, divu2.
-
-- Support of globals saved in fixed registers between TBs.
-
-Ideas:
-
-- Move the slow part of the qemu_ld/st ops after the end of the TB.
-
-- Change exception syntax to get closer to QOP system (exception
- parameters given with a specific instruction).
-
-- Add float and vector support.
OPC_PADDSB, OPC_PADDSW, OPC_UD2, OPC_UD2
};
static int const usadd_insn[4] = {
- OPC_PADDSB, OPC_PADDSW, OPC_UD2, OPC_UD2
+ OPC_PADDUB, OPC_PADDUW, OPC_UD2, OPC_UD2
};
static int const sub_insn[4] = {
OPC_PSUBB, OPC_PSUBW, OPC_PSUBD, OPC_PSUBQ
OPC_PSUBSB, OPC_PSUBSW, OPC_UD2, OPC_UD2
};
static int const ussub_insn[4] = {
- OPC_PSUBSB, OPC_PSUBSW, OPC_UD2, OPC_UD2
+ OPC_PSUBUB, OPC_PSUBUW, OPC_UD2, OPC_UD2
};
static int const mul_insn[4] = {
OPC_UD2, OPC_PMULLW, OPC_PMULLD, OPC_UD2
static inline void gen_set_label(TCGLabel *l)
{
+ l->present = 1;
tcg_gen_op1(INDEX_op_set_label, label_arg(l));
}
*l = (TCGLabel){
.id = s->nb_labels++
};
+#ifdef CONFIG_DEBUG_TCG
+ QSIMPLEQ_INSERT_TAIL(&s->labels, l, next);
+#endif
return l;
}
QTAILQ_INIT(&s->ops);
QTAILQ_INIT(&s->free_ops);
+#ifdef CONFIG_DEBUG_TCG
+ QSIMPLEQ_INIT(&s->labels);
+#endif
}
static inline TCGTemp *tcg_temp_alloc(TCGContext *s)
}
#endif
+#ifdef CONFIG_DEBUG_TCG
+ /* Ensure all labels referenced have been emitted. */
+ {
+ TCGLabel *l;
+ bool error = false;
+
+ QSIMPLEQ_FOREACH(l, &s->labels, next) {
+ if (unlikely(!l->present) && l->refs) {
+ qemu_log_mask(CPU_LOG_TB_OP,
+ "$L%d referenced but not present.\n", l->id);
+ error = true;
+ }
+ }
+ assert(!error);
+ }
+#endif
+
#ifdef CONFIG_PROFILER
atomic_set(&prof->opt_time, prof->opt_time - profile_getclock());
#endif
intptr_t addend;
} TCGRelocation;
-typedef struct TCGLabel {
+typedef struct TCGLabel TCGLabel;
+struct TCGLabel {
+ unsigned present : 1;
unsigned has_value : 1;
- unsigned id : 15;
+ unsigned id : 14;
unsigned refs : 16;
union {
uintptr_t value;
tcg_insn_unit *value_ptr;
TCGRelocation *first_reloc;
} u;
-} TCGLabel;
+#ifdef CONFIG_DEBUG_TCG
+ QSIMPLEQ_ENTRY(TCGLabel) next;
+#endif
+};
typedef struct TCGPool {
struct TCGPool *next;
#endif
#ifdef CONFIG_DEBUG_TCG
+ QSIMPLEQ_HEAD(, TCGLabel) labels;
int temps_in_use;
int goto_tb_issue_mask;
#endif
check-*
!check-*.c
!check-*.sh
+fp/*.out
qht-bench
rcutorture
test-*
check-unit-y += tests/test-thread-pool$(EXESUF)
check-unit-y += tests/test-hbitmap$(EXESUF)
check-unit-y += tests/test-bdrv-drain$(EXESUF)
+check-unit-y += tests/test-bdrv-graph-mod$(EXESUF)
check-unit-y += tests/test-blockjob$(EXESUF)
check-unit-y += tests/test-blockjob-txn$(EXESUF)
check-unit-y += tests/test-block-backend$(EXESUF)
check-unit-$(land,$(CONFIG_LINUX),$(CONFIG_VIRTIO_SERIAL)) += tests/test-qga$(EXESUF)
endif
check-unit-y += tests/test-timed-average$(EXESUF)
+check-unit-$(CONFIG_INOTIFY1) += tests/test-util-filemonitor$(EXESUF)
check-unit-y += tests/test-util-sockets$(EXESUF)
+check-unit-y += tests/test-authz-simple$(EXESUF)
+check-unit-y += tests/test-authz-list$(EXESUF)
+check-unit-y += tests/test-authz-listfile$(EXESUF)
+check-unit-$(CONFIG_AUTH_PAM) += tests/test-authz-pam$(EXESUF)
check-unit-y += tests/test-io-task$(EXESUF)
check-unit-y += tests/test-io-channel-socket$(EXESUF)
check-unit-y += tests/test-io-channel-file$(EXESUF)
# check-qtest-i386-$(CONFIG_ISA_IPMI_BT) += tests/ipmi-bt-test$(EXESUF)
check-qtest-i386-y += tests/i440fx-test$(EXESUF)
check-qtest-i386-y += tests/fw_cfg-test$(EXESUF)
+check-qtest-i386-y += tests/device-plug-test$(EXESUF)
check-qtest-i386-y += tests/drive_del-test$(EXESUF)
check-qtest-i386-$(CONFIG_WDT_IB700) += tests/wdt_ib700-test$(EXESUF)
check-qtest-i386-y += tests/tco-test$(EXESUF)
check-qtest-ppc64-y += $(check-qtest-ppc-y)
check-qtest-ppc64-$(CONFIG_PSERIES) += tests/spapr-phb-test$(EXESUF)
+check-qtest-ppc64-$(CONFIG_PSERIES) += tests/device-plug-test$(EXESUF)
check-qtest-ppc64-$(CONFIG_POWERNV) += tests/pnv-xscom-test$(EXESUF)
check-qtest-ppc64-y += tests/migration-test$(EXESUF)
check-qtest-ppc64-$(CONFIG_PSERIES) += tests/rtas-test$(EXESUF)
check-qtest-s390x-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF)
check-qtest-s390x-$(CONFIG_POSIX) += tests/test-filter-redirector$(EXESUF)
check-qtest-s390x-y += tests/drive_del-test$(EXESUF)
+check-qtest-s390x-y += tests/device-plug-test$(EXESUF)
check-qtest-s390x-y += tests/virtio-ccw-test$(EXESUF)
check-qtest-s390x-y += tests/cpu-plug-test$(EXESUF)
check-qtest-s390x-y += tests/migration-test$(EXESUF)
test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
tests/test-qapi-introspect.o \
$(test-qom-obj-y)
-benchmark-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
-test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
+benchmark-crypto-obj-y = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y)
+test-crypto-obj-y = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y)
test-io-obj-y = $(io-obj-y) $(test-crypto-obj-y)
+test-authz-obj-y = $(test-qom-obj-y) $(authz-obj-y)
test-block-obj-y = $(block-obj-y) $(test-io-obj-y) tests/iothread.o
tests/check-qnum$(EXESUF): tests/check-qnum.o $(test-util-obj-y)
tests/test-aio-multithread$(EXESUF): tests/test-aio-multithread.o $(test-block-obj-y)
tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(test-util-obj-y)
+tests/test-bdrv-graph-mod$(EXESUF): tests/test-bdrv-graph-mod.o $(test-block-obj-y) $(test-util-obj-y)
tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y)
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y)
tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o \
tests/crypto-tls-psk-helpers.o \
$(test-crypto-obj-y)
+tests/test-util-filemonitor$(EXESUF): tests/test-util-filemonitor.o \
+ $(test-util-obj-y)
tests/test-util-sockets$(EXESUF): tests/test-util-sockets.o \
tests/socket-helpers.o $(test-util-obj-y)
+tests/test-authz-simple$(EXESUF): tests/test-authz-simple.o $(test-authz-obj-y)
+tests/test-authz-list$(EXESUF): tests/test-authz-list.o $(test-authz-obj-y)
+tests/test-authz-listfile$(EXESUF): tests/test-authz-listfile.o $(test-authz-obj-y)
+tests/test-authz-pam$(EXESUF): tests/test-authz-pam.o $(test-authz-obj-y)
tests/test-io-task$(EXESUF): tests/test-io-task.o $(test-io-obj-y)
tests/test-io-channel-socket$(EXESUF): tests/test-io-channel-socket.o \
tests/io-channel-helpers.o tests/socket-helpers.o $(test-io-obj-y)
tests/qom-test$(EXESUF): tests/qom-test.o
tests/test-hmp$(EXESUF): tests/test-hmp.o
tests/machine-none-test$(EXESUF): tests/machine-none-test.o
+tests/device-plug-test$(EXESUF): tests/device-plug-test.o
tests/drive_del-test$(EXESUF): tests/drive_del-test.o $(libqos-virtio-obj-y)
tests/nvme-test$(EXESUF): tests/nvme-test.o $(libqos-pc-obj-y)
tests/pvpanic-test$(EXESUF): tests/pvpanic-test.o
rm $(INITRD_WORK_DIR)/init
rmdir $(INITRD_WORK_DIR)
-ifeq ($(CONFIG_POSIX),y)
-LIBS += -lutil
-endif
-
# QTest rules
TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGET_DIRS)))
"BUILD", "$(notdir $@)")
# The full test suite can take a bit of time, default to a quick run
-ifeq ($(SPEED), quick)
-FP_TL=-l 1
-else
-FP_TL=-l 2 -r all
-endif
+# "-l 2 -r all" can take more than a day for some operations and is best
+# run manually
+FP_TL=-l 1 -r all
-# $1 = tests, $2 = description
+# $1 = tests, $2 = description, $3 = test flags
test-softfloat = $(call quiet-command, \
cd $(BUILD_DIR)/tests/fp && \
- ./fp-test -s $(FP_TL) $1 > $2.out 2>&1 || \
+ ./fp-test -s $(if $3,$3,$(FP_TL)) $1 > $2.out 2>&1 || \
(cat $2.out && exit 1;), \
"FLOAT TEST", $2)
# Conversion Routines:
# FIXME: i32_to_extF80 (broken), i64_to_extF80 (broken)
-# ui32_to_f128 (not implemented), f128_to_ui32 (not implemented)
-# extF80_roundToInt (broken)
+# ui32_to_f128 (not implemented), extF80_roundToInt (broken)
#
check-softfloat-conv: $(FP_TEST_BIN)
$(call test-softfloat, \
f16_to_ui32 f16_to_ui32_r_minMag \
f32_to_ui32 f32_to_ui32_r_minMag \
f64_to_ui32 f64_to_ui32_r_minMag \
+ f128_to_ui32 f128_to_ui32_r_minMag \
f16_to_ui64 f16_to_ui64_r_minMag \
f32_to_ui64 f32_to_ui64_r_minMag \
- f64_to_ui64 f64_to_ui64_r_minMag, \
+ f64_to_ui64 f64_to_ui64_r_minMag \
+ f128_to_ui64 f128_to_ui64_r_minMag, \
float-to-uint)
$(call test-softfloat, \
f16_roundToInt f32_roundToInt \
check-softfloat-mulAdd: $(FP_TEST_BIN)
$(call test-softfloat, \
f16_mulAdd f32_mulAdd f64_mulAdd f128_mulAdd, \
- mulAdd)
+ mulAdd,-l 1)
# FIXME: extF80_rem (broken)
check-softfloat-rem: $(FP_TEST_BIN)
qtest_add_data_func("cdrom/boot/virtio-scsi",
"-device virtio-scsi -device scsi-cd,drive=cdr "
"-blockdev file,node-name=cdr,filename=", test_cdboot);
- qtest_add_data_func("cdrom/boot/isapc", "-M isapc "
- "-drive if=ide,media=cdrom,file=", test_cdboot);
+ /*
+ * Unstable CI test under load
+ * See https://lists.gnu.org/archive/html/qemu-devel/2019-02/msg05509.html
+ */
+ if (g_test_slow()) {
+ qtest_add_data_func("cdrom/boot/isapc", "-M isapc "
+ "-drive if=ide,media=cdrom,file=", test_cdboot);
+ }
qtest_add_data_func("cdrom/boot/am53c974",
"-device am53c974 -device scsi-cd,drive=cd1 "
"-drive if=none,id=cd1,format=raw,file=", test_cdboot);
--- /dev/null
+/*
+ * QEMU device plug/unplug handling
+ *
+ * Copyright (C) 2019 Red Hat Inc.
+ *
+ * Authors:
+ * David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qstring.h"
+
+static void device_del_start(QTestState *qtest, const char *id)
+{
+ qtest_qmp_send(qtest,
+ "{'execute': 'device_del', 'arguments': { 'id': %s } }", id);
+}
+
+static void device_del_finish(QTestState *qtest)
+{
+ QDict *resp = qtest_qmp_receive(qtest);
+
+ g_assert(qdict_haskey(resp, "return"));
+ qobject_unref(resp);
+}
+
+static void device_del_request(QTestState *qtest, const char *id)
+{
+ device_del_start(qtest, id);
+ device_del_finish(qtest);
+}
+
+static void system_reset(QTestState *qtest)
+{
+ QDict *resp;
+
+ resp = qtest_qmp(qtest, "{'execute': 'system_reset'}");
+ g_assert(qdict_haskey(resp, "return"));
+ qobject_unref(resp);
+}
+
+static void wait_device_deleted_event(QTestState *qtest, const char *id)
+{
+ QDict *resp, *data;
+ QString *qstr;
+
+ /*
+ * Other devices might get removed along with the removed device. Skip
+ * these. The device of interest will be the last one.
+ */
+ for (;;) {
+ resp = qtest_qmp_eventwait_ref(qtest, "DEVICE_DELETED");
+ data = qdict_get_qdict(resp, "data");
+ if (!data || !qdict_get(data, "device")) {
+ qobject_unref(resp);
+ continue;
+ }
+ qstr = qobject_to(QString, qdict_get(data, "device"));
+ g_assert(qstr);
+ if (!strcmp(qstring_get_str(qstr), id)) {
+ qobject_unref(resp);
+ break;
+ }
+ qobject_unref(resp);
+ }
+}
+
+static void test_pci_unplug_request(void)
+{
+ QTestState *qtest = qtest_initf("-device virtio-mouse-pci,id=dev0");
+
+ /*
+ * Request device removal. As the guest is not running, the request won't
+ * be processed. However during system reset, the removal will be
+ * handled, removing the device.
+ */
+ device_del_request(qtest, "dev0");
+ system_reset(qtest);
+ wait_device_deleted_event(qtest, "dev0");
+
+ qtest_quit(qtest);
+}
+
+static void test_ccw_unplug(void)
+{
+ QTestState *qtest = qtest_initf("-device virtio-balloon-ccw,id=dev0");
+
+ /*
+ * The DEVICE_DELETED events will be sent before the command
+ * completes.
+ */
+ device_del_start(qtest, "dev0");
+ wait_device_deleted_event(qtest, "dev0");
+ device_del_finish(qtest);
+
+ qtest_quit(qtest);
+}
+
+static void test_spapr_cpu_unplug_request(void)
+{
+ QTestState *qtest;
+
+ qtest = qtest_initf("-cpu power9_v2.0 -smp 1,maxcpus=2 "
+ "-device power9_v2.0-spapr-cpu-core,core-id=1,id=dev0");
+
+ /* similar to test_pci_unplug_request */
+ device_del_request(qtest, "dev0");
+ system_reset(qtest);
+ wait_device_deleted_event(qtest, "dev0");
+
+ qtest_quit(qtest);
+}
+
+static void test_spapr_memory_unplug_request(void)
+{
+ QTestState *qtest;
+
+ qtest = qtest_initf("-m 256M,slots=1,maxmem=768M "
+ "-object memory-backend-ram,id=mem0,size=512M "
+ "-device pc-dimm,id=dev0,memdev=mem0");
+
+ /* similar to test_pci_unplug_request */
+ device_del_request(qtest, "dev0");
+ system_reset(qtest);
+ wait_device_deleted_event(qtest, "dev0");
+
+ qtest_quit(qtest);
+}
+
+static void test_spapr_phb_unplug_request(void)
+{
+ QTestState *qtest;
+
+ qtest = qtest_initf("-device spapr-pci-host-bridge,index=1,id=dev0");
+
+ /* similar to test_pci_unplug_request */
+ device_del_request(qtest, "dev0");
+ system_reset(qtest);
+ wait_device_deleted_event(qtest, "dev0");
+
+ qtest_quit(qtest);
+}
+
+int main(int argc, char **argv)
+{
+ const char *arch = qtest_get_arch();
+
+ g_test_init(&argc, &argv, NULL);
+
+ /*
+ * We need a system that will process unplug requests during system resets
+ * and does not do PCI surprise removal. This holds for x86 ACPI,
+ * s390x and spapr.
+ */
+ qtest_add_func("/device-plug/pci-unplug-request",
+ test_pci_unplug_request);
+
+ if (!strcmp(arch, "s390x")) {
+ qtest_add_func("/device-plug/ccw-unplug",
+ test_ccw_unplug);
+ }
+
+ if (!strcmp(arch, "ppc64")) {
+ qtest_add_func("/device-plug/spapr-cpu-unplug-request",
+ test_spapr_cpu_unplug_request);
+ qtest_add_func("/device-plug/spapr-memory-unplug-request",
+ test_spapr_memory_unplug_request);
+ qtest_add_func("/device-plug/spapr-phb-unplug-request",
+ test_spapr_phb_unplug_request);
+ }
+
+ return g_test_run();
+}
docker-image-debian-armel-cross: docker-image-debian9
docker-image-debian-armhf-cross: docker-image-debian9
docker-image-debian-arm64-cross: docker-image-debian9
+docker-image-debian-buster-arm64-cross: docker-image-debian10
docker-image-debian-mips-cross: docker-image-debian9
docker-image-debian-mipsel-cross: docker-image-debian9
docker-image-debian-mips64el-cross: docker-image-debian9
from io import StringIO
from shutil import copy, rmtree
from pwd import getpwuid
-from datetime import datetime,timedelta
+from datetime import datetime, timedelta
FILTERED_ENV_NAMES = ['ftp_proxy', 'http_proxy', 'https_proxy']
"""Calculate a digest string unique to the text content"""
return hashlib.sha1(text).hexdigest()
+
def _file_checksum(filename):
return _text_checksum(open(filename, 'rb').read())
+
def _guess_docker_command():
""" Guess a working docker command or raise exception if not found"""
commands = [["docker"], ["sudo", "-n", "docker"]]
except OSError:
pass
commands_txt = "\n".join([" " + " ".join(x) for x in commands])
- raise Exception("Cannot find working docker command. Tried:\n%s" % \
+ raise Exception("Cannot find working docker command. Tried:\n%s" %
commands_txt)
+
def _copy_with_mkdir(src, root_dir, sub_path='.'):
"""Copy src into root_dir, creating sub_path as needed."""
dest_dir = os.path.normpath("%s/%s" % (root_dir, sub_path))
return libs
-def _copy_binary_with_libs(src, dest_dir):
- """Copy a binary executable and all its dependent libraries.
+
+def _copy_binary_with_libs(src, bin_dest, dest_dir):
+ """Maybe copy a binary and all its dependent libraries.
+
+ If bin_dest isn't set we only copy the support libraries because
+ we don't need qemu in the docker path to run (due to persistent
+ mapping). Indeed users may get confused if we aren't running what
+ is in the image.
This does rely on the host file-system being fairly multi-arch
- aware so the file don't clash with the guests layout."""
+ aware so the file don't clash with the guests layout.
+ """
- _copy_with_mkdir(src, dest_dir, "/usr/bin")
+ if bin_dest:
+ _copy_with_mkdir(src, dest_dir, os.path.dirname(bin_dest))
+ else:
+ print("only copying support libraries for %s" % (src))
libs = _get_so_libs(src)
if libs:
for l in libs:
so_path = os.path.dirname(l)
- _copy_with_mkdir(l , dest_dir, so_path)
+ _copy_with_mkdir(l, dest_dir, so_path)
def _check_binfmt_misc(executable):
The details of setting up binfmt_misc are outside the scope of
this script but we should at least fail early with a useful
- message if it won't work."""
+ message if it won't work.
+
+ Returns the configured binfmt path and a valid flag. For
+ persistent configurations we will still want to copy and dependent
+ libraries.
+ """
binary = os.path.basename(executable)
binfmt_entry = "/proc/sys/fs/binfmt_misc/%s" % (binary)
if not os.path.exists(binfmt_entry):
print ("No binfmt_misc entry for %s" % (binary))
- return False
+ return None, False
with open(binfmt_entry) as x: entry = x.read()
- qpath = "/usr/bin/%s" % (binary)
- if not re.search("interpreter %s\n" % (qpath), entry):
- print ("binfmt_misc for %s does not point to %s" % (binary, qpath))
- return False
+ if re.search("flags:.*F.*\n", entry):
+ print("binfmt_misc for %s uses persistent(F) mapping to host binary" %
+ (binary))
+ return None, True
- return True
+ m = re.search("interpreter (\S+)\n", entry)
+ interp = m.group(1)
+ if interp and interp != executable:
+ print("binfmt_misc for %s does not point to %s, using %s" %
+ (binary, executable, interp))
+
+ return interp, True
def _read_qemu_dockerfile(img_name):
img_name + ".docker")
return open(df, "r").read()
+
def _dockerfile_preprocess(df):
out = ""
for l in df.splitlines():
out += l + "\n"
return out
+
class Docker(object):
""" Running Docker commands """
def __init__(self):
def build_image(self, tag, docker_dir, dockerfile,
quiet=True, user=False, argv=None, extra_files_cksum=[]):
- if argv == None:
+ if argv is None:
argv = []
tmp_df = tempfile.NamedTemporaryFile(dir=docker_dir, suffix=".docker")
tmp_df.flush()
- self._do_check(["build", "-t", tag, "-f", tmp_df.name] + argv + \
+ self._do_check(["build", "-t", tag, "-f", tmp_df.name] + argv +
[docker_dir],
quiet=quiet)
def command(self, cmd, argv, quiet):
return self._do([cmd] + argv, quiet=quiet)
+
class SubCommand(object):
"""A SubCommand template base class"""
- name = None # Subcommand name
+ name = None # Subcommand name
+
def shared_args(self, parser):
parser.add_argument("--quiet", action="store_true",
help="Run quietly unless an error occurred")
def args(self, parser):
"""Setup argument parser"""
pass
+
def run(self, args, argv):
"""Run command.
args: parsed argument by argument parser.
"""
pass
+
class RunCommand(SubCommand):
"""Invoke docker run and take care of cleaning up"""
name = "run"
+
def args(self, parser):
parser.add_argument("--keep", action="store_true",
help="Don't remove image when command completes")
+
def run(self, args, argv):
return Docker().run(argv, args.keep, quiet=args.quiet)
+
class BuildCommand(SubCommand):
- """ Build docker image out of a dockerfile. Arguments: <tag> <dockerfile>"""
+ """ Build docker image out of a dockerfile. Arg: <tag> <dockerfile>"""
name = "build"
+
def args(self, parser):
parser.add_argument("--include-executable", "-e",
help="""Specify a binary that will be copied to the
# Validate binfmt_misc will work
if args.include_executable:
- if not _check_binfmt_misc(args.include_executable):
+ qpath, enabled = _check_binfmt_misc(args.include_executable)
+ if not enabled:
return 1
# Is there a .pre file to run in the build context?
# FIXME: there is no checksum of this executable and the linked
# libraries, once the image built any change of this executable
# or any library won't trigger another build.
- _copy_binary_with_libs(args.include_executable, docker_dir)
+ _copy_binary_with_libs(args.include_executable,
+ qpath, docker_dir)
+
for filename in args.extra_files or []:
_copy_with_mkdir(filename, docker_dir)
cksum += [(filename, _file_checksum(filename))]
argv += ["--build-arg=" + k.lower() + "=" + v
- for k, v in os.environ.iteritems()
- if k.lower() in FILTERED_ENV_NAMES]
+ for k, v in os.environ.iteritems()
+ if k.lower() in FILTERED_ENV_NAMES]
dkr.build_image(tag, docker_dir, dockerfile,
quiet=args.quiet, user=args.user, argv=argv,
extra_files_cksum=cksum)
return 0
+
class UpdateCommand(SubCommand):
- """ Update a docker image with new executables. Arguments: <tag> <executable>"""
+ """ Update a docker image with new executables. Args: <tag> <executable>"""
name = "update"
+
def args(self, parser):
parser.add_argument("tag",
help="Image Tag")
tmp = tempfile.NamedTemporaryFile(suffix="dckr.tar.gz")
tmp_tar = TarFile(fileobj=tmp, mode='w')
- # Add the executable to the tarball
- bn = os.path.basename(args.executable)
- ff = "/usr/bin/%s" % bn
- tmp_tar.add(args.executable, arcname=ff)
+ # Add the executable to the tarball, using the current
+ # configured binfmt_misc path. If we don't get a path then we
+ # only need the support libraries copied
+ ff, enabled = _check_binfmt_misc(args.executable)
+
+ if not enabled:
+ print("binfmt_misc not enabled, update disabled")
+ return 1
+
+ if ff:
+ tmp_tar.add(args.executable, arcname=ff)
# Add any associated libraries
libs = _get_so_libs(args.executable)
return 0
+
class CleanCommand(SubCommand):
"""Clean up docker instances"""
name = "clean"
+
def run(self, args, argv):
Docker().clean()
return 0
+
class ImagesCommand(SubCommand):
"""Run "docker images" command"""
name = "images"
+
def run(self, args, argv):
return Docker().command("images", argv, args.quiet)
try:
dkr = Docker()
- except:
+ except subprocess.CalledProcessError:
print("Docker not set up")
return 1
def main():
parser = argparse.ArgumentParser(description="A Docker helper",
- usage="%s <subcommand> ..." % os.path.basename(sys.argv[0]))
+ usage="%s <subcommand> ..." %
+ os.path.basename(sys.argv[0]))
subparsers = parser.add_subparsers(title="subcommands", help=None)
for cls in SubCommand.__subclasses__():
cmd = cls()
args, argv = parser.parse_known_args()
return args.cmdobj.run(args, argv)
+
if __name__ == "__main__":
sys.exit(main())
FROM centos:7
-RUN yum install -y epel-release centos-release-xen
+RUN yum install -y epel-release centos-release-xen-48
+
RUN yum -y update
ENV PACKAGES \
bison \
ccache \
csnappy-devel \
flex \
- g++ \
+ gcc-c++ \
gcc \
gettext \
git \
apt-get install -y --no-install-recommends \
linux-headers-amd64
RUN git clone https://github.com/luigirizzo/netmap.git /usr/src/netmap
+RUN cd /usr/src/netmap && git checkout v11.3
RUN cd /usr/src/netmap/LINUX && ./configure --no-drivers --no-apps --kernel-dir=$(ls -d /usr/src/linux-headers-*-amd64) && make install
ENV QEMU_CONFIGURE_OPTS --enable-netmap
--- /dev/null
+#
+# Docker arm64 cross-compiler target
+#
+# This docker target builds on the Debian's Buster base image. There
+# are no QEMU pre-requistes so this image can only be used to build
+# test cases.
+#
+FROM qemu:debian10
+
+# Add the foreign architecture we want and install dependencies
+RUN dpkg --add-architecture arm64
+RUN apt update
+RUN DEBIAN_FRONTEND=noninteractive eatmydata \
+ apt-get install -y --no-install-recommends \
+ crossbuild-essential-arm64
--- /dev/null
+#
+# Docker multiarch cross-compiler target
+#
+# This docker target is builds on Debian cross compiler targets to build distro
+# with a selection of cross compilers for building test binaries.
+#
+# On its own you can't build much but the docker-foo-cross targets
+# build on top of the base debian image.
+#
+FROM debian:buster-slim
+
+# Duplicate deb line as deb-src
+RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> /etc/apt/sources.list
+
+# Install common build utilities
+RUN apt update
+RUN DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata
+RUN DEBIAN_FRONTEND=noninteractive eatmydata \
+ apt install -y --no-install-recommends \
+ bison \
+ build-essential \
+ ca-certificates \
+ clang \
+ flex \
+ gettext \
+ git \
+ pkg-config \
+ psmisc \
+ python \
+ texinfo \
+ $(apt-get -s build-dep qemu | egrep ^Inst | fgrep '[all]' | cut -d\ -f2)
RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> /etc/apt/sources.list
# Install common build utilities
-RUN apt update
-RUN DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata
+RUN apt-get update && \
+ DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata
RUN DEBIAN_FRONTEND=noninteractive eatmydata \
apt install -y --no-install-recommends \
bison \
static bool blacklisted(unsigned op, int rmode)
{
- /* odd has only been implemented for a few 128-bit ops */
+ /* odd has not been implemented for any 80-bit ops */
if (rmode == softfloat_round_odd) {
switch (op) {
- case F128_ADD:
- case F128_SUB:
- case F128_MUL:
- case F128_DIV:
- case F128_TO_F64:
- case F128_SQRT:
- return false;
- default:
+ case EXTF80_TO_UI32:
+ case EXTF80_TO_UI64:
+ case EXTF80_TO_I32:
+ case EXTF80_TO_I64:
+ case EXTF80_TO_UI32_R_MINMAG:
+ case EXTF80_TO_UI64_R_MINMAG:
+ case EXTF80_TO_I32_R_MINMAG:
+ case EXTF80_TO_I64_R_MINMAG:
+ case EXTF80_TO_F16:
+ case EXTF80_TO_F32:
+ case EXTF80_TO_F64:
+ case EXTF80_TO_F128:
+ case EXTF80_ROUNDTOINT:
+ case EXTF80_ADD:
+ case EXTF80_SUB:
+ case EXTF80_MUL:
+ case EXTF80_DIV:
+ case EXTF80_REM:
+ case EXTF80_SQRT:
+ case EXTF80_EQ:
+ case EXTF80_LE:
+ case EXTF80_LT:
+ case EXTF80_EQ_SIGNALING:
+ case EXTF80_LE_QUIET:
+ case EXTF80_LT_QUIET:
+ case UI32_TO_EXTF80:
+ case UI64_TO_EXTF80:
+ case I32_TO_EXTF80:
+ case I64_TO_EXTF80:
+ case F16_TO_EXTF80:
+ case F32_TO_EXTF80:
+ case F64_TO_EXTF80:
+ case F128_TO_EXTF80:
return true;
}
}
test_ab_extF80_z_bool(true_ab_extF80M_z_bool, subj_ab_extF80M_z_bool);
break;
case F128_TO_UI32:
- not_implemented();
+ test_a_f128_z_ui32_rx(slow_f128M_to_ui32, qemu_f128M_to_ui32, rmode,
+ exact);
break;
case F128_TO_UI64:
test_a_f128_z_ui64_rx(slow_f128M_to_ui64, qemu_f128M_to_ui64, rmode,
WRAP_128_TO_INT(qemu_f128M_to_i32, float128_to_int32, int_fast32_t)
WRAP_128_TO_INT(qemu_f128M_to_i64, float128_to_int64, int_fast64_t)
+WRAP_128_TO_INT(qemu_f128M_to_ui32, float128_to_uint32, uint_fast32_t)
WRAP_128_TO_INT(qemu_f128M_to_ui64, float128_to_uint64, uint_fast64_t)
#undef WRAP_128_TO_INT
{
char *cmd;
- cmd = g_strdup_printf("-chardev socket,id=chr0,path=%s,nowait "
+ cmd = g_strdup_printf("-chardev socket,id=chr0,path=%s "
"-device ivshmem-doorbell,chardev=chr0,vectors=%d",
tmpserver, nvectors);
qtest_add_abrt_handler(kill_qemu_hook_func, s);
command = g_strdup_printf("exec %s "
- "-qtest unix:%s,nowait "
+ "-qtest unix:%s "
"-qtest-log %s "
- "-chardev socket,path=%s,nowait,id=char0 "
+ "-chardev socket,path=%s,id=char0 "
"-mon chardev=char0,mode=control "
"-machine accel=qtest "
"-display none "
+module None
object q_empty
enum QType
prefix QTYPE
+module None
object q_empty
enum QType
prefix QTYPE
+module None
object q_empty
enum QType
prefix QTYPE
+module None
object q_empty
enum QType
prefix QTYPE
+module None
object q_empty
enum QType
prefix QTYPE
+module None
object q_empty
enum QType
prefix QTYPE
+module None
object q_empty
enum QType
prefix QTYPE
+module None
object q_empty
enum QType
prefix QTYPE
+module None
object q_empty
enum QType
prefix QTYPE
+module None
object q_empty
enum QType
prefix QTYPE
+module None
object q_empty
enum QType
prefix QTYPE
qemu_img('create', '-f', iotests.imgfmt, image0, '128K')
# Add an unused monitor, to verify it works fine when two monitor
# instances present
- self.vm.add_monitor_telnet("0",4445)
+ self.vm.add_monitor_null()
self.vm.launch()
def tearDown(self):
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.orig"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writeback
Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writeback
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writethrough
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writeback, ignore flushes
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.orig"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writeback
Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writeback
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writethrough
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writeback, ignore flushes
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
_cleanup()
{
_cleanup_test_img
+ rm -f "$TEST_IMG.copy"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
echo
# Across blkdebug without a config file, you cannot reconstruct filenames, so
-# qemu is incapable of knowing the directory of the top image
+# qemu is incapable of knowing the directory of the top image from the filename
+# alone. However, using bdrv_dirname(), it should still work.
TEST_IMG="json:{
'driver': '$IMGFMT',
'file': {
# omit the image size; it should work anyway
_make_test_img -b "$TEST_IMG_REL.base"
+echo
+echo '=== Nodes without a common directory ==='
+echo
+
+cp "$TEST_IMG" "$TEST_IMG.copy"
+
+# Should inform us that the actual path of the backing file cannot be determined
+TEST_IMG="json:{
+ 'driver': '$IMGFMT',
+ 'file': {
+ 'driver': 'quorum',
+ 'vote-threshold': 1,
+ 'children': [
+ {
+ 'driver': 'file',
+ 'filename': '$TEST_IMG'
+ },
+ {
+ 'driver': 'file',
+ 'filename': '$TEST_IMG.copy'
+ }
+ ]
+ }
+}" _img_info | _filter_img_info
+
# success, all done
echo '*** done'
image: json:{"driver": "IMGFMT", "file": {"set-state.0.event": "read_aio", "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "set-state.0.new_state": 42}}
file format: IMGFMT
virtual size: 64M (67108864 bytes)
-backing file: t.IMGFMT.base (cannot determine actual path)
+backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
=== Backing name is always relative to the backed image ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.base
+
+=== Nodes without a common directory ===
+
+image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.copy"}], "driver": "quorum", "vote-threshold": 1}}
+file format: IMGFMT
+virtual size: 64M (67108864 bytes)
+backing file: t.IMGFMT.base (cannot determine actual path)
*** done
self.assert_qmp(result, 'return[0]/dirty-bitmaps[0]/count', 458752)
self.assert_qmp(result, 'return[0]/dirty-bitmaps[0]/granularity', 65536)
self.assert_qmp(result, 'return[0]/dirty-bitmaps[0]/status', 'active')
+ self.assert_qmp(result, 'return[0]/dirty-bitmaps[0]/persistent', False)
# Prepare a cluster_size=128k backup target without a backing file.
(target, _) = bitmap0.new_target()
# The backing file doesn't need to exist :)
$QEMU_IMG measure --output=$ofmt -o backing_file=x \
-f "$fmt" -O "$IMGFMT" "$TEST_IMG"
+
+ echo
+ echo "== $fmt input image and LUKS encryption =="
+ echo
+ $QEMU_IMG measure --output=$ofmt \
+ --object secret,id=sec0,data=base \
+ -o encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10 \
+ -f "$fmt" -O "$IMGFMT" "$TEST_IMG"
fi
echo
required size: 1074135040
fully allocated size: 1074135040
+== qcow2 input image and LUKS encryption ==
+
+required size: 2686976
+fully allocated size: 1076232192
+
== qcow2 input image and preallocation (human) ==
required size: 1074135040
required size: 1074135040
fully allocated size: 1074135040
+== raw input image and LUKS encryption ==
+
+required size: 2686976
+fully allocated size: 1076232192
+
== raw input image and preallocation (human) ==
required size: 1074135040
"fully-allocated": 1074135040
}
+== qcow2 input image and LUKS encryption ==
+
+{
+ "required": 2686976,
+ "fully-allocated": 1076232192
+}
+
== qcow2 input image and preallocation (json) ==
{
"fully-allocated": 1074135040
}
+== raw input image and LUKS encryption ==
+
+{
+ "required": 2686976,
+ "fully-allocated": 1076232192
+}
+
== raw input image and preallocation (json) ==
{
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node_name": "imgfile"}}
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node-name": "imgfile"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Successful image creation (inline blockdev-add, explicit defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": false, "preallocation": "off", "refcount-bits": 16, "size": 67108864, "version": "v3"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 65536, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": false, "preallocation": "off", "refcount-bits": 16, "size": 67108864, "version": "v3"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Successful image creation (v3 non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": true, "preallocation": "falloc", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": true, "preallocation": "falloc", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 2097152, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": true, "preallocation": "metadata", "refcount-bits": 1, "size": 33554432, "version": "v3"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 2097152, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": true, "preallocation": "metadata", "refcount-bits": 1, "size": 33554432, "version": "v3"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Successful image creation (v2 non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "TEST_DIR/PID-t.qcow2.base", "backing-fmt": "qcow2", "cluster-size": 512, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432, "version": "v2"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-file": "TEST_DIR/PID-t.qcow2.base", "backing-fmt": "qcow2", "cluster-size": 512, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432, "version": "v2"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Successful image creation (encrypted) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid BlockdevRef ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "this doesn't exist", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "this doesn't exist", "size": 33554432}}}
{"return": {}}
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid sizes ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 1234}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 1234}}}
{"return": {}}
Job failed: Image size must be a multiple of 512 bytes
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 18446744073709551104}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 18446744073709551104}}}
{"return": {}}
Job failed: Could not resize image: Image size cannot be negative
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775808}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775808}}}
{"return": {}}
Job failed: Could not resize image: Image size cannot be negative
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}}
{"return": {}}
Job failed: Could not resize image: Failed to grow the L1 table: File too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid version ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}}
{"return": {}}
Job failed: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 8, "size": 67108864, "version": "v2"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 8, "size": 67108864, "version": "v2"}}}
{"return": {}}
Job failed: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater)
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid backing file options ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}}
{"return": {}}
Job failed: Backing file and preallocation cannot be used at the same time
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-fmt": "qcow2", "driver": "qcow2", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-fmt": "qcow2", "driver": "qcow2", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Backing format cannot be used without backing file
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid cluster size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "qcow2", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1234, "driver": "qcow2", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size must be a power of two between 512 and 2048k
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "qcow2", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 128, "driver": "qcow2", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size must be a power of two between 512 and 2048k
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4194304, "driver": "qcow2", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 4194304, "driver": "qcow2", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size must be a power of two between 512 and 2048k
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "qcow2", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 0, "driver": "qcow2", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size must be a power of two between 512 and 2048k
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "qcow2", "file": "node0", "size": 281474976710656}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 512, "driver": "qcow2", "file": "node0", "size": 281474976710656}}}
{"return": {}}
Job failed: Could not resize image: Failed to grow the L1 table: File too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid refcount width ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 128, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 128, "size": 67108864}}}
{"return": {}}
Job failed: Refcount width must be a power of two and may not exceed 64 bits
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 0, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 0, "size": 67108864}}}
{"return": {}}
Job failed: Refcount width must be a power of two and may not exceed 64 bits
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 7, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 7, "size": 67108864}}}
{"return": {}}
Job failed: Refcount width must be a power of two and may not exceed 64 bits
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
iotests.verify_image_format(supported_fmts=['raw'])
iotests.verify_protocol(supported=['ssh'])
-def filter_hash(msg):
- return re.sub('"hash": "[0-9a-f]+"', '"hash": HASH', msg)
+def filter_hash(qmsg):
+ def _filter(key, value):
+ if key == 'hash' and re.match('[0-9a-f]+', value):
+ return 'HASH'
+ return value
+ return iotests.filter_qmp(qmsg, _filter)
def blockdev_create(vm, options):
result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
- filters=[iotests.filter_testfiles, filter_hash])
+ filters=[iotests.filter_qmp_testfiles, filter_hash])
if 'return' in result:
assert result['return'] == {}
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Test host-key-check options ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
file format: IMGFMT
virtual size: 8.0M (8388608 bytes)
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "known_hosts"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "known_hosts"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
file format: IMGFMT
virtual size: 4.0M (4194304 bytes)
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
{"return": {}}
Job failed: remote host key does not match host_key_check 'wrong'
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
file format: IMGFMT
virtual size: 8.0M (8388608 bytes)
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
{"return": {}}
Job failed: remote host key does not match host_key_check 'wrong'
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid path and user ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
{"return": {}}
Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31)
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}, "user": "invalid user"}, "size": 4194304}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}, "user": "invalid user"}, "size": 4194304}}}
{"return": {}}
Job failed: failed to authenticate using publickey authentication and the identities held by your ssh-agent
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
iotests.verify_protocol(supported=['file'])
def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
+ filters=[iotests.filter_qmp_testfiles])
if 'return' in result:
assert result['return'] == {}
'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
- node_name='imgfile')
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
blockdev_create(vm, { 'driver': imgfmt,
'file': 'imgfile',
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "node_name": "imgfile"}}
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "node-name": "imgfile"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "imgfile", "iter-time": 10, "key-secret": "keysec0", "size": 134217728}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "imgfile", "iter-time": 10, "key-secret": "keysec0", "size": 134217728}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Successful image creation (with non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid BlockdevRef ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "this doesn't exist", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "this doesn't exist", "size": 67108864}}}
{"return": {}}
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
=== Zero size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "iter-time": 10, "key-secret": "keysec0", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "iter-time": 10, "key-secret": "keysec0", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid sizes ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 18446744073709551104}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 18446744073709551104}}}
{"return": {}}
Job failed: The requested file size is too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775808}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775808}}}
{"return": {}}
Job failed: The requested file size is too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775296}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775296}}}
{"return": {}}
Job failed: The requested file size is too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
=== Resize image with invalid sizes ===
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775296}}
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 9223372036854775296}}
{"error": {"class": "GenericError", "desc": "The requested file size is too large"}}
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775808}}
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 9223372036854775808}}
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}}
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 18446744073709551104}}
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 18446744073709551104}}
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}}
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": -9223372036854775808}}
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": -9223372036854775808}}
{"error": {"class": "GenericError", "desc": "Parameter 'size' expects a >0 size"}}
image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"}
file format: IMGFMT
iotests.verify_protocol(supported=['file'])
def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
+ filters=[iotests.filter_qmp_testfiles])
if 'return' in result:
assert result['return'] == {}
- vm.run_job('job0')
+ error = vm.run_job('job0')
+ if error and 'Could not allocate bmap' in error:
+ iotests.notrun('Insufficient memory')
iotests.log("")
with iotests.FilePath('t.vdi') as disk_path, \
'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
- node_name='imgfile')
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
blockdev_create(vm, { 'driver': imgfmt,
'file': 'imgfile',
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "node_name": "imgfile"}}
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "node-name": "imgfile"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "imgfile", "size": 134217728}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "imgfile", "size": 134217728}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Successful image creation (explicit defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "off", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "off", "size": 67108864}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Successful image creation (with non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "metadata", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "metadata", "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid BlockdevRef ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}}
{"return": {}}
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
=== Zero size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Maximum size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203584}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203584}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid sizes ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 18446744073709551104}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 18446744073709551104}}}
{"return": {}}
Job failed: Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000)
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 9223372036854775808}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 9223372036854775808}}}
{"return": {}}
Job failed: Unsupported VDI image size (size is 0x8000000000000000, max supported is 0x1fffff8000000)
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203585}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203585}}}
{"return": {}}
Job failed: Unsupported VDI image size (size is 0x1fffff8000001, max supported is 0x1fffff8000000)
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
iotests.verify_protocol(supported=['file'])
def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
+ filters=[iotests.filter_qmp_testfiles])
if 'return' in result:
assert result['return'] == {}
'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
- node_name='imgfile')
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
blockdev_create(vm, { 'driver': imgfmt,
'file': 'imgfile',
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "node_name": "imgfile"}}
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "node-name": "imgfile"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "imgfile", "size": 134217728}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "imgfile", "size": 134217728}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Successful image creation (explicit defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1048576, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1048576, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 67108864}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Successful image creation (with non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 65536, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid BlockdevRef ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "this doesn't exist", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "this doesn't exist", "size": 33554432}}}
{"return": {}}
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
=== Zero size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Maximum size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627369984}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627369984}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid sizes ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 1234}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 1234}}}
{"return": {}}
Job failed: Image size must be a multiple of 512 bytes
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 18446744073709551104}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 18446744073709551104}}}
{"return": {}}
Job failed: Image size is too large for this cluster size
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775808}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775808}}}
{"return": {}}
Job failed: Image size is too large for this cluster size
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775296}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775296}}}
{"return": {}}
Job failed: Image size is too large for this cluster size
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627370497}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627370497}}}
{"return": {}}
Job failed: Image size is too large for this cluster size
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
=== Invalid cluster size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "parallels", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1234, "driver": "parallels", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size must be a multiple of 512 bytes
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "parallels", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 128, "driver": "parallels", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size must be a multiple of 512 bytes
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4294967296, "driver": "parallels", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 4294967296, "driver": "parallels", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size is too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 9223372036854775808, "driver": "parallels", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 9223372036854775808, "driver": "parallels", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size is too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 18446744073709551104, "driver": "parallels", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 18446744073709551104, "driver": "parallels", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size is too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "parallels", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 0, "driver": "parallels", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Image size is too large for this cluster size
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "parallels", "file": "node0", "size": 281474976710656}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 512, "driver": "parallels", "file": "node0", "size": 281474976710656}}}
{"return": {}}
Job failed: Image size is too large for this cluster size
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
iotests.verify_protocol(supported=['file'])
def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
+ filters=[iotests.filter_qmp_testfiles])
if 'return' in result:
assert result['return'] == {}
'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
- node_name='imgfile')
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
blockdev_create(vm, { 'driver': imgfmt,
'file': 'imgfile',
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "node_name": "imgfile"}}
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "node-name": "imgfile"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "imgfile", "size": 134217728}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "imgfile", "size": 134217728}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Successful image creation (explicit defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 8388608, "block-state-zero": true, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 1048576, "size": 67108864, "subformat": "dynamic"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 8388608, "block-state-zero": true, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 1048576, "size": 67108864, "subformat": "dynamic"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Successful image creation (with non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 268435456, "block-state-zero": false, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 8388608, "size": 33554432, "subformat": "fixed"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 268435456, "block-state-zero": false, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 8388608, "size": 33554432, "subformat": "fixed"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid BlockdevRef ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "this doesn't exist", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "this doesn't exist", "size": 33554432}}}
{"return": {}}
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
=== Zero size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Maximum size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177664}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177664}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid sizes ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 18446744073709551104}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 18446744073709551104}}}
{"return": {}}
Job failed: Image size too large; max of 64TB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775808}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775808}}}
{"return": {}}
Job failed: Image size too large; max of 64TB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775296}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775296}}}
{"return": {}}
Job failed: Image size too large; max of 64TB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177665}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177665}}}
{"return": {}}
Job failed: Image size too large; max of 64TB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
=== Invalid block size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 1234567, "driver": "vhdx", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 1234567, "driver": "vhdx", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Block size must be a multiple of 1 MB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 128, "driver": "vhdx", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 128, "driver": "vhdx", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Block size must be a multiple of 1 MB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 3145728, "driver": "vhdx", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 3145728, "driver": "vhdx", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Block size must be a power of two
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 536870912, "driver": "vhdx", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 536870912, "driver": "vhdx", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Block size must not exceed 268435456
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 0, "driver": "vhdx", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 0, "driver": "vhdx", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Block size must be a multiple of 1 MB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
=== Invalid log size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 1234567, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 1234567, "size": 67108864}}}
{"return": {}}
Job failed: Log size must be a multiple of 1 MB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 128, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 128, "size": 67108864}}}
{"return": {}}
Job failed: Log size must be a multiple of 1 MB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 4294967296, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 4294967296, "size": 67108864}}}
{"return": {}}
Job failed: Log size must be smaller than 4 GB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 0, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 0, "size": 67108864}}}
{"return": {}}
Job failed: Log size must be a multiple of 1 MB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
--- /dev/null
+#!/usr/bin/env python
+#
+# Test json:{} filenames with qemu-internal BDSs
+# (the one of commit, to be precise)
+#
+# Copyright (C) 2018 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Creator/Owner: Max Reitz <mreitz@redhat.com>
+
+import iotests
+from iotests import log, qemu_img, qemu_io_silent, filter_qmp_testfiles, \
+ filter_qmp_imgfmt
+import json
+
+# Need backing file support (for arbitrary backing formats)
+iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed'])
+iotests.verify_platform(['linux'])
+
+
+# There are two variations of this test:
+# (1) We do not set filter_node_name. In that case, the commit_top
+# driver should not appear anywhere.
+# (2) We do set filter_node_name. In that case, it should appear.
+#
+# This for loop executes both.
+for filter_node_name in False, True:
+ log('')
+ log('--- filter_node_name: %s ---' % filter_node_name)
+ log('')
+
+ with iotests.FilePath('base.img') as base_img_path, \
+ iotests.FilePath('mid.img') as mid_img_path, \
+ iotests.FilePath('top.img') as top_img_path, \
+ iotests.VM() as vm:
+
+ assert qemu_img('create', '-f', iotests.imgfmt,
+ base_img_path, '64M') == 0
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
+ mid_img_path) == 0
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', mid_img_path,
+ top_img_path) == 0
+
+ # Something to commit
+ assert qemu_io_silent(mid_img_path, '-c', 'write -P 1 0 1M') == 0
+
+ vm.launch()
+
+ # Change the bottom-most image's backing file (to null-co://)
+ # to enforce json:{} filenames
+ vm.qmp_log('blockdev-add',
+ node_name='top',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': top_img_path
+ },
+ backing={
+ 'node-name': 'mid',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': mid_img_path
+ },
+ 'backing': {
+ 'node-name': 'base',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': base_img_path
+ },
+ 'backing': {
+ 'driver': 'null-co'
+ }
+ }
+ },
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ # As long as block-commit does not accept node names, we have to
+ # get our mid/base filenames here
+ mid_name = vm.node_info('mid')['image']['filename']
+ base_name = vm.node_info('base')['image']['filename']
+
+ assert mid_name[:5] == 'json:'
+ assert base_name[:5] == 'json:'
+
+ # Start the block job
+ if filter_node_name:
+ vm.qmp_log('block-commit',
+ job_id='commit',
+ device='top',
+ filter_node_name='filter_node',
+ top=mid_name,
+ base=base_name,
+ speed=1,
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+ else:
+ vm.qmp_log('block-commit',
+ job_id='commit',
+ device='top',
+ top=mid_name,
+ base=base_name,
+ speed=1,
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ vm.qmp_log('job-pause', id='commit')
+
+ # Get and parse top's json:{} filename
+ top_name = vm.node_info('top')['image']['filename']
+
+ vm.shutdown()
+
+ assert top_name[:5] == 'json:'
+ top_options = json.loads(top_name[5:])
+
+ if filter_node_name:
+ # This should be present and set
+ assert top_options['backing']['driver'] == 'commit_top'
+ # And the mid image is commit_top's backing image
+ mid_options = top_options['backing']['backing']
+ else:
+ # The mid image should appear as the immediate backing BDS
+ # of top
+ mid_options = top_options['backing']
+
+ assert mid_options['driver'] == iotests.imgfmt
+ assert mid_options['file']['filename'] == mid_img_path
--- /dev/null
+
+--- filter_node_name: False ---
+
+{"execute": "blockdev-add", "arguments": {"backing": {"backing": {"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "base"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-mid.img"}, "node-name": "mid"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "top"}}
+{"return": {}}
+{"execute": "block-commit", "arguments": {"base": "json:{\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}", "device": "top", "job-id": "commit", "speed": 1, "top": "json:{\"backing\": {\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-mid.img\"}}"}}
+{"return": {}}
+{"execute": "job-pause", "arguments": {"id": "commit"}}
+{"return": {}}
+
+--- filter_node_name: True ---
+
+{"execute": "blockdev-add", "arguments": {"backing": {"backing": {"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "base"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-mid.img"}, "node-name": "mid"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "top"}}
+{"return": {}}
+{"execute": "block-commit", "arguments": {"base": "json:{\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}", "device": "top", "filter-node-name": "filter_node", "job-id": "commit", "speed": 1, "top": "json:{\"backing\": {\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-mid.img\"}}"}}
+{"return": {}}
+{"execute": "job-pause", "arguments": {"id": "commit"}}
+{"return": {}}
--- /dev/null
+#!/usr/bin/env python
+#
+# Test for when a backing file is considered overridden (thus, a
+# json:{} filename is generated for the overlay) and when it is not
+#
+# Copyright (C) 2018 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Creator/Owner: Max Reitz <mreitz@redhat.com>
+
+import iotests
+from iotests import log, qemu_img, filter_testfiles, filter_imgfmt, \
+ filter_qmp_testfiles, filter_qmp_imgfmt
+
+# Need backing file and change-backing-file support
+iotests.verify_image_format(supported_fmts=['qcow2', 'qed'])
+iotests.verify_platform(['linux'])
+
+
+def log_node_info(node):
+ log('')
+
+ log('bs->filename: ' + node['image']['filename'],
+ filters=[filter_testfiles, filter_imgfmt])
+ log('bs->backing_file: ' + node['backing_file'],
+ filters=[filter_testfiles, filter_imgfmt])
+
+ if 'backing-image' in node['image']:
+ log('bs->backing->bs->filename: ' +
+ node['image']['backing-image']['filename'],
+ filters=[filter_testfiles, filter_imgfmt])
+ else:
+ log('bs->backing: (none)')
+
+ log('')
+
+
+with iotests.FilePath('base.img') as base_img_path, \
+ iotests.FilePath('top.img') as top_img_path, \
+ iotests.VM() as vm:
+
+ assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0
+ # Choose a funny way to describe the backing filename
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b',
+ 'file:' + base_img_path, top_img_path) == 0
+
+ vm.launch()
+
+ log('--- Implicit backing file ---')
+ log('')
+
+ vm.qmp_log('blockdev-add',
+ node_name='node0',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': top_img_path
+ },
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ # Filename should be plain, and the backing filename should not
+ # contain the "file:" prefix
+ log_node_info(vm.node_info('node0'))
+
+ vm.qmp_log('blockdev-del', node_name='node0')
+
+ log('')
+ log('--- change-backing-file ---')
+ log('')
+
+ vm.qmp_log('blockdev-add',
+ node_name='node0',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': top_img_path
+ },
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ # Changing the backing file to a qemu-reported filename should
+ # result in qemu accepting the corresponding BDS as the implicit
+ # backing BDS (and thus not generate a json:{} filename).
+ # So, first, query the backing filename.
+
+ backing_filename = \
+ vm.node_info('node0')['image']['backing-image']['filename']
+
+ # Next, change the backing file to something different
+
+ vm.qmp_log('change-backing-file',
+ image_node_name='node0',
+ device='node0',
+ backing_file='null-co://',
+ filters=[filter_qmp_testfiles])
+
+ # Now, verify that we get a json:{} filename
+ # (Image header says "null-co://", actual backing file still is
+ # base_img_path)
+
+ log_node_info(vm.node_info('node0'))
+
+ # Change it back
+ # (To get header and backing file in sync)
+
+ vm.qmp_log('change-backing-file',
+ image_node_name='node0',
+ device='node0',
+ backing_file=backing_filename,
+ filters=[filter_qmp_testfiles])
+
+ # And verify that we get our original results
+
+ log_node_info(vm.node_info('node0'))
+
+ # Finally, try a "file:" prefix. While this is actually what we
+ # originally had in the image header, qemu will not reopen the
+ # backing file here, so it cannot verify that this filename
+ # "resolves" to the actual backing BDS's filename and will thus
+ # consider both to be different.
+ # (This may be fixed in the future.)
+
+ vm.qmp_log('change-backing-file',
+ image_node_name='node0',
+ device='node0',
+ backing_file=('file:' + backing_filename),
+ filters=[filter_qmp_testfiles])
+
+ # So now we should get a json:{} filename
+
+ log_node_info(vm.node_info('node0'))
+
+ # Remove and re-attach so we can see that (as in our first try),
+ # opening the image anew helps qemu resolve the header backing
+ # filename.
+
+ vm.qmp_log('blockdev-del', node_name='node0')
+
+ vm.qmp_log('blockdev-add',
+ node_name='node0',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': top_img_path
+ },
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ log_node_info(vm.node_info('node0'))
+
+ vm.qmp_log('blockdev-del', node_name='node0')
+
+ log('')
+ log('--- Override backing file ---')
+ log('')
+
+ # For this test, we need the plain filename in the image header
+ # (because qemu cannot "canonicalize"/"resolve" the backing
+ # filename unless the backing file is opened implicitly with the
+ # overlay)
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
+ top_img_path) == 0
+
+ # You can only reliably override backing options by using a node
+ # reference (or by specifying file.filename, but, well...)
+ vm.qmp_log('blockdev-add', node_name='null', driver='null-co')
+
+ vm.qmp_log('blockdev-add',
+ node_name='node0',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': top_img_path
+ },
+ backing='null',
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ # Should get a json:{} filename (and bs->backing_file is
+ # null-co://, because that field actually has not much to do
+ # with the header backing filename (except that it is changed by
+ # change-backing-file))
+
+ log_node_info(vm.node_info('node0'))
+
+ # Detach the backing file by reopening the whole thing
+
+ vm.qmp_log('blockdev-del', node_name='node0')
+ vm.qmp_log('blockdev-del', node_name='null')
+
+ vm.qmp_log('blockdev-add',
+ node_name='node0',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': top_img_path
+ },
+ backing=None,
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ # Should get a json:{} filename (because we overrode the backing
+ # file to not be there)
+
+ log_node_info(vm.node_info('node0'))
+
+ # Open the original backing file
+
+ vm.qmp_log('blockdev-add',
+ node_name='original-backing',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': base_img_path
+ },
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ # Attach the original backing file to its overlay
+
+ vm.qmp_log('blockdev-snapshot',
+ node='original-backing',
+ overlay='node0')
+
+ # This should give us the original plain result
+
+ log_node_info(vm.node_info('node0'))
+
+ vm.qmp_log('blockdev-del', node_name='node0')
+ vm.qmp_log('blockdev-del', node_name='original-backing')
+
+ vm.shutdown()
--- /dev/null
+--- Implicit backing file ---
+
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
+{"return": {}}
+
+bs->filename: TEST_DIR/PID-top.img
+bs->backing_file: TEST_DIR/PID-base.img
+bs->backing->bs->filename: TEST_DIR/PID-base.img
+
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
+{"return": {}}
+
+--- change-backing-file ---
+
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
+{"return": {}}
+{"execute": "change-backing-file", "arguments": {"backing-file": "null-co://", "device": "node0", "image-node-name": "node0"}}
+{"return": {}}
+
+bs->filename: json:{"backing": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
+bs->backing_file: null-co://
+bs->backing->bs->filename: TEST_DIR/PID-base.img
+
+{"execute": "change-backing-file", "arguments": {"backing-file": "TEST_DIR/PID-base.img", "device": "node0", "image-node-name": "node0"}}
+{"return": {}}
+
+bs->filename: TEST_DIR/PID-top.img
+bs->backing_file: TEST_DIR/PID-base.img
+bs->backing->bs->filename: TEST_DIR/PID-base.img
+
+{"execute": "change-backing-file", "arguments": {"backing-file": "file:TEST_DIR/PID-base.img", "device": "node0", "image-node-name": "node0"}}
+{"return": {}}
+
+bs->filename: json:{"backing": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
+bs->backing_file: file:TEST_DIR/PID-base.img
+bs->backing->bs->filename: TEST_DIR/PID-base.img
+
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
+{"return": {}}
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
+{"return": {}}
+
+bs->filename: TEST_DIR/PID-top.img
+bs->backing_file: TEST_DIR/PID-base.img
+bs->backing->bs->filename: TEST_DIR/PID-base.img
+
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
+{"return": {}}
+
+--- Override backing file ---
+
+{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "null"}}
+{"return": {}}
+{"execute": "blockdev-add", "arguments": {"backing": "null", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
+{"return": {}}
+
+bs->filename: json:{"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
+bs->backing_file: null-co://
+bs->backing->bs->filename: null-co://
+
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
+{"return": {}}
+{"execute": "blockdev-del", "arguments": {"node-name": "null"}}
+{"return": {}}
+{"execute": "blockdev-add", "arguments": {"backing": null, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
+{"return": {}}
+
+bs->filename: json:{"backing": null, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
+bs->backing_file: TEST_DIR/PID-base.img
+bs->backing: (none)
+
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "original-backing"}}
+{"return": {}}
+{"execute": "blockdev-snapshot", "arguments": {"node": "original-backing", "overlay": "node0"}}
+{"return": {}}
+
+bs->filename: TEST_DIR/PID-top.img
+bs->backing_file: TEST_DIR/PID-base.img
+bs->backing->bs->filename: TEST_DIR/PID-base.img
+
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
+{"return": {}}
+{"execute": "blockdev-del", "arguments": {"node-name": "original-backing"}}
+{"return": {}}
_cleanup()
{
_cleanup_test_img
- rm -f $TEST_IMG.snap
}
trap "_cleanup; exit \$status" 0 1 2 3 15
_make_test_img $size
+if [ -n "$TEST_IMG_FILE" ]; then
+ TEST_IMG=$TEST_IMG_FILE
+fi
+
echo
echo "=== -drive with read-write image: read-only/auto-read-only combinations ==="
echo
{
nbd_server_stop
_cleanup_test_img
+ # If we aborted early we want to see this log for diagnosis
+ test -f "$TEST_DIR/server.log" && cat "$TEST_DIR/server.log"
rm -f "$TEST_DIR/server.log"
tls_x509_cleanup
}
echo
echo "== final server log =="
cat "$TEST_DIR/server.log"
+rm -f "$TEST_DIR/server.log"
# success, all done
echo "*** done"
"count": 262144,
"granularity": 65536,
"name": "bitmapB",
+ "persistent": false,
"status": "active"
},
{
"count": 262144,
"granularity": 65536,
"name": "bitmapA",
+ "persistent": false,
"status": "active"
}
]
"count": 262144,
"granularity": 65536,
"name": "bitmapB",
+ "persistent": false,
"status": "active"
},
{
"count": 262144,
"granularity": 65536,
"name": "bitmapA",
+ "persistent": false,
"status": "active"
}
]
"count": 393216,
"granularity": 65536,
"name": "bitmapC",
+ "persistent": false,
"status": "disabled"
},
{
"count": 262144,
"granularity": 65536,
"name": "bitmapB",
+ "persistent": false,
"status": "disabled"
},
{
"count": 458752,
"granularity": 65536,
"name": "bitmapA",
+ "persistent": false,
"status": "disabled"
}
]
"count": 393216,
"granularity": 65536,
"name": "bitmapC",
+ "persistent": false,
"status": "disabled"
},
{
"count": 262144,
"granularity": 65536,
"name": "bitmapB",
+ "persistent": false,
"status": "disabled"
},
{
"count": 458752,
"granularity": 65536,
"name": "bitmapA",
+ "persistent": false,
"status": "disabled"
}
]
"count": 458752,
"granularity": 65536,
"name": "bitmapD",
+ "persistent": false,
"status": "disabled"
},
{
"count": 393216,
"granularity": 65536,
"name": "bitmapC",
+ "persistent": false,
"status": "disabled"
},
{
"count": 262144,
"granularity": 65536,
"name": "bitmapB",
+ "persistent": false,
"status": "disabled"
},
{
"count": 458752,
"granularity": 65536,
"name": "bitmapA",
+ "persistent": false,
"status": "disabled"
}
]
iotests.verify_image_format(supported_fmts=['vmdk'])
def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
+ filters=[iotests.filter_qmp_testfiles])
if 'return' in result:
assert result['return'] == {}
'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
- node_name='imgfile')
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
blockdev_create(vm, { 'driver': imgfmt,
'file': 'imgfile',
iotests.log("= %s %d =" % (subfmt, size))
iotests.log("")
- num_extents = math.ceil(size / 2.0**31)
+ num_extents = int(math.ceil(size / 2.0**31))
extents = [ "ext%d" % (i) for i in range(1, num_extents + 1) ]
vm.launch()
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "node_name": "imgfile"}}
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "node-name": "imgfile"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "imgfile", "size": 5368709120}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "imgfile", "size": 5368709120}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Successful image creation (inline blockdev-add, explicit defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "hwversion": "4", "size": 67108864, "subformat": "monolithicSparse", "zeroed-grain": false}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "hwversion": "4", "size": 67108864, "subformat": "monolithicSparse", "zeroed-grain": false}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Successful image creation (with non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "size": 33554432, "subformat": "monolithicSparse", "zeroed-grain": true}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "size": 33554432, "subformat": "monolithicSparse", "zeroed-grain": true}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid BlockdevRef ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "this doesn't exist", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "this doesn't exist", "size": 33554432}}}
{"return": {}}
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
== Valid adapter types ==
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "lsilogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "lsilogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "legacyESX", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "legacyESX", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
== Invalid adapter types ==
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter 'foo'"}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter 'IDE'"}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter 'legacyesx'"}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'options.adapter-type', expected: string"}}
=== Other subformats ===
== Missing extent ==
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
{"return": {}}
Job failed: Extent [0] not specified
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
== Correct extent ==
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
== Extra extent ==
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}}
{"return": {}}
Job failed: List of extents contains unused extents
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
= twoGbMaxExtentFlat 512 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
= twoGbMaxExtentSparse 512 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
= twoGbMaxExtentFlat 1073741824 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
= twoGbMaxExtentSparse 1073741824 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
= twoGbMaxExtentFlat 2147483648 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
= twoGbMaxExtentSparse 2147483648 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
= twoGbMaxExtentFlat 5368709120 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentFlat"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
= twoGbMaxExtentSparse 5368709120 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentSparse"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentSparse"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
--- /dev/null
+#!/usr/bin/env python
+#
+# Test for qcow2 bitmap printed information
+#
+# Copyright (c) 2019 Virtuozzo International GmbH
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import iotests
+import json
+import struct
+from iotests import qemu_img_create, qemu_io, qemu_img_pipe, \
+ file_path, img_info_log, log, filter_qemu_io
+
+iotests.verify_image_format(supported_fmts=['qcow2'])
+
+disk = file_path('disk')
+chunk = 256 * 1024
+bitmap_flag_unknown = 1 << 2
+# flag_offset = 5*cluster_size + flag_offset_in_bitmap_directory_entry
+flag_offset = 0x5000f
+
+
+def print_bitmap(extra_args):
+ log('qemu-img info dump:\n')
+ img_info_log(disk, extra_args=extra_args)
+ result = json.loads(qemu_img_pipe('info', '--force-share',
+ '--output=json', disk))
+ if 'bitmaps' in result['format-specific']['data']:
+ bitmaps = result['format-specific']['data']['bitmaps']
+ log('The same bitmaps in JSON format:')
+ log(bitmaps, indent=2)
+ else:
+ log('No bitmap in JSON format output')
+
+
+def add_bitmap(bitmap_number, persistent, disabled):
+ granularity = 1 << (13 + bitmap_number)
+ bitmap_name = 'bitmap-' + str(bitmap_number-1)
+ vm = iotests.VM().add_drive(disk)
+ vm.launch()
+ vm.qmp_log('block-dirty-bitmap-add', node='drive0', name=bitmap_name,
+ granularity=granularity, persistent=persistent,
+ disabled=disabled)
+ vm.shutdown()
+
+
+def write_to_disk(offset, size):
+ write = 'write {} {}'.format(offset, size)
+ log(qemu_io('-c', write, disk), filters=[filter_qemu_io])
+
+
+def toggle_flag(offset):
+ with open(disk, "r+b") as f:
+ f.seek(offset, 0)
+ # Read one byte in a way compatible with Python 2
+ flags = struct.unpack("B", f.read(1))
+ toggled = flags[0] ^ bitmap_flag_unknown
+ f.seek(-1, 1)
+ f.write(struct.pack("B", toggled))
+
+
+qemu_img_create('-f', iotests.imgfmt, disk, '1M')
+
+for num in range(1, 4):
+ disabled = False
+ if num == 2:
+ disabled = True
+ log('Test {}'.format(num))
+ add_bitmap(num, num > 1, disabled)
+ write_to_disk((num-1) * chunk, chunk)
+ print_bitmap([])
+ log('')
+
+vm = iotests.VM().add_drive(disk)
+vm.launch()
+num += 1
+log('Test {}\nChecking "in-use" flag...'.format(num))
+print_bitmap(['--force-share'])
+vm.shutdown()
+
+num += 1
+log('\nTest {}'.format(num))
+qemu_img_create('-f', iotests.imgfmt, disk, '1M')
+add_bitmap(1, True, False)
+log('Write an unknown bitmap flag \'{}\' into a new QCOW2 image at offset {}'
+ .format(hex(bitmap_flag_unknown), flag_offset))
+toggle_flag(flag_offset)
+img_info_log(disk)
+toggle_flag(flag_offset)
+log('Unset the unknown bitmap flag \'{}\' in the bitmap directory entry:\n'
+ .format(hex(bitmap_flag_unknown)))
+img_info_log(disk)
+log('Test complete')
--- /dev/null
+Test 1
+{"execute": "block-dirty-bitmap-add", "arguments": {"disabled": false, "granularity": 16384, "name": "bitmap-0", "node": "drive0", "persistent": false}}
+{"return": {}}
+wrote 262144/262144 bytes at offset 0
+256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+qemu-img info dump:
+
+image: TEST_IMG
+file format: IMGFMT
+virtual size: 1.0M (1048576 bytes)
+cluster_size: 65536
+Format specific information:
+ compat: 1.1
+ lazy refcounts: false
+ refcount bits: 16
+ corrupt: false
+
+No bitmap in JSON format output
+
+Test 2
+{"execute": "block-dirty-bitmap-add", "arguments": {"disabled": true, "granularity": 32768, "name": "bitmap-1", "node": "drive0", "persistent": true}}
+{"return": {}}
+wrote 262144/262144 bytes at offset 262144
+256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+qemu-img info dump:
+
+image: TEST_IMG
+file format: IMGFMT
+virtual size: 1.0M (1048576 bytes)
+cluster_size: 65536
+Format specific information:
+ compat: 1.1
+ lazy refcounts: false
+ bitmaps:
+ [0]:
+ flags:
+ name: bitmap-1
+ granularity: 32768
+ refcount bits: 16
+ corrupt: false
+
+The same bitmaps in JSON format:
+[
+ {
+ "flags": [],
+ "granularity": 32768,
+ "name": "bitmap-1"
+ }
+]
+
+Test 3
+{"execute": "block-dirty-bitmap-add", "arguments": {"disabled": false, "granularity": 65536, "name": "bitmap-2", "node": "drive0", "persistent": true}}
+{"return": {}}
+wrote 262144/262144 bytes at offset 524288
+256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+qemu-img info dump:
+
+image: TEST_IMG
+file format: IMGFMT
+virtual size: 1.0M (1048576 bytes)
+cluster_size: 65536
+Format specific information:
+ compat: 1.1
+ lazy refcounts: false
+ bitmaps:
+ [0]:
+ flags:
+ name: bitmap-1
+ granularity: 32768
+ [1]:
+ flags:
+ [0]: auto
+ name: bitmap-2
+ granularity: 65536
+ refcount bits: 16
+ corrupt: false
+
+The same bitmaps in JSON format:
+[
+ {
+ "flags": [],
+ "granularity": 32768,
+ "name": "bitmap-1"
+ },
+ {
+ "flags": [
+ "auto"
+ ],
+ "granularity": 65536,
+ "name": "bitmap-2"
+ }
+]
+
+Test 4
+Checking "in-use" flag...
+qemu-img info dump:
+
+image: TEST_IMG
+file format: IMGFMT
+virtual size: 1.0M (1048576 bytes)
+cluster_size: 65536
+Format specific information:
+ compat: 1.1
+ lazy refcounts: false
+ bitmaps:
+ [0]:
+ flags:
+ [0]: in-use
+ name: bitmap-1
+ granularity: 32768
+ [1]:
+ flags:
+ [0]: in-use
+ [1]: auto
+ name: bitmap-2
+ granularity: 65536
+ refcount bits: 16
+ corrupt: false
+
+The same bitmaps in JSON format:
+[
+ {
+ "flags": [
+ "in-use"
+ ],
+ "granularity": 32768,
+ "name": "bitmap-1"
+ },
+ {
+ "flags": [
+ "in-use",
+ "auto"
+ ],
+ "granularity": 65536,
+ "name": "bitmap-2"
+ }
+]
+
+Test 5
+{"execute": "block-dirty-bitmap-add", "arguments": {"disabled": false, "granularity": 16384, "name": "bitmap-0", "node": "drive0", "persistent": true}}
+{"return": {}}
+Write an unknown bitmap flag '0x4' into a new QCOW2 image at offset 327695
+qemu-img: Could not open 'TEST_IMG': Bitmap 'bitmap-0' doesn't satisfy the constraints
+
+Unset the unknown bitmap flag '0x4' in the bitmap directory entry:
+
+image: TEST_IMG
+file format: IMGFMT
+virtual size: 1.0M (1048576 bytes)
+cluster_size: 65536
+Format specific information:
+ compat: 1.1
+ lazy refcounts: false
+ bitmaps:
+ [0]:
+ flags:
+ [0]: auto
+ name: bitmap-0
+ granularity: 16384
+ refcount bits: 16
+ corrupt: false
+
+Test complete
TEST_IMG="nbd:127.0.0.1:10810"
elif [ "$IMGPROTO" = "ssh" ]; then
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
+ REMOTE_TEST_DIR="ssh://127.0.0.1$TEST_DIR"
TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE"
elif [ "$IMGPROTO" = "nfs" ]; then
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
}
+tls_certtool()
+{
+ certtool "$@" 1>"${tls_dir}"/certtool.log 2>&1
+ if test "$?" = 0; then
+ head -1 "${tls_dir}"/certtool.log
+ else
+ cat "${tls_dir}"/certtool.log
+ fi
+ rm -f "${tls_dir}"/certtool.log
+}
+
tls_x509_init()
{
(certtool --help) >/dev/null 2>&1 || \
cert_signing_key
EOF
- certtool --generate-self-signed \
- --load-privkey "${tls_dir}/key.pem" \
- --template "${tls_dir}/ca.info" \
- --outfile "${tls_dir}/$name-cert.pem" 2>&1 | head -1
+ tls_certtool \
+ --generate-self-signed \
+ --load-privkey "${tls_dir}/key.pem" \
+ --template "${tls_dir}/ca.info" \
+ --outfile "${tls_dir}/$name-cert.pem"
rm -f "${tls_dir}/ca.info"
}
signing_key
EOF
- certtool --generate-certificate \
- --load-ca-privkey "${tls_dir}/key.pem" \
- --load-ca-certificate "${tls_dir}/$caname-cert.pem" \
- --load-privkey "${tls_dir}/key.pem" \
- --template "${tls_dir}/cert.info" \
- --outfile "${tls_dir}/$name/server-cert.pem" 2>&1 | head -1
+ tls_certtool \
+ --generate-certificate \
+ --load-ca-privkey "${tls_dir}/key.pem" \
+ --load-ca-certificate "${tls_dir}/$caname-cert.pem" \
+ --load-privkey "${tls_dir}/key.pem" \
+ --template "${tls_dir}/cert.info" \
+ --outfile "${tls_dir}/$name/server-cert.pem"
+
ln -s "${tls_dir}/$caname-cert.pem" "${tls_dir}/$name/ca-cert.pem"
ln -s "${tls_dir}/key.pem" "${tls_dir}/$name/server-key.pem"
signing_key
EOF
- certtool --generate-certificate \
- --load-ca-privkey "${tls_dir}/key.pem" \
- --load-ca-certificate "${tls_dir}/$caname-cert.pem" \
- --load-privkey "${tls_dir}/key.pem" \
- --template "${tls_dir}/cert.info" \
- --outfile "${tls_dir}/$name/client-cert.pem" 2>&1 | head -1
+ tls_certtool \
+ --generate-certificate \
+ --load-ca-privkey "${tls_dir}/key.pem" \
+ --load-ca-certificate "${tls_dir}/$caname-cert.pem" \
+ --load-privkey "${tls_dir}/key.pem" \
+ --template "${tls_dir}/cert.info" \
+ --outfile "${tls_dir}/$name/client-cert.pem"
+
ln -s "${tls_dir}/$caname-cert.pem" "${tls_dir}/$name/ca-cert.pem"
ln -s "${tls_dir}/key.pem" "${tls_dir}/$name/client-key.pem"
221 rw auto quick
222 rw auto quick
223 rw auto quick
+224 rw auto quick
225 rw auto quick
226 auto quick
227 auto quick
+228 rw auto quick
229 auto quick
231 auto quick
232 auto quick
238 auto quick
239 rw auto quick
240 auto quick
+242 rw auto quick
sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
return exitcode
-def ordered_qmp(qmsg):
+def ordered_qmp(qmsg, conv_keys=True):
# Dictionaries are not ordered prior to 3.6, therefore:
if isinstance(qmsg, list):
return [ordered_qmp(atom) for atom in qmsg]
if isinstance(qmsg, dict):
od = OrderedDict()
for k, v in sorted(qmsg.items()):
- od[k] = ordered_qmp(v)
+ if conv_keys:
+ k = k.replace('_', '-')
+ od[k] = ordered_qmp(v, conv_keys=False)
return od
return qmsg
r = qemu_img_pipe('info', '--output=json', '-f', imgfmt, img)
return json.loads(r)['virtual-size']
+def is_str(val):
+ if sys.version_info.major >= 3:
+ return isinstance(val, str)
+ else:
+ return isinstance(val, str) or isinstance(val, unicode)
+
test_dir_re = re.compile(r"%s" % test_dir)
def filter_test_dir(msg):
return test_dir_re.sub("TEST_DIR", msg)
def filter_qmp_testfiles(qmsg):
def _filter(key, value):
- if key == 'filename' or key == 'backing-file':
+ if is_str(value):
return filter_testfiles(value)
return value
return filter_qmp(qmsg, _filter)
lines.append(line)
return '\n'.join(lines)
+def filter_imgfmt(msg):
+ return msg.replace(imgfmt, 'IMGFMT')
+
+def filter_qmp_imgfmt(qmsg):
+ def _filter(key, value):
+ if is_str(value):
+ return filter_imgfmt(value)
+ return value
+ return filter_qmp(qmsg, _filter)
+
def log(msg, filters=[], indent=None):
'''Logs either a string message or a JSON serializable message (like QMP).
If indent is provided, JSON serializable messages are pretty-printed.'''
log(result, filters, indent=indent)
return result
+ # Returns None on success, and an error string on failure
def run_job(self, job, auto_finalize=True, auto_dismiss=False):
+ error = None
while True:
for ev in self.get_qmp_events_filtered(wait=True):
if ev['event'] == 'JOB_STATUS_CHANGE':
result = self.qmp('query-jobs')
for j in result['return']:
if j['id'] == job:
+ error = j['error']
log('Job failed: %s' % (j['error']))
elif status == 'pending' and not auto_finalize:
self.qmp_log('job-finalize', id=job)
elif status == 'concluded' and not auto_dismiss:
self.qmp_log('job-dismiss', id=job)
elif status == 'null':
- return
+ return error
else:
iotests.log(ev)
+ def node_info(self, node_name):
+ nodes = self.qmp('query-named-block-nodes')
+ for x in nodes['return']:
+ if x['node-name'] == node_name:
+ return x
+ return None
+
index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
# We don't have any bigendian build tools so we only use this for AArch64
ifeq ($(TARGET_NAME),aarch64)
-DOCKER_IMAGE=debian-arm64-cross
+DOCKER_IMAGE=debian-buster-arm64-cross
DOCKER_CROSS_COMPILER=aarch64-linux-gnu-gcc
endif
# we don't build any of the ARM tests
AARCH64_TESTS=$(filter-out $(ARM_TESTS), $(TESTS))
AARCH64_TESTS+=fcvt
-TESTS:=$(AARCH64_TESTS)
fcvt: LDFLAGS+=-lm
run-fcvt: fcvt
$(call run-test,$<,$(QEMU) $<, "$< on $(TARGET_NAME)")
$(call diff-out,$<,$(AARCH64_SRC)/fcvt.ref)
+
+AARCH64_TESTS += pauth-1
+run-pauth-%: QEMU += -cpu max
+
+TESTS:=$(AARCH64_TESTS)
--- /dev/null
+#include <assert.h>
+#include <sys/prctl.h>
+
+asm(".arch armv8.4-a");
+
+#ifndef PR_PAC_RESET_KEYS
+#define PR_PAC_RESET_KEYS 54
+#define PR_PAC_APDAKEY (1 << 2)
+#endif
+
+int main()
+{
+ int x;
+ void *p0 = &x, *p1, *p2;
+
+ asm volatile("pacdza %0" : "=r"(p1) : "0"(p0));
+ prctl(PR_PAC_RESET_KEYS, PR_PAC_APDAKEY, 0, 0, 0);
+ asm volatile("pacdza %0" : "=r"(p2) : "0"(p0));
+
+ assert(p1 != p0);
+ assert(p1 != p2);
+ return 0;
+}
--- /dev/null
+/*
+ * Header file for pattern and random test inputs
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef TEST_INPUTS_H
+#define TEST_INPUTS_H
+
+#include <stdint.h>
+
+
+#define PATTERN_INPUTS_COUNT 64
+#define PATTERN_INPUTS_SHORT_COUNT 8
+
+uint64_t b128_pattern[PATTERN_INPUTS_COUNT][2] = {
+ { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xAAAAAAAAAAAAAAAAULL, 0xAAAAAAAAAAAAAAAAULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xCCCCCCCCCCCCCCCCULL, 0xCCCCCCCCCCCCCCCCULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xE38E38E38E38E38EULL, 0x38E38E38E38E38E3ULL, },
+ { 0x1C71C71C71C71C71ULL, 0xC71C71C71C71C71CULL, },
+ { 0xF0F0F0F0F0F0F0F0ULL, 0xF0F0F0F0F0F0F0F0ULL, }, /* 8 */
+ { 0x0F0F0F0F0F0F0F0FULL, 0x0F0F0F0F0F0F0F0FULL, },
+ { 0xF83E0F83E0F83E0FULL, 0x83E0F83E0F83E0F8ULL, },
+ { 0x07C1F07C1F07C1F0ULL, 0x7C1F07C1F07C1F07ULL, },
+ { 0xFC0FC0FC0FC0FC0FULL, 0xC0FC0FC0FC0FC0FCULL, },
+ { 0x03F03F03F03F03F0ULL, 0x3F03F03F03F03F03ULL, },
+ { 0xFE03F80FE03F80FEULL, 0x03F80FE03F80FE03ULL, },
+ { 0x01FC07F01FC07F01ULL, 0xFC07F01FC07F01FCULL, },
+ { 0xFF00FF00FF00FF00ULL, 0xFF00FF00FF00FF00ULL, }, /* 16 */
+ { 0x00FF00FF00FF00FFULL, 0x00FF00FF00FF00FFULL, },
+ { 0xFF803FE00FF803FEULL, 0x00FF803FE00FF803ULL, },
+ { 0x007FC01FF007FC01ULL, 0xFF007FC01FF007FCULL, },
+ { 0xFFC00FFC00FFC00FULL, 0xFC00FFC00FFC00FFULL, },
+ { 0x003FF003FF003FF0ULL, 0x03FF003FF003FF00ULL, },
+ { 0xFFE003FF800FFE00ULL, 0x3FF800FFE003FF80ULL, },
+ { 0x001FFC007FF001FFULL, 0xC007FF001FFC007FULL, },
+ { 0xFFF000FFF000FFF0ULL, 0x00FFF000FFF000FFULL, }, /* 24 */
+ { 0x000FFF000FFF000FULL, 0xFF000FFF000FFF00ULL, },
+ { 0xFFF8003FFE000FFFULL, 0x8003FFE000FFF800ULL, },
+ { 0x0007FFC001FFF000ULL, 0x7FFC001FFF0007FFULL, },
+ { 0xFFFC000FFFC000FFULL, 0xFC000FFFC000FFFCULL, },
+ { 0x0003FFF0003FFF00ULL, 0x03FFF0003FFF0003ULL, },
+ { 0xFFFE0003FFF8000FULL, 0xFFE0003FFF8000FFULL, },
+ { 0x0001FFFC0007FFF0ULL, 0x001FFFC0007FFF00ULL, },
+ { 0xFFFF0000FFFF0000ULL, 0xFFFF0000FFFF0000ULL, }, /* 32 */
+ { 0x0000FFFF0000FFFFULL, 0x0000FFFF0000FFFFULL, },
+ { 0xFFFF80003FFFE000ULL, 0x0FFFF80003FFFE00ULL, },
+ { 0x00007FFFC0001FFFULL, 0xF00007FFFC0001FFULL, },
+ { 0xFFFFC0000FFFFC00ULL, 0x00FFFFC0000FFFFCULL, },
+ { 0x00003FFFF00003FFULL, 0xFF00003FFFF00003ULL, },
+ { 0xFFFFE00003FFFF80ULL, 0x000FFFFE00003FFFULL, },
+ { 0x00001FFFFC00007FULL, 0xFFF00001FFFFC000ULL, },
+ { 0xFFFFF00000FFFFF0ULL, 0x0000FFFFF00000FFULL, }, /* 40 */
+ { 0x00000FFFFF00000FULL, 0xFFFF00000FFFFF00ULL, },
+ { 0xFFFFF800003FFFFEULL, 0x00000FFFFF800003ULL, },
+ { 0x000007FFFFC00001ULL, 0xFFFFF000007FFFFCULL, },
+ { 0xFFFFFC00000FFFFFULL, 0xC00000FFFFFC0000ULL, },
+ { 0x000003FFFFF00000ULL, 0x3FFFFF000003FFFFULL, },
+ { 0xFFFFFE000003FFFFULL, 0xF800000FFFFFE000ULL, },
+ { 0x000001FFFFFC0000ULL, 0x07FFFFF000001FFFULL, },
+ { 0xFFFFFF000000FFFFULL, 0xFF000000FFFFFF00ULL, }, /* 48 */
+ { 0x000000FFFFFF0000ULL, 0x00FFFFFF000000FFULL, },
+ { 0xFFFFFF8000003FFFULL, 0xFFE000000FFFFFF8ULL, },
+ { 0x0000007FFFFFC000ULL, 0x001FFFFFF0000007ULL, },
+ { 0xFFFFFFC000000FFFULL, 0xFFFC000000FFFFFFULL, },
+ { 0x0000003FFFFFF000ULL, 0x0003FFFFFF000000ULL, },
+ { 0xFFFFFFE0000003FFULL, 0xFFFF8000000FFFFFULL, },
+ { 0x0000001FFFFFFC00ULL, 0x00007FFFFFF00000ULL, },
+ { 0xFFFFFFF0000000FFULL, 0xFFFFF0000000FFFFULL, }, /* 56 */
+ { 0x0000000FFFFFFF00ULL, 0x00000FFFFFFF0000ULL, },
+ { 0xFFFFFFF80000003FULL, 0xFFFFFE0000000FFFULL, },
+ { 0x00000007FFFFFFC0ULL, 0x000001FFFFFFF000ULL, },
+ { 0xFFFFFFFC0000000FULL, 0xFFFFFFC0000000FFULL, },
+ { 0x00000003FFFFFFF0ULL, 0x0000003FFFFFFF00ULL, },
+ { 0xFFFFFFFE00000003ULL, 0xFFFFFFF80000000FULL, },
+ { 0x00000001FFFFFFFCULL, 0x00000007FFFFFFF0ULL, },
+};
+
+
+#define RANDOM_INPUTS_COUNT 16
+#define RANDOM_INPUTS_SHORT_COUNT 4
+
+uint64_t b128_random[RANDOM_INPUTS_COUNT][2] = {
+ { 0x886AE6CC28625540ULL, 0x4B670B5EFE7BB00CULL, }, /* 0 */
+ { 0xFBBE00634D93C708ULL, 0x12F7BB1A153F52FCULL, },
+ { 0xAC5AAEAAB9CF8B80ULL, 0x27D8C6FFAB2B2514ULL, },
+ { 0x704F164D5E31E24EULL, 0x8DF188D8A942E2A0ULL, },
+ { 0xB9926B7C7DAF4258ULL, 0xA1227CADDCCE65B6ULL, },
+ { 0xD027BE89FF0A2EF9ULL, 0x170B5050FEA53078ULL, },
+ { 0xB83B580665CABC4AULL, 0x91230822BFF0BA62ULL, },
+ { 0xFC8F23F09AA6B782ULL, 0x93FD6637124275AEULL, },
+ { 0x201E09CD56AEE649ULL, 0xEF5DE039A6A52758ULL, }, /* 8 */
+ { 0xA57CD91365D9E5D7ULL, 0x9321BC9881ECBA5CULL, },
+ { 0xA2E8F6F5C9CBC61BULL, 0xB2C471545E0D7A12ULL, },
+ { 0xA89CF2F131A864AEULL, 0xD2A3E87A5DB986E7ULL, },
+ { 0xE61438E9A652EA0AULL, 0xA85483D97879D41CULL, },
+ { 0x944A35FD192361A8ULL, 0xF3912DA36A0B2D6BULL, },
+ { 0x4630426322BEF79CULL, 0xEB5686F7CB19304EULL, },
+ { 0x8B5AA7A2F259DEADULL, 0xD278CBCD696417E3ULL, },
+};
+
+
+#endif
--- /dev/null
+/*
+ * Header file for test utilities
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef TEST_UTILS_H
+#define TEST_UTILS_H
+
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+
+#define PRINT_RESULTS 1
+
+
+static inline int32_t check_results(char *instruction_name,
+ uint32_t test_count,
+ double elapsed_time,
+ uint64_t *b128_result,
+ uint64_t *b128_expect)
+{
+#if PRINT_RESULTS
+ uint32_t ii;
+ printf("\n");
+ for (ii = 0; ii < test_count; ii++) {
+ uint64_t a, b;
+ memcpy(&a, (b128_result + 2 * ii), 8);
+ memcpy(&b, (b128_result + 2 * ii + 1), 8);
+ if (ii % 8 != 0) {
+ printf(" { 0x%016llxULL, 0x%016llxULL, },\n", a, b);
+ } else {
+ printf(" { 0x%016llxULL, 0x%016llxULL, }, /* %3d */\n",
+ a, b, ii);
+ }
+ }
+ printf("\n");
+#endif
+ uint32_t i;
+ uint32_t pass_count = 0;
+ uint32_t fail_count = 0;
+
+ printf("%s: ", instruction_name);
+ for (i = 0; i < test_count; i++) {
+ if (b128_result[i] == b128_expect[i]) {
+ pass_count++;
+ } else {
+ fail_count++;
+ }
+ }
+
+ printf("PASS: %3d FAIL: %3d elapsed time: %5.2f ms\n",
+ pass_count, fail_count, elapsed_time);
+
+ if (fail_count > 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+#endif
--- /dev/null
+/*
+ * Header file for wrappers around MSA instructions assembler invocations
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef WRAPPERS_MSA_H
+#define WRAPPERS_MSA_H
+
+
+#define DO_MSA__WD__WS(suffix, mnemonic) \
+static inline void do_msa_##suffix(void *input, void *output) \
+{ \
+ __asm__ volatile ( \
+ "move $t0, %0\n\t" \
+ "ld.d $w11, 0($t0)\n\t" \
+ #mnemonic " $w10, $w11\n\t" \
+ "move $t0, %1\n\t" \
+ "st.d $w10, 0($t0)\n\t" \
+ : \
+ : "r" (input), "r" (output) \
+ : "t0", "memory" \
+ ); \
+}
+
+DO_MSA__WD__WS(NLOC_B, nloc.b)
+DO_MSA__WD__WS(NLOC_H, nloc.h)
+DO_MSA__WD__WS(NLOC_W, nloc.w)
+DO_MSA__WD__WS(NLOC_D, nloc.d)
+
+DO_MSA__WD__WS(NLZC_B, nlzc.b)
+DO_MSA__WD__WS(NLZC_H, nlzc.h)
+DO_MSA__WD__WS(NLZC_W, nlzc.w)
+DO_MSA__WD__WS(NLZC_D, nlzc.d)
+
+DO_MSA__WD__WS(PCNT_B, pcnt.b)
+DO_MSA__WD__WS(PCNT_H, pcnt.h)
+DO_MSA__WD__WS(PCNT_W, pcnt.w)
+DO_MSA__WD__WS(PCNT_D, pcnt.d)
+
+
+#define DO_MSA__WD__WS_WT(suffix, mnemonic) \
+static inline void do_msa_##suffix(void *input1, void *input2, \
+ void *output) \
+{ \
+ __asm__ volatile ( \
+ "move $t0, %0\n\t" \
+ "ld.d $w11, 0($t0)\n\t" \
+ "move $t0, %1\n\t" \
+ "ld.d $w12, 0($t0)\n\t" \
+ #mnemonic " $w10, $w11, $w12\n\t" \
+ "move $t0, %2\n\t" \
+ "st.d $w10, 0($t0)\n\t" \
+ : \
+ : "r" (input1), "r" (input2), "r" (output) \
+ : "t0", "memory" \
+ ); \
+}
+
+DO_MSA__WD__WS_WT(ILVEV_B, ilvev.b)
+DO_MSA__WD__WS_WT(ILVEV_H, ilvev.h)
+DO_MSA__WD__WS_WT(ILVEV_W, ilvev.w)
+DO_MSA__WD__WS_WT(ILVEV_D, ilvev.d)
+
+DO_MSA__WD__WS_WT(ILVOD_B, ilvod.b)
+DO_MSA__WD__WS_WT(ILVOD_H, ilvod.h)
+DO_MSA__WD__WS_WT(ILVOD_W, ilvod.w)
+DO_MSA__WD__WS_WT(ILVOD_D, ilvod.d)
+
+DO_MSA__WD__WS_WT(ILVL_B, ilvl.b)
+DO_MSA__WD__WS_WT(ILVL_H, ilvl.h)
+DO_MSA__WD__WS_WT(ILVL_W, ilvl.w)
+DO_MSA__WD__WS_WT(ILVL_D, ilvl.d)
+
+DO_MSA__WD__WS_WT(ILVR_B, ilvr.b)
+DO_MSA__WD__WS_WT(ILVR_H, ilvr.h)
+DO_MSA__WD__WS_WT(ILVR_W, ilvr.w)
+DO_MSA__WD__WS_WT(ILVR_D, ilvr.d)
+
+DO_MSA__WD__WS_WT(AND_V, and.v)
+DO_MSA__WD__WS_WT(NOR_V, nor.v)
+DO_MSA__WD__WS_WT(OR_V, or.v)
+DO_MSA__WD__WS_WT(XOR_V, xor.v)
+
+DO_MSA__WD__WS_WT(CEQ_B, ceq.b)
+DO_MSA__WD__WS_WT(CEQ_H, ceq.h)
+DO_MSA__WD__WS_WT(CEQ_W, ceq.w)
+DO_MSA__WD__WS_WT(CEQ_D, ceq.d)
+
+DO_MSA__WD__WS_WT(CLE_S_B, cle_s.b)
+DO_MSA__WD__WS_WT(CLE_S_H, cle_s.h)
+DO_MSA__WD__WS_WT(CLE_S_W, cle_s.w)
+DO_MSA__WD__WS_WT(CLE_S_D, cle_s.d)
+
+DO_MSA__WD__WS_WT(CLE_U_B, cle_u.b)
+DO_MSA__WD__WS_WT(CLE_U_H, cle_u.h)
+DO_MSA__WD__WS_WT(CLE_U_W, cle_u.w)
+DO_MSA__WD__WS_WT(CLE_U_D, cle_u.d)
+
+DO_MSA__WD__WS_WT(CLT_S_B, clt_s.b)
+DO_MSA__WD__WS_WT(CLT_S_H, clt_s.h)
+DO_MSA__WD__WS_WT(CLT_S_W, clt_s.w)
+DO_MSA__WD__WS_WT(CLT_S_D, clt_s.d)
+
+DO_MSA__WD__WS_WT(CLT_U_B, clt_u.b)
+DO_MSA__WD__WS_WT(CLT_U_H, clt_u.h)
+DO_MSA__WD__WS_WT(CLT_U_W, clt_u.w)
+DO_MSA__WD__WS_WT(CLT_U_D, clt_u.d)
+
+DO_MSA__WD__WS_WT(MAX_A_B, max_a.b)
+DO_MSA__WD__WS_WT(MAX_A_H, max_a.h)
+DO_MSA__WD__WS_WT(MAX_A_W, max_a.w)
+DO_MSA__WD__WS_WT(MAX_A_D, max_a.d)
+
+DO_MSA__WD__WS_WT(MIN_A_B, min_a.b)
+DO_MSA__WD__WS_WT(MIN_A_H, min_a.h)
+DO_MSA__WD__WS_WT(MIN_A_W, min_a.w)
+DO_MSA__WD__WS_WT(MIN_A_D, min_a.d)
+
+DO_MSA__WD__WS_WT(MAX_S_B, max_s.b)
+DO_MSA__WD__WS_WT(MAX_S_H, max_s.h)
+DO_MSA__WD__WS_WT(MAX_S_W, max_s.w)
+DO_MSA__WD__WS_WT(MAX_S_D, max_s.d)
+
+DO_MSA__WD__WS_WT(MIN_S_B, min_s.b)
+DO_MSA__WD__WS_WT(MIN_S_H, min_s.h)
+DO_MSA__WD__WS_WT(MIN_S_W, min_s.w)
+DO_MSA__WD__WS_WT(MIN_S_D, min_s.d)
+
+DO_MSA__WD__WS_WT(MAX_U_B, max_u.b)
+DO_MSA__WD__WS_WT(MAX_U_H, max_u.h)
+DO_MSA__WD__WS_WT(MAX_U_W, max_u.w)
+DO_MSA__WD__WS_WT(MAX_U_D, max_u.d)
+
+DO_MSA__WD__WS_WT(MIN_U_B, min_u.b)
+DO_MSA__WD__WS_WT(MIN_U_H, min_u.h)
+DO_MSA__WD__WS_WT(MIN_U_W, min_u.w)
+DO_MSA__WD__WS_WT(MIN_U_D, min_u.d)
+
+
+#endif
+++ /dev/null
-[Dolphin]
-Timestamp=2012,8,3,16,41,52
--- /dev/null
+/*
+ * Test program for MSA instruction NLOC.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "NLOC.B";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0808080808080808ULL, 0x0808080808080808ULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0202020202020202ULL, 0x0202020202020202ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0301000301000301ULL, 0x0003010003010003ULL, },
+ { 0x0000020000020000ULL, 0x0200000200000200ULL, },
+ { 0x0404040404040404ULL, 0x0404040404040404ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0500000103050000ULL, 0x0103050000010305ULL, },
+ { 0x0002040000000204ULL, 0x0000000204000000ULL, },
+ { 0x0600020600020600ULL, 0x0206000206000206ULL, },
+ { 0x0004000004000004ULL, 0x0000040000040000ULL, },
+ { 0x0700050003000107ULL, 0x0005000300010700ULL, },
+ { 0x0006000400020000ULL, 0x0600040002000006ULL, },
+ { 0x0800080008000800ULL, 0x0800080008000800ULL, }, /* 16 */
+ { 0x0008000800080008ULL, 0x0008000800080008ULL, },
+ { 0x0801000300050007ULL, 0x0008010003000500ULL, },
+ { 0x0000020004000600ULL, 0x0800000200040006ULL, },
+ { 0x0802000600080200ULL, 0x0600080200060008ULL, },
+ { 0x0000040008000004ULL, 0x0008000004000800ULL, },
+ { 0x0803000801000700ULL, 0x0005000803000801ULL, },
+ { 0x0000060000040008ULL, 0x0200080000060000ULL, },
+ { 0x0804000804000804ULL, 0x0008040008040008ULL, }, /* 24 */
+ { 0x0000080000080000ULL, 0x0800000800000800ULL, },
+ { 0x0805000007000008ULL, 0x0100080300080500ULL, },
+ { 0x0000080200080400ULL, 0x0006000008000008ULL, },
+ { 0x0806000008020008ULL, 0x0600000802000806ULL, },
+ { 0x0000080400000800ULL, 0x0008040000080000ULL, },
+ { 0x0807000008050000ULL, 0x0803000008010008ULL, },
+ { 0x0000080600000804ULL, 0x0000080200000800ULL, },
+ { 0x0808000008080000ULL, 0x0808000008080000ULL, }, /* 32 */
+ { 0x0000080800000808ULL, 0x0000080800000808ULL, },
+ { 0x0808010000080300ULL, 0x0008050000080700ULL, },
+ { 0x0000000802000008ULL, 0x0400000806000008ULL, },
+ { 0x0808020000080600ULL, 0x0008080200000806ULL, },
+ { 0x0000000804000008ULL, 0x0800000008040000ULL, },
+ { 0x0808030000080801ULL, 0x0000080700000008ULL, },
+ { 0x0000000806000000ULL, 0x0804000008080200ULL, },
+ { 0x0808040000080804ULL, 0x0000080804000008ULL, }, /* 40 */
+ { 0x0000000808000000ULL, 0x0808000000080800ULL, },
+ { 0x0808050000000807ULL, 0x0000000808010000ULL, },
+ { 0x0000000808020000ULL, 0x0808040000000806ULL, },
+ { 0x0808060000000808ULL, 0x0200000808060000ULL, },
+ { 0x0000000808040000ULL, 0x0008080000000808ULL, },
+ { 0x0808070000000808ULL, 0x0500000008080300ULL, },
+ { 0x0000000808060000ULL, 0x0008080400000008ULL, },
+ { 0x0808080000000808ULL, 0x0800000008080800ULL, }, /* 48 */
+ { 0x0000000808080000ULL, 0x0008080800000008ULL, },
+ { 0x0808080100000008ULL, 0x0803000000080805ULL, },
+ { 0x0000000008080200ULL, 0x0000080804000000ULL, },
+ { 0x0808080200000008ULL, 0x0806000000080808ULL, },
+ { 0x0000000008080400ULL, 0x0000080808000000ULL, },
+ { 0x0808080300000008ULL, 0x0808010000000808ULL, },
+ { 0x0000000008080600ULL, 0x0000000808040000ULL, },
+ { 0x0808080400000008ULL, 0x0808040000000808ULL, }, /* 56 */
+ { 0x0000000008080800ULL, 0x0000000808080000ULL, },
+ { 0x0808080500000000ULL, 0x0808070000000008ULL, },
+ { 0x0000000008080802ULL, 0x0000000808080400ULL, },
+ { 0x0808080600000000ULL, 0x0808080200000008ULL, },
+ { 0x0000000008080804ULL, 0x0000000008080800ULL, },
+ { 0x0808080700000000ULL, 0x0808080500000000ULL, },
+ { 0x0000000008080806ULL, 0x0000000008080804ULL, },
+ { 0x0100030200000000ULL, 0x0000000007000100ULL, }, /* 64 */
+ { 0x0501000000010200ULL, 0x0004010000000006ULL, },
+ { 0x0100010101020101ULL, 0x0002020801000000ULL, },
+ { 0x0000000000000300ULL, 0x0104010201000301ULL, },
+ { 0x0101000000010000ULL, 0x0100000102020001ULL, },
+ { 0x0200010108000005ULL, 0x0000000007010000ULL, },
+ { 0x0100000000020100ULL, 0x0100000001040100ULL, },
+ { 0x0601000401010101ULL, 0x0106000000000001ULL, },
+ { 0x0000000200010300ULL, 0x0300030001010000ULL, }, /* 72 */
+ { 0x0100020000020302ULL, 0x0100010101030100ULL, },
+ { 0x0103040402020200ULL, 0x0102000000000000ULL, },
+ { 0x0101040400010001ULL, 0x0201030000010103ULL, },
+ { 0x0300000301000300ULL, 0x0100010200000200ULL, },
+ { 0x0100000600000001ULL, 0x0401000100000000ULL, },
+ { 0x0000000000010401ULL, 0x0300010402000000ULL, },
+ { 0x0100010104000201ULL, 0x0200020200000003ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_COUNT) {
+ do_msa_NLOC_B(b128_pattern[i], b128_result[i]);
+ } else {
+ do_msa_NLOC_B(b128_random[i - PATTERN_INPUTS_COUNT],
+ b128_result[i]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction NLOC.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "NLOC.D";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000040ULL, 0x0000000000000040ULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000002ULL, 0x0000000000000002ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000003ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000002ULL, },
+ { 0x0000000000000004ULL, 0x0000000000000004ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000005ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000006ULL, 0x0000000000000002ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000007ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000006ULL, },
+ { 0x0000000000000008ULL, 0x0000000000000008ULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000009ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000008ULL, },
+ { 0x000000000000000aULL, 0x0000000000000006ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000000bULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000002ULL, },
+ { 0x000000000000000cULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000008ULL, },
+ { 0x000000000000000dULL, 0x0000000000000001ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000000eULL, 0x0000000000000006ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000000fULL, 0x000000000000000bULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000010ULL, 0x0000000000000010ULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000011ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000004ULL, },
+ { 0x0000000000000012ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000008ULL, },
+ { 0x0000000000000013ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x000000000000000cULL, },
+ { 0x0000000000000014ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000010ULL, },
+ { 0x0000000000000015ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000014ULL, },
+ { 0x0000000000000016ULL, 0x0000000000000002ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000017ULL, 0x0000000000000005ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000018ULL, 0x0000000000000008ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000019ULL, 0x000000000000000bULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000001aULL, 0x000000000000000eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000001bULL, 0x0000000000000011ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000001cULL, 0x0000000000000014ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000001dULL, 0x0000000000000017ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000001eULL, 0x000000000000001aULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000001fULL, 0x000000000000001dULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0x0000000000000005ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000002ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000006ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000003ULL, }, /* 72 */
+ { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000002ULL, },
+ { 0x0000000000000003ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000004ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000003ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000002ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_COUNT) {
+ do_msa_NLOC_D(b128_pattern[i], b128_result[i]);
+ } else {
+ do_msa_NLOC_D(b128_random[i - PATTERN_INPUTS_COUNT],
+ b128_result[i]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction NLOC.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "NLOC.H";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0010001000100010ULL, 0x0010001000100010ULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0002000200020002ULL, 0x0002000200020002ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0003000000010003ULL, 0x0000000100030000ULL, },
+ { 0x0000000200000000ULL, 0x0002000000000002ULL, },
+ { 0x0004000400040004ULL, 0x0004000400040004ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0005000000030000ULL, 0x0001000500000003ULL, },
+ { 0x0000000400000002ULL, 0x0000000000040000ULL, },
+ { 0x0006000200000006ULL, 0x0002000000060002ULL, },
+ { 0x0000000000040000ULL, 0x0000000400000000ULL, },
+ { 0x0007000500030001ULL, 0x0000000000000007ULL, },
+ { 0x0000000000000000ULL, 0x0006000400020000ULL, },
+ { 0x0008000800080008ULL, 0x0008000800080008ULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0009000000000000ULL, 0x0000000100030005ULL, },
+ { 0x0000000200040006ULL, 0x0008000000000000ULL, },
+ { 0x000a000000000002ULL, 0x0006000a00000000ULL, },
+ { 0x0000000400080000ULL, 0x0000000000040008ULL, },
+ { 0x000b000000010007ULL, 0x0000000000030009ULL, },
+ { 0x0000000600000000ULL, 0x0002000800000000ULL, },
+ { 0x000c00000004000cULL, 0x00000004000c0000ULL, }, /* 24 */
+ { 0x0000000800000000ULL, 0x0008000000000008ULL, },
+ { 0x000d000000070000ULL, 0x0001000b00000005ULL, },
+ { 0x0000000a00000004ULL, 0x0000000000080000ULL, },
+ { 0x000e0000000a0000ULL, 0x000600000002000eULL, },
+ { 0x0000000c00000008ULL, 0x0000000400000000ULL, },
+ { 0x000f0000000d0000ULL, 0x000b000000090000ULL, },
+ { 0x0000000e0000000cULL, 0x0000000a00000008ULL, },
+ { 0x0010000000100000ULL, 0x0010000000100000ULL, }, /* 32 */
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, },
+ { 0x0010000100000003ULL, 0x0000000500000007ULL, },
+ { 0x0000000000020000ULL, 0x0004000000060000ULL, },
+ { 0x0010000200000006ULL, 0x0000000a0000000eULL, },
+ { 0x0000000000040000ULL, 0x00080000000c0000ULL, },
+ { 0x0010000300000009ULL, 0x0000000f00000000ULL, },
+ { 0x0000000000060000ULL, 0x000c000000100002ULL, },
+ { 0x001000040000000cULL, 0x0000001000040000ULL, }, /* 40 */
+ { 0x0000000000080000ULL, 0x0010000000000008ULL, },
+ { 0x001000050000000fULL, 0x0000000000090000ULL, },
+ { 0x00000000000a0000ULL, 0x001000040000000eULL, },
+ { 0x0010000600000010ULL, 0x00020000000e0000ULL, },
+ { 0x00000000000c0000ULL, 0x0000000800000010ULL, },
+ { 0x0010000700000010ULL, 0x0005000000100003ULL, },
+ { 0x00000000000e0000ULL, 0x0000000c00000000ULL, },
+ { 0x0010000800000010ULL, 0x0008000000100008ULL, }, /* 48 */
+ { 0x0000000000100000ULL, 0x0000001000000000ULL, },
+ { 0x0010000900000000ULL, 0x000b00000000000dULL, },
+ { 0x0000000000100002ULL, 0x0000001000040000ULL, },
+ { 0x0010000a00000000ULL, 0x000e000000000010ULL, },
+ { 0x0000000000100004ULL, 0x0000001000080000ULL, },
+ { 0x0010000b00000000ULL, 0x0010000100000010ULL, },
+ { 0x0000000000100006ULL, 0x00000000000c0000ULL, },
+ { 0x0010000c00000000ULL, 0x0010000400000010ULL, }, /* 56 */
+ { 0x0000000000100008ULL, 0x0000000000100000ULL, },
+ { 0x0010000d00000000ULL, 0x0010000700000000ULL, },
+ { 0x000000000010000aULL, 0x0000000000100004ULL, },
+ { 0x0010000e00000000ULL, 0x0010000a00000000ULL, },
+ { 0x000000000010000cULL, 0x0000000000100008ULL, },
+ { 0x0010000f00000000ULL, 0x0010000d00000000ULL, },
+ { 0x000000000010000eULL, 0x000000000010000cULL, },
+ { 0x0001000300000000ULL, 0x0000000000070001ULL, }, /* 64 */
+ { 0x0005000000000002ULL, 0x0000000100000000ULL, },
+ { 0x0001000100010001ULL, 0x0000000200010000ULL, },
+ { 0x0000000000000003ULL, 0x0001000100010003ULL, },
+ { 0x0001000000000000ULL, 0x0001000000020000ULL, },
+ { 0x0002000100080000ULL, 0x0000000000070000ULL, },
+ { 0x0001000000000001ULL, 0x0001000000010001ULL, },
+ { 0x0006000000010001ULL, 0x0001000000000000ULL, },
+ { 0x0000000000000003ULL, 0x0003000300010000ULL, }, /* 72 */
+ { 0x0001000200000003ULL, 0x0001000100010001ULL, },
+ { 0x0001000400020002ULL, 0x0001000000000000ULL, },
+ { 0x0001000400000000ULL, 0x0002000300000001ULL, },
+ { 0x0003000000010003ULL, 0x0001000100000002ULL, },
+ { 0x0001000000000000ULL, 0x0004000000000000ULL, },
+ { 0x0000000000000004ULL, 0x0003000100020000ULL, },
+ { 0x0001000100040002ULL, 0x0002000200000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_COUNT) {
+ do_msa_NLOC_H(b128_pattern[i], b128_result[i]);
+ } else {
+ do_msa_NLOC_H(b128_random[i - PATTERN_INPUTS_COUNT],
+ b128_result[i]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction NLOC.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "NLOC.W";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000002000000020ULL, 0x0000002000000020ULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000200000002ULL, 0x0000000200000002ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000300000001ULL, 0x0000000000000003ULL, },
+ { 0x0000000000000000ULL, 0x0000000200000000ULL, },
+ { 0x0000000400000004ULL, 0x0000000400000004ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000500000003ULL, 0x0000000100000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000004ULL, },
+ { 0x0000000600000000ULL, 0x0000000200000006ULL, },
+ { 0x0000000000000004ULL, 0x0000000000000000ULL, },
+ { 0x0000000700000003ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000600000002ULL, },
+ { 0x0000000800000008ULL, 0x0000000800000008ULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000900000000ULL, 0x0000000000000003ULL, },
+ { 0x0000000000000004ULL, 0x0000000800000000ULL, },
+ { 0x0000000a00000000ULL, 0x0000000600000000ULL, },
+ { 0x0000000000000008ULL, 0x0000000000000004ULL, },
+ { 0x0000000b00000001ULL, 0x0000000000000003ULL, },
+ { 0x0000000000000000ULL, 0x0000000200000000ULL, },
+ { 0x0000000c00000004ULL, 0x000000000000000cULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000800000000ULL, },
+ { 0x0000000d00000007ULL, 0x0000000100000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000008ULL, },
+ { 0x0000000e0000000aULL, 0x0000000600000002ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000f0000000dULL, 0x0000000b00000009ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000001100000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000002ULL, 0x0000000400000006ULL, },
+ { 0x0000001200000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000004ULL, 0x000000080000000cULL, },
+ { 0x0000001300000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000006ULL, 0x0000000c00000012ULL, },
+ { 0x0000001400000000ULL, 0x0000000000000004ULL, }, /* 40 */
+ { 0x0000000000000008ULL, 0x0000001000000000ULL, },
+ { 0x0000001500000000ULL, 0x0000000000000009ULL, },
+ { 0x000000000000000aULL, 0x0000001400000000ULL, },
+ { 0x0000001600000000ULL, 0x000000020000000eULL, },
+ { 0x000000000000000cULL, 0x0000000000000000ULL, },
+ { 0x0000001700000000ULL, 0x0000000500000013ULL, },
+ { 0x000000000000000eULL, 0x0000000000000000ULL, },
+ { 0x0000001800000000ULL, 0x0000000800000018ULL, }, /* 48 */
+ { 0x0000000000000010ULL, 0x0000000000000000ULL, },
+ { 0x0000001900000000ULL, 0x0000000b00000000ULL, },
+ { 0x0000000000000012ULL, 0x0000000000000004ULL, },
+ { 0x0000001a00000000ULL, 0x0000000e00000000ULL, },
+ { 0x0000000000000014ULL, 0x0000000000000008ULL, },
+ { 0x0000001b00000000ULL, 0x0000001100000000ULL, },
+ { 0x0000000000000016ULL, 0x000000000000000cULL, },
+ { 0x0000001c00000000ULL, 0x0000001400000000ULL, }, /* 56 */
+ { 0x0000000000000018ULL, 0x0000000000000010ULL, },
+ { 0x0000001d00000000ULL, 0x0000001700000000ULL, },
+ { 0x000000000000001aULL, 0x0000000000000014ULL, },
+ { 0x0000001e00000000ULL, 0x0000001a00000000ULL, },
+ { 0x000000000000001cULL, 0x0000000000000018ULL, },
+ { 0x0000001f00000000ULL, 0x0000001d00000000ULL, },
+ { 0x000000000000001eULL, 0x000000000000001cULL, },
+ { 0x0000000100000000ULL, 0x0000000000000007ULL, }, /* 64 */
+ { 0x0000000500000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000100000001ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000000ULL, 0x0000000100000001ULL, },
+ { 0x0000000100000000ULL, 0x0000000100000002ULL, },
+ { 0x0000000200000008ULL, 0x0000000000000007ULL, },
+ { 0x0000000100000000ULL, 0x0000000100000001ULL, },
+ { 0x0000000600000001ULL, 0x0000000100000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000300000001ULL, }, /* 72 */
+ { 0x0000000100000000ULL, 0x0000000100000001ULL, },
+ { 0x0000000100000002ULL, 0x0000000100000000ULL, },
+ { 0x0000000100000000ULL, 0x0000000200000000ULL, },
+ { 0x0000000300000001ULL, 0x0000000100000000ULL, },
+ { 0x0000000100000000ULL, 0x0000000400000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000300000002ULL, },
+ { 0x0000000100000004ULL, 0x0000000200000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_COUNT) {
+ do_msa_NLOC_W(b128_pattern[i], b128_result[i]);
+ } else {
+ do_msa_NLOC_W(b128_random[i - PATTERN_INPUTS_COUNT],
+ b128_result[i]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction NLZC.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "NLZC.B";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0x0808080808080808ULL, 0x0808080808080808ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0202020202020202ULL, 0x0202020202020202ULL, },
+ { 0x0000020000020000ULL, 0x0200000200000200ULL, },
+ { 0x0301000301000301ULL, 0x0003010003010003ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0404040404040404ULL, 0x0404040404040404ULL, },
+ { 0x0002040000000204ULL, 0x0000000204000000ULL, },
+ { 0x0500000103050000ULL, 0x0103050000010305ULL, },
+ { 0x0004000004000004ULL, 0x0000040000040000ULL, },
+ { 0x0600020600020600ULL, 0x0206000206000206ULL, },
+ { 0x0006000400020000ULL, 0x0600040002000006ULL, },
+ { 0x0700050003000107ULL, 0x0005000300010700ULL, },
+ { 0x0008000800080008ULL, 0x0008000800080008ULL, }, /* 16 */
+ { 0x0800080008000800ULL, 0x0800080008000800ULL, },
+ { 0x0000020004000600ULL, 0x0800000200040006ULL, },
+ { 0x0801000300050007ULL, 0x0008010003000500ULL, },
+ { 0x0000040008000004ULL, 0x0008000004000800ULL, },
+ { 0x0802000600080200ULL, 0x0600080200060008ULL, },
+ { 0x0000060000040008ULL, 0x0200080000060000ULL, },
+ { 0x0803000801000700ULL, 0x0005000803000801ULL, },
+ { 0x0000080000080000ULL, 0x0800000800000800ULL, }, /* 24 */
+ { 0x0804000804000804ULL, 0x0008040008040008ULL, },
+ { 0x0000080200080400ULL, 0x0006000008000008ULL, },
+ { 0x0805000007000008ULL, 0x0100080300080500ULL, },
+ { 0x0000080400000800ULL, 0x0008040000080000ULL, },
+ { 0x0806000008020008ULL, 0x0600000802000806ULL, },
+ { 0x0000080600000804ULL, 0x0000080200000800ULL, },
+ { 0x0807000008050000ULL, 0x0803000008010008ULL, },
+ { 0x0000080800000808ULL, 0x0000080800000808ULL, }, /* 32 */
+ { 0x0808000008080000ULL, 0x0808000008080000ULL, },
+ { 0x0000000802000008ULL, 0x0400000806000008ULL, },
+ { 0x0808010000080300ULL, 0x0008050000080700ULL, },
+ { 0x0000000804000008ULL, 0x0800000008040000ULL, },
+ { 0x0808020000080600ULL, 0x0008080200000806ULL, },
+ { 0x0000000806000000ULL, 0x0804000008080200ULL, },
+ { 0x0808030000080801ULL, 0x0000080700000008ULL, },
+ { 0x0000000808000000ULL, 0x0808000000080800ULL, }, /* 40 */
+ { 0x0808040000080804ULL, 0x0000080804000008ULL, },
+ { 0x0000000808020000ULL, 0x0808040000000806ULL, },
+ { 0x0808050000000807ULL, 0x0000000808010000ULL, },
+ { 0x0000000808040000ULL, 0x0008080000000808ULL, },
+ { 0x0808060000000808ULL, 0x0200000808060000ULL, },
+ { 0x0000000808060000ULL, 0x0008080400000008ULL, },
+ { 0x0808070000000808ULL, 0x0500000008080300ULL, },
+ { 0x0000000808080000ULL, 0x0008080800000008ULL, }, /* 48 */
+ { 0x0808080000000808ULL, 0x0800000008080800ULL, },
+ { 0x0000000008080200ULL, 0x0000080804000000ULL, },
+ { 0x0808080100000008ULL, 0x0803000000080805ULL, },
+ { 0x0000000008080400ULL, 0x0000080808000000ULL, },
+ { 0x0808080200000008ULL, 0x0806000000080808ULL, },
+ { 0x0000000008080600ULL, 0x0000000808040000ULL, },
+ { 0x0808080300000008ULL, 0x0808010000000808ULL, },
+ { 0x0000000008080800ULL, 0x0000000808080000ULL, }, /* 56 */
+ { 0x0808080400000008ULL, 0x0808040000000808ULL, },
+ { 0x0000000008080802ULL, 0x0000000808080400ULL, },
+ { 0x0808080500000000ULL, 0x0808070000000008ULL, },
+ { 0x0000000008080804ULL, 0x0000000008080800ULL, },
+ { 0x0808080600000000ULL, 0x0808080200000008ULL, },
+ { 0x0000000008080806ULL, 0x0000000008080804ULL, },
+ { 0x0808080700000000ULL, 0x0808080500000000ULL, },
+ { 0x0001000002010101ULL, 0x0101040100010004ULL, }, /* 64 */
+ { 0x0000080101000004ULL, 0x0300000303020100ULL, },
+ { 0x0001000000000000ULL, 0x0200000000020203ULL, },
+ { 0x0101030101020001ULL, 0x0000000000010000ULL, },
+ { 0x0000010101000101ULL, 0x0002010000000100ULL, },
+ { 0x0002000000040200ULL, 0x0304010100000201ULL, },
+ { 0x0002010501000001ULL, 0x0002040200000001ULL, },
+ { 0x0000020000000000ULL, 0x0000010203010100ULL, },
+ { 0x0203040001000001ULL, 0x0001000200000201ULL, }, /* 72 */
+ { 0x0001000301000000ULL, 0x0002000000000001ULL, },
+ { 0x0000000000000003ULL, 0x0000010101040103ULL, },
+ { 0x0000000002000100ULL, 0x0000000101000000ULL, },
+ { 0x0003020000010004ULL, 0x0001000001010003ULL, },
+ { 0x0001020003020100ULL, 0x0000020001040201ULL, },
+ { 0x0102010102000000ULL, 0x0001000000030201ULL, },
+ { 0x0001000000010000ULL, 0x0001000001010300ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_COUNT) {
+ do_msa_NLZC_B(b128_pattern[i], b128_result[i]);
+ } else {
+ do_msa_NLZC_B(b128_random[i - PATTERN_INPUTS_COUNT],
+ b128_result[i]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction NLZC.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "NLZC.D";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0x0000000000000040ULL, 0x0000000000000040ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000002ULL, 0x0000000000000002ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000002ULL, },
+ { 0x0000000000000003ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000004ULL, 0x0000000000000004ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000005ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000006ULL, 0x0000000000000002ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000006ULL, },
+ { 0x0000000000000007ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */
+ { 0x0000000000000008ULL, 0x0000000000000008ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000008ULL, },
+ { 0x0000000000000009ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000000aULL, 0x0000000000000006ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000002ULL, },
+ { 0x000000000000000bULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000008ULL, }, /* 24 */
+ { 0x000000000000000cULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000000dULL, 0x0000000000000001ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000000eULL, 0x0000000000000006ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000000fULL, 0x000000000000000bULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */
+ { 0x0000000000000010ULL, 0x0000000000000010ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000004ULL, },
+ { 0x0000000000000011ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000008ULL, },
+ { 0x0000000000000012ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x000000000000000cULL, },
+ { 0x0000000000000013ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000010ULL, }, /* 40 */
+ { 0x0000000000000014ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000014ULL, },
+ { 0x0000000000000015ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000016ULL, 0x0000000000000002ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000017ULL, 0x0000000000000005ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0x0000000000000018ULL, 0x0000000000000008ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000019ULL, 0x000000000000000bULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000001aULL, 0x000000000000000eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000001bULL, 0x0000000000000011ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */
+ { 0x000000000000001cULL, 0x0000000000000014ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000001dULL, 0x0000000000000017ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000001eULL, 0x000000000000001aULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000001fULL, 0x000000000000001dULL, },
+ { 0x0000000000000000ULL, 0x0000000000000001ULL, }, /* 64 */
+ { 0x0000000000000000ULL, 0x0000000000000003ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000002ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000003ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000002ULL, 0x0000000000000000ULL, }, /* 72 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_COUNT) {
+ do_msa_NLZC_D(b128_pattern[i], b128_result[i]);
+ } else {
+ do_msa_NLZC_D(b128_random[i - PATTERN_INPUTS_COUNT],
+ b128_result[i]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction NLZC.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "NLZC.H";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0x0010001000100010ULL, 0x0010001000100010ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0002000200020002ULL, 0x0002000200020002ULL, },
+ { 0x0000000200000000ULL, 0x0002000000000002ULL, },
+ { 0x0003000000010003ULL, 0x0000000100030000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0004000400040004ULL, 0x0004000400040004ULL, },
+ { 0x0000000400000002ULL, 0x0000000000040000ULL, },
+ { 0x0005000000030000ULL, 0x0001000500000003ULL, },
+ { 0x0000000000040000ULL, 0x0000000400000000ULL, },
+ { 0x0006000200000006ULL, 0x0002000000060002ULL, },
+ { 0x0000000000000000ULL, 0x0006000400020000ULL, },
+ { 0x0007000500030001ULL, 0x0000000000000007ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */
+ { 0x0008000800080008ULL, 0x0008000800080008ULL, },
+ { 0x0000000200040006ULL, 0x0008000000000000ULL, },
+ { 0x0009000000000000ULL, 0x0000000100030005ULL, },
+ { 0x0000000400080000ULL, 0x0000000000040008ULL, },
+ { 0x000a000000000002ULL, 0x0006000a00000000ULL, },
+ { 0x0000000600000000ULL, 0x0002000800000000ULL, },
+ { 0x000b000000010007ULL, 0x0000000000030009ULL, },
+ { 0x0000000800000000ULL, 0x0008000000000008ULL, }, /* 24 */
+ { 0x000c00000004000cULL, 0x00000004000c0000ULL, },
+ { 0x0000000a00000004ULL, 0x0000000000080000ULL, },
+ { 0x000d000000070000ULL, 0x0001000b00000005ULL, },
+ { 0x0000000c00000008ULL, 0x0000000400000000ULL, },
+ { 0x000e0000000a0000ULL, 0x000600000002000eULL, },
+ { 0x0000000e0000000cULL, 0x0000000a00000008ULL, },
+ { 0x000f0000000d0000ULL, 0x000b000000090000ULL, },
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, }, /* 32 */
+ { 0x0010000000100000ULL, 0x0010000000100000ULL, },
+ { 0x0000000000020000ULL, 0x0004000000060000ULL, },
+ { 0x0010000100000003ULL, 0x0000000500000007ULL, },
+ { 0x0000000000040000ULL, 0x00080000000c0000ULL, },
+ { 0x0010000200000006ULL, 0x0000000a0000000eULL, },
+ { 0x0000000000060000ULL, 0x000c000000100002ULL, },
+ { 0x0010000300000009ULL, 0x0000000f00000000ULL, },
+ { 0x0000000000080000ULL, 0x0010000000000008ULL, }, /* 40 */
+ { 0x001000040000000cULL, 0x0000001000040000ULL, },
+ { 0x00000000000a0000ULL, 0x001000040000000eULL, },
+ { 0x001000050000000fULL, 0x0000000000090000ULL, },
+ { 0x00000000000c0000ULL, 0x0000000800000010ULL, },
+ { 0x0010000600000010ULL, 0x00020000000e0000ULL, },
+ { 0x00000000000e0000ULL, 0x0000000c00000000ULL, },
+ { 0x0010000700000010ULL, 0x0005000000100003ULL, },
+ { 0x0000000000100000ULL, 0x0000001000000000ULL, }, /* 48 */
+ { 0x0010000800000010ULL, 0x0008000000100008ULL, },
+ { 0x0000000000100002ULL, 0x0000001000040000ULL, },
+ { 0x0010000900000000ULL, 0x000b00000000000dULL, },
+ { 0x0000000000100004ULL, 0x0000001000080000ULL, },
+ { 0x0010000a00000000ULL, 0x000e000000000010ULL, },
+ { 0x0000000000100006ULL, 0x00000000000c0000ULL, },
+ { 0x0010000b00000000ULL, 0x0010000100000010ULL, },
+ { 0x0000000000100008ULL, 0x0000000000100000ULL, }, /* 56 */
+ { 0x0010000c00000000ULL, 0x0010000400000010ULL, },
+ { 0x000000000010000aULL, 0x0000000000100004ULL, },
+ { 0x0010000d00000000ULL, 0x0010000700000000ULL, },
+ { 0x000000000010000cULL, 0x0000000000100008ULL, },
+ { 0x0010000e00000000ULL, 0x0010000a00000000ULL, },
+ { 0x000000000010000eULL, 0x000000000010000cULL, },
+ { 0x0010000f00000000ULL, 0x0010000d00000000ULL, },
+ { 0x0000000000020001ULL, 0x0001000400000000ULL, }, /* 64 */
+ { 0x0000000900010000ULL, 0x0003000000030001ULL, },
+ { 0x0000000000000000ULL, 0x0002000000000002ULL, },
+ { 0x0001000300010000ULL, 0x0000000000000000ULL, },
+ { 0x0000000100010001ULL, 0x0000000100000001ULL, },
+ { 0x0000000000000002ULL, 0x0003000100000002ULL, },
+ { 0x0000000100010000ULL, 0x0000000400000000ULL, },
+ { 0x0000000200000000ULL, 0x0000000100030001ULL, },
+ { 0x0002000400010000ULL, 0x0000000000000002ULL, }, /* 72 */
+ { 0x0000000000010000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000100010001ULL, },
+ { 0x0000000000020001ULL, 0x0000000000010000ULL, },
+ { 0x0000000200000000ULL, 0x0000000000010000ULL, },
+ { 0x0000000200030001ULL, 0x0000000200010002ULL, },
+ { 0x0001000100020000ULL, 0x0000000000000002ULL, },
+ { 0x0000000000000000ULL, 0x0000000000010003ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_COUNT) {
+ do_msa_NLZC_H(b128_pattern[i], b128_result[i]);
+ } else {
+ do_msa_NLZC_H(b128_random[i - PATTERN_INPUTS_COUNT],
+ b128_result[i]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction NLZC.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "NLZC.W";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0x0000002000000020ULL, 0x0000002000000020ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000200000002ULL, 0x0000000200000002ULL, },
+ { 0x0000000000000000ULL, 0x0000000200000000ULL, },
+ { 0x0000000300000001ULL, 0x0000000000000003ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000400000004ULL, 0x0000000400000004ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000004ULL, },
+ { 0x0000000500000003ULL, 0x0000000100000000ULL, },
+ { 0x0000000000000004ULL, 0x0000000000000000ULL, },
+ { 0x0000000600000000ULL, 0x0000000200000006ULL, },
+ { 0x0000000000000000ULL, 0x0000000600000002ULL, },
+ { 0x0000000700000003ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */
+ { 0x0000000800000008ULL, 0x0000000800000008ULL, },
+ { 0x0000000000000004ULL, 0x0000000800000000ULL, },
+ { 0x0000000900000000ULL, 0x0000000000000003ULL, },
+ { 0x0000000000000008ULL, 0x0000000000000004ULL, },
+ { 0x0000000a00000000ULL, 0x0000000600000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000200000000ULL, },
+ { 0x0000000b00000001ULL, 0x0000000000000003ULL, },
+ { 0x0000000000000000ULL, 0x0000000800000000ULL, }, /* 24 */
+ { 0x0000000c00000004ULL, 0x000000000000000cULL, },
+ { 0x0000000000000000ULL, 0x0000000000000008ULL, },
+ { 0x0000000d00000007ULL, 0x0000000100000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000e0000000aULL, 0x0000000600000002ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000f0000000dULL, 0x0000000b00000009ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, },
+ { 0x0000000000000002ULL, 0x0000000400000006ULL, },
+ { 0x0000001100000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000004ULL, 0x000000080000000cULL, },
+ { 0x0000001200000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000006ULL, 0x0000000c00000012ULL, },
+ { 0x0000001300000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000008ULL, 0x0000001000000000ULL, }, /* 40 */
+ { 0x0000001400000000ULL, 0x0000000000000004ULL, },
+ { 0x000000000000000aULL, 0x0000001400000000ULL, },
+ { 0x0000001500000000ULL, 0x0000000000000009ULL, },
+ { 0x000000000000000cULL, 0x0000000000000000ULL, },
+ { 0x0000001600000000ULL, 0x000000020000000eULL, },
+ { 0x000000000000000eULL, 0x0000000000000000ULL, },
+ { 0x0000001700000000ULL, 0x0000000500000013ULL, },
+ { 0x0000000000000010ULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0x0000001800000000ULL, 0x0000000800000018ULL, },
+ { 0x0000000000000012ULL, 0x0000000000000004ULL, },
+ { 0x0000001900000000ULL, 0x0000000b00000000ULL, },
+ { 0x0000000000000014ULL, 0x0000000000000008ULL, },
+ { 0x0000001a00000000ULL, 0x0000000e00000000ULL, },
+ { 0x0000000000000016ULL, 0x000000000000000cULL, },
+ { 0x0000001b00000000ULL, 0x0000001100000000ULL, },
+ { 0x0000000000000018ULL, 0x0000000000000010ULL, }, /* 56 */
+ { 0x0000001c00000000ULL, 0x0000001400000000ULL, },
+ { 0x000000000000001aULL, 0x0000000000000014ULL, },
+ { 0x0000001d00000000ULL, 0x0000001700000000ULL, },
+ { 0x000000000000001cULL, 0x0000000000000018ULL, },
+ { 0x0000001e00000000ULL, 0x0000001a00000000ULL, },
+ { 0x000000000000001eULL, 0x000000000000001cULL, },
+ { 0x0000001f00000000ULL, 0x0000001d00000000ULL, },
+ { 0x0000000000000002ULL, 0x0000000100000000ULL, }, /* 64 */
+ { 0x0000000000000001ULL, 0x0000000300000003ULL, },
+ { 0x0000000000000000ULL, 0x0000000200000000ULL, },
+ { 0x0000000100000001ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000300000000ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000003ULL, },
+ { 0x0000000200000001ULL, 0x0000000000000000ULL, }, /* 72 */
+ { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000002ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000001ULL, },
+ { 0x0000000000000003ULL, 0x0000000000000001ULL, },
+ { 0x0000000100000002ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000001ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_COUNT) {
+ do_msa_NLZC_W(b128_pattern[i], b128_result[i]);
+ } else {
+ do_msa_NLZC_W(b128_random[i - PATTERN_INPUTS_COUNT],
+ b128_result[i]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction PCNT.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "PCNT.B";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0808080808080808ULL, 0x0808080808080808ULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0404040404040404ULL, 0x0404040404040404ULL, },
+ { 0x0404040404040404ULL, 0x0404040404040404ULL, },
+ { 0x0404040404040404ULL, 0x0404040404040404ULL, },
+ { 0x0404040404040404ULL, 0x0404040404040404ULL, },
+ { 0x0504030504030504ULL, 0x0305040305040305ULL, },
+ { 0x0304050304050304ULL, 0x0503040503040503ULL, },
+ { 0x0404040404040404ULL, 0x0404040404040404ULL, }, /* 8 */
+ { 0x0404040404040404ULL, 0x0404040404040404ULL, },
+ { 0x0505040303050504ULL, 0x0303050504030305ULL, },
+ { 0x0303040505030304ULL, 0x0505030304050503ULL, },
+ { 0x0604020604020604ULL, 0x0206040206040206ULL, },
+ { 0x0204060204060204ULL, 0x0602040602040602ULL, },
+ { 0x0702050403060107ULL, 0x0205040306010702ULL, },
+ { 0x0106030405020701ULL, 0x0603040502070106ULL, },
+ { 0x0800080008000800ULL, 0x0800080008000800ULL, }, /* 16 */
+ { 0x0008000800080008ULL, 0x0008000800080008ULL, },
+ { 0x0801060304050207ULL, 0x0008010603040502ULL, },
+ { 0x0007020504030601ULL, 0x0800070205040306ULL, },
+ { 0x0802040600080204ULL, 0x0600080204060008ULL, },
+ { 0x0006040208000604ULL, 0x0208000604020800ULL, },
+ { 0x0803020801040700ULL, 0x0605000803020801ULL, },
+ { 0x0005060007040108ULL, 0x0203080005060007ULL, },
+ { 0x0804000804000804ULL, 0x0008040008040008ULL, }, /* 24 */
+ { 0x0004080004080004ULL, 0x0800040800040800ULL, },
+ { 0x0805000607000408ULL, 0x0102080300080500ULL, },
+ { 0x0003080201080400ULL, 0x0706000508000308ULL, },
+ { 0x0806000408020008ULL, 0x0600040802000806ULL, },
+ { 0x0002080400060800ULL, 0x0208040006080002ULL, },
+ { 0x0807000208050004ULL, 0x0803000608010008ULL, },
+ { 0x0001080600030804ULL, 0x0005080200070800ULL, },
+ { 0x0808000008080000ULL, 0x0808000008080000ULL, }, /* 32 */
+ { 0x0000080800000808ULL, 0x0000080800000808ULL, },
+ { 0x0808010006080300ULL, 0x0408050002080700ULL, },
+ { 0x0000070802000508ULL, 0x0400030806000108ULL, },
+ { 0x0808020004080600ULL, 0x0008080200040806ULL, },
+ { 0x0000060804000208ULL, 0x0800000608040002ULL, },
+ { 0x0808030002080801ULL, 0x0004080700000608ULL, },
+ { 0x0000050806000007ULL, 0x0804000108080200ULL, },
+ { 0x0808040000080804ULL, 0x0000080804000008ULL, }, /* 40 */
+ { 0x0000040808000004ULL, 0x0808000004080800ULL, },
+ { 0x0808050000060807ULL, 0x0000040808010002ULL, },
+ { 0x0000030808020001ULL, 0x0808040000070806ULL, },
+ { 0x0808060000040808ULL, 0x0200000808060000ULL, },
+ { 0x0000020808040000ULL, 0x0608080000020808ULL, },
+ { 0x0808070000020808ULL, 0x0500000408080300ULL, },
+ { 0x0000010808060000ULL, 0x0308080400000508ULL, },
+ { 0x0808080000000808ULL, 0x0800000008080800ULL, }, /* 48 */
+ { 0x0000000808080000ULL, 0x0008080800000008ULL, },
+ { 0x0808080100000608ULL, 0x0803000004080805ULL, },
+ { 0x0000000708080200ULL, 0x0005080804000003ULL, },
+ { 0x0808080200000408ULL, 0x0806000000080808ULL, },
+ { 0x0000000608080400ULL, 0x0002080808000000ULL, },
+ { 0x0808080300000208ULL, 0x0808010000040808ULL, },
+ { 0x0000000508080600ULL, 0x0000070808040000ULL, },
+ { 0x0808080400000008ULL, 0x0808040000000808ULL, }, /* 56 */
+ { 0x0000000408080800ULL, 0x0000040808080000ULL, },
+ { 0x0808080500000006ULL, 0x0808070000000408ULL, },
+ { 0x0000000308080802ULL, 0x0000010808080400ULL, },
+ { 0x0808080600000004ULL, 0x0808080200000008ULL, },
+ { 0x0000000208080804ULL, 0x0000000608080800ULL, },
+ { 0x0808080700000002ULL, 0x0808080500000004ULL, },
+ { 0x0000000108080806ULL, 0x0000000308080804ULL, },
+ { 0x0204050402030401ULL, 0x0405030507060302ULL, }, /* 64 */
+ { 0x0706000404040501ULL, 0x0207060303060306ULL, },
+ { 0x0404050405060401ULL, 0x0404040805040302ULL, },
+ { 0x0305030405030404ULL, 0x0405020404020402ULL, },
+ { 0x0503050506060203ULL, 0x0302050505050405ULL, },
+ { 0x0304060308020406ULL, 0x0403020207040204ULL, },
+ { 0x0405030204040503ULL, 0x0303010207040503ULL, },
+ { 0x0605030404040602ULL, 0x0407040502020505ULL, },
+ { 0x0104020504050503ULL, 0x0705030404040403ULL, }, /* 72 */
+ { 0x0405050304050506ULL, 0x0402050302050504ULL, },
+ { 0x0304060604050404ULL, 0x0403040305030502ULL, },
+ { 0x0304050503030305ULL, 0x0404040505050306ULL, },
+ { 0x0502030504030502ULL, 0x0303030504050403ULL, },
+ { 0x0303040703030303ULL, 0x0603040404030405ULL, },
+ { 0x0302020402060704ULL, 0x0604030705030204ULL, },
+ { 0x0404050305040605ULL, 0x0404050504030405ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_COUNT) {
+ do_msa_PCNT_B(b128_pattern[i], b128_result[i]);
+ } else {
+ do_msa_PCNT_B(b128_random[i - PATTERN_INPUTS_COUNT],
+ b128_result[i]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction PCNT.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "PCNT.D";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000040ULL, 0x0000000000000040ULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000020ULL, 0x0000000000000020ULL, },
+ { 0x0000000000000020ULL, 0x0000000000000020ULL, },
+ { 0x0000000000000020ULL, 0x0000000000000020ULL, },
+ { 0x0000000000000020ULL, 0x0000000000000020ULL, },
+ { 0x0000000000000021ULL, 0x0000000000000020ULL, },
+ { 0x000000000000001fULL, 0x0000000000000020ULL, },
+ { 0x0000000000000020ULL, 0x0000000000000020ULL, }, /* 8 */
+ { 0x0000000000000020ULL, 0x0000000000000020ULL, },
+ { 0x0000000000000022ULL, 0x000000000000001fULL, },
+ { 0x000000000000001eULL, 0x0000000000000021ULL, },
+ { 0x0000000000000022ULL, 0x0000000000000020ULL, },
+ { 0x000000000000001eULL, 0x0000000000000020ULL, },
+ { 0x0000000000000023ULL, 0x000000000000001eULL, },
+ { 0x000000000000001dULL, 0x0000000000000022ULL, },
+ { 0x0000000000000020ULL, 0x0000000000000020ULL, }, /* 16 */
+ { 0x0000000000000020ULL, 0x0000000000000020ULL, },
+ { 0x0000000000000024ULL, 0x000000000000001dULL, },
+ { 0x000000000000001cULL, 0x0000000000000023ULL, },
+ { 0x0000000000000022ULL, 0x0000000000000022ULL, },
+ { 0x000000000000001eULL, 0x000000000000001eULL, },
+ { 0x0000000000000021ULL, 0x0000000000000021ULL, },
+ { 0x000000000000001fULL, 0x000000000000001fULL, },
+ { 0x0000000000000024ULL, 0x0000000000000020ULL, }, /* 24 */
+ { 0x000000000000001cULL, 0x0000000000000020ULL, },
+ { 0x0000000000000026ULL, 0x000000000000001bULL, },
+ { 0x000000000000001aULL, 0x0000000000000025ULL, },
+ { 0x0000000000000024ULL, 0x0000000000000022ULL, },
+ { 0x000000000000001cULL, 0x000000000000001eULL, },
+ { 0x0000000000000022ULL, 0x0000000000000022ULL, },
+ { 0x000000000000001eULL, 0x000000000000001eULL, },
+ { 0x0000000000000020ULL, 0x0000000000000020ULL, }, /* 32 */
+ { 0x0000000000000020ULL, 0x0000000000000020ULL, },
+ { 0x0000000000000022ULL, 0x0000000000000022ULL, },
+ { 0x000000000000001eULL, 0x000000000000001eULL, },
+ { 0x0000000000000024ULL, 0x0000000000000024ULL, },
+ { 0x000000000000001cULL, 0x000000000000001cULL, },
+ { 0x0000000000000026ULL, 0x0000000000000021ULL, },
+ { 0x000000000000001aULL, 0x000000000000001fULL, },
+ { 0x0000000000000028ULL, 0x000000000000001cULL, }, /* 40 */
+ { 0x0000000000000018ULL, 0x0000000000000024ULL, },
+ { 0x000000000000002aULL, 0x0000000000000017ULL, },
+ { 0x0000000000000016ULL, 0x0000000000000029ULL, },
+ { 0x000000000000002aULL, 0x0000000000000018ULL, },
+ { 0x0000000000000016ULL, 0x0000000000000028ULL, },
+ { 0x0000000000000029ULL, 0x000000000000001cULL, },
+ { 0x0000000000000017ULL, 0x0000000000000024ULL, },
+ { 0x0000000000000028ULL, 0x0000000000000020ULL, }, /* 48 */
+ { 0x0000000000000018ULL, 0x0000000000000020ULL, },
+ { 0x0000000000000027ULL, 0x0000000000000024ULL, },
+ { 0x0000000000000019ULL, 0x000000000000001cULL, },
+ { 0x0000000000000026ULL, 0x0000000000000026ULL, },
+ { 0x000000000000001aULL, 0x000000000000001aULL, },
+ { 0x0000000000000025ULL, 0x0000000000000025ULL, },
+ { 0x000000000000001bULL, 0x000000000000001bULL, },
+ { 0x0000000000000024ULL, 0x0000000000000024ULL, }, /* 56 */
+ { 0x000000000000001cULL, 0x000000000000001cULL, },
+ { 0x0000000000000023ULL, 0x0000000000000023ULL, },
+ { 0x000000000000001dULL, 0x000000000000001dULL, },
+ { 0x0000000000000022ULL, 0x0000000000000022ULL, },
+ { 0x000000000000001eULL, 0x000000000000001eULL, },
+ { 0x0000000000000021ULL, 0x0000000000000021ULL, },
+ { 0x000000000000001fULL, 0x000000000000001fULL, },
+ { 0x0000000000000019ULL, 0x0000000000000023ULL, }, /* 64 */
+ { 0x000000000000001fULL, 0x0000000000000024ULL, },
+ { 0x0000000000000021ULL, 0x0000000000000022ULL, },
+ { 0x000000000000001fULL, 0x000000000000001bULL, },
+ { 0x0000000000000023ULL, 0x0000000000000022ULL, },
+ { 0x0000000000000024ULL, 0x000000000000001cULL, },
+ { 0x000000000000001eULL, 0x000000000000001cULL, },
+ { 0x0000000000000022ULL, 0x0000000000000022ULL, },
+ { 0x000000000000001dULL, 0x0000000000000022ULL, }, /* 72 */
+ { 0x0000000000000025ULL, 0x000000000000001eULL, },
+ { 0x0000000000000024ULL, 0x000000000000001dULL, },
+ { 0x000000000000001fULL, 0x0000000000000024ULL, },
+ { 0x000000000000001dULL, 0x000000000000001eULL, },
+ { 0x000000000000001dULL, 0x0000000000000021ULL, },
+ { 0x000000000000001eULL, 0x0000000000000022ULL, },
+ { 0x0000000000000024ULL, 0x0000000000000022ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_COUNT) {
+ do_msa_PCNT_D(b128_pattern[i], b128_result[i]);
+ } else {
+ do_msa_PCNT_D(b128_random[i - PATTERN_INPUTS_COUNT],
+ b128_result[i]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction PCNT.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "PCNT.H";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0010001000100010ULL, 0x0010001000100010ULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0008000800080008ULL, 0x0008000800080008ULL, },
+ { 0x0008000800080008ULL, 0x0008000800080008ULL, },
+ { 0x0008000800080008ULL, 0x0008000800080008ULL, },
+ { 0x0008000800080008ULL, 0x0008000800080008ULL, },
+ { 0x0009000800070009ULL, 0x0008000700090008ULL, },
+ { 0x0007000800090007ULL, 0x0008000900070008ULL, },
+ { 0x0008000800080008ULL, 0x0008000800080008ULL, }, /* 8 */
+ { 0x0008000800080008ULL, 0x0008000800080008ULL, },
+ { 0x000a000700080009ULL, 0x0006000a00070008ULL, },
+ { 0x0006000900080007ULL, 0x000a000600090008ULL, },
+ { 0x000a00080006000aULL, 0x00080006000a0008ULL, },
+ { 0x00060008000a0006ULL, 0x0008000a00060008ULL, },
+ { 0x0009000900090008ULL, 0x0007000700070009ULL, },
+ { 0x0007000700070008ULL, 0x0009000900090007ULL, },
+ { 0x0008000800080008ULL, 0x0008000800080008ULL, }, /* 16 */
+ { 0x0008000800080008ULL, 0x0008000800080008ULL, },
+ { 0x0009000900090009ULL, 0x0008000700070007ULL, },
+ { 0x0007000700070007ULL, 0x0008000900090009ULL, },
+ { 0x000a000a00080006ULL, 0x0006000a000a0008ULL, },
+ { 0x000600060008000aULL, 0x000a000600060008ULL, },
+ { 0x000b000a00050007ULL, 0x000b000800050009ULL, },
+ { 0x00050006000b0009ULL, 0x00050008000b0007ULL, },
+ { 0x000c00080004000cULL, 0x00080004000c0008ULL, }, /* 24 */
+ { 0x00040008000c0004ULL, 0x0008000c00040008ULL, },
+ { 0x000d00060007000cULL, 0x0003000b00080005ULL, },
+ { 0x0003000a00090004ULL, 0x000d00050008000bULL, },
+ { 0x000e0004000a0008ULL, 0x0006000c0002000eULL, },
+ { 0x0002000c00060008ULL, 0x000a0004000e0002ULL, },
+ { 0x000f0002000d0004ULL, 0x000b000600090008ULL, },
+ { 0x0001000e0003000cULL, 0x0005000a00070008ULL, },
+ { 0x0010000000100000ULL, 0x0010000000100000ULL, }, /* 32 */
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, },
+ { 0x00100001000e0003ULL, 0x000c0005000a0007ULL, },
+ { 0x0000000f0002000dULL, 0x0004000b00060009ULL, },
+ { 0x00100002000c0006ULL, 0x0008000a0004000eULL, },
+ { 0x0000000e0004000aULL, 0x00080006000c0002ULL, },
+ { 0x00100003000a0009ULL, 0x0004000f0000000eULL, },
+ { 0x0000000d00060007ULL, 0x000c000100100002ULL, },
+ { 0x001000040008000cULL, 0x0000001000040008ULL, }, /* 40 */
+ { 0x0000000c00080004ULL, 0x00100000000c0008ULL, },
+ { 0x001000050006000fULL, 0x0000000c00090002ULL, },
+ { 0x0000000b000a0001ULL, 0x001000040007000eULL, },
+ { 0x0010000600040010ULL, 0x00020008000e0000ULL, },
+ { 0x0000000a000c0000ULL, 0x000e000800020010ULL, },
+ { 0x0010000700020010ULL, 0x0005000400100003ULL, },
+ { 0x00000009000e0000ULL, 0x000b000c0000000dULL, },
+ { 0x0010000800000010ULL, 0x0008000000100008ULL, }, /* 48 */
+ { 0x0000000800100000ULL, 0x0008001000000008ULL, },
+ { 0x001000090000000eULL, 0x000b0000000c000dULL, },
+ { 0x0000000700100002ULL, 0x0005001000040003ULL, },
+ { 0x0010000a0000000cULL, 0x000e000000080010ULL, },
+ { 0x0000000600100004ULL, 0x0002001000080000ULL, },
+ { 0x0010000b0000000aULL, 0x0010000100040010ULL, },
+ { 0x0000000500100006ULL, 0x0000000f000c0000ULL, },
+ { 0x0010000c00000008ULL, 0x0010000400000010ULL, }, /* 56 */
+ { 0x0000000400100008ULL, 0x0000000c00100000ULL, },
+ { 0x0010000d00000006ULL, 0x001000070000000cULL, },
+ { 0x000000030010000aULL, 0x0000000900100004ULL, },
+ { 0x0010000e00000004ULL, 0x0010000a00000008ULL, },
+ { 0x000000020010000cULL, 0x0000000600100008ULL, },
+ { 0x0010000f00000002ULL, 0x0010000d00000004ULL, },
+ { 0x000000010010000eULL, 0x000000030010000cULL, },
+ { 0x0006000900050005ULL, 0x00090008000d0005ULL, }, /* 64 */
+ { 0x000d000400080006ULL, 0x0009000900090009ULL, },
+ { 0x00080009000b0005ULL, 0x0008000c00090005ULL, },
+ { 0x0008000700080008ULL, 0x0009000600060006ULL, },
+ { 0x0008000a000c0005ULL, 0x0005000a000a0009ULL, },
+ { 0x00070009000a000aULL, 0x00070004000b0006ULL, },
+ { 0x0009000500080008ULL, 0x00060003000b0008ULL, },
+ { 0x000b000700080008ULL, 0x000b00090004000aULL, },
+ { 0x0005000700090008ULL, 0x000c000700080007ULL, }, /* 72 */
+ { 0x000900080009000bULL, 0x0006000800070009ULL, },
+ { 0x0007000c00090008ULL, 0x0007000700080007ULL, },
+ { 0x0007000a00060008ULL, 0x00080009000a0009ULL, },
+ { 0x0007000800070007ULL, 0x0006000800090007ULL, },
+ { 0x0006000b00060006ULL, 0x0009000800070009ULL, },
+ { 0x000500060008000bULL, 0x000a000a00080006ULL, },
+ { 0x000800080009000bULL, 0x0008000a00070009ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_COUNT) {
+ do_msa_PCNT_H(b128_pattern[i], b128_result[i]);
+ } else {
+ do_msa_PCNT_H(b128_random[i - PATTERN_INPUTS_COUNT],
+ b128_result[i]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction PCNT.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "PCNT.W";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000002000000020ULL, 0x0000002000000020ULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, },
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, },
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, },
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, },
+ { 0x0000001100000010ULL, 0x0000000f00000011ULL, },
+ { 0x0000000f00000010ULL, 0x000000110000000fULL, },
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, }, /* 8 */
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, },
+ { 0x0000001100000011ULL, 0x000000100000000fULL, },
+ { 0x0000000f0000000fULL, 0x0000001000000011ULL, },
+ { 0x0000001200000010ULL, 0x0000000e00000012ULL, },
+ { 0x0000000e00000010ULL, 0x000000120000000eULL, },
+ { 0x0000001200000011ULL, 0x0000000e00000010ULL, },
+ { 0x0000000e0000000fULL, 0x0000001200000010ULL, },
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, }, /* 16 */
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, },
+ { 0x0000001200000012ULL, 0x0000000f0000000eULL, },
+ { 0x0000000e0000000eULL, 0x0000001100000012ULL, },
+ { 0x000000140000000eULL, 0x0000001000000012ULL, },
+ { 0x0000000c00000012ULL, 0x000000100000000eULL, },
+ { 0x000000150000000cULL, 0x000000130000000eULL, },
+ { 0x0000000b00000014ULL, 0x0000000d00000012ULL, },
+ { 0x0000001400000010ULL, 0x0000000c00000014ULL, }, /* 24 */
+ { 0x0000000c00000010ULL, 0x000000140000000cULL, },
+ { 0x0000001300000013ULL, 0x0000000e0000000dULL, },
+ { 0x0000000d0000000dULL, 0x0000001200000013ULL, },
+ { 0x0000001200000012ULL, 0x0000001200000010ULL, },
+ { 0x0000000e0000000eULL, 0x0000000e00000010ULL, },
+ { 0x0000001100000011ULL, 0x0000001100000011ULL, },
+ { 0x0000000f0000000fULL, 0x0000000f0000000fULL, },
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, }, /* 32 */
+ { 0x0000001000000010ULL, 0x0000001000000010ULL, },
+ { 0x0000001100000011ULL, 0x0000001100000011ULL, },
+ { 0x0000000f0000000fULL, 0x0000000f0000000fULL, },
+ { 0x0000001200000012ULL, 0x0000001200000012ULL, },
+ { 0x0000000e0000000eULL, 0x0000000e0000000eULL, },
+ { 0x0000001300000013ULL, 0x000000130000000eULL, },
+ { 0x0000000d0000000dULL, 0x0000000d00000012ULL, },
+ { 0x0000001400000014ULL, 0x000000100000000cULL, }, /* 40 */
+ { 0x0000000c0000000cULL, 0x0000001000000014ULL, },
+ { 0x0000001500000015ULL, 0x0000000c0000000bULL, },
+ { 0x0000000b0000000bULL, 0x0000001400000015ULL, },
+ { 0x0000001600000014ULL, 0x0000000a0000000eULL, },
+ { 0x0000000a0000000cULL, 0x0000001600000012ULL, },
+ { 0x0000001700000012ULL, 0x0000000900000013ULL, },
+ { 0x000000090000000eULL, 0x000000170000000dULL, },
+ { 0x0000001800000010ULL, 0x0000000800000018ULL, }, /* 48 */
+ { 0x0000000800000010ULL, 0x0000001800000008ULL, },
+ { 0x000000190000000eULL, 0x0000000b00000019ULL, },
+ { 0x0000000700000012ULL, 0x0000001500000007ULL, },
+ { 0x0000001a0000000cULL, 0x0000000e00000018ULL, },
+ { 0x0000000600000014ULL, 0x0000001200000008ULL, },
+ { 0x0000001b0000000aULL, 0x0000001100000014ULL, },
+ { 0x0000000500000016ULL, 0x0000000f0000000cULL, },
+ { 0x0000001c00000008ULL, 0x0000001400000010ULL, }, /* 56 */
+ { 0x0000000400000018ULL, 0x0000000c00000010ULL, },
+ { 0x0000001d00000006ULL, 0x000000170000000cULL, },
+ { 0x000000030000001aULL, 0x0000000900000014ULL, },
+ { 0x0000001e00000004ULL, 0x0000001a00000008ULL, },
+ { 0x000000020000001cULL, 0x0000000600000018ULL, },
+ { 0x0000001f00000002ULL, 0x0000001d00000004ULL, },
+ { 0x000000010000001eULL, 0x000000030000001cULL, },
+ { 0x0000000f0000000aULL, 0x0000001100000012ULL, }, /* 64 */
+ { 0x000000110000000eULL, 0x0000001200000012ULL, },
+ { 0x0000001100000010ULL, 0x000000140000000eULL, },
+ { 0x0000000f00000010ULL, 0x0000000f0000000cULL, },
+ { 0x0000001200000011ULL, 0x0000000f00000013ULL, },
+ { 0x0000001000000014ULL, 0x0000000b00000011ULL, },
+ { 0x0000000e00000010ULL, 0x0000000900000013ULL, },
+ { 0x0000001200000010ULL, 0x000000140000000eULL, },
+ { 0x0000000c00000011ULL, 0x000000130000000fULL, }, /* 72 */
+ { 0x0000001100000014ULL, 0x0000000e00000010ULL, },
+ { 0x0000001300000011ULL, 0x0000000e0000000fULL, },
+ { 0x000000110000000eULL, 0x0000001100000013ULL, },
+ { 0x0000000f0000000eULL, 0x0000000e00000010ULL, },
+ { 0x000000110000000cULL, 0x0000001100000010ULL, },
+ { 0x0000000b00000013ULL, 0x000000140000000eULL, },
+ { 0x0000001000000014ULL, 0x0000001200000010ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_COUNT) {
+ do_msa_PCNT_W(b128_pattern[i], b128_result[i]);
+ } else {
+ do_msa_PCNT_W(b128_random[i - PATTERN_INPUTS_COUNT],
+ b128_result[i]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CEQ.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CEQ.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 72 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CEQ_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CEQ_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CEQ.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CEQ.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 72 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CEQ_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CEQ_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CEQ.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CEQ.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 72 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CEQ_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CEQ_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CEQ.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CEQ.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 72 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CEQ_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CEQ_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLE_S.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLE_S.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, /* 48 */
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, /* 56 */
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xff00ffffff000000ULL, 0x00000000ff00ff00ULL, },
+ { 0xff00000000000000ULL, 0x000000000000ffffULL, },
+ { 0xff00ffffff0000ffULL, 0x000000000000ff00ULL, },
+ { 0x00ff000000ffffffULL, 0xffffffff00ff00ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00ff000000ff0000ULL, 0xff00ff00000000ffULL, },
+ { 0xffffff00ffffffffULL, 0x0000000000ff0000ULL, },
+ { 0x00ffffffffffffffULL, 0xffffffffffff0000ULL, }, /* 72 */
+ { 0xff00ffffff00ffffULL, 0x00ff00ffffffff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff00ffffffffffffULL, 0x00ff000000ff0000ULL, },
+ { 0x00ff000000ffff00ULL, 0xffffffffffff00ffULL, },
+ { 0x000000ff00000000ULL, 0xffffffffff00ffffULL, },
+ { 0x00ff000000000000ULL, 0xff00ffffff00ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_S_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_S_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLE_S.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLE_S.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_S_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_S_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLE_S.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLE_S.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, /* 48 */
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, /* 56 */
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffffffffffff0000ULL, 0x00000000ffffffffULL, },
+ { 0xffff000000000000ULL, 0x000000000000ffffULL, },
+ { 0xffffffffffff0000ULL, 0x000000000000ffffULL, },
+ { 0x000000000000ffffULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000ffffffffffffULL, 0xffffffffffff0000ULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x000000000000ffffULL, 0xffffffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_S_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_S_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLE_S.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLE_S.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, /* 48 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_S_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_S_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLE_U.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLE_U.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffff0000ffffff00ULL, 0x00ffff00000000ffULL, },
+ { 0xff000000ffffffffULL, 0x00ffffff000000ffULL, },
+ { 0x00000000ff00ffffULL, 0xffffffff0000ffffULL, },
+ { 0x0000ffff000000ffULL, 0xff0000ffffffff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffffffff00ffULL, 0xff00ffffff000000ULL, },
+ { 0x0000ff00ff00ffffULL, 0xff0000ffffffff00ULL, },
+ { 0x00ffffff00000000ULL, 0xff000000ffffff00ULL, }, /* 72 */
+ { 0xffff00000000ff00ULL, 0x00ff000000ffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x000000000000ff00ULL, 0xffff000000ffffffULL, },
+ { 0xffffffff00ff0000ULL, 0x00000000ffff0000ULL, },
+ { 0xffff00ff00ff0000ULL, 0x00ffff00000000ffULL, },
+ { 0xffffffffffff00ffULL, 0x0000ffffff000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_U_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_U_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLE_U.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLE_U.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_U_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_U_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLE_U.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLE_U.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffff0000ffffffffULL, 0x0000ffff00000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffff00000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff0000ffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff0000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffffffff0000ULL, },
+ { 0x0000ffffffffffffULL, 0xffff0000ffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff0000ffffffffULL, }, /* 72 */
+ { 0xffff00000000ffffULL, 0x000000000000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x000000000000ffffULL, 0xffff00000000ffffULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffff0000ULL, },
+ { 0xffff000000000000ULL, 0x0000ffff00000000ULL, },
+ { 0xffffffffffff0000ULL, 0x0000ffffffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_U_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_U_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLE_U.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLE_U.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_U_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_U_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLT_S.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLT_S.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, /* 48 */
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, /* 56 */
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xff00ffffff000000ULL, 0x00000000ff00ff00ULL, },
+ { 0xff00000000000000ULL, 0x000000000000ffffULL, },
+ { 0xff00ffffff0000ffULL, 0x000000000000ff00ULL, },
+ { 0x00ff000000ffffffULL, 0xffffffff00ff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00ff000000ff0000ULL, 0xff00ff00000000ffULL, },
+ { 0xffffff00ffffffffULL, 0x0000000000ff0000ULL, },
+ { 0x00ffffffffffffffULL, 0xffffffffffff0000ULL, }, /* 72 */
+ { 0xff00ffffff00ffffULL, 0x00ff00ffffffff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff00ffffffffffffULL, 0x00ff000000ff0000ULL, },
+ { 0x00ff000000ffff00ULL, 0xffffffffffff00ffULL, },
+ { 0x000000ff00000000ULL, 0xffffffffff00ffffULL, },
+ { 0x00ff000000000000ULL, 0xff00ffffff00ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_S_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_S_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLT_S.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLT_S.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_S_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_S_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLT_S.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLT_S.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, /* 48 */
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, /* 56 */
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffffffffffff0000ULL, 0x00000000ffffffffULL, },
+ { 0xffff000000000000ULL, 0x000000000000ffffULL, },
+ { 0xffffffffffff0000ULL, 0x000000000000ffffULL, },
+ { 0x000000000000ffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000ffffffffffffULL, 0xffffffffffff0000ULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x000000000000ffffULL, 0xffffffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_S_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_S_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLT_S.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLT_S.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, /* 48 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_S_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_S_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLT_U.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLT_U.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffff0000ffffff00ULL, 0x00ffff00000000ffULL, },
+ { 0xff000000ffffffffULL, 0x00ffffff000000ffULL, },
+ { 0x00000000ff00ffffULL, 0xffffffff0000ffffULL, },
+ { 0x0000ffff000000ffULL, 0xff0000ffffffff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ffffffff00ffULL, 0xff00ffffff000000ULL, },
+ { 0x0000ff00ff00ffffULL, 0xff0000ffffffff00ULL, },
+ { 0x00ffffff00000000ULL, 0xff000000ffffff00ULL, }, /* 72 */
+ { 0xffff00000000ff00ULL, 0x00ff000000ffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000ff00ULL, 0xffff000000ffffffULL, },
+ { 0xffffffff00ff0000ULL, 0x00000000ffff0000ULL, },
+ { 0xffff00ff00ff0000ULL, 0x00ffff00000000ffULL, },
+ { 0xffffffffffff00ffULL, 0x0000ffffff000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_U_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_U_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLT_U.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLT_U.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_U_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_U_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLT_U.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLT_U.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffff0000ffffffffULL, 0x0000ffff00000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffff00000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff0000ffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff0000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffffffff0000ULL, },
+ { 0x0000ffffffffffffULL, 0xffff0000ffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff0000ffffffffULL, }, /* 72 */
+ { 0xffff00000000ffffULL, 0x000000000000ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000ffffULL, 0xffff00000000ffffULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffff0000ULL, },
+ { 0xffff000000000000ULL, 0x0000ffff00000000ULL, },
+ { 0xffffffffffff0000ULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_U_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_U_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction CLT_U.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLT_U.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_U_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_U_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MAX_A.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MAX_A.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaa8eaaaa8eaaaa8eULL, 0xaaaa8eaaaa8eaaaaULL, },
+ { 0xaa71aaaa71aaaa71ULL, 0xaaaa71aaaa71aaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x558e55558e55558eULL, 0x55558e55558e5555ULL, },
+ { 0x5571555571555571ULL, 0x5555715555715555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcc8e38cc8e38cc8eULL, 0x38cc8e38cc8e38ccULL, },
+ { 0xcc71c7cc71c7cc71ULL, 0xc7cc71c7cc71c7ccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x338e38338e38338eULL, 0x38338e38338e3833ULL, },
+ { 0x3371c73371c73371ULL, 0xc73371c73371c733ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xaa8eaaaa8eaaaa8eULL, 0xaaaa8eaaaa8eaaaaULL, },
+ { 0x558e55558e55558eULL, 0x55558e55558e5555ULL, },
+ { 0xcc8e38cc8e38cc8eULL, 0x38cc8e38cc8e38ccULL, },
+ { 0x338e38338e38338eULL, 0x38338e38338e3833ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaa71aaaa71aaaa71ULL, 0xaaaa71aaaa71aaaaULL, },
+ { 0x5571555571555571ULL, 0x5555715555715555ULL, },
+ { 0xcc71c7cc71c7cc71ULL, 0xc7cc71c7cc71c7ccULL, },
+ { 0x3371c73371c73371ULL, 0xc73371c73371c733ULL, },
+ { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6634d935540ULL, 0x4b67bb5e157b520cULL, },
+ { 0x886aaeaab9628b80ULL, 0x4b67c65eab7bb014ULL, },
+ { 0x886ae64d5e62554eULL, 0x8d67885ea97bb0a0ULL, },
+ { 0x886ae6634d935540ULL, 0x4b67bb5e157b520cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aae634d938b80ULL, 0x27d8bb1aab3f5214ULL, },
+ { 0x704f16635e93c74eULL, 0x8df188d8a94252a0ULL, },
+ { 0x886aaeaab9628b80ULL, 0x4b67c65eab7bb014ULL, }, /* 72 */
+ { 0xac5aae634d938b80ULL, 0x27d8bb1aab3f5214ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x705aaeaa5e318b80ULL, 0x8dd888d8a94225a0ULL, },
+ { 0x886ae64d5e62554eULL, 0x8d67885ea97bb0a0ULL, },
+ { 0x704f16635e93c74eULL, 0x8df188d8a94252a0ULL, },
+ { 0x705aaeaa5ecf8b80ULL, 0x8dd888d8a94225a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_A_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_A_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MAX_A.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MAX_A.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_A_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_A_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MAX_A.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MAX_A.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa8e38aaaaULL, 0xaaaa8e38aaaaaaaaULL, },
+ { 0xaaaaaaaa71c7aaaaULL, 0xaaaa71c7aaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x555555558e385555ULL, 0x55558e3855555555ULL, },
+ { 0x5555555571c75555ULL, 0x555571c755555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccc38e38e38ccccULL, 0x38e38e38cccc38e3ULL, },
+ { 0xccccc71c71c7ccccULL, 0xc71c71c7ccccc71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x333338e38e383333ULL, 0x38e38e38333338e3ULL, },
+ { 0x3333c71c71c73333ULL, 0xc71c71c73333c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xaaaaaaaa8e38aaaaULL, 0xaaaa8e38aaaaaaaaULL, },
+ { 0x555555558e385555ULL, 0x55558e3855555555ULL, },
+ { 0xcccc38e38e38ccccULL, 0x38e38e38cccc38e3ULL, },
+ { 0x333338e38e383333ULL, 0x38e38e38333338e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaa71c7aaaaULL, 0xaaaa71c7aaaaaaaaULL, },
+ { 0x5555555571c75555ULL, 0x555571c755555555ULL, },
+ { 0xccccc71c71c7ccccULL, 0xc71c71c7ccccc71cULL, },
+ { 0x3333c71c71c73333ULL, 0xc71c71c73333c71cULL, },
+ { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc4d935540ULL, 0x4b67bb1a153f52fcULL, },
+ { 0x886aaeaab9cf8b80ULL, 0x4b67c6ffab2bb00cULL, },
+ { 0x886ae6cc5e315540ULL, 0x8df188d8a942b00cULL, },
+ { 0x886ae6cc4d935540ULL, 0x4b67bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaa4d938b80ULL, 0x27d8bb1aab2b52fcULL, },
+ { 0x704f164d5e31c708ULL, 0x8df188d8a94252fcULL, },
+ { 0x886aaeaab9cf8b80ULL, 0x4b67c6ffab2bb00cULL, }, /* 72 */
+ { 0xac5aaeaa4d938b80ULL, 0x27d8bb1aab2b52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704faeaa5e318b80ULL, 0x8df188d8a9422514ULL, },
+ { 0x886ae6cc5e315540ULL, 0x8df188d8a942b00cULL, },
+ { 0x704f164d5e31c708ULL, 0x8df188d8a94252fcULL, },
+ { 0x704faeaa5e318b80ULL, 0x8df188d8a9422514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_A_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_A_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MAX_A.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MAX_A.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x555555558e38e38eULL, 0x5555555555555555ULL, },
+ { 0x5555555571c71c71ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, },
+ { 0xcccccccc71c71c71ULL, 0xc71c71c7ccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x333333338e38e38eULL, 0x38e38e3833333333ULL, },
+ { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x555555558e38e38eULL, 0x5555555555555555ULL, },
+ { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, },
+ { 0x333333338e38e38eULL, 0x38e38e3833333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaa71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555571c71c71ULL, 0x5555555555555555ULL, },
+ { 0xcccccccc71c71c71ULL, 0xc71c71c7ccccccccULL, },
+ { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc4d93c708ULL, 0x4b670b5e153f52fcULL, },
+ { 0x886ae6ccb9cf8b80ULL, 0x4b670b5eab2b2514ULL, },
+ { 0x886ae6cc5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc4d93c708ULL, 0x4b670b5e153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaa4d93c708ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6ccb9cf8b80ULL, 0x4b670b5eab2b2514ULL, }, /* 72 */
+ { 0xac5aaeaa4d93c708ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_A_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_A_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MAX_S.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MAX_S.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xffff38ffff38ffffULL, 0x38ffff38ffff38ffULL, },
+ { 0x1c71ff1c71ff1c71ULL, 0xff1c71ff1c71ff1cULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x0000380000380000ULL, 0x3800003800003800ULL, },
+ { 0x1c71001c71001c71ULL, 0x001c71001c71001cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe3aa38e3aa38e3aaULL, 0x38e3aa38e3aa38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5571555571555571ULL, 0x5555715555715555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe3cc38e3cc38e3ccULL, 0x38e3cc38e3cc38e3ULL, },
+ { 0x1c71cc1c71cc1c71ULL, 0xcc1c71cc1c71cc1cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333383333383333ULL, 0x3833333833333833ULL, },
+ { 0x3371333371333371ULL, 0x3333713333713333ULL, },
+ { 0xffff38ffff38ffffULL, 0x38ffff38ffff38ffULL, }, /* 48 */
+ { 0x0000380000380000ULL, 0x3800003800003800ULL, },
+ { 0xe3aa38e3aa38e3aaULL, 0x38e3aa38e3aa38e3ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe3cc38e3cc38e3ccULL, 0x38e3cc38e3cc38e3ULL, },
+ { 0x3333383333383333ULL, 0x3833333833333833ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, },
+ { 0x1c71ff1c71ff1c71ULL, 0xff1c71ff1c71ff1cULL, }, /* 56 */
+ { 0x1c71001c71001c71ULL, 0x001c71001c71001cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5571555571555571ULL, 0x5555715555715555ULL, },
+ { 0x1c71cc1c71cc1c71ULL, 0xcc1c71cc1c71cc1cULL, },
+ { 0x3371333371333371ULL, 0x3333713333713333ULL, },
+ { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfb6a00634d625540ULL, 0x4b670b5e157b520cULL, },
+ { 0xac6ae6cc28625540ULL, 0x4b670b5efe7b2514ULL, },
+ { 0x706a164d5e62554eULL, 0x4b670b5efe7be20cULL, },
+ { 0xfb6a00634d625540ULL, 0x4b670b5e157b520cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfb5a00634dcfc708ULL, 0x27f7c61a153f5214ULL, },
+ { 0x704f16635e31e24eULL, 0x12f7bb1a154252fcULL, },
+ { 0xac6ae6cc28625540ULL, 0x4b670b5efe7b2514ULL, }, /* 72 */
+ { 0xfb5a00634dcfc708ULL, 0x27f7c61a153f5214ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x705a164d5e31e24eULL, 0x27f1c6ffab422514ULL, },
+ { 0x706a164d5e62554eULL, 0x4b670b5efe7be20cULL, },
+ { 0x704f16635e31e24eULL, 0x12f7bb1a154252fcULL, },
+ { 0x705a164d5e31e24eULL, 0x27f1c6ffab422514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_S_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_S_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MAX_S.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MAX_S.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x0000000000000000ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_S_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_S_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MAX_S.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MAX_S.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xffff38e3ffffffffULL, 0x38e3ffffffff38e3ULL, },
+ { 0x1c71ffff71c71c71ULL, 0xffff71c71c71ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x000038e300000000ULL, 0x38e30000000038e3ULL, },
+ { 0x1c71000071c71c71ULL, 0x000071c71c710000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3aaaae38eULL, 0x38e3aaaae38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555571c75555ULL, 0x555571c755555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3cccce38eULL, 0x38e3cccce38e38e3ULL, },
+ { 0x1c71cccc71c71c71ULL, 0xcccc71c71c71ccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x333338e333333333ULL, 0x38e33333333338e3ULL, },
+ { 0x3333333371c73333ULL, 0x333371c733333333ULL, },
+ { 0xffff38e3ffffffffULL, 0x38e3ffffffff38e3ULL, }, /* 48 */
+ { 0x000038e300000000ULL, 0x38e30000000038e3ULL, },
+ { 0xe38e38e3aaaae38eULL, 0x38e3aaaae38e38e3ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e3cccce38eULL, 0x38e3cccce38e38e3ULL, },
+ { 0x333338e333333333ULL, 0x38e33333333338e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, },
+ { 0x1c71ffff71c71c71ULL, 0xffff71c71c71ffffULL, }, /* 56 */
+ { 0x1c71000071c71c71ULL, 0x000071c71c710000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555571c75555ULL, 0x555571c755555555ULL, },
+ { 0x1c71cccc71c71c71ULL, 0xcccc71c71c71ccccULL, },
+ { 0x3333333371c73333ULL, 0x333371c733333333ULL, },
+ { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00634d935540ULL, 0x4b670b5e153f52fcULL, },
+ { 0xac5ae6cc28625540ULL, 0x4b670b5efe7b2514ULL, },
+ { 0x704f164d5e315540ULL, 0x4b670b5efe7be2a0ULL, },
+ { 0xfbbe00634d935540ULL, 0x4b670b5e153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ff153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5ae6cc28625540ULL, 0x4b670b5efe7b2514ULL, }, /* 72 */
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ff153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e315540ULL, 0x4b670b5efe7be2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_S_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_S_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MAX_S.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MAX_S.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x38e38e38ffffffffULL, },
+ { 0x1c71c71c71c71c71ULL, 0xffffffff1c71c71cULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x0000000000000000ULL, 0x38e38e3800000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x000000001c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555571c71c71ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3ccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xcccccccc1c71c71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x38e38e3833333333ULL, },
+ { 0x3333333371c71c71ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x38e38e38ffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x38e38e3800000000ULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e3ccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x38e38e3833333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xffffffff1c71c71cULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0x000000001c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555571c71c71ULL, 0x5555555555555555ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xcccccccc1c71c71cULL, },
+ { 0x3333333371c71c71ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00634d93c708ULL, 0x4b670b5e153f52fcULL, },
+ { 0xac5aaeaa28625540ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x4b670b5e153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ff153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaa28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ff153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_S_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_S_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MAX_U.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MAX_U.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe3aaaae3aaaae3aaULL, 0xaae3aaaae3aaaae3ULL, },
+ { 0xaaaac7aaaac7aaaaULL, 0xc7aaaac7aaaac7aaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e55e38e55e38eULL, 0x55e38e55e38e55e3ULL, },
+ { 0x5571c75571c75571ULL, 0xc75571c75571c755ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xe3cccce3cccce3ccULL, 0xcce3cccce3cccce3ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3371c73371c73371ULL, 0xc73371c73371c733ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe3aaaae3aaaae3aaULL, 0xaae3aaaae3aaaae3ULL, },
+ { 0xe38e55e38e55e38eULL, 0x55e38e55e38e55e3ULL, },
+ { 0xe3cccce3cccce3ccULL, 0xcce3cccce3cccce3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaac7aaaac7aaaaULL, 0xc7aaaac7aaaac7aaULL, },
+ { 0x5571c75571c75571ULL, 0xc75571c75571c755ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3371c73371c73371ULL, 0xc73371c73371c733ULL, },
+ { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbee6cc4d93c740ULL, 0x4bf7bb5efe7bb0fcULL, },
+ { 0xac6ae6ccb9cf8b80ULL, 0x4bd8c6fffe7bb014ULL, },
+ { 0x886ae6cc5e62e24eULL, 0x8df188d8fe7be2a0ULL, },
+ { 0xfbbee6cc4d93c740ULL, 0x4bf7bb5efe7bb0fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbeaeaab9cfc780ULL, 0x27f7c6ffab3f52fcULL, },
+ { 0xfbbe16635e93e24eULL, 0x8df7bbd8a942e2fcULL, },
+ { 0xac6ae6ccb9cf8b80ULL, 0x4bd8c6fffe7bb014ULL, }, /* 72 */
+ { 0xfbbeaeaab9cfc780ULL, 0x27f7c6ffab3f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cfe280ULL, 0x8df1c6ffab42e2a0ULL, },
+ { 0x886ae6cc5e62e24eULL, 0x8df188d8fe7be2a0ULL, },
+ { 0xfbbe16635e93e24eULL, 0x8df7bbd8a942e2fcULL, },
+ { 0xac5aaeaab9cfe280ULL, 0x8df1c6ffab42e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_U_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_U_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MAX_U.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MAX_U.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e38e38e38eULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0x5555555555555555ULL, },
+ { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_U_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_U_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MAX_U.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MAX_U.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38eaaaaaaaae38eULL, 0xaaaaaaaae38eaaaaULL, },
+ { 0xaaaac71caaaaaaaaULL, 0xc71caaaaaaaac71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e55558e38e38eULL, 0x55558e38e38e5555ULL, },
+ { 0x5555c71c71c75555ULL, 0xc71c71c75555c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xe38ecccccccce38eULL, 0xcccccccce38eccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333c71c71c73333ULL, 0xc71c71c73333c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38eaaaaaaaae38eULL, 0xaaaaaaaae38eaaaaULL, },
+ { 0xe38e55558e38e38eULL, 0x55558e38e38e5555ULL, },
+ { 0xe38ecccccccce38eULL, 0xcccccccce38eccccULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaac71caaaaaaaaULL, 0xc71caaaaaaaac71cULL, },
+ { 0x5555c71c71c75555ULL, 0xc71c71c75555c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333c71c71c73333ULL, 0xc71c71c73333c71cULL, },
+ { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbee6cc4d93c708ULL, 0x4b67bb1afe7bb00cULL, },
+ { 0xac5ae6ccb9cf8b80ULL, 0x4b67c6fffe7bb00cULL, },
+ { 0x886ae6cc5e31e24eULL, 0x8df188d8fe7be2a0ULL, },
+ { 0xfbbee6cc4d93c708ULL, 0x4b67bb1afe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbeaeaab9cfc708ULL, 0x27d8c6ffab2b52fcULL, },
+ { 0xfbbe164d5e31e24eULL, 0x8df1bb1aa942e2a0ULL, },
+ { 0xac5ae6ccb9cf8b80ULL, 0x4b67c6fffe7bb00cULL, }, /* 72 */
+ { 0xfbbeaeaab9cfc708ULL, 0x27d8c6ffab2b52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cfe24eULL, 0x8df1c6ffab2be2a0ULL, },
+ { 0x886ae6cc5e31e24eULL, 0x8df188d8fe7be2a0ULL, },
+ { 0xfbbe164d5e31e24eULL, 0x8df1bb1aa942e2a0ULL, },
+ { 0xac5aaeaab9cfe24eULL, 0x8df1c6ffab2be2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_U_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_U_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MAX_U.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MAX_U.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0xaaaaaaaae38e38e3ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c7aaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e38e38e38eULL, 0x55555555e38e38e3ULL, },
+ { 0x5555555571c71c71ULL, 0xc71c71c755555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0xaaaaaaaae38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x55555555e38e38e3ULL, },
+ { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c7aaaaaaaaULL, },
+ { 0x5555555571c71c71ULL, 0xc71c71c755555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x886ae6cc5e31e24eULL, 0x8df188d8fe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe0063b9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xfbbe00635e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */
+ { 0xfbbe0063b9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8ab2b2514ULL, },
+ { 0x886ae6cc5e31e24eULL, 0x8df188d8fe7bb00cULL, },
+ { 0xfbbe00635e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8ab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_U_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_U_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MIN_A.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MIN_A.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe3aa38e3aa38e3aaULL, 0x38e3aa38e3aa38e3ULL, },
+ { 0x1caac71caac71caaULL, 0xc71caac71caac71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe35538e35538e355ULL, 0x38e35538e35538e3ULL, },
+ { 0x1c55c71c55c71c55ULL, 0xc71c55c71c55c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe3cccce3cccce3ccULL, 0xcce3cccce3cccce3ULL, },
+ { 0x1ccccc1ccccc1cccULL, 0xcc1ccccc1ccccc1cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe33333e33333e333ULL, 0x33e33333e33333e3ULL, },
+ { 0x1c33331c33331c33ULL, 0x331c33331c33331cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe3aa38e3aa38e3aaULL, 0x38e3aa38e3aa38e3ULL, },
+ { 0xe35538e35538e355ULL, 0x38e35538e35538e3ULL, },
+ { 0xe3cccce3cccce3ccULL, 0xcce3cccce3cccce3ULL, },
+ { 0xe33333e33333e333ULL, 0x33e33333e33333e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1caac71caac71caaULL, 0xc71caac71caac71cULL, },
+ { 0x1c55c71c55c71c55ULL, 0xc71c55c71c55c71cULL, },
+ { 0x1ccccc1ccccc1cccULL, 0xcc1ccccc1ccccc1cULL, },
+ { 0x1c33331c33331c33ULL, 0x331c33331c33331cULL, },
+ { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00cc2862c708ULL, 0x12f70b1afe3fb0fcULL, },
+ { 0xac5ae6cc28cf5540ULL, 0x27d80bfffe2b250cULL, },
+ { 0x704f16cc2831e240ULL, 0x4bf10bd8fe42e20cULL, },
+ { 0xfbbe00cc2862c708ULL, 0x12f70b1afe3fb0fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00aab9cfc708ULL, 0x12f7c6ff152b25fcULL, },
+ { 0xfbbe004d4d31e208ULL, 0x12f7bb1a153fe2fcULL, },
+ { 0xac5ae6cc28cf5540ULL, 0x27d80bfffe2b250cULL, }, /* 72 */
+ { 0xfbbe00aab9cfc708ULL, 0x12f7c6ff152b25fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac4f164db931e24eULL, 0x27f1c6ffab2be214ULL, },
+ { 0x704f16cc2831e240ULL, 0x4bf10bd8fe42e20cULL, },
+ { 0xfbbe004d4d31e208ULL, 0x12f7bb1a153fe2fcULL, },
+ { 0xac4f164db9cfe24eULL, 0x27f1c6ffab2be214ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_A_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_A_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MIN_A.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MIN_A.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, },
+ { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, },
+ { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_A_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_A_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MIN_A.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MIN_A.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3aaaae38eULL, 0x38e3aaaae38e38e3ULL, },
+ { 0x1c71c71caaaa1c71ULL, 0xc71caaaa1c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e35555e38eULL, 0x38e35555e38e38e3ULL, },
+ { 0x1c71c71c55551c71ULL, 0xc71c55551c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38ecccccccce38eULL, 0xcccccccce38eccccULL, },
+ { 0x1c71cccccccc1c71ULL, 0xcccccccc1c71ccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e33333333e38eULL, 0x33333333e38e3333ULL, },
+ { 0x1c71333333331c71ULL, 0x333333331c713333ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e3aaaae38eULL, 0x38e3aaaae38e38e3ULL, },
+ { 0xe38e38e35555e38eULL, 0x38e35555e38e38e3ULL, },
+ { 0xe38ecccccccce38eULL, 0xcccccccce38eccccULL, },
+ { 0xe38e33333333e38eULL, 0x33333333e38e3333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71caaaa1c71ULL, 0xc71caaaa1c71c71cULL, },
+ { 0x1c71c71c55551c71ULL, 0xc71c55551c71c71cULL, },
+ { 0x1c71cccccccc1c71ULL, 0xcccccccc1c71ccccULL, },
+ { 0x1c71333333331c71ULL, 0x333333331c713333ULL, },
+ { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00632862c708ULL, 0x12f70b5efe7bb00cULL, },
+ { 0xac5ae6cc28625540ULL, 0x27d80b5efe7b2514ULL, },
+ { 0x704f164d2862e24eULL, 0x4b670b5efe7be2a0ULL, },
+ { 0xfbbe00632862c708ULL, 0x12f70b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe0063b9cfc708ULL, 0x12f7c6ff153f2514ULL, },
+ { 0xfbbe00634d93e24eULL, 0x12f7bb1a153fe2a0ULL, },
+ { 0xac5ae6cc28625540ULL, 0x27d80b5efe7b2514ULL, }, /* 72 */
+ { 0xfbbe0063b9cfc708ULL, 0x12f7c6ff153f2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5a164db9cfe24eULL, 0x27d8c6ffab2be2a0ULL, },
+ { 0x704f164d2862e24eULL, 0x4b670b5efe7be2a0ULL, },
+ { 0xfbbe00634d93e24eULL, 0x12f7bb1a153fe2a0ULL, },
+ { 0xac5a164db9cfe24eULL, 0x27d8c6ffab2be2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_A_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_A_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MIN_A.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MIN_A.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71caaaaaaaaULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e355555555ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, },
+ { 0x1c71c71cccccccccULL, 0xcccccccc1c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e333333333ULL, 0x33333333e38e38e3ULL, },
+ { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e355555555ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, },
+ { 0xe38e38e333333333ULL, 0x33333333e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71caaaaaaaaULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71cccccccccULL, 0xcccccccc1c71c71cULL, },
+ { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe006328625540ULL, 0x12f7bb1afe7bb00cULL, },
+ { 0xac5aaeaa28625540ULL, 0x27d8c6fffe7bb00cULL, },
+ { 0x704f164d28625540ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe006328625540ULL, 0x12f7bb1afe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe0063b9cf8b80ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaa28625540ULL, 0x27d8c6fffe7bb00cULL, }, /* 72 */
+ { 0xfbbe0063b9cf8b80ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d28625540ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_A_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_A_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MIN_S.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MIN_S.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xe38effe38effe38eULL, 0xffe38effe38effe3ULL, },
+ { 0xffffc7ffffc7ffffULL, 0xc7ffffc7ffffc7ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e00e38e00e38eULL, 0x00e38e00e38e00e3ULL, },
+ { 0x0000c70000c70000ULL, 0xc70000c70000c700ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaa8eaaaa8eaaaa8eULL, 0xaaaa8eaaaa8eaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c55c71c55c71c55ULL, 0xc71c55c71c55c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcc8ecccc8ecccc8eULL, 0xcccc8ecccc8eccccULL, },
+ { 0xccccc7ccccc7ccccULL, 0xc7ccccc7ccccc7ccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e33e38e33e38eULL, 0x33e38e33e38e33e3ULL, },
+ { 0x1c33c71c33c71c33ULL, 0xc71c33c71c33c71cULL, },
+ { 0xe38effe38effe38eULL, 0xffe38effe38effe3ULL, }, /* 48 */
+ { 0xe38e00e38e00e38eULL, 0x00e38e00e38e00e3ULL, },
+ { 0xaa8eaaaa8eaaaa8eULL, 0xaaaa8eaaaa8eaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xcc8ecccc8ecccc8eULL, 0xcccc8ecccc8eccccULL, },
+ { 0xe38e33e38e33e38eULL, 0x33e38e33e38e33e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, },
+ { 0xffffc7ffffc7ffffULL, 0xc7ffffc7ffffc7ffULL, }, /* 56 */
+ { 0x0000c70000c70000ULL, 0xc70000c70000c700ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c55c71c55c71c55ULL, 0xc71c55c71c55c71cULL, },
+ { 0xccccc7ccccc7ccccULL, 0xc7ccccc7ccccc7ccULL, },
+ { 0x1c33c71c33c71c33ULL, 0xc71c33c71c33c71cULL, },
+ { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x88bee6cc2893c708ULL, 0x12f7bb1afe3fb0fcULL, },
+ { 0x885aaeaab9cf8b80ULL, 0x27d8c6ffab2bb00cULL, },
+ { 0x884fe6cc2831e240ULL, 0x8df188d8a942b0a0ULL, },
+ { 0x88bee6cc2893c708ULL, 0x12f7bb1afe3fb0fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xacbeaeaab9938b80ULL, 0x12d8bbffab2b25fcULL, },
+ { 0xfbbe004d4d93c708ULL, 0x8df188d8a93fe2a0ULL, },
+ { 0x885aaeaab9cf8b80ULL, 0x27d8c6ffab2bb00cULL, }, /* 72 */
+ { 0xacbeaeaab9938b80ULL, 0x12d8bbffab2b25fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac4faeaab9cf8b80ULL, 0x8dd888d8a92be2a0ULL, },
+ { 0x884fe6cc2831e240ULL, 0x8df188d8a942b0a0ULL, },
+ { 0xfbbe004d4d93c708ULL, 0x8df188d8a93fe2a0ULL, },
+ { 0xac4faeaab9cf8b80ULL, 0x8dd888d8a92be2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_S_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_S_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MIN_S.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MIN_S.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xe38e38e38e38e38eULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_S_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_S_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MIN_S.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MIN_S.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xe38effff8e38e38eULL, 0xffff8e38e38effffULL, },
+ { 0xffffc71cffffffffULL, 0xc71cffffffffc71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e00008e38e38eULL, 0x00008e38e38e0000ULL, },
+ { 0x0000c71c00000000ULL, 0xc71c00000000c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa8e38aaaaULL, 0xaaaa8e38aaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c55551c71ULL, 0xc71c55551c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccccccc8e38ccccULL, 0xcccc8e38ccccccccULL, },
+ { 0xccccc71cccccccccULL, 0xc71cccccccccc71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e33338e38e38eULL, 0x33338e38e38e3333ULL, },
+ { 0x1c71c71c33331c71ULL, 0xc71c33331c71c71cULL, },
+ { 0xe38effff8e38e38eULL, 0xffff8e38e38effffULL, }, /* 48 */
+ { 0xe38e00008e38e38eULL, 0x00008e38e38e0000ULL, },
+ { 0xaaaaaaaa8e38aaaaULL, 0xaaaa8e38aaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xcccccccc8e38ccccULL, 0xcccc8e38ccccccccULL, },
+ { 0xe38e33338e38e38eULL, 0x33338e38e38e3333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, },
+ { 0xffffc71cffffffffULL, 0xc71cffffffffc71cULL, }, /* 56 */
+ { 0x0000c71c00000000ULL, 0xc71c00000000c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c71c71c55551c71ULL, 0xc71c55551c71c71cULL, },
+ { 0xccccc71cccccccccULL, 0xc71cccccccccc71cULL, },
+ { 0x1c71c71c33331c71ULL, 0xc71c33331c71c71cULL, },
+ { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc2862c708ULL, 0x12f7bb1afe7bb00cULL, },
+ { 0x886aaeaab9cf8b80ULL, 0x27d8c6ffab2bb00cULL, },
+ { 0x886ae6cc2862e24eULL, 0x8df188d8a942b00cULL, },
+ { 0x886ae6cc2862c708ULL, 0x12f7bb1afe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1aab2b2514ULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886aaeaab9cf8b80ULL, 0x27d8c6ffab2bb00cULL, }, /* 72 */
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1aab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc2862e24eULL, 0x8df188d8a942b00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_S_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_S_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MIN_S.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MIN_S.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xe38e38e38e38e38eULL, 0xffffffffe38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xc71c71c7ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0x00000000e38e38e3ULL, },
+ { 0x0000000000000000ULL, 0xc71c71c700000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccccccc8e38e38eULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c7ccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x33333333e38e38e3ULL, },
+ { 0x1c71c71c33333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0xffffffffe38e38e3ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x00000000e38e38e3ULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xcccccccc8e38e38eULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0x33333333e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xc71c71c7ffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xc71c71c700000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c7ccccccccULL, },
+ { 0x1c71c71c33333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc28625540ULL, 0x12f7bb1afe7bb00cULL, },
+ { 0x886ae6ccb9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x12f7bb1afe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1aab2b2514ULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6ccb9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1aab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_S_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_S_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MIN_U.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MIN_U.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaa8e38aa8e38aa8eULL, 0x38aa8e38aa8e38aaULL, },
+ { 0x1c71aa1c71aa1c71ULL, 0xaa1c71aa1c71aa1cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555385555385555ULL, 0x3855553855553855ULL, },
+ { 0x1c55551c55551c55ULL, 0x551c55551c55551cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xcc8e38cc8e38cc8eULL, 0x38cc8e38cc8e38ccULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c33331c33331c33ULL, 0x331c33331c33331cULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaa8e38aa8e38aa8eULL, 0x38aa8e38aa8e38aaULL, },
+ { 0x5555385555385555ULL, 0x3855553855553855ULL, },
+ { 0xcc8e38cc8e38cc8eULL, 0x38cc8e38cc8e38ccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71aa1c71aa1c71ULL, 0xaa1c71aa1c71aa1cULL, },
+ { 0x1c55551c55551c55ULL, 0x551c55551c55551cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c33331c33331c33ULL, 0x331c33331c33331cULL, },
+ { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886a006328625508ULL, 0x12670b1a153f520cULL, },
+ { 0x885aaeaa28625540ULL, 0x27670b5eab2b250cULL, },
+ { 0x704f164d28315540ULL, 0x4b670b5ea942b00cULL, },
+ { 0x886a006328625508ULL, 0x12670b1a153f520cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5a00634d938b08ULL, 0x12d8bb1a152b2514ULL, },
+ { 0x704f004d4d31c708ULL, 0x12f1881a153f52a0ULL, },
+ { 0x885aaeaa28625540ULL, 0x27670b5eab2b250cULL, }, /* 72 */
+ { 0xac5a00634d938b08ULL, 0x12d8bb1a152b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e318b4eULL, 0x27d888d8a92b2514ULL, },
+ { 0x704f164d28315540ULL, 0x4b670b5ea942b00cULL, },
+ { 0x704f004d4d31c708ULL, 0x12f1881a153f52a0ULL, },
+ { 0x704f164d5e318b4eULL, 0x27d888d8a92b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_U_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_U_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MIN_U.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MIN_U.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x5555555555555555ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c71c71c71c71c71ULL, 0x5555555555555555ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_U_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_U_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MIN_U.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MIN_U.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaa38e38e38aaaaULL, 0x38e38e38aaaa38e3ULL, },
+ { 0x1c71aaaa71c71c71ULL, 0xaaaa71c71c71aaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x555538e355555555ULL, 0x38e35555555538e3ULL, },
+ { 0x1c71555555551c71ULL, 0x555555551c715555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xcccc38e38e38ccccULL, 0x38e38e38cccc38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c71333333331c71ULL, 0x333333331c713333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaa38e38e38aaaaULL, 0x38e38e38aaaa38e3ULL, },
+ { 0x555538e355555555ULL, 0x38e35555555538e3ULL, },
+ { 0xcccc38e38e38ccccULL, 0x38e38e38cccc38e3ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71aaaa71c71c71ULL, 0xaaaa71c71c71aaaaULL, },
+ { 0x1c71555555551c71ULL, 0x555555551c715555ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71333333331c71ULL, 0x333333331c713333ULL, },
+ { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886a006328625540ULL, 0x12f70b5e153f52fcULL, },
+ { 0x886aaeaa28625540ULL, 0x27d80b5eab2b2514ULL, },
+ { 0x704f164d28625540ULL, 0x4b670b5ea942b00cULL, },
+ { 0x886a006328625540ULL, 0x12f70b5e153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5a00634d938b80ULL, 0x12f7bb1a153f2514ULL, },
+ { 0x704f00634d93c708ULL, 0x12f788d8153f52fcULL, },
+ { 0x886aaeaa28625540ULL, 0x27d80b5eab2b2514ULL, }, /* 72 */
+ { 0xac5a00634d938b80ULL, 0x12f7bb1a153f2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e318b80ULL, 0x27d888d8a9422514ULL, },
+ { 0x704f164d28625540ULL, 0x4b670b5ea942b00cULL, },
+ { 0x704f00634d93c708ULL, 0x12f788d8153f52fcULL, },
+ { 0x704f164d5e318b80ULL, 0x27d888d8a9422514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_U_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_U_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction MIN_U.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MIN_U.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0x38e38e38aaaaaaaaULL, },
+ { 0x1c71c71c71c71c71ULL, 0xaaaaaaaa1c71c71cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x38e38e3855555555ULL, },
+ { 0x1c71c71c55555555ULL, 0x555555551c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0x38e38e38aaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x38e38e3855555555ULL, },
+ { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xaaaaaaaa1c71c71cULL, },
+ { 0x1c71c71c55555555ULL, 0x555555551c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d28625540ULL, 0x4b670b5ea942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaa4d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d4d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */
+ { 0xac5aaeaa4d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffa942e2a0ULL, },
+ { 0x704f164d28625540ULL, 0x4b670b5ea942e2a0ULL, },
+ { 0x704f164d4d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffa942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_U_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_U_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVEV.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "*ILVEV.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xff00ff00ff00ff00ULL, 0xff00ff00ff00ff00ULL, },
+ { 0xffaaffaaffaaffaaULL, 0xffaaffaaffaaffaaULL, },
+ { 0xff55ff55ff55ff55ULL, 0xff55ff55ff55ff55ULL, },
+ { 0xffccffccffccffccULL, 0xffccffccffccffccULL, },
+ { 0xff33ff33ff33ff33ULL, 0xff33ff33ff33ff33ULL, },
+ { 0xff8effe3ff38ff8eULL, 0xffe3ff38ff8effe3ULL, },
+ { 0xff71ff1cffc7ff71ULL, 0xff1cffc7ff71ff1cULL, },
+ { 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00aa00aa00aa00aaULL, 0x00aa00aa00aa00aaULL, },
+ { 0x0055005500550055ULL, 0x0055005500550055ULL, },
+ { 0x00cc00cc00cc00ccULL, 0x00cc00cc00cc00ccULL, },
+ { 0x0033003300330033ULL, 0x0033003300330033ULL, },
+ { 0x008e00e30038008eULL, 0x00e30038008e00e3ULL, },
+ { 0x0071001c00c70071ULL, 0x001c00c70071001cULL, },
+ { 0xaaffaaffaaffaaffULL, 0xaaffaaffaaffaaffULL, }, /* 16 */
+ { 0xaa00aa00aa00aa00ULL, 0xaa00aa00aa00aa00ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaa55aa55aa55aa55ULL, 0xaa55aa55aa55aa55ULL, },
+ { 0xaaccaaccaaccaaccULL, 0xaaccaaccaaccaaccULL, },
+ { 0xaa33aa33aa33aa33ULL, 0xaa33aa33aa33aa33ULL, },
+ { 0xaa8eaae3aa38aa8eULL, 0xaae3aa38aa8eaae3ULL, },
+ { 0xaa71aa1caac7aa71ULL, 0xaa1caac7aa71aa1cULL, },
+ { 0x55ff55ff55ff55ffULL, 0x55ff55ff55ff55ffULL, }, /* 24 */
+ { 0x5500550055005500ULL, 0x5500550055005500ULL, },
+ { 0x55aa55aa55aa55aaULL, 0x55aa55aa55aa55aaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x55cc55cc55cc55ccULL, 0x55cc55cc55cc55ccULL, },
+ { 0x5533553355335533ULL, 0x5533553355335533ULL, },
+ { 0x558e55e35538558eULL, 0x55e35538558e55e3ULL, },
+ { 0x5571551c55c75571ULL, 0x551c55c75571551cULL, },
+ { 0xccffccffccffccffULL, 0xccffccffccffccffULL, }, /* 32 */
+ { 0xcc00cc00cc00cc00ULL, 0xcc00cc00cc00cc00ULL, },
+ { 0xccaaccaaccaaccaaULL, 0xccaaccaaccaaccaaULL, },
+ { 0xcc55cc55cc55cc55ULL, 0xcc55cc55cc55cc55ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcc33cc33cc33cc33ULL, 0xcc33cc33cc33cc33ULL, },
+ { 0xcc8ecce3cc38cc8eULL, 0xcce3cc38cc8ecce3ULL, },
+ { 0xcc71cc1cccc7cc71ULL, 0xcc1cccc7cc71cc1cULL, },
+ { 0x33ff33ff33ff33ffULL, 0x33ff33ff33ff33ffULL, }, /* 40 */
+ { 0x3300330033003300ULL, 0x3300330033003300ULL, },
+ { 0x33aa33aa33aa33aaULL, 0x33aa33aa33aa33aaULL, },
+ { 0x3355335533553355ULL, 0x3355335533553355ULL, },
+ { 0x33cc33cc33cc33ccULL, 0x33cc33cc33cc33ccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x338e33e33338338eULL, 0x33e33338338e33e3ULL, },
+ { 0x3371331c33c73371ULL, 0x331c33c73371331cULL, },
+ { 0x8effe3ff38ff8effULL, 0xe3ff38ff8effe3ffULL, }, /* 48 */
+ { 0x8e00e30038008e00ULL, 0xe30038008e00e300ULL, },
+ { 0x8eaae3aa38aa8eaaULL, 0xe3aa38aa8eaae3aaULL, },
+ { 0x8e55e35538558e55ULL, 0xe35538558e55e355ULL, },
+ { 0x8ecce3cc38cc8eccULL, 0xe3cc38cc8ecce3ccULL, },
+ { 0x8e33e33338338e33ULL, 0xe33338338e33e333ULL, },
+ { 0x8e8ee3e338388e8eULL, 0xe3e338388e8ee3e3ULL, },
+ { 0x8e71e31c38c78e71ULL, 0xe31c38c78e71e31cULL, },
+ { 0x71ff1cffc7ff71ffULL, 0x1cffc7ff71ff1cffULL, }, /* 56 */
+ { 0x71001c00c7007100ULL, 0x1c00c70071001c00ULL, },
+ { 0x71aa1caac7aa71aaULL, 0x1caac7aa71aa1caaULL, },
+ { 0x71551c55c7557155ULL, 0x1c55c75571551c55ULL, },
+ { 0x71cc1cccc7cc71ccULL, 0x1cccc7cc71cc1cccULL, },
+ { 0x71331c33c7337133ULL, 0x1c33c73371331c33ULL, },
+ { 0x718e1ce3c738718eULL, 0x1ce3c738718e1ce3ULL, },
+ { 0x71711c1cc7c77171ULL, 0x1c1cc7c771711c1cULL, },
+ { 0x6a6acccc62624040ULL, 0x67675e5e7b7b0c0cULL, }, /* 64 */
+ { 0x6abecc6362934008ULL, 0x67f75e1a7b3f0cfcULL, },
+ { 0x6a5accaa62cf4080ULL, 0x67d85eff7b2b0c14ULL, },
+ { 0x6a4fcc4d6231404eULL, 0x67f15ed87b420ca0ULL, },
+ { 0xbe6a63cc93620840ULL, 0xf7671a5e3f7bfc0cULL, },
+ { 0xbebe636393930808ULL, 0xf7f71a1a3f3ffcfcULL, },
+ { 0xbe5a63aa93cf0880ULL, 0xf7d81aff3f2bfc14ULL, },
+ { 0xbe4f634d9331084eULL, 0xf7f11ad83f42fca0ULL, },
+ { 0x5a6aaacccf628040ULL, 0xd867ff5e2b7b140cULL, }, /* 72 */
+ { 0x5abeaa63cf938008ULL, 0xd8f7ff1a2b3f14fcULL, },
+ { 0x5a5aaaaacfcf8080ULL, 0xd8d8ffff2b2b1414ULL, },
+ { 0x5a4faa4dcf31804eULL, 0xd8f1ffd82b4214a0ULL, },
+ { 0x4f6a4dcc31624e40ULL, 0xf167d85e427ba00cULL, },
+ { 0x4fbe4d6331934e08ULL, 0xf1f7d81a423fa0fcULL, },
+ { 0x4f5a4daa31cf4e80ULL, 0xf1d8d8ff422ba014ULL, },
+ { 0x4f4f4d4d31314e4eULL, 0xf1f1d8d84242a0a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVEV_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVEV_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVEV.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "*ILVEV.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0xffffffffffffffffULL, },
+ { 0xe38e38e38e38e38eULL, 0xffffffffffffffffULL, },
+ { 0x1c71c71c71c71c71ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e38e38e38eULL, 0x5555555555555555ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, },
+ { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0xe38e38e38e38e38eULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0xe38e38e38e38e38eULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xe38e38e38e38e38eULL, },
+ { 0x5555555555555555ULL, 0xe38e38e38e38e38eULL, },
+ { 0xccccccccccccccccULL, 0xe38e38e38e38e38eULL, },
+ { 0x3333333333333333ULL, 0xe38e38e38e38e38eULL, },
+ { 0xe38e38e38e38e38eULL, 0xe38e38e38e38e38eULL, },
+ { 0x1c71c71c71c71c71ULL, 0xe38e38e38e38e38eULL, },
+ { 0xffffffffffffffffULL, 0x1c71c71c71c71c71ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x1c71c71c71c71c71ULL, },
+ { 0x5555555555555555ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xccccccccccccccccULL, 0x1c71c71c71c71c71ULL, },
+ { 0x3333333333333333ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xe38e38e38e38e38eULL, 0x1c71c71c71c71c71ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x1c71c71c71c71c71ULL, },
+ { 0x886ae6cc28625540ULL, 0x886ae6cc28625540ULL, }, /* 64 */
+ { 0xfbbe00634d93c708ULL, 0x886ae6cc28625540ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x886ae6cc28625540ULL, },
+ { 0x704f164d5e31e24eULL, 0x886ae6cc28625540ULL, },
+ { 0x886ae6cc28625540ULL, 0xfbbe00634d93c708ULL, },
+ { 0xfbbe00634d93c708ULL, 0xfbbe00634d93c708ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0xfbbe00634d93c708ULL, },
+ { 0x704f164d5e31e24eULL, 0xfbbe00634d93c708ULL, },
+ { 0x886ae6cc28625540ULL, 0xac5aaeaab9cf8b80ULL, }, /* 72 */
+ { 0xfbbe00634d93c708ULL, 0xac5aaeaab9cf8b80ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0xac5aaeaab9cf8b80ULL, },
+ { 0x704f164d5e31e24eULL, 0xac5aaeaab9cf8b80ULL, },
+ { 0x886ae6cc28625540ULL, 0x704f164d5e31e24eULL, },
+ { 0xfbbe00634d93c708ULL, 0x704f164d5e31e24eULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x704f164d5e31e24eULL, },
+ { 0x704f164d5e31e24eULL, 0x704f164d5e31e24eULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVEV_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVEV_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVEV.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "*ILVEV.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffff0000ffff0000ULL, 0xffff0000ffff0000ULL, },
+ { 0xffffaaaaffffaaaaULL, 0xffffaaaaffffaaaaULL, },
+ { 0xffff5555ffff5555ULL, 0xffff5555ffff5555ULL, },
+ { 0xffffccccffffccccULL, 0xffffccccffffccccULL, },
+ { 0xffff3333ffff3333ULL, 0xffff3333ffff3333ULL, },
+ { 0xffff38e3ffffe38eULL, 0xffff8e38ffff38e3ULL, },
+ { 0xffffc71cffff1c71ULL, 0xffff71c7ffffc71cULL, },
+ { 0x0000ffff0000ffffULL, 0x0000ffff0000ffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000aaaa0000aaaaULL, 0x0000aaaa0000aaaaULL, },
+ { 0x0000555500005555ULL, 0x0000555500005555ULL, },
+ { 0x0000cccc0000ccccULL, 0x0000cccc0000ccccULL, },
+ { 0x0000333300003333ULL, 0x0000333300003333ULL, },
+ { 0x000038e30000e38eULL, 0x00008e38000038e3ULL, },
+ { 0x0000c71c00001c71ULL, 0x000071c70000c71cULL, },
+ { 0xaaaaffffaaaaffffULL, 0xaaaaffffaaaaffffULL, }, /* 16 */
+ { 0xaaaa0000aaaa0000ULL, 0xaaaa0000aaaa0000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaa5555aaaa5555ULL, 0xaaaa5555aaaa5555ULL, },
+ { 0xaaaaccccaaaaccccULL, 0xaaaaccccaaaaccccULL, },
+ { 0xaaaa3333aaaa3333ULL, 0xaaaa3333aaaa3333ULL, },
+ { 0xaaaa38e3aaaae38eULL, 0xaaaa8e38aaaa38e3ULL, },
+ { 0xaaaac71caaaa1c71ULL, 0xaaaa71c7aaaac71cULL, },
+ { 0x5555ffff5555ffffULL, 0x5555ffff5555ffffULL, }, /* 24 */
+ { 0x5555000055550000ULL, 0x5555000055550000ULL, },
+ { 0x5555aaaa5555aaaaULL, 0x5555aaaa5555aaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555cccc5555ccccULL, 0x5555cccc5555ccccULL, },
+ { 0x5555333355553333ULL, 0x5555333355553333ULL, },
+ { 0x555538e35555e38eULL, 0x55558e38555538e3ULL, },
+ { 0x5555c71c55551c71ULL, 0x555571c75555c71cULL, },
+ { 0xccccffffccccffffULL, 0xccccffffccccffffULL, }, /* 32 */
+ { 0xcccc0000cccc0000ULL, 0xcccc0000cccc0000ULL, },
+ { 0xccccaaaaccccaaaaULL, 0xccccaaaaccccaaaaULL, },
+ { 0xcccc5555cccc5555ULL, 0xcccc5555cccc5555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccc3333cccc3333ULL, 0xcccc3333cccc3333ULL, },
+ { 0xcccc38e3cccce38eULL, 0xcccc8e38cccc38e3ULL, },
+ { 0xccccc71ccccc1c71ULL, 0xcccc71c7ccccc71cULL, },
+ { 0x3333ffff3333ffffULL, 0x3333ffff3333ffffULL, }, /* 40 */
+ { 0x3333000033330000ULL, 0x3333000033330000ULL, },
+ { 0x3333aaaa3333aaaaULL, 0x3333aaaa3333aaaaULL, },
+ { 0x3333555533335555ULL, 0x3333555533335555ULL, },
+ { 0x3333cccc3333ccccULL, 0x3333cccc3333ccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x333338e33333e38eULL, 0x33338e38333338e3ULL, },
+ { 0x3333c71c33331c71ULL, 0x333371c73333c71cULL, },
+ { 0x38e3ffffe38effffULL, 0x8e38ffff38e3ffffULL, }, /* 48 */
+ { 0x38e30000e38e0000ULL, 0x8e38000038e30000ULL, },
+ { 0x38e3aaaae38eaaaaULL, 0x8e38aaaa38e3aaaaULL, },
+ { 0x38e35555e38e5555ULL, 0x8e38555538e35555ULL, },
+ { 0x38e3cccce38eccccULL, 0x8e38cccc38e3ccccULL, },
+ { 0x38e33333e38e3333ULL, 0x8e38333338e33333ULL, },
+ { 0x38e338e3e38ee38eULL, 0x8e388e3838e338e3ULL, },
+ { 0x38e3c71ce38e1c71ULL, 0x8e3871c738e3c71cULL, },
+ { 0xc71cffff1c71ffffULL, 0x71c7ffffc71cffffULL, }, /* 56 */
+ { 0xc71c00001c710000ULL, 0x71c70000c71c0000ULL, },
+ { 0xc71caaaa1c71aaaaULL, 0x71c7aaaac71caaaaULL, },
+ { 0xc71c55551c715555ULL, 0x71c75555c71c5555ULL, },
+ { 0xc71ccccc1c71ccccULL, 0x71c7ccccc71cccccULL, },
+ { 0xc71c33331c713333ULL, 0x71c73333c71c3333ULL, },
+ { 0xc71c38e31c71e38eULL, 0x71c78e38c71c38e3ULL, },
+ { 0xc71cc71c1c711c71ULL, 0x71c771c7c71cc71cULL, },
+ { 0xe6cce6cc55405540ULL, 0x0b5e0b5eb00cb00cULL, }, /* 64 */
+ { 0xe6cc00635540c708ULL, 0x0b5ebb1ab00c52fcULL, },
+ { 0xe6ccaeaa55408b80ULL, 0x0b5ec6ffb00c2514ULL, },
+ { 0xe6cc164d5540e24eULL, 0x0b5e88d8b00ce2a0ULL, },
+ { 0x0063e6ccc7085540ULL, 0xbb1a0b5e52fcb00cULL, },
+ { 0x00630063c708c708ULL, 0xbb1abb1a52fc52fcULL, },
+ { 0x0063aeaac7088b80ULL, 0xbb1ac6ff52fc2514ULL, },
+ { 0x0063164dc708e24eULL, 0xbb1a88d852fce2a0ULL, },
+ { 0xaeaae6cc8b805540ULL, 0xc6ff0b5e2514b00cULL, }, /* 72 */
+ { 0xaeaa00638b80c708ULL, 0xc6ffbb1a251452fcULL, },
+ { 0xaeaaaeaa8b808b80ULL, 0xc6ffc6ff25142514ULL, },
+ { 0xaeaa164d8b80e24eULL, 0xc6ff88d82514e2a0ULL, },
+ { 0x164de6cce24e5540ULL, 0x88d80b5ee2a0b00cULL, },
+ { 0x164d0063e24ec708ULL, 0x88d8bb1ae2a052fcULL, },
+ { 0x164daeaae24e8b80ULL, 0x88d8c6ffe2a02514ULL, },
+ { 0x164d164de24ee24eULL, 0x88d888d8e2a0e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVEV_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVEV_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVEV.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "ILVEV.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffff00000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffaaaaaaaaULL, 0xffffffffaaaaaaaaULL, },
+ { 0xffffffff55555555ULL, 0xffffffff55555555ULL, },
+ { 0xffffffffccccccccULL, 0xffffffffccccccccULL, },
+ { 0xffffffff33333333ULL, 0xffffffff33333333ULL, },
+ { 0xffffffff8e38e38eULL, 0xffffffffe38e38e3ULL, },
+ { 0xffffffff71c71c71ULL, 0xffffffff1c71c71cULL, },
+ { 0x00000000ffffffffULL, 0x00000000ffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000aaaaaaaaULL, 0x00000000aaaaaaaaULL, },
+ { 0x0000000055555555ULL, 0x0000000055555555ULL, },
+ { 0x00000000ccccccccULL, 0x00000000ccccccccULL, },
+ { 0x0000000033333333ULL, 0x0000000033333333ULL, },
+ { 0x000000008e38e38eULL, 0x00000000e38e38e3ULL, },
+ { 0x0000000071c71c71ULL, 0x000000001c71c71cULL, },
+ { 0xaaaaaaaaffffffffULL, 0xaaaaaaaaffffffffULL, }, /* 16 */
+ { 0xaaaaaaaa00000000ULL, 0xaaaaaaaa00000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa55555555ULL, 0xaaaaaaaa55555555ULL, },
+ { 0xaaaaaaaaccccccccULL, 0xaaaaaaaaccccccccULL, },
+ { 0xaaaaaaaa33333333ULL, 0xaaaaaaaa33333333ULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaae38e38e3ULL, },
+ { 0xaaaaaaaa71c71c71ULL, 0xaaaaaaaa1c71c71cULL, },
+ { 0x55555555ffffffffULL, 0x55555555ffffffffULL, }, /* 24 */
+ { 0x5555555500000000ULL, 0x5555555500000000ULL, },
+ { 0x55555555aaaaaaaaULL, 0x55555555aaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x55555555ccccccccULL, 0x55555555ccccccccULL, },
+ { 0x5555555533333333ULL, 0x5555555533333333ULL, },
+ { 0x555555558e38e38eULL, 0x55555555e38e38e3ULL, },
+ { 0x5555555571c71c71ULL, 0x555555551c71c71cULL, },
+ { 0xccccccccffffffffULL, 0xccccccccffffffffULL, }, /* 32 */
+ { 0xcccccccc00000000ULL, 0xcccccccc00000000ULL, },
+ { 0xccccccccaaaaaaaaULL, 0xccccccccaaaaaaaaULL, },
+ { 0xcccccccc55555555ULL, 0xcccccccc55555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccccccc33333333ULL, 0xcccccccc33333333ULL, },
+ { 0xcccccccc8e38e38eULL, 0xcccccccce38e38e3ULL, },
+ { 0xcccccccc71c71c71ULL, 0xcccccccc1c71c71cULL, },
+ { 0x33333333ffffffffULL, 0x33333333ffffffffULL, }, /* 40 */
+ { 0x3333333300000000ULL, 0x3333333300000000ULL, },
+ { 0x33333333aaaaaaaaULL, 0x33333333aaaaaaaaULL, },
+ { 0x3333333355555555ULL, 0x3333333355555555ULL, },
+ { 0x33333333ccccccccULL, 0x33333333ccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x333333338e38e38eULL, 0x33333333e38e38e3ULL, },
+ { 0x3333333371c71c71ULL, 0x333333331c71c71cULL, },
+ { 0x8e38e38effffffffULL, 0xe38e38e3ffffffffULL, }, /* 48 */
+ { 0x8e38e38e00000000ULL, 0xe38e38e300000000ULL, },
+ { 0x8e38e38eaaaaaaaaULL, 0xe38e38e3aaaaaaaaULL, },
+ { 0x8e38e38e55555555ULL, 0xe38e38e355555555ULL, },
+ { 0x8e38e38eccccccccULL, 0xe38e38e3ccccccccULL, },
+ { 0x8e38e38e33333333ULL, 0xe38e38e333333333ULL, },
+ { 0x8e38e38e8e38e38eULL, 0xe38e38e3e38e38e3ULL, },
+ { 0x8e38e38e71c71c71ULL, 0xe38e38e31c71c71cULL, },
+ { 0x71c71c71ffffffffULL, 0x1c71c71cffffffffULL, }, /* 56 */
+ { 0x71c71c7100000000ULL, 0x1c71c71c00000000ULL, },
+ { 0x71c71c71aaaaaaaaULL, 0x1c71c71caaaaaaaaULL, },
+ { 0x71c71c7155555555ULL, 0x1c71c71c55555555ULL, },
+ { 0x71c71c71ccccccccULL, 0x1c71c71cccccccccULL, },
+ { 0x71c71c7133333333ULL, 0x1c71c71c33333333ULL, },
+ { 0x71c71c718e38e38eULL, 0x1c71c71ce38e38e3ULL, },
+ { 0x71c71c7171c71c71ULL, 0x1c71c71c1c71c71cULL, },
+ { 0x2862554028625540ULL, 0xfe7bb00cfe7bb00cULL, }, /* 64 */
+ { 0x286255404d93c708ULL, 0xfe7bb00c153f52fcULL, },
+ { 0x28625540b9cf8b80ULL, 0xfe7bb00cab2b2514ULL, },
+ { 0x286255405e31e24eULL, 0xfe7bb00ca942e2a0ULL, },
+ { 0x4d93c70828625540ULL, 0x153f52fcfe7bb00cULL, },
+ { 0x4d93c7084d93c708ULL, 0x153f52fc153f52fcULL, },
+ { 0x4d93c708b9cf8b80ULL, 0x153f52fcab2b2514ULL, },
+ { 0x4d93c7085e31e24eULL, 0x153f52fca942e2a0ULL, },
+ { 0xb9cf8b8028625540ULL, 0xab2b2514fe7bb00cULL, }, /* 72 */
+ { 0xb9cf8b804d93c708ULL, 0xab2b2514153f52fcULL, },
+ { 0xb9cf8b80b9cf8b80ULL, 0xab2b2514ab2b2514ULL, },
+ { 0xb9cf8b805e31e24eULL, 0xab2b2514a942e2a0ULL, },
+ { 0x5e31e24e28625540ULL, 0xa942e2a0fe7bb00cULL, },
+ { 0x5e31e24e4d93c708ULL, 0xa942e2a0153f52fcULL, },
+ { 0x5e31e24eb9cf8b80ULL, 0xa942e2a0ab2b2514ULL, },
+ { 0x5e31e24e5e31e24eULL, 0xa942e2a0a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVEV_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVEV_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVL.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "ILVL.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xff00ff00ff00ff00ULL, 0xff00ff00ff00ff00ULL, },
+ { 0xffaaffaaffaaffaaULL, 0xffaaffaaffaaffaaULL, },
+ { 0xff55ff55ff55ff55ULL, 0xff55ff55ff55ff55ULL, },
+ { 0xffccffccffccffccULL, 0xffccffccffccffccULL, },
+ { 0xff33ff33ff33ff33ULL, 0xff33ff33ff33ff33ULL, },
+ { 0xffe3ff8eff38ffe3ULL, 0xff38ffe3ff8eff38ULL, },
+ { 0xff1cff71ffc7ff1cULL, 0xffc7ff1cff71ffc7ULL, },
+ { 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00aa00aa00aa00aaULL, 0x00aa00aa00aa00aaULL, },
+ { 0x0055005500550055ULL, 0x0055005500550055ULL, },
+ { 0x00cc00cc00cc00ccULL, 0x00cc00cc00cc00ccULL, },
+ { 0x0033003300330033ULL, 0x0033003300330033ULL, },
+ { 0x00e3008e003800e3ULL, 0x003800e3008e0038ULL, },
+ { 0x001c007100c7001cULL, 0x00c7001c007100c7ULL, },
+ { 0xaaffaaffaaffaaffULL, 0xaaffaaffaaffaaffULL, }, /* 16 */
+ { 0xaa00aa00aa00aa00ULL, 0xaa00aa00aa00aa00ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaa55aa55aa55aa55ULL, 0xaa55aa55aa55aa55ULL, },
+ { 0xaaccaaccaaccaaccULL, 0xaaccaaccaaccaaccULL, },
+ { 0xaa33aa33aa33aa33ULL, 0xaa33aa33aa33aa33ULL, },
+ { 0xaae3aa8eaa38aae3ULL, 0xaa38aae3aa8eaa38ULL, },
+ { 0xaa1caa71aac7aa1cULL, 0xaac7aa1caa71aac7ULL, },
+ { 0x55ff55ff55ff55ffULL, 0x55ff55ff55ff55ffULL, }, /* 24 */
+ { 0x5500550055005500ULL, 0x5500550055005500ULL, },
+ { 0x55aa55aa55aa55aaULL, 0x55aa55aa55aa55aaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x55cc55cc55cc55ccULL, 0x55cc55cc55cc55ccULL, },
+ { 0x5533553355335533ULL, 0x5533553355335533ULL, },
+ { 0x55e3558e553855e3ULL, 0x553855e3558e5538ULL, },
+ { 0x551c557155c7551cULL, 0x55c7551c557155c7ULL, },
+ { 0xccffccffccffccffULL, 0xccffccffccffccffULL, }, /* 32 */
+ { 0xcc00cc00cc00cc00ULL, 0xcc00cc00cc00cc00ULL, },
+ { 0xccaaccaaccaaccaaULL, 0xccaaccaaccaaccaaULL, },
+ { 0xcc55cc55cc55cc55ULL, 0xcc55cc55cc55cc55ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcc33cc33cc33cc33ULL, 0xcc33cc33cc33cc33ULL, },
+ { 0xcce3cc8ecc38cce3ULL, 0xcc38cce3cc8ecc38ULL, },
+ { 0xcc1ccc71ccc7cc1cULL, 0xccc7cc1ccc71ccc7ULL, },
+ { 0x33ff33ff33ff33ffULL, 0x33ff33ff33ff33ffULL, }, /* 40 */
+ { 0x3300330033003300ULL, 0x3300330033003300ULL, },
+ { 0x33aa33aa33aa33aaULL, 0x33aa33aa33aa33aaULL, },
+ { 0x3355335533553355ULL, 0x3355335533553355ULL, },
+ { 0x33cc33cc33cc33ccULL, 0x33cc33cc33cc33ccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x33e3338e333833e3ULL, 0x333833e3338e3338ULL, },
+ { 0x331c337133c7331cULL, 0x33c7331c337133c7ULL, },
+ { 0xe3ff8eff38ffe3ffULL, 0x38ffe3ff8eff38ffULL, }, /* 48 */
+ { 0xe3008e003800e300ULL, 0x3800e3008e003800ULL, },
+ { 0xe3aa8eaa38aae3aaULL, 0x38aae3aa8eaa38aaULL, },
+ { 0xe3558e553855e355ULL, 0x3855e3558e553855ULL, },
+ { 0xe3cc8ecc38cce3ccULL, 0x38cce3cc8ecc38ccULL, },
+ { 0xe3338e333833e333ULL, 0x3833e3338e333833ULL, },
+ { 0xe3e38e8e3838e3e3ULL, 0x3838e3e38e8e3838ULL, },
+ { 0xe31c8e7138c7e31cULL, 0x38c7e31c8e7138c7ULL, },
+ { 0x1cff71ffc7ff1cffULL, 0xc7ff1cff71ffc7ffULL, }, /* 56 */
+ { 0x1c007100c7001c00ULL, 0xc7001c007100c700ULL, },
+ { 0x1caa71aac7aa1caaULL, 0xc7aa1caa71aac7aaULL, },
+ { 0x1c557155c7551c55ULL, 0xc7551c557155c755ULL, },
+ { 0x1ccc71ccc7cc1cccULL, 0xc7cc1ccc71ccc7ccULL, },
+ { 0x1c337133c7331c33ULL, 0xc7331c337133c733ULL, },
+ { 0x1ce3718ec7381ce3ULL, 0xc7381ce3718ec738ULL, },
+ { 0x1c1c7171c7c71c1cULL, 0xc7c71c1c7171c7c7ULL, },
+ { 0xfefe7b7bb0b00c0cULL, 0x4b4b67670b0b5e5eULL, }, /* 64 */
+ { 0xfe157b3fb0520cfcULL, 0x4b1267f70bbb5e1aULL, },
+ { 0xfeab7b2bb0250c14ULL, 0x4b2767d80bc65effULL, },
+ { 0xfea97b42b0e20ca0ULL, 0x4b8d67f10b885ed8ULL, },
+ { 0x15fe3f7b52b0fc0cULL, 0x124bf767bb0b1a5eULL, },
+ { 0x15153f3f5252fcfcULL, 0x1212f7f7bbbb1a1aULL, },
+ { 0x15ab3f2b5225fc14ULL, 0x1227f7d8bbc61affULL, },
+ { 0x15a93f4252e2fca0ULL, 0x128df7f1bb881ad8ULL, },
+ { 0xabfe2b7b25b0140cULL, 0x274bd867c60bff5eULL, }, /* 72 */
+ { 0xab152b3f255214fcULL, 0x2712d8f7c6bbff1aULL, },
+ { 0xabab2b2b25251414ULL, 0x2727d8d8c6c6ffffULL, },
+ { 0xaba92b4225e214a0ULL, 0x278dd8f1c688ffd8ULL, },
+ { 0xa9fe427be2b0a00cULL, 0x8d4bf167880bd85eULL, },
+ { 0xa915423fe252a0fcULL, 0x8d12f1f788bbd81aULL, },
+ { 0xa9ab422be225a014ULL, 0x8d27f1d888c6d8ffULL, },
+ { 0xa9a94242e2e2a0a0ULL, 0x8d8df1f18888d8d8ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVL_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVL_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVL.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "ILVL.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0xffffffffffffffffULL, },
+ { 0x38e38e38e38e38e3ULL, 0xffffffffffffffffULL, },
+ { 0xc71c71c71c71c71cULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x0000000000000000ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x0000000000000000ULL, },
+ { 0xc71c71c71c71c71cULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x38e38e38e38e38e3ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xc71c71c71c71c71cULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x5555555555555555ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x5555555555555555ULL, },
+ { 0xc71c71c71c71c71cULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xccccccccccccccccULL, },
+ { 0x38e38e38e38e38e3ULL, 0xccccccccccccccccULL, },
+ { 0xc71c71c71c71c71cULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x3333333333333333ULL, },
+ { 0xc71c71c71c71c71cULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x5555555555555555ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xc71c71c71c71c71cULL, 0x38e38e38e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0x38e38e38e38e38e3ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc71c71c71c71c71cULL, 0xc71c71c71c71c71cULL, },
+ { 0x4b670b5efe7bb00cULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x12f7bb1a153f52fcULL, 0x4b670b5efe7bb00cULL, },
+ { 0x27d8c6ffab2b2514ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x8df188d8a942e2a0ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x4b670b5efe7bb00cULL, 0x12f7bb1a153f52fcULL, },
+ { 0x12f7bb1a153f52fcULL, 0x12f7bb1a153f52fcULL, },
+ { 0x27d8c6ffab2b2514ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x8df188d8a942e2a0ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x4b670b5efe7bb00cULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */
+ { 0x12f7bb1a153f52fcULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x27d8c6ffab2b2514ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x8df188d8a942e2a0ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x4b670b5efe7bb00cULL, 0x8df188d8a942e2a0ULL, },
+ { 0x12f7bb1a153f52fcULL, 0x8df188d8a942e2a0ULL, },
+ { 0x27d8c6ffab2b2514ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x8df188d8a942e2a0ULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVL_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVL_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVL.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "ILVL.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffff0000ffff0000ULL, 0xffff0000ffff0000ULL, },
+ { 0xffffaaaaffffaaaaULL, 0xffffaaaaffffaaaaULL, },
+ { 0xffff5555ffff5555ULL, 0xffff5555ffff5555ULL, },
+ { 0xffffccccffffccccULL, 0xffffccccffffccccULL, },
+ { 0xffff3333ffff3333ULL, 0xffff3333ffff3333ULL, },
+ { 0xffffe38effff38e3ULL, 0xffff38e3ffff8e38ULL, },
+ { 0xffff1c71ffffc71cULL, 0xffffc71cffff71c7ULL, },
+ { 0x0000ffff0000ffffULL, 0x0000ffff0000ffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000aaaa0000aaaaULL, 0x0000aaaa0000aaaaULL, },
+ { 0x0000555500005555ULL, 0x0000555500005555ULL, },
+ { 0x0000cccc0000ccccULL, 0x0000cccc0000ccccULL, },
+ { 0x0000333300003333ULL, 0x0000333300003333ULL, },
+ { 0x0000e38e000038e3ULL, 0x000038e300008e38ULL, },
+ { 0x00001c710000c71cULL, 0x0000c71c000071c7ULL, },
+ { 0xaaaaffffaaaaffffULL, 0xaaaaffffaaaaffffULL, }, /* 16 */
+ { 0xaaaa0000aaaa0000ULL, 0xaaaa0000aaaa0000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaa5555aaaa5555ULL, 0xaaaa5555aaaa5555ULL, },
+ { 0xaaaaccccaaaaccccULL, 0xaaaaccccaaaaccccULL, },
+ { 0xaaaa3333aaaa3333ULL, 0xaaaa3333aaaa3333ULL, },
+ { 0xaaaae38eaaaa38e3ULL, 0xaaaa38e3aaaa8e38ULL, },
+ { 0xaaaa1c71aaaac71cULL, 0xaaaac71caaaa71c7ULL, },
+ { 0x5555ffff5555ffffULL, 0x5555ffff5555ffffULL, }, /* 24 */
+ { 0x5555000055550000ULL, 0x5555000055550000ULL, },
+ { 0x5555aaaa5555aaaaULL, 0x5555aaaa5555aaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555cccc5555ccccULL, 0x5555cccc5555ccccULL, },
+ { 0x5555333355553333ULL, 0x5555333355553333ULL, },
+ { 0x5555e38e555538e3ULL, 0x555538e355558e38ULL, },
+ { 0x55551c715555c71cULL, 0x5555c71c555571c7ULL, },
+ { 0xccccffffccccffffULL, 0xccccffffccccffffULL, }, /* 32 */
+ { 0xcccc0000cccc0000ULL, 0xcccc0000cccc0000ULL, },
+ { 0xccccaaaaccccaaaaULL, 0xccccaaaaccccaaaaULL, },
+ { 0xcccc5555cccc5555ULL, 0xcccc5555cccc5555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccc3333cccc3333ULL, 0xcccc3333cccc3333ULL, },
+ { 0xcccce38ecccc38e3ULL, 0xcccc38e3cccc8e38ULL, },
+ { 0xcccc1c71ccccc71cULL, 0xccccc71ccccc71c7ULL, },
+ { 0x3333ffff3333ffffULL, 0x3333ffff3333ffffULL, }, /* 40 */
+ { 0x3333000033330000ULL, 0x3333000033330000ULL, },
+ { 0x3333aaaa3333aaaaULL, 0x3333aaaa3333aaaaULL, },
+ { 0x3333555533335555ULL, 0x3333555533335555ULL, },
+ { 0x3333cccc3333ccccULL, 0x3333cccc3333ccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333e38e333338e3ULL, 0x333338e333338e38ULL, },
+ { 0x33331c713333c71cULL, 0x3333c71c333371c7ULL, },
+ { 0xe38effff38e3ffffULL, 0x38e3ffff8e38ffffULL, }, /* 48 */
+ { 0xe38e000038e30000ULL, 0x38e300008e380000ULL, },
+ { 0xe38eaaaa38e3aaaaULL, 0x38e3aaaa8e38aaaaULL, },
+ { 0xe38e555538e35555ULL, 0x38e355558e385555ULL, },
+ { 0xe38ecccc38e3ccccULL, 0x38e3cccc8e38ccccULL, },
+ { 0xe38e333338e33333ULL, 0x38e333338e383333ULL, },
+ { 0xe38ee38e38e338e3ULL, 0x38e338e38e388e38ULL, },
+ { 0xe38e1c7138e3c71cULL, 0x38e3c71c8e3871c7ULL, },
+ { 0x1c71ffffc71cffffULL, 0xc71cffff71c7ffffULL, }, /* 56 */
+ { 0x1c710000c71c0000ULL, 0xc71c000071c70000ULL, },
+ { 0x1c71aaaac71caaaaULL, 0xc71caaaa71c7aaaaULL, },
+ { 0x1c715555c71c5555ULL, 0xc71c555571c75555ULL, },
+ { 0x1c71ccccc71cccccULL, 0xc71ccccc71c7ccccULL, },
+ { 0x1c713333c71c3333ULL, 0xc71c333371c73333ULL, },
+ { 0x1c71e38ec71c38e3ULL, 0xc71c38e371c78e38ULL, },
+ { 0x1c711c71c71cc71cULL, 0xc71cc71c71c771c7ULL, },
+ { 0xfe7bfe7bb00cb00cULL, 0x4b674b670b5e0b5eULL, }, /* 64 */
+ { 0xfe7b153fb00c52fcULL, 0x4b6712f70b5ebb1aULL, },
+ { 0xfe7bab2bb00c2514ULL, 0x4b6727d80b5ec6ffULL, },
+ { 0xfe7ba942b00ce2a0ULL, 0x4b678df10b5e88d8ULL, },
+ { 0x153ffe7b52fcb00cULL, 0x12f74b67bb1a0b5eULL, },
+ { 0x153f153f52fc52fcULL, 0x12f712f7bb1abb1aULL, },
+ { 0x153fab2b52fc2514ULL, 0x12f727d8bb1ac6ffULL, },
+ { 0x153fa94252fce2a0ULL, 0x12f78df1bb1a88d8ULL, },
+ { 0xab2bfe7b2514b00cULL, 0x27d84b67c6ff0b5eULL, }, /* 72 */
+ { 0xab2b153f251452fcULL, 0x27d812f7c6ffbb1aULL, },
+ { 0xab2bab2b25142514ULL, 0x27d827d8c6ffc6ffULL, },
+ { 0xab2ba9422514e2a0ULL, 0x27d88df1c6ff88d8ULL, },
+ { 0xa942fe7be2a0b00cULL, 0x8df14b6788d80b5eULL, },
+ { 0xa942153fe2a052fcULL, 0x8df112f788d8bb1aULL, },
+ { 0xa942ab2be2a02514ULL, 0x8df127d888d8c6ffULL, },
+ { 0xa942a942e2a0e2a0ULL, 0x8df18df188d888d8ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVL_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVL_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVL.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "ILVL.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffff00000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffaaaaaaaaULL, 0xffffffffaaaaaaaaULL, },
+ { 0xffffffff55555555ULL, 0xffffffff55555555ULL, },
+ { 0xffffffffccccccccULL, 0xffffffffccccccccULL, },
+ { 0xffffffff33333333ULL, 0xffffffff33333333ULL, },
+ { 0xffffffffe38e38e3ULL, 0xffffffff38e38e38ULL, },
+ { 0xffffffff1c71c71cULL, 0xffffffffc71c71c7ULL, },
+ { 0x00000000ffffffffULL, 0x00000000ffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000aaaaaaaaULL, 0x00000000aaaaaaaaULL, },
+ { 0x0000000055555555ULL, 0x0000000055555555ULL, },
+ { 0x00000000ccccccccULL, 0x00000000ccccccccULL, },
+ { 0x0000000033333333ULL, 0x0000000033333333ULL, },
+ { 0x00000000e38e38e3ULL, 0x0000000038e38e38ULL, },
+ { 0x000000001c71c71cULL, 0x00000000c71c71c7ULL, },
+ { 0xaaaaaaaaffffffffULL, 0xaaaaaaaaffffffffULL, }, /* 16 */
+ { 0xaaaaaaaa00000000ULL, 0xaaaaaaaa00000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa55555555ULL, 0xaaaaaaaa55555555ULL, },
+ { 0xaaaaaaaaccccccccULL, 0xaaaaaaaaccccccccULL, },
+ { 0xaaaaaaaa33333333ULL, 0xaaaaaaaa33333333ULL, },
+ { 0xaaaaaaaae38e38e3ULL, 0xaaaaaaaa38e38e38ULL, },
+ { 0xaaaaaaaa1c71c71cULL, 0xaaaaaaaac71c71c7ULL, },
+ { 0x55555555ffffffffULL, 0x55555555ffffffffULL, }, /* 24 */
+ { 0x5555555500000000ULL, 0x5555555500000000ULL, },
+ { 0x55555555aaaaaaaaULL, 0x55555555aaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x55555555ccccccccULL, 0x55555555ccccccccULL, },
+ { 0x5555555533333333ULL, 0x5555555533333333ULL, },
+ { 0x55555555e38e38e3ULL, 0x5555555538e38e38ULL, },
+ { 0x555555551c71c71cULL, 0x55555555c71c71c7ULL, },
+ { 0xccccccccffffffffULL, 0xccccccccffffffffULL, }, /* 32 */
+ { 0xcccccccc00000000ULL, 0xcccccccc00000000ULL, },
+ { 0xccccccccaaaaaaaaULL, 0xccccccccaaaaaaaaULL, },
+ { 0xcccccccc55555555ULL, 0xcccccccc55555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccccccc33333333ULL, 0xcccccccc33333333ULL, },
+ { 0xcccccccce38e38e3ULL, 0xcccccccc38e38e38ULL, },
+ { 0xcccccccc1c71c71cULL, 0xccccccccc71c71c7ULL, },
+ { 0x33333333ffffffffULL, 0x33333333ffffffffULL, }, /* 40 */
+ { 0x3333333300000000ULL, 0x3333333300000000ULL, },
+ { 0x33333333aaaaaaaaULL, 0x33333333aaaaaaaaULL, },
+ { 0x3333333355555555ULL, 0x3333333355555555ULL, },
+ { 0x33333333ccccccccULL, 0x33333333ccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x33333333e38e38e3ULL, 0x3333333338e38e38ULL, },
+ { 0x333333331c71c71cULL, 0x33333333c71c71c7ULL, },
+ { 0xe38e38e3ffffffffULL, 0x38e38e38ffffffffULL, }, /* 48 */
+ { 0xe38e38e300000000ULL, 0x38e38e3800000000ULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0x38e38e38aaaaaaaaULL, },
+ { 0xe38e38e355555555ULL, 0x38e38e3855555555ULL, },
+ { 0xe38e38e3ccccccccULL, 0x38e38e38ccccccccULL, },
+ { 0xe38e38e333333333ULL, 0x38e38e3833333333ULL, },
+ { 0xe38e38e3e38e38e3ULL, 0x38e38e3838e38e38ULL, },
+ { 0xe38e38e31c71c71cULL, 0x38e38e38c71c71c7ULL, },
+ { 0x1c71c71cffffffffULL, 0xc71c71c7ffffffffULL, }, /* 56 */
+ { 0x1c71c71c00000000ULL, 0xc71c71c700000000ULL, },
+ { 0x1c71c71caaaaaaaaULL, 0xc71c71c7aaaaaaaaULL, },
+ { 0x1c71c71c55555555ULL, 0xc71c71c755555555ULL, },
+ { 0x1c71c71cccccccccULL, 0xc71c71c7ccccccccULL, },
+ { 0x1c71c71c33333333ULL, 0xc71c71c733333333ULL, },
+ { 0x1c71c71ce38e38e3ULL, 0xc71c71c738e38e38ULL, },
+ { 0x1c71c71c1c71c71cULL, 0xc71c71c7c71c71c7ULL, },
+ { 0xfe7bb00cfe7bb00cULL, 0x4b670b5e4b670b5eULL, }, /* 64 */
+ { 0xfe7bb00c153f52fcULL, 0x4b670b5e12f7bb1aULL, },
+ { 0xfe7bb00cab2b2514ULL, 0x4b670b5e27d8c6ffULL, },
+ { 0xfe7bb00ca942e2a0ULL, 0x4b670b5e8df188d8ULL, },
+ { 0x153f52fcfe7bb00cULL, 0x12f7bb1a4b670b5eULL, },
+ { 0x153f52fc153f52fcULL, 0x12f7bb1a12f7bb1aULL, },
+ { 0x153f52fcab2b2514ULL, 0x12f7bb1a27d8c6ffULL, },
+ { 0x153f52fca942e2a0ULL, 0x12f7bb1a8df188d8ULL, },
+ { 0xab2b2514fe7bb00cULL, 0x27d8c6ff4b670b5eULL, }, /* 72 */
+ { 0xab2b2514153f52fcULL, 0x27d8c6ff12f7bb1aULL, },
+ { 0xab2b2514ab2b2514ULL, 0x27d8c6ff27d8c6ffULL, },
+ { 0xab2b2514a942e2a0ULL, 0x27d8c6ff8df188d8ULL, },
+ { 0xa942e2a0fe7bb00cULL, 0x8df188d84b670b5eULL, },
+ { 0xa942e2a0153f52fcULL, 0x8df188d812f7bb1aULL, },
+ { 0xa942e2a0ab2b2514ULL, 0x8df188d827d8c6ffULL, },
+ { 0xa942e2a0a942e2a0ULL, 0x8df188d88df188d8ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVL_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVL_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVOD.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "ILVOD.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xff00ff00ff00ff00ULL, 0xff00ff00ff00ff00ULL, },
+ { 0xffaaffaaffaaffaaULL, 0xffaaffaaffaaffaaULL, },
+ { 0xff55ff55ff55ff55ULL, 0xff55ff55ff55ff55ULL, },
+ { 0xffccffccffccffccULL, 0xffccffccffccffccULL, },
+ { 0xff33ff33ff33ff33ULL, 0xff33ff33ff33ff33ULL, },
+ { 0xffe3ff38ff8effe3ULL, 0xff38ff8effe3ff38ULL, },
+ { 0xff1cffc7ff71ff1cULL, 0xffc7ff71ff1cffc7ULL, },
+ { 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00aa00aa00aa00aaULL, 0x00aa00aa00aa00aaULL, },
+ { 0x0055005500550055ULL, 0x0055005500550055ULL, },
+ { 0x00cc00cc00cc00ccULL, 0x00cc00cc00cc00ccULL, },
+ { 0x0033003300330033ULL, 0x0033003300330033ULL, },
+ { 0x00e30038008e00e3ULL, 0x0038008e00e30038ULL, },
+ { 0x001c00c70071001cULL, 0x00c70071001c00c7ULL, },
+ { 0xaaffaaffaaffaaffULL, 0xaaffaaffaaffaaffULL, }, /* 16 */
+ { 0xaa00aa00aa00aa00ULL, 0xaa00aa00aa00aa00ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaa55aa55aa55aa55ULL, 0xaa55aa55aa55aa55ULL, },
+ { 0xaaccaaccaaccaaccULL, 0xaaccaaccaaccaaccULL, },
+ { 0xaa33aa33aa33aa33ULL, 0xaa33aa33aa33aa33ULL, },
+ { 0xaae3aa38aa8eaae3ULL, 0xaa38aa8eaae3aa38ULL, },
+ { 0xaa1caac7aa71aa1cULL, 0xaac7aa71aa1caac7ULL, },
+ { 0x55ff55ff55ff55ffULL, 0x55ff55ff55ff55ffULL, }, /* 24 */
+ { 0x5500550055005500ULL, 0x5500550055005500ULL, },
+ { 0x55aa55aa55aa55aaULL, 0x55aa55aa55aa55aaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x55cc55cc55cc55ccULL, 0x55cc55cc55cc55ccULL, },
+ { 0x5533553355335533ULL, 0x5533553355335533ULL, },
+ { 0x55e35538558e55e3ULL, 0x5538558e55e35538ULL, },
+ { 0x551c55c75571551cULL, 0x55c75571551c55c7ULL, },
+ { 0xccffccffccffccffULL, 0xccffccffccffccffULL, }, /* 32 */
+ { 0xcc00cc00cc00cc00ULL, 0xcc00cc00cc00cc00ULL, },
+ { 0xccaaccaaccaaccaaULL, 0xccaaccaaccaaccaaULL, },
+ { 0xcc55cc55cc55cc55ULL, 0xcc55cc55cc55cc55ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcc33cc33cc33cc33ULL, 0xcc33cc33cc33cc33ULL, },
+ { 0xcce3cc38cc8ecce3ULL, 0xcc38cc8ecce3cc38ULL, },
+ { 0xcc1cccc7cc71cc1cULL, 0xccc7cc71cc1cccc7ULL, },
+ { 0x33ff33ff33ff33ffULL, 0x33ff33ff33ff33ffULL, }, /* 40 */
+ { 0x3300330033003300ULL, 0x3300330033003300ULL, },
+ { 0x33aa33aa33aa33aaULL, 0x33aa33aa33aa33aaULL, },
+ { 0x3355335533553355ULL, 0x3355335533553355ULL, },
+ { 0x33cc33cc33cc33ccULL, 0x33cc33cc33cc33ccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x33e33338338e33e3ULL, 0x3338338e33e33338ULL, },
+ { 0x331c33c73371331cULL, 0x33c73371331c33c7ULL, },
+ { 0xe3ff38ff8effe3ffULL, 0x38ff8effe3ff38ffULL, }, /* 48 */
+ { 0xe30038008e00e300ULL, 0x38008e00e3003800ULL, },
+ { 0xe3aa38aa8eaae3aaULL, 0x38aa8eaae3aa38aaULL, },
+ { 0xe35538558e55e355ULL, 0x38558e55e3553855ULL, },
+ { 0xe3cc38cc8ecce3ccULL, 0x38cc8ecce3cc38ccULL, },
+ { 0xe33338338e33e333ULL, 0x38338e33e3333833ULL, },
+ { 0xe3e338388e8ee3e3ULL, 0x38388e8ee3e33838ULL, },
+ { 0xe31c38c78e71e31cULL, 0x38c78e71e31c38c7ULL, },
+ { 0x1cffc7ff71ff1cffULL, 0xc7ff71ff1cffc7ffULL, }, /* 56 */
+ { 0x1c00c70071001c00ULL, 0xc70071001c00c700ULL, },
+ { 0x1caac7aa71aa1caaULL, 0xc7aa71aa1caac7aaULL, },
+ { 0x1c55c75571551c55ULL, 0xc75571551c55c755ULL, },
+ { 0x1cccc7cc71cc1cccULL, 0xc7cc71cc1cccc7ccULL, },
+ { 0x1c33c73371331c33ULL, 0xc73371331c33c733ULL, },
+ { 0x1ce3c738718e1ce3ULL, 0xc738718e1ce3c738ULL, },
+ { 0x1c1cc7c771711c1cULL, 0xc7c771711c1cc7c7ULL, },
+ { 0x8888e6e628285555ULL, 0x4b4b0b0bfefeb0b0ULL, }, /* 64 */
+ { 0x88fbe600284d55c7ULL, 0x4b120bbbfe15b052ULL, },
+ { 0x88ace6ae28b9558bULL, 0x4b270bc6feabb025ULL, },
+ { 0x8870e616285e55e2ULL, 0x4b8d0b88fea9b0e2ULL, },
+ { 0xfb8800e64d28c755ULL, 0x124bbb0b15fe52b0ULL, },
+ { 0xfbfb00004d4dc7c7ULL, 0x1212bbbb15155252ULL, },
+ { 0xfbac00ae4db9c78bULL, 0x1227bbc615ab5225ULL, },
+ { 0xfb7000164d5ec7e2ULL, 0x128dbb8815a952e2ULL, },
+ { 0xac88aee6b9288b55ULL, 0x274bc60babfe25b0ULL, }, /* 72 */
+ { 0xacfbae00b94d8bc7ULL, 0x2712c6bbab152552ULL, },
+ { 0xacacaeaeb9b98b8bULL, 0x2727c6c6abab2525ULL, },
+ { 0xac70ae16b95e8be2ULL, 0x278dc688aba925e2ULL, },
+ { 0x708816e65e28e255ULL, 0x8d4b880ba9fee2b0ULL, },
+ { 0x70fb16005e4de2c7ULL, 0x8d1288bba915e252ULL, },
+ { 0x70ac16ae5eb9e28bULL, 0x8d2788c6a9abe225ULL, },
+ { 0x707016165e5ee2e2ULL, 0x8d8d8888a9a9e2e2ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVOD_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVOD_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVOD.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "ILVOD.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0xffffffffffffffffULL, },
+ { 0x38e38e38e38e38e3ULL, 0xffffffffffffffffULL, },
+ { 0xc71c71c71c71c71cULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x0000000000000000ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x0000000000000000ULL, },
+ { 0xc71c71c71c71c71cULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x38e38e38e38e38e3ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xc71c71c71c71c71cULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x5555555555555555ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x5555555555555555ULL, },
+ { 0xc71c71c71c71c71cULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xccccccccccccccccULL, },
+ { 0x38e38e38e38e38e3ULL, 0xccccccccccccccccULL, },
+ { 0xc71c71c71c71c71cULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x3333333333333333ULL, },
+ { 0xc71c71c71c71c71cULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x5555555555555555ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xc71c71c71c71c71cULL, 0x38e38e38e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0x38e38e38e38e38e3ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc71c71c71c71c71cULL, 0xc71c71c71c71c71cULL, },
+ { 0x4b670b5efe7bb00cULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x12f7bb1a153f52fcULL, 0x4b670b5efe7bb00cULL, },
+ { 0x27d8c6ffab2b2514ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x8df188d8a942e2a0ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x4b670b5efe7bb00cULL, 0x12f7bb1a153f52fcULL, },
+ { 0x12f7bb1a153f52fcULL, 0x12f7bb1a153f52fcULL, },
+ { 0x27d8c6ffab2b2514ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x8df188d8a942e2a0ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x4b670b5efe7bb00cULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */
+ { 0x12f7bb1a153f52fcULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x27d8c6ffab2b2514ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x8df188d8a942e2a0ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x4b670b5efe7bb00cULL, 0x8df188d8a942e2a0ULL, },
+ { 0x12f7bb1a153f52fcULL, 0x8df188d8a942e2a0ULL, },
+ { 0x27d8c6ffab2b2514ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x8df188d8a942e2a0ULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVOD_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVOD_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVOD.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "ILVOD.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffff0000ffff0000ULL, 0xffff0000ffff0000ULL, },
+ { 0xffffaaaaffffaaaaULL, 0xffffaaaaffffaaaaULL, },
+ { 0xffff5555ffff5555ULL, 0xffff5555ffff5555ULL, },
+ { 0xffffccccffffccccULL, 0xffffccccffffccccULL, },
+ { 0xffff3333ffff3333ULL, 0xffff3333ffff3333ULL, },
+ { 0xffffe38effff8e38ULL, 0xffff38e3ffffe38eULL, },
+ { 0xffff1c71ffff71c7ULL, 0xffffc71cffff1c71ULL, },
+ { 0x0000ffff0000ffffULL, 0x0000ffff0000ffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000aaaa0000aaaaULL, 0x0000aaaa0000aaaaULL, },
+ { 0x0000555500005555ULL, 0x0000555500005555ULL, },
+ { 0x0000cccc0000ccccULL, 0x0000cccc0000ccccULL, },
+ { 0x0000333300003333ULL, 0x0000333300003333ULL, },
+ { 0x0000e38e00008e38ULL, 0x000038e30000e38eULL, },
+ { 0x00001c71000071c7ULL, 0x0000c71c00001c71ULL, },
+ { 0xaaaaffffaaaaffffULL, 0xaaaaffffaaaaffffULL, }, /* 16 */
+ { 0xaaaa0000aaaa0000ULL, 0xaaaa0000aaaa0000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaa5555aaaa5555ULL, 0xaaaa5555aaaa5555ULL, },
+ { 0xaaaaccccaaaaccccULL, 0xaaaaccccaaaaccccULL, },
+ { 0xaaaa3333aaaa3333ULL, 0xaaaa3333aaaa3333ULL, },
+ { 0xaaaae38eaaaa8e38ULL, 0xaaaa38e3aaaae38eULL, },
+ { 0xaaaa1c71aaaa71c7ULL, 0xaaaac71caaaa1c71ULL, },
+ { 0x5555ffff5555ffffULL, 0x5555ffff5555ffffULL, }, /* 24 */
+ { 0x5555000055550000ULL, 0x5555000055550000ULL, },
+ { 0x5555aaaa5555aaaaULL, 0x5555aaaa5555aaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555cccc5555ccccULL, 0x5555cccc5555ccccULL, },
+ { 0x5555333355553333ULL, 0x5555333355553333ULL, },
+ { 0x5555e38e55558e38ULL, 0x555538e35555e38eULL, },
+ { 0x55551c71555571c7ULL, 0x5555c71c55551c71ULL, },
+ { 0xccccffffccccffffULL, 0xccccffffccccffffULL, }, /* 32 */
+ { 0xcccc0000cccc0000ULL, 0xcccc0000cccc0000ULL, },
+ { 0xccccaaaaccccaaaaULL, 0xccccaaaaccccaaaaULL, },
+ { 0xcccc5555cccc5555ULL, 0xcccc5555cccc5555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccc3333cccc3333ULL, 0xcccc3333cccc3333ULL, },
+ { 0xcccce38ecccc8e38ULL, 0xcccc38e3cccce38eULL, },
+ { 0xcccc1c71cccc71c7ULL, 0xccccc71ccccc1c71ULL, },
+ { 0x3333ffff3333ffffULL, 0x3333ffff3333ffffULL, }, /* 40 */
+ { 0x3333000033330000ULL, 0x3333000033330000ULL, },
+ { 0x3333aaaa3333aaaaULL, 0x3333aaaa3333aaaaULL, },
+ { 0x3333555533335555ULL, 0x3333555533335555ULL, },
+ { 0x3333cccc3333ccccULL, 0x3333cccc3333ccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333e38e33338e38ULL, 0x333338e33333e38eULL, },
+ { 0x33331c71333371c7ULL, 0x3333c71c33331c71ULL, },
+ { 0xe38effff8e38ffffULL, 0x38e3ffffe38effffULL, }, /* 48 */
+ { 0xe38e00008e380000ULL, 0x38e30000e38e0000ULL, },
+ { 0xe38eaaaa8e38aaaaULL, 0x38e3aaaae38eaaaaULL, },
+ { 0xe38e55558e385555ULL, 0x38e35555e38e5555ULL, },
+ { 0xe38ecccc8e38ccccULL, 0x38e3cccce38eccccULL, },
+ { 0xe38e33338e383333ULL, 0x38e33333e38e3333ULL, },
+ { 0xe38ee38e8e388e38ULL, 0x38e338e3e38ee38eULL, },
+ { 0xe38e1c718e3871c7ULL, 0x38e3c71ce38e1c71ULL, },
+ { 0x1c71ffff71c7ffffULL, 0xc71cffff1c71ffffULL, }, /* 56 */
+ { 0x1c71000071c70000ULL, 0xc71c00001c710000ULL, },
+ { 0x1c71aaaa71c7aaaaULL, 0xc71caaaa1c71aaaaULL, },
+ { 0x1c71555571c75555ULL, 0xc71c55551c715555ULL, },
+ { 0x1c71cccc71c7ccccULL, 0xc71ccccc1c71ccccULL, },
+ { 0x1c71333371c73333ULL, 0xc71c33331c713333ULL, },
+ { 0x1c71e38e71c78e38ULL, 0xc71c38e31c71e38eULL, },
+ { 0x1c711c7171c771c7ULL, 0xc71cc71c1c711c71ULL, },
+ { 0x886a886a28622862ULL, 0x4b674b67fe7bfe7bULL, }, /* 64 */
+ { 0x886afbbe28624d93ULL, 0x4b6712f7fe7b153fULL, },
+ { 0x886aac5a2862b9cfULL, 0x4b6727d8fe7bab2bULL, },
+ { 0x886a704f28625e31ULL, 0x4b678df1fe7ba942ULL, },
+ { 0xfbbe886a4d932862ULL, 0x12f74b67153ffe7bULL, },
+ { 0xfbbefbbe4d934d93ULL, 0x12f712f7153f153fULL, },
+ { 0xfbbeac5a4d93b9cfULL, 0x12f727d8153fab2bULL, },
+ { 0xfbbe704f4d935e31ULL, 0x12f78df1153fa942ULL, },
+ { 0xac5a886ab9cf2862ULL, 0x27d84b67ab2bfe7bULL, }, /* 72 */
+ { 0xac5afbbeb9cf4d93ULL, 0x27d812f7ab2b153fULL, },
+ { 0xac5aac5ab9cfb9cfULL, 0x27d827d8ab2bab2bULL, },
+ { 0xac5a704fb9cf5e31ULL, 0x27d88df1ab2ba942ULL, },
+ { 0x704f886a5e312862ULL, 0x8df14b67a942fe7bULL, },
+ { 0x704ffbbe5e314d93ULL, 0x8df112f7a942153fULL, },
+ { 0x704fac5a5e31b9cfULL, 0x8df127d8a942ab2bULL, },
+ { 0x704f704f5e315e31ULL, 0x8df18df1a942a942ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVOD_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVOD_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVOD.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "ILVOD.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffff00000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffaaaaaaaaULL, 0xffffffffaaaaaaaaULL, },
+ { 0xffffffff55555555ULL, 0xffffffff55555555ULL, },
+ { 0xffffffffccccccccULL, 0xffffffffccccccccULL, },
+ { 0xffffffff33333333ULL, 0xffffffff33333333ULL, },
+ { 0xffffffffe38e38e3ULL, 0xffffffff38e38e38ULL, },
+ { 0xffffffff1c71c71cULL, 0xffffffffc71c71c7ULL, },
+ { 0x00000000ffffffffULL, 0x00000000ffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000aaaaaaaaULL, 0x00000000aaaaaaaaULL, },
+ { 0x0000000055555555ULL, 0x0000000055555555ULL, },
+ { 0x00000000ccccccccULL, 0x00000000ccccccccULL, },
+ { 0x0000000033333333ULL, 0x0000000033333333ULL, },
+ { 0x00000000e38e38e3ULL, 0x0000000038e38e38ULL, },
+ { 0x000000001c71c71cULL, 0x00000000c71c71c7ULL, },
+ { 0xaaaaaaaaffffffffULL, 0xaaaaaaaaffffffffULL, }, /* 16 */
+ { 0xaaaaaaaa00000000ULL, 0xaaaaaaaa00000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa55555555ULL, 0xaaaaaaaa55555555ULL, },
+ { 0xaaaaaaaaccccccccULL, 0xaaaaaaaaccccccccULL, },
+ { 0xaaaaaaaa33333333ULL, 0xaaaaaaaa33333333ULL, },
+ { 0xaaaaaaaae38e38e3ULL, 0xaaaaaaaa38e38e38ULL, },
+ { 0xaaaaaaaa1c71c71cULL, 0xaaaaaaaac71c71c7ULL, },
+ { 0x55555555ffffffffULL, 0x55555555ffffffffULL, }, /* 24 */
+ { 0x5555555500000000ULL, 0x5555555500000000ULL, },
+ { 0x55555555aaaaaaaaULL, 0x55555555aaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x55555555ccccccccULL, 0x55555555ccccccccULL, },
+ { 0x5555555533333333ULL, 0x5555555533333333ULL, },
+ { 0x55555555e38e38e3ULL, 0x5555555538e38e38ULL, },
+ { 0x555555551c71c71cULL, 0x55555555c71c71c7ULL, },
+ { 0xccccccccffffffffULL, 0xccccccccffffffffULL, }, /* 32 */
+ { 0xcccccccc00000000ULL, 0xcccccccc00000000ULL, },
+ { 0xccccccccaaaaaaaaULL, 0xccccccccaaaaaaaaULL, },
+ { 0xcccccccc55555555ULL, 0xcccccccc55555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccccccc33333333ULL, 0xcccccccc33333333ULL, },
+ { 0xcccccccce38e38e3ULL, 0xcccccccc38e38e38ULL, },
+ { 0xcccccccc1c71c71cULL, 0xccccccccc71c71c7ULL, },
+ { 0x33333333ffffffffULL, 0x33333333ffffffffULL, }, /* 40 */
+ { 0x3333333300000000ULL, 0x3333333300000000ULL, },
+ { 0x33333333aaaaaaaaULL, 0x33333333aaaaaaaaULL, },
+ { 0x3333333355555555ULL, 0x3333333355555555ULL, },
+ { 0x33333333ccccccccULL, 0x33333333ccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x33333333e38e38e3ULL, 0x3333333338e38e38ULL, },
+ { 0x333333331c71c71cULL, 0x33333333c71c71c7ULL, },
+ { 0xe38e38e3ffffffffULL, 0x38e38e38ffffffffULL, }, /* 48 */
+ { 0xe38e38e300000000ULL, 0x38e38e3800000000ULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0x38e38e38aaaaaaaaULL, },
+ { 0xe38e38e355555555ULL, 0x38e38e3855555555ULL, },
+ { 0xe38e38e3ccccccccULL, 0x38e38e38ccccccccULL, },
+ { 0xe38e38e333333333ULL, 0x38e38e3833333333ULL, },
+ { 0xe38e38e3e38e38e3ULL, 0x38e38e3838e38e38ULL, },
+ { 0xe38e38e31c71c71cULL, 0x38e38e38c71c71c7ULL, },
+ { 0x1c71c71cffffffffULL, 0xc71c71c7ffffffffULL, }, /* 56 */
+ { 0x1c71c71c00000000ULL, 0xc71c71c700000000ULL, },
+ { 0x1c71c71caaaaaaaaULL, 0xc71c71c7aaaaaaaaULL, },
+ { 0x1c71c71c55555555ULL, 0xc71c71c755555555ULL, },
+ { 0x1c71c71cccccccccULL, 0xc71c71c7ccccccccULL, },
+ { 0x1c71c71c33333333ULL, 0xc71c71c733333333ULL, },
+ { 0x1c71c71ce38e38e3ULL, 0xc71c71c738e38e38ULL, },
+ { 0x1c71c71c1c71c71cULL, 0xc71c71c7c71c71c7ULL, },
+ { 0x886ae6cc886ae6ccULL, 0x4b670b5e4b670b5eULL, }, /* 64 */
+ { 0x886ae6ccfbbe0063ULL, 0x4b670b5e12f7bb1aULL, },
+ { 0x886ae6ccac5aaeaaULL, 0x4b670b5e27d8c6ffULL, },
+ { 0x886ae6cc704f164dULL, 0x4b670b5e8df188d8ULL, },
+ { 0xfbbe0063886ae6ccULL, 0x12f7bb1a4b670b5eULL, },
+ { 0xfbbe0063fbbe0063ULL, 0x12f7bb1a12f7bb1aULL, },
+ { 0xfbbe0063ac5aaeaaULL, 0x12f7bb1a27d8c6ffULL, },
+ { 0xfbbe0063704f164dULL, 0x12f7bb1a8df188d8ULL, },
+ { 0xac5aaeaa886ae6ccULL, 0x27d8c6ff4b670b5eULL, }, /* 72 */
+ { 0xac5aaeaafbbe0063ULL, 0x27d8c6ff12f7bb1aULL, },
+ { 0xac5aaeaaac5aaeaaULL, 0x27d8c6ff27d8c6ffULL, },
+ { 0xac5aaeaa704f164dULL, 0x27d8c6ff8df188d8ULL, },
+ { 0x704f164d886ae6ccULL, 0x8df188d84b670b5eULL, },
+ { 0x704f164dfbbe0063ULL, 0x8df188d812f7bb1aULL, },
+ { 0x704f164dac5aaeaaULL, 0x8df188d827d8c6ffULL, },
+ { 0x704f164d704f164dULL, 0x8df188d88df188d8ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVOD_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVOD_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVR.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "ILVR.B";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xff00ff00ff00ff00ULL, 0xff00ff00ff00ff00ULL, },
+ { 0xffaaffaaffaaffaaULL, 0xffaaffaaffaaffaaULL, },
+ { 0xff55ff55ff55ff55ULL, 0xff55ff55ff55ff55ULL, },
+ { 0xffccffccffccffccULL, 0xffccffccffccffccULL, },
+ { 0xff33ff33ff33ff33ULL, 0xff33ff33ff33ff33ULL, },
+ { 0xff8eff38ffe3ff8eULL, 0xffe3ff8eff38ffe3ULL, },
+ { 0xff71ffc7ff1cff71ULL, 0xff1cff71ffc7ff1cULL, },
+ { 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00aa00aa00aa00aaULL, 0x00aa00aa00aa00aaULL, },
+ { 0x0055005500550055ULL, 0x0055005500550055ULL, },
+ { 0x00cc00cc00cc00ccULL, 0x00cc00cc00cc00ccULL, },
+ { 0x0033003300330033ULL, 0x0033003300330033ULL, },
+ { 0x008e003800e3008eULL, 0x00e3008e003800e3ULL, },
+ { 0x007100c7001c0071ULL, 0x001c007100c7001cULL, },
+ { 0xaaffaaffaaffaaffULL, 0xaaffaaffaaffaaffULL, }, /* 16 */
+ { 0xaa00aa00aa00aa00ULL, 0xaa00aa00aa00aa00ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaa55aa55aa55aa55ULL, 0xaa55aa55aa55aa55ULL, },
+ { 0xaaccaaccaaccaaccULL, 0xaaccaaccaaccaaccULL, },
+ { 0xaa33aa33aa33aa33ULL, 0xaa33aa33aa33aa33ULL, },
+ { 0xaa8eaa38aae3aa8eULL, 0xaae3aa8eaa38aae3ULL, },
+ { 0xaa71aac7aa1caa71ULL, 0xaa1caa71aac7aa1cULL, },
+ { 0x55ff55ff55ff55ffULL, 0x55ff55ff55ff55ffULL, }, /* 24 */
+ { 0x5500550055005500ULL, 0x5500550055005500ULL, },
+ { 0x55aa55aa55aa55aaULL, 0x55aa55aa55aa55aaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x55cc55cc55cc55ccULL, 0x55cc55cc55cc55ccULL, },
+ { 0x5533553355335533ULL, 0x5533553355335533ULL, },
+ { 0x558e553855e3558eULL, 0x55e3558e553855e3ULL, },
+ { 0x557155c7551c5571ULL, 0x551c557155c7551cULL, },
+ { 0xccffccffccffccffULL, 0xccffccffccffccffULL, }, /* 32 */
+ { 0xcc00cc00cc00cc00ULL, 0xcc00cc00cc00cc00ULL, },
+ { 0xccaaccaaccaaccaaULL, 0xccaaccaaccaaccaaULL, },
+ { 0xcc55cc55cc55cc55ULL, 0xcc55cc55cc55cc55ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcc33cc33cc33cc33ULL, 0xcc33cc33cc33cc33ULL, },
+ { 0xcc8ecc38cce3cc8eULL, 0xcce3cc8ecc38cce3ULL, },
+ { 0xcc71ccc7cc1ccc71ULL, 0xcc1ccc71ccc7cc1cULL, },
+ { 0x33ff33ff33ff33ffULL, 0x33ff33ff33ff33ffULL, }, /* 40 */
+ { 0x3300330033003300ULL, 0x3300330033003300ULL, },
+ { 0x33aa33aa33aa33aaULL, 0x33aa33aa33aa33aaULL, },
+ { 0x3355335533553355ULL, 0x3355335533553355ULL, },
+ { 0x33cc33cc33cc33ccULL, 0x33cc33cc33cc33ccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x338e333833e3338eULL, 0x33e3338e333833e3ULL, },
+ { 0x337133c7331c3371ULL, 0x331c337133c7331cULL, },
+ { 0x8eff38ffe3ff8effULL, 0xe3ff8eff38ffe3ffULL, }, /* 48 */
+ { 0x8e003800e3008e00ULL, 0xe3008e003800e300ULL, },
+ { 0x8eaa38aae3aa8eaaULL, 0xe3aa8eaa38aae3aaULL, },
+ { 0x8e553855e3558e55ULL, 0xe3558e553855e355ULL, },
+ { 0x8ecc38cce3cc8eccULL, 0xe3cc8ecc38cce3ccULL, },
+ { 0x8e333833e3338e33ULL, 0xe3338e333833e333ULL, },
+ { 0x8e8e3838e3e38e8eULL, 0xe3e38e8e3838e3e3ULL, },
+ { 0x8e7138c7e31c8e71ULL, 0xe31c8e7138c7e31cULL, },
+ { 0x71ffc7ff1cff71ffULL, 0x1cff71ffc7ff1cffULL, }, /* 56 */
+ { 0x7100c7001c007100ULL, 0x1c007100c7001c00ULL, },
+ { 0x71aac7aa1caa71aaULL, 0x1caa71aac7aa1caaULL, },
+ { 0x7155c7551c557155ULL, 0x1c557155c7551c55ULL, },
+ { 0x71ccc7cc1ccc71ccULL, 0x1ccc71ccc7cc1cccULL, },
+ { 0x7133c7331c337133ULL, 0x1c337133c7331c33ULL, },
+ { 0x718ec7381ce3718eULL, 0x1ce3718ec7381ce3ULL, },
+ { 0x7171c7c71c1c7171ULL, 0x1c1c7171c7c71c1cULL, },
+ { 0x2828626255554040ULL, 0x88886a6ae6e6ccccULL, }, /* 64 */
+ { 0x284d629355c74008ULL, 0x88fb6abee600cc63ULL, },
+ { 0x28b962cf558b4080ULL, 0x88ac6a5ae6aeccaaULL, },
+ { 0x285e623155e2404eULL, 0x88706a4fe616cc4dULL, },
+ { 0x4d289362c7550840ULL, 0xfb88be6a00e663ccULL, },
+ { 0x4d4d9393c7c70808ULL, 0xfbfbbebe00006363ULL, },
+ { 0x4db993cfc78b0880ULL, 0xfbacbe5a00ae63aaULL, },
+ { 0x4d5e9331c7e2084eULL, 0xfb70be4f0016634dULL, },
+ { 0xb928cf628b558040ULL, 0xac885a6aaee6aaccULL, }, /* 72 */
+ { 0xb94dcf938bc78008ULL, 0xacfb5abeae00aa63ULL, },
+ { 0xb9b9cfcf8b8b8080ULL, 0xacac5a5aaeaeaaaaULL, },
+ { 0xb95ecf318be2804eULL, 0xac705a4fae16aa4dULL, },
+ { 0x5e283162e2554e40ULL, 0x70884f6a16e64dccULL, },
+ { 0x5e4d3193e2c74e08ULL, 0x70fb4fbe16004d63ULL, },
+ { 0x5eb931cfe28b4e80ULL, 0x70ac4f5a16ae4daaULL, },
+ { 0x5e5e3131e2e24e4eULL, 0x70704f4f16164d4dULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVR_B(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVR_B(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVR.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "ILVR.D";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0xffffffffffffffffULL, },
+ { 0xe38e38e38e38e38eULL, 0xffffffffffffffffULL, },
+ { 0x1c71c71c71c71c71ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e38e38e38eULL, 0x5555555555555555ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, },
+ { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0xe38e38e38e38e38eULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0xe38e38e38e38e38eULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xe38e38e38e38e38eULL, },
+ { 0x5555555555555555ULL, 0xe38e38e38e38e38eULL, },
+ { 0xccccccccccccccccULL, 0xe38e38e38e38e38eULL, },
+ { 0x3333333333333333ULL, 0xe38e38e38e38e38eULL, },
+ { 0xe38e38e38e38e38eULL, 0xe38e38e38e38e38eULL, },
+ { 0x1c71c71c71c71c71ULL, 0xe38e38e38e38e38eULL, },
+ { 0xffffffffffffffffULL, 0x1c71c71c71c71c71ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x1c71c71c71c71c71ULL, },
+ { 0x5555555555555555ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xccccccccccccccccULL, 0x1c71c71c71c71c71ULL, },
+ { 0x3333333333333333ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xe38e38e38e38e38eULL, 0x1c71c71c71c71c71ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x1c71c71c71c71c71ULL, },
+ { 0x886ae6cc28625540ULL, 0x886ae6cc28625540ULL, }, /* 64 */
+ { 0xfbbe00634d93c708ULL, 0x886ae6cc28625540ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x886ae6cc28625540ULL, },
+ { 0x704f164d5e31e24eULL, 0x886ae6cc28625540ULL, },
+ { 0x886ae6cc28625540ULL, 0xfbbe00634d93c708ULL, },
+ { 0xfbbe00634d93c708ULL, 0xfbbe00634d93c708ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0xfbbe00634d93c708ULL, },
+ { 0x704f164d5e31e24eULL, 0xfbbe00634d93c708ULL, },
+ { 0x886ae6cc28625540ULL, 0xac5aaeaab9cf8b80ULL, }, /* 72 */
+ { 0xfbbe00634d93c708ULL, 0xac5aaeaab9cf8b80ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0xac5aaeaab9cf8b80ULL, },
+ { 0x704f164d5e31e24eULL, 0xac5aaeaab9cf8b80ULL, },
+ { 0x886ae6cc28625540ULL, 0x704f164d5e31e24eULL, },
+ { 0xfbbe00634d93c708ULL, 0x704f164d5e31e24eULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x704f164d5e31e24eULL, },
+ { 0x704f164d5e31e24eULL, 0x704f164d5e31e24eULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVR_D(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVR_D(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVR.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "ILVR.H";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffff0000ffff0000ULL, 0xffff0000ffff0000ULL, },
+ { 0xffffaaaaffffaaaaULL, 0xffffaaaaffffaaaaULL, },
+ { 0xffff5555ffff5555ULL, 0xffff5555ffff5555ULL, },
+ { 0xffffccccffffccccULL, 0xffffccccffffccccULL, },
+ { 0xffff3333ffff3333ULL, 0xffff3333ffff3333ULL, },
+ { 0xffff8e38ffffe38eULL, 0xffffe38effff38e3ULL, },
+ { 0xffff71c7ffff1c71ULL, 0xffff1c71ffffc71cULL, },
+ { 0x0000ffff0000ffffULL, 0x0000ffff0000ffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000aaaa0000aaaaULL, 0x0000aaaa0000aaaaULL, },
+ { 0x0000555500005555ULL, 0x0000555500005555ULL, },
+ { 0x0000cccc0000ccccULL, 0x0000cccc0000ccccULL, },
+ { 0x0000333300003333ULL, 0x0000333300003333ULL, },
+ { 0x00008e380000e38eULL, 0x0000e38e000038e3ULL, },
+ { 0x000071c700001c71ULL, 0x00001c710000c71cULL, },
+ { 0xaaaaffffaaaaffffULL, 0xaaaaffffaaaaffffULL, }, /* 16 */
+ { 0xaaaa0000aaaa0000ULL, 0xaaaa0000aaaa0000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaa5555aaaa5555ULL, 0xaaaa5555aaaa5555ULL, },
+ { 0xaaaaccccaaaaccccULL, 0xaaaaccccaaaaccccULL, },
+ { 0xaaaa3333aaaa3333ULL, 0xaaaa3333aaaa3333ULL, },
+ { 0xaaaa8e38aaaae38eULL, 0xaaaae38eaaaa38e3ULL, },
+ { 0xaaaa71c7aaaa1c71ULL, 0xaaaa1c71aaaac71cULL, },
+ { 0x5555ffff5555ffffULL, 0x5555ffff5555ffffULL, }, /* 24 */
+ { 0x5555000055550000ULL, 0x5555000055550000ULL, },
+ { 0x5555aaaa5555aaaaULL, 0x5555aaaa5555aaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555cccc5555ccccULL, 0x5555cccc5555ccccULL, },
+ { 0x5555333355553333ULL, 0x5555333355553333ULL, },
+ { 0x55558e385555e38eULL, 0x5555e38e555538e3ULL, },
+ { 0x555571c755551c71ULL, 0x55551c715555c71cULL, },
+ { 0xccccffffccccffffULL, 0xccccffffccccffffULL, }, /* 32 */
+ { 0xcccc0000cccc0000ULL, 0xcccc0000cccc0000ULL, },
+ { 0xccccaaaaccccaaaaULL, 0xccccaaaaccccaaaaULL, },
+ { 0xcccc5555cccc5555ULL, 0xcccc5555cccc5555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccc3333cccc3333ULL, 0xcccc3333cccc3333ULL, },
+ { 0xcccc8e38cccce38eULL, 0xcccce38ecccc38e3ULL, },
+ { 0xcccc71c7cccc1c71ULL, 0xcccc1c71ccccc71cULL, },
+ { 0x3333ffff3333ffffULL, 0x3333ffff3333ffffULL, }, /* 40 */
+ { 0x3333000033330000ULL, 0x3333000033330000ULL, },
+ { 0x3333aaaa3333aaaaULL, 0x3333aaaa3333aaaaULL, },
+ { 0x3333555533335555ULL, 0x3333555533335555ULL, },
+ { 0x3333cccc3333ccccULL, 0x3333cccc3333ccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x33338e383333e38eULL, 0x3333e38e333338e3ULL, },
+ { 0x333371c733331c71ULL, 0x33331c713333c71cULL, },
+ { 0x8e38ffffe38effffULL, 0xe38effff38e3ffffULL, }, /* 48 */
+ { 0x8e380000e38e0000ULL, 0xe38e000038e30000ULL, },
+ { 0x8e38aaaae38eaaaaULL, 0xe38eaaaa38e3aaaaULL, },
+ { 0x8e385555e38e5555ULL, 0xe38e555538e35555ULL, },
+ { 0x8e38cccce38eccccULL, 0xe38ecccc38e3ccccULL, },
+ { 0x8e383333e38e3333ULL, 0xe38e333338e33333ULL, },
+ { 0x8e388e38e38ee38eULL, 0xe38ee38e38e338e3ULL, },
+ { 0x8e3871c7e38e1c71ULL, 0xe38e1c7138e3c71cULL, },
+ { 0x71c7ffff1c71ffffULL, 0x1c71ffffc71cffffULL, }, /* 56 */
+ { 0x71c700001c710000ULL, 0x1c710000c71c0000ULL, },
+ { 0x71c7aaaa1c71aaaaULL, 0x1c71aaaac71caaaaULL, },
+ { 0x71c755551c715555ULL, 0x1c715555c71c5555ULL, },
+ { 0x71c7cccc1c71ccccULL, 0x1c71ccccc71cccccULL, },
+ { 0x71c733331c713333ULL, 0x1c713333c71c3333ULL, },
+ { 0x71c78e381c71e38eULL, 0x1c71e38ec71c38e3ULL, },
+ { 0x71c771c71c711c71ULL, 0x1c711c71c71cc71cULL, },
+ { 0x2862286255405540ULL, 0x886a886ae6cce6ccULL, }, /* 64 */
+ { 0x28624d935540c708ULL, 0x886afbbee6cc0063ULL, },
+ { 0x2862b9cf55408b80ULL, 0x886aac5ae6ccaeaaULL, },
+ { 0x28625e315540e24eULL, 0x886a704fe6cc164dULL, },
+ { 0x4d932862c7085540ULL, 0xfbbe886a0063e6ccULL, },
+ { 0x4d934d93c708c708ULL, 0xfbbefbbe00630063ULL, },
+ { 0x4d93b9cfc7088b80ULL, 0xfbbeac5a0063aeaaULL, },
+ { 0x4d935e31c708e24eULL, 0xfbbe704f0063164dULL, },
+ { 0xb9cf28628b805540ULL, 0xac5a886aaeaae6ccULL, }, /* 72 */
+ { 0xb9cf4d938b80c708ULL, 0xac5afbbeaeaa0063ULL, },
+ { 0xb9cfb9cf8b808b80ULL, 0xac5aac5aaeaaaeaaULL, },
+ { 0xb9cf5e318b80e24eULL, 0xac5a704faeaa164dULL, },
+ { 0x5e312862e24e5540ULL, 0x704f886a164de6ccULL, },
+ { 0x5e314d93e24ec708ULL, 0x704ffbbe164d0063ULL, },
+ { 0x5e31b9cfe24e8b80ULL, 0x704fac5a164daeaaULL, },
+ { 0x5e315e31e24ee24eULL, 0x704f704f164d164dULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVR_H(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVR_H(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction ILVR.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "ILVR.W";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffff00000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffaaaaaaaaULL, 0xffffffffaaaaaaaaULL, },
+ { 0xffffffff55555555ULL, 0xffffffff55555555ULL, },
+ { 0xffffffffccccccccULL, 0xffffffffccccccccULL, },
+ { 0xffffffff33333333ULL, 0xffffffff33333333ULL, },
+ { 0xffffffff8e38e38eULL, 0xffffffffe38e38e3ULL, },
+ { 0xffffffff71c71c71ULL, 0xffffffff1c71c71cULL, },
+ { 0x00000000ffffffffULL, 0x00000000ffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000aaaaaaaaULL, 0x00000000aaaaaaaaULL, },
+ { 0x0000000055555555ULL, 0x0000000055555555ULL, },
+ { 0x00000000ccccccccULL, 0x00000000ccccccccULL, },
+ { 0x0000000033333333ULL, 0x0000000033333333ULL, },
+ { 0x000000008e38e38eULL, 0x00000000e38e38e3ULL, },
+ { 0x0000000071c71c71ULL, 0x000000001c71c71cULL, },
+ { 0xaaaaaaaaffffffffULL, 0xaaaaaaaaffffffffULL, }, /* 16 */
+ { 0xaaaaaaaa00000000ULL, 0xaaaaaaaa00000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa55555555ULL, 0xaaaaaaaa55555555ULL, },
+ { 0xaaaaaaaaccccccccULL, 0xaaaaaaaaccccccccULL, },
+ { 0xaaaaaaaa33333333ULL, 0xaaaaaaaa33333333ULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaae38e38e3ULL, },
+ { 0xaaaaaaaa71c71c71ULL, 0xaaaaaaaa1c71c71cULL, },
+ { 0x55555555ffffffffULL, 0x55555555ffffffffULL, }, /* 24 */
+ { 0x5555555500000000ULL, 0x5555555500000000ULL, },
+ { 0x55555555aaaaaaaaULL, 0x55555555aaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x55555555ccccccccULL, 0x55555555ccccccccULL, },
+ { 0x5555555533333333ULL, 0x5555555533333333ULL, },
+ { 0x555555558e38e38eULL, 0x55555555e38e38e3ULL, },
+ { 0x5555555571c71c71ULL, 0x555555551c71c71cULL, },
+ { 0xccccccccffffffffULL, 0xccccccccffffffffULL, }, /* 32 */
+ { 0xcccccccc00000000ULL, 0xcccccccc00000000ULL, },
+ { 0xccccccccaaaaaaaaULL, 0xccccccccaaaaaaaaULL, },
+ { 0xcccccccc55555555ULL, 0xcccccccc55555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccccccc33333333ULL, 0xcccccccc33333333ULL, },
+ { 0xcccccccc8e38e38eULL, 0xcccccccce38e38e3ULL, },
+ { 0xcccccccc71c71c71ULL, 0xcccccccc1c71c71cULL, },
+ { 0x33333333ffffffffULL, 0x33333333ffffffffULL, }, /* 40 */
+ { 0x3333333300000000ULL, 0x3333333300000000ULL, },
+ { 0x33333333aaaaaaaaULL, 0x33333333aaaaaaaaULL, },
+ { 0x3333333355555555ULL, 0x3333333355555555ULL, },
+ { 0x33333333ccccccccULL, 0x33333333ccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x333333338e38e38eULL, 0x33333333e38e38e3ULL, },
+ { 0x3333333371c71c71ULL, 0x333333331c71c71cULL, },
+ { 0x8e38e38effffffffULL, 0xe38e38e3ffffffffULL, }, /* 48 */
+ { 0x8e38e38e00000000ULL, 0xe38e38e300000000ULL, },
+ { 0x8e38e38eaaaaaaaaULL, 0xe38e38e3aaaaaaaaULL, },
+ { 0x8e38e38e55555555ULL, 0xe38e38e355555555ULL, },
+ { 0x8e38e38eccccccccULL, 0xe38e38e3ccccccccULL, },
+ { 0x8e38e38e33333333ULL, 0xe38e38e333333333ULL, },
+ { 0x8e38e38e8e38e38eULL, 0xe38e38e3e38e38e3ULL, },
+ { 0x8e38e38e71c71c71ULL, 0xe38e38e31c71c71cULL, },
+ { 0x71c71c71ffffffffULL, 0x1c71c71cffffffffULL, }, /* 56 */
+ { 0x71c71c7100000000ULL, 0x1c71c71c00000000ULL, },
+ { 0x71c71c71aaaaaaaaULL, 0x1c71c71caaaaaaaaULL, },
+ { 0x71c71c7155555555ULL, 0x1c71c71c55555555ULL, },
+ { 0x71c71c71ccccccccULL, 0x1c71c71cccccccccULL, },
+ { 0x71c71c7133333333ULL, 0x1c71c71c33333333ULL, },
+ { 0x71c71c718e38e38eULL, 0x1c71c71ce38e38e3ULL, },
+ { 0x71c71c7171c71c71ULL, 0x1c71c71c1c71c71cULL, },
+ { 0x2862554028625540ULL, 0x886ae6cc886ae6ccULL, }, /* 64 */
+ { 0x286255404d93c708ULL, 0x886ae6ccfbbe0063ULL, },
+ { 0x28625540b9cf8b80ULL, 0x886ae6ccac5aaeaaULL, },
+ { 0x286255405e31e24eULL, 0x886ae6cc704f164dULL, },
+ { 0x4d93c70828625540ULL, 0xfbbe0063886ae6ccULL, },
+ { 0x4d93c7084d93c708ULL, 0xfbbe0063fbbe0063ULL, },
+ { 0x4d93c708b9cf8b80ULL, 0xfbbe0063ac5aaeaaULL, },
+ { 0x4d93c7085e31e24eULL, 0xfbbe0063704f164dULL, },
+ { 0xb9cf8b8028625540ULL, 0xac5aaeaa886ae6ccULL, }, /* 72 */
+ { 0xb9cf8b804d93c708ULL, 0xac5aaeaafbbe0063ULL, },
+ { 0xb9cf8b80b9cf8b80ULL, 0xac5aaeaaac5aaeaaULL, },
+ { 0xb9cf8b805e31e24eULL, 0xac5aaeaa704f164dULL, },
+ { 0x5e31e24e28625540ULL, 0x704f164d886ae6ccULL, },
+ { 0x5e31e24e4d93c708ULL, 0x704f164dfbbe0063ULL, },
+ { 0x5e31e24eb9cf8b80ULL, 0x704f164dac5aaeaaULL, },
+ { 0x5e31e24e5e31e24eULL, 0x704f164d704f164dULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVR_W(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ILVR_W(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction AND.V
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "AND.V";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+ { 0xa28a28a28a28a28aULL, 0x28a28a28a28a28a2ULL, },
+ { 0x0820820820820820ULL, 0x8208208208208208ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+ { 0x1111111111111111ULL, 0x1111111111111111ULL, },
+ { 0x4104104104104104ULL, 0x1041041041041041ULL, },
+ { 0x1451451451451451ULL, 0x4514514514514514ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xc08c08c08c08c08cULL, 0x08c08c08c08c08c0ULL, },
+ { 0x0c40c40c40c40c40ULL, 0xc40c40c40c40c40cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+ { 0x1111111111111111ULL, 0x1111111111111111ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x2302302302302302ULL, 0x3023023023023023ULL, },
+ { 0x1031031031031031ULL, 0x0310310310310310ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xa28a28a28a28a28aULL, 0x28a28a28a28a28a2ULL, },
+ { 0x4104104104104104ULL, 0x1041041041041041ULL, },
+ { 0xc08c08c08c08c08cULL, 0x08c08c08c08c08c0ULL, },
+ { 0x2302302302302302ULL, 0x3023023023023023ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0820820820820820ULL, 0x8208208208208208ULL, },
+ { 0x1451451451451451ULL, 0x4514514514514514ULL, },
+ { 0x0c40c40c40c40c40ULL, 0xc40c40c40c40c40cULL, },
+ { 0x1031031031031031ULL, 0x0310310310310310ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x882a004008024500ULL, 0x02670b1a143b100cULL, },
+ { 0x884aa68828420100ULL, 0x0340025eaa2b2004ULL, },
+ { 0x004a064c08204040ULL, 0x09610858a842a000ULL, },
+ { 0x882a004008024500ULL, 0x02670b1a143b100cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xa81a002209838300ULL, 0x02d0821a012b0014ULL, },
+ { 0x700e00414c11c208ULL, 0x00f18818010242a0ULL, },
+ { 0x884aa68828420100ULL, 0x0340025eaa2b2004ULL, }, /* 72 */
+ { 0xa81a002209838300ULL, 0x02d0821a012b0014ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x204a060818018200ULL, 0x05d080d8a9022000ULL, },
+ { 0x004a064c08204040ULL, 0x09610858a842a000ULL, },
+ { 0x700e00414c11c208ULL, 0x00f18818010242a0ULL, },
+ { 0x204a060818018200ULL, 0x05d080d8a9022000ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_AND_V(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_AND_V(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction NOR.V
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "NOR.V";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1111111111111111ULL, 0x1111111111111111ULL, },
+ { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+ { 0x1451451451451451ULL, 0x4514514514514514ULL, },
+ { 0x4104104104104104ULL, 0x1041041041041041ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x0820820820820820ULL, 0x8208208208208208ULL, },
+ { 0xa28a28a28a28a28aULL, 0x28a28a28a28a28a2ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1111111111111111ULL, 0x1111111111111111ULL, },
+ { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1031031031031031ULL, 0x0310310310310310ULL, },
+ { 0x2302302302302302ULL, 0x3023023023023023ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0c40c40c40c40c40ULL, 0xc40c40c40c40c40cULL, },
+ { 0xc08c08c08c08c08cULL, 0x08c08c08c08c08c0ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1451451451451451ULL, 0x4514514514514514ULL, },
+ { 0x0820820820820820ULL, 0x8208208208208208ULL, },
+ { 0x1031031031031031ULL, 0x0310310310310310ULL, },
+ { 0x0c40c40c40c40c40ULL, 0xc40c40c40c40c40cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x4104104104104104ULL, 0x1041041041041041ULL, },
+ { 0xa28a28a28a28a28aULL, 0x28a28a28a28a28a2ULL, },
+ { 0x2302302302302302ULL, 0x3023023023023023ULL, },
+ { 0xc08c08c08c08c08cULL, 0x08c08c08c08c08c0ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x77951933d79daabfULL, 0xb498f4a101844ff3ULL, }, /* 64 */
+ { 0x04011910920c28b7ULL, 0xa40844a100800d03ULL, },
+ { 0x538511114610203fULL, 0x9000300000844ae3ULL, },
+ { 0x07900932818c08b1ULL, 0x3008742100840d53ULL, },
+ { 0x04011910920c28b7ULL, 0xa40844a100800d03ULL, },
+ { 0x0441ff9cb26c38f7ULL, 0xed0844e5eac0ad03ULL, },
+ { 0x0001511402203077ULL, 0xc800000040c08803ULL, },
+ { 0x0400e990a04c18b1ULL, 0x6008442542800d03ULL, },
+ { 0x538511114610203fULL, 0x9000300000844ae3ULL, }, /* 72 */
+ { 0x0001511402203077ULL, 0xc800000040c08803ULL, },
+ { 0x53a551554630747fULL, 0xd827390054d4daebULL, },
+ { 0x03a0411000001431ULL, 0x500631005494184bULL, },
+ { 0x07900932818c08b1ULL, 0x3008742100840d53ULL, },
+ { 0x0400e990a04c18b1ULL, 0x6008442542800d03ULL, },
+ { 0x03a0411000001431ULL, 0x500631005494184bULL, },
+ { 0x8fb0e9b2a1ce1db1ULL, 0x720e772756bd1d5fULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_NOR_V(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_NOR_V(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction OR.V
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "OR.V";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xeeeeeeeeeeeeeeeeULL, 0xeeeeeeeeeeeeeeeeULL, },
+ { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+ { 0xebaebaebaebaebaeULL, 0xbaebaebaebaebaebULL, },
+ { 0xbefbefbefbefbefbULL, 0xefbefbefbefbefbeULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+ { 0xf7df7df7df7df7dfULL, 0x7df7df7df7df7df7ULL, },
+ { 0x5d75d75d75d75d75ULL, 0xd75d75d75d75d75dULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xeeeeeeeeeeeeeeeeULL, 0xeeeeeeeeeeeeeeeeULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xefcefcefcefcefceULL, 0xfcefcefcefcefcefULL, },
+ { 0xdcfdcfdcfdcfdcfdULL, 0xcfdcfdcfdcfdcfdcULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+ { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xf3bf3bf3bf3bf3bfULL, 0x3bf3bf3bf3bf3bf3ULL, },
+ { 0x3f73f73f73f73f73ULL, 0xf73f73f73f73f73fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xebaebaebaebaebaeULL, 0xbaebaebaebaebaebULL, },
+ { 0xf7df7df7df7df7dfULL, 0x7df7df7df7df7df7ULL, },
+ { 0xefcefcefcefcefceULL, 0xfcefcefcefcefcefULL, },
+ { 0xf3bf3bf3bf3bf3bfULL, 0x3bf3bf3bf3bf3bf3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xbefbefbefbefbefbULL, 0xefbefbefbefbefbeULL, },
+ { 0x5d75d75d75d75d75ULL, 0xd75d75d75d75d75dULL, },
+ { 0xdcfdcfdcfdcfdcfdULL, 0xcfdcfdcfdcfdcfdcULL, },
+ { 0x3f73f73f73f73f73ULL, 0xf73f73f73f73f73fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbfee6ef6df3d748ULL, 0x5bf7bb5eff7ff2fcULL, },
+ { 0xac7aeeeeb9efdfc0ULL, 0x6fffcfffff7bb51cULL, },
+ { 0xf86ff6cd7e73f74eULL, 0xcff78bdeff7bf2acULL, },
+ { 0xfbfee6ef6df3d748ULL, 0x5bf7bb5eff7ff2fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfffeaeebfddfcf88ULL, 0x37ffffffbf3f77fcULL, },
+ { 0xfbff166f5fb3e74eULL, 0x9ff7bbdabd7ff2fcULL, },
+ { 0xac7aeeeeb9efdfc0ULL, 0x6fffcfffff7bb51cULL, }, /* 72 */
+ { 0xfffeaeebfddfcf88ULL, 0x37ffffffbf3f77fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xfc5fbeefffffebceULL, 0xaff9ceffab6be7b4ULL, },
+ { 0xf86ff6cd7e73f74eULL, 0xcff78bdeff7bf2acULL, },
+ { 0xfbff166f5fb3e74eULL, 0x9ff7bbdabd7ff2fcULL, },
+ { 0xfc5fbeefffffebceULL, 0xaff9ceffab6be7b4ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_OR_V(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_OR_V(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Test program for MSA instruction XOR.V
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 Aleksandar Markovic <amarkovic@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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL ( \
+ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+ (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+ char *instruction_name = "XOR.V";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b128_result[TEST_COUNT_TOTAL][2];
+ uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+ { 0x4924924924924924ULL, 0x9249249249249249ULL, },
+ { 0xb6db6db6db6db6dbULL, 0x6db6db6db6db6db6ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0xb6db6db6db6db6dbULL, 0x6db6db6db6db6db6ULL, },
+ { 0x4924924924924924ULL, 0x9249249249249249ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x2f42f42f42f42f42ULL, 0xf42f42f42f42f42fULL, },
+ { 0xd0bd0bd0bd0bd0bdULL, 0x0bd0bd0bd0bd0bd0ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xd0bd0bd0bd0bd0bdULL, 0x0bd0bd0bd0bd0bd0ULL, },
+ { 0x2f42f42f42f42f42ULL, 0xf42f42f42f42f42fULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x4924924924924924ULL, 0x9249249249249249ULL, },
+ { 0xb6db6db6db6db6dbULL, 0x6db6db6db6db6db6ULL, },
+ { 0x2f42f42f42f42f42ULL, 0xf42f42f42f42f42fULL, },
+ { 0xd0bd0bd0bd0bd0bdULL, 0x0bd0bd0bd0bd0bd0ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xb6db6db6db6db6dbULL, 0x6db6db6db6db6db6ULL, },
+ { 0x4924924924924924ULL, 0x9249249249249249ULL, },
+ { 0xd0bd0bd0bd0bd0bdULL, 0x0bd0bd0bd0bd0bd0ULL, },
+ { 0x2f42f42f42f42f42ULL, 0xf42f42f42f42f42fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0x73d4e6af65f19248ULL, 0x5990b044eb44e2f0ULL, },
+ { 0x2430486691addec0ULL, 0x6cbfcda155509518ULL, },
+ { 0xf825f0817653b70eULL, 0xc6968386573952acULL, },
+ { 0x73d4e6af65f19248ULL, 0x5990b044eb44e2f0ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x57e4aec9f45c4c88ULL, 0x352f7de5be1477e8ULL, },
+ { 0x8bf1162e13a22546ULL, 0x9f0633c2bc7db05cULL, },
+ { 0x2430486691addec0ULL, 0x6cbfcda155509518ULL, }, /* 72 */
+ { 0x57e4aec9f45c4c88ULL, 0x352f7de5be1477e8ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xdc15b8e7e7fe69ceULL, 0xaa294e270269c7b4ULL, },
+ { 0xf825f0817653b70eULL, 0xc6968386573952acULL, },
+ { 0x8bf1162e13a22546ULL, 0x9f0633c2bc7db05cULL, },
+ { 0xdc15b8e7e7fe69ceULL, 0xaa294e270269c7b4ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_XOR_V(b128_pattern[i], b128_pattern[j],
+ b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+ do_msa_XOR_V(b128_random[i], b128_random[j],
+ b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+ (PATTERN_INPUTS_SHORT_COUNT)) +
+ RANDOM_INPUTS_SHORT_COUNT * i + j]);
+ }
+ }
+
+ gettimeofday(&end, NULL);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+ elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+ ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ &b128_result[0][0], &b128_expect[0][0]);
+
+ return ret;
+}
--- /dev/null
+/*
+ * QEMU list file authorization object tests
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+
+#include "authz/list.h"
+
+static void test_authz_default_deny(void)
+{
+ QAuthZList *auth = qauthz_list_new("auth0",
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort);
+
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_default_allow(void)
+{
+ QAuthZList *auth = qauthz_list_new("auth0",
+ QAUTHZ_LIST_POLICY_ALLOW,
+ &error_abort);
+
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_explicit_deny(void)
+{
+ QAuthZList *auth = qauthz_list_new("auth0",
+ QAUTHZ_LIST_POLICY_ALLOW,
+ &error_abort);
+
+ qauthz_list_append_rule(auth, "fred", QAUTHZ_LIST_POLICY_DENY,
+ QAUTHZ_LIST_FORMAT_EXACT, &error_abort);
+
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_explicit_allow(void)
+{
+ QAuthZList *auth = qauthz_list_new("auth0",
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort);
+
+ qauthz_list_append_rule(auth, "fred", QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_EXACT, &error_abort);
+
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+
+static void test_authz_complex(void)
+{
+ QAuthZList *auth = qauthz_list_new("auth0",
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort);
+
+ qauthz_list_append_rule(auth, "fred", QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_EXACT, &error_abort);
+ qauthz_list_append_rule(auth, "bob", QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_EXACT, &error_abort);
+ qauthz_list_append_rule(auth, "dan", QAUTHZ_LIST_POLICY_DENY,
+ QAUTHZ_LIST_FORMAT_EXACT, &error_abort);
+ qauthz_list_append_rule(auth, "dan*", QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_GLOB, &error_abort);
+
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "bob", &error_abort));
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "danb", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_add_remove(void)
+{
+ QAuthZList *auth = qauthz_list_new("auth0",
+ QAUTHZ_LIST_POLICY_ALLOW,
+ &error_abort);
+
+ g_assert_cmpint(qauthz_list_append_rule(auth, "fred",
+ QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_EXACT,
+ &error_abort),
+ ==, 0);
+ g_assert_cmpint(qauthz_list_append_rule(auth, "bob",
+ QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_EXACT,
+ &error_abort),
+ ==, 1);
+ g_assert_cmpint(qauthz_list_append_rule(auth, "dan",
+ QAUTHZ_LIST_POLICY_DENY,
+ QAUTHZ_LIST_FORMAT_EXACT,
+ &error_abort),
+ ==, 2);
+ g_assert_cmpint(qauthz_list_append_rule(auth, "frank",
+ QAUTHZ_LIST_POLICY_DENY,
+ QAUTHZ_LIST_FORMAT_EXACT,
+ &error_abort),
+ ==, 3);
+
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+
+ g_assert_cmpint(qauthz_list_delete_rule(auth, "dan"),
+ ==, 2);
+
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+
+ g_assert_cmpint(qauthz_list_insert_rule(auth, "dan",
+ QAUTHZ_LIST_POLICY_DENY,
+ QAUTHZ_LIST_FORMAT_EXACT,
+ 2,
+ &error_abort),
+ ==, 2);
+
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ module_call_init(MODULE_INIT_QOM);
+
+ g_test_add_func("/auth/list/default/deny", test_authz_default_deny);
+ g_test_add_func("/auth/list/default/allow", test_authz_default_allow);
+ g_test_add_func("/auth/list/explicit/deny", test_authz_explicit_deny);
+ g_test_add_func("/auth/list/explicit/allow", test_authz_explicit_allow);
+ g_test_add_func("/auth/list/complex", test_authz_complex);
+ g_test_add_func("/auth/list/add-remove", test_authz_add_remove);
+
+ return g_test_run();
+}
--- /dev/null
+/*
+ * QEMU list authorization object tests
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "authz/listfile.h"
+
+static char *workdir;
+
+static gchar *qemu_authz_listfile_test_save(const gchar *name,
+ const gchar *cfg)
+{
+ gchar *path = g_strdup_printf("%s/default-deny.cfg", workdir);
+ GError *gerr = NULL;
+
+ if (!g_file_set_contents(path, cfg, -1, &gerr)) {
+ g_printerr("Unable to save config %s: %s\n",
+ path, gerr->message);
+ g_error_free(gerr);
+ g_free(path);
+ rmdir(workdir);
+ abort();
+ }
+
+ return path;
+}
+
+static void test_authz_default_deny(void)
+{
+ gchar *file = qemu_authz_listfile_test_save(
+ "default-deny.cfg",
+ "{ \"policy\": \"deny\" }");
+ Error *local_err = NULL;
+
+ QAuthZListFile *auth = qauthz_list_file_new("auth0",
+ file, false,
+ &local_err);
+ unlink(file);
+ g_free(file);
+ g_assert(local_err == NULL);
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_default_allow(void)
+{
+ gchar *file = qemu_authz_listfile_test_save(
+ "default-allow.cfg",
+ "{ \"policy\": \"allow\" }");
+ Error *local_err = NULL;
+
+ QAuthZListFile *auth = qauthz_list_file_new("auth0",
+ file, false,
+ &local_err);
+ unlink(file);
+ g_free(file);
+ g_assert(local_err == NULL);
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_explicit_deny(void)
+{
+ gchar *file = qemu_authz_listfile_test_save(
+ "explicit-deny.cfg",
+ "{ \"rules\": [ "
+ " { \"match\": \"fred\","
+ " \"policy\": \"deny\","
+ " \"format\": \"exact\" } ],"
+ " \"policy\": \"allow\" }");
+ Error *local_err = NULL;
+
+ QAuthZListFile *auth = qauthz_list_file_new("auth0",
+ file, false,
+ &local_err);
+ unlink(file);
+ g_free(file);
+ g_assert(local_err == NULL);
+
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_explicit_allow(void)
+{
+ gchar *file = qemu_authz_listfile_test_save(
+ "explicit-allow.cfg",
+ "{ \"rules\": [ "
+ " { \"match\": \"fred\","
+ " \"policy\": \"allow\","
+ " \"format\": \"exact\" } ],"
+ " \"policy\": \"deny\" }");
+ Error *local_err = NULL;
+
+ QAuthZListFile *auth = qauthz_list_file_new("auth0",
+ file, false,
+ &local_err);
+ unlink(file);
+ g_free(file);
+ g_assert(local_err == NULL);
+
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+
+static void test_authz_complex(void)
+{
+ gchar *file = qemu_authz_listfile_test_save(
+ "complex.cfg",
+ "{ \"rules\": [ "
+ " { \"match\": \"fred\","
+ " \"policy\": \"allow\","
+ " \"format\": \"exact\" },"
+ " { \"match\": \"bob\","
+ " \"policy\": \"allow\","
+ " \"format\": \"exact\" },"
+ " { \"match\": \"dan\","
+ " \"policy\": \"deny\","
+ " \"format\": \"exact\" },"
+ " { \"match\": \"dan*\","
+ " \"policy\": \"allow\","
+ " \"format\": \"glob\" } ],"
+ " \"policy\": \"deny\" }");
+
+ Error *local_err = NULL;
+
+ QAuthZListFile *auth = qauthz_list_file_new("auth0",
+ file, false,
+ &local_err);
+ unlink(file);
+ g_free(file);
+ g_assert(local_err == NULL);
+
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "bob", &error_abort));
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "danb", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+
+int main(int argc, char **argv)
+{
+ int ret;
+ GError *gerr = NULL;
+
+ g_test_init(&argc, &argv, NULL);
+
+ module_call_init(MODULE_INIT_QOM);
+
+ workdir = g_dir_make_tmp("qemu-test-authz-listfile-XXXXXX",
+ &gerr);
+ if (!workdir) {
+ g_printerr("Unable to create temporary dir: %s\n",
+ gerr->message);
+ g_error_free(gerr);
+ abort();
+ }
+
+ g_test_add_func("/auth/list/default/deny", test_authz_default_deny);
+ g_test_add_func("/auth/list/default/allow", test_authz_default_allow);
+ g_test_add_func("/auth/list/explicit/deny", test_authz_explicit_deny);
+ g_test_add_func("/auth/list/explicit/allow", test_authz_explicit_allow);
+ g_test_add_func("/auth/list/complex", test_authz_complex);
+
+ ret = g_test_run();
+
+ rmdir(workdir);
+ g_free(workdir);
+
+ return ret;
+}
--- /dev/null
+/*
+ * QEMU PAM authorization object tests
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "authz/pamacct.h"
+
+#include <security/pam_appl.h>
+
+static bool failauth;
+
+/*
+ * These two functions are exported by libpam.so.
+ *
+ * By defining them again here, our impls are resolved
+ * by the linker instead of those in libpam.so
+ *
+ * The test suite is thus isolated from the host system
+ * PAM setup, so we can do predictable test scenarios
+ */
+int
+pam_start(const char *service_name, const char *user,
+ const struct pam_conv *pam_conversation,
+ pam_handle_t **pamh)
+{
+ failauth = true;
+ if (!g_str_equal(service_name, "qemu-vnc")) {
+ return PAM_AUTH_ERR;
+ }
+
+ if (g_str_equal(user, "fred")) {
+ failauth = false;
+ }
+
+ return PAM_SUCCESS;
+}
+
+
+int
+pam_acct_mgmt(pam_handle_t *pamh, int flags)
+{
+ if (failauth) {
+ return PAM_AUTH_ERR;
+ }
+
+ return PAM_SUCCESS;
+}
+
+
+static void test_authz_unknown_service(void)
+{
+ Error *local_err = NULL;
+ QAuthZPAM *auth = qauthz_pam_new("auth0",
+ "qemu-does-not-exist",
+ &error_abort);
+
+ g_assert_nonnull(auth);
+
+ g_assert_false(qauthz_is_allowed(QAUTHZ(auth), "fred", &local_err));
+
+ error_free_or_abort(&local_err);
+ object_unparent(OBJECT(auth));
+}
+
+
+static void test_authz_good_user(void)
+{
+ QAuthZPAM *auth = qauthz_pam_new("auth0",
+ "qemu-vnc",
+ &error_abort);
+
+ g_assert_nonnull(auth);
+
+ g_assert_true(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+
+static void test_authz_bad_user(void)
+{
+ Error *local_err = NULL;
+ QAuthZPAM *auth = qauthz_pam_new("auth0",
+ "qemu-vnc",
+ &error_abort);
+
+ g_assert_nonnull(auth);
+
+ g_assert_false(qauthz_is_allowed(QAUTHZ(auth), "bob", &local_err));
+
+ error_free_or_abort(&local_err);
+ object_unparent(OBJECT(auth));
+}
+
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ module_call_init(MODULE_INIT_QOM);
+
+ g_test_add_func("/auth/pam/unknown-service", test_authz_unknown_service);
+ g_test_add_func("/auth/pam/good-user", test_authz_good_user);
+ g_test_add_func("/auth/pam/bad-user", test_authz_bad_user);
+
+ return g_test_run();
+}
--- /dev/null
+/*
+ * QEMU simple authorization object testing
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+
+#include "authz/simple.h"
+
+
+static void test_authz_simple(void)
+{
+ QAuthZSimple *authz = qauthz_simple_new("authz0",
+ "cthulu",
+ &error_abort);
+
+ g_assert(!qauthz_is_allowed(QAUTHZ(authz), "cthul", &error_abort));
+ g_assert(qauthz_is_allowed(QAUTHZ(authz), "cthulu", &error_abort));
+ g_assert(!qauthz_is_allowed(QAUTHZ(authz), "cthuluu", &error_abort));
+ g_assert(!qauthz_is_allowed(QAUTHZ(authz), "fred", &error_abort));
+
+ object_unparent(OBJECT(authz));
+}
+
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ module_call_init(MODULE_INIT_QOM);
+
+ g_test_add_func("/authz/simple", test_authz_simple);
+
+ return g_test_run();
+}
BlockAIOCB *acb;
int aio_ret;
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = NULL,
- .iov_len = 0,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0);
blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
AioContext *ctx_a = iothread_get_aio_context(a);
AioContext *ctx_b = iothread_get_aio_context(b);
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = NULL,
- .iov_len = 0,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0);
/* bdrv_drain_all() may only be called from the main loop thread */
if (drain_type == BDRV_DRAIN_ALL && drain_thread != 0) {
BlockDriverState *bs = blk_bs(blk);
BDRVTestTopState *tts = bs->opaque;
void *buffer = g_malloc(65536);
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = buffer,
- .iov_len = 65536,
- };
-
- qemu_iovec_init_external(&qiov, &iov, 1);
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buffer, 65536);
/* Pretend some internal write operation from parent to child.
* Important: We have to read from the child, not from the parent!
BdrvChild *child_a, *child_b;
BlockAIOCB *acb;
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = NULL,
- .iov_len = 0,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0);
if (!by_parent_cb) {
detach_by_driver_cb_role = child_file;
blk_unref(blk);
}
+static void test_set_aio_context(void)
+{
+ BlockDriverState *bs;
+ IOThread *a = iothread_new();
+ IOThread *b = iothread_new();
+ AioContext *ctx_a = iothread_get_aio_context(a);
+ AioContext *ctx_b = iothread_get_aio_context(b);
+
+ bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
+ &error_abort);
+
+ bdrv_drained_begin(bs);
+ bdrv_set_aio_context(bs, ctx_a);
+
+ aio_context_acquire(ctx_a);
+ bdrv_drained_end(bs);
+
+ bdrv_drained_begin(bs);
+ bdrv_set_aio_context(bs, ctx_b);
+ aio_context_release(ctx_a);
+ aio_context_acquire(ctx_b);
+ bdrv_set_aio_context(bs, qemu_get_aio_context());
+ aio_context_release(ctx_b);
+ bdrv_drained_end(bs);
+
+ bdrv_unref(bs);
+ iothread_join(a);
+ iothread_join(b);
+}
+
int main(int argc, char **argv)
{
int ret;
g_test_add_func("/bdrv-drain/attach/drain", test_append_to_drained);
+ g_test_add_func("/bdrv-drain/set_aio_context", test_set_aio_context);
+
ret = g_test_run();
qemu_event_destroy(&done_event);
return ret;
--- /dev/null
+/*
+ * Block node graph modifications tests
+ *
+ * Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "block/block_int.h"
+#include "sysemu/block-backend.h"
+
+static BlockDriver bdrv_pass_through = {
+ .format_name = "pass-through",
+ .bdrv_child_perm = bdrv_filter_default_perms,
+};
+
+static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c,
+ const BdrvChildRole *role,
+ BlockReopenQueue *reopen_queue,
+ uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared)
+{
+ *nperm = 0;
+ *nshared = BLK_PERM_ALL;
+}
+
+static BlockDriver bdrv_no_perm = {
+ .format_name = "no-perm",
+ .bdrv_child_perm = no_perm_default_perms,
+};
+
+static BlockDriverState *no_perm_node(const char *name)
+{
+ return bdrv_new_open_driver(&bdrv_no_perm, name, BDRV_O_RDWR, &error_abort);
+}
+
+static BlockDriverState *pass_through_node(const char *name)
+{
+ return bdrv_new_open_driver(&bdrv_pass_through, name,
+ BDRV_O_RDWR, &error_abort);
+}
+
+/*
+ * test_update_perm_tree
+ *
+ * When checking node for a possibility to update permissions, it's subtree
+ * should be correctly checked too. New permissions for each node should be
+ * calculated and checked in context of permissions of other nodes. If we
+ * check new permissions of the node only in context of old permissions of
+ * its neighbors, we can finish up with wrong permission graph.
+ *
+ * This test firstly create the following graph:
+ * +--------+
+ * | root |
+ * +--------+
+ * |
+ * | perm: write, read
+ * | shared: except write
+ * v
+ * +-------------------+ +----------------+
+ * | passtrough filter |---------->| null-co node |
+ * +-------------------+ +----------------+
+ *
+ *
+ * and then, tries to append filter under node. Expected behavior: fail.
+ * Otherwise we'll get the following picture, with two BdrvChild'ren, having
+ * write permission to one node, without actually sharing it.
+ *
+ * +--------+
+ * | root |
+ * +--------+
+ * |
+ * | perm: write, read
+ * | shared: except write
+ * v
+ * +-------------------+
+ * | passtrough filter |
+ * +-------------------+
+ * | |
+ * perm: write, read | | perm: write, read
+ * shared: except write | | shared: except write
+ * v v
+ * +----------------+
+ * | null co node |
+ * +----------------+
+ */
+static void test_update_perm_tree(void)
+{
+ Error *local_err = NULL;
+
+ BlockBackend *root = blk_new(BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ,
+ BLK_PERM_ALL & ~BLK_PERM_WRITE);
+ BlockDriverState *bs = no_perm_node("node");
+ BlockDriverState *filter = pass_through_node("filter");
+
+ blk_insert_bs(root, bs, &error_abort);
+
+ bdrv_attach_child(filter, bs, "child", &child_file, &error_abort);
+
+ bdrv_append(filter, bs, &local_err);
+
+ g_assert_nonnull(local_err);
+
+ bdrv_unref(bs);
+ blk_unref(root);
+}
+
+/*
+ * test_should_update_child
+ *
+ * Test that bdrv_replace_node, and concretely should_update_child
+ * do the right thing, i.e. not creating loops on the graph.
+ *
+ * The test does the following:
+ * 1. initial graph:
+ *
+ * +------+ +--------+
+ * | root | | filter |
+ * +------+ +--------+
+ * | |
+ * root| target|
+ * v v
+ * +------+ +--------+
+ * | node |<---------| target |
+ * +------+ backing +--------+
+ *
+ * 2. Append @filter above @node. If should_update_child works correctly,
+ * it understands, that backing child of @target should not be updated,
+ * as it will create a loop on node graph. Resulting picture should
+ * be the left one, not the right:
+ *
+ * +------+ +------+
+ * | root | | root |
+ * +------+ +------+
+ * | |
+ * root| root|
+ * v v
+ * +--------+ target +--------+ target
+ * | filter |--------------+ | filter |--------------+
+ * +--------+ | +--------+ |
+ * | | | ^ v
+ * backing| | backing| | +--------+
+ * v v | +-----------| target |
+ * +------+ +--------+ v backing +--------+
+ * | node |<---------| target | +------+
+ * +------+ backing +--------+ | node |
+ * +------+
+ *
+ * (good picture) (bad picture)
+ *
+ */
+static void test_should_update_child(void)
+{
+ BlockBackend *root = blk_new(0, BLK_PERM_ALL);
+ BlockDriverState *bs = no_perm_node("node");
+ BlockDriverState *filter = no_perm_node("filter");
+ BlockDriverState *target = no_perm_node("target");
+
+ blk_insert_bs(root, bs, &error_abort);
+
+ bdrv_set_backing_hd(target, bs, &error_abort);
+
+ g_assert(target->backing->bs == bs);
+ bdrv_attach_child(filter, target, "target", &child_file, &error_abort);
+ bdrv_append(filter, bs, &error_abort);
+ g_assert(target->backing->bs == bs);
+
+ bdrv_unref(bs);
+ blk_unref(root);
+}
+
+int main(int argc, char *argv[])
+{
+ bdrv_init();
+ qemu_init_main_loop(&error_abort);
+
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/bdrv-graph-mod/update-perm-tree", test_update_perm_tree);
+ g_test_add_func("/bdrv-graph-mod/should-update-child",
+ test_should_update_child);
+
+ return g_test_run();
+}
#include "qapi/qapi-commands-char.h"
#include "qapi/qmp/qdict.h"
#include "qom/qom-qobject.h"
+#include "io/channel-socket.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qapi-visit-sockets.h"
static bool quit;
typedef struct FeHandler {
int read_count;
+ bool is_open;
+ int openclose_count;
+ bool openclose_mismatch;
int last_event;
char read_buf[128];
} FeHandler;
static void fe_event(void *opaque, int event)
{
FeHandler *h = opaque;
+ bool new_open_state;
h->last_event = event;
- if (event != CHR_EVENT_BREAK) {
+ switch (event) {
+ case CHR_EVENT_BREAK:
+ break;
+ case CHR_EVENT_OPENED:
+ case CHR_EVENT_CLOSED:
+ h->openclose_count++;
+ new_open_state = (event == CHR_EVENT_OPENED);
+ if (h->is_open == new_open_state) {
+ h->openclose_mismatch = true;
+ }
+ h->is_open = new_open_state;
+ /* no break */
+ default:
quit = true;
+ break;
}
}
1, &error_abort);
qemu_opt_set(opts, "backend", "console", &error_abort);
- chr = qemu_chr_new_from_opts(opts, NULL);
+ chr = qemu_chr_new_from_opts(opts, NULL, NULL);
g_assert_nonnull(chr);
qemu_chr_write_all(chr, (const uint8_t *)"CONSOLE", 7);
CharBackend be;
int ret;
- chr = qemu_chr_new("label", "stdio");
+ chr = qemu_chr_new("label", "stdio", NULL);
g_assert_nonnull(chr);
qemu_chr_fe_init(&be, chr, &error_abort);
qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
qemu_opt_set(opts, "size", "5", &error_abort);
- chr = qemu_chr_new_from_opts(opts, NULL);
+ chr = qemu_chr_new_from_opts(opts, NULL, NULL);
g_assert_null(chr);
qemu_opts_del(opts);
1, &error_abort);
qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
qemu_opt_set(opts, "size", "2", &error_abort);
- chr = qemu_chr_new_from_opts(opts, &error_abort);
+ chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
g_assert_nonnull(chr);
qemu_opts_del(opts);
1, &error_abort);
qemu_opt_set(opts, "backend", "memory", &error_abort);
qemu_opt_set(opts, "size", "2", &error_abort);
- chr = qemu_chr_new_from_opts(opts, NULL);
+ chr = qemu_chr_new_from_opts(opts, NULL, NULL);
g_assert_nonnull(chr);
object_unparent(OBJECT(chr));
qemu_opts_del(opts);
QemuOpts *opts;
Chardev *chr, *base;
char *data;
- FeHandler h1 = { 0, }, h2 = { 0, };
+ FeHandler h1 = { 0, false, 0, false, }, h2 = { 0, false, 0, false, };
CharBackend chr_be1, chr_be2;
opts = qemu_opts_create(qemu_find_opts("chardev"), "mux-label",
qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
qemu_opt_set(opts, "size", "128", &error_abort);
qemu_opt_set(opts, "mux", "on", &error_abort);
- chr = qemu_chr_new_from_opts(opts, &error_abort);
+ chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
g_assert_nonnull(chr);
qemu_opts_del(opts);
g_assert_cmpint(h1.last_event, ==, CHR_EVENT_BREAK);
g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT);
+ /* open/close state and corresponding events */
+ g_assert_true(qemu_chr_fe_backend_open(&chr_be1));
+ g_assert_true(qemu_chr_fe_backend_open(&chr_be2));
+ g_assert_true(h1.is_open);
+ g_assert_false(h1.openclose_mismatch);
+ g_assert_true(h2.is_open);
+ g_assert_false(h2.openclose_mismatch);
+
+ h1.openclose_count = h2.openclose_count = 0;
+
+ qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL,
+ NULL, NULL, false);
+ qemu_chr_fe_set_handlers(&chr_be2, NULL, NULL, NULL, NULL,
+ NULL, NULL, false);
+ g_assert_cmpint(h1.openclose_count, ==, 0);
+ g_assert_cmpint(h2.openclose_count, ==, 0);
+
+ h1.is_open = h2.is_open = false;
+ qemu_chr_fe_set_handlers(&chr_be1,
+ NULL,
+ NULL,
+ fe_event,
+ NULL,
+ &h1,
+ NULL, false);
+ qemu_chr_fe_set_handlers(&chr_be2,
+ NULL,
+ NULL,
+ fe_event,
+ NULL,
+ &h2,
+ NULL, false);
+ g_assert_cmpint(h1.openclose_count, ==, 1);
+ g_assert_false(h1.openclose_mismatch);
+ g_assert_cmpint(h2.openclose_count, ==, 1);
+ g_assert_false(h2.openclose_mismatch);
+
+ qemu_chr_be_event(base, CHR_EVENT_CLOSED);
+ qemu_chr_be_event(base, CHR_EVENT_OPENED);
+ g_assert_cmpint(h1.openclose_count, ==, 3);
+ g_assert_false(h1.openclose_mismatch);
+ g_assert_cmpint(h2.openclose_count, ==, 3);
+ g_assert_false(h2.openclose_mismatch);
+
+ qemu_chr_fe_set_handlers(&chr_be2,
+ fe_can_read,
+ fe_read,
+ fe_event,
+ NULL,
+ &h2,
+ NULL, false);
+ qemu_chr_fe_set_handlers(&chr_be1,
+ fe_can_read,
+ fe_read,
+ fe_event,
+ NULL,
+ &h1,
+ NULL, false);
+
/* remove first handler */
qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL,
NULL, NULL, true);
qemu_chr_fe_deinit(&chr_be2, true);
}
-typedef struct SocketIdleData {
- GMainLoop *loop;
- Chardev *chr;
- bool conn_expected;
- CharBackend *be;
- CharBackend *client_be;
-} SocketIdleData;
-
-static gboolean char_socket_test_idle(gpointer user_data)
-{
- SocketIdleData *data = user_data;
-
- if (object_property_get_bool(OBJECT(data->chr), "connected", NULL)
- == data->conn_expected) {
- quit = true;
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void socket_read(void *opaque, const uint8_t *buf, int size)
-{
- SocketIdleData *data = opaque;
-
- g_assert_cmpint(size, ==, 1);
- g_assert_cmpint(*buf, ==, 'Z');
-
- size = qemu_chr_fe_write(data->be, (const uint8_t *)"hello", 5);
- g_assert_cmpint(size, ==, 5);
-}
-
-static int socket_can_read(void *opaque)
-{
- return 10;
-}
-
-static void socket_read_hello(void *opaque, const uint8_t *buf, int size)
-{
- g_assert_cmpint(size, ==, 5);
- g_assert(strncmp((char *)buf, "hello", 5) == 0);
-
- quit = true;
-}
-
-static int socket_can_read_hello(void *opaque)
-{
- return 10;
-}
-
-static void char_socket_test_common(Chardev *chr, bool reconnect)
-{
- Chardev *chr_client;
- QObject *addr;
- QDict *qdict;
- const char *port;
- SocketIdleData d = { .chr = chr };
- CharBackend be;
- CharBackend client_be;
- char *tmp;
-
- d.be = &be;
- d.client_be = &be;
-
- g_assert_nonnull(chr);
- g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
-
- addr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort);
- qdict = qobject_to(QDict, addr);
- port = qdict_get_str(qdict, "port");
- tmp = g_strdup_printf("tcp:127.0.0.1:%s%s", port,
- reconnect ? ",reconnect=1" : "");
- qobject_unref(qdict);
-
- qemu_chr_fe_init(&be, chr, &error_abort);
- qemu_chr_fe_set_handlers(&be, socket_can_read, socket_read,
- NULL, NULL, &d, NULL, true);
-
- chr_client = qemu_chr_new("client", tmp);
- qemu_chr_fe_init(&client_be, chr_client, &error_abort);
- qemu_chr_fe_set_handlers(&client_be, socket_can_read_hello,
- socket_read_hello,
- NULL, NULL, &d, NULL, true);
- g_free(tmp);
-
- d.conn_expected = true;
- guint id = g_idle_add(char_socket_test_idle, &d);
- g_source_set_name_by_id(id, "test-idle");
- g_assert_cmpint(id, >, 0);
- main_loop();
-
- d.chr = chr_client;
- id = g_idle_add(char_socket_test_idle, &d);
- g_source_set_name_by_id(id, "test-idle");
- g_assert_cmpint(id, >, 0);
- main_loop();
-
- g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort));
- g_assert(object_property_get_bool(OBJECT(chr_client),
- "connected", &error_abort));
-
- qemu_chr_write_all(chr_client, (const uint8_t *)"Z", 1);
- main_loop();
-
- object_unparent(OBJECT(chr_client));
-
- d.chr = chr;
- d.conn_expected = false;
- g_idle_add(char_socket_test_idle, &d);
- main_loop();
-
- object_unparent(OBJECT(chr));
-}
-
-
-static void char_socket_basic_test(void)
-{
- Chardev *chr = qemu_chr_new("server", "tcp:127.0.0.1:0,server,nowait");
-
- char_socket_test_common(chr, false);
-}
-
-
-static void char_socket_reconnect_test(void)
-{
- Chardev *chr = qemu_chr_new("server", "tcp:127.0.0.1:0,server,nowait");
-
- char_socket_test_common(chr, true);
-}
-
-
-static void char_socket_fdpass_test(void)
-{
- Chardev *chr;
- char *optstr;
- QemuOpts *opts;
- int fd;
- SocketAddress *addr = g_new0(SocketAddress, 1);
-
- addr->type = SOCKET_ADDRESS_TYPE_INET;
- addr->u.inet.host = g_strdup("127.0.0.1");
- addr->u.inet.port = g_strdup("0");
-
- fd = socket_listen(addr, &error_abort);
- g_assert(fd >= 0);
-
- qapi_free_SocketAddress(addr);
-
- optstr = g_strdup_printf("socket,id=cdev,fd=%d,server,nowait", fd);
-
- opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"),
- optstr, true);
- g_free(optstr);
- g_assert_nonnull(opts);
-
- chr = qemu_chr_new_from_opts(opts, &error_abort);
-
- qemu_opts_del(opts);
-
- char_socket_test_common(chr, false);
-}
-
static void websock_server_read(void *opaque, const uint8_t *buf, int size)
{
CharBackend client_be;
Chardev *chr_client;
Chardev *chr = qemu_chr_new("server",
- "websocket:127.0.0.1:0,server,nowait");
+ "websocket:127.0.0.1:0,server,nowait", NULL);
const char handshake[] = "GET / HTTP/1.1\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
qemu_chr_fe_set_handlers(&be, websock_server_can_read, websock_server_read,
NULL, NULL, chr, NULL, true);
- chr_client = qemu_chr_new("client", tmp);
+ chr_client = qemu_chr_new("client", tmp, NULL);
qemu_chr_fe_init(&client_be, chr_client, &error_abort);
qemu_chr_fe_set_handlers(&client_be, websock_client_can_read,
websock_client_read,
}
tmp = g_strdup_printf("pipe:%s", pipe);
- chr = qemu_chr_new("pipe", tmp);
+ chr = qemu_chr_new("pipe", tmp, NULL);
g_assert_nonnull(chr);
g_free(tmp);
}
#endif
+typedef struct SocketIdleData {
+ GMainLoop *loop;
+ Chardev *chr;
+ bool conn_expected;
+ CharBackend *be;
+ CharBackend *client_be;
+} SocketIdleData;
+
+
+static void socket_read_hello(void *opaque, const uint8_t *buf, int size)
+{
+ g_assert_cmpint(size, ==, 5);
+ g_assert(strncmp((char *)buf, "hello", 5) == 0);
+
+ quit = true;
+}
+
+static int socket_can_read_hello(void *opaque)
+{
+ return 10;
+}
+
static int make_udp_socket(int *port)
{
struct sockaddr_in addr = { 0, };
int port;
sock = make_udp_socket(&port);
tmp = g_strdup_printf("udp:127.0.0.1:%d", port);
- chr = qemu_chr_new("client", tmp);
+ chr = qemu_chr_new("client", tmp, NULL);
g_assert_nonnull(chr);
be = g_alloca(sizeof(CharBackend));
char_udp_test_internal(NULL, 0);
}
+
+typedef struct {
+ int event;
+ bool got_pong;
+} CharSocketTestData;
+
+
+#define SOCKET_PING "Hello"
+#define SOCKET_PONG "World"
+
+
+static void
+char_socket_event(void *opaque, int event)
+{
+ CharSocketTestData *data = opaque;
+ data->event = event;
+}
+
+
+static void
+char_socket_read(void *opaque, const uint8_t *buf, int size)
+{
+ CharSocketTestData *data = opaque;
+ g_assert_cmpint(size, ==, sizeof(SOCKET_PONG));
+ g_assert(memcmp(buf, SOCKET_PONG, size) == 0);
+ data->got_pong = true;
+}
+
+
+static int
+char_socket_can_read(void *opaque)
+{
+ return sizeof(SOCKET_PONG);
+}
+
+
+static char *
+char_socket_addr_to_opt_str(SocketAddress *addr, bool fd_pass,
+ const char *reconnect, bool is_listen)
+{
+ if (fd_pass) {
+ QIOChannelSocket *ioc = qio_channel_socket_new();
+ int fd;
+ char *optstr;
+ g_assert(!reconnect);
+ if (is_listen) {
+ qio_channel_socket_listen_sync(ioc, addr, &error_abort);
+ } else {
+ qio_channel_socket_connect_sync(ioc, addr, &error_abort);
+ }
+ fd = ioc->fd;
+ ioc->fd = -1;
+ optstr = g_strdup_printf("socket,id=cdev0,fd=%d%s",
+ fd, is_listen ? ",server,nowait" : "");
+ object_unref(OBJECT(ioc));
+ return optstr;
+ } else {
+ switch (addr->type) {
+ case SOCKET_ADDRESS_TYPE_INET:
+ return g_strdup_printf("socket,id=cdev0,host=%s,port=%s%s%s",
+ addr->u.inet.host,
+ addr->u.inet.port,
+ reconnect ? reconnect : "",
+ is_listen ? ",server,nowait" : "");
+
+ case SOCKET_ADDRESS_TYPE_UNIX:
+ return g_strdup_printf("socket,id=cdev0,path=%s%s%s",
+ addr->u.q_unix.path,
+ reconnect ? reconnect : "",
+ is_listen ? ",server,nowait" : "");
+
+ default:
+ g_assert_not_reached();
+ }
+ }
+}
+
+
+static void
+char_socket_ping_pong(QIOChannel *ioc)
+{
+ char greeting[sizeof(SOCKET_PING)];
+ const char *response = SOCKET_PONG;
+
+ qio_channel_read_all(ioc, greeting, sizeof(greeting), &error_abort);
+
+ g_assert(memcmp(greeting, SOCKET_PING, sizeof(greeting)) == 0);
+
+ qio_channel_write_all(ioc, response, sizeof(SOCKET_PONG), &error_abort);
+
+ object_unref(OBJECT(ioc));
+}
+
+
+static gpointer
+char_socket_server_client_thread(gpointer data)
+{
+ SocketAddress *addr = data;
+ QIOChannelSocket *ioc = qio_channel_socket_new();
+
+ qio_channel_socket_connect_sync(ioc, addr, &error_abort);
+
+ char_socket_ping_pong(QIO_CHANNEL(ioc));
+
+ return NULL;
+}
+
+
+typedef struct {
+ SocketAddress *addr;
+ bool wait_connected;
+ bool fd_pass;
+} CharSocketServerTestConfig;
+
+
+static void char_socket_server_test(gconstpointer opaque)
+{
+ const CharSocketServerTestConfig *config = opaque;
+ Chardev *chr;
+ CharBackend be = {0};
+ CharSocketTestData data = {0};
+ QObject *qaddr;
+ SocketAddress *addr;
+ Visitor *v;
+ QemuThread thread;
+ int ret;
+ bool reconnected;
+ char *optstr;
+ QemuOpts *opts;
+
+ g_setenv("QTEST_SILENT_ERRORS", "1", 1);
+ /*
+ * We rely on config->addr containing "nowait", otherwise
+ * qemu_chr_new() will block until a client connects. We
+ * can't spawn our client thread though, because until
+ * qemu_chr_new() returns we don't know what TCP port was
+ * allocated by the OS
+ */
+ optstr = char_socket_addr_to_opt_str(config->addr,
+ config->fd_pass,
+ NULL,
+ true);
+ opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"),
+ optstr, true);
+ g_assert_nonnull(opts);
+ chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
+ qemu_opts_del(opts);
+ g_assert_nonnull(chr);
+ g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
+
+ qaddr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort);
+ g_assert_nonnull(qaddr);
+
+ v = qobject_input_visitor_new(qaddr);
+ visit_type_SocketAddress(v, "addr", &addr, &error_abort);
+ visit_free(v);
+ qobject_unref(qaddr);
+
+ qemu_chr_fe_init(&be, chr, &error_abort);
+
+ reconnect:
+ data.event = -1;
+ qemu_chr_fe_set_handlers(&be, NULL, NULL,
+ char_socket_event, NULL,
+ &data, NULL, true);
+ g_assert(data.event == -1);
+
+ /*
+ * Kick off a thread to act as the "remote" client
+ * which just plays ping-pong with us
+ */
+ qemu_thread_create(&thread, "client",
+ char_socket_server_client_thread,
+ addr, QEMU_THREAD_JOINABLE);
+ g_assert(data.event == -1);
+
+ if (config->wait_connected) {
+ /* Synchronously accept a connection */
+ qemu_chr_wait_connected(chr, &error_abort);
+ } else {
+ /*
+ * Asynchronously accept a connection when the evnt
+ * loop reports the listener socket as readable
+ */
+ while (data.event == -1) {
+ main_loop_wait(false);
+ }
+ }
+ g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort));
+ g_assert(data.event == CHR_EVENT_OPENED);
+ data.event = -1;
+
+ /* Send a greeting to the client */
+ ret = qemu_chr_fe_write_all(&be, (const uint8_t *)SOCKET_PING,
+ sizeof(SOCKET_PING));
+ g_assert_cmpint(ret, ==, sizeof(SOCKET_PING));
+ g_assert(data.event == -1);
+
+ /* Setup a callback to receive the reply to our greeting */
+ qemu_chr_fe_set_handlers(&be, char_socket_can_read,
+ char_socket_read,
+ char_socket_event, NULL,
+ &data, NULL, true);
+ g_assert(data.event == CHR_EVENT_OPENED);
+ data.event = -1;
+
+ /* Wait for the client to go away */
+ while (data.event == -1) {
+ main_loop_wait(false);
+ }
+ g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
+ g_assert(data.event == CHR_EVENT_CLOSED);
+ g_assert(data.got_pong);
+
+ qemu_thread_join(&thread);
+
+ if (!reconnected) {
+ reconnected = true;
+ goto reconnect;
+ }
+
+ qapi_free_SocketAddress(addr);
+ object_unparent(OBJECT(chr));
+ g_free(optstr);
+ g_unsetenv("QTEST_SILENT_ERRORS");
+}
+
+
+static gpointer
+char_socket_client_server_thread(gpointer data)
+{
+ QIOChannelSocket *ioc = data;
+ QIOChannelSocket *cioc;
+
+ cioc = qio_channel_socket_accept(ioc, &error_abort);
+ g_assert_nonnull(cioc);
+
+ char_socket_ping_pong(QIO_CHANNEL(cioc));
+
+ return NULL;
+}
+
+
+typedef struct {
+ SocketAddress *addr;
+ const char *reconnect;
+ bool wait_connected;
+ bool fd_pass;
+} CharSocketClientTestConfig;
+
+
+static void char_socket_client_test(gconstpointer opaque)
+{
+ const CharSocketClientTestConfig *config = opaque;
+ QIOChannelSocket *ioc;
+ char *optstr;
+ Chardev *chr;
+ CharBackend be = {0};
+ CharSocketTestData data = {0};
+ SocketAddress *addr;
+ QemuThread thread;
+ int ret;
+ bool reconnected = false;
+ QemuOpts *opts;
+
+ /*
+ * Setup a listener socket and determine get its address
+ * so we know the TCP port for the client later
+ */
+ ioc = qio_channel_socket_new();
+ g_assert_nonnull(ioc);
+ qio_channel_socket_listen_sync(ioc, config->addr, &error_abort);
+ addr = qio_channel_socket_get_local_address(ioc, &error_abort);
+ g_assert_nonnull(addr);
+
+ /*
+ * Kick off a thread to act as the "remote" client
+ * which just plays ping-pong with us
+ */
+ qemu_thread_create(&thread, "client",
+ char_socket_client_server_thread,
+ ioc, QEMU_THREAD_JOINABLE);
+
+ /*
+ * Populate the chardev address based on what the server
+ * is actually listening on
+ */
+ optstr = char_socket_addr_to_opt_str(addr,
+ config->fd_pass,
+ config->reconnect,
+ false);
+
+ opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"),
+ optstr, true);
+ g_assert_nonnull(opts);
+ chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
+ qemu_opts_del(opts);
+ g_assert_nonnull(chr);
+
+ if (config->reconnect) {
+ /*
+ * If reconnect is set, the connection will be
+ * established in a background thread and we won't
+ * see the "connected" status updated until we
+ * run the main event loop, or call qemu_chr_wait_connected
+ */
+ g_assert(!object_property_get_bool(OBJECT(chr), "connected",
+ &error_abort));
+ } else {
+ g_assert(object_property_get_bool(OBJECT(chr), "connected",
+ &error_abort));
+ }
+
+ qemu_chr_fe_init(&be, chr, &error_abort);
+
+ reconnect:
+ data.event = -1;
+ qemu_chr_fe_set_handlers(&be, NULL, NULL,
+ char_socket_event, NULL,
+ &data, NULL, true);
+ if (config->reconnect) {
+ g_assert(data.event == -1);
+ } else {
+ g_assert(data.event == CHR_EVENT_OPENED);
+ }
+
+ if (config->wait_connected) {
+ /*
+ * Synchronously wait for the connection to complete
+ * This should be a no-op if reconnect is not set.
+ */
+ qemu_chr_wait_connected(chr, &error_abort);
+ } else {
+ /*
+ * Asynchronously wait for the connection to be reported
+ * as complete when the background thread reports its
+ * status.
+ * The loop will short-circuit if reconnect was set
+ */
+ while (data.event == -1) {
+ main_loop_wait(false);
+ }
+ }
+ g_assert(data.event == CHR_EVENT_OPENED);
+ data.event = -1;
+ g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort));
+
+ /* Send a greeting to the server */
+ ret = qemu_chr_fe_write_all(&be, (const uint8_t *)SOCKET_PING,
+ sizeof(SOCKET_PING));
+ g_assert_cmpint(ret, ==, sizeof(SOCKET_PING));
+ g_assert(data.event == -1);
+
+ /* Setup a callback to receive the reply to our greeting */
+ qemu_chr_fe_set_handlers(&be, char_socket_can_read,
+ char_socket_read,
+ char_socket_event, NULL,
+ &data, NULL, true);
+ g_assert(data.event == CHR_EVENT_OPENED);
+ data.event = -1;
+
+ /* Wait for the server to go away */
+ while (data.event == -1) {
+ main_loop_wait(false);
+ }
+ g_assert(data.event == CHR_EVENT_CLOSED);
+ g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
+ g_assert(data.got_pong);
+ qemu_thread_join(&thread);
+
+ if (config->reconnect && !reconnected) {
+ reconnected = true;
+ qemu_thread_create(&thread, "client",
+ char_socket_client_server_thread,
+ ioc, QEMU_THREAD_JOINABLE);
+ goto reconnect;
+ }
+
+ object_unref(OBJECT(ioc));
+ object_unparent(OBJECT(chr));
+ qapi_free_SocketAddress(addr);
+ g_free(optstr);
+}
+
+
#ifdef HAVE_CHARDEV_SERIAL
static void char_serial_test(void)
{
qemu_opt_set(opts, "backend", "serial", &error_abort);
qemu_opt_set(opts, "path", "/dev/null", &error_abort);
- chr = qemu_chr_new_from_opts(opts, NULL);
+ chr = qemu_chr_new_from_opts(opts, NULL, NULL);
g_assert_nonnull(chr);
/* TODO: add more tests with a pty */
object_unparent(OBJECT(chr));
/* test tty alias */
qemu_opt_set(opts, "backend", "tty", &error_abort);
- chr = qemu_chr_new_from_opts(opts, NULL);
+ chr = qemu_chr_new_from_opts(opts, NULL, NULL);
g_assert_nonnull(chr);
object_unparent(OBJECT(chr));
g_assert_cmpint(ret, ==, 8);
chr = qemu_chardev_new("label-file", TYPE_CHARDEV_FILE, &backend,
- &error_abort);
+ NULL, &error_abort);
qemu_chr_fe_init(&be, chr, &error_abort);
qemu_chr_fe_set_handlers(&be,
out = g_build_filename(tmp_path, "out", NULL);
file.out = out;
chr = qemu_chardev_new(NULL, TYPE_CHARDEV_FILE, &backend,
- &error_abort);
+ NULL, &error_abort);
}
ret = qemu_chr_write_all(chr, (uint8_t *)"hello!", 6);
g_assert_cmpint(ret, ==, 6);
chr = qemu_chr_find("label-null");
g_assert_null(chr);
- chr = qemu_chr_new("label-null", "null");
+ chr = qemu_chr_new("label-null", "null", NULL);
chr = qemu_chr_find("label-null");
g_assert_nonnull(chr);
static void char_invalid_test(void)
{
Chardev *chr;
-
- chr = qemu_chr_new("label-invalid", "invalid");
+ g_setenv("QTEST_SILENT_ERRORS", "1", 1);
+ chr = qemu_chr_new("label-invalid", "invalid", NULL);
g_assert_null(chr);
+ g_unsetenv("QTEST_SILENT_ERRORS");
}
static int chardev_change(void *opaque)
chr_args = g_strdup_printf("udp:127.0.0.1:%d", port);
- chr = qemu_chr_new("chardev", chr_args);
+ chr = qemu_chr_new("chardev", chr_args, NULL);
qemu_chr_fe_init(&be, chr, &error_abort);
/* check that chardev operates correctly */
#ifndef _WIN32
g_test_add_func("/char/file-fifo", char_file_fifo_test);
#endif
- g_test_add_func("/char/socket/basic", char_socket_basic_test);
- g_test_add_func("/char/socket/reconnect", char_socket_reconnect_test);
- g_test_add_func("/char/socket/fdpass", char_socket_fdpass_test);
+
+ SocketAddress tcpaddr = {
+ .type = SOCKET_ADDRESS_TYPE_INET,
+ .u.inet.host = (char *)"127.0.0.1",
+ .u.inet.port = (char *)"0",
+ };
+#ifndef WIN32
+ SocketAddress unixaddr = {
+ .type = SOCKET_ADDRESS_TYPE_UNIX,
+ .u.q_unix.path = (char *)"test-char.sock",
+ };
+#endif
+
+#define SOCKET_SERVER_TEST(name, addr) \
+ CharSocketServerTestConfig server1 ## name = \
+ { addr, false, false }; \
+ CharSocketServerTestConfig server2 ## name = \
+ { addr, true, false }; \
+ CharSocketServerTestConfig server3 ## name = \
+ { addr, false, true }; \
+ CharSocketServerTestConfig server4 ## name = \
+ { addr, true, true }; \
+ g_test_add_data_func("/char/socket/server/mainloop/" # name, \
+ &server1 ##name, char_socket_server_test); \
+ g_test_add_data_func("/char/socket/server/wait-conn/" # name, \
+ &server2 ##name, char_socket_server_test); \
+ g_test_add_data_func("/char/socket/server/mainloop-fdpass/" # name, \
+ &server3 ##name, char_socket_server_test); \
+ g_test_add_data_func("/char/socket/server/wait-conn-fdpass/" # name, \
+ &server4 ##name, char_socket_server_test)
+
+#define SOCKET_CLIENT_TEST(name, addr) \
+ CharSocketClientTestConfig client1 ## name = \
+ { addr, NULL, false, false }; \
+ CharSocketClientTestConfig client2 ## name = \
+ { addr, NULL, true, false }; \
+ CharSocketClientTestConfig client3 ## name = \
+ { addr, ",reconnect=1", false }; \
+ CharSocketClientTestConfig client4 ## name = \
+ { addr, ",reconnect=1", true }; \
+ CharSocketClientTestConfig client5 ## name = \
+ { addr, NULL, false, true }; \
+ CharSocketClientTestConfig client6 ## name = \
+ { addr, NULL, true, true }; \
+ g_test_add_data_func("/char/socket/client/mainloop/" # name, \
+ &client1 ##name, char_socket_client_test); \
+ g_test_add_data_func("/char/socket/client/wait-conn/" # name, \
+ &client2 ##name, char_socket_client_test); \
+ g_test_add_data_func("/char/socket/client/mainloop-reconnect/" # name, \
+ &client3 ##name, char_socket_client_test); \
+ g_test_add_data_func("/char/socket/client/wait-conn-reconnect/" # name, \
+ &client4 ##name, char_socket_client_test); \
+ g_test_add_data_func("/char/socket/client/mainloop-fdpass/" # name, \
+ &client5 ##name, char_socket_client_test); \
+ g_test_add_data_func("/char/socket/client/wait-conn-fdpass/" # name, \
+ &client6 ##name, char_socket_client_test)
+
+ SOCKET_SERVER_TEST(tcp, &tcpaddr);
+ SOCKET_CLIENT_TEST(tcp, &tcpaddr);
+#ifndef WIN32
+ SOCKET_SERVER_TEST(unix, &unixaddr);
+ SOCKET_CLIENT_TEST(unix, &unixaddr);
+#endif
+
+
g_test_add_func("/char/udp", char_udp_test);
#ifdef HAVE_CHARDEV_SERIAL
g_test_add_func("/char/serial", char_serial_test);
#include "qom/object_interfaces.h"
#include "qapi/error.h"
#include "qemu/sockets.h"
-#include "qemu/acl.h"
+#include "authz/list.h"
#ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT
QCryptoTLSCreds *serverCreds;
QCryptoTLSSession *clientSess = NULL;
QCryptoTLSSession *serverSess = NULL;
- qemu_acl *acl;
+ QAuthZList *auth;
const char * const *wildcards;
int channel[2];
bool clientShake = false;
SERVER_CERT_DIR);
g_assert(serverCreds != NULL);
- acl = qemu_acl_init("tlssessionacl");
- qemu_acl_reset(acl);
+ auth = qauthz_list_new("tlssessionacl",
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort);
wildcards = data->wildcards;
while (wildcards && *wildcards) {
- qemu_acl_append(acl, 0, *wildcards);
+ qauthz_list_append_rule(auth, *wildcards,
+ QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_GLOB,
+ &error_abort);
wildcards++;
}
object_unparent(OBJECT(serverCreds));
object_unparent(OBJECT(clientCreds));
+ object_unparent(OBJECT(auth));
qcrypto_tls_session_free(serverSess);
qcrypto_tls_session_free(clientSess);
"-device %s,netdev=qtest-bn0,id=qtest-e0 "
"-chardev socket,id=redirector0,path=%s,server,nowait "
"-chardev socket,id=redirector1,path=%s,server,nowait "
- "-chardev socket,id=redirector2,path=%s,nowait "
+ "-chardev socket,id=redirector2,path=%s "
"-object filter-redirector,id=qtest-f0,netdev=qtest-bn0,"
"queue=tx,outdev=redirector0 "
"-object filter-redirector,id=qtest-f1,netdev=qtest-bn0,"
"-device %s,netdev=qtest-bn0,id=qtest-e0 "
"-chardev socket,id=redirector0,path=%s,server,nowait "
"-chardev socket,id=redirector1,path=%s,server,nowait "
- "-chardev socket,id=redirector2,path=%s,nowait "
+ "-chardev socket,id=redirector2,path=%s "
"-object filter-redirector,id=qtest-f0,netdev=qtest-bn0,"
"queue=rx,indev=redirector0 "
"-object filter-redirector,id=qtest-f1,netdev=qtest-bn0,"
#include "io-channel-helpers.h"
#include "crypto/init.h"
#include "crypto/tlscredsx509.h"
-#include "qemu/acl.h"
#include "qapi/error.h"
+#include "authz/list.h"
#include "qom/object_interfaces.h"
#ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT
QIOChannelTLS *serverChanTLS;
QIOChannelSocket *clientChanSock;
QIOChannelSocket *serverChanSock;
- qemu_acl *acl;
+ QAuthZList *auth;
const char * const *wildcards;
int channel[2];
struct QIOChannelTLSHandshakeData clientHandshake = { false, false };
SERVER_CERT_DIR);
g_assert(serverCreds != NULL);
- acl = qemu_acl_init("channeltlsacl");
- qemu_acl_reset(acl);
+ auth = qauthz_list_new("channeltlsacl",
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort);
wildcards = data->wildcards;
while (wildcards && *wildcards) {
- qemu_acl_append(acl, 0, *wildcards);
+ qauthz_list_append_rule(auth, *wildcards,
+ QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_GLOB,
+ &error_abort);
wildcards++;
}
object_unref(OBJECT(serverChanSock));
object_unref(OBJECT(clientChanSock));
+ object_unparent(OBJECT(auth));
+
close(channel[0]);
close(channel[1]);
}
#include "qapi/qmp/qstring.h"
#include "qapi/qmp-event.h"
#include "test-qapi-events.h"
+#include "test-qapi-emit-events.h"
typedef struct TestEventData {
QDict *expect;
const void *unused)
{
do_test_visitor_in_qmp_introspect(data, &test_qmp_schema_qlit);
- do_test_visitor_in_qmp_introspect(data, &qmp_schema_qlit);
}
int main(int argc, char **argv)
--- /dev/null
+/*
+ * Tests for util/filemonitor-*.c
+ *
+ * Copyright 2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "qapi/error.h"
+#include "qemu/filemonitor.h"
+
+#include <utime.h>
+
+enum {
+ QFILE_MONITOR_TEST_OP_CREATE,
+ QFILE_MONITOR_TEST_OP_APPEND,
+ QFILE_MONITOR_TEST_OP_TRUNC,
+ QFILE_MONITOR_TEST_OP_RENAME,
+ QFILE_MONITOR_TEST_OP_TOUCH,
+ QFILE_MONITOR_TEST_OP_UNLINK,
+};
+
+typedef struct {
+ int type;
+ const char *filesrc;
+ const char *filedst;
+} QFileMonitorTestOp;
+
+typedef struct {
+ const char *file;
+} QFileMonitorTestWatch;
+
+typedef struct {
+ gsize nwatches;
+ const QFileMonitorTestWatch *watches;
+
+ gsize nops;
+ const QFileMonitorTestOp *ops;
+} QFileMonitorTestPlan;
+
+typedef struct {
+ int id;
+ QFileMonitorEvent event;
+ char *filename;
+} QFileMonitorTestRecord;
+
+
+typedef struct {
+ QemuMutex lock;
+ GList *records;
+} QFileMonitorTestData;
+
+static QemuMutex evlock;
+static bool evstopping;
+static bool evrunning;
+
+/*
+ * Main function for a background thread that is
+ * running the event loop during the test
+ */
+static void *
+qemu_file_monitor_test_event_loop(void *opaque G_GNUC_UNUSED)
+{
+ qemu_mutex_lock(&evlock);
+
+ while (!evstopping) {
+ qemu_mutex_unlock(&evlock);
+ main_loop_wait(true);
+ qemu_mutex_lock(&evlock);
+ }
+
+ evrunning = false;
+ qemu_mutex_unlock(&evlock);
+ return NULL;
+}
+
+
+/*
+ * File monitor event handler which simply maintains
+ * an ordered list of all events that it receives
+ */
+static void
+qemu_file_monitor_test_handler(int id,
+ QFileMonitorEvent event,
+ const char *filename,
+ void *opaque)
+{
+ QFileMonitorTestData *data = opaque;
+ QFileMonitorTestRecord *rec = g_new0(QFileMonitorTestRecord, 1);
+
+ rec->id = id;
+ rec->event = event;
+ rec->filename = g_strdup(filename);
+
+ qemu_mutex_lock(&data->lock);
+ data->records = g_list_append(data->records, rec);
+ qemu_mutex_unlock(&data->lock);
+}
+
+
+static void
+qemu_file_monitor_test_record_free(QFileMonitorTestRecord *rec)
+{
+ g_free(rec->filename);
+ g_free(rec);
+}
+
+
+/*
+ * Get the next event record that has been received by
+ * the file monitor event handler. Since events are
+ * emitted in the background thread running the event
+ * loop, we can't assume there is a record available
+ * immediately. Thus we will sleep for upto 5 seconds
+ * to wait for the event to be queued for us.
+ */
+static QFileMonitorTestRecord *
+qemu_file_monitor_test_next_record(QFileMonitorTestData *data)
+{
+ GTimer *timer = g_timer_new();
+ QFileMonitorTestRecord *record = NULL;
+ GList *tmp;
+
+ qemu_mutex_lock(&data->lock);
+ while (!data->records && g_timer_elapsed(timer, NULL) < 5) {
+ qemu_mutex_unlock(&data->lock);
+ usleep(10 * 1000);
+ qemu_mutex_lock(&data->lock);
+ }
+ if (data->records) {
+ record = data->records->data;
+ tmp = data->records;
+ data->records = g_list_remove_link(data->records, tmp);
+ g_list_free(tmp);
+ }
+ qemu_mutex_unlock(&data->lock);
+
+ g_timer_destroy(timer);
+ return record;
+}
+
+
+/*
+ * Check whether the event record we retrieved matches
+ * data we were expecting to see for the event
+ */
+static bool
+qemu_file_monitor_test_expect(QFileMonitorTestData *data,
+ int id,
+ QFileMonitorEvent event,
+ const char *filename)
+{
+ QFileMonitorTestRecord *rec;
+ bool ret = false;
+
+ rec = qemu_file_monitor_test_next_record(data);
+
+ if (!rec) {
+ g_printerr("Missing event watch id %d event %d file %s\n",
+ id, event, filename);
+ return false;
+ }
+
+ if (id != rec->id) {
+ g_printerr("Expected watch id %d but got %d\n", id, rec->id);
+ goto cleanup;
+ }
+
+ if (event != rec->event) {
+ g_printerr("Expected event %d but got %d\n", event, rec->event);
+ goto cleanup;
+ }
+
+ if (!g_str_equal(filename, rec->filename)) {
+ g_printerr("Expected filename %s but got %s\n",
+ filename, rec->filename);
+ goto cleanup;
+ }
+
+ ret = true;
+
+ cleanup:
+ qemu_file_monitor_test_record_free(rec);
+ return ret;
+}
+
+
+static void
+test_file_monitor_events(const void *opaque)
+{
+ const QFileMonitorTestPlan *plan = opaque;
+ Error *local_err = NULL;
+ GError *gerr = NULL;
+ QFileMonitor *mon = qemu_file_monitor_new(&local_err);
+ QemuThread th;
+ GTimer *timer;
+ gchar *dir = NULL;
+ int err = -1;
+ gsize i, j;
+ char *pathsrc = NULL;
+ char *pathdst = NULL;
+ QFileMonitorTestData data;
+
+ qemu_mutex_init(&data.lock);
+ data.records = NULL;
+
+ /*
+ * The file monitor needs the main loop running in
+ * order to receive events from inotify. We must
+ * thus spawn a background thread to run an event
+ * loop impl, while this thread triggers the
+ * actual file operations we're testing
+ */
+ evrunning = 1;
+ evstopping = 0;
+ qemu_thread_create(&th, "event-loop",
+ qemu_file_monitor_test_event_loop, NULL,
+ QEMU_THREAD_JOINABLE);
+
+ if (local_err) {
+ g_printerr("File monitoring not available: %s",
+ error_get_pretty(local_err));
+ error_free(local_err);
+ return;
+ }
+
+ dir = g_dir_make_tmp("test-util-filemonitor-XXXXXX",
+ &gerr);
+ if (!dir) {
+ g_printerr("Unable to create tmp dir %s",
+ gerr->message);
+ g_error_free(gerr);
+ abort();
+ }
+
+ /*
+ * First register all the directory / file watches
+ * we're interested in seeing events against
+ */
+ for (i = 0; i < plan->nwatches; i++) {
+ int watchid;
+ watchid = qemu_file_monitor_add_watch(mon,
+ dir,
+ plan->watches[i].file,
+ qemu_file_monitor_test_handler,
+ &data,
+ &local_err);
+ if (watchid < 0) {
+ g_printerr("Unable to add watch %s",
+ error_get_pretty(local_err));
+ goto cleanup;
+ }
+ }
+
+
+ /*
+ * Now invoke all the file operations (create,
+ * delete, rename, chmod, etc). These operations
+ * will trigger the various file monitor events
+ */
+ for (i = 0; i < plan->nops; i++) {
+ const QFileMonitorTestOp *op = &(plan->ops[i]);
+ int fd;
+ struct utimbuf ubuf;
+
+ pathsrc = g_strdup_printf("%s/%s", dir, op->filesrc);
+ if (op->filedst) {
+ pathdst = g_strdup_printf("%s/%s", dir, op->filedst);
+ }
+
+ switch (op->type) {
+ case QFILE_MONITOR_TEST_OP_CREATE:
+ fd = open(pathsrc, O_WRONLY | O_CREAT, 0700);
+ if (fd < 0) {
+ g_printerr("Unable to create %s: %s",
+ pathsrc, strerror(errno));
+ goto cleanup;
+ }
+ close(fd);
+ break;
+
+ case QFILE_MONITOR_TEST_OP_APPEND:
+ fd = open(pathsrc, O_WRONLY | O_APPEND, 0700);
+ if (fd < 0) {
+ g_printerr("Unable to open %s: %s",
+ pathsrc, strerror(errno));
+ goto cleanup;
+ }
+
+ if (write(fd, "Hello World", 10) != 10) {
+ g_printerr("Unable to write %s: %s",
+ pathsrc, strerror(errno));
+ close(fd);
+ goto cleanup;
+ }
+ close(fd);
+ break;
+
+ case QFILE_MONITOR_TEST_OP_TRUNC:
+ if (truncate(pathsrc, 4) < 0) {
+ g_printerr("Unable to truncate %s: %s",
+ pathsrc, strerror(errno));
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_RENAME:
+ if (rename(pathsrc, pathdst) < 0) {
+ g_printerr("Unable to rename %s to %s: %s",
+ pathsrc, pathdst, strerror(errno));
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_UNLINK:
+ if (unlink(pathsrc) < 0) {
+ g_printerr("Unable to unlink %s: %s",
+ pathsrc, strerror(errno));
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_TOUCH:
+ ubuf.actime = 1024;
+ ubuf.modtime = 1025;
+ if (utime(pathsrc, &ubuf) < 0) {
+ g_printerr("Unable to touch %s: %s",
+ pathsrc, strerror(errno));
+ goto cleanup;
+ }
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+
+ g_free(pathsrc);
+ g_free(pathdst);
+ pathsrc = pathdst = NULL;
+ }
+
+
+ /*
+ * Finally validate that we have received all the events
+ * we expect to see for the combination of watches and
+ * file operations
+ */
+ for (i = 0; i < plan->nops; i++) {
+ const QFileMonitorTestOp *op = &(plan->ops[i]);
+
+ switch (op->type) {
+ case QFILE_MONITOR_TEST_OP_CREATE:
+ for (j = 0; j < plan->nwatches; j++) {
+ if (plan->watches[j].file &&
+ !g_str_equal(plan->watches[j].file, op->filesrc))
+ continue;
+
+ if (!qemu_file_monitor_test_expect(
+ &data, j, QFILE_MONITOR_EVENT_CREATED, op->filesrc))
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_APPEND:
+ case QFILE_MONITOR_TEST_OP_TRUNC:
+ for (j = 0; j < plan->nwatches; j++) {
+ if (plan->watches[j].file &&
+ !g_str_equal(plan->watches[j].file, op->filesrc))
+ continue;
+
+ if (!qemu_file_monitor_test_expect(
+ &data, j, QFILE_MONITOR_EVENT_MODIFIED, op->filesrc))
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_RENAME:
+ for (j = 0; j < plan->nwatches; j++) {
+ if (plan->watches[j].file &&
+ !g_str_equal(plan->watches[j].file, op->filesrc))
+ continue;
+
+ if (!qemu_file_monitor_test_expect(
+ &data, j, QFILE_MONITOR_EVENT_DELETED, op->filesrc))
+ goto cleanup;
+ }
+
+ for (j = 0; j < plan->nwatches; j++) {
+ if (plan->watches[j].file &&
+ !g_str_equal(plan->watches[j].file, op->filedst))
+ continue;
+
+ if (!qemu_file_monitor_test_expect(
+ &data, j, QFILE_MONITOR_EVENT_CREATED, op->filedst))
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_TOUCH:
+ for (j = 0; j < plan->nwatches; j++) {
+ if (plan->watches[j].file &&
+ !g_str_equal(plan->watches[j].file, op->filesrc))
+ continue;
+
+ if (!qemu_file_monitor_test_expect(
+ &data, j, QFILE_MONITOR_EVENT_ATTRIBUTES, op->filesrc))
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_UNLINK:
+ for (j = 0; j < plan->nwatches; j++) {
+ if (plan->watches[j].file &&
+ !g_str_equal(plan->watches[j].file, op->filesrc))
+ continue;
+
+ if (!qemu_file_monitor_test_expect(
+ &data, j, QFILE_MONITOR_EVENT_DELETED, op->filesrc))
+ goto cleanup;
+ }
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+ }
+
+ err = 0;
+
+ cleanup:
+ g_free(pathsrc);
+ g_free(pathdst);
+
+ qemu_mutex_lock(&evlock);
+ evstopping = 1;
+ timer = g_timer_new();
+ while (evrunning && g_timer_elapsed(timer, NULL) < 5) {
+ qemu_mutex_unlock(&evlock);
+ usleep(10 * 1000);
+ qemu_mutex_lock(&evlock);
+ }
+ qemu_mutex_unlock(&evlock);
+
+ if (g_timer_elapsed(timer, NULL) >= 5) {
+ g_printerr("Event loop failed to quit after 5 seconds\n");
+ }
+ g_timer_destroy(timer);
+
+ for (i = 0; i < plan->nops; i++) {
+ const QFileMonitorTestOp *op = &(plan->ops[i]);
+ pathsrc = g_strdup_printf("%s/%s", dir, op->filesrc);
+ unlink(pathsrc);
+ g_free(pathsrc);
+ if (op->filedst) {
+ pathdst = g_strdup_printf("%s/%s", dir, op->filedst);
+ unlink(pathdst);
+ g_free(pathdst);
+ }
+ }
+
+ qemu_file_monitor_free(mon);
+ g_list_foreach(data.records,
+ (GFunc)qemu_file_monitor_test_record_free, NULL);
+ g_list_free(data.records);
+ qemu_mutex_destroy(&data.lock);
+ if (dir) {
+ rmdir(dir);
+ }
+ g_free(dir);
+ g_assert(err == 0);
+}
+
+
+/*
+ * Set of structs which define which file name patterns
+ * we're trying to watch against. NULL, means all files
+ * in the directory
+ */
+static const QFileMonitorTestWatch watches_any[] = {
+ { NULL },
+};
+
+static const QFileMonitorTestWatch watches_one[] = {
+ { "one.txt" },
+};
+
+static const QFileMonitorTestWatch watches_two[] = {
+ { "two.txt" },
+};
+
+static const QFileMonitorTestWatch watches_many[] = {
+ { NULL },
+ { "one.txt" },
+ { "two.txt" },
+};
+
+
+/*
+ * Various sets of file operations we're going to
+ * trigger and validate events for
+ */
+static const QFileMonitorTestOp ops_create_one[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", }
+};
+
+static const QFileMonitorTestOp ops_delete_one[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_UNLINK,
+ .filesrc = "one.txt", }
+};
+
+static const QFileMonitorTestOp ops_create_many[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "two.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "three.txt", }
+};
+
+static const QFileMonitorTestOp ops_rename_one[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_RENAME,
+ .filesrc = "one.txt", .filedst = "two.txt" }
+};
+
+static const QFileMonitorTestOp ops_rename_many[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "two.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_RENAME,
+ .filesrc = "one.txt", .filedst = "two.txt" }
+};
+
+static const QFileMonitorTestOp ops_append_one[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_APPEND,
+ .filesrc = "one.txt", },
+};
+
+static const QFileMonitorTestOp ops_trunc_one[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_TRUNC,
+ .filesrc = "one.txt", },
+};
+
+static const QFileMonitorTestOp ops_touch_one[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_TOUCH,
+ .filesrc = "one.txt", },
+};
+
+
+/*
+ * No we define data sets for the combinatorial
+ * expansion of file watches and operation sets
+ */
+#define PLAN_DATA(o, w) \
+ static const QFileMonitorTestPlan plan_ ## o ## _ ## w = { \
+ .nops = G_N_ELEMENTS(ops_ ##o), \
+ .ops = ops_ ##o, \
+ .nwatches = G_N_ELEMENTS(watches_ ##w), \
+ .watches = watches_ ## w, \
+ }
+
+PLAN_DATA(create_one, any);
+PLAN_DATA(create_one, one);
+PLAN_DATA(create_one, two);
+PLAN_DATA(create_one, many);
+
+PLAN_DATA(delete_one, any);
+PLAN_DATA(delete_one, one);
+PLAN_DATA(delete_one, two);
+PLAN_DATA(delete_one, many);
+
+PLAN_DATA(create_many, any);
+PLAN_DATA(create_many, one);
+PLAN_DATA(create_many, two);
+PLAN_DATA(create_many, many);
+
+PLAN_DATA(rename_one, any);
+PLAN_DATA(rename_one, one);
+PLAN_DATA(rename_one, two);
+PLAN_DATA(rename_one, many);
+
+PLAN_DATA(rename_many, any);
+PLAN_DATA(rename_many, one);
+PLAN_DATA(rename_many, two);
+PLAN_DATA(rename_many, many);
+
+PLAN_DATA(append_one, any);
+PLAN_DATA(append_one, one);
+PLAN_DATA(append_one, two);
+PLAN_DATA(append_one, many);
+
+PLAN_DATA(trunc_one, any);
+PLAN_DATA(trunc_one, one);
+PLAN_DATA(trunc_one, two);
+PLAN_DATA(trunc_one, many);
+
+PLAN_DATA(touch_one, any);
+PLAN_DATA(touch_one, one);
+PLAN_DATA(touch_one, two);
+PLAN_DATA(touch_one, many);
+
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ qemu_init_main_loop(&error_abort);
+
+ qemu_mutex_init(&evlock);
+
+ /*
+ * Register test cases for the combinatorial
+ * expansion of file watches and operation sets
+ */
+ #define PLAN_REGISTER(o, w) \
+ g_test_add_data_func("/util/filemonitor/" # o "/" # w, \
+ &plan_ ## o ## _ ## w, test_file_monitor_events)
+
+ PLAN_REGISTER(create_one, any);
+ PLAN_REGISTER(create_one, one);
+ PLAN_REGISTER(create_one, two);
+ PLAN_REGISTER(create_one, many);
+
+ PLAN_REGISTER(delete_one, any);
+ PLAN_REGISTER(delete_one, one);
+ PLAN_REGISTER(delete_one, two);
+ PLAN_REGISTER(delete_one, many);
+
+ PLAN_REGISTER(create_many, any);
+ PLAN_REGISTER(create_many, one);
+ PLAN_REGISTER(create_many, two);
+ PLAN_REGISTER(create_many, many);
+
+ PLAN_REGISTER(rename_one, any);
+ PLAN_REGISTER(rename_one, one);
+ PLAN_REGISTER(rename_one, two);
+ PLAN_REGISTER(rename_one, many);
+
+ PLAN_REGISTER(rename_many, any);
+ PLAN_REGISTER(rename_many, one);
+ PLAN_REGISTER(rename_many, two);
+ PLAN_REGISTER(rename_many, many);
+
+ PLAN_REGISTER(append_one, any);
+ PLAN_REGISTER(append_one, one);
+ PLAN_REGISTER(append_one, two);
+ PLAN_REGISTER(append_one, many);
+
+ PLAN_REGISTER(trunc_one, any);
+ PLAN_REGISTER(trunc_one, one);
+ PLAN_REGISTER(trunc_one, two);
+ PLAN_REGISTER(trunc_one, many);
+
+ PLAN_REGISTER(touch_one, any);
+ PLAN_REGISTER(touch_one, one);
+ PLAN_REGISTER(touch_one, two);
+ PLAN_REGISTER(touch_one, many);
+
+ return g_test_run();
+}
#define VHOST_USER_F_PROTOCOL_FEATURES 30
#define VHOST_USER_PROTOCOL_F_MQ 0
#define VHOST_USER_PROTOCOL_F_LOG_SHMFD 1
+#define VHOST_USER_PROTOCOL_F_CROSS_ENDIAN 6
#define VHOST_LOG_PAGE 0x1000
}
}
-static void init_virtio_dev(TestServer *s, uint32_t features_mask)
+static void init_virtio_dev(QTestState *qts, TestServer *s, uint32_t features_mask)
{
uint32_t features;
int i;
- s->bus = qpci_init_pc(global_qtest, NULL);
+ s->bus = qpci_init_pc(qts, NULL);
g_assert_nonnull(s->bus);
s->dev = qvirtio_pci_device_find(s->bus, VIRTIO_ID_NET);
qvirtio_set_acknowledge(&s->dev->vdev);
qvirtio_set_driver(&s->dev->vdev);
- s->alloc = pc_alloc_init(global_qtest);
+ s->alloc = pc_alloc_init(qts);
for (i = 0; i < s->queues * 2; i++) {
s->vq[i] = qvirtqueue_setup(&s->dev->vdev, s->alloc, i);
qvirtio_pci_device_free(s->dev);
}
-static void wait_for_fds(TestServer *s)
+static bool wait_for_fds(TestServer *s)
{
gint64 end_time;
+ bool got_region;
+ int i;
g_mutex_lock(&s->data_mutex);
g_assert_cmpint(s->fds_num, ==, s->memory.nregions);
g_mutex_unlock(&s->data_mutex);
+
+ got_region = false;
+ for (i = 0; i < s->memory.nregions; ++i) {
+ VhostUserMemoryRegion *reg = &s->memory.regions[i];
+ if (reg->guest_phys_addr == 0) {
+ got_region = true;
+ break;
+ }
+ }
+ if (!got_region) {
+ g_test_skip("No memory at address 0x0");
+ }
+ return got_region;
}
-static void read_guest_mem_server(TestServer *s)
+static void read_guest_mem_server(QTestState *qts, TestServer *s)
{
- uint32_t *guest_mem;
+ uint8_t *guest_mem;
int i, j;
size_t size;
- wait_for_fds(s);
-
g_mutex_lock(&s->data_mutex);
/* iterate all regions */
g_assert(guest_mem != MAP_FAILED);
guest_mem += (s->memory.regions[i].mmap_offset / sizeof(*guest_mem));
- for (j = 0; j < 256; j++) {
- uint32_t a = readl(s->memory.regions[i].guest_phys_addr + j*4);
+ for (j = 0; j < 1024; j++) {
+ uint32_t a = qtest_readb(qts, s->memory.regions[i].guest_phys_addr + j);
uint32_t b = guest_mem[j];
g_assert_cmpint(a, ==, b);
msg.flags |= VHOST_USER_REPLY_MASK;
msg.size = sizeof(m.payload.u64);
msg.payload.u64 = 1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD;
+ msg.payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_CROSS_ENDIAN;
if (s->queues > 1) {
msg.payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_MQ;
}
assert(msg.payload.state.index < s->queues * 2);
s->rings &= ~(0x1ULL << msg.payload.state.index);
+ g_cond_broadcast(&s->data_cond);
break;
case VHOST_USER_SET_MEM_TABLE:
G_N_ELEMENTS(s->fds));
/* signal the test that it can continue */
- g_cond_signal(&s->data_cond);
+ g_cond_broadcast(&s->data_cond);
break;
case VHOST_USER_SET_VRING_KICK:
p = (uint8_t *) &msg;
qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE);
- g_cond_signal(&s->data_cond);
+ g_cond_broadcast(&s->data_cond);
break;
case VHOST_USER_SET_VRING_BASE:
assert(msg.payload.state.index < s->queues * 2);
s->rings |= 0x1ULL << msg.payload.state.index;
+ g_cond_broadcast(&s->data_cond);
break;
case VHOST_USER_GET_QUEUE_NUM:
Chardev *chr;
chr_path = g_strdup_printf("unix:%s%s", server->socket_path, opt);
- chr = qemu_chr_new(server->chr_name, chr_path);
+ chr = qemu_chr_new(server->chr_name, chr_path, NULL);
g_free(chr_path);
g_assert_nonnull(chr);
int i, j;
size_t size;
- wait_for_fds(s);
-
/* iterate all regions */
for (i = 0; i < s->fds_num; i++) {
s = qtest_start(qemu_cmd);
g_free(qemu_cmd);
- init_virtio_dev(server, 1u << VIRTIO_NET_F_MAC);
+ init_virtio_dev(global_qtest, server, 1u << VIRTIO_NET_F_MAC);
+
+ if (!wait_for_fds(server)) {
+ goto exit;
+ }
- read_guest_mem_server(server);
+ read_guest_mem_server(global_qtest, server);
+exit:
uninit_virtio_dev(server);
qtest_quit(s);
TestServer *s = test_server_new("src");
TestServer *dest = test_server_new("dest");
char *uri = g_strdup_printf("%s%s", "unix:", dest->mig_path);
- QTestState *global = global_qtest, *from, *to;
+ QTestState *from, *to;
GSource *source;
gchar *cmd, *tmp;
QDict *rsp;
from = qtest_start(cmd);
g_free(cmd);
- init_virtio_dev(s, 1u << VIRTIO_NET_F_MAC);
- init_virtio_dev(dest, 1u << VIRTIO_NET_F_MAC);
- wait_for_fds(s);
+ init_virtio_dev(from, s, 1u << VIRTIO_NET_F_MAC);
+ if (!wait_for_fds(s)) {
+ goto exit;
+ }
+
size = get_log_size(s);
g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8));
g_free(tmp);
to = qtest_init(cmd);
g_free(cmd);
+ init_virtio_dev(to, dest, 1u << VIRTIO_NET_F_MAC);
source = g_source_new(&test_migrate_source_funcs,
sizeof(TestMigrateSource));
qobject_unref(rsp);
qmp_eventwait("STOP");
+ qtest_qmp_eventwait(to, "RESUME");
- global_qtest = to;
- qmp_eventwait("RESUME");
+ g_assert(wait_for_fds(dest));
+ read_guest_mem_server(to, dest);
- read_guest_mem_server(dest);
-
- uninit_virtio_dev(s);
uninit_virtio_dev(dest);
+ qtest_quit(to);
g_source_destroy(source);
g_source_unref(source);
- qtest_quit(to);
+exit:
+ uninit_virtio_dev(s);
+
test_server_free(dest);
qtest_quit(from);
test_server_free(s);
g_free(uri);
-
- global_qtest = global;
}
static void wait_for_rings_started(TestServer *s, size_t count)
qtest_start(cmd);
g_free(cmd);
- init_virtio_dev(s, 1u << VIRTIO_NET_F_MAC);
- wait_for_fds(s);
+ init_virtio_dev(global_qtest, s, 1u << VIRTIO_NET_F_MAC);
+ if (!wait_for_fds(s)) {
+ goto exit;
+ }
+
wait_for_rings_started(s, 2);
/* reconnect */
s->fds_num = 0;
s->rings = 0;
g_idle_add(reconnect_cb, s);
- wait_for_fds(s);
+ g_assert(wait_for_fds(s));
wait_for_rings_started(s, 2);
+exit:
uninit_virtio_dev(s);
qtest_end();
qtest_start(cmd);
g_free(cmd);
- init_virtio_dev(s, 1u << VIRTIO_NET_F_MAC);
- wait_for_fds(s);
+ init_virtio_dev(global_qtest, s, 1u << VIRTIO_NET_F_MAC);
+ if (!wait_for_fds(s)) {
+ goto exit;
+ }
wait_for_rings_started(s, 2);
+exit:
uninit_virtio_dev(s);
qtest_end();
qtest_start(cmd);
g_free(cmd);
- init_virtio_dev(s, 1u << VIRTIO_NET_F_MAC);
- wait_for_fds(s);
+ init_virtio_dev(global_qtest, s, 1u << VIRTIO_NET_F_MAC);
+ if (!wait_for_fds(s)) {
+ goto exit;
+ }
wait_for_rings_started(s, 2);
+exit:
uninit_virtio_dev(s);
qtest_end();
qtest_start(cmd);
g_free(cmd);
- init_virtio_dev(s, features_mask);
+ init_virtio_dev(global_qtest, s, features_mask);
wait_for_rings_started(s, s->queues * 2);
uint8_t status;
} QVirtioBlkReq;
+#ifdef HOST_WORDS_BIGENDIAN
+const bool host_is_big_endian = true;
+#else
+const bool host_is_big_endian; /* false */
+#endif
+
static char *drive_create(void)
{
int fd, ret;
static inline void virtio_blk_fix_request(QVirtioDevice *d, QVirtioBlkReq *req)
{
-#ifdef HOST_WORDS_BIGENDIAN
- const bool host_is_big_endian = true;
-#else
- const bool host_is_big_endian = false;
-#endif
-
if (qvirtio_is_big_endian(d) != host_is_big_endian) {
req->type = bswap32(req->type);
req->ioprio = bswap32(req->ioprio);
}
}
+
+static inline void virtio_blk_fix_dwz_hdr(QVirtioDevice *d,
+ struct virtio_blk_discard_write_zeroes *dwz_hdr)
+{
+ if (qvirtio_is_big_endian(d) != host_is_big_endian) {
+ dwz_hdr->sector = bswap64(dwz_hdr->sector);
+ dwz_hdr->num_sectors = bswap32(dwz_hdr->num_sectors);
+ dwz_hdr->flags = bswap32(dwz_hdr->flags);
+ }
+}
+
static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioDevice *d,
QVirtioBlkReq *req, uint64_t data_size)
{
uint64_t addr;
uint8_t status = 0xFF;
- g_assert_cmpuint(data_size % 512, ==, 0);
+ switch (req->type) {
+ case VIRTIO_BLK_T_IN:
+ case VIRTIO_BLK_T_OUT:
+ g_assert_cmpuint(data_size % 512, ==, 0);
+ break;
+ case VIRTIO_BLK_T_DISCARD:
+ case VIRTIO_BLK_T_WRITE_ZEROES:
+ g_assert_cmpuint(data_size %
+ sizeof(struct virtio_blk_discard_write_zeroes), ==, 0);
+ break;
+ default:
+ g_assert_cmpuint(data_size, ==, 0);
+ }
+
addr = guest_alloc(alloc, sizeof(*req) + data_size);
virtio_blk_fix_request(d, req);
guest_free(alloc, req_addr);
+ if (features & (1u << VIRTIO_BLK_F_WRITE_ZEROES)) {
+ struct virtio_blk_discard_write_zeroes dwz_hdr;
+ void *expected;
+
+ /*
+ * WRITE_ZEROES request on the same sector of previous test where
+ * we wrote "TEST".
+ */
+ req.type = VIRTIO_BLK_T_WRITE_ZEROES;
+ req.data = (char *) &dwz_hdr;
+ dwz_hdr.sector = 0;
+ dwz_hdr.num_sectors = 1;
+ dwz_hdr.flags = 0;
+
+ virtio_blk_fix_dwz_hdr(dev, &dwz_hdr);
+
+ req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));
+
+ free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
+ qvirtqueue_add(vq, req_addr + 16, sizeof(dwz_hdr), false, true);
+ qvirtqueue_add(vq, req_addr + 16 + sizeof(dwz_hdr), 1, true, false);
+
+ qvirtqueue_kick(dev, vq, free_head);
+
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL,
+ QVIRTIO_BLK_TIMEOUT_US);
+ status = readb(req_addr + 16 + sizeof(dwz_hdr));
+ g_assert_cmpint(status, ==, 0);
+
+ guest_free(alloc, req_addr);
+
+ /* Read request to check if the sector contains all zeroes */
+ req.type = VIRTIO_BLK_T_IN;
+ req.ioprio = 1;
+ req.sector = 0;
+ req.data = g_malloc0(512);
+
+ req_addr = virtio_blk_request(alloc, dev, &req, 512);
+
+ g_free(req.data);
+
+ free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
+ qvirtqueue_add(vq, req_addr + 16, 512, true, true);
+ qvirtqueue_add(vq, req_addr + 528, 1, true, false);
+
+ qvirtqueue_kick(dev, vq, free_head);
+
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL,
+ QVIRTIO_BLK_TIMEOUT_US);
+ status = readb(req_addr + 528);
+ g_assert_cmpint(status, ==, 0);
+
+ data = g_malloc(512);
+ expected = g_malloc0(512);
+ memread(req_addr + 16, data, 512);
+ g_assert_cmpmem(data, 512, expected, 512);
+ g_free(expected);
+ g_free(data);
+
+ guest_free(alloc, req_addr);
+ }
+
+ if (features & (1u << VIRTIO_BLK_F_DISCARD)) {
+ struct virtio_blk_discard_write_zeroes dwz_hdr;
+
+ req.type = VIRTIO_BLK_T_DISCARD;
+ req.data = (char *) &dwz_hdr;
+ dwz_hdr.sector = 0;
+ dwz_hdr.num_sectors = 1;
+ dwz_hdr.flags = 0;
+
+ virtio_blk_fix_dwz_hdr(dev, &dwz_hdr);
+
+ req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));
+
+ free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
+ qvirtqueue_add(vq, req_addr + 16, sizeof(dwz_hdr), false, true);
+ qvirtqueue_add(vq, req_addr + 16 + sizeof(dwz_hdr), 1, true, false);
+
+ qvirtqueue_kick(dev, vq, free_head);
+
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL,
+ QVIRTIO_BLK_TIMEOUT_US);
+ status = readb(req_addr + 16 + sizeof(dwz_hdr));
+ g_assert_cmpint(status, ==, 0);
+
+ guest_free(alloc, req_addr);
+ }
+
if (features & (1u << VIRTIO_F_ANY_LAYOUT)) {
/* Write and read with 2 descriptor layout */
/* Write request */
.PHONY: vm-build-all vm-clean-all
IMAGES := ubuntu.i386 freebsd netbsd openbsd centos
-IMAGE_FILES := $(patsubst %, tests/vm/%.img, $(IMAGES))
+IMAGES_DIR := $(HOME)/.cache/qemu-vm/images
+IMAGE_FILES := $(patsubst %, $(IMAGES_DIR)/%.img, $(IMAGES))
.PRECIOUS: $(IMAGE_FILES)
@echo ""
@echo " vm-build-all - Build QEMU in all VMs"
@echo " vm-clean-all - Clean up VM images"
+ @echo
+ @echo "Special variables:"
+ @echo " BUILD_TARGET=foo - override the build target"
+ @echo " TARGET_LIST=a,b,c - Override target list in builds."
+ @echo ' EXTRA_CONFIGURE_OPTS="..."'
vm-build-all: $(addprefix vm-build-, $(IMAGES))
vm-clean-all:
rm -f $(IMAGE_FILES)
-tests/vm/%.img: $(SRC_PATH)/tests/vm/% \
- $(SRC_PATH)/tests/vm/basevm.py \
- $(SRC_PATH)/tests/vm/Makefile.include
+$(IMAGES_DIR)/%.img: $(SRC_PATH)/tests/vm/% \
+ $(SRC_PATH)/tests/vm/basevm.py \
+ $(SRC_PATH)/tests/vm/Makefile.include
+ @mkdir -p $(IMAGES_DIR)
$(call quiet-command, \
$< \
$(if $(V)$(DEBUG), --debug) \
# Build in VM $(IMAGE)
-vm-build-%: tests/vm/%.img
+vm-build-%: $(IMAGES_DIR)/%.img
$(call quiet-command, \
$(SRC_PATH)/tests/vm/$* \
$(if $(V)$(DEBUG), --debug) \
$(if $(J),--jobs $(J)) \
$(if $(V),--verbose) \
--image "$<" \
- --build-qemu $(SRC_PATH), \
+ $(if $(BUILD_TARGET),--build-target $(BUILD_TARGET)) \
+ --build-qemu $(SRC_PATH) -- \
+ $(if $(TARGET_LIST),--target-list=$(TARGET_LIST)) \
+ $(if $(EXTRA_CONFIGURE_OPTS),$(EXTRA_CONFIGURE_OPTS)), \
" VM-BUILD $*")
help="build image")
parser.add_option("--build-qemu",
help="build QEMU from source in guest")
+ parser.add_option("--build-target",
+ help="QEMU build target", default="check")
parser.add_option("--interactive", "-I", action="store_true",
help="Interactively run command")
parser.add_option("--snapshot", "-s", action="store_true",
cmd = [vm.BUILD_SCRIPT.format(
configure_opts = " ".join(argv),
jobs=args.jobs,
+ target=args.build_target,
verbose = "V=1" if args.verbose else "")]
else:
cmd = argv
def build_image(self, img):
cimg = self._download_with_cache("https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1802.qcow2.xz")
img_tmp = img + ".tmp"
+ sys.stderr.write("Extracting the image...\n")
subprocess.check_call(["cp", "-f", cimg, img_tmp + ".xz"])
- subprocess.check_call(["xz", "-df", img_tmp + ".xz"])
+ subprocess.check_call(["xz", "-dvf", img_tmp + ".xz"])
subprocess.check_call(["qemu-img", "resize", img_tmp, "50G"])
self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()])
self.wait_ssh()
cd $(mktemp -d /var/tmp/qemu-test.XXXXXX);
tar -xf /dev/vtbd1;
./configure {configure_opts};
- gmake --output-sync -j{jobs} {verbose};
- gmake --output-sync -j{jobs} check {verbose};
+ gmake --output-sync -j{jobs} {target} {verbose};
"""
def build_image(self, img):
sha256sum='adcb771549b37bc63826c501f05121a206ed3d9f55f49145908f7e1432d65891')
img_tmp_xz = img + ".tmp.xz"
img_tmp = img + ".tmp"
+ sys.stderr.write("Extracting the image...\n")
subprocess.check_call(["cp", "-f", cimg, img_tmp_xz])
- subprocess.check_call(["xz", "-df", img_tmp_xz])
+ subprocess.check_call(["xz", "-dvf", img_tmp_xz])
if os.path.exists(img):
os.remove(img)
os.rename(img_tmp, img)
cd $(mktemp -d /var/tmp/qemu-test.XXXXXX);
tar -xf /dev/rld1a;
./configure --python=python2.7 {configure_opts};
- gmake --output-sync -j{jobs} {verbose};
- gmake --output-sync -j{jobs} check {verbose};
+ gmake --output-sync -j{jobs} {target} {verbose};
"""
def build_image(self, img):
sha256sum='b633d565b0eac3d02015cd0c81440bd8a7a8df8512615ac1ee05d318be015732')
img_tmp_xz = img + ".tmp.xz"
img_tmp = img + ".tmp"
+ sys.stderr.write("Extracting the image...\n")
subprocess.check_call(["cp", "-f", cimg, img_tmp_xz])
- subprocess.check_call(["xz", "-df", img_tmp_xz])
+ subprocess.check_call(["xz", "-dvf", img_tmp_xz])
if os.path.exists(img):
os.remove(img)
os.rename(img_tmp, img)
sha256sum='8c6cedc483e602cfee5e04f0406c64eb99138495e8ca580bc0293bcf0640c1bf')
img_tmp_xz = img + ".tmp.xz"
img_tmp = img + ".tmp"
+ sys.stderr.write("Extracting the image...\n")
subprocess.check_call(["cp", "-f", cimg, img_tmp_xz])
- subprocess.check_call(["xz", "-df", img_tmp_xz])
+ subprocess.check_call(["xz", "-dvf", img_tmp_xz])
if os.path.exists(img):
os.remove(img)
os.rename(img_tmp, img)
sudo chmod a+r /dev/vdb;
tar -xf /dev/vdb;
./configure {configure_opts};
- make --output-sync -j{jobs};
- make --output-sync check -j{jobs} {verbose};
+ make --output-sync {target} -j{jobs} {verbose};
"""
def _gen_cloud_init_iso(self):
vnc-obj-y += vnc-jobs.o
common-obj-y += keymaps.o console.o cursor.o qemu-pixman.o
-common-obj-y += input.o input-keymap.o input-legacy.o
+common-obj-y += input.o input-keymap.o input-legacy.o kbd-state.o
common-obj-$(CONFIG_LINUX) += input-linux.o
common-obj-$(CONFIG_SPICE) += spice-core.o spice-input.o spice-display.o
common-obj-$(CONFIG_COCOA) += cocoa.o
curses.mo-cflags := $(CURSES_CFLAGS)
curses.mo-libs := $(CURSES_LIBS)
+common-obj-$(call land,$(CONFIG_SPICE),$(CONFIG_GIO)) += spice-app.mo
+spice-app.mo-objs := spice-app.o
+spice-app.mo-cflags := $(GIO_CFLAGS)
+spice-app.mo-libs := $(GIO_LIBS)
+
common-obj-$(CONFIG_OPENGL) += shader.o
common-obj-$(CONFIG_OPENGL) += console-gl.o
common-obj-$(CONFIG_OPENGL) += egl-helpers.o
#ifndef MAC_OS_X_VERSION_10_12
#define MAC_OS_X_VERSION_10_12 101200
#endif
+#ifndef MAC_OS_X_VERSION_10_13
+#define MAC_OS_X_VERSION_10_13 101300
+#endif
/* macOS 10.12 deprecated many constants, #define the new names for older SDKs */
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9
#define NSModalResponseOK NSFileHandlingPanelOKButton
#endif
+/* 10.14 deprecates NSOnState and NSOffState in favor of
+ * NSControlStateValueOn/Off, which were introduced in 10.13.
+ * Define for older versions
+ */
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_13
+#define NSControlStateValueOn NSOnState
+#define NSControlStateValueOff NSOffState
+#endif
//#define DEBUG
COCOA_DEBUG("QemuCocoaView: drawRect\n");
// get CoreGraphic context
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10
CGContextRef viewContextRef = [[NSGraphicsContext currentContext] graphicsPort];
+#else
+ CGContextRef viewContextRef = [[NSGraphicsContext currentContext] CGContext];
+#endif
+
CGContextSetInterpolationQuality (viewContextRef, kCGInterpolationNone);
CGContextSetShouldAntialias (viewContextRef, NO);
{
stretch_video = !stretch_video;
if (stretch_video == true) {
- [sender setState: NSOnState];
+ [sender setState: NSControlStateValueOn];
} else {
- [sender setState: NSOffState];
+ [sender setState: NSControlStateValueOff];
}
}
{
/* Unselect the currently selected item */
for (NSMenuItem *item in [menu itemArray]) {
- if (item.state == NSOnState) {
- [item setState: NSOffState];
+ if (item.state == NSControlStateValueOn) {
+ [item setState: NSControlStateValueOff];
break;
}
}
}
// check the menu item
- [sender setState: NSOnState];
+ [sender setState: NSControlStateValueOn];
// get the throttle percentage
throttle_pct = [sender tag];
initWithTitle: [NSString stringWithFormat: @"%d%%", percentage] action:@selector(adjustSpeed:) keyEquivalent:@""] autorelease];
if (percentage == 100) {
- [menuItem setState: NSOnState];
+ [menuItem setState: NSControlStateValueOn];
}
/* Calculate the throttle percentage */
}
keycode = keysym2scancode(kbd_layout, keysym & KEYSYM_MASK,
- false, false, false);
+ NULL, false);
if (keycode == 0)
continue;
egl_texture_blit(edpy->gls, &edpy->blit_fb, &edpy->guest_fb,
!edpy->y_0_top);
egl_texture_blend(edpy->gls, &edpy->blit_fb, &edpy->cursor_fb,
- !edpy->y_0_top, edpy->pos_x, edpy->pos_y);
+ !edpy->y_0_top, edpy->pos_x, edpy->pos_y,
+ 1.0, 1.0);
} else {
/* no cursor -> use simple framebuffer blit */
egl_fb_blit(&edpy->blit_fb, &edpy->guest_fb, edpy->y_0_top);
}
void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip,
- int x, int y)
+ int x, int y, double scale_x, double scale_y)
{
glBindFramebuffer(GL_FRAMEBUFFER_EXT, dst->framebuffer);
+ int w = scale_x * src->width;
+ int h = scale_y * src->height;
if (flip) {
- glViewport(x, y, src->width, src->height);
+ glViewport(x, y, w, h);
} else {
- glViewport(x, dst->height - src->height - y,
- src->width, src->height);
+ glViewport(x, dst->height - h - y, w, h);
}
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, src->texture);
vc->gfx.y0_top);
egl_texture_blend(vc->gfx.gls, &vc->gfx.win_fb, &vc->gfx.cursor_fb,
vc->gfx.y0_top,
- vc->gfx.cursor_x, vc->gfx.cursor_y);
+ vc->gfx.cursor_x, vc->gfx.cursor_y,
+ vc->gfx.scale_x, vc->gfx.scale_y);
} else {
egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top);
}
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * Portions from gtk-vnc:
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Portions from gtk-vnc (originally licensed under the LGPL v2+):
*
* GTK VNC Widget
*
* Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
* Copyright (C) 2009-2010 Daniel P. Berrange <dan@berrange.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.0 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define GETTEXT_PACKAGE "qemu"
#define HOTKEY_MODIFIERS (GDK_CONTROL_MASK | GDK_MOD1_MASK)
-static const int modifier_keycode[] = {
- Q_KEY_CODE_SHIFT,
- Q_KEY_CODE_SHIFT_R,
- Q_KEY_CODE_CTRL,
- Q_KEY_CODE_CTRL_R,
- Q_KEY_CODE_ALT,
- Q_KEY_CODE_ALT_R,
- Q_KEY_CODE_META_L,
- Q_KEY_CODE_META_R,
-};
-
static const guint16 *keycode_map;
static size_t keycode_maplen;
bool external_pause_update;
- bool modifier_pressed[ARRAY_SIZE(modifier_keycode)];
bool ignore_keys;
DisplayOptions *opts;
static void gtk_release_modifiers(GtkDisplayState *s)
{
VirtualConsole *vc = gd_vc_find_current(s);
- int i, qcode;
if (vc->type != GD_VC_GFX ||
!qemu_console_is_graphic(vc->gfx.dcl.con)) {
return;
}
- for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) {
- qcode = modifier_keycode[i];
- if (!s->modifier_pressed[i]) {
- continue;
- }
- qemu_input_event_send_key_qcode(vc->gfx.dcl.con, qcode, false);
- s->modifier_pressed[i] = false;
- }
+ qkbd_state_lift_all_keys(vc->gfx.kbd);
}
static void gd_widget_reparent(GtkWidget *from, GtkWidget *to,
&delta_x, &delta_y)) {
return TRUE;
}
- if (delta_y > 0) {
+ if (delta_y == 0) {
+ return TRUE;
+ } else if (delta_y > 0) {
btn = INPUT_BUTTON_WHEEL_DOWN;
} else {
btn = INPUT_BUTTON_WHEEL_UP;
VirtualConsole *vc = opaque;
GtkDisplayState *s = vc->s;
int qcode;
- int i;
if (s->ignore_keys) {
s->ignore_keys = (key->type == GDK_KEY_PRESS);
|| key->hardware_keycode == VK_PAUSE
#endif
) {
- qemu_input_event_send_key_qcode(vc->gfx.dcl.con, Q_KEY_CODE_PAUSE,
- key->type == GDK_KEY_PRESS);
+ qkbd_state_key_event(vc->gfx.kbd, Q_KEY_CODE_PAUSE,
+ key->type == GDK_KEY_PRESS);
return TRUE;
}
trace_gd_key_event(vc->label, key->hardware_keycode, qcode,
(key->type == GDK_KEY_PRESS) ? "down" : "up");
- for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) {
- if (qcode == modifier_keycode[i]) {
- s->modifier_pressed[i] = (key->type == GDK_KEY_PRESS);
- }
- }
-
- qemu_input_event_send_key_qcode(vc->gfx.dcl.con, qcode,
- key->type == GDK_KEY_PRESS);
+ qkbd_state_key_event(vc->gfx.kbd, qcode,
+ key->type == GDK_KEY_PRESS);
return TRUE;
}
GDK_ENTER_NOTIFY_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_SCROLL_MASK |
+ GDK_SMOOTH_SCROLL_MASK |
GDK_KEY_PRESS_MASK);
gtk_widget_set_can_focus(vc->gfx.drawing_area, TRUE);
gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook),
vc->tab_item, gtk_label_new(vc->label));
+ vc->gfx.kbd = qkbd_state_init(con);
vc->gfx.dcl.con = con;
register_displaychangelistener(&vc->gfx.dcl);
--- /dev/null
+/*
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qemu/bitmap.h"
+#include "qemu/queue.h"
+#include "ui/console.h"
+#include "ui/input.h"
+#include "ui/kbd-state.h"
+
+struct QKbdState {
+ QemuConsole *con;
+ int key_delay_ms;
+ DECLARE_BITMAP(keys, Q_KEY_CODE__MAX);
+ DECLARE_BITMAP(mods, QKBD_MOD__MAX);
+};
+
+static void qkbd_state_modifier_update(QKbdState *kbd,
+ QKeyCode qcode1, QKeyCode qcode2,
+ QKbdModifier mod)
+{
+ if (test_bit(qcode1, kbd->keys) || test_bit(qcode2, kbd->keys)) {
+ set_bit(mod, kbd->mods);
+ } else {
+ clear_bit(mod, kbd->mods);
+ }
+}
+
+bool qkbd_state_modifier_get(QKbdState *kbd, QKbdModifier mod)
+{
+ return test_bit(mod, kbd->mods);
+}
+
+bool qkbd_state_key_get(QKbdState *kbd, QKeyCode qcode)
+{
+ return test_bit(qcode, kbd->keys);
+}
+
+void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down)
+{
+ bool state = test_bit(qcode, kbd->keys);
+
+ if (down == false /* got key-up event */ &&
+ state == false /* key is not pressed */) {
+ /*
+ * Filter out suspicious key-up events.
+ *
+ * This allows simply sending along all key-up events, and
+ * this function will filter out everything where the
+ * corresponding key-down event wasn't sent to the guest, for
+ * example due to being a host hotkey.
+ *
+ * Note that key-down events on already pressed keys are *not*
+ * suspicious, those are keyboard autorepeat events.
+ */
+ return;
+ }
+
+ /* update key and modifier state */
+ change_bit(qcode, kbd->keys);
+ switch (qcode) {
+ case Q_KEY_CODE_SHIFT:
+ case Q_KEY_CODE_SHIFT_R:
+ qkbd_state_modifier_update(kbd, Q_KEY_CODE_SHIFT, Q_KEY_CODE_SHIFT_R,
+ QKBD_MOD_SHIFT);
+ break;
+ case Q_KEY_CODE_CTRL:
+ case Q_KEY_CODE_CTRL_R:
+ qkbd_state_modifier_update(kbd, Q_KEY_CODE_CTRL, Q_KEY_CODE_CTRL_R,
+ QKBD_MOD_CTRL);
+ break;
+ case Q_KEY_CODE_ALT:
+ qkbd_state_modifier_update(kbd, Q_KEY_CODE_ALT, Q_KEY_CODE_ALT,
+ QKBD_MOD_ALT);
+ break;
+ case Q_KEY_CODE_ALT_R:
+ qkbd_state_modifier_update(kbd, Q_KEY_CODE_ALT_R, Q_KEY_CODE_ALT_R,
+ QKBD_MOD_ALTGR);
+ break;
+ case Q_KEY_CODE_CAPS_LOCK:
+ if (down) {
+ change_bit(QKBD_MOD_CAPSLOCK, kbd->mods);
+ }
+ break;
+ case Q_KEY_CODE_NUM_LOCK:
+ if (down) {
+ change_bit(QKBD_MOD_NUMLOCK, kbd->mods);
+ }
+ break;
+ default:
+ /* keep gcc happy */
+ break;
+ }
+
+ /* send to guest */
+ if (qemu_console_is_graphic(kbd->con)) {
+ qemu_input_event_send_key_qcode(kbd->con, qcode, down);
+ if (kbd->key_delay_ms) {
+ qemu_input_event_send_key_delay(kbd->key_delay_ms);
+ }
+ }
+}
+
+void qkbd_state_lift_all_keys(QKbdState *kbd)
+{
+ int qcode;
+
+ for (qcode = 0; qcode < Q_KEY_CODE__MAX; qcode++) {
+ if (test_bit(qcode, kbd->keys)) {
+ qkbd_state_key_event(kbd, qcode, false);
+ }
+ }
+}
+
+void qkbd_state_set_delay(QKbdState *kbd, int delay_ms)
+{
+ kbd->key_delay_ms = delay_ms;
+}
+
+void qkbd_state_free(QKbdState *kbd)
+{
+ g_free(kbd);
+}
+
+QKbdState *qkbd_state_init(QemuConsole *con)
+{
+ QKbdState *kbd = g_new0(QKbdState, 1);
+
+ kbd->con = con;
+
+ return kbd;
+}
#include "trace.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
+#include "ui/input.h"
struct keysym2code {
uint32_t count;
int keysym2scancode(kbd_layout_t *k, int keysym,
- bool shift, bool altgr, bool ctrl)
+ QKbdState *kbd, bool down)
{
static const uint32_t mask =
SCANCODE_SHIFT | SCANCODE_ALTGR | SCANCODE_CTRL;
return keysym2code->keycodes[0];
}
- /*
- * We have multiple keysym -> keycode mappings.
- *
- * Check whenever we find one mapping where the modifier state of
- * the mapping matches the current user interface modifier state.
- * If so, prefer that one.
- */
- mods = 0;
- if (shift) {
- mods |= SCANCODE_SHIFT;
- }
- if (altgr) {
- mods |= SCANCODE_ALTGR;
- }
- if (ctrl) {
- mods |= SCANCODE_CTRL;
- }
+ /* We have multiple keysym -> keycode mappings. */
+ if (down) {
+ /*
+ * On keydown: Check whenever we find one mapping where the
+ * modifier state of the mapping matches the current user
+ * interface modifier state. If so, prefer that one.
+ */
+ mods = 0;
+ if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_SHIFT)) {
+ mods |= SCANCODE_SHIFT;
+ }
+ if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_ALTGR)) {
+ mods |= SCANCODE_ALTGR;
+ }
+ if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_CTRL)) {
+ mods |= SCANCODE_CTRL;
+ }
- for (i = 0; i < keysym2code->count; i++) {
- if ((keysym2code->keycodes[i] & mask) == mods) {
- return keysym2code->keycodes[i];
+ for (i = 0; i < keysym2code->count; i++) {
+ if ((keysym2code->keycodes[i] & mask) == mods) {
+ return keysym2code->keycodes[i];
+ }
+ }
+ } else {
+ /*
+ * On keyup: Try find a key which is actually down.
+ */
+ for (i = 0; i < keysym2code->count; i++) {
+ QKeyCode qcode = qemu_input_key_number_to_qcode
+ (keysym2code->keycodes[i]);
+ if (kbd && qkbd_state_key_get(kbd, qcode)) {
+ return keysym2code->keycodes[i];
+ }
}
}
return keysym2code->keycodes[0];
#define QEMU_KEYMAPS_H
#include "qemu-common.h"
+#include "ui/kbd-state.h"
typedef struct {
const char* name;
kbd_layout_t *init_keyboard_layout(const name2keysym_t *table,
const char *language, Error **errp);
int keysym2scancode(kbd_layout_t *k, int keysym,
- bool shift, bool altgr, bool ctrl);
+ QKbdState *kbd, bool down);
int keycode_is_keypad(kbd_layout_t *k, int keycode);
int keysym_is_numlock(kbd_layout_t *k, int keysym);
#include "ui/sdl2.h"
#include "sysemu/sysemu.h"
-static uint8_t modifiers_state[SDL_NUM_SCANCODES];
-
-void sdl2_reset_keys(struct sdl2_console *scon)
-{
- QemuConsole *con = scon ? scon->dcl.con : NULL;
- int i;
-
- for (i = 0 ;
- i < SDL_NUM_SCANCODES && i < qemu_input_map_usb_to_qcode_len ;
- i++) {
- if (modifiers_state[i]) {
- int qcode = qemu_input_map_usb_to_qcode[i];
- qemu_input_event_send_key_qcode(con, qcode, false);
- modifiers_state[i] = 0;
- }
- }
-}
-
void sdl2_process_key(struct sdl2_console *scon,
SDL_KeyboardEvent *ev)
{
int qcode;
- QemuConsole *con = scon ? scon->dcl.con : NULL;
+ QemuConsole *con = scon->dcl.con;
if (ev->keysym.scancode >= qemu_input_map_usb_to_qcode_len) {
return;
}
-
qcode = qemu_input_map_usb_to_qcode[ev->keysym.scancode];
-
- /* modifier state tracking */
- switch (ev->keysym.scancode) {
- case SDL_SCANCODE_LCTRL:
- case SDL_SCANCODE_LSHIFT:
- case SDL_SCANCODE_LALT:
- case SDL_SCANCODE_LGUI:
- case SDL_SCANCODE_RCTRL:
- case SDL_SCANCODE_RSHIFT:
- case SDL_SCANCODE_RALT:
- case SDL_SCANCODE_RGUI:
- if (ev->type == SDL_KEYUP) {
- modifiers_state[ev->keysym.scancode] = 0;
- } else {
- modifiers_state[ev->keysym.scancode] = 1;
- }
- break;
- default:
- /* nothing */
- break;
- }
+ qkbd_state_key_event(scon->kbd, qcode, ev->type == SDL_KEYDOWN);
if (!qemu_console_is_graphic(con)) {
- bool ctrl = (modifiers_state[SDL_SCANCODE_LCTRL] ||
- modifiers_state[SDL_SCANCODE_RCTRL]);
+ bool ctrl = qkbd_state_modifier_get(scon->kbd, QKBD_MOD_CTRL);
if (ev->type == SDL_KEYDOWN) {
- switch (ev->keysym.scancode) {
- case SDL_SCANCODE_RETURN:
+ switch (qcode) {
+ case Q_KEY_CODE_RET:
kbd_put_keysym_console(con, '\n');
break;
default:
break;
}
}
- } else {
- qemu_input_event_send_key_qcode(con, qcode,
- ev->type == SDL_KEYDOWN);
}
}
static int gui_saved_grab;
static int gui_fullscreen;
-static int gui_keysym;
static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
static SDL_Cursor *sdl_cursor_normal;
static SDL_Cursor *sdl_cursor_hidden;
int win;
struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
int gui_key_modifier_pressed = get_mod_state();
+ int gui_keysym = 0;
if (!scon->ignore_hotkeys && gui_key_modifier_pressed && !ev->key.repeat) {
switch (ev->key.keysym.scancode) {
static void handle_keyup(SDL_Event *ev)
{
struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
- int gui_key_modifier_pressed = get_mod_state();
scon->ignore_hotkeys = false;
-
- if (!gui_key_modifier_pressed) {
- gui_keysym = 0;
- }
- if (!gui_keysym) {
- sdl2_process_key(scon, &ev->key);
- }
+ sdl2_process_key(scon, &ev->key);
}
static void handle_textinput(SDL_Event *ev)
sdl2_console[i].dcl.ops = &dcl_2d_ops;
#endif
sdl2_console[i].dcl.con = con;
+ sdl2_console[i].kbd = qkbd_state_init(con);
register_displaychangelistener(&sdl2_console[i].dcl);
#if defined(SDL_VIDEO_DRIVER_WINDOWS) || defined(SDL_VIDEO_DRIVER_X11)
+++ /dev/null
-
-#include "keymaps.h"
-
-static const name2keysym_t name2keysym[]={
-/* ascii */
- { "space", 0x020},
- { "exclam", 0x021},
- { "quotedbl", 0x022},
- { "numbersign", 0x023},
- { "dollar", 0x024},
- { "percent", 0x025},
- { "ampersand", 0x026},
- { "apostrophe", 0x027},
- { "parenleft", 0x028},
- { "parenright", 0x029},
- { "asterisk", 0x02a},
- { "plus", 0x02b},
- { "comma", 0x02c},
- { "minus", 0x02d},
- { "period", 0x02e},
- { "slash", 0x02f},
- { "0", 0x030},
- { "1", 0x031},
- { "2", 0x032},
- { "3", 0x033},
- { "4", 0x034},
- { "5", 0x035},
- { "6", 0x036},
- { "7", 0x037},
- { "8", 0x038},
- { "9", 0x039},
- { "colon", 0x03a},
- { "semicolon", 0x03b},
- { "less", 0x03c},
- { "equal", 0x03d},
- { "greater", 0x03e},
- { "question", 0x03f},
- { "at", 0x040},
- { "A", 0x041},
- { "B", 0x042},
- { "C", 0x043},
- { "D", 0x044},
- { "E", 0x045},
- { "F", 0x046},
- { "G", 0x047},
- { "H", 0x048},
- { "I", 0x049},
- { "J", 0x04a},
- { "K", 0x04b},
- { "L", 0x04c},
- { "M", 0x04d},
- { "N", 0x04e},
- { "O", 0x04f},
- { "P", 0x050},
- { "Q", 0x051},
- { "R", 0x052},
- { "S", 0x053},
- { "T", 0x054},
- { "U", 0x055},
- { "V", 0x056},
- { "W", 0x057},
- { "X", 0x058},
- { "Y", 0x059},
- { "Z", 0x05a},
- { "bracketleft", 0x05b},
- { "backslash", 0x05c},
- { "bracketright", 0x05d},
- { "asciicircum", 0x05e},
- { "underscore", 0x05f},
- { "grave", 0x060},
- { "a", 0x061},
- { "b", 0x062},
- { "c", 0x063},
- { "d", 0x064},
- { "e", 0x065},
- { "f", 0x066},
- { "g", 0x067},
- { "h", 0x068},
- { "i", 0x069},
- { "j", 0x06a},
- { "k", 0x06b},
- { "l", 0x06c},
- { "m", 0x06d},
- { "n", 0x06e},
- { "o", 0x06f},
- { "p", 0x070},
- { "q", 0x071},
- { "r", 0x072},
- { "s", 0x073},
- { "t", 0x074},
- { "u", 0x075},
- { "v", 0x076},
- { "w", 0x077},
- { "x", 0x078},
- { "y", 0x079},
- { "z", 0x07a},
- { "braceleft", 0x07b},
- { "bar", 0x07c},
- { "braceright", 0x07d},
- { "asciitilde", 0x07e},
-
-/* latin 1 extensions */
-{ "nobreakspace", 0x0a0},
-{ "exclamdown", 0x0a1},
-{ "cent", 0x0a2},
-{ "sterling", 0x0a3},
-{ "currency", 0x0a4},
-{ "yen", 0x0a5},
-{ "brokenbar", 0x0a6},
-{ "section", 0x0a7},
-{ "diaeresis", 0x0a8},
-{ "copyright", 0x0a9},
-{ "ordfeminine", 0x0aa},
-{ "guillemotleft", 0x0ab},
-{ "notsign", 0x0ac},
-{ "hyphen", 0x0ad},
-{ "registered", 0x0ae},
-{ "macron", 0x0af},
-{ "degree", 0x0b0},
-{ "plusminus", 0x0b1},
-{ "twosuperior", 0x0b2},
-{ "threesuperior", 0x0b3},
-{ "acute", 0x0b4},
-{ "mu", 0x0b5},
-{ "paragraph", 0x0b6},
-{ "periodcentered", 0x0b7},
-{ "cedilla", 0x0b8},
-{ "onesuperior", 0x0b9},
-{ "masculine", 0x0ba},
-{ "guillemotright", 0x0bb},
-{ "onequarter", 0x0bc},
-{ "onehalf", 0x0bd},
-{ "threequarters", 0x0be},
-{ "questiondown", 0x0bf},
-{ "Agrave", 0x0c0},
-{ "Aacute", 0x0c1},
-{ "Acircumflex", 0x0c2},
-{ "Atilde", 0x0c3},
-{ "Adiaeresis", 0x0c4},
-{ "Aring", 0x0c5},
-{ "AE", 0x0c6},
-{ "Ccedilla", 0x0c7},
-{ "Egrave", 0x0c8},
-{ "Eacute", 0x0c9},
-{ "Ecircumflex", 0x0ca},
-{ "Ediaeresis", 0x0cb},
-{ "Igrave", 0x0cc},
-{ "Iacute", 0x0cd},
-{ "Icircumflex", 0x0ce},
-{ "Idiaeresis", 0x0cf},
-{ "ETH", 0x0d0},
-{ "Eth", 0x0d0},
-{ "Ntilde", 0x0d1},
-{ "Ograve", 0x0d2},
-{ "Oacute", 0x0d3},
-{ "Ocircumflex", 0x0d4},
-{ "Otilde", 0x0d5},
-{ "Odiaeresis", 0x0d6},
-{ "multiply", 0x0d7},
-{ "Ooblique", 0x0d8},
-{ "Oslash", 0x0d8},
-{ "Ugrave", 0x0d9},
-{ "Uacute", 0x0da},
-{ "Ucircumflex", 0x0db},
-{ "Udiaeresis", 0x0dc},
-{ "Yacute", 0x0dd},
-{ "THORN", 0x0de},
-{ "Thorn", 0x0de},
-{ "ssharp", 0x0df},
-{ "agrave", 0x0e0},
-{ "aacute", 0x0e1},
-{ "acircumflex", 0x0e2},
-{ "atilde", 0x0e3},
-{ "adiaeresis", 0x0e4},
-{ "aring", 0x0e5},
-{ "ae", 0x0e6},
-{ "ccedilla", 0x0e7},
-{ "egrave", 0x0e8},
-{ "eacute", 0x0e9},
-{ "ecircumflex", 0x0ea},
-{ "ediaeresis", 0x0eb},
-{ "igrave", 0x0ec},
-{ "iacute", 0x0ed},
-{ "icircumflex", 0x0ee},
-{ "idiaeresis", 0x0ef},
-{ "eth", 0x0f0},
-{ "ntilde", 0x0f1},
-{ "ograve", 0x0f2},
-{ "oacute", 0x0f3},
-{ "ocircumflex", 0x0f4},
-{ "otilde", 0x0f5},
-{ "odiaeresis", 0x0f6},
-{ "division", 0x0f7},
-{ "oslash", 0x0f8},
-{ "ooblique", 0x0f8},
-{ "ugrave", 0x0f9},
-{ "uacute", 0x0fa},
-{ "ucircumflex", 0x0fb},
-{ "udiaeresis", 0x0fc},
-{ "yacute", 0x0fd},
-{ "thorn", 0x0fe},
-{ "ydiaeresis", 0x0ff},
-#if SDL_MAJOR_VERSION == 1
-{"EuroSign", SDLK_EURO},
-
- /* modifiers */
-{"Control_L", SDLK_LCTRL},
-{"Control_R", SDLK_RCTRL},
-{"Alt_L", SDLK_LALT},
-{"Alt_R", SDLK_RALT},
-{"Caps_Lock", SDLK_CAPSLOCK},
-{"Meta_L", SDLK_LMETA},
-{"Meta_R", SDLK_RMETA},
-{"Shift_L", SDLK_LSHIFT},
-{"Shift_R", SDLK_RSHIFT},
-{"Super_L", SDLK_LSUPER},
-{"Super_R", SDLK_RSUPER},
-
- /* special keys */
-{"BackSpace", SDLK_BACKSPACE},
-{"Tab", SDLK_TAB},
-{"Return", SDLK_RETURN},
-{"Right", SDLK_RIGHT},
-{"Left", SDLK_LEFT},
-{"Up", SDLK_UP},
-{"Down", SDLK_DOWN},
-{"Page_Down", SDLK_PAGEDOWN},
-{"Page_Up", SDLK_PAGEUP},
-{"Insert", SDLK_INSERT},
-{"Delete", SDLK_DELETE},
-{"Home", SDLK_HOME},
-{"End", SDLK_END},
-{"Scroll_Lock", SDLK_SCROLLOCK},
-{"F1", SDLK_F1},
-{"F2", SDLK_F2},
-{"F3", SDLK_F3},
-{"F4", SDLK_F4},
-{"F5", SDLK_F5},
-{"F6", SDLK_F6},
-{"F7", SDLK_F7},
-{"F8", SDLK_F8},
-{"F9", SDLK_F9},
-{"F10", SDLK_F10},
-{"F11", SDLK_F11},
-{"F12", SDLK_F12},
-{"F13", SDLK_F13},
-{"F14", SDLK_F14},
-{"F15", SDLK_F15},
-{"Sys_Req", SDLK_SYSREQ},
-{"KP_0", SDLK_KP0},
-{"KP_1", SDLK_KP1},
-{"KP_2", SDLK_KP2},
-{"KP_3", SDLK_KP3},
-{"KP_4", SDLK_KP4},
-{"KP_5", SDLK_KP5},
-{"KP_6", SDLK_KP6},
-{"KP_7", SDLK_KP7},
-{"KP_8", SDLK_KP8},
-{"KP_9", SDLK_KP9},
-{"KP_Add", SDLK_KP_PLUS},
-{"KP_Decimal", SDLK_KP_PERIOD},
-{"KP_Divide", SDLK_KP_DIVIDE},
-{"KP_Enter", SDLK_KP_ENTER},
-{"KP_Equal", SDLK_KP_EQUALS},
-{"KP_Multiply", SDLK_KP_MULTIPLY},
-{"KP_Subtract", SDLK_KP_MINUS},
-{"help", SDLK_HELP},
-{"Menu", SDLK_MENU},
-{"Power", SDLK_POWER},
-{"Print", SDLK_PRINT},
-{"Mode_switch", SDLK_MODE},
-{"Multi_Key", SDLK_COMPOSE},
-{"Num_Lock", SDLK_NUMLOCK},
-{"Pause", SDLK_PAUSE},
-{"Escape", SDLK_ESCAPE},
-#endif
-{NULL, 0},
-};
--- /dev/null
+/*
+ * QEMU external Spice client display driver
+ *
+ * Copyright (c) 2018 Marc-André Lureau <marcandre.lureau@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+
+#include <gio/gio.h>
+
+#include "qemu-common.h"
+#include "ui/console.h"
+#include "qemu/config-file.h"
+#include "qemu/option.h"
+#include "qemu/cutils.h"
+#include "qapi/error.h"
+#include "io/channel-command.h"
+#include "chardev/spice.h"
+#include "sysemu/sysemu.h"
+
+static const char *tmp_dir;
+static char *app_dir;
+static char *sock_path;
+
+typedef struct VCChardev {
+ SpiceChardev parent;
+} VCChardev;
+
+#define TYPE_CHARDEV_VC "chardev-vc"
+#define VC_CHARDEV(obj) OBJECT_CHECK(VCChardev, (obj), TYPE_CHARDEV_VC)
+
+static ChardevBackend *
+chr_spice_backend_new(void)
+{
+ ChardevBackend *be = g_new0(ChardevBackend, 1);
+
+ be->type = CHARDEV_BACKEND_KIND_SPICEPORT;
+ be->u.spiceport.data = g_new0(ChardevSpicePort, 1);
+
+ return be;
+}
+
+static void vc_chr_open(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ ChardevBackend *be;
+ const char *fqdn = NULL;
+
+ if (strstart(chr->label, "serial", NULL)) {
+ fqdn = "org.qemu.console.serial.0";
+ } else if (strstart(chr->label, "parallel", NULL)) {
+ fqdn = "org.qemu.console.parallel.0";
+ } else if (strstart(chr->label, "compat_monitor", NULL)) {
+ fqdn = "org.qemu.monitor.hmp.0";
+ }
+
+ be = chr_spice_backend_new();
+ be->u.spiceport.data->fqdn = fqdn ?
+ g_strdup(fqdn) : g_strdup_printf("org.qemu.console.%s", chr->label);
+ qemu_chr_open_spice_port(chr, be, be_opened, errp);
+ qapi_free_ChardevBackend(be);
+}
+
+static void vc_chr_set_echo(Chardev *chr, bool echo)
+{
+ /* TODO: set echo for frontends QMP and qtest */
+}
+
+static void char_vc_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->parse = qemu_chr_parse_vc;
+ cc->open = vc_chr_open;
+ cc->chr_set_echo = vc_chr_set_echo;
+}
+
+static const TypeInfo char_vc_type_info = {
+ .name = TYPE_CHARDEV_VC,
+ .parent = TYPE_CHARDEV_SPICEPORT,
+ .instance_size = sizeof(VCChardev),
+ .class_init = char_vc_class_init,
+};
+
+static void spice_app_atexit(void)
+{
+ if (sock_path) {
+ unlink(sock_path);
+ }
+ if (tmp_dir) {
+ rmdir(tmp_dir);
+ }
+ g_free(sock_path);
+ g_free(app_dir);
+}
+
+static void spice_app_display_early_init(DisplayOptions *opts)
+{
+ QemuOpts *qopts;
+ ChardevBackend *be = chr_spice_backend_new();
+ GError *err = NULL;
+
+ if (opts->has_full_screen) {
+ error_report("spice-app full-screen isn't supported yet.");
+ exit(1);
+ }
+ if (opts->has_window_close) {
+ error_report("spice-app window-close isn't supported yet.");
+ exit(1);
+ }
+
+ atexit(spice_app_atexit);
+
+ if (qemu_name) {
+ app_dir = g_build_filename(g_get_user_runtime_dir(),
+ "qemu", qemu_name, NULL);
+ if (g_mkdir_with_parents(app_dir, S_IRWXU) < -1) {
+ error_report("Failed to create directory %s: %s",
+ app_dir, strerror(errno));
+ exit(1);
+ }
+ } else {
+ app_dir = g_dir_make_tmp(NULL, &err);
+ tmp_dir = app_dir;
+ if (err) {
+ error_report("Failed to create temporary directory: %s",
+ err->message);
+ exit(1);
+ }
+ }
+
+ type_register(&char_vc_type_info);
+
+ sock_path = g_strjoin("", app_dir, "/", "spice.sock", NULL);
+ qopts = qemu_opts_create(qemu_find_opts("spice"), NULL, 0, &error_abort);
+ qemu_opt_set(qopts, "disable-ticketing", "on", &error_abort);
+ qemu_opt_set(qopts, "unix", "on", &error_abort);
+ qemu_opt_set(qopts, "addr", sock_path, &error_abort);
+ qemu_opt_set(qopts, "image-compression", "off", &error_abort);
+ qemu_opt_set(qopts, "streaming-video", "off", &error_abort);
+ qemu_opt_set(qopts, "gl", opts->has_gl ? "on" : "off", &error_abort);
+ display_opengl = opts->has_gl;
+
+ be->u.spiceport.data->fqdn = g_strdup("org.qemu.monitor.qmp.0");
+ qemu_chardev_new("org.qemu.monitor.qmp", TYPE_CHARDEV_SPICEPORT,
+ be, NULL, &error_abort);
+ qopts = qemu_opts_create(qemu_find_opts("mon"),
+ NULL, 0, &error_fatal);
+ qemu_opt_set(qopts, "chardev", "org.qemu.monitor.qmp", &error_abort);
+ qemu_opt_set(qopts, "mode", "control", &error_abort);
+
+ qapi_free_ChardevBackend(be);
+}
+
+static void spice_app_display_init(DisplayState *ds, DisplayOptions *opts)
+{
+ GError *err = NULL;
+ gchar *uri;
+
+ uri = g_strjoin("", "spice+unix://", app_dir, "/", "spice.sock", NULL);
+ info_report("Launching display with URI: %s", uri);
+ g_app_info_launch_default_for_uri(uri, NULL, &err);
+ if (err) {
+ error_report("Failed to launch %s URI: %s", uri, err->message);
+ error_report("You need a capable Spice client, "
+ "such as virt-viewer 8.0");
+ exit(1);
+ }
+ g_free(uri);
+}
+
+static QemuDisplay qemu_display_spice_app = {
+ .type = DISPLAY_TYPE_SPICE_APP,
+ .early_init = spice_app_display_early_init,
+ .init = spice_app_display_init,
+};
+
+static void register_spice_app(void)
+{
+ qemu_display_register(&qemu_display_spice_app);
+}
+
+type_init(register_spice_app);
#include "qemu/option.h"
#include "migration/misc.h"
#include "hw/hw.h"
+#include "hw/pci/pci_bus.h"
#include "ui/spice-display.h"
/* core bits */
static QemuOptsList qemu_spice_opts = {
.name = "spice",
.head = QTAILQ_HEAD_INITIALIZER(qemu_spice_opts.head),
+ .merge_lists = true,
.desc = {
{
.name = "port",
{
if (running) {
qemu_spice_display_start();
- } else {
+ } else if (state != RUN_STATE_PAUSED) {
qemu_spice_display_stop();
}
}
qemu_opt_foreach(opts, add_channel, &tls_port, &error_fatal);
- spice_server_set_name(spice_server, qemu_name);
+ spice_server_set_name(spice_server, qemu_name ?: "QEMU " QEMU_VERSION);
spice_server_set_uuid(spice_server, (unsigned char *)&qemu_uuid);
seamless_migration = qemu_opt_get_bool(opts, "seamless-migration", 0);
return false;
}
+/*
+ * Recursively (in reverse order) appends addresses of PCI devices as it moves
+ * up in the PCI hierarchy.
+ *
+ * @returns true on success, false when the buffer wasn't large enough
+ */
+static bool append_pci_address(char *buf, size_t buf_size, const PCIDevice *pci)
+{
+ PCIBus *bus = pci_get_bus(pci);
+ /*
+ * equivalent to if (!pci_bus_is_root(bus)), but the function is not built
+ * with PCI_CONFIG=n, avoid using an #ifdef by checking directly
+ */
+ if (bus->parent_dev != NULL) {
+ append_pci_address(buf, buf_size, bus->parent_dev);
+ }
+
+ size_t len = strlen(buf);
+ ssize_t written = snprintf(buf + len, buf_size - len, "/%02x.%x",
+ PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn));
+
+ return written > 0 && written < buf_size - len;
+}
+
+bool qemu_spice_fill_device_address(QemuConsole *con,
+ char *device_address,
+ size_t size)
+{
+ DeviceState *dev = DEVICE(object_property_get_link(OBJECT(con),
+ "device",
+ &error_abort));
+ PCIDevice *pci = (PCIDevice *) object_dynamic_cast(OBJECT(dev),
+ TYPE_PCI_DEVICE);
+
+ if (pci == NULL) {
+ warn_report("Setting device address of a display device to SPICE: "
+ "Not a PCI device.");
+ return false;
+ }
+
+ strncpy(device_address, "pci/0000", size);
+ if (!append_pci_address(device_address, size, pci)) {
+ warn_report("Setting device address of a display device to SPICE: "
+ "Too many PCI devices in the chain.");
+ return false;
+ }
+
+ return true;
+}
+
int qemu_spice_add_display_interface(QXLInstance *qxlin, QemuConsole *con)
{
if (g_slist_find(spice_consoles, con)) {
void qemu_spice_display_start(void)
{
+ if (spice_display_is_running) {
+ return;
+ }
+
spice_display_is_running = true;
spice_server_vm_start(spice_server);
}
void qemu_spice_display_stop(void)
{
+ if (!spice_display_is_running) {
+ return;
+ }
+
spice_server_vm_stop(spice_server);
spice_display_is_running = false;
}
egl_texture_blit(ssd->gls, &ssd->blit_fb, &ssd->guest_fb,
!y_0_top);
egl_texture_blend(ssd->gls, &ssd->blit_fb, &ssd->cursor_fb,
- !y_0_top, x, y);
+ !y_0_top, x, y, 1.0, 1.0);
glFlush();
}
ssd->qxl.base.sif = &dpy_interface.base;
qemu_spice_add_display_interface(&ssd->qxl, con);
+
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
+ char device_address[256] = "";
+ if (qemu_spice_fill_device_address(con, device_address, 256)) {
+ spice_qxl_set_device_info(&ssd->qxl,
+ device_address,
+ qemu_console_get_head(con),
+ 1);
+ }
+#endif
+
qemu_spice_create_host_memslot(ssd);
register_displaychangelistener(&ssd->dcl);
#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "authz/base.h"
#include "vnc.h"
#include "trace.h"
static int vnc_auth_sasl_check_access(VncState *vs)
{
const void *val;
- int err;
- int allow;
+ int rv;
+ Error *err = NULL;
+ bool allow;
- err = sasl_getprop(vs->sasl.conn, SASL_USERNAME, &val);
- if (err != SASL_OK) {
+ rv = sasl_getprop(vs->sasl.conn, SASL_USERNAME, &val);
+ if (rv != SASL_OK) {
trace_vnc_auth_fail(vs, vs->auth, "Cannot fetch SASL username",
- sasl_errstring(err, NULL, NULL));
+ sasl_errstring(rv, NULL, NULL));
return -1;
}
if (val == NULL) {
vs->sasl.username = g_strdup((const char*)val);
trace_vnc_auth_sasl_username(vs, vs->sasl.username);
- if (vs->vd->sasl.acl == NULL) {
+ if (vs->vd->sasl.authzid == NULL) {
trace_vnc_auth_sasl_acl(vs, 1);
return 0;
}
- allow = qemu_acl_party_is_allowed(vs->vd->sasl.acl, vs->sasl.username);
+ allow = qauthz_is_allowed_by_id(vs->vd->sasl.authzid,
+ vs->sasl.username, &err);
+ if (err) {
+ trace_vnc_auth_fail(vs, vs->auth, "Error from authz",
+ error_get_pretty(err));
+ error_free(err);
+ return -1;
+ }
trace_vnc_auth_sasl_acl(vs, allow);
return allow ? 0 : -1;
typedef struct VncStateSASL VncStateSASL;
typedef struct VncDisplaySASL VncDisplaySASL;
-#include "qemu/acl.h"
#include "qemu/main-loop.h"
+#include "authz/base.h"
struct VncStateSASL {
sasl_conn_t *conn;
};
struct VncDisplaySASL {
- qemu_acl *acl;
+ QAuthZ *authz;
+ char *authzid;
};
void vnc_sasl_client_cleanup(VncState *vs);
tls = qio_channel_tls_new_server(
vs->ioc,
vs->vd->tlscreds,
- vs->vd->tlsaclname,
+ vs->vd->tlsauthzid,
&err);
if (!tls) {
trace_vnc_auth_fail(vs, vs->auth, "TLS setup failed",
int n_subtiles = 0;
for (j = 0; j < h; j++) {
- for (i = 0; i < w; i++) {
- switch (n_colors) {
- case 0:
- bg = irow[i];
- n_colors = 1;
- break;
- case 1:
- if (irow[i] != bg) {
- fg = irow[i];
- n_colors = 2;
- }
- break;
- case 2:
- if (irow[i] != bg && irow[i] != fg) {
- n_colors = 3;
- } else {
- if (irow[i] == bg)
- bg_count++;
- else if (irow[i] == fg)
- fg_count++;
- }
- break;
- default:
- break;
- }
- }
- if (n_colors > 2)
- break;
- irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
+ for (i = 0; i < w; i++) {
+ switch (n_colors) {
+ case 0:
+ bg = irow[i];
+ n_colors = 1;
+ break;
+ case 1:
+ if (irow[i] != bg) {
+ fg = irow[i];
+ n_colors = 2;
+ }
+ break;
+ case 2:
+ if (irow[i] != bg && irow[i] != fg) {
+ n_colors = 3;
+ } else {
+ if (irow[i] == bg)
+ bg_count++;
+ else if (irow[i] == fg)
+ fg_count++;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (n_colors > 2)
+ break;
+ irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
}
if (n_colors > 1 && fg_count > bg_count) {
- pixel_t tmp = fg;
- fg = bg;
- bg = tmp;
+ pixel_t tmp = fg;
+ fg = bg;
+ bg = tmp;
}
if (!*has_bg || *last_bg != bg) {
- flags |= 0x02;
- *has_bg = 1;
- *last_bg = bg;
+ flags |= 0x02;
+ *has_bg = 1;
+ *last_bg = bg;
}
if (n_colors < 3 && (!*has_fg || *last_fg != fg)) {
- flags |= 0x04;
- *has_fg = 1;
- *last_fg = fg;
+ flags |= 0x04;
+ *has_fg = 1;
+ *last_fg = fg;
}
switch (n_colors) {
case 1:
- n_data = 0;
- break;
+ n_data = 0;
+ break;
case 2:
- flags |= 0x08;
-
- irow = (pixel_t *)row;
-
- for (j = 0; j < h; j++) {
- int min_x = -1;
- for (i = 0; i < w; i++) {
- if (irow[i] == fg) {
- if (min_x == -1)
- min_x = i;
- } else if (min_x != -1) {
- hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
- n_data += 2;
- n_subtiles++;
- min_x = -1;
- }
- }
- if (min_x != -1) {
- hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
- n_data += 2;
- n_subtiles++;
- }
- irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
- }
- break;
+ flags |= 0x08;
+
+ irow = (pixel_t *)row;
+
+ for (j = 0; j < h; j++) {
+ int min_x = -1;
+ for (i = 0; i < w; i++) {
+ if (irow[i] == fg) {
+ if (min_x == -1)
+ min_x = i;
+ } else if (min_x != -1) {
+ hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
+ n_data += 2;
+ n_subtiles++;
+ min_x = -1;
+ }
+ }
+ if (min_x != -1) {
+ hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
+ n_data += 2;
+ n_subtiles++;
+ }
+ irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
+ }
+ break;
case 3:
- flags |= 0x18;
-
- irow = (pixel_t *)row;
-
- if (!*has_bg || *last_bg != bg)
- flags |= 0x02;
-
- for (j = 0; j < h; j++) {
- int has_color = 0;
- int min_x = -1;
- pixel_t color = 0; /* shut up gcc */
-
- for (i = 0; i < w; i++) {
- if (!has_color) {
- if (irow[i] == bg)
- continue;
- color = irow[i];
- min_x = i;
- has_color = 1;
- } else if (irow[i] != color) {
- has_color = 0;
+ flags |= 0x18;
+
+ irow = (pixel_t *)row;
+
+ if (!*has_bg || *last_bg != bg)
+ flags |= 0x02;
+
+ for (j = 0; j < h; j++) {
+ int has_color = 0;
+ int min_x = -1;
+ pixel_t color = 0; /* shut up gcc */
+
+ for (i = 0; i < w; i++) {
+ if (!has_color) {
+ if (irow[i] == bg)
+ continue;
+ color = irow[i];
+ min_x = i;
+ has_color = 1;
+ } else if (irow[i] != color) {
+ has_color = 0;
#ifdef GENERIC
vnc_convert_pixel(vs, data + n_data, color);
n_data += vs->client_pf.bytes_per_pixel;
#else
- memcpy(data + n_data, &color, sizeof(color));
+ memcpy(data + n_data, &color, sizeof(color));
n_data += sizeof(pixel_t);
#endif
- hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
- n_data += 2;
- n_subtiles++;
-
- min_x = -1;
- if (irow[i] != bg) {
- color = irow[i];
- min_x = i;
- has_color = 1;
- }
- }
- }
- if (has_color) {
+ hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
+ n_data += 2;
+ n_subtiles++;
+
+ min_x = -1;
+ if (irow[i] != bg) {
+ color = irow[i];
+ min_x = i;
+ has_color = 1;
+ }
+ }
+ }
+ if (has_color) {
#ifdef GENERIC
vnc_convert_pixel(vs, data + n_data, color);
n_data += vs->client_pf.bytes_per_pixel;
memcpy(data + n_data, &color, sizeof(color));
n_data += sizeof(pixel_t);
#endif
- hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
- n_data += 2;
- n_subtiles++;
- }
- irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
- }
-
- /* A SubrectsColoured subtile invalidates the foreground color */
- *has_fg = 0;
- if (n_data > (w * h * sizeof(pixel_t))) {
- n_colors = 4;
- flags = 0x01;
- *has_bg = 0;
-
- /* we really don't have to invalidate either the bg or fg
- but we've lost the old values. oh well. */
- }
+ hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
+ n_data += 2;
+ n_subtiles++;
+ }
+ irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
+ }
+
+ /* A SubrectsColoured subtile invalidates the foreground color */
+ *has_fg = 0;
+ if (n_data > (w * h * sizeof(pixel_t))) {
+ n_colors = 4;
+ flags = 0x01;
+ *has_bg = 0;
+
+ /* we really don't have to invalidate either the bg or fg
+ but we've lost the old values. oh well. */
+ }
break;
default:
- break;
+ break;
}
if (n_colors > 3) {
- flags = 0x01;
- *has_fg = 0;
- *has_bg = 0;
- n_colors = 4;
+ flags = 0x01;
+ *has_fg = 0;
+ *has_bg = 0;
+ n_colors = 4;
}
vnc_write_u8(vs, flags);
if (n_colors < 4) {
- if (flags & 0x02)
- vs->write_pixels(vs, last_bg, sizeof(pixel_t));
- if (flags & 0x04)
- vs->write_pixels(vs, last_fg, sizeof(pixel_t));
- if (n_subtiles) {
- vnc_write_u8(vs, n_subtiles);
- vnc_write(vs, data, n_data);
- }
+ if (flags & 0x02)
+ vs->write_pixels(vs, last_bg, sizeof(pixel_t));
+ if (flags & 0x04)
+ vs->write_pixels(vs, last_fg, sizeof(pixel_t));
+ if (n_subtiles) {
+ vnc_write_u8(vs, n_subtiles);
+ vnc_write(vs, data, n_data);
+ }
} else {
- for (j = 0; j < h; j++) {
- vs->write_pixels(vs, row, w * 4);
- row += vnc_server_fb_stride(vd);
- }
+ for (j = 0; j < h; j++) {
+ vs->write_pixels(vs, row, w * 4);
+ row += vnc_server_fb_stride(vd);
+ }
}
}
#ifndef ZYWRLE_QUANTIZE
/* Type A:lower bit omitting of EZW style. */
static const unsigned int zywrle_param[3][3]={
- {0x0000F000, 0x00000000, 0x00000000},
- {0x0000C000, 0x00F0F0F0, 0x00000000},
- {0x0000C000, 0x00C0C0C0, 0x00F0F0F0},
+ {0x0000F000, 0x00000000, 0x00000000},
+ {0x0000C000, 0x00F0F0F0, 0x00000000},
+ {0x0000C000, 0x00C0C0C0, 0x00F0F0F0},
/* {0x0000FF00, 0x00000000, 0x00000000},
- {0x0000FF00, 0x00FFFFFF, 0x00000000},
- {0x0000FF00, 0x00FFFFFF, 0x00FFFFFF}, */
+ {0x0000FF00, 0x00FFFFFF, 0x00000000},
+ {0x0000FF00, 0x00FFFFFF, 0x00FFFFFF}, */
};
#else
/* Type B:Non liner quantization filter. */
static const int8_t zywrle_conv[4][256]={
{ /* bi=5, bo=5 r=0.0:PSNR=24.849 */
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
{ /* bi=5, bo=5 r=2.0:PSNR=74.031 */
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 64, 64, 64, 64,
- 64, 64, 64, 64, 72, 72, 72, 72,
- 72, 72, 72, 72, 80, 80, 80, 80,
- 80, 80, 88, 88, 88, 88, 88, 88,
- 88, 88, 88, 88, 88, 88, 96, 96,
- 96, 96, 96, 104, 104, 104, 104, 104,
- 104, 104, 104, 104, 104, 112, 112, 112,
- 112, 112, 112, 112, 112, 112, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 0, -120, -120, -120, -120, -120, -120, -120,
- -120, -120, -120, -112, -112, -112, -112, -112,
- -112, -112, -112, -112, -104, -104, -104, -104,
- -104, -104, -104, -104, -104, -104, -96, -96,
- -96, -96, -96, -88, -88, -88, -88, -88,
- -88, -88, -88, -88, -88, -88, -88, -80,
- -80, -80, -80, -80, -80, -72, -72, -72,
- -72, -72, -72, -72, -72, -64, -64, -64,
- -64, -64, -64, -64, -64, -56, -56, -56,
- -56, -56, -56, -56, -56, -56, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48,
- -48, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 64, 64, 64, 64,
+ 64, 64, 64, 64, 72, 72, 72, 72,
+ 72, 72, 72, 72, 80, 80, 80, 80,
+ 80, 80, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 96, 96,
+ 96, 96, 96, 104, 104, 104, 104, 104,
+ 104, 104, 104, 104, 104, 112, 112, 112,
+ 112, 112, 112, 112, 112, 112, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120,
+ 0, -120, -120, -120, -120, -120, -120, -120,
+ -120, -120, -120, -112, -112, -112, -112, -112,
+ -112, -112, -112, -112, -104, -104, -104, -104,
+ -104, -104, -104, -104, -104, -104, -96, -96,
+ -96, -96, -96, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -80,
+ -80, -80, -80, -80, -80, -72, -72, -72,
+ -72, -72, -72, -72, -72, -64, -64, -64,
+ -64, -64, -64, -64, -64, -56, -56, -56,
+ -56, -56, -56, -56, -56, -56, -48, -48,
+ -48, -48, -48, -48, -48, -48, -48, -48,
+ -48, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
{ /* bi=5, bo=4 r=2.0:PSNR=64.441 */
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 88, 88, 88,
- 88, 88, 88, 88, 88, 88, 88, 88,
- 104, 104, 104, 104, 104, 104, 104, 104,
- 104, 104, 104, 112, 112, 112, 112, 112,
- 112, 112, 112, 112, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 0, -120, -120, -120, -120, -120, -120, -120,
- -120, -120, -120, -120, -120, -112, -112, -112,
- -112, -112, -112, -112, -112, -112, -104, -104,
- -104, -104, -104, -104, -104, -104, -104, -104,
- -104, -88, -88, -88, -88, -88, -88, -88,
- -88, -88, -88, -88, -80, -80, -80, -80,
- -80, -80, -80, -80, -80, -80, -80, -80,
- -80, -64, -64, -64, -64, -64, -64, -64,
- -64, -64, -64, -64, -64, -64, -64, -64,
- -64, -48, -48, -48, -48, -48, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48,
- -48, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88,
+ 104, 104, 104, 104, 104, 104, 104, 104,
+ 104, 104, 104, 112, 112, 112, 112, 112,
+ 112, 112, 112, 112, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120,
+ 0, -120, -120, -120, -120, -120, -120, -120,
+ -120, -120, -120, -120, -120, -112, -112, -112,
+ -112, -112, -112, -112, -112, -112, -104, -104,
+ -104, -104, -104, -104, -104, -104, -104, -104,
+ -104, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -80, -80, -80, -80,
+ -80, -80, -80, -80, -80, -80, -80, -80,
+ -80, -64, -64, -64, -64, -64, -64, -64,
+ -64, -64, -64, -64, -64, -64, -64, -64,
+ -64, -48, -48, -48, -48, -48, -48, -48,
+ -48, -48, -48, -48, -48, -48, -48, -48,
+ -48, -48, -48, -48, -48, -48, -48, -48,
+ -48, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
{ /* bi=5, bo=2 r=2.0:PSNR=43.175 */
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 88, 88, 88, 88, 88, 88, 88, 88,
- 88, 88, 88, 88, 88, 88, 88, 88,
- 88, 88, 88, 88, 88, 88, 88, 88,
- 88, 88, 88, 88, 88, 88, 88, 88,
- 88, 88, 88, 88, 88, 88, 88, 88,
- 88, 88, 88, 88, 88, 88, 88, 88,
- 88, 88, 88, 88, 88, 88, 88, 88,
- 88, 88, 88, 88, 88, 88, 88, 88,
- 0, -88, -88, -88, -88, -88, -88, -88,
- -88, -88, -88, -88, -88, -88, -88, -88,
- -88, -88, -88, -88, -88, -88, -88, -88,
- -88, -88, -88, -88, -88, -88, -88, -88,
- -88, -88, -88, -88, -88, -88, -88, -88,
- -88, -88, -88, -88, -88, -88, -88, -88,
- -88, -88, -88, -88, -88, -88, -88, -88,
- -88, -88, -88, -88, -88, -88, -88, -88,
- -88, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88,
+ 0, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
}
};
static const int8_t *zywrle_param[3][3][3]={
- {{zywrle_conv[0], zywrle_conv[2], zywrle_conv[0]},
+ {{zywrle_conv[0], zywrle_conv[2], zywrle_conv[0]},
{zywrle_conv[0], zywrle_conv[0], zywrle_conv[0]},
{zywrle_conv[0], zywrle_conv[0], zywrle_conv[0]}},
- {{zywrle_conv[0], zywrle_conv[3], zywrle_conv[0]},
+ {{zywrle_conv[0], zywrle_conv[3], zywrle_conv[0]},
{zywrle_conv[1], zywrle_conv[1], zywrle_conv[1]},
{zywrle_conv[0], zywrle_conv[0], zywrle_conv[0]}},
- {{zywrle_conv[0], zywrle_conv[3], zywrle_conv[0]},
+ {{zywrle_conv[0], zywrle_conv[3], zywrle_conv[0]},
{zywrle_conv[2], zywrle_conv[2], zywrle_conv[2]},
{zywrle_conv[1], zywrle_conv[1], zywrle_conv[1]}},
};
#define ZYWRLE_UVMASK15 0xFFFFFFF8
#define ZYWRLE_LOAD_PIXEL15(src, r, g, b) \
do { \
- r = (((uint8_t*)src)[S_1]<< 1)& 0xF8; \
- g = (((uint8_t*)src)[S_1]<< 6) | (((uint8_t*)src)[S_0]>> 2); \
+ r = (((uint8_t*)src)[S_1]<< 1)& 0xF8; \
+ g = (((uint8_t*)src)[S_1]<< 6) | (((uint8_t*)src)[S_0]>> 2); \
g &= 0xF8; \
- b = (((uint8_t*)src)[S_0]<< 3)& 0xF8; \
+ b = (((uint8_t*)src)[S_0]<< 3)& 0xF8; \
} while (0)
#define ZYWRLE_SAVE_PIXEL15(dst, r, g, b) \
do { \
- r &= 0xF8; \
- g &= 0xF8; \
- b &= 0xF8; \
- ((uint8_t*)dst)[S_1] = (uint8_t)((r >> 1)|(g >> 6)); \
- ((uint8_t*)dst)[S_0] = (uint8_t)(((b >> 3)|(g << 2))& 0xFF); \
+ r &= 0xF8; \
+ g &= 0xF8; \
+ b &= 0xF8; \
+ ((uint8_t*)dst)[S_1] = (uint8_t)((r >> 1)|(g >> 6)); \
+ ((uint8_t*)dst)[S_0] = (uint8_t)(((b >> 3)|(g << 2))& 0xFF); \
} while (0)
#define ZYWRLE_YMASK16 0xFFFFFFFC
#define ZYWRLE_UVMASK16 0xFFFFFFF8
#define ZYWRLE_LOAD_PIXEL16(src, r, g, b) \
do { \
- r = ((uint8_t*)src)[S_1] & 0xF8; \
- g = (((uint8_t*)src)[S_1]<< 5) | (((uint8_t*)src)[S_0] >> 3); \
+ r = ((uint8_t*)src)[S_1] & 0xF8; \
+ g = (((uint8_t*)src)[S_1]<< 5) | (((uint8_t*)src)[S_0] >> 3); \
g &= 0xFC; \
- b = (((uint8_t*)src)[S_0]<< 3) & 0xF8; \
+ b = (((uint8_t*)src)[S_0]<< 3) & 0xF8; \
} while (0)
#define ZYWRLE_SAVE_PIXEL16(dst, r, g,b) \
do { \
- r &= 0xF8; \
- g &= 0xFC; \
- b &= 0xF8; \
- ((uint8_t*)dst)[S_1] = (uint8_t)(r | (g >> 5)); \
- ((uint8_t*)dst)[S_0] = (uint8_t)(((b >> 3)|(g << 3)) & 0xFF); \
+ r &= 0xF8; \
+ g &= 0xFC; \
+ b &= 0xF8; \
+ ((uint8_t*)dst)[S_1] = (uint8_t)(r | (g >> 5)); \
+ ((uint8_t*)dst)[S_0] = (uint8_t)(((b >> 3)|(g << 3)) & 0xFF); \
} while (0)
#define ZYWRLE_YMASK32 0xFFFFFFFF
#define ZYWRLE_UVMASK32 0xFFFFFFFF
#define ZYWRLE_LOAD_PIXEL32(src, r, g, b) \
do { \
- r = ((uint8_t*)src)[L_2]; \
- g = ((uint8_t*)src)[L_1]; \
- b = ((uint8_t*)src)[L_0]; \
+ r = ((uint8_t*)src)[L_2]; \
+ g = ((uint8_t*)src)[L_1]; \
+ b = ((uint8_t*)src)[L_0]; \
} while (0)
#define ZYWRLE_SAVE_PIXEL32(dst, r, g, b) \
do { \
- ((uint8_t*)dst)[L_2] = (uint8_t)r; \
- ((uint8_t*)dst)[L_1] = (uint8_t)g; \
- ((uint8_t*)dst)[L_0] = (uint8_t)b; \
+ ((uint8_t*)dst)[L_2] = (uint8_t)r; \
+ ((uint8_t*)dst)[L_1] = (uint8_t)g; \
+ ((uint8_t*)dst)[L_0] = (uint8_t)b; \
} while (0)
static inline void harr(int8_t *px0, int8_t *px1)
static inline void wavelet(int *buf, int width, int height, int level)
{
- int l, s;
- int *top;
- int *end;
-
- for (l = 0; l < level; l++) {
- top = buf;
- end = buf + height * width;
- s = width << l;
- while (top < end) {
- wavelet_level(top, width, l, 1);
- top += s;
- }
- top = buf;
- end = buf + width;
- s = 1<<l;
- while (top < end) {
- wavelet_level(top, height, l, width);
- top += s;
- }
- filter_wavelet_square(buf, width, height, level, l);
- }
+ int l, s;
+ int *top;
+ int *end;
+
+ for (l = 0; l < level; l++) {
+ top = buf;
+ end = buf + height * width;
+ s = width << l;
+ while (top < end) {
+ wavelet_level(top, width, l, 1);
+ top += s;
+ }
+ top = buf;
+ end = buf + width;
+ s = 1<<l;
+ while (top < end) {
+ wavelet_level(top, height, l, width);
+ top += s;
+ }
+ filter_wavelet_square(buf, width, height, level, l);
+ }
}
Coefficients manages as 24 bits little-endian pixel. */
#define ZYWRLE_LOAD_COEFF(src, r, g, b) \
do { \
- r = ((int8_t*)src)[2]; \
- g = ((int8_t*)src)[1]; \
- b = ((int8_t*)src)[0]; \
+ r = ((int8_t*)src)[2]; \
+ g = ((int8_t*)src)[1]; \
+ b = ((int8_t*)src)[0]; \
} while (0)
#define ZYWRLE_SAVE_COEFF(dst, r, g, b) \
do { \
- ((int8_t*)dst)[2] = (int8_t)r; \
- ((int8_t*)dst)[1] = (int8_t)g; \
- ((int8_t*)dst)[0] = (int8_t)b; \
+ ((int8_t*)dst)[2] = (int8_t)r; \
+ ((int8_t*)dst)[1] = (int8_t)g; \
+ ((int8_t*)dst)[0] = (int8_t)b; \
} while (0)
/*
More exact PLHarr, we reduce to odd range(-127<=x<=127). */
#define ZYWRLE_RGBYUV_(r, g, b, y, u, v, ymask, uvmask) \
do { \
- y = (r + (g << 1) + b) >> 2; \
- u = b - g; \
- v = r - g; \
- y -= 128; \
- u >>= 1; \
- v >>= 1; \
- y &= ymask; \
- u &= uvmask; \
- v &= uvmask; \
- if (y == -128) { \
+ y = (r + (g << 1) + b) >> 2; \
+ u = b - g; \
+ v = r - g; \
+ y -= 128; \
+ u >>= 1; \
+ v >>= 1; \
+ y &= ymask; \
+ u &= uvmask; \
+ v &= uvmask; \
+ if (y == -128) { \
y += (0xFFFFFFFF - ymask + 1); \
} \
- if (u == -128) { \
+ if (u == -128) { \
u += (0xFFFFFFFF - uvmask + 1); \
} \
- if (v == -128) { \
+ if (v == -128) { \
v += (0xFFFFFFFF - uvmask + 1); \
} \
} while (0)
tls = qio_channel_tls_new_server(
vs->ioc,
vs->vd->tlscreds,
- vs->vd->tlsaclname,
+ vs->vd->tlsauthzid,
&err);
if (!tls) {
VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err));
#include "qemu/option.h"
#include "qemu/sockets.h"
#include "qemu/timer.h"
-#include "qemu/acl.h"
+#include "authz/list.h"
#include "qemu/config-file.h"
-#include "qapi/qapi-events.h"
+#include "qapi/qapi-emit-events.h"
+#include "qapi/qapi-events-ui.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-ui.h"
#include "ui/input.h"
QTAILQ_HEAD_INITIALIZER(vnc_displays);
static int vnc_cursor_define(VncState *vs);
-static void vnc_release_modifiers(VncState *vs);
static void vnc_update_throttle_offset(VncState *vs);
static void vnc_set_share_mode(VncState *vs, VncShareMode mode)
vnc_sasl_client_cleanup(vs);
#endif /* CONFIG_VNC_SASL */
audio_del(vs);
- vnc_release_modifiers(vs);
+ qkbd_state_lift_all_keys(vs->vd->kbd);
if (vs->mouse_mode_notifier.notify != NULL) {
qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
qemu_input_event_sync();
}
-static void reset_keys(VncState *vs)
+static void press_key(VncState *vs, QKeyCode qcode)
{
- int i;
- for(i = 0; i < 256; i++) {
- if (vs->modifiers_state[i]) {
- qemu_input_event_send_key_number(vs->vd->dcl.con, i, false);
- qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
- vs->modifiers_state[i] = 0;
- }
- }
-}
-
-static void press_key(VncState *vs, int keysym)
-{
- int keycode = keysym2scancode(vs->vd->kbd_layout, keysym,
- false, false, false) & SCANCODE_KEYMASK;
- qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, true);
- qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
- qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false);
- qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
+ qkbd_state_key_event(vs->vd->kbd, qcode, true);
+ qkbd_state_key_event(vs->vd->kbd, qcode, false);
}
static void vnc_led_state_change(VncState *vs)
static void do_key_event(VncState *vs, int down, int keycode, int sym)
{
+ QKeyCode qcode = qemu_input_key_number_to_qcode(keycode);
+
/* QEMU console switch */
- switch(keycode) {
- case 0x2a: /* Left Shift */
- case 0x36: /* Right Shift */
- case 0x1d: /* Left CTRL */
- case 0x9d: /* Right CTRL */
- case 0x38: /* Left ALT */
- case 0xb8: /* Right ALT */
- if (down)
- vs->modifiers_state[keycode] = 1;
- else
- vs->modifiers_state[keycode] = 0;
- break;
- case 0x02 ... 0x0a: /* '1' to '9' keys */
- if (vs->vd->dcl.con == NULL &&
- down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
+ switch (qcode) {
+ case Q_KEY_CODE_1 ... Q_KEY_CODE_9: /* '1' to '9' keys */
+ if (vs->vd->dcl.con == NULL && down &&
+ qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTRL) &&
+ qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_ALT)) {
/* Reset the modifiers sent to the current console */
- reset_keys(vs);
- console_select(keycode - 0x02);
+ qkbd_state_lift_all_keys(vs->vd->kbd);
+ console_select(qcode - Q_KEY_CODE_1);
return;
}
- break;
- case 0x3a: /* CapsLock */
- case 0x45: /* NumLock */
- if (down)
- vs->modifiers_state[keycode] ^= 1;
+ default:
break;
}
toggles numlock away from the VNC window.
*/
if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) {
- if (!vs->modifiers_state[0x45]) {
+ if (!qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK)) {
trace_vnc_key_sync_numlock(true);
- vs->modifiers_state[0x45] = 1;
- press_key(vs, 0xff7f);
+ press_key(vs, Q_KEY_CODE_NUM_LOCK);
}
} else {
- if (vs->modifiers_state[0x45]) {
+ if (qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK)) {
trace_vnc_key_sync_numlock(false);
- vs->modifiers_state[0x45] = 0;
- press_key(vs, 0xff7f);
+ press_key(vs, Q_KEY_CODE_NUM_LOCK);
}
}
}
toggles capslock away from the VNC window.
*/
int uppercase = !!(sym >= 'A' && sym <= 'Z');
- int shift = !!(vs->modifiers_state[0x2a] | vs->modifiers_state[0x36]);
- int capslock = !!(vs->modifiers_state[0x3a]);
+ bool shift = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_SHIFT);
+ bool capslock = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CAPSLOCK);
if (capslock) {
if (uppercase == shift) {
trace_vnc_key_sync_capslock(false);
- vs->modifiers_state[0x3a] = 0;
- press_key(vs, 0xffe5);
+ press_key(vs, Q_KEY_CODE_CAPS_LOCK);
}
} else {
if (uppercase != shift) {
trace_vnc_key_sync_capslock(true);
- vs->modifiers_state[0x3a] = 1;
- press_key(vs, 0xffe5);
+ press_key(vs, Q_KEY_CODE_CAPS_LOCK);
}
}
}
- if (qemu_console_is_graphic(NULL)) {
- qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, down);
- qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
- } else {
- bool numlock = vs->modifiers_state[0x45];
- bool control = (vs->modifiers_state[0x1d] ||
- vs->modifiers_state[0x9d]);
+ qkbd_state_key_event(vs->vd->kbd, qcode, down);
+ if (!qemu_console_is_graphic(NULL)) {
+ bool numlock = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK);
+ bool control = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTRL);
/* QEMU console emulation */
if (down) {
switch (keycode) {
}
}
-static void vnc_release_modifiers(VncState *vs)
-{
- static const int keycodes[] = {
- /* shift, control, alt keys, both left & right */
- 0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8,
- };
- int i, keycode;
-
- if (!qemu_console_is_graphic(NULL)) {
- return;
- }
- for (i = 0; i < ARRAY_SIZE(keycodes); i++) {
- keycode = keycodes[i];
- if (!vs->modifiers_state[keycode]) {
- continue;
- }
- qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false);
- qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
- }
-}
-
static const char *code2name(int keycode)
{
return QKeyCode_str(qemu_input_key_number_to_qcode(keycode));
static void key_event(VncState *vs, int down, uint32_t sym)
{
- bool shift = vs->modifiers_state[0x2a] || vs->modifiers_state[0x36];
- bool altgr = vs->modifiers_state[0xb8];
- bool ctrl = vs->modifiers_state[0x1d] || vs->modifiers_state[0x9d];
int keycode;
int lsym = sym;
}
keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF,
- shift, altgr, ctrl) & SCANCODE_KEYMASK;
+ vs->vd->kbd, down) & SCANCODE_KEYMASK;
trace_vnc_key_event_map(down, sym, keycode, code2name(keycode));
do_key_event(vs, down, keycode, sym);
}
vd->dcl.ops = &dcl_ops;
register_displaychangelistener(&vd->dcl);
+ vd->kbd = qkbd_state_init(vd->dcl.con);
}
object_unparent(OBJECT(vd->tlscreds));
vd->tlscreds = NULL;
}
- g_free(vd->tlsaclname);
- vd->tlsaclname = NULL;
+ if (vd->tlsauthz) {
+ object_unparent(OBJECT(vd->tlsauthz));
+ vd->tlsauthz = NULL;
+ }
+ g_free(vd->tlsauthzid);
+ vd->tlsauthzid = NULL;
if (vd->lock_key_sync) {
qemu_remove_led_event_handler(vd->led);
vd->led = NULL;
}
+#ifdef CONFIG_VNC_SASL
+ if (vd->sasl.authz) {
+ object_unparent(OBJECT(vd->sasl.authz));
+ vd->sasl.authz = NULL;
+ }
+ g_free(vd->sasl.authzid);
+ vd->sasl.authzid = NULL;
+#endif
}
int vnc_display_password(const char *id, const char *password)
if (acl) {
if (strcmp(vd->id, "default") == 0) {
- vd->tlsaclname = g_strdup("vnc.x509dname");
+ vd->tlsauthzid = g_strdup("vnc.x509dname");
} else {
- vd->tlsaclname = g_strdup_printf("vnc.%s.x509dname", vd->id);
+ vd->tlsauthzid = g_strdup_printf("vnc.%s.x509dname", vd->id);
}
- qemu_acl_init(vd->tlsaclname);
+ vd->tlsauthz = QAUTHZ(qauthz_list_new(vd->tlsauthzid,
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort));
}
#ifdef CONFIG_VNC_SASL
if (acl && sasl) {
- char *aclname;
-
if (strcmp(vd->id, "default") == 0) {
- aclname = g_strdup("vnc.username");
+ vd->sasl.authzid = g_strdup("vnc.username");
} else {
- aclname = g_strdup_printf("vnc.%s.username", vd->id);
+ vd->sasl.authzid = g_strdup_printf("vnc.%s.username", vd->id);
}
- vd->sasl.acl = qemu_acl_init(aclname);
- g_free(aclname);
+ vd->sasl.authz = QAUTHZ(qauthz_list_new(vd->sasl.authzid,
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort));
}
#endif
vd->led = qemu_add_led_event_handler(kbd_leds, vd);
}
vd->ledstate = 0;
- vd->key_delay_ms = key_delay_ms;
device_id = qemu_opt_get(opts, "display");
if (device_id) {
}
if (con != vd->dcl.con) {
+ qkbd_state_free(vd->kbd);
unregister_displaychangelistener(&vd->dcl);
vd->dcl.con = con;
register_displaychangelistener(&vd->dcl);
+ vd->kbd = qkbd_state_init(vd->dcl.con);
}
+ qkbd_state_set_delay(vd->kbd, key_delay_ms);
if (saddr == NULL) {
goto cleanup;
#include "io/channel-socket.h"
#include "io/channel-tls.h"
#include "io/net-listener.h"
+#include "authz/base.h"
#include <zlib.h>
#include "keymaps.h"
#include "vnc-palette.h"
#include "vnc-enc-zrle.h"
+#include "ui/kbd-state.h"
// #define _VNC_DEBUG 1
int lock_key_sync;
QEMUPutLEDEntry *led;
int ledstate;
- int key_delay_ms;
+ QKbdState *kbd;
QemuMutex mutex;
QEMUCursor *cursor;
bool lossy;
bool non_adaptive;
QCryptoTLSCreds *tlscreds;
- char *tlsaclname;
+ QAuthZ *tlsauthz;
+ char *tlsauthzid;
#ifdef CONFIG_VNC_SASL
VncDisplaySASL sasl;
#endif
VncReadEvent *read_handler;
size_t read_handler_expect;
- /* input */
- uint8_t modifiers_state[256];
bool abort;
QemuMutex output_mutex;
util-obj-y += host-utils.o
util-obj-y += bitmap.o bitops.o hbitmap.o
util-obj-y += fifo8.o
-util-obj-y += acl.o
util-obj-y += cacheinfo.o
util-obj-y += error.o qemu-error.o
util-obj-y += id.o
util-obj-y += stats64.o
util-obj-y += systemd.o
util-obj-y += iova-tree.o
+util-obj-$(CONFIG_INOTIFY1) += filemonitor-inotify.o
util-obj-$(CONFIG_LINUX) += vfio-helpers.o
util-obj-$(CONFIG_OPENGL) += drm.o
+
+stub-obj-y += filemonitor-stub.o
+++ /dev/null
-/*
- * QEMU access control list management
- *
- * Copyright (C) 2009 Red Hat, Inc
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/acl.h"
-
-#ifdef CONFIG_FNMATCH
-#include <fnmatch.h>
-#endif
-
-
-static unsigned int nacls = 0;
-static qemu_acl **acls = NULL;
-
-
-
-qemu_acl *qemu_acl_find(const char *aclname)
-{
- int i;
- for (i = 0 ; i < nacls ; i++) {
- if (strcmp(acls[i]->aclname, aclname) == 0)
- return acls[i];
- }
-
- return NULL;
-}
-
-qemu_acl *qemu_acl_init(const char *aclname)
-{
- qemu_acl *acl;
-
- acl = qemu_acl_find(aclname);
- if (acl)
- return acl;
-
- acl = g_malloc(sizeof(*acl));
- acl->aclname = g_strdup(aclname);
- /* Deny by default, so there is no window of "open
- * access" between QEMU starting, and the user setting
- * up ACLs in the monitor */
- acl->defaultDeny = 1;
-
- acl->nentries = 0;
- QTAILQ_INIT(&acl->entries);
-
- acls = g_realloc(acls, sizeof(*acls) * (nacls +1));
- acls[nacls] = acl;
- nacls++;
-
- return acl;
-}
-
-int qemu_acl_party_is_allowed(qemu_acl *acl,
- const char *party)
-{
- qemu_acl_entry *entry;
-
- QTAILQ_FOREACH(entry, &acl->entries, next) {
-#ifdef CONFIG_FNMATCH
- if (fnmatch(entry->match, party, 0) == 0)
- return entry->deny ? 0 : 1;
-#else
- /* No fnmatch, so fallback to exact string matching
- * instead of allowing wildcards */
- if (strcmp(entry->match, party) == 0)
- return entry->deny ? 0 : 1;
-#endif
- }
-
- return acl->defaultDeny ? 0 : 1;
-}
-
-
-void qemu_acl_reset(qemu_acl *acl)
-{
- qemu_acl_entry *entry, *next_entry;
-
- /* Put back to deny by default, so there is no window
- * of "open access" while the user re-initializes the
- * access control list */
- acl->defaultDeny = 1;
- QTAILQ_FOREACH_SAFE(entry, &acl->entries, next, next_entry) {
- QTAILQ_REMOVE(&acl->entries, entry, next);
- g_free(entry->match);
- g_free(entry);
- }
- acl->nentries = 0;
-}
-
-
-int qemu_acl_append(qemu_acl *acl,
- int deny,
- const char *match)
-{
- qemu_acl_entry *entry;
-
- entry = g_malloc(sizeof(*entry));
- entry->match = g_strdup(match);
- entry->deny = deny;
-
- QTAILQ_INSERT_TAIL(&acl->entries, entry, next);
- acl->nentries++;
-
- return acl->nentries;
-}
-
-
-int qemu_acl_insert(qemu_acl *acl,
- int deny,
- const char *match,
- int index)
-{
- qemu_acl_entry *tmp;
- int i = 0;
-
- if (index <= 0)
- return -1;
- if (index > acl->nentries) {
- return qemu_acl_append(acl, deny, match);
- }
-
- QTAILQ_FOREACH(tmp, &acl->entries, next) {
- i++;
- if (i == index) {
- qemu_acl_entry *entry;
- entry = g_malloc(sizeof(*entry));
- entry->match = g_strdup(match);
- entry->deny = deny;
-
- QTAILQ_INSERT_BEFORE(tmp, entry, next);
- acl->nentries++;
- break;
- }
- }
-
- return i;
-}
-
-int qemu_acl_remove(qemu_acl *acl,
- const char *match)
-{
- qemu_acl_entry *entry;
- int i = 0;
-
- QTAILQ_FOREACH(entry, &acl->entries, next) {
- i++;
- if (strcmp(entry->match, match) == 0) {
- QTAILQ_REMOVE(&acl->entries, entry, next);
- acl->nentries--;
- g_free(entry->match);
- g_free(entry);
- return i;
- }
- }
- return -1;
-}
int64_t timeout;
int64_t start = 0;
+ assert(in_aio_context_home_thread(ctx));
+
/* aio_notify can avoid the expensive event_notifier_set if
* everything (file descriptors, bottom halves, timers) will
* be re-evaluated before the next blocking poll(). This is
* so disable the optimization now.
*/
if (blocking) {
- assert(in_aio_context_home_thread(ctx));
atomic_add(&ctx->notify_me, 2);
}
--- /dev/null
+/*
+ * QEMU file monitor Linux inotify impl
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/filemonitor.h"
+#include "qemu/main-loop.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "trace.h"
+
+#include <sys/inotify.h>
+
+struct QFileMonitor {
+ int fd;
+
+ QemuMutex lock; /* protects dirs & idmap */
+ GHashTable *dirs; /* dirname => QFileMonitorDir */
+ GHashTable *idmap; /* inotify ID => dirname */
+};
+
+
+typedef struct {
+ int id; /* watch ID */
+ char *filename; /* optional filter */
+ QFileMonitorHandler cb;
+ void *opaque;
+} QFileMonitorWatch;
+
+
+typedef struct {
+ char *path;
+ int id; /* inotify ID */
+ int nextid; /* watch ID counter */
+ GArray *watches; /* QFileMonitorWatch elements */
+} QFileMonitorDir;
+
+
+static void qemu_file_monitor_watch(void *arg)
+{
+ QFileMonitor *mon = arg;
+ char buf[4096]
+ __attribute__ ((aligned(__alignof__(struct inotify_event))));
+ int used = 0;
+ int len;
+
+ qemu_mutex_lock(&mon->lock);
+
+ if (mon->fd == -1) {
+ qemu_mutex_unlock(&mon->lock);
+ return;
+ }
+
+ len = read(mon->fd, buf, sizeof(buf));
+
+ if (len < 0) {
+ if (errno != EAGAIN) {
+ error_report("Failure monitoring inotify FD '%s',"
+ "disabling events", strerror(errno));
+ goto cleanup;
+ }
+
+ /* no more events right now */
+ goto cleanup;
+ }
+
+ /* Loop over all events in the buffer */
+ while (used < len) {
+ struct inotify_event *ev =
+ (struct inotify_event *)(buf + used);
+ const char *name = ev->len ? ev->name : "";
+ QFileMonitorDir *dir = g_hash_table_lookup(mon->idmap,
+ GINT_TO_POINTER(ev->wd));
+ uint32_t iev = ev->mask &
+ (IN_CREATE | IN_MODIFY | IN_DELETE | IN_IGNORED |
+ IN_MOVED_TO | IN_MOVED_FROM | IN_ATTRIB);
+ int qev;
+ gsize i;
+
+ used += sizeof(struct inotify_event) + ev->len;
+
+ if (!dir) {
+ continue;
+ }
+
+ /*
+ * During a rename operation, the old name gets
+ * IN_MOVED_FROM and the new name gets IN_MOVED_TO.
+ * To simplify life for callers, we turn these into
+ * DELETED and CREATED events
+ */
+ switch (iev) {
+ case IN_CREATE:
+ case IN_MOVED_TO:
+ qev = QFILE_MONITOR_EVENT_CREATED;
+ break;
+ case IN_MODIFY:
+ qev = QFILE_MONITOR_EVENT_MODIFIED;
+ break;
+ case IN_DELETE:
+ case IN_MOVED_FROM:
+ qev = QFILE_MONITOR_EVENT_DELETED;
+ break;
+ case IN_ATTRIB:
+ qev = QFILE_MONITOR_EVENT_ATTRIBUTES;
+ break;
+ case IN_IGNORED:
+ qev = QFILE_MONITOR_EVENT_IGNORED;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ trace_qemu_file_monitor_event(mon, dir->path, name, ev->mask, dir->id);
+ for (i = 0; i < dir->watches->len; i++) {
+ QFileMonitorWatch *watch = &g_array_index(dir->watches,
+ QFileMonitorWatch,
+ i);
+
+ if (watch->filename == NULL ||
+ (name && g_str_equal(watch->filename, name))) {
+ trace_qemu_file_monitor_dispatch(mon, dir->path, name,
+ qev, watch->cb,
+ watch->opaque, watch->id);
+ watch->cb(watch->id, qev, name, watch->opaque);
+ }
+ }
+ }
+
+ cleanup:
+ qemu_mutex_unlock(&mon->lock);
+}
+
+
+static void
+qemu_file_monitor_dir_free(void *data)
+{
+ QFileMonitorDir *dir = data;
+ gsize i;
+
+ for (i = 0; i < dir->watches->len; i++) {
+ QFileMonitorWatch *watch = &g_array_index(dir->watches,
+ QFileMonitorWatch, i);
+ g_free(watch->filename);
+ }
+ g_array_unref(dir->watches);
+ g_free(dir->path);
+ g_free(dir);
+}
+
+
+QFileMonitor *
+qemu_file_monitor_new(Error **errp)
+{
+ int fd;
+ QFileMonitor *mon;
+
+ fd = inotify_init1(IN_NONBLOCK);
+ if (fd < 0) {
+ error_setg_errno(errp, errno,
+ "Unable to initialize inotify");
+ return NULL;
+ }
+
+ mon = g_new0(QFileMonitor, 1);
+ qemu_mutex_init(&mon->lock);
+ mon->fd = fd;
+
+ mon->dirs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+ qemu_file_monitor_dir_free);
+ mon->idmap = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+ trace_qemu_file_monitor_new(mon, mon->fd);
+
+ return mon;
+}
+
+static gboolean
+qemu_file_monitor_free_idle(void *opaque)
+{
+ QFileMonitor *mon = opaque;
+
+ if (!mon) {
+ return G_SOURCE_REMOVE;
+ }
+
+ qemu_mutex_lock(&mon->lock);
+
+ g_hash_table_unref(mon->idmap);
+ g_hash_table_unref(mon->dirs);
+
+ qemu_mutex_unlock(&mon->lock);
+
+ qemu_mutex_destroy(&mon->lock);
+ g_free(mon);
+
+ return G_SOURCE_REMOVE;
+}
+
+void
+qemu_file_monitor_free(QFileMonitor *mon)
+{
+ if (!mon) {
+ return;
+ }
+
+ qemu_mutex_lock(&mon->lock);
+ if (mon->fd != -1) {
+ qemu_set_fd_handler(mon->fd, NULL, NULL, NULL);
+ close(mon->fd);
+ mon->fd = -1;
+ }
+ qemu_mutex_unlock(&mon->lock);
+
+ /*
+ * Can't free it yet, because another thread
+ * may be running event loop, so the inotify
+ * callback might be pending. Using an idle
+ * source ensures we'll only free after the
+ * pending callback is done
+ */
+ g_idle_add((GSourceFunc)qemu_file_monitor_free_idle, mon);
+}
+
+int
+qemu_file_monitor_add_watch(QFileMonitor *mon,
+ const char *dirpath,
+ const char *filename,
+ QFileMonitorHandler cb,
+ void *opaque,
+ Error **errp)
+{
+ QFileMonitorDir *dir;
+ QFileMonitorWatch watch;
+ int ret = -1;
+
+ qemu_mutex_lock(&mon->lock);
+ dir = g_hash_table_lookup(mon->dirs, dirpath);
+ if (!dir) {
+ int rv = inotify_add_watch(mon->fd, dirpath,
+ IN_CREATE | IN_DELETE | IN_MODIFY |
+ IN_MOVED_TO | IN_MOVED_FROM | IN_ATTRIB);
+
+ if (rv < 0) {
+ error_setg_errno(errp, errno, "Unable to watch '%s'", dirpath);
+ goto cleanup;
+ }
+
+ trace_qemu_file_monitor_enable_watch(mon, dirpath, rv);
+
+ dir = g_new0(QFileMonitorDir, 1);
+ dir->path = g_strdup(dirpath);
+ dir->id = rv;
+ dir->watches = g_array_new(FALSE, TRUE, sizeof(QFileMonitorWatch));
+
+ g_hash_table_insert(mon->dirs, dir->path, dir);
+ g_hash_table_insert(mon->idmap, GINT_TO_POINTER(rv), dir);
+
+ if (g_hash_table_size(mon->dirs) == 1) {
+ qemu_set_fd_handler(mon->fd, qemu_file_monitor_watch, NULL, mon);
+ }
+ }
+
+ watch.id = dir->nextid++;
+ watch.filename = g_strdup(filename);
+ watch.cb = cb;
+ watch.opaque = opaque;
+
+ g_array_append_val(dir->watches, watch);
+
+ trace_qemu_file_monitor_add_watch(mon, dirpath,
+ filename ? filename : "<none>",
+ cb, opaque, watch.id);
+
+ ret = watch.id;
+
+ cleanup:
+ qemu_mutex_unlock(&mon->lock);
+ return ret;
+}
+
+
+void qemu_file_monitor_remove_watch(QFileMonitor *mon,
+ const char *dirpath,
+ int id)
+{
+ QFileMonitorDir *dir;
+ gsize i;
+
+ qemu_mutex_lock(&mon->lock);
+
+ trace_qemu_file_monitor_remove_watch(mon, dirpath, id);
+
+ dir = g_hash_table_lookup(mon->dirs, dirpath);
+ if (!dir) {
+ goto cleanup;
+ }
+
+ for (i = 0; i < dir->watches->len; i++) {
+ QFileMonitorWatch *watch = &g_array_index(dir->watches,
+ QFileMonitorWatch, i);
+ if (watch->id == id) {
+ g_free(watch->filename);
+ g_array_remove_index(dir->watches, i);
+ break;
+ }
+ }
+
+ if (dir->watches->len == 0) {
+ inotify_rm_watch(mon->fd, dir->id);
+ trace_qemu_file_monitor_disable_watch(mon, dir->path, dir->id);
+
+ g_hash_table_remove(mon->idmap, GINT_TO_POINTER(dir->id));
+ g_hash_table_remove(mon->dirs, dir->path);
+
+ if (g_hash_table_size(mon->dirs) == 0) {
+ qemu_set_fd_handler(mon->fd, NULL, NULL, NULL);
+ }
+ }
+
+ cleanup:
+ qemu_mutex_unlock(&mon->lock);
+}
--- /dev/null
+/*
+ * QEMU file monitor stub impl
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/filemonitor.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+
+
+QFileMonitor *
+qemu_file_monitor_new(Error **errp)
+{
+ error_setg(errp, "File monitoring not available on this platform");
+ return NULL;
+}
+
+
+void
+qemu_file_monitor_free(QFileMonitor *mon G_GNUC_UNUSED)
+{
+}
+
+
+int
+qemu_file_monitor_add_watch(QFileMonitor *mon G_GNUC_UNUSED,
+ const char *dirpath G_GNUC_UNUSED,
+ const char *filename G_GNUC_UNUSED,
+ QFileMonitorHandler cb G_GNUC_UNUSED,
+ void *opaque G_GNUC_UNUSED,
+ Error **errp)
+{
+ error_setg(errp, "File monitoring not available on this platform");
+ return -1;
+}
+
+
+void
+qemu_file_monitor_remove_watch(QFileMonitor *mon G_GNUC_UNUSED,
+ const char *dirpath G_GNUC_UNUSED,
+ int id G_GNUC_UNUSED)
+{
+}
}
#endif
+static NotifierList main_loop_poll_notifiers =
+ NOTIFIER_LIST_INITIALIZER(main_loop_poll_notifiers);
+
+void main_loop_poll_add_notifier(Notifier *notify)
+{
+ notifier_list_add(&main_loop_poll_notifiers, notify);
+}
+
+void main_loop_poll_remove_notifier(Notifier *notify)
+{
+ notifier_remove(notify);
+}
+
void main_loop_wait(int nonblocking)
{
+ MainLoopPoll mlpoll = {
+ .state = MAIN_LOOP_POLL_FILL,
+ .timeout = UINT32_MAX,
+ .pollfds = gpollfds,
+ };
int ret;
- uint32_t timeout = UINT32_MAX;
int64_t timeout_ns;
if (nonblocking) {
- timeout = 0;
+ mlpoll.timeout = 0;
}
/* poll any events */
g_array_set_size(gpollfds, 0); /* reset for new iteration */
/* XXX: separate device handlers from system ones */
- slirp_pollfds_fill(gpollfds, &timeout);
+ notifier_list_notify(&main_loop_poll_notifiers, &mlpoll);
- if (timeout == UINT32_MAX) {
+ if (mlpoll.timeout == UINT32_MAX) {
timeout_ns = -1;
} else {
- timeout_ns = (uint64_t)timeout * (int64_t)(SCALE_MS);
+ timeout_ns = (uint64_t)mlpoll.timeout * (int64_t)(SCALE_MS);
}
timeout_ns = qemu_soonest_timeout(timeout_ns,
&main_loop_tlg));
ret = os_host_main_loop_wait(timeout_ns);
- slirp_pollfds_poll(gpollfds, (ret < 0));
+ mlpoll.state = ret < 0 ? MAIN_LOOP_POLL_ERR : MAIN_LOOP_POLL_OK;
+ notifier_list_notify(&main_loop_poll_notifiers, &mlpoll);
/* CPU thread can infinitely wait for event after
missing the warp */
#include <sys/statvfs.h>
/* See MySQL bug #7156 (http://bugs.mysql.com/bug.php?id=7156) for
discussion about Solaris header problems */
-extern int madvise(caddr_t, size_t, int);
+extern int madvise(char *, size_t, int);
#endif
#include "qemu-common.h"
buffer_move(const char *buf, size_t len, const char *from) "%s: %zd bytes from %s"
buffer_free(const char *buf, size_t len) "%s: capacity %zd"
+# util/filemonitor.c
+qemu_file_monitor_add_watch(void *mon, const char *dirpath, const char *filename, void *cb, void *opaque, int id) "File monitor %p add watch dir='%s' file='%s' cb=%p opaque=%p id=%u"
+qemu_file_monitor_remove_watch(void *mon, const char *dirpath, int id) "File monitor %p remove watch dir='%s' id=%u"
+qemu_file_monitor_new(void *mon, int fd) "File monitor %p created fd=%d"
+qemu_file_monitor_enable_watch(void *mon, const char *dirpath, int id) "File monitor %p enable watch dir='%s' id=%u"
+qemu_file_monitor_disable_watch(void *mon, const char *dirpath, int id) "Fle monitor %p disable watch dir='%s' id=%u"
+qemu_file_monitor_event(void *mon, const char *dirpath, const char *filename, int mask, unsigned int id) "File monitor %p event dir='%s' file='%s' mask=0x%x id=%u"
+qemu_file_monitor_dispatch(void *mon, const char *dirpath, const char *filename, int ev, void *cb, void *opaque, unsigned int id) "File monitor %p dispatch dir='%s' file='%s' ev=%d cb=%p opaque=%p id=%u"
+
# util/qemu-coroutine.c
qemu_aio_coroutine_enter(void *ctx, void *from, void *to, void *opaque) "ctx %p from %p to %p opaque %p"
qemu_coroutine_yield(void *from, void *to) "from %p to %p"
QEMUClockType rtc_clock;
int vga_interface_type = VGA_NONE;
static DisplayOptions dpy;
-int no_frame;
static int num_serial_hds;
static Chardev **serial_hds;
Chardev *parallel_hds[MAX_PARALLEL_PORTS];
-Chardev *virtcon_hds[MAX_VIRTIO_CONSOLES];
int win2k_install_hack = 0;
int singlestep = 0;
int smp_cpus;
static int has_defaults = 1;
static int default_serial = 1;
static int default_parallel = 1;
-static int default_virtcon = 1;
static int default_monitor = 1;
static int default_floppy = 1;
static int default_cdrom = 1;
{ .driver = "ide-drive", .flag = &default_cdrom },
{ .driver = "scsi-cd", .flag = &default_cdrom },
{ .driver = "scsi-hd", .flag = &default_cdrom },
- { .driver = "virtio-serial-pci", .flag = &default_virtcon },
- { .driver = "virtio-serial", .flag = &default_virtcon },
{ .driver = "VGA", .flag = &default_vga },
{ .driver = "isa-vga", .flag = &default_vga },
{ .driver = "cirrus-vga", .flag = &default_vga },
while (*opts) {
const char *nextopt;
- if (strstart(opts, ",frame=", &nextopt)) {
- g_printerr("The frame= sdl option is deprecated, and will be\n"
- "removed in a future release.\n");
- opts = nextopt;
- if (strstart(opts, "on", &nextopt)) {
- no_frame = 0;
- } else if (strstart(opts, "off", &nextopt)) {
- no_frame = 1;
- } else {
- goto invalid_sdl_args;
- }
- } else if (strstart(opts, ",alt_grab=", &nextopt)) {
+ if (strstart(opts, ",alt_grab=", &nextopt)) {
opts = nextopt;
if (strstart(opts, "on", &nextopt)) {
alt_grab = 1;
{
Error *local_err = NULL;
- if (!qemu_chr_new_from_opts(opts, &local_err)) {
+ if (!qemu_chr_new_from_opts(opts, NULL, &local_err)) {
if (local_err) {
error_propagate(errp, local_err);
return -1;
DEV_BT, /* -bt */
DEV_SERIAL, /* -serial */
DEV_PARALLEL, /* -parallel */
- DEV_VIRTCON, /* -virtioconsole */
DEV_DEBUGCON, /* -debugcon */
DEV_GDB, /* -gdb, -s */
DEV_SCLP, /* s390 sclp */
snprintf(label, sizeof(label), "serial%d", index);
serial_hds = g_renew(Chardev *, serial_hds, index + 1);
- serial_hds[index] = qemu_chr_new_mux_mon(label, devname);
+ serial_hds[index] = qemu_chr_new_mux_mon(label, devname, NULL);
if (!serial_hds[index]) {
error_report("could not connect serial device"
" to character backend '%s'", devname);
exit(1);
}
snprintf(label, sizeof(label), "parallel%d", index);
- parallel_hds[index] = qemu_chr_new_mux_mon(label, devname);
+ parallel_hds[index] = qemu_chr_new_mux_mon(label, devname, NULL);
if (!parallel_hds[index]) {
error_report("could not connect parallel device"
" to character backend '%s'", devname);
return 0;
}
-static int virtcon_parse(const char *devname)
-{
- QemuOptsList *device = qemu_find_opts("device");
- static int index = 0;
- char label[32];
- QemuOpts *bus_opts, *dev_opts;
-
- if (strcmp(devname, "none") == 0)
- return 0;
- if (index == MAX_VIRTIO_CONSOLES) {
- error_report("too many virtio consoles");
- exit(1);
- }
-
- bus_opts = qemu_opts_create(device, NULL, 0, &error_abort);
- qemu_opt_set(bus_opts, "driver", "virtio-serial", &error_abort);
-
- dev_opts = qemu_opts_create(device, NULL, 0, &error_abort);
- qemu_opt_set(dev_opts, "driver", "virtconsole", &error_abort);
-
- snprintf(label, sizeof(label), "virtcon%d", index);
- virtcon_hds[index] = qemu_chr_new_mux_mon(label, devname);
- if (!virtcon_hds[index]) {
- error_report("could not connect virtio console"
- " to character backend '%s'", devname);
- return -1;
- }
- qemu_opt_set(dev_opts, "chardev", label, &error_abort);
-
- index++;
- return 0;
-}
-
static int debugcon_parse(const char *devname)
{
QemuOpts *opts;
- if (!qemu_chr_new_mux_mon("debugcon", devname)) {
+ if (!qemu_chr_new_mux_mon("debugcon", devname, NULL)) {
error_report("invalid character backend '%s'", devname);
exit(1);
}
exit(1);
}
break;
- case QEMU_OPTION_virtiocon:
- warn_report("This option is deprecated, "
- "use '-device virtconsole' instead");
- add_device_config(DEV_VIRTCON, optarg);
- default_virtcon = 0;
- if (strncmp(optarg, "mon:", 4) == 0) {
- default_monitor = 0;
- }
- break;
case QEMU_OPTION_parallel:
add_device_config(DEV_PARALLEL, optarg);
default_parallel = 0;
dpy.has_full_screen = true;
dpy.full_screen = true;
break;
- case QEMU_OPTION_no_frame:
- g_printerr("The -no-frame switch is deprecated, and will be\n"
- "removed in a future release.\n");
- no_frame = 1;
- break;
case QEMU_OPTION_alt_grab:
alt_grab = 1;
break;
olist = qemu_find_opts("machine");
qemu_opts_parse_noisily(olist, "accel=kvm", false);
break;
- case QEMU_OPTION_enable_hax:
- warn_report("Option is deprecated, use '-accel hax' instead");
- olist = qemu_find_opts("machine");
- qemu_opts_parse_noisily(olist, "accel=hax", false);
- break;
case QEMU_OPTION_M:
case QEMU_OPTION_machine:
olist = qemu_find_opts("machine");
case QEMU_OPTION_old_param:
old_param = 1;
break;
- case QEMU_OPTION_clock:
- /* Clock options no longer exist. Keep this option for
- * backward compatibility.
- */
- warn_report("This option is ignored and will be removed soon");
- break;
case QEMU_OPTION_rtc:
opts = qemu_opts_parse_noisily(qemu_find_opts("rtc"), optarg,
false);
if (!has_defaults || machine_class->no_parallel) {
default_parallel = 0;
}
- if (!has_defaults || !machine_class->use_virtcon) {
- default_virtcon = 0;
- }
if (!has_defaults || machine_class->no_floppy) {
default_floppy = 0;
}
* usage, -nographic is just a no-op in this case.
*/
if (nographic
- && (default_parallel || default_serial
- || default_monitor || default_virtcon)) {
+ && (default_parallel || default_serial || default_monitor)) {
error_report("-nographic cannot be used with -daemonize");
exit(1);
}
add_device_config(DEV_PARALLEL, "null");
if (default_serial && default_monitor) {
add_device_config(DEV_SERIAL, "mon:stdio");
- } else if (default_virtcon && default_monitor) {
- add_device_config(DEV_VIRTCON, "mon:stdio");
} else {
if (default_serial)
add_device_config(DEV_SERIAL, "stdio");
- if (default_virtcon)
- add_device_config(DEV_VIRTCON, "stdio");
if (default_monitor)
monitor_parse("stdio", "readline", false);
}
add_device_config(DEV_PARALLEL, "vc:80Cx24C");
if (default_monitor)
monitor_parse("vc:80Cx24C", "readline", false);
- if (default_virtcon)
- add_device_config(DEV_VIRTCON, "vc:80Cx24C");
}
#if defined(CONFIG_VNC)
dpy.type = DISPLAY_TYPE_NONE;
}
- if ((no_frame || alt_grab || ctrl_grab) && dpy.type != DISPLAY_TYPE_SDL) {
- error_report("-no-frame, -alt-grab and -ctrl-grab are only valid "
+ if ((alt_grab || ctrl_grab) && dpy.type != DISPLAY_TYPE_SDL) {
+ error_report("-alt-grab and -ctrl-grab are only valid "
"for SDL, ignoring option");
}
if (dpy.has_window_close &&
exit(1);
if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0)
exit(1);
- if (foreach_device_config(DEV_VIRTCON, virtcon_parse) < 0)
- exit(1);
if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
exit(1);