aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS25
-rw-r--r--Makefile66
-rw-r--r--Makefile.target18
-rw-r--r--block.c50
-rw-r--r--block/block-backend.c31
-rw-r--r--block/io.c25
-rw-r--r--block/raw-posix.c44
-rw-r--r--block/raw-win32.c56
-rw-r--r--blockdev.c112
-rw-r--r--bsd-user/main.c10
-rwxr-xr-xconfigure19
-rw-r--r--cpus.c4
-rw-r--r--default-configs/arm-softmmu.mak2
-rw-r--r--docs/generic-loader.txt84
-rw-r--r--hw/Makefile.objs1
-rw-r--r--hw/adc/Makefile.objs1
-rw-r--r--hw/adc/stm32f2xx_adc.c306
-rw-r--r--hw/arm/integratorcp.c35
-rw-r--r--hw/arm/mainstone.c5
-rw-r--r--hw/arm/stm32f205_soc.c92
-rw-r--r--hw/arm/virt-acpi-build.c12
-rw-r--r--hw/arm/virt.c66
-rw-r--r--hw/core/Makefile.objs3
-rw-r--r--hw/core/generic-loader.c211
-rw-r--r--hw/core/or-irq.c107
-rw-r--r--hw/dma/rc4030.c81
-rw-r--r--hw/i386/xen/xen_platform.c2
-rw-r--r--hw/ide/piix.c4
-rw-r--r--hw/input/tsc2005.c190
-rw-r--r--hw/input/tsc210x.c227
-rw-r--r--hw/intc/Makefile.objs2
-rw-r--r--hw/intc/arm_gic_kvm.c12
-rw-r--r--hw/intc/arm_gicv3_its_common.c148
-rw-r--r--hw/intc/arm_gicv3_its_kvm.c121
-rw-r--r--hw/intc/arm_gicv3_kvm.c13
-rw-r--r--hw/net/cadence_gem.c22
-rw-r--r--hw/ppc/spapr.c104
-rw-r--r--hw/ppc/spapr_cpu_core.c8
-rw-r--r--hw/s390x/css.c12
-rw-r--r--hw/s390x/s390-pci-bus.c48
-rw-r--r--hw/s390x/s390-pci-bus.h4
-rw-r--r--hw/s390x/s390-pci-inst.c6
-rw-r--r--hw/scsi/spapr_vscsi.c2
-rw-r--r--hw/scsi/trace-events2
-rw-r--r--hw/smbios/smbios.c2
-rw-r--r--hw/ssi/Makefile.objs1
-rw-r--r--hw/ssi/stm32f2xx_spi.c225
-rw-r--r--hw/timer/stm32f2xx_timer.c9
-rw-r--r--hw/xenpv/xen_domainbuild.c2
-rw-r--r--include/block/block.h2
-rw-r--r--include/hw/acpi/acpi-defs.h13
-rw-r--r--include/hw/adc/stm32f2xx_adc.h87
-rw-r--r--include/hw/arm/stm32f205_soc.h9
-rw-r--r--include/hw/core/generic-loader.h46
-rw-r--r--include/hw/i386/pc.h15
-rw-r--r--include/hw/intc/arm_gicv3_its_common.h78
-rw-r--r--include/hw/or-irq.h44
-rw-r--r--include/hw/ppc/spapr.h1
-rw-r--r--include/hw/ssi/stm32f2xx_spi.h72
-rw-r--r--include/qemu/coroutine_int.h2
-rw-r--r--include/sysemu/block-backend.h3
-rw-r--r--include/sysemu/kvm.h9
-rw-r--r--include/sysemu/os-posix.h27
-rw-r--r--kvm-all.c9
-rw-r--r--kvm-stub.c1
-rw-r--r--pc-bios/optionrom/Makefile8
-rw-r--r--pc-bios/s390-ccw.imgbin26440 -> 26392 bytes
-rw-r--r--pc-bios/s390-ccw/Makefile4
-rw-r--r--pc-bios/s390-ccw/virtio.c3
-rw-r--r--pc-bios/spapr-rtas/Makefile4
-rw-r--r--po/Makefile6
-rw-r--r--qapi/block-core.json31
-rw-r--r--qga/vss-win32/Makefile.objs6
-rw-r--r--rules.mak32
-rw-r--r--target-arm/kvm_arm.h35
-rw-r--r--target-arm/machine.c15
-rw-r--r--target-arm/translate-a64.c2
-rw-r--r--target-arm/translate.c7
-rw-r--r--target-i386/cpu.c25
-rw-r--r--target-i386/monitor.c3
-rw-r--r--target-ppc/helper.h8
-rw-r--r--target-ppc/int_helper.c61
-rw-r--r--target-ppc/kvm.c42
-rw-r--r--target-ppc/kvm_ppc.h6
-rw-r--r--target-ppc/translate.c4
-rw-r--r--target-ppc/translate/vmx-impl.inc.c49
-rw-r--r--target-ppc/translate/vmx-ops.inc.c20
-rw-r--r--target-ppc/translate/vsx-impl.inc.c234
-rw-r--r--target-ppc/translate/vsx-ops.inc.c7
-rw-r--r--target-s390x/Makefile.objs4
-rw-r--r--target-s390x/kvm.c13
-rw-r--r--tests/Makefile.include36
-rw-r--r--tests/boot-sector.c9
-rw-r--r--tests/docker/Makefile.include8
-rwxr-xr-xtests/docker/common.rc3
-rwxr-xr-xtests/docker/test-clang2
-rwxr-xr-xtests/docker/test-full2
-rwxr-xr-xtests/docker/test-mingw2
-rwxr-xr-xtests/docker/test-quick2
-rw-r--r--tests/e1000e-test.c2
-rw-r--r--tests/i440fx-test.c2
-rw-r--r--tests/ide-test.c2
-rw-r--r--tests/ivshmem-test.c2
-rw-r--r--tests/libqos/ahci.c2
-rw-r--r--tests/libqos/libqos-pc.c8
-rw-r--r--tests/libqos/libqos-spapr.c8
-rw-r--r--tests/libqos/libqos.c32
-rw-r--r--tests/libqos/libqos.h11
-rw-r--r--tests/libqos/pci-pc.c24
-rw-r--r--tests/libqos/pci-pc.h3
-rw-r--r--tests/libqos/pci-spapr.c288
-rw-r--r--tests/libqos/pci-spapr.h17
-rw-r--r--tests/libqos/pci.c22
-rw-r--r--tests/libqos/rtas.c45
-rw-r--r--tests/libqos/rtas.h4
-rw-r--r--tests/pxe-test.c22
-rw-r--r--tests/q35-test.c2
-rwxr-xr-xtests/qemu-iotests/0874
-rw-r--r--tests/qemu-iotests/087.out2
-rw-r--r--tests/rtas-test.c2
-rw-r--r--tests/rtl8139-test.c2
-rw-r--r--tests/tco-test.c2
-rw-r--r--tests/usb-hcd-ehci-test.c2
-rw-r--r--tests/usb-hcd-uhci-test.c24
-rw-r--r--tests/vhost-user-test.c4
-rw-r--r--tests/virtio-9p-test.c2
-rw-r--r--tests/virtio-blk-test.c2
-rw-r--r--tests/virtio-net-test.c2
-rw-r--r--tests/virtio-scsi-test.c2
-rw-r--r--trace/Makefile.objs24
-rw-r--r--util/coroutine-sigaltstack.c25
-rw-r--r--util/coroutine-ucontext.c11
-rw-r--r--util/coroutine-win32.c2
-rw-r--r--util/oslib-posix.c77
134 files changed, 3539 insertions, 889 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 9b7e846ec2..9bca506365 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -145,7 +145,7 @@ F: disas/microblaze.c
MIPS
M: Aurelien Jarno <aurelien@aurel32.net>
-M: Leon Alrae <leon.alrae@imgtec.com>
+M: Yongbok Kim <yongbok.kim@imgtec.com>
S: Maintained
F: target-mips/
F: hw/mips/
@@ -479,6 +479,21 @@ S: Maintained
F: hw/arm/virt-acpi-build.c
F: include/hw/arm/virt-acpi-build.h
+STM32F205
+M: Alistair Francis <alistair@alistair23.me>
+S: Maintained
+F: hw/arm/stm32f205_soc.c
+F: hw/misc/stm32f2xx_syscfg.c
+F: hw/char/stm32f2xx_usart.c
+F: hw/timer/stm32f2xx_timer.c
+F: hw/adc/*
+F: hw/ssi/stm32f2xx_spi.c
+
+Netduino 2
+M: Alistair Francis <alistair@alistair23.me>
+S: Maintained
+F: hw/arm/netduino2.c
+
CRIS Machines
-------------
Axis Dev88
@@ -605,6 +620,7 @@ S: Maintained
F: hw/ppc/mac_oldworld.c
F: hw/pci-host/grackle.c
F: hw/misc/macio/
+F: hw/intc/heathrow_pic.c
PReP
L: qemu-devel@nongnu.org
@@ -613,6 +629,7 @@ S: Odd Fixes
F: hw/ppc/prep.c
F: hw/pci-host/prep.[hc]
F: hw/isa/pc87312.[hc]
+F: pc-bios/ppc_rom.bin
sPAPR
M: David Gibson <david@gibson.dropbear.id.au>
@@ -1014,6 +1031,12 @@ M: Dmitry Fleytman <dmitry@daynix.com>
S: Maintained
F: hw/net/e1000e*
+Generic Loader
+M: Alistair Francis <alistair.francis@xilinx.com>
+S: Maintained
+F: hw/core/generic-loader.c
+F: include/hw/core/generic-loader.h
+
Subsystems
----------
Audio
diff --git a/Makefile b/Makefile
index f148077f8f..5f6acaed3b 100644
--- a/Makefile
+++ b/Makefile
@@ -107,20 +107,20 @@ SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %-config-devices.mak.d, $(TARGET_DIRS))
ifeq ($(SUBDIR_DEVICES_MAK),)
config-all-devices.mak:
- $(call quiet-command,echo '# no devices' > $@," GEN $@")
+ $(call quiet-command,echo '# no devices' > $@,"GEN","$@")
else
config-all-devices.mak: $(SUBDIR_DEVICES_MAK)
$(call quiet-command, sed -n \
's|^\([^=]*\)=\(.*\)$$|\1:=$$(findstring y,$$(\1)\2)|p' \
$(SUBDIR_DEVICES_MAK) | sort -u > $@, \
- " GEN $@")
+ "GEN","$@")
endif
-include $(SUBDIR_DEVICES_MAK_DEP)
%/config-devices.mak: default-configs/%.mak $(SRC_PATH)/scripts/make_device_config.sh
$(call quiet-command, \
- $(SHELL) $(SRC_PATH)/scripts/make_device_config.sh $< $*-config-devices.mak.d $@ > $@.tmp, " GEN $@.tmp")
+ $(SHELL) $(SRC_PATH)/scripts/make_device_config.sh $< $*-config-devices.mak.d $@ > $@.tmp,"GEN","$@.tmp")
$(call quiet-command, if test -f $@; then \
if cmp -s $@.old $@; then \
mv $@.tmp $@; \
@@ -137,7 +137,7 @@ endif
else \
mv $@.tmp $@; \
cp -p $@ $@.old; \
- fi, " GEN $@");
+ fi,"GEN","$@");
defconfig:
rm -f config-all-devices.mak $(SUBDIR_DEVICES_MAK)
@@ -191,7 +191,7 @@ qemu-version.h: FORCE
config-host.h: config-host.h-timestamp
config-host.h-timestamp: config-host.mak
qemu-options.def: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
- $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$@")
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
SOFTMMU_SUBDIR_RULES=$(filter %-softmmu,$(SUBDIR_RULES))
@@ -235,9 +235,9 @@ ALL_SUBDIRS=$(TARGET_DIRS) $(patsubst %,pc-bios/%, $(ROMS))
recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
$(BUILD_DIR)/version.o: $(SRC_PATH)/version.rc config-host.h | $(BUILD_DIR)/version.lo
- $(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<," RC version.o")
+ $(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<,"RC","version.o")
$(BUILD_DIR)/version.lo: $(SRC_PATH)/version.rc config-host.h
- $(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<," RC version.lo")
+ $(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<,"RC","version.lo")
Makefile: $(version-obj-y) $(version-lobj-y)
@@ -261,7 +261,7 @@ fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/9p-marshal
fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
- $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$@")
qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
qemu-ga$(EXESUF): QEMU_CFLAGS += -I qga/qapi-generated
@@ -274,17 +274,17 @@ qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h :\
$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
- " GEN $@")
+ "GEN","$@")
qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h :\
$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
- " GEN $@")
+ "GEN","$@")
qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c :\
$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
- " GEN $@")
+ "GEN","$@")
qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
$(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
@@ -296,27 +296,27 @@ qapi-types.c qapi-types.h :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
$(gen-out-type) -o "." -b $<, \
- " GEN $@")
+ "GEN","$@")
qapi-visit.c qapi-visit.h :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
$(gen-out-type) -o "." -b $<, \
- " GEN $@")
+ "GEN","$@")
qapi-event.c qapi-event.h :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
$(gen-out-type) -o "." $<, \
- " GEN $@")
+ "GEN","$@")
qmp-commands.h qmp-marshal.c :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o "." $<, \
- " GEN $@")
+ "GEN","$@")
qmp-introspect.h qmp-introspect.c :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-introspect.py \
$(gen-out-type) -o "." $<, \
- " GEN $@")
+ "GEN","$@")
QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
@@ -335,7 +335,7 @@ $(QEMU_GA_MSI): config-host.mak
$(QEMU_GA_MSI): $(SRC_PATH)/qga/installer/qemu-ga.wxs
$(call quiet-command,QEMU_GA_VERSION="$(QEMU_GA_VERSION)" QEMU_GA_MANUFACTURER="$(QEMU_GA_MANUFACTURER)" QEMU_GA_DISTRO="$(QEMU_GA_DISTRO)" BUILD_DIR="$(BUILD_DIR)" \
- wixl -o $@ $(QEMU_GA_MSI_ARCH) $(QEMU_GA_MSI_WITH_VSS) $(QEMU_GA_MSI_MINGW_DLL_PATH) $<, " WIXL $@")
+ wixl -o $@ $(QEMU_GA_MSI_ARCH) $(QEMU_GA_MSI_WITH_VSS) $(QEMU_GA_MSI_MINGW_DLL_PATH) $<,"WIXL","$@")
else
msi:
@echo "MSI build not configured or dependency resolution failed (reconfigure with --enable-guest-agent-msi option)"
@@ -354,7 +354,7 @@ ivshmem-server$(EXESUF): $(ivshmem-server-obj-y) libqemuutil.a libqemustub.a
module_block.h: $(SRC_PATH)/scripts/modules/module_block.py config-host.mak
$(call quiet-command,$(PYTHON) $< $@ \
$(addprefix $(SRC_PATH)/,$(patsubst %.mo,%.c,$(block-obj-m))), \
- " GEN $@")
+ "GEN","$@")
clean:
# avoid old build problems by removing potentially incorrect old files
@@ -520,13 +520,13 @@ ui/shader/%-vert.h: $(SRC_PATH)/ui/shader/%.vert $(SRC_PATH)/scripts/shaderinclu
@mkdir -p $(dir $@)
$(call quiet-command,\
perl $(SRC_PATH)/scripts/shaderinclude.pl $< > $@,\
- " VERT $@")
+ "VERT","$@")
ui/shader/%-frag.h: $(SRC_PATH)/ui/shader/%.frag $(SRC_PATH)/scripts/shaderinclude.pl
@mkdir -p $(dir $@)
$(call quiet-command,\
perl $(SRC_PATH)/scripts/shaderinclude.pl $< > $@,\
- " FRAG $@")
+ "FRAG","$@")
ui/console-gl.o: $(SRC_PATH)/ui/console-gl.c \
ui/shader/texture-blit-vert.h ui/shader/texture-blit-frag.h
@@ -536,60 +536,60 @@ MAKEINFO=makeinfo
MAKEINFOFLAGS=--no-headers --no-split --number-sections
TEXIFLAG=$(if $(V),,--quiet)
%.dvi: %.texi
- $(call quiet-command,texi2dvi $(TEXIFLAG) -I . $<," GEN $@")
+ $(call quiet-command,texi2dvi $(TEXIFLAG) -I . $<,"GEN","$@")
%.html: %.texi
$(call quiet-command,LC_ALL=C $(MAKEINFO) $(MAKEINFOFLAGS) --html $< -o $@, \
- " GEN $@")
+ "GEN","$@")
%.info: %.texi
- $(call quiet-command,$(MAKEINFO) $< -o $@," GEN $@")
+ $(call quiet-command,$(MAKEINFO) $< -o $@,"GEN","$@")
%.pdf: %.texi
- $(call quiet-command,texi2pdf $(TEXIFLAG) -I . $<," GEN $@")
+ $(call quiet-command,texi2pdf $(TEXIFLAG) -I . $<,"GEN","$@")
qemu-options.texi: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
- $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@")
qemu-monitor.texi: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
- $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@")
qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
- $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@")
qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
- $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@")
qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi qemu-monitor-info.texi
$(call quiet-command, \
perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu.pod && \
$(POD2MAN) --section=1 --center=" " --release=" " qemu.pod > $@, \
- " GEN $@")
+ "GEN","$@")
qemu.1: qemu-option-trace.texi
qemu-img.1: qemu-img.texi qemu-option-trace.texi qemu-img-cmds.texi
$(call quiet-command, \
perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-img.pod && \
$(POD2MAN) --section=1 --center=" " --release=" " qemu-img.pod > $@, \
- " GEN $@")
+ "GEN","$@")
fsdev/virtfs-proxy-helper.1: fsdev/virtfs-proxy-helper.texi
$(call quiet-command, \
perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< fsdev/virtfs-proxy-helper.pod && \
$(POD2MAN) --section=1 --center=" " --release=" " fsdev/virtfs-proxy-helper.pod > $@, \
- " GEN $@")
+ "GEN","$@")
qemu-nbd.8: qemu-nbd.texi qemu-option-trace.texi
$(call quiet-command, \
perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-nbd.pod && \
$(POD2MAN) --section=8 --center=" " --release=" " qemu-nbd.pod > $@, \
- " GEN $@")
+ "GEN","$@")
qemu-ga.8: qemu-ga.texi
$(call quiet-command, \
perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-ga.pod && \
$(POD2MAN) --section=8 --center=" " --release=" " qemu-ga.pod > $@, \
- " GEN $@")
+ "GEN","$@")
dvi: qemu-doc.dvi
html: qemu-doc.html
diff --git a/Makefile.target b/Makefile.target
index 19cc49c0d7..9968871d6e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -26,7 +26,7 @@ ifneq (,$(findstring -mwindows,$(libs_softmmu)))
# Terminate program name with a 'w' because the linker builds a windows executable.
QEMU_PROGW=qemu-system-$(TARGET_NAME)w$(EXESUF)
$(QEMU_PROG): $(QEMU_PROGW)
- $(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG)," GEN $(TARGET_DIR)$(QEMU_PROG)")
+ $(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG),"GEN","$(TARGET_DIR)$(QEMU_PROG)")
QEMU_PROG_BUILD = $(QEMU_PROGW)
else
QEMU_PROG_BUILD = $(QEMU_PROG)
@@ -55,7 +55,7 @@ $(QEMU_PROG).stp-installed: $(BUILD_DIR)/trace-events-all
--binary=$(bindir)/$(QEMU_PROG) \
--target-name=$(TARGET_NAME) \
--target-type=$(TARGET_TYPE) \
- < $< > $@," GEN $(TARGET_DIR)$(QEMU_PROG).stp-installed")
+ < $< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG).stp-installed")
$(QEMU_PROG).stp: $(BUILD_DIR)/trace-events-all
$(call quiet-command,$(TRACETOOL) \
@@ -64,14 +64,14 @@ $(QEMU_PROG).stp: $(BUILD_DIR)/trace-events-all
--binary=$(realpath .)/$(QEMU_PROG) \
--target-name=$(TARGET_NAME) \
--target-type=$(TARGET_TYPE) \
- < $< > $@," GEN $(TARGET_DIR)$(QEMU_PROG).stp")
+ < $< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG).stp")
$(QEMU_PROG)-simpletrace.stp: $(BUILD_DIR)/trace-events-all
$(call quiet-command,$(TRACETOOL) \
--format=simpletrace-stap \
--backends=$(TRACE_BACKENDS) \
--probe-prefix=qemu.$(TARGET_TYPE).$(TARGET_NAME) \
- < $< > $@," GEN $(TARGET_DIR)$(QEMU_PROG)-simpletrace.stp")
+ < $< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG)-simpletrace.stp")
else
stap:
@@ -196,18 +196,18 @@ $(QEMU_PROG_BUILD): config-devices.mak
$(QEMU_PROG_BUILD): $(all-obj-y) ../libqemuutil.a ../libqemustub.a
$(call LINK, $(filter-out %.mak, $^))
ifdef CONFIG_DARWIN
- $(call quiet-command,Rez -append $(SRC_PATH)/pc-bios/qemu.rsrc -o $@," REZ $(TARGET_DIR)$@")
- $(call quiet-command,SetFile -a C $@," SETFILE $(TARGET_DIR)$@")
+ $(call quiet-command,Rez -append $(SRC_PATH)/pc-bios/qemu.rsrc -o $@,"REZ","$(TARGET_DIR)$@")
+ $(call quiet-command,SetFile -a C $@,"SETFILE","$(TARGET_DIR)$@")
endif
gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
- $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@")
+ $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES),"GEN","$(TARGET_DIR)$@")
hmp-commands.h: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
- $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$(TARGET_DIR)$@")
hmp-commands-info.h: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
- $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$(TARGET_DIR)$@")
clean: clean-target
rm -f *.a *~ $(PROGS)
diff --git a/block.c b/block.c
index 493ecf3137..bb1f1ec957 100644
--- a/block.c
+++ b/block.c
@@ -42,6 +42,7 @@
#include "qapi-event.h"
#include "qemu/cutils.h"
#include "qemu/id.h"
+#include "qapi/util.h"
#ifdef CONFIG_BSD
#include <sys/ioctl.h>
@@ -764,7 +765,7 @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
/* Our block drivers take care to send flushes and respect unmap policy,
* so we can default to enable both on lower layers regardless of the
* corresponding parent options. */
- flags |= BDRV_O_UNMAP;
+ qdict_set_default_str(child_options, BDRV_OPT_DISCARD, "unmap");
/* Clear flags that only apply to the top layer */
flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ |
@@ -954,6 +955,16 @@ static QemuOptsList bdrv_runtime_opts = {
.type = QEMU_OPT_BOOL,
.help = "Node is opened in read-only mode",
},
+ {
+ .name = "detect-zeroes",
+ .type = QEMU_OPT_STRING,
+ .help = "try to optimize zero writes (off, on, unmap)",
+ },
+ {
+ .name = "discard",
+ .type = QEMU_OPT_STRING,
+ .help = "discard operation (ignore/off, unmap/on)",
+ },
{ /* end of list */ }
},
};
@@ -970,6 +981,8 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
const char *filename;
const char *driver_name = NULL;
const char *node_name = NULL;
+ const char *discard;
+ const char *detect_zeroes;
QemuOpts *opts;
BlockDriver *drv;
Error *local_err = NULL;
@@ -1038,6 +1051,41 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
}
}
+ discard = qemu_opt_get(opts, "discard");
+ if (discard != NULL) {
+ if (bdrv_parse_discard_flags(discard, &bs->open_flags) != 0) {
+ error_setg(errp, "Invalid discard option");
+ ret = -EINVAL;
+ goto fail_opts;
+ }
+ }
+
+ detect_zeroes = qemu_opt_get(opts, "detect-zeroes");
+ if (detect_zeroes) {
+ BlockdevDetectZeroesOptions value =
+ qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
+ detect_zeroes,
+ BLOCKDEV_DETECT_ZEROES_OPTIONS__MAX,
+ BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
+ &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ goto fail_opts;
+ }
+
+ if (value == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
+ !(bs->open_flags & BDRV_O_UNMAP))
+ {
+ error_setg(errp, "setting detect-zeroes to unmap is not allowed "
+ "without setting discard operation to unmap");
+ ret = -EINVAL;
+ goto fail_opts;
+ }
+
+ bs->detect_zeroes = value;
+ }
+
if (filename != NULL) {
pstrcpy(bs->filename, sizeof(bs->filename), filename);
} else {
diff --git a/block/block-backend.c b/block/block-backend.c
index 0bd19abdfb..639294b8e6 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1592,13 +1592,12 @@ void blk_update_root_state(BlockBackend *blk)
}
/*
- * Applies the information in the root state to the given BlockDriverState. This
- * does not include the flags which have to be specified for bdrv_open(), use
- * blk_get_open_flags_from_root_state() to inquire them.
+ * Returns the detect-zeroes setting to be used for bdrv_open() of a
+ * BlockDriverState which is supposed to inherit the root state.
*/
-void blk_apply_root_state(BlockBackend *blk, BlockDriverState *bs)
+bool blk_get_detect_zeroes_from_root_state(BlockBackend *blk)
{
- bs->detect_zeroes = blk->root_state.detect_zeroes;
+ return blk->root_state.detect_zeroes;
}
/*
@@ -1640,28 +1639,6 @@ int blk_commit_all(void)
return 0;
}
-int blk_flush_all(void)
-{
- BlockBackend *blk = NULL;
- int result = 0;
-
- while ((blk = blk_all_next(blk)) != NULL) {
- AioContext *aio_context = blk_get_aio_context(blk);
- int ret;
-
- aio_context_acquire(aio_context);
- if (blk_is_inserted(blk)) {
- ret = blk_flush(blk);
- if (ret < 0 && !result) {
- result = ret;
- }
- }
- aio_context_release(aio_context);
- }
-
- return result;
-}
-
/* throttling disk I/O limits */
void blk_set_io_limits(BlockBackend *blk, ThrottleConfig *cfg)
diff --git a/block/io.c b/block/io.c
index fdf70807b0..57a2eeb512 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1619,6 +1619,31 @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
BDRV_REQ_ZERO_WRITE | flags);
}
+/*
+ * Flush ALL BDSes regardless of if they are reachable via a BlkBackend or not.
+ */
+int bdrv_flush_all(void)
+{
+ BdrvNextIterator it;
+ BlockDriverState *bs = NULL;
+ int result = 0;
+
+ for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
+ AioContext *aio_context = bdrv_get_aio_context(bs);
+ int ret;
+
+ aio_context_acquire(aio_context);
+ ret = bdrv_flush(bs);
+ if (ret < 0 && !result) {
+ result = ret;
+ }
+ aio_context_release(aio_context);
+ }
+
+ return result;
+}
+
+
typedef struct BdrvCoGetBlockStatusData {
BlockDriverState *bs;
BlockDriverState *base;
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 6ed7547392..166e9d1ad5 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -143,6 +143,7 @@ typedef struct BDRVRawState {
bool has_discard:1;
bool has_write_zeroes:1;
bool discard_zeroes:1;
+ bool use_linux_aio:1;
bool has_fallocate;
bool needs_alignment;
} BDRVRawState;
@@ -367,18 +368,6 @@ static void raw_parse_flags(int bdrv_flags, int *open_flags)
}
}
-#ifdef CONFIG_LINUX_AIO
-static bool raw_use_aio(int bdrv_flags)
-{
- /*
- * Currently Linux do AIO only for files opened with O_DIRECT
- * specified so check NOCACHE flag too
- */
- return (bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
- (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO);
-}
-#endif
-
static void raw_parse_filename(const char *filename, QDict *options,
Error **errp)
{
@@ -399,6 +388,11 @@ static QemuOptsList raw_runtime_opts = {
.type = QEMU_OPT_STRING,
.help = "File name of the image",
},
+ {
+ .name = "aio",
+ .type = QEMU_OPT_STRING,
+ .help = "host AIO implementation (threads, native)",
+ },
{ /* end of list */ }
},
};
@@ -410,6 +404,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
QemuOpts *opts;
Error *local_err = NULL;
const char *filename = NULL;
+ BlockdevAioOptions aio, aio_default;
int fd, ret;
struct stat st;
@@ -429,6 +424,18 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
goto fail;
}
+ aio_default = (bdrv_flags & BDRV_O_NATIVE_AIO)
+ ? BLOCKDEV_AIO_OPTIONS_NATIVE
+ : BLOCKDEV_AIO_OPTIONS_THREADS;
+ aio = qapi_enum_parse(BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"),
+ BLOCKDEV_AIO_OPTIONS__MAX, aio_default, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ goto fail;
+ }
+ s->use_linux_aio = (aio == BLOCKDEV_AIO_OPTIONS_NATIVE);
+
s->open_flags = open_flags;
raw_parse_flags(bdrv_flags, &s->open_flags);
@@ -444,14 +451,15 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
s->fd = fd;
#ifdef CONFIG_LINUX_AIO
- if (!raw_use_aio(bdrv_flags) && (bdrv_flags & BDRV_O_NATIVE_AIO)) {
+ /* Currently Linux does AIO only for files opened with O_DIRECT */
+ if (s->use_linux_aio && !(s->open_flags & O_DIRECT)) {
error_setg(errp, "aio=native was specified, but it requires "
"cache.direct=on, which was not specified.");
ret = -EINVAL;
goto fail;
}
#else
- if (bdrv_flags & BDRV_O_NATIVE_AIO) {
+ if (s->use_linux_aio) {
error_setg(errp, "aio=native was specified, but is not supported "
"in this build.");
ret = -EINVAL;
@@ -1256,7 +1264,7 @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
if (!bdrv_qiov_is_aligned(bs, qiov)) {
type |= QEMU_AIO_MISALIGNED;
#ifdef CONFIG_LINUX_AIO
- } else if (bs->open_flags & BDRV_O_NATIVE_AIO) {
+ } else if (s->use_linux_aio) {
LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
assert(qiov->size == bytes);
return laio_co_submit(bs, aio, s->fd, offset, qiov, type);
@@ -1285,7 +1293,8 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, uint64_t offset,
static void raw_aio_plug(BlockDriverState *bs)
{
#ifdef CONFIG_LINUX_AIO
- if (bs->open_flags & BDRV_O_NATIVE_AIO) {
+ BDRVRawState *s = bs->opaque;
+ if (s->use_linux_aio) {
LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
laio_io_plug(bs, aio);
}
@@ -1295,7 +1304,8 @@ static void raw_aio_plug(BlockDriverState *bs)
static void raw_aio_unplug(BlockDriverState *bs)
{
#ifdef CONFIG_LINUX_AIO
- if (bs->open_flags & BDRV_O_NATIVE_AIO) {
+ BDRVRawState *s = bs->opaque;
+ if (s->use_linux_aio) {
LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
laio_io_unplug(bs, aio);
}
diff --git a/block/raw-win32.c b/block/raw-win32.c
index 56f45fea9e..734bb105bd 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -32,6 +32,7 @@
#include "block/thread-pool.h"
#include "qemu/iov.h"
#include "qapi/qmp/qstring.h"
+#include "qapi/util.h"
#include <windows.h>
#include <winioctl.h>
@@ -252,7 +253,8 @@ static void raw_probe_alignment(BlockDriverState *bs, Error **errp)
}
}
-static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped)
+static void raw_parse_flags(int flags, bool use_aio, int *access_flags,
+ DWORD *overlapped)
{
assert(access_flags != NULL);
assert(overlapped != NULL);
@@ -264,7 +266,7 @@ static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped)
}
*overlapped = FILE_ATTRIBUTE_NORMAL;
- if (flags & BDRV_O_NATIVE_AIO) {
+ if (use_aio) {
*overlapped |= FILE_FLAG_OVERLAPPED;
}
if (flags & BDRV_O_NOCACHE) {
@@ -292,10 +294,35 @@ static QemuOptsList raw_runtime_opts = {
.type = QEMU_OPT_STRING,
.help = "File name of the image",
},
+ {
+ .name = "aio",
+ .type = QEMU_OPT_STRING,
+ .help = "host AIO implementation (threads, native)",
+ },
{ /* end of list */ }
},
};
+static bool get_aio_option(QemuOpts *opts, int flags, Error **errp)
+{
+ BlockdevAioOptions aio, aio_default;
+
+ aio_default = (flags & BDRV_O_NATIVE_AIO) ? BLOCKDEV_AIO_OPTIONS_NATIVE
+ : BLOCKDEV_AIO_OPTIONS_THREADS;
+ aio = qapi_enum_parse(BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"),
+ BLOCKDEV_AIO_OPTIONS__MAX, aio_default, errp);
+
+ switch (aio) {
+ case BLOCKDEV_AIO_OPTIONS_NATIVE:
+ return true;
+ case BLOCKDEV_AIO_OPTIONS_THREADS:
+ return false;
+ default:
+ error_setg(errp, "Invalid AIO option");
+ }
+ return false;
+}
+
static int raw_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
@@ -305,6 +332,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
QemuOpts *opts;
Error *local_err = NULL;
const char *filename;
+ bool use_aio;
int ret;
s->type = FTYPE_FILE;
@@ -319,7 +347,14 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
filename = qemu_opt_get(opts, "filename");
- raw_parse_flags(flags, &access_flags, &overlapped);
+ use_aio = get_aio_option(opts, flags, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ raw_parse_flags(flags, use_aio, &access_flags, &overlapped);
if (filename[0] && filename[1] == ':') {
snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", filename[0]);
@@ -346,7 +381,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
goto fail;
}
- if (flags & BDRV_O_NATIVE_AIO) {
+ if (use_aio) {
s->aio = win32_aio_init();
if (s->aio == NULL) {
CloseHandle(s->hfile);
@@ -647,6 +682,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
Error *local_err = NULL;
const char *filename;
+ bool use_aio;
QemuOpts *opts = qemu_opts_create(&raw_runtime_opts, NULL, 0,
&error_abort);
@@ -659,6 +695,16 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
filename = qemu_opt_get(opts, "filename");
+ use_aio = get_aio_option(opts, flags, &local_err);
+ if (!local_err && use_aio) {
+ error_setg(&local_err, "AIO is not supported on Windows host devices");
+ }
+ if (local_err) {
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ goto done;
+ }
+
if (strstart(filename, "/dev/cdrom", NULL)) {
if (find_cdrom(device_name, sizeof(device_name)) < 0) {
error_setg(errp, "Could not open CD-ROM drive");
@@ -677,7 +723,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
}
s->type = find_device_type(bs, filename);
- raw_parse_flags(flags, &access_flags, &overlapped);
+ raw_parse_flags(flags, use_aio, &access_flags, &overlapped);
create_flags = OPEN_EXISTING;
diff --git a/blockdev.c b/blockdev.c
index 29c6561fd8..07ec733905 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -356,7 +356,6 @@ static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags,
const char **throttling_group, ThrottleConfig *throttle_cfg,
BlockdevDetectZeroesOptions *detect_zeroes, Error **errp)
{
- const char *discard;
Error *local_error = NULL;
const char *aio;
@@ -365,13 +364,6 @@ static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags,
*bdrv_flags |= BDRV_O_COPY_ON_READ;
}
- if ((discard = qemu_opt_get(opts, "discard")) != NULL) {
- if (bdrv_parse_discard_flags(discard, bdrv_flags) != 0) {
- error_setg(errp, "Invalid discard option");
- return;
- }
- }
-
if ((aio = qemu_opt_get(opts, "aio")) != NULL) {
if (!strcmp(aio, "native")) {
*bdrv_flags |= BDRV_O_NATIVE_AIO;
@@ -449,15 +441,6 @@ static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags,
error_propagate(errp, local_error);
return;
}
-
- if (bdrv_flags &&
- *detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
- !(*bdrv_flags & BDRV_O_UNMAP))
- {
- error_setg(errp, "setting detect-zeroes to unmap is not allowed "
- "without setting discard operation to unmap");
- return;
- }
}
}
@@ -650,35 +633,11 @@ err_no_opts:
return NULL;
}
-static QemuOptsList qemu_root_bds_opts;
-
/* Takes the ownership of bs_opts */
static BlockDriverState *bds_tree_init(QDict *bs_opts, Error **errp)
{
- BlockDriverState *bs;
- QemuOpts *opts;
- Error *local_error = NULL;
- BlockdevDetectZeroesOptions detect_zeroes;
int bdrv_flags = 0;
- opts = qemu_opts_create(&qemu_root_bds_opts, NULL, 1, errp);
- if (!opts) {
- goto fail;
- }
-
- qemu_opts_absorb_qdict(opts, bs_opts, &local_error);
- if (local_error) {
- error_propagate(errp, local_error);
- goto fail;
- }
-
- extract_common_blockdev_options(opts, &bdrv_flags, NULL, NULL,
- &detect_zeroes, &local_error);
- if (local_error) {
- error_propagate(errp, local_error);
- goto fail;
- }
-
/* bdrv_open() defaults to the values in bdrv_flags (for compatibility
* with other callers) rather than what we want as the real defaults.
* Apply the defaults here instead. */
@@ -690,21 +649,7 @@ static BlockDriverState *bds_tree_init(QDict *bs_opts, Error **errp)
bdrv_flags |= BDRV_O_INACTIVE;
}
- bs = bdrv_open(NULL, NULL, bs_opts, bdrv_flags, errp);
- if (!bs) {
- goto fail_no_bs_opts;
- }
-
- bs->detect_zeroes = detect_zeroes;
-
-fail_no_bs_opts:
- qemu_opts_del(opts);
- return bs;
-
-fail:
- qemu_opts_del(opts);
- QDECREF(bs_opts);
- return NULL;
+ return bdrv_open(NULL, NULL, bs_opts, bdrv_flags, errp);
}
void blockdev_close_all_bdrv_states(void)
@@ -2549,6 +2494,7 @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
BlockBackend *blk;
BlockDriverState *medium_bs = NULL;
int bdrv_flags;
+ bool detect_zeroes;
int rc;
QDict *options = NULL;
Error *err = NULL;
@@ -2588,8 +2534,12 @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
abort();
}
+ options = qdict_new();
+ detect_zeroes = blk_get_detect_zeroes_from_root_state(blk);
+ qdict_put(options, "detect-zeroes",
+ qstring_from_str(detect_zeroes ? "on" : "off"));
+
if (has_format) {
- options = qdict_new();
qdict_put(options, "driver", qstring_from_str(format));
}
@@ -2614,7 +2564,7 @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
error_free(err);
err = NULL;
- qmp_x_blockdev_remove_medium(has_device, device, has_id, id, errp);
+ qmp_x_blockdev_remove_medium(has_device, device, has_id, id, &err);
if (err) {
error_propagate(errp, err);
goto fail;
@@ -2626,8 +2576,6 @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
goto fail;
}
- blk_apply_root_state(blk, medium_bs);
-
qmp_blockdev_close_tray(has_device, device, has_id, id, errp);
fail:
@@ -3832,21 +3780,6 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
QDict *qdict;
Error *local_err = NULL;
- /* TODO Sort it out in raw-posix and drive_new(): Reject aio=native with
- * cache.direct=false instead of silently switching to aio=threads, except
- * when called from drive_new().
- *
- * For now, simply forbidding the combination for all drivers will do. */
- if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) {
- bool direct = options->has_cache &&
- options->cache->has_direct &&
- options->cache->direct;
- if (!direct) {
- error_setg(errp, "aio=native requires cache.direct=true");
- goto fail;
- }
- }
-
visit_type_BlockdevOptions(v, NULL, &options, &local_err);
if (local_err) {
error_propagate(errp, local_err);
@@ -4005,10 +3938,6 @@ QemuOptsList qemu_common_drive_opts = {
.type = QEMU_OPT_BOOL,
.help = "enable/disable snapshot mode",
},{
- .name = "discard",
- .type = QEMU_OPT_STRING,
- .help = "discard operation (ignore/off, unmap/on)",
- },{
.name = "aio",
.type = QEMU_OPT_STRING,
.help = "host AIO implementation (threads, native)",
@@ -4135,31 +4064,6 @@ QemuOptsList qemu_common_drive_opts = {
},
};
-static QemuOptsList qemu_root_bds_opts = {
- .name = "root-bds",
- .head = QTAILQ_HEAD_INITIALIZER(qemu_root_bds_opts.head),
- .desc = {
- {
- .name = "discard",
- .type = QEMU_OPT_STRING,
- .help = "discard operation (ignore/off, unmap/on)",
- },{
- .name = "aio",
- .type = QEMU_OPT_STRING,
- .help = "host AIO implementation (threads, native)",
- },{
- .name = "copy-on-read",
- .type = QEMU_OPT_BOOL,
- .help = "copy read data from backing file into image file",
- },{
- .name = "detect-zeroes",
- .type = QEMU_OPT_STRING,
- .help = "try to optimize zero writes (off, on, unmap)",
- },
- { /* end of list */ }
- },
-};
-
QemuOptsList qemu_drive_opts = {
.name = "drive",
.head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
diff --git a/bsd-user/main.c b/bsd-user/main.c
index d803d3e10c..d8367bda46 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -695,6 +695,16 @@ static void usage(void)
THREAD CPUState *thread_cpu;
+bool qemu_cpu_is_self(CPUState *cpu)
+{
+ return thread_cpu == cpu;
+}
+
+void qemu_cpu_kick(CPUState *cpu)
+{
+ cpu_exit(cpu);
+}
+
/* Assumes contents are already zeroed. */
void init_task_state(TaskState *ts)
{
diff --git a/configure b/configure
index df4a247fc2..5751d8ecaa 100755
--- a/configure
+++ b/configure
@@ -296,6 +296,7 @@ libiscsi=""
libnfs=""
coroutine=""
coroutine_pool=""
+debug_stack_usage="no"
seccomp=""
glusterfs=""
glusterfs_xlator_opt="no"
@@ -1004,6 +1005,8 @@ for opt do
;;
--enable-coroutine-pool) coroutine_pool="yes"
;;
+ --enable-debug-stack-usage) debug_stack_usage="yes"
+ ;;
--disable-docs) docs="no"
;;
--enable-docs) docs="yes"
@@ -4331,6 +4334,17 @@ if test "$coroutine" = "gthread" -a "$coroutine_pool" = "yes"; then
error_exit "'gthread' coroutine backend does not support pool (use --disable-coroutine-pool)"
fi
+if test "$debug_stack_usage" = "yes"; then
+ if test "$cpu" = "ia64" -o "$cpu" = "hppa"; then
+ error_exit "stack usage debugging is not supported for $cpu"
+ fi
+ if test "$coroutine_pool" = "yes"; then
+ echo "WARN: disabling coroutine pool for stack usage debugging"
+ coroutine_pool=no
+ fi
+fi
+
+
##########################################
# check if we have open_by_handle_at
@@ -4916,6 +4930,7 @@ echo "QGA MSI support $guest_agent_msi"
echo "seccomp support $seccomp"
echo "coroutine backend $coroutine"
echo "coroutine pool $coroutine_pool"
+echo "debug stack usage $debug_stack_usage"
echo "GlusterFS support $glusterfs"
echo "Archipelago support $archipelago"
echo "gcov $gcov_tool"
@@ -5384,6 +5399,10 @@ else
echo "CONFIG_COROUTINE_POOL=0" >> $config_host_mak
fi
+if test "$debug_stack_usage" = "yes" ; then
+ echo "CONFIG_DEBUG_STACK_USAGE=y" >> $config_host_mak
+fi
+
if test "$open_by_handle_at" = "yes" ; then
echo "CONFIG_OPEN_BY_HANDLE=y" >> $config_host_mak
fi
diff --git a/cpus.c b/cpus.c
index b2fbe33304..31204bb4b3 100644
--- a/cpus.c
+++ b/cpus.c
@@ -751,7 +751,7 @@ static int do_vm_stop(RunState state)
bdrv_drain_all();
replay_disable_events();
- ret = blk_flush_all();
+ ret = bdrv_flush_all();
return ret;
}
@@ -1408,7 +1408,7 @@ int vm_stop_force_state(RunState state)
bdrv_drain_all();
/* Make sure to return an error if the flush in a previous vm_stop()
* failed. */
- return blk_flush_all();
+ return bdrv_flush_all();
}
}
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index e1243602e9..6de3e16a3e 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -86,6 +86,8 @@ CONFIG_ZYNQ=y
CONFIG_STM32F2XX_TIMER=y
CONFIG_STM32F2XX_USART=y
CONFIG_STM32F2XX_SYSCFG=y
+CONFIG_STM32F2XX_ADC=y
+CONFIG_STM32F2XX_SPI=y
CONFIG_STM32F205_SOC=y
CONFIG_VERSATILE_PCI=y
diff --git a/docs/generic-loader.txt b/docs/generic-loader.txt
new file mode 100644
index 0000000000..8fcb550414
--- /dev/null
+++ b/docs/generic-loader.txt
@@ -0,0 +1,84 @@
+Copyright (c) 2016 Xilinx Inc.
+
+This work is licensed under the terms of the GNU GPL, version 2 or later. See
+the COPYING file in the top-level directory.
+
+
+The 'loader' device allows the user to load multiple images or values into
+QEMU at startup.
+
+Loading Data into Memory Values
+---------------------
+The loader device allows memory values to be set from the command line. This
+can be done by following the syntax below:
+
+ -device loader,addr=<addr>,data=<data>,data-len=<data-len>
+ [,data-be=<data-be>][,cpu-num=<cpu-num>]
+
+ <addr> - The address to store the data in.
+ <data> - The value to be written to the address. The maximum size of
+ the data is 8 bytes.
+ <data-len> - The length of the data in bytes. This argument must be
+ included if the data argument is.
+ <data-be> - Set to true if the data to be stored on the guest should be
+ written as big endian data. The default is to write little
+ endian data.
+ <cpu-num> - The number of the CPU's address space where the data should
+ be loaded. If not specified the address space of the first
+ CPU is used.
+
+All values are parsed using the standard QemuOps parsing. This allows the user
+to specify any values in any format supported. By default the values
+will be parsed as decimal. To use hex values the user should prefix the number
+with a '0x'.
+
+An example of loading value 0x8000000e to address 0xfd1a0104 is:
+ -device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4
+
+Setting a CPU's Program Counter
+---------------------
+The loader device allows the CPU's PC to be set from the command line. This
+can be done by following the syntax below:
+
+ -device loader,addr=<addr>,cpu-num=<cpu-num>
+
+ <addr> - The value to use as the CPU's PC.
+ <cpu-num> - The number of the CPU whose PC should be set to the
+ specified value.
+
+All values are parsed using the standard QemuOps parsing. This allows the user
+to specify any values in any format supported. By default the values
+will be parsed as decimal. To use hex values the user should prefix the number
+with a '0x'.
+
+An example of setting CPU 0's PC to 0x8000 is:
+ -device loader,addr=0x8000,cpu-num=0
+
+Loading Files
+---------------------
+The loader device also allows files to be loaded into memory. This can be done
+similarly to setting memory values. The syntax is shown below:
+
+ -device loader,file=<file>[,addr=<addr>][,cpu-num=<cpu-num>][,force-raw=<raw>]
+
+ <file> - A file to be loaded into memory
+ <addr> - The addr in memory that the file should be loaded. This is
+ ignored if you are using an ELF (unless force-raw is true).
+ This is required if you aren't loading an ELF.
+ <cpu-num> - This specifies the CPU that should be used. This is an
+ optional argument and will cause the CPU's PC to be set to
+ where the image is stored or in the case of an ELF file to
+ the value in the header. This option should only be used
+ for the boot image.
+ This will also cause the image to be written to the specified
+ CPU's address space. If not specified, the default is CPU 0.
+ <force-raw> - Forces the file to be treated as a raw image. This can be
+ used to specify the load address of ELF files.
+
+All values are parsed using the standard QemuOps parsing. This allows the user
+to specify any values in any format supported. By default the values
+will be parsed as decimal. To use hex values the user should prefix the number
+with a '0x'.
+
+An example of loading an ELF file which CPU0 will boot is shown below:
+ -device loader,file=./images/boot.elf,cpu-num=0
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 4a07ed4344..0ffd281145 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -1,5 +1,6 @@
devices-dirs-$(call land, $(CONFIG_VIRTIO),$(call land,$(CONFIG_VIRTFS),$(CONFIG_PCI))) += 9pfs/
devices-dirs-$(CONFIG_ACPI) += acpi/
+devices-dirs-$(CONFIG_SOFTMMU) += adc/
devices-dirs-$(CONFIG_SOFTMMU) += audio/
devices-dirs-$(CONFIG_SOFTMMU) += block/
devices-dirs-$(CONFIG_SOFTMMU) += bt/
diff --git a/hw/adc/Makefile.objs b/hw/adc/Makefile.objs
new file mode 100644
index 0000000000..3f6dfdedae
--- /dev/null
+++ b/hw/adc/Makefile.objs
@@ -0,0 +1 @@
+obj-$(CONFIG_STM32F2XX_ADC) += stm32f2xx_adc.o
diff --git a/hw/adc/stm32f2xx_adc.c b/hw/adc/stm32f2xx_adc.c
new file mode 100644
index 0000000000..90fe9de299
--- /dev/null
+++ b/hw/adc/stm32f2xx_adc.c
@@ -0,0 +1,306 @@
+/*
+ * STM32F2XX ADC
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * 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/sysbus.h"
+#include "hw/hw.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "hw/adc/stm32f2xx_adc.h"
+
+#ifndef STM_ADC_ERR_DEBUG
+#define STM_ADC_ERR_DEBUG 0
+#endif
+
+#define DB_PRINT_L(lvl, fmt, args...) do { \
+ if (STM_ADC_ERR_DEBUG >= lvl) { \
+ qemu_log("%s: " fmt, __func__, ## args); \
+ } \
+} while (0);
+
+#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
+
+static void stm32f2xx_adc_reset(DeviceState *dev)
+{
+ STM32F2XXADCState *s = STM32F2XX_ADC(dev);
+
+ s->adc_sr = 0x00000000;
+ s->adc_cr1 = 0x00000000;
+ s->adc_cr2 = 0x00000000;
+ s->adc_smpr1 = 0x00000000;
+ s->adc_smpr2 = 0x00000000;
+ s->adc_jofr[0] = 0x00000000;
+ s->adc_jofr[1] = 0x00000000;
+ s->adc_jofr[2] = 0x00000000;
+ s->adc_jofr[3] = 0x00000000;
+ s->adc_htr = 0x00000FFF;
+ s->adc_ltr = 0x00000000;
+ s->adc_sqr1 = 0x00000000;
+ s->adc_sqr2 = 0x00000000;
+ s->adc_sqr3 = 0x00000000;
+ s->adc_jsqr = 0x00000000;
+ s->adc_jdr[0] = 0x00000000;
+ s->adc_jdr[1] = 0x00000000;
+ s->adc_jdr[2] = 0x00000000;
+ s->adc_jdr[3] = 0x00000000;
+ s->adc_dr = 0x00000000;
+}
+
+static uint32_t stm32f2xx_adc_generate_value(STM32F2XXADCState *s)
+{
+ /* Attempts to fake some ADC values */
+ s->adc_dr = s->adc_dr + 7;
+
+ switch ((s->adc_cr1 & ADC_CR1_RES) >> 24) {
+ case 0:
+ /* 12-bit */
+ s->adc_dr &= 0xFFF;
+ break;
+ case 1:
+ /* 10-bit */
+ s->adc_dr &= 0x3FF;
+ break;
+ case 2:
+ /* 8-bit */
+ s->adc_dr &= 0xFF;
+ break;
+ default:
+ /* 6-bit */
+ s->adc_dr &= 0x3F;
+ }
+
+ if (s->adc_cr2 & ADC_CR2_ALIGN) {
+ return (s->adc_dr << 1) & 0xFFF0;
+ } else {
+ return s->adc_dr;
+ }
+}
+
+static uint64_t stm32f2xx_adc_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+ STM32F2XXADCState *s = opaque;
+
+ DB_PRINT("Address: 0x%" HWADDR_PRIx "\n", addr);
+
+ if (addr >= ADC_COMMON_ADDRESS) {
+ qemu_log_mask(LOG_UNIMP,
+ "%s: ADC Common Register Unsupported\n", __func__);
+ }
+
+ switch (addr) {
+ case ADC_SR:
+ return s->adc_sr;
+ case ADC_CR1:
+ return s->adc_cr1;
+ case ADC_CR2:
+ return s->adc_cr2 & 0xFFFFFFF;
+ case ADC_SMPR1:
+ return s->adc_smpr1;
+ case ADC_SMPR2:
+ return s->adc_smpr2;
+ case ADC_JOFR1:
+ case ADC_JOFR2:
+ case ADC_JOFR3:
+ case ADC_JOFR4:
+ qemu_log_mask(LOG_UNIMP, "%s: " \
+ "Injection ADC is not implemented, the registers are " \
+ "included for compatibility\n", __func__);
+ return s->adc_jofr[(addr - ADC_JOFR1) / 4];
+ case ADC_HTR:
+ return s->adc_htr;
+ case ADC_LTR:
+ return s->adc_ltr;
+ case ADC_SQR1:
+ return s->adc_sqr1;
+ case ADC_SQR2:
+ return s->adc_sqr2;
+ case ADC_SQR3:
+ return s->adc_sqr3;
+ case ADC_JSQR:
+ qemu_log_mask(LOG_UNIMP, "%s: " \
+ "Injection ADC is not implemented, the registers are " \
+ "included for compatibility\n", __func__);
+ return s->adc_jsqr;
+ case ADC_JDR1:
+ case ADC_JDR2:
+ case ADC_JDR3:
+ case ADC_JDR4:
+ qemu_log_mask(LOG_UNIMP, "%s: " \
+ "Injection ADC is not implemented, the registers are " \
+ "included for compatibility\n", __func__);
+ return s->adc_jdr[(addr - ADC_JDR1) / 4] -
+ s->adc_jofr[(addr - ADC_JDR1) / 4];
+ case ADC_DR:
+ if ((s->adc_cr2 & ADC_CR2_ADON) && (s->adc_cr2 & ADC_CR2_SWSTART)) {
+ s->adc_cr2 ^= ADC_CR2_SWSTART;
+ return stm32f2xx_adc_generate_value(s);
+ } else {
+ return 0;
+ }
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
+ }
+
+ return 0;
+}
+
+static void stm32f2xx_adc_write(void *opaque, hwaddr addr,
+ uint64_t val64, unsigned int size)
+{
+ STM32F2XXADCState *s = opaque;
+ uint32_t value = (uint32_t) val64;
+
+ DB_PRINT("Address: 0x%" HWADDR_PRIx ", Value: 0x%x\n",
+ addr, value);
+
+ if (addr >= 0x100) {
+ qemu_log_mask(LOG_UNIMP,
+ "%s: ADC Common Register Unsupported\n", __func__);
+ }
+
+ switch (addr) {
+ case ADC_SR:
+ s->adc_sr &= (value & 0x3F);
+ break;
+ case ADC_CR1:
+ s->adc_cr1 = value;
+ break;
+ case ADC_CR2:
+ s->adc_cr2 = value;
+ break;
+ case ADC_SMPR1:
+ s->adc_smpr1 = value;
+ break;
+ case ADC_SMPR2:
+ s->adc_smpr2 = value;
+ break;
+ case ADC_JOFR1:
+ case ADC_JOFR2:
+ case ADC_JOFR3:
+ case ADC_JOFR4:
+ s->adc_jofr[(addr - ADC_JOFR1) / 4] = (value & 0xFFF);
+ qemu_log_mask(LOG_UNIMP, "%s: " \
+ "Injection ADC is not implemented, the registers are " \
+ "included for compatibility\n", __func__);
+ break;
+ case ADC_HTR:
+ s->adc_htr = value;
+ break;
+ case ADC_LTR:
+ s->adc_ltr = value;
+ break;
+ case ADC_SQR1:
+ s->adc_sqr1 = value;
+ break;
+ case ADC_SQR2:
+ s->adc_sqr2 = value;
+ break;
+ case ADC_SQR3:
+ s->adc_sqr3 = value;
+ break;
+ case ADC_JSQR:
+ s->adc_jsqr = value;
+ qemu_log_mask(LOG_UNIMP, "%s: " \
+ "Injection ADC is not implemented, the registers are " \
+ "included for compatibility\n", __func__);
+ break;
+ case ADC_JDR1:
+ case ADC_JDR2:
+ case ADC_JDR3:
+ case ADC_JDR4:
+ s->adc_jdr[(addr - ADC_JDR1) / 4] = value;
+ qemu_log_mask(LOG_UNIMP, "%s: " \
+ "Injection ADC is not implemented, the registers are " \
+ "included for compatibility\n", __func__);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
+ }
+}
+
+static const MemoryRegionOps stm32f2xx_adc_ops = {
+ .read = stm32f2xx_adc_read,
+ .write = stm32f2xx_adc_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_stm32f2xx_adc = {
+ .name = TYPE_STM32F2XX_ADC,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(adc_sr, STM32F2XXADCState),
+ VMSTATE_UINT32(adc_cr1, STM32F2XXADCState),
+ VMSTATE_UINT32(adc_cr2, STM32F2XXADCState),
+ VMSTATE_UINT32(adc_smpr1, STM32F2XXADCState),
+ VMSTATE_UINT32(adc_smpr2, STM32F2XXADCState),
+ VMSTATE_UINT32_ARRAY(adc_jofr, STM32F2XXADCState, 4),
+ VMSTATE_UINT32(adc_htr, STM32F2XXADCState),
+ VMSTATE_UINT32(adc_ltr, STM32F2XXADCState),
+ VMSTATE_UINT32(adc_sqr1, STM32F2XXADCState),
+ VMSTATE_UINT32(adc_sqr2, STM32F2XXADCState),
+ VMSTATE_UINT32(adc_sqr3, STM32F2XXADCState),
+ VMSTATE_UINT32(adc_jsqr, STM32F2XXADCState),
+ VMSTATE_UINT32_ARRAY(adc_jdr, STM32F2XXADCState, 4),
+ VMSTATE_UINT32(adc_dr, STM32F2XXADCState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void stm32f2xx_adc_init(Object *obj)
+{
+ STM32F2XXADCState *s = STM32F2XX_ADC(obj);
+
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
+
+ memory_region_init_io(&s->mmio, obj, &stm32f2xx_adc_ops, s,
+ TYPE_STM32F2XX_ADC, 0xFF);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+}
+
+static void stm32f2xx_adc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = stm32f2xx_adc_reset;
+ dc->vmsd = &vmstate_stm32f2xx_adc;
+}
+
+static const TypeInfo stm32f2xx_adc_info = {
+ .name = TYPE_STM32F2XX_ADC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(STM32F2XXADCState),
+ .instance_init = stm32f2xx_adc_init,
+ .class_init = stm32f2xx_adc_class_init,
+};
+
+static void stm32f2xx_adc_register_types(void)
+{
+ type_register_static(&stm32f2xx_adc_info);
+}
+
+type_init(stm32f2xx_adc_register_types)
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index 96dc150025..039812a3fd 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -252,6 +252,26 @@ static void integratorcm_init(Object *obj)
/* ??? What should the high bits of this value be? */
s->cm_auxosc = 0x0007feff;
s->cm_sdram = 0x00011122;
+ memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
+ s->cm_init = 0x00000112;
+ s->cm_refcnt_offset = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
+ 1000);
+ memory_region_init_ram(&s->flash, obj, "integrator.flash", 0x100000,
+ &error_fatal);
+ vmstate_register_ram_global(&s->flash);
+
+ memory_region_init_io(&s->iomem, obj, &integratorcm_ops, s,
+ "integratorcm", 0x00800000);
+ sysbus_init_mmio(dev, &s->iomem);
+
+ integratorcm_do_remap(s);
+ /* ??? Save/restore. */
+}
+
+static void integratorcm_realize(DeviceState *d, Error **errp)
+{
+ IntegratorCMState *s = INTEGRATOR_CM(d);
+
if (s->memsz >= 256) {
integrator_spd[31] = 64;
s->cm_sdram |= 0x10;
@@ -267,20 +287,6 @@ static void integratorcm_init(Object *obj)
} else {
integrator_spd[31] = 2;
}
- memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
- s->cm_init = 0x00000112;
- s->cm_refcnt_offset = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
- 1000);
- memory_region_init_ram(&s->flash, obj, "integrator.flash", 0x100000,
- &error_fatal);
- vmstate_register_ram_global(&s->flash);
-
- memory_region_init_io(&s->iomem, obj, &integratorcm_ops, s,
- "integratorcm", 0x00800000);
- sysbus_init_mmio(dev, &s->iomem);
-
- integratorcm_do_remap(s);
- /* ??? Save/restore. */
}
/* Integrator/CP hardware emulation. */
@@ -633,6 +639,7 @@ static void core_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->props = core_properties;
+ dc->realize = integratorcm_realize;
}
static const TypeInfo core_info = {
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
index 454acc5d2b..f962236cf4 100644
--- a/hw/arm/mainstone.c
+++ b/hw/arm/mainstone.c
@@ -73,8 +73,10 @@ static const struct keymap map[0xE0] = {
[0x2f] = {3,3}, /* v */
[0x11] = {3,4}, /* w */
[0x2d] = {3,5}, /* x */
+ [0x34] = {4,0}, /* . */
[0x15] = {4,2}, /* y */
[0x2c] = {4,3}, /* z */
+ [0x35] = {4,4}, /* / */
[0xc7] = {5,0}, /* Home */
[0x2a] = {5,1}, /* shift */
/*
@@ -88,7 +90,8 @@ static const struct keymap map[0xE0] = {
* Matrix position {5,4} and other keys are missing here.
* TODO: Compare with Linux code and test real hardware.
*/
- [0x1c] = {5,5}, /* enter (TODO: might be wrong) */
+ [0x1c] = {5,4}, /* enter */
+ [0x0e] = {5,5}, /* backspace */
[0xc8] = {6,0}, /* up */
[0xd0] = {6,1}, /* down */
[0xcb] = {6,2}, /* left */
diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c
index de26b8caff..38425bda6c 100644
--- a/hw/arm/stm32f205_soc.c
+++ b/hw/arm/stm32f205_soc.c
@@ -34,9 +34,15 @@ static const uint32_t timer_addr[STM_NUM_TIMERS] = { 0x40000000, 0x40000400,
0x40000800, 0x40000C00 };
static const uint32_t usart_addr[STM_NUM_USARTS] = { 0x40011000, 0x40004400,
0x40004800, 0x40004C00, 0x40005000, 0x40011400 };
+static const uint32_t adc_addr[STM_NUM_ADCS] = { 0x40012000, 0x40012100,
+ 0x40012200 };
+static const uint32_t spi_addr[STM_NUM_SPIS] = { 0x40013000, 0x40003800,
+ 0x40003C00 };
static const int timer_irq[STM_NUM_TIMERS] = {28, 29, 30, 50};
static const int usart_irq[STM_NUM_USARTS] = {37, 38, 39, 52, 53, 71};
+#define ADC_IRQ 18
+static const int spi_irq[STM_NUM_SPIS] = {35, 36, 51};
static void stm32f205_soc_initfn(Object *obj)
{
@@ -57,13 +63,27 @@ static void stm32f205_soc_initfn(Object *obj)
TYPE_STM32F2XX_TIMER);
qdev_set_parent_bus(DEVICE(&s->timer[i]), sysbus_get_default());
}
+
+ s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
+
+ for (i = 0; i < STM_NUM_ADCS; i++) {
+ object_initialize(&s->adc[i], sizeof(s->adc[i]),
+ TYPE_STM32F2XX_ADC);
+ qdev_set_parent_bus(DEVICE(&s->adc[i]), sysbus_get_default());
+ }
+
+ for (i = 0; i < STM_NUM_SPIS; i++) {
+ object_initialize(&s->spi[i], sizeof(s->spi[i]),
+ TYPE_STM32F2XX_SPI);
+ qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
+ }
}
static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
{
STM32F205State *s = STM32F205_SOC(dev_soc);
- DeviceState *syscfgdev, *usartdev, *timerdev, *nvic;
- SysBusDevice *syscfgbusdev, *usartbusdev, *timerbusdev;
+ DeviceState *dev, *nvic;
+ SysBusDevice *busdev;
Error *err = NULL;
int i;
@@ -94,44 +114,80 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
s->kernel_filename, s->cpu_model);
/* System configuration controller */
- syscfgdev = DEVICE(&s->syscfg);
+ dev = DEVICE(&s->syscfg);
object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
return;
}
- syscfgbusdev = SYS_BUS_DEVICE(syscfgdev);
- sysbus_mmio_map(syscfgbusdev, 0, 0x40013800);
- sysbus_connect_irq(syscfgbusdev, 0, qdev_get_gpio_in(nvic, 71));
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, 0x40013800);
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(nvic, 71));
/* Attach UART (uses USART registers) and USART controllers */
for (i = 0; i < STM_NUM_USARTS; i++) {
- usartdev = DEVICE(&(s->usart[i]));
- qdev_prop_set_chr(usartdev, "chardev", i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL);
+ dev = DEVICE(&(s->usart[i]));
+ qdev_prop_set_chr(dev, "chardev",
+ i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL);
object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
return;
}
- usartbusdev = SYS_BUS_DEVICE(usartdev);
- sysbus_mmio_map(usartbusdev, 0, usart_addr[i]);
- sysbus_connect_irq(usartbusdev, 0,
- qdev_get_gpio_in(nvic, usart_irq[i]));
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, usart_addr[i]);
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(nvic, usart_irq[i]));
}
/* Timer 2 to 5 */
for (i = 0; i < STM_NUM_TIMERS; i++) {
- timerdev = DEVICE(&(s->timer[i]));
- qdev_prop_set_uint64(timerdev, "clock-frequency", 1000000000);
+ dev = DEVICE(&(s->timer[i]));
+ qdev_prop_set_uint64(dev, "clock-frequency", 1000000000);
object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
return;
}
- timerbusdev = SYS_BUS_DEVICE(timerdev);
- sysbus_mmio_map(timerbusdev, 0, timer_addr[i]);
- sysbus_connect_irq(timerbusdev, 0,
- qdev_get_gpio_in(nvic, timer_irq[i]));
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, timer_addr[i]);
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(nvic, timer_irq[i]));
+ }
+
+ /* ADC 1 to 3 */
+ object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS,
+ "num-lines", &err);
+ object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ return;
+ }
+ qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
+ qdev_get_gpio_in(nvic, ADC_IRQ));
+
+ for (i = 0; i < STM_NUM_ADCS; i++) {
+ dev = DEVICE(&(s->adc[i]));
+ object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ return;
+ }
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, adc_addr[i]);
+ sysbus_connect_irq(busdev, 0,
+ qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
+ }
+
+ /* SPI 1 and 2 */
+ for (i = 0; i < STM_NUM_SPIS; i++) {
+ dev = DEVICE(&(s->spi[i]));
+ object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ return;
+ }
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, spi_addr[i]);
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(nvic, spi_irq[i]));
}
}
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 295ec86828..7b39b1d2d6 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -44,6 +44,7 @@
#include "hw/pci/pcie_host.h"
#include "hw/pci/pci.h"
#include "sysemu/numa.h"
+#include "kvm_arm.h"
#define ARM_SPI_BASE 32
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
@@ -546,6 +547,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
}
if (guest_info->gic_version == 3) {
+ AcpiMadtGenericTranslator *gic_its;
AcpiMadtGenericRedistributor *gicr = acpi_data_push(table_data,
sizeof *gicr);
@@ -553,6 +555,16 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
gicr->length = sizeof(*gicr);
gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base);
gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size);
+
+ if (!its_class_name()) {
+ return;
+ }
+
+ gic_its = acpi_data_push(table_data, sizeof *gic_its);
+ gic_its->type = ACPI_APIC_GENERIC_TRANSLATOR;
+ gic_its->length = sizeof(*gic_its);
+ gic_its->translation_id = 0;
+ gic_its->base_address = cpu_to_le64(memmap[VIRT_GIC_ITS].base);
} else {
gic_msi = acpi_data_push(table_data, sizeof *gic_msi);
gic_msi->type = ACPI_APIC_GENERIC_MSI_FRAME;
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index a193b5a95b..0f6305d3c7 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -76,7 +76,7 @@ typedef struct VirtBoardInfo {
int fdt_size;
uint32_t clock_phandle;
uint32_t gic_phandle;
- uint32_t v2m_phandle;
+ uint32_t msi_phandle;
bool using_psci;
} VirtBoardInfo;
@@ -423,9 +423,22 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
}
}
+static void fdt_add_its_gic_node(VirtBoardInfo *vbi)
+{
+ vbi->msi_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
+ qemu_fdt_add_subnode(vbi->fdt, "/intc/its");
+ qemu_fdt_setprop_string(vbi->fdt, "/intc/its", "compatible",
+ "arm,gic-v3-its");
+ qemu_fdt_setprop(vbi->fdt, "/intc/its", "msi-controller", NULL, 0);
+ qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc/its", "reg",
+ 2, vbi->memmap[VIRT_GIC_ITS].base,
+ 2, vbi->memmap[VIRT_GIC_ITS].size);
+ qemu_fdt_setprop_cell(vbi->fdt, "/intc/its", "phandle", vbi->msi_phandle);
+}
+
static void fdt_add_v2m_gic_node(VirtBoardInfo *vbi)
{
- vbi->v2m_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
+ vbi->msi_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
qemu_fdt_add_subnode(vbi->fdt, "/intc/v2m");
qemu_fdt_setprop_string(vbi->fdt, "/intc/v2m", "compatible",
"arm,gic-v2m-frame");
@@ -433,7 +446,7 @@ static void fdt_add_v2m_gic_node(VirtBoardInfo *vbi)
qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc/v2m", "reg",
2, vbi->memmap[VIRT_GIC_V2M].base,
2, vbi->memmap[VIRT_GIC_V2M].size);
- qemu_fdt_setprop_cell(vbi->fdt, "/intc/v2m", "phandle", vbi->v2m_phandle);
+ qemu_fdt_setprop_cell(vbi->fdt, "/intc/v2m", "phandle", vbi->msi_phandle);
}
static void fdt_add_gic_node(VirtBoardInfo *vbi, int type)
@@ -500,6 +513,26 @@ static void fdt_add_pmu_nodes(const VirtBoardInfo *vbi, int gictype)
}
}
+static void create_its(VirtBoardInfo *vbi, DeviceState *gicdev)
+{
+ const char *itsclass = its_class_name();
+ DeviceState *dev;
+
+ if (!itsclass) {
+ /* Do nothing if not supported */
+ return;
+ }
+
+ dev = qdev_create(NULL, itsclass);
+
+ object_property_set_link(OBJECT(dev), OBJECT(gicdev), "parent-gicv3",
+ &error_abort);
+ qdev_init_nofail(dev);
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vbi->memmap[VIRT_GIC_ITS].base);
+
+ fdt_add_its_gic_node(vbi);
+}
+
static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic)
{
int i;
@@ -583,7 +616,9 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type, bool secure)
fdt_add_gic_node(vbi, type);
- if (type == 2) {
+ if (type == 3) {
+ create_its(vbi, gicdev);
+ } else {
create_v2m(vbi, pic);
}
}
@@ -1025,9 +1060,9 @@ static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic,
nr_pcie_buses - 1);
qemu_fdt_setprop(vbi->fdt, nodename, "dma-coherent", NULL, 0);
- if (vbi->v2m_phandle) {
+ if (vbi->msi_phandle) {
qemu_fdt_setprop_cells(vbi->fdt, nodename, "msi-parent",
- vbi->v2m_phandle);
+ vbi->msi_phandle);
}
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
@@ -1479,7 +1514,7 @@ static void machvirt_machine_init(void)
}
type_init(machvirt_machine_init);
-static void virt_2_7_instance_init(Object *obj)
+static void virt_2_8_instance_init(Object *obj)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -1512,10 +1547,25 @@ static void virt_2_7_instance_init(Object *obj)
"Valid values are 2, 3 and host", NULL);
}
+static void virt_machine_2_8_options(MachineClass *mc)
+{
+}
+DEFINE_VIRT_MACHINE_AS_LATEST(2, 8)
+
+#define VIRT_COMPAT_2_7 \
+ HW_COMPAT_2_7
+
+static void virt_2_7_instance_init(Object *obj)
+{
+ virt_2_8_instance_init(obj);
+}
+
static void virt_machine_2_7_options(MachineClass *mc)
{
+ virt_machine_2_8_options(mc);
+ SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_7);
}
-DEFINE_VIRT_MACHINE_AS_LATEST(2, 7)
+DEFINE_VIRT_MACHINE(2, 7)
#define VIRT_COMPAT_2_6 \
HW_COMPAT_2_6
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
index cfd4840397..a4c94e522d 100644
--- a/hw/core/Makefile.objs
+++ b/hw/core/Makefile.objs
@@ -16,4 +16,7 @@ common-obj-$(CONFIG_SOFTMMU) += null-machine.o
common-obj-$(CONFIG_SOFTMMU) += loader.o
common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
common-obj-$(CONFIG_SOFTMMU) += register.o
+common-obj-$(CONFIG_SOFTMMU) += or-irq.o
common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o
+
+obj-$(CONFIG_SOFTMMU) += generic-loader.o
diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c
new file mode 100644
index 0000000000..79ab6df357
--- /dev/null
+++ b/hw/core/generic-loader.c
@@ -0,0 +1,211 @@
+/*
+ * Generic Loader
+ *
+ * Copyright (C) 2014 Li Guang
+ * Copyright (C) 2016 Xilinx Inc.
+ * Written by Li Guang <lig.fnst@cn.fujitsu.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.
+ *
+ */
+
+/*
+ * Internally inside QEMU this is a device. It is a strange device that
+ * provides no hardware interface but allows QEMU to monkey patch memory
+ * specified when it is created. To be able to do this it has a reset
+ * callback that does the memory operations.
+
+ * This device allows the user to monkey patch memory. To be able to do
+ * this it needs a backend to manage the datas, the same as other
+ * memory-related devices. In this case as the backend is so trivial we
+ * have merged it with the frontend instead of creating and maintaining a
+ * seperate backend.
+ */
+
+#include "qemu/osdep.h"
+#include "qom/cpu.h"
+#include "hw/sysbus.h"
+#include "sysemu/dma.h"
+#include "hw/loader.h"
+#include "qapi/error.h"
+#include "hw/core/generic-loader.h"
+
+#define CPU_NONE 0xFFFFFFFF
+
+static void generic_loader_reset(void *opaque)
+{
+ GenericLoaderState *s = GENERIC_LOADER(opaque);
+
+ if (s->set_pc) {
+ CPUClass *cc = CPU_GET_CLASS(s->cpu);
+ cpu_reset(s->cpu);
+ if (cc) {
+ cc->set_pc(s->cpu, s->addr);
+ }
+ }
+
+ if (s->data_len) {
+ assert(s->data_len < sizeof(s->data));
+ dma_memory_write(s->cpu->as, s->addr, &s->data, s->data_len);
+ }
+}
+
+static void generic_loader_realize(DeviceState *dev, Error **errp)
+{
+ GenericLoaderState *s = GENERIC_LOADER(dev);
+ hwaddr entry;
+ int big_endian;
+ int size = 0;
+
+ s->set_pc = false;
+
+ /* Perform some error checking on the user's options */
+ if (s->data || s->data_len || s->data_be) {
+ /* User is loading memory values */
+ if (s->file) {
+ error_setg(errp, "Specifying a file is not supported when loading "
+ "memory values");
+ return;
+ } else if (s->force_raw) {
+ error_setg(errp, "Specifying force-raw is not supported when "
+ "loading memory values");
+ return;
+ } else if (!s->data_len) {
+ /* We cant' check for !data here as a value of 0 is still valid. */
+ error_setg(errp, "Both data and data-len must be specified");
+ return;
+ } else if (s->data_len > 8) {
+ error_setg(errp, "data-len cannot be greater then 8 bytes");
+ return;
+ }
+ } else if (s->file || s->force_raw) {
+ /* User is loading an image */
+ if (s->data || s->data_len || s->data_be) {
+ error_setg(errp, "data can not be specified when loading an "
+ "image");
+ return;
+ }
+ s->set_pc = true;
+ } else if (s->addr) {
+ /* User is setting the PC */
+ if (s->data || s->data_len || s->data_be) {
+ error_setg(errp, "data can not be specified when setting a "
+ "program counter");
+ return;
+ } else if (!s->cpu_num) {
+ error_setg(errp, "cpu_num must be specified when setting a "
+ "program counter");
+ return;
+ }
+ s->set_pc = true;
+ } else {
+ /* Did the user specify anything? */
+ error_setg(errp, "please include valid arguments");
+ return;
+ }
+
+ qemu_register_reset(generic_loader_reset, dev);
+
+ if (s->cpu_num != CPU_NONE) {
+ s->cpu = qemu_get_cpu(s->cpu_num);
+ if (!s->cpu) {
+ error_setg(errp, "Specified boot CPU#%d is nonexistent",
+ s->cpu_num);
+ return;
+ }
+ } else {
+ s->cpu = first_cpu;
+ }
+
+#ifdef TARGET_WORDS_BIGENDIAN
+ big_endian = 1;
+#else
+ big_endian = 0;
+#endif
+
+ if (s->file) {
+ if (!s->force_raw) {
+ size = load_elf_as(s->file, NULL, NULL, &entry, NULL, NULL,
+ big_endian, 0, 0, 0, s->cpu->as);
+
+ if (size < 0) {
+ size = load_uimage_as(s->file, &entry, NULL, NULL, NULL, NULL,
+ s->cpu->as);
+ }
+ }
+
+ if (size < 0 || s->force_raw) {
+ /* Default to the maximum size being the machine's ram size */
+ size = load_image_targphys_as(s->file, s->addr, ram_size,
+ s->cpu->as);
+ } else {
+ s->addr = entry;
+ }
+
+ if (size < 0) {
+ error_setg(errp, "Cannot load specified image %s", s->file);
+ return;
+ }
+ }
+
+ /* Convert the data endiannes */
+ if (s->data_be) {
+ s->data = cpu_to_be64(s->data);
+ } else {
+ s->data = cpu_to_le64(s->data);
+ }
+}
+
+static void generic_loader_unrealize(DeviceState *dev, Error **errp)
+{
+ qemu_unregister_reset(generic_loader_reset, dev);
+}
+
+static Property generic_loader_props[] = {
+ DEFINE_PROP_UINT64("addr", GenericLoaderState, addr, 0),
+ DEFINE_PROP_UINT64("data", GenericLoaderState, data, 0),
+ DEFINE_PROP_UINT8("data-len", GenericLoaderState, data_len, 0),
+ DEFINE_PROP_BOOL("data-be", GenericLoaderState, data_be, false),
+ DEFINE_PROP_UINT32("cpu-num", GenericLoaderState, cpu_num, CPU_NONE),
+ DEFINE_PROP_BOOL("force-raw", GenericLoaderState, force_raw, false),
+ DEFINE_PROP_STRING("file", GenericLoaderState, file),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void generic_loader_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ /* The reset function is not registered here and is instead registered in
+ * the realize function to allow this device to be added via the device_add
+ * command in the QEMU monitor.
+ * TODO: Improve the device_add functionality to allow resets to be
+ * connected
+ */
+ dc->realize = generic_loader_realize;
+ dc->unrealize = generic_loader_unrealize;
+ dc->props = generic_loader_props;
+ dc->desc = "Generic Loader";
+}
+
+static TypeInfo generic_loader_info = {
+ .name = TYPE_GENERIC_LOADER,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(GenericLoaderState),
+ .class_init = generic_loader_class_init,
+};
+
+static void generic_loader_register_type(void)
+{
+ type_register_static(&generic_loader_info);
+}
+
+type_init(generic_loader_register_type)
diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c
new file mode 100644
index 0000000000..1ac090d1a4
--- /dev/null
+++ b/hw/core/or-irq.c
@@ -0,0 +1,107 @@
+/*
+ * QEMU IRQ/GPIO common code.
+ *
+ * Copyright (c) 2016 Alistair Francis <alistair@alistair23.me>.
+ *
+ * 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/or-irq.h"
+
+static void or_irq_handler(void *opaque, int n, int level)
+{
+ qemu_or_irq *s = OR_IRQ(opaque);
+ int or_level = 0;
+ int i;
+
+ s->levels[n] = level;
+
+ for (i = 0; i < s->num_lines; i++) {
+ or_level |= s->levels[i];
+ }
+
+ qemu_set_irq(s->out_irq, or_level);
+}
+
+static void or_irq_reset(DeviceState *dev)
+{
+ qemu_or_irq *s = OR_IRQ(dev);
+ int i;
+
+ for (i = 0; i < MAX_OR_LINES; i++) {
+ s->levels[i] = false;
+ }
+}
+
+static void or_irq_realize(DeviceState *dev, Error **errp)
+{
+ qemu_or_irq *s = OR_IRQ(dev);
+
+ assert(s->num_lines < MAX_OR_LINES);
+
+ qdev_init_gpio_in(dev, or_irq_handler, s->num_lines);
+}
+
+static void or_irq_init(Object *obj)
+{
+ qemu_or_irq *s = OR_IRQ(obj);
+
+ qdev_init_gpio_out(DEVICE(obj), &s->out_irq, 1);
+}
+
+static const VMStateDescription vmstate_or_irq = {
+ .name = TYPE_OR_IRQ,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_BOOL_ARRAY(levels, qemu_or_irq, MAX_OR_LINES),
+ VMSTATE_END_OF_LIST(),
+ }
+};
+
+static Property or_irq_properties[] = {
+ DEFINE_PROP_UINT16("num-lines", qemu_or_irq, num_lines, 1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void or_irq_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = or_irq_reset;
+ dc->props = or_irq_properties;
+ dc->realize = or_irq_realize;
+ dc->vmsd = &vmstate_or_irq;
+}
+
+static const TypeInfo or_irq_type_info = {
+ .name = TYPE_OR_IRQ,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(qemu_or_irq),
+ .instance_init = or_irq_init,
+ .class_init = or_irq_class_init,
+};
+
+static void or_irq_register_types(void)
+{
+ type_register_static(&or_irq_type_info);
+}
+
+type_init(or_irq_register_types)
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index 2f2576fafb..17c8518fea 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -616,34 +616,9 @@ static void rc4030_reset(DeviceState *dev)
qemu_irq_lower(s->jazz_bus_irq);
}
-static int rc4030_load(QEMUFile *f, void *opaque, int version_id)
+static int rc4030_post_load(void *opaque, int version_id)
{
rc4030State* s = opaque;
- int i, j;
-
- if (version_id != 2)
- return -EINVAL;
-
- s->config = qemu_get_be32(f);
- s->invalid_address_register = qemu_get_be32(f);
- for (i = 0; i < 8; i++)
- for (j = 0; j < 4; j++)
- s->dma_regs[i][j] = qemu_get_be32(f);
- s->dma_tl_base = qemu_get_be32(f);
- s->dma_tl_limit = qemu_get_be32(f);
- s->cache_maint = qemu_get_be32(f);
- s->remote_failed_address = qemu_get_be32(f);
- s->memory_failed_address = qemu_get_be32(f);
- s->cache_ptag = qemu_get_be32(f);
- s->cache_ltag = qemu_get_be32(f);
- s->cache_bmask = qemu_get_be32(f);
- s->memory_refresh_rate = qemu_get_be32(f);
- s->nvram_protect = qemu_get_be32(f);
- for (i = 0; i < 15; i++)
- s->rem_speed[i] = qemu_get_be32(f);
- s->imr_jazz = qemu_get_be32(f);
- s->isr_jazz = qemu_get_be32(f);
- s->itr = qemu_get_be32(f);
set_next_tick(s);
update_jazz_irq(s);
@@ -651,32 +626,31 @@ static int rc4030_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
-static void rc4030_save(QEMUFile *f, void *opaque)
-{
- rc4030State* s = opaque;
- int i, j;
-
- qemu_put_be32(f, s->config);
- qemu_put_be32(f, s->invalid_address_register);
- for (i = 0; i < 8; i++)
- for (j = 0; j < 4; j++)
- qemu_put_be32(f, s->dma_regs[i][j]);
- qemu_put_be32(f, s->dma_tl_base);
- qemu_put_be32(f, s->dma_tl_limit);
- qemu_put_be32(f, s->cache_maint);
- qemu_put_be32(f, s->remote_failed_address);
- qemu_put_be32(f, s->memory_failed_address);
- qemu_put_be32(f, s->cache_ptag);
- qemu_put_be32(f, s->cache_ltag);
- qemu_put_be32(f, s->cache_bmask);
- qemu_put_be32(f, s->memory_refresh_rate);
- qemu_put_be32(f, s->nvram_protect);
- for (i = 0; i < 15; i++)
- qemu_put_be32(f, s->rem_speed[i]);
- qemu_put_be32(f, s->imr_jazz);
- qemu_put_be32(f, s->isr_jazz);
- qemu_put_be32(f, s->itr);
-}
+static const VMStateDescription vmstate_rc4030 = {
+ .name = "rc4030",
+ .version_id = 3,
+ .post_load = rc4030_post_load,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32(config, rc4030State),
+ VMSTATE_UINT32(invalid_address_register, rc4030State),
+ VMSTATE_UINT32_2DARRAY(dma_regs, rc4030State, 8, 4),
+ VMSTATE_UINT32(dma_tl_base, rc4030State),
+ VMSTATE_UINT32(dma_tl_limit, rc4030State),
+ VMSTATE_UINT32(cache_maint, rc4030State),
+ VMSTATE_UINT32(remote_failed_address, rc4030State),
+ VMSTATE_UINT32(memory_failed_address, rc4030State),
+ VMSTATE_UINT32(cache_ptag, rc4030State),
+ VMSTATE_UINT32(cache_ltag, rc4030State),
+ VMSTATE_UINT32(cache_bmask, rc4030State),
+ VMSTATE_UINT32(memory_refresh_rate, rc4030State),
+ VMSTATE_UINT32(nvram_protect, rc4030State),
+ VMSTATE_UINT32_ARRAY(rem_speed, rc4030State, 16),
+ VMSTATE_UINT32(imr_jazz, rc4030State),
+ VMSTATE_UINT32(isr_jazz, rc4030State),
+ VMSTATE_UINT32(itr, rc4030State),
+ VMSTATE_END_OF_LIST()
+ }
+};
static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, int is_write)
{
@@ -753,8 +727,6 @@ static void rc4030_initfn(Object *obj)
sysbus_init_irq(sysbus, &s->timer_irq);
sysbus_init_irq(sysbus, &s->jazz_bus_irq);
- register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s);
-
sysbus_init_mmio(sysbus, &s->iomem_chipset);
sysbus_init_mmio(sysbus, &s->iomem_jazzio);
}
@@ -813,6 +785,7 @@ static void rc4030_class_init(ObjectClass *klass, void *class_data)
dc->realize = rc4030_realize;
dc->unrealize = rc4030_unrealize;
dc->reset = rc4030_reset;
+ dc->vmsd = &vmstate_rc4030;
}
static const TypeInfo rc4030_info = {
diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c
index aa7839324c..f85635cc9a 100644
--- a/hw/i386/xen/xen_platform.c
+++ b/hw/i386/xen/xen_platform.c
@@ -134,8 +134,6 @@ static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t v
devices, and bit 2 the non-primary-master IDE devices. */
if (val & UNPLUG_ALL_IDE_DISKS) {
DPRINTF("unplug disks\n");
- blk_drain_all();
- blk_flush_all();
pci_unplug_disks(pci_dev->bus);
}
if (val & UNPLUG_ALL_NICS) {
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index c190fcaa3c..d5777fd0b3 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -179,6 +179,10 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
if (di != NULL && !di->media_cd) {
BlockBackend *blk = blk_by_legacy_dinfo(di);
DeviceState *ds = blk_get_attached_dev(blk);
+
+ blk_drain(blk);
+ blk_flush(blk);
+
if (ds) {
blk_detach_dev(blk, ds);
}
diff --git a/hw/input/tsc2005.c b/hw/input/tsc2005.c
index 9b359aaec0..eb5320af40 100644
--- a/hw/input/tsc2005.c
+++ b/hw/input/tsc2005.c
@@ -31,30 +31,31 @@ typedef struct {
QEMUTimer *timer;
uint16_t model;
- int x, y;
- int pressure;
+ int32_t x, y;
+ bool pressure;
- int state, reg, irq, command;
+ uint8_t reg, state;
+ bool irq, command;
uint16_t data, dav;
- int busy;
- int enabled;
- int host_mode;
- int function;
- int nextfunction;
- int precision;
- int nextprecision;
- int filter;
- int pin_func;
- int timing[2];
- int noise;
- int reset;
- int pdst;
- int pnd0;
+ bool busy;
+ bool enabled;
+ bool host_mode;
+ int8_t function;
+ int8_t nextfunction;
+ bool precision;
+ bool nextprecision;
+ uint16_t filter;
+ uint8_t pin_func;
+ uint16_t timing[2];
+ uint8_t noise;
+ bool reset;
+ bool pdst;
+ bool pnd0;
uint16_t temp_thr[2];
uint16_t aux_thr[2];
- int tr[8];
+ int32_t tr[8];
} TSC2005State;
enum {
@@ -149,7 +150,7 @@ static uint16_t tsc2005_read(TSC2005State *s, int reg)
ret = s->dav | (s->reset << 7) | (s->pdst << 2) | 0x0;
s->dav &= ~(mode_regs[TSC_MODE_X_TEST] | mode_regs[TSC_MODE_Y_TEST] |
mode_regs[TSC_MODE_TS_TEST]);
- s->reset = 1;
+ s->reset = true;
return ret;
case 0x8: /* AUX high treshold */
@@ -196,14 +197,14 @@ static void tsc2005_write(TSC2005State *s, int reg, uint16_t data)
break;
case 0xc: /* CFR0 */
- s->host_mode = data >> 15;
+ s->host_mode = (data >> 15) != 0;
if (s->enabled != !(data & 0x4000)) {
s->enabled = !(data & 0x4000);
fprintf(stderr, "%s: touchscreen sense %sabled\n",
__FUNCTION__, s->enabled ? "en" : "dis");
if (s->busy && !s->enabled)
timer_del(s->timer);
- s->busy &= s->enabled;
+ s->busy = s->busy && s->enabled;
}
s->nextprecision = (data >> 13) & 1;
s->timing[0] = data & 0x1fff;
@@ -229,7 +230,7 @@ static void tsc2005_write(TSC2005State *s, int reg, uint16_t data)
static void tsc2005_pin_update(TSC2005State *s)
{
int64_t expires;
- int pin_state;
+ bool pin_state;
switch (s->pin_func) {
case 0:
@@ -253,7 +254,7 @@ static void tsc2005_pin_update(TSC2005State *s)
case TSC_MODE_XYZ_SCAN:
case TSC_MODE_XY_SCAN:
if (!s->host_mode && s->dav)
- s->enabled = 0;
+ s->enabled = false;
if (!s->pressure)
return;
/* Fall through */
@@ -273,7 +274,7 @@ static void tsc2005_pin_update(TSC2005State *s)
case TSC_MODE_Y_TEST:
case TSC_MODE_TS_TEST:
if (s->dav)
- s->enabled = 0;
+ s->enabled = false;
break;
case TSC_MODE_RESERVED:
@@ -287,7 +288,7 @@ static void tsc2005_pin_update(TSC2005State *s)
if (!s->enabled || s->busy)
return;
- s->busy = 1;
+ s->busy = true;
s->precision = s->nextprecision;
s->function = s->nextfunction;
s->pdst = !s->pnd0; /* Synchronised on internal clock */
@@ -300,17 +301,17 @@ static void tsc2005_reset(TSC2005State *s)
{
s->state = 0;
s->pin_func = 0;
- s->enabled = 0;
- s->busy = 0;
- s->nextprecision = 0;
+ s->enabled = false;
+ s->busy = false;
+ s->nextprecision = false;
s->nextfunction = 0;
s->timing[0] = 0;
s->timing[1] = 0;
- s->irq = 0;
+ s->irq = false;
s->dav = 0;
- s->reset = 0;
- s->pdst = 1;
- s->pnd0 = 0;
+ s->reset = false;
+ s->pdst = true;
+ s->pnd0 = false;
s->function = -1;
s->temp_thr[0] = 0x000;
s->temp_thr[1] = 0xfff;
@@ -340,7 +341,7 @@ static uint8_t tsc2005_txrx_word(void *opaque, uint8_t value)
__FUNCTION__, s->enabled ? "en" : "dis");
if (s->busy && !s->enabled)
timer_del(s->timer);
- s->busy &= s->enabled;
+ s->busy = s->busy && s->enabled;
}
tsc2005_pin_update(s);
}
@@ -407,7 +408,7 @@ static void tsc2005_timer_tick(void *opaque)
if (!s->busy)
return;
- s->busy = 0;
+ s->busy = false;
s->dav |= mode_regs[s->function];
s->function = -1;
tsc2005_pin_update(s);
@@ -434,86 +435,9 @@ static void tsc2005_touchscreen_event(void *opaque,
tsc2005_pin_update(s);
}
-static void tsc2005_save(QEMUFile *f, void *opaque)
+static int tsc2005_post_load(void *opaque, int version_id)
{
TSC2005State *s = (TSC2005State *) opaque;
- int i;
-
- qemu_put_be16(f, s->x);
- qemu_put_be16(f, s->y);
- qemu_put_byte(f, s->pressure);
-
- qemu_put_byte(f, s->state);
- qemu_put_byte(f, s->reg);
- qemu_put_byte(f, s->command);
-
- qemu_put_byte(f, s->irq);
- qemu_put_be16s(f, &s->dav);
- qemu_put_be16s(f, &s->data);
-
- timer_put(f, s->timer);
- qemu_put_byte(f, s->enabled);
- qemu_put_byte(f, s->host_mode);
- qemu_put_byte(f, s->function);
- qemu_put_byte(f, s->nextfunction);
- qemu_put_byte(f, s->precision);
- qemu_put_byte(f, s->nextprecision);
- qemu_put_be16(f, s->filter);
- qemu_put_byte(f, s->pin_func);
- qemu_put_be16(f, s->timing[0]);
- qemu_put_be16(f, s->timing[1]);
- qemu_put_be16s(f, &s->temp_thr[0]);
- qemu_put_be16s(f, &s->temp_thr[1]);
- qemu_put_be16s(f, &s->aux_thr[0]);
- qemu_put_be16s(f, &s->aux_thr[1]);
- qemu_put_be32(f, s->noise);
- qemu_put_byte(f, s->reset);
- qemu_put_byte(f, s->pdst);
- qemu_put_byte(f, s->pnd0);
-
- for (i = 0; i < 8; i ++)
- qemu_put_be32(f, s->tr[i]);
-}
-
-static int tsc2005_load(QEMUFile *f, void *opaque, int version_id)
-{
- TSC2005State *s = (TSC2005State *) opaque;
- int i;
-
- s->x = qemu_get_be16(f);
- s->y = qemu_get_be16(f);
- s->pressure = qemu_get_byte(f);
-
- s->state = qemu_get_byte(f);
- s->reg = qemu_get_byte(f);
- s->command = qemu_get_byte(f);
-
- s->irq = qemu_get_byte(f);
- qemu_get_be16s(f, &s->dav);
- qemu_get_be16s(f, &s->data);
-
- timer_get(f, s->timer);
- s->enabled = qemu_get_byte(f);
- s->host_mode = qemu_get_byte(f);
- s->function = qemu_get_byte(f);
- s->nextfunction = qemu_get_byte(f);
- s->precision = qemu_get_byte(f);
- s->nextprecision = qemu_get_byte(f);
- s->filter = qemu_get_be16(f);
- s->pin_func = qemu_get_byte(f);
- s->timing[0] = qemu_get_be16(f);
- s->timing[1] = qemu_get_be16(f);
- qemu_get_be16s(f, &s->temp_thr[0]);
- qemu_get_be16s(f, &s->temp_thr[1]);
- qemu_get_be16s(f, &s->aux_thr[0]);
- qemu_get_be16s(f, &s->aux_thr[1]);
- s->noise = qemu_get_be32(f);
- s->reset = qemu_get_byte(f);
- s->pdst = qemu_get_byte(f);
- s->pnd0 = qemu_get_byte(f);
-
- for (i = 0; i < 8; i ++)
- s->tr[i] = qemu_get_be32(f);
s->busy = timer_pending(s->timer);
tsc2005_pin_update(s);
@@ -521,6 +445,42 @@ static int tsc2005_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
+static const VMStateDescription vmstate_tsc2005 = {
+ .name = "tsc2005",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .post_load = tsc2005_post_load,
+ .fields = (VMStateField []) {
+ VMSTATE_BOOL(pressure, TSC2005State),
+ VMSTATE_BOOL(irq, TSC2005State),
+ VMSTATE_BOOL(command, TSC2005State),
+ VMSTATE_BOOL(enabled, TSC2005State),
+ VMSTATE_BOOL(host_mode, TSC2005State),
+ VMSTATE_BOOL(reset, TSC2005State),
+ VMSTATE_BOOL(pdst, TSC2005State),
+ VMSTATE_BOOL(pnd0, TSC2005State),
+ VMSTATE_BOOL(precision, TSC2005State),
+ VMSTATE_BOOL(nextprecision, TSC2005State),
+ VMSTATE_UINT8(reg, TSC2005State),
+ VMSTATE_UINT8(state, TSC2005State),
+ VMSTATE_UINT16(data, TSC2005State),
+ VMSTATE_UINT16(dav, TSC2005State),
+ VMSTATE_UINT16(filter, TSC2005State),
+ VMSTATE_INT8(nextfunction, TSC2005State),
+ VMSTATE_INT8(function, TSC2005State),
+ VMSTATE_INT32(x, TSC2005State),
+ VMSTATE_INT32(y, TSC2005State),
+ VMSTATE_TIMER_PTR(timer, TSC2005State),
+ VMSTATE_UINT8(pin_func, TSC2005State),
+ VMSTATE_UINT16_ARRAY(timing, TSC2005State, 2),
+ VMSTATE_UINT8(noise, TSC2005State),
+ VMSTATE_UINT16_ARRAY(temp_thr, TSC2005State, 2),
+ VMSTATE_UINT16_ARRAY(aux_thr, TSC2005State, 2),
+ VMSTATE_INT32_ARRAY(tr, TSC2005State, 8),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
void *tsc2005_init(qemu_irq pintdav)
{
TSC2005State *s;
@@ -529,8 +489,8 @@ void *tsc2005_init(qemu_irq pintdav)
g_malloc0(sizeof(TSC2005State));
s->x = 400;
s->y = 240;
- s->pressure = 0;
- s->precision = s->nextprecision = 0;
+ s->pressure = false;
+ s->precision = s->nextprecision = false;
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tsc2005_timer_tick, s);
s->pint = pintdav;
s->model = 0x2005;
@@ -550,7 +510,7 @@ void *tsc2005_init(qemu_irq pintdav)
"QEMU TSC2005-driven Touchscreen");
qemu_register_reset((void *) tsc2005_reset, s);
- register_savevm(NULL, "tsc2005", -1, 0, tsc2005_save, tsc2005_load, s);
+ vmstate_register(NULL, 0, &vmstate_tsc2005, s);
return s;
}
diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c
index 93ca374fcd..b068343771 100644
--- a/hw/input/tsc210x.c
+++ b/hw/input/tsc210x.c
@@ -47,24 +47,25 @@ typedef struct {
uint8_t out_fifo[16384];
uint16_t model;
- int x, y;
- int pressure;
-
- int state, page, offset, irq;
- uint16_t command, dav;
-
- int busy;
- int enabled;
- int host_mode;
- int function;
- int nextfunction;
- int precision;
- int nextprecision;
- int filter;
- int pin_func;
- int ref;
- int timing;
- int noise;
+ int32_t x, y;
+ bool pressure;
+
+ uint8_t page, offset;
+ uint16_t dav;
+
+ bool state;
+ bool irq;
+ bool command;
+ bool busy;
+ bool enabled;
+ bool host_mode;
+ uint8_t function, nextfunction;
+ uint8_t precision, nextprecision;
+ uint8_t filter;
+ uint8_t pin_func;
+ uint8_t ref;
+ uint8_t timing;
+ uint8_t noise;
uint16_t audio_ctrl1;
uint16_t audio_ctrl2;
@@ -72,7 +73,7 @@ typedef struct {
uint16_t pll[3];
uint16_t volume;
int64_t volume_change;
- int softstep;
+ bool softstep;
uint16_t dac_power;
int64_t powerdown;
uint16_t filter_data[0x14];
@@ -93,6 +94,7 @@ typedef struct {
int mode;
int intr;
} kb;
+ int64_t now; /* Time at migration */
} TSC210xState;
static const int resolution[4] = { 12, 8, 10, 12 };
@@ -154,14 +156,14 @@ static const uint16_t mode_regs[16] = {
static void tsc210x_reset(TSC210xState *s)
{
- s->state = 0;
+ s->state = false;
s->pin_func = 2;
- s->enabled = 0;
- s->busy = 0;
+ s->enabled = false;
+ s->busy = false;
s->nextfunction = 0;
s->ref = 0;
s->timing = 0;
- s->irq = 0;
+ s->irq = false;
s->dav = 0;
s->audio_ctrl1 = 0x0000;
@@ -172,7 +174,7 @@ static void tsc210x_reset(TSC210xState *s)
s->pll[2] = 0x1fff;
s->volume = 0xffff;
s->dac_power = 0x8540;
- s->softstep = 1;
+ s->softstep = true;
s->volume_change = 0;
s->powerdown = 0;
s->filter_data[0x00] = 0x6be3;
@@ -566,7 +568,7 @@ static void tsc2102_control_register_write(
s->enabled = !(value & 0x4000);
if (s->busy && !s->enabled)
timer_del(s->timer);
- s->busy &= s->enabled;
+ s->busy = s->busy && s->enabled;
s->nextfunction = (value >> 10) & 0xf;
s->nextprecision = (value >> 8) & 3;
s->filter = value & 0xff;
@@ -773,7 +775,7 @@ static void tsc2102_audio_register_write(
static void tsc210x_pin_update(TSC210xState *s)
{
int64_t expires;
- int pin_state;
+ bool pin_state;
switch (s->pin_func) {
case 0:
@@ -788,7 +790,7 @@ static void tsc210x_pin_update(TSC210xState *s)
}
if (!s->enabled)
- pin_state = 0;
+ pin_state = false;
if (pin_state != s->irq) {
s->irq = pin_state;
@@ -814,7 +816,7 @@ static void tsc210x_pin_update(TSC210xState *s)
case TSC_MODE_TEMP1:
case TSC_MODE_TEMP2:
if (s->dav)
- s->enabled = 0;
+ s->enabled = false;
break;
case TSC_MODE_AUX_SCAN:
@@ -832,7 +834,7 @@ static void tsc210x_pin_update(TSC210xState *s)
if (!s->enabled || s->busy || s->dav)
return;
- s->busy = 1;
+ s->busy = true;
s->precision = s->nextprecision;
s->function = s->nextfunction;
expires = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
@@ -867,7 +869,7 @@ static uint16_t tsc210x_read(TSC210xState *s)
/* Allow sequential reads. */
s->offset ++;
- s->state = 0;
+ s->state = false;
return ret;
}
@@ -878,10 +880,10 @@ static void tsc210x_write(TSC210xState *s, uint16_t value)
* command and data every second time.
*/
if (!s->state) {
- s->command = value >> 15;
+ s->command = (value >> 15) != 0;
s->page = (value >> 11) & 0x0f;
s->offset = (value >> 5) & 0x3f;
- s->state = 1;
+ s->state = true;
} else {
if (s->command)
fprintf(stderr, "tsc210x_write: SPI overrun!\n");
@@ -901,7 +903,7 @@ static void tsc210x_write(TSC210xState *s, uint16_t value)
}
tsc210x_pin_update(s);
- s->state = 0;
+ s->state = false;
}
}
@@ -933,7 +935,7 @@ static void tsc210x_timer_tick(void *opaque)
if (!s->busy)
return;
- s->busy = 0;
+ s->busy = false;
s->dav |= mode_regs[s->function];
tsc210x_pin_update(s);
qemu_irq_lower(s->davint);
@@ -974,108 +976,34 @@ static void tsc210x_i2s_set_rate(TSC210xState *s, int in, int out)
s->i2s_rx_rate = in;
}
-static void tsc210x_save(QEMUFile *f, void *opaque)
+static void tsc210x_pre_save(void *opaque)
{
TSC210xState *s = (TSC210xState *) opaque;
- int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- int i;
-
- qemu_put_be16(f, s->x);
- qemu_put_be16(f, s->y);
- qemu_put_byte(f, s->pressure);
-
- qemu_put_byte(f, s->state);
- qemu_put_byte(f, s->page);
- qemu_put_byte(f, s->offset);
- qemu_put_byte(f, s->command);
-
- qemu_put_byte(f, s->irq);
- qemu_put_be16s(f, &s->dav);
-
- timer_put(f, s->timer);
- qemu_put_byte(f, s->enabled);
- qemu_put_byte(f, s->host_mode);
- qemu_put_byte(f, s->function);
- qemu_put_byte(f, s->nextfunction);
- qemu_put_byte(f, s->precision);
- qemu_put_byte(f, s->nextprecision);
- qemu_put_byte(f, s->filter);
- qemu_put_byte(f, s->pin_func);
- qemu_put_byte(f, s->ref);
- qemu_put_byte(f, s->timing);
- qemu_put_be32(f, s->noise);
-
- qemu_put_be16s(f, &s->audio_ctrl1);
- qemu_put_be16s(f, &s->audio_ctrl2);
- qemu_put_be16s(f, &s->audio_ctrl3);
- qemu_put_be16s(f, &s->pll[0]);
- qemu_put_be16s(f, &s->pll[1]);
- qemu_put_be16s(f, &s->volume);
- qemu_put_sbe64(f, (s->volume_change - now));
- qemu_put_sbe64(f, (s->powerdown - now));
- qemu_put_byte(f, s->softstep);
- qemu_put_be16s(f, &s->dac_power);
-
- for (i = 0; i < 0x14; i ++)
- qemu_put_be16s(f, &s->filter_data[i]);
+ s->now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
-static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
+static int tsc210x_post_load(void *opaque, int version_id)
{
TSC210xState *s = (TSC210xState *) opaque;
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- int i;
-
- s->x = qemu_get_be16(f);
- s->y = qemu_get_be16(f);
- s->pressure = qemu_get_byte(f);
-
- s->state = qemu_get_byte(f);
- s->page = qemu_get_byte(f);
- s->offset = qemu_get_byte(f);
- s->command = qemu_get_byte(f);
- s->irq = qemu_get_byte(f);
- qemu_get_be16s(f, &s->dav);
-
- timer_get(f, s->timer);
- s->enabled = qemu_get_byte(f);
- s->host_mode = qemu_get_byte(f);
- s->function = qemu_get_byte(f);
- if (s->function < 0 || s->function >= ARRAY_SIZE(mode_regs)) {
+ if (s->function >= ARRAY_SIZE(mode_regs)) {
return -EINVAL;
}
- s->nextfunction = qemu_get_byte(f);
- if (s->nextfunction < 0 || s->nextfunction >= ARRAY_SIZE(mode_regs)) {
+ if (s->nextfunction >= ARRAY_SIZE(mode_regs)) {
return -EINVAL;
}
- s->precision = qemu_get_byte(f);
- if (s->precision < 0 || s->precision >= ARRAY_SIZE(resolution)) {
+ if (s->precision >= ARRAY_SIZE(resolution)) {
return -EINVAL;
}
- s->nextprecision = qemu_get_byte(f);
- if (s->nextprecision < 0 || s->nextprecision >= ARRAY_SIZE(resolution)) {
+ if (s->nextprecision >= ARRAY_SIZE(resolution)) {
return -EINVAL;
}
- s->filter = qemu_get_byte(f);
- s->pin_func = qemu_get_byte(f);
- s->ref = qemu_get_byte(f);
- s->timing = qemu_get_byte(f);
- s->noise = qemu_get_be32(f);
-
- qemu_get_be16s(f, &s->audio_ctrl1);
- qemu_get_be16s(f, &s->audio_ctrl2);
- qemu_get_be16s(f, &s->audio_ctrl3);
- qemu_get_be16s(f, &s->pll[0]);
- qemu_get_be16s(f, &s->pll[1]);
- qemu_get_be16s(f, &s->volume);
- s->volume_change = qemu_get_sbe64(f) + now;
- s->powerdown = qemu_get_sbe64(f) + now;
- s->softstep = qemu_get_byte(f);
- qemu_get_be16s(f, &s->dac_power);
-
- for (i = 0; i < 0x14; i ++)
- qemu_get_be16s(f, &s->filter_data[i]);
+
+ s->volume_change -= s->now;
+ s->volume_change += now;
+ s->powerdown -= s->now;
+ s->powerdown += now;
s->busy = timer_pending(s->timer);
qemu_set_irq(s->pint, !s->irq);
@@ -1084,6 +1012,60 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
+static VMStateField vmstatefields_tsc210x[] = {
+ VMSTATE_BOOL(enabled, TSC210xState),
+ VMSTATE_BOOL(host_mode, TSC210xState),
+ VMSTATE_BOOL(irq, TSC210xState),
+ VMSTATE_BOOL(command, TSC210xState),
+ VMSTATE_BOOL(pressure, TSC210xState),
+ VMSTATE_BOOL(softstep, TSC210xState),
+ VMSTATE_BOOL(state, TSC210xState),
+ VMSTATE_UINT16(dav, TSC210xState),
+ VMSTATE_INT32(x, TSC210xState),
+ VMSTATE_INT32(y, TSC210xState),
+ VMSTATE_UINT8(offset, TSC210xState),
+ VMSTATE_UINT8(page, TSC210xState),
+ VMSTATE_UINT8(filter, TSC210xState),
+ VMSTATE_UINT8(pin_func, TSC210xState),
+ VMSTATE_UINT8(ref, TSC210xState),
+ VMSTATE_UINT8(timing, TSC210xState),
+ VMSTATE_UINT8(noise, TSC210xState),
+ VMSTATE_UINT8(function, TSC210xState),
+ VMSTATE_UINT8(nextfunction, TSC210xState),
+ VMSTATE_UINT8(precision, TSC210xState),
+ VMSTATE_UINT8(nextprecision, TSC210xState),
+ VMSTATE_UINT16(audio_ctrl1, TSC210xState),
+ VMSTATE_UINT16(audio_ctrl2, TSC210xState),
+ VMSTATE_UINT16(audio_ctrl3, TSC210xState),
+ VMSTATE_UINT16_ARRAY(pll, TSC210xState, 3),
+ VMSTATE_UINT16(volume, TSC210xState),
+ VMSTATE_UINT16(dac_power, TSC210xState),
+ VMSTATE_INT64(volume_change, TSC210xState),
+ VMSTATE_INT64(powerdown, TSC210xState),
+ VMSTATE_INT64(now, TSC210xState),
+ VMSTATE_UINT16_ARRAY(filter_data, TSC210xState, 0x14),
+ VMSTATE_TIMER_PTR(timer, TSC210xState),
+ VMSTATE_END_OF_LIST()
+};
+
+static const VMStateDescription vmstate_tsc2102 = {
+ .name = "tsc2102",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .pre_save = tsc210x_pre_save,
+ .post_load = tsc210x_post_load,
+ .fields = vmstatefields_tsc210x,
+};
+
+static const VMStateDescription vmstate_tsc2301 = {
+ .name = "tsc2301",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .pre_save = tsc210x_pre_save,
+ .post_load = tsc210x_post_load,
+ .fields = vmstatefields_tsc210x,
+};
+
uWireSlave *tsc2102_init(qemu_irq pint)
{
TSC210xState *s;
@@ -1125,8 +1107,7 @@ uWireSlave *tsc2102_init(qemu_irq pint)
AUD_register_card(s->name, &s->card);
qemu_register_reset((void *) tsc210x_reset, s);
- register_savevm(NULL, s->name, -1, 0,
- tsc210x_save, tsc210x_load, s);
+ vmstate_register(NULL, 0, &vmstate_tsc2102, s);
return &s->chip;
}
@@ -1174,7 +1155,7 @@ uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav)
AUD_register_card(s->name, &s->card);
qemu_register_reset((void *) tsc210x_reset, s);
- register_savevm(NULL, s->name, -1, 0, tsc210x_save, tsc210x_load, s);
+ vmstate_register(NULL, 0, &vmstate_tsc2301, s);
return &s->chip;
}
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index f24c837118..2f44a2da26 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -16,12 +16,14 @@ common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_common.o
common-obj-$(CONFIG_ARM_GIC) += arm_gicv3.o
common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_dist.o
common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_redist.o
+common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_its_common.o
common-obj-$(CONFIG_OPENPIC) += openpic.o
common-obj-y += intc.o
obj-$(CONFIG_APIC) += apic.o apic_common.o
obj-$(CONFIG_ARM_GIC_KVM) += arm_gic_kvm.o
obj-$(call land,$(CONFIG_ARM_GIC_KVM),$(TARGET_AARCH64)) += arm_gicv3_kvm.o
+obj-$(call land,$(CONFIG_ARM_GIC_KVM),$(TARGET_AARCH64)) += arm_gicv3_its_kvm.o
obj-$(CONFIG_STELLARIS) += armv7m_nvic.o
obj-$(CONFIG_EXYNOS4) += exynos4210_gic.o exynos4210_combiner.o
obj-$(CONFIG_GRLIB) += grlib_irqmp.o
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index 5593cdb3e4..ae7ac58ffd 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -577,6 +577,18 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
"not support vGICv2 migration");
migrate_add_blocker(s->migration_blocker);
}
+
+ if (kvm_has_gsi_routing()) {
+ /* set up irq routing */
+ kvm_init_irq_routing(kvm_state);
+ for (i = 0; i < s->num_irq - GIC_INTERNAL; ++i) {
+ kvm_irqchip_add_irq_route(kvm_state, i, 0, i);
+ }
+
+ kvm_gsi_routing_allowed = true;
+
+ kvm_irqchip_commit_routes(kvm_state);
+ }
}
static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)
diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c
new file mode 100644
index 0000000000..9d67c5c1ee
--- /dev/null
+++ b/hw/intc/arm_gicv3_its_common.c
@@ -0,0 +1,148 @@
+/*
+ * ITS base class for a GICv3-based system
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Written by Pavel Fedin
+ *
+ * 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 "hw/pci/msi.h"
+#include "hw/intc/arm_gicv3_its_common.h"
+#include "qemu/log.h"
+
+static void gicv3_its_pre_save(void *opaque)
+{
+ GICv3ITSState *s = (GICv3ITSState *)opaque;
+ GICv3ITSCommonClass *c = ARM_GICV3_ITS_COMMON_GET_CLASS(s);
+
+ if (c->pre_save) {
+ c->pre_save(s);
+ }
+}
+
+static int gicv3_its_post_load(void *opaque, int version_id)
+{
+ GICv3ITSState *s = (GICv3ITSState *)opaque;
+ GICv3ITSCommonClass *c = ARM_GICV3_ITS_COMMON_GET_CLASS(s);
+
+ if (c->post_load) {
+ c->post_load(s);
+ }
+ return 0;
+}
+
+static const VMStateDescription vmstate_its = {
+ .name = "arm_gicv3_its",
+ .pre_save = gicv3_its_pre_save,
+ .post_load = gicv3_its_post_load,
+ .unmigratable = true,
+};
+
+static MemTxResult gicv3_its_trans_read(void *opaque, hwaddr offset,
+ uint64_t *data, unsigned size,
+ MemTxAttrs attrs)
+{
+ qemu_log_mask(LOG_GUEST_ERROR, "ITS read at offset 0x%"PRIx64"\n", offset);
+ return MEMTX_ERROR;
+}
+
+static MemTxResult gicv3_its_trans_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size,
+ MemTxAttrs attrs)
+{
+ if (offset == 0x0040 && ((size == 2) || (size == 4))) {
+ GICv3ITSState *s = ARM_GICV3_ITS_COMMON(opaque);
+ GICv3ITSCommonClass *c = ARM_GICV3_ITS_COMMON_GET_CLASS(s);
+ int ret = c->send_msi(s, le64_to_cpu(value), attrs.requester_id);
+
+ if (ret <= 0) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "ITS: Error sending MSI: %s\n", strerror(-ret));
+ return MEMTX_DECODE_ERROR;
+ }
+
+ return MEMTX_OK;
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "ITS write at bad offset 0x%"PRIx64"\n", offset);
+ return MEMTX_DECODE_ERROR;
+ }
+}
+
+static const MemoryRegionOps gicv3_its_trans_ops = {
+ .read_with_attrs = gicv3_its_trans_read,
+ .write_with_attrs = gicv3_its_trans_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(s);
+
+ memory_region_init_io(&s->iomem_its_cntrl, OBJECT(s), ops, s,
+ "control", ITS_CONTROL_SIZE);
+ memory_region_init_io(&s->iomem_its_translation, OBJECT(s),
+ &gicv3_its_trans_ops, s,
+ "translation", ITS_TRANS_SIZE);
+
+ /* Our two regions are always adjacent, therefore we now combine them
+ * into a single one in order to make our users' life easier.
+ */
+ memory_region_init(&s->iomem_main, OBJECT(s), "gicv3_its", ITS_SIZE);
+ memory_region_add_subregion(&s->iomem_main, 0, &s->iomem_its_cntrl);
+ memory_region_add_subregion(&s->iomem_main, ITS_CONTROL_SIZE,
+ &s->iomem_its_translation);
+ sysbus_init_mmio(sbd, &s->iomem_main);
+
+ msi_nonbroken = true;
+}
+
+static void gicv3_its_common_reset(DeviceState *dev)
+{
+ GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
+
+ s->ctlr = 0;
+ s->cbaser = 0;
+ s->cwriter = 0;
+ s->creadr = 0;
+ memset(&s->baser, 0, sizeof(s->baser));
+
+ gicv3_its_post_load(s, 0);
+}
+
+static void gicv3_its_common_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = gicv3_its_common_reset;
+ dc->vmsd = &vmstate_its;
+}
+
+static const TypeInfo gicv3_its_common_info = {
+ .name = TYPE_ARM_GICV3_ITS_COMMON,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(GICv3ITSState),
+ .class_size = sizeof(GICv3ITSCommonClass),
+ .class_init = gicv3_its_common_class_init,
+ .abstract = true,
+};
+
+static void gicv3_its_common_register_types(void)
+{
+ type_register_static(&gicv3_its_common_info);
+}
+
+type_init(gicv3_its_common_register_types)
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
new file mode 100644
index 0000000000..fc246e0cb5
--- /dev/null
+++ b/hw/intc/arm_gicv3_its_kvm.c
@@ -0,0 +1,121 @@
+/*
+ * KVM-based ITS implementation for a GICv3-based system
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Written by Pavel Fedin <p.fedin@samsung.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 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 "hw/intc/arm_gicv3_its_common.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "kvm_arm.h"
+#include "migration/migration.h"
+
+#define TYPE_KVM_ARM_ITS "arm-its-kvm"
+#define KVM_ARM_ITS(obj) OBJECT_CHECK(GICv3ITSState, (obj), TYPE_KVM_ARM_ITS)
+
+static int kvm_its_send_msi(GICv3ITSState *s, uint32_t value, uint16_t devid)
+{
+ struct kvm_msi msi;
+
+ if (unlikely(!s->translater_gpa_known)) {
+ MemoryRegion *mr = &s->iomem_its_translation;
+ MemoryRegionSection mrs;
+
+ mrs = memory_region_find(mr, 0, 1);
+ memory_region_unref(mrs.mr);
+ s->gits_translater_gpa = mrs.offset_within_address_space + 0x40;
+ s->translater_gpa_known = true;
+ }
+
+ msi.address_lo = extract64(s->gits_translater_gpa, 0, 32);
+ msi.address_hi = extract64(s->gits_translater_gpa, 32, 32);
+ msi.data = le32_to_cpu(value);
+ msi.flags = KVM_MSI_VALID_DEVID;
+ msi.devid = devid;
+ memset(msi.pad, 0, sizeof(msi.pad));
+
+ return kvm_vm_ioctl(kvm_state, KVM_SIGNAL_MSI, &msi);
+}
+
+static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
+{
+ GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
+
+ s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_ITS, false);
+ if (s->dev_fd < 0) {
+ error_setg_errno(errp, -s->dev_fd, "error creating in-kernel ITS");
+ return;
+ }
+
+ /* explicit init of the ITS */
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
+ KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
+
+ /* register the base address */
+ kvm_arm_register_device(&s->iomem_its_cntrl, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
+ KVM_VGIC_ITS_ADDR_TYPE, s->dev_fd);
+
+ gicv3_its_init_mmio(s, NULL);
+
+ /*
+ * Block migration of a KVM GICv3 ITS device: the API for saving and
+ * restoring the state in the kernel is not yet available
+ */
+ error_setg(&s->migration_blocker, "vITS migration is not implemented");
+ migrate_add_blocker(s->migration_blocker);
+
+ kvm_msi_use_devid = true;
+ kvm_gsi_direct_mapping = false;
+ kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
+}
+
+static void kvm_arm_its_init(Object *obj)
+{
+ GICv3ITSState *s = KVM_ARM_ITS(obj);
+
+ object_property_add_link(obj, "parent-gicv3",
+ "kvm-arm-gicv3", (Object **)&s->gicv3,
+ object_property_allow_set_link,
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
+ &error_abort);
+}
+
+static void kvm_arm_its_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ GICv3ITSCommonClass *icc = ARM_GICV3_ITS_COMMON_CLASS(klass);
+
+ dc->realize = kvm_arm_its_realize;
+ icc->send_msi = kvm_its_send_msi;
+}
+
+static const TypeInfo kvm_arm_its_info = {
+ .name = TYPE_KVM_ARM_ITS,
+ .parent = TYPE_ARM_GICV3_ITS_COMMON,
+ .instance_size = sizeof(GICv3ITSState),
+ .instance_init = kvm_arm_its_init,
+ .class_init = kvm_arm_its_class_init,
+};
+
+static void kvm_arm_its_register_types(void)
+{
+ type_register_static(&kvm_arm_its_info);
+}
+
+type_init(kvm_arm_its_register_types)
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index 711fde38f3..199a439ccf 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -85,6 +85,7 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
GICv3State *s = KVM_ARM_GICV3(dev);
KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s);
Error *local_err = NULL;
+ int i;
DPRINTF("kvm_arm_gicv3_realize\n");
@@ -127,6 +128,18 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
*/
error_setg(&s->migration_blocker, "vGICv3 migration is not implemented");
migrate_add_blocker(s->migration_blocker);
+
+ if (kvm_has_gsi_routing()) {
+ /* set up irq routing */
+ kvm_init_irq_routing(kvm_state);
+ for (i = 0; i < s->num_irq - GIC_INTERNAL; ++i) {
+ kvm_irqchip_add_irq_route(kvm_state, i, 0, i);
+ }
+
+ kvm_gsi_routing_allowed = true;
+
+ kvm_irqchip_commit_routes(kvm_state);
+ }
}
static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data)
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index 8618e7acac..7915732f74 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -147,25 +147,19 @@
#define GEM_INT_Q1_MASK (0x00000640 / 4)
#define GEM_TRANSMIT_Q1_PTR (0x00000440 / 4)
-#define GEM_TRANSMIT_Q15_PTR (GEM_TRANSMIT_Q1_PTR + 14)
+#define GEM_TRANSMIT_Q7_PTR (GEM_TRANSMIT_Q1_PTR + 6)
#define GEM_RECEIVE_Q1_PTR (0x00000480 / 4)
-#define GEM_RECEIVE_Q15_PTR (GEM_RECEIVE_Q1_PTR + 14)
+#define GEM_RECEIVE_Q7_PTR (GEM_RECEIVE_Q1_PTR + 6)
#define GEM_INT_Q1_ENABLE (0x00000600 / 4)
#define GEM_INT_Q7_ENABLE (GEM_INT_Q1_ENABLE + 6)
-#define GEM_INT_Q8_ENABLE (0x00000660 / 4)
-#define GEM_INT_Q15_ENABLE (GEM_INT_Q8_ENABLE + 7)
#define GEM_INT_Q1_DISABLE (0x00000620 / 4)
#define GEM_INT_Q7_DISABLE (GEM_INT_Q1_DISABLE + 6)
-#define GEM_INT_Q8_DISABLE (0x00000680 / 4)
-#define GEM_INT_Q15_DISABLE (GEM_INT_Q8_DISABLE + 7)
#define GEM_INT_Q1_MASK (0x00000640 / 4)
#define GEM_INT_Q7_MASK (GEM_INT_Q1_MASK + 6)
-#define GEM_INT_Q8_MASK (0x000006A0 / 4)
-#define GEM_INT_Q15_MASK (GEM_INT_Q8_MASK + 7)
#define GEM_SCREENING_TYPE1_REGISTER_0 (0x00000500 / 4)
@@ -1372,13 +1366,13 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
case GEM_RXQBASE:
s->rx_desc_addr[0] = val;
break;
- case GEM_RECEIVE_Q1_PTR ... GEM_RECEIVE_Q15_PTR:
+ case GEM_RECEIVE_Q1_PTR ... GEM_RECEIVE_Q7_PTR:
s->rx_desc_addr[offset - GEM_RECEIVE_Q1_PTR + 1] = val;
break;
case GEM_TXQBASE:
s->tx_desc_addr[0] = val;
break;
- case GEM_TRANSMIT_Q1_PTR ... GEM_TRANSMIT_Q15_PTR:
+ case GEM_TRANSMIT_Q1_PTR ... GEM_TRANSMIT_Q7_PTR:
s->tx_desc_addr[offset - GEM_TRANSMIT_Q1_PTR + 1] = val;
break;
case GEM_RXSTATUS:
@@ -1392,10 +1386,6 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_ENABLE] &= ~val;
gem_update_int_status(s);
break;
- case GEM_INT_Q8_ENABLE ... GEM_INT_Q15_ENABLE:
- s->regs[GEM_INT_Q8_MASK + offset - GEM_INT_Q8_ENABLE] &= ~val;
- gem_update_int_status(s);
- break;
case GEM_IDR:
s->regs[GEM_IMR] |= val;
gem_update_int_status(s);
@@ -1404,10 +1394,6 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_DISABLE] |= val;
gem_update_int_status(s);
break;
- case GEM_INT_Q8_DISABLE ... GEM_INT_Q15_DISABLE:
- s->regs[GEM_INT_Q8_MASK + offset - GEM_INT_Q8_DISABLE] |= val;
- gem_update_int_status(s);
- break;
case GEM_SPADDR1LO:
case GEM_SPADDR2LO:
case GEM_SPADDR3LO:
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 14b6821a94..03e38039e8 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -546,6 +546,51 @@ static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt)
return 0;
}
+/* Populate the "ibm,pa-features" property */
+static void spapr_populate_pa_features(CPUPPCState *env, void *fdt, int offset)
+{
+ uint8_t pa_features_206[] = { 6, 0,
+ 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 };
+ uint8_t pa_features_207[] = { 24, 0,
+ 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+ 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 };
+ uint8_t *pa_features;
+ size_t pa_size;
+
+ switch (env->mmu_model) {
+ case POWERPC_MMU_2_06:
+ case POWERPC_MMU_2_06a:
+ pa_features = pa_features_206;
+ pa_size = sizeof(pa_features_206);
+ break;
+ case POWERPC_MMU_2_07:
+ case POWERPC_MMU_2_07a:
+ pa_features = pa_features_207;
+ pa_size = sizeof(pa_features_207);
+ break;
+ default:
+ return;
+ }
+
+ if (env->ci_large_pages) {
+ /*
+ * Note: we keep CI large pages off by default because a 64K capable
+ * guest provisioned with large pages might otherwise try to map a qemu
+ * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages
+ * even if that qemu runs on a 4k host.
+ * We dd this bit back here if we are confident this is not an issue
+ */
+ pa_features[3] |= 0x20;
+ }
+ if (kvmppc_has_cap_htm() && pa_size > 24) {
+ pa_features[24] |= 0x80; /* Transactional memory support */
+ }
+
+ _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size)));
+}
+
static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
sPAPRMachineState *spapr)
{
@@ -573,24 +618,6 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
_FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index)));
}
- /* Note: we keep CI large pages off for now because a 64K capable guest
- * provisioned with large pages might otherwise try to map a qemu
- * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages
- * even if that qemu runs on a 4k host.
- *
- * We can later add this bit back when we are confident this is not
- * an issue (!HV KVM or 64K host)
- */
- uint8_t pa_features_206[] = { 6, 0,
- 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 };
- uint8_t pa_features_207[] = { 24, 0,
- 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
- 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
- uint8_t *pa_features;
- size_t pa_size;
-
_FDT((fdt_setprop_cell(fdt, offset, "reg", index)));
_FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
@@ -657,18 +684,7 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
page_sizes_prop, page_sizes_prop_size)));
}
- /* Do the ibm,pa-features property, adjust it for ci-large-pages */
- if (env->mmu_model == POWERPC_MMU_2_06) {
- pa_features = pa_features_206;
- pa_size = sizeof(pa_features_206);
- } else /* env->mmu_model == POWERPC_MMU_2_07 */ {
- pa_features = pa_features_207;
- pa_size = sizeof(pa_features_207);
- }
- if (env->ci_large_pages) {
- pa_features[3] |= 0x20;
- }
- _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size)));
+ spapr_populate_pa_features(env, fdt, offset);
_FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id",
cs->cpu_index / vcpus_per_socket)));
@@ -1759,7 +1775,7 @@ static void ppc_spapr_init(MachineState *machine)
/* init CPUs */
if (machine->cpu_model == NULL) {
- machine->cpu_model = kvm_enabled() ? "host" : "POWER7";
+ machine->cpu_model = kvm_enabled() ? "host" : smc->tcg_default_cpu;
}
ppc_cpu_parse_features(machine->cpu_model);
@@ -2386,6 +2402,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id;
smc->dr_lmb_enabled = true;
+ smc->tcg_default_cpu = "POWER8";
mc->query_hotpluggable_cpus = spapr_query_hotpluggable_cpus;
fwc->get_dev_path = spapr_get_fw_dev_path;
nc->nmi_monitor_handler = spapr_nmi;
@@ -2437,18 +2454,39 @@ static const TypeInfo spapr_machine_info = {
type_init(spapr_machine_register_##suffix)
/*
+ * pseries-2.8
+ */
+static void spapr_machine_2_8_instance_options(MachineState *machine)
+{
+}
+
+static void spapr_machine_2_8_class_options(MachineClass *mc)
+{
+ /* Defaults for the latest behaviour inherited from the base class */
+}
+
+DEFINE_SPAPR_MACHINE(2_8, "2.8", true);
+
+/*
* pseries-2.7
*/
+#define SPAPR_COMPAT_2_7 \
+ HW_COMPAT_2_7 \
+
static void spapr_machine_2_7_instance_options(MachineState *machine)
{
}
static void spapr_machine_2_7_class_options(MachineClass *mc)
{
- /* Defaults for the latest behaviour inherited from the base class */
+ sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+
+ spapr_machine_2_8_class_options(mc);
+ smc->tcg_default_cpu = "POWER7";
+ SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_7);
}
-DEFINE_SPAPR_MACHINE(2_7, "2.7", true);
+DEFINE_SPAPR_MACHINE(2_7, "2.7", false);
/*
* pseries-2.6
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 6f0533c342..35d1873b9f 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -92,20 +92,20 @@ char *spapr_get_cpu_core_type(const char *model)
gchar **model_pieces = g_strsplit(model, ",", 2);
core_type = g_strdup_printf("%s-%s", model_pieces[0], TYPE_SPAPR_CPU_CORE);
- g_strfreev(model_pieces);
/* Check whether it exists or whether we have to look up an alias name */
if (!object_class_by_name(core_type)) {
const char *realmodel;
g_free(core_type);
- realmodel = ppc_cpu_lookup_alias(model);
+ core_type = NULL;
+ realmodel = ppc_cpu_lookup_alias(model_pieces[0]);
if (realmodel) {
- return spapr_get_cpu_core_type(realmodel);
+ core_type = spapr_get_cpu_core_type(realmodel);
}
- return NULL;
}
+ g_strfreev(model_pieces);
return core_type;
}
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index b0e81efc27..0f2580d644 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -775,7 +775,7 @@ int css_do_xsch(SubchDev *sch)
PMCW *p = &sch->curr_status.pmcw;
int ret;
- if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
+ if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
ret = -ENODEV;
goto out;
}
@@ -815,7 +815,7 @@ int css_do_csch(SubchDev *sch)
PMCW *p = &sch->curr_status.pmcw;
int ret;
- if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
+ if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
ret = -ENODEV;
goto out;
}
@@ -837,7 +837,7 @@ int css_do_hsch(SubchDev *sch)
PMCW *p = &sch->curr_status.pmcw;
int ret;
- if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
+ if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
ret = -ENODEV;
goto out;
}
@@ -913,7 +913,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb)
PMCW *p = &sch->curr_status.pmcw;
int ret;
- if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
+ if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
ret = -ENODEV;
goto out;
}
@@ -990,7 +990,7 @@ int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)
uint16_t stctl;
IRB irb;
- if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
+ if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
return 3;
}
@@ -1196,7 +1196,7 @@ int css_do_rsch(SubchDev *sch)
PMCW *p = &sch->curr_status.pmcw;
int ret;
- if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
+ if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
ret = -ENODEV;
goto out;
}
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index ac8f06d9e7..b7f8bca1fd 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -383,7 +383,6 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
uint64_t pte;
uint32_t flags;
S390PCIBusDevice *pbdev = container_of(iommu, S390PCIBusDevice, iommu_mr);
- S390pciState *s;
IOMMUTLBEntry ret = {
.target_as = &address_space_memory,
.iova = 0,
@@ -405,19 +404,6 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr);
- s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev->pdev)->qbus.parent);
- /* s390 does not have an APIC mapped to main storage so we use
- * a separate AddressSpace only for msix notifications
- */
- if (addr == ZPCI_MSI_ADDR) {
- ret.target_as = &s->msix_notify_as;
- ret.iova = addr;
- ret.translated_addr = addr;
- ret.addr_mask = 0xfff;
- ret.perm = IOMMU_RW;
- return ret;
- }
-
if (addr < pbdev->pba || addr > pbdev->pal) {
return ret;
}
@@ -476,7 +462,7 @@ static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set)
static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data,
unsigned int size)
{
- S390PCIBusDevice *pbdev;
+ S390PCIBusDevice *pbdev = opaque;
uint32_t io_int_word;
uint32_t idx = data >> ZPCI_MSI_VEC_BITS;
uint32_t vec = data & ZPCI_MSI_VEC_MASK;
@@ -486,7 +472,6 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data,
DPRINTF("write_msix data 0x%" PRIx64 " idx %d vec 0x%x\n", data, idx, vec);
- pbdev = s390_pci_find_dev_by_idx(idx);
if (!pbdev) {
e |= (vec << ERR_EVENT_MVN_OFFSET);
s390_pci_generate_error_event(ERR_EVENT_NOMSI, idx, 0, addr, e);
@@ -548,10 +533,6 @@ static void s390_pcihost_init_as(S390pciState *s)
s->iommu[i] = iommu;
}
-
- memory_region_init_io(&s->msix_notify_mr, OBJECT(s),
- &s390_msi_ctrl_ops, s, "msix-s390", UINT64_MAX);
- address_space_init(&s->msix_notify_as, &s->msix_notify_mr, "msix-pci");
}
static int s390_pcihost_init(SysBusDevice *dev)
@@ -581,7 +562,7 @@ static int s390_pcihost_init(SysBusDevice *dev)
return 0;
}
-static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev)
+static int s390_pci_setup_msix(S390PCIBusDevice *pbdev)
{
uint8_t pos;
uint16_t ctrl;
@@ -609,6 +590,26 @@ static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev)
return 0;
}
+static void s390_pci_msix_init(S390PCIBusDevice *pbdev)
+{
+ char *name;
+
+ name = g_strdup_printf("msix-s390-%04x", pbdev->uid);
+
+ memory_region_init_io(&pbdev->msix_notify_mr, OBJECT(pbdev),
+ &s390_msi_ctrl_ops, pbdev, name, PAGE_SIZE);
+ memory_region_add_subregion(&pbdev->iommu->mr, ZPCI_MSI_ADDR,
+ &pbdev->msix_notify_mr);
+
+ g_free(name);
+}
+
+static void s390_pci_msix_free(S390PCIBusDevice *pbdev)
+{
+ memory_region_del_subregion(&pbdev->iommu->mr, &pbdev->msix_notify_mr);
+ object_unparent(OBJECT(&pbdev->msix_notify_mr));
+}
+
static S390PCIBusDevice *s390_pci_device_new(const char *target)
{
DeviceState *dev = NULL;
@@ -662,7 +663,9 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
pbdev->pdev = pdev;
pbdev->iommu = s->iommu[PCI_SLOT(pdev->devfn)];
pbdev->state = ZPCI_FS_STANDBY;
- s390_pcihost_setup_msix(pbdev);
+
+ s390_pci_msix_init(pbdev);
+ s390_pci_setup_msix(pbdev);
if (dev->hotplugged) {
s390_pci_generate_plug_event(HP_EVENT_RESERVED_TO_STANDBY,
@@ -749,6 +752,7 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev,
s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED,
pbdev->fh, pbdev->fid);
object_unparent(OBJECT(pci_dev));
+ s390_pci_msix_free(pbdev);
pbdev->pdev = NULL;
pbdev->state = ZPCI_FS_RESERVED;
out:
diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h
index 4f564e02f2..7f2701301e 100644
--- a/hw/s390x/s390-pci-bus.h
+++ b/hw/s390x/s390-pci-bus.h
@@ -82,6 +82,7 @@
#define ZPCI_EDMA_ADDR 0x1ffffffffffffffULL
#define PAGE_SHIFT 12
+#define PAGE_SIZE (1 << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#define PAGE_DEFAULT_ACC 0
#define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4)
@@ -283,6 +284,7 @@ typedef struct S390PCIBusDevice {
AdapterRoutes routes;
S390PCIIOMMU *iommu;
MemoryRegion iommu_mr;
+ MemoryRegion msix_notify_mr;
IndAddr *summary_ind;
IndAddr *indicator;
QEMUTimer *release_timer;
@@ -297,8 +299,6 @@ typedef struct S390pciState {
S390PCIBus *bus;
S390PCIBusDevice *pbdev[PCI_SLOT_MAX];
S390PCIIOMMU *iommu[PCI_SLOT_MAX];
- AddressSpace msix_notify_as;
- MemoryRegion msix_notify_mr;
QTAILQ_HEAD(, SeiContainer) pending_sei;
} S390pciState;
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index f069b110b4..80a51049ca 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -315,6 +315,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
S390PCIBusDevice *pbdev;
uint64_t offset;
uint64_t data;
+ MemoryRegion *mr;
uint8_t len;
uint32_t fh;
uint8_t pcias;
@@ -363,7 +364,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
program_interrupt(env, PGM_OPERAND, 4);
return 0;
}
- MemoryRegion *mr = pbdev->pdev->io_regions[pcias].memory;
+ mr = pbdev->pdev->io_regions[pcias].memory;
memory_region_dispatch_read(mr, offset, &data, len,
MEMTXATTRS_UNSPECIFIED);
} else if (pcias == 15) {
@@ -442,6 +443,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
CPUS390XState *env = &cpu->env;
uint64_t offset, data;
S390PCIBusDevice *pbdev;
+ MemoryRegion *mr;
uint8_t len;
uint32_t fh;
uint8_t pcias;
@@ -491,7 +493,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
program_interrupt(env, PGM_OPERAND, 4);
return 0;
}
- MemoryRegion *mr;
+
if (trap_msix(pbdev, offset, pcias)) {
offset = offset - pbdev->msix.table_offset;
mr = &pbdev->pdev->msix_table_mmio;
diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
index d8a2296b7b..6090a204a0 100644
--- a/hw/scsi/spapr_vscsi.c
+++ b/hw/scsi/spapr_vscsi.c
@@ -658,7 +658,7 @@ static void vscsi_process_login(VSCSIState *s, vscsi_req *req)
struct srp_login_rsp *rsp = &iu->srp.login_rsp;
uint64_t tag = iu->srp.rsp.tag;
- trace_spapr_vscsi__process_login();
+ trace_spapr_vscsi_process_login();
/* TODO handle case that requested size is wrong and
* buffer format is wrong
diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events
index d1995b84f8..4a2e5d66df 100644
--- a/hw/scsi/trace-events
+++ b/hw/scsi/trace-events
@@ -225,7 +225,7 @@ spapr_vscsi_command_complete_sense_data2(unsigned s8, unsigned s9, unsigned s10,
spapr_vscsi_command_complete_status(uint32_t status) "Command complete err=%"PRIu32
spapr_vscsi_save_request(uint32_t qtag, unsigned desc, unsigned offset) "saving tag=%"PRIu32", current desc#%u, offset=0x%x"
spapr_vscsi_load_request(uint32_t qtag, unsigned desc, unsigned offset) "restoring tag=%"PRIu32", current desc#%u, offset=0x%x"
-spapr_vscsi__process_login(void) "Got login, sending response !"
+spapr_vscsi_process_login(void) "Got login, sending response !"
spapr_vscsi_queue_cmd_no_drive(uint64_t lun) "Command for lun %08" PRIx64 " with no drive"
spapr_vscsi_queue_cmd(uint32_t qtag, unsigned cdb, const char *cmd, int lun, int ret) "Queued command tag 0x%"PRIx32" CMD 0x%x=%s LUN %d ret: %d"
spapr_vscsi_do_crq(unsigned c0, unsigned c1) "crq: %02x %02x ..."
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index 9a6552aa60..3a96cededd 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -486,7 +486,7 @@ static void smbios_build_type_0_table(void)
*/
static void smbios_encode_uuid(struct smbios_uuid *uuid, QemuUUID *in)
{
- memcpy(uuid, &in, 16);
+ memcpy(uuid, in, 16);
if (smbios_uuid_encoded) {
uuid->time_low = bswap32(uuid->time_low);
uuid->time_mid = bswap16(uuid->time_mid);
diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs
index c79a8dcd86..487add2879 100644
--- a/hw/ssi/Makefile.objs
+++ b/hw/ssi/Makefile.objs
@@ -3,6 +3,7 @@ common-obj-$(CONFIG_SSI) += ssi.o
common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o
common-obj-$(CONFIG_ASPEED_SOC) += aspeed_smc.o
+common-obj-$(CONFIG_STM32F2XX_SPI) += stm32f2xx_spi.o
obj-$(CONFIG_OMAP) += omap_spi.o
obj-$(CONFIG_IMX) += imx_spi.o
diff --git a/hw/ssi/stm32f2xx_spi.c b/hw/ssi/stm32f2xx_spi.c
new file mode 100644
index 0000000000..26a1b4ddf5
--- /dev/null
+++ b/hw/ssi/stm32f2xx_spi.c
@@ -0,0 +1,225 @@
+/*
+ * STM32F405 SPI
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * 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 "qapi/error.h"
+#include "qemu/log.h"
+#include "hw/ssi/stm32f2xx_spi.h"
+
+#ifndef STM_SPI_ERR_DEBUG
+#define STM_SPI_ERR_DEBUG 0
+#endif
+
+#define DB_PRINT_L(lvl, fmt, args...) do { \
+ if (STM_SPI_ERR_DEBUG >= lvl) { \
+ qemu_log("%s: " fmt, __func__, ## args); \
+ } \
+} while (0);
+
+#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
+
+static void stm32f2xx_spi_reset(DeviceState *dev)
+{
+ STM32F2XXSPIState *s = STM32F2XX_SPI(dev);
+
+ s->spi_cr1 = 0x00000000;
+ s->spi_cr2 = 0x00000000;
+ s->spi_sr = 0x0000000A;
+ s->spi_dr = 0x0000000C;
+ s->spi_crcpr = 0x00000007;
+ s->spi_rxcrcr = 0x00000000;
+ s->spi_txcrcr = 0x00000000;
+ s->spi_i2scfgr = 0x00000000;
+ s->spi_i2spr = 0x00000002;
+}
+
+static void stm32f2xx_spi_transfer(STM32F2XXSPIState *s)
+{
+ DB_PRINT("Data to send: 0x%x\n", s->spi_dr);
+
+ s->spi_dr = ssi_transfer(s->ssi, s->spi_dr);
+ s->spi_sr |= STM_SPI_SR_RXNE;
+
+ DB_PRINT("Data received: 0x%x\n", s->spi_dr);
+}
+
+static uint64_t stm32f2xx_spi_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+ STM32F2XXSPIState *s = opaque;
+
+ DB_PRINT("Address: 0x%" HWADDR_PRIx "\n", addr);
+
+ switch (addr) {
+ case STM_SPI_CR1:
+ return s->spi_cr1;
+ case STM_SPI_CR2:
+ qemu_log_mask(LOG_UNIMP, "%s: Interrupts and DMA are not implemented\n",
+ __func__);
+ return s->spi_cr2;
+ case STM_SPI_SR:
+ return s->spi_sr;
+ case STM_SPI_DR:
+ stm32f2xx_spi_transfer(s);
+ s->spi_sr &= ~STM_SPI_SR_RXNE;
+ return s->spi_dr;
+ case STM_SPI_CRCPR:
+ qemu_log_mask(LOG_UNIMP, "%s: CRC is not implemented, the registers " \
+ "are included for compatibility\n", __func__);
+ return s->spi_crcpr;
+ case STM_SPI_RXCRCR:
+ qemu_log_mask(LOG_UNIMP, "%s: CRC is not implemented, the registers " \
+ "are included for compatibility\n", __func__);
+ return s->spi_rxcrcr;
+ case STM_SPI_TXCRCR:
+ qemu_log_mask(LOG_UNIMP, "%s: CRC is not implemented, the registers " \
+ "are included for compatibility\n", __func__);
+ return s->spi_txcrcr;
+ case STM_SPI_I2SCFGR:
+ qemu_log_mask(LOG_UNIMP, "%s: I2S is not implemented, the registers " \
+ "are included for compatibility\n", __func__);
+ return s->spi_i2scfgr;
+ case STM_SPI_I2SPR:
+ qemu_log_mask(LOG_UNIMP, "%s: I2S is not implemented, the registers " \
+ "are included for compatibility\n", __func__);
+ return s->spi_i2spr;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
+ __func__, addr);
+ }
+
+ return 0;
+}
+
+static void stm32f2xx_spi_write(void *opaque, hwaddr addr,
+ uint64_t val64, unsigned int size)
+{
+ STM32F2XXSPIState *s = opaque;
+ uint32_t value = val64;
+
+ DB_PRINT("Address: 0x%" HWADDR_PRIx ", Value: 0x%x\n", addr, value);
+
+ switch (addr) {
+ case STM_SPI_CR1:
+ s->spi_cr1 = value;
+ return;
+ case STM_SPI_CR2:
+ qemu_log_mask(LOG_UNIMP, "%s: " \
+ "Interrupts and DMA are not implemented\n", __func__);
+ s->spi_cr2 = value;
+ return;
+ case STM_SPI_SR:
+ /* Read only register, except for clearing the CRCERR bit, which
+ * is not supported
+ */
+ return;
+ case STM_SPI_DR:
+ s->spi_dr = value;
+ stm32f2xx_spi_transfer(s);
+ return;
+ case STM_SPI_CRCPR:
+ qemu_log_mask(LOG_UNIMP, "%s: CRC is not implemented\n", __func__);
+ return;
+ case STM_SPI_RXCRCR:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Read only register: " \
+ "0x%" HWADDR_PRIx "\n", __func__, addr);
+ return;
+ case STM_SPI_TXCRCR:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Read only register: " \
+ "0x%" HWADDR_PRIx "\n", __func__, addr);
+ return;
+ case STM_SPI_I2SCFGR:
+ qemu_log_mask(LOG_UNIMP, "%s: " \
+ "I2S is not implemented\n", __func__);
+ return;
+ case STM_SPI_I2SPR:
+ qemu_log_mask(LOG_UNIMP, "%s: " \
+ "I2S is not implemented\n", __func__);
+ return;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
+ }
+}
+
+static const MemoryRegionOps stm32f2xx_spi_ops = {
+ .read = stm32f2xx_spi_read,
+ .write = stm32f2xx_spi_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_stm32f2xx_spi = {
+ .name = TYPE_STM32F2XX_SPI,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(spi_cr1, STM32F2XXSPIState),
+ VMSTATE_UINT32(spi_cr2, STM32F2XXSPIState),
+ VMSTATE_UINT32(spi_sr, STM32F2XXSPIState),
+ VMSTATE_UINT32(spi_dr, STM32F2XXSPIState),
+ VMSTATE_UINT32(spi_crcpr, STM32F2XXSPIState),
+ VMSTATE_UINT32(spi_rxcrcr, STM32F2XXSPIState),
+ VMSTATE_UINT32(spi_txcrcr, STM32F2XXSPIState),
+ VMSTATE_UINT32(spi_i2scfgr, STM32F2XXSPIState),
+ VMSTATE_UINT32(spi_i2spr, STM32F2XXSPIState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void stm32f2xx_spi_init(Object *obj)
+{
+ STM32F2XXSPIState *s = STM32F2XX_SPI(obj);
+ DeviceState *dev = DEVICE(obj);
+
+ memory_region_init_io(&s->mmio, obj, &stm32f2xx_spi_ops, s,
+ TYPE_STM32F2XX_SPI, 0x400);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
+
+ s->ssi = ssi_create_bus(dev, "ssi");
+}
+
+static void stm32f2xx_spi_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = stm32f2xx_spi_reset;
+ dc->vmsd = &vmstate_stm32f2xx_spi;
+}
+
+static const TypeInfo stm32f2xx_spi_info = {
+ .name = TYPE_STM32F2XX_SPI,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(STM32F2XXSPIState),
+ .instance_init = stm32f2xx_spi_init,
+ .class_init = stm32f2xx_spi_class_init,
+};
+
+static void stm32f2xx_spi_register_types(void)
+{
+ type_register_static(&stm32f2xx_spi_info);
+}
+
+type_init(stm32f2xx_spi_register_types)
diff --git a/hw/timer/stm32f2xx_timer.c b/hw/timer/stm32f2xx_timer.c
index bf0fb288c4..8c4c1f9f05 100644
--- a/hw/timer/stm32f2xx_timer.c
+++ b/hw/timer/stm32f2xx_timer.c
@@ -51,6 +51,15 @@ static void stm32f2xx_timer_interrupt(void *opaque)
qemu_irq_pulse(s->irq);
stm32f2xx_timer_set_alarm(s, s->hit_time);
}
+
+ if (s->tim_ccmr1 & (TIM_CCMR1_OC2M2 | TIM_CCMR1_OC2M1) &&
+ !(s->tim_ccmr1 & TIM_CCMR1_OC2M0) &&
+ s->tim_ccmr1 & TIM_CCMR1_OC2PE &&
+ s->tim_ccer & TIM_CCER_CC2E) {
+ /* PWM 2 - Mode 1 */
+ DB_PRINT("PWM2 Duty Cycle: %d%%\n",
+ s->tim_ccr2 / (100 * (s->tim_psc + 1)));
+ }
}
static inline int64_t stm32f2xx_ns_to_ticks(STM32F2XXTimerState *s, int64_t t)
diff --git a/hw/xenpv/xen_domainbuild.c b/hw/xenpv/xen_domainbuild.c
index b439b0ed5d..457a8976c3 100644
--- a/hw/xenpv/xen_domainbuild.c
+++ b/hw/xenpv/xen_domainbuild.c
@@ -232,7 +232,7 @@ int xen_domain_build_pv(const char *kernel, const char *ramdisk,
unsigned long xenstore_mfn = 0, console_mfn = 0;
int rc;
- memcpy(uuid, qemu_uuid, sizeof(uuid));
+ memcpy(uuid, &qemu_uuid, sizeof(uuid));
rc = xen_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid);
if (rc < 0) {
fprintf(stderr, "xen: xc_domain_create() failed\n");
diff --git a/include/block/block.h b/include/block/block.h
index e18233afe0..107c603605 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -108,6 +108,7 @@ typedef struct HDGeometry {
#define BDRV_OPT_CACHE_DIRECT "cache.direct"
#define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
#define BDRV_OPT_READ_ONLY "read-only"
+#define BDRV_OPT_DISCARD "discard"
#define BDRV_SECTOR_BITS 9
@@ -333,6 +334,7 @@ int bdrv_inactivate_all(void);
/* Ensure contents are flushed to disk. */
int bdrv_flush(BlockDriverState *bs);
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
+int bdrv_flush_all(void);
void bdrv_close_all(void);
void bdrv_drain(BlockDriverState *bs);
void coroutine_fn bdrv_co_drain(BlockDriverState *bs);
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 41c1d95c4c..9c1b7cb5d6 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -294,7 +294,8 @@ typedef struct AcpiMultipleApicTable AcpiMultipleApicTable;
#define ACPI_APIC_GENERIC_DISTRIBUTOR 12
#define ACPI_APIC_GENERIC_MSI_FRAME 13
#define ACPI_APIC_GENERIC_REDISTRIBUTOR 14
-#define ACPI_APIC_RESERVED 15 /* 15 and greater are reserved */
+#define ACPI_APIC_GENERIC_TRANSLATOR 15
+#define ACPI_APIC_RESERVED 16 /* 16 and greater are reserved */
/*
* MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
@@ -395,6 +396,16 @@ struct AcpiMadtGenericRedistributor {
typedef struct AcpiMadtGenericRedistributor AcpiMadtGenericRedistributor;
+struct AcpiMadtGenericTranslator {
+ ACPI_SUB_HEADER_DEF
+ uint16_t reserved;
+ uint32_t translation_id;
+ uint64_t base_address;
+ uint32_t reserved2;
+} QEMU_PACKED;
+
+typedef struct AcpiMadtGenericTranslator AcpiMadtGenericTranslator;
+
/*
* Generic Timer Description Table (GTDT)
*/
diff --git a/include/hw/adc/stm32f2xx_adc.h b/include/hw/adc/stm32f2xx_adc.h
new file mode 100644
index 0000000000..a72f734eb1
--- /dev/null
+++ b/include/hw/adc/stm32f2xx_adc.h
@@ -0,0 +1,87 @@
+/*
+ * STM32F2XX ADC
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * 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 HW_STM32F2XX_ADC_H
+#define HW_STM32F2XX_ADC_H
+
+#define ADC_SR 0x00
+#define ADC_CR1 0x04
+#define ADC_CR2 0x08
+#define ADC_SMPR1 0x0C
+#define ADC_SMPR2 0x10
+#define ADC_JOFR1 0x14
+#define ADC_JOFR2 0x18
+#define ADC_JOFR3 0x1C
+#define ADC_JOFR4 0x20
+#define ADC_HTR 0x24
+#define ADC_LTR 0x28
+#define ADC_SQR1 0x2C
+#define ADC_SQR2 0x30
+#define ADC_SQR3 0x34
+#define ADC_JSQR 0x38
+#define ADC_JDR1 0x3C
+#define ADC_JDR2 0x40
+#define ADC_JDR3 0x44
+#define ADC_JDR4 0x48
+#define ADC_DR 0x4C
+
+#define ADC_CR2_ADON 0x01
+#define ADC_CR2_CONT 0x02
+#define ADC_CR2_ALIGN 0x800
+#define ADC_CR2_SWSTART 0x40000000
+
+#define ADC_CR1_RES 0x3000000
+
+#define ADC_COMMON_ADDRESS 0x100
+
+#define TYPE_STM32F2XX_ADC "stm32f2xx-adc"
+#define STM32F2XX_ADC(obj) \
+ OBJECT_CHECK(STM32F2XXADCState, (obj), TYPE_STM32F2XX_ADC)
+
+typedef struct {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion mmio;
+
+ uint32_t adc_sr;
+ uint32_t adc_cr1;
+ uint32_t adc_cr2;
+ uint32_t adc_smpr1;
+ uint32_t adc_smpr2;
+ uint32_t adc_jofr[4];
+ uint32_t adc_htr;
+ uint32_t adc_ltr;
+ uint32_t adc_sqr1;
+ uint32_t adc_sqr2;
+ uint32_t adc_sqr3;
+ uint32_t adc_jsqr;
+ uint32_t adc_jdr[4];
+ uint32_t adc_dr;
+
+ qemu_irq irq;
+} STM32F2XXADCState;
+
+#endif /* HW_STM32F2XX_ADC_H */
diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h
index 779b5da2dc..133214195b 100644
--- a/include/hw/arm/stm32f205_soc.h
+++ b/include/hw/arm/stm32f205_soc.h
@@ -28,6 +28,9 @@
#include "hw/misc/stm32f2xx_syscfg.h"
#include "hw/timer/stm32f2xx_timer.h"
#include "hw/char/stm32f2xx_usart.h"
+#include "hw/adc/stm32f2xx_adc.h"
+#include "hw/or-irq.h"
+#include "hw/ssi/stm32f2xx_spi.h"
#define TYPE_STM32F205_SOC "stm32f205-soc"
#define STM32F205_SOC(obj) \
@@ -35,6 +38,8 @@
#define STM_NUM_USARTS 6
#define STM_NUM_TIMERS 4
+#define STM_NUM_ADCS 3
+#define STM_NUM_SPIS 3
#define FLASH_BASE_ADDRESS 0x08000000
#define FLASH_SIZE (1024 * 1024)
@@ -52,6 +57,10 @@ typedef struct STM32F205State {
STM32F2XXSyscfgState syscfg;
STM32F2XXUsartState usart[STM_NUM_USARTS];
STM32F2XXTimerState timer[STM_NUM_TIMERS];
+ STM32F2XXADCState adc[STM_NUM_ADCS];
+ STM32F2XXSPIState spi[STM_NUM_SPIS];
+
+ qemu_or_irq *adc_irqs;
} STM32F205State;
#endif
diff --git a/include/hw/core/generic-loader.h b/include/hw/core/generic-loader.h
new file mode 100644
index 0000000000..dd27c42ab0
--- /dev/null
+++ b/include/hw/core/generic-loader.h
@@ -0,0 +1,46 @@
+/*
+ * Generic Loader
+ *
+ * Copyright (C) 2014 Li Guang
+ * Written by Li Guang <lig.fnst@cn.fujitsu.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.
+ */
+
+#ifndef GENERIC_LOADER_H
+#define GENERIC_LOADER_H
+
+#include "elf.h"
+
+typedef struct GenericLoaderState {
+ /* <private> */
+ DeviceState parent_obj;
+
+ /* <public> */
+ CPUState *cpu;
+
+ uint64_t addr;
+ uint64_t data;
+ uint8_t data_len;
+ uint32_t cpu_num;
+
+ char *file;
+
+ bool force_raw;
+ bool data_be;
+ bool set_pc;
+} GenericLoaderState;
+
+#define TYPE_GENERIC_LOADER "loader"
+#define GENERIC_LOADER(obj) OBJECT_CHECK(GenericLoaderState, (obj), \
+ TYPE_GENERIC_LOADER)
+
+#endif
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 142b57f753..b16c448249 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -377,6 +377,21 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
.driver = TYPE_X86_CPU,\
.property = "full-cpuid-auto-level",\
.value = "off",\
+ },\
+ {\
+ .driver = "Opteron_G3" "-" TYPE_X86_CPU,\
+ .property = "family",\
+ .value = "15",\
+ },\
+ {\
+ .driver = "Opteron_G3" "-" TYPE_X86_CPU,\
+ .property = "model",\
+ .value = "6",\
+ },\
+ {\
+ .driver = "Opteron_G3" "-" TYPE_X86_CPU,\
+ .property = "stepping",\
+ .value = "1",\
},
#define PC_COMPAT_2_6 \
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
new file mode 100644
index 0000000000..1ba18944cf
--- /dev/null
+++ b/include/hw/intc/arm_gicv3_its_common.h
@@ -0,0 +1,78 @@
+/*
+ * ITS support for ARM GICv3
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Written by Pavel Fedin
+ *
+ * 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/>.
+ */
+
+#ifndef QEMU_ARM_GICV3_ITS_COMMON_H
+#define QEMU_ARM_GICV3_ITS_COMMON_H
+
+#include "hw/sysbus.h"
+#include "hw/intc/arm_gicv3_common.h"
+
+#define ITS_CONTROL_SIZE 0x10000
+#define ITS_TRANS_SIZE 0x10000
+#define ITS_SIZE (ITS_CONTROL_SIZE + ITS_TRANS_SIZE)
+
+struct GICv3ITSState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem_main;
+ MemoryRegion iomem_its_cntrl;
+ MemoryRegion iomem_its_translation;
+
+ GICv3State *gicv3;
+
+ int dev_fd; /* kvm device fd if backed by kvm vgic support */
+ uint64_t gits_translater_gpa;
+ bool translater_gpa_known;
+
+ /* Registers */
+ uint32_t ctlr;
+ uint64_t cbaser;
+ uint64_t cwriter;
+ uint64_t creadr;
+ uint64_t baser[8];
+
+ Error *migration_blocker;
+};
+
+typedef struct GICv3ITSState GICv3ITSState;
+
+void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops);
+
+#define TYPE_ARM_GICV3_ITS_COMMON "arm-gicv3-its-common"
+#define ARM_GICV3_ITS_COMMON(obj) \
+ OBJECT_CHECK(GICv3ITSState, (obj), TYPE_ARM_GICV3_ITS_COMMON)
+#define ARM_GICV3_ITS_COMMON_CLASS(klass) \
+ OBJECT_CLASS_CHECK(GICv3ITSCommonClass, (klass), TYPE_ARM_GICV3_ITS_COMMON)
+#define ARM_GICV3_ITS_COMMON_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(GICv3ITSCommonClass, (obj), TYPE_ARM_GICV3_ITS_COMMON)
+
+struct GICv3ITSCommonClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+
+ int (*send_msi)(GICv3ITSState *s, uint32_t data, uint16_t devid);
+ void (*pre_save)(GICv3ITSState *s);
+ void (*post_load)(GICv3ITSState *s);
+};
+
+typedef struct GICv3ITSCommonClass GICv3ITSCommonClass;
+
+#endif
diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h
new file mode 100644
index 0000000000..d400a8120b
--- /dev/null
+++ b/include/hw/or-irq.h
@@ -0,0 +1,44 @@
+/*
+ * QEMU IRQ/GPIO common code.
+ *
+ * Copyright (c) 2016 Alistair Francis <alistair@alistair23.me>.
+ *
+ * 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 "hw/irq.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_OR_IRQ "or-irq"
+
+#define MAX_OR_LINES 16
+
+typedef struct OrIRQState qemu_or_irq;
+
+#define OR_IRQ(obj) OBJECT_CHECK(qemu_or_irq, (obj), TYPE_OR_IRQ)
+
+struct OrIRQState {
+ DeviceState parent_obj;
+
+ qemu_irq out_irq;
+ qemu_irq *in_irqs;
+ bool levels[MAX_OR_LINES];
+ uint16_t num_lines;
+};
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 6289d50dbf..39dadaa9ce 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -39,6 +39,7 @@ struct sPAPRMachineClass {
/*< public >*/
bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */
bool use_ohci_by_default; /* use USB-OHCI instead of XHCI */
+ const char *tcg_default_cpu; /* which (TCG) CPU to simulate by default */
};
/**
diff --git a/include/hw/ssi/stm32f2xx_spi.h b/include/hw/ssi/stm32f2xx_spi.h
new file mode 100644
index 0000000000..1cd73e4cd4
--- /dev/null
+++ b/include/hw/ssi/stm32f2xx_spi.h
@@ -0,0 +1,72 @@
+/*
+ * STM32F2XX SPI
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * 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 HW_STM32F2XX_SPI_H
+#define HW_STM32F2XX_SPI_H
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/ssi/ssi.h"
+
+#define STM_SPI_CR1 0x00
+#define STM_SPI_CR2 0x04
+#define STM_SPI_SR 0x08
+#define STM_SPI_DR 0x0C
+#define STM_SPI_CRCPR 0x10
+#define STM_SPI_RXCRCR 0x14
+#define STM_SPI_TXCRCR 0x18
+#define STM_SPI_I2SCFGR 0x1C
+#define STM_SPI_I2SPR 0x20
+
+#define STM_SPI_CR1_SPE (1 << 6)
+#define STM_SPI_CR1_MSTR (1 << 2)
+
+#define STM_SPI_SR_RXNE 1
+
+#define TYPE_STM32F2XX_SPI "stm32f2xx-spi"
+#define STM32F2XX_SPI(obj) \
+ OBJECT_CHECK(STM32F2XXSPIState, (obj), TYPE_STM32F2XX_SPI)
+
+typedef struct {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion mmio;
+
+ uint32_t spi_cr1;
+ uint32_t spi_cr2;
+ uint32_t spi_sr;
+ uint32_t spi_dr;
+ uint32_t spi_crcpr;
+ uint32_t spi_rxcrcr;
+ uint32_t spi_txcrcr;
+ uint32_t spi_i2scfgr;
+ uint32_t spi_i2spr;
+
+ qemu_irq irq;
+ SSIBus *ssi;
+} STM32F2XXSPIState;
+
+#endif /* HW_STM32F2XX_SPI_H */
diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h
index 6df9d33352..14d4f1d1f2 100644
--- a/include/qemu/coroutine_int.h
+++ b/include/qemu/coroutine_int.h
@@ -28,6 +28,8 @@
#include "qemu/queue.h"
#include "qemu/coroutine.h"
+#define COROUTINE_STACK_SIZE (1 << 20)
+
typedef enum {
COROUTINE_YIELD = 1,
COROUTINE_TERMINATE = 2,
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 3b29317349..a7993afcda 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -152,7 +152,6 @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
int blk_co_pdiscard(BlockBackend *blk, int64_t offset, int count);
int blk_co_flush(BlockBackend *blk);
int blk_flush(BlockBackend *blk);
-int blk_flush_all(void);
int blk_commit_all(void);
void blk_drain(BlockBackend *blk);
void blk_drain_all(void);
@@ -199,7 +198,7 @@ void blk_io_unplug(BlockBackend *blk);
BlockAcctStats *blk_get_stats(BlockBackend *blk);
BlockBackendRootState *blk_get_root_state(BlockBackend *blk);
void blk_update_root_state(BlockBackend *blk);
-void blk_apply_root_state(BlockBackend *blk, BlockDriverState *bs);
+bool blk_get_detect_zeroes_from_root_state(BlockBackend *blk);
int blk_get_open_flags_from_root_state(BlockBackend *blk);
void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 3e17ba76ce..df67cc0672 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -53,6 +53,7 @@ extern bool kvm_gsi_direct_mapping;
extern bool kvm_readonly_mem_allowed;
extern bool kvm_direct_msi_allowed;
extern bool kvm_ioeventfd_any_length_allowed;
+extern bool kvm_msi_use_devid;
#if defined CONFIG_KVM || !defined NEED_CPU_H
#define kvm_enabled() (kvm_allowed)
@@ -169,6 +170,13 @@ extern bool kvm_ioeventfd_any_length_allowed;
*/
#define kvm_ioeventfd_any_length_enabled() (kvm_ioeventfd_any_length_allowed)
+/**
+ * kvm_msi_devid_required:
+ * Returns: true if KVM requires a device id to be provided while
+ * defining an MSI routing entry.
+ */
+#define kvm_msi_devid_required() (kvm_msi_use_devid)
+
#else
#define kvm_enabled() (0)
#define kvm_irqchip_in_kernel() (false)
@@ -184,6 +192,7 @@ extern bool kvm_ioeventfd_any_length_allowed;
#define kvm_readonly_mem_enabled() (false)
#define kvm_direct_msi_enabled() (false)
#define kvm_ioeventfd_any_length_enabled() (false)
+#define kvm_msi_devid_required() (false)
#endif
struct kvm_run;
diff --git a/include/sysemu/os-posix.h b/include/sysemu/os-posix.h
index 9c7dfdfbec..3cfedbc28b 100644
--- a/include/sysemu/os-posix.h
+++ b/include/sysemu/os-posix.h
@@ -60,4 +60,31 @@ int qemu_utimens(const char *path, const qemu_timespec *times);
bool is_daemonized(void);
+/**
+ * qemu_alloc_stack:
+ * @sz: pointer to a size_t holding the requested usable stack size
+ *
+ * Allocate memory that can be used as a stack, for instance for
+ * coroutines. If the memory cannot be allocated, this function
+ * will abort (like g_malloc()). This function also inserts an
+ * additional guard page to catch a potential stack overflow.
+ * Note that the memory required for the guard page and alignment
+ * and minimal stack size restrictions will increase the value of sz.
+ *
+ * The allocated stack must be freed with qemu_free_stack().
+ *
+ * Returns: pointer to (the lowest address of) the stack memory.
+ */
+void *qemu_alloc_stack(size_t *sz);
+
+/**
+ * qemu_free_stack:
+ * @stack: stack to free
+ * @sz: size of stack in bytes
+ *
+ * Free a stack allocated via qemu_alloc_stack(). Note that sz must
+ * be exactly the adjusted stack size returned by qemu_alloc_stack.
+ */
+void qemu_free_stack(void *stack, size_t sz);
+
#endif
diff --git a/kvm-all.c b/kvm-all.c
index fc2898a951..efb5fe37e2 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -119,6 +119,7 @@ bool kvm_readonly_mem_allowed;
bool kvm_vm_attributes_allowed;
bool kvm_direct_msi_allowed;
bool kvm_ioeventfd_any_length_allowed;
+bool kvm_msi_use_devid;
static const KVMCapabilityInfo kvm_required_capabilites[] = {
KVM_CAP_INFO(USER_MEMORY),
@@ -1275,6 +1276,10 @@ int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
kroute.u.msi.address_lo = (uint32_t)msg.address;
kroute.u.msi.address_hi = msg.address >> 32;
kroute.u.msi.data = le32_to_cpu(msg.data);
+ if (kvm_msi_devid_required()) {
+ kroute.flags = KVM_MSI_VALID_DEVID;
+ kroute.u.msi.devid = pci_requester_id(dev);
+ }
if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data, dev)) {
kvm_irqchip_release_virq(s, virq);
return -EINVAL;
@@ -1308,6 +1313,10 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg,
kroute.u.msi.address_lo = (uint32_t)msg.address;
kroute.u.msi.address_hi = msg.address >> 32;
kroute.u.msi.data = le32_to_cpu(msg.data);
+ if (kvm_msi_devid_required()) {
+ kroute.flags = KVM_MSI_VALID_DEVID;
+ kroute.u.msi.devid = pci_requester_id(dev);
+ }
if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data, dev)) {
return -EINVAL;
}
diff --git a/kvm-stub.c b/kvm-stub.c
index 322712764f..b1b6b96c96 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -31,6 +31,7 @@ bool kvm_gsi_direct_mapping;
bool kvm_allowed;
bool kvm_readonly_mem_allowed;
bool kvm_ioeventfd_any_length_allowed;
+bool kvm_msi_use_devid;
int kvm_destroy_vcpu(CPUState *cpu)
{
diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile
index afa48f1cf1..fa53d9e58e 100644
--- a/pc-bios/optionrom/Makefile
+++ b/pc-bios/optionrom/Makefile
@@ -43,16 +43,16 @@ build-all: multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin
%.o: %.S
- $(call quiet-command,$(CPP) $(QEMU_INCLUDES) $(QEMU_DGFLAGS) -c -o - $< | $(AS) $(ASFLAGS) -o $@," AS $(TARGET_DIR)$@")
+ $(call quiet-command,$(CPP) $(QEMU_INCLUDES) $(QEMU_DGFLAGS) -c -o - $< | $(AS) $(ASFLAGS) -o $@,"AS","$(TARGET_DIR)$@")
%.img: %.o
- $(call quiet-command,$(LD) $(LDFLAGS_NOPIE) -m $(LD_I386_EMULATION) -T $(SRC_PATH)/pc-bios/optionrom/flat.lds -s -o $@ $<," Building $(TARGET_DIR)$@")
+ $(call quiet-command,$(LD) $(LDFLAGS_NOPIE) -m $(LD_I386_EMULATION) -T $(SRC_PATH)/pc-bios/optionrom/flat.lds -s -o $@ $<,"BUILD","$(TARGET_DIR)$@")
%.raw: %.img
- $(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@," Building $(TARGET_DIR)$@")
+ $(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@,"BUILD","$(TARGET_DIR)$@")
%.bin: %.raw
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/signrom.py $< $@," Signing $(TARGET_DIR)$@")
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/signrom.py $< $@,"SIGN","$(TARGET_DIR)$@")
clean:
rm -f *.o *.d *.raw *.img *.bin *~
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
index 089f6ba5e9..cf05bf0be2 100644
--- a/pc-bios/s390-ccw.img
+++ b/pc-bios/s390-ccw.img
Binary files differ
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index 0ab25388a4..0339c24789 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -19,10 +19,10 @@ LDFLAGS += -Wl,-pie -nostdlib
build-all: s390-ccw.img
s390-ccw.elf: $(OBJECTS)
- $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS)," Building $(TARGET_DIR)$@")
+ $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS),"BUILD","$(TARGET_DIR)$@")
s390-ccw.img: s390-ccw.elf
- $(call quiet-command,strip --strip-unneeded $< -o $@," Stripping $(TARGET_DIR)$@")
+ $(call quiet-command,strip --strip-unneeded $< -o $@,"STRIP","$(TARGET_DIR)$@")
$(OBJECTS): Makefile
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index 1d34e8c1aa..b333734955 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -97,7 +97,8 @@ static int run_ccw(VDev *vdev, int cmd, void *ptr, int len)
/* start command processing */
stsch_err(vdev->schid, &schib);
- schib.scsw.ctrl = SCSW_FCTL_START_FUNC;
+ /* enable the subchannel for IPL device */
+ schib.pmcw.ena = 1;
msch(vdev->schid, &schib);
/* start subchannel command */
diff --git a/pc-bios/spapr-rtas/Makefile b/pc-bios/spapr-rtas/Makefile
index dc8b23e3ce..f26dd428b7 100644
--- a/pc-bios/spapr-rtas/Makefile
+++ b/pc-bios/spapr-rtas/Makefile
@@ -15,10 +15,10 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/spapr-rtas)
build-all: spapr-rtas.bin
%.img: %.o
- $(call quiet-command,$(CC) -nostdlib -o $@ $<," Building $(TARGET_DIR)$@")
+ $(call quiet-command,$(CC) -nostdlib -o $@ $<,"Building","$(TARGET_DIR)$@")
%.bin: %.img
- $(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@," Building $(TARGET_DIR)$@")
+ $(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@,"Building","$(TARGET_DIR)$@")
clean:
rm -f *.o *.d *.img *.bin *~
diff --git a/po/Makefile b/po/Makefile
index 7bab09dce2..cc630363de 100644
--- a/po/Makefile
+++ b/po/Makefile
@@ -10,7 +10,7 @@ all:
.PHONY: all build clean install update
%.mo: %.po
- $(call quiet-command, msgfmt -o $@ $<, " GEN $@")
+ $(call quiet-command, msgfmt -o $@ $<,"GEN","$@")
-include ../config-host.mak
include $(SRC_PATH)/rules.mak
@@ -46,7 +46,7 @@ $(PO_PATH)/messages.po: $(SRC_PATH)/ui/gtk.c
xgettext -o - --from-code=UTF-8 --foreign-user \
--package-name=QEMU --package-version=$(VERSION) \
--msgid-bugs-address=qemu-devel@nongnu.org -k_ -C ui/gtk.c | \
- sed -e s/CHARSET/UTF-8/) >$@, " GEN $@")
+ sed -e s/CHARSET/UTF-8/) >$@,"GEN","$@")
$(PO_PATH)/%.po: $(PO_PATH)/messages.po
- $(call quiet-command, msgmerge -q $@ $< > $@.bak && mv $@.bak $@, " GEN $@")
+ $(call quiet-command, msgmerge -q $@ $< > $@.bak && mv $@.bak $@,"GEN","$@")
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 92193ab0a1..9d797b8fe0 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1721,15 +1721,16 @@
##
# @BlockdevOptionsFile
#
-# Driver specific block device options for the file backend and similar
-# protocols.
+# Driver specific block device options for the file backend.
#
# @filename: path to the image file
+# @aio: #optional AIO backend (default: threads) (since: 2.8)
#
# Since: 1.7
##
{ 'struct': 'BlockdevOptionsFile',
- 'data': { 'filename': 'str' } }
+ 'data': { 'filename': 'str',
+ '*aio': 'BlockdevAioOptions' } }
##
# @BlockdevOptionsNull
@@ -2211,6 +2212,18 @@
'*top-id': 'str' } }
##
+# @BlockdevOptionsCurl
+#
+# Driver specific block device options for the curl backend.
+#
+# @filename: path to the image file
+#
+# Since: 1.7
+##
+{ 'struct': 'BlockdevOptionsCurl',
+ 'data': { 'filename': 'str' } }
+
+##
# @BlockdevOptions
#
# Options for creating a block device. Many options are available for all
@@ -2221,7 +2234,6 @@
# This option is required on the top level of blockdev-add.
# @discard: #optional discard-related options (default: ignore)
# @cache: #optional cache-related options
-# @aio: #optional AIO backend (default: threads)
# @read-only: #optional whether the block device should be read-only
# (default: false)
# @detect-zeroes: #optional detect and optimize zero writes (Since 2.1)
@@ -2236,7 +2248,6 @@
'*node-name': 'str',
'*discard': 'BlockdevDiscardOptions',
'*cache': 'BlockdevCacheOptions',
- '*aio': 'BlockdevAioOptions',
'*read-only': 'bool',
'*detect-zeroes': 'BlockdevDetectZeroesOptions' },
'discriminator': 'driver',
@@ -2248,13 +2259,13 @@
'cloop': 'BlockdevOptionsGenericFormat',
'dmg': 'BlockdevOptionsGenericFormat',
'file': 'BlockdevOptionsFile',
- 'ftp': 'BlockdevOptionsFile',
- 'ftps': 'BlockdevOptionsFile',
+ 'ftp': 'BlockdevOptionsCurl',
+ 'ftps': 'BlockdevOptionsCurl',
'gluster': 'BlockdevOptionsGluster',
'host_cdrom': 'BlockdevOptionsFile',
'host_device':'BlockdevOptionsFile',
- 'http': 'BlockdevOptionsFile',
- 'https': 'BlockdevOptionsFile',
+ 'http': 'BlockdevOptionsCurl',
+ 'https': 'BlockdevOptionsCurl',
# TODO iscsi: Wait for structured options
'luks': 'BlockdevOptionsLUKS',
# TODO nbd: Should take InetSocketAddress for 'host'?
@@ -2271,7 +2282,7 @@
'replication':'BlockdevOptionsReplication',
# TODO sheepdog: Wait for structured options
# TODO ssh: Should take InetSocketAddress for 'host'?
- 'tftp': 'BlockdevOptionsFile',
+ 'tftp': 'BlockdevOptionsCurl',
'vdi': 'BlockdevOptionsGenericFormat',
'vhdx': 'BlockdevOptionsGenericFormat',
'vmdk': 'BlockdevOptionsGenericCOWFormat',
diff --git a/qga/vss-win32/Makefile.objs b/qga/vss-win32/Makefile.objs
index 7c96c6b288..23d08da225 100644
--- a/qga/vss-win32/Makefile.objs
+++ b/qga/vss-win32/Makefile.objs
@@ -7,7 +7,7 @@ $(obj-qga-vss-dll-obj-y): QEMU_CXXFLAGS = $(filter-out -Wstrict-prototypes -Wmis
$(obj)/qga-vss.dll: LDFLAGS = -shared -Wl,--add-stdcall-alias,--enable-stdcall-fixup -lole32 -loleaut32 -lshlwapi -luuid -static
$(obj)/qga-vss.dll: $(obj-qga-vss-dll-obj-y) $(SRC_PATH)/$(obj)/qga-vss.def
- $(call quiet-command,$(CXX) -o $@ $(qga-vss-dll-obj-y) $(SRC_PATH)/qga/vss-win32/qga-vss.def $(CXXFLAGS) $(LDFLAGS)," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(CXX) -o $@ $(qga-vss-dll-obj-y) $(SRC_PATH)/qga/vss-win32/qga-vss.def $(CXXFLAGS) $(LDFLAGS),"LINK","$(TARGET_DIR)$@")
# rules to build qga-provider.tlb
@@ -17,7 +17,7 @@ MIDL=$(WIN_SDK)/Bin/midl
$(obj)/qga-vss.tlb: $(SRC_PATH)/$(obj)/qga-vss.idl
ifeq ($(WIN_SDK),"")
- $(call quiet-command,cp $(dir $<)qga-vss.tlb $@, " COPY $(TARGET_DIR)$@")
+ $(call quiet-command,cp $(dir $<)qga-vss.tlb $@,"COPY","$(TARGET_DIR)$@")
else
- $(call quiet-command,$(MIDL) -tlb $@ -I $(WIN_SDK)/Include $<," MIDL $(TARGET_DIR)$@")
+ $(call quiet-command,$(MIDL) -tlb $@ -I $(WIN_SDK)/Include $<,"MIDL","$(TARGET_DIR)$@")
endif
diff --git a/rules.mak b/rules.mak
index 5c82c19f73..3fdb261e32 100644
--- a/rules.mak
+++ b/rules.mak
@@ -57,9 +57,9 @@ expand-objs = $(strip $(sort $(filter %.o,$1)) \
$(filter-out %.o %.mo,$1))
%.o: %.c
- $(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<," CC $(TARGET_DIR)$@")
+ $(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<,"CC","$(TARGET_DIR)$@")
%.o: %.rc
- $(call quiet-command,$(WINDRES) -I. -o $@ $<," RC $(TARGET_DIR)$@")
+ $(call quiet-command,$(WINDRES) -I. -o $@ $<,"RC","$(TARGET_DIR)$@")
# If we have a CXX we might have some C++ objects, in which case we
# must link with the C++ compiler, not the plain C compiler.
@@ -67,22 +67,22 @@ LINKPROG = $(or $(CXX),$(CC))
LINK = $(call quiet-command, $(LINKPROG) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
$(call process-archive-undefs, $1) \
- $(version-obj-y) $(call extract-libs,$1) $(LIBS)," LINK $(TARGET_DIR)$@")
+ $(version-obj-y) $(call extract-libs,$1) $(LIBS),"LINK","$(TARGET_DIR)$@")
%.o: %.S
- $(call quiet-command,$(CCAS) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CCAS $(TARGET_DIR)$@")
+ $(call quiet-command,$(CCAS) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"CCAS","$(TARGET_DIR)$@")
%.o: %.cc
- $(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<," CXX $(TARGET_DIR)$@")
+ $(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<,"CXX","$(TARGET_DIR)$@")
%.o: %.cpp
- $(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<," CXX $(TARGET_DIR)$@")
+ $(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<,"CXX","$(TARGET_DIR)$@")
%.o: %.m
- $(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<," OBJC $(TARGET_DIR)$@")
+ $(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<,"OBJC","$(TARGET_DIR)$@")
%.o: %.dtrace
- $(call quiet-command,dtrace -o $@ -G -s $<, " GEN $(TARGET_DIR)$@")
+ $(call quiet-command,dtrace -o $@ -G -s $<,"GEN","$(TARGET_DIR)$@")
DSO_OBJ_CFLAGS := -fPIC -DBUILD_DSO
module-common.o: CFLAGS += $(DSO_OBJ_CFLAGS)
@@ -90,13 +90,13 @@ module-common.o: CFLAGS += $(DSO_OBJ_CFLAGS)
%$(DSOSUF): %.mo
$(call LINK,$^)
@# Copy to build root so modules can be loaded when program started without install
- $(if $(findstring /,$@),$(call quiet-command,cp $@ $(subst /,-,$@), " CP $(subst /,-,$@)"))
+ $(if $(findstring /,$@),$(call quiet-command,cp $@ $(subst /,-,$@),"CP","$(subst /,-,$@)"))
LD_REL := $(CC) -nostdlib -Wl,-r $(LD_REL_FLAGS)
%.mo:
- $(call quiet-command,$(LD_REL) -o $@ $^," LD -r $(TARGET_DIR)$@")
+ $(call quiet-command,$(LD_REL) -o $@ $^,"LD","$(TARGET_DIR)$@")
.PHONY: modules
modules:
@@ -105,9 +105,15 @@ modules:
$(call LINK,$(filter %.o %.a %.mo, $^))
%.a:
- $(call quiet-command,rm -f $@ && $(AR) rcs $@ $^," AR $(TARGET_DIR)$@")
+ $(call quiet-command,rm -f $@ && $(AR) rcs $@ $^,"AR","$(TARGET_DIR)$@")
-quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1))
+# Usage: $(call quiet-command,command and args,"NAME","args to print")
+# This will run "command and args", and either:
+# if V=1 just print the whole command and args
+# otherwise print the 'quiet' output in the format " NAME args to print"
+# NAME should be a short name of the command, 7 letters or fewer.
+# If called with only a single argument, will print nothing in quiet mode.
+quiet-command = $(if $(V),$1,$(if $(2),@printf " %-7s %s\n" $2 $3 && $1, @$1))
# cc-option
# Usage: CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0)
@@ -173,7 +179,7 @@ config-%.h: config-%.h-timestamp
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
config-%.h-timestamp: config-%.mak $(SRC_PATH)/scripts/create_config
- $(call quiet-command, sh $(SRC_PATH)/scripts/create_config < $< > $@, " GEN $(TARGET_DIR)config-$*.h")
+ $(call quiet-command, sh $(SRC_PATH)/scripts/create_config < $< > $@,"GEN","$(TARGET_DIR)config-$*.h")
.PHONY: clean-timestamp
clean-timestamp:
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
index a4193684a8..633d08828a 100644
--- a/target-arm/kvm_arm.h
+++ b/target-arm/kvm_arm.h
@@ -13,6 +13,7 @@
#include "sysemu/kvm.h"
#include "exec/memory.h"
+#include "qemu/error-report.h"
/**
* kvm_arm_vcpu_init:
@@ -223,7 +224,20 @@ static inline const char *gic_class_name(void)
*
* Returns: class name to use
*/
-const char *gicv3_class_name(void);
+static inline const char *gicv3_class_name(void)
+{
+ if (kvm_irqchip_in_kernel()) {
+#ifdef TARGET_AARCH64
+ return "kvm-arm-gicv3";
+#else
+ error_report("KVM GICv3 acceleration is not supported on this "
+ "platform");
+ exit(1);
+#endif
+ } else {
+ return "arm-gicv3";
+ }
+}
/**
* kvm_arm_handle_debug:
@@ -255,4 +269,23 @@ struct kvm_guest_debug_arch;
void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr);
+/**
+ * its_class_name
+ *
+ * Return the ITS class name to use depending on whether KVM acceleration
+ * and KVM CAP_SIGNAL_MSI are supported
+ *
+ * Returns: class name to use or NULL
+ */
+static inline const char *its_class_name(void)
+{
+ if (kvm_irqchip_in_kernel()) {
+ /* KVM implementation requires this capability */
+ return kvm_direct_msi_enabled() ? "arm-its-kvm" : NULL;
+ } else {
+ /* Software emulation is not implemented yet */
+ return NULL;
+ }
+}
+
#endif
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 7a6ca31a8e..d90943b6db 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -331,18 +331,3 @@ const VMStateDescription vmstate_arm_cpu = {
NULL
}
};
-
-const char *gicv3_class_name(void)
-{
- if (kvm_irqchip_in_kernel()) {
-#ifdef TARGET_AARCH64
- return "kvm-arm-gicv3";
-#else
- error_report("KVM GICv3 acceleration is not supported on this "
- "platform");
- exit(1);
-#endif
- } else {
- return "arm-gicv3";
- }
-}
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index ddf52f5e79..307e281557 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -2025,7 +2025,7 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
do_fp_ld(s, rt, tcg_addr, size);
} else {
/* Only unsigned 32bit loads target 32bit registers. */
- bool iss_sf = opc == 0 ? 32 : 64;
+ bool iss_sf = opc != 0;
do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false,
true, rt, iss_sf, false);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 693d4bc6a2..8df24bf35a 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -180,7 +180,12 @@ static inline TCGv_i32 load_reg(DisasContext *s, int reg)
static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
{
if (reg == 15) {
- tcg_gen_andi_i32(var, var, ~1);
+ /* In Thumb mode, we must ignore bit 0.
+ * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
+ * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
+ * We choose to ignore [1:0] in ARM mode for all architecture versions.
+ */
+ tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
s->is_jmp = DISAS_JUMP;
}
tcg_gen_mov_i32(cpu_R[reg], var);
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 333309b9a7..1c57fce81b 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -258,6 +258,7 @@ typedef struct FeatureWordInfo {
int cpuid_reg; /* output register (R_* constant) */
uint32_t tcg_features; /* Feature flags supported by TCG */
uint32_t unmigratable_flags; /* Feature flags known to be unmigratable */
+ uint32_t migratable_flags; /* Feature flags known to be migratable */
} FeatureWordInfo;
static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
@@ -494,6 +495,10 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
.cpuid_needs_ecx = true, .cpuid_ecx = 0,
.cpuid_reg = R_EAX,
.tcg_features = ~0U,
+ .migratable_flags = XSTATE_FP_MASK | XSTATE_SSE_MASK |
+ XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | XSTATE_BNDCSR_MASK |
+ XSTATE_OPMASK_MASK | XSTATE_ZMM_Hi256_MASK | XSTATE_Hi16_ZMM_MASK |
+ XSTATE_PKRU_MASK,
},
[FEAT_XSAVE_COMP_HI] = {
.cpuid_eax = 0xD,
@@ -600,15 +605,13 @@ static uint32_t x86_cpu_get_migratable_flags(FeatureWord w)
for (i = 0; i < 32; i++) {
uint32_t f = 1U << i;
- /* If the feature name is unknown, it is not supported by QEMU yet */
- if (!wi->feat_names[i]) {
- continue;
- }
- /* Skip features known to QEMU, but explicitly marked as unmigratable */
- if (wi->unmigratable_flags & f) {
- continue;
+
+ /* If the feature name is known, it is implicitly considered migratable,
+ * unless it is explicitly set in unmigratable_flags */
+ if ((wi->migratable_flags & f) ||
+ (wi->feat_names[i] && !(wi->unmigratable_flags & f))) {
+ r |= f;
}
- r |= f;
}
return r;
}
@@ -1425,9 +1428,9 @@ static X86CPUDefinition builtin_x86_defs[] = {
.name = "Opteron_G3",
.level = 5,
.vendor = CPUID_VENDOR_AMD,
- .family = 15,
- .model = 6,
- .stepping = 1,
+ .family = 16,
+ .model = 2,
+ .stepping = 3,
.features[FEAT_1_EDX] =
CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
diff --git a/target-i386/monitor.c b/target-i386/monitor.c
index fccfe40ab7..9a3b4d746e 100644
--- a/target-i386/monitor.c
+++ b/target-i386/monitor.c
@@ -504,7 +504,8 @@ void hmp_info_local_apic(Monitor *mon, const QDict *qdict)
void hmp_info_io_apic(Monitor *mon, const QDict *qdict)
{
- if (kvm_irqchip_in_kernel()) {
+ if (kvm_irqchip_in_kernel() &&
+ !kvm_irqchip_is_split()) {
kvm_ioapic_dump_state(mon, qdict);
} else {
ioapic_dump_state(mon, qdict);
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index a1c29628bd..796ad455f8 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -147,6 +147,9 @@ 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_4(vcmpequd, void, env, avr, avr, avr)
+DEF_HELPER_4(vcmpneb, void, env, avr, avr, avr)
+DEF_HELPER_4(vcmpneh, void, env, avr, avr, avr)
+DEF_HELPER_4(vcmpnew, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpnezb, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpnezh, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpnezw, void, env, avr, avr, avr)
@@ -166,6 +169,9 @@ DEF_HELPER_4(vcmpequb_dot, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpequh_dot, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpequw_dot, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpequd_dot, void, env, avr, avr, avr)
+DEF_HELPER_4(vcmpneb_dot, void, env, avr, avr, avr)
+DEF_HELPER_4(vcmpneh_dot, void, env, avr, avr, avr)
+DEF_HELPER_4(vcmpnew_dot, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpnezb_dot, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpnezh_dot, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpnezw_dot, void, env, avr, avr, avr)
@@ -337,6 +343,8 @@ DEF_HELPER_2(vpopcntb, void, avr, avr)
DEF_HELPER_2(vpopcnth, void, avr, avr)
DEF_HELPER_2(vpopcntw, void, avr, avr)
DEF_HELPER_2(vpopcntd, void, avr, avr)
+DEF_HELPER_1(vclzlsbb, tl, avr)
+DEF_HELPER_1(vctzlsbb, tl, avr)
DEF_HELPER_3(vbpermd, void, avr, avr, avr)
DEF_HELPER_3(vbpermq, void, avr, avr, avr)
DEF_HELPER_2(vgbbd, void, avr, avr)
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index 51a9ac5182..202854fabd 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -735,20 +735,24 @@ VCMP(gtsd, >, s64)
#undef VCMP_DO
#undef VCMP
-#define VCMPNEZ_DO(suffix, element, etype, record) \
-void helper_vcmpnez##suffix(CPUPPCState *env, ppc_avr_t *r, \
+#define VCMPNE_DO(suffix, element, etype, cmpzero, record) \
+void helper_vcmpne##suffix(CPUPPCState *env, ppc_avr_t *r, \
ppc_avr_t *a, ppc_avr_t *b) \
{ \
etype ones = (etype)-1; \
etype all = ones; \
- etype none = 0; \
+ etype result, none = 0; \
int i; \
\
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
- etype result = ((a->element[i] == 0) \
+ if (cmpzero) { \
+ result = ((a->element[i] == 0) \
|| (b->element[i] == 0) \
|| (a->element[i] != b->element[i]) ? \
ones : 0x0); \
+ } else { \
+ result = (a->element[i] != b->element[i]) ? ones : 0x0; \
+ } \
r->element[i] = result; \
all &= result; \
none |= result; \
@@ -762,14 +766,17 @@ void helper_vcmpnez##suffix(CPUPPCState *env, ppc_avr_t *r, \
* suffix - instruction mnemonic suffix (b: byte, h: halfword, w: word)
* element - element type to access from vector
*/
-#define VCMPNEZ(suffix, element, etype) \
- VCMPNEZ_DO(suffix, element, etype, 0) \
- VCMPNEZ_DO(suffix##_dot, element, etype, 1)
-VCMPNEZ(b, u8, uint8_t)
-VCMPNEZ(h, u16, uint16_t)
-VCMPNEZ(w, u32, uint32_t)
-#undef VCMPNEZ_DO
-#undef VCMPNEZ
+#define VCMPNE(suffix, element, etype, cmpzero) \
+ VCMPNE_DO(suffix, element, etype, cmpzero, 0) \
+ VCMPNE_DO(suffix##_dot, element, etype, cmpzero, 1)
+VCMPNE(zb, u8, uint8_t, 1)
+VCMPNE(zh, u16, uint16_t, 1)
+VCMPNE(zw, u32, uint32_t, 1)
+VCMPNE(b, u8, uint8_t, 0)
+VCMPNE(h, u16, uint16_t, 0)
+VCMPNE(w, u32, uint32_t, 0)
+#undef VCMPNE_DO
+#undef VCMPNE
#define VCMPFP_DO(suffix, compare, order, record) \
void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r, \
@@ -874,6 +881,36 @@ VCT(uxs, cvtsduw, u32)
VCT(sxs, cvtsdsw, s32)
#undef VCT
+target_ulong helper_vclzlsbb(ppc_avr_t *r)
+{
+ target_ulong count = 0;
+ int i;
+ VECTOR_FOR_INORDER_I(i, u8) {
+ if (r->u8[i] & 0x01) {
+ break;
+ }
+ count++;
+ }
+ return count;
+}
+
+target_ulong helper_vctzlsbb(ppc_avr_t *r)
+{
+ target_ulong count = 0;
+ int i;
+#if defined(HOST_WORDS_BIGENDIAN)
+ for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) {
+#else
+ for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
+#endif
+ if (r->u8[i] & 0x01) {
+ break;
+ }
+ count++;
+ }
+ return count;
+}
+
void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
ppc_avr_t *b, ppc_avr_t *c)
{
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index a18d4d5654..9c4834c4fc 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -80,6 +80,7 @@ static int cap_ppc_watchdog;
static int cap_papr;
static int cap_htab_fd;
static int cap_fixup_hcalls;
+static int cap_htm; /* Hardware transactional memory support */
static uint32_t debug_inst_opcode;
@@ -101,6 +102,16 @@ static void kvm_kick_cpu(void *opaque)
qemu_cpu_kick(CPU(cpu));
}
+/* Check whether we are running with KVM-PR (instead of KVM-HV). This
+ * should only be used for fallback tests - generally we should use
+ * explicit capabilities for the features we want, rather than
+ * assuming what is/isn't available depending on the KVM variant. */
+static bool kvmppc_is_pr(KVMState *ks)
+{
+ /* Assume KVM-PR if the GET_PVINFO capability is available */
+ return kvm_check_extension(ks, KVM_CAP_PPC_GET_PVINFO) != 0;
+}
+
static int kvm_ppc_register_host_cpu_type(void);
int kvm_arch_init(MachineState *ms, KVMState *s)
@@ -122,6 +133,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
* only activated after this by kvmppc_set_papr() */
cap_htab_fd = kvm_check_extension(s, KVM_CAP_PPC_HTAB_FD);
cap_fixup_hcalls = kvm_check_extension(s, KVM_CAP_PPC_FIXUP_HCALL);
+ cap_htm = kvm_vm_check_extension(s, KVM_CAP_PPC_HTM);
if (!cap_interrupt_level) {
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -221,10 +233,9 @@ static void kvm_get_fallback_smmu_info(PowerPCCPU *cpu,
*
* For that to work we make a few assumptions:
*
- * - If KVM_CAP_PPC_GET_PVINFO is supported we are running "PR"
- * KVM which only supports 4K and 16M pages, but supports them
- * regardless of the backing store characteritics. We also don't
- * support 1T segments.
+ * - Check whether we are running "PR" KVM which only supports 4K
+ * and 16M pages, but supports them regardless of the backing
+ * store characteritics. We also don't support 1T segments.
*
* This is safe as if HV KVM ever supports that capability or PR
* KVM grows supports for more page/segment sizes, those versions
@@ -239,7 +250,7 @@ static void kvm_get_fallback_smmu_info(PowerPCCPU *cpu,
* implements KVM_CAP_PPC_GET_SMMU_INFO and thus doesn't hit
* this fallback.
*/
- if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO)) {
+ if (kvmppc_is_pr(cs->kvm_state)) {
/* No flags */
info->flags = 0;
info->slb_size = 64;
@@ -559,11 +570,18 @@ int kvm_arch_init_vcpu(CPUState *cs)
idle_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, kvm_kick_cpu, cpu);
- /* Some targets support access to KVM's guest TLB. */
switch (cenv->mmu_model) {
case POWERPC_MMU_BOOKE206:
+ /* This target supports access to KVM's guest TLB */
ret = kvm_booke206_tlb_init(cpu);
break;
+ case POWERPC_MMU_2_07:
+ if (!cap_htm && !kvmppc_is_pr(cs->kvm_state)) {
+ /* KVM-HV has transactional memory on POWER8 also without the
+ * KVM_CAP_PPC_HTM extension, so enable it here instead. */
+ cap_htm = true;
+ }
+ break;
default:
break;
}
@@ -2268,11 +2286,8 @@ int kvmppc_reset_htab(int shift_hint)
/* We have a kernel that predates the htab reset calls. For PR
* KVM, we need to allocate the htab ourselves, for an HV KVM of
- * this era, it has allocated a 16MB fixed size hash table
- * already. Kernels of this era have the GET_PVINFO capability
- * only on PR, so we use this hack to determine the right
- * answer */
- if (kvm_check_extension(kvm_state, KVM_CAP_PPC_GET_PVINFO)) {
+ * this era, it has allocated a 16MB fixed size hash table already. */
+ if (kvmppc_is_pr(kvm_state)) {
/* PR - tell caller to allocate htab */
return 0;
} else {
@@ -2353,6 +2368,11 @@ bool kvmppc_has_cap_fixup_hcalls(void)
return cap_fixup_hcalls;
}
+bool kvmppc_has_cap_htm(void)
+{
+ return cap_htm;
+}
+
static PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc)
{
ObjectClass *oc = OBJECT_CLASS(pcc);
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index a778184567..bd1d78bfbe 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -55,6 +55,7 @@ void kvmppc_hash64_free_pteg(uint64_t token);
void kvmppc_hash64_write_pte(CPUPPCState *env, target_ulong pte_index,
target_ulong pte0, target_ulong pte1);
bool kvmppc_has_cap_fixup_hcalls(void);
+bool kvmppc_has_cap_htm(void);
int kvmppc_enable_hwrng(void);
int kvmppc_put_books_sregs(PowerPCCPU *cpu);
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
@@ -249,6 +250,11 @@ static inline bool kvmppc_has_cap_fixup_hcalls(void)
abort();
}
+static inline bool kvmppc_has_cap_htm(void)
+{
+ return false;
+}
+
static inline int kvmppc_enable_hwrng(void)
{
return -1;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 8eefd8231d..dab8f19a91 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -6203,7 +6203,7 @@ static opcode_t opcodes[] = {
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
-GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER),
+GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400001, PPC_INTEGER),
GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
#if defined(TARGET_PPC64)
GEN_HANDLER_E(cmpeqb, 0x1F, 0x00, 0x07, 0x00600000, PPC_NONE, PPC2_ISA300),
@@ -6297,7 +6297,7 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
-GEN_HANDLER_E(bctar, 0x13, 0x10, 0x11, 0, PPC_NONE, PPC2_BCTAR_ISA207),
+GEN_HANDLER_E(bctar, 0x13, 0x10, 0x11, 0x0000E000, PPC_NONE, PPC2_BCTAR_ISA207),
GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
#if defined(TARGET_PPC64)
diff --git a/target-ppc/translate/vmx-impl.inc.c b/target-ppc/translate/vmx-impl.inc.c
index 3ce374d891..25cd0735ac 100644
--- a/target-ppc/translate/vmx-impl.inc.c
+++ b/target-ppc/translate/vmx-impl.inc.c
@@ -510,7 +510,16 @@ GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM(vcmpgtfp, 3, 11)
GEN_VXRFORM(vcmpbfp, 3, 15)
-
+GEN_VXRFORM(vcmpneb, 3, 0)
+GEN_VXRFORM(vcmpneh, 3, 1)
+GEN_VXRFORM(vcmpnew, 3, 2)
+
+GEN_VXRFORM_DUAL(vcmpequb, PPC_ALTIVEC, PPC_NONE, \
+ vcmpneb, PPC_NONE, PPC2_ISA300)
+GEN_VXRFORM_DUAL(vcmpequh, PPC_ALTIVEC, PPC_NONE, \
+ vcmpneh, PPC_NONE, PPC2_ISA300)
+GEN_VXRFORM_DUAL(vcmpequw, PPC_ALTIVEC, PPC_NONE, \
+ vcmpnew, PPC_NONE, PPC2_ISA300)
GEN_VXRFORM_DUAL(vcmpeqfp, PPC_ALTIVEC, PPC_NONE, \
vcmpequd, PPC_NONE, PPC2_ALTIVEC_207)
GEN_VXRFORM_DUAL(vcmpbfp, PPC_ALTIVEC, PPC_NONE, \
@@ -584,6 +593,18 @@ static void glue(gen_, name)(DisasContext *ctx) \
tcg_temp_free_ptr(rd); \
}
+#define GEN_VXFORM_NOA_3(name, opc2, opc3, opc4) \
+static void glue(gen_, name)(DisasContext *ctx) \
+ { \
+ TCGv_ptr rb; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ rb = gen_avr_ptr(rB(ctx->opcode)); \
+ gen_helper_##name(cpu_gpr[rD(ctx->opcode)], rb); \
+ tcg_temp_free_ptr(rb); \
+ }
GEN_VXFORM_NOA(vupkhsb, 7, 8);
GEN_VXFORM_NOA(vupkhsh, 7, 9);
GEN_VXFORM_NOA(vupkhsw, 7, 25);
@@ -691,18 +712,18 @@ GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15);
-GEN_VXFORM_DUAL(vspltb, PPC_NONE, PPC2_ALTIVEC_207,
- vextractub, PPC_NONE, PPC2_ISA300);
-GEN_VXFORM_DUAL(vsplth, PPC_NONE, PPC2_ALTIVEC_207,
- vextractuh, PPC_NONE, PPC2_ISA300);
-GEN_VXFORM_DUAL(vspltw, PPC_NONE, PPC2_ALTIVEC_207,
- vextractuw, PPC_NONE, PPC2_ISA300);
-GEN_VXFORM_DUAL(vspltisb, PPC_NONE, PPC2_ALTIVEC_207,
- vinsertb, PPC_NONE, PPC2_ISA300);
-GEN_VXFORM_DUAL(vspltish, PPC_NONE, PPC2_ALTIVEC_207,
- vinserth, PPC_NONE, PPC2_ISA300);
-GEN_VXFORM_DUAL(vspltisw, PPC_NONE, PPC2_ALTIVEC_207,
- vinsertw, PPC_NONE, PPC2_ISA300);
+GEN_VXFORM_DUAL(vspltb, PPC_ALTIVEC, PPC_NONE,
+ vextractub, PPC_NONE, PPC2_ISA300);
+GEN_VXFORM_DUAL(vsplth, PPC_ALTIVEC, PPC_NONE,
+ vextractuh, PPC_NONE, PPC2_ISA300);
+GEN_VXFORM_DUAL(vspltw, PPC_ALTIVEC, PPC_NONE,
+ vextractuw, PPC_NONE, PPC2_ISA300);
+GEN_VXFORM_DUAL(vspltisb, PPC_ALTIVEC, PPC_NONE,
+ vinsertb, PPC_NONE, PPC2_ISA300);
+GEN_VXFORM_DUAL(vspltish, PPC_ALTIVEC, PPC_NONE,
+ vinserth, PPC_NONE, PPC2_ISA300);
+GEN_VXFORM_DUAL(vspltisw, PPC_ALTIVEC, PPC_NONE,
+ vinsertw, PPC_NONE, PPC2_ISA300);
static void gen_vsldoi(DisasContext *ctx)
{
@@ -798,6 +819,8 @@ GEN_VXFORM_NOA_2(vctzb, 1, 24, 28)
GEN_VXFORM_NOA_2(vctzh, 1, 24, 29)
GEN_VXFORM_NOA_2(vctzw, 1, 24, 30)
GEN_VXFORM_NOA_2(vctzd, 1, 24, 31)
+GEN_VXFORM_NOA_3(vclzlsbb, 1, 24, 0)
+GEN_VXFORM_NOA_3(vctzlsbb, 1, 24, 1)
GEN_VXFORM_NOA(vpopcntb, 1, 28)
GEN_VXFORM_NOA(vpopcnth, 1, 29)
GEN_VXFORM_NOA(vpopcntw, 1, 30)
diff --git a/target-ppc/translate/vmx-ops.inc.c b/target-ppc/translate/vmx-ops.inc.c
index a7022a0de5..ac1dc9b2b2 100644
--- a/target-ppc/translate/vmx-ops.inc.c
+++ b/target-ppc/translate/vmx-ops.inc.c
@@ -181,9 +181,6 @@ GEN_HANDLER2_E(name, str, 0x4, opc2, opc3, 0x00000000, PPC_NONE, PPC2_ISA300),
GEN_VXRFORM1_300(name, name, #name, opc2, opc3) \
GEN_VXRFORM1_300(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
-GEN_VXRFORM(vcmpequb, 3, 0)
-GEN_VXRFORM(vcmpequh, 3, 1)
-GEN_VXRFORM(vcmpequw, 3, 2)
GEN_VXRFORM_300(vcmpnezb, 3, 4)
GEN_VXRFORM_300(vcmpnezh, 3, 5)
GEN_VXRFORM_300(vcmpnezw, 3, 6)
@@ -197,28 +194,33 @@ GEN_VXRFORM_DUAL(vcmpeqfp, vcmpequd, 3, 3, PPC_ALTIVEC, PPC_NONE)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM_DUAL(vcmpgtfp, vcmpgtud, 3, 11, PPC_ALTIVEC, PPC_NONE)
GEN_VXRFORM_DUAL(vcmpbfp, vcmpgtsd, 3, 15, PPC_ALTIVEC, PPC_NONE)
+GEN_VXRFORM_DUAL(vcmpequb, vcmpneb, 3, 0, PPC_ALTIVEC, PPC_NONE)
+GEN_VXRFORM_DUAL(vcmpequh, vcmpneh, 3, 1, PPC_ALTIVEC, PPC_NONE)
+GEN_VXRFORM_DUAL(vcmpequw, vcmpnew, 3, 2, PPC_ALTIVEC, PPC_NONE)
#define GEN_VXFORM_DUAL_INV(name0, name1, opc2, opc3, inval0, inval1, type) \
GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, \
PPC_NONE)
GEN_VXFORM_DUAL_INV(vspltb, vextractub, 6, 8, 0x00000000, 0x100000,
- PPC2_ALTIVEC_207),
+ PPC_ALTIVEC),
GEN_VXFORM_DUAL_INV(vsplth, vextractuh, 6, 9, 0x00000000, 0x100000,
- PPC2_ALTIVEC_207),
+ PPC_ALTIVEC),
GEN_VXFORM_DUAL_INV(vspltw, vextractuw, 6, 10, 0x00000000, 0x100000,
- PPC2_ALTIVEC_207),
+ PPC_ALTIVEC),
GEN_VXFORM_300_EXT(vextractd, 6, 11, 0x100000),
GEN_VXFORM_DUAL_INV(vspltisb, vinsertb, 6, 12, 0x00000000, 0x100000,
- PPC2_ALTIVEC_207),
+ PPC_ALTIVEC),
GEN_VXFORM_DUAL_INV(vspltish, vinserth, 6, 13, 0x00000000, 0x100000,
- PPC2_ALTIVEC_207),
+ PPC_ALTIVEC),
GEN_VXFORM_DUAL_INV(vspltisw, vinsertw, 6, 14, 0x00000000, 0x100000,
- PPC2_ALTIVEC_207),
+ PPC_ALTIVEC),
GEN_VXFORM_300_EXT(vinsertd, 6, 15, 0x100000),
GEN_VXFORM_300_EO(vctzb, 0x01, 0x18, 0x1C),
GEN_VXFORM_300_EO(vctzh, 0x01, 0x18, 0x1D),
GEN_VXFORM_300_EO(vctzw, 0x01, 0x18, 0x1E),
GEN_VXFORM_300_EO(vctzd, 0x01, 0x18, 0x1F),
+GEN_VXFORM_300_EO(vclzlsbb, 0x01, 0x18, 0x0),
+GEN_VXFORM_300_EO(vctzlsbb, 0x01, 0x18, 0x1),
GEN_VXFORM_300(vpermr, 0x1D, 0xFF),
#define GEN_VXFORM_NOA(name, opc2, opc3) \
diff --git a/target-ppc/translate/vsx-impl.inc.c b/target-ppc/translate/vsx-impl.inc.c
index eee6052d03..23ec1e115c 100644
--- a/target-ppc/translate/vsx-impl.inc.c
+++ b/target-ppc/translate/vsx-impl.inc.c
@@ -75,7 +75,6 @@ static void gen_lxvdsx(DisasContext *ctx)
static void gen_lxvw4x(DisasContext *ctx)
{
TCGv EA;
- TCGv_i64 tmp;
TCGv_i64 xth = cpu_vsrh(xT(ctx->opcode));
TCGv_i64 xtl = cpu_vsrl(xT(ctx->opcode));
if (unlikely(!ctx->vsx_enabled)) {
@@ -84,22 +83,95 @@ static void gen_lxvw4x(DisasContext *ctx)
}
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
- tmp = tcg_temp_new_i64();
gen_addr_reg_index(ctx, EA);
- gen_qemu_ld32u_i64(ctx, tmp, EA);
- tcg_gen_addi_tl(EA, EA, 4);
- gen_qemu_ld32u_i64(ctx, xth, EA);
- tcg_gen_deposit_i64(xth, xth, tmp, 32, 32);
+ if (ctx->le_mode) {
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+
+ tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEQ);
+ tcg_gen_shri_i64(t1, t0, 32);
+ tcg_gen_deposit_i64(xth, t1, t0, 32, 32);
+ tcg_gen_addi_tl(EA, EA, 8);
+ tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEQ);
+ tcg_gen_shri_i64(t1, t0, 32);
+ tcg_gen_deposit_i64(xtl, t1, t0, 32, 32);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+ } else {
+ tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_addi_tl(EA, EA, 8);
+ tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
+ }
+ tcg_temp_free(EA);
+}
+
+static void gen_bswap16x8(TCGv_i64 outh, TCGv_i64 outl,
+ TCGv_i64 inh, TCGv_i64 inl)
+{
+ TCGv_i64 mask = tcg_const_i64(0x00FF00FF00FF00FF);
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+
+ /* outh = ((inh & mask) << 8) | ((inh >> 8) & mask) */
+ tcg_gen_and_i64(t0, inh, mask);
+ tcg_gen_shli_i64(t0, t0, 8);
+ tcg_gen_shri_i64(t1, inh, 8);
+ tcg_gen_and_i64(t1, t1, mask);
+ tcg_gen_or_i64(outh, t0, t1);
+
+ /* outl = ((inl & mask) << 8) | ((inl >> 8) & mask) */
+ tcg_gen_and_i64(t0, inl, mask);
+ tcg_gen_shli_i64(t0, t0, 8);
+ tcg_gen_shri_i64(t1, inl, 8);
+ tcg_gen_and_i64(t1, t1, mask);
+ tcg_gen_or_i64(outl, t0, t1);
+
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+ tcg_temp_free_i64(mask);
+}
+
+static void gen_lxvh8x(DisasContext *ctx)
+{
+ TCGv EA;
+ TCGv_i64 xth = cpu_vsrh(xT(ctx->opcode));
+ TCGv_i64 xtl = cpu_vsrl(xT(ctx->opcode));
+
+ if (unlikely(!ctx->vsx_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VSXU);
+ return;
+ }
+ gen_set_access_type(ctx, ACCESS_INT);
+
+ EA = tcg_temp_new();
+ gen_addr_reg_index(ctx, EA);
+ tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_addi_tl(EA, EA, 8);
+ tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
+ if (ctx->le_mode) {
+ gen_bswap16x8(xth, xtl, xth, xtl);
+ }
+ tcg_temp_free(EA);
+}
- tcg_gen_addi_tl(EA, EA, 4);
- gen_qemu_ld32u_i64(ctx, tmp, EA);
- tcg_gen_addi_tl(EA, EA, 4);
- gen_qemu_ld32u_i64(ctx, xtl, EA);
- tcg_gen_deposit_i64(xtl, xtl, tmp, 32, 32);
+static void gen_lxvb16x(DisasContext *ctx)
+{
+ TCGv EA;
+ TCGv_i64 xth = cpu_vsrh(xT(ctx->opcode));
+ TCGv_i64 xtl = cpu_vsrl(xT(ctx->opcode));
+ if (unlikely(!ctx->vsx_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VSXU);
+ return;
+ }
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ gen_addr_reg_index(ctx, EA);
+ tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_addi_tl(EA, EA, 8);
+ tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
tcg_temp_free(EA);
- tcg_temp_free_i64(tmp);
}
#define VSX_STORE_SCALAR(name, operation) \
@@ -142,7 +214,8 @@ static void gen_stxvd2x(DisasContext *ctx)
static void gen_stxvw4x(DisasContext *ctx)
{
- TCGv_i64 tmp;
+ TCGv_i64 xsh = cpu_vsrh(xS(ctx->opcode));
+ TCGv_i64 xsl = cpu_vsrl(xS(ctx->opcode));
TCGv EA;
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
@@ -151,21 +224,75 @@ static void gen_stxvw4x(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
- tmp = tcg_temp_new_i64();
+ if (ctx->le_mode) {
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+
+ tcg_gen_shri_i64(t0, xsh, 32);
+ tcg_gen_deposit_i64(t1, t0, xsh, 32, 32);
+ tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEQ);
+ tcg_gen_addi_tl(EA, EA, 8);
+ tcg_gen_shri_i64(t0, xsl, 32);
+ tcg_gen_deposit_i64(t1, t0, xsl, 32, 32);
+ tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEQ);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+ } else {
+ tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_addi_tl(EA, EA, 8);
+ tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
+ }
+ tcg_temp_free(EA);
+}
- tcg_gen_shri_i64(tmp, cpu_vsrh(xS(ctx->opcode)), 32);
- gen_qemu_st32_i64(ctx, tmp, EA);
- tcg_gen_addi_tl(EA, EA, 4);
- gen_qemu_st32_i64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
+static void gen_stxvh8x(DisasContext *ctx)
+{
+ TCGv_i64 xsh = cpu_vsrh(xS(ctx->opcode));
+ TCGv_i64 xsl = cpu_vsrl(xS(ctx->opcode));
+ TCGv EA;
- tcg_gen_shri_i64(tmp, cpu_vsrl(xS(ctx->opcode)), 32);
- tcg_gen_addi_tl(EA, EA, 4);
- gen_qemu_st32_i64(ctx, tmp, EA);
- tcg_gen_addi_tl(EA, EA, 4);
- gen_qemu_st32_i64(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
+ if (unlikely(!ctx->vsx_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VSXU);
+ return;
+ }
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ gen_addr_reg_index(ctx, EA);
+ if (ctx->le_mode) {
+ TCGv_i64 outh = tcg_temp_new_i64();
+ TCGv_i64 outl = tcg_temp_new_i64();
+
+ gen_bswap16x8(outh, outl, xsh, xsl);
+ tcg_gen_qemu_st_i64(outh, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_addi_tl(EA, EA, 8);
+ tcg_gen_qemu_st_i64(outl, EA, ctx->mem_idx, MO_BEQ);
+ tcg_temp_free_i64(outh);
+ tcg_temp_free_i64(outl);
+ } else {
+ tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_addi_tl(EA, EA, 8);
+ tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
+ }
+ tcg_temp_free(EA);
+}
+static void gen_stxvb16x(DisasContext *ctx)
+{
+ TCGv_i64 xsh = cpu_vsrh(xS(ctx->opcode));
+ TCGv_i64 xsl = cpu_vsrl(xS(ctx->opcode));
+ TCGv EA;
+
+ if (unlikely(!ctx->vsx_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VSXU);
+ return;
+ }
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ gen_addr_reg_index(ctx, EA);
+ tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_addi_tl(EA, EA, 8);
+ tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
tcg_temp_free(EA);
- tcg_temp_free_i64(tmp);
}
#define MV_VSRW(name, tcgop1, tcgop2, target, source) \
@@ -217,6 +344,65 @@ static void gen_##name(DisasContext *ctx) \
MV_VSRD(mfvsrd, cpu_gpr[rA(ctx->opcode)], cpu_vsrh(xS(ctx->opcode)))
MV_VSRD(mtvsrd, cpu_vsrh(xT(ctx->opcode)), cpu_gpr[rA(ctx->opcode)])
+static void gen_mfvsrld(DisasContext *ctx)
+{
+ if (xS(ctx->opcode) < 32) {
+ if (unlikely(!ctx->vsx_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VSXU);
+ return;
+ }
+ } else {
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
+ }
+ }
+
+ tcg_gen_mov_i64(cpu_gpr[rA(ctx->opcode)], cpu_vsrl(xS(ctx->opcode)));
+}
+
+static void gen_mtvsrdd(DisasContext *ctx)
+{
+ if (xT(ctx->opcode) < 32) {
+ if (unlikely(!ctx->vsx_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VSXU);
+ return;
+ }
+ } else {
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
+ }
+ }
+
+ if (!rA(ctx->opcode)) {
+ tcg_gen_movi_i64(cpu_vsrh(xT(ctx->opcode)), 0);
+ } else {
+ tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_gpr[rA(ctx->opcode)]);
+ }
+
+ tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_gpr[rB(ctx->opcode)]);
+}
+
+static void gen_mtvsrws(DisasContext *ctx)
+{
+ if (xT(ctx->opcode) < 32) {
+ if (unlikely(!ctx->vsx_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VSXU);
+ return;
+ }
+ } else {
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
+ }
+ }
+
+ tcg_gen_deposit_i64(cpu_vsrl(xT(ctx->opcode)), cpu_gpr[rA(ctx->opcode)],
+ cpu_gpr[rA(ctx->opcode)], 32, 32);
+ tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrl(xT(ctx->opcode)));
+}
+
#endif
static void gen_xxpermdi(DisasContext *ctx)
diff --git a/target-ppc/translate/vsx-ops.inc.c b/target-ppc/translate/vsx-ops.inc.c
index 414b73bd10..10eb4b9470 100644
--- a/target-ppc/translate/vsx-ops.inc.c
+++ b/target-ppc/translate/vsx-ops.inc.c
@@ -7,6 +7,8 @@ GEN_HANDLER_E(lxsspx, 0x1F, 0x0C, 0x10, 0, PPC_NONE, PPC2_VSX207),
GEN_HANDLER_E(lxvd2x, 0x1F, 0x0C, 0x1A, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(lxvdsx, 0x1F, 0x0C, 0x0A, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(lxvw4x, 0x1F, 0x0C, 0x18, 0, PPC_NONE, PPC2_VSX),
+GEN_HANDLER_E(lxvh8x, 0x1F, 0x0C, 0x19, 0, PPC_NONE, PPC2_ISA300),
+GEN_HANDLER_E(lxvb16x, 0x1F, 0x0C, 0x1B, 0, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(stxsdx, 0x1F, 0xC, 0x16, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(stxsibx, 0x1F, 0xD, 0x1C, 0, PPC_NONE, PPC2_ISA300),
@@ -15,6 +17,8 @@ GEN_HANDLER_E(stxsiwx, 0x1F, 0xC, 0x04, 0, PPC_NONE, PPC2_VSX207),
GEN_HANDLER_E(stxsspx, 0x1F, 0xC, 0x14, 0, PPC_NONE, PPC2_VSX207),
GEN_HANDLER_E(stxvd2x, 0x1F, 0xC, 0x1E, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(stxvw4x, 0x1F, 0xC, 0x1C, 0, PPC_NONE, PPC2_VSX),
+GEN_HANDLER_E(stxvh8x, 0x1F, 0x0C, 0x1D, 0, PPC_NONE, PPC2_ISA300),
+GEN_HANDLER_E(stxvb16x, 0x1F, 0x0C, 0x1F, 0, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(mfvsrwz, 0x1F, 0x13, 0x03, 0x0000F800, PPC_NONE, PPC2_VSX207),
GEN_HANDLER_E(mtvsrwa, 0x1F, 0x13, 0x06, 0x0000F800, PPC_NONE, PPC2_VSX207),
@@ -22,6 +26,9 @@ GEN_HANDLER_E(mtvsrwz, 0x1F, 0x13, 0x07, 0x0000F800, PPC_NONE, PPC2_VSX207),
#if defined(TARGET_PPC64)
GEN_HANDLER_E(mfvsrd, 0x1F, 0x13, 0x01, 0x0000F800, PPC_NONE, PPC2_VSX207),
GEN_HANDLER_E(mtvsrd, 0x1F, 0x13, 0x05, 0x0000F800, PPC_NONE, PPC2_VSX207),
+GEN_HANDLER_E(mfvsrld, 0X1F, 0x13, 0x09, 0x0000F800, PPC_NONE, PPC2_ISA300),
+GEN_HANDLER_E(mtvsrdd, 0X1F, 0x13, 0x0D, 0x0, PPC_NONE, PPC2_ISA300),
+GEN_HANDLER_E(mtvsrws, 0x1F, 0x13, 0x0C, 0x0000F800, PPC_NONE, PPC2_ISA300),
#endif
#define GEN_XX1FORM(name, opc2, opc3, fl2) \
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 4329d39c13..6b02b1794c 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -14,10 +14,10 @@ endif
$(feat-dst)gen-features.h: $(feat-dst)gen-features.h-timestamp
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
$(feat-dst)gen-features.h-timestamp: $(feat-dst)gen-features
- $(call quiet-command,$< >$@," GEN $(TARGET_DIR)gen-features.h")
+ $(call quiet-command,$< >$@,"GEN","$(TARGET_DIR)gen-features.h")
$(feat-dst)gen-features: $(feat-src)gen-features.c
- $(call quiet-command,$(HOST_CC) $(QEMU_INCLUDES) -o $@ $<," CC $(TARGET_DIR)gen-features")
+ $(call quiet-command,$(HOST_CC) $(QEMU_INCLUDES) -o $@ $<,"CC","$(TARGET_DIR)gen-features")
clean-target:
rm -f gen-features.h-timestamp
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index fd929e8351..7f745726bd 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -132,6 +132,8 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
KVM_CAP_LAST_INFO
};
+static QemuMutex qemu_sigp_mutex;
+
static int cap_sync_regs;
static int cap_async_pf;
static int cap_mem_op;
@@ -287,6 +289,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
}
}
+ qemu_mutex_init(&qemu_sigp_mutex);
+
return 0;
}
@@ -1776,6 +1780,11 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
status_reg = &env->regs[r1];
param = (r1 % 2) ? env->regs[r1] : env->regs[r1 + 1];
+ if (qemu_mutex_trylock(&qemu_sigp_mutex)) {
+ ret = SIGP_CC_BUSY;
+ goto out;
+ }
+
switch (order) {
case SIGP_SET_ARCH:
ret = sigp_set_architecture(cpu, param, status_reg);
@@ -1785,7 +1794,9 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
dst_cpu = s390_cpu_addr2state(env->regs[r3]);
ret = handle_sigp_single_dst(dst_cpu, order, param, status_reg);
}
+ qemu_mutex_unlock(&qemu_sigp_mutex);
+out:
trace_kvm_sigp_finished(order, CPU(cpu)->cpu_index,
dst_cpu ? CPU(dst_cpu)->cpu_index : -1, ret);
@@ -1990,7 +2001,7 @@ static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr, uint8_t ar)
strcpy((char *)sysib.ext_names[0], "KVMguest");
}
/* Insert UUID */
- memcpy(sysib.vm[0].uuid, qemu_uuid, sizeof(sysib.vm[0].uuid));
+ memcpy(sysib.vm[0].uuid, &qemu_uuid, sizeof(sysib.vm[0].uuid));
s390_cpu_virt_mem_write(cpu, addr, ar, &sysib, sizeof(sysib));
}
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 8162f6f735..a77777cf9c 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -271,6 +271,13 @@ check-qtest-ppc64-y += tests/drive_del-test$(EXESUF)
check-qtest-ppc64-y += tests/postcopy-test$(EXESUF)
check-qtest-ppc64-y += tests/boot-serial-test$(EXESUF)
check-qtest-ppc64-y += tests/rtas-test$(EXESUF)
+check-qtest-ppc64-y += tests/pxe-test$(EXESUF)
+check-qtest-ppc64-y += tests/usb-hcd-ohci-test$(EXESUF)
+gcov-files-ppc64-y += hw/usb/hcd-ohci.c
+check-qtest-ppc64-y += tests/usb-hcd-uhci-test$(EXESUF)
+gcov-files-ppc64-y += hw/usb/hcd-uhci.c
+check-qtest-ppc64-y += tests/usb-hcd-xhci-test$(EXESUF)
+gcov-files-ppc64-y += hw/usb/hcd-xhci.c
check-qtest-sh4-y = tests/endianness-test$(EXESUF)
@@ -517,27 +524,27 @@ tests/test-qapi-types.c tests/test-qapi-types.h :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
$(gen-out-type) -o tests -p "test-" $<, \
- " GEN $@")
+ "GEN","$@")
tests/test-qapi-visit.c tests/test-qapi-visit.h :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
$(gen-out-type) -o tests -p "test-" $<, \
- " GEN $@")
+ "GEN","$@")
tests/test-qmp-commands.h tests/test-qmp-marshal.c :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o tests -p "test-" $<, \
- " GEN $@")
+ "GEN","$@")
tests/test-qapi-event.c tests/test-qapi-event.h :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
$(gen-out-type) -o tests -p "test-" $<, \
- " GEN $@")
+ "GEN","$@")
tests/test-qmp-introspect.c tests/test-qmp-introspect.h :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-introspect.py \
$(gen-out-type) -o tests -p "test-" $<, \
- " GEN $@")
+ "GEN","$@")
tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y)
tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y)
@@ -590,12 +597,13 @@ libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o
libqos-spapr-obj-y = $(libqos-obj-y) tests/libqos/malloc-spapr.o
libqos-spapr-obj-y += tests/libqos/libqos-spapr.o
libqos-spapr-obj-y += tests/libqos/rtas.o
+libqos-spapr-obj-y += tests/libqos/pci-spapr.o
libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o
libqos-pc-obj-y += tests/libqos/ahci.o
libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o
libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o
-libqos-usb-obj-y = $(libqos-pc-obj-y) tests/libqos/usb.o
+libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/usb.o
libqos-virtio-obj-y = $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o tests/libqos/malloc-generic.o
tests/device-introspect-test$(EXESUF): tests/device-introspect-test.o
@@ -671,7 +679,7 @@ tests/ptimer-test$(EXESUF): tests/ptimer-test.o tests/ptimer-test-stubs.o hw/cor
tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y)
tests/migration/stress$(EXESUF): tests/migration/stress.o
- $(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ," LINK $(TARGET_DIR)$@")
+ $(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"LINK","$(TARGET_DIR)$@")
INITRD_WORK_DIR=tests/migration/initrd
@@ -734,7 +742,7 @@ $(patsubst %, check-qtest-%, $(QTEST_TARGETS)): check-qtest-%: $(check-qtest-y)
$(call quiet-command,QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \
QTEST_QEMU_IMG=qemu-img$(EXESUF) \
MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$((RANDOM % 255 + 1))} \
- gtester $(GTESTER_OPTIONS) -m=$(SPEED) $(check-qtest-$*-y) $(check-qtest-generic-y),"GTESTER $@")
+ gtester $(GTESTER_OPTIONS) -m=$(SPEED) $(check-qtest-$*-y) $(check-qtest-generic-y),"GTESTER","$@")
$(if $(CONFIG_GCOV),@for f in $(gcov-files-$*-y) $(gcov-files-generic-y); do \
echo Gcov report for $$f:;\
$(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \
@@ -745,7 +753,7 @@ $(patsubst %, check-%, $(check-unit-y)): check-%: %
$(if $(CONFIG_GCOV),@rm -f *.gcda */*.gcda */*/*.gcda */*/*/*.gcda,)
$(call quiet-command, \
MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$((RANDOM % 255 + 1))} \
- gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER $*")
+ gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER","$*")
$(if $(CONFIG_GCOV),@for f in $(gcov-files-$(subst tests/,,$*)-y) $(gcov-files-generic-y); do \
echo Gcov report for $$f:;\
$(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \
@@ -756,18 +764,18 @@ $(patsubst %, check-%, $(check-unit-y)): check-%: %
$(patsubst %, check-report-qtest-%.xml, $(QTEST_TARGETS)): check-report-qtest-%.xml: $(check-qtest-y)
$(call quiet-command,QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \
QTEST_QEMU_IMG=qemu-img$(EXESUF) \
- gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $(check-qtest-$*-y) $(check-qtest-generic-y),"GTESTER $@")
+ gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $(check-qtest-$*-y) $(check-qtest-generic-y),"GTESTER","$@")
check-report-unit.xml: $(check-unit-y)
- $(call quiet-command,gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $^, "GTESTER $@")
+ $(call quiet-command,gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $^,"GTESTER","$@")
# Reports and overall runs
check-report.xml: $(patsubst %,check-report-qtest-%.xml, $(QTEST_TARGETS)) check-report-unit.xml
- $(call quiet-command,$(SRC_PATH)/scripts/gtester-cat $^ > $@, " GEN $@")
+ $(call quiet-command,$(SRC_PATH)/scripts/gtester-cat $^ > $@,"GEN","$@")
check-report.html: check-report.xml
- $(call quiet-command,gtester-report $< > $@, " GEN $@")
+ $(call quiet-command,gtester-report $< > $@,"GEN","$@")
# Other tests
@@ -787,7 +795,7 @@ $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
$(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py \
$^ >$*.test.out 2>$*.test.err; \
echo $$? >$*.test.exit, \
- " TEST $*.out")
+ "TEST","$*.out")
@diff -q $(SRC_PATH)/$*.out $*.test.out
@# Sanitize error messages (make them independent of build directory)
@perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff -q $(SRC_PATH)/$*.err -
diff --git a/tests/boot-sector.c b/tests/boot-sector.c
index 3ffe2987ff..e3193c0a12 100644
--- a/tests/boot-sector.c
+++ b/tests/boot-sector.c
@@ -77,6 +77,15 @@ int boot_sector_init(const char *fname)
fprintf(stderr, "Couldn't open \"%s\": %s", fname, strerror(errno));
return 1;
}
+
+ /* For Open Firmware based system, we can use a Forth script instead */
+ if (strcmp(qtest_get_arch(), "ppc64") == 0) {
+ memset(boot_sector, ' ', sizeof boot_sector);
+ sprintf((char *)boot_sector, "\\ Bootscript\n%x %x c! %x %x c!\n",
+ LOW(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET,
+ HIGH(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
+ }
+
fwrite(boot_sector, 1, sizeof boot_sector, f);
fclose(f);
return 0;
diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index 2fcc3c6418..b44daabbce 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -25,7 +25,7 @@ make-archive-maybe = $(if $(wildcard $1/*), \
else \
git archive -1 $$(git stash create) --format=tar.gz; \
fi) > $2, \
- " ARCHIVE $(notdir $2)"))
+ "ARCHIVE","$(notdir $2)"))
CUR_TIME := $(shell date +%Y-%m-%d-%H.%M.%S.$$$$)
DOCKER_SRC_COPY := docker-src.$(CUR_TIME)
@@ -36,7 +36,7 @@ $(DOCKER_SRC_COPY):
$(call make-archive-maybe, $(SRC_PATH)/dtc, $@/dtc.tgz)
$(call make-archive-maybe, $(SRC_PATH)/pixman, $@/pixman.tgz)
$(call quiet-command, cp $(SRC_PATH)/tests/docker/run $@/run, \
- " COPY RUNNER")
+ "COPY","RUNNER")
docker-qemu-src: $(DOCKER_SRC_COPY)
@@ -51,7 +51,7 @@ docker-image-%: $(DOCKER_FILES_DIR)/%.docker
$(SRC_PATH)/tests/docker/docker.py build qemu:$* $< \
$(if $V,,--quiet) $(if $(NOCACHE),--no-cache) \
$(if $(EXECUTABLE),--include-executable=$(EXECUTABLE)),\
- " BUILD $*")
+ "BUILD","$*")
# Expand all the pre-requistes for each docker image and test combination
$(foreach i,$(DOCKER_IMAGES), \
@@ -125,7 +125,7 @@ docker-run-%: docker-qemu-src
/var/tmp/qemu/run \
$(CMD); \
fi \
- , " RUN $(CMD) in $(IMAGE)")))
+ ,"RUN","$(CMD) in $(IMAGE)")))
docker-clean:
$(call quiet-command, $(SRC_PATH)/tests/docker/docker.py clean)
diff --git a/tests/docker/common.rc b/tests/docker/common.rc
index 510a3ad3f4..21657e87c6 100755
--- a/tests/docker/common.rc
+++ b/tests/docker/common.rc
@@ -11,6 +11,9 @@
# or (at your option) any later version. See the COPYING file in
# the top-level directory.
+BUILD_DIR=/var/tmp/qemu-build
+mkdir $BUILD_DIR
+
requires()
{
for c in $@; do
diff --git a/tests/docker/test-clang b/tests/docker/test-clang
index 60e4e976b3..16485e6b7e 100755
--- a/tests/docker/test-clang
+++ b/tests/docker/test-clang
@@ -15,6 +15,8 @@
requires clang
+cd "$BUILD_DIR"
+
OPTS="--enable-debug --cxx=clang++ --cc=clang --host-cc=clang"
# -fsanitize=undefined is broken on Fedora 23, skip it for now
# See also: https://bugzilla.redhat.com/show_bug.cgi?id=1263834
diff --git a/tests/docker/test-full b/tests/docker/test-full
index fd9b798947..05f0d491d1 100755
--- a/tests/docker/test-full
+++ b/tests/docker/test-full
@@ -13,5 +13,7 @@
. common.rc
+cd "$BUILD_DIR"
+
build_qemu
make check $MAKEFLAGS
diff --git a/tests/docker/test-mingw b/tests/docker/test-mingw
index c03757add8..33968769f8 100755
--- a/tests/docker/test-mingw
+++ b/tests/docker/test-mingw
@@ -15,6 +15,8 @@
requires mingw dtc
+cd "$BUILD_DIR"
+
for prefix in x86_64-w64-mingw32- i686-w64-mingw32-; do
TARGET_LIST=x86_64-softmmu,aarch64-softmmu \
build_qemu --cross-prefix=$prefix \
diff --git a/tests/docker/test-quick b/tests/docker/test-quick
index 7885dfafdb..c465dc06d8 100755
--- a/tests/docker/test-quick
+++ b/tests/docker/test-quick
@@ -13,6 +13,8 @@
. common.rc
+cd "$BUILD_DIR"
+
DEF_TARGET_LIST="x86_64-softmmu,aarch64-softmmu"
TARGET_LIST=${TARGET_LIST:-$DEF_TARGET_LIST} \
build_qemu
diff --git a/tests/e1000e-test.c b/tests/e1000e-test.c
index d497b0857c..3979b20bb0 100644
--- a/tests/e1000e-test.c
+++ b/tests/e1000e-test.c
@@ -390,7 +390,7 @@ static void data_test_init(e1000e_device *d)
qtest_start(cmdline);
g_free(cmdline);
- test_bus = qpci_init_pc();
+ test_bus = qpci_init_pc(NULL);
g_assert_nonnull(test_bus);
test_alloc = pc_alloc_init();
diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c
index 3542ad114e..da2d5a53f0 100644
--- a/tests/i440fx-test.c
+++ b/tests/i440fx-test.c
@@ -38,7 +38,7 @@ static QPCIBus *test_start_get_bus(const TestData *s)
cmdline = g_strdup_printf("-smp %d", s->num_cpus);
qtest_start(cmdline);
g_free(cmdline);
- return qpci_init_pc();
+ return qpci_init_pc(NULL);
}
static void test_i440fx_defaults(gconstpointer opaque)
diff --git a/tests/ide-test.c b/tests/ide-test.c
index 1e51af2a94..a8a4081f78 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -143,7 +143,7 @@ static QPCIDevice *get_pci_device(uint16_t *bmdma_base)
uint16_t vendor_id, device_id;
if (!pcibus) {
- pcibus = qpci_init_pc();
+ pcibus = qpci_init_pc(NULL);
}
/* Find PCI device and verify it's the right one */
diff --git a/tests/ivshmem-test.c b/tests/ivshmem-test.c
index 0957ee7555..f36bfe7d0a 100644
--- a/tests/ivshmem-test.c
+++ b/tests/ivshmem-test.c
@@ -105,7 +105,7 @@ static void setup_vm_cmd(IVState *s, const char *cmd, bool msix)
uint64_t barsize;
s->qtest = qtest_start(cmd);
- s->pcibus = qpci_init_pc();
+ s->pcibus = qpci_init_pc(NULL);
s->dev = get_device(s->pcibus);
s->reg_base = qpci_iomap(s->dev, 0, &barsize);
diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c
index f3be5500e1..716ab7939e 100644
--- a/tests/libqos/ahci.c
+++ b/tests/libqos/ahci.c
@@ -128,7 +128,7 @@ QPCIDevice *get_ahci_device(uint32_t *fingerprint)
uint32_t ahci_fingerprint;
QPCIBus *pcibus;
- pcibus = qpci_init_pc();
+ pcibus = qpci_init_pc(NULL);
/* Find the AHCI PCI device and verify it's the right one. */
ahci = qpci_device_find(pcibus, QPCI_DEVFN(0x1F, 0x02));
diff --git a/tests/libqos/libqos-pc.c b/tests/libqos/libqos-pc.c
index df340928a6..b554758802 100644
--- a/tests/libqos/libqos-pc.c
+++ b/tests/libqos/libqos-pc.c
@@ -1,10 +1,14 @@
#include "qemu/osdep.h"
#include "libqos/libqos-pc.h"
#include "libqos/malloc-pc.h"
+#include "libqos/pci-pc.h"
static QOSOps qos_ops = {
.init_allocator = pc_alloc_init_flags,
- .uninit_allocator = pc_alloc_uninit
+ .uninit_allocator = pc_alloc_uninit,
+ .qpci_init = qpci_init_pc,
+ .qpci_free = qpci_free_pc,
+ .shutdown = qtest_pc_shutdown,
};
QOSState *qtest_pc_vboot(const char *cmdline_fmt, va_list ap)
@@ -28,5 +32,5 @@ QOSState *qtest_pc_boot(const char *cmdline_fmt, ...)
void qtest_pc_shutdown(QOSState *qs)
{
- return qtest_shutdown(qs);
+ return qtest_common_shutdown(qs);
}
diff --git a/tests/libqos/libqos-spapr.c b/tests/libqos/libqos-spapr.c
index f19408be00..a37791e5d0 100644
--- a/tests/libqos/libqos-spapr.c
+++ b/tests/libqos/libqos-spapr.c
@@ -1,10 +1,14 @@
#include "qemu/osdep.h"
#include "libqos/libqos-spapr.h"
#include "libqos/malloc-spapr.h"
+#include "libqos/pci-spapr.h"
static QOSOps qos_ops = {
.init_allocator = spapr_alloc_init_flags,
- .uninit_allocator = spapr_alloc_uninit
+ .uninit_allocator = spapr_alloc_uninit,
+ .qpci_init = qpci_init_spapr,
+ .qpci_free = qpci_free_spapr,
+ .shutdown = qtest_spapr_shutdown,
};
QOSState *qtest_spapr_vboot(const char *cmdline_fmt, va_list ap)
@@ -26,5 +30,5 @@ QOSState *qtest_spapr_boot(const char *cmdline_fmt, ...)
void qtest_spapr_shutdown(QOSState *qs)
{
- return qtest_shutdown(qs);
+ return qtest_common_shutdown(qs);
}
diff --git a/tests/libqos/libqos.c b/tests/libqos/libqos.c
index a852dc5f8e..7abb48254e 100644
--- a/tests/libqos/libqos.c
+++ b/tests/libqos/libqos.c
@@ -20,8 +20,13 @@ QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap)
cmdline = g_strdup_vprintf(cmdline_fmt, ap);
qs->qts = qtest_start(cmdline);
qs->ops = ops;
- if (ops && ops->init_allocator) {
- qs->alloc = ops->init_allocator(ALLOC_NO_FLAGS);
+ if (ops) {
+ if (ops->init_allocator) {
+ qs->alloc = ops->init_allocator(ALLOC_NO_FLAGS);
+ }
+ if (ops->qpci_init && qs->alloc) {
+ qs->pcibus = ops->qpci_init(qs->alloc);
+ }
}
g_free(cmdline);
@@ -47,16 +52,31 @@ QOSState *qtest_boot(QOSOps *ops, const char *cmdline_fmt, ...)
/**
* Tear down the QEMU instance.
*/
-void qtest_shutdown(QOSState *qs)
+void qtest_common_shutdown(QOSState *qs)
{
- if (qs->alloc && qs->ops && qs->ops->uninit_allocator) {
- qs->ops->uninit_allocator(qs->alloc);
- qs->alloc = NULL;
+ if (qs->ops) {
+ if (qs->pcibus && qs->ops->qpci_free) {
+ qs->ops->qpci_free(qs->pcibus);
+ qs->pcibus = NULL;
+ }
+ if (qs->alloc && qs->ops->uninit_allocator) {
+ qs->ops->uninit_allocator(qs->alloc);
+ qs->alloc = NULL;
+ }
}
qtest_quit(qs->qts);
g_free(qs);
}
+void qtest_shutdown(QOSState *qs)
+{
+ if (qs->ops && qs->ops->shutdown) {
+ qs->ops->shutdown(qs);
+ } else {
+ qtest_common_shutdown(qs);
+ }
+}
+
void set_context(QOSState *s)
{
global_qtest = s->qts;
diff --git a/tests/libqos/libqos.h b/tests/libqos/libqos.h
index 604980d125..231969766f 100644
--- a/tests/libqos/libqos.h
+++ b/tests/libqos/libqos.h
@@ -5,19 +5,26 @@
#include "libqos/pci.h"
#include "libqos/malloc-pc.h"
+typedef struct QOSState QOSState;
+
typedef struct QOSOps {
QGuestAllocator *(*init_allocator)(QAllocOpts);
void (*uninit_allocator)(QGuestAllocator *);
+ QPCIBus *(*qpci_init)(QGuestAllocator *alloc);
+ void (*qpci_free)(QPCIBus *bus);
+ void (*shutdown)(QOSState *);
} QOSOps;
-typedef struct QOSState {
+struct QOSState {
QTestState *qts;
QGuestAllocator *alloc;
+ QPCIBus *pcibus;
QOSOps *ops;
-} QOSState;
+};
QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap);
QOSState *qtest_boot(QOSOps *ops, const char *cmdline_fmt, ...);
+void qtest_common_shutdown(QOSState *qs);
void qtest_shutdown(QOSState *qs);
bool have_qemu_img(void);
void mkimg(const char *file, const char *fmt, unsigned size_mb);
diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
index 1ae2d3780f..9600ed6e41 100644
--- a/tests/libqos/pci-pc.c
+++ b/tests/libqos/pci-pc.c
@@ -212,7 +212,7 @@ static void qpci_pc_iounmap(QPCIBus *bus, void *data)
/* FIXME */
}
-QPCIBus *qpci_init_pc(void)
+QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
{
QPCIBusPC *ret;
@@ -255,28 +255,6 @@ void qpci_free_pc(QPCIBus *bus)
g_free(s);
}
-void qpci_plug_device_test(const char *driver, const char *id,
- uint8_t slot, const char *opts)
-{
- QDict *response;
- char *cmd;
-
- cmd = g_strdup_printf("{'execute': 'device_add',"
- " 'arguments': {"
- " 'driver': '%s',"
- " 'addr': '%d',"
- " %s%s"
- " 'id': '%s'"
- "}}", driver, slot,
- opts ? opts : "", opts ? "," : "",
- id);
- response = qmp(cmd);
- g_free(cmd);
- g_assert(response);
- g_assert(!qdict_haskey(response, "error"));
- QDECREF(response);
-}
-
void qpci_unplug_acpi_device_test(const char *id, uint8_t slot)
{
QDict *response;
diff --git a/tests/libqos/pci-pc.h b/tests/libqos/pci-pc.h
index 26211790cd..9479b51642 100644
--- a/tests/libqos/pci-pc.h
+++ b/tests/libqos/pci-pc.h
@@ -14,8 +14,9 @@
#define LIBQOS_PCI_PC_H
#include "libqos/pci.h"
+#include "libqos/malloc.h"
-QPCIBus *qpci_init_pc(void);
+QPCIBus *qpci_init_pc(QGuestAllocator *alloc);
void qpci_free_pc(QPCIBus *bus);
#endif
diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c
new file mode 100644
index 0000000000..2f73badfd9
--- /dev/null
+++ b/tests/libqos/pci-spapr.c
@@ -0,0 +1,288 @@
+/*
+ * libqos PCI bindings for SPAPR
+ *
+ * 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 "libqos/pci-spapr.h"
+#include "libqos/rtas.h"
+
+#include "hw/pci/pci_regs.h"
+
+#include "qemu-common.h"
+#include "qemu/host-utils.h"
+
+
+/* From include/hw/pci-host/spapr.h */
+
+#define SPAPR_PCI_BASE_BUID 0x800000020000000ULL
+
+#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
+
+#define SPAPR_PCI_WINDOW_BASE 0x10000000000ULL
+#define SPAPR_PCI_WINDOW_SPACING 0x1000000000ULL
+#define SPAPR_PCI_MMIO_WIN_OFF 0xA0000000
+#define SPAPR_PCI_MMIO_WIN_SIZE (SPAPR_PCI_WINDOW_SPACING - \
+ SPAPR_PCI_MEM_WIN_BUS_OFFSET)
+#define SPAPR_PCI_IO_WIN_OFF 0x80000000
+#define SPAPR_PCI_IO_WIN_SIZE 0x10000
+
+/* index is the phb index */
+
+#define BUIDBASE(index) (SPAPR_PCI_BASE_BUID + (index))
+#define PCIBASE(index) (SPAPR_PCI_WINDOW_BASE + \
+ (index) * SPAPR_PCI_WINDOW_SPACING)
+#define IOBASE(index) (PCIBASE(index) + SPAPR_PCI_IO_WIN_OFF)
+#define MMIOBASE(index) (PCIBASE(index) + SPAPR_PCI_MMIO_WIN_OFF)
+
+typedef struct QPCIBusSPAPR {
+ QPCIBus bus;
+ QGuestAllocator *alloc;
+
+ uint64_t pci_hole_start;
+ uint64_t pci_hole_size;
+ uint64_t pci_hole_alloc;
+
+ uint32_t pci_iohole_start;
+ uint32_t pci_iohole_size;
+ uint32_t pci_iohole_alloc;
+} QPCIBusSPAPR;
+
+/*
+ * PCI devices are always little-endian
+ * SPAPR by default is big-endian
+ * so PCI accessors need to swap data endianness
+ */
+
+static uint8_t qpci_spapr_io_readb(QPCIBus *bus, void *addr)
+{
+ uint64_t port = (uintptr_t)addr;
+ uint8_t v;
+ if (port < SPAPR_PCI_IO_WIN_SIZE) {
+ v = readb(IOBASE(0) + port);
+ } else {
+ v = readb(MMIOBASE(0) + port);
+ }
+ return v;
+}
+
+static uint16_t qpci_spapr_io_readw(QPCIBus *bus, void *addr)
+{
+ uint64_t port = (uintptr_t)addr;
+ uint16_t v;
+ if (port < SPAPR_PCI_IO_WIN_SIZE) {
+ v = readw(IOBASE(0) + port);
+ } else {
+ v = readw(MMIOBASE(0) + port);
+ }
+ return bswap16(v);
+}
+
+static uint32_t qpci_spapr_io_readl(QPCIBus *bus, void *addr)
+{
+ uint64_t port = (uintptr_t)addr;
+ uint32_t v;
+ if (port < SPAPR_PCI_IO_WIN_SIZE) {
+ v = readl(IOBASE(0) + port);
+ } else {
+ v = readl(MMIOBASE(0) + port);
+ }
+ return bswap32(v);
+}
+
+static void qpci_spapr_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
+{
+ uint64_t port = (uintptr_t)addr;
+ if (port < SPAPR_PCI_IO_WIN_SIZE) {
+ writeb(IOBASE(0) + port, value);
+ } else {
+ writeb(MMIOBASE(0) + port, value);
+ }
+}
+
+static void qpci_spapr_io_writew(QPCIBus *bus, void *addr, uint16_t value)
+{
+ uint64_t port = (uintptr_t)addr;
+ value = bswap16(value);
+ if (port < SPAPR_PCI_IO_WIN_SIZE) {
+ writew(IOBASE(0) + port, value);
+ } else {
+ writew(MMIOBASE(0) + port, value);
+ }
+}
+
+static void qpci_spapr_io_writel(QPCIBus *bus, void *addr, uint32_t value)
+{
+ uint64_t port = (uintptr_t)addr;
+ value = bswap32(value);
+ if (port < SPAPR_PCI_IO_WIN_SIZE) {
+ writel(IOBASE(0) + port, value);
+ } else {
+ writel(MMIOBASE(0) + port, value);
+ }
+}
+
+static uint8_t qpci_spapr_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
+{
+ QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+ uint32_t config_addr = (devfn << 8) | offset;
+ return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0),
+ config_addr, 1);
+}
+
+static uint16_t qpci_spapr_config_readw(QPCIBus *bus, int devfn, uint8_t offset)
+{
+ QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+ uint32_t config_addr = (devfn << 8) | offset;
+ return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0),
+ config_addr, 2);
+}
+
+static uint32_t qpci_spapr_config_readl(QPCIBus *bus, int devfn, uint8_t offset)
+{
+ QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+ uint32_t config_addr = (devfn << 8) | offset;
+ return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0),
+ config_addr, 4);
+}
+
+static void qpci_spapr_config_writeb(QPCIBus *bus, int devfn, uint8_t offset,
+ uint8_t value)
+{
+ QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+ uint32_t config_addr = (devfn << 8) | offset;
+ qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0),
+ config_addr, 1, value);
+}
+
+static void qpci_spapr_config_writew(QPCIBus *bus, int devfn, uint8_t offset,
+ uint16_t value)
+{
+ QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+ uint32_t config_addr = (devfn << 8) | offset;
+ qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0),
+ config_addr, 2, value);
+}
+
+static void qpci_spapr_config_writel(QPCIBus *bus, int devfn, uint8_t offset,
+ uint32_t value)
+{
+ QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+ uint32_t config_addr = (devfn << 8) | offset;
+ qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0),
+ config_addr, 4, value);
+}
+
+static void *qpci_spapr_iomap(QPCIBus *bus, QPCIDevice *dev, int barno,
+ uint64_t *sizeptr)
+{
+ QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+ static const int bar_reg_map[] = {
+ PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
+ PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
+ };
+ int bar_reg;
+ uint32_t addr;
+ uint64_t size;
+ uint32_t io_type;
+
+ g_assert(barno >= 0 && barno <= 5);
+ bar_reg = bar_reg_map[barno];
+
+ qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
+ addr = qpci_config_readl(dev, bar_reg);
+
+ io_type = addr & PCI_BASE_ADDRESS_SPACE;
+ if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
+ addr &= PCI_BASE_ADDRESS_IO_MASK;
+ } else {
+ addr &= PCI_BASE_ADDRESS_MEM_MASK;
+ }
+
+ size = (1ULL << ctzl(addr));
+ if (size == 0) {
+ return NULL;
+ }
+ if (sizeptr) {
+ *sizeptr = size;
+ }
+
+ if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
+ uint16_t loc;
+
+ g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
+ <= s->pci_iohole_size);
+ s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
+ loc = s->pci_iohole_start + s->pci_iohole_alloc;
+ s->pci_iohole_alloc += size;
+
+ qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
+
+ return (void *)(unsigned long)loc;
+ } else {
+ uint64_t loc;
+
+ g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
+ <= s->pci_hole_size);
+ s->pci_hole_alloc = QEMU_ALIGN_UP(s->pci_hole_alloc, size);
+ loc = s->pci_hole_start + s->pci_hole_alloc;
+ s->pci_hole_alloc += size;
+
+ qpci_config_writel(dev, bar_reg, loc);
+
+ return (void *)(unsigned long)loc;
+ }
+}
+
+static void qpci_spapr_iounmap(QPCIBus *bus, void *data)
+{
+ /* FIXME */
+}
+
+QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
+{
+ QPCIBusSPAPR *ret;
+
+ ret = g_malloc(sizeof(*ret));
+
+ ret->alloc = alloc;
+
+ ret->bus.io_readb = qpci_spapr_io_readb;
+ ret->bus.io_readw = qpci_spapr_io_readw;
+ ret->bus.io_readl = qpci_spapr_io_readl;
+
+ ret->bus.io_writeb = qpci_spapr_io_writeb;
+ ret->bus.io_writew = qpci_spapr_io_writew;
+ ret->bus.io_writel = qpci_spapr_io_writel;
+
+ ret->bus.config_readb = qpci_spapr_config_readb;
+ ret->bus.config_readw = qpci_spapr_config_readw;
+ ret->bus.config_readl = qpci_spapr_config_readl;
+
+ ret->bus.config_writeb = qpci_spapr_config_writeb;
+ ret->bus.config_writew = qpci_spapr_config_writew;
+ ret->bus.config_writel = qpci_spapr_config_writel;
+
+ ret->bus.iomap = qpci_spapr_iomap;
+ ret->bus.iounmap = qpci_spapr_iounmap;
+
+ ret->pci_hole_start = 0xC0000000;
+ ret->pci_hole_size = SPAPR_PCI_MMIO_WIN_SIZE;
+ ret->pci_hole_alloc = 0;
+
+ ret->pci_iohole_start = 0xc000;
+ ret->pci_iohole_size = SPAPR_PCI_IO_WIN_SIZE;
+ ret->pci_iohole_alloc = 0;
+
+ return &ret->bus;
+}
+
+void qpci_free_spapr(QPCIBus *bus)
+{
+ QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+
+ g_free(s);
+}
diff --git a/tests/libqos/pci-spapr.h b/tests/libqos/pci-spapr.h
new file mode 100644
index 0000000000..4192126d86
--- /dev/null
+++ b/tests/libqos/pci-spapr.h
@@ -0,0 +1,17 @@
+/*
+ * libqos PCI bindings for SPAPR
+ *
+ * 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 LIBQOS_PCI_SPAPR_H
+#define LIBQOS_PCI_SPAPR_H
+
+#include "libqos/malloc.h"
+#include "libqos/pci.h"
+
+QPCIBus *qpci_init_spapr(QGuestAllocator *alloc);
+void qpci_free_spapr(QPCIBus *bus);
+
+#endif
diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
index ed78d91cea..c3f3382b7c 100644
--- a/tests/libqos/pci.c
+++ b/tests/libqos/pci.c
@@ -263,4 +263,24 @@ void qpci_iounmap(QPCIDevice *dev, void *data)
dev->bus->iounmap(dev->bus, data);
}
-
+void qpci_plug_device_test(const char *driver, const char *id,
+ uint8_t slot, const char *opts)
+{
+ QDict *response;
+ char *cmd;
+
+ cmd = g_strdup_printf("{'execute': 'device_add',"
+ " 'arguments': {"
+ " 'driver': '%s',"
+ " 'addr': '%d',"
+ " %s%s"
+ " 'id': '%s'"
+ "}}", driver, slot,
+ opts ? opts : "", opts ? "," : "",
+ id);
+ response = qmp(cmd);
+ g_free(cmd);
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+}
diff --git a/tests/libqos/rtas.c b/tests/libqos/rtas.c
index 820321a3a7..0269803ce0 100644
--- a/tests/libqos/rtas.c
+++ b/tests/libqos/rtas.c
@@ -69,3 +69,48 @@ int qrtas_get_time_of_day(QGuestAllocator *alloc, struct tm *tm, uint32_t *ns)
return res;
}
+
+uint32_t qrtas_ibm_read_pci_config(QGuestAllocator *alloc, uint64_t buid,
+ uint32_t addr, uint32_t size)
+{
+ int res;
+ uint32_t args[4], ret[2];
+
+ args[0] = addr;
+ args[1] = buid >> 32;
+ args[2] = buid & 0xffffffff;
+ args[3] = size;
+ res = qrtas_call(alloc, "ibm,read-pci-config", 4, args, 2, ret);
+ if (res != 0) {
+ return -1;
+ }
+
+ if (ret[0] != 0) {
+ return -1;
+ }
+
+ return ret[1];
+}
+
+int qrtas_ibm_write_pci_config(QGuestAllocator *alloc, uint64_t buid,
+ uint32_t addr, uint32_t size, uint32_t val)
+{
+ int res;
+ uint32_t args[5], ret[1];
+
+ args[0] = addr;
+ args[1] = buid >> 32;
+ args[2] = buid & 0xffffffff;
+ args[3] = size;
+ args[4] = val;
+ res = qrtas_call(alloc, "ibm,write-pci-config", 5, args, 1, ret);
+ if (res != 0) {
+ return -1;
+ }
+
+ if (ret[0] != 0) {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tests/libqos/rtas.h b/tests/libqos/rtas.h
index a1b60a8eb4..498eb19230 100644
--- a/tests/libqos/rtas.h
+++ b/tests/libqos/rtas.h
@@ -8,4 +8,8 @@
#include "libqos/malloc.h"
int qrtas_get_time_of_day(QGuestAllocator *alloc, struct tm *tm, uint32_t *ns);
+uint32_t qrtas_ibm_read_pci_config(QGuestAllocator *alloc, uint64_t buid,
+ uint32_t addr, uint32_t size);
+int qrtas_ibm_write_pci_config(QGuestAllocator *alloc, uint64_t buid,
+ uint32_t addr, uint32_t size, uint32_t val);
#endif /* LIBQOS_RTAS_H */
diff --git a/tests/pxe-test.c b/tests/pxe-test.c
index b2cc355a95..5d3ddbe5e9 100644
--- a/tests/pxe-test.c
+++ b/tests/pxe-test.c
@@ -21,14 +21,14 @@
static const char *disk = "tests/pxe-test-disk.raw";
-static void test_pxe_one(const char *params)
+static void test_pxe_one(const char *params, bool ipv6)
{
char *args;
- args = g_strdup_printf("-machine accel=tcg "
- "-netdev user,id=" NETNAME ",tftp=./,bootfile=%s "
- "%s ",
- disk, params);
+ args = g_strdup_printf("-machine accel=tcg -nodefaults -boot order=n "
+ "-netdev user,id=" NETNAME ",tftp=./,bootfile=%s,"
+ "ipv4=%s,ipv6=%s %s", disk, ipv6 ? "off" : "on",
+ ipv6 ? "on" : "off", params);
qtest_start(args);
boot_sector_test();
@@ -38,12 +38,17 @@ static void test_pxe_one(const char *params)
static void test_pxe_e1000(void)
{
- test_pxe_one("-device e1000,netdev=" NETNAME);
+ test_pxe_one("-device e1000,netdev=" NETNAME, false);
}
static void test_pxe_virtio_pci(void)
{
- test_pxe_one("-device virtio-net-pci,netdev=" NETNAME);
+ test_pxe_one("-device virtio-net-pci,netdev=" NETNAME, false);
+}
+
+static void test_pxe_spapr_vlan(void)
+{
+ test_pxe_one("-device spapr-vlan,netdev=" NETNAME, true);
}
int main(int argc, char *argv[])
@@ -60,6 +65,9 @@ int main(int argc, char *argv[])
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
qtest_add_func("pxe/e1000", test_pxe_e1000);
qtest_add_func("pxe/virtio", test_pxe_virtio_pci);
+ } else if (strcmp(arch, "ppc64") == 0) {
+ qtest_add_func("pxe/virtio", test_pxe_virtio_pci);
+ qtest_add_func("pxe/spapr-vlan", test_pxe_spapr_vlan);
}
ret = g_test_run();
boot_sector_cleanup(disk);
diff --git a/tests/q35-test.c b/tests/q35-test.c
index 71538fc17c..763fe3d6ae 100644
--- a/tests/q35-test.c
+++ b/tests/q35-test.c
@@ -42,7 +42,7 @@ static void test_smram_lock(void)
QPCIDevice *pcidev;
QDict *response;
- pcibus = qpci_init_pc();
+ pcibus = qpci_init_pc(NULL);
g_assert(pcibus != NULL);
pcidev = qpci_device_find(pcibus, 0);
diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087
index 5c04577b36..b1ac71f2b8 100755
--- a/tests/qemu-iotests/087
+++ b/tests/qemu-iotests/087
@@ -117,10 +117,10 @@ run_qemu <<EOF
"options": {
"driver": "$IMGFMT",
"node-name": "disk",
- "aio": "native",
"file": {
"driver": "file",
- "filename": "$TEST_IMG"
+ "filename": "$TEST_IMG",
+ "aio": "native"
}
}
}
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
index bef68626c8..cd02eaed4c 100644
--- a/tests/qemu-iotests/087.out
+++ b/tests/qemu-iotests/087.out
@@ -27,7 +27,7 @@ QMP_VERSION
Testing:
QMP_VERSION
{"return": {}}
-{"error": {"class": "GenericError", "desc": "aio=native requires cache.direct=true"}}
+{"error": {"class": "GenericError", "desc": "aio=native was specified, but it requires cache.direct=on, which was not specified."}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
diff --git a/tests/rtas-test.c b/tests/rtas-test.c
index 73c780339b..ba0867afbd 100644
--- a/tests/rtas-test.c
+++ b/tests/rtas-test.c
@@ -22,7 +22,7 @@ static void test_rtas_get_time_of_day(void)
t2 = mktimegm(&tm);
g_assert(t2 - t1 < 5); /* 5 sec max to run the test */
- qtest_spapr_shutdown(qs);
+ qtest_shutdown(qs);
}
int main(int argc, char *argv[])
diff --git a/tests/rtl8139-test.c b/tests/rtl8139-test.c
index 13de7eeafd..c2f601a380 100644
--- a/tests/rtl8139-test.c
+++ b/tests/rtl8139-test.c
@@ -35,7 +35,7 @@ static QPCIDevice *get_device(void)
{
QPCIDevice *dev;
- pcibus = qpci_init_pc();
+ pcibus = qpci_init_pc(NULL);
qpci_device_foreach(pcibus, 0x10ec, 0x8139, save_fn, &dev);
g_assert(dev != NULL);
diff --git a/tests/tco-test.c b/tests/tco-test.c
index 0d13aa8d63..0d201b1fcb 100644
--- a/tests/tco-test.c
+++ b/tests/tco-test.c
@@ -57,7 +57,7 @@ static void test_init(TestData *d)
qtest_irq_intercept_in(qs, "ioapic");
g_free(s);
- bus = qpci_init_pc();
+ bus = qpci_init_pc(NULL);
d->dev = qpci_device_find(bus, QPCI_DEVFN(0x1f, 0x00));
g_assert(d->dev != NULL);
diff --git a/tests/usb-hcd-ehci-test.c b/tests/usb-hcd-ehci-test.c
index eb247ad453..a4ceeaaa43 100644
--- a/tests/usb-hcd-ehci-test.c
+++ b/tests/usb-hcd-ehci-test.c
@@ -56,7 +56,7 @@ static void pci_init(void)
if (pcibus) {
return;
}
- pcibus = qpci_init_pc();
+ pcibus = qpci_init_pc(NULL);
g_assert(pcibus != NULL);
qusb_pci_init_one(pcibus, &uhci1, QPCI_DEVFN(0x1d, 0), 4);
diff --git a/tests/usb-hcd-uhci-test.c b/tests/usb-hcd-uhci-test.c
index 5cd59ad91f..4b951ce492 100644
--- a/tests/usb-hcd-uhci-test.c
+++ b/tests/usb-hcd-uhci-test.c
@@ -9,9 +9,13 @@
#include "qemu/osdep.h"
#include "libqtest.h"
+#include "libqos/libqos.h"
#include "libqos/usb.h"
+#include "libqos/libqos-pc.h"
+#include "libqos/libqos-spapr.h"
#include "hw/usb/uhci-regs.h"
+static QOSState *qs;
static void test_uhci_init(void)
{
@@ -19,13 +23,10 @@ static void test_uhci_init(void)
static void test_port(int port)
{
- QPCIBus *pcibus;
struct qhc uhci;
g_assert(port > 0);
- pcibus = qpci_init_pc();
- g_assert(pcibus != NULL);
- qusb_pci_init_one(pcibus, &uhci, QPCI_DEVFN(0x1d, 0), 4);
+ qusb_pci_init_one(qs->pcibus, &uhci, QPCI_DEVFN(0x1d, 0), 4);
uhci_port_test(&uhci, port - 1, UHCI_PORT_CCS);
}
@@ -75,6 +76,7 @@ static void test_usb_storage_hotplug(void)
int main(int argc, char **argv)
{
+ const char *arch = qtest_get_arch();
int ret;
g_test_init(&argc, &argv, NULL);
@@ -84,11 +86,17 @@ int main(int argc, char **argv)
qtest_add_func("/uhci/pci/hotplug", test_uhci_hotplug);
qtest_add_func("/uhci/pci/hotplug/usb-storage", test_usb_storage_hotplug);
- qtest_start("-device piix3-usb-uhci,id=uhci,addr=1d.0"
- " -drive id=drive0,if=none,file=/dev/null,format=raw"
- " -device usb-tablet,bus=uhci.0,port=1");
+ if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+ qs = qtest_pc_boot("-device piix3-usb-uhci,id=uhci,addr=1d.0"
+ " -drive id=drive0,if=none,file=/dev/null,format=raw"
+ " -device usb-tablet,bus=uhci.0,port=1");
+ } else if (strcmp(arch, "ppc64") == 0) {
+ qs = qtest_spapr_boot("-device piix3-usb-uhci,id=uhci,addr=1d.0"
+ " -drive id=drive0,if=none,file=/dev/null,format=raw"
+ " -device usb-tablet,bus=uhci.0,port=1");
+ }
ret = g_test_run();
- qtest_end();
+ qtest_shutdown(qs);
return ret;
}
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index a39846e6fd..d7c48c589a 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -163,7 +163,7 @@ static void init_virtio_dev(TestServer *s)
QVirtioPCIDevice *dev;
uint32_t features;
- bus = qpci_init_pc();
+ bus = qpci_init_pc(NULL);
g_assert_nonnull(bus);
dev = qvirtio_pci_device_find(bus, VIRTIO_ID_NET);
@@ -884,7 +884,7 @@ static void test_multiqueue(void)
qtest_start(cmd);
g_free(cmd);
- bus = qpci_init_pc();
+ bus = qpci_init_pc(NULL);
dev = virtio_net_pci_init(bus, PCI_SLOT);
alloc = pc_alloc_init();
diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index b8fb6cd869..e8b21967d8 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -63,7 +63,7 @@ static QVirtIO9P *qvirtio_9p_pci_init(void)
v9p = g_new0(QVirtIO9P, 1);
v9p->alloc = pc_alloc_init();
- v9p->bus = qpci_init_pc();
+ v9p->bus = qpci_init_pc(NULL);
dev = qvirtio_pci_device_find(v9p->bus, VIRTIO_ID_9P);
g_assert_nonnull(dev);
diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
index 811cf756c8..3c4fecc1f0 100644
--- a/tests/virtio-blk-test.c
+++ b/tests/virtio-blk-test.c
@@ -75,7 +75,7 @@ static QPCIBus *pci_test_start(void)
g_free(tmp_path);
g_free(cmdline);
- return qpci_init_pc();
+ return qpci_init_pc(NULL);
}
static void arm_test_start(void)
diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c
index 361506faf5..a343a6b048 100644
--- a/tests/virtio-net-test.c
+++ b/tests/virtio-net-test.c
@@ -62,7 +62,7 @@ static QPCIBus *pci_test_start(int socket)
qtest_start(cmdline);
g_free(cmdline);
- return qpci_init_pc();
+ return qpci_init_pc(NULL);
}
static void driver_init(const QVirtioBus *bus, QVirtioDevice *dev)
diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
index f1489e68a0..79088bb249 100644
--- a/tests/virtio-scsi-test.c
+++ b/tests/virtio-scsi-test.c
@@ -146,7 +146,7 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
vs = g_new0(QVirtIOSCSI, 1);
vs->alloc = pc_alloc_init();
- vs->bus = qpci_init_pc();
+ vs->bus = qpci_init_pc(NULL);
dev = qvirtio_pci_device_find(vs->bus, VIRTIO_ID_SCSI);
vs->dev = (QVirtioDevice *)dev;
diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index 4d91b3b833..24d3b3758c 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -22,7 +22,7 @@ $(obj)/generated-ust-provider.h-timestamp: $(BUILD_DIR)/trace-events-all $(trace
$(call quiet-command,$(TRACETOOL) \
--format=ust-events-h \
--backends=$(TRACE_BACKENDS) \
- < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
$(obj)/generated-ust.c: $(obj)/generated-ust.c-timestamp $(BUILD_DIR)/config-host.mak
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
@@ -30,7 +30,7 @@ $(obj)/generated-ust.c-timestamp: $(BUILD_DIR)/trace-events-all $(tracetool-y)
$(call quiet-command,$(TRACETOOL) \
--format=ust-events-c \
--backends=$(TRACE_BACKENDS) \
- < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
$(obj)/generated-events.h: $(obj)/generated-ust-provider.h
$(obj)/generated-events.c: $(obj)/generated-ust.c
@@ -46,7 +46,7 @@ $(obj)/generated-events.h-timestamp: $(BUILD_DIR)/trace-events-all $(tracetool-y
$(call quiet-command,$(TRACETOOL) \
--format=events-h \
--backends=$(TRACE_BACKENDS) \
- < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
$(obj)/generated-events.c: $(obj)/generated-events.c-timestamp $(BUILD_DIR)/config-host.mak
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
@@ -54,7 +54,7 @@ $(obj)/generated-events.c-timestamp: $(BUILD_DIR)/trace-events-all $(tracetool-y
$(call quiet-command,$(TRACETOOL) \
--format=events-c \
--backends=$(TRACE_BACKENDS) \
- < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
util-obj-y += generated-events.o
@@ -71,7 +71,7 @@ $(obj)/generated-tracers.h-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR)
$(call quiet-command,$(TRACETOOL) \
--format=h \
--backends=$(TRACE_BACKENDS) \
- < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
##############################
# non-DTrace
@@ -82,7 +82,7 @@ $(obj)/generated-tracers.c-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR)
$(call quiet-command,$(TRACETOOL) \
--format=c \
--backends=$(TRACE_BACKENDS) \
- < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
$(obj)/generated-tracers.o: $(obj)/generated-tracers.c $(obj)/generated-tracers.h
@@ -100,10 +100,10 @@ $(obj)/generated-tracers-dtrace.dtrace-timestamp: $(BUILD_DIR)/trace-events-all
$(call quiet-command,$(TRACETOOL) \
--format=d \
--backends=$(TRACE_BACKENDS) \
- < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
$(obj)/generated-tracers-dtrace.h: $(obj)/generated-tracers-dtrace.dtrace
- $(call quiet-command,dtrace -o $@ -h -s $<, " GEN $@")
+ $(call quiet-command,dtrace -o $@ -h -s $<,"GEN","$@")
$(obj)/generated-tracers-dtrace.o: $(obj)/generated-tracers-dtrace.dtrace
@@ -119,7 +119,7 @@ $(obj)/generated-helpers-wrappers.h-timestamp: $(BUILD_DIR)/trace-events-all $(B
$(call quiet-command,$(TRACETOOL) \
--format=tcg-helper-wrapper-h \
--backend=$(TRACE_BACKENDS) \
- < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
$(obj)/generated-helpers.h: $(obj)/generated-helpers.h-timestamp
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
@@ -127,7 +127,7 @@ $(obj)/generated-helpers.h-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR)
$(call quiet-command,$(TRACETOOL) \
--format=tcg-helper-h \
--backend=$(TRACE_BACKENDS) \
- < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
$(obj)/generated-helpers.c: $(obj)/generated-helpers.c-timestamp
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
@@ -135,7 +135,7 @@ $(obj)/generated-helpers.c-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR)
$(call quiet-command,$(TRACETOOL) \
--format=tcg-helper-c \
--backend=$(TRACE_BACKENDS) \
- < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
$(obj)/generated-helpers.o: $(obj)/generated-helpers.c
@@ -148,7 +148,7 @@ $(obj)/generated-tcg-tracers.h-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_
$(call quiet-command,$(TRACETOOL) \
--format=tcg-h \
--backend=$(TRACE_BACKENDS) \
- < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
######################################################################
diff --git a/util/coroutine-sigaltstack.c b/util/coroutine-sigaltstack.c
index a7c3366553..f6fc49a0e5 100644
--- a/util/coroutine-sigaltstack.c
+++ b/util/coroutine-sigaltstack.c
@@ -33,8 +33,9 @@
typedef struct {
Coroutine base;
void *stack;
+ size_t stack_size;
sigjmp_buf env;
-} CoroutineUContext;
+} CoroutineSigAltStack;
/**
* Per-thread coroutine bookkeeping
@@ -44,7 +45,7 @@ typedef struct {
Coroutine *current;
/** The default coroutine */
- CoroutineUContext leader;
+ CoroutineSigAltStack leader;
/** Information for the signal handler (trampoline) */
sigjmp_buf tr_reenter;
@@ -89,7 +90,7 @@ static void __attribute__((constructor)) coroutine_init(void)
* (from the signal handler when it is not signal handling, read ahead
* for more information).
*/
-static void coroutine_bootstrap(CoroutineUContext *self, Coroutine *co)
+static void coroutine_bootstrap(CoroutineSigAltStack *self, Coroutine *co)
{
/* Initialize longjmp environment and switch back the caller */
if (!sigsetjmp(self->env, 0)) {
@@ -109,7 +110,7 @@ static void coroutine_bootstrap(CoroutineUContext *self, Coroutine *co)
*/
static void coroutine_trampoline(int signal)
{
- CoroutineUContext *self;
+ CoroutineSigAltStack *self;
Coroutine *co;
CoroutineThreadState *coTS;
@@ -143,8 +144,7 @@ static void coroutine_trampoline(int signal)
Coroutine *qemu_coroutine_new(void)
{
- const size_t stack_size = 1 << 20;
- CoroutineUContext *co;
+ CoroutineSigAltStack *co;
CoroutineThreadState *coTS;
struct sigaction sa;
struct sigaction osa;
@@ -164,7 +164,8 @@ Coroutine *qemu_coroutine_new(void)
*/
co = g_malloc0(sizeof(*co));
- co->stack = g_malloc(stack_size);
+ co->stack_size = COROUTINE_STACK_SIZE;
+ co->stack = qemu_alloc_stack(&co->stack_size);
co->base.entry_arg = &old_env; /* stash away our jmp_buf */
coTS = coroutine_get_thread_state();
@@ -189,7 +190,7 @@ Coroutine *qemu_coroutine_new(void)
* Set the new stack.
*/
ss.ss_sp = co->stack;
- ss.ss_size = stack_size;
+ ss.ss_size = co->stack_size;
ss.ss_flags = 0;
if (sigaltstack(&ss, &oss) < 0) {
abort();
@@ -251,17 +252,17 @@ Coroutine *qemu_coroutine_new(void)
void qemu_coroutine_delete(Coroutine *co_)
{
- CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
+ CoroutineSigAltStack *co = DO_UPCAST(CoroutineSigAltStack, base, co_);
- g_free(co->stack);
+ qemu_free_stack(co->stack, co->stack_size);
g_free(co);
}
CoroutineAction qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
CoroutineAction action)
{
- CoroutineUContext *from = DO_UPCAST(CoroutineUContext, base, from_);
- CoroutineUContext *to = DO_UPCAST(CoroutineUContext, base, to_);
+ CoroutineSigAltStack *from = DO_UPCAST(CoroutineSigAltStack, base, from_);
+ CoroutineSigAltStack *to = DO_UPCAST(CoroutineSigAltStack, base, to_);
CoroutineThreadState *s = coroutine_get_thread_state();
int ret;
diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c
index 2bb7e10d4b..6621f3f692 100644
--- a/util/coroutine-ucontext.c
+++ b/util/coroutine-ucontext.c
@@ -34,6 +34,7 @@
typedef struct {
Coroutine base;
void *stack;
+ size_t stack_size;
sigjmp_buf env;
#ifdef CONFIG_VALGRIND_H
@@ -82,7 +83,6 @@ static void coroutine_trampoline(int i0, int i1)
Coroutine *qemu_coroutine_new(void)
{
- const size_t stack_size = 1 << 20;
CoroutineUContext *co;
ucontext_t old_uc, uc;
sigjmp_buf old_env;
@@ -101,17 +101,18 @@ Coroutine *qemu_coroutine_new(void)
}
co = g_malloc0(sizeof(*co));
- co->stack = g_malloc(stack_size);
+ co->stack_size = COROUTINE_STACK_SIZE;
+ co->stack = qemu_alloc_stack(&co->stack_size);
co->base.entry_arg = &old_env; /* stash away our jmp_buf */
uc.uc_link = &old_uc;
uc.uc_stack.ss_sp = co->stack;
- uc.uc_stack.ss_size = stack_size;
+ uc.uc_stack.ss_size = co->stack_size;
uc.uc_stack.ss_flags = 0;
#ifdef CONFIG_VALGRIND_H
co->valgrind_stack_id =
- VALGRIND_STACK_REGISTER(co->stack, co->stack + stack_size);
+ VALGRIND_STACK_REGISTER(co->stack, co->stack + co->stack_size);
#endif
arg.p = co;
@@ -149,7 +150,7 @@ void qemu_coroutine_delete(Coroutine *co_)
valgrind_stack_deregister(co);
#endif
- g_free(co->stack);
+ qemu_free_stack(co->stack, co->stack_size);
g_free(co);
}
diff --git a/util/coroutine-win32.c b/util/coroutine-win32.c
index 02e28e825f..de6bd4fd3e 100644
--- a/util/coroutine-win32.c
+++ b/util/coroutine-win32.c
@@ -71,7 +71,7 @@ static void CALLBACK coroutine_trampoline(void *co_)
Coroutine *qemu_coroutine_new(void)
{
- const size_t stack_size = 1 << 20;
+ const size_t stack_size = COROUTINE_STACK_SIZE;
CoroutineWin32 *co;
co = g_malloc0(sizeof(*co));
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 8c1e8d6841..8ec99ccb4f 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -51,6 +51,10 @@
#include "qemu/mmap-alloc.h"
+#ifdef CONFIG_DEBUG_STACK_USAGE
+#include "qemu/error-report.h"
+#endif
+
int qemu_get_thread_id(void)
{
#if defined(__linux__)
@@ -526,3 +530,76 @@ pid_t qemu_fork(Error **errp)
}
return pid;
}
+
+void *qemu_alloc_stack(size_t *sz)
+{
+ void *ptr, *guardpage;
+#ifdef CONFIG_DEBUG_STACK_USAGE
+ void *ptr2;
+#endif
+ size_t pagesz = getpagesize();
+#ifdef _SC_THREAD_STACK_MIN
+ /* avoid stacks smaller than _SC_THREAD_STACK_MIN */
+ long min_stack_sz = sysconf(_SC_THREAD_STACK_MIN);
+ *sz = MAX(MAX(min_stack_sz, 0), *sz);
+#endif
+ /* adjust stack size to a multiple of the page size */
+ *sz = ROUND_UP(*sz, pagesz);
+ /* allocate one extra page for the guard page */
+ *sz += pagesz;
+
+ ptr = mmap(NULL, *sz, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (ptr == MAP_FAILED) {
+ abort();
+ }
+
+#if defined(HOST_IA64)
+ /* separate register stack */
+ guardpage = ptr + (((*sz - pagesz) / 2) & ~pagesz);
+#elif defined(HOST_HPPA)
+ /* stack grows up */
+ guardpage = ptr + *sz - pagesz;
+#else
+ /* stack grows down */
+ guardpage = ptr;
+#endif
+ if (mprotect(guardpage, pagesz, PROT_NONE) != 0) {
+ abort();
+ }
+
+#ifdef CONFIG_DEBUG_STACK_USAGE
+ for (ptr2 = ptr + pagesz; ptr2 < ptr + *sz; ptr2 += sizeof(uint32_t)) {
+ *(uint32_t *)ptr2 = 0xdeadbeaf;
+ }
+#endif
+
+ return ptr;
+}
+
+#ifdef CONFIG_DEBUG_STACK_USAGE
+static __thread unsigned int max_stack_usage;
+#endif
+
+void qemu_free_stack(void *stack, size_t sz)
+{
+#ifdef CONFIG_DEBUG_STACK_USAGE
+ unsigned int usage;
+ void *ptr;
+
+ for (ptr = stack + getpagesize(); ptr < stack + sz;
+ ptr += sizeof(uint32_t)) {
+ if (*(uint32_t *)ptr != 0xdeadbeaf) {
+ break;
+ }
+ }
+ usage = sz - (uintptr_t) (ptr - stack);
+ if (usage > max_stack_usage) {
+ error_report("thread %d max stack usage increased from %u to %u",
+ qemu_get_thread_id(), max_stack_usage, usage);
+ max_stack_usage = usage;
+ }
+#endif
+
+ munmap(stack, sz);
+}