aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile32
-rw-r--r--Makefile.hw7
-rw-r--r--Makefile.objs314
-rw-r--r--Makefile.target339
-rw-r--r--audio/Makefile.objs14
-rw-r--r--audio/winwaveaudio.c2
-rw-r--r--block/Makefile.objs11
-rw-r--r--block/qcow2-cluster.c2
-rw-r--r--blockdev.c2
-rw-r--r--bsd-user/Makefile.objs2
-rw-r--r--bsd-user/main.c2
-rwxr-xr-xconfigure75
-rw-r--r--cpu-all.h1
-rw-r--r--cpu-common.h4
-rw-r--r--cpu-exec.c26
-rw-r--r--default-configs/microblaze-softmmu.mak2
-rw-r--r--default-configs/microblazeel-softmmu.mak2
-rw-r--r--default-configs/ppc-softmmu.mak1
-rw-r--r--default-configs/ppc64-softmmu.mak1
-rw-r--r--default-configs/ppcemb-softmmu.mak1
-rw-r--r--dump-stub.c64
-rw-r--r--dump.c873
-rw-r--r--dump.h35
-rw-r--r--elf.h5
-rw-r--r--exec.c37
-rw-r--r--fsdev/Makefile.objs9
-rw-r--r--gdbstub.c19
-rw-r--r--gdbstub.h9
-rw-r--r--hmp-commands.hx34
-rw-r--r--hmp.c52
-rw-r--r--hmp.h3
-rw-r--r--hw/9pfs/Makefile.objs9
-rw-r--r--hw/Makefile.objs172
-rw-r--r--hw/alpha/Makefile.objs4
-rw-r--r--hw/arm-misc.h8
-rw-r--r--hw/arm/Makefile.objs40
-rw-r--r--hw/arm_boot.c21
-rw-r--r--hw/arm_pic.c8
-rw-r--r--hw/armv7m.c17
-rw-r--r--hw/axis_dev88.c6
-rw-r--r--hw/collie.c2
-rw-r--r--hw/cris-boot.c10
-rw-r--r--hw/cris-boot.h2
-rw-r--r--hw/cris/Makefile.objs13
-rw-r--r--hw/exynos4210.c9
-rw-r--r--hw/exynos4210.h4
-rw-r--r--hw/exynos4_boards.c4
-rw-r--r--hw/highbank.c13
-rw-r--r--hw/i386/Makefile.objs13
-rw-r--r--hw/ide/Makefile.objs10
-rw-r--r--hw/integratorcp.c14
-rw-r--r--hw/kvm/apic.c2
-rw-r--r--hw/kvm/i8254.c57
-rw-r--r--hw/leon3.c14
-rw-r--r--hw/lm32/Makefile.objs23
-rw-r--r--hw/lm32_boards.c18
-rw-r--r--hw/m68k/Makefile.objs4
-rw-r--r--hw/mainstone.c16
-rw-r--r--hw/mc146818rtc.c7
-rw-r--r--hw/microblaze/Makefile.objs9
-rw-r--r--hw/microblaze_boot.c16
-rw-r--r--hw/microblaze_boot.h4
-rw-r--r--hw/milkymist.c12
-rw-r--r--hw/mips/Makefile.objs6
-rw-r--r--hw/mips_fulong2e.c13
-rw-r--r--hw/mips_jazz.c13
-rw-r--r--hw/mips_malta.c15
-rw-r--r--hw/mips_mipssim.c15
-rw-r--r--hw/mips_r4k.c15
-rw-r--r--hw/musicpal.c10
-rw-r--r--hw/nseries.c72
-rw-r--r--hw/omap.h2
-rw-r--r--hw/omap1.c20
-rw-r--r--hw/omap2.c8
-rw-r--r--hw/omap_sx1.c6
-rw-r--r--hw/palm.c12
-rw-r--r--hw/pc.c19
-rw-r--r--hw/pci-hotplug.c8
-rw-r--r--hw/pci.c2
-rw-r--r--hw/pci.h2
-rw-r--r--hw/petalogix_ml605_mmu.c12
-rw-r--r--hw/petalogix_s3adsp1800_mmu.c14
-rw-r--r--hw/ppc/Makefile.objs28
-rw-r--r--hw/ppc440_bamboo.c13
-rw-r--r--hw/ppc4xx_devs.c13
-rw-r--r--hw/ppc_newworld.c13
-rw-r--r--hw/ppc_oldworld.c13
-rw-r--r--hw/ppc_prep.c13
-rw-r--r--hw/ppce500_mpc8544ds.c21
-rw-r--r--hw/pxa.h4
-rw-r--r--hw/pxa2xx.c40
-rw-r--r--hw/pxa2xx_gpio.c9
-rw-r--r--hw/pxa2xx_pic.c32
-rw-r--r--hw/qdev-addr.c4
-rw-r--r--hw/qdev-monitor.c7
-rw-r--r--hw/qdev-properties.c205
-rw-r--r--hw/qdev.h4
-rw-r--r--hw/r2d.c18
-rw-r--r--hw/realview.c12
-rw-r--r--hw/rtl8139.c9
-rw-r--r--hw/s390-virtio-bus.c6
-rw-r--r--hw/s390-virtio.c12
-rw-r--r--hw/s390x/Makefile.objs3
-rw-r--r--hw/scsi-bus.c8
-rw-r--r--hw/scsi-disk.c16
-rw-r--r--hw/sh4/Makefile.objs5
-rw-r--r--hw/spapr.c14
-rw-r--r--hw/sparc/Makefile.objs8
-rw-r--r--hw/sparc64/Makefile.objs4
-rw-r--r--hw/spitz.c24
-rw-r--r--hw/strongarm.c6
-rw-r--r--hw/strongarm.h2
-rw-r--r--hw/sun4m.c20
-rw-r--r--hw/sun4u.c25
-rw-r--r--hw/tosa.c14
-rw-r--r--hw/usb/Makefile.objs13
-rw-r--r--hw/usb/dev-network.c7
-rw-r--r--hw/usb/dev-storage.c71
-rw-r--r--hw/usb/hcd-ehci.c610
-rw-r--r--hw/usb/hcd-uhci.c67
-rw-r--r--hw/usb/hcd-xhci.c251
-rw-r--r--hw/versatilepb.c13
-rw-r--r--hw/vexpress.c18
-rw-r--r--hw/virtex_ml507.c29
-rw-r--r--hw/watchdog.c2
-rw-r--r--hw/xen_disk.c14
-rw-r--r--hw/xen_machine_pv.c4
-rw-r--r--hw/xilinx.h30
-rw-r--r--hw/xilinx_axidma.c6
-rw-r--r--hw/xilinx_axienet.c6
-rw-r--r--hw/xilinx_ethlite.c9
-rw-r--r--hw/xilinx_intc.c4
-rw-r--r--hw/xilinx_timer.c23
-rw-r--r--hw/xilinx_uartlite.c5
-rw-r--r--hw/xilinx_zynq.c10
-rw-r--r--hw/xtensa/Makefile.objs5
-rw-r--r--hw/xtensa_lx60.c15
-rw-r--r--hw/xtensa_sim.c17
-rw-r--r--hw/z2.c26
-rw-r--r--kvm-all.c16
-rw-r--r--libcacard/Makefile17
-rw-r--r--linux-user/Makefile.objs7
-rw-r--r--linux-user/arm/nwfpe/Makefile.objs2
-rw-r--r--linux-user/main.c2
-rw-r--r--linux-user/syscall.c2
-rw-r--r--memory_mapping-stub.c33
-rw-r--r--memory_mapping.c246
-rw-r--r--memory_mapping.h64
-rw-r--r--monitor.c107
-rw-r--r--monitor.h4
-rw-r--r--net.c104
-rw-r--r--net.h6
-rw-r--r--net/Makefile.objs12
-rw-r--r--net/dump.c2
-rw-r--r--net/dump.h3
-rw-r--r--net/slirp.c5
-rw-r--r--net/slirp.h5
-rw-r--r--net/socket.c8
-rw-r--r--net/socket.h3
-rw-r--r--net/tap-bsd.c6
-rw-r--r--net/tap-win32.c2
-rw-r--r--net/tap.c9
-rw-r--r--net/tap.h5
-rw-r--r--net/vde.c2
-rw-r--r--net/vde.h2
-rw-r--r--qapi-schema.json107
-rw-r--r--qapi/Makefile.objs3
-rw-r--r--qapi/qapi-visit-core.c139
-rw-r--r--qapi/qapi-visit-core.h16
-rw-r--r--qapi/string-output-visitor.c2
-rw-r--r--qemu-char.c22
-rw-r--r--qemu-config.c43
-rw-r--r--qemu-config.h3
-rw-r--r--qemu-log.h2
-rw-r--r--qemu-option.c175
-rw-r--r--qemu-option.h11
-rw-r--r--qemu-sockets.c8
-rw-r--r--qerror.c4
-rw-r--r--qerror.h3
-rw-r--r--qga/Makefile.objs3
-rw-r--r--qmp-commands.hx83
-rw-r--r--qom/Makefile2
-rw-r--r--qom/Makefile.objs4
-rw-r--r--readline.c3
-rw-r--r--rules.mak40
-rw-r--r--slirp/Makefile.objs3
-rw-r--r--target-alpha/Makefile.objs3
-rw-r--r--target-arm/Makefile.objs6
-rw-r--r--target-arm/arm-semi.c (renamed from arm-semi.c)0
-rw-r--r--target-arm/helper.c7
-rw-r--r--target-cris/Makefile.objs4
-rw-r--r--target-cris/cpu.h16
-rw-r--r--target-cris/helper.c8
-rw-r--r--target-cris/op_helper.c4
-rw-r--r--target-cris/translate.c112
-rw-r--r--target-cris/translate_v10.c1
-rw-r--r--target-i386/Makefile.objs7
-rw-r--r--target-i386/arch_dump.c449
-rw-r--r--target-i386/arch_memory_mapping.c272
-rw-r--r--target-i386/cpu.c42
-rw-r--r--target-i386/cpu.h16
-rw-r--r--target-i386/helper.c23
-rw-r--r--target-i386/ioport-user.c (renamed from ioport-user.c)0
-rw-r--r--target-i386/kvm.c6
-rw-r--r--target-lm32/Makefile.objs4
-rw-r--r--target-lm32/cpu.c2
-rw-r--r--target-lm32/cpu.h12
-rw-r--r--target-lm32/helper.c10
-rw-r--r--target-m68k/Makefile.objs5
-rw-r--r--target-m68k/helper.c5
-rw-r--r--target-m68k/m68k-semi.c (renamed from m68k-semi.c)0
-rw-r--r--target-microblaze/Makefile.objs4
-rw-r--r--target-microblaze/cpu.h12
-rw-r--r--target-microblaze/translate.c29
-rw-r--r--target-mips/Makefile.objs4
-rw-r--r--target-mips/cpu.h15
-rw-r--r--target-mips/helper.c3
-rw-r--r--target-mips/translate.c6
-rw-r--r--target-ppc/Makefile.objs6
-rw-r--r--target-ppc/cpu.h12
-rw-r--r--target-ppc/helper.c9
-rw-r--r--target-s390x/Makefile.objs5
-rw-r--r--target-s390x/cpu.c2
-rw-r--r--target-s390x/cpu.h10
-rw-r--r--target-s390x/helper.c13
-rw-r--r--target-s390x/kvm.c12
-rw-r--r--target-sh4/Makefile.objs4
-rw-r--r--target-sh4/cpu.h12
-rw-r--r--target-sh4/translate.c9
-rw-r--r--target-sparc/Makefile.objs8
-rw-r--r--target-sparc/cpu.c9
-rw-r--r--target-sparc/cpu.h17
-rw-r--r--target-unicore32/Makefile.objs4
-rw-r--r--target-xtensa/Makefile.objs6
-rw-r--r--target-xtensa/cpu.c2
-rw-r--r--target-xtensa/cpu.h21
-rw-r--r--target-xtensa/helper.c70
-rw-r--r--target-xtensa/helper.h58
-rw-r--r--target-xtensa/op_helper.c203
-rw-r--r--target-xtensa/translate.c66
-rw-r--r--target-xtensa/xtensa-semi.c (renamed from xtensa-semi.c)1
-rw-r--r--tests/Makefile5
-rw-r--r--tests/tcg/xtensa/test_mmu.S221
-rw-r--r--tests/test-string-output-visitor.c2
-rw-r--r--tests/test-visitor-serialization.c784
-rw-r--r--trace-events46
-rw-r--r--trace/simple.c5
-rw-r--r--ui/Makefile.objs18
-rw-r--r--vl.c28
249 files changed, 6486 insertions, 2304 deletions
diff --git a/Makefile b/Makefile
index 9b7a85e4d2..32550cbfaf 100644
--- a/Makefile
+++ b/Makefile
@@ -33,7 +33,7 @@ configure: ;
.PHONY: all clean cscope distclean dvi html info install install-doc \
pdf recurse-all speed tar tarbin test build-all
-$(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw)
+$(call set-vpath, $(SRC_PATH))
LIBS+=-lz $(LIBS_TOOLS)
@@ -91,19 +91,18 @@ qemu-options.def: $(SRC_PATH)/qemu-options.hx
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
-subdir-%: $(GENERATED_HEADERS)
+subdir-%:
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $* V="$(V)" TARGET_DIR="$*/" all,)
ifneq ($(wildcard config-host.mak),)
include $(SRC_PATH)/Makefile.objs
endif
-$(universal-obj-y) $(common-obj-y): $(GENERATED_HEADERS)
subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o
-$(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) subdir-libdis
+$(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) $(extra-obj-y) subdir-libdis
-$(filter %-user,$(SUBDIR_RULES)): $(GENERATED_HEADERS) $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser
+$(filter %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser
ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
romsubdir-%:
@@ -121,7 +120,7 @@ QEMU_CFLAGS += -I$(SRC_PATH)/include
ui/cocoa.o: ui/cocoa.m
-ui/sdl.o audio/sdlaudio.o ui/sdl_zoom.o baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
+ui/sdl.o audio/sdlaudio.o ui/sdl_zoom.o hw/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
ui/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
@@ -142,16 +141,19 @@ libcacard.la:
install-libcacard:
@echo "libtool is missing, please install and rerun configure"; exit 1
else
-libcacard.la: $(GENERATED_HEADERS) $(oslib-obj-y) qemu-timer-common.o $(addsuffix .lo, $(basename $(trace-obj-y)))
+libcacard.la: $(oslib-obj-y) qemu-timer-common.o $(addsuffix .lo, $(basename $(trace-obj-y)))
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libcacard V="$(V)" TARGET_DIR="$*/" libcacard.la,)
install-libcacard: libcacard.la
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libcacard V="$(V)" TARGET_DIR="$*/" install-libcacard,)
endif
+
+vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) qemu-timer-common.o libcacard/vscclient.o
+ $(call quiet-command,$(CC) -o $@ $^ $(libcacard_libs) $(LIBS)," LINK $@")
+
######################################################################
qemu-img.o: qemu-img-cmds.h
-qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o qemu-ga.o: $(GENERATED_HEADERS)
tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \
qemu-timer-common.o main-loop.o notify.o iohandler.o cutils.o async.o
@@ -162,7 +164,6 @@ qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
-qemu-bridge-helper.o: $(GENERATED_HEADERS)
fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y)
fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
@@ -170,7 +171,6 @@ fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $@")
-$(qapi-obj-y): $(GENERATED_HEADERS)
qapi-dir := $(BUILD_DIR)/qapi-generated
qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
@@ -203,8 +203,8 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
QGALIB_OBJ=$(addprefix $(qapi-dir)/, qga-qapi-types.o qga-qapi-visit.o qga-qmp-marshal.o)
QGALIB_GEN=$(addprefix $(qapi-dir)/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
-$(QGALIB_OBJ): $(QGALIB_GEN) $(GENERATED_HEADERS)
-$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) $(GENERATED_HEADERS)
+$(QGALIB_OBJ): $(QGALIB_GEN)
+$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(tools-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y) $(QGALIB_OBJ)
@@ -218,6 +218,7 @@ clean:
rm -Rf .libs
rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d qapi/*.o qapi/*.d qga/*.o qga/*.d
rm -f qom/*.o qom/*.d
+ rm -f usb/*.o usb/*.d hw/*.o hw/*.d
rm -f qemu-img-cmds.h
rm -f trace/*.o trace/*.d
rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp
@@ -399,5 +400,10 @@ tar:
cd /tmp && tar zcvf ~/$(FILE).tar.gz $(FILE) --exclude CVS --exclude .git --exclude .svn
rm -rf /tmp/$(FILE)
+# Add a dependency on the generated files, so that they are always
+# rebuilt before other object files
+Makefile: $(GENERATED_HEADERS)
+
# Include automatically generated dependency files
--include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d qapi/*.d qga/*.d)
+-include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d qapi/*.d)
+-include $(wildcard qga/*.d hw/*.d hw/usb/*.d)
diff --git a/Makefile.hw b/Makefile.hw
index 33f1ab0183..2bcbaffb4f 100644
--- a/Makefile.hw
+++ b/Makefile.hw
@@ -7,7 +7,7 @@ include $(SRC_PATH)/rules.mak
.PHONY: all
-$(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw)
+$(call set-vpath, $(SRC_PATH))
QEMU_CFLAGS+=-I..
QEMU_CFLAGS += -I$(SRC_PATH)/include
@@ -19,7 +19,8 @@ all: $(hw-obj-y)
@true
clean:
- rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~
+ rm -f $(addsuffix /*.o, $(dir $(sort $(hw-obj-y))))
+ rm -f $(addsuffix /*.d, $(dir $(sort $(hw-obj-y))))
# Include automatically generated dependency files
--include $(wildcard *.d */*.d)
+-include $(patsubst %.o, %.d, $(hw-obj-y))
diff --git a/Makefile.objs b/Makefile.objs
index 70c5c79a6e..74110dda7e 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -12,9 +12,7 @@ universal-obj-y += $(qobject-obj-y)
#######################################################################
# QOM
-include $(SRC_PATH)/qom/Makefile
-qom-obj-y = $(addprefix qom/, $(qom-y))
-qom-obj-twice-y = $(addprefix qom/, $(qom-twice-y))
+qom-obj-y = qom/
universal-obj-y += $(qom-obj-y)
@@ -47,45 +45,13 @@ block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o qemu-sock
block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y)
block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
-
-block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
-block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
-block-nested-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
-block-nested-y += qed-check.o
-block-nested-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o
-block-nested-y += stream.o
-block-nested-$(CONFIG_WIN32) += raw-win32.o
-block-nested-$(CONFIG_POSIX) += raw-posix.o
-block-nested-$(CONFIG_LIBISCSI) += iscsi.o
-block-nested-$(CONFIG_CURL) += curl.o
-block-nested-$(CONFIG_RBD) += rbd.o
-
-block-obj-y += $(addprefix block/, $(block-nested-y))
-
-net-obj-y = net.o
-net-nested-y = queue.o checksum.o util.o
-net-nested-y += socket.o
-net-nested-y += dump.o
-net-nested-$(CONFIG_POSIX) += tap.o
-net-nested-$(CONFIG_LINUX) += tap-linux.o
-net-nested-$(CONFIG_WIN32) += tap-win32.o
-net-nested-$(CONFIG_BSD) += tap-bsd.o
-net-nested-$(CONFIG_SOLARIS) += tap-solaris.o
-net-nested-$(CONFIG_AIX) += tap-aix.o
-net-nested-$(CONFIG_HAIKU) += tap-haiku.o
-net-nested-$(CONFIG_SLIRP) += slirp.o
-net-nested-$(CONFIG_VDE) += vde.o
-net-obj-y += $(addprefix net/, $(net-nested-y))
+block-obj-y += block/
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
# only pull in the actual virtio-9p device if we also enabled virtio.
CONFIG_REALLY_VIRTFS=y
-fsdev-nested-y = qemu-fsdev.o virtio-9p-marshal.o
-else
-fsdev-nested-y = qemu-fsdev-dummy.o
endif
-fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y))
######################################################################
# Target independent part of system emulation. The long term path is to
@@ -93,104 +59,40 @@ fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y))
# single QEMU executable should support all CPUs and machines.
common-obj-y = $(block-obj-y) blockdev.o
-common-obj-y += $(net-obj-y)
-common-obj-y += $(qom-obj-twice-y)
-common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
+common-obj-y += net.o net/
+common-obj-y += qom/
common-obj-y += readline.o console.o cursor.o
common-obj-y += $(oslib-obj-y)
common-obj-$(CONFIG_WIN32) += os-win32.o
common-obj-$(CONFIG_POSIX) += os-posix.o
+common-obj-$(CONFIG_LINUX) += fsdev/
+extra-obj-$(CONFIG_LINUX) += fsdev/
+
common-obj-y += tcg-runtime.o host-utils.o main-loop.o
-common-obj-y += irq.o input.o
-common-obj-$(CONFIG_PTIMER) += ptimer.o
-common-obj-$(CONFIG_MAX7310) += max7310.o
-common-obj-$(CONFIG_WM8750) += wm8750.o
-common-obj-$(CONFIG_TWL92230) += twl92230.o
-common-obj-$(CONFIG_TSC2005) += tsc2005.o
-common-obj-$(CONFIG_LM832X) += lm832x.o
-common-obj-$(CONFIG_TMP105) += tmp105.o
-common-obj-$(CONFIG_STELLARIS_INPUT) += stellaris_input.o
-common-obj-$(CONFIG_SSD0303) += ssd0303.o
-common-obj-$(CONFIG_SSD0323) += ssd0323.o
-common-obj-$(CONFIG_ADS7846) += ads7846.o
-common-obj-$(CONFIG_MAX111X) += max111x.o
-common-obj-$(CONFIG_DS1338) += ds1338.o
-common-obj-y += i2c.o smbus.o smbus_eeprom.o
-common-obj-y += eeprom93xx.o
-common-obj-y += scsi-disk.o cdrom.o
-common-obj-y += scsi-generic.o scsi-bus.o
-common-obj-y += hid.o
-common-obj-y += usb/core.o usb/bus.o usb/desc.o usb/dev-hub.o
-common-obj-y += usb/host-$(HOST_USB).o
-common-obj-y += usb/dev-hid.o usb/dev-storage.o usb/dev-wacom.o
-common-obj-y += usb/dev-serial.o usb/dev-network.o usb/dev-audio.o
-common-obj-$(CONFIG_SSI) += ssi.o
-common-obj-$(CONFIG_SSI_SD) += ssi-sd.o
-common-obj-$(CONFIG_SD) += sd.o
-common-obj-y += bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
-common-obj-y += bt-hci-csr.o usb/dev-bluetooth.o
+common-obj-y += input.o
common-obj-y += buffered_file.o migration.o migration-tcp.o
common-obj-y += qemu-char.o #aio.o
-common-obj-y += msmouse.o ps2.o
-common-obj-y += qdev.o qdev-properties.o qdev-monitor.o
common-obj-y += block-migration.o iohandler.o
common-obj-y += pflib.o
common-obj-y += bitmap.o bitops.o
-common-obj-$(CONFIG_BRLAPI) += baum.o
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
common-obj-$(CONFIG_WIN32) += version.o
-common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display.o spice-qemu-char.o
-
-audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
-audio-obj-$(CONFIG_SDL) += sdlaudio.o
-audio-obj-$(CONFIG_OSS) += ossaudio.o
-audio-obj-$(CONFIG_SPICE) += spiceaudio.o
-audio-obj-$(CONFIG_COREAUDIO) += coreaudio.o
-audio-obj-$(CONFIG_ALSA) += alsaaudio.o
-audio-obj-$(CONFIG_DSOUND) += dsoundaudio.o
-audio-obj-$(CONFIG_FMOD) += fmodaudio.o
-audio-obj-$(CONFIG_ESD) += esdaudio.o
-audio-obj-$(CONFIG_PA) += paaudio.o
-audio-obj-$(CONFIG_WINWAVE) += winwaveaudio.o
-audio-obj-$(CONFIG_AUDIO_PT_INT) += audio_pt_int.o
-audio-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o
-audio-obj-y += wavcapture.o
-common-obj-y += $(addprefix audio/, $(audio-obj-y))
-
-ui-obj-y += keymaps.o
-ui-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o
-ui-obj-$(CONFIG_COCOA) += cocoa.o
-ui-obj-$(CONFIG_CURSES) += curses.o
-vnc-obj-y += vnc.o d3des.o
-vnc-obj-y += vnc-enc-zlib.o vnc-enc-hextile.o
-vnc-obj-y += vnc-enc-tight.o vnc-palette.o
-vnc-obj-y += vnc-enc-zrle.o
-vnc-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
-vnc-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
-ifdef CONFIG_VNC_THREAD
-vnc-obj-y += vnc-jobs-async.o
-else
-vnc-obj-y += vnc-jobs-sync.o
-endif
-common-obj-y += $(addprefix ui/, $(ui-obj-y))
-common-obj-$(CONFIG_VNC) += $(addprefix ui/, $(vnc-obj-y))
+common-obj-$(CONFIG_SPICE) += spice-qemu-char.o
+
+common-obj-y += audio/
+common-obj-y += hw/
+common-obj-y += ui/
+common-obj-y += bt-host.o bt-vhci.o
common-obj-y += iov.o acl.o
common-obj-$(CONFIG_POSIX) += compatfd.o
common-obj-y += notify.o event_notifier.o
common-obj-y += qemu-timer.o qemu-timer-common.o
-slirp-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o
-slirp-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
-slirp-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o
-common-obj-$(CONFIG_SLIRP) += $(addprefix slirp/, $(slirp-obj-y))
-
-# xen backend driver support
-common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
-common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o xenfb.o xen_disk.o xen_nic.o
+common-obj-$(CONFIG_SLIRP) += slirp/
######################################################################
# libuser
@@ -202,152 +104,12 @@ user-obj-y += cutils.o cache-utils.o
user-obj-y += module.o
user-obj-y += qemu-user.o
user-obj-y += $(trace-obj-y)
-user-obj-y += $(qom-obj-twice-y)
+user-obj-y += qom/
######################################################################
# libhw
-hw-obj-y =
-hw-obj-y += vl.o loader.o
-hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
-hw-obj-y += usb/libhw.o
-hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
-hw-obj-y += fw_cfg.o
-hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o
-hw-obj-$(CONFIG_PCI) += msix.o msi.o
-hw-obj-$(CONFIG_PCI) += shpc.o
-hw-obj-$(CONFIG_PCI) += slotid_cap.o
-hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
-hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
-hw-obj-y += watchdog.o
-hw-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
-hw-obj-$(CONFIG_ECC) += ecc.o
-hw-obj-$(CONFIG_NAND) += nand.o
-hw-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
-hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
-
-hw-obj-$(CONFIG_M48T59) += m48t59.o
-hw-obj-$(CONFIG_ESCC) += escc.o
-hw-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
-
-hw-obj-$(CONFIG_SERIAL) += serial.o
-hw-obj-$(CONFIG_PARALLEL) += parallel.o
-hw-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
-hw-obj-$(CONFIG_PCSPK) += pcspk.o
-hw-obj-$(CONFIG_PCKBD) += pckbd.o
-hw-obj-$(CONFIG_USB_UHCI) += usb/hcd-uhci.o
-hw-obj-$(CONFIG_USB_OHCI) += usb/hcd-ohci.o
-hw-obj-$(CONFIG_USB_EHCI) += usb/hcd-ehci.o
-hw-obj-$(CONFIG_USB_XHCI) += usb/hcd-xhci.o
-hw-obj-$(CONFIG_FDC) += fdc.o
-hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
-hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
-hw-obj-$(CONFIG_DMA) += dma.o
-hw-obj-$(CONFIG_I82374) += i82374.o
-hw-obj-$(CONFIG_HPET) += hpet.o
-hw-obj-$(CONFIG_APPLESMC) += applesmc.o
-hw-obj-$(CONFIG_SMARTCARD) += usb/dev-smartcard-reader.o ccid-card-passthru.o
-hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
-hw-obj-$(CONFIG_USB_REDIR) += usb/redirect.o
-hw-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
-
-# PPC devices
-hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
-hw-obj-$(CONFIG_I82378) += i82378.o
-# Mac shared devices
-hw-obj-$(CONFIG_MACIO) += macio.o
-hw-obj-$(CONFIG_CUDA) += cuda.o
-hw-obj-$(CONFIG_ADB) += adb.o
-hw-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
-hw-obj-$(CONFIG_MAC_DBDMA) += mac_dbdma.o
-# OldWorld PowerMac
-hw-obj-$(CONFIG_HEATHROW_PIC) += heathrow_pic.o
-hw-obj-$(CONFIG_GRACKLE_PCI) += grackle_pci.o
-# NewWorld PowerMac
-hw-obj-$(CONFIG_UNIN_PCI) += unin_pci.o
-hw-obj-$(CONFIG_DEC_PCI) += dec_pci.o
-# PowerPC E500 boards
-hw-obj-$(CONFIG_PPCE500_PCI) += ppce500_pci.o
-
-# MIPS devices
-hw-obj-$(CONFIG_PIIX4) += piix4.o
-hw-obj-$(CONFIG_G364FB) += g364fb.o
-hw-obj-$(CONFIG_JAZZ_LED) += jazz_led.o
-
-# PCI watchdog devices
-hw-obj-$(CONFIG_PCI) += wdt_i6300esb.o
-
-hw-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
-
-# PCI network cards
-hw-obj-$(CONFIG_NE2000_PCI) += ne2000.o
-hw-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o
-hw-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
-hw-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
-hw-obj-$(CONFIG_E1000_PCI) += e1000.o
-hw-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
-
-hw-obj-$(CONFIG_SMC91C111) += smc91c111.o
-hw-obj-$(CONFIG_LAN9118) += lan9118.o
-hw-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o
-hw-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o
-
-# IDE
-hw-obj-$(CONFIG_IDE_CORE) += ide/core.o ide/atapi.o
-hw-obj-$(CONFIG_IDE_QDEV) += ide/qdev.o
-hw-obj-$(CONFIG_IDE_PCI) += ide/pci.o
-hw-obj-$(CONFIG_IDE_ISA) += ide/isa.o
-hw-obj-$(CONFIG_IDE_PIIX) += ide/piix.o
-hw-obj-$(CONFIG_IDE_CMD646) += ide/cmd646.o
-hw-obj-$(CONFIG_IDE_MACIO) += ide/macio.o
-hw-obj-$(CONFIG_IDE_VIA) += ide/via.o
-hw-obj-$(CONFIG_AHCI) += ide/ahci.o
-hw-obj-$(CONFIG_AHCI) += ide/ich.o
-
-# SCSI layer
-hw-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o
-hw-obj-$(CONFIG_ESP) += esp.o
-
-hw-obj-y += dma-helpers.o sysbus.o isa-bus.o
-hw-obj-y += qdev-addr.o
-
-# VGA
-hw-obj-$(CONFIG_VGA_PCI) += vga-pci.o
-hw-obj-$(CONFIG_VGA_ISA) += vga-isa.o
-hw-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o
-hw-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o
-hw-obj-$(CONFIG_VMMOUSE) += vmmouse.o
-hw-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o
-
-hw-obj-$(CONFIG_RC4030) += rc4030.o
-hw-obj-$(CONFIG_DP8393X) += dp8393x.o
-hw-obj-$(CONFIG_DS1225Y) += ds1225y.o
-hw-obj-$(CONFIG_MIPSNET) += mipsnet.o
-
-hw-obj-y += qtest.o
-
-# Sound
-sound-obj-y =
-sound-obj-$(CONFIG_SB16) += sb16.o
-sound-obj-$(CONFIG_ES1370) += es1370.o
-sound-obj-$(CONFIG_AC97) += ac97.o
-sound-obj-$(CONFIG_ADLIB) += fmopl.o adlib.o
-sound-obj-$(CONFIG_GUS) += gus.o gusemu_hal.o gusemu_mixer.o
-sound-obj-$(CONFIG_CS4231A) += cs4231a.o
-sound-obj-$(CONFIG_HDA) += intel-hda.o hda-audio.o
-
-adlib.o fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
-hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
-
-9pfs-nested-$(CONFIG_VIRTFS) = virtio-9p.o
-9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o
-9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
-9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o cofile.o
-9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o virtio-9p-synth.o
-9pfs-nested-$(CONFIG_OPEN_BY_HANDLE) += virtio-9p-handle.o
-9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-proxy.o
-
-hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
+hw-obj-y = vl.o dma-helpers.o qtest.o hw/
######################################################################
# libdis
@@ -425,31 +187,29 @@ ifneq ($(TRACE_BACKEND),dtrace)
trace-obj-y = trace.o
endif
-trace-nested-$(CONFIG_TRACE_DEFAULT) += default.o
-
-trace-nested-$(CONFIG_TRACE_SIMPLE) += simple.o
+trace-obj-$(CONFIG_TRACE_DEFAULT) += trace/default.o
+trace-obj-$(CONFIG_TRACE_SIMPLE) += trace/simple.o
trace-obj-$(CONFIG_TRACE_SIMPLE) += qemu-timer-common.o
-
-trace-nested-$(CONFIG_TRACE_STDERR) += stderr.o
-
-trace-nested-y += control.o
-
-trace-obj-y += $(addprefix trace/, $(trace-nested-y))
+trace-obj-$(CONFIG_TRACE_STDERR) += trace/stderr.o
+trace-obj-y += trace/control.o
$(trace-obj-y): $(GENERATED_HEADERS)
######################################################################
# smartcard
-libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o card_7816.o
+libcacard-y += libcacard/cac.o libcacard/event.o
+libcacard-y += libcacard/vcard.o libcacard/vreader.o
+libcacard-y += libcacard/vcard_emul_nss.o
+libcacard-y += libcacard/vcard_emul_type.o
+libcacard-y += libcacard/card_7816.o
+
+common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y)
######################################################################
# qapi
-qapi-nested-y = qapi-visit-core.o qapi-dealloc-visitor.o qmp-input-visitor.o
-qapi-nested-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
-qapi-nested-y += string-input-visitor.o string-output-visitor.o
-qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
+qapi-obj-y = qapi/
common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o
common-obj-y += qmp.o hmp.o
@@ -459,11 +219,7 @@ universal-obj-y += $(qapi-obj-y)
######################################################################
# guest agent
-qga-nested-y = commands.o guest-agent-command-state.o
-qga-nested-$(CONFIG_POSIX) += commands-posix.o channel-posix.o
-qga-nested-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o
-qga-obj-y = $(addprefix qga/, $(qga-nested-y))
-qga-obj-y += qemu-ga.o module.o
+qga-obj-y = qga/ qemu-ga.o module.o
qga-obj-$(CONFIG_WIN32) += oslib-win32.o
qga-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-sockets.o qemu-option.o
@@ -473,3 +229,13 @@ vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
QEMU_CFLAGS+=$(GLIB_CFLAGS)
+nested-vars += \
+ hw-obj-y \
+ qga-obj-y \
+ block-obj-y \
+ qom-obj-y \
+ qapi-obj-y \
+ user-obj-y \
+ common-obj-y \
+ extra-obj-y
+dummy := $(call unnest-vars)
diff --git a/Makefile.target b/Makefile.target
index 15829041c7..2907aad0c4 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -1,10 +1,5 @@
# -*- Mode: makefile -*-
-GENERATED_HEADERS = config-target.h
-CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
-CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
-CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
-
include ../config-host.mak
include config-devices.mak
include config-target.mak
@@ -13,14 +8,11 @@ ifneq ($(HWDIR),)
include $(HWDIR)/config.mak
endif
-TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
-$(call set-vpath, $(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw)
+$(call set-vpath, $(SRC_PATH))
ifdef CONFIG_LINUX
QEMU_CFLAGS += -I../linux-headers
endif
-QEMU_CFLAGS += -I.. -I$(TARGET_PATH) -DNEED_CPU_H
-
-include $(SRC_PATH)/Makefile.objs
+QEMU_CFLAGS += -I.. -I$(SRC_PATH)/target-$(TARGET_BASE_ARCH) -DNEED_CPU_H
QEMU_CFLAGS+=-I$(SRC_PATH)/include
@@ -77,78 +69,34 @@ all: $(PROGS) stap
#########################################################
# cpu emulator library
-libobj-y = exec.o translate-all.o cpu-exec.o translate.o
-libobj-y += tcg/tcg.o tcg/optimize.o
-libobj-$(CONFIG_TCG_INTERPRETER) += tci.o
-libobj-y += fpu/softfloat.o
-ifneq ($(TARGET_BASE_ARCH), sparc)
-ifneq ($(TARGET_BASE_ARCH), alpha)
-libobj-y += op_helper.o
-endif
-endif
-libobj-y += helper.o
-ifneq ($(TARGET_BASE_ARCH), ppc)
-libobj-y += cpu.o
-endif
-libobj-$(TARGET_SPARC64) += vis_helper.o
-libobj-$(CONFIG_NEED_MMU) += mmu.o
-libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
-ifeq ($(TARGET_BASE_ARCH), sparc)
-libobj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o
-endif
-libobj-$(TARGET_SPARC) += int32_helper.o
-libobj-$(TARGET_SPARC64) += int64_helper.o
-libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
-
-libobj-y += disas.o
-libobj-$(CONFIG_TCI_DIS) += tci-dis.o
+obj-y = exec.o translate-all.o cpu-exec.o
+obj-y += tcg/tcg.o tcg/optimize.o
+obj-$(CONFIG_TCG_INTERPRETER) += tci.o
+obj-y += fpu/softfloat.o
+obj-y += disas.o
+obj-$(CONFIG_TCI_DIS) += tci-dis.o
+obj-y += target-$(TARGET_BASE_ARCH)/
+obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci
-$(libobj-y): $(GENERATED_HEADERS)
-
# HELPER_CFLAGS is used for all the legacy code compiled with static register
# variables
-ifneq ($(TARGET_BASE_ARCH), sparc)
-op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
-endif
user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
# Note: this is a workaround. The real fix is to avoid compiling
# cpu_signal_handler() in user-exec.c.
-signal.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+%/signal.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
#########################################################
# Linux user emulator target
ifdef CONFIG_LINUX_USER
-$(call set-vpath, $(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR))
-
QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
-obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \
- elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \
- user-exec.o $(oslib-obj-y)
-
-obj-$(TARGET_HAS_BFLT) += flatload.o
-
-obj-$(TARGET_I386) += vm86.o
-obj-i386-y += ioport-user.o
-
-nwfpe-obj-y = fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o fpopcode.o
-nwfpe-obj-y += single_cpdo.o double_cpdo.o extended_cpdo.o
-obj-arm-y += $(addprefix nwfpe/, $(nwfpe-obj-y))
-obj-arm-y += arm-semi.o
-
-obj-m68k-y += m68k-sim.o m68k-semi.o
-
-$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
-
-obj-y += $(addprefix ../, $(universal-obj-y))
-obj-y += $(addprefix ../libuser/, $(user-obj-y))
-obj-y += $(addprefix ../libdis-user/, $(libdis-y))
-obj-y += $(libobj-y)
+obj-y += linux-user/
+obj-y += gdbstub.o thunk.o user-exec.o $(oslib-obj-y)
endif #CONFIG_LINUX_USER
@@ -157,269 +105,81 @@ endif #CONFIG_LINUX_USER
ifdef CONFIG_BSD_USER
-$(call set-vpath, $(SRC_PATH)/bsd-user)
-
QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ARCH)
-obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
- gdbstub.o uaccess.o user-exec.o
-
-obj-i386-y += ioport-user.o
-
-$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
-
-obj-y += $(addprefix ../, $(universal-obj-y))
-obj-y += $(addprefix ../libuser/, $(user-obj-y))
-obj-y += $(addprefix ../libdis-user/, $(libdis-y))
-obj-y += $(libobj-y)
+obj-y += bsd-user/
+obj-y += gdbstub.o user-exec.o
endif #CONFIG_BSD_USER
#########################################################
# System emulator target
ifdef CONFIG_SOFTMMU
+CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
+CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
+CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
+CONFIG_NO_GET_MEMORY_MAPPING = $(if $(subst n,,$(CONFIG_HAVE_GET_MEMORY_MAPPING)),n,y)
+CONFIG_NO_CORE_DUMP = $(if $(subst n,,$(CONFIG_HAVE_CORE_DUMP)),n,y)
-obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o
-# virtio has to be here due to weird dependency between PCI and virtio-net.
-# need to fix this properly
-obj-$(CONFIG_NO_PCI) += pci-stub.o
-obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
-obj-$(CONFIG_VIRTIO) += virtio-scsi.o
-obj-y += vhost_net.o
-obj-$(CONFIG_VHOST_NET) += vhost.o
-obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
-obj-$(CONFIG_KVM) += kvm.o kvm-all.o
+obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o
+obj-y += hw/
+obj-$(CONFIG_KVM) += kvm-all.o
obj-$(CONFIG_NO_KVM) += kvm-stub.o
-obj-$(CONFIG_VGA) += vga.o
obj-y += memory.o savevm.o cputlb.o
+obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += memory_mapping.o
+obj-$(CONFIG_HAVE_CORE_DUMP) += dump.o
+obj-$(CONFIG_NO_GET_MEMORY_MAPPING) += memory_mapping-stub.o
+obj-$(CONFIG_NO_CORE_DUMP) += dump-stub.o
LIBS+=-lz
-obj-i386-$(CONFIG_KVM) += hyperv.o
-
QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
# xen support
-obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
+obj-$(CONFIG_XEN) += xen-all.o xen-mapcache.o
obj-$(CONFIG_NO_XEN) += xen-stub.o
-obj-i386-$(CONFIG_XEN) += xen_platform.o xen_apic.o
-
-# Inter-VM PCI shared memory
-CONFIG_IVSHMEM =
-ifeq ($(CONFIG_KVM), y)
- ifeq ($(CONFIG_PCI), y)
- CONFIG_IVSHMEM = y
- endif
-endif
-obj-$(CONFIG_IVSHMEM) += ivshmem.o
-
-# Generic hotplugging
-obj-y += device-hotplug.o
-
# Hardware support
-obj-i386-y += mc146818rtc.o pc.o
-obj-i386-y += apic_common.o apic.o kvmvapic.o
-obj-i386-y += sga.o ioapic_common.o ioapic.o piix_pci.o
-obj-i386-y += vmport.o
-obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
-obj-i386-y += debugcon.o multiboot.o
-obj-i386-y += pc_piix.o
-obj-i386-y += pc_sysfw.o
-obj-i386-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o kvm/i8259.o kvm/ioapic.o kvm/i8254.o
-obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
-
-# shared objects
-obj-ppc-y = ppc.o ppc_booke.o
-# PREP target
-obj-ppc-y += mc146818rtc.o
-obj-ppc-y += ppc_prep.o
-# OldWorld PowerMac
-obj-ppc-y += ppc_oldworld.o
-# NewWorld PowerMac
-obj-ppc-y += ppc_newworld.o
-# IBM pSeries (sPAPR)
-obj-ppc-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
-obj-ppc-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
-obj-ppc-$(CONFIG_PSERIES) += spapr_pci.o device-hotplug.o pci-hotplug.o
-# PowerPC 4xx boards
-obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
-obj-ppc-y += ppc440_bamboo.o
-# PowerPC E500 boards
-obj-ppc-y += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o
-# PowerPC 440 Xilinx ML507 reference board.
-obj-ppc-y += virtex_ml507.o
-obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
-obj-ppc-$(CONFIG_FDT) += device_tree.o
-# PowerPC OpenPIC
-obj-ppc-y += openpic.o
-
-# Xilinx PPC peripherals
-obj-ppc-y += xilinx_intc.o
-obj-ppc-y += xilinx_timer.o
-obj-ppc-y += xilinx_uartlite.o
-obj-ppc-y += xilinx_ethlite.o
-
-# LM32 boards
-obj-lm32-y += lm32_boards.o
-obj-lm32-y += milkymist.o
-
-# LM32 peripherals
-obj-lm32-y += lm32_pic.o
-obj-lm32-y += lm32_juart.o
-obj-lm32-y += lm32_timer.o
-obj-lm32-y += lm32_uart.o
-obj-lm32-y += lm32_sys.o
-obj-lm32-y += milkymist-ac97.o
-obj-lm32-y += milkymist-hpdmc.o
-obj-lm32-y += milkymist-memcard.o
-obj-lm32-y += milkymist-minimac2.o
-obj-lm32-y += milkymist-pfpu.o
-obj-lm32-y += milkymist-softusb.o
-obj-lm32-y += milkymist-sysctl.o
-obj-lm32-$(CONFIG_OPENGL) += milkymist-tmu2.o
-obj-lm32-y += milkymist-uart.o
-obj-lm32-y += milkymist-vgafb.o
-obj-lm32-y += framebuffer.o
-
-obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
-obj-mips-y += mips_addr.o mips_timer.o mips_int.o
-obj-mips-y += gt64xxx.o mc146818rtc.o
-obj-mips-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
-
-obj-microblaze-y = petalogix_s3adsp1800_mmu.o
-obj-microblaze-y += petalogix_ml605_mmu.o
-obj-microblaze-y += microblaze_boot.o
-
-obj-microblaze-y += microblaze_pic_cpu.o
-obj-microblaze-y += xilinx_intc.o
-obj-microblaze-y += xilinx_timer.o
-obj-microblaze-y += xilinx_uartlite.o
-obj-microblaze-y += xilinx_ethlite.o
-obj-microblaze-y += xilinx_axidma.o
-obj-microblaze-y += xilinx_axienet.o
-
-obj-microblaze-$(CONFIG_FDT) += device_tree.o
-
-# Boards
-obj-cris-y = cris_pic_cpu.o
-obj-cris-y += cris-boot.o
-obj-cris-y += axis_dev88.o
-
-# IO blocks
-obj-cris-y += etraxfs_dma.o
-obj-cris-y += etraxfs_pic.o
-obj-cris-y += etraxfs_eth.o
-obj-cris-y += etraxfs_timer.o
-obj-cris-y += etraxfs_ser.o
-
ifeq ($(TARGET_ARCH), sparc64)
-obj-sparc-y = sun4u.o apb_pci.o
-obj-sparc-y += mc146818rtc.o
+obj-y += hw/sparc64/
else
-obj-sparc-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o
-obj-sparc-y += slavio_timer.o slavio_misc.o sparc32_dma.o
-obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o
-
-# GRLIB
-obj-sparc-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o
+obj-y += hw/$(TARGET_BASE_ARCH)/
endif
-obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
-obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
-obj-arm-y += versatile_pci.o
-obj-arm-y += versatile_i2c.o
-obj-arm-y += cadence_uart.o
-obj-arm-y += cadence_ttc.o
-obj-arm-y += cadence_gem.o
-obj-arm-y += xilinx_zynq.o zynq_slcr.o
-obj-arm-y += arm_gic.o
-obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
-obj-arm-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
-obj-arm-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
-obj-arm-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o
-obj-arm-y += arm_l2x0.o
-obj-arm-y += arm_mptimer.o a15mpcore.o
-obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
-obj-arm-y += highbank.o
-obj-arm-y += pl061.o
-obj-arm-y += xgmac.o
-obj-arm-y += arm-semi.o
-obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
-obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
-obj-arm-y += gumstix.o
-obj-arm-y += zaurus.o ide/microdrive.o spitz.o tosa.o tc6393xb.o
-obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
- omap_gpio.o omap_intc.o omap_uart.o
-obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
- omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
-obj-arm-y += omap_sx1.o palm.o tsc210x.o
-obj-arm-y += nseries.o blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
-obj-arm-y += mst_fpga.o mainstone.o
-obj-arm-y += z2.o
-obj-arm-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
-obj-arm-y += framebuffer.o
-obj-arm-y += vexpress.o
-obj-arm-y += strongarm.o
-obj-arm-y += collie.o
-obj-arm-y += pl041.o lm4549.o
-obj-arm-$(CONFIG_FDT) += device_tree.o
-
-obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
-obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
-obj-sh4-y += ide/mmio.o
-
-obj-m68k-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
-obj-m68k-y += m68k-semi.o dummy_m68k.o
-
-obj-s390x-y = s390-virtio-bus.o s390-virtio.o
-
-obj-alpha-y = mc146818rtc.o
-obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
-
-obj-xtensa-y += xtensa_pic.o
-obj-xtensa-y += xtensa_sim.o
-obj-xtensa-y += xtensa_lx60.o
-obj-xtensa-y += xtensa-semi.o
-obj-xtensa-y += core-dc232b.o
-obj-xtensa-y += core-dc233c.o
-obj-xtensa-y += core-fsf.o
-
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
-monitor.o: hmp-commands.h qmp-commands-old.h
+GENERATED_HEADERS += hmp-commands.h qmp-commands-old.h
-$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
+endif # CONFIG_SOFTMMU
-obj-y += $(addprefix ../, $(universal-obj-y))
-obj-y += $(addprefix ../, $(common-obj-y))
-obj-y += $(addprefix ../libdis/, $(libdis-y))
-obj-y += $(libobj-y)
-obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))
-obj-y += $(addprefix ../, $(trace-obj-y))
+nested-vars += obj-y
-endif # CONFIG_SOFTMMU
+# This resolves all nested paths, so it must come last
+include $(SRC_PATH)/Makefile.objs
-ifndef CONFIG_LINUX_USER
-ifndef CONFIG_BSD_USER
-# libcacard needs qemu-thread support, and besides is only needed by devices
-# so not requires with linux-user / bsd-user targets
-obj-$(CONFIG_SMARTCARD_NSS) += $(addprefix ../libcacard/, $(libcacard-y))
-endif # CONFIG_BSD_USER
-endif # CONFIG_LINUX_USER
+all-obj-y = $(obj-y)
+all-obj-y += $(addprefix ../, $(universal-obj-y))
-obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
+ifdef CONFIG_SOFTMMU
+all-obj-y += $(addprefix ../, $(common-obj-y))
+all-obj-y += $(addprefix ../libdis/, $(libdis-y))
+all-obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))
+all-obj-y += $(addprefix ../, $(trace-obj-y))
+else
+all-obj-y += $(addprefix ../libuser/, $(user-obj-y))
+all-obj-y += $(addprefix ../libdis-user/, $(libdis-y))
+endif #CONFIG_LINUX_USER
ifdef QEMU_PROGW
# The linker builds a windows executable. Make also a console executable.
-$(QEMU_PROGW): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
+$(QEMU_PROGW): $(all-obj-y)
$(call LINK,$^)
$(QEMU_PROG): $(QEMU_PROGW)
$(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG)," GEN $(TARGET_DIR)$(QEMU_PROG)")
else
-$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
+$(QEMU_PROG): $(all-obj-y)
$(call LINK,$^)
endif
@@ -452,5 +212,8 @@ ifdef CONFIG_TRACE_SYSTEMTAP
$(INSTALL_DATA) $(QEMU_PROG).stp "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset"
endif
+GENERATED_HEADERS += config-target.h
+Makefile: $(GENERATED_HEADERS)
+
# Include automatically generated dependency files
-include $(wildcard *.d */*.d)
diff --git a/audio/Makefile.objs b/audio/Makefile.objs
new file mode 100644
index 0000000000..0f2932d1b3
--- /dev/null
+++ b/audio/Makefile.objs
@@ -0,0 +1,14 @@
+common-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
+common-obj-$(CONFIG_SDL) += sdlaudio.o
+common-obj-$(CONFIG_OSS) += ossaudio.o
+common-obj-$(CONFIG_SPICE) += spiceaudio.o
+common-obj-$(CONFIG_COREAUDIO) += coreaudio.o
+common-obj-$(CONFIG_ALSA) += alsaaudio.o
+common-obj-$(CONFIG_DSOUND) += dsoundaudio.o
+common-obj-$(CONFIG_FMOD) += fmodaudio.o
+common-obj-$(CONFIG_ESD) += esdaudio.o
+common-obj-$(CONFIG_PA) += paaudio.o
+common-obj-$(CONFIG_WINWAVE) += winwaveaudio.o
+common-obj-$(CONFIG_AUDIO_PT_INT) += audio_pt_int.o
+common-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o
+common-obj-y += wavcapture.o
diff --git a/audio/winwaveaudio.c b/audio/winwaveaudio.c
index 87e7493270..663abb9b50 100644
--- a/audio/winwaveaudio.c
+++ b/audio/winwaveaudio.c
@@ -72,7 +72,7 @@ static void winwave_log_mmresult (MMRESULT mr)
break;
case MMSYSERR_NOMEM:
- str = "Unable to allocate or locl memory";
+ str = "Unable to allocate or lock memory";
break;
case WAVERR_SYNC:
diff --git a/block/Makefile.objs b/block/Makefile.objs
new file mode 100644
index 0000000000..b5754d39bf
--- /dev/null
+++ b/block/Makefile.objs
@@ -0,0 +1,11 @@
+block-obj-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
+block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
+block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
+block-obj-y += qed-check.o
+block-obj-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o
+block-obj-y += stream.o
+block-obj-$(CONFIG_WIN32) += raw-win32.o
+block-obj-$(CONFIG_POSIX) += raw-posix.o
+block-obj-$(CONFIG_LIBISCSI) += iscsi.o
+block-obj-$(CONFIG_CURL) += curl.o
+block-obj-$(CONFIG_RBD) += rbd.o
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 4b3345b11b..c173fcd488 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -471,6 +471,8 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO);
*cluster_offset &= L2E_OFFSET_MASK;
break;
+ default:
+ abort();
}
qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
diff --git a/blockdev.c b/blockdev.c
index 67895b25d5..622ecba04e 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -569,7 +569,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
break;
case IF_VIRTIO:
/* add virtio block device */
- opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+ opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL);
if (arch_type == QEMU_ARCH_S390X) {
qemu_opt_set(opts, "driver", "virtio-blk-s390");
} else {
diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs
new file mode 100644
index 0000000000..5e77f57782
--- /dev/null
+++ b/bsd-user/Makefile.objs
@@ -0,0 +1,2 @@
+obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
+ uaccess.o
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 0689e38fb8..cd33d655f5 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -918,7 +918,7 @@ int main(int argc, char **argv)
exit(1);
}
#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
- cpu_state_reset(env);
+ cpu_reset(ENV_GET_CPU(env));
#endif
thread_env = env;
diff --git a/configure b/configure
index 1f338f8dce..5d73c82563 100755
--- a/configure
+++ b/configure
@@ -42,6 +42,7 @@ compile_prog() {
# symbolically link $1 to $2. Portable version of "ln -sf".
symlink() {
rm -rf "$2"
+ mkdir -p "$(dirname "$2")"
ln -s "$1" "$2"
}
@@ -2811,7 +2812,11 @@ fi
open_by_hande_at=no
cat > $TMPC << EOF
#include <fcntl.h>
+#if !defined(AT_EMPTY_PATH)
+# error missing definition
+#else
int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
+#endif
EOF
if compile_prog "" "" ; then
open_by_handle_at=yes
@@ -2915,7 +2920,8 @@ if test "$softmmu" = yes ; then
tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)"
else
if test "$virtfs" = yes; then
- feature_not_found "virtfs"
+ echo "VirtFS is supported only on Linux and requires libcap-devel and libattr-devel"
+ exit 1
fi
virtfs=no
fi
@@ -2927,6 +2933,9 @@ if test "$softmmu" = yes ; then
fi
fi
fi
+if test "$smartcard_nss" = "yes" ; then
+ tools="vscclient\$(EXESUF) $tools"
+fi
# Mac OS X ships with a broken assembler
roms=
@@ -3451,14 +3460,12 @@ if test -f ${config_host_ld}~ ; then
fi
for d in libdis libdis-user; do
- mkdir -p $d
symlink "$source_path/Makefile.dis" "$d/Makefile"
echo > $d/config.mak
done
# use included Linux headers
if test "$linux" = "yes" ; then
- mkdir -p linux-headers
case "$cpu" in
i386|x86_64)
symlink "$source_path/linux-headers/asm-x86" linux-headers/asm
@@ -3514,18 +3521,6 @@ case "$target" in
esac
mkdir -p $target_dir
-mkdir -p $target_dir/fpu
-mkdir -p $target_dir/tcg
-mkdir -p $target_dir/ide
-mkdir -p $target_dir/usb
-mkdir -p $target_dir/9pfs
-mkdir -p $target_dir/kvm
-if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" -o "$target" = "arm-bsd-user" -o "$target" = "armeb-bsd-user" ; then
- mkdir -p $target_dir/nwfpe
-fi
-symlink "$source_path/Makefile.target" "$target_dir/Makefile"
-
-
echo "# Automatically generated by configure - do not modify" > $config_target_mak
bflt="no"
@@ -3676,9 +3671,16 @@ case "$target_arch2" in
exit 1
;;
esac
+# TARGET_BASE_ARCH needs to be defined after TARGET_ARCH
+if [ "$TARGET_BASE_ARCH" = "" ]; then
+ TARGET_BASE_ARCH=$TARGET_ARCH
+fi
+
+symlink "$source_path/Makefile.target" "$target_dir/Makefile"
+
case "$target_arch2" in
- alpha | sparc*)
+ alpha | sparc* | xtensa*)
echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
;;
esac
@@ -3691,10 +3693,6 @@ echo "TARGET_ARCH=$TARGET_ARCH" >> $config_target_mak
target_arch_name="`echo $TARGET_ARCH | LC_ALL=C tr '[a-z]' '[A-Z]'`"
echo "TARGET_$target_arch_name=y" >> $config_target_mak
echo "TARGET_ARCH2=$target_arch2" >> $config_target_mak
-# TARGET_BASE_ARCH needs to be defined after TARGET_ARCH
-if [ "$TARGET_BASE_ARCH" = "" ]; then
- TARGET_BASE_ARCH=$TARGET_ARCH
-fi
echo "TARGET_BASE_ARCH=$TARGET_BASE_ARCH" >> $config_target_mak
if [ "$TARGET_ABI_DIR" = "" ]; then
TARGET_ABI_DIR=$TARGET_ARCH
@@ -3729,6 +3727,10 @@ case "$target_arch2" in
fi
fi
esac
+case "$target_arch2" in
+ i386|x86_64)
+ echo "CONFIG_HAVE_GET_MEMORY_MAPPING=y" >> $config_target_mak
+esac
if test "$target_arch2" = "ppc64" -a "$fdt" = "yes"; then
echo "CONFIG_PSERIES=y" >> $config_target_mak
fi
@@ -3744,6 +3746,10 @@ if test "$target_softmmu" = "yes" ; then
if test "$smartcard_nss" = "yes" ; then
echo "subdir-$target: subdir-libcacard" >> $config_host_mak
fi
+ case "$target_arch2" in
+ i386|x86_64)
+ echo "CONFIG_HAVE_CORE_DUMP=y" >> $config_target_mak
+ esac
fi
if test "$target_user_only" = "yes" ; then
echo "CONFIG_USER_ONLY=y" >> $config_target_mak
@@ -3893,12 +3899,6 @@ if test "$target_softmmu" = "yes" ; then
esac
fi
-if test "$target_softmmu" = "yes" -a \( \
- "$TARGET_ARCH" = "microblaze" -o \
- "$TARGET_ARCH" = "cris" \) ; then
- echo "CONFIG_NEED_MMU=y" >> $config_target_mak
-fi
-
if test "$gprof" = "yes" ; then
echo "TARGET_GPROF=yes" >> $config_target_mak
if test "$target_linux_user" = "yes" ; then
@@ -3940,15 +3940,13 @@ done # for target in $targets
# build tree in object directory in case the source is not in the current directory
DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32"
-DIRS="$DIRS slirp audio block net pc-bios/optionrom"
-DIRS="$DIRS pc-bios/spapr-rtas"
+DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas"
DIRS="$DIRS roms/seabios roms/vgabios"
-DIRS="$DIRS fsdev ui usb"
-DIRS="$DIRS qapi qapi-generated"
-DIRS="$DIRS qga trace qom"
+DIRS="$DIRS qapi-generated"
+DIRS="$DIRS libcacard libcacard/libcacard libcacard/trace"
FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
-FILES="$FILES tests/tcg/lm32/Makefile"
+FILES="$FILES tests/tcg/lm32/Makefile libcacard/Makefile"
FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
FILES="$FILES pc-bios/spapr-rtas/Makefile"
FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
@@ -3983,24 +3981,11 @@ done
for hwlib in 32 64; do
d=libhw$hwlib
- mkdir -p $d
- mkdir -p $d/ide
- mkdir -p $d/usb
symlink "$source_path/Makefile.hw" "$d/Makefile"
- mkdir -p $d/9pfs
echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak
done
-if [ "$source_path" != `pwd` ]; then
- # out of tree build
- mkdir -p libcacard
- symlink "$source_path/libcacard/Makefile" libcacard/Makefile
-fi
-
d=libuser
-mkdir -p $d
-mkdir -p $d/trace
-mkdir -p $d/qom
symlink "$source_path/Makefile.user" "$d/Makefile"
if test "$docs" = "yes" ; then
diff --git a/cpu-all.h b/cpu-all.h
index 028528f0be..3a93c0c98a 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -443,7 +443,6 @@ void cpu_watchpoint_remove_all(CPUArchState *env, int mask);
#define SSTEP_NOTIMER 0x4 /* Do not Timers while single stepping */
void cpu_single_step(CPUArchState *env, int enabled);
-void cpu_state_reset(CPUArchState *s);
int cpu_is_stopped(CPUArchState *env);
void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data);
diff --git a/cpu-common.h b/cpu-common.h
index dca5175652..1fe3280701 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -71,6 +71,10 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
void cpu_unregister_map_client(void *cookie);
+#ifndef CONFIG_USER_ONLY
+bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr);
+#endif
+
/* Coalesced MMIO regions are areas where write operations can be reordered.
* This usually implies that write operations are side-effect free. This allows
* batching which can make a major impact on performance when using
diff --git a/cpu-exec.c b/cpu-exec.c
index 0344cd5c59..624c409f7b 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -184,6 +184,9 @@ volatile sig_atomic_t exit_request;
int cpu_exec(CPUArchState *env)
{
+#ifdef TARGET_PPC
+ CPUState *cpu = ENV_GET_CPU(env);
+#endif
int ret, interrupt_request;
TranslationBlock *tb;
uint8_t *tc_ptr;
@@ -287,11 +290,11 @@ int cpu_exec(CPUArchState *env)
#if defined(TARGET_I386)
if (interrupt_request & CPU_INTERRUPT_INIT) {
svm_check_intercept(env, SVM_EXIT_INIT);
- do_cpu_init(env);
+ do_cpu_init(x86_env_get_cpu(env));
env->exception_index = EXCP_HALTED;
cpu_loop_exit(env);
} else if (interrupt_request & CPU_INTERRUPT_SIPI) {
- do_cpu_sipi(env);
+ do_cpu_sipi(x86_env_get_cpu(env));
} else if (env->hflags2 & HF2_GIF_MASK) {
if ((interrupt_request & CPU_INTERRUPT_SMI) &&
!(env->hflags & HF_SMM_MASK)) {
@@ -341,7 +344,7 @@ int cpu_exec(CPUArchState *env)
}
#elif defined(TARGET_PPC)
if ((interrupt_request & CPU_INTERRUPT_RESET)) {
- cpu_state_reset(env);
+ cpu_reset(cpu);
}
if (interrupt_request & CPU_INTERRUPT_HARD) {
ppc_hw_interrupt(env);
@@ -464,11 +467,18 @@ int cpu_exec(CPUArchState *env)
do_interrupt(env);
next_tb = 0;
}
- if (interrupt_request & CPU_INTERRUPT_NMI
- && (env->pregs[PR_CCS] & M_FLAG)) {
- env->exception_index = EXCP_NMI;
- do_interrupt(env);
- next_tb = 0;
+ if (interrupt_request & CPU_INTERRUPT_NMI) {
+ unsigned int m_flag_archval;
+ if (env->pregs[PR_VR] < 32) {
+ m_flag_archval = M_FLAG_V10;
+ } else {
+ m_flag_archval = M_FLAG_V32;
+ }
+ if ((env->pregs[PR_CCS] & m_flag_archval)) {
+ env->exception_index = EXCP_NMI;
+ do_interrupt(env);
+ next_tb = 0;
+ }
}
#elif defined(TARGET_M68K)
if (interrupt_request & CPU_INTERRUPT_HARD
diff --git a/default-configs/microblaze-softmmu.mak b/default-configs/microblaze-softmmu.mak
index 613edab742..64c9485de4 100644
--- a/default-configs/microblaze-softmmu.mak
+++ b/default-configs/microblaze-softmmu.mak
@@ -3,3 +3,5 @@
CONFIG_PTIMER=y
CONFIG_PFLASH_CFI01=y
CONFIG_SERIAL=y
+CONFIG_XILINX=y
+CONFIG_XILINX_AXI=y
diff --git a/default-configs/microblazeel-softmmu.mak b/default-configs/microblazeel-softmmu.mak
index 4b40fb21a5..a9622760c9 100644
--- a/default-configs/microblazeel-softmmu.mak
+++ b/default-configs/microblazeel-softmmu.mak
@@ -3,3 +3,5 @@
CONFIG_PTIMER=y
CONFIG_PFLASH_CFI01=y
CONFIG_SERIAL=y
+CONFIG_XILINX=y
+CONFIG_XILINX_AXI=y
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 1a768fc519..d0fde7b93d 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -36,3 +36,4 @@ CONFIG_PFLASH_CFI01=y
CONFIG_PFLASH_CFI02=y
CONFIG_PTIMER=y
CONFIG_I8259=y
+CONFIG_XILINX=y
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index f490368c64..e4265b4978 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -33,3 +33,4 @@ CONFIG_PFLASH_CFI01=y
CONFIG_PFLASH_CFI02=y
CONFIG_PTIMER=y
CONFIG_I8259=y
+CONFIG_XILINX=y
diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
index 829f462105..aaa9cdc1f7 100644
--- a/default-configs/ppcemb-softmmu.mak
+++ b/default-configs/ppcemb-softmmu.mak
@@ -33,3 +33,4 @@ CONFIG_PFLASH_CFI01=y
CONFIG_PFLASH_CFI02=y
CONFIG_PTIMER=y
CONFIG_I8259=y
+CONFIG_XILINX=y
diff --git a/dump-stub.c b/dump-stub.c
new file mode 100644
index 0000000000..56d4564f0f
--- /dev/null
+++ b/dump-stub.c
@@ -0,0 +1,64 @@
+/*
+ * QEMU dump
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ * Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "dump.h"
+#include "qerror.h"
+#include "qmp-commands.h"
+
+/* we need this function in hmp.c */
+void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
+ int64_t begin, bool has_length, int64_t length,
+ Error **errp)
+{
+ error_set(errp, QERR_UNSUPPORTED);
+}
+
+int cpu_write_elf64_note(write_core_dump_function f,
+ CPUArchState *env, int cpuid,
+ void *opaque)
+{
+ return -1;
+}
+
+int cpu_write_elf32_note(write_core_dump_function f,
+ CPUArchState *env, int cpuid,
+ void *opaque)
+{
+ return -1;
+}
+
+int cpu_write_elf64_qemunote(write_core_dump_function f,
+ CPUArchState *env,
+ void *opaque)
+{
+ return -1;
+}
+
+int cpu_write_elf32_qemunote(write_core_dump_function f,
+ CPUArchState *env,
+ void *opaque)
+{
+ return -1;
+}
+
+int cpu_get_dump_info(ArchDumpInfo *info)
+{
+ return -1;
+}
+
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+ return -1;
+}
+
diff --git a/dump.c b/dump.c
new file mode 100644
index 0000000000..2bf8d8d994
--- /dev/null
+++ b/dump.c
@@ -0,0 +1,873 @@
+/*
+ * QEMU dump
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ * Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "elf.h"
+#include "cpu.h"
+#include "cpu-all.h"
+#include "targphys.h"
+#include "monitor.h"
+#include "kvm.h"
+#include "dump.h"
+#include "sysemu.h"
+#include "memory_mapping.h"
+#include "error.h"
+#include "qmp-commands.h"
+#include "gdbstub.h"
+
+static uint16_t cpu_convert_to_target16(uint16_t val, int endian)
+{
+ if (endian == ELFDATA2LSB) {
+ val = cpu_to_le16(val);
+ } else {
+ val = cpu_to_be16(val);
+ }
+
+ return val;
+}
+
+static uint32_t cpu_convert_to_target32(uint32_t val, int endian)
+{
+ if (endian == ELFDATA2LSB) {
+ val = cpu_to_le32(val);
+ } else {
+ val = cpu_to_be32(val);
+ }
+
+ return val;
+}
+
+static uint64_t cpu_convert_to_target64(uint64_t val, int endian)
+{
+ if (endian == ELFDATA2LSB) {
+ val = cpu_to_le64(val);
+ } else {
+ val = cpu_to_be64(val);
+ }
+
+ return val;
+}
+
+typedef struct DumpState {
+ ArchDumpInfo dump_info;
+ MemoryMappingList list;
+ uint16_t phdr_num;
+ uint32_t sh_info;
+ bool have_section;
+ bool resume;
+ size_t note_size;
+ target_phys_addr_t memory_offset;
+ int fd;
+
+ RAMBlock *block;
+ ram_addr_t start;
+ bool has_filter;
+ int64_t begin;
+ int64_t length;
+ Error **errp;
+} DumpState;
+
+static int dump_cleanup(DumpState *s)
+{
+ int ret = 0;
+
+ memory_mapping_list_free(&s->list);
+ if (s->fd != -1) {
+ close(s->fd);
+ }
+ if (s->resume) {
+ vm_start();
+ }
+
+ return ret;
+}
+
+static void dump_error(DumpState *s, const char *reason)
+{
+ dump_cleanup(s);
+}
+
+static int fd_write_vmcore(void *buf, size_t size, void *opaque)
+{
+ DumpState *s = opaque;
+ int fd = s->fd;
+ size_t writen_size;
+
+ /* The fd may be passed from user, and it can be non-blocked */
+ while (size) {
+ writen_size = qemu_write_full(fd, buf, size);
+ if (writen_size != size && errno != EAGAIN) {
+ return -1;
+ }
+
+ buf += writen_size;
+ size -= writen_size;
+ }
+
+ return 0;
+}
+
+static int write_elf64_header(DumpState *s)
+{
+ Elf64_Ehdr elf_header;
+ int ret;
+ int endian = s->dump_info.d_endian;
+
+ memset(&elf_header, 0, sizeof(Elf64_Ehdr));
+ memcpy(&elf_header, ELFMAG, SELFMAG);
+ elf_header.e_ident[EI_CLASS] = ELFCLASS64;
+ elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
+ elf_header.e_ident[EI_VERSION] = EV_CURRENT;
+ elf_header.e_type = cpu_convert_to_target16(ET_CORE, endian);
+ elf_header.e_machine = cpu_convert_to_target16(s->dump_info.d_machine,
+ endian);
+ elf_header.e_version = cpu_convert_to_target32(EV_CURRENT, endian);
+ elf_header.e_ehsize = cpu_convert_to_target16(sizeof(elf_header), endian);
+ elf_header.e_phoff = cpu_convert_to_target64(sizeof(Elf64_Ehdr), endian);
+ elf_header.e_phentsize = cpu_convert_to_target16(sizeof(Elf64_Phdr),
+ endian);
+ elf_header.e_phnum = cpu_convert_to_target16(s->phdr_num, endian);
+ if (s->have_section) {
+ uint64_t shoff = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * s->sh_info;
+
+ elf_header.e_shoff = cpu_convert_to_target64(shoff, endian);
+ elf_header.e_shentsize = cpu_convert_to_target16(sizeof(Elf64_Shdr),
+ endian);
+ elf_header.e_shnum = cpu_convert_to_target16(1, endian);
+ }
+
+ ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
+ if (ret < 0) {
+ dump_error(s, "dump: failed to write elf header.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int write_elf32_header(DumpState *s)
+{
+ Elf32_Ehdr elf_header;
+ int ret;
+ int endian = s->dump_info.d_endian;
+
+ memset(&elf_header, 0, sizeof(Elf32_Ehdr));
+ memcpy(&elf_header, ELFMAG, SELFMAG);
+ elf_header.e_ident[EI_CLASS] = ELFCLASS32;
+ elf_header.e_ident[EI_DATA] = endian;
+ elf_header.e_ident[EI_VERSION] = EV_CURRENT;
+ elf_header.e_type = cpu_convert_to_target16(ET_CORE, endian);
+ elf_header.e_machine = cpu_convert_to_target16(s->dump_info.d_machine,
+ endian);
+ elf_header.e_version = cpu_convert_to_target32(EV_CURRENT, endian);
+ elf_header.e_ehsize = cpu_convert_to_target16(sizeof(elf_header), endian);
+ elf_header.e_phoff = cpu_convert_to_target32(sizeof(Elf32_Ehdr), endian);
+ elf_header.e_phentsize = cpu_convert_to_target16(sizeof(Elf32_Phdr),
+ endian);
+ elf_header.e_phnum = cpu_convert_to_target16(s->phdr_num, endian);
+ if (s->have_section) {
+ uint32_t shoff = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * s->sh_info;
+
+ elf_header.e_shoff = cpu_convert_to_target32(shoff, endian);
+ elf_header.e_shentsize = cpu_convert_to_target16(sizeof(Elf32_Shdr),
+ endian);
+ elf_header.e_shnum = cpu_convert_to_target16(1, endian);
+ }
+
+ ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
+ if (ret < 0) {
+ dump_error(s, "dump: failed to write elf header.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping,
+ int phdr_index, target_phys_addr_t offset)
+{
+ Elf64_Phdr phdr;
+ int ret;
+ int endian = s->dump_info.d_endian;
+
+ memset(&phdr, 0, sizeof(Elf64_Phdr));
+ phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
+ phdr.p_offset = cpu_convert_to_target64(offset, endian);
+ phdr.p_paddr = cpu_convert_to_target64(memory_mapping->phys_addr, endian);
+ if (offset == -1) {
+ /* When the memory is not stored into vmcore, offset will be -1 */
+ phdr.p_filesz = 0;
+ } else {
+ phdr.p_filesz = cpu_convert_to_target64(memory_mapping->length, endian);
+ }
+ phdr.p_memsz = cpu_convert_to_target64(memory_mapping->length, endian);
+ phdr.p_vaddr = cpu_convert_to_target64(memory_mapping->virt_addr, endian);
+
+ ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s);
+ if (ret < 0) {
+ dump_error(s, "dump: failed to write program header table.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping,
+ int phdr_index, target_phys_addr_t offset)
+{
+ Elf32_Phdr phdr;
+ int ret;
+ int endian = s->dump_info.d_endian;
+
+ memset(&phdr, 0, sizeof(Elf32_Phdr));
+ phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
+ phdr.p_offset = cpu_convert_to_target32(offset, endian);
+ phdr.p_paddr = cpu_convert_to_target32(memory_mapping->phys_addr, endian);
+ if (offset == -1) {
+ /* When the memory is not stored into vmcore, offset will be -1 */
+ phdr.p_filesz = 0;
+ } else {
+ phdr.p_filesz = cpu_convert_to_target32(memory_mapping->length, endian);
+ }
+ phdr.p_memsz = cpu_convert_to_target32(memory_mapping->length, endian);
+ phdr.p_vaddr = cpu_convert_to_target32(memory_mapping->virt_addr, endian);
+
+ ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
+ if (ret < 0) {
+ dump_error(s, "dump: failed to write program header table.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int write_elf64_note(DumpState *s)
+{
+ Elf64_Phdr phdr;
+ int endian = s->dump_info.d_endian;
+ target_phys_addr_t begin = s->memory_offset - s->note_size;
+ int ret;
+
+ memset(&phdr, 0, sizeof(Elf64_Phdr));
+ phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian);
+ phdr.p_offset = cpu_convert_to_target64(begin, endian);
+ phdr.p_paddr = 0;
+ phdr.p_filesz = cpu_convert_to_target64(s->note_size, endian);
+ phdr.p_memsz = cpu_convert_to_target64(s->note_size, endian);
+ phdr.p_vaddr = 0;
+
+ ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s);
+ if (ret < 0) {
+ dump_error(s, "dump: failed to write program header table.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int write_elf64_notes(DumpState *s)
+{
+ CPUArchState *env;
+ int ret;
+ int id;
+
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ id = cpu_index(env);
+ ret = cpu_write_elf64_note(fd_write_vmcore, env, id, s);
+ if (ret < 0) {
+ dump_error(s, "dump: failed to write elf notes.\n");
+ return -1;
+ }
+ }
+
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ ret = cpu_write_elf64_qemunote(fd_write_vmcore, env, s);
+ if (ret < 0) {
+ dump_error(s, "dump: failed to write CPU status.\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int write_elf32_note(DumpState *s)
+{
+ target_phys_addr_t begin = s->memory_offset - s->note_size;
+ Elf32_Phdr phdr;
+ int endian = s->dump_info.d_endian;
+ int ret;
+
+ memset(&phdr, 0, sizeof(Elf32_Phdr));
+ phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian);
+ phdr.p_offset = cpu_convert_to_target32(begin, endian);
+ phdr.p_paddr = 0;
+ phdr.p_filesz = cpu_convert_to_target32(s->note_size, endian);
+ phdr.p_memsz = cpu_convert_to_target32(s->note_size, endian);
+ phdr.p_vaddr = 0;
+
+ ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
+ if (ret < 0) {
+ dump_error(s, "dump: failed to write program header table.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int write_elf32_notes(DumpState *s)
+{
+ CPUArchState *env;
+ int ret;
+ int id;
+
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ id = cpu_index(env);
+ ret = cpu_write_elf32_note(fd_write_vmcore, env, id, s);
+ if (ret < 0) {
+ dump_error(s, "dump: failed to write elf notes.\n");
+ return -1;
+ }
+ }
+
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ ret = cpu_write_elf32_qemunote(fd_write_vmcore, env, s);
+ if (ret < 0) {
+ dump_error(s, "dump: failed to write CPU status.\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int write_elf_section(DumpState *s, int type)
+{
+ Elf32_Shdr shdr32;
+ Elf64_Shdr shdr64;
+ int endian = s->dump_info.d_endian;
+ int shdr_size;
+ void *shdr;
+ int ret;
+
+ if (type == 0) {
+ shdr_size = sizeof(Elf32_Shdr);
+ memset(&shdr32, 0, shdr_size);
+ shdr32.sh_info = cpu_convert_to_target32(s->sh_info, endian);
+ shdr = &shdr32;
+ } else {
+ shdr_size = sizeof(Elf64_Shdr);
+ memset(&shdr64, 0, shdr_size);
+ shdr64.sh_info = cpu_convert_to_target32(s->sh_info, endian);
+ shdr = &shdr64;
+ }
+
+ ret = fd_write_vmcore(&shdr, shdr_size, s);
+ if (ret < 0) {
+ dump_error(s, "dump: failed to write section header table.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int write_data(DumpState *s, void *buf, int length)
+{
+ int ret;
+
+ ret = fd_write_vmcore(buf, length, s);
+ if (ret < 0) {
+ dump_error(s, "dump: failed to save memory.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* write the memroy to vmcore. 1 page per I/O. */
+static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
+ int64_t size)
+{
+ int64_t i;
+ int ret;
+
+ for (i = 0; i < size / TARGET_PAGE_SIZE; i++) {
+ ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
+ TARGET_PAGE_SIZE);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ if ((size % TARGET_PAGE_SIZE) != 0) {
+ ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
+ size % TARGET_PAGE_SIZE);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/* get the memory's offset in the vmcore */
+static target_phys_addr_t get_offset(target_phys_addr_t phys_addr,
+ DumpState *s)
+{
+ RAMBlock *block;
+ target_phys_addr_t offset = s->memory_offset;
+ int64_t size_in_block, start;
+
+ if (s->has_filter) {
+ if (phys_addr < s->begin || phys_addr >= s->begin + s->length) {
+ return -1;
+ }
+ }
+
+ QLIST_FOREACH(block, &ram_list.blocks, next) {
+ if (s->has_filter) {
+ if (block->offset >= s->begin + s->length ||
+ block->offset + block->length <= s->begin) {
+ /* This block is out of the range */
+ continue;
+ }
+
+ if (s->begin <= block->offset) {
+ start = block->offset;
+ } else {
+ start = s->begin;
+ }
+
+ size_in_block = block->length - (start - block->offset);
+ if (s->begin + s->length < block->offset + block->length) {
+ size_in_block -= block->offset + block->length -
+ (s->begin + s->length);
+ }
+ } else {
+ start = block->offset;
+ size_in_block = block->length;
+ }
+
+ if (phys_addr >= start && phys_addr < start + size_in_block) {
+ return phys_addr - start + offset;
+ }
+
+ offset += size_in_block;
+ }
+
+ return -1;
+}
+
+static int write_elf_loads(DumpState *s)
+{
+ target_phys_addr_t offset;
+ MemoryMapping *memory_mapping;
+ uint32_t phdr_index = 1;
+ int ret;
+ uint32_t max_index;
+
+ if (s->have_section) {
+ max_index = s->sh_info;
+ } else {
+ max_index = s->phdr_num;
+ }
+
+ QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
+ offset = get_offset(memory_mapping->phys_addr, s);
+ if (s->dump_info.d_class == ELFCLASS64) {
+ ret = write_elf64_load(s, memory_mapping, phdr_index++, offset);
+ } else {
+ ret = write_elf32_load(s, memory_mapping, phdr_index++, offset);
+ }
+
+ if (ret < 0) {
+ return -1;
+ }
+
+ if (phdr_index >= max_index) {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* write elf header, PT_NOTE and elf note to vmcore. */
+static int dump_begin(DumpState *s)
+{
+ int ret;
+
+ /*
+ * the vmcore's format is:
+ * --------------
+ * | elf header |
+ * --------------
+ * | PT_NOTE |
+ * --------------
+ * | PT_LOAD |
+ * --------------
+ * | ...... |
+ * --------------
+ * | PT_LOAD |
+ * --------------
+ * | sec_hdr |
+ * --------------
+ * | elf note |
+ * --------------
+ * | memory |
+ * --------------
+ *
+ * we only know where the memory is saved after we write elf note into
+ * vmcore.
+ */
+
+ /* write elf header to vmcore */
+ if (s->dump_info.d_class == ELFCLASS64) {
+ ret = write_elf64_header(s);
+ } else {
+ ret = write_elf32_header(s);
+ }
+ if (ret < 0) {
+ return -1;
+ }
+
+ if (s->dump_info.d_class == ELFCLASS64) {
+ /* write PT_NOTE to vmcore */
+ if (write_elf64_note(s) < 0) {
+ return -1;
+ }
+
+ /* write all PT_LOAD to vmcore */
+ if (write_elf_loads(s) < 0) {
+ return -1;
+ }
+
+ /* write section to vmcore */
+ if (s->have_section) {
+ if (write_elf_section(s, 1) < 0) {
+ return -1;
+ }
+ }
+
+ /* write notes to vmcore */
+ if (write_elf64_notes(s) < 0) {
+ return -1;
+ }
+
+ } else {
+ /* write PT_NOTE to vmcore */
+ if (write_elf32_note(s) < 0) {
+ return -1;
+ }
+
+ /* write all PT_LOAD to vmcore */
+ if (write_elf_loads(s) < 0) {
+ return -1;
+ }
+
+ /* write section to vmcore */
+ if (s->have_section) {
+ if (write_elf_section(s, 0) < 0) {
+ return -1;
+ }
+ }
+
+ /* write notes to vmcore */
+ if (write_elf32_notes(s) < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* write PT_LOAD to vmcore */
+static int dump_completed(DumpState *s)
+{
+ dump_cleanup(s);
+ return 0;
+}
+
+static int get_next_block(DumpState *s, RAMBlock *block)
+{
+ while (1) {
+ block = QLIST_NEXT(block, next);
+ if (!block) {
+ /* no more block */
+ return 1;
+ }
+
+ s->start = 0;
+ s->block = block;
+ if (s->has_filter) {
+ if (block->offset >= s->begin + s->length ||
+ block->offset + block->length <= s->begin) {
+ /* This block is out of the range */
+ continue;
+ }
+
+ if (s->begin > block->offset) {
+ s->start = s->begin - block->offset;
+ }
+ }
+
+ return 0;
+ }
+}
+
+/* write all memory to vmcore */
+static int dump_iterate(DumpState *s)
+{
+ RAMBlock *block;
+ int64_t size;
+ int ret;
+
+ while (1) {
+ block = s->block;
+
+ size = block->length;
+ if (s->has_filter) {
+ size -= s->start;
+ if (s->begin + s->length < block->offset + block->length) {
+ size -= block->offset + block->length - (s->begin + s->length);
+ }
+ }
+ ret = write_memory(s, block, s->start, size);
+ if (ret == -1) {
+ return ret;
+ }
+
+ ret = get_next_block(s, block);
+ if (ret == 1) {
+ dump_completed(s);
+ return 0;
+ }
+ }
+}
+
+static int create_vmcore(DumpState *s)
+{
+ int ret;
+
+ ret = dump_begin(s);
+ if (ret < 0) {
+ return -1;
+ }
+
+ ret = dump_iterate(s);
+ if (ret < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static ram_addr_t get_start_block(DumpState *s)
+{
+ RAMBlock *block;
+
+ if (!s->has_filter) {
+ s->block = QLIST_FIRST(&ram_list.blocks);
+ return 0;
+ }
+
+ QLIST_FOREACH(block, &ram_list.blocks, next) {
+ if (block->offset >= s->begin + s->length ||
+ block->offset + block->length <= s->begin) {
+ /* This block is out of the range */
+ continue;
+ }
+
+ s->block = block;
+ if (s->begin > block->offset) {
+ s->start = s->begin - block->offset;
+ } else {
+ s->start = 0;
+ }
+ return s->start;
+ }
+
+ return -1;
+}
+
+static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
+ int64_t begin, int64_t length, Error **errp)
+{
+ CPUArchState *env;
+ int nr_cpus;
+ int ret;
+
+ if (runstate_is_running()) {
+ vm_stop(RUN_STATE_SAVE_VM);
+ s->resume = true;
+ } else {
+ s->resume = false;
+ }
+
+ s->errp = errp;
+ s->fd = fd;
+ s->has_filter = has_filter;
+ s->begin = begin;
+ s->length = length;
+ s->start = get_start_block(s);
+ if (s->start == -1) {
+ error_set(errp, QERR_INVALID_PARAMETER, "begin");
+ goto cleanup;
+ }
+
+ /*
+ * get dump info: endian, class and architecture.
+ * If the target architecture is not supported, cpu_get_dump_info() will
+ * return -1.
+ *
+ * if we use kvm, we should synchronize the register before we get dump
+ * info.
+ */
+ nr_cpus = 0;
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ cpu_synchronize_state(env);
+ nr_cpus++;
+ }
+
+ ret = cpu_get_dump_info(&s->dump_info);
+ if (ret < 0) {
+ error_set(errp, QERR_UNSUPPORTED);
+ goto cleanup;
+ }
+
+ s->note_size = cpu_get_note_size(s->dump_info.d_class,
+ s->dump_info.d_machine, nr_cpus);
+ if (ret < 0) {
+ error_set(errp, QERR_UNSUPPORTED);
+ goto cleanup;
+ }
+
+ /* get memory mapping */
+ memory_mapping_list_init(&s->list);
+ if (paging) {
+ qemu_get_guest_memory_mapping(&s->list);
+ } else {
+ qemu_get_guest_simple_memory_mapping(&s->list);
+ }
+
+ if (s->has_filter) {
+ memory_mapping_filter(&s->list, s->begin, s->length);
+ }
+
+ /*
+ * calculate phdr_num
+ *
+ * the type of ehdr->e_phnum is uint16_t, so we should avoid overflow
+ */
+ s->phdr_num = 1; /* PT_NOTE */
+ if (s->list.num < UINT16_MAX - 2) {
+ s->phdr_num += s->list.num;
+ s->have_section = false;
+ } else {
+ s->have_section = true;
+ s->phdr_num = PN_XNUM;
+ s->sh_info = 1; /* PT_NOTE */
+
+ /* the type of shdr->sh_info is uint32_t, so we should avoid overflow */
+ if (s->list.num <= UINT32_MAX - 1) {
+ s->sh_info += s->list.num;
+ } else {
+ s->sh_info = UINT32_MAX;
+ }
+ }
+
+ if (s->dump_info.d_class == ELFCLASS64) {
+ if (s->have_section) {
+ s->memory_offset = sizeof(Elf64_Ehdr) +
+ sizeof(Elf64_Phdr) * s->sh_info +
+ sizeof(Elf64_Shdr) + s->note_size;
+ } else {
+ s->memory_offset = sizeof(Elf64_Ehdr) +
+ sizeof(Elf64_Phdr) * s->phdr_num + s->note_size;
+ }
+ } else {
+ if (s->have_section) {
+ s->memory_offset = sizeof(Elf32_Ehdr) +
+ sizeof(Elf32_Phdr) * s->sh_info +
+ sizeof(Elf32_Shdr) + s->note_size;
+ } else {
+ s->memory_offset = sizeof(Elf32_Ehdr) +
+ sizeof(Elf32_Phdr) * s->phdr_num + s->note_size;
+ }
+ }
+
+ return 0;
+
+cleanup:
+ if (s->resume) {
+ vm_start();
+ }
+
+ return -1;
+}
+
+void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
+ int64_t begin, bool has_length, int64_t length,
+ Error **errp)
+{
+ const char *p;
+ int fd = -1;
+ DumpState *s;
+ int ret;
+
+ if (has_begin && !has_length) {
+ error_set(errp, QERR_MISSING_PARAMETER, "length");
+ return;
+ }
+ if (!has_begin && has_length) {
+ error_set(errp, QERR_MISSING_PARAMETER, "begin");
+ return;
+ }
+
+#if !defined(WIN32)
+ if (strstart(file, "fd:", &p)) {
+ fd = monitor_get_fd(cur_mon, p);
+ if (fd == -1) {
+ error_set(errp, QERR_FD_NOT_FOUND, p);
+ return;
+ }
+ }
+#endif
+
+ if (strstart(file, "file:", &p)) {
+ fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR);
+ if (fd < 0) {
+ error_set(errp, QERR_OPEN_FILE_FAILED, p);
+ return;
+ }
+ }
+
+ if (fd == -1) {
+ error_set(errp, QERR_INVALID_PARAMETER, "protocol");
+ return;
+ }
+
+ s = g_malloc(sizeof(DumpState));
+
+ ret = dump_init(s, fd, paging, has_begin, begin, length, errp);
+ if (ret < 0) {
+ g_free(s);
+ return;
+ }
+
+ if (create_vmcore(s) < 0 && !error_is_set(s->errp)) {
+ error_set(errp, QERR_IO_ERROR);
+ }
+
+ g_free(s);
+}
diff --git a/dump.h b/dump.h
new file mode 100644
index 0000000000..e25b7cfb73
--- /dev/null
+++ b/dump.h
@@ -0,0 +1,35 @@
+/*
+ * QEMU dump
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ * Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef DUMP_H
+#define DUMP_H
+
+typedef struct ArchDumpInfo {
+ int d_machine; /* Architecture */
+ int d_endian; /* ELFDATA2LSB or ELFDATA2MSB */
+ int d_class; /* ELFCLASS32 or ELFCLASS64 */
+} ArchDumpInfo;
+
+typedef int (*write_core_dump_function)(void *buf, size_t size, void *opaque);
+int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+ int cpuid, void *opaque);
+int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
+ int cpuid, void *opaque);
+int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
+ void *opaque);
+int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
+ void *opaque);
+int cpu_get_dump_info(ArchDumpInfo *info);
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
+
+#endif
diff --git a/elf.h b/elf.h
index e1422b81ee..9c9acfaf75 100644
--- a/elf.h
+++ b/elf.h
@@ -1037,6 +1037,11 @@ typedef struct elf64_sym {
#define EI_NIDENT 16
+/* Special value for e_phnum. This indicates that the real number of
+ program headers is too large to fit into e_phnum. Instead the real
+ value is in the field sh_info of section 0. */
+#define PN_XNUM 0xffff
+
typedef struct elf32_hdr{
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
diff --git a/exec.c b/exec.c
index a0494c72bf..5c9b7627bf 100644
--- a/exec.c
+++ b/exec.c
@@ -1076,11 +1076,11 @@ TranslationBlock *tb_gen_code(CPUArchState *env,
}
/*
- * invalidate all TBs which intersect with the target physical pages
- * starting in range [start;end[. NOTE: start and end may refer to
- * different physical pages. 'is_cpu_write_access' should be true if called
- * from a real cpu write access: the virtual CPU will exit the current
- * TB if code is modified inside this TB.
+ * Invalidate all TBs which intersect with the target physical address range
+ * [start;end[. NOTE: start and end may refer to *different* physical pages.
+ * 'is_cpu_write_access' should be true if called from a real cpu write
+ * access: the virtual CPU will exit the current TB if code is modified inside
+ * this TB.
*/
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end,
int is_cpu_write_access)
@@ -1092,11 +1092,13 @@ void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end,
}
}
-/* invalidate all TBs which intersect with the target physical page
- starting in range [start;end[. NOTE: start and end must refer to
- the same physical page. 'is_cpu_write_access' should be true if called
- from a real cpu write access: the virtual CPU will exit the current
- TB if code is modified inside this TB. */
+/*
+ * Invalidate all TBs which intersect with the target physical address range
+ * [start;end[. NOTE: start and end must refer to the *same* physical page.
+ * 'is_cpu_write_access' should be true if called from a real cpu write
+ * access: the virtual CPU will exit the current TB if code is modified inside
+ * this TB.
+ */
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
int is_cpu_write_access)
{
@@ -1492,7 +1494,8 @@ void tb_invalidate_phys_addr(target_phys_addr_t addr)
static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
{
- tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc));
+ tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc) |
+ (pc & ~TARGET_PAGE_MASK));
}
#endif
#endif /* TARGET_HAS_ICE */
@@ -4336,3 +4339,15 @@ bool virtio_is_big_endian(void)
}
#endif
+
+#ifndef CONFIG_USER_ONLY
+bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr)
+{
+ MemoryRegionSection *section;
+
+ section = phys_page_find(phys_addr >> TARGET_PAGE_BITS);
+
+ return !(memory_region_is_ram(section->mr) ||
+ memory_region_is_romd(section->mr));
+}
+#endif
diff --git a/fsdev/Makefile.objs b/fsdev/Makefile.objs
new file mode 100644
index 0000000000..cb1e2500b9
--- /dev/null
+++ b/fsdev/Makefile.objs
@@ -0,0 +1,9 @@
+ifeq ($(CONFIG_REALLY_VIRTFS),y)
+common-obj-y = qemu-fsdev.o virtio-9p-marshal.o
+
+# Toplevel always builds this; targets without virtio will put it in
+# common-obj-y
+extra-obj-y = qemu-fsdev-dummy.o
+else
+common-obj-y = qemu-fsdev-dummy.o
+endif
diff --git a/gdbstub.c b/gdbstub.c
index 6a77a6696b..08cf8645d7 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1937,21 +1937,12 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
#endif
}
-static inline int gdb_id(CPUArchState *env)
-{
-#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL)
- return env->host_tid;
-#else
- return env->cpu_index + 1;
-#endif
-}
-
static CPUArchState *find_cpu(uint32_t thread_id)
{
CPUArchState *env;
for (env = first_cpu; env != NULL; env = env->next_cpu) {
- if (gdb_id(env) == thread_id) {
+ if (cpu_index(env) == thread_id) {
return env;
}
}
@@ -1979,7 +1970,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
case '?':
/* TODO: Make this return the correct value for user-mode. */
snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP,
- gdb_id(s->c_cpu));
+ cpu_index(s->c_cpu));
put_packet(s, buf);
/* Remove all the breakpoints when this query is issued,
* because gdb is doing and initial connect and the state
@@ -2274,7 +2265,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
} else if (strcmp(p,"sThreadInfo") == 0) {
report_cpuinfo:
if (s->query_cpu) {
- snprintf(buf, sizeof(buf), "m%x", gdb_id(s->query_cpu));
+ snprintf(buf, sizeof(buf), "m%x", cpu_index(s->query_cpu));
put_packet(s, buf);
s->query_cpu = s->query_cpu->next_cpu;
} else
@@ -2422,7 +2413,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
}
snprintf(buf, sizeof(buf),
"T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
- GDB_SIGNAL_TRAP, gdb_id(env), type,
+ GDB_SIGNAL_TRAP, cpu_index(env), type,
env->watchpoint_hit->vaddr);
env->watchpoint_hit = NULL;
goto send_packet;
@@ -2455,7 +2446,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
ret = GDB_SIGNAL_UNKNOWN;
break;
}
- snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, gdb_id(env));
+ snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(env));
send_packet:
put_packet(s, buf);
diff --git a/gdbstub.h b/gdbstub.h
index b44e27523a..668de66000 100644
--- a/gdbstub.h
+++ b/gdbstub.h
@@ -30,6 +30,15 @@ void gdb_register_coprocessor(CPUArchState *env,
gdb_reg_cb get_reg, gdb_reg_cb set_reg,
int num_regs, const char *xml, int g_pos);
+static inline int cpu_index(CPUArchState *env)
+{
+#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL)
+ return env->host_tid;
+#else
+ return env->cpu_index + 1;
+#endif
+}
+
#endif
#ifdef CONFIG_USER_ONLY
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 18cb415ac4..f5d9d91de8 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -878,6 +878,34 @@ server will ask the spice/vnc client to automatically reconnect using the
new parameters (if specified) once the vm migration finished successfully.
ETEXI
+#if defined(CONFIG_HAVE_CORE_DUMP)
+ {
+ .name = "dump-guest-memory",
+ .args_type = "paging:-p,protocol:s,begin:i?,length:i?",
+ .params = "[-p] protocol [begin] [length]",
+ .help = "dump guest memory to file"
+ "\n\t\t\t begin(optional): the starting physical address"
+ "\n\t\t\t length(optional): the memory size, in bytes",
+ .user_print = monitor_user_noop,
+ .mhandler.cmd = hmp_dump_guest_memory,
+ },
+
+
+STEXI
+@item dump-guest-memory [-p] @var{protocol} @var{begin} @var{length}
+@findex dump-guest-memory
+Dump guest memory to @var{protocol}. The file can be processed with crash or
+gdb.
+ protocol: destination file(started with "file:") or destination file
+ descriptor (started with "fd:")
+ paging: do paging to get guest's memory mapping
+ begin: the starting physical address. It's optional, and should be
+ specified with length together.
+ length: the memory size, in bytes. It's optional, and should be specified
+ with begin together.
+ETEXI
+#endif
+
{
.name = "snapshot_blkdev",
.args_type = "reuse:-n,device:B,snapshot-file:s?,format:s?",
@@ -1009,8 +1037,7 @@ ETEXI
.args_type = "netdev:O",
.params = "[user|tap|socket],id=str[,prop=value][,...]",
.help = "add host network device",
- .user_print = monitor_user_noop,
- .mhandler.cmd_new = do_netdev_add,
+ .mhandler.cmd = hmp_netdev_add,
},
STEXI
@@ -1024,8 +1051,7 @@ ETEXI
.args_type = "id:s",
.params = "id",
.help = "remove host network device",
- .user_print = monitor_user_noop,
- .mhandler.cmd_new = do_netdev_del,
+ .mhandler.cmd = hmp_netdev_del,
},
STEXI
diff --git a/hmp.c b/hmp.c
index bb0952e00b..2ce8cb9df1 100644
--- a/hmp.c
+++ b/hmp.c
@@ -14,6 +14,8 @@
*/
#include "hmp.h"
+#include "net.h"
+#include "qemu-option.h"
#include "qemu-timer.h"
#include "qmp-commands.h"
@@ -947,3 +949,53 @@ void hmp_device_del(Monitor *mon, const QDict *qdict)
qmp_device_del(id, &err);
hmp_handle_error(mon, &err);
}
+
+void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
+{
+ Error *errp = NULL;
+ int paging = qdict_get_try_bool(qdict, "paging", 0);
+ const char *file = qdict_get_str(qdict, "protocol");
+ bool has_begin = qdict_haskey(qdict, "begin");
+ bool has_length = qdict_haskey(qdict, "length");
+ int64_t begin = 0;
+ int64_t length = 0;
+
+ if (has_begin) {
+ begin = qdict_get_int(qdict, "begin");
+ }
+ if (has_length) {
+ length = qdict_get_int(qdict, "length");
+ }
+
+ qmp_dump_guest_memory(paging, file, has_begin, begin, has_length, length,
+ &errp);
+ hmp_handle_error(mon, &errp);
+}
+
+void hmp_netdev_add(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ QemuOpts *opts;
+
+ opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err);
+ if (error_is_set(&err)) {
+ goto out;
+ }
+
+ netdev_add(opts, &err);
+ if (error_is_set(&err)) {
+ qemu_opts_del(opts);
+ }
+
+out:
+ hmp_handle_error(mon, &err);
+}
+
+void hmp_netdev_del(Monitor *mon, const QDict *qdict)
+{
+ const char *id = qdict_get_str(qdict, "id");
+ Error *err = NULL;
+
+ qmp_netdev_del(id, &err);
+ hmp_handle_error(mon, &err);
+}
diff --git a/hmp.h b/hmp.h
index 443b812923..79d138d3ee 100644
--- a/hmp.h
+++ b/hmp.h
@@ -61,5 +61,8 @@ void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict);
void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
void hmp_migrate(Monitor *mon, const QDict *qdict);
void hmp_device_del(Monitor *mon, const QDict *qdict);
+void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
+void hmp_netdev_add(Monitor *mon, const QDict *qdict);
+void hmp_netdev_del(Monitor *mon, const QDict *qdict);
#endif
diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs
new file mode 100644
index 0000000000..972df24050
--- /dev/null
+++ b/hw/9pfs/Makefile.objs
@@ -0,0 +1,9 @@
+hw-obj-y = virtio-9p.o
+hw-obj-y += virtio-9p-local.o virtio-9p-xattr.o
+hw-obj-y += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
+hw-obj-y += virtio-9p-coth.o cofs.o codir.o cofile.o
+hw-obj-y += coxattr.o virtio-9p-synth.o
+hw-obj-$(CONFIG_OPEN_BY_HANDLE) += virtio-9p-handle.o
+hw-obj-y += virtio-9p-proxy.o
+
+obj-y += virtio-9p-device.o
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
new file mode 100644
index 0000000000..3d7725934f
--- /dev/null
+++ b/hw/Makefile.objs
@@ -0,0 +1,172 @@
+hw-obj-y = usb/ ide/
+hw-obj-y += loader.o
+hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
+hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
+hw-obj-y += fw_cfg.o
+hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o
+hw-obj-$(CONFIG_PCI) += msix.o msi.o
+hw-obj-$(CONFIG_PCI) += shpc.o
+hw-obj-$(CONFIG_PCI) += slotid_cap.o
+hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
+hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
+hw-obj-y += watchdog.o
+hw-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
+hw-obj-$(CONFIG_ECC) += ecc.o
+hw-obj-$(CONFIG_NAND) += nand.o
+hw-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
+hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
+
+hw-obj-$(CONFIG_M48T59) += m48t59.o
+hw-obj-$(CONFIG_ESCC) += escc.o
+hw-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
+
+hw-obj-$(CONFIG_SERIAL) += serial.o
+hw-obj-$(CONFIG_PARALLEL) += parallel.o
+hw-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
+hw-obj-$(CONFIG_PCSPK) += pcspk.o
+hw-obj-$(CONFIG_PCKBD) += pckbd.o
+hw-obj-$(CONFIG_FDC) += fdc.o
+hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
+hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
+hw-obj-$(CONFIG_DMA) += dma.o
+hw-obj-$(CONFIG_I82374) += i82374.o
+hw-obj-$(CONFIG_HPET) += hpet.o
+hw-obj-$(CONFIG_APPLESMC) += applesmc.o
+hw-obj-$(CONFIG_SMARTCARD) += ccid-card-passthru.o
+hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
+hw-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
+
+# PPC devices
+hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
+hw-obj-$(CONFIG_I82378) += i82378.o
+# Mac shared devices
+hw-obj-$(CONFIG_MACIO) += macio.o
+hw-obj-$(CONFIG_CUDA) += cuda.o
+hw-obj-$(CONFIG_ADB) += adb.o
+hw-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
+hw-obj-$(CONFIG_MAC_DBDMA) += mac_dbdma.o
+# OldWorld PowerMac
+hw-obj-$(CONFIG_HEATHROW_PIC) += heathrow_pic.o
+hw-obj-$(CONFIG_GRACKLE_PCI) += grackle_pci.o
+# NewWorld PowerMac
+hw-obj-$(CONFIG_UNIN_PCI) += unin_pci.o
+hw-obj-$(CONFIG_DEC_PCI) += dec_pci.o
+# PowerPC E500 boards
+hw-obj-$(CONFIG_PPCE500_PCI) += ppce500_pci.o
+
+# MIPS devices
+hw-obj-$(CONFIG_PIIX4) += piix4.o
+hw-obj-$(CONFIG_G364FB) += g364fb.o
+hw-obj-$(CONFIG_JAZZ_LED) += jazz_led.o
+
+# Xilinx devices
+hw-obj-$(CONFIG_XILINX) += xilinx_intc.o
+hw-obj-$(CONFIG_XILINX) += xilinx_timer.o
+hw-obj-$(CONFIG_XILINX) += xilinx_uartlite.o
+hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o
+hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o
+
+# PCI watchdog devices
+hw-obj-$(CONFIG_PCI) += wdt_i6300esb.o
+
+hw-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
+
+# PCI network cards
+hw-obj-$(CONFIG_NE2000_PCI) += ne2000.o
+hw-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o
+hw-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
+hw-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
+hw-obj-$(CONFIG_E1000_PCI) += e1000.o
+hw-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
+
+hw-obj-$(CONFIG_SMC91C111) += smc91c111.o
+hw-obj-$(CONFIG_LAN9118) += lan9118.o
+hw-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o
+hw-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o
+
+# SCSI layer
+hw-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o
+hw-obj-$(CONFIG_ESP) += esp.o
+
+hw-obj-y += sysbus.o isa-bus.o
+hw-obj-y += qdev-addr.o
+
+# VGA
+hw-obj-$(CONFIG_VGA_PCI) += vga-pci.o
+hw-obj-$(CONFIG_VGA_ISA) += vga-isa.o
+hw-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o
+hw-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o
+hw-obj-$(CONFIG_VMMOUSE) += vmmouse.o
+hw-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o
+
+hw-obj-$(CONFIG_RC4030) += rc4030.o
+hw-obj-$(CONFIG_DP8393X) += dp8393x.o
+hw-obj-$(CONFIG_DS1225Y) += ds1225y.o
+hw-obj-$(CONFIG_MIPSNET) += mipsnet.o
+
+# Sound
+sound-obj-y =
+sound-obj-$(CONFIG_SB16) += sb16.o
+sound-obj-$(CONFIG_ES1370) += es1370.o
+sound-obj-$(CONFIG_AC97) += ac97.o
+sound-obj-$(CONFIG_ADLIB) += fmopl.o adlib.o
+sound-obj-$(CONFIG_GUS) += gus.o gusemu_hal.o gusemu_mixer.o
+sound-obj-$(CONFIG_CS4231A) += cs4231a.o
+sound-obj-$(CONFIG_HDA) += intel-hda.o hda-audio.o
+
+$(obj)/adlib.o $(obj)/fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
+
+hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
+
+hw-obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
+
+common-obj-y += usb/
+common-obj-y += irq.o
+common-obj-$(CONFIG_PTIMER) += ptimer.o
+common-obj-$(CONFIG_MAX7310) += max7310.o
+common-obj-$(CONFIG_WM8750) += wm8750.o
+common-obj-$(CONFIG_TWL92230) += twl92230.o
+common-obj-$(CONFIG_TSC2005) += tsc2005.o
+common-obj-$(CONFIG_LM832X) += lm832x.o
+common-obj-$(CONFIG_TMP105) += tmp105.o
+common-obj-$(CONFIG_STELLARIS_INPUT) += stellaris_input.o
+common-obj-$(CONFIG_SSD0303) += ssd0303.o
+common-obj-$(CONFIG_SSD0323) += ssd0323.o
+common-obj-$(CONFIG_ADS7846) += ads7846.o
+common-obj-$(CONFIG_MAX111X) += max111x.o
+common-obj-$(CONFIG_DS1338) += ds1338.o
+common-obj-y += i2c.o smbus.o smbus_eeprom.o
+common-obj-y += eeprom93xx.o
+common-obj-y += scsi-disk.o cdrom.o
+common-obj-y += scsi-generic.o scsi-bus.o
+common-obj-y += hid.o
+common-obj-$(CONFIG_SSI) += ssi.o
+common-obj-$(CONFIG_SSI_SD) += ssi-sd.o
+common-obj-$(CONFIG_SD) += sd.o
+common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
+common-obj-y += bt-hci-csr.o
+common-obj-y += msmouse.o ps2.o
+common-obj-y += qdev.o qdev-properties.o qdev-monitor.o
+common-obj-$(CONFIG_BRLAPI) += baum.o
+
+# xen backend driver support
+common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
+common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o xenfb.o xen_disk.o xen_nic.o
+
+# Per-target files
+# virtio has to be here due to weird dependency between PCI and virtio-net.
+# need to fix this properly
+obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o
+obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o virtio-scsi.o
+obj-$(CONFIG_SOFTMMU) += vhost_net.o
+obj-$(CONFIG_VHOST_NET) += vhost.o
+obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
+obj-$(CONFIG_NO_PCI) += pci-stub.o
+obj-$(CONFIG_VGA) += vga.o
+obj-$(CONFIG_SOFTMMU) += device-hotplug.o
+obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
+
+# Inter-VM PCI shared memory
+ifeq ($(CONFIG_PCI), y)
+obj-$(CONFIG_KVM) += ivshmem.o
+endif
diff --git a/hw/alpha/Makefile.objs b/hw/alpha/Makefile.objs
new file mode 100644
index 0000000000..af1c07fa7c
--- /dev/null
+++ b/hw/alpha/Makefile.objs
@@ -0,0 +1,4 @@
+obj-y = mc146818rtc.o
+obj-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index 2f46e214cf..1d51570c88 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -16,7 +16,7 @@
/* The CPU is also modeled as an interrupt controller. */
#define ARM_PIC_CPU_IRQ 0
#define ARM_PIC_CPU_FIQ 1
-qemu_irq *arm_pic_init_cpu(CPUARMState *env);
+qemu_irq *arm_pic_init_cpu(ARMCPU *cpu);
/* armv7m.c */
qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
@@ -50,16 +50,16 @@ struct arm_boot_info {
* perform any necessary CPU reset handling and set the PC for thei
* secondary CPUs to point at this boot blob.
*/
- void (*write_secondary_boot)(CPUARMState *env,
+ void (*write_secondary_boot)(ARMCPU *cpu,
const struct arm_boot_info *info);
- void (*secondary_cpu_reset_hook)(CPUARMState *env,
+ void (*secondary_cpu_reset_hook)(ARMCPU *cpu,
const struct arm_boot_info *info);
/* Used internally by arm_boot.c */
int is_linux;
target_phys_addr_t initrd_size;
target_phys_addr_t entry;
};
-void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info);
+void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info);
/* Multiplication factor to convert from system clock ticks to qemu timer
ticks. */
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
new file mode 100644
index 0000000000..a0ff6a62d6
--- /dev/null
+++ b/hw/arm/Makefile.objs
@@ -0,0 +1,40 @@
+obj-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
+obj-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
+obj-y += versatile_pci.o
+obj-y += versatile_i2c.o
+obj-y += cadence_uart.o
+obj-y += cadence_ttc.o
+obj-y += cadence_gem.o
+obj-y += xilinx_zynq.o zynq_slcr.o
+obj-y += arm_gic.o
+obj-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
+obj-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
+obj-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
+obj-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o
+obj-y += arm_l2x0.o
+obj-y += arm_mptimer.o a15mpcore.o
+obj-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
+obj-y += highbank.o
+obj-y += pl061.o
+obj-y += xgmac.o
+obj-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
+obj-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
+obj-y += gumstix.o
+obj-y += zaurus.o ide/microdrive.o spitz.o tosa.o tc6393xb.o
+obj-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
+ omap_gpio.o omap_intc.o omap_uart.o
+obj-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
+ omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
+obj-y += omap_sx1.o palm.o tsc210x.o
+obj-y += nseries.o blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
+obj-y += mst_fpga.o mainstone.o
+obj-y += z2.o
+obj-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
+obj-y += framebuffer.o
+obj-y += vexpress.o
+obj-y += strongarm.o
+obj-y += collie.o
+obj-y += pl041.o lm4549.o
+obj-$(CONFIG_FDT) += ../device_tree.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 7447f5c169..d0e643ba11 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -59,7 +59,7 @@ static uint32_t smpboot[] = {
0 /* bootreg: Boot register address is held here */
};
-static void default_write_secondary(CPUARMState *env,
+static void default_write_secondary(ARMCPU *cpu,
const struct arm_boot_info *info)
{
int n;
@@ -72,9 +72,11 @@ static void default_write_secondary(CPUARMState *env,
info->smp_loader_start);
}
-static void default_reset_secondary(CPUARMState *env,
+static void default_reset_secondary(ARMCPU *cpu,
const struct arm_boot_info *info)
{
+ CPUARMState *env = &cpu->env;
+
stl_phys_notdirty(info->smp_bootreg_addr, 0);
env->regs[15] = info->smp_loader_start;
}
@@ -274,10 +276,11 @@ static int load_dtb(target_phys_addr_t addr, const struct arm_boot_info *binfo)
static void do_cpu_reset(void *opaque)
{
- CPUARMState *env = opaque;
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
const struct arm_boot_info *info = env->boot_info;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
if (info) {
if (!info->is_linux) {
/* Jump to the entry point. */
@@ -294,14 +297,15 @@ static void do_cpu_reset(void *opaque)
}
}
} else {
- info->secondary_cpu_reset_hook(env, info);
+ info->secondary_cpu_reset_hook(cpu, info);
}
}
}
}
-void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info)
+void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
{
+ CPUARMState *env = &cpu->env;
int kernel_size;
int initrd_size;
int n;
@@ -400,13 +404,14 @@ void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info)
rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
info->loader_start);
if (info->nb_cpus > 1) {
- info->write_secondary_boot(env, info);
+ info->write_secondary_boot(cpu, info);
}
}
info->is_linux = is_linux;
for (; env; env = env->next_cpu) {
+ cpu = arm_env_get_cpu(env);
env->boot_info = info;
- qemu_register_reset(do_cpu_reset, env);
+ qemu_register_reset(do_cpu_reset, cpu);
}
}
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index 109496528c..ffb4d4171a 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -13,7 +13,9 @@
/* Input 0 is IRQ and input 1 is FIQ. */
static void arm_pic_cpu_handler(void *opaque, int irq, int level)
{
- CPUARMState *env = (CPUARMState *)opaque;
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
+
switch (irq) {
case ARM_PIC_CPU_IRQ:
if (level)
@@ -32,7 +34,7 @@ static void arm_pic_cpu_handler(void *opaque, int irq, int level)
}
}
-qemu_irq *arm_pic_init_cpu(CPUARMState *env)
+qemu_irq *arm_pic_init_cpu(ARMCPU *cpu)
{
- return qemu_allocate_irqs(arm_pic_cpu_handler, env, 2);
+ return qemu_allocate_irqs(arm_pic_cpu_handler, cpu, 2);
}
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 4aac076e48..8cec78db96 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -149,7 +149,9 @@ static void armv7m_bitband_init(void)
static void armv7m_reset(void *opaque)
{
- cpu_state_reset((CPUARMState *)opaque);
+ ARMCPU *cpu = opaque;
+
+ cpu_reset(CPU(cpu));
}
/* Init CPU and memory for a v7-M based board.
@@ -160,6 +162,7 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
int flash_size, int sram_size,
const char *kernel_filename, const char *cpu_model)
{
+ ARMCPU *cpu;
CPUARMState *env;
DeviceState *nvic;
/* FIXME: make this local state. */
@@ -177,13 +180,15 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
flash_size *= 1024;
sram_size *= 1024;
- if (!cpu_model)
+ if (cpu_model == NULL) {
cpu_model = "cortex-m3";
- env = cpu_init(cpu_model);
- if (!env) {
+ }
+ cpu = cpu_arm_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+ env = &cpu->env;
#if 0
/* > 32Mb SRAM gets complicated because it overlaps the bitband area.
@@ -210,7 +215,7 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
nvic = qdev_create(NULL, "armv7m_nvic");
env->nvic = nvic;
qdev_init_nofail(nvic);
- cpu_pic = arm_pic_init_cpu(env);
+ cpu_pic = arm_pic_init_cpu(cpu);
sysbus_connect_irq(sysbus_from_qdev(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
for (i = 0; i < 64; i++) {
pic[i] = qdev_get_gpio_in(nvic, i);
@@ -241,7 +246,7 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
vmstate_register_ram_global(hack);
memory_region_add_subregion(address_space_mem, 0xfffff000, hack);
- qemu_register_reset(armv7m_reset, env);
+ qemu_register_reset(armv7m_reset, cpu);
return pic;
}
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 2304e3533a..eab6327bed 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -247,6 +247,7 @@ void axisdev88_init (ram_addr_t ram_size,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
+ CRISCPU *cpu;
CPUCRISState *env;
DeviceState *dev;
SysBusDevice *s;
@@ -263,7 +264,8 @@ void axisdev88_init (ram_addr_t ram_size,
if (cpu_model == NULL) {
cpu_model = "crisv32";
}
- env = cpu_init(cpu_model);
+ cpu = cpu_cris_init(cpu_model);
+ env = &cpu->env;
/* allocate RAM */
memory_region_init_ram(phys_ram, "axisdev88.ram", ram_size);
@@ -344,7 +346,7 @@ void axisdev88_init (ram_addr_t ram_size,
li.image_filename = kernel_filename;
li.cmdline = kernel_cmdline;
- cris_load_image(env, &li);
+ cris_load_image(cpu, &li);
}
static QEMUMachine axisdev88_machine = {
diff --git a/hw/collie.c b/hw/collie.c
index 42f4310816..56f89a9f2e 100644
--- a/hw/collie.c
+++ b/hw/collie.c
@@ -54,7 +54,7 @@ static void collie_init(ram_addr_t ram_size,
collie_binfo.kernel_cmdline = kernel_cmdline;
collie_binfo.initrd_filename = initrd_filename;
collie_binfo.board_id = 0x208;
- arm_load_kernel(s->env, &collie_binfo);
+ arm_load_kernel(s->cpu, &collie_binfo);
}
static QEMUMachine collie_machine = {
diff --git a/hw/cris-boot.c b/hw/cris-boot.c
index ca6c52fa8e..b21326fade 100644
--- a/hw/cris-boot.c
+++ b/hw/cris-boot.c
@@ -29,12 +29,13 @@
static void main_cpu_reset(void *opaque)
{
- CPUCRISState *env = opaque;
+ CRISCPU *cpu = opaque;
+ CPUCRISState *env = &cpu->env;
struct cris_load_info *li;
li = env->load_info;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
if (!li) {
/* nothing more to do. */
@@ -60,8 +61,9 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
return addr - 0x80000000LL;
}
-void cris_load_image(CPUCRISState *env, struct cris_load_info *li)
+void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
{
+ CPUCRISState *env = &cpu->env;
uint64_t entry, high;
int kcmdline_len;
int image_size;
@@ -92,5 +94,5 @@ void cris_load_image(CPUCRISState *env, struct cris_load_info *li)
}
pstrcpy_targphys("cmdline", 0x40000000, 256, li->cmdline);
}
- qemu_register_reset(main_cpu_reset, env);
+ qemu_register_reset(main_cpu_reset, cpu);
}
diff --git a/hw/cris-boot.h b/hw/cris-boot.h
index ecb9779e49..0a2c242411 100644
--- a/hw/cris-boot.h
+++ b/hw/cris-boot.h
@@ -8,4 +8,4 @@ struct cris_load_info
target_phys_addr_t entry;
};
-void cris_load_image(CPUCRISState *env, struct cris_load_info *li);
+void cris_load_image(CRISCPU *cpu, struct cris_load_info *li);
diff --git a/hw/cris/Makefile.objs b/hw/cris/Makefile.objs
new file mode 100644
index 0000000000..aa9298a0ed
--- /dev/null
+++ b/hw/cris/Makefile.objs
@@ -0,0 +1,13 @@
+# Boards
+obj-y = cris_pic_cpu.o
+obj-y += cris-boot.o
+obj-y += axis_dev88.o
+
+# IO blocks
+obj-y += etraxfs_dma.o
+obj-y += etraxfs_pic.o
+obj-y += etraxfs_eth.o
+obj-y += etraxfs_timer.o
+obj-y += etraxfs_ser.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/exynos4210.c b/hw/exynos4210.c
index afc4bdc7e0..dd14d01b01 100644
--- a/hw/exynos4210.c
+++ b/hw/exynos4210.c
@@ -65,7 +65,7 @@
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
0x09, 0x00, 0x00, 0x00 };
-void exynos4210_write_secondary(CPUARMState *env,
+void exynos4210_write_secondary(ARMCPU *cpu,
const struct arm_boot_info *info)
{
int n;
@@ -107,13 +107,14 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
SysBusDevice *busdev;
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
- s->env[n] = cpu_init("cortex-a9");
- if (!s->env[n]) {
+ s->cpu[n] = cpu_arm_init("cortex-a9");
+ if (!s->cpu[n]) {
fprintf(stderr, "Unable to find CPU %d definition\n", n);
exit(1);
}
+
/* Create PIC controller for each processor instance */
- irqp = arm_pic_init_cpu(s->env[n]);
+ irqp = arm_pic_init_cpu(s->cpu[n]);
/*
* Get GICs gpio_in cpu_irq to connect a combiner to them later.
diff --git a/hw/exynos4210.h b/hw/exynos4210.h
index f7c7027302..b1b4609054 100644
--- a/hw/exynos4210.h
+++ b/hw/exynos4210.h
@@ -83,7 +83,7 @@ typedef struct Exynos4210Irq {
} Exynos4210Irq;
typedef struct Exynos4210State {
- CPUARMState * env[EXYNOS4210_NCPUS];
+ ARMCPU *cpu[EXYNOS4210_NCPUS];
Exynos4210Irq irqs;
qemu_irq *irq_table;
@@ -97,7 +97,7 @@ typedef struct Exynos4210State {
MemoryRegion bootreg_mem;
} Exynos4210State;
-void exynos4210_write_secondary(CPUARMState *env,
+void exynos4210_write_secondary(ARMCPU *cpu,
const struct arm_boot_info *info);
Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c
index ea32c51dcc..e5c2a5f388 100644
--- a/hw/exynos4_boards.c
+++ b/hw/exynos4_boards.c
@@ -138,7 +138,7 @@ static void nuri_init(ram_addr_t ram_size,
exynos4_boards_init_common(kernel_filename, kernel_cmdline,
initrd_filename, EXYNOS4_BOARD_NURI);
- arm_load_kernel(first_cpu, &exynos4_board_binfo);
+ arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
}
static void smdkc210_init(ram_addr_t ram_size,
@@ -151,7 +151,7 @@ static void smdkc210_init(ram_addr_t ram_size,
lan9215_init(SMDK_LAN9118_BASE_ADDR,
qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)]));
- arm_load_kernel(first_cpu, &exynos4_board_binfo);
+ arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
}
static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS] = {
diff --git a/hw/highbank.c b/hw/highbank.c
index 4d6d728a28..4bdea5df7d 100644
--- a/hw/highbank.c
+++ b/hw/highbank.c
@@ -36,7 +36,7 @@
/* Board init. */
-static void hb_write_secondary(CPUARMState *env, const struct arm_boot_info *info)
+static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
{
int n;
uint32_t smpboot[] = {
@@ -60,8 +60,10 @@ static void hb_write_secondary(CPUARMState *env, const struct arm_boot_info *inf
rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
}
-static void hb_reset_secondary(CPUARMState *env, const struct arm_boot_info *info)
+static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
{
+ CPUARMState *env = &cpu->env;
+
switch (info->nb_cpus) {
case 4:
stl_phys_notdirty(SMP_BOOT_REG + 0x30, 0);
@@ -190,7 +192,6 @@ static void highbank_init(ram_addr_t ram_size,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
- CPUARMState *env = NULL;
DeviceState *dev;
SysBusDevice *busdev;
qemu_irq *irqp;
@@ -213,10 +214,10 @@ static void highbank_init(ram_addr_t ram_size,
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- env = &cpu->env;
+
/* This will become a QOM property eventually */
cpu->reset_cbar = GIC_BASE_ADDR;
- irqp = arm_pic_init_cpu(env);
+ irqp = arm_pic_init_cpu(cpu);
cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
}
@@ -316,7 +317,7 @@ static void highbank_init(ram_addr_t ram_size,
highbank_binfo.loader_start = 0;
highbank_binfo.write_secondary_boot = hb_write_secondary;
highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
- arm_load_kernel(first_cpu, &highbank_binfo);
+ arm_load_kernel(arm_env_get_cpu(first_cpu), &highbank_binfo);
}
static QEMUMachine highbank_machine = {
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
new file mode 100644
index 0000000000..d43f1df5f0
--- /dev/null
+++ b/hw/i386/Makefile.objs
@@ -0,0 +1,13 @@
+obj-y += mc146818rtc.o pc.o
+obj-y += apic_common.o apic.o kvmvapic.o
+obj-y += sga.o ioapic_common.o ioapic.o piix_pci.o
+obj-y += vmport.o
+obj-y += pci-hotplug.o smbios.o wdt_ib700.o
+obj-y += debugcon.o multiboot.o
+obj-y += pc_piix.o
+obj-y += pc_sysfw.o
+obj-$(CONFIG_XEN) += xen_platform.o xen_apic.o
+obj-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o kvm/i8259.o kvm/ioapic.o kvm/i8254.o
+obj-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs
new file mode 100644
index 0000000000..cf718dd016
--- /dev/null
+++ b/hw/ide/Makefile.objs
@@ -0,0 +1,10 @@
+hw-obj-$(CONFIG_IDE_CORE) += core.o atapi.o
+hw-obj-$(CONFIG_IDE_QDEV) += qdev.o
+hw-obj-$(CONFIG_IDE_PCI) += pci.o
+hw-obj-$(CONFIG_IDE_ISA) += isa.o
+hw-obj-$(CONFIG_IDE_PIIX) += piix.o
+hw-obj-$(CONFIG_IDE_CMD646) += cmd646.o
+hw-obj-$(CONFIG_IDE_MACIO) += macio.o
+hw-obj-$(CONFIG_IDE_VIA) += via.o
+hw-obj-$(CONFIG_AHCI) += ahci.o
+hw-obj-$(CONFIG_AHCI) += ich.o
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 9bdb9e62d6..deacbf4d0d 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -443,7 +443,7 @@ static void integratorcp_init(ram_addr_t ram_size,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
- CPUARMState *env;
+ ARMCPU *cpu;
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
@@ -452,13 +452,15 @@ static void integratorcp_init(ram_addr_t ram_size,
DeviceState *dev;
int i;
- if (!cpu_model)
+ if (!cpu_model) {
cpu_model = "arm926";
- env = cpu_init(cpu_model);
- if (!env) {
+ }
+ cpu = cpu_arm_init(cpu_model);
+ if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+
memory_region_init_ram(ram, "integrator.ram", ram_size);
vmstate_register_ram_global(ram);
/* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash. */
@@ -474,7 +476,7 @@ static void integratorcp_init(ram_addr_t ram_size,
qdev_init_nofail(dev);
sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
- cpu_pic = arm_pic_init_cpu(env);
+ cpu_pic = arm_pic_init_cpu(cpu);
dev = sysbus_create_varargs("integrator_pic", 0x14000000,
cpu_pic[ARM_PIC_CPU_IRQ],
cpu_pic[ARM_PIC_CPU_FIQ], NULL);
@@ -500,7 +502,7 @@ static void integratorcp_init(ram_addr_t ram_size,
integrator_binfo.kernel_filename = kernel_filename;
integrator_binfo.kernel_cmdline = kernel_cmdline;
integrator_binfo.initrd_filename = initrd_filename;
- arm_load_kernel(env, &integrator_binfo);
+ arm_load_kernel(cpu, &integrator_binfo);
}
static QEMUMachine integratorcp_machine = {
diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c
index 8ba4079025..80e3e48333 100644
--- a/hw/kvm/apic.c
+++ b/hw/kvm/apic.c
@@ -30,7 +30,7 @@ void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic)
APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
int i;
- memset(kapic, 0, sizeof(kapic));
+ memset(kapic, 0, sizeof(*kapic));
kvm_apic_set_reg(kapic, 0x2, s->id << 24);
kvm_apic_set_reg(kapic, 0x8, s->tpr);
kvm_apic_set_reg(kapic, 0xd, s->log_dest << 24);
diff --git a/hw/kvm/i8254.c b/hw/kvm/i8254.c
index bb5fe07d1e..c5d3711a04 100644
--- a/hw/kvm/i8254.c
+++ b/hw/kvm/i8254.c
@@ -23,31 +23,63 @@
* THE SOFTWARE.
*/
#include "qemu-timer.h"
+#include "sysemu.h"
#include "hw/i8254.h"
#include "hw/i8254_internal.h"
#include "kvm.h"
#define KVM_PIT_REINJECT_BIT 0
+#define CALIBRATION_ROUNDS 3
+
typedef struct KVMPITState {
PITCommonState pit;
LostTickPolicy lost_tick_policy;
+ bool state_valid;
} KVMPITState;
-static void kvm_pit_get(PITCommonState *s)
+static int64_t abs64(int64_t v)
{
+ return v < 0 ? -v : v;
+}
+
+static void kvm_pit_get(PITCommonState *pit)
+{
+ KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit);
struct kvm_pit_state2 kpit;
struct kvm_pit_channel_state *kchan;
struct PITChannelState *sc;
+ int64_t offset, clock_offset;
+ struct timespec ts;
int i, ret;
+ if (s->state_valid) {
+ return;
+ }
+
+ /*
+ * Measure the delta between CLOCK_MONOTONIC, the base used for
+ * kvm_pit_channel_state::count_load_time, and vm_clock. Take the
+ * minimum of several samples to filter out scheduling noise.
+ */
+ clock_offset = INT64_MAX;
+ for (i = 0; i < CALIBRATION_ROUNDS; i++) {
+ offset = qemu_get_clock_ns(vm_clock);
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ offset -= ts.tv_nsec;
+ offset -= (int64_t)ts.tv_sec * 1000000000;
+ if (abs64(offset) < abs64(clock_offset)) {
+ clock_offset = offset;
+ }
+ }
+
if (kvm_has_pit_state2()) {
ret = kvm_vm_ioctl(kvm_state, KVM_GET_PIT2, &kpit);
if (ret < 0) {
fprintf(stderr, "KVM_GET_PIT2 failed: %s\n", strerror(ret));
abort();
}
- s->channels[0].irq_disabled = kpit.flags & KVM_PIT_FLAGS_HPET_LEGACY;
+ pit->channels[0].irq_disabled = kpit.flags & KVM_PIT_FLAGS_HPET_LEGACY;
} else {
/*
* kvm_pit_state2 is superset of kvm_pit_state struct,
@@ -61,7 +93,7 @@ static void kvm_pit_get(PITCommonState *s)
}
for (i = 0; i < 3; i++) {
kchan = &kpit.channels[i];
- sc = &s->channels[i];
+ sc = &pit->channels[i];
sc->count = kchan->count;
sc->latched_count = kchan->latched_count;
sc->count_latched = kchan->count_latched;
@@ -74,10 +106,10 @@ static void kvm_pit_get(PITCommonState *s)
sc->mode = kchan->mode;
sc->bcd = kchan->bcd;
sc->gate = kchan->gate;
- sc->count_load_time = kchan->count_load_time;
+ sc->count_load_time = kchan->count_load_time + clock_offset;
}
- sc = &s->channels[0];
+ sc = &pit->channels[0];
sc->next_transition_time =
pit_get_next_transition_time(sc, sc->count_load_time);
}
@@ -173,6 +205,19 @@ static void kvm_pit_irq_control(void *opaque, int n, int enable)
kvm_pit_put(pit);
}
+static void kvm_pit_vm_state_change(void *opaque, int running,
+ RunState state)
+{
+ KVMPITState *s = opaque;
+
+ if (running) {
+ s->state_valid = false;
+ } else {
+ kvm_pit_get(&s->pit);
+ s->state_valid = true;
+ }
+}
+
static int kvm_pit_initfn(PITCommonState *pit)
{
KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit);
@@ -215,6 +260,8 @@ static int kvm_pit_initfn(PITCommonState *pit)
qdev_init_gpio_in(&pit->dev.qdev, kvm_pit_irq_control, 1);
+ qemu_add_vm_change_state_handler(kvm_pit_vm_state_change, s);
+
return 0;
}
diff --git a/hw/leon3.c b/hw/leon3.c
index 0a5ff165a1..878d3aa557 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -42,16 +42,16 @@
#define MAX_PILS 16
typedef struct ResetData {
- CPUSPARCState *env;
+ SPARCCPU *cpu;
uint32_t entry; /* save kernel entry in case of reset */
} ResetData;
static void main_cpu_reset(void *opaque)
{
ResetData *s = (ResetData *)opaque;
- CPUSPARCState *env = s->env;
+ CPUSPARCState *env = &s->cpu->env;
- cpu_state_reset(env);
+ cpu_reset(CPU(s->cpu));
env->halted = 0;
env->pc = s->entry;
@@ -101,6 +101,7 @@ static void leon3_generic_hw_init(ram_addr_t ram_size,
const char *initrd_filename,
const char *cpu_model)
{
+ SPARCCPU *cpu;
CPUSPARCState *env;
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
@@ -117,17 +118,18 @@ static void leon3_generic_hw_init(ram_addr_t ram_size,
cpu_model = "LEON3";
}
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_sparc_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
exit(1);
}
+ env = &cpu->env;
cpu_sparc_set_id(env, 0);
/* Reset data */
reset_info = g_malloc0(sizeof(ResetData));
- reset_info->env = env;
+ reset_info->cpu = cpu;
qemu_register_reset(main_cpu_reset, reset_info);
/* Allocate IRQ manager */
diff --git a/hw/lm32/Makefile.objs b/hw/lm32/Makefile.objs
new file mode 100644
index 0000000000..4e1843c11d
--- /dev/null
+++ b/hw/lm32/Makefile.objs
@@ -0,0 +1,23 @@
+# LM32 boards
+obj-y += lm32_boards.o
+obj-y += milkymist.o
+
+# LM32 peripherals
+obj-y += lm32_pic.o
+obj-y += lm32_juart.o
+obj-y += lm32_timer.o
+obj-y += lm32_uart.o
+obj-y += lm32_sys.o
+obj-y += milkymist-ac97.o
+obj-y += milkymist-hpdmc.o
+obj-y += milkymist-memcard.o
+obj-y += milkymist-minimac2.o
+obj-y += milkymist-pfpu.o
+obj-y += milkymist-softusb.o
+obj-y += milkymist-sysctl.o
+obj-$(CONFIG_OPENGL) += milkymist-tmu2.o
+obj-y += milkymist-uart.o
+obj-y += milkymist-vgafb.o
+obj-y += framebuffer.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index 4dd4f0ab90..b76d8008be 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -31,7 +31,7 @@
#include "exec-memory.h"
typedef struct {
- CPULM32State *env;
+ LM32CPU *cpu;
target_phys_addr_t bootstrap_pc;
target_phys_addr_t flash_base;
target_phys_addr_t hwsetup_base;
@@ -54,9 +54,9 @@ static void cpu_irq_handler(void *opaque, int irq, int level)
static void main_cpu_reset(void *opaque)
{
ResetInfo *reset_info = opaque;
- CPULM32State *env = reset_info->env;
+ CPULM32State *env = &reset_info->cpu->env;
- cpu_state_reset(env);
+ cpu_reset(CPU(reset_info->cpu));
/* init defaults */
env->pc = (uint32_t)reset_info->bootstrap_pc;
@@ -75,6 +75,7 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used,
const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
+ LM32CPU *cpu;
CPULM32State *env;
DriveInfo *dinfo;
MemoryRegion *address_space_mem = get_system_memory();
@@ -101,8 +102,9 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used,
if (cpu_model == NULL) {
cpu_model = "lm32-full";
}
- env = cpu_init(cpu_model);
- reset_info->env = env;
+ cpu = cpu_lm32_init(cpu_model);
+ env = &cpu->env;
+ reset_info->cpu = cpu;
reset_info->flash_base = flash_base;
@@ -163,6 +165,7 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used,
const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
+ LM32CPU *cpu;
CPULM32State *env;
DriveInfo *dinfo;
MemoryRegion *address_space_mem = get_system_memory();
@@ -196,8 +199,9 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used,
if (cpu_model == NULL) {
cpu_model = "lm32-full";
}
- env = cpu_init(cpu_model);
- reset_info->env = env;
+ cpu = cpu_lm32_init(cpu_model);
+ env = &cpu->env;
+ reset_info->cpu = cpu;
reset_info->flash_base = flash_base;
diff --git a/hw/m68k/Makefile.objs b/hw/m68k/Makefile.objs
new file mode 100644
index 0000000000..93b6d25baf
--- /dev/null
+++ b/hw/m68k/Makefile.objs
@@ -0,0 +1,4 @@
+obj-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
+obj-y += dummy_m68k.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 27f59009f6..97687b6eeb 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -102,7 +102,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
{
uint32_t sector_len = 256 * 1024;
target_phys_addr_t mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
- PXA2xxState *cpu;
+ PXA2xxState *mpu;
DeviceState *mst_irq;
DriveInfo *dinfo;
int i;
@@ -113,7 +113,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
cpu_model = "pxa270-c5";
/* Setup CPU & memory */
- cpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, cpu_model);
+ mpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, cpu_model);
memory_region_init_ram(rom, "mainstone.rom", MAINSTONE_ROM);
vmstate_register_ram_global(rom);
memory_region_set_readonly(rom, true);
@@ -145,19 +145,19 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
}
mst_irq = sysbus_create_simple("mainstone-fpga", MST_FPGA_PHYS,
- qdev_get_gpio_in(cpu->gpio, 0));
+ qdev_get_gpio_in(mpu->gpio, 0));
/* setup keypad */
printf("map addr %p\n", &map);
- pxa27x_register_keypad(cpu->kp, map, 0xe0);
+ pxa27x_register_keypad(mpu->kp, map, 0xe0);
/* MMC/SD host */
- pxa2xx_mmci_handlers(cpu->mmc, NULL, qdev_get_gpio_in(mst_irq, MMC_IRQ));
+ pxa2xx_mmci_handlers(mpu->mmc, NULL, qdev_get_gpio_in(mst_irq, MMC_IRQ));
- pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
+ pxa2xx_pcmcia_set_irq_cb(mpu->pcmcia[0],
qdev_get_gpio_in(mst_irq, S0_IRQ),
qdev_get_gpio_in(mst_irq, S0_CD_IRQ));
- pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
+ pxa2xx_pcmcia_set_irq_cb(mpu->pcmcia[1],
qdev_get_gpio_in(mst_irq, S1_IRQ),
qdev_get_gpio_in(mst_irq, S1_CD_IRQ));
@@ -168,7 +168,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
mainstone_binfo.kernel_cmdline = kernel_cmdline;
mainstone_binfo.initrd_filename = initrd_filename;
mainstone_binfo.board_id = arm_id;
- arm_load_kernel(cpu->env, &mainstone_binfo);
+ arm_load_kernel(mpu->cpu, &mainstone_binfo);
}
static void mainstone_init(ram_addr_t ram_size,
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 9c64e0ae25..3777f858a1 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -599,13 +599,6 @@ static const MemoryRegionOps cmos_ops = {
.old_portio = cmos_portio
};
-// FIXME add int32 visitor
-static void visit_type_int32(Visitor *v, int *value, const char *name, Error **errp)
-{
- int64_t val = *value;
- visit_type_int(v, &val, name, errp);
-}
-
static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
diff --git a/hw/microblaze/Makefile.objs b/hw/microblaze/Makefile.objs
new file mode 100644
index 0000000000..274d2c543e
--- /dev/null
+++ b/hw/microblaze/Makefile.objs
@@ -0,0 +1,9 @@
+obj-y = petalogix_s3adsp1800_mmu.o
+obj-y += petalogix_ml605_mmu.o
+obj-y += microblaze_boot.o
+
+obj-y += microblaze_pic_cpu.o
+obj-y += xilinx_ethlite.o
+obj-$(CONFIG_FDT) += ../device_tree.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/microblaze_boot.c b/hw/microblaze_boot.c
index b4fbb10dd0..1030e9c8ed 100644
--- a/hw/microblaze_boot.c
+++ b/hw/microblaze_boot.c
@@ -35,7 +35,7 @@
static struct
{
- void (*machine_cpu_reset)(CPUMBState *);
+ void (*machine_cpu_reset)(MicroBlazeCPU *);
uint32_t bootstrap_pc;
uint32_t cmdline;
uint32_t fdt;
@@ -43,14 +43,15 @@ static struct
static void main_cpu_reset(void *opaque)
{
- CPUMBState *env = opaque;
+ MicroBlazeCPU *cpu = opaque;
+ CPUMBState *env = &cpu->env;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
env->regs[5] = boot_info.cmdline;
env->regs[7] = boot_info.fdt;
env->sregs[SR_PC] = boot_info.bootstrap_pc;
if (boot_info.machine_cpu_reset) {
- boot_info.machine_cpu_reset(env);
+ boot_info.machine_cpu_reset(cpu);
}
}
@@ -99,11 +100,10 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
return addr - 0x30000000LL;
}
-void microblaze_load_kernel(CPUMBState *env, target_phys_addr_t ddr_base,
+void microblaze_load_kernel(MicroBlazeCPU *cpu, target_phys_addr_t ddr_base,
uint32_t ramsize, const char *dtb_filename,
- void (*machine_cpu_reset)(CPUMBState *))
+ void (*machine_cpu_reset)(MicroBlazeCPU *))
{
-
QemuOpts *machine_opts;
const char *kernel_filename = NULL;
const char *kernel_cmdline = NULL;
@@ -122,7 +122,7 @@ void microblaze_load_kernel(CPUMBState *env, target_phys_addr_t ddr_base,
}
boot_info.machine_cpu_reset = machine_cpu_reset;
- qemu_register_reset(main_cpu_reset, env);
+ qemu_register_reset(main_cpu_reset, cpu);
if (kernel_filename) {
int kernel_size;
diff --git a/hw/microblaze_boot.h b/hw/microblaze_boot.h
index bf9d136f12..c9a3064d27 100644
--- a/hw/microblaze_boot.h
+++ b/hw/microblaze_boot.h
@@ -3,8 +3,8 @@
#include "hw.h"
-void microblaze_load_kernel(CPUMBState *env, target_phys_addr_t ddr_base,
+void microblaze_load_kernel(MicroBlazeCPU *cpu, target_phys_addr_t ddr_base,
uint32_t ramsize, const char *dtb_filename,
- void (*machine_cpu_reset)(CPUMBState *));
+ void (*machine_cpu_reset)(MicroBlazeCPU *));
#endif /* __MICROBLAZE_BOOT __ */
diff --git a/hw/milkymist.c b/hw/milkymist.c
index 8bb6a97b22..2e7235b4b3 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -37,7 +37,7 @@
#define KERNEL_LOAD_ADDR 0x40000000
typedef struct {
- CPULM32State *env;
+ LM32CPU *cpu;
target_phys_addr_t bootstrap_pc;
target_phys_addr_t flash_base;
target_phys_addr_t initrd_base;
@@ -59,9 +59,9 @@ static void cpu_irq_handler(void *opaque, int irq, int level)
static void main_cpu_reset(void *opaque)
{
ResetInfo *reset_info = opaque;
- CPULM32State *env = reset_info->env;
+ CPULM32State *env = &reset_info->cpu->env;
- cpu_state_reset(env);
+ cpu_reset(CPU(reset_info->cpu));
/* init defaults */
env->pc = reset_info->bootstrap_pc;
@@ -79,6 +79,7 @@ milkymist_init(ram_addr_t ram_size_not_used,
const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
+ LM32CPU *cpu;
CPULM32State *env;
int kernel_size;
DriveInfo *dinfo;
@@ -105,8 +106,9 @@ milkymist_init(ram_addr_t ram_size_not_used,
if (cpu_model == NULL) {
cpu_model = "lm32-full";
}
- env = cpu_init(cpu_model);
- reset_info->env = env;
+ cpu = cpu_lm32_init(cpu_model);
+ env = &cpu->env;
+ reset_info->cpu = cpu;
cpu_lm32_set_phys_msb_ignore(env, 1);
diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
new file mode 100644
index 0000000000..29a5d0db04
--- /dev/null
+++ b/hw/mips/Makefile.objs
@@ -0,0 +1,6 @@
+obj-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
+obj-y += mips_addr.o mips_timer.o mips_int.o
+obj-y += gt64xxx.o mc146818rtc.o
+obj-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index 1a8df10429..38e4b86150 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -198,9 +198,10 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base, int64_t kernel_a
static void main_cpu_reset(void *opaque)
{
- CPUMIPSState *env = opaque;
+ MIPSCPU *cpu = opaque;
+ CPUMIPSState *env = &cpu->env;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
/* TODO: 2E reset stuff */
if (loaderparams.kernel_filename) {
env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
@@ -272,19 +273,21 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
i2c_bus *smbus;
int i;
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+ MIPSCPU *cpu;
CPUMIPSState *env;
/* init CPUs */
if (cpu_model == NULL) {
cpu_model = "Loongson-2E";
}
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_mips_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+ env = &cpu->env;
- qemu_register_reset(main_cpu_reset, env);
+ qemu_register_reset(main_cpu_reset, cpu);
/* fulong 2e has 256M ram. */
ram_size = 256 * 1024 * 1024;
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index a6bc7badff..bf1b799c4d 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -50,8 +50,9 @@ enum jazz_model_e
static void main_cpu_reset(void *opaque)
{
- CPUMIPSState *env = opaque;
- cpu_state_reset(env);
+ MIPSCPU *cpu = opaque;
+
+ cpu_reset(CPU(cpu));
}
static uint64_t rtc_read(void *opaque, target_phys_addr_t addr, unsigned size)
@@ -112,6 +113,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
{
char *filename;
int bios_size, n;
+ MIPSCPU *cpu;
CPUMIPSState *env;
qemu_irq *rc4030, *i8259;
rc4030_dma *dmas;
@@ -140,12 +142,13 @@ static void mips_jazz_init(MemoryRegion *address_space,
cpu_model = "24Kf";
#endif
}
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_mips_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- qemu_register_reset(main_cpu_reset, env);
+ env = &cpu->env;
+ qemu_register_reset(main_cpu_reset, cpu);
/* allocate RAM */
memory_region_init_ram(ram, "mips_jazz.ram", ram_size);
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 4752bb2865..dfd7b6b113 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -751,8 +751,10 @@ static void malta_mips_config(CPUMIPSState *env)
static void main_cpu_reset(void *opaque)
{
- CPUMIPSState *env = opaque;
- cpu_state_reset(env);
+ MIPSCPU *cpu = opaque;
+ CPUMIPSState *env = &cpu->env;
+
+ cpu_reset(CPU(cpu));
/* The bootloader does not need to be rewritten as it is located in a
read only location. The kernel location and the arguments table
@@ -788,6 +790,7 @@ void mips_malta_init (ram_addr_t ram_size,
int64_t kernel_entry;
PCIBus *pci_bus;
ISABus *isa_bus;
+ MIPSCPU *cpu;
CPUMIPSState *env;
qemu_irq *isa_irq;
qemu_irq *cpu_exit_irq;
@@ -825,15 +828,17 @@ void mips_malta_init (ram_addr_t ram_size,
}
for (i = 0; i < smp_cpus; i++) {
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_mips_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+ env = &cpu->env;
+
/* Init internal devices */
cpu_mips_irq_init_cpu(env);
cpu_mips_clock_init(env);
- qemu_register_reset(main_cpu_reset, env);
+ qemu_register_reset(main_cpu_reset, cpu);
}
env = first_cpu;
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 1ea7b58323..eb03047433 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -46,7 +46,7 @@ static struct _loaderparams {
} loaderparams;
typedef struct ResetData {
- CPUMIPSState *env;
+ MIPSCPU *cpu;
uint64_t vector;
} ResetData;
@@ -105,9 +105,9 @@ static int64_t load_kernel(void)
static void main_cpu_reset(void *opaque)
{
ResetData *s = (ResetData *)opaque;
- CPUMIPSState *env = s->env;
+ CPUMIPSState *env = &s->cpu->env;
- cpu_state_reset(env);
+ cpu_reset(CPU(s->cpu));
env->active_tc.PC = s->vector & ~(target_ulong)1;
if (s->vector & 1) {
env->hflags |= MIPS_HFLAG_M16;
@@ -140,6 +140,7 @@ mips_mipssim_init (ram_addr_t ram_size,
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *bios = g_new(MemoryRegion, 1);
+ MIPSCPU *cpu;
CPUMIPSState *env;
ResetData *reset_info;
int bios_size;
@@ -152,13 +153,15 @@ mips_mipssim_init (ram_addr_t ram_size,
cpu_model = "24Kf";
#endif
}
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_mips_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+ env = &cpu->env;
+
reset_info = g_malloc0(sizeof(ResetData));
- reset_info->env = env;
+ reset_info->cpu = cpu;
reset_info->vector = env->active_tc.PC;
qemu_register_reset(main_cpu_reset, reset_info);
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index e2da49c09d..d68599965a 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -65,7 +65,7 @@ static const MemoryRegionOps mips_qemu_ops = {
};
typedef struct ResetData {
- CPUMIPSState *env;
+ MIPSCPU *cpu;
uint64_t vector;
} ResetData;
@@ -143,9 +143,9 @@ static int64_t load_kernel(void)
static void main_cpu_reset(void *opaque)
{
ResetData *s = (ResetData *)opaque;
- CPUMIPSState *env = s->env;
+ CPUMIPSState *env = &s->cpu->env;
- cpu_state_reset(env);
+ cpu_reset(CPU(s->cpu));
env->active_tc.PC = s->vector;
}
@@ -162,6 +162,7 @@ void mips_r4k_init (ram_addr_t ram_size,
MemoryRegion *bios;
MemoryRegion *iomem = g_new(MemoryRegion, 1);
int bios_size;
+ MIPSCPU *cpu;
CPUMIPSState *env;
ResetData *reset_info;
int i;
@@ -179,13 +180,15 @@ void mips_r4k_init (ram_addr_t ram_size,
cpu_model = "24Kf";
#endif
}
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_mips_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+ env = &cpu->env;
+
reset_info = g_malloc0(sizeof(ResetData));
- reset_info->env = env;
+ reset_info->cpu = cpu;
reset_info->vector = env->active_tc.PC;
qemu_register_reset(main_cpu_reset, reset_info);
diff --git a/hw/musicpal.c b/hw/musicpal.c
index c9f845a3f2..f14f20d689 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1513,7 +1513,7 @@ static void musicpal_init(ram_addr_t ram_size,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
- CPUARMState *env;
+ ARMCPU *cpu;
qemu_irq *cpu_pic;
qemu_irq pic[32];
DeviceState *dev;
@@ -1533,12 +1533,12 @@ static void musicpal_init(ram_addr_t ram_size,
if (!cpu_model) {
cpu_model = "arm926";
}
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_arm_init(cpu_model);
+ if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- cpu_pic = arm_pic_init_cpu(env);
+ cpu_pic = arm_pic_init_cpu(cpu);
/* For now we use a fixed - the original - RAM size */
memory_region_init_ram(ram, "musicpal.ram", MP_RAM_DEFAULT_SIZE);
@@ -1651,7 +1651,7 @@ static void musicpal_init(ram_addr_t ram_size,
musicpal_binfo.kernel_filename = kernel_filename;
musicpal_binfo.kernel_cmdline = kernel_cmdline;
musicpal_binfo.initrd_filename = initrd_filename;
- arm_load_kernel(env, &musicpal_binfo);
+ arm_load_kernel(cpu, &musicpal_binfo);
}
static QEMUMachine musicpal_machine = {
diff --git a/hw/nseries.c b/hw/nseries.c
index a5cfa8ccbc..fcc85466e7 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -37,7 +37,7 @@
/* Nokia N8x0 support */
struct n800_s {
- struct omap_mpu_state_s *cpu;
+ struct omap_mpu_state_s *mpu;
struct rfbi_chip_s blizzard;
struct {
@@ -135,10 +135,10 @@ static void n800_mmc_cs_cb(void *opaque, int line, int level)
static void n8x0_gpio_setup(struct n800_s *s)
{
- qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->cpu->mmc, 1);
- qdev_connect_gpio_out(s->cpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]);
+ qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->mpu->mmc, 1);
+ qdev_connect_gpio_out(s->mpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]);
- qemu_irq_lower(qdev_get_gpio_in(s->cpu->gpio, N800_BAT_COVER_GPIO));
+ qemu_irq_lower(qdev_get_gpio_in(s->mpu->gpio, N800_BAT_COVER_GPIO));
}
#define MAEMO_CAL_HEADER(...) \
@@ -179,8 +179,8 @@ static void n8x0_nand_setup(struct n800_s *s)
}
qdev_init_nofail(s->nand);
sysbus_connect_irq(sysbus_from_qdev(s->nand), 0,
- qdev_get_gpio_in(s->cpu->gpio, N8X0_ONENAND_GPIO));
- omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS,
+ qdev_get_gpio_in(s->mpu->gpio, N8X0_ONENAND_GPIO));
+ omap_gpmc_attach(s->mpu->gpmc, N8X0_ONENAND_CS,
sysbus_mmio_get_region(sysbus_from_qdev(s->nand), 0));
otp_region = onenand_raw_otp(s->nand);
@@ -192,13 +192,13 @@ static void n8x0_nand_setup(struct n800_s *s)
static void n8x0_i2c_setup(struct n800_s *s)
{
DeviceState *dev;
- qemu_irq tmp_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TMP105_GPIO);
- i2c_bus *i2c = omap_i2c_bus(s->cpu->i2c[0]);
+ qemu_irq tmp_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TMP105_GPIO);
+ i2c_bus *i2c = omap_i2c_bus(s->mpu->i2c[0]);
/* Attach a menelaus PM chip */
dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR);
qdev_connect_gpio_out(dev, 3,
- qdev_get_gpio_in(s->cpu->ih[0],
+ qdev_get_gpio_in(s->mpu->ih[0],
OMAP_INT_24XX_SYS_NIRQ));
qemu_system_powerdown = qdev_get_gpio_in(dev, 3);
@@ -263,8 +263,8 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
/* XXX: are the three pins inverted inside the chip between the
* tsc and the cpu (N4111)? */
qemu_irq penirq = NULL; /* NC */
- qemu_irq kbirq = qdev_get_gpio_in(s->cpu->gpio, N800_TSC_KP_IRQ_GPIO);
- qemu_irq dav = qdev_get_gpio_in(s->cpu->gpio, N800_TSC_TS_GPIO);
+ qemu_irq kbirq = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_KP_IRQ_GPIO);
+ qemu_irq dav = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_TS_GPIO);
s->ts.chip = tsc2301_init(penirq, kbirq, dav);
s->ts.opaque = s->ts.chip->opaque;
@@ -283,7 +283,7 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
static void n810_tsc_setup(struct n800_s *s)
{
- qemu_irq pintdav = qdev_get_gpio_in(s->cpu->gpio, N810_TSC_TS_GPIO);
+ qemu_irq pintdav = qdev_get_gpio_in(s->mpu->gpio, N810_TSC_TS_GPIO);
s->ts.opaque = tsc2005_init(pintdav);
s->ts.txrx = tsc2005_txrx;
@@ -375,7 +375,7 @@ static int n810_keys[0x80] = {
static void n810_kbd_setup(struct n800_s *s)
{
- qemu_irq kbd_irq = qdev_get_gpio_in(s->cpu->gpio, N810_KEYBOARD_GPIO);
+ qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO);
int i;
for (i = 0; i < 0x80; i ++)
@@ -388,7 +388,7 @@ static void n810_kbd_setup(struct n800_s *s)
/* Attach the LM8322 keyboard to the I2C bus,
* should happen in n8x0_i2c_setup and s->kbd be initialised here. */
- s->kbd = i2c_create_slave(omap_i2c_bus(s->cpu->i2c[0]),
+ s->kbd = i2c_create_slave(omap_i2c_bus(s->mpu->i2c[0]),
"lm8323", N810_LM8323_ADDR);
qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
}
@@ -679,8 +679,8 @@ static void n8x0_spi_setup(struct n800_s *s)
void *tsc = s->ts.opaque;
void *mipid = mipid_init();
- omap_mcspi_attach(s->cpu->mcspi[0], s->ts.txrx, tsc, 0);
- omap_mcspi_attach(s->cpu->mcspi[0], mipid_txrx, mipid, 1);
+ omap_mcspi_attach(s->mpu->mcspi[0], s->ts.txrx, tsc, 0);
+ omap_mcspi_attach(s->mpu->mcspi[0], mipid_txrx, mipid, 1);
}
/* This task is normally performed by the bootloader. If we're loading
@@ -735,20 +735,20 @@ static void n8x0_dss_setup(struct n800_s *s)
s->blizzard.write = s1d13745_write;
s->blizzard.read = s1d13745_read;
- omap_rfbi_attach(s->cpu->dss, 0, &s->blizzard);
+ omap_rfbi_attach(s->mpu->dss, 0, &s->blizzard);
}
static void n8x0_cbus_setup(struct n800_s *s)
{
- qemu_irq dat_out = qdev_get_gpio_in(s->cpu->gpio, N8X0_CBUS_DAT_GPIO);
- qemu_irq retu_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_RETU_GPIO);
- qemu_irq tahvo_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TAHVO_GPIO);
+ qemu_irq dat_out = qdev_get_gpio_in(s->mpu->gpio, N8X0_CBUS_DAT_GPIO);
+ qemu_irq retu_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_RETU_GPIO);
+ qemu_irq tahvo_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TAHVO_GPIO);
CBus *cbus = cbus_init(dat_out);
- qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
- qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
- qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
+ qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
+ qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
+ qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
@@ -757,14 +757,14 @@ static void n8x0_cbus_setup(struct n800_s *s)
static void n8x0_uart_setup(struct n800_s *s)
{
CharDriverState *radio = uart_hci_init(
- qdev_get_gpio_in(s->cpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
+ qdev_get_gpio_in(s->mpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
- qdev_connect_gpio_out(s->cpu->gpio, N8X0_BT_RESET_GPIO,
+ qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_RESET_GPIO,
csrhci_pins_get(radio)[csrhci_pin_reset]);
- qdev_connect_gpio_out(s->cpu->gpio, N8X0_BT_WKUP_GPIO,
+ qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_WKUP_GPIO,
csrhci_pins_get(radio)[csrhci_pin_wakeup]);
- omap_uart_attach(s->cpu->uart[BT_UART], radio);
+ omap_uart_attach(s->mpu->uart[BT_UART], radio);
}
static void n8x0_usb_setup(struct n800_s *s)
@@ -774,13 +774,13 @@ static void n8x0_usb_setup(struct n800_s *s)
dev = sysbus_from_qdev(s->usb);
qdev_init_nofail(s->usb);
sysbus_connect_irq(dev, 0,
- qdev_get_gpio_in(s->cpu->gpio, N8X0_TUSB_INT_GPIO));
+ qdev_get_gpio_in(s->mpu->gpio, N8X0_TUSB_INT_GPIO));
/* Using the NOR interface */
- omap_gpmc_attach(s->cpu->gpmc, N8X0_USB_ASYNC_CS,
+ omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_ASYNC_CS,
sysbus_mmio_get_region(dev, 0));
- omap_gpmc_attach(s->cpu->gpmc, N8X0_USB_SYNC_CS,
+ omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_SYNC_CS,
sysbus_mmio_get_region(dev, 1));
- qdev_connect_gpio_out(s->cpu->gpio, N8X0_TUSB_ENABLE_GPIO,
+ qdev_connect_gpio_out(s->mpu->gpio, N8X0_TUSB_ENABLE_GPIO,
qdev_get_gpio_in(s->usb, 0)); /* tusb_pwr */
}
@@ -1023,11 +1023,11 @@ static void n8x0_boot_init(void *opaque)
n800_dss_init(&s->blizzard);
/* CPU setup */
- s->cpu->env->GE = 0x5;
+ s->mpu->cpu->env.GE = 0x5;
/* If the machine has a slided keyboard, open it */
if (s->kbd)
- qemu_irq_raise(qdev_get_gpio_in(s->cpu->gpio, N810_SLIDE_GPIO));
+ qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO));
}
#define OMAP_TAG_NOKIA_BT 0x4e01
@@ -1281,7 +1281,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
int sdram_size = binfo->ram_size;
DisplayState *ds;
- s->cpu = omap2420_mpu_init(sysmem, sdram_size, cpu_model);
+ s->mpu = omap2420_mpu_init(sysmem, sdram_size, cpu_model);
/* Setup peripherals
*
@@ -1329,7 +1329,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
binfo->kernel_filename = kernel_filename;
binfo->kernel_cmdline = kernel_cmdline;
binfo->initrd_filename = initrd_filename;
- arm_load_kernel(s->cpu->env, binfo);
+ arm_load_kernel(s->mpu->cpu, binfo);
qemu_register_reset(n8x0_boot_init, s);
}
@@ -1338,7 +1338,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
int rom_size;
uint8_t nolo_tags[0x10000];
/* No, wait, better start at the ROM. */
- s->cpu->env->regs[15] = OMAP2_Q2_BASE + 0x400000;
+ s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
/* This is intended for loading the `secondary.bin' program from
* Nokia images (the NOLO bootloader). The entry point seems
diff --git a/hw/omap.h b/hw/omap.h
index 6c3d004719..2819e5df9a 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -804,7 +804,7 @@ struct omap_mpu_state_s {
omap3630,
} mpu_model;
- CPUARMState *env;
+ ARMCPU *cpu;
qemu_irq *drq;
diff --git a/hw/omap1.c b/hw/omap1.c
index 80d47f0b85..ad60cc4919 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -1519,8 +1519,9 @@ static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
{
omap_clk clk;
- if (value & (1 << 11)) /* SETARM_IDLE */
- cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
+ if (value & (1 << 11)) { /* SETARM_IDLE */
+ cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+ }
if (!(value & (1 << 10))) /* WKUP_MODE */
qemu_system_shutdown_request(); /* XXX: disable wakeup from IRQ */
@@ -1734,7 +1735,7 @@ static uint64_t omap_clkdsp_read(void *opaque, target_phys_addr_t addr,
case 0x18: /* DSP_SYSST */
return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
- (s->env->halted << 6); /* Quite useless... */
+ (s->cpu->env.halted << 6); /* Quite useless... */
}
OMAP_BAD_REG(addr);
@@ -3701,7 +3702,7 @@ static void omap1_mpu_reset(void *opaque)
omap_lpg_reset(mpu->led[0]);
omap_lpg_reset(mpu->led[1]);
omap_clkm_reset(mpu);
- cpu_state_reset(mpu->env);
+ cpu_reset(CPU(mpu->cpu));
}
static const struct omap_map_s {
@@ -3751,8 +3752,9 @@ void omap_mpu_wakeup(void *opaque, int irq, int req)
{
struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
- if (mpu->env->halted)
- cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
+ if (mpu->cpu->env.halted) {
+ cpu_interrupt(&mpu->cpu->env, CPU_INTERRUPT_EXITTB);
+ }
}
static const struct dma_irq_map omap1_dma_irq_map[] = {
@@ -3829,8 +3831,8 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
/* Core */
s->mpu_model = omap310;
- s->env = cpu_init(core);
- if (!s->env) {
+ s->cpu = cpu_arm_init(core);
+ if (s->cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
@@ -3852,7 +3854,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
omap_clkm_init(system_memory, 0xfffece00, 0xe1008000, s);
- cpu_irq = arm_pic_init_cpu(s->env);
+ cpu_irq = arm_pic_init_cpu(s->cpu);
s->ih[0] = qdev_create(NULL, "omap-intc");
qdev_prop_set_uint32(s->ih[0], "size", 0x100);
qdev_prop_set_ptr(s->ih[0], "clk", omap_findclk(s, "arminth_ck"));
diff --git a/hw/omap2.c b/hw/omap2.c
index 42fce5e986..4278dd19c4 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2222,7 +2222,7 @@ static void omap2_mpu_reset(void *opaque)
omap_mmc_reset(mpu->mmc);
omap_mcspi_reset(mpu->mcspi[0]);
omap_mcspi_reset(mpu->mcspi[1]);
- cpu_state_reset(mpu->env);
+ cpu_reset(CPU(mpu->cpu));
}
static int omap2_validate_addr(struct omap_mpu_state_s *s,
@@ -2253,8 +2253,8 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
/* Core */
s->mpu_model = omap2420;
- s->env = cpu_init(core ?: "arm1136-r2");
- if (!s->env) {
+ s->cpu = cpu_arm_init(core ?: "arm1136-r2");
+ if (s->cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
@@ -2277,7 +2277,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
/* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
- cpu_irq = arm_pic_init_cpu(s->env);
+ cpu_irq = arm_pic_init_cpu(s->cpu);
s->ih[0] = qdev_create(NULL, "omap2-intc");
qdev_prop_set_uint8(s->ih[0], "revision", 0x21);
qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk"));
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index 4e8ec4a990..abca341926 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -103,7 +103,7 @@ static void sx1_init(ram_addr_t ram_size,
const char *initrd_filename, const char *cpu_model,
const int version)
{
- struct omap_mpu_state_s *cpu;
+ struct omap_mpu_state_s *mpu;
MemoryRegion *address_space = get_system_memory();
MemoryRegion *flash = g_new(MemoryRegion, 1);
MemoryRegion *flash_1 = g_new(MemoryRegion, 1);
@@ -121,7 +121,7 @@ static void sx1_init(ram_addr_t ram_size,
flash_size = flash2_size;
}
- cpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, cpu_model);
+ mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, cpu_model);
/* External Flash (EMIFS) */
memory_region_init_ram(flash, "omap_sx1.flash0-0", flash_size);
@@ -202,7 +202,7 @@ static void sx1_init(ram_addr_t ram_size,
sx1_binfo.kernel_filename = kernel_filename;
sx1_binfo.kernel_cmdline = kernel_cmdline;
sx1_binfo.initrd_filename = initrd_filename;
- arm_load_kernel(cpu->env, &sx1_binfo);
+ arm_load_kernel(mpu->cpu, &sx1_binfo);
}
/* TODO: fix next line */
diff --git a/hw/palm.c b/hw/palm.c
index b1252ab1e9..bacdc90d4a 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -196,7 +196,7 @@ static void palmte_init(ram_addr_t ram_size,
const char *initrd_filename, const char *cpu_model)
{
MemoryRegion *address_space_mem = get_system_memory();
- struct omap_mpu_state_s *cpu;
+ struct omap_mpu_state_s *mpu;
int flash_size = 0x00800000;
int sdram_size = palmte_binfo.ram_size;
static uint32_t cs0val = 0xffffffff;
@@ -208,7 +208,7 @@ static void palmte_init(ram_addr_t ram_size,
MemoryRegion *flash = g_new(MemoryRegion, 1);
MemoryRegion *cs = g_new(MemoryRegion, 4);
- cpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model);
+ mpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model);
/* External Flash (EMIFS) */
memory_region_init_ram(flash, "palmte.flash", flash_size);
@@ -230,11 +230,11 @@ static void palmte_init(ram_addr_t ram_size,
OMAP_CS3_SIZE);
memory_region_add_subregion(address_space_mem, OMAP_CS3_BASE, &cs[3]);
- palmte_microwire_setup(cpu);
+ palmte_microwire_setup(mpu);
- qemu_add_kbd_event_handler(palmte_button_event, cpu);
+ qemu_add_kbd_event_handler(palmte_button_event, mpu);
- palmte_gpio_setup(cpu);
+ palmte_gpio_setup(mpu);
/* Setup initial (reset) machine state */
if (nb_option_roms) {
@@ -265,7 +265,7 @@ static void palmte_init(ram_addr_t ram_size,
palmte_binfo.kernel_filename = kernel_filename;
palmte_binfo.kernel_cmdline = kernel_cmdline;
palmte_binfo.initrd_filename = initrd_filename;
- arm_load_kernel(cpu->env, &palmte_binfo);
+ arm_load_kernel(mpu->cpu, &palmte_binfo);
}
/* FIXME: We shouldn't really be doing this here. The LCD controller
diff --git a/hw/pc.c b/hw/pc.c
index c790bcbfd7..8368701efb 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -926,27 +926,30 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
static void pc_cpu_reset(void *opaque)
{
- CPUX86State *env = opaque;
+ X86CPU *cpu = opaque;
+ CPUX86State *env = &cpu->env;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
env->halted = !cpu_is_bsp(env);
}
-static CPUX86State *pc_new_cpu(const char *cpu_model)
+static X86CPU *pc_new_cpu(const char *cpu_model)
{
+ X86CPU *cpu;
CPUX86State *env;
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_x86_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find x86 CPU definition\n");
exit(1);
}
+ env = &cpu->env;
if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {
env->apic_state = apic_init(env, env->cpuid_apic_id);
}
- qemu_register_reset(pc_cpu_reset, env);
- pc_cpu_reset(env);
- return env;
+ qemu_register_reset(pc_cpu_reset, cpu);
+ pc_cpu_reset(cpu);
+ return cpu;
}
void pc_cpus_init(const char *cpu_model)
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index c55d8b9396..61257f457b 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -39,6 +39,7 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
const char *devaddr,
const char *opts_str)
{
+ Error *local_err = NULL;
QemuOpts *opts;
PCIBus *bus;
int ret, devfn;
@@ -60,9 +61,12 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
qemu_opt_set(opts, "type", "nic");
- ret = net_client_init(mon, opts, 0);
- if (ret < 0)
+ ret = net_client_init(opts, 0, &local_err);
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
return NULL;
+ }
if (nd_table[ret].devaddr) {
monitor_printf(mon, "Parameter addr not supported\n");
return NULL;
diff --git a/hw/pci.c b/hw/pci.c
index d5c664c9cd..9daa0bfb20 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1545,7 +1545,7 @@ PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
DeviceState *dev;
dev = qdev_create(&bus->qbus, name);
- qdev_prop_set_uint32(dev, "addr", devfn);
+ qdev_prop_set_int32(dev, "addr", devfn);
qdev_prop_set_bit(dev, "multifunction", multifunction);
return PCI_DEVICE(dev);
}
diff --git a/hw/pci.h b/hw/pci.h
index c3cacce046..7f223c01e1 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -197,7 +197,7 @@ struct PCIDevice {
/* the following fields are read only */
PCIBus *bus;
- uint32_t devfn;
+ int32_t devfn;
char name[64];
PCIIORegion io_regions[PCI_NUM_REGIONS];
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
index 31a434872d..6a7d0c0bff 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -54,8 +54,10 @@
#define AXIENET_BASEADDR 0x82780000
#define AXIDMA_BASEADDR 0x84600000
-static void machine_cpu_reset(CPUMBState *env)
+static void machine_cpu_reset(MicroBlazeCPU *cpu)
{
+ CPUMBState *env = &cpu->env;
+
env->pvr.regs[10] = 0x0e000000; /* virtex 6 */
/* setup pvr to match kernel setting */
env->pvr.regs[5] |= PVR5_DCACHE_WRITEBACK_MASK;
@@ -75,6 +77,7 @@ petalogix_ml605_init(ram_addr_t ram_size,
{
MemoryRegion *address_space_mem = get_system_memory();
DeviceState *dev;
+ MicroBlazeCPU *cpu;
CPUMBState *env;
DriveInfo *dinfo;
int i;
@@ -87,7 +90,8 @@ petalogix_ml605_init(ram_addr_t ram_size,
if (cpu_model == NULL) {
cpu_model = "microblaze";
}
- env = cpu_init(cpu_model);
+ cpu = cpu_mb_init(cpu_model);
+ env = &cpu->env;
/* Attach emulated BRAM through the LMB. */
memory_region_init_ram(phys_lmb_bram, "petalogix_ml605.lmb_bram",
@@ -119,7 +123,7 @@ petalogix_ml605_init(ram_addr_t ram_size,
irq[5], 115200, serial_hds[0], DEVICE_LITTLE_ENDIAN);
/* 2 timers at irq 2 @ 100 Mhz. */
- xilinx_timer_create(TIMER_BASEADDR, irq[2], 2, 100 * 1000000);
+ xilinx_timer_create(TIMER_BASEADDR, irq[2], 0, 100 * 1000000);
/* axi ethernet and dma initialization. TODO: Dynamically connect them. */
{
@@ -131,7 +135,7 @@ petalogix_ml605_init(ram_addr_t ram_size,
irq[1], irq[0], 100 * 1000000);
}
- microblaze_load_kernel(env, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE,
+ microblaze_load_kernel(cpu, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE,
machine_cpu_reset);
}
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 8b37336001..2cf68828ed 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -49,8 +49,10 @@
#define UARTLITE_BASEADDR 0x84000000
#define ETHLITE_BASEADDR 0x81000000
-static void machine_cpu_reset(CPUMBState *env)
+static void machine_cpu_reset(MicroBlazeCPU *cpu)
{
+ CPUMBState *env = &cpu->env;
+
env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family. */
}
@@ -62,6 +64,7 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
const char *initrd_filename, const char *cpu_model)
{
DeviceState *dev;
+ MicroBlazeCPU *cpu;
CPUMBState *env;
DriveInfo *dinfo;
int i;
@@ -75,7 +78,8 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
if (cpu_model == NULL) {
cpu_model = "microblaze";
}
- env = cpu_init(cpu_model);
+ cpu = cpu_mb_init(cpu_model);
+ env = &cpu->env;
/* Attach emulated BRAM through the LMB. */
memory_region_init_ram(phys_lmb_bram,
@@ -100,12 +104,12 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
irq[i] = qdev_get_gpio_in(dev, i);
}
- sysbus_create_simple("xilinx,uartlite", UARTLITE_BASEADDR, irq[3]);
+ sysbus_create_simple("xlnx.xps-uartlite", UARTLITE_BASEADDR, irq[3]);
/* 2 timers at irq 2 @ 62 Mhz. */
- xilinx_timer_create(TIMER_BASEADDR, irq[0], 2, 62 * 1000000);
+ xilinx_timer_create(TIMER_BASEADDR, irq[0], 0, 62 * 1000000);
xilinx_ethlite_create(&nd_table[0], ETHLITE_BASEADDR, irq[1], 0, 0);
- microblaze_load_kernel(env, ddr_base, ram_size,
+ microblaze_load_kernel(cpu, ddr_base, ram_size,
BINARY_DEVICE_TREE_FILE, machine_cpu_reset);
}
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
new file mode 100644
index 0000000000..44a1e8cdab
--- /dev/null
+++ b/hw/ppc/Makefile.objs
@@ -0,0 +1,28 @@
+# shared objects
+obj-y = ppc.o ppc_booke.o
+# PREP target
+obj-y += mc146818rtc.o
+obj-y += ppc_prep.o
+# OldWorld PowerMac
+obj-y += ppc_oldworld.o
+# NewWorld PowerMac
+obj-y += ppc_newworld.o
+# IBM pSeries (sPAPR)
+obj-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
+obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
+obj-$(CONFIG_PSERIES) += spapr_pci.o pci-hotplug.o
+# PowerPC 4xx boards
+obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
+obj-y += ppc440_bamboo.o
+# PowerPC E500 boards
+obj-y += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o
+# PowerPC 440 Xilinx ML507 reference board.
+obj-y += virtex_ml507.o
+# PowerPC OpenPIC
+obj-y += openpic.o
+obj-$(CONFIG_FDT) += ../device_tree.o
+
+# Xilinx PPC peripherals
+obj-y += xilinx_ethlite.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index f0a3ae49e6..0dd4dab318 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -145,9 +145,10 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env,
static void main_cpu_reset(void *opaque)
{
- CPUPPCState *env = opaque;
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
env->gpr[1] = (16<<20) - 8;
env->gpr[3] = FDT_ADDR;
env->nip = entry;
@@ -172,6 +173,7 @@ static void bamboo_init(ram_addr_t ram_size,
qemu_irq *pic;
qemu_irq *irqs;
PCIBus *pcibus;
+ PowerPCCPU *cpu;
CPUPPCState *env;
uint64_t elf_entry;
uint64_t elf_lowaddr;
@@ -185,13 +187,14 @@ static void bamboo_init(ram_addr_t ram_size,
if (cpu_model == NULL) {
cpu_model = "440EP";
}
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_ppc_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to initialize CPU!\n");
exit(1);
}
+ env = &cpu->env;
- qemu_register_reset(main_cpu_reset, env);
+ qemu_register_reset(main_cpu_reset, cpu);
ppc_booke_timers_init(env, 400000000, 0);
ppc_dcr_init(env, NULL, NULL);
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 00e36f4109..41163e607d 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -40,9 +40,9 @@
static void ppc4xx_reset(void *opaque)
{
- CPUPPCState *env = opaque;
+ PowerPCCPU *cpu = opaque;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
}
/*****************************************************************************/
@@ -51,15 +51,18 @@ CPUPPCState *ppc4xx_init (const char *cpu_model,
clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
uint32_t sysclk)
{
+ PowerPCCPU *cpu;
CPUPPCState *env;
/* init CPUs */
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_ppc_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find PowerPC %s CPU definition\n",
cpu_model);
exit(1);
}
+ env = &cpu->env;
+
cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
cpu_clk->opaque = env;
/* Set time-base frequency to sysclk */
@@ -67,7 +70,7 @@ CPUPPCState *ppc4xx_init (const char *cpu_model,
tb_clk->opaque = env;
ppc_dcr_init(env, NULL, NULL);
/* Register qemu callbacks */
- qemu_register_reset(ppc4xx_reset, env);
+ qemu_register_reset(ppc4xx_reset, cpu);
return env;
}
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 879651018b..4e2a6e691b 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -123,9 +123,9 @@ static target_phys_addr_t round_page(target_phys_addr_t addr)
static void ppc_core99_reset(void *opaque)
{
- CPUPPCState *env = opaque;
+ PowerPCCPU *cpu = opaque;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
}
/* PowerPC Mac99 hardware initialisation */
@@ -136,6 +136,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
const char *initrd_filename,
const char *cpu_model)
{
+ PowerPCCPU *cpu = NULL;
CPUPPCState *env = NULL;
char *filename;
qemu_irq *pic, **openpic_irqs;
@@ -166,14 +167,16 @@ static void ppc_core99_init (ram_addr_t ram_size,
cpu_model = "G4";
#endif
for (i = 0; i < smp_cpus; i++) {
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_ppc_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find PowerPC CPU definition\n");
exit(1);
}
+ env = &cpu->env;
+
/* Set time-base frequency to 100 Mhz */
cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
- qemu_register_reset(ppc_core99_reset, env);
+ qemu_register_reset(ppc_core99_reset, cpu);
}
/* allocate RAM */
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 7e73d37c34..f2c6908534 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -67,9 +67,9 @@ static target_phys_addr_t round_page(target_phys_addr_t addr)
static void ppc_heathrow_reset(void *opaque)
{
- CPUPPCState *env = opaque;
+ PowerPCCPU *cpu = opaque;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
}
static void ppc_heathrow_init (ram_addr_t ram_size,
@@ -80,6 +80,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
const char *cpu_model)
{
MemoryRegion *sysmem = get_system_memory();
+ PowerPCCPU *cpu = NULL;
CPUPPCState *env = NULL;
char *filename;
qemu_irq *pic, **heathrow_irqs;
@@ -104,14 +105,16 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
if (cpu_model == NULL)
cpu_model = "G3";
for (i = 0; i < smp_cpus; i++) {
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_ppc_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find PowerPC CPU definition\n");
exit(1);
}
+ env = &cpu->env;
+
/* Set time-base frequency to 16.6 Mhz */
cpu_ppc_tb_init(env, 16600000UL);
- qemu_register_reset(ppc_heathrow_reset, env);
+ qemu_register_reset(ppc_heathrow_reset, cpu);
}
/* allocate RAM */
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index b1da114114..be2b26830d 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -441,9 +441,9 @@ static void cpu_request_exit(void *opaque, int irq, int level)
static void ppc_prep_reset(void *opaque)
{
- CPUPPCState *env = opaque;
+ PowerPCCPU *cpu = opaque;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
}
/* PowerPC PREP hardware initialisation */
@@ -455,6 +455,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
const char *cpu_model)
{
MemoryRegion *sysmem = get_system_memory();
+ PowerPCCPU *cpu = NULL;
CPUPPCState *env = NULL;
char *filename;
nvram_t nvram;
@@ -487,11 +488,13 @@ static void ppc_prep_init (ram_addr_t ram_size,
if (cpu_model == NULL)
cpu_model = "602";
for (i = 0; i < smp_cpus; i++) {
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_ppc_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find PowerPC CPU definition\n");
exit(1);
}
+ env = &cpu->env;
+
if (env->flags & POWERPC_FLAG_RTC_CLK) {
/* POWER / PowerPC 601 RTC clock frequency is 7.8125 MHz */
cpu_ppc_tb_init(env, 7812500UL);
@@ -499,7 +502,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
/* Set time-base frequency to 100 Mhz */
cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
}
- qemu_register_reset(ppc_prep_reset, env);
+ qemu_register_reset(ppc_prep_reset, cpu);
}
/* allocate RAM */
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index f1dfbe181c..3eb8a23779 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -196,9 +196,10 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env,
static void mpc8544ds_cpu_reset_sec(void *opaque)
{
- CPUPPCState *env = opaque;
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
/* Secondary CPU starts in halted state for now. Needs to change when
implementing non-kernel boot. */
@@ -208,10 +209,11 @@ static void mpc8544ds_cpu_reset_sec(void *opaque)
static void mpc8544ds_cpu_reset(void *opaque)
{
- CPUPPCState *env = opaque;
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
struct boot_info *bi = env->load_info;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
/* Set initial guest state. */
env->halted = 0;
@@ -254,12 +256,15 @@ static void mpc8544ds_init(ram_addr_t ram_size,
irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
for (i = 0; i < smp_cpus; i++) {
+ PowerPCCPU *cpu;
qemu_irq *input;
- env = cpu_ppc_init(cpu_model);
- if (!env) {
+
+ cpu = cpu_ppc_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to initialize CPU!\n");
exit(1);
}
+ env = &cpu->env;
if (!firstenv) {
firstenv = env;
@@ -278,11 +283,11 @@ static void mpc8544ds_init(ram_addr_t ram_size,
/* Primary CPU */
struct boot_info *boot_info;
boot_info = g_malloc0(sizeof(struct boot_info));
- qemu_register_reset(mpc8544ds_cpu_reset, env);
+ qemu_register_reset(mpc8544ds_cpu_reset, cpu);
env->load_info = boot_info;
} else {
/* Secondary CPUs */
- qemu_register_reset(mpc8544ds_cpu_reset_sec, env);
+ qemu_register_reset(mpc8544ds_cpu_reset_sec, cpu);
}
}
diff --git a/hw/pxa.h b/hw/pxa.h
index 025be34f86..6a2120555f 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -65,7 +65,7 @@
# define PXA2XX_INTERNAL_SIZE 0x40000
/* pxa2xx_pic.c */
-DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUARMState *env);
+DeviceState *pxa2xx_pic_init(target_phys_addr_t base, ARMCPU *cpu);
/* pxa2xx_gpio.c */
DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
@@ -122,7 +122,7 @@ typedef struct PXA2xxI2SState PXA2xxI2SState;
typedef struct PXA2xxFIrState PXA2xxFIrState;
typedef struct {
- CPUARMState *env;
+ ARMCPU *cpu;
DeviceState *pic;
qemu_irq reset;
MemoryRegion sdram;
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index ddaa846882..7958d14003 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -269,24 +269,24 @@ static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
case 1:
/* Idle */
if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) { /* CPDIS */
- cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
+ cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
break;
}
/* Fall through. */
case 2:
/* Deep-Idle */
- cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
+ cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
goto message;
case 3:
- s->env->uncached_cpsr =
+ s->cpu->env.uncached_cpsr =
ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
- s->env->cp15.c1_sys = 0;
- s->env->cp15.c1_coproc = 0;
- s->env->cp15.c2_base0 = 0;
- s->env->cp15.c3 = 0;
+ s->cpu->env.cp15.c1_sys = 0;
+ s->cpu->env.cp15.c1_coproc = 0;
+ s->cpu->env.cp15.c2_base0 = 0;
+ s->cpu->env.cp15.c3 = 0;
s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
@@ -296,8 +296,8 @@ static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
* lack of a resuming bootloader, perform a jump
* directly to that address.
*/
- memset(s->env->regs, 0, 4 * 15);
- s->env->regs[15] = s->pm_regs[PSPR >> 2];
+ memset(s->cpu->env.regs, 0, 4 * 15);
+ s->cpu->env.regs[15] = s->pm_regs[PSPR >> 2];
#if 0
buffer = 0xe59ff000; /* ldr pc, [pc, #0] */
@@ -2044,7 +2044,7 @@ static void pxa2xx_reset(void *opaque, int line, int level)
PXA2xxState *s = (PXA2xxState *) opaque;
if (level && (s->pm_regs[PCFR >> 2] & 0x10)) { /* GPR_EN */
- cpu_state_reset(s->env);
+ cpu_reset(CPU(s->cpu));
/* TODO: reset peripherals */
}
}
@@ -2065,8 +2065,8 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
if (!revision)
revision = "pxa270";
- s->env = cpu_init(revision);
- if (!s->env) {
+ s->cpu = cpu_arm_init(revision);
+ if (s->cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
@@ -2081,7 +2081,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
&s->internal);
- s->pic = pxa2xx_pic_init(0x40d00000, s->env);
+ s->pic = pxa2xx_pic_init(0x40d00000, s->cpu);
s->dma = pxa27x_dma_init(0x40000000,
qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
@@ -2094,7 +2094,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
qdev_get_gpio_in(s->pic, PXA27X_PIC_OST_4_11),
NULL);
- s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 121);
+ s->gpio = pxa2xx_gpio_init(0x40e00000, &s->cpu->env, s->pic, 121);
dinfo = drive_get(IF_SD, 0, 0);
if (!dinfo) {
@@ -2133,7 +2133,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
- cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
+ cpu_arm_set_cp_io(&s->cpu->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
s->mm_base = 0x48000000;
s->mm_regs[MDMRS >> 2] = 0x00020002;
@@ -2196,8 +2196,8 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
- s->env = cpu_init("pxa255");
- if (!s->env) {
+ s->cpu = cpu_arm_init("pxa255");
+ if (s->cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
@@ -2213,7 +2213,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
&s->internal);
- s->pic = pxa2xx_pic_init(0x40d00000, s->env);
+ s->pic = pxa2xx_pic_init(0x40d00000, s->cpu);
s->dma = pxa255_dma_init(0x40000000,
qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
@@ -2225,7 +2225,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 3),
NULL);
- s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 85);
+ s->gpio = pxa2xx_gpio_init(0x40e00000, &s->cpu->env, s->pic, 85);
dinfo = drive_get(IF_SD, 0, 0);
if (!dinfo) {
@@ -2264,7 +2264,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
- cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
+ cpu_arm_set_cp_io(&s->cpu->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
s->mm_base = 0x48000000;
s->mm_regs[MDMRS >> 2] = 0x00020002;
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 09a408b781..3c90c9c4e0 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -20,7 +20,7 @@ struct PXA2xxGPIOInfo {
qemu_irq irq0, irq1, irqX;
int lines;
int ncpu;
- CPUARMState *cpu_env;
+ ARMCPU *cpu;
/* XXX: GNU C vectors are more suitable */
uint32_t ilevel[PXA2XX_GPIO_BANKS];
@@ -118,8 +118,9 @@ static void pxa2xx_gpio_set(void *opaque, int line, int level)
pxa2xx_gpio_irq_update(s);
/* Wake-up GPIOs */
- if (s->cpu_env->halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank]))
- cpu_interrupt(s->cpu_env, CPU_INTERRUPT_EXITTB);
+ if (s->cpu->env.halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
+ cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+ }
}
static void pxa2xx_gpio_handler_update(PXA2xxGPIOInfo *s) {
@@ -275,7 +276,7 @@ static int pxa2xx_gpio_initfn(SysBusDevice *dev)
s = FROM_SYSBUS(PXA2xxGPIOInfo, dev);
- s->cpu_env = qemu_get_cpu(s->ncpu);
+ s->cpu = arm_env_get_cpu(qemu_get_cpu(s->ncpu));
qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines);
qdev_init_gpio_out(&dev->qdev, s->handler, s->lines);
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index a806b80b0f..c560133930 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -34,7 +34,7 @@
typedef struct {
SysBusDevice busdev;
MemoryRegion iomem;
- CPUARMState *cpu_env;
+ ARMCPU *cpu;
uint32_t int_enabled[2];
uint32_t int_pending[2];
uint32_t is_fiq[2];
@@ -47,25 +47,28 @@ static void pxa2xx_pic_update(void *opaque)
uint32_t mask[2];
PXA2xxPICState *s = (PXA2xxPICState *) opaque;
- if (s->cpu_env->halted) {
+ if (s->cpu->env.halted) {
mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle);
mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle);
- if (mask[0] || mask[1])
- cpu_interrupt(s->cpu_env, CPU_INTERRUPT_EXITTB);
+ if (mask[0] || mask[1]) {
+ cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+ }
}
mask[0] = s->int_pending[0] & s->int_enabled[0];
mask[1] = s->int_pending[1] & s->int_enabled[1];
- if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1]))
- cpu_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
- else
- cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
+ if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1])) {
+ cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
+ } else {
+ cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
+ }
- if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1]))
- cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
- else
- cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+ if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1])) {
+ cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+ }
}
/* Note: Here level means state of the signal on a pin, not
@@ -245,12 +248,13 @@ static int pxa2xx_pic_post_load(void *opaque, int version_id)
return 0;
}
-DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUARMState *env)
+DeviceState *pxa2xx_pic_init(target_phys_addr_t base, ARMCPU *cpu)
{
+ CPUARMState *env = &cpu->env;
DeviceState *dev = qdev_create(NULL, "pxa2xx_pic");
PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, sysbus_from_qdev(dev));
- s->cpu_env = env;
+ s->cpu = cpu;
s->int_pending[0] = 0;
s->int_pending[1] = 0;
diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c
index 0bb16c7eb3..b711b6bf96 100644
--- a/hw/qdev-addr.c
+++ b/hw/qdev-addr.c
@@ -27,7 +27,7 @@ static void get_taddr(Object *obj, Visitor *v, void *opaque,
int64_t value;
value = *ptr;
- visit_type_int(v, &value, name, errp);
+ visit_type_int64(v, &value, name, errp);
}
static void set_taddr(Object *obj, Visitor *v, void *opaque,
@@ -44,7 +44,7 @@ static void set_taddr(Object *obj, Visitor *v, void *opaque,
return;
}
- visit_type_int(v, &value, name, &local_err);
+ visit_type_int64(v, &value, name, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
index eed781d2f0..b01ef0600e 100644
--- a/hw/qdev-monitor.c
+++ b/hw/qdev-monitor.c
@@ -554,10 +554,13 @@ void do_info_qdm(Monitor *mon)
int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
+ Error *local_err = NULL;
QemuOpts *opts;
- opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
- if (!opts) {
+ opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
return -1;
}
if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index b7b5597c62..9ae318717e 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -76,52 +76,35 @@ PropertyInfo qdev_prop_bit = {
/* --- 8bit integer --- */
-static void get_int8(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void get_uint8(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
- int8_t *ptr = qdev_get_prop_ptr(dev, prop);
- int64_t value;
+ uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
- value = *ptr;
- visit_type_int(v, &value, name, errp);
+ visit_type_uint8(v, ptr, name, errp);
}
-static void set_int8(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void set_uint8(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
- int8_t *ptr = qdev_get_prop_ptr(dev, prop);
- Error *local_err = NULL;
- int64_t value;
+ uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
if (dev->state != DEV_STATE_CREATED) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
- visit_type_int(v, &value, name, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- if (value >= prop->info->min && value <= prop->info->max) {
- *ptr = value;
- } else {
- error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
- dev->id?:"", name, value, prop->info->min,
- prop->info->max);
- }
+ visit_type_uint8(v, ptr, name, errp);
}
PropertyInfo qdev_prop_uint8 = {
.name = "uint8",
- .get = get_int8,
- .set = set_int8,
- .min = 0,
- .max = 255,
+ .get = get_uint8,
+ .set = set_uint8,
};
/* --- 8bit hex value --- */
@@ -154,74 +137,78 @@ PropertyInfo qdev_prop_hex8 = {
.legacy_name = "hex8",
.parse = parse_hex8,
.print = print_hex8,
- .get = get_int8,
- .set = set_int8,
- .min = 0,
- .max = 255,
+ .get = get_uint8,
+ .set = set_uint8,
};
/* --- 16bit integer --- */
-static void get_int16(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void get_uint16(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
- int16_t *ptr = qdev_get_prop_ptr(dev, prop);
- int64_t value;
+ uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
- value = *ptr;
- visit_type_int(v, &value, name, errp);
+ visit_type_uint16(v, ptr, name, errp);
}
-static void set_int16(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void set_uint16(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
- int16_t *ptr = qdev_get_prop_ptr(dev, prop);
- Error *local_err = NULL;
- int64_t value;
+ uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
if (dev->state != DEV_STATE_CREATED) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
- visit_type_int(v, &value, name, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- if (value >= prop->info->min && value <= prop->info->max) {
- *ptr = value;
- } else {
- error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
- dev->id?:"", name, value, prop->info->min,
- prop->info->max);
- }
+ visit_type_uint16(v, ptr, name, errp);
}
PropertyInfo qdev_prop_uint16 = {
.name = "uint16",
- .get = get_int16,
- .set = set_int16,
- .min = 0,
- .max = 65535,
+ .get = get_uint16,
+ .set = set_uint16,
};
/* --- 32bit integer --- */
+static void get_uint32(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
+
+ visit_type_uint32(v, ptr, name, errp);
+}
+
+static void set_uint32(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
+
+ if (dev->state != DEV_STATE_CREATED) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ visit_type_uint32(v, ptr, name, errp);
+}
+
static void get_int32(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
int32_t *ptr = qdev_get_prop_ptr(dev, prop);
- int64_t value;
- value = *ptr;
- visit_type_int(v, &value, name, errp);
+ visit_type_int32(v, ptr, name, errp);
}
static void set_int32(Object *obj, Visitor *v, void *opaque,
@@ -230,42 +217,25 @@ static void set_int32(Object *obj, Visitor *v, void *opaque,
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
int32_t *ptr = qdev_get_prop_ptr(dev, prop);
- Error *local_err = NULL;
- int64_t value;
if (dev->state != DEV_STATE_CREATED) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
- visit_type_int(v, &value, name, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- if (value >= prop->info->min && value <= prop->info->max) {
- *ptr = value;
- } else {
- error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
- dev->id?:"", name, value, prop->info->min,
- prop->info->max);
- }
+ visit_type_int32(v, ptr, name, errp);
}
PropertyInfo qdev_prop_uint32 = {
.name = "uint32",
- .get = get_int32,
- .set = set_int32,
- .min = 0,
- .max = 0xFFFFFFFFULL,
+ .get = get_uint32,
+ .set = set_uint32,
};
PropertyInfo qdev_prop_int32 = {
.name = "int32",
.get = get_int32,
.set = set_int32,
- .min = -0x80000000LL,
- .max = 0x7FFFFFFFLL,
};
/* --- 32bit hex value --- */
@@ -298,43 +268,41 @@ PropertyInfo qdev_prop_hex32 = {
.legacy_name = "hex32",
.parse = parse_hex32,
.print = print_hex32,
- .get = get_int32,
- .set = set_int32,
- .min = 0,
- .max = 0xFFFFFFFFULL,
+ .get = get_uint32,
+ .set = set_uint32,
};
/* --- 64bit integer --- */
-static void get_int64(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void get_uint64(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
- int64_t *ptr = qdev_get_prop_ptr(dev, prop);
+ uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
- visit_type_int(v, ptr, name, errp);
+ visit_type_uint64(v, ptr, name, errp);
}
-static void set_int64(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void set_uint64(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
- int64_t *ptr = qdev_get_prop_ptr(dev, prop);
+ uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
if (dev->state != DEV_STATE_CREATED) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
- visit_type_int(v, ptr, name, errp);
+ visit_type_uint64(v, ptr, name, errp);
}
PropertyInfo qdev_prop_uint64 = {
.name = "uint64",
- .get = get_int64,
- .set = set_int64,
+ .get = get_uint64,
+ .set = set_uint64,
};
/* --- 64bit hex value --- */
@@ -367,8 +335,8 @@ PropertyInfo qdev_prop_hex64 = {
.legacy_name = "hex64",
.parse = parse_hex64,
.print = print_hex64,
- .get = get_int64,
- .set = set_int64,
+ .get = get_uint64,
+ .set = set_uint64,
};
/* --- string --- */
@@ -645,7 +613,7 @@ static void get_vlan(Object *obj, Visitor *v, void *opaque,
int64_t id;
id = *ptr ? (*ptr)->id : -1;
- visit_type_int(v, &id, name, errp);
+ visit_type_int64(v, &id, name, errp);
}
static void set_vlan(Object *obj, Visitor *v, void *opaque,
@@ -663,7 +631,7 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque,
return;
}
- visit_type_int(v, &id, name, &local_err);
+ visit_type_int64(v, &id, name, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -824,7 +792,7 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
- uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
+ int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
unsigned int slot, fn, n;
Error *local_err = NULL;
char *str;
@@ -837,7 +805,17 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
visit_type_str(v, &str, name, &local_err);
if (local_err) {
error_free(local_err);
- return set_int32(obj, v, opaque, name, errp);
+ local_err = NULL;
+ visit_type_int32(v, &value, name, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ } else if (value < -1 || value > 255) {
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "pci_devfn");
+ } else {
+ *ptr = value;
+ }
+ return;
}
if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
@@ -860,7 +838,7 @@ invalid:
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
{
- uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
+ int32_t *ptr = qdev_get_prop_ptr(dev, prop);
if (*ptr == -1) {
return snprintf(dest, len, "<unset>");
@@ -875,11 +853,6 @@ PropertyInfo qdev_prop_pci_devfn = {
.print = print_pci_devfn,
.get = get_int32,
.set = set_pci_devfn,
- /* FIXME: this should be -1...255, but the address is stored
- * into an uint32_t rather than int32_t.
- */
- .min = 0,
- .max = 0xFFFFFFFFULL,
};
/* --- blocksize --- */
@@ -889,31 +862,31 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
- int16_t *ptr = qdev_get_prop_ptr(dev, prop);
+ uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
Error *local_err = NULL;
- int64_t value;
+ const int64_t min = 512;
+ const int64_t max = 32768;
if (dev->state != DEV_STATE_CREATED) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
- visit_type_int(v, &value, name, &local_err);
+ visit_type_uint16(v, &value, name, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
- if (value < prop->info->min || value > prop->info->max) {
+ if (value < min || value > max) {
error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
- dev->id?:"", name, value, prop->info->min,
- prop->info->max);
+ dev->id?:"", name, (int64_t)value, min, max);
return;
}
/* We rely on power-of-2 blocksizes for bitmasks */
if ((value & (value - 1)) != 0) {
error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
- dev->id?:"", name, value);
+ dev->id?:"", name, (int64_t)value);
return;
}
@@ -922,10 +895,8 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
PropertyInfo qdev_prop_blocksize = {
.name = "blocksize",
- .get = get_int16,
+ .get = get_uint16,
.set = set_blocksize,
- .min = 512,
- .max = 65024,
};
/* --- public helpers --- */
diff --git a/hw/qdev.h b/hw/qdev.h
index 4e90119471..5386b165bc 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -122,8 +122,6 @@ struct PropertyInfo {
const char *name;
const char *legacy_name;
const char **enum_table;
- int64_t min;
- int64_t max;
int (*parse)(DeviceState *dev, Property *prop, const char *str);
int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
ObjectPropertyAccessor *get;
@@ -267,7 +265,7 @@ extern PropertyInfo qdev_prop_blocksize;
#define DEFINE_PROP_HEX64(_n, _s, _f, _d) \
DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t)
#define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, uint32_t)
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
#define DEFINE_PROP_PTR(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*)
diff --git a/hw/r2d.c b/hw/r2d.c
index c55de0141b..0f16e81afe 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -192,16 +192,16 @@ static qemu_irq *r2d_fpga_init(MemoryRegion *sysmem,
}
typedef struct ResetData {
- CPUSH4State *env;
+ SuperHCPU *cpu;
uint32_t vector;
} ResetData;
static void main_cpu_reset(void *opaque)
{
ResetData *s = (ResetData *)opaque;
- CPUSH4State *env = s->env;
+ CPUSH4State *env = &s->cpu->env;
- cpu_state_reset(env);
+ cpu_reset(CPU(s->cpu));
env->pc = s->vector;
}
@@ -224,6 +224,7 @@ static void r2d_init(ram_addr_t ram_size,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
+ SuperHCPU *cpu;
CPUSH4State *env;
ResetData *reset_info;
struct SH7750State *s;
@@ -235,16 +236,19 @@ static void r2d_init(ram_addr_t ram_size,
SysBusDevice *busdev;
MemoryRegion *address_space_mem = get_system_memory();
- if (!cpu_model)
+ if (cpu_model == NULL) {
cpu_model = "SH7751R";
+ }
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_sh4_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+ env = &cpu->env;
+
reset_info = g_malloc0(sizeof(ResetData));
- reset_info->env = env;
+ reset_info->cpu = cpu;
reset_info->vector = env->pc;
qemu_register_reset(main_cpu_reset, reset_info);
diff --git a/hw/realview.c b/hw/realview.c
index ecf470179a..19db4d026b 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -50,7 +50,8 @@ static void realview_init(ram_addr_t ram_size,
const char *initrd_filename, const char *cpu_model,
enum realview_board_type board_type)
{
- CPUARMState *env = NULL;
+ ARMCPU *cpu = NULL;
+ CPUARMState *env;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
@@ -88,14 +89,15 @@ static void realview_init(ram_addr_t ram_size,
break;
}
for (n = 0; n < smp_cpus; n++) {
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_arm_init(cpu_model);
+ if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- irqp = arm_pic_init_cpu(env);
+ irqp = arm_pic_init_cpu(cpu);
cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
}
+ env = &cpu->env;
if (arm_feature(env, ARM_FEATURE_V7)) {
if (is_mpcore) {
proc_id = 0x0c000000;
@@ -325,7 +327,7 @@ static void realview_init(ram_addr_t ram_size,
realview_binfo.nb_cpus = smp_cpus;
realview_binfo.board_id = realview_board_id[board_type];
realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
- arm_load_kernel(first_cpu, &realview_binfo);
+ arm_load_kernel(arm_env_get_cpu(first_cpu), &realview_binfo);
}
static void realview_eb_init(ram_addr_t ram_size,
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 060404c137..f6f144b525 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -791,6 +791,9 @@ static int rtl8139_can_receive(VLANClientState *nc)
return 1;
if (!rtl8139_receiver_enabled(s))
return 1;
+ /* network/host communication happens only in normal mode */
+ if ((s->Cfg9346 & Chip9346_op_mask) != Cfg9346_Normal)
+ return 0;
if (rtl8139_cp_receiver_enabled(s)) {
/* ??? Flow control not implemented in c+ mode.
@@ -833,6 +836,12 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
return -1;
}
+ /* check whether we are in normal mode */
+ if ((s->Cfg9346 & Chip9346_op_mask) != Cfg9346_Normal) {
+ DPRINTF("not in normal op mode\n");
+ return -1;
+ }
+
/* XXX: check this */
if (s->RxConfig & AcceptAllPhys) {
/* promiscuous: receive all */
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 1d38a8f5c5..23ef35b3bb 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -140,7 +140,8 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
s390_virtio_device_sync(dev);
s390_virtio_reset_idx(dev);
if (dev->qdev.hotplugged) {
- CPUS390XState *env = s390_cpu_addr2state(0);
+ S390CPU *cpu = s390_cpu_addr2state(0);
+ CPUS390XState *env = &cpu->env;
s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
}
@@ -354,7 +355,8 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
{
VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
uint64_t token = s390_virtio_device_vq_token(dev, vector);
- CPUS390XState *env = s390_cpu_addr2state(0);
+ S390CPU *cpu = s390_cpu_addr2state(0);
+ CPUS390XState *env = &cpu->env;
s390_virtio_irq(env, 0, token);
}
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index c0e19fd66d..47eed35da3 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -61,9 +61,9 @@
#define MAX_BLK_DEVS 10
static VirtIOS390Bus *s390_bus;
-static CPUS390XState **ipi_states;
+static S390CPU **ipi_states;
-CPUS390XState *s390_cpu_addr2state(uint16_t cpu_addr)
+S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
{
if (cpu_addr >= smp_cpus) {
return NULL;
@@ -206,16 +206,18 @@ static void s390_init(ram_addr_t my_ram_size,
cpu_model = "host";
}
- ipi_states = g_malloc(sizeof(CPUS390XState *) * smp_cpus);
+ ipi_states = g_malloc(sizeof(S390CPU *) * smp_cpus);
for (i = 0; i < smp_cpus; i++) {
+ S390CPU *cpu;
CPUS390XState *tmp_env;
- tmp_env = cpu_init(cpu_model);
+ cpu = cpu_s390x_init(cpu_model);
+ tmp_env = &cpu->env;
if (!env) {
env = tmp_env;
}
- ipi_states[i] = tmp_env;
+ ipi_states[i] = cpu;
tmp_env->halted = 1;
tmp_env->exception_index = EXCP_HLT;
tmp_env->storage_keys = storage_keys;
diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
new file mode 100644
index 0000000000..dcdcac8a81
--- /dev/null
+++ b/hw/s390x/Makefile.objs
@@ -0,0 +1,3 @@
+obj-y = s390-virtio-bus.o s390-virtio.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index f10f3ec25c..4a798210ce 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1507,10 +1507,9 @@ static void put_scsi_requests(QEMUFile *f, void *pv, size_t size)
QTAILQ_FOREACH(req, &s->requests, next) {
assert(!req->io_canceled);
assert(req->status == -1);
- assert(req->retry);
assert(req->enqueued);
- qemu_put_sbyte(f, 1);
+ qemu_put_sbyte(f, req->retry ? 1 : 2);
qemu_put_buffer(f, req->cmd.buf, sizeof(req->cmd.buf));
qemu_put_be32s(f, &req->tag);
qemu_put_be32s(f, &req->lun);
@@ -1528,8 +1527,9 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
{
SCSIDevice *s = pv;
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
+ int8_t sbyte;
- while (qemu_get_sbyte(f)) {
+ while ((sbyte = qemu_get_sbyte(f)) > 0) {
uint8_t buf[SCSI_CMD_BUF_SIZE];
uint32_t tag;
uint32_t lun;
@@ -1539,6 +1539,7 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
qemu_get_be32s(f, &tag);
qemu_get_be32s(f, &lun);
req = scsi_req_new(s, tag, lun, buf, NULL);
+ req->retry = (sbyte == 1);
if (bus->info->load_request) {
req->hba_private = bus->info->load_request(f, req);
}
@@ -1547,7 +1548,6 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
}
/* Just restart it later. */
- req->retry = true;
scsi_req_enqueue_internal(req);
/* At this point, the request will be kept alive by the reference
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 045c764d9b..1691491c03 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -132,8 +132,14 @@ static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req)
qemu_put_be64s(f, &r->sector);
qemu_put_be32s(f, &r->sector_count);
qemu_put_be32s(f, &r->buflen);
- if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
- qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
+ if (r->buflen) {
+ if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
+ qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
+ } else if (!req->retry) {
+ uint32_t len = r->iov.iov_len;
+ qemu_put_be32s(f, &len);
+ qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
+ }
}
}
@@ -148,6 +154,12 @@ static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
scsi_init_iovec(r, r->buflen);
if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
+ } else if (!r->req.retry) {
+ uint32_t len;
+ qemu_get_be32s(f, &len);
+ r->iov.iov_len = len;
+ assert(r->iov.iov_len <= r->buflen);
+ qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
}
}
diff --git a/hw/sh4/Makefile.objs b/hw/sh4/Makefile.objs
new file mode 100644
index 0000000000..68c5921790
--- /dev/null
+++ b/hw/sh4/Makefile.objs
@@ -0,0 +1,5 @@
+obj-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
+obj-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
+obj-y += ide/mmio.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/spapr.c b/hw/spapr.c
index cca20f9a51..d0bddbce95 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -505,9 +505,9 @@ static void spapr_reset(void *opaque)
static void spapr_cpu_reset(void *opaque)
{
- CPUPPCState *env = opaque;
+ PowerPCCPU *cpu = opaque;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
}
/* pSeries LPAR / sPAPR hardware init */
@@ -518,6 +518,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
const char *initrd_filename,
const char *cpu_model)
{
+ PowerPCCPU *cpu;
CPUPPCState *env;
int i;
MemoryRegion *sysmem = get_system_memory();
@@ -560,15 +561,16 @@ static void ppc_spapr_init(ram_addr_t ram_size,
cpu_model = kvm_enabled() ? "host" : "POWER7";
}
for (i = 0; i < smp_cpus; i++) {
- env = cpu_init(cpu_model);
-
- if (!env) {
+ cpu = cpu_ppc_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find PowerPC CPU definition\n");
exit(1);
}
+ env = &cpu->env;
+
/* Set time-base frequency to 512 MHz */
cpu_ppc_tb_init(env, TIMEBASE_FREQ);
- qemu_register_reset(spapr_cpu_reset, env);
+ qemu_register_reset(spapr_cpu_reset, cpu);
env->hreset_vector = 0x60;
env->hreset_excp_prefix = 0;
diff --git a/hw/sparc/Makefile.objs b/hw/sparc/Makefile.objs
new file mode 100644
index 0000000000..a39a511c52
--- /dev/null
+++ b/hw/sparc/Makefile.objs
@@ -0,0 +1,8 @@
+obj-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o
+obj-y += slavio_timer.o slavio_misc.o sparc32_dma.o
+obj-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o
+
+# GRLIB
+obj-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/sparc64/Makefile.objs b/hw/sparc64/Makefile.objs
new file mode 100644
index 0000000000..8c65fc4215
--- /dev/null
+++ b/hw/sparc64/Makefile.objs
@@ -0,0 +1,4 @@
+obj-y = sun4u.o apb_pci.o
+obj-y += mc146818rtc.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/spitz.c b/hw/spitz.c
index 1d6d2b0e1b..20e7835191 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -884,7 +884,7 @@ static void spitz_common_init(ram_addr_t ram_size,
const char *kernel_cmdline, const char *initrd_filename,
const char *cpu_model, enum spitz_model_e model, int arm_id)
{
- PXA2xxState *cpu;
+ PXA2xxState *mpu;
DeviceState *scp0, *scp1 = NULL;
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *rom = g_new(MemoryRegion, 1);
@@ -893,9 +893,9 @@ static void spitz_common_init(ram_addr_t ram_size,
cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
/* Setup CPU & memory */
- cpu = pxa270_init(address_space_mem, spitz_binfo.ram_size, cpu_model);
+ mpu = pxa270_init(address_space_mem, spitz_binfo.ram_size, cpu_model);
- sl_flash_register(cpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
+ sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
memory_region_init_ram(rom, "spitz.rom", SPITZ_ROM);
vmstate_register_ram_global(rom);
@@ -903,36 +903,36 @@ static void spitz_common_init(ram_addr_t ram_size,
memory_region_add_subregion(address_space_mem, 0, rom);
/* Setup peripherals */
- spitz_keyboard_register(cpu);
+ spitz_keyboard_register(mpu);
- spitz_ssp_attach(cpu);
+ spitz_ssp_attach(mpu);
scp0 = sysbus_create_simple("scoop", 0x10800000, NULL);
if (model != akita) {
scp1 = sysbus_create_simple("scoop", 0x08800040, NULL);
}
- spitz_scoop_gpio_setup(cpu, scp0, scp1);
+ spitz_scoop_gpio_setup(mpu, scp0, scp1);
- spitz_gpio_setup(cpu, (model == akita) ? 1 : 2);
+ spitz_gpio_setup(mpu, (model == akita) ? 1 : 2);
- spitz_i2c_setup(cpu);
+ spitz_i2c_setup(mpu);
if (model == akita)
- spitz_akita_i2c_setup(cpu);
+ spitz_akita_i2c_setup(mpu);
if (model == terrier)
/* A 6.0 GB microdrive is permanently sitting in CF slot 1. */
- spitz_microdrive_attach(cpu, 1);
+ spitz_microdrive_attach(mpu, 1);
else if (model != akita)
/* A 4.0 GB microdrive is permanently sitting in CF slot 0. */
- spitz_microdrive_attach(cpu, 0);
+ spitz_microdrive_attach(mpu, 0);
spitz_binfo.kernel_filename = kernel_filename;
spitz_binfo.kernel_cmdline = kernel_cmdline;
spitz_binfo.initrd_filename = initrd_filename;
spitz_binfo.board_id = arm_id;
- arm_load_kernel(cpu->env, &spitz_binfo);
+ arm_load_kernel(mpu->cpu, &spitz_binfo);
sl_bootparam_write(SL_PXA_PARAM_BASE);
}
diff --git a/hw/strongarm.c b/hw/strongarm.c
index 1b15f399f1..7150eeb2db 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -1563,9 +1563,9 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
exit(1);
}
- s->env = cpu_init(rev);
+ s->cpu = cpu_arm_init(rev);
- if (!s->env) {
+ if (!s->cpu) {
error_report("Unable to find CPU definition");
exit(1);
}
@@ -1574,7 +1574,7 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
vmstate_register_ram_global(&s->sdram);
memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram);
- pic = arm_pic_init_cpu(s->env);
+ pic = arm_pic_init_cpu(s->cpu);
s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000,
pic[ARM_PIC_CPU_IRQ], pic[ARM_PIC_CPU_FIQ], NULL);
diff --git a/hw/strongarm.h b/hw/strongarm.h
index 02acac3db1..d30dd6ac5e 100644
--- a/hw/strongarm.h
+++ b/hw/strongarm.h
@@ -53,7 +53,7 @@ enum {
};
typedef struct {
- CPUARMState *env;
+ ARMCPU *cpu;
MemoryRegion sdram;
DeviceState *pic;
DeviceState *gpio;
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 34088ad185..a959261209 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -281,17 +281,19 @@ static void dummy_cpu_set_irq(void *opaque, int irq, int level)
static void main_cpu_reset(void *opaque)
{
- CPUSPARCState *env = opaque;
+ SPARCCPU *cpu = opaque;
+ CPUSPARCState *env = &cpu->env;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
env->halted = 0;
}
static void secondary_cpu_reset(void *opaque)
{
- CPUSPARCState *env = opaque;
+ SPARCCPU *cpu = opaque;
+ CPUSPARCState *env = &cpu->env;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
env->halted = 1;
}
@@ -809,19 +811,21 @@ static TypeInfo ram_info = {
static void cpu_devinit(const char *cpu_model, unsigned int id,
uint64_t prom_addr, qemu_irq **cpu_irqs)
{
+ SPARCCPU *cpu;
CPUSPARCState *env;
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_sparc_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
exit(1);
}
+ env = &cpu->env;
cpu_sparc_set_id(env, id);
if (id == 0) {
- qemu_register_reset(main_cpu_reset, env);
+ qemu_register_reset(main_cpu_reset, cpu);
} else {
- qemu_register_reset(secondary_cpu_reset, env);
+ qemu_register_reset(secondary_cpu_reset, cpu);
env->halted = 1;
}
*cpu_irqs = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 517bdb818d..137a7c6666 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -342,7 +342,7 @@ static void cpu_set_ivec_irq(void *opaque, int irq, int level)
}
typedef struct ResetData {
- CPUSPARCState *env;
+ SPARCCPU *cpu;
uint64_t prom_addr;
} ResetData;
@@ -395,10 +395,10 @@ static void cpu_timer_reset(CPUTimer *timer)
static void main_cpu_reset(void *opaque)
{
ResetData *s = (ResetData *)opaque;
- CPUSPARCState *env = s->env;
+ CPUSPARCState *env = &s->cpu->env;
static unsigned int nr_resets;
- cpu_state_reset(env);
+ cpu_reset(CPU(s->cpu));
cpu_timer_reset(env->tick);
cpu_timer_reset(env->stick);
@@ -752,8 +752,9 @@ static TypeInfo ram_info = {
.class_init = ram_class_init,
};
-static CPUSPARCState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
+static SPARCCPU *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
{
+ SPARCCPU *cpu;
CPUSPARCState *env;
ResetData *reset_info;
@@ -761,13 +762,15 @@ static CPUSPARCState *cpu_devinit(const char *cpu_model, const struct hwdef *hwd
uint32_t stick_frequency = 100*1000000;
uint32_t hstick_frequency = 100*1000000;
- if (!cpu_model)
+ if (cpu_model == NULL) {
cpu_model = hwdef->default_cpu_model;
- env = cpu_init(cpu_model);
- if (!env) {
+ }
+ cpu = cpu_sparc_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find Sparc CPU definition\n");
exit(1);
}
+ env = &cpu->env;
env->tick = cpu_timer_create("tick", env, tick_irq,
tick_frequency, TICK_NPT_MASK);
@@ -779,11 +782,11 @@ static CPUSPARCState *cpu_devinit(const char *cpu_model, const struct hwdef *hwd
hstick_frequency, TICK_INT_DIS);
reset_info = g_malloc0(sizeof(ResetData));
- reset_info->env = env;
+ reset_info->cpu = cpu;
reset_info->prom_addr = hwdef->prom_addr;
qemu_register_reset(main_cpu_reset, reset_info);
- return env;
+ return cpu;
}
static void sun4uv_init(MemoryRegion *address_space_mem,
@@ -793,6 +796,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
const char *initrd_filename, const char *cpu_model,
const struct hwdef *hwdef)
{
+ SPARCCPU *cpu;
CPUSPARCState *env;
M48t59State *nvram;
unsigned int i;
@@ -805,7 +809,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
void *fw_cfg;
/* init CPUs */
- env = cpu_devinit(cpu_model, hwdef);
+ cpu = cpu_devinit(cpu_model, hwdef);
+ env = &cpu->env;
/* set up devices */
ram_init(0, RAM_size);
diff --git a/hw/tosa.c b/hw/tosa.c
index 6baa17d6b5..297a8c2ed0 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -212,14 +212,14 @@ static void tosa_init(ram_addr_t ram_size,
{
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *rom = g_new(MemoryRegion, 1);
- PXA2xxState *cpu;
+ PXA2xxState *mpu;
TC6393xbState *tmio;
DeviceState *scp0, *scp1;
if (!cpu_model)
cpu_model = "pxa255";
- cpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
+ mpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
memory_region_init_ram(rom, "tosa.rom", TOSA_ROM);
vmstate_register_ram_global(rom);
@@ -227,22 +227,22 @@ static void tosa_init(ram_addr_t ram_size,
memory_region_add_subregion(address_space_mem, 0, rom);
tmio = tc6393xb_init(address_space_mem, 0x10000000,
- qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_TC6393XB_INT));
+ qdev_get_gpio_in(mpu->gpio, TOSA_GPIO_TC6393XB_INT));
scp0 = sysbus_create_simple("scoop", 0x08800000, NULL);
scp1 = sysbus_create_simple("scoop", 0x14800040, NULL);
- tosa_gpio_setup(cpu, scp0, scp1, tmio);
+ tosa_gpio_setup(mpu, scp0, scp1, tmio);
- tosa_microdrive_attach(cpu);
+ tosa_microdrive_attach(mpu);
- tosa_tg_init(cpu);
+ tosa_tg_init(mpu);
tosa_binfo.kernel_filename = kernel_filename;
tosa_binfo.kernel_cmdline = kernel_cmdline;
tosa_binfo.initrd_filename = initrd_filename;
tosa_binfo.board_id = 0x208;
- arm_load_kernel(cpu->env, &tosa_binfo);
+ arm_load_kernel(mpu->cpu, &tosa_binfo);
sl_bootparam_write(SL_PXA_PARAM_BASE);
}
diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
new file mode 100644
index 0000000000..9c7ddf5cb2
--- /dev/null
+++ b/hw/usb/Makefile.objs
@@ -0,0 +1,13 @@
+hw-obj-$(CONFIG_USB_UHCI) += hcd-uhci.o
+hw-obj-$(CONFIG_USB_OHCI) += hcd-ohci.o
+hw-obj-$(CONFIG_USB_EHCI) += hcd-ehci.o
+hw-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o
+hw-obj-y += libhw.o
+
+hw-obj-$(CONFIG_SMARTCARD) += dev-smartcard-reader.o
+hw-obj-$(CONFIG_USB_REDIR) += redirect.o
+
+common-obj-y += core.o bus.o desc.o dev-hub.o
+common-obj-y += host-$(HOST_USB).o dev-bluetooth.o
+common-obj-y += dev-hid.o dev-storage.o dev-wacom.o
+common-obj-y += dev-serial.o dev-network.o dev-audio.o
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index b238a0973d..5d2f0982c9 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1356,6 +1356,7 @@ static int usb_net_initfn(USBDevice *dev)
static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
{
+ Error *local_err = NULL;
USBDevice *dev;
QemuOpts *opts;
int idx;
@@ -1367,8 +1368,10 @@ static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
qemu_opt_set(opts, "type", "nic");
qemu_opt_set(opts, "model", "usb");
- idx = net_client_init(NULL, opts, 0);
- if (idx == -1) {
+ idx = net_client_init(opts, 0, &local_err);
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
return NULL;
}
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index ae22fb1c97..097d7b4a6d 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -48,10 +48,9 @@ struct usb_msd_csw {
typedef struct {
USBDevice dev;
enum USBMSDMode mode;
+ uint32_t scsi_off;
uint32_t scsi_len;
- uint8_t *scsi_buf;
uint32_t data_len;
- uint32_t residue;
struct usb_msd_csw csw;
SCSIRequest *req;
SCSIBus bus;
@@ -179,9 +178,9 @@ static void usb_msd_copy_data(MSDState *s, USBPacket *p)
len = p->iov.size - p->result;
if (len > s->scsi_len)
len = s->scsi_len;
- usb_packet_copy(p, s->scsi_buf, len);
+ usb_packet_copy(p, scsi_req_get_buf(s->req) + s->scsi_off, len);
s->scsi_len -= len;
- s->scsi_buf += len;
+ s->scsi_off += len;
s->data_len -= len;
if (s->scsi_len == 0 || s->data_len == 0) {
scsi_req_continue(s->req);
@@ -201,6 +200,18 @@ static void usb_msd_send_status(MSDState *s, USBPacket *p)
memset(&s->csw, 0, sizeof(s->csw));
}
+static void usb_msd_packet_complete(MSDState *s)
+{
+ USBPacket *p = s->packet;
+
+ /* Set s->packet to NULL before calling usb_packet_complete
+ because another request may be issued before
+ usb_packet_complete returns. */
+ DPRINTF("Packet complete %p\n", p);
+ s->packet = NULL;
+ usb_packet_complete(&s->dev, p);
+}
+
static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
{
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
@@ -208,17 +219,12 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV));
s->scsi_len = len;
- s->scsi_buf = scsi_req_get_buf(req);
+ s->scsi_off = 0;
if (p) {
usb_msd_copy_data(s, p);
p = s->packet;
if (p && p->result == p->iov.size) {
- /* Set s->packet to NULL before calling usb_packet_complete
- because another request may be issued before
- usb_packet_complete returns. */
- DPRINTF("Packet complete %p\n", p);
- s->packet = NULL;
- usb_packet_complete(&s->dev, p);
+ usb_msd_packet_complete(s);
}
}
}
@@ -229,11 +235,10 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r
USBPacket *p = s->packet;
DPRINTF("Command complete %d tag 0x%x\n", status, req->tag);
- s->residue = s->data_len;
s->csw.sig = cpu_to_le32(0x53425355);
s->csw.tag = cpu_to_le32(req->tag);
- s->csw.residue = cpu_to_le32(s->residue);
+ s->csw.residue = cpu_to_le32(s->data_len);
s->csw.status = status != 0;
if (s->packet) {
@@ -252,8 +257,7 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r
s->mode = USB_MSDM_CSW;
}
}
- s->packet = NULL;
- usb_packet_complete(&s->dev, p);
+ usb_msd_packet_complete(s);
} else if (s->data_len == 0) {
s->mode = USB_MSDM_CSW;
}
@@ -283,10 +287,8 @@ static void usb_msd_handle_reset(USBDevice *dev)
assert(s->req == NULL);
if (s->packet) {
- USBPacket *p = s->packet;
- s->packet = NULL;
- p->result = USB_RET_STALL;
- usb_packet_complete(dev, p);
+ s->packet->result = USB_RET_STALL;
+ usb_msd_packet_complete(s);
}
s->mode = USB_MSDM_CBW;
@@ -378,7 +380,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
}
DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
tag, cbw.flags, cbw.cmd_len, s->data_len);
- s->residue = 0;
+ assert(le32_to_cpu(s->csw.residue) == 0);
s->scsi_len = 0;
s->req = scsi_req_new(s->scsi_dev, tag, 0, cbw.cmd, NULL);
scsi_req_enqueue(s->req);
@@ -397,7 +399,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
if (s->scsi_len) {
usb_msd_copy_data(s, p);
}
- if (s->residue) {
+ if (le32_to_cpu(s->csw.residue)) {
int len = p->iov.size - p->result;
if (len) {
usb_packet_skip(p, len);
@@ -458,7 +460,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
if (s->scsi_len) {
usb_msd_copy_data(s, p);
}
- if (s->residue) {
+ if (le32_to_cpu(s->csw.residue)) {
int len = p->iov.size - p->result;
if (len) {
usb_packet_skip(p, len);
@@ -504,6 +506,17 @@ static void usb_msd_password_cb(void *opaque, int err)
qdev_unplug(&s->dev.qdev, NULL);
}
+static void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req)
+{
+ MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
+
+ /* nothing to load, just store req in our state struct */
+ assert(s->req == NULL);
+ scsi_req_ref(req);
+ s->req = req;
+ return NULL;
+}
+
static const struct SCSIBusInfo usb_msd_scsi_info = {
.tcq = false,
.max_target = 0,
@@ -511,7 +524,8 @@ static const struct SCSIBusInfo usb_msd_scsi_info = {
.transfer_data = usb_msd_transfer_data,
.complete = usb_msd_command_complete,
- .cancel = usb_msd_request_cancelled
+ .cancel = usb_msd_request_cancelled,
+ .load_request = usb_msd_load_request,
};
static int usb_msd_initfn(USBDevice *dev)
@@ -584,7 +598,7 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
/* parse -usbdevice disk: syntax into drive opts */
snprintf(id, sizeof(id), "usb%d", nr++);
- opts = qemu_opts_create(qemu_find_opts("drive"), id, 0);
+ opts = qemu_opts_create(qemu_find_opts("drive"), id, 0, NULL);
p1 = strchr(filename, ':');
if (p1++) {
@@ -631,11 +645,18 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
static const VMStateDescription vmstate_usb_msd = {
.name = "usb-storage",
- .unmigratable = 1, /* FIXME: handle transactions which are in flight */
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField []) {
VMSTATE_USB_DEVICE(dev, MSDState),
+ VMSTATE_UINT32(mode, MSDState),
+ VMSTATE_UINT32(scsi_len, MSDState),
+ VMSTATE_UINT32(scsi_off, MSDState),
+ VMSTATE_UINT32(data_len, MSDState),
+ VMSTATE_UINT32(csw.sig, MSDState),
+ VMSTATE_UINT32(csw.tag, MSDState),
+ VMSTATE_UINT32(csw.residue, MSDState),
+ VMSTATE_UINT8(csw.status, MSDState),
VMSTATE_END_OF_LIST()
}
};
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index e759c996ce..5298204d9d 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -334,6 +334,7 @@ typedef struct EHCIfstn {
uint32_t backptr; // Standard next link pointer
} EHCIfstn;
+typedef struct EHCIPacket EHCIPacket;
typedef struct EHCIQueue EHCIQueue;
typedef struct EHCIState EHCIState;
@@ -343,26 +344,36 @@ enum async_state {
EHCI_ASYNC_FINISHED,
};
+struct EHCIPacket {
+ EHCIQueue *queue;
+ QTAILQ_ENTRY(EHCIPacket) next;
+
+ EHCIqtd qtd; /* copy of current QTD (being worked on) */
+ uint32_t qtdaddr; /* address QTD read from */
+
+ USBPacket packet;
+ QEMUSGList sgl;
+ int pid;
+ uint32_t tbytes;
+ enum async_state async;
+ int usb_status;
+};
+
struct EHCIQueue {
EHCIState *ehci;
QTAILQ_ENTRY(EHCIQueue) next;
uint32_t seen;
uint64_t ts;
+ int async;
/* cached data from guest - needs to be flushed
* when guest removes an entry (doorbell, handshake sequence)
*/
- EHCIqh qh; // copy of current QH (being worked on)
- uint32_t qhaddr; // address QH read from
- EHCIqtd qtd; // copy of current QTD (being worked on)
- uint32_t qtdaddr; // address QTD read from
-
- USBPacket packet;
- QEMUSGList sgl;
- int pid;
- uint32_t tbytes;
- enum async_state async;
- int usb_status;
+ EHCIqh qh; /* copy of current QH (being worked on) */
+ uint32_t qhaddr; /* address QH read from */
+ uint32_t qtdaddr; /* address QTD read from */
+ USBDevice *dev;
+ QTAILQ_HEAD(, EHCIPacket) packets;
};
typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead;
@@ -375,7 +386,6 @@ struct EHCIState {
int companion_count;
/* properties */
- uint32_t freq;
uint32_t maxframes;
/*
@@ -403,7 +413,7 @@ struct EHCIState {
* Internal states, shadow registers, etc
*/
QEMUTimer *frame_timer;
- int attach_poll_counter;
+ QEMUBH *async_bh;
int astate; // Current state in asynchronous schedule
int pstate; // Current state in periodic schedule
USBPort ports[NB_PORTS];
@@ -419,6 +429,7 @@ struct EHCIState {
QEMUSGList isgl;
uint64_t last_run_ns;
+ uint32_t async_stepdown;
};
#define SET_LAST_RUN_CLOCK(s) \
@@ -574,14 +585,37 @@ static inline void ehci_commit_interrupt(EHCIState *s)
s->usbsts_pending = 0;
}
+static void ehci_update_halt(EHCIState *s)
+{
+ if (s->usbcmd & USBCMD_RUNSTOP) {
+ ehci_clear_usbsts(s, USBSTS_HALT);
+ } else {
+ if (s->astate == EST_INACTIVE && s->pstate == EST_INACTIVE) {
+ ehci_set_usbsts(s, USBSTS_HALT);
+ }
+ }
+}
+
static void ehci_set_state(EHCIState *s, int async, int state)
{
if (async) {
trace_usb_ehci_state("async", state2str(state));
s->astate = state;
+ if (s->astate == EST_INACTIVE) {
+ ehci_clear_usbsts(s, USBSTS_ASS);
+ ehci_update_halt(s);
+ } else {
+ ehci_set_usbsts(s, USBSTS_ASS);
+ }
} else {
trace_usb_ehci_state("periodic", state2str(state));
s->pstate = state;
+ if (s->pstate == EST_INACTIVE) {
+ ehci_clear_usbsts(s, USBSTS_PSS);
+ ehci_update_halt(s);
+ } else {
+ ehci_set_usbsts(s, USBSTS_PSS);
+ }
}
}
@@ -655,27 +689,71 @@ static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
(bool)(sitd->results & SITD_RESULTS_ACTIVE));
}
+static inline bool ehci_enabled(EHCIState *s)
+{
+ return s->usbcmd & USBCMD_RUNSTOP;
+}
+
+static inline bool ehci_async_enabled(EHCIState *s)
+{
+ return ehci_enabled(s) && (s->usbcmd & USBCMD_ASE);
+}
+
+static inline bool ehci_periodic_enabled(EHCIState *s)
+{
+ return ehci_enabled(s) && (s->usbcmd & USBCMD_PSE);
+}
+
+/* packet management */
+
+static EHCIPacket *ehci_alloc_packet(EHCIQueue *q)
+{
+ EHCIPacket *p;
+
+ p = g_new0(EHCIPacket, 1);
+ p->queue = q;
+ usb_packet_init(&p->packet);
+ QTAILQ_INSERT_TAIL(&q->packets, p, next);
+ trace_usb_ehci_packet_action(p->queue, p, "alloc");
+ return p;
+}
+
+static void ehci_free_packet(EHCIPacket *p)
+{
+ trace_usb_ehci_packet_action(p->queue, p, "free");
+ if (p->async == EHCI_ASYNC_INFLIGHT) {
+ usb_cancel_packet(&p->packet);
+ }
+ QTAILQ_REMOVE(&p->queue->packets, p, next);
+ usb_packet_cleanup(&p->packet);
+ g_free(p);
+}
+
/* queue management */
-static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
+static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async)
{
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q;
q = g_malloc0(sizeof(*q));
q->ehci = ehci;
- usb_packet_init(&q->packet);
+ q->qhaddr = addr;
+ q->async = async;
+ QTAILQ_INIT(&q->packets);
QTAILQ_INSERT_HEAD(head, q, next);
trace_usb_ehci_queue_action(q, "alloc");
return q;
}
-static void ehci_free_queue(EHCIQueue *q, int async)
+static void ehci_free_queue(EHCIQueue *q)
{
- EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
+ EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues;
+ EHCIPacket *p;
+
trace_usb_ehci_queue_action(q, "free");
- if (q->async == EHCI_ASYNC_INFLIGHT) {
- usb_cancel_packet(&q->packet);
+ while ((p = QTAILQ_FIRST(&q->packets)) != NULL) {
+ ehci_free_packet(p);
}
QTAILQ_REMOVE(head, q, next);
g_free(q);
@@ -698,6 +776,7 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
{
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
+ uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4;
EHCIQueue *q, *tmp;
QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
@@ -706,11 +785,10 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
q->ts = ehci->last_run_ns;
continue;
}
- if (!flush && ehci->last_run_ns < q->ts + 250000000) {
- /* allow 0.25 sec idle */
+ if (!flush && ehci->last_run_ns < q->ts + maxage) {
continue;
}
- ehci_free_queue(q, async);
+ ehci_free_queue(q);
}
}
@@ -720,11 +798,10 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
EHCIQueue *q, *tmp;
QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
- if (!usb_packet_is_inflight(&q->packet) ||
- q->packet.ep->dev != dev) {
+ if (q->dev != dev) {
continue;
}
- ehci_free_queue(q, async);
+ ehci_free_queue(q);
}
}
@@ -734,7 +811,7 @@ static void ehci_queues_rip_all(EHCIState *ehci, int async)
EHCIQueue *q, *tmp;
QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
- ehci_free_queue(q, async);
+ ehci_free_queue(q);
}
}
@@ -812,6 +889,8 @@ static void ehci_wakeup(USBPort *port)
USBPort *companion = s->companion_ports[port->index];
if (companion->ops->wakeup) {
companion->ops->wakeup(companion);
+ } else {
+ qemu_bh_schedule(s->async_bh);
}
}
}
@@ -904,7 +983,6 @@ static void ehci_reset(void *opaque)
s->astate = EST_INACTIVE;
s->pstate = EST_INACTIVE;
- s->attach_poll_counter = 0;
for(i = 0; i < NB_PORTS; i++) {
if (s->companion_ports[i]) {
@@ -920,6 +998,7 @@ static void ehci_reset(void *opaque)
ehci_queues_rip_all(s, 0);
ehci_queues_rip_all(s, 1);
qemu_del_timer(s->frame_timer);
+ qemu_bh_cancel(s->async_bh);
}
static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr)
@@ -1064,22 +1143,20 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
/* Do any register specific pre-write processing here. */
switch(addr) {
case USBCMD:
- if ((val & USBCMD_RUNSTOP) && !(s->usbcmd & USBCMD_RUNSTOP)) {
- qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
- SET_LAST_RUN_CLOCK(s);
- ehci_clear_usbsts(s, USBSTS_HALT);
- }
-
- if (!(val & USBCMD_RUNSTOP) && (s->usbcmd & USBCMD_RUNSTOP)) {
- qemu_del_timer(s->frame_timer);
- ehci_queues_rip_all(s, 0);
- ehci_queues_rip_all(s, 1);
- ehci_set_usbsts(s, USBSTS_HALT);
- }
-
if (val & USBCMD_HCRESET) {
ehci_reset(s);
val = s->usbcmd;
+ break;
+ }
+
+ if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) !=
+ ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) {
+ if (s->pstate == EST_INACTIVE) {
+ SET_LAST_RUN_CLOCK(s);
+ }
+ ehci_update_halt(s);
+ s->async_stepdown = 0;
+ qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
}
/* not supporting dynamic frame list size at the moment */
@@ -1114,7 +1191,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
break;
case PERIODICLISTBASE:
- if ((s->usbcmd & USBCMD_PSE) && (s->usbcmd & USBCMD_RUNSTOP)) {
+ if (ehci_periodic_enabled(s)) {
fprintf(stderr,
"ehci: PERIODIC list base register set while periodic schedule\n"
" is enabled and HC is enabled\n");
@@ -1122,7 +1199,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
break;
case ASYNCLISTADDR:
- if ((s->usbcmd & USBCMD_ASE) && (s->usbcmd & USBCMD_RUNSTOP)) {
+ if (ehci_async_enabled(s)) {
fprintf(stderr,
"ehci: ASYNC list address register set while async schedule\n"
" is enabled and HC is enabled\n");
@@ -1169,21 +1246,25 @@ static inline int put_dwords(EHCIState *ehci, uint32_t addr,
static int ehci_qh_do_overlay(EHCIQueue *q)
{
+ EHCIPacket *p = QTAILQ_FIRST(&q->packets);
int i;
int dtoggle;
int ping;
int eps;
int reload;
+ assert(p != NULL);
+ assert(p->qtdaddr == q->qtdaddr);
+
// remember values in fields to preserve in qh after overlay
dtoggle = q->qh.token & QTD_TOKEN_DTOGGLE;
ping = q->qh.token & QTD_TOKEN_PING;
- q->qh.current_qtd = q->qtdaddr;
- q->qh.next_qtd = q->qtd.next;
- q->qh.altnext_qtd = q->qtd.altnext;
- q->qh.token = q->qtd.token;
+ q->qh.current_qtd = p->qtdaddr;
+ q->qh.next_qtd = p->qtd.next;
+ q->qh.altnext_qtd = p->qtd.altnext;
+ q->qh.token = p->qtd.token;
eps = get_field(q->qh.epchar, QH_EPCHAR_EPS);
@@ -1196,7 +1277,7 @@ static int ehci_qh_do_overlay(EHCIQueue *q)
set_field(&q->qh.altnext_qtd, reload, QH_ALTNEXT_NAKCNT);
for (i = 0; i < 5; i++) {
- q->qh.bufptr[i] = q->qtd.bufptr[i];
+ q->qh.bufptr[i] = p->qtd.bufptr[i];
}
if (!(q->qh.epchar & QH_EPCHAR_DTC)) {
@@ -1214,15 +1295,15 @@ static int ehci_qh_do_overlay(EHCIQueue *q)
return 0;
}
-static int ehci_init_transfer(EHCIQueue *q)
+static int ehci_init_transfer(EHCIPacket *p)
{
uint32_t cpage, offset, bytes, plen;
dma_addr_t page;
- cpage = get_field(q->qh.token, QTD_TOKEN_CPAGE);
- bytes = get_field(q->qh.token, QTD_TOKEN_TBYTES);
- offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK;
- pci_dma_sglist_init(&q->sgl, &q->ehci->dev, 5);
+ cpage = get_field(p->qtd.token, QTD_TOKEN_CPAGE);
+ bytes = get_field(p->qtd.token, QTD_TOKEN_TBYTES);
+ offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK;
+ pci_dma_sglist_init(&p->sgl, &p->queue->ehci->dev, 5);
while (bytes > 0) {
if (cpage > 4) {
@@ -1230,7 +1311,7 @@ static int ehci_init_transfer(EHCIQueue *q)
return USB_RET_PROCERR;
}
- page = q->qh.bufptr[cpage] & QTD_BUFPTR_MASK;
+ page = p->qtd.bufptr[cpage] & QTD_BUFPTR_MASK;
page += offset;
plen = bytes;
if (plen > 4096 - offset) {
@@ -1239,7 +1320,7 @@ static int ehci_init_transfer(EHCIQueue *q)
cpage++;
}
- qemu_sglist_add(&q->sgl, page, plen);
+ qemu_sglist_add(&p->sgl, page, plen);
bytes -= plen;
}
return 0;
@@ -1249,8 +1330,6 @@ static void ehci_finish_transfer(EHCIQueue *q, int status)
{
uint32_t cpage, offset;
- qemu_sglist_destroy(&q->sgl);
-
if (status > 0) {
/* update cpage & offset */
cpage = get_field(q->qh.token, QTD_TOKEN_CPAGE);
@@ -1268,7 +1347,7 @@ static void ehci_finish_transfer(EHCIQueue *q, int status)
static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
{
- EHCIQueue *q;
+ EHCIPacket *p;
EHCIState *s = port->opaque;
uint32_t portsc = s->portsc[port->index];
@@ -1278,23 +1357,31 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
return;
}
- q = container_of(packet, EHCIQueue, packet);
- trace_usb_ehci_queue_action(q, "wakeup");
- assert(q->async == EHCI_ASYNC_INFLIGHT);
- q->async = EHCI_ASYNC_FINISHED;
- q->usb_status = packet->result;
+ p = container_of(packet, EHCIPacket, packet);
+ trace_usb_ehci_packet_action(p->queue, p, "wakeup");
+ assert(p->async == EHCI_ASYNC_INFLIGHT);
+ p->async = EHCI_ASYNC_FINISHED;
+ p->usb_status = packet->result;
+
+ if (p->queue->async) {
+ qemu_bh_schedule(p->queue->ehci->async_bh);
+ }
}
static void ehci_execute_complete(EHCIQueue *q)
{
- assert(q->async != EHCI_ASYNC_INFLIGHT);
- q->async = EHCI_ASYNC_NONE;
+ EHCIPacket *p = QTAILQ_FIRST(&q->packets);
+
+ assert(p != NULL);
+ assert(p->qtdaddr == q->qtdaddr);
+ assert(p->async != EHCI_ASYNC_INFLIGHT);
+ p->async = EHCI_ASYNC_NONE;
DPRINTF("execute_complete: qhaddr 0x%x, next %x, qtdaddr 0x%x, status %d\n",
q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status);
- if (q->usb_status < 0) {
- switch(q->usb_status) {
+ if (p->usb_status < 0) {
+ switch (p->usb_status) {
case USB_RET_IOERROR:
case USB_RET_NODEV:
q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
@@ -1314,28 +1401,29 @@ static void ehci_execute_complete(EHCIQueue *q)
break;
default:
/* should not be triggerable */
- fprintf(stderr, "USB invalid response %d to handle\n", q->usb_status);
+ fprintf(stderr, "USB invalid response %d\n", p->usb_status);
assert(0);
break;
}
- } else if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
- q->usb_status = USB_RET_BABBLE;
+ } else if ((p->usb_status > p->tbytes) && (p->pid == USB_TOKEN_IN)) {
+ p->usb_status = USB_RET_BABBLE;
q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
} else {
// TODO check 4.12 for splits
- if (q->tbytes && q->pid == USB_TOKEN_IN) {
- q->tbytes -= q->usb_status;
+ if (p->tbytes && p->pid == USB_TOKEN_IN) {
+ p->tbytes -= p->usb_status;
} else {
- q->tbytes = 0;
+ p->tbytes = 0;
}
- DPRINTF("updating tbytes to %d\n", q->tbytes);
- set_field(&q->qh.token, q->tbytes, QTD_TOKEN_TBYTES);
+ DPRINTF("updating tbytes to %d\n", p->tbytes);
+ set_field(&q->qh.token, p->tbytes, QTD_TOKEN_TBYTES);
}
- ehci_finish_transfer(q, q->usb_status);
- usb_packet_unmap(&q->packet);
+ ehci_finish_transfer(q, p->usb_status);
+ qemu_sglist_destroy(&p->sgl);
+ usb_packet_unmap(&p->packet);
q->qh.token ^= QTD_TOKEN_DTOGGLE;
q->qh.token &= ~QTD_TOKEN_ACTIVE;
@@ -1347,48 +1435,51 @@ static void ehci_execute_complete(EHCIQueue *q)
// 4.10.3
-static int ehci_execute(EHCIQueue *q)
+static int ehci_execute(EHCIPacket *p, const char *action)
{
- USBDevice *dev;
USBEndpoint *ep;
int ret;
int endp;
- int devadr;
- if ( !(q->qh.token & QTD_TOKEN_ACTIVE)) {
- fprintf(stderr, "Attempting to execute inactive QH\n");
+ if (!(p->qtd.token & QTD_TOKEN_ACTIVE)) {
+ fprintf(stderr, "Attempting to execute inactive qtd\n");
return USB_RET_PROCERR;
}
- q->tbytes = (q->qh.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH;
- if (q->tbytes > BUFF_SIZE) {
+ p->tbytes = (p->qtd.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH;
+ if (p->tbytes > BUFF_SIZE) {
fprintf(stderr, "Request for more bytes than allowed\n");
return USB_RET_PROCERR;
}
- q->pid = (q->qh.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;
- switch(q->pid) {
- case 0: q->pid = USB_TOKEN_OUT; break;
- case 1: q->pid = USB_TOKEN_IN; break;
- case 2: q->pid = USB_TOKEN_SETUP; break;
- default: fprintf(stderr, "bad token\n"); break;
+ p->pid = (p->qtd.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;
+ switch (p->pid) {
+ case 0:
+ p->pid = USB_TOKEN_OUT;
+ break;
+ case 1:
+ p->pid = USB_TOKEN_IN;
+ break;
+ case 2:
+ p->pid = USB_TOKEN_SETUP;
+ break;
+ default:
+ fprintf(stderr, "bad token\n");
+ break;
}
- if (ehci_init_transfer(q) != 0) {
+ if (ehci_init_transfer(p) != 0) {
return USB_RET_PROCERR;
}
- endp = get_field(q->qh.epchar, QH_EPCHAR_EP);
- devadr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
+ endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP);
+ ep = usb_ep_get(p->queue->dev, p->pid, endp);
- /* TODO: associating device with ehci port */
- dev = ehci_find_device(q->ehci, devadr);
- ep = usb_ep_get(dev, q->pid, endp);
+ usb_packet_setup(&p->packet, p->pid, ep);
+ usb_packet_map(&p->packet, &p->sgl);
- usb_packet_setup(&q->packet, q->pid, ep);
- usb_packet_map(&q->packet, &q->sgl);
-
- ret = usb_handle_packet(dev, &q->packet);
+ trace_usb_ehci_packet_action(p->queue, p, action);
+ ret = usb_handle_packet(p->queue->dev, &p->packet);
DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
"(total %d) endp %x ret %d\n",
q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
@@ -1504,6 +1595,24 @@ static int ehci_process_itd(EHCIState *ehci,
return 0;
}
+
+/*
+ * Write the qh back to guest physical memory. This step isn't
+ * in the EHCI spec but we need to do it since we don't share
+ * physical memory with our guest VM.
+ *
+ * The first three dwords are read-only for the EHCI, so skip them
+ * when writing back the qh.
+ */
+static void ehci_flush_qh(EHCIQueue *q)
+{
+ uint32_t *qh = (uint32_t *) &q->qh;
+ uint32_t dwords = sizeof(EHCIqh) >> 2;
+ uint32_t addr = NLPTR_GET(q->qhaddr);
+
+ put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3);
+}
+
/* This state is the entry point for asynchronous schedule
* processing. Entry here consitutes a EHCI start event state (4.8.5)
*/
@@ -1601,17 +1710,18 @@ out:
static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
{
- uint32_t entry;
+ EHCIPacket *p;
+ uint32_t entry, devaddr;
EHCIQueue *q;
entry = ehci_get_fetch_addr(ehci, async);
q = ehci_find_queue_by_qh(ehci, entry, async);
if (NULL == q) {
- q = ehci_alloc_queue(ehci, async);
+ q = ehci_alloc_queue(ehci, entry, async);
}
- q->qhaddr = entry;
- q->seen++;
+ p = QTAILQ_FIRST(&q->packets);
+ q->seen++;
if (q->seen > 1) {
/* we are going in circles -- stop processing */
ehci_set_state(ehci, async, EST_ACTIVE);
@@ -1623,14 +1733,28 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
(uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
- if (q->async == EHCI_ASYNC_INFLIGHT) {
+ devaddr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
+ if (q->dev != NULL && q->dev->addr != devaddr) {
+ if (!QTAILQ_EMPTY(&q->packets)) {
+ /* should not happen (guest bug) */
+ while ((p = QTAILQ_FIRST(&q->packets)) != NULL) {
+ ehci_free_packet(p);
+ }
+ }
+ q->dev = NULL;
+ }
+ if (q->dev == NULL) {
+ q->dev = ehci_find_device(q->ehci, devaddr);
+ }
+
+ if (p && p->async == EHCI_ASYNC_INFLIGHT) {
/* I/O still in progress -- skip queue */
ehci_set_state(ehci, async, EST_HORIZONTALQH);
goto out;
}
- if (q->async == EHCI_ASYNC_FINISHED) {
+ if (p && p->async == EHCI_ASYNC_FINISHED) {
/* I/O finished -- continue processing queue */
- trace_usb_ehci_queue_action(q, "resume");
+ trace_usb_ehci_packet_action(p->queue, p, "complete");
ehci_set_state(ehci, async, EST_EXECUTING);
goto out;
}
@@ -1726,7 +1850,7 @@ static int ehci_state_fetchsitd(EHCIState *ehci, int async)
}
/* Section 4.10.2 - paragraph 3 */
-static int ehci_state_advqueue(EHCIQueue *q, int async)
+static int ehci_state_advqueue(EHCIQueue *q)
{
#if 0
/* TO-DO: 4.10.2 - paragraph 2
@@ -1745,81 +1869,117 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
if (((q->qh.token & QTD_TOKEN_TBYTES_MASK) != 0) &&
(NLPTR_TBIT(q->qh.altnext_qtd) == 0)) {
q->qtdaddr = q->qh.altnext_qtd;
- ehci_set_state(q->ehci, async, EST_FETCHQTD);
+ ehci_set_state(q->ehci, q->async, EST_FETCHQTD);
/*
* next qTD is valid
*/
} else if (NLPTR_TBIT(q->qh.next_qtd) == 0) {
q->qtdaddr = q->qh.next_qtd;
- ehci_set_state(q->ehci, async, EST_FETCHQTD);
+ ehci_set_state(q->ehci, q->async, EST_FETCHQTD);
/*
* no valid qTD, try next QH
*/
} else {
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
}
return 1;
}
/* Section 4.10.2 - paragraph 4 */
-static int ehci_state_fetchqtd(EHCIQueue *q, int async)
+static int ehci_state_fetchqtd(EHCIQueue *q)
{
+ EHCIqtd qtd;
+ EHCIPacket *p;
int again = 0;
- get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &q->qtd,
+ get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &qtd,
sizeof(EHCIqtd) >> 2);
- ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &q->qtd);
+ ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd);
- if (q->qtd.token & QTD_TOKEN_ACTIVE) {
- ehci_set_state(q->ehci, async, EST_EXECUTE);
+ p = QTAILQ_FIRST(&q->packets);
+ while (p != NULL && p->qtdaddr != q->qtdaddr) {
+ /* should not happen (guest bug) */
+ ehci_free_packet(p);
+ p = QTAILQ_FIRST(&q->packets);
+ }
+ if (p != NULL) {
+ ehci_qh_do_overlay(q);
+ ehci_flush_qh(q);
+ if (p->async == EHCI_ASYNC_INFLIGHT) {
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
+ } else {
+ ehci_set_state(q->ehci, q->async, EST_EXECUTING);
+ }
+ again = 1;
+ } else if (qtd.token & QTD_TOKEN_ACTIVE) {
+ p = ehci_alloc_packet(q);
+ p->qtdaddr = q->qtdaddr;
+ p->qtd = qtd;
+ ehci_set_state(q->ehci, q->async, EST_EXECUTE);
again = 1;
} else {
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
again = 1;
}
return again;
}
-static int ehci_state_horizqh(EHCIQueue *q, int async)
+static int ehci_state_horizqh(EHCIQueue *q)
{
int again = 0;
- if (ehci_get_fetch_addr(q->ehci, async) != q->qh.next) {
- ehci_set_fetch_addr(q->ehci, async, q->qh.next);
- ehci_set_state(q->ehci, async, EST_FETCHENTRY);
+ if (ehci_get_fetch_addr(q->ehci, q->async) != q->qh.next) {
+ ehci_set_fetch_addr(q->ehci, q->async, q->qh.next);
+ ehci_set_state(q->ehci, q->async, EST_FETCHENTRY);
again = 1;
} else {
- ehci_set_state(q->ehci, async, EST_ACTIVE);
+ ehci_set_state(q->ehci, q->async, EST_ACTIVE);
}
return again;
}
-/*
- * Write the qh back to guest physical memory. This step isn't
- * in the EHCI spec but we need to do it since we don't share
- * physical memory with our guest VM.
- *
- * The first three dwords are read-only for the EHCI, so skip them
- * when writing back the qh.
- */
-static void ehci_flush_qh(EHCIQueue *q)
+static void ehci_fill_queue(EHCIPacket *p)
{
- uint32_t *qh = (uint32_t *) &q->qh;
- uint32_t dwords = sizeof(EHCIqh) >> 2;
- uint32_t addr = NLPTR_GET(q->qhaddr);
+ EHCIQueue *q = p->queue;
+ EHCIqtd qtd = p->qtd;
+ uint32_t qtdaddr;
- put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3);
+ for (;;) {
+ if (NLPTR_TBIT(qtd.altnext) == 0) {
+ break;
+ }
+ if (NLPTR_TBIT(qtd.next) != 0) {
+ break;
+ }
+ qtdaddr = qtd.next;
+ get_dwords(q->ehci, NLPTR_GET(qtdaddr),
+ (uint32_t *) &qtd, sizeof(EHCIqtd) >> 2);
+ ehci_trace_qtd(q, NLPTR_GET(qtdaddr), &qtd);
+ if (!(qtd.token & QTD_TOKEN_ACTIVE)) {
+ break;
+ }
+ p = ehci_alloc_packet(q);
+ p->qtdaddr = qtdaddr;
+ p->qtd = qtd;
+ p->usb_status = ehci_execute(p, "queue");
+ assert(p->usb_status = USB_RET_ASYNC);
+ p->async = EHCI_ASYNC_INFLIGHT;
+ }
}
-static int ehci_state_execute(EHCIQueue *q, int async)
+static int ehci_state_execute(EHCIQueue *q)
{
+ EHCIPacket *p = QTAILQ_FIRST(&q->packets);
int again = 0;
+ assert(p != NULL);
+ assert(p->qtdaddr == q->qtdaddr);
+
if (ehci_qh_do_overlay(q) != 0) {
return -1;
}
@@ -1828,55 +1988,60 @@ static int ehci_state_execute(EHCIQueue *q, int async)
// TODO write back ptr to async list when done or out of time
// TODO Windows does not seem to ever set the MULT field
- if (!async) {
+ if (!q->async) {
int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
if (!transactCtr) {
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
again = 1;
goto out;
}
}
- if (async) {
+ if (q->async) {
ehci_set_usbsts(q->ehci, USBSTS_REC);
}
- q->usb_status = ehci_execute(q);
- if (q->usb_status == USB_RET_PROCERR) {
+ p->usb_status = ehci_execute(p, "process");
+ if (p->usb_status == USB_RET_PROCERR) {
again = -1;
goto out;
}
- if (q->usb_status == USB_RET_ASYNC) {
+ if (p->usb_status == USB_RET_ASYNC) {
ehci_flush_qh(q);
- trace_usb_ehci_queue_action(q, "suspend");
- q->async = EHCI_ASYNC_INFLIGHT;
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+ trace_usb_ehci_packet_action(p->queue, p, "async");
+ p->async = EHCI_ASYNC_INFLIGHT;
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
again = 1;
+ ehci_fill_queue(p);
goto out;
}
- ehci_set_state(q->ehci, async, EST_EXECUTING);
+ ehci_set_state(q->ehci, q->async, EST_EXECUTING);
again = 1;
out:
return again;
}
-static int ehci_state_executing(EHCIQueue *q, int async)
+static int ehci_state_executing(EHCIQueue *q)
{
+ EHCIPacket *p = QTAILQ_FIRST(&q->packets);
int again = 0;
+ assert(p != NULL);
+ assert(p->qtdaddr == q->qtdaddr);
+
ehci_execute_complete(q);
- if (q->usb_status == USB_RET_ASYNC) {
+ if (p->usb_status == USB_RET_ASYNC) {
goto out;
}
- if (q->usb_status == USB_RET_PROCERR) {
+ if (p->usb_status == USB_RET_PROCERR) {
again = -1;
goto out;
}
// 4.10.3
- if (!async) {
+ if (!q->async) {
int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
transactCtr--;
set_field(&q->qh.epcap, transactCtr, QH_EPCAP_MULT);
@@ -1885,10 +2050,10 @@ static int ehci_state_executing(EHCIQueue *q, int async)
}
/* 4.10.5 */
- if (q->usb_status == USB_RET_NAK) {
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+ if (p->usb_status == USB_RET_NAK) {
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
} else {
- ehci_set_state(q->ehci, async, EST_WRITEBACK);
+ ehci_set_state(q->ehci, q->async, EST_WRITEBACK);
}
again = 1;
@@ -1899,14 +2064,19 @@ out:
}
-static int ehci_state_writeback(EHCIQueue *q, int async)
+static int ehci_state_writeback(EHCIQueue *q)
{
+ EHCIPacket *p = QTAILQ_FIRST(&q->packets);
int again = 0;
/* Write back the QTD from the QH area */
- ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), (EHCIqtd*) &q->qh.next_qtd);
- put_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &q->qh.next_qtd,
+ assert(p != NULL);
+ assert(p->qtdaddr == q->qtdaddr);
+
+ ehci_trace_qtd(q, NLPTR_GET(p->qtdaddr), (EHCIqtd *) &q->qh.next_qtd);
+ put_dwords(q->ehci, NLPTR_GET(p->qtdaddr), (uint32_t *) &q->qh.next_qtd,
sizeof(EHCIqtd) >> 2);
+ ehci_free_packet(p);
/*
* EHCI specs say go horizontal here.
@@ -1917,10 +2087,10 @@ static int ehci_state_writeback(EHCIQueue *q, int async)
* bit is clear.
*/
if (q->qh.token & QTD_TOKEN_HALT) {
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
again = 1;
} else {
- ehci_set_state(q->ehci, async, EST_ADVANCEQUEUE);
+ ehci_set_state(q->ehci, q->async, EST_ADVANCEQUEUE);
again = 1;
}
return again;
@@ -1930,8 +2100,7 @@ static int ehci_state_writeback(EHCIQueue *q, int async)
* This is the state machine that is common to both async and periodic
*/
-static void ehci_advance_state(EHCIState *ehci,
- int async)
+static void ehci_advance_state(EHCIState *ehci, int async)
{
EHCIQueue *q = NULL;
int again;
@@ -1948,7 +2117,12 @@ static void ehci_advance_state(EHCIState *ehci,
case EST_FETCHQH:
q = ehci_state_fetchqh(ehci, async);
- again = q ? 1 : 0;
+ if (q != NULL) {
+ assert(q->async == async);
+ again = 1;
+ } else {
+ again = 0;
+ }
break;
case EST_FETCHITD:
@@ -1960,29 +2134,35 @@ static void ehci_advance_state(EHCIState *ehci,
break;
case EST_ADVANCEQUEUE:
- again = ehci_state_advqueue(q, async);
+ again = ehci_state_advqueue(q);
break;
case EST_FETCHQTD:
- again = ehci_state_fetchqtd(q, async);
+ again = ehci_state_fetchqtd(q);
break;
case EST_HORIZONTALQH:
- again = ehci_state_horizqh(q, async);
+ again = ehci_state_horizqh(q);
break;
case EST_EXECUTE:
- again = ehci_state_execute(q, async);
+ again = ehci_state_execute(q);
+ if (async) {
+ ehci->async_stepdown = 0;
+ }
break;
case EST_EXECUTING:
assert(q != NULL);
- again = ehci_state_executing(q, async);
+ if (async) {
+ ehci->async_stepdown = 0;
+ }
+ again = ehci_state_executing(q);
break;
case EST_WRITEBACK:
assert(q != NULL);
- again = ehci_state_writeback(q, async);
+ again = ehci_state_writeback(q);
break;
default:
@@ -2009,17 +2189,15 @@ static void ehci_advance_async_state(EHCIState *ehci)
switch(ehci_get_state(ehci, async)) {
case EST_INACTIVE:
- if (!(ehci->usbcmd & USBCMD_ASE)) {
+ if (!ehci_async_enabled(ehci)) {
break;
}
- ehci_set_usbsts(ehci, USBSTS_ASS);
ehci_set_state(ehci, async, EST_ACTIVE);
// No break, fall through to ACTIVE
case EST_ACTIVE:
- if ( !(ehci->usbcmd & USBCMD_ASE)) {
+ if (!ehci_async_enabled(ehci)) {
ehci_queues_rip_all(ehci, async);
- ehci_clear_usbsts(ehci, USBSTS_ASS);
ehci_set_state(ehci, async, EST_INACTIVE);
break;
}
@@ -2070,17 +2248,15 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
switch(ehci_get_state(ehci, async)) {
case EST_INACTIVE:
- if ( !(ehci->frindex & 7) && (ehci->usbcmd & USBCMD_PSE)) {
- ehci_set_usbsts(ehci, USBSTS_PSS);
+ if (!(ehci->frindex & 7) && ehci_periodic_enabled(ehci)) {
ehci_set_state(ehci, async, EST_ACTIVE);
// No break, fall through to ACTIVE
} else
break;
case EST_ACTIVE:
- if ( !(ehci->frindex & 7) && !(ehci->usbcmd & USBCMD_PSE)) {
+ if (!(ehci->frindex & 7) && !ehci_periodic_enabled(ehci)) {
ehci_queues_rip_all(ehci, async);
- ehci_clear_usbsts(ehci, USBSTS_PSS);
ehci_set_state(ehci, async, EST_INACTIVE);
break;
}
@@ -2111,58 +2287,86 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
}
}
+static void ehci_update_frindex(EHCIState *ehci, int frames)
+{
+ int i;
+
+ if (!ehci_enabled(ehci)) {
+ return;
+ }
+
+ for (i = 0; i < frames; i++) {
+ ehci->frindex += 8;
+
+ if (ehci->frindex == 0x00002000) {
+ ehci_set_interrupt(ehci, USBSTS_FLR);
+ }
+
+ if (ehci->frindex == 0x00004000) {
+ ehci_set_interrupt(ehci, USBSTS_FLR);
+ ehci->frindex = 0;
+ }
+ }
+}
+
static void ehci_frame_timer(void *opaque)
{
EHCIState *ehci = opaque;
+ int schedules = 0;
int64_t expire_time, t_now;
uint64_t ns_elapsed;
- int frames;
+ int frames, skipped_frames;
int i;
- int skipped_frames = 0;
t_now = qemu_get_clock_ns(vm_clock);
- expire_time = t_now + (get_ticks_per_sec() / ehci->freq);
-
ns_elapsed = t_now - ehci->last_run_ns;
frames = ns_elapsed / FRAME_TIMER_NS;
- for (i = 0; i < frames; i++) {
- if ( !(ehci->usbsts & USBSTS_HALT)) {
- ehci->frindex += 8;
-
- if (ehci->frindex == 0x00002000) {
- ehci_set_interrupt(ehci, USBSTS_FLR);
- }
+ if (ehci_periodic_enabled(ehci) || ehci->pstate != EST_INACTIVE) {
+ schedules++;
+ expire_time = t_now + (get_ticks_per_sec() / FRAME_TIMER_FREQ);
- if (ehci->frindex == 0x00004000) {
- ehci_set_interrupt(ehci, USBSTS_FLR);
- ehci->frindex = 0;
- }
+ if (frames > ehci->maxframes) {
+ skipped_frames = frames - ehci->maxframes;
+ ehci_update_frindex(ehci, skipped_frames);
+ ehci->last_run_ns += FRAME_TIMER_NS * skipped_frames;
+ frames -= skipped_frames;
+ DPRINTF("WARNING - EHCI skipped %d frames\n", skipped_frames);
}
- if (frames - i > ehci->maxframes) {
- skipped_frames++;
- } else {
+ for (i = 0; i < frames; i++) {
+ ehci_update_frindex(ehci, 1);
ehci_advance_periodic_state(ehci);
+ ehci->last_run_ns += FRAME_TIMER_NS;
}
-
- ehci->last_run_ns += FRAME_TIMER_NS;
- }
-
-#if 0
- if (skipped_frames) {
- DPRINTF("WARNING - EHCI skipped %d frames\n", skipped_frames);
+ } else {
+ if (ehci->async_stepdown < ehci->maxframes / 2) {
+ ehci->async_stepdown++;
+ }
+ expire_time = t_now + (get_ticks_per_sec()
+ * ehci->async_stepdown / FRAME_TIMER_FREQ);
+ ehci_update_frindex(ehci, frames);
+ ehci->last_run_ns += FRAME_TIMER_NS * frames;
}
-#endif
/* Async is not inside loop since it executes everything it can once
* called
*/
- ehci_advance_async_state(ehci);
+ if (ehci_async_enabled(ehci) || ehci->astate != EST_INACTIVE) {
+ schedules++;
+ qemu_bh_schedule(ehci->async_bh);
+ }
- qemu_mod_timer(ehci->frame_timer, expire_time);
+ if (schedules) {
+ qemu_mod_timer(ehci->frame_timer, expire_time);
+ }
}
+static void ehci_async_bh(void *opaque)
+{
+ EHCIState *ehci = opaque;
+ ehci_advance_async_state(ehci);
+}
static const MemoryRegionOps ehci_mem_ops = {
.old_mmio = {
@@ -2192,7 +2396,6 @@ static const VMStateDescription vmstate_ehci = {
};
static Property ehci_properties[] = {
- DEFINE_PROP_UINT32("freq", EHCIState, freq, FRAME_TIMER_FREQ),
DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128),
DEFINE_PROP_END_OF_LIST(),
};
@@ -2298,6 +2501,7 @@ static int usb_ehci_initfn(PCIDevice *dev)
}
s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
+ s->async_bh = qemu_bh_new(ehci_async_bh, s);
QTAILQ_INIT(&s->aqueues);
QTAILQ_INIT(&s->pqueues);
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 9e211a0bb4..9871e24f50 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -131,10 +131,14 @@ struct UHCIState {
uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
int64_t expire_time;
QEMUTimer *frame_timer;
+ QEMUBH *bh;
+ uint32_t frame_bytes;
+ uint32_t frame_bandwidth;
UHCIPort ports[NB_PORTS];
/* Interrupts that should be raised at the end of the current frame. */
uint32_t pending_int_mask;
+ int irq_pin;
/* Active packets */
QTAILQ_HEAD(, UHCIQueue) queues;
@@ -337,7 +341,7 @@ static void uhci_update_irq(UHCIState *s)
} else {
level = 0;
}
- qemu_set_irq(s->dev.irq[3], level);
+ qemu_set_irq(s->dev.irq[s->irq_pin], level);
}
static void uhci_reset(void *opaque)
@@ -369,16 +373,10 @@ static void uhci_reset(void *opaque)
}
uhci_async_cancel_all(s);
+ qemu_bh_cancel(s->bh);
uhci_update_irq(s);
}
-static void uhci_pre_save(void *opaque)
-{
- UHCIState *s = opaque;
-
- uhci_async_cancel_all(s);
-}
-
static const VMStateDescription vmstate_uhci_port = {
.name = "uhci port",
.version_id = 1,
@@ -395,7 +393,6 @@ static const VMStateDescription vmstate_uhci = {
.version_id = 2,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
- .pre_save = uhci_pre_save,
.fields = (VMStateField []) {
VMSTATE_PCI_DEVICE(dev, UHCIState),
VMSTATE_UINT8_EQUAL(num_ports_vmstate, UHCIState),
@@ -905,7 +902,9 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
uhci_async_free(async);
} else {
async->done = 1;
- uhci_process_frame(s);
+ if (s->frame_bytes < s->frame_bandwidth) {
+ qemu_bh_schedule(s->bh);
+ }
}
}
@@ -985,7 +984,7 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
static void uhci_process_frame(UHCIState *s)
{
uint32_t frame_addr, link, old_td_ctrl, val, int_mask;
- uint32_t curr_qh, td_count = 0, bytes_count = 0;
+ uint32_t curr_qh, td_count = 0;
int cnt, ret;
UHCI_TD td;
UHCI_QH qh;
@@ -1002,6 +1001,12 @@ static void uhci_process_frame(UHCIState *s)
qhdb_reset(&qhdb);
for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
+ if (s->frame_bytes >= s->frame_bandwidth) {
+ /* We've reached the usb 1.1 bandwidth, which is
+ 1280 bytes/frame, stop processing */
+ trace_usb_uhci_frame_stop_bandwidth();
+ break;
+ }
if (is_qh(link)) {
/* QH */
trace_usb_uhci_qh_load(link & ~0xf);
@@ -1011,18 +1016,12 @@ static void uhci_process_frame(UHCIState *s)
* We're going in circles. Which is not a bug because
* HCD is allowed to do that as part of the BW management.
*
- * Stop processing here if
- * (a) no transaction has been done since we've been
- * here last time, or
- * (b) we've reached the usb 1.1 bandwidth, which is
- * 1280 bytes/frame.
+ * Stop processing here if no transaction has been done
+ * since we've been here last time.
*/
if (td_count == 0) {
trace_usb_uhci_frame_loop_stop_idle();
break;
- } else if (bytes_count >= 1280) {
- trace_usb_uhci_frame_loop_stop_bandwidth();
- break;
} else {
trace_usb_uhci_frame_loop_continue();
td_count = 0;
@@ -1085,7 +1084,7 @@ static void uhci_process_frame(UHCIState *s)
trace_usb_uhci_td_complete(curr_qh & ~0xf, link & ~0xf);
link = td.link;
td_count++;
- bytes_count += (td.ctrl & 0x7ff) + 1;
+ s->frame_bytes += (td.ctrl & 0x7ff) + 1;
if (curr_qh) {
/* update QH element link */
@@ -1112,12 +1111,20 @@ out:
s->pending_int_mask |= int_mask;
}
+static void uhci_bh(void *opaque)
+{
+ UHCIState *s = opaque;
+ uhci_process_frame(s);
+}
+
static void uhci_frame_timer(void *opaque)
{
UHCIState *s = opaque;
/* prepare the timer for the next frame */
s->expire_time += (get_ticks_per_sec() / FRAME_TIMER_FREQ);
+ s->frame_bytes = 0;
+ qemu_bh_cancel(s->bh);
if (!(s->cmd & UHCI_CMD_RS)) {
/* Full stop */
@@ -1178,15 +1185,31 @@ static USBBusOps uhci_bus_ops = {
static int usb_uhci_common_initfn(PCIDevice *dev)
{
+ PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
uint8_t *pci_conf = s->dev.config;
int i;
pci_conf[PCI_CLASS_PROG] = 0x00;
/* TODO: reset value should be 0. */
- pci_conf[PCI_INTERRUPT_PIN] = 4; /* interrupt pin D */
pci_conf[USB_SBRN] = USB_RELEASE_1; // release number
+ switch (pc->device_id) {
+ case PCI_DEVICE_ID_INTEL_82801I_UHCI1:
+ s->irq_pin = 0; /* A */
+ break;
+ case PCI_DEVICE_ID_INTEL_82801I_UHCI2:
+ s->irq_pin = 1; /* B */
+ break;
+ case PCI_DEVICE_ID_INTEL_82801I_UHCI3:
+ s->irq_pin = 2; /* C */
+ break;
+ default:
+ s->irq_pin = 3; /* D */
+ break;
+ }
+ pci_config_set_interrupt_pin(pci_conf, s->irq_pin + 1);
+
if (s->masterbus) {
USBPort *ports[NB_PORTS];
for(i = 0; i < NB_PORTS; i++) {
@@ -1204,6 +1227,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
}
}
+ s->bh = qemu_bh_new(uhci_bh, s);
s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
s->num_ports_vmstate = NB_PORTS;
QTAILQ_INIT(&s->queues);
@@ -1244,6 +1268,7 @@ static int usb_uhci_exit(PCIDevice *dev)
static Property uhci_properties[] = {
DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
+ DEFINE_PROP_UINT32("bandwidth", UHCIState, frame_bandwidth, 1280),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 5cf1a64699..6c2ff024e0 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -23,6 +23,7 @@
#include "hw/usb.h"
#include "hw/pci.h"
#include "hw/msi.h"
+#include "trace.h"
//#define DEBUG_XHCI
//#define DEBUG_DATA
@@ -421,7 +422,6 @@ typedef struct XHCIEvRingSeg {
uint32_t rsvd;
} XHCIEvRingSeg;
-#ifdef DEBUG_XHCI
static const char *TRBType_names[] = {
[TRB_RESERVED] = "TRB_RESERVED",
[TR_NORMAL] = "TR_NORMAL",
@@ -473,7 +473,6 @@ static const char *trb_name(XHCITRB *trb)
return lookup_name(TRB_TYPE(*trb), TRBType_names,
ARRAY_SIZE(TRBType_names));
}
-#endif
static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
unsigned int epid);
@@ -505,14 +504,13 @@ static void xhci_irq_update(XHCIState *xhci)
level = 1;
}
- DPRINTF("xhci_irq_update(): %d\n", level);
-
if (xhci->msi && msi_enabled(&xhci->pci_dev)) {
if (level) {
- DPRINTF("xhci_irq_update(): MSI signal\n");
+ trace_usb_xhci_irq_msi(0);
msi_notify(&xhci->pci_dev, 0);
}
} else {
+ trace_usb_xhci_irq_intx(level);
qemu_set_irq(xhci->irq, level);
}
}
@@ -542,9 +540,8 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
}
ev_trb.control = cpu_to_le32(ev_trb.control);
- DPRINTF("xhci_write_event(): [%d] %016"PRIx64" %08x %08x %s\n",
- xhci->er_ep_idx, ev_trb.parameter, ev_trb.status, ev_trb.control,
- trb_name(&ev_trb));
+ trace_usb_xhci_queue_event(xhci->er_ep_idx, trb_name(&ev_trb),
+ ev_trb.parameter, ev_trb.status, ev_trb.control);
addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx;
pci_dma_write(&xhci->pci_dev, addr, &ev_trb, TRB_SIZE);
@@ -704,10 +701,8 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
le32_to_cpus(&trb->status);
le32_to_cpus(&trb->control);
- DPRINTF("xhci: TRB fetched [" DMA_ADDR_FMT "]: "
- "%016" PRIx64 " %08x %08x %s\n",
- ring->dequeue, trb->parameter, trb->status, trb->control,
- trb_name(trb));
+ trace_usb_xhci_fetch_trb(ring->dequeue, trb_name(trb),
+ trb->parameter, trb->status, trb->control);
if ((trb->control & TRB_C) != ring->ccs) {
return 0;
@@ -746,10 +741,6 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
le32_to_cpus(&trb.status);
le32_to_cpus(&trb.control);
- DPRINTF("xhci: TRB peeked [" DMA_ADDR_FMT "]: "
- "%016" PRIx64 " %08x %08x\n",
- dequeue, trb.parameter, trb.status, trb.control);
-
if ((trb.control & TRB_C) != ccs) {
return -length;
}
@@ -812,14 +803,13 @@ static void xhci_er_reset(XHCIState *xhci)
static void xhci_run(XHCIState *xhci)
{
- DPRINTF("xhci_run()\n");
-
+ trace_usb_xhci_run();
xhci->usbsts &= ~USBSTS_HCH;
}
static void xhci_stop(XHCIState *xhci)
{
- DPRINTF("xhci_stop()\n");
+ trace_usb_xhci_stop();
xhci->usbsts |= USBSTS_HCH;
xhci->crcr_low &= ~CRCR_CRR;
}
@@ -852,11 +842,10 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
dma_addr_t dequeue;
int i;
+ trace_usb_xhci_ep_enable(slotid, epid);
assert(slotid >= 1 && slotid <= MAXSLOTS);
assert(epid >= 1 && epid <= 31);
- DPRINTF("xhci_enable_ep(%d, %d)\n", slotid, epid);
-
slot = &xhci->slots[slotid-1];
if (slot->eps[epid-1]) {
fprintf(stderr, "xhci: slot %d ep %d already enabled!\n", slotid, epid);
@@ -971,11 +960,10 @@ static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid,
XHCISlot *slot;
XHCIEPContext *epctx;
+ trace_usb_xhci_ep_disable(slotid, epid);
assert(slotid >= 1 && slotid <= MAXSLOTS);
assert(epid >= 1 && epid <= 31);
- DPRINTF("xhci_disable_ep(%d, %d)\n", slotid, epid);
-
slot = &xhci->slots[slotid-1];
if (!slot->eps[epid-1]) {
@@ -1001,8 +989,7 @@ static TRBCCode xhci_stop_ep(XHCIState *xhci, unsigned int slotid,
XHCISlot *slot;
XHCIEPContext *epctx;
- DPRINTF("xhci_stop_ep(%d, %d)\n", slotid, epid);
-
+ trace_usb_xhci_ep_stop(slotid, epid);
assert(slotid >= 1 && slotid <= MAXSLOTS);
if (epid < 1 || epid > 31) {
@@ -1036,10 +1023,9 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid,
XHCIEPContext *epctx;
USBDevice *dev;
+ trace_usb_xhci_ep_reset(slotid, epid);
assert(slotid >= 1 && slotid <= MAXSLOTS);
- DPRINTF("xhci_reset_ep(%d, %d)\n", slotid, epid);
-
if (epid < 1 || epid > 31) {
fprintf(stderr, "xhci: bad ep %d\n", epid);
return CC_TRB_ERROR;
@@ -1416,12 +1402,14 @@ static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
static int xhci_complete_packet(XHCITransfer *xfer, int ret)
{
if (ret == USB_RET_ASYNC) {
+ trace_usb_xhci_xfer_async(xfer);
xfer->running_async = 1;
xfer->running_retry = 0;
xfer->complete = 0;
xfer->cancelled = 0;
return 0;
} else if (ret == USB_RET_NAK) {
+ trace_usb_xhci_xfer_nak(xfer);
xfer->running_async = 0;
xfer->running_retry = 1;
xfer->complete = 0;
@@ -1436,10 +1424,12 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret)
if (ret >= 0) {
xfer->status = CC_SUCCESS;
xhci_xfer_data(xfer, xfer->data, ret, xfer->in_xfer, 0, 1);
+ trace_usb_xhci_xfer_success(xfer, ret);
return 0;
}
/* error */
+ trace_usb_xhci_xfer_error(xfer, ret);
switch (ret) {
case USB_RET_NODEV:
xfer->status = CC_USB_TRANSACTION_ERROR;
@@ -1475,11 +1465,12 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
USBDevice *dev;
int ret;
- DPRINTF("xhci_fire_ctl_transfer(slot=%d)\n", xfer->slotid);
-
trb_setup = &xfer->trbs[0];
trb_status = &xfer->trbs[xfer->trb_count-1];
+ trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid,
+ trb_setup->parameter >> 48);
+
/* at most one Event Data TRB allowed after STATUS */
if (TRB_TYPE(*trb_status) == TR_EVDATA && xfer->trb_count > 2) {
trb_status--;
@@ -1620,15 +1611,14 @@ static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext
unsigned int length = 0;
XHCITRB *trb;
- DPRINTF("xhci_fire_transfer(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid);
-
for (i = 0; i < xfer->trb_count; i++) {
trb = &xfer->trbs[i];
if (TRB_TYPE(*trb) == TR_NORMAL || TRB_TYPE(*trb) == TR_ISOCH) {
length += trb->status & 0x1ffff;
}
}
- DPRINTF("xhci: total TD length=%d\n", length);
+
+ trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid, length);
if (!epctx->has_bg) {
xfer->data_length = length;
@@ -1664,9 +1654,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
int length;
int i;
+ trace_usb_xhci_ep_kick(slotid, epid);
assert(slotid >= 1 && slotid <= MAXSLOTS);
assert(epid >= 1 && epid <= 31);
- DPRINTF("xhci_kick_ep(%d, %d)\n", slotid, epid);
if (!xhci->slots[slotid-1].enabled) {
fprintf(stderr, "xhci: xhci_kick_ep for disabled slot %d\n", slotid);
@@ -1684,15 +1674,13 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
XHCITransfer *xfer = epctx->retry;
int result;
- DPRINTF("xhci: retry nack'ed transfer ...\n");
+ trace_usb_xhci_xfer_retry(xfer);
assert(xfer->running_retry);
xhci_setup_packet(xfer, xfer->packet.ep->dev);
result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
if (result == USB_RET_NAK) {
- DPRINTF("xhci: ... xfer still nacked\n");
return;
}
- DPRINTF("xhci: ... result %d\n", result);
xhci_complete_packet(xfer, result);
assert(!xfer->running_retry);
epctx->retry = NULL;
@@ -1708,21 +1696,14 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
while (1) {
XHCITransfer *xfer = &epctx->transfers[epctx->next_xfer];
if (xfer->running_async || xfer->running_retry || xfer->backgrounded) {
- DPRINTF("xhci: ep is busy (#%d,%d,%d,%d)\n",
- epctx->next_xfer, xfer->running_async,
- xfer->running_retry, xfer->backgrounded);
break;
- } else {
- DPRINTF("xhci: ep: using #%d\n", epctx->next_xfer);
}
length = xhci_ring_chain_length(xhci, &epctx->ring);
if (length < 0) {
- DPRINTF("xhci: incomplete TD (%d TRBs)\n", -length);
break;
} else if (length == 0) {
break;
}
- DPRINTF("xhci: fetching %d-TRB TD\n", length);
if (xfer->trbs && xfer->trb_alloced < length) {
xfer->trb_count = 0;
xfer->trb_alloced = 0;
@@ -1757,7 +1738,6 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
}
if (epctx->state == EP_HALTED) {
- DPRINTF("xhci: ep halted, stopping schedule\n");
break;
}
if (xfer->running_retry) {
@@ -1770,8 +1750,8 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
static TRBCCode xhci_enable_slot(XHCIState *xhci, unsigned int slotid)
{
+ trace_usb_xhci_slot_enable(slotid);
assert(slotid >= 1 && slotid <= MAXSLOTS);
- DPRINTF("xhci_enable_slot(%d)\n", slotid);
xhci->slots[slotid-1].enabled = 1;
xhci->slots[slotid-1].port = 0;
memset(xhci->slots[slotid-1].eps, 0, sizeof(XHCIEPContext*)*31);
@@ -1783,8 +1763,8 @@ static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid)
{
int i;
+ trace_usb_xhci_slot_disable(slotid);
assert(slotid >= 1 && slotid <= MAXSLOTS);
- DPRINTF("xhci_disable_slot(%d)\n", slotid);
for (i = 1; i <= 31; i++) {
if (xhci->slots[slotid-1].eps[i-1]) {
@@ -1810,8 +1790,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
int i;
TRBCCode res;
+ trace_usb_xhci_slot_address(slotid);
assert(slotid >= 1 && slotid <= MAXSLOTS);
- DPRINTF("xhci_address_slot(%d)\n", slotid);
dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
pci_dma_read(&xhci->pci_dev, dcbaap + 8*slotid, &poctx, sizeof(poctx));
@@ -1897,8 +1877,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
int i;
TRBCCode res;
+ trace_usb_xhci_slot_configure(slotid);
assert(slotid >= 1 && slotid <= MAXSLOTS);
- DPRINTF("xhci_configure_slot(%d)\n", slotid);
ictx = xhci_mask64(pictx);
octx = xhci->slots[slotid-1].ctx;
@@ -1985,8 +1965,8 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
uint32_t islot_ctx[4];
uint32_t slot_ctx[4];
+ trace_usb_xhci_slot_evaluate(slotid);
assert(slotid >= 1 && slotid <= MAXSLOTS);
- DPRINTF("xhci_evaluate_slot(%d)\n", slotid);
ictx = xhci_mask64(pictx);
octx = xhci->slots[slotid-1].ctx;
@@ -2048,8 +2028,8 @@ static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid)
dma_addr_t octx;
int i;
+ trace_usb_xhci_slot_reset(slotid);
assert(slotid >= 1 && slotid <= MAXSLOTS);
- DPRINTF("xhci_reset_slot(%d)\n", slotid);
octx = xhci->slots[slotid-1].ctx;
@@ -2296,12 +2276,12 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach)
}
}
-static void xhci_reset(void *opaque)
+static void xhci_reset(DeviceState *dev)
{
- XHCIState *xhci = opaque;
+ XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev.qdev, dev);
int i;
- DPRINTF("xhci: full reset\n");
+ trace_usb_xhci_reset();
if (!(xhci->usbsts & USBSTS_HCH)) {
fprintf(stderr, "xhci: reset while running!\n");
}
@@ -2342,77 +2322,98 @@ static void xhci_reset(void *opaque)
static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
{
- DPRINTF("xhci_cap_read(0x%x)\n", reg);
+ uint32_t ret;
switch (reg) {
case 0x00: /* HCIVERSION, CAPLENGTH */
- return 0x01000000 | LEN_CAP;
+ ret = 0x01000000 | LEN_CAP;
+ break;
case 0x04: /* HCSPARAMS 1 */
- return (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS;
+ ret = (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS;
+ break;
case 0x08: /* HCSPARAMS 2 */
- return 0x0000000f;
+ ret = 0x0000000f;
+ break;
case 0x0c: /* HCSPARAMS 3 */
- return 0x00000000;
+ ret = 0x00000000;
+ break;
case 0x10: /* HCCPARAMS */
-#if TARGET_PHYS_ADDR_BITS > 32
- return 0x00081001;
-#else
- return 0x00081000;
-#endif
+ if (sizeof(dma_addr_t) == 4) {
+ ret = 0x00081000;
+ } else {
+ ret = 0x00081001;
+ }
+ break;
case 0x14: /* DBOFF */
- return OFF_DOORBELL;
+ ret = OFF_DOORBELL;
+ break;
case 0x18: /* RTSOFF */
- return OFF_RUNTIME;
+ ret = OFF_RUNTIME;
+ break;
/* extended capabilities */
case 0x20: /* Supported Protocol:00 */
-#if USB3_PORTS > 0
- return 0x02000402; /* USB 2.0 */
-#else
- return 0x02000002; /* USB 2.0 */
-#endif
+ ret = 0x02000402; /* USB 2.0 */
+ break;
case 0x24: /* Supported Protocol:04 */
- return 0x20425455; /* "USB " */
+ ret = 0x20425455; /* "USB " */
+ break;
case 0x28: /* Supported Protocol:08 */
- return 0x00000001 | (USB2_PORTS<<8);
+ ret = 0x00000001 | (USB2_PORTS<<8);
+ break;
case 0x2c: /* Supported Protocol:0c */
- return 0x00000000; /* reserved */
-#if USB3_PORTS > 0
+ ret = 0x00000000; /* reserved */
+ break;
case 0x30: /* Supported Protocol:00 */
- return 0x03000002; /* USB 3.0 */
+ ret = 0x03000002; /* USB 3.0 */
+ break;
case 0x34: /* Supported Protocol:04 */
- return 0x20425455; /* "USB " */
+ ret = 0x20425455; /* "USB " */
+ break;
case 0x38: /* Supported Protocol:08 */
- return 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8);
+ ret = 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8);
+ break;
case 0x3c: /* Supported Protocol:0c */
- return 0x00000000; /* reserved */
-#endif
+ ret = 0x00000000; /* reserved */
+ break;
default:
fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", reg);
+ ret = 0;
}
- return 0;
+
+ trace_usb_xhci_cap_read(reg, ret);
+ return ret;
}
static uint32_t xhci_port_read(XHCIState *xhci, uint32_t reg)
{
uint32_t port = reg >> 4;
+ uint32_t ret;
+
if (port >= MAXPORTS) {
fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
- return 0;
+ ret = 0;
+ goto out;
}
switch (reg & 0xf) {
case 0x00: /* PORTSC */
- return xhci->ports[port].portsc;
+ ret = xhci->ports[port].portsc;
+ break;
case 0x04: /* PORTPMSC */
case 0x08: /* PORTLI */
- return 0;
+ ret = 0;
+ break;
case 0x0c: /* reserved */
default:
fprintf(stderr, "xhci_port_read (port %d): reg 0x%x unimplemented\n",
port, reg);
- return 0;
+ ret = 0;
}
+
+out:
+ trace_usb_xhci_port_read(port, reg & 0x0f, ret);
+ return ret;
}
static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
@@ -2420,6 +2421,8 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
uint32_t port = reg >> 4;
uint32_t portsc;
+ trace_usb_xhci_port_write(port, reg & 0x0f, val);
+
if (port >= MAXPORTS) {
fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
return;
@@ -2457,7 +2460,7 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
{
- DPRINTF("xhci_oper_read(0x%x)\n", reg);
+ uint32_t ret;
if (reg >= 0x400) {
return xhci_port_read(xhci, reg - 0x400);
@@ -2465,38 +2468,50 @@ static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
switch (reg) {
case 0x00: /* USBCMD */
- return xhci->usbcmd;
+ ret = xhci->usbcmd;
+ break;
case 0x04: /* USBSTS */
- return xhci->usbsts;
+ ret = xhci->usbsts;
+ break;
case 0x08: /* PAGESIZE */
- return 1; /* 4KiB */
+ ret = 1; /* 4KiB */
+ break;
case 0x14: /* DNCTRL */
- return xhci->dnctrl;
+ ret = xhci->dnctrl;
+ break;
case 0x18: /* CRCR low */
- return xhci->crcr_low & ~0xe;
+ ret = xhci->crcr_low & ~0xe;
+ break;
case 0x1c: /* CRCR high */
- return xhci->crcr_high;
+ ret = xhci->crcr_high;
+ break;
case 0x30: /* DCBAAP low */
- return xhci->dcbaap_low;
+ ret = xhci->dcbaap_low;
+ break;
case 0x34: /* DCBAAP high */
- return xhci->dcbaap_high;
+ ret = xhci->dcbaap_high;
+ break;
case 0x38: /* CONFIG */
- return xhci->config;
+ ret = xhci->config;
+ break;
default:
fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", reg);
+ ret = 0;
}
- return 0;
+
+ trace_usb_xhci_oper_read(reg, ret);
+ return ret;
}
static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
{
- DPRINTF("xhci_oper_write(0x%x, 0x%08x)\n", reg, val);
-
if (reg >= 0x400) {
xhci_port_write(xhci, reg - 0x400, val);
return;
}
+ trace_usb_xhci_oper_write(reg, val);
+
switch (reg) {
case 0x00: /* USBCMD */
if ((val & USBCMD_RS) && !(xhci->usbcmd & USBCMD_RS)) {
@@ -2506,7 +2521,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
}
xhci->usbcmd = val & 0xc0f;
if (val & USBCMD_HCRST) {
- xhci_reset(xhci);
+ xhci_reset(&xhci->pci_dev.qdev);
}
xhci_irq_update(xhci);
break;
@@ -2552,35 +2567,46 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
{
- DPRINTF("xhci_runtime_read(0x%x)\n", reg);
+ uint32_t ret;
switch (reg) {
case 0x00: /* MFINDEX */
fprintf(stderr, "xhci_runtime_read: MFINDEX not yet implemented\n");
- return xhci->mfindex;
+ ret = xhci->mfindex;
+ break;
case 0x20: /* IMAN */
- return xhci->iman;
+ ret = xhci->iman;
+ break;
case 0x24: /* IMOD */
- return xhci->imod;
+ ret = xhci->imod;
+ break;
case 0x28: /* ERSTSZ */
- return xhci->erstsz;
+ ret = xhci->erstsz;
+ break;
case 0x30: /* ERSTBA low */
- return xhci->erstba_low;
+ ret = xhci->erstba_low;
+ break;
case 0x34: /* ERSTBA high */
- return xhci->erstba_high;
+ ret = xhci->erstba_high;
+ break;
case 0x38: /* ERDP low */
- return xhci->erdp_low;
+ ret = xhci->erdp_low;
+ break;
case 0x3c: /* ERDP high */
- return xhci->erdp_high;
+ ret = xhci->erdp_high;
+ break;
default:
fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg);
+ ret = 0;
}
- return 0;
+
+ trace_usb_xhci_runtime_read(reg, ret);
+ return ret;
}
static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
{
- DPRINTF("xhci_runtime_write(0x%x, 0x%08x)\n", reg, val);
+ trace_usb_xhci_runtime_read(reg, val);
switch (reg) {
case 0x20: /* IMAN */
@@ -2623,14 +2649,14 @@ static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
static uint32_t xhci_doorbell_read(XHCIState *xhci, uint32_t reg)
{
- DPRINTF("xhci_doorbell_read(0x%x)\n", reg);
/* doorbells always read as 0 */
+ trace_usb_xhci_doorbell_read(reg, 0);
return 0;
}
static void xhci_doorbell_write(XHCIState *xhci, uint32_t reg, uint32_t val)
{
- DPRINTF("xhci_doorbell_write(0x%x, 0x%08x)\n", reg, val);
+ trace_usb_xhci_doorbell_write(reg, val);
if (!xhci_running(xhci)) {
fprintf(stderr, "xhci: wrote doorbell while xHC stopped or paused\n");
@@ -2831,8 +2857,6 @@ static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
for (i = 0; i < MAXSLOTS; i++) {
xhci->slots[i].enabled = 0;
}
-
- qemu_register_reset(xhci_reset, xhci);
}
static int usb_xhci_initfn(struct PCIDevice *dev)
@@ -2895,6 +2919,7 @@ static void xhci_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_xhci;
dc->props = xhci_properties;
+ dc->reset = xhci_reset;
k->init = usb_xhci_initfn;
k->vendor_id = PCI_VENDOR_ID_NEC;
k->device_id = PCI_DEVICE_ID_NEC_UPD720200;
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 7c79c54d08..4fd5d9b04b 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -173,7 +173,7 @@ static void versatile_init(ram_addr_t ram_size,
const char *initrd_filename, const char *cpu_model,
int board_id)
{
- CPUARMState *env;
+ ARMCPU *cpu;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
qemu_irq *cpu_pic;
@@ -189,10 +189,11 @@ static void versatile_init(ram_addr_t ram_size,
int done_smc = 0;
DriveInfo *dinfo;
- if (!cpu_model)
+ if (!cpu_model) {
cpu_model = "arm926";
- env = cpu_init(cpu_model);
- if (!env) {
+ }
+ cpu = cpu_arm_init(cpu_model);
+ if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
@@ -208,7 +209,7 @@ static void versatile_init(ram_addr_t ram_size,
qdev_init_nofail(sysctl);
sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000);
- cpu_pic = arm_pic_init_cpu(env);
+ cpu_pic = arm_pic_init_cpu(cpu);
dev = sysbus_create_varargs("pl190", 0x10140000,
cpu_pic[0], cpu_pic[1], NULL);
for (n = 0; n < 32; n++) {
@@ -338,7 +339,7 @@ static void versatile_init(ram_addr_t ram_size,
versatile_binfo.kernel_cmdline = kernel_cmdline;
versatile_binfo.initrd_filename = initrd_filename;
versatile_binfo.board_id = board_id;
- arm_load_kernel(env, &versatile_binfo);
+ arm_load_kernel(cpu, &versatile_binfo);
}
static void vpb_init(ram_addr_t ram_size,
diff --git a/hw/vexpress.c b/hw/vexpress.c
index 18d87ac378..8072c5ada9 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -159,7 +159,6 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
const char *cpu_model,
qemu_irq *pic, uint32_t *proc_id)
{
- CPUARMState *env = NULL;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *lowram = g_new(MemoryRegion, 1);
@@ -177,12 +176,12 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
*proc_id = 0x0c000191;
for (n = 0; n < smp_cpus; n++) {
- env = cpu_init(cpu_model);
- if (!env) {
+ ARMCPU *cpu = cpu_arm_init(cpu_model);
+ if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- irqp = arm_pic_init_cpu(env);
+ irqp = arm_pic_init_cpu(cpu);
cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
}
@@ -259,7 +258,6 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
qemu_irq *pic, uint32_t *proc_id)
{
int n;
- CPUARMState *env = NULL;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *sram = g_new(MemoryRegion, 1);
@@ -274,13 +272,15 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
*proc_id = 0x14000217;
for (n = 0; n < smp_cpus; n++) {
+ ARMCPU *cpu;
qemu_irq *irqp;
- env = cpu_init(cpu_model);
- if (!env) {
+
+ cpu = cpu_arm_init(cpu_model);
+ if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- irqp = arm_pic_init_cpu(env);
+ irqp = arm_pic_init_cpu(cpu);
cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
}
@@ -438,7 +438,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
vexpress_binfo.smp_loader_start = map[VE_SRAM];
vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
vexpress_binfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr;
- arm_load_kernel(first_cpu, &vexpress_binfo);
+ arm_load_kernel(arm_env_get_cpu(first_cpu), &vexpress_binfo);
}
static void vexpress_a9_init(ram_addr_t ram_size,
diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index 4a133b5d1e..79bc0d10ee 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -78,19 +78,21 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env,
tlb->PID = 0;
}
-static CPUPPCState *ppc440_init_xilinx(ram_addr_t *ram_size,
- int do_init,
- const char *cpu_model,
- uint32_t sysclk)
+static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size,
+ int do_init,
+ const char *cpu_model,
+ uint32_t sysclk)
{
+ PowerPCCPU *cpu;
CPUPPCState *env;
qemu_irq *irqs;
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_ppc_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to initialize CPU!\n");
exit(1);
}
+ env = &cpu->env;
ppc_booke_timers_init(env, sysclk, 0/* no flags */);
@@ -101,15 +103,16 @@ static CPUPPCState *ppc440_init_xilinx(ram_addr_t *ram_size,
irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
ppcuic_init(env, irqs, 0x0C0, 0, 1);
- return env;
+ return cpu;
}
static void main_cpu_reset(void *opaque)
{
- CPUPPCState *env = opaque;
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
struct boot_info *bi = env->load_info;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
/* Linux Kernel Parameters (passing device tree):
* r3: pointer to the fdt
* r4: 0
@@ -188,6 +191,7 @@ static void virtex_init(ram_addr_t ram_size,
{
MemoryRegion *address_space_mem = get_system_memory();
DeviceState *dev;
+ PowerPCCPU *cpu;
CPUPPCState *env;
target_phys_addr_t ram_base = 0;
DriveInfo *dinfo;
@@ -201,8 +205,9 @@ static void virtex_init(ram_addr_t ram_size,
cpu_model = "440-Xilinx";
}
- env = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
- qemu_register_reset(main_cpu_reset, env);
+ cpu = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
+ env = &cpu->env;
+ qemu_register_reset(main_cpu_reset, cpu);
memory_region_init_ram(phys_ram, "ram", ram_size);
vmstate_register_ram_global(phys_ram);
@@ -224,7 +229,7 @@ static void virtex_init(ram_addr_t ram_size,
serial_hds[0], DEVICE_LITTLE_ENDIAN);
/* 2 timers at irq 2 @ 62 Mhz. */
- xilinx_timer_create(0x83c00000, irq[3], 2, 62 * 1000000);
+ xilinx_timer_create(0x83c00000, irq[3], 0, 62 * 1000000);
if (kernel_filename) {
uint64_t entry, low, high;
diff --git a/hw/watchdog.c b/hw/watchdog.c
index 4c18965654..a42124d520 100644
--- a/hw/watchdog.c
+++ b/hw/watchdog.c
@@ -66,7 +66,7 @@ int select_watchdog(const char *p)
QLIST_FOREACH(model, &watchdog_list, entry) {
if (strcasecmp(model->wdt_name, p) == 0) {
/* add the device */
- opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+ opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL);
qemu_opt_set(opts, "driver", p);
return 0;
}
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 07594bc0c8..de7e8a4a5c 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -537,6 +537,15 @@ static void blk_bh(void *opaque)
blk_handle_requests(blkdev);
}
+/*
+ * We need to account for the grant allocations requiring contiguous
+ * chunks; the worst case number would be
+ * max_req * max_seg + (max_req - 1) * (max_seg - 1) + 1,
+ * but in order to keep things simple just use
+ * 2 * max_req * max_seg.
+ */
+#define MAX_GRANTS(max_req, max_seg) (2 * (max_req) * (max_seg))
+
static void blk_alloc(struct XenDevice *xendev)
{
struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
@@ -548,6 +557,11 @@ static void blk_alloc(struct XenDevice *xendev)
if (xen_mode != XEN_EMULATE) {
batch_maps = 1;
}
+ if (xc_gnttab_set_max_grants(xendev->gnttabdev,
+ MAX_GRANTS(max_requests, BLKIF_MAX_SEGMENTS_PER_REQUEST)) < 0) {
+ xen_be_printf(xendev, 0, "xc_gnttab_set_max_grants failed: %s\n",
+ strerror(errno));
+ }
}
static int blk_init(struct XenDevice *xendev)
diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
index 7eee770eea..4b72aa7557 100644
--- a/hw/xen_machine_pv.c
+++ b/hw/xen_machine_pv.c
@@ -36,6 +36,7 @@ static void xen_init_pv(ram_addr_t ram_size,
const char *initrd_filename,
const char *cpu_model)
{
+ X86CPU *cpu;
CPUX86State *env;
DriveInfo *dinfo;
int i;
@@ -48,7 +49,8 @@ static void xen_init_pv(ram_addr_t ram_size,
cpu_model = "qemu32";
#endif
}
- env = cpu_init(cpu_model);
+ cpu = cpu_x86_init(cpu_model);
+ env = &cpu->env;
env->halted = 1;
/* Initialize backend core & drivers */
diff --git a/hw/xilinx.h b/hw/xilinx.h
index 35f35bd7fc..7df21eb958 100644
--- a/hw/xilinx.h
+++ b/hw/xilinx.h
@@ -6,7 +6,7 @@ xilinx_intc_create(target_phys_addr_t base, qemu_irq irq, int kind_of_intr)
{
DeviceState *dev;
- dev = qdev_create(NULL, "xilinx,intc");
+ dev = qdev_create(NULL, "xlnx.xps-intc");
qdev_prop_set_uint32(dev, "kind-of-intr", kind_of_intr);
qdev_init_nofail(dev);
sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
@@ -16,12 +16,12 @@ xilinx_intc_create(target_phys_addr_t base, qemu_irq irq, int kind_of_intr)
/* OPB Timer/Counter. */
static inline DeviceState *
-xilinx_timer_create(target_phys_addr_t base, qemu_irq irq, int nr, int freq)
+xilinx_timer_create(target_phys_addr_t base, qemu_irq irq, int oto, int freq)
{
DeviceState *dev;
- dev = qdev_create(NULL, "xilinx,timer");
- qdev_prop_set_uint32(dev, "nr-timers", nr);
+ dev = qdev_create(NULL, "xlnx,xps-timer");
+ qdev_prop_set_uint32(dev, "one-timer-only", oto);
qdev_prop_set_uint32(dev, "frequency", freq);
qdev_init_nofail(dev);
sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
@@ -36,12 +36,12 @@ xilinx_ethlite_create(NICInfo *nd, target_phys_addr_t base, qemu_irq irq,
{
DeviceState *dev;
- qemu_check_nic_model(nd, "xilinx-ethlite");
+ qemu_check_nic_model(nd, "xlnx.xps-ethernetlite");
- dev = qdev_create(NULL, "xilinx,ethlite");
+ dev = qdev_create(NULL, "xlnx.xps-ethernetlite");
qdev_set_nic_properties(dev, nd);
- qdev_prop_set_uint32(dev, "txpingpong", txpingpong);
- qdev_prop_set_uint32(dev, "rxpingpong", rxpingpong);
+ qdev_prop_set_uint32(dev, "tx-ping-pong", txpingpong);
+ qdev_prop_set_uint32(dev, "rx-ping-pong", rxpingpong);
qdev_init_nofail(dev);
sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
@@ -54,12 +54,12 @@ xilinx_axiethernet_create(void *dmach,
int txmem, int rxmem)
{
DeviceState *dev;
- qemu_check_nic_model(nd, "xilinx-axienet");
+ qemu_check_nic_model(nd, "xlnx.axi-ethernet");
- dev = qdev_create(NULL, "xilinx,axienet");
+ dev = qdev_create(NULL, "xlnx.axi-ethernet");
qdev_set_nic_properties(dev, nd);
- qdev_prop_set_uint32(dev, "c_rxmem", rxmem);
- qdev_prop_set_uint32(dev, "c_txmem", txmem);
+ qdev_prop_set_uint32(dev, "rxmem", rxmem);
+ qdev_prop_set_uint32(dev, "txmem", txmem);
qdev_prop_set_ptr(dev, "dmach", dmach);
qdev_init_nofail(dev);
sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
@@ -75,14 +75,14 @@ xilinx_axiethernetdma_create(void *dmach,
{
DeviceState *dev = NULL;
- dev = qdev_create(NULL, "xilinx,axidma");
+ dev = qdev_create(NULL, "xlnx.axi-dma");
qdev_prop_set_uint32(dev, "freqhz", freqhz);
qdev_prop_set_ptr(dev, "dmach", dmach);
qdev_init_nofail(dev);
sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
- sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq2);
- sysbus_connect_irq(sysbus_from_qdev(dev), 1, irq);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 1, irq2);
return dev;
}
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index 85dfcbf2b9..f4bec37c7a 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -463,8 +463,8 @@ static int xilinx_axidma_init(SysBusDevice *dev)
struct XilinxAXIDMA *s = FROM_SYSBUS(typeof(*s), dev);
int i;
- sysbus_init_irq(dev, &s->streams[1].irq);
sysbus_init_irq(dev, &s->streams[0].irq);
+ sysbus_init_irq(dev, &s->streams[1].irq);
if (!s->dmach) {
hw_error("Unconnected DMA channel.\n");
@@ -473,7 +473,7 @@ static int xilinx_axidma_init(SysBusDevice *dev)
xlx_dma_connect_dma(s->dmach, s, axidma_push);
memory_region_init_io(&s->iomem, &axidma_ops, s,
- "axidma", R_MAX * 4 * 2);
+ "xlnx.axi-dma", R_MAX * 4 * 2);
sysbus_init_mmio(dev, &s->iomem);
for (i = 0; i < 2; i++) {
@@ -502,7 +502,7 @@ static void axidma_class_init(ObjectClass *klass, void *data)
}
static TypeInfo axidma_info = {
- .name = "xilinx,axidma",
+ .name = "xlnx.axi-dma",
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct XilinxAXIDMA),
.class_init = axidma_class_init,
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index 7526273b4d..2e8d8a59ba 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -872,8 +872,8 @@ static int xilinx_enet_init(SysBusDevice *dev)
static Property xilinx_enet_properties[] = {
DEFINE_PROP_UINT32("phyaddr", struct XilinxAXIEnet, c_phyaddr, 7),
- DEFINE_PROP_UINT32("c_rxmem", struct XilinxAXIEnet, c_rxmem, 0x1000),
- DEFINE_PROP_UINT32("c_txmem", struct XilinxAXIEnet, c_txmem, 0x1000),
+ DEFINE_PROP_UINT32("rxmem", struct XilinxAXIEnet, c_rxmem, 0x1000),
+ DEFINE_PROP_UINT32("txmem", struct XilinxAXIEnet, c_txmem, 0x1000),
DEFINE_PROP_PTR("dmach", struct XilinxAXIEnet, dmach),
DEFINE_NIC_PROPERTIES(struct XilinxAXIEnet, conf),
DEFINE_PROP_END_OF_LIST(),
@@ -889,7 +889,7 @@ static void xilinx_enet_class_init(ObjectClass *klass, void *data)
}
static TypeInfo xilinx_enet_info = {
- .name = "xilinx,axienet",
+ .name = "xlnx.axi-ethernet",
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct XilinxAXIEnet),
.class_init = xilinx_enet_class_init,
diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c
index 857b33d172..affbb8bfff 100644
--- a/hw/xilinx_ethlite.c
+++ b/hw/xilinx_ethlite.c
@@ -216,7 +216,8 @@ static int xilinx_ethlite_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq);
s->rxbuf = 0;
- memory_region_init_io(&s->mmio, &eth_ops, s, "xilinx-ethlite", R_MAX * 4);
+ memory_region_init_io(&s->mmio, &eth_ops, s, "xlnx.xps-ethernetlite",
+ R_MAX * 4);
sysbus_init_mmio(dev, &s->mmio);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
@@ -227,8 +228,8 @@ static int xilinx_ethlite_init(SysBusDevice *dev)
}
static Property xilinx_ethlite_properties[] = {
- DEFINE_PROP_UINT32("txpingpong", struct xlx_ethlite, c_tx_pingpong, 1),
- DEFINE_PROP_UINT32("rxpingpong", struct xlx_ethlite, c_rx_pingpong, 1),
+ DEFINE_PROP_UINT32("tx-ping-pong", struct xlx_ethlite, c_tx_pingpong, 1),
+ DEFINE_PROP_UINT32("rx-ping-pong", struct xlx_ethlite, c_rx_pingpong, 1),
DEFINE_NIC_PROPERTIES(struct xlx_ethlite, conf),
DEFINE_PROP_END_OF_LIST(),
};
@@ -243,7 +244,7 @@ static void xilinx_ethlite_class_init(ObjectClass *klass, void *data)
}
static TypeInfo xilinx_ethlite_info = {
- .name = "xilinx,ethlite",
+ .name = "xlnx.xps-ethernetlite",
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct xlx_ethlite),
.class_init = xilinx_ethlite_class_init,
diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c
index 553f8488f6..386fd30743 100644
--- a/hw/xilinx_intc.c
+++ b/hw/xilinx_intc.c
@@ -156,7 +156,7 @@ static int xilinx_intc_init(SysBusDevice *dev)
qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
sysbus_init_irq(dev, &p->parent_irq);
- memory_region_init_io(&p->mmio, &pic_ops, p, "xilinx-pic", R_MAX * 4);
+ memory_region_init_io(&p->mmio, &pic_ops, p, "xlnx.xps-intc", R_MAX * 4);
sysbus_init_mmio(dev, &p->mmio);
return 0;
}
@@ -176,7 +176,7 @@ static void xilinx_intc_class_init(ObjectClass *klass, void *data)
}
static TypeInfo xilinx_intc_info = {
- .name = "xilinx,intc",
+ .name = "xlnx.xps-intc",
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct xlx_pic),
.class_init = xilinx_intc_class_init,
diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c
index 3ab2f2bb03..0683ce1ecf 100644
--- a/hw/xilinx_timer.c
+++ b/hw/xilinx_timer.c
@@ -62,11 +62,16 @@ struct timerblock
SysBusDevice busdev;
MemoryRegion mmio;
qemu_irq irq;
- uint32_t nr_timers;
+ uint8_t one_timer_only;
uint32_t freq_hz;
struct xlx_timer *timers;
};
+static inline unsigned int num_timers(struct timerblock *t)
+{
+ return 2 - t->one_timer_only;
+}
+
static inline unsigned int timer_from_addr(target_phys_addr_t addr)
{
/* Timers get a 4x32bit control reg area each. */
@@ -78,7 +83,7 @@ static void timer_update_irq(struct timerblock *t)
unsigned int i, irq = 0;
uint32_t csr;
- for (i = 0; i < t->nr_timers; i++) {
+ for (i = 0; i < num_timers(t); i++) {
csr = t->timers[i].regs[R_TCSR];
irq |= (csr & TCSR_TINT) && (csr & TCSR_ENIT);
}
@@ -202,8 +207,8 @@ static int xilinx_timer_init(SysBusDevice *dev)
sysbus_init_irq(dev, &t->irq);
/* Init all the ptimers. */
- t->timers = g_malloc0(sizeof t->timers[0] * t->nr_timers);
- for (i = 0; i < t->nr_timers; i++) {
+ t->timers = g_malloc0(sizeof t->timers[0] * num_timers(t));
+ for (i = 0; i < num_timers(t); i++) {
struct xlx_timer *xt = &t->timers[i];
xt->parent = t;
@@ -213,15 +218,15 @@ static int xilinx_timer_init(SysBusDevice *dev)
ptimer_set_freq(xt->ptimer, t->freq_hz);
}
- memory_region_init_io(&t->mmio, &timer_ops, t, "xilinx-timer",
- R_MAX * 4 * t->nr_timers);
+ memory_region_init_io(&t->mmio, &timer_ops, t, "xlnx,xps-timer",
+ R_MAX * 4 * num_timers(t));
sysbus_init_mmio(dev, &t->mmio);
return 0;
}
static Property xilinx_timer_properties[] = {
- DEFINE_PROP_UINT32("frequency", struct timerblock, freq_hz, 0),
- DEFINE_PROP_UINT32("nr-timers", struct timerblock, nr_timers, 0),
+ DEFINE_PROP_UINT32("frequency", struct timerblock, freq_hz, 62 * 1000000),
+ DEFINE_PROP_UINT8("one-timer-only", struct timerblock, one_timer_only, 0),
DEFINE_PROP_END_OF_LIST(),
};
@@ -235,7 +240,7 @@ static void xilinx_timer_class_init(ObjectClass *klass, void *data)
}
static TypeInfo xilinx_timer_info = {
- .name = "xilinx,timer",
+ .name = "xlnx,xps-timer",
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct timerblock),
.class_init = xilinx_timer_class_init,
diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
index aa0170db49..d0f32db2c6 100644
--- a/hw/xilinx_uartlite.c
+++ b/hw/xilinx_uartlite.c
@@ -202,7 +202,8 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq);
uart_update_status(s);
- memory_region_init_io(&s->mmio, &uart_ops, s, "xilinx-uartlite", R_MAX * 4);
+ memory_region_init_io(&s->mmio, &uart_ops, s, "xlnx.xps-uartlite",
+ R_MAX * 4);
sysbus_init_mmio(dev, &s->mmio);
s->chr = qemu_char_get_next_serial();
@@ -219,7 +220,7 @@ static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
}
static TypeInfo xilinx_uartlite_info = {
- .name = "xilinx,uartlite",
+ .name = "xlnx.xps-uartlite",
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof (struct xlx_uartlite),
.class_init = xilinx_uartlite_class_init,
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index 7290c64a4c..7e6c27359e 100644
--- a/hw/xilinx_zynq.c
+++ b/hw/xilinx_zynq.c
@@ -50,7 +50,7 @@ static void zynq_init(ram_addr_t ram_size, const char *boot_device,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
- CPUARMState *env = NULL;
+ ARMCPU *cpu;
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
@@ -66,12 +66,12 @@ static void zynq_init(ram_addr_t ram_size, const char *boot_device,
cpu_model = "cortex-a9";
}
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_arm_init(cpu_model);
+ if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- irqp = arm_pic_init_cpu(env);
+ irqp = arm_pic_init_cpu(cpu);
cpu_irq = irqp[ARM_PIC_CPU_IRQ];
/* max 2GB ram */
@@ -137,7 +137,7 @@ static void zynq_init(ram_addr_t ram_size, const char *boot_device,
zynq_binfo.nb_cpus = 1;
zynq_binfo.board_id = 0xd32;
zynq_binfo.loader_start = 0;
- arm_load_kernel(first_cpu, &zynq_binfo);
+ arm_load_kernel(arm_env_get_cpu(first_cpu), &zynq_binfo);
}
static QEMUMachine zynq_machine = {
diff --git a/hw/xtensa/Makefile.objs b/hw/xtensa/Makefile.objs
new file mode 100644
index 0000000000..79698e903d
--- /dev/null
+++ b/hw/xtensa/Makefile.objs
@@ -0,0 +1,5 @@
+obj-y += xtensa_pic.o
+obj-y += xtensa_sim.o
+obj-y += xtensa_lx60.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
index afdef494b2..b153bfdddf 100644
--- a/hw/xtensa_lx60.c
+++ b/hw/xtensa_lx60.c
@@ -148,9 +148,9 @@ static uint64_t translate_phys_addr(void *env, uint64_t addr)
static void lx60_reset(void *opaque)
{
- CPUXtensaState *env = opaque;
+ XtensaCPU *cpu = opaque;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
}
static void lx_init(const LxBoardDesc *board,
@@ -164,6 +164,7 @@ static void lx_init(const LxBoardDesc *board,
int be = 0;
#endif
MemoryRegion *system_memory = get_system_memory();
+ XtensaCPU *cpu = NULL;
CPUXtensaState *env = NULL;
MemoryRegion *ram, *rom, *system_io;
DriveInfo *dinfo;
@@ -175,17 +176,19 @@ static void lx_init(const LxBoardDesc *board,
}
for (n = 0; n < smp_cpus; n++) {
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_xtensa_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+ env = &cpu->env;
+
env->sregs[PRID] = n;
- qemu_register_reset(lx60_reset, env);
+ qemu_register_reset(lx60_reset, cpu);
/* Need MMU initialized prior to ELF loading,
* so that ELF gets loaded into virtual addresses
*/
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
}
ram = g_malloc(sizeof(*ram));
diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c
index c7e05dcf4e..1ce07fb899 100644
--- a/hw/xtensa_sim.c
+++ b/hw/xtensa_sim.c
@@ -37,9 +37,11 @@ static uint64_t translate_phys_addr(void *env, uint64_t addr)
return cpu_get_phys_page_debug(env, addr);
}
-static void sim_reset(void *env)
+static void sim_reset(void *opaque)
{
- cpu_state_reset(env);
+ XtensaCPU *cpu = opaque;
+
+ cpu_reset(CPU(cpu));
}
static void sim_init(ram_addr_t ram_size,
@@ -47,22 +49,25 @@ static void sim_init(ram_addr_t ram_size,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
+ XtensaCPU *cpu = NULL;
CPUXtensaState *env = NULL;
MemoryRegion *ram, *rom;
int n;
for (n = 0; n < smp_cpus; n++) {
- env = cpu_init(cpu_model);
- if (!env) {
+ cpu = cpu_xtensa_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+ env = &cpu->env;
+
env->sregs[PRID] = n;
- qemu_register_reset(sim_reset, env);
+ qemu_register_reset(sim_reset, cpu);
/* Need MMU initialized prior to ELF loading,
* so that ELF gets loaded into virtual addresses
*/
- sim_reset(env);
+ sim_reset(cpu);
}
ram = g_malloc(sizeof(*ram));
diff --git a/hw/z2.c b/hw/z2.c
index 654ac55f5c..289cee90c4 100644
--- a/hw/z2.c
+++ b/hw/z2.c
@@ -301,7 +301,7 @@ static void z2_init(ram_addr_t ram_size,
{
MemoryRegion *address_space_mem = get_system_memory();
uint32_t sector_len = 0x10000;
- PXA2xxState *cpu;
+ PXA2xxState *mpu;
DriveInfo *dinfo;
int be;
void *z2_lcd;
@@ -313,7 +313,7 @@ static void z2_init(ram_addr_t ram_size,
}
/* Setup CPU & memory */
- cpu = pxa270_init(address_space_mem, z2_binfo.ram_size, cpu_model);
+ mpu = pxa270_init(address_space_mem, z2_binfo.ram_size, cpu_model);
#ifdef TARGET_WORDS_BIGENDIAN
be = 1;
@@ -337,25 +337,25 @@ static void z2_init(ram_addr_t ram_size,
}
/* setup keypad */
- pxa27x_register_keypad(cpu->kp, map, 0x100);
+ pxa27x_register_keypad(mpu->kp, map, 0x100);
/* MMC/SD host */
- pxa2xx_mmci_handlers(cpu->mmc,
+ pxa2xx_mmci_handlers(mpu->mmc,
NULL,
- qdev_get_gpio_in(cpu->gpio, Z2_GPIO_SD_DETECT));
+ qdev_get_gpio_in(mpu->gpio, Z2_GPIO_SD_DETECT));
type_register_static(&zipit_lcd_info);
type_register_static(&aer915_info);
- z2_lcd = ssi_create_slave(cpu->ssp[1], "zipit-lcd");
- bus = pxa2xx_i2c_bus(cpu->i2c[0]);
+ z2_lcd = ssi_create_slave(mpu->ssp[1], "zipit-lcd");
+ bus = pxa2xx_i2c_bus(mpu->i2c[0]);
i2c_create_slave(bus, "aer915", 0x55);
wm = i2c_create_slave(bus, "wm8750", 0x1b);
- cpu->i2s->opaque = wm;
- cpu->i2s->codec_out = wm8750_dac_dat;
- cpu->i2s->codec_in = wm8750_adc_dat;
- wm8750_data_req_set(wm, cpu->i2s->data_req, cpu->i2s);
+ mpu->i2s->opaque = wm;
+ mpu->i2s->codec_out = wm8750_dac_dat;
+ mpu->i2s->codec_in = wm8750_adc_dat;
+ wm8750_data_req_set(wm, mpu->i2s->data_req, mpu->i2s);
- qdev_connect_gpio_out(cpu->gpio, Z2_GPIO_LCD_CS,
+ qdev_connect_gpio_out(mpu->gpio, Z2_GPIO_LCD_CS,
qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
if (kernel_filename) {
@@ -363,7 +363,7 @@ static void z2_init(ram_addr_t ram_size,
z2_binfo.kernel_cmdline = kernel_cmdline;
z2_binfo.initrd_filename = initrd_filename;
z2_binfo.board_id = 0x6dd;
- arm_load_kernel(cpu->env, &z2_binfo);
+ arm_load_kernel(mpu->cpu, &z2_binfo);
}
}
diff --git a/kvm-all.c b/kvm-all.c
index 489ee53ad2..4ea7d85fe2 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -62,11 +62,6 @@ typedef struct KVMSlot
typedef struct kvm_dirty_log KVMDirtyLog;
-typedef struct KVMMSIRoute {
- struct kvm_irq_routing_entry kroute;
- QTAILQ_ENTRY(KVMMSIRoute) entry;
-} KVMMSIRoute;
-
struct KVMState
{
KVMSlot slots[32];
@@ -867,6 +862,11 @@ int kvm_irqchip_set_irq(KVMState *s, int irq, int level)
}
#ifdef KVM_CAP_IRQ_ROUTING
+typedef struct KVMMSIRoute {
+ struct kvm_irq_routing_entry kroute;
+ QTAILQ_ENTRY(KVMMSIRoute) entry;
+} KVMMSIRoute;
+
static void set_gsi(KVMState *s, unsigned int gsi)
{
s->used_gsi_bitmap[gsi / 32] |= 1U << (gsi % 32);
@@ -1129,6 +1129,10 @@ static void kvm_init_irq_routing(KVMState *s)
{
}
+void kvm_irqchip_release_virq(KVMState *s, int virq)
+{
+}
+
int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
{
abort();
@@ -1286,7 +1290,9 @@ int kvm_init(void)
s->pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2);
#endif
+#ifdef KVM_CAP_IRQ_ROUTING
s->direct_msi = (kvm_check_extension(s, KVM_CAP_SIGNAL_MSI) > 0);
+#endif
ret = kvm_arch_init(s);
if (ret < 0) {
diff --git a/libcacard/Makefile b/libcacard/Makefile
index c6a896a739..fdc287370d 100644
--- a/libcacard/Makefile
+++ b/libcacard/Makefile
@@ -2,29 +2,23 @@
-include $(SRC_PATH)/Makefile.objs
-include $(SRC_PATH)/rules.mak
-libcacard_srcpath=$(SRC_PATH)/libcacard
libcacard_includedir=$(includedir)/cacard
-$(call set-vpath, $(SRC_PATH):$(libcacard_srcpath))
-
-# objects linked against normal qemu binaries, not compiled with libtool
-QEMU_OBJS=$(addprefix ../,$(oslib-obj-y) qemu-timer-common.o $(trace-obj-y))
+$(call set-vpath, $(SRC_PATH))
# objects linked into a shared library, built with libtool with -fPIC if required
-QEMU_OBJS_LIB=$(addsuffix .lo,$(basename $(QEMU_OBJS)))
+QEMU_OBJS=$(oslib-obj-y) qemu-timer-common.o $(trace-obj-y)
+QEMU_OBJS_LIB=$(patsubst %.o,%.lo,$(QEMU_OBJS))
QEMU_CFLAGS+=-I../
-libcacard.lib-y=$(addsuffix .lo,$(basename $(libcacard-y)))
-
-vscclient: $(libcacard-y) $(QEMU_OBJS) vscclient.o
- $(call quiet-command,$(CC) -o $@ $^ $(libcacard_libs) $(LIBS)," LINK $@")
+libcacard.lib-y=$(patsubst %.o,%.lo,$(libcacard-y))
clean:
rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~ vscclient *.lo .libs/* *.la *.pc
rm -Rf .libs
-all: vscclient
+all: libcacard.la libcacard.pc
# Dummy command so that make thinks it has done something
@true
@@ -41,6 +35,7 @@ else
libcacard.la: $(libcacard.lib-y) $(QEMU_OBJS_LIB)
$(call quiet-command,$(LIBTOOL) --mode=link --quiet --tag=CC $(CC) -rpath $(libdir) -o $@ $^ $(libcacard_libs)," lt LINK $@")
+libcacard_srcpath=$(SRC_PATH)/libcacard
libcacard.pc: $(libcacard_srcpath)/libcacard.pc.in
sed -e 's|@LIBDIR@|$(libdir)|' \
-e 's|@INCLUDEDIR@|$(libcacard_includedir)|' \
diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs
new file mode 100644
index 0000000000..5899d72d3e
--- /dev/null
+++ b/linux-user/Makefile.objs
@@ -0,0 +1,7 @@
+obj-y = main.o syscall.o strace.o mmap.o signal.o \
+ elfload.o linuxload.o uaccess.o cpu-uname.o
+
+obj-$(TARGET_HAS_BFLT) += flatload.o
+obj-$(TARGET_I386) += vm86.o
+obj-$(TARGET_ARM) += arm/nwfpe/
+obj-$(TARGET_M68K) += m68k-sim.o
diff --git a/linux-user/arm/nwfpe/Makefile.objs b/linux-user/arm/nwfpe/Makefile.objs
new file mode 100644
index 0000000000..51b0c32c2a
--- /dev/null
+++ b/linux-user/arm/nwfpe/Makefile.objs
@@ -0,0 +1,2 @@
+obj-y = fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o fpopcode.o
+obj-y += single_cpdo.o double_cpdo.o extended_cpdo.o
diff --git a/linux-user/main.c b/linux-user/main.c
index 191b75060d..49108b81d3 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3405,7 +3405,7 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
- cpu_state_reset(env);
+ cpu_reset(ENV_GET_CPU(env));
#endif
thread_env = env;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 20d2a74877..539af3f94b 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4262,7 +4262,7 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
/* we create a new CPU instance. */
new_env = cpu_copy(env);
#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
- cpu_state_reset(new_env);
+ cpu_reset(ENV_GET_CPU(new_env));
#endif
/* Init regs that differ from the parent. */
cpu_clone_regs(new_env, newsp);
diff --git a/memory_mapping-stub.c b/memory_mapping-stub.c
new file mode 100644
index 0000000000..76be34d89f
--- /dev/null
+++ b/memory_mapping-stub.c
@@ -0,0 +1,33 @@
+/*
+ * QEMU memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ * Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "cpu.h"
+#include "cpu-all.h"
+#include "memory_mapping.h"
+
+int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+{
+ return -2;
+}
+
+int cpu_get_memory_mapping(MemoryMappingList *list,
+ CPUArchState *env)
+{
+ return -1;
+}
+
+bool cpu_paging_enabled(CPUArchState *env)
+{
+ return true;
+}
+
diff --git a/memory_mapping.c b/memory_mapping.c
new file mode 100644
index 0000000000..6f5a2e3f71
--- /dev/null
+++ b/memory_mapping.c
@@ -0,0 +1,246 @@
+/*
+ * QEMU memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ * Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "cpu.h"
+#include "cpu-all.h"
+#include "memory_mapping.h"
+
+static void memory_mapping_list_add_mapping_sorted(MemoryMappingList *list,
+ MemoryMapping *mapping)
+{
+ MemoryMapping *p;
+
+ QTAILQ_FOREACH(p, &list->head, next) {
+ if (p->phys_addr >= mapping->phys_addr) {
+ QTAILQ_INSERT_BEFORE(p, mapping, next);
+ return;
+ }
+ }
+ QTAILQ_INSERT_TAIL(&list->head, mapping, next);
+}
+
+static void create_new_memory_mapping(MemoryMappingList *list,
+ target_phys_addr_t phys_addr,
+ target_phys_addr_t virt_addr,
+ ram_addr_t length)
+{
+ MemoryMapping *memory_mapping;
+
+ memory_mapping = g_malloc(sizeof(MemoryMapping));
+ memory_mapping->phys_addr = phys_addr;
+ memory_mapping->virt_addr = virt_addr;
+ memory_mapping->length = length;
+ list->last_mapping = memory_mapping;
+ list->num++;
+ memory_mapping_list_add_mapping_sorted(list, memory_mapping);
+}
+
+static inline bool mapping_contiguous(MemoryMapping *map,
+ target_phys_addr_t phys_addr,
+ target_phys_addr_t virt_addr)
+{
+ return phys_addr == map->phys_addr + map->length &&
+ virt_addr == map->virt_addr + map->length;
+}
+
+/*
+ * [map->phys_addr, map->phys_addr + map->length) and
+ * [phys_addr, phys_addr + length) have intersection?
+ */
+static inline bool mapping_have_same_region(MemoryMapping *map,
+ target_phys_addr_t phys_addr,
+ ram_addr_t length)
+{
+ return !(phys_addr + length < map->phys_addr ||
+ phys_addr >= map->phys_addr + map->length);
+}
+
+/*
+ * [map->phys_addr, map->phys_addr + map->length) and
+ * [phys_addr, phys_addr + length) have intersection. The virtual address in the
+ * intersection are the same?
+ */
+static inline bool mapping_conflict(MemoryMapping *map,
+ target_phys_addr_t phys_addr,
+ target_phys_addr_t virt_addr)
+{
+ return virt_addr - map->virt_addr != phys_addr - map->phys_addr;
+}
+
+/*
+ * [map->virt_addr, map->virt_addr + map->length) and
+ * [virt_addr, virt_addr + length) have intersection. And the physical address
+ * in the intersection are the same.
+ */
+static inline void mapping_merge(MemoryMapping *map,
+ target_phys_addr_t virt_addr,
+ ram_addr_t length)
+{
+ if (virt_addr < map->virt_addr) {
+ map->length += map->virt_addr - virt_addr;
+ map->virt_addr = virt_addr;
+ }
+
+ if ((virt_addr + length) >
+ (map->virt_addr + map->length)) {
+ map->length = virt_addr + length - map->virt_addr;
+ }
+}
+
+void memory_mapping_list_add_merge_sorted(MemoryMappingList *list,
+ target_phys_addr_t phys_addr,
+ target_phys_addr_t virt_addr,
+ ram_addr_t length)
+{
+ MemoryMapping *memory_mapping, *last_mapping;
+
+ if (QTAILQ_EMPTY(&list->head)) {
+ create_new_memory_mapping(list, phys_addr, virt_addr, length);
+ return;
+ }
+
+ last_mapping = list->last_mapping;
+ if (last_mapping) {
+ if (mapping_contiguous(last_mapping, phys_addr, virt_addr)) {
+ last_mapping->length += length;
+ return;
+ }
+ }
+
+ QTAILQ_FOREACH(memory_mapping, &list->head, next) {
+ if (mapping_contiguous(memory_mapping, phys_addr, virt_addr)) {
+ memory_mapping->length += length;
+ list->last_mapping = memory_mapping;
+ return;
+ }
+
+ if (phys_addr + length < memory_mapping->phys_addr) {
+ /* create a new region before memory_mapping */
+ break;
+ }
+
+ if (mapping_have_same_region(memory_mapping, phys_addr, length)) {
+ if (mapping_conflict(memory_mapping, phys_addr, virt_addr)) {
+ continue;
+ }
+
+ /* merge this region into memory_mapping */
+ mapping_merge(memory_mapping, virt_addr, length);
+ list->last_mapping = memory_mapping;
+ return;
+ }
+ }
+
+ /* this region can not be merged into any existed memory mapping. */
+ create_new_memory_mapping(list, phys_addr, virt_addr, length);
+}
+
+void memory_mapping_list_free(MemoryMappingList *list)
+{
+ MemoryMapping *p, *q;
+
+ QTAILQ_FOREACH_SAFE(p, &list->head, next, q) {
+ QTAILQ_REMOVE(&list->head, p, next);
+ g_free(p);
+ }
+
+ list->num = 0;
+ list->last_mapping = NULL;
+}
+
+void memory_mapping_list_init(MemoryMappingList *list)
+{
+ list->num = 0;
+ list->last_mapping = NULL;
+ QTAILQ_INIT(&list->head);
+}
+
+static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu)
+{
+ CPUArchState *env;
+
+ for (env = start_cpu; env != NULL; env = env->next_cpu) {
+ if (cpu_paging_enabled(env)) {
+ return env;
+ }
+ }
+
+ return NULL;
+}
+
+int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+{
+ CPUArchState *env, *first_paging_enabled_cpu;
+ RAMBlock *block;
+ ram_addr_t offset, length;
+ int ret;
+
+ first_paging_enabled_cpu = find_paging_enabled_cpu(first_cpu);
+ if (first_paging_enabled_cpu) {
+ for (env = first_paging_enabled_cpu; env != NULL; env = env->next_cpu) {
+ ret = cpu_get_memory_mapping(list, env);
+ if (ret < 0) {
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ /*
+ * If the guest doesn't use paging, the virtual address is equal to physical
+ * address.
+ */
+ QLIST_FOREACH(block, &ram_list.blocks, next) {
+ offset = block->offset;
+ length = block->length;
+ create_new_memory_mapping(list, offset, offset, length);
+ }
+
+ return 0;
+}
+
+void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list)
+{
+ RAMBlock *block;
+
+ QLIST_FOREACH(block, &ram_list.blocks, next) {
+ create_new_memory_mapping(list, block->offset, 0, block->length);
+ }
+}
+
+void memory_mapping_filter(MemoryMappingList *list, int64_t begin,
+ int64_t length)
+{
+ MemoryMapping *cur, *next;
+
+ QTAILQ_FOREACH_SAFE(cur, &list->head, next, next) {
+ if (cur->phys_addr >= begin + length ||
+ cur->phys_addr + cur->length <= begin) {
+ QTAILQ_REMOVE(&list->head, cur, next);
+ list->num--;
+ continue;
+ }
+
+ if (cur->phys_addr < begin) {
+ cur->length -= begin - cur->phys_addr;
+ if (cur->virt_addr) {
+ cur->virt_addr += begin - cur->phys_addr;
+ }
+ cur->phys_addr = begin;
+ }
+
+ if (cur->phys_addr + cur->length > begin + length) {
+ cur->length -= cur->phys_addr + cur->length - begin - length;
+ }
+ }
+}
diff --git a/memory_mapping.h b/memory_mapping.h
new file mode 100644
index 0000000000..ef72b0abad
--- /dev/null
+++ b/memory_mapping.h
@@ -0,0 +1,64 @@
+/*
+ * QEMU memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ * Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef MEMORY_MAPPING_H
+#define MEMORY_MAPPING_H
+
+#include "qemu-queue.h"
+
+/* The physical and virtual address in the memory mapping are contiguous. */
+typedef struct MemoryMapping {
+ target_phys_addr_t phys_addr;
+ target_ulong virt_addr;
+ ram_addr_t length;
+ QTAILQ_ENTRY(MemoryMapping) next;
+} MemoryMapping;
+
+typedef struct MemoryMappingList {
+ unsigned int num;
+ MemoryMapping *last_mapping;
+ QTAILQ_HEAD(, MemoryMapping) head;
+} MemoryMappingList;
+
+int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env);
+bool cpu_paging_enabled(CPUArchState *env);
+
+/*
+ * add or merge the memory region [phys_addr, phys_addr + length) into the
+ * memory mapping's list. The region's virtual address starts with virt_addr,
+ * and is contiguous. The list is sorted by phys_addr.
+ */
+void memory_mapping_list_add_merge_sorted(MemoryMappingList *list,
+ target_phys_addr_t phys_addr,
+ target_phys_addr_t virt_addr,
+ ram_addr_t length);
+
+void memory_mapping_list_free(MemoryMappingList *list);
+
+void memory_mapping_list_init(MemoryMappingList *list);
+
+/*
+ * Return value:
+ * 0: success
+ * -1: failed
+ * -2: unsupported
+ */
+int qemu_get_guest_memory_mapping(MemoryMappingList *list);
+
+/* get guest's memory mapping without do paging(virtual address is 0). */
+void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list);
+
+void memory_mapping_filter(MemoryMappingList *list, int64_t begin,
+ int64_t length);
+
+#endif
diff --git a/monitor.c b/monitor.c
index 12a6fe25ad..a3bc2c7253 100644
--- a/monitor.c
+++ b/monitor.c
@@ -422,6 +422,30 @@ static void timestamp_put(QDict *qdict)
qdict_put_obj(qdict, "timestamp", obj);
}
+
+static const char *monitor_event_names[] = {
+ [QEVENT_SHUTDOWN] = "SHUTDOWN",
+ [QEVENT_RESET] = "RESET",
+ [QEVENT_POWERDOWN] = "POWERDOWN",
+ [QEVENT_STOP] = "STOP",
+ [QEVENT_RESUME] = "RESUME",
+ [QEVENT_VNC_CONNECTED] = "VNC_CONNECTED",
+ [QEVENT_VNC_INITIALIZED] = "VNC_INITIALIZED",
+ [QEVENT_VNC_DISCONNECTED] = "VNC_DISCONNECTED",
+ [QEVENT_BLOCK_IO_ERROR] = "BLOCK_IO_ERROR",
+ [QEVENT_RTC_CHANGE] = "RTC_CHANGE",
+ [QEVENT_WATCHDOG] = "WATCHDOG",
+ [QEVENT_SPICE_CONNECTED] = "SPICE_CONNECTED",
+ [QEVENT_SPICE_INITIALIZED] = "SPICE_INITIALIZED",
+ [QEVENT_SPICE_DISCONNECTED] = "SPICE_DISCONNECTED",
+ [QEVENT_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED",
+ [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED",
+ [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED",
+ [QEVENT_SUSPEND] = "SUSPEND",
+ [QEVENT_WAKEUP] = "WAKEUP",
+};
+QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX)
+
/**
* monitor_protocol_event(): Generate a Monitor event
*
@@ -435,68 +459,8 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
assert(event < QEVENT_MAX);
- switch (event) {
- case QEVENT_SHUTDOWN:
- event_name = "SHUTDOWN";
- break;
- case QEVENT_RESET:
- event_name = "RESET";
- break;
- case QEVENT_POWERDOWN:
- event_name = "POWERDOWN";
- break;
- case QEVENT_STOP:
- event_name = "STOP";
- break;
- case QEVENT_RESUME:
- event_name = "RESUME";
- break;
- case QEVENT_VNC_CONNECTED:
- event_name = "VNC_CONNECTED";
- break;
- case QEVENT_VNC_INITIALIZED:
- event_name = "VNC_INITIALIZED";
- break;
- case QEVENT_VNC_DISCONNECTED:
- event_name = "VNC_DISCONNECTED";
- break;
- case QEVENT_BLOCK_IO_ERROR:
- event_name = "BLOCK_IO_ERROR";
- break;
- case QEVENT_RTC_CHANGE:
- event_name = "RTC_CHANGE";
- break;
- case QEVENT_WATCHDOG:
- event_name = "WATCHDOG";
- break;
- case QEVENT_SPICE_CONNECTED:
- event_name = "SPICE_CONNECTED";
- break;
- case QEVENT_SPICE_INITIALIZED:
- event_name = "SPICE_INITIALIZED";
- break;
- case QEVENT_SPICE_DISCONNECTED:
- event_name = "SPICE_DISCONNECTED";
- break;
- case QEVENT_BLOCK_JOB_COMPLETED:
- event_name = "BLOCK_JOB_COMPLETED";
- break;
- case QEVENT_BLOCK_JOB_CANCELLED:
- event_name = "BLOCK_JOB_CANCELLED";
- break;
- case QEVENT_DEVICE_TRAY_MOVED:
- event_name = "DEVICE_TRAY_MOVED";
- break;
- case QEVENT_SUSPEND:
- event_name = "SUSPEND";
- break;
- case QEVENT_WAKEUP:
- event_name = "WAKEUP";
- break;
- default:
- abort();
- break;
- }
+ event_name = monitor_event_names[event];
+ assert(event_name != NULL);
qmp = qdict_new();
timestamp_put(qmp);
@@ -738,6 +702,25 @@ CommandInfoList *qmp_query_commands(Error **errp)
return cmd_list;
}
+EventInfoList *qmp_query_events(Error **errp)
+{
+ EventInfoList *info, *ev_list = NULL;
+ MonitorEvent e;
+
+ for (e = 0 ; e < QEVENT_MAX ; e++) {
+ const char *event_name = monitor_event_names[e];
+ assert(event_name != NULL);
+ info = g_malloc0(sizeof(*info));
+ info->value = g_malloc0(sizeof(*info->value));
+ info->value->name = g_strdup(event_name);
+
+ info->next = ev_list;
+ ev_list = info;
+ }
+
+ return ev_list;
+}
+
/* set the current CPU defined by the user */
int monitor_set_cpu(int cpu_index)
{
diff --git a/monitor.h b/monitor.h
index 0d498006f8..cd1d8786d1 100644
--- a/monitor.h
+++ b/monitor.h
@@ -41,6 +41,10 @@ typedef enum MonitorEvent {
QEVENT_DEVICE_TRAY_MOVED,
QEVENT_SUSPEND,
QEVENT_WAKEUP,
+
+ /* Add to 'monitor_event_names' array in monitor.c when
+ * defining new events here */
+
QEVENT_MAX,
} MonitorEvent;
diff --git a/net.c b/net.c
index 1922d8abd1..4aa416cffb 100644
--- a/net.c
+++ b/net.c
@@ -745,10 +745,7 @@ int net_handle_fd_param(Monitor *mon, const char *param)
return fd;
}
-static int net_init_nic(QemuOpts *opts,
- Monitor *mon,
- const char *name,
- VLANState *vlan)
+static int net_init_nic(QemuOpts *opts, const char *name, VLANState *vlan)
{
int idx;
NICInfo *nd;
@@ -821,7 +818,6 @@ static int net_init_nic(QemuOpts *opts,
}
typedef int (*net_client_init_func)(QemuOpts *opts,
- Monitor *mon,
const char *name,
VLANState *vlan);
@@ -1085,7 +1081,7 @@ static const struct {
#endif /* CONFIG_NET_BRIDGE */
};
-int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
+int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)
{
const char *name;
const char *type;
@@ -1093,7 +1089,7 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
type = qemu_opt_get(opts, "type");
if (!type) {
- qerror_report(QERR_MISSING_PARAMETER, "type");
+ error_set(errp, QERR_MISSING_PARAMETER, "type");
return -1;
}
@@ -1109,21 +1105,21 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
strcmp(type, "vde") != 0 &&
#endif
strcmp(type, "socket") != 0) {
- qerror_report(QERR_INVALID_PARAMETER_VALUE, "type",
- "a netdev backend type");
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type",
+ "a netdev backend type");
return -1;
}
if (qemu_opt_get(opts, "vlan")) {
- qerror_report(QERR_INVALID_PARAMETER, "vlan");
+ error_set(errp, QERR_INVALID_PARAMETER, "vlan");
return -1;
}
if (qemu_opt_get(opts, "name")) {
- qerror_report(QERR_INVALID_PARAMETER, "name");
+ error_set(errp, QERR_INVALID_PARAMETER, "name");
return -1;
}
if (!qemu_opts_id(opts)) {
- qerror_report(QERR_MISSING_PARAMETER, "id");
+ error_set(errp, QERR_MISSING_PARAMETER, "id");
return -1;
}
}
@@ -1136,10 +1132,13 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
for (i = 0; i < NET_CLIENT_TYPE_MAX; i++) {
if (net_client_types[i].type != NULL &&
!strcmp(net_client_types[i].type, type)) {
+ Error *local_err = NULL;
VLANState *vlan = NULL;
int ret;
- if (qemu_opts_validate(opts, &net_client_types[i].desc[0]) == -1) {
+ qemu_opts_validate(opts, &net_client_types[i].desc[0], &local_err);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
return -1;
}
@@ -1152,10 +1151,10 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
ret = 0;
if (net_client_types[i].init) {
- ret = net_client_types[i].init(opts, mon, name, vlan);
+ ret = net_client_types[i].init(opts, name, vlan);
if (ret < 0) {
/* TODO push error reporting into init() methods */
- qerror_report(QERR_DEVICE_INIT_FAILED, type);
+ error_set(errp, QERR_DEVICE_INIT_FAILED, type);
return -1;
}
}
@@ -1163,8 +1162,8 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
}
}
- qerror_report(QERR_INVALID_PARAMETER_VALUE, "type",
- "a network client type");
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type",
+ "a network client type");
return -1;
}
@@ -1195,6 +1194,7 @@ void net_host_device_add(Monitor *mon, const QDict *qdict)
{
const char *device = qdict_get_str(qdict, "device");
const char *opts_str = qdict_get_try_str(qdict, "opts");
+ Error *local_err = NULL;
QemuOpts *opts;
if (!net_host_check_device(device)) {
@@ -1209,7 +1209,10 @@ void net_host_device_add(Monitor *mon, const QDict *qdict)
qemu_opt_set(opts, "type", device);
- if (net_client_init(mon, opts, 0) < 0) {
+ net_client_init(opts, 0, &local_err);
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
monitor_printf(mon, "adding host network device %s failed\n", device);
}
}
@@ -1231,37 +1234,53 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict)
qemu_del_vlan_client(vc);
}
-int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void netdev_add(QemuOpts *opts, Error **errp)
{
+ net_client_init(opts, 1, errp);
+}
+
+int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret)
+{
+ Error *local_err = NULL;
+ QemuOptsList *opts_list;
QemuOpts *opts;
- int res;
- opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict);
- if (!opts) {
- return -1;
+ opts_list = qemu_find_opts_err("netdev", &local_err);
+ if (error_is_set(&local_err)) {
+ goto exit_err;
+ }
+
+ opts = qemu_opts_from_qdict(opts_list, qdict, &local_err);
+ if (error_is_set(&local_err)) {
+ goto exit_err;
}
- res = net_client_init(mon, opts, 1);
- if (res < 0) {
+ netdev_add(opts, &local_err);
+ if (error_is_set(&local_err)) {
qemu_opts_del(opts);
+ goto exit_err;
}
- return res;
+ return 0;
+
+exit_err:
+ qerror_report_err(local_err);
+ error_free(local_err);
+ return -1;
}
-int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_netdev_del(const char *id, Error **errp)
{
- const char *id = qdict_get_str(qdict, "id");
VLANClientState *vc;
vc = qemu_find_netdev(id);
if (!vc) {
- qerror_report(QERR_DEVICE_NOT_FOUND, id);
- return -1;
+ error_set(errp, QERR_DEVICE_NOT_FOUND, id);
+ return;
}
+
qemu_del_vlan_client(vc);
- qemu_opts_del(qemu_opts_find(qemu_find_opts("netdev"), id));
- return 0;
+ qemu_opts_del(qemu_opts_find(qemu_find_opts_err("netdev", errp), id));
}
static void print_net_client(Monitor *mon, VLANClientState *vc)
@@ -1424,14 +1443,31 @@ void net_check_clients(void)
static int net_init_client(QemuOpts *opts, void *dummy)
{
- if (net_client_init(NULL, opts, 0) < 0)
+ Error *local_err = NULL;
+
+ net_client_init(opts, 0, &local_err);
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
return -1;
+ }
+
return 0;
}
static int net_init_netdev(QemuOpts *opts, void *dummy)
{
- return net_client_init(NULL, opts, 1);
+ Error *local_err = NULL;
+ int ret;
+
+ ret = net_client_init(opts, 1, &local_err);
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
+ return -1;
+ }
+
+ return ret;
}
int net_init_clients(void)
diff --git a/net.h b/net.h
index 64993b43ef..bdc2a0602d 100644
--- a/net.h
+++ b/net.h
@@ -163,15 +163,15 @@ struct HCIInfo *qemu_next_hci(void);
extern const char *legacy_tftp_prefix;
extern const char *legacy_bootp_filename;
-int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev);
+int net_client_init(QemuOpts *opts, int is_netdev, Error **errp);
int net_client_parse(QemuOptsList *opts_list, const char *str);
int net_init_clients(void);
void net_check_clients(void);
void net_cleanup(void);
void net_host_device_add(Monitor *mon, const QDict *qdict);
void net_host_device_remove(Monitor *mon, const QDict *qdict);
-int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
+void netdev_add(QemuOpts *opts, Error **errp);
+int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret);
#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
diff --git a/net/Makefile.objs b/net/Makefile.objs
new file mode 100644
index 0000000000..72f50bc903
--- /dev/null
+++ b/net/Makefile.objs
@@ -0,0 +1,12 @@
+common-obj-y = queue.o checksum.o util.o
+common-obj-y += socket.o
+common-obj-y += dump.o
+common-obj-$(CONFIG_POSIX) += tap.o
+common-obj-$(CONFIG_LINUX) += tap-linux.o
+common-obj-$(CONFIG_WIN32) += tap-win32.o
+common-obj-$(CONFIG_BSD) += tap-bsd.o
+common-obj-$(CONFIG_SOLARIS) += tap-solaris.o
+common-obj-$(CONFIG_AIX) += tap-aix.o
+common-obj-$(CONFIG_HAIKU) += tap-haiku.o
+common-obj-$(CONFIG_SLIRP) += slirp.o
+common-obj-$(CONFIG_VDE) += vde.o
diff --git a/net/dump.c b/net/dump.c
index 4b48d48408..f835c51187 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -144,7 +144,7 @@ static int net_dump_init(VLANState *vlan, const char *device,
return 0;
}
-int net_init_dump(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
+int net_init_dump(QemuOpts *opts, const char *name, VLANState *vlan)
{
int len;
const char *file;
diff --git a/net/dump.h b/net/dump.h
index fdc91ad6dc..2b5d9ba644 100644
--- a/net/dump.h
+++ b/net/dump.h
@@ -27,7 +27,6 @@
#include "net.h"
#include "qemu-common.h"
-int net_init_dump(QemuOpts *opts, Monitor *mon,
- const char *name, VLANState *vlan);
+int net_init_dump(QemuOpts *opts, const char *name, VLANState *vlan);
#endif /* QEMU_NET_DUMP_H */
diff --git a/net/slirp.c b/net/slirp.c
index 96f5032c4c..37b6ccfde9 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -676,10 +676,7 @@ static int net_init_slirp_configs(const char *name, const char *value, void *opa
return 0;
}
-int net_init_slirp(QemuOpts *opts,
- Monitor *mon,
- const char *name,
- VLANState *vlan)
+int net_init_slirp(QemuOpts *opts, const char *name, VLANState *vlan)
{
struct slirp_config_str *config;
const char *vhost;
diff --git a/net/slirp.h b/net/slirp.h
index c17de8ed47..53fe95dc12 100644
--- a/net/slirp.h
+++ b/net/slirp.h
@@ -30,10 +30,7 @@
#ifdef CONFIG_SLIRP
-int net_init_slirp(QemuOpts *opts,
- Monitor *mon,
- const char *name,
- VLANState *vlan);
+int net_init_slirp(QemuOpts *opts, const char *name, VLANState *vlan);
void net_slirp_hostfwd_add(Monitor *mon, const QDict *qdict);
void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict);
diff --git a/net/socket.c b/net/socket.c
index 0bcf229c24..fcd0a3c162 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -26,6 +26,7 @@
#include "config-host.h"
#include "net.h"
+#include "monitor.h"
#include "qemu-char.h"
#include "qemu-common.h"
#include "qemu-error.h"
@@ -585,10 +586,7 @@ static int net_socket_udp_init(VLANState *vlan,
return 0;
}
-int net_init_socket(QemuOpts *opts,
- Monitor *mon,
- const char *name,
- VLANState *vlan)
+int net_init_socket(QemuOpts *opts, const char *name, VLANState *vlan)
{
if (qemu_opt_get(opts, "fd")) {
int fd;
@@ -601,7 +599,7 @@ int net_init_socket(QemuOpts *opts,
return -1;
}
- fd = net_handle_fd_param(mon, qemu_opt_get(opts, "fd"));
+ fd = net_handle_fd_param(cur_mon, qemu_opt_get(opts, "fd"));
if (fd == -1) {
return -1;
}
diff --git a/net/socket.h b/net/socket.h
index ea46f02dd8..e1fe959412 100644
--- a/net/socket.h
+++ b/net/socket.h
@@ -27,7 +27,6 @@
#include "net.h"
#include "qemu-common.h"
-int net_init_socket(QemuOpts *opts, Monitor *mon,
- const char *name, VLANState *vlan);
+int net_init_socket(QemuOpts *opts, const char *name, VLANState *vlan);
#endif /* QEMU_NET_SOCKET_H */
diff --git a/net/tap-bsd.c b/net/tap-bsd.c
index 4b6b3a41a0..937a94b11f 100644
--- a/net/tap-bsd.c
+++ b/net/tap-bsd.c
@@ -33,12 +33,6 @@
#include <net/if_tap.h>
#endif
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-#include <libutil.h>
-#else
-#include <util.h>
-#endif
-
int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required)
{
int fd;
diff --git a/net/tap-win32.c b/net/tap-win32.c
index 596132e272..a801a553c4 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -699,7 +699,7 @@ static int tap_win32_init(VLANState *vlan, const char *model,
return 0;
}
-int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
+int net_init_tap(QemuOpts *opts, const char *name, VLANState *vlan)
{
const char *ifname;
diff --git a/net/tap.c b/net/tap.c
index f2400283c3..5ac4ba3343 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -512,8 +512,7 @@ static int net_bridge_run_helper(const char *helper, const char *bridge)
return -1;
}
-int net_init_bridge(QemuOpts *opts, Monitor *mon, const char *name,
- VLANState *vlan)
+int net_init_bridge(QemuOpts *opts, const char *name, VLANState *vlan)
{
TAPState *s;
int fd, vnet_hdr;
@@ -583,7 +582,7 @@ static int net_tap_init(QemuOpts *opts, int *vnet_hdr)
return fd;
}
-int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
+int net_init_tap(QemuOpts *opts, const char *name, VLANState *vlan)
{
TAPState *s;
int fd, vnet_hdr = 0;
@@ -600,7 +599,7 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
return -1;
}
- fd = net_handle_fd_param(mon, qemu_opt_get(opts, "fd"));
+ fd = net_handle_fd_param(cur_mon, qemu_opt_get(opts, "fd"));
if (fd == -1) {
return -1;
}
@@ -687,7 +686,7 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
int vhostfd, r;
bool force = qemu_opt_get_bool(opts, "vhostforce", false);
if (qemu_opt_get(opts, "vhostfd")) {
- r = net_handle_fd_param(mon, qemu_opt_get(opts, "vhostfd"));
+ r = net_handle_fd_param(cur_mon, qemu_opt_get(opts, "vhostfd"));
if (r == -1) {
return -1;
}
diff --git a/net/tap.h b/net/tap.h
index 56c591fc8e..b2a9450aab 100644
--- a/net/tap.h
+++ b/net/tap.h
@@ -32,7 +32,7 @@
#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
-int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan);
+int net_init_tap(QemuOpts *opts, const char *name, VLANState *vlan);
int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required);
@@ -57,7 +57,6 @@ int tap_get_fd(VLANClientState *vc);
struct vhost_net;
struct vhost_net *tap_get_vhost_net(VLANClientState *vc);
-int net_init_bridge(QemuOpts *opts, Monitor *mon, const char *name,
- VLANState *vlan);
+int net_init_bridge(QemuOpts *opts, const char *name, VLANState *vlan);
#endif /* QEMU_NET_TAP_H */
diff --git a/net/vde.c b/net/vde.c
index ac48ab2f0a..6b9d45294a 100644
--- a/net/vde.c
+++ b/net/vde.c
@@ -110,7 +110,7 @@ static int net_vde_init(VLANState *vlan, const char *model,
return 0;
}
-int net_init_vde(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
+int net_init_vde(QemuOpts *opts, const char *name, VLANState *vlan)
{
const char *sock;
const char *group;
diff --git a/net/vde.h b/net/vde.h
index 3e6ca3e876..732e5756f6 100644
--- a/net/vde.h
+++ b/net/vde.h
@@ -29,7 +29,7 @@
#ifdef CONFIG_VDE
-int net_init_vde(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan);
+int net_init_vde(QemuOpts *opts, const char *name, VLANState *vlan);
#endif /* CONFIG_VDE */
diff --git a/qapi-schema.json b/qapi-schema.json
index 2ca7195d25..3b6e3468b4 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -228,6 +228,28 @@
{ 'command': 'query-commands', 'returns': ['CommandInfo'] }
##
+# @EventInfo:
+#
+# Information about a QMP event
+#
+# @name: The event name
+#
+# Since: 1.2.0
+##
+{ 'type': 'EventInfo', 'data': {'name': 'str'} }
+
+##
+# @query-events:
+#
+# Return a list of supported QMP events by this server
+#
+# Returns: A list of @EventInfo for all supported events
+#
+# Since: 1.2.0
+##
+{ 'command': 'query-events', 'returns': ['EventInfo'] }
+
+##
# @MigrationStats
#
# Detailed migration status.
@@ -1755,3 +1777,88 @@
# Since: 0.14.0
##
{ 'command': 'device_del', 'data': {'id': 'str'} }
+
+##
+# @dump-guest-memory
+#
+# Dump guest's memory to vmcore. It is a synchronous operation that can take
+# very long depending on the amount of guest memory. This command is only
+# supported only on i386 and x86_64
+#
+# @paging: if true, do paging to get guest's memory mapping. The @paging's
+# default value of @paging is false, If you want to use gdb to process the
+# core, please set @paging to true. The reason why the @paging's value is
+# false:
+# 1. guest machine in a catastrophic state can have corrupted memory,
+# which we cannot trust.
+# 2. The guest machine can be in read-mode even if paging is enabled.
+# For example: the guest machine uses ACPI to sleep, and ACPI sleep
+# state goes in real-mode
+# @protocol: the filename or file descriptor of the vmcore. The supported
+# protocol can be file or fd:
+# 1. file: the protocol starts with "file:", and the following string is
+# the file's path.
+# 2. fd: the protocol starts with "fd:", and the following string is the
+# fd's name.
+# @begin: #optional if specified, the starting physical address.
+# @length: #optional if specified, the memory size, in bytes. If you don't
+# want to dump all guest's memory, please specify the start @begin and
+# @length
+#
+# Returns: nothing on success
+# If @begin contains an invalid address, InvalidParameter
+# If only one of @begin and @length is specified, MissingParameter
+# If @protocol stats with "fd:", and the fd cannot be found, FdNotFound
+# If @protocol starts with "file:", and the file cannot be
+# opened, OpenFileFailed
+# If @protocol does not start with "fd:" or "file:", InvalidParameter
+# If an I/O error occurs while writing the file, IOError
+# If the target does not support this command, Unsupported
+#
+# Since: 1.2
+##
+{ 'command': 'dump-guest-memory',
+ 'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int',
+ '*length': 'int' } }
+##
+# @netdev_add:
+#
+# Add a network backend.
+#
+# @type: the type of network backend. Current valid values are 'user', 'tap',
+# 'vde', 'socket', 'dump' and 'bridge'
+#
+# @id: the name of the new network backend
+#
+# @props: #optional a list of properties to be passed to the backend in
+# the format 'name=value', like 'ifname=tap0,script=no'
+#
+# Notes: The semantics of @props is not well defined. Future commands will be
+# introduced that provide stronger typing for backend creation.
+#
+# Since: 0.14.0
+#
+# Returns: Nothing on success
+# If @type is not a valid network backend, DeviceNotFound
+# If @id is not a valid identifier, InvalidParameterValue
+# if @id already exists, DuplicateId
+# If @props contains an invalid parameter for this backend,
+# InvalidParameter
+##
+{ 'command': 'netdev_add',
+ 'data': {'type': 'str', 'id': 'str', '*props': '**'},
+ 'gen': 'no' }
+
+##
+# @netdev_del:
+#
+# Remove a network backend.
+#
+# @id: the name of the network backend to remove
+#
+# Returns: Nothing on success
+# If @id is not a valid network backend, DeviceNotFound
+#
+# Since: 0.14.0
+##
+{ 'command': 'netdev_del', 'data': {'id': 'str'} }
diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs
new file mode 100644
index 0000000000..d0b0c16b90
--- /dev/null
+++ b/qapi/Makefile.objs
@@ -0,0 +1,3 @@
+qapi-obj-y = qapi-visit-core.o qapi-dealloc-visitor.o qmp-input-visitor.o
+qapi-obj-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
+qapi-obj-y += string-input-visitor.o string-output-visitor.o
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index a4e088c9fc..ffffbf79aa 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -97,6 +97,145 @@ void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)
}
}
+void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp)
+{
+ int64_t value;
+ if (!error_is_set(errp)) {
+ if (v->type_uint8) {
+ v->type_uint8(v, obj, name, errp);
+ } else {
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ if (value < 0 || value > UINT8_MAX) {
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "uint8_t");
+ return;
+ }
+ *obj = value;
+ }
+ }
+}
+
+void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name, Error **errp)
+{
+ int64_t value;
+ if (!error_is_set(errp)) {
+ if (v->type_uint16) {
+ v->type_uint16(v, obj, name, errp);
+ } else {
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ if (value < 0 || value > UINT16_MAX) {
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "uint16_t");
+ return;
+ }
+ *obj = value;
+ }
+ }
+}
+
+void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name, Error **errp)
+{
+ int64_t value;
+ if (!error_is_set(errp)) {
+ if (v->type_uint32) {
+ v->type_uint32(v, obj, name, errp);
+ } else {
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ if (value < 0 || value > UINT32_MAX) {
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "uint32_t");
+ return;
+ }
+ *obj = value;
+ }
+ }
+}
+
+void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp)
+{
+ int64_t value;
+ if (!error_is_set(errp)) {
+ if (v->type_uint64) {
+ v->type_uint64(v, obj, name, errp);
+ } else {
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ *obj = value;
+ }
+ }
+}
+
+void visit_type_int8(Visitor *v, int8_t *obj, const char *name, Error **errp)
+{
+ int64_t value;
+ if (!error_is_set(errp)) {
+ if (v->type_int8) {
+ v->type_int8(v, obj, name, errp);
+ } else {
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ if (value < INT8_MIN || value > INT8_MAX) {
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "int8_t");
+ return;
+ }
+ *obj = value;
+ }
+ }
+}
+
+void visit_type_int16(Visitor *v, int16_t *obj, const char *name, Error **errp)
+{
+ int64_t value;
+ if (!error_is_set(errp)) {
+ if (v->type_int16) {
+ v->type_int16(v, obj, name, errp);
+ } else {
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ if (value < INT16_MIN || value > INT16_MAX) {
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "int16_t");
+ return;
+ }
+ *obj = value;
+ }
+ }
+}
+
+void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp)
+{
+ int64_t value;
+ if (!error_is_set(errp)) {
+ if (v->type_int32) {
+ v->type_int32(v, obj, name, errp);
+ } else {
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ if (value < INT32_MIN || value > INT32_MAX) {
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "int32_t");
+ return;
+ }
+ *obj = value;
+ }
+ }
+}
+
+void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp)
+{
+ if (!error_is_set(errp)) {
+ if (v->type_int64) {
+ v->type_int64(v, obj, name, errp);
+ } else {
+ v->type_int(v, obj, name, errp);
+ }
+ }
+}
+
void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp)
{
if (!error_is_set(errp)) {
diff --git a/qapi/qapi-visit-core.h b/qapi/qapi-visit-core.h
index e850746b75..a19d70c104 100644
--- a/qapi/qapi-visit-core.h
+++ b/qapi/qapi-visit-core.h
@@ -52,6 +52,14 @@ struct Visitor
void (*start_handle)(Visitor *v, void **obj, const char *kind,
const char *name, Error **errp);
void (*end_handle)(Visitor *v, Error **errp);
+ void (*type_uint8)(Visitor *v, uint8_t *obj, const char *name, Error **errp);
+ void (*type_uint16)(Visitor *v, uint16_t *obj, const char *name, Error **errp);
+ void (*type_uint32)(Visitor *v, uint32_t *obj, const char *name, Error **errp);
+ void (*type_uint64)(Visitor *v, uint64_t *obj, const char *name, Error **errp);
+ void (*type_int8)(Visitor *v, int8_t *obj, const char *name, Error **errp);
+ void (*type_int16)(Visitor *v, int16_t *obj, const char *name, Error **errp);
+ void (*type_int32)(Visitor *v, int32_t *obj, const char *name, Error **errp);
+ void (*type_int64)(Visitor *v, int64_t *obj, const char *name, Error **errp);
};
void visit_start_handle(Visitor *v, void **obj, const char *kind,
@@ -69,6 +77,14 @@ void visit_end_optional(Visitor *v, Error **errp);
void visit_type_enum(Visitor *v, int *obj, const char *strings[],
const char *kind, const char *name, Error **errp);
void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp);
+void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp);
+void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name, Error **errp);
+void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name, Error **errp);
+void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp);
+void visit_type_int8(Visitor *v, int8_t *obj, const char *name, Error **errp);
+void visit_type_int16(Visitor *v, int16_t *obj, const char *name, Error **errp);
+void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp);
+void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp);
void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c
index 92b0305212..34e525eadd 100644
--- a/qapi/string-output-visitor.c
+++ b/qapi/string-output-visitor.c
@@ -52,7 +52,7 @@ static void print_type_number(Visitor *v, double *obj, const char *name,
Error **errp)
{
StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
- string_output_set(sov, g_strdup_printf("%g", *obj));
+ string_output_set(sov, g_strdup_printf("%f", *obj));
}
char *string_output_get_string(StringOutputVisitor *sov)
diff --git a/qemu-char.c b/qemu-char.c
index fe1126fe86..c2aaaeeb8f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -56,19 +56,19 @@
#include <sys/select.h>
#ifdef CONFIG_BSD
#include <sys/stat.h>
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#include <libutil.h>
-#include <dev/ppbus/ppi.h>
-#include <dev/ppbus/ppbconf.h>
#if defined(__GLIBC__)
#include <pty.h>
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+#include <libutil.h>
+#else
+#include <util.h>
#endif
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#include <dev/ppbus/ppi.h>
+#include <dev/ppbus/ppbconf.h>
#elif defined(__DragonFly__)
-#include <libutil.h>
#include <dev/misc/ppi/ppi.h>
#include <bus/ppbus/ppbconf.h>
-#else
-#include <util.h>
#endif
#else
#ifdef __linux__
@@ -2584,10 +2584,14 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
int pos;
const char *p;
QemuOpts *opts;
+ Error *local_err = NULL;
- opts = qemu_opts_create(qemu_find_opts("chardev"), label, 1);
- if (NULL == opts)
+ opts = qemu_opts_create(qemu_find_opts("chardev"), label, 1, &local_err);
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
return NULL;
+ }
if (strstart(filename, "mon:", &p)) {
filename = p;
diff --git a/qemu-config.c b/qemu-config.c
index be84a0347c..bb3bff426a 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -3,6 +3,7 @@
#include "qemu-option.h"
#include "qemu-config.h"
#include "hw/qdev.h"
+#include "error.h"
static QemuOptsList qemu_drive_opts = {
.name = "drive",
@@ -631,7 +632,8 @@ static QemuOptsList *vm_config_groups[32] = {
NULL,
};
-static QemuOptsList *find_list(QemuOptsList **lists, const char *group)
+static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
+ Error **errp)
{
int i;
@@ -640,14 +642,28 @@ static QemuOptsList *find_list(QemuOptsList **lists, const char *group)
break;
}
if (lists[i] == NULL) {
- error_report("there is no option group \"%s\"", group);
+ error_set(errp, QERR_INVALID_OPTION_GROUP, group);
}
return lists[i];
}
QemuOptsList *qemu_find_opts(const char *group)
{
- return find_list(vm_config_groups, group);
+ QemuOptsList *ret;
+ Error *local_err = NULL;
+
+ ret = find_list(vm_config_groups, group, &local_err);
+ if (error_is_set(&local_err)) {
+ error_report("%s\n", error_get_pretty(local_err));
+ error_free(local_err);
+ }
+
+ return ret;
+}
+
+QemuOptsList *qemu_find_opts_err(const char *group, Error **errp)
+{
+ return find_list(vm_config_groups, group, errp);
}
void qemu_add_opts(QemuOptsList *list)
@@ -709,7 +725,7 @@ int qemu_global_option(const char *str)
return -1;
}
- opts = qemu_opts_create(&qemu_global_opts, NULL, 0);
+ opts = qemu_opts_create(&qemu_global_opts, NULL, 0, NULL);
qemu_opt_set(opts, "driver", driver);
qemu_opt_set(opts, "property", property);
qemu_opt_set(opts, "value", str+offset+1);
@@ -762,6 +778,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
char line[1024], group[64], id[64], arg[64], value[1024];
Location loc;
QemuOptsList *list = NULL;
+ Error *local_err = NULL;
QemuOpts *opts = NULL;
int res = -1, lno = 0;
@@ -778,18 +795,24 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
}
if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
/* group with id */
- list = find_list(lists, group);
- if (list == NULL)
+ list = find_list(lists, group, &local_err);
+ if (error_is_set(&local_err)) {
+ error_report("%s\n", error_get_pretty(local_err));
+ error_free(local_err);
goto out;
- opts = qemu_opts_create(list, id, 1);
+ }
+ opts = qemu_opts_create(list, id, 1, NULL);
continue;
}
if (sscanf(line, "[%63[^]]]", group) == 1) {
/* group without id */
- list = find_list(lists, group);
- if (list == NULL)
+ list = find_list(lists, group, &local_err);
+ if (error_is_set(&local_err)) {
+ error_report("%s\n", error_get_pretty(local_err));
+ error_free(local_err);
goto out;
- opts = qemu_opts_create(list, NULL, 0);
+ }
+ opts = qemu_opts_create(list, NULL, 0, NULL);
continue;
}
if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
diff --git a/qemu-config.h b/qemu-config.h
index 6d7365d35b..e9f2ef4c7b 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -1,11 +1,14 @@
#ifndef QEMU_CONFIG_H
#define QEMU_CONFIG_H
+#include "error.h"
+
extern QemuOptsList qemu_fsdev_opts;
extern QemuOptsList qemu_virtfs_opts;
extern QemuOptsList qemu_spice_opts;
QemuOptsList *qemu_find_opts(const char *group);
+QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
void qemu_add_opts(QemuOptsList *list);
int qemu_set_option(const char *str);
int qemu_global_option(const char *str);
diff --git a/qemu-log.h b/qemu-log.h
index fccfb1100e..a9b3ca4e0b 100644
--- a/qemu-log.h
+++ b/qemu-log.h
@@ -50,6 +50,7 @@ extern int loglevel;
/* Special cases: */
+#ifdef NEED_CPU_H
/* cpu_dump_state() logging functions: */
#define log_cpu_state(env, f) cpu_dump_state((env), logfile, fprintf, (f));
#define log_cpu_state_mask(b, env, f) do { \
@@ -64,6 +65,7 @@ extern int loglevel;
/* page_dump() output to the log file: */
#define log_page_dump() page_dump(logfile)
+#endif
diff --git a/qemu-option.c b/qemu-option.c
index 35cd609f75..bb3886c6b9 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -30,6 +30,7 @@
#include "qemu-error.h"
#include "qemu-objects.h"
#include "qemu-option.h"
+#include "error.h"
#include "qerror.h"
/*
@@ -168,7 +169,8 @@ QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
return NULL;
}
-static int parse_option_bool(const char *name, const char *value, bool *ret)
+static void parse_option_bool(const char *name, const char *value, bool *ret,
+ Error **errp)
{
if (value != NULL) {
if (!strcmp(value, "on")) {
@@ -176,16 +178,15 @@ static int parse_option_bool(const char *name, const char *value, bool *ret)
} else if (!strcmp(value, "off")) {
*ret = 0;
} else {
- qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
- return -1;
+ error_set(errp,QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
}
} else {
*ret = 1;
}
- return 0;
}
-static int parse_option_number(const char *name, const char *value, uint64_t *ret)
+static void parse_option_number(const char *name, const char *value,
+ uint64_t *ret, Error **errp)
{
char *postfix;
uint64_t number;
@@ -193,18 +194,17 @@ static int parse_option_number(const char *name, const char *value, uint64_t *re
if (value != NULL) {
number = strtoull(value, &postfix, 0);
if (*postfix != '\0') {
- qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
- return -1;
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
+ return;
}
*ret = number;
} else {
- qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
- return -1;
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
}
- return 0;
}
-static int parse_option_size(const char *name, const char *value, uint64_t *ret)
+static void parse_option_size(const char *name, const char *value,
+ uint64_t *ret, Error **errp)
{
char *postfix;
double sizef;
@@ -230,16 +230,14 @@ static int parse_option_size(const char *name, const char *value, uint64_t *ret)
*ret = (uint64_t) sizef;
break;
default:
- qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
error_printf_unless_qmp("You may use k, M, G or T suffixes for "
"kilobytes, megabytes, gigabytes and terabytes.\n");
- return -1;
+ return;
}
} else {
- qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
- return -1;
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
}
- return 0;
}
/*
@@ -263,6 +261,7 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
const char *value)
{
bool flag;
+ Error *local_err = NULL;
// Find a matching parameter
list = get_option_parameter(list, name);
@@ -274,9 +273,10 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
// Process parameter
switch (list->type) {
case OPT_FLAG:
- if (parse_option_bool(name, value, &flag) == -1)
- return -1;
- list->value.n = flag;
+ parse_option_bool(name, value, &flag, &local_err);
+ if (!error_is_set(&local_err)) {
+ list->value.n = flag;
+ }
break;
case OPT_STRING:
@@ -289,8 +289,7 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
break;
case OPT_SIZE:
- if (parse_option_size(name, value, &list->value.n) == -1)
- return -1;
+ parse_option_size(name, value, &list->value.n, &local_err);
break;
default:
@@ -298,6 +297,12 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
return -1;
}
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
+ return -1;
+ }
+
return 0;
}
@@ -576,20 +581,24 @@ uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
return opt->value.uint;
}
-static int qemu_opt_parse(QemuOpt *opt)
+static void qemu_opt_parse(QemuOpt *opt, Error **errp)
{
if (opt->desc == NULL)
- return 0;
+ return;
+
switch (opt->desc->type) {
case QEMU_OPT_STRING:
/* nothing */
- return 0;
+ return;
case QEMU_OPT_BOOL:
- return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
+ parse_option_bool(opt->name, opt->str, &opt->value.boolean, errp);
+ break;
case QEMU_OPT_NUMBER:
- return parse_option_number(opt->name, opt->str, &opt->value.uint);
+ parse_option_number(opt->name, opt->str, &opt->value.uint, errp);
+ break;
case QEMU_OPT_SIZE:
- return parse_option_size(opt->name, opt->str, &opt->value.uint);
+ parse_option_size(opt->name, opt->str, &opt->value.uint, errp);
+ break;
default:
abort();
}
@@ -603,11 +612,12 @@ static void qemu_opt_del(QemuOpt *opt)
g_free(opt);
}
-static int opt_set(QemuOpts *opts, const char *name, const char *value,
- bool prepend)
+static void opt_set(QemuOpts *opts, const char *name, const char *value,
+ bool prepend, Error **errp)
{
QemuOpt *opt;
const QemuOptDesc *desc = opts->list->desc;
+ Error *local_err = NULL;
int i;
for (i = 0; desc[i].name != NULL; i++) {
@@ -619,8 +629,8 @@ static int opt_set(QemuOpts *opts, const char *name, const char *value,
if (i == 0) {
/* empty list -> allow any */;
} else {
- qerror_report(QERR_INVALID_PARAMETER, name);
- return -1;
+ error_set(errp, QERR_INVALID_PARAMETER, name);
+ return;
}
}
@@ -638,16 +648,31 @@ static int opt_set(QemuOpts *opts, const char *name, const char *value,
if (value) {
opt->str = g_strdup(value);
}
- if (qemu_opt_parse(opt) < 0) {
+ qemu_opt_parse(opt, &local_err);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
qemu_opt_del(opt);
+ }
+}
+
+int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
+{
+ Error *local_err = NULL;
+
+ opt_set(opts, name, value, false, &local_err);
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
return -1;
}
+
return 0;
}
-int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
+void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
+ Error **errp)
{
- return opt_set(opts, name, value, false);
+ opt_set(opts, name, value, false, errp);
}
int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
@@ -729,20 +754,21 @@ static int id_wellformed(const char *id)
return 1;
}
-QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
+QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
+ int fail_if_exists, Error **errp)
{
QemuOpts *opts = NULL;
if (id) {
if (!id_wellformed(id)) {
- qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
+ error_set(errp,QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
return NULL;
}
opts = qemu_opts_find(list, id);
if (opts != NULL) {
if (fail_if_exists && !list->merge_lists) {
- qerror_report(QERR_DUPLICATE_ID, id, list->name);
+ error_set(errp, QERR_DUPLICATE_ID, id, list->name);
return NULL;
} else {
return opts;
@@ -783,9 +809,12 @@ int qemu_opts_set(QemuOptsList *list, const char *id,
const char *name, const char *value)
{
QemuOpts *opts;
+ Error *local_err = NULL;
- opts = qemu_opts_create(list, id, 1);
- if (opts == NULL) {
+ opts = qemu_opts_create(list, id, 1, &local_err);
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
return -1;
}
return qemu_opt_set(opts, name, value);
@@ -829,6 +858,7 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
{
char option[128], value[1024];
const char *p,*pe,*pc;
+ Error *local_err = NULL;
for (p = params; *p != '\0'; p++) {
pe = strchr(p, '=');
@@ -860,7 +890,10 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
}
if (strcmp(option, "id") != 0) {
/* store and parse */
- if (opt_set(opts, option, value, prepend) == -1) {
+ opt_set(opts, option, value, prepend, &local_err);
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
return -1;
}
}
@@ -883,6 +916,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
char value[1024], *id = NULL;
const char *p;
QemuOpts *opts;
+ Error *local_err = NULL;
assert(!permit_abbrev || list->implied_opt_name);
firstname = permit_abbrev ? list->implied_opt_name : NULL;
@@ -898,13 +932,18 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
if (!id && !QTAILQ_EMPTY(&list->head)) {
opts = qemu_opts_find(list, NULL);
} else {
- opts = qemu_opts_create(list, id, 0);
+ opts = qemu_opts_create(list, id, 0, &local_err);
}
} else {
- opts = qemu_opts_create(list, id, 1);
+ opts = qemu_opts_create(list, id, 1, &local_err);
}
- if (opts == NULL)
+ if (opts == NULL) {
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
+ }
return NULL;
+ }
if (opts_do_parse(opts, params, firstname, defaults) != 0) {
qemu_opts_del(opts);
@@ -929,13 +968,19 @@ void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
assert(opts);
}
+typedef struct OptsFromQDictState {
+ QemuOpts *opts;
+ Error **errp;
+} OptsFromQDictState;
+
static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
{
+ OptsFromQDictState *state = opaque;
char buf[32];
const char *value;
int n;
- if (!strcmp(key, "id")) {
+ if (!strcmp(key, "id") || error_is_set(state->errp)) {
return;
}
@@ -963,7 +1008,8 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
default:
return;
}
- qemu_opt_set(opaque, key, value);
+
+ qemu_opt_set_err(state->opts, key, value, state->errp);
}
/*
@@ -972,15 +1018,31 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
* Only QStrings, QInts, QFloats and QBools are copied. Entries with
* other types are silently ignored.
*/
-QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
+QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
+ Error **errp)
{
+ OptsFromQDictState state;
+ Error *local_err = NULL;
QemuOpts *opts;
- opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1);
- if (opts == NULL)
+ opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
+ &local_err);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
+ return NULL;
+ }
+
+ assert(opts != NULL);
+
+ state.errp = &local_err;
+ state.opts = opts;
+ qdict_iter(qdict, qemu_opts_from_qdict_1, &state);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
+ qemu_opts_del(opts);
return NULL;
+ }
- qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
return opts;
}
@@ -1011,9 +1073,10 @@ QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
/* Validate parsed opts against descriptions where no
* descriptions were provided in the QemuOptsList.
*/
-int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
+void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
{
QemuOpt *opt;
+ Error *local_err = NULL;
assert(opts->list->desc[0].name == NULL);
@@ -1026,18 +1089,18 @@ int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
}
}
if (desc[i].name == NULL) {
- qerror_report(QERR_INVALID_PARAMETER, opt->name);
- return -1;
+ error_set(errp, QERR_INVALID_PARAMETER, opt->name);
+ return;
}
opt->desc = &desc[i];
- if (qemu_opt_parse(opt) < 0) {
- return -1;
+ qemu_opt_parse(opt, &local_err);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
+ return;
}
}
-
- return 0;
}
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
diff --git a/qemu-option.h b/qemu-option.h
index 3ca00c3cec..951dec3cc4 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -28,6 +28,7 @@
#include <stdint.h>
#include "qemu-queue.h"
+#include "error.h"
#include "qdict.h"
enum QEMUOptionParType {
@@ -110,25 +111,29 @@ bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
+void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
+ Error **errp);
int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val);
typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque);
int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
int abort_on_failure);
QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id);
-QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists);
+QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
+ int fail_if_exists, Error **errp);
void qemu_opts_reset(QemuOptsList *list);
void qemu_opts_loc_restore(QemuOpts *opts);
int qemu_opts_set(QemuOptsList *list, const char *id,
const char *name, const char *value);
const char *qemu_opts_id(QemuOpts *opts);
void qemu_opts_del(QemuOpts *opts);
-int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc);
+void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp);
int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname);
QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev);
void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
int permit_abbrev);
-QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict);
+QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
+ Error **errp);
QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict);
typedef int (*qemu_opts_loopfunc)(QemuOpts *opts, void *opaque);
diff --git a/qemu-sockets.c b/qemu-sockets.c
index 46c7619c7e..2ae715db76 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -461,7 +461,7 @@ int inet_listen(const char *str, char *ostr, int olen,
char *optstr;
int sock = -1;
- opts = qemu_opts_create(&dummy_opts, NULL, 0);
+ opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
if (inet_parse(opts, str) == 0) {
sock = inet_listen_opts(opts, port_offset, errp);
if (sock != -1 && ostr) {
@@ -490,7 +490,7 @@ int inet_connect(const char *str, bool block, Error **errp)
QemuOpts *opts;
int sock = -1;
- opts = qemu_opts_create(&dummy_opts, NULL, 0);
+ opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
if (inet_parse(opts, str) == 0) {
if (block) {
qemu_opt_set(opts, "block", "on");
@@ -589,7 +589,7 @@ int unix_listen(const char *str, char *ostr, int olen)
char *path, *optstr;
int sock, len;
- opts = qemu_opts_create(&dummy_opts, NULL, 0);
+ opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
optstr = strchr(str, ',');
if (optstr) {
@@ -617,7 +617,7 @@ int unix_connect(const char *path)
QemuOpts *opts;
int sock;
- opts = qemu_opts_create(&dummy_opts, NULL, 0);
+ opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
qemu_opt_set(opts, "path", path);
sock = unix_connect_opts(opts);
qemu_opts_del(opts);
diff --git a/qerror.c b/qerror.c
index 5092fe7549..92c4eff179 100644
--- a/qerror.c
+++ b/qerror.c
@@ -156,6 +156,10 @@ static const QErrorStringTable qerror_table[] = {
.desc = "Invalid block format '%(name)'",
},
{
+ .error_fmt = QERR_INVALID_OPTION_GROUP,
+ .desc = "There is no option group '%(group)'",
+ },
+ {
.error_fmt = QERR_INVALID_PARAMETER,
.desc = "Invalid parameter '%(name)'",
},
diff --git a/qerror.h b/qerror.h
index 4cbba48c5a..b4c8758f40 100644
--- a/qerror.h
+++ b/qerror.h
@@ -139,6 +139,9 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_INVALID_BLOCK_FORMAT \
"{ 'class': 'InvalidBlockFormat', 'data': { 'name': %s } }"
+#define QERR_INVALID_OPTION_GROUP \
+ "{ 'class': 'InvalidOptionGroup', 'data': { 'group': %s } }"
+
#define QERR_INVALID_PARAMETER \
"{ 'class': 'InvalidParameter', 'data': { 'name': %s } }"
diff --git a/qga/Makefile.objs b/qga/Makefile.objs
new file mode 100644
index 0000000000..6a4d843436
--- /dev/null
+++ b/qga/Makefile.objs
@@ -0,0 +1,3 @@
+qga-obj-y = commands.o guest-agent-command-state.o
+qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o
+qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o
diff --git a/qmp-commands.hx b/qmp-commands.hx
index db980fa811..2e1a38e695 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -604,12 +604,45 @@ Example:
EQMP
{
+ .name = "dump-guest-memory",
+ .args_type = "paging:b,protocol:s,begin:i?,end:i?",
+ .params = "-p protocol [begin] [length]",
+ .help = "dump guest memory to file",
+ .user_print = monitor_user_noop,
+ .mhandler.cmd_new = qmp_marshal_input_dump_guest_memory,
+ },
+
+SQMP
+dump
+
+
+Dump guest memory to file. The file can be processed with crash or gdb.
+
+Arguments:
+
+- "paging": do paging to get guest's memory mapping (json-bool)
+- "protocol": destination file(started with "file:") or destination file
+ descriptor (started with "fd:") (json-string)
+- "begin": the starting physical address. It's optional, and should be specified
+ with length together (json-int)
+- "length": the memory size, in bytes. It's optional, and should be specified
+ with begin together (json-int)
+
+Example:
+
+-> { "execute": "dump-guest-memory", "arguments": { "protocol": "fd:dump" } }
+<- { "return": {} }
+
+Notes:
+
+(1) All boolean arguments default to false
+
+EQMP
+
+ {
.name = "netdev_add",
.args_type = "netdev:O",
- .params = "[user|tap|socket],id=str[,prop=value][,...]",
- .help = "add host network device",
- .user_print = monitor_user_noop,
- .mhandler.cmd_new = do_netdev_add,
+ .mhandler.cmd_new = qmp_netdev_add,
},
SQMP
@@ -638,10 +671,7 @@ EQMP
{
.name = "netdev_del",
.args_type = "id:s",
- .params = "id",
- .help = "remove host network device",
- .user_print = monitor_user_noop,
- .mhandler.cmd_new = do_netdev_del,
+ .mhandler.cmd_new = qmp_marshal_input_netdev_del,
},
SQMP
@@ -1179,6 +1209,43 @@ EQMP
},
SQMP
+query-events
+--------------
+
+List QMP available events.
+
+Each event is represented by a json-object, the returned value is a json-array
+of all events.
+
+Each json-object contains:
+
+- "name": event's name (json-string)
+
+Example:
+
+-> { "execute": "query-events" }
+<- {
+ "return":[
+ {
+ "name":"SHUTDOWN"
+ },
+ {
+ "name":"RESET"
+ }
+ ]
+ }
+
+Note: This example has been shortened as the real response is too long.
+
+EQMP
+
+ {
+ .name = "query-events",
+ .args_type = "",
+ .mhandler.cmd_new = qmp_marshal_input_query_events,
+ },
+
+SQMP
query-chardev
-------------
diff --git a/qom/Makefile b/qom/Makefile
deleted file mode 100644
index 34c6de558a..0000000000
--- a/qom/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-qom-y = object.o container.o qom-qobject.o
-qom-twice-y = cpu.o
diff --git a/qom/Makefile.objs b/qom/Makefile.objs
new file mode 100644
index 0000000000..5ef060a401
--- /dev/null
+++ b/qom/Makefile.objs
@@ -0,0 +1,4 @@
+qom-obj-y = object.o container.o qom-qobject.o
+qom-obj-twice-y = cpu.o
+common-obj-y = $(qom-obj-twice-y)
+user-obj-y = $(qom-obj-twice-y)
diff --git a/readline.c b/readline.c
index a6c0039ad2..540cd8a025 100644
--- a/readline.c
+++ b/readline.c
@@ -337,6 +337,9 @@ static void readline_completion(ReadLineState *rs)
}
readline_show_prompt(rs);
}
+ for (i = 0; i < rs->nb_completions; i++) {
+ g_free(rs->completions[i]);
+ }
}
/* return true if command handled */
diff --git a/rules.mak b/rules.mak
index efef6f242d..4bc5e52fa3 100644
--- a/rules.mak
+++ b/rules.mak
@@ -73,3 +73,43 @@ TRACETOOL=$(PYTHON) $(SRC_PATH)/scripts/tracetool.py
# will delete the target of a rule if commands exit with a nonzero exit status
.DELETE_ON_ERROR:
+
+# magic to descend into other directories
+
+obj := .
+old-nested-dirs :=
+
+define push-var
+$(eval save-$2-$1 = $(value $1))
+$(eval $1 :=)
+endef
+
+define pop-var
+$(eval subdir-$2-$1 := $(if $(filter $2,$(save-$2-$1)),$(addprefix $2,$($1))))
+$(eval $1 = $(value save-$2-$1) $$(subdir-$2-$1))
+$(eval save-$2-$1 :=)
+endef
+
+define unnest-dir
+$(foreach var,$(nested-vars),$(call push-var,$(var),$1/))
+$(eval obj := $(obj)/$1)
+$(eval include $(SRC_PATH)/$1/Makefile.objs)
+$(eval obj := $(patsubst %/$1,%,$(obj)))
+$(foreach var,$(nested-vars),$(call pop-var,$(var),$1/))
+endef
+
+define unnest-vars-1
+$(eval nested-dirs := $(filter-out \
+ $(old-nested-dirs), \
+ $(sort $(foreach var,$(nested-vars), $(filter %/, $($(var)))))))
+$(if $(nested-dirs),
+ $(foreach dir,$(nested-dirs),$(call unnest-dir,$(patsubst %/,%,$(dir))))
+ $(eval old-nested-dirs := $(old-nested-dirs) $(nested-dirs))
+ $(call unnest-vars-1))
+endef
+
+define unnest-vars
+$(call unnest-vars-1)
+$(foreach var,$(nested-vars),$(eval $(var) := $(filter-out %/, $($(var)))))
+$(shell mkdir -p $(sort $(foreach var,$(nested-vars),$(dir $($(var))))))
+endef
diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs
new file mode 100644
index 0000000000..bb43d3c08c
--- /dev/null
+++ b/slirp/Makefile.objs
@@ -0,0 +1,3 @@
+common-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o
+common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
+common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o
diff --git a/target-alpha/Makefile.objs b/target-alpha/Makefile.objs
new file mode 100644
index 0000000000..590304cc61
--- /dev/null
+++ b/target-alpha/Makefile.objs
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-y += translate.o helper.o cpu.o
+obj-y += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
new file mode 100644
index 0000000000..f447c4fdf2
--- /dev/null
+++ b/target-arm/Makefile.objs
@@ -0,0 +1,6 @@
+obj-y += arm-semi.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += neon_helper.o iwmmxt_helper.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/arm-semi.c b/target-arm/arm-semi.c
index 88ca9bb1b7..88ca9bb1b7 100644
--- a/arm-semi.c
+++ b/target-arm/arm-semi.c
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 7e1c2c06bd..bbb1d05d10 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4,11 +4,6 @@
#include "host-utils.h"
#include "sysemu.h"
-void cpu_state_reset(CPUARMState *env)
-{
- cpu_reset(ENV_GET_CPU(env));
-}
-
static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
{
int nregs;
@@ -80,7 +75,7 @@ ARMCPU *cpu_arm_init(const char *cpu_model)
arm_translate_init();
}
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
if (arm_feature(env, ARM_FEATURE_NEON)) {
gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
51, "arm-neon.xml", 0);
diff --git a/target-cris/Makefile.objs b/target-cris/Makefile.objs
new file mode 100644
index 0000000000..4b09e8c6b5
--- /dev/null
+++ b/target-cris/Makefile.objs
@@ -0,0 +1,4 @@
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += mmu.o machine.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 5449cc48b6..4f4df6d9b5 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -64,17 +64,19 @@
#define PR_NRP 12
#define PR_CCS 13
#define PR_USP 14
+#define PRV10_BRP 14
#define PR_SPC 15
/* CPU flags. */
#define Q_FLAG 0x80000000
-#define M_FLAG 0x40000000
+#define M_FLAG_V32 0x40000000
#define PFIX_FLAG 0x800 /* CRISv10 Only. */
#define F_FLAG_V10 0x400
#define P_FLAG_V10 0x200
#define S_FLAG 0x200
#define R_FLAG 0x100
#define P_FLAG 0x80
+#define M_FLAG_V10 0x80
#define U_FLAG 0x40
#define I_FLAG 0x20
#define X_FLAG 0x10
@@ -171,7 +173,7 @@ typedef struct CPUCRISState {
#include "cpu-qom.h"
-CPUCRISState *cpu_cris_init(const char *cpu_model);
+CRISCPU *cpu_cris_init(const char *cpu_model);
int cpu_cris_exec(CPUCRISState *s);
void cpu_cris_close(CPUCRISState *s);
void do_interrupt(CPUCRISState *env);
@@ -216,7 +218,15 @@ enum {
#define TARGET_PHYS_ADDR_SPACE_BITS 32
#define TARGET_VIRT_ADDR_SPACE_BITS 32
-#define cpu_init cpu_cris_init
+static inline CPUCRISState *cpu_init(const char *cpu_model)
+{
+ CRISCPU *cpu = cpu_cris_init(cpu_model);
+ if (cpu == NULL) {
+ return NULL;
+ }
+ return &cpu->env;
+}
+
#define cpu_exec cpu_cris_exec
#define cpu_gen_code cpu_cris_gen_code
#define cpu_signal_handler cpu_cris_signal_handler
diff --git a/target-cris/helper.c b/target-cris/helper.c
index 8680f436a0..bfbc29ec6a 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -121,14 +121,14 @@ static void do_interruptv10(CPUCRISState *env)
/* These exceptions are genereated by the core itself.
ERP should point to the insn following the brk. */
ex_vec = env->trap_vector;
- env->pregs[PR_ERP] = env->pc;
+ env->pregs[PRV10_BRP] = env->pc;
break;
case EXCP_NMI:
/* NMI is hardwired to vector zero. */
ex_vec = 0;
- env->pregs[PR_CCS] &= ~M_FLAG;
- env->pregs[PR_NRP] = env->pc;
+ env->pregs[PR_CCS] &= ~M_FLAG_V10;
+ env->pregs[PRV10_BRP] = env->pc;
break;
case EXCP_BUSFAULT:
@@ -185,7 +185,7 @@ void do_interrupt(CPUCRISState *env)
case EXCP_NMI:
/* NMI is hardwired to vector zero. */
ex_vec = 0;
- env->pregs[PR_CCS] &= ~M_FLAG;
+ env->pregs[PR_CCS] &= ~M_FLAG_V32;
env->pregs[PR_NRP] = env->pc;
break;
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
index b92c106e10..ac7c98c8ed 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -247,8 +247,8 @@ void helper_rfn(void)
if (!rflag)
env->pregs[PR_CCS] |= P_FLAG;
- /* Always set the M flag. */
- env->pregs[PR_CCS] |= M_FLAG;
+ /* Always set the M flag. */
+ env->pregs[PR_CCS] |= M_FLAG_V32;
}
uint32_t helper_lz(uint32_t t0)
diff --git a/target-cris/translate.c b/target-cris/translate.c
index e353ea3fa8..1ad9ec788e 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3503,81 +3503,77 @@ static uint32_t vr_by_name(const char *name)
return 32;
}
-CPUCRISState *cpu_cris_init (const char *cpu_model)
+CRISCPU *cpu_cris_init(const char *cpu_model)
{
CRISCPU *cpu;
- CPUCRISState *env;
- static int tcg_initialized = 0;
- int i;
+ CPUCRISState *env;
+ static int tcg_initialized = 0;
+ int i;
cpu = CRIS_CPU(object_new(TYPE_CRIS_CPU));
env = &cpu->env;
- env->pregs[PR_VR] = vr_by_name(cpu_model);
+ env->pregs[PR_VR] = vr_by_name(cpu_model);
cpu_reset(CPU(cpu));
- qemu_init_vcpu(env);
+ qemu_init_vcpu(env);
- if (tcg_initialized)
- return env;
+ if (tcg_initialized) {
+ return cpu;
+ }
- tcg_initialized = 1;
+ tcg_initialized = 1;
#define GEN_HELPER 2
#include "helper.h"
- if (env->pregs[PR_VR] < 32) {
- cpu_crisv10_init(env);
- return env;
- }
-
+ if (env->pregs[PR_VR] < 32) {
+ cpu_crisv10_init(env);
+ return cpu;
+ }
- cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
- cc_x = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUCRISState, cc_x), "cc_x");
- cc_src = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUCRISState, cc_src), "cc_src");
- cc_dest = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUCRISState, cc_dest),
- "cc_dest");
- cc_result = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUCRISState, cc_result),
- "cc_result");
- cc_op = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUCRISState, cc_op), "cc_op");
- cc_size = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUCRISState, cc_size),
- "cc_size");
- cc_mask = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUCRISState, cc_mask),
- "cc_mask");
-
- env_pc = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUCRISState, pc),
- "pc");
- env_btarget = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUCRISState, btarget),
- "btarget");
- env_btaken = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUCRISState, btaken),
- "btaken");
- for (i = 0; i < 16; i++) {
- cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUCRISState, regs[i]),
- regnames[i]);
- }
- for (i = 0; i < 16; i++) {
- cpu_PR[i] = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUCRISState, pregs[i]),
- pregnames[i]);
- }
- return env;
-}
+ cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+ cc_x = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUCRISState, cc_x), "cc_x");
+ cc_src = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUCRISState, cc_src), "cc_src");
+ cc_dest = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUCRISState, cc_dest),
+ "cc_dest");
+ cc_result = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUCRISState, cc_result),
+ "cc_result");
+ cc_op = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUCRISState, cc_op), "cc_op");
+ cc_size = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUCRISState, cc_size),
+ "cc_size");
+ cc_mask = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUCRISState, cc_mask),
+ "cc_mask");
+
+ env_pc = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUCRISState, pc),
+ "pc");
+ env_btarget = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUCRISState, btarget),
+ "btarget");
+ env_btaken = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUCRISState, btaken),
+ "btaken");
+ for (i = 0; i < 16; i++) {
+ cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUCRISState, regs[i]),
+ regnames[i]);
+ }
+ for (i = 0; i < 16; i++) {
+ cpu_PR[i] = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUCRISState, pregs[i]),
+ pregnames[i]);
+ }
-void cpu_state_reset(CPUCRISState *env)
-{
- cpu_reset(ENV_GET_CPU(env));
+ return cpu;
}
void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb, int pc_pos)
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index 4ada3ed09f..3629629d9d 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -1132,6 +1132,7 @@ static unsigned int dec10_ind(DisasContext *dc)
LOG_DIS("break %d\n", dc->src);
cris_evaluate_flags(dc);
tcg_gen_movi_tl(env_pc, dc->pc + 2);
+ t_gen_mov_env_TN(trap_vector, tcg_const_tl(dc->src + 2));
t_gen_raise_exception(EXCP_BREAK);
dc->is_jmp = DISAS_UPDATE;
return insn_len;
diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs
new file mode 100644
index 0000000000..f91375578c
--- /dev/null
+++ b/target-i386/Makefile.objs
@@ -0,0 +1,7 @@
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o
+obj-$(CONFIG_KVM) += kvm.o hyperv.o
+obj-$(CONFIG_LINUX_USER) += ioport-user.o
+obj-$(CONFIG_BSD_USER) += ioport-user.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
new file mode 100644
index 0000000000..4240278edd
--- /dev/null
+++ b/target-i386/arch_dump.c
@@ -0,0 +1,449 @@
+/*
+ * i386 memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ * Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "cpu.h"
+#include "cpu-all.h"
+#include "dump.h"
+#include "elf.h"
+
+#ifdef TARGET_X86_64
+typedef struct {
+ target_ulong r15, r14, r13, r12, rbp, rbx, r11, r10;
+ target_ulong r9, r8, rax, rcx, rdx, rsi, rdi, orig_rax;
+ target_ulong rip, cs, eflags;
+ target_ulong rsp, ss;
+ target_ulong fs_base, gs_base;
+ target_ulong ds, es, fs, gs;
+} x86_64_user_regs_struct;
+
+typedef struct {
+ char pad1[32];
+ uint32_t pid;
+ char pad2[76];
+ x86_64_user_regs_struct regs;
+ char pad3[8];
+} x86_64_elf_prstatus;
+
+static int x86_64_write_elf64_note(write_core_dump_function f,
+ CPUArchState *env, int id,
+ void *opaque)
+{
+ x86_64_user_regs_struct regs;
+ Elf64_Nhdr *note;
+ char *buf;
+ int descsz, note_size, name_size = 5;
+ const char *name = "CORE";
+ int ret;
+
+ regs.r15 = env->regs[15];
+ regs.r14 = env->regs[14];
+ regs.r13 = env->regs[13];
+ regs.r12 = env->regs[12];
+ regs.r11 = env->regs[11];
+ regs.r10 = env->regs[10];
+ regs.r9 = env->regs[9];
+ regs.r8 = env->regs[8];
+ regs.rbp = env->regs[R_EBP];
+ regs.rsp = env->regs[R_ESP];
+ regs.rdi = env->regs[R_EDI];
+ regs.rsi = env->regs[R_ESI];
+ regs.rdx = env->regs[R_EDX];
+ regs.rcx = env->regs[R_ECX];
+ regs.rbx = env->regs[R_EBX];
+ regs.rax = env->regs[R_EAX];
+ regs.rip = env->eip;
+ regs.eflags = env->eflags;
+
+ regs.orig_rax = 0; /* FIXME */
+ regs.cs = env->segs[R_CS].selector;
+ regs.ss = env->segs[R_SS].selector;
+ regs.fs_base = env->segs[R_FS].base;
+ regs.gs_base = env->segs[R_GS].base;
+ regs.ds = env->segs[R_DS].selector;
+ regs.es = env->segs[R_ES].selector;
+ regs.fs = env->segs[R_FS].selector;
+ regs.gs = env->segs[R_GS].selector;
+
+ descsz = sizeof(x86_64_elf_prstatus);
+ note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
+ (descsz + 3) / 4) * 4;
+ note = g_malloc(note_size);
+
+ memset(note, 0, note_size);
+ note->n_namesz = cpu_to_le32(name_size);
+ note->n_descsz = cpu_to_le32(descsz);
+ note->n_type = cpu_to_le32(NT_PRSTATUS);
+ buf = (char *)note;
+ buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
+ memcpy(buf, name, name_size);
+ buf += ((name_size + 3) / 4) * 4;
+ memcpy(buf + 32, &id, 4); /* pr_pid */
+ buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong);
+ memcpy(buf, &regs, sizeof(x86_64_user_regs_struct));
+
+ ret = f(note, note_size, opaque);
+ g_free(note);
+ if (ret < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+typedef struct {
+ uint32_t ebx, ecx, edx, esi, edi, ebp, eax;
+ unsigned short ds, __ds, es, __es;
+ unsigned short fs, __fs, gs, __gs;
+ uint32_t orig_eax, eip;
+ unsigned short cs, __cs;
+ uint32_t eflags, esp;
+ unsigned short ss, __ss;
+} x86_user_regs_struct;
+
+typedef struct {
+ char pad1[24];
+ uint32_t pid;
+ char pad2[44];
+ x86_user_regs_struct regs;
+ char pad3[4];
+} x86_elf_prstatus;
+
+static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUArchState *env,
+ int id)
+{
+ memset(prstatus, 0, sizeof(x86_elf_prstatus));
+ prstatus->regs.ebp = env->regs[R_EBP] & 0xffffffff;
+ prstatus->regs.esp = env->regs[R_ESP] & 0xffffffff;
+ prstatus->regs.edi = env->regs[R_EDI] & 0xffffffff;
+ prstatus->regs.esi = env->regs[R_ESI] & 0xffffffff;
+ prstatus->regs.edx = env->regs[R_EDX] & 0xffffffff;
+ prstatus->regs.ecx = env->regs[R_ECX] & 0xffffffff;
+ prstatus->regs.ebx = env->regs[R_EBX] & 0xffffffff;
+ prstatus->regs.eax = env->regs[R_EAX] & 0xffffffff;
+ prstatus->regs.eip = env->eip & 0xffffffff;
+ prstatus->regs.eflags = env->eflags & 0xffffffff;
+
+ prstatus->regs.cs = env->segs[R_CS].selector;
+ prstatus->regs.ss = env->segs[R_SS].selector;
+ prstatus->regs.ds = env->segs[R_DS].selector;
+ prstatus->regs.es = env->segs[R_ES].selector;
+ prstatus->regs.fs = env->segs[R_FS].selector;
+ prstatus->regs.gs = env->segs[R_GS].selector;
+
+ prstatus->pid = id;
+}
+
+static int x86_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+ int id, void *opaque)
+{
+ x86_elf_prstatus prstatus;
+ Elf64_Nhdr *note;
+ char *buf;
+ int descsz, note_size, name_size = 5;
+ const char *name = "CORE";
+ int ret;
+
+ x86_fill_elf_prstatus(&prstatus, env, id);
+ descsz = sizeof(x86_elf_prstatus);
+ note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
+ (descsz + 3) / 4) * 4;
+ note = g_malloc(note_size);
+
+ memset(note, 0, note_size);
+ note->n_namesz = cpu_to_le32(name_size);
+ note->n_descsz = cpu_to_le32(descsz);
+ note->n_type = cpu_to_le32(NT_PRSTATUS);
+ buf = (char *)note;
+ buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
+ memcpy(buf, name, name_size);
+ buf += ((name_size + 3) / 4) * 4;
+ memcpy(buf, &prstatus, sizeof(prstatus));
+
+ ret = f(note, note_size, opaque);
+ g_free(note);
+ if (ret < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+ int cpuid, void *opaque)
+{
+ int ret;
+#ifdef TARGET_X86_64
+ bool lma = !!(first_cpu->hflags & HF_LMA_MASK);
+
+ if (lma) {
+ ret = x86_64_write_elf64_note(f, env, cpuid, opaque);
+ } else {
+#endif
+ ret = x86_write_elf64_note(f, env, cpuid, opaque);
+#ifdef TARGET_X86_64
+ }
+#endif
+
+ return ret;
+}
+
+int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
+ int cpuid, void *opaque)
+{
+ x86_elf_prstatus prstatus;
+ Elf32_Nhdr *note;
+ char *buf;
+ int descsz, note_size, name_size = 5;
+ const char *name = "CORE";
+ int ret;
+
+ x86_fill_elf_prstatus(&prstatus, env, cpuid);
+ descsz = sizeof(x86_elf_prstatus);
+ note_size = ((sizeof(Elf32_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
+ (descsz + 3) / 4) * 4;
+ note = g_malloc(note_size);
+
+ memset(note, 0, note_size);
+ note->n_namesz = cpu_to_le32(name_size);
+ note->n_descsz = cpu_to_le32(descsz);
+ note->n_type = cpu_to_le32(NT_PRSTATUS);
+ buf = (char *)note;
+ buf += ((sizeof(Elf32_Nhdr) + 3) / 4) * 4;
+ memcpy(buf, name, name_size);
+ buf += ((name_size + 3) / 4) * 4;
+ memcpy(buf, &prstatus, sizeof(prstatus));
+
+ ret = f(note, note_size, opaque);
+ g_free(note);
+ if (ret < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * please count up QEMUCPUSTATE_VERSION if you have changed definition of
+ * QEMUCPUState, and modify the tools using this information accordingly.
+ */
+#define QEMUCPUSTATE_VERSION (1)
+
+struct QEMUCPUSegment {
+ uint32_t selector;
+ uint32_t limit;
+ uint32_t flags;
+ uint32_t pad;
+ uint64_t base;
+};
+
+typedef struct QEMUCPUSegment QEMUCPUSegment;
+
+struct QEMUCPUState {
+ uint32_t version;
+ uint32_t size;
+ uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp;
+ uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
+ uint64_t rip, rflags;
+ QEMUCPUSegment cs, ds, es, fs, gs, ss;
+ QEMUCPUSegment ldt, tr, gdt, idt;
+ uint64_t cr[5];
+};
+
+typedef struct QEMUCPUState QEMUCPUState;
+
+static void copy_segment(QEMUCPUSegment *d, SegmentCache *s)
+{
+ d->pad = 0;
+ d->selector = s->selector;
+ d->limit = s->limit;
+ d->flags = s->flags;
+ d->base = s->base;
+}
+
+static void qemu_get_cpustate(QEMUCPUState *s, CPUArchState *env)
+{
+ memset(s, 0, sizeof(QEMUCPUState));
+
+ s->version = QEMUCPUSTATE_VERSION;
+ s->size = sizeof(QEMUCPUState);
+
+ s->rax = env->regs[R_EAX];
+ s->rbx = env->regs[R_EBX];
+ s->rcx = env->regs[R_ECX];
+ s->rdx = env->regs[R_EDX];
+ s->rsi = env->regs[R_ESI];
+ s->rdi = env->regs[R_EDI];
+ s->rsp = env->regs[R_ESP];
+ s->rbp = env->regs[R_EBP];
+#ifdef TARGET_X86_64
+ s->r8 = env->regs[8];
+ s->r9 = env->regs[9];
+ s->r10 = env->regs[10];
+ s->r11 = env->regs[11];
+ s->r12 = env->regs[12];
+ s->r13 = env->regs[13];
+ s->r14 = env->regs[14];
+ s->r15 = env->regs[15];
+#endif
+ s->rip = env->eip;
+ s->rflags = env->eflags;
+
+ copy_segment(&s->cs, &env->segs[R_CS]);
+ copy_segment(&s->ds, &env->segs[R_DS]);
+ copy_segment(&s->es, &env->segs[R_ES]);
+ copy_segment(&s->fs, &env->segs[R_FS]);
+ copy_segment(&s->gs, &env->segs[R_GS]);
+ copy_segment(&s->ss, &env->segs[R_SS]);
+ copy_segment(&s->ldt, &env->ldt);
+ copy_segment(&s->tr, &env->tr);
+ copy_segment(&s->gdt, &env->gdt);
+ copy_segment(&s->idt, &env->idt);
+
+ s->cr[0] = env->cr[0];
+ s->cr[1] = env->cr[1];
+ s->cr[2] = env->cr[2];
+ s->cr[3] = env->cr[3];
+ s->cr[4] = env->cr[4];
+}
+
+static inline int cpu_write_qemu_note(write_core_dump_function f,
+ CPUArchState *env,
+ void *opaque,
+ int type)
+{
+ QEMUCPUState state;
+ Elf64_Nhdr *note64;
+ Elf32_Nhdr *note32;
+ void *note;
+ char *buf;
+ int descsz, note_size, name_size = 5, note_head_size;
+ const char *name = "QEMU";
+ int ret;
+
+ qemu_get_cpustate(&state, env);
+
+ descsz = sizeof(state);
+ if (type == 0) {
+ note_head_size = sizeof(Elf32_Nhdr);
+ } else {
+ note_head_size = sizeof(Elf64_Nhdr);
+ }
+ note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
+ (descsz + 3) / 4) * 4;
+ note = g_malloc(note_size);
+
+ memset(note, 0, note_size);
+ if (type == 0) {
+ note32 = note;
+ note32->n_namesz = cpu_to_le32(name_size);
+ note32->n_descsz = cpu_to_le32(descsz);
+ note32->n_type = 0;
+ } else {
+ note64 = note;
+ note64->n_namesz = cpu_to_le32(name_size);
+ note64->n_descsz = cpu_to_le32(descsz);
+ note64->n_type = 0;
+ }
+ buf = note;
+ buf += ((note_head_size + 3) / 4) * 4;
+ memcpy(buf, name, name_size);
+ buf += ((name_size + 3) / 4) * 4;
+ memcpy(buf, &state, sizeof(state));
+
+ ret = f(note, note_size, opaque);
+ g_free(note);
+ if (ret < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
+ void *opaque)
+{
+ return cpu_write_qemu_note(f, env, opaque, 1);
+}
+
+int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
+ void *opaque)
+{
+ return cpu_write_qemu_note(f, env, opaque, 0);
+}
+
+int cpu_get_dump_info(ArchDumpInfo *info)
+{
+ bool lma = false;
+ RAMBlock *block;
+
+#ifdef TARGET_X86_64
+ lma = !!(first_cpu->hflags & HF_LMA_MASK);
+#endif
+
+ if (lma) {
+ info->d_machine = EM_X86_64;
+ } else {
+ info->d_machine = EM_386;
+ }
+ info->d_endian = ELFDATA2LSB;
+
+ if (lma) {
+ info->d_class = ELFCLASS64;
+ } else {
+ info->d_class = ELFCLASS32;
+
+ QLIST_FOREACH(block, &ram_list.blocks, next) {
+ if (block->offset + block->length > UINT_MAX) {
+ /* The memory size is greater than 4G */
+ info->d_class = ELFCLASS64;
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+ int name_size = 5; /* "CORE" or "QEMU" */
+ size_t elf_note_size = 0;
+ size_t qemu_note_size = 0;
+ int elf_desc_size = 0;
+ int qemu_desc_size = 0;
+ int note_head_size;
+
+ if (class == ELFCLASS32) {
+ note_head_size = sizeof(Elf32_Nhdr);
+ } else {
+ note_head_size = sizeof(Elf64_Nhdr);
+ }
+
+ if (machine == EM_386) {
+ elf_desc_size = sizeof(x86_elf_prstatus);
+ }
+#ifdef TARGET_X86_64
+ else {
+ elf_desc_size = sizeof(x86_64_elf_prstatus);
+ }
+#endif
+ qemu_desc_size = sizeof(QEMUCPUState);
+
+ elf_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
+ (elf_desc_size + 3) / 4) * 4;
+ qemu_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
+ (qemu_desc_size + 3) / 4) * 4;
+
+ return (elf_note_size + qemu_note_size) * nr_cpus;
+}
diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c
new file mode 100644
index 0000000000..8e5a56a3a8
--- /dev/null
+++ b/target-i386/arch_memory_mapping.c
@@ -0,0 +1,272 @@
+/*
+ * i386 memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ * Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "cpu.h"
+#include "cpu-all.h"
+#include "memory_mapping.h"
+
+/* PAE Paging or IA-32e Paging */
+static void walk_pte(MemoryMappingList *list, target_phys_addr_t pte_start_addr,
+ int32_t a20_mask, target_ulong start_line_addr)
+{
+ target_phys_addr_t pte_addr, start_paddr;
+ uint64_t pte;
+ target_ulong start_vaddr;
+ int i;
+
+ for (i = 0; i < 512; i++) {
+ pte_addr = (pte_start_addr + i * 8) & a20_mask;
+ pte = ldq_phys(pte_addr);
+ if (!(pte & PG_PRESENT_MASK)) {
+ /* not present */
+ continue;
+ }
+
+ start_paddr = (pte & ~0xfff) & ~(0x1ULL << 63);
+ if (cpu_physical_memory_is_io(start_paddr)) {
+ /* I/O region */
+ continue;
+ }
+
+ start_vaddr = start_line_addr | ((i & 0x1fff) << 12);
+ memory_mapping_list_add_merge_sorted(list, start_paddr,
+ start_vaddr, 1 << 12);
+ }
+}
+
+/* 32-bit Paging */
+static void walk_pte2(MemoryMappingList *list,
+ target_phys_addr_t pte_start_addr, int32_t a20_mask,
+ target_ulong start_line_addr)
+{
+ target_phys_addr_t pte_addr, start_paddr;
+ uint32_t pte;
+ target_ulong start_vaddr;
+ int i;
+
+ for (i = 0; i < 1024; i++) {
+ pte_addr = (pte_start_addr + i * 4) & a20_mask;
+ pte = ldl_phys(pte_addr);
+ if (!(pte & PG_PRESENT_MASK)) {
+ /* not present */
+ continue;
+ }
+
+ start_paddr = pte & ~0xfff;
+ if (cpu_physical_memory_is_io(start_paddr)) {
+ /* I/O region */
+ continue;
+ }
+
+ start_vaddr = start_line_addr | ((i & 0x3ff) << 12);
+ memory_mapping_list_add_merge_sorted(list, start_paddr,
+ start_vaddr, 1 << 12);
+ }
+}
+
+/* PAE Paging or IA-32e Paging */
+static void walk_pde(MemoryMappingList *list, target_phys_addr_t pde_start_addr,
+ int32_t a20_mask, target_ulong start_line_addr)
+{
+ target_phys_addr_t pde_addr, pte_start_addr, start_paddr;
+ uint64_t pde;
+ target_ulong line_addr, start_vaddr;
+ int i;
+
+ for (i = 0; i < 512; i++) {
+ pde_addr = (pde_start_addr + i * 8) & a20_mask;
+ pde = ldq_phys(pde_addr);
+ if (!(pde & PG_PRESENT_MASK)) {
+ /* not present */
+ continue;
+ }
+
+ line_addr = start_line_addr | ((i & 0x1ff) << 21);
+ if (pde & PG_PSE_MASK) {
+ /* 2 MB page */
+ start_paddr = (pde & ~0x1fffff) & ~(0x1ULL << 63);
+ if (cpu_physical_memory_is_io(start_paddr)) {
+ /* I/O region */
+ continue;
+ }
+ start_vaddr = line_addr;
+ memory_mapping_list_add_merge_sorted(list, start_paddr,
+ start_vaddr, 1 << 21);
+ continue;
+ }
+
+ pte_start_addr = (pde & ~0xfff) & a20_mask;
+ walk_pte(list, pte_start_addr, a20_mask, line_addr);
+ }
+}
+
+/* 32-bit Paging */
+static void walk_pde2(MemoryMappingList *list,
+ target_phys_addr_t pde_start_addr, int32_t a20_mask,
+ bool pse)
+{
+ target_phys_addr_t pde_addr, pte_start_addr, start_paddr;
+ uint32_t pde;
+ target_ulong line_addr, start_vaddr;
+ int i;
+
+ for (i = 0; i < 1024; i++) {
+ pde_addr = (pde_start_addr + i * 4) & a20_mask;
+ pde = ldl_phys(pde_addr);
+ if (!(pde & PG_PRESENT_MASK)) {
+ /* not present */
+ continue;
+ }
+
+ line_addr = (((unsigned int)i & 0x3ff) << 22);
+ if ((pde & PG_PSE_MASK) && pse) {
+ /* 4 MB page */
+ start_paddr = (pde & ~0x3fffff) | ((pde & 0x1fe000) << 19);
+ if (cpu_physical_memory_is_io(start_paddr)) {
+ /* I/O region */
+ continue;
+ }
+ start_vaddr = line_addr;
+ memory_mapping_list_add_merge_sorted(list, start_paddr,
+ start_vaddr, 1 << 22);
+ continue;
+ }
+
+ pte_start_addr = (pde & ~0xfff) & a20_mask;
+ walk_pte2(list, pte_start_addr, a20_mask, line_addr);
+ }
+}
+
+/* PAE Paging */
+static void walk_pdpe2(MemoryMappingList *list,
+ target_phys_addr_t pdpe_start_addr, int32_t a20_mask)
+{
+ target_phys_addr_t pdpe_addr, pde_start_addr;
+ uint64_t pdpe;
+ target_ulong line_addr;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
+ pdpe = ldq_phys(pdpe_addr);
+ if (!(pdpe & PG_PRESENT_MASK)) {
+ /* not present */
+ continue;
+ }
+
+ line_addr = (((unsigned int)i & 0x3) << 30);
+ pde_start_addr = (pdpe & ~0xfff) & a20_mask;
+ walk_pde(list, pde_start_addr, a20_mask, line_addr);
+ }
+}
+
+#ifdef TARGET_X86_64
+/* IA-32e Paging */
+static void walk_pdpe(MemoryMappingList *list,
+ target_phys_addr_t pdpe_start_addr, int32_t a20_mask,
+ target_ulong start_line_addr)
+{
+ target_phys_addr_t pdpe_addr, pde_start_addr, start_paddr;
+ uint64_t pdpe;
+ target_ulong line_addr, start_vaddr;
+ int i;
+
+ for (i = 0; i < 512; i++) {
+ pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
+ pdpe = ldq_phys(pdpe_addr);
+ if (!(pdpe & PG_PRESENT_MASK)) {
+ /* not present */
+ continue;
+ }
+
+ line_addr = start_line_addr | ((i & 0x1ffULL) << 30);
+ if (pdpe & PG_PSE_MASK) {
+ /* 1 GB page */
+ start_paddr = (pdpe & ~0x3fffffff) & ~(0x1ULL << 63);
+ if (cpu_physical_memory_is_io(start_paddr)) {
+ /* I/O region */
+ continue;
+ }
+ start_vaddr = line_addr;
+ memory_mapping_list_add_merge_sorted(list, start_paddr,
+ start_vaddr, 1 << 30);
+ continue;
+ }
+
+ pde_start_addr = (pdpe & ~0xfff) & a20_mask;
+ walk_pde(list, pde_start_addr, a20_mask, line_addr);
+ }
+}
+
+/* IA-32e Paging */
+static void walk_pml4e(MemoryMappingList *list,
+ target_phys_addr_t pml4e_start_addr, int32_t a20_mask)
+{
+ target_phys_addr_t pml4e_addr, pdpe_start_addr;
+ uint64_t pml4e;
+ target_ulong line_addr;
+ int i;
+
+ for (i = 0; i < 512; i++) {
+ pml4e_addr = (pml4e_start_addr + i * 8) & a20_mask;
+ pml4e = ldq_phys(pml4e_addr);
+ if (!(pml4e & PG_PRESENT_MASK)) {
+ /* not present */
+ continue;
+ }
+
+ line_addr = ((i & 0x1ffULL) << 39) | (0xffffULL << 48);
+ pdpe_start_addr = (pml4e & ~0xfff) & a20_mask;
+ walk_pdpe(list, pdpe_start_addr, a20_mask, line_addr);
+ }
+}
+#endif
+
+int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
+{
+ if (!cpu_paging_enabled(env)) {
+ /* paging is disabled */
+ return 0;
+ }
+
+ if (env->cr[4] & CR4_PAE_MASK) {
+#ifdef TARGET_X86_64
+ if (env->hflags & HF_LMA_MASK) {
+ target_phys_addr_t pml4e_addr;
+
+ pml4e_addr = (env->cr[3] & ~0xfff) & env->a20_mask;
+ walk_pml4e(list, pml4e_addr, env->a20_mask);
+ } else
+#endif
+ {
+ target_phys_addr_t pdpe_addr;
+
+ pdpe_addr = (env->cr[3] & ~0x1f) & env->a20_mask;
+ walk_pdpe2(list, pdpe_addr, env->a20_mask);
+ }
+ } else {
+ target_phys_addr_t pde_addr;
+ bool pse;
+
+ pde_addr = (env->cr[3] & ~0xfff) & env->a20_mask;
+ pse = !!(env->cr[4] & CR4_PSE_MASK);
+ walk_pde2(list, pde_addr, env->a20_mask, pse);
+ }
+
+ return 0;
+}
+
+bool cpu_paging_enabled(CPUArchState *env)
+{
+ return env->cr[0] & CR0_PG_MASK;
+}
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 388bc5c527..0b6116246f 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -723,66 +723,32 @@ static void x86_cpuid_get_level(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
- int64_t value;
- value = cpu->env.cpuid_level;
- /* TODO Use visit_type_uint32() once available */
- visit_type_int(v, &value, name, errp);
+ visit_type_uint32(v, &cpu->env.cpuid_level, name, errp);
}
static void x86_cpuid_set_level(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
- const int64_t min = 0;
- const int64_t max = UINT32_MAX;
- int64_t value;
-
- /* TODO Use visit_type_uint32() once available */
- visit_type_int(v, &value, name, errp);
- if (error_is_set(errp)) {
- return;
- }
- if (value < min || value > max) {
- error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
- name ? name : "null", value, min, max);
- return;
- }
- cpu->env.cpuid_level = value;
+ visit_type_uint32(v, &cpu->env.cpuid_level, name, errp);
}
static void x86_cpuid_get_xlevel(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
- int64_t value;
- value = cpu->env.cpuid_xlevel;
- /* TODO Use visit_type_uint32() once available */
- visit_type_int(v, &value, name, errp);
+ visit_type_uint32(v, &cpu->env.cpuid_xlevel, name, errp);
}
static void x86_cpuid_set_xlevel(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
- const int64_t min = 0;
- const int64_t max = UINT32_MAX;
- int64_t value;
-
- /* TODO Use visit_type_uint32() once available */
- visit_type_int(v, &value, name, errp);
- if (error_is_set(errp)) {
- return;
- }
- if (value < min || value > max) {
- error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
- name ? name : "null", value, min, max);
- return;
- }
- cpu->env.cpuid_xlevel = value;
+ visit_type_uint32(v, &cpu->env.cpuid_xlevel, name, errp);
}
static char *x86_cpuid_get_vendor(Object *obj, Error **errp)
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 2460f6348b..bcf663eeb5 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -787,7 +787,7 @@ typedef struct CPUX86State {
#include "cpu-qom.h"
-CPUX86State *cpu_x86_init(const char *cpu_model);
+X86CPU *cpu_x86_init(const char *cpu_model);
int cpu_x86_exec(CPUX86State *s);
void x86_cpu_list (FILE *f, fprintf_function cpu_fprintf, const char *optarg);
void x86_cpudef_setup(void);
@@ -960,7 +960,15 @@ uint64_t cpu_get_tsc(CPUX86State *env);
#define TARGET_VIRT_ADDR_SPACE_BITS 32
#endif
-#define cpu_init cpu_x86_init
+static inline CPUX86State *cpu_init(const char *cpu_model)
+{
+ X86CPU *cpu = cpu_x86_init(cpu_model);
+ if (cpu == NULL) {
+ return NULL;
+ }
+ return &cpu->env;
+}
+
#define cpu_exec cpu_x86_exec
#define cpu_gen_code cpu_x86_gen_code
#define cpu_signal_handler cpu_x86_signal_handler
@@ -1053,8 +1061,8 @@ static inline void cpu_get_tb_cpu_state(CPUX86State *env, target_ulong *pc,
(env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK));
}
-void do_cpu_init(CPUX86State *env);
-void do_cpu_sipi(CPUX86State *env);
+void do_cpu_init(X86CPU *cpu);
+void do_cpu_sipi(X86CPU *cpu);
#define MCE_INJECT_BROADCAST 1
#define MCE_INJECT_UNCOND_AO 2
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 3421be2276..2cc80977e8 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -26,12 +26,6 @@
//#define DEBUG_MMU
-/* NOTE: must be called outside the CPU execute loop */
-void cpu_state_reset(CPUX86State *env)
-{
- cpu_reset(ENV_GET_CPU(env));
-}
-
static void cpu_x86_version(CPUX86State *env, int *family, int *model)
{
int cpuver = env->cpuid_version;
@@ -1157,7 +1151,7 @@ int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
return 1;
}
-CPUX86State *cpu_x86_init(const char *cpu_model)
+X86CPU *cpu_x86_init(const char *cpu_model)
{
X86CPU *cpu;
CPUX86State *env;
@@ -1183,31 +1177,34 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
x86_cpu_realize(OBJECT(cpu), NULL);
- return env;
+ return cpu;
}
#if !defined(CONFIG_USER_ONLY)
-void do_cpu_init(CPUX86State *env)
+void do_cpu_init(X86CPU *cpu)
{
+ CPUX86State *env = &cpu->env;
int sipi = env->interrupt_request & CPU_INTERRUPT_SIPI;
uint64_t pat = env->pat;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
env->interrupt_request = sipi;
env->pat = pat;
apic_init_reset(env->apic_state);
env->halted = !cpu_is_bsp(env);
}
-void do_cpu_sipi(CPUX86State *env)
+void do_cpu_sipi(X86CPU *cpu)
{
+ CPUX86State *env = &cpu->env;
+
apic_sipi(env->apic_state);
}
#else
-void do_cpu_init(CPUX86State *env)
+void do_cpu_init(X86CPU *cpu)
{
}
-void do_cpu_sipi(CPUX86State *env)
+void do_cpu_sipi(X86CPU *cpu)
{
}
#endif
diff --git a/ioport-user.c b/target-i386/ioport-user.c
index 03fac22d22..03fac22d22 100644
--- a/ioport-user.c
+++ b/target-i386/ioport-user.c
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index e74a9e4641..0d0d8f69d3 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1698,6 +1698,8 @@ void kvm_arch_post_run(CPUX86State *env, struct kvm_run *run)
int kvm_arch_process_async_events(CPUX86State *env)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
+
if (env->interrupt_request & CPU_INTERRUPT_MCE) {
/* We must not raise CPU_INTERRUPT_MCE if it's not supported. */
assert(env->mcg_cap);
@@ -1732,11 +1734,11 @@ int kvm_arch_process_async_events(CPUX86State *env)
}
if (env->interrupt_request & CPU_INTERRUPT_INIT) {
kvm_cpu_synchronize_state(env);
- do_cpu_init(env);
+ do_cpu_init(cpu);
}
if (env->interrupt_request & CPU_INTERRUPT_SIPI) {
kvm_cpu_synchronize_state(env);
- do_cpu_sipi(env);
+ do_cpu_sipi(cpu);
}
if (env->interrupt_request & CPU_INTERRUPT_TPR) {
env->interrupt_request &= ~CPU_INTERRUPT_TPR;
diff --git a/target-lm32/Makefile.objs b/target-lm32/Makefile.objs
new file mode 100644
index 0000000000..2e0e093e1f
--- /dev/null
+++ b/target-lm32/Makefile.objs
@@ -0,0 +1,4 @@
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index 48a5fe3f86..caa4834075 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -18,7 +18,7 @@
* <http://www.gnu.org/licenses/lgpl-2.1.html>
*/
-#include "cpu-qom.h"
+#include "cpu.h"
#include "qemu-common.h"
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 422a55b063..da80469f51 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -186,7 +186,7 @@ struct CPULM32State {
#include "cpu-qom.h"
-CPULM32State *cpu_lm32_init(const char *cpu_model);
+LM32CPU *cpu_lm32_init(const char *cpu_model);
void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf);
int cpu_lm32_exec(CPULM32State *s);
void cpu_lm32_close(CPULM32State *s);
@@ -199,8 +199,16 @@ int cpu_lm32_signal_handler(int host_signum, void *pinfo,
void lm32_translate_init(void);
void cpu_lm32_set_phys_msb_ignore(CPULM32State *env, int value);
+static inline CPULM32State *cpu_init(const char *cpu_model)
+{
+ LM32CPU *cpu = cpu_lm32_init(cpu_model);
+ if (cpu == NULL) {
+ return NULL;
+ }
+ return &cpu->env;
+}
+
#define cpu_list cpu_lm32_list
-#define cpu_init cpu_lm32_init
#define cpu_exec cpu_lm32_exec
#define cpu_gen_code cpu_lm32_gen_code
#define cpu_signal_handler cpu_lm32_signal_handler
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index d0bc1931d8..1ea477fea3 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -192,7 +192,7 @@ static uint32_t cfg_by_def(const LM32Def *def)
return cfg;
}
-CPULM32State *cpu_lm32_init(const char *cpu_model)
+LM32CPU *cpu_lm32_init(const char *cpu_model)
{
LM32CPU *cpu;
CPULM32State *env;
@@ -219,7 +219,7 @@ CPULM32State *cpu_lm32_init(const char *cpu_model)
lm32_translate_init();
}
- return env;
+ return cpu;
}
/* Some soc ignores the MSB on the address bus. Thus creating a shadow memory
@@ -233,9 +233,3 @@ void cpu_lm32_set_phys_msb_ignore(CPULM32State *env, int value)
env->flags &= ~LM32_FLAG_IGNORE_MSB;
}
}
-
-void cpu_state_reset(CPULM32State *env)
-{
- cpu_reset(ENV_GET_CPU(env));
-}
-
diff --git a/target-m68k/Makefile.objs b/target-m68k/Makefile.objs
new file mode 100644
index 0000000000..cda60157f5
--- /dev/null
+++ b/target-m68k/Makefile.objs
@@ -0,0 +1,5 @@
+obj-y += m68k-semi.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index f428375d7d..eac0053c5d 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -98,11 +98,6 @@ static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
return 0;
}
-void cpu_state_reset(CPUM68KState *env)
-{
- cpu_reset(ENV_GET_CPU(env));
-}
-
CPUM68KState *cpu_m68k_init(const char *cpu_model)
{
M68kCPU *cpu;
diff --git a/m68k-semi.c b/target-m68k/m68k-semi.c
index 3bb30cd1f7..3bb30cd1f7 100644
--- a/m68k-semi.c
+++ b/target-m68k/m68k-semi.c
diff --git a/target-microblaze/Makefile.objs b/target-microblaze/Makefile.objs
new file mode 100644
index 0000000000..4b09e8c6b5
--- /dev/null
+++ b/target-microblaze/Makefile.objs
@@ -0,0 +1,4 @@
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += mmu.o machine.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index b0ba9fe296..4968c244e8 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -272,7 +272,7 @@ struct CPUMBState {
#include "cpu-qom.h"
-CPUMBState *cpu_mb_init(const char *cpu_model);
+MicroBlazeCPU *cpu_mb_init(const char *cpu_model);
int cpu_mb_exec(CPUMBState *s);
void cpu_mb_close(CPUMBState *s);
void do_interrupt(CPUMBState *env);
@@ -295,7 +295,15 @@ enum {
#define TARGET_PHYS_ADDR_SPACE_BITS 32
#define TARGET_VIRT_ADDR_SPACE_BITS 32
-#define cpu_init cpu_mb_init
+static inline CPUMBState *cpu_init(const char *cpu_model)
+{
+ MicroBlazeCPU *cpu = cpu_mb_init(cpu_model);
+ if (cpu == NULL) {
+ return NULL;
+ }
+ return &cpu->env;
+}
+
#define cpu_exec cpu_mb_exec
#define cpu_gen_code cpu_mb_gen_code
#define cpu_signal_handler cpu_mb_signal_handler
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index f0ebd596c0..c0a6bfd9c3 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1105,7 +1105,7 @@ static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
static void dec_store(DisasContext *dc)
{
- TCGv t, *addr, swx_addr, r_check = 0;
+ TCGv t, *addr, swx_addr, r_check;
int swx_skip = 0;
unsigned int size, rev = 0, ex = 0;
@@ -1129,9 +1129,9 @@ static void dec_store(DisasContext *dc)
sync_jmpstate(dc);
addr = compute_ldst_addr(dc, &t);
+ r_check = tcg_temp_new();
+ swx_addr = tcg_temp_local_new();
if (ex) { /* swx */
- r_check = tcg_temp_new();
- swx_addr = tcg_temp_local_new();
/* Force addr into the swx_addr. */
tcg_gen_mov_tl(swx_addr, *addr);
@@ -1221,11 +1221,12 @@ static void dec_store(DisasContext *dc)
gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
tcg_const_tl(1), tcg_const_tl(size - 1));
}
+
if (ex) {
gen_set_label(swx_skip);
- tcg_temp_free(r_check);
- tcg_temp_free(swx_addr);
}
+ tcg_temp_free(r_check);
+ tcg_temp_free(swx_addr);
if (addr == &t)
tcg_temp_free(t);
@@ -1951,21 +1952,20 @@ void cpu_dump_state (CPUMBState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "\n\n");
}
-CPUMBState *cpu_mb_init (const char *cpu_model)
+MicroBlazeCPU *cpu_mb_init(const char *cpu_model)
{
MicroBlazeCPU *cpu;
- CPUMBState *env;
static int tcg_initialized = 0;
int i;
cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU));
- env = &cpu->env;
cpu_reset(CPU(cpu));
- qemu_init_vcpu(env);
+ qemu_init_vcpu(&cpu->env);
- if (tcg_initialized)
- return env;
+ if (tcg_initialized) {
+ return cpu;
+ }
tcg_initialized = 1;
@@ -1999,12 +1999,7 @@ CPUMBState *cpu_mb_init (const char *cpu_model)
#define GEN_HELPER 2
#include "helper.h"
- return env;
-}
-
-void cpu_state_reset(CPUMBState *env)
-{
- cpu_reset(ENV_GET_CPU(env));
+ return cpu;
}
void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos)
diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs
new file mode 100644
index 0000000000..2e0e093e1f
--- /dev/null
+++ b/target-mips/Makefile.objs
@@ -0,0 +1,4 @@
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 44c1152a3a..ce3467f140 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -496,7 +496,6 @@ void cpu_unassigned_access(CPUMIPSState *env, target_phys_addr_t addr,
void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
-#define cpu_init cpu_mips_init
#define cpu_exec cpu_mips_exec
#define cpu_gen_code cpu_mips_gen_code
#define cpu_signal_handler cpu_mips_signal_handler
@@ -626,9 +625,21 @@ enum {
#define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0
int cpu_mips_exec(CPUMIPSState *s);
-CPUMIPSState *cpu_mips_init(const char *cpu_model);
+MIPSCPU *cpu_mips_init(const char *cpu_model);
int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
+static inline CPUMIPSState *cpu_init(const char *cpu_model)
+{
+ MIPSCPU *cpu = cpu_mips_init(cpu_model);
+ if (cpu == NULL) {
+ return NULL;
+ }
+ return &cpu->env;
+}
+
+/* TODO QOM'ify CPU reset and remove */
+void cpu_state_reset(CPUMIPSState *s);
+
/* mips_timer.c */
uint32_t cpu_mips_get_random (CPUMIPSState *env);
uint32_t cpu_mips_get_count (CPUMIPSState *env);
diff --git a/target-mips/helper.c b/target-mips/helper.c
index ddf9cb72f4..4208bb20c8 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -399,6 +399,7 @@ static void set_hflags_for_handler (CPUMIPSState *env)
void do_interrupt (CPUMIPSState *env)
{
#if !defined(CONFIG_USER_ONLY)
+ MIPSCPU *cpu = mips_env_get_cpu(env);
target_ulong offset;
int cause = -1;
const char *name;
@@ -452,7 +453,7 @@ void do_interrupt (CPUMIPSState *env)
set_hflags_for_handler(env);
break;
case EXCP_RESET:
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
break;
case EXCP_SRESET:
env->CP0_Status |= (1 << CP0St_SR);
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 0c563eedfa..4e15ee36b8 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -12689,7 +12689,7 @@ static void mips_tcg_init(void)
#include "translate_init.c"
-CPUMIPSState *cpu_mips_init (const char *cpu_model)
+MIPSCPU *cpu_mips_init(const char *cpu_model)
{
MIPSCPU *cpu;
CPUMIPSState *env;
@@ -12709,9 +12709,9 @@ CPUMIPSState *cpu_mips_init (const char *cpu_model)
fpu_init(env, def);
mvp_init(env, def);
mips_tcg_init();
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
qemu_init_vcpu(env);
- return env;
+ return cpu;
}
void cpu_state_reset(CPUMIPSState *env)
diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
new file mode 100644
index 0000000000..f78161004e
--- /dev/null
+++ b/target-ppc/Makefile.objs
@@ -0,0 +1,6 @@
+obj-y += translate.o op_helper.o helper.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o
+obj-y += op_helper.o helper.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 84c9674157..77a28580af 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1099,7 +1099,7 @@ struct mmu_ctx_t {
#include "cpu-qom.h"
/*****************************************************************************/
-CPUPPCState *cpu_ppc_init (const char *cpu_model);
+PowerPCCPU *cpu_ppc_init(const char *cpu_model);
void ppc_translate_init(void);
int cpu_ppc_exec (CPUPPCState *s);
/* you can call this signal handler from your SIGBUS and SIGSEGV
@@ -1214,7 +1214,15 @@ static inline uint64_t ppc_dump_gpr(CPUPPCState *env, int gprn)
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp);
int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val);
-#define cpu_init cpu_ppc_init
+static inline CPUPPCState *cpu_init(const char *cpu_model)
+{
+ PowerPCCPU *cpu = cpu_ppc_init(cpu_model);
+ if (cpu == NULL) {
+ return NULL;
+ }
+ return &cpu->env;
+}
+
#define cpu_exec cpu_ppc_exec
#define cpu_gen_code cpu_ppc_gen_code
#define cpu_signal_handler cpu_ppc_signal_handler
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index e97e49640d..f556f8567a 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -3186,12 +3186,7 @@ void cpu_dump_rfi (target_ulong RA, target_ulong msr)
TARGET_FMT_lx "\n", RA, msr);
}
-void cpu_state_reset(CPUPPCState *env)
-{
- cpu_reset(ENV_GET_CPU(env));
-}
-
-CPUPPCState *cpu_ppc_init (const char *cpu_model)
+PowerPCCPU *cpu_ppc_init(const char *cpu_model)
{
PowerPCCPU *cpu;
CPUPPCState *env;
@@ -3213,5 +3208,5 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model)
qemu_init_vcpu(env);
- return env;
+ return cpu;
}
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
new file mode 100644
index 0000000000..262747f8a6
--- /dev/null
+++ b/target-s390x/Makefile.objs
@@ -0,0 +1,5 @@
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-$(CONFIG_KVM) += kvm.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index f183213eab..619b202b92 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -20,7 +20,7 @@
* <http://www.gnu.org/licenses/lgpl-2.1.html>
*/
-#include "cpu-qom.h"
+#include "cpu.h"
#include "qemu-common.h"
#include "qemu-timer.h"
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 2f3f3942c0..c30ac3a0e1 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -105,6 +105,8 @@ typedef struct CPUS390XState {
QEMUTimer *cpu_timer;
} CPUS390XState;
+#include "cpu-qom.h"
+
#if defined(CONFIG_USER_ONLY)
static inline void cpu_clone_regs(CPUS390XState *env, target_ulong newsp)
{
@@ -271,7 +273,7 @@ static inline int get_ilc(uint8_t opc)
#define ILC_LATER_INC_2 0x22
-CPUS390XState *cpu_s390x_init(const char *cpu_model);
+S390CPU *cpu_s390x_init(const char *cpu_model);
void s390x_translate_init(void);
int cpu_s390x_exec(CPUS390XState *s);
void cpu_s390x_close(CPUS390XState *s);
@@ -314,7 +316,7 @@ static inline void kvm_s390_interrupt_internal(CPUS390XState *env, int type,
{
}
#endif
-CPUS390XState *s390_cpu_addr2state(uint16_t cpu_addr);
+S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
void s390_add_running_cpu(CPUS390XState *env);
unsigned s390_del_running_cpu(CPUS390XState *env);
@@ -340,7 +342,7 @@ static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
env->aregs[1] = newtls & 0xffffffffULL;
}
-#define cpu_init cpu_s390x_init
+#define cpu_init(model) (&cpu_s390x_init(model)->env)
#define cpu_exec cpu_s390x_exec
#define cpu_gen_code cpu_s390x_gen_code
#define cpu_signal_handler cpu_s390x_signal_handler
@@ -994,6 +996,4 @@ static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb)
env->psw.addr = tb->pc;
}
-#include "cpu-qom.h"
-
#endif
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 209a69603c..d0a1180a83 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -70,7 +70,7 @@ void s390x_cpu_timer(void *opaque)
}
#endif
-CPUS390XState *cpu_s390x_init(const char *cpu_model)
+S390CPU *cpu_s390x_init(const char *cpu_model)
{
S390CPU *cpu;
CPUS390XState *env;
@@ -86,7 +86,7 @@ CPUS390XState *cpu_s390x_init(const char *cpu_model)
env->cpu_model_str = cpu_model;
qemu_init_vcpu(env);
- return env;
+ return cpu;
}
#if defined(CONFIG_USER_ONLY)
@@ -106,14 +106,7 @@ int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw
return 1;
}
-#endif /* CONFIG_USER_ONLY */
-
-void cpu_state_reset(CPUS390XState *env)
-{
- cpu_reset(ENV_GET_CPU(env));
-}
-
-#ifndef CONFIG_USER_ONLY
+#else /* !CONFIG_USER_ONLY */
/* Ensure to exit the TB after this call! */
static void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilc)
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 90aad61eb0..5800fd612c 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -292,8 +292,10 @@ static int handle_diag(CPUS390XState *env, struct kvm_run *run, int ipb_code)
return r;
}
-static int s390_cpu_restart(CPUS390XState *env)
+static int s390_cpu_restart(S390CPU *cpu)
{
+ CPUS390XState *env = &cpu->env;
+
kvm_s390_interrupt(env, KVM_S390_RESTART, 0);
s390_add_running_cpu(env);
qemu_cpu_kick(env);
@@ -333,6 +335,7 @@ static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
uint16_t cpu_addr;
uint8_t t;
int r = -1;
+ S390CPU *target_cpu;
CPUS390XState *target_env;
cpu_synchronize_state(env);
@@ -353,14 +356,15 @@ static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
parameter = env->regs[t] & 0x7ffffe00;
cpu_addr = env->regs[ipa1 & 0x0f];
- target_env = s390_cpu_addr2state(cpu_addr);
- if (!target_env) {
+ target_cpu = s390_cpu_addr2state(cpu_addr);
+ if (target_cpu == NULL) {
goto out;
}
+ target_env = &target_cpu->env;
switch (order_code) {
case SIGP_RESTART:
- r = s390_cpu_restart(target_env);
+ r = s390_cpu_restart(target_cpu);
break;
case SIGP_STORE_STATUS_ADDR:
r = s390_store_status(target_env, parameter);
diff --git a/target-sh4/Makefile.objs b/target-sh4/Makefile.objs
new file mode 100644
index 0000000000..2e0e093e1f
--- /dev/null
+++ b/target-sh4/Makefile.objs
@@ -0,0 +1,4 @@
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index b6768f1648..bf592227ee 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -191,7 +191,7 @@ typedef struct CPUSH4State {
#include "cpu-qom.h"
-CPUSH4State *cpu_sh4_init(const char *cpu_model);
+SuperHCPU *cpu_sh4_init(const char *cpu_model);
int cpu_sh4_exec(CPUSH4State * s);
int cpu_sh4_signal_handler(int host_signum, void *pinfo,
void *puc);
@@ -232,7 +232,15 @@ void cpu_load_tlb(CPUSH4State * env);
#include "softfloat.h"
-#define cpu_init cpu_sh4_init
+static inline CPUSH4State *cpu_init(const char *cpu_model)
+{
+ SuperHCPU *cpu = cpu_sh4_init(cpu_model);
+ if (cpu == NULL) {
+ return NULL;
+ }
+ return &cpu->env;
+}
+
#define cpu_exec cpu_sh4_exec
#define cpu_gen_code cpu_sh4_gen_code
#define cpu_signal_handler cpu_sh4_signal_handler
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index d25f0c5a29..6532ad2ade 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -178,11 +178,6 @@ void cpu_dump_state(CPUSH4State * env, FILE * f,
}
}
-void cpu_state_reset(CPUSH4State *env)
-{
- cpu_reset(ENV_GET_CPU(env));
-}
-
typedef struct {
const char *name;
int id;
@@ -247,7 +242,7 @@ static void cpu_register(CPUSH4State *env, const sh4_def_t *def)
env->id = def->id;
}
-CPUSH4State *cpu_sh4_init(const char *cpu_model)
+SuperHCPU *cpu_sh4_init(const char *cpu_model)
{
SuperHCPU *cpu;
CPUSH4State *env;
@@ -264,7 +259,7 @@ CPUSH4State *cpu_sh4_init(const char *cpu_model)
cpu_reset(CPU(cpu));
cpu_register(env, def);
qemu_init_vcpu(env);
- return env;
+ return cpu;
}
static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
diff --git a/target-sparc/Makefile.objs b/target-sparc/Makefile.objs
new file mode 100644
index 0000000000..a93e07deb1
--- /dev/null
+++ b/target-sparc/Makefile.objs
@@ -0,0 +1,8 @@
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-y += translate.o helper.o cpu.o
+obj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o
+obj-$(TARGET_SPARC) += int32_helper.o
+obj-$(TARGET_SPARC64) += int64_helper.o
+obj-$(TARGET_SPARC64) += vis_helper.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 7ac6bdb058..f7c004c7d8 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -23,11 +23,6 @@
static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
-void cpu_state_reset(CPUSPARCState *env)
-{
- cpu_reset(ENV_GET_CPU(env));
-}
-
/* CPUClass::reset() */
static void sparc_cpu_reset(CPUState *s)
{
@@ -111,7 +106,7 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
return 0;
}
-CPUSPARCState *cpu_sparc_init(const char *cpu_model)
+SPARCCPU *cpu_sparc_init(const char *cpu_model)
{
SPARCCPU *cpu;
CPUSPARCState *env;
@@ -129,7 +124,7 @@ CPUSPARCState *cpu_sparc_init(const char *cpu_model)
}
qemu_init_vcpu(env);
- return env;
+ return cpu;
}
void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 29c63c711f..e16b7b3515 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -511,9 +511,11 @@ struct CPUSPARCState {
uint32_t cache_control;
};
+#include "cpu-qom.h"
+
#ifndef NO_CPU_IO_DEFS
/* cpu_init.c */
-CPUSPARCState *cpu_sparc_init(const char *cpu_model);
+SPARCCPU *cpu_sparc_init(const char *cpu_model);
void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf);
/* mmu_helper.c */
@@ -590,7 +592,17 @@ target_phys_addr_t cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong ad
#endif
int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
-#define cpu_init cpu_sparc_init
+#ifndef NO_CPU_IO_DEFS
+static inline CPUSPARCState *cpu_init(const char *cpu_model)
+{
+ SPARCCPU *cpu = cpu_sparc_init(cpu_model);
+ if (cpu == NULL) {
+ return NULL;
+ }
+ return &cpu->env;
+}
+#endif
+
#define cpu_exec cpu_sparc_exec
#define cpu_gen_code cpu_sparc_gen_code
#define cpu_signal_handler cpu_sparc_signal_handler
@@ -691,7 +703,6 @@ static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp)
#endif
#include "cpu-all.h"
-#include "cpu-qom.h"
#ifdef TARGET_SPARC64
/* sun4u.c */
diff --git a/target-unicore32/Makefile.objs b/target-unicore32/Makefile.objs
new file mode 100644
index 0000000000..2e0e093e1f
--- /dev/null
+++ b/target-unicore32/Makefile.objs
@@ -0,0 +1,4 @@
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-xtensa/Makefile.objs b/target-xtensa/Makefile.objs
new file mode 100644
index 0000000000..b30e5a8466
--- /dev/null
+++ b/target-xtensa/Makefile.objs
@@ -0,0 +1,6 @@
+obj-y += xtensa-semi.o
+obj-y += core-dc232b.o
+obj-y += core-dc233c.o
+obj-y += core-fsf.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index 97deacb478..9d01983d44 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -28,7 +28,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "cpu-qom.h"
+#include "cpu.h"
#include "qemu-common.h"
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 6d0ea7c038..f7db116400 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -344,13 +344,24 @@ typedef struct CPUXtensaState {
CPU_COMMON
} CPUXtensaState;
-#define cpu_init cpu_xtensa_init
+#include "cpu-qom.h"
+
#define cpu_exec cpu_xtensa_exec
#define cpu_gen_code cpu_xtensa_gen_code
#define cpu_signal_handler cpu_xtensa_signal_handler
#define cpu_list xtensa_cpu_list
-CPUXtensaState *cpu_xtensa_init(const char *cpu_model);
+XtensaCPU *cpu_xtensa_init(const char *cpu_model);
+
+static inline CPUXtensaState *cpu_init(const char *cpu_model)
+{
+ XtensaCPU *cpu = cpu_xtensa_init(cpu_model);
+ if (cpu == NULL) {
+ return NULL;
+ }
+ return &cpu->env;
+}
+
void xtensa_translate_init(void);
int cpu_xtensa_exec(CPUXtensaState *s);
void xtensa_register_core(XtensaConfigList *node);
@@ -370,9 +381,12 @@ void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb,
uint32_t *vpn, uint32_t wi, uint32_t *ei);
int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb,
uint32_t *pwi, uint32_t *pei, uint8_t *pring);
+void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
+ xtensa_tlb_entry *entry, bool dtlb,
+ unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
-int xtensa_get_physical_addr(CPUXtensaState *env,
+int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb,
uint32_t vaddr, int is_write, int mmu_idx,
uint32_t *paddr, uint32_t *page_size, unsigned *access);
void reset_mmu(CPUXtensaState *env);
@@ -471,7 +485,6 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
}
#include "cpu-all.h"
-#include "cpu-qom.h"
#include "exec-all.h"
static inline int cpu_has_work(CPUXtensaState *env)
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 2094227843..044ce18364 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -33,11 +33,6 @@
#include "hw/loader.h"
#endif
-void cpu_state_reset(CPUXtensaState *env)
-{
- cpu_reset(ENV_GET_CPU(env));
-}
-
static struct XtensaConfigList *xtensa_cores;
void xtensa_register_core(XtensaConfigList *node)
@@ -80,7 +75,7 @@ static void breakpoint_handler(CPUXtensaState *env)
}
}
-CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
+XtensaCPU *cpu_xtensa_init(const char *cpu_model)
{
static int tcg_inited;
static int debug_handler_inited;
@@ -116,7 +111,7 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
xtensa_irq_init(env);
qemu_init_vcpu(env);
- return env;
+ return cpu;
}
@@ -135,11 +130,11 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUXtensaState *env, target_ulong add
uint32_t page_size;
unsigned access;
- if (xtensa_get_physical_addr(env, addr, 0, 0,
+ if (xtensa_get_physical_addr(env, false, addr, 0, 0,
&paddr, &page_size, &access) == 0) {
return paddr;
}
- if (xtensa_get_physical_addr(env, addr, 2, 0,
+ if (xtensa_get_physical_addr(env, false, addr, 2, 0,
&paddr, &page_size, &access) == 0) {
return paddr;
}
@@ -448,30 +443,48 @@ static bool is_access_granted(unsigned access, int is_write)
}
}
-static int autorefill_mmu(CPUXtensaState *env, uint32_t vaddr, bool dtlb,
- uint32_t *wi, uint32_t *ei, uint8_t *ring);
+static int get_pte(CPUXtensaState *env, uint32_t vaddr, uint32_t *pte);
-static int get_physical_addr_mmu(CPUXtensaState *env,
+static int get_physical_addr_mmu(CPUXtensaState *env, bool update_tlb,
uint32_t vaddr, int is_write, int mmu_idx,
- uint32_t *paddr, uint32_t *page_size, unsigned *access)
+ uint32_t *paddr, uint32_t *page_size, unsigned *access,
+ bool may_lookup_pt)
{
bool dtlb = is_write != 2;
uint32_t wi;
uint32_t ei;
uint8_t ring;
+ uint32_t vpn;
+ uint32_t pte;
+ const xtensa_tlb_entry *entry = NULL;
+ xtensa_tlb_entry tmp_entry;
int ret = xtensa_tlb_lookup(env, vaddr, dtlb, &wi, &ei, &ring);
if ((ret == INST_TLB_MISS_CAUSE || ret == LOAD_STORE_TLB_MISS_CAUSE) &&
- (mmu_idx != 0 || ((vaddr ^ env->sregs[PTEVADDR]) & 0xffc00000)) &&
- autorefill_mmu(env, vaddr, dtlb, &wi, &ei, &ring) == 0) {
+ may_lookup_pt && get_pte(env, vaddr, &pte) == 0) {
+ ring = (pte >> 4) & 0x3;
+ wi = 0;
+ split_tlb_entry_spec_way(env, vaddr, dtlb, &vpn, wi, &ei);
+
+ if (update_tlb) {
+ wi = ++env->autorefill_idx & 0x3;
+ xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, pte);
+ env->sregs[EXCVADDR] = vaddr;
+ qemu_log("%s: autorefill(%08x): %08x -> %08x\n",
+ __func__, vaddr, vpn, pte);
+ } else {
+ xtensa_tlb_set_entry_mmu(env, &tmp_entry, dtlb, wi, ei, vpn, pte);
+ entry = &tmp_entry;
+ }
ret = 0;
}
if (ret != 0) {
return ret;
}
- const xtensa_tlb_entry *entry =
- xtensa_tlb_get_entry(env, dtlb, wi, ei);
+ if (entry == NULL) {
+ entry = xtensa_tlb_get_entry(env, dtlb, wi, ei);
+ }
if (ring < mmu_idx) {
return dtlb ?
@@ -494,30 +507,21 @@ static int get_physical_addr_mmu(CPUXtensaState *env,
return 0;
}
-static int autorefill_mmu(CPUXtensaState *env, uint32_t vaddr, bool dtlb,
- uint32_t *wi, uint32_t *ei, uint8_t *ring)
+static int get_pte(CPUXtensaState *env, uint32_t vaddr, uint32_t *pte)
{
uint32_t paddr;
uint32_t page_size;
unsigned access;
uint32_t pt_vaddr =
(env->sregs[PTEVADDR] | (vaddr >> 10)) & 0xfffffffc;
- int ret = get_physical_addr_mmu(env, pt_vaddr, 0, 0,
- &paddr, &page_size, &access);
+ int ret = get_physical_addr_mmu(env, false, pt_vaddr, 0, 0,
+ &paddr, &page_size, &access, false);
qemu_log("%s: trying autorefill(%08x) -> %08x\n", __func__,
vaddr, ret ? ~0 : paddr);
if (ret == 0) {
- uint32_t vpn;
- uint32_t pte = ldl_phys(paddr);
-
- *ring = (pte >> 4) & 0x3;
- *wi = (++env->autorefill_idx) & 0x3;
- split_tlb_entry_spec_way(env, vaddr, dtlb, &vpn, *wi, ei);
- xtensa_tlb_set_entry(env, dtlb, *wi, *ei, vpn, pte);
- qemu_log("%s: autorefill(%08x): %08x -> %08x\n",
- __func__, vaddr, vpn, pte);
+ *pte = ldl_phys(paddr);
}
return ret;
}
@@ -553,13 +557,13 @@ static int get_physical_addr_region(CPUXtensaState *env,
*
* \return 0 if ok, exception cause code otherwise
*/
-int xtensa_get_physical_addr(CPUXtensaState *env,
+int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb,
uint32_t vaddr, int is_write, int mmu_idx,
uint32_t *paddr, uint32_t *page_size, unsigned *access)
{
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
- return get_physical_addr_mmu(env, vaddr, is_write, mmu_idx,
- paddr, page_size, access);
+ return get_physical_addr_mmu(env, update_tlb,
+ vaddr, is_write, mmu_idx, paddr, page_size, access, true);
} else if (xtensa_option_bits_enabled(env->config,
XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION))) {
diff --git a/target-xtensa/helper.h b/target-xtensa/helper.h
index 48a741e46d..152fec044d 100644
--- a/target-xtensa/helper.h
+++ b/target-xtensa/helper.h
@@ -1,39 +1,39 @@
#include "def-helper.h"
-DEF_HELPER_1(exception, void, i32)
-DEF_HELPER_2(exception_cause, void, i32, i32)
-DEF_HELPER_3(exception_cause_vaddr, void, i32, i32, i32)
-DEF_HELPER_2(debug_exception, void, i32, i32)
+DEF_HELPER_2(exception, noreturn, env, i32)
+DEF_HELPER_3(exception_cause, noreturn, env, i32, i32)
+DEF_HELPER_4(exception_cause_vaddr, noreturn, env, i32, i32, i32)
+DEF_HELPER_3(debug_exception, noreturn, env, i32, i32)
-DEF_HELPER_1(nsa, i32, i32)
-DEF_HELPER_1(nsau, i32, i32)
-DEF_HELPER_1(wsr_windowbase, void, i32)
-DEF_HELPER_3(entry, void, i32, i32, i32)
-DEF_HELPER_1(retw, i32, i32)
-DEF_HELPER_1(rotw, void, i32)
-DEF_HELPER_2(window_check, void, i32, i32)
-DEF_HELPER_0(restore_owb, void)
-DEF_HELPER_1(movsp, void, i32)
-DEF_HELPER_1(wsr_lbeg, void, i32)
-DEF_HELPER_1(wsr_lend, void, i32)
+DEF_HELPER_FLAGS_1(nsa, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(nsau, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_2(wsr_windowbase, void, env, i32)
+DEF_HELPER_4(entry, void, env, i32, i32, i32)
+DEF_HELPER_2(retw, i32, env, i32)
+DEF_HELPER_2(rotw, void, env, i32)
+DEF_HELPER_3(window_check, void, env, i32, i32)
+DEF_HELPER_1(restore_owb, void, env)
+DEF_HELPER_2(movsp, void, env, i32)
+DEF_HELPER_2(wsr_lbeg, void, env, i32)
+DEF_HELPER_2(wsr_lend, void, env, i32)
DEF_HELPER_1(simcall, void, env)
-DEF_HELPER_0(dump_state, void)
+DEF_HELPER_1(dump_state, void, env)
-DEF_HELPER_2(waiti, void, i32, i32)
-DEF_HELPER_2(timer_irq, void, i32, i32)
-DEF_HELPER_1(advance_ccount, void, i32)
+DEF_HELPER_3(waiti, void, env, i32, i32)
+DEF_HELPER_3(timer_irq, void, env, i32, i32)
+DEF_HELPER_2(advance_ccount, void, env, i32)
DEF_HELPER_1(check_interrupts, void, env)
-DEF_HELPER_1(wsr_rasid, void, i32)
-DEF_HELPER_2(rtlb0, i32, i32, i32)
-DEF_HELPER_2(rtlb1, i32, i32, i32)
-DEF_HELPER_2(itlb, void, i32, i32)
-DEF_HELPER_2(ptlb, i32, i32, i32)
-DEF_HELPER_3(wtlb, void, i32, i32, i32)
+DEF_HELPER_2(wsr_rasid, void, env, i32)
+DEF_HELPER_FLAGS_3(rtlb0, TCG_CALL_CONST | TCG_CALL_PURE, i32, env, i32, i32)
+DEF_HELPER_FLAGS_3(rtlb1, TCG_CALL_CONST | TCG_CALL_PURE, i32, env, i32, i32)
+DEF_HELPER_3(itlb, void, env, i32, i32)
+DEF_HELPER_3(ptlb, i32, env, i32, i32)
+DEF_HELPER_4(wtlb, void, env, i32, i32, i32)
-DEF_HELPER_1(wsr_ibreakenable, void, i32)
-DEF_HELPER_2(wsr_ibreaka, void, i32, i32)
-DEF_HELPER_2(wsr_dbreaka, void, i32, i32)
-DEF_HELPER_2(wsr_dbreakc, void, i32, i32)
+DEF_HELPER_2(wsr_ibreakenable, void, env, i32)
+DEF_HELPER_3(wsr_ibreaka, void, env, i32, i32)
+DEF_HELPER_3(wsr_dbreaka, void, env, i32, i32)
+DEF_HELPER_3(wsr_dbreakc, void, env, i32, i32)
#include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 364dc19bc0..2659c0e00f 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -26,12 +26,11 @@
*/
#include "cpu.h"
-#include "dyngen-exec.h"
#include "helper.h"
#include "host-utils.h"
-static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
- uintptr_t retaddr);
+static void do_unaligned_access(CPUXtensaState *env,
+ target_ulong addr, int is_write, int is_user, uintptr_t retaddr);
#define ALIGNED_ONLY
#define MMUSUFFIX _mmu
@@ -48,7 +47,7 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
#define SHIFT 3
#include "softmmu_template.h"
-static void do_restore_state(uintptr_t pc)
+static void do_restore_state(CPUXtensaState *env, uintptr_t pc)
{
TranslationBlock *tb;
@@ -58,44 +57,38 @@ static void do_restore_state(uintptr_t pc)
}
}
-static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
- uintptr_t retaddr)
+static void do_unaligned_access(CPUXtensaState *env,
+ target_ulong addr, int is_write, int is_user, uintptr_t retaddr)
{
if (xtensa_option_enabled(env->config, XTENSA_OPTION_UNALIGNED_EXCEPTION) &&
!xtensa_option_enabled(env->config, XTENSA_OPTION_HW_ALIGNMENT)) {
- do_restore_state(retaddr);
- HELPER(exception_cause_vaddr)(
+ do_restore_state(env, retaddr);
+ HELPER(exception_cause_vaddr)(env,
env->pc, LOAD_STORE_ALIGNMENT_CAUSE, addr);
}
}
-void tlb_fill(CPUXtensaState *env1, target_ulong vaddr, int is_write, int mmu_idx,
- uintptr_t retaddr)
+void tlb_fill(CPUXtensaState *env,
+ target_ulong vaddr, int is_write, int mmu_idx, uintptr_t retaddr)
{
- CPUXtensaState *saved_env = env;
-
- env = env1;
- {
- uint32_t paddr;
- uint32_t page_size;
- unsigned access;
- int ret = xtensa_get_physical_addr(env, vaddr, is_write, mmu_idx,
- &paddr, &page_size, &access);
+ uint32_t paddr;
+ uint32_t page_size;
+ unsigned access;
+ int ret = xtensa_get_physical_addr(env, true, vaddr, is_write, mmu_idx,
+ &paddr, &page_size, &access);
- qemu_log("%s(%08x, %d, %d) -> %08x, ret = %d\n", __func__,
- vaddr, is_write, mmu_idx, paddr, ret);
+ qemu_log("%s(%08x, %d, %d) -> %08x, ret = %d\n", __func__,
+ vaddr, is_write, mmu_idx, paddr, ret);
- if (ret == 0) {
- tlb_set_page(env,
- vaddr & TARGET_PAGE_MASK,
- paddr & TARGET_PAGE_MASK,
- access, mmu_idx, page_size);
- } else {
- do_restore_state(retaddr);
- HELPER(exception_cause_vaddr)(env->pc, ret, vaddr);
- }
+ if (ret == 0) {
+ tlb_set_page(env,
+ vaddr & TARGET_PAGE_MASK,
+ paddr & TARGET_PAGE_MASK,
+ access, mmu_idx, page_size);
+ } else {
+ do_restore_state(env, retaddr);
+ HELPER(exception_cause_vaddr)(env, env->pc, ret, vaddr);
}
- env = saved_env;
}
static void tb_invalidate_virtual_addr(CPUXtensaState *env, uint32_t vaddr)
@@ -103,20 +96,20 @@ static void tb_invalidate_virtual_addr(CPUXtensaState *env, uint32_t vaddr)
uint32_t paddr;
uint32_t page_size;
unsigned access;
- int ret = xtensa_get_physical_addr(env, vaddr, 2, 0,
+ int ret = xtensa_get_physical_addr(env, false, vaddr, 2, 0,
&paddr, &page_size, &access);
if (ret == 0) {
tb_invalidate_phys_addr(paddr);
}
}
-void HELPER(exception)(uint32_t excp)
+void HELPER(exception)(CPUXtensaState *env, uint32_t excp)
{
env->exception_index = excp;
cpu_loop_exit(env);
}
-void HELPER(exception_cause)(uint32_t pc, uint32_t cause)
+void HELPER(exception_cause)(CPUXtensaState *env, uint32_t pc, uint32_t cause)
{
uint32_t vector;
@@ -136,24 +129,24 @@ void HELPER(exception_cause)(uint32_t pc, uint32_t cause)
env->sregs[EXCCAUSE] = cause;
env->sregs[PS] |= PS_EXCM;
- HELPER(exception)(vector);
+ HELPER(exception)(env, vector);
}
-void HELPER(exception_cause_vaddr)(uint32_t pc, uint32_t cause, uint32_t vaddr)
+void HELPER(exception_cause_vaddr)(CPUXtensaState *env,
+ uint32_t pc, uint32_t cause, uint32_t vaddr)
{
env->sregs[EXCVADDR] = vaddr;
- HELPER(exception_cause)(pc, cause);
+ HELPER(exception_cause)(env, pc, cause);
}
-void debug_exception_env(CPUXtensaState *new_env, uint32_t cause)
+void debug_exception_env(CPUXtensaState *env, uint32_t cause)
{
- if (xtensa_get_cintlevel(new_env) < new_env->config->debug_level) {
- env = new_env;
- HELPER(debug_exception)(env->pc, cause);
+ if (xtensa_get_cintlevel(env) < env->config->debug_level) {
+ HELPER(debug_exception)(env, env->pc, cause);
}
}
-void HELPER(debug_exception)(uint32_t pc, uint32_t cause)
+void HELPER(debug_exception)(CPUXtensaState *env, uint32_t pc, uint32_t cause)
{
unsigned level = env->config->debug_level;
@@ -163,7 +156,7 @@ void HELPER(debug_exception)(uint32_t pc, uint32_t cause)
env->sregs[EPS2 + level - 2] = env->sregs[PS];
env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) | PS_EXCM |
(level << PS_INTLEVEL_SHIFT);
- HELPER(exception)(EXC_DEBUG);
+ HELPER(exception)(env, EXC_DEBUG);
}
uint32_t HELPER(nsa)(uint32_t v)
@@ -232,39 +225,39 @@ void xtensa_sync_phys_from_window(CPUXtensaState *env)
copy_phys_from_window(env, env->sregs[WINDOW_BASE] * 4, 0, 16);
}
-static void rotate_window_abs(uint32_t position)
+static void rotate_window_abs(CPUXtensaState *env, uint32_t position)
{
xtensa_sync_phys_from_window(env);
env->sregs[WINDOW_BASE] = windowbase_bound(position, env);
xtensa_sync_window_from_phys(env);
}
-static void rotate_window(uint32_t delta)
+static void rotate_window(CPUXtensaState *env, uint32_t delta)
{
- rotate_window_abs(env->sregs[WINDOW_BASE] + delta);
+ rotate_window_abs(env, env->sregs[WINDOW_BASE] + delta);
}
-void HELPER(wsr_windowbase)(uint32_t v)
+void HELPER(wsr_windowbase)(CPUXtensaState *env, uint32_t v)
{
- rotate_window_abs(v);
+ rotate_window_abs(env, v);
}
-void HELPER(entry)(uint32_t pc, uint32_t s, uint32_t imm)
+void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
{
int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT;
if (s > 3 || ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) != 0) {
qemu_log("Illegal entry instruction(pc = %08x), PS = %08x\n",
pc, env->sregs[PS]);
- HELPER(exception_cause)(pc, ILLEGAL_INSTRUCTION_CAUSE);
+ HELPER(exception_cause)(env, pc, ILLEGAL_INSTRUCTION_CAUSE);
} else {
env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - (imm << 3);
- rotate_window(callinc);
+ rotate_window(env, callinc);
env->sregs[WINDOW_START] |=
windowstart_bit(env->sregs[WINDOW_BASE], env);
}
}
-void HELPER(window_check)(uint32_t pc, uint32_t w)
+void HELPER(window_check)(CPUXtensaState *env, uint32_t pc, uint32_t w)
{
uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);
uint32_t windowstart = env->sregs[WINDOW_START];
@@ -284,21 +277,21 @@ void HELPER(window_check)(uint32_t pc, uint32_t w)
}
m = windowbase_bound(windowbase + n, env);
- rotate_window(n);
+ rotate_window(env, n);
env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) |
(windowbase << PS_OWB_SHIFT) | PS_EXCM;
env->sregs[EPC1] = env->pc = pc;
if (windowstart & windowstart_bit(m + 1, env)) {
- HELPER(exception)(EXC_WINDOW_OVERFLOW4);
+ HELPER(exception)(env, EXC_WINDOW_OVERFLOW4);
} else if (windowstart & windowstart_bit(m + 2, env)) {
- HELPER(exception)(EXC_WINDOW_OVERFLOW8);
+ HELPER(exception)(env, EXC_WINDOW_OVERFLOW8);
} else {
- HELPER(exception)(EXC_WINDOW_OVERFLOW12);
+ HELPER(exception)(env, EXC_WINDOW_OVERFLOW12);
}
}
-uint32_t HELPER(retw)(uint32_t pc)
+uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
{
int n = (env->regs[0] >> 30) & 0x3;
int m = 0;
@@ -319,13 +312,13 @@ uint32_t HELPER(retw)(uint32_t pc)
qemu_log("Illegal retw instruction(pc = %08x), "
"PS = %08x, m = %d, n = %d\n",
pc, env->sregs[PS], m, n);
- HELPER(exception_cause)(pc, ILLEGAL_INSTRUCTION_CAUSE);
+ HELPER(exception_cause)(env, pc, ILLEGAL_INSTRUCTION_CAUSE);
} else {
int owb = windowbase;
ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff);
- rotate_window(-n);
+ rotate_window(env, -n);
if (windowstart & windowstart_bit(env->sregs[WINDOW_BASE], env)) {
env->sregs[WINDOW_START] &= ~windowstart_bit(owb, env);
} else {
@@ -335,38 +328,38 @@ uint32_t HELPER(retw)(uint32_t pc)
env->sregs[EPC1] = env->pc = pc;
if (n == 1) {
- HELPER(exception)(EXC_WINDOW_UNDERFLOW4);
+ HELPER(exception)(env, EXC_WINDOW_UNDERFLOW4);
} else if (n == 2) {
- HELPER(exception)(EXC_WINDOW_UNDERFLOW8);
+ HELPER(exception)(env, EXC_WINDOW_UNDERFLOW8);
} else if (n == 3) {
- HELPER(exception)(EXC_WINDOW_UNDERFLOW12);
+ HELPER(exception)(env, EXC_WINDOW_UNDERFLOW12);
}
}
}
return ret_pc;
}
-void HELPER(rotw)(uint32_t imm4)
+void HELPER(rotw)(CPUXtensaState *env, uint32_t imm4)
{
- rotate_window(imm4);
+ rotate_window(env, imm4);
}
-void HELPER(restore_owb)(void)
+void HELPER(restore_owb)(CPUXtensaState *env)
{
- rotate_window_abs((env->sregs[PS] & PS_OWB) >> PS_OWB_SHIFT);
+ rotate_window_abs(env, (env->sregs[PS] & PS_OWB) >> PS_OWB_SHIFT);
}
-void HELPER(movsp)(uint32_t pc)
+void HELPER(movsp)(CPUXtensaState *env, uint32_t pc)
{
if ((env->sregs[WINDOW_START] &
(windowstart_bit(env->sregs[WINDOW_BASE] - 3, env) |
windowstart_bit(env->sregs[WINDOW_BASE] - 2, env) |
windowstart_bit(env->sregs[WINDOW_BASE] - 1, env))) == 0) {
- HELPER(exception_cause)(pc, ALLOCA_CAUSE);
+ HELPER(exception_cause)(env, pc, ALLOCA_CAUSE);
}
}
-void HELPER(wsr_lbeg)(uint32_t v)
+void HELPER(wsr_lbeg)(CPUXtensaState *env, uint32_t v)
{
if (env->sregs[LBEG] != v) {
tb_invalidate_virtual_addr(env, env->sregs[LEND] - 1);
@@ -374,7 +367,7 @@ void HELPER(wsr_lbeg)(uint32_t v)
}
}
-void HELPER(wsr_lend)(uint32_t v)
+void HELPER(wsr_lend)(CPUXtensaState *env, uint32_t v)
{
if (env->sregs[LEND] != v) {
tb_invalidate_virtual_addr(env, env->sregs[LEND] - 1);
@@ -383,12 +376,12 @@ void HELPER(wsr_lend)(uint32_t v)
}
}
-void HELPER(dump_state)(void)
+void HELPER(dump_state)(CPUXtensaState *env)
{
cpu_dump_state(env, stderr, fprintf, 0);
}
-void HELPER(waiti)(uint32_t pc, uint32_t intlevel)
+void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, uint32_t intlevel)
{
env->pc = pc;
env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) |
@@ -404,15 +397,15 @@ void HELPER(waiti)(uint32_t pc, uint32_t intlevel)
if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
xtensa_rearm_ccompare_timer(env);
}
- HELPER(exception)(EXCP_HLT);
+ HELPER(exception)(env, EXCP_HLT);
}
-void HELPER(timer_irq)(uint32_t id, uint32_t active)
+void HELPER(timer_irq)(CPUXtensaState *env, uint32_t id, uint32_t active)
{
xtensa_timer_irq(env, id, active);
}
-void HELPER(advance_ccount)(uint32_t d)
+void HELPER(advance_ccount)(CPUXtensaState *env, uint32_t d)
{
xtensa_advance_ccount(env, d);
}
@@ -422,7 +415,7 @@ void HELPER(check_interrupts)(CPUXtensaState *env)
check_interrupts(env);
}
-void HELPER(wsr_rasid)(uint32_t v)
+void HELPER(wsr_rasid)(CPUXtensaState *env, uint32_t v)
{
v = (v & 0xffffff00) | 0x1;
if (v != env->sregs[RASID]) {
@@ -574,7 +567,7 @@ void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb,
* Split TLB address into TLB way, entry index and VPN (with index).
* See ISA, 4.6.5.5 - 4.6.5.8 for the TLB addressing format
*/
-static void split_tlb_entry_spec(uint32_t v, bool dtlb,
+static void split_tlb_entry_spec(CPUXtensaState *env, uint32_t v, bool dtlb,
uint32_t *vpn, uint32_t *wi, uint32_t *ei)
{
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
@@ -587,41 +580,42 @@ static void split_tlb_entry_spec(uint32_t v, bool dtlb,
}
}
-static xtensa_tlb_entry *get_tlb_entry(uint32_t v, bool dtlb, uint32_t *pwi)
+static xtensa_tlb_entry *get_tlb_entry(CPUXtensaState *env,
+ uint32_t v, bool dtlb, uint32_t *pwi)
{
uint32_t vpn;
uint32_t wi;
uint32_t ei;
- split_tlb_entry_spec(v, dtlb, &vpn, &wi, &ei);
+ split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
if (pwi) {
*pwi = wi;
}
return xtensa_tlb_get_entry(env, dtlb, wi, ei);
}
-uint32_t HELPER(rtlb0)(uint32_t v, uint32_t dtlb)
+uint32_t HELPER(rtlb0)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
{
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
uint32_t wi;
- const xtensa_tlb_entry *entry = get_tlb_entry(v, dtlb, &wi);
+ const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;
} else {
return v & REGION_PAGE_MASK;
}
}
-uint32_t HELPER(rtlb1)(uint32_t v, uint32_t dtlb)
+uint32_t HELPER(rtlb1)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
{
- const xtensa_tlb_entry *entry = get_tlb_entry(v, dtlb, NULL);
+ const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, NULL);
return entry->paddr | entry->attr;
}
-void HELPER(itlb)(uint32_t v, uint32_t dtlb)
+void HELPER(itlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
{
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
uint32_t wi;
- xtensa_tlb_entry *entry = get_tlb_entry(v, dtlb, &wi);
+ xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
if (entry->variable && entry->asid) {
tlb_flush_page(env, entry->vaddr);
entry->asid = 0;
@@ -629,7 +623,7 @@ void HELPER(itlb)(uint32_t v, uint32_t dtlb)
}
}
-uint32_t HELPER(ptlb)(uint32_t v, uint32_t dtlb)
+uint32_t HELPER(ptlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
{
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
uint32_t wi;
@@ -646,7 +640,7 @@ uint32_t HELPER(ptlb)(uint32_t v, uint32_t dtlb)
case INST_TLB_MULTI_HIT_CAUSE:
case LOAD_STORE_TLB_MULTI_HIT_CAUSE:
- HELPER(exception_cause_vaddr)(env->pc, res, v);
+ HELPER(exception_cause_vaddr)(env, env->pc, res, v);
break;
}
return 0;
@@ -655,6 +649,16 @@ uint32_t HELPER(ptlb)(uint32_t v, uint32_t dtlb)
}
}
+void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
+ xtensa_tlb_entry *entry, bool dtlb,
+ unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte)
+{
+ entry->vaddr = vpn;
+ entry->paddr = pte & xtensa_tlb_get_addr_mask(env, dtlb, wi);
+ entry->asid = (env->sregs[RASID] >> ((pte >> 1) & 0x18)) & 0xff;
+ entry->attr = pte & 0xf;
+}
+
void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte)
{
@@ -665,10 +669,8 @@ void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
if (entry->asid) {
tlb_flush_page(env, entry->vaddr);
}
- entry->vaddr = vpn;
- entry->paddr = pte & xtensa_tlb_get_addr_mask(env, dtlb, wi);
- entry->asid = (env->sregs[RASID] >> ((pte >> 1) & 0x18)) & 0xff;
- entry->attr = pte & 0xf;
+ xtensa_tlb_set_entry_mmu(env, entry, dtlb, wi, ei, vpn, pte);
+ tlb_flush_page(env, entry->vaddr);
} else {
qemu_log("%s %d, %d, %d trying to set immutable entry\n",
__func__, dtlb, wi, ei);
@@ -683,17 +685,17 @@ void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
}
}
-void HELPER(wtlb)(uint32_t p, uint32_t v, uint32_t dtlb)
+void HELPER(wtlb)(CPUXtensaState *env, uint32_t p, uint32_t v, uint32_t dtlb)
{
uint32_t vpn;
uint32_t wi;
uint32_t ei;
- split_tlb_entry_spec(v, dtlb, &vpn, &wi, &ei);
+ split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
}
-void HELPER(wsr_ibreakenable)(uint32_t v)
+void HELPER(wsr_ibreakenable)(CPUXtensaState *env, uint32_t v)
{
uint32_t change = v ^ env->sregs[IBREAKENABLE];
unsigned i;
@@ -706,7 +708,7 @@ void HELPER(wsr_ibreakenable)(uint32_t v)
env->sregs[IBREAKENABLE] = v & ((1 << env->config->nibreak) - 1);
}
-void HELPER(wsr_ibreaka)(uint32_t i, uint32_t v)
+void HELPER(wsr_ibreaka)(CPUXtensaState *env, uint32_t i, uint32_t v)
{
if (env->sregs[IBREAKENABLE] & (1 << i) && env->sregs[IBREAKA + i] != v) {
tb_invalidate_virtual_addr(env, env->sregs[IBREAKA + i]);
@@ -715,7 +717,8 @@ void HELPER(wsr_ibreaka)(uint32_t i, uint32_t v)
env->sregs[IBREAKA + i] = v;
}
-static void set_dbreak(unsigned i, uint32_t dbreaka, uint32_t dbreakc)
+static void set_dbreak(CPUXtensaState *env, unsigned i, uint32_t dbreaka,
+ uint32_t dbreakc)
{
int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
uint32_t mask = dbreakc | ~DBREAKC_MASK;
@@ -743,22 +746,22 @@ static void set_dbreak(unsigned i, uint32_t dbreaka, uint32_t dbreakc)
}
}
-void HELPER(wsr_dbreaka)(uint32_t i, uint32_t v)
+void HELPER(wsr_dbreaka)(CPUXtensaState *env, uint32_t i, uint32_t v)
{
uint32_t dbreakc = env->sregs[DBREAKC + i];
if ((dbreakc & DBREAKC_SB_LB) &&
env->sregs[DBREAKA + i] != v) {
- set_dbreak(i, v, dbreakc);
+ set_dbreak(env, i, v, dbreakc);
}
env->sregs[DBREAKA + i] = v;
}
-void HELPER(wsr_dbreakc)(uint32_t i, uint32_t v)
+void HELPER(wsr_dbreakc)(CPUXtensaState *env, uint32_t i, uint32_t v)
{
if ((env->sregs[DBREAKC + i] ^ v) & (DBREAKC_SB_LB | DBREAKC_MASK)) {
if (v & DBREAKC_SB_LB) {
- set_dbreak(i, env->sregs[DBREAKA + i], v);
+ set_dbreak(env, i, env->sregs[DBREAKA + i], v);
} else {
if (env->cpu_watchpoint[i]) {
cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[i]);
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 521c0e6226..b883e6bb72 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -254,7 +254,7 @@ static void gen_advance_ccount(DisasContext *dc)
if (dc->ccount_delta > 0) {
TCGv_i32 tmp = tcg_const_i32(dc->ccount_delta);
dc->ccount_delta = 0;
- gen_helper_advance_ccount(tmp);
+ gen_helper_advance_ccount(cpu_env, tmp);
tcg_temp_free(tmp);
}
}
@@ -268,7 +268,7 @@ static void gen_exception(DisasContext *dc, int excp)
{
TCGv_i32 tmp = tcg_const_i32(excp);
gen_advance_ccount(dc);
- gen_helper_exception(tmp);
+ gen_helper_exception(cpu_env, tmp);
tcg_temp_free(tmp);
}
@@ -277,7 +277,7 @@ static void gen_exception_cause(DisasContext *dc, uint32_t cause)
TCGv_i32 tpc = tcg_const_i32(dc->pc);
TCGv_i32 tcause = tcg_const_i32(cause);
gen_advance_ccount(dc);
- gen_helper_exception_cause(tpc, tcause);
+ gen_helper_exception_cause(cpu_env, tpc, tcause);
tcg_temp_free(tpc);
tcg_temp_free(tcause);
if (cause == ILLEGAL_INSTRUCTION_CAUSE ||
@@ -292,7 +292,7 @@ static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
TCGv_i32 tpc = tcg_const_i32(dc->pc);
TCGv_i32 tcause = tcg_const_i32(cause);
gen_advance_ccount(dc);
- gen_helper_exception_cause_vaddr(tpc, tcause, vaddr);
+ gen_helper_exception_cause_vaddr(cpu_env, tpc, tcause, vaddr);
tcg_temp_free(tpc);
tcg_temp_free(tcause);
}
@@ -302,7 +302,7 @@ static void gen_debug_exception(DisasContext *dc, uint32_t cause)
TCGv_i32 tpc = tcg_const_i32(dc->pc);
TCGv_i32 tcause = tcg_const_i32(cause);
gen_advance_ccount(dc);
- gen_helper_debug_exception(tpc, tcause);
+ gen_helper_debug_exception(cpu_env, tpc, tcause);
tcg_temp_free(tpc);
tcg_temp_free(tcause);
if (cause & (DEBUGCAUSE_IB | DEBUGCAUSE_BI | DEBUGCAUSE_BN)) {
@@ -388,6 +388,7 @@ static bool gen_check_loop_end(DisasContext *dc, int slot)
dc->next_pc == dc->lend) {
int label = gen_new_label();
+ gen_advance_ccount(dc);
tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_SR[LCOUNT], 0, label);
tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_SR[LCOUNT], 1);
gen_jumpi(dc, dc->lbeg, slot);
@@ -410,6 +411,7 @@ static void gen_brcond(DisasContext *dc, TCGCond cond,
{
int label = gen_new_label();
+ gen_advance_ccount(dc);
tcg_gen_brcond_i32(cond, t0, t1, label);
gen_jumpi_check_loop_end(dc, 0);
gen_set_label(label);
@@ -458,13 +460,13 @@ static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
static void gen_wsr_lbeg(DisasContext *dc, uint32_t sr, TCGv_i32 s)
{
- gen_helper_wsr_lbeg(s);
+ gen_helper_wsr_lbeg(cpu_env, s);
gen_jumpi_check_loop_end(dc, 0);
}
static void gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 s)
{
- gen_helper_wsr_lend(s);
+ gen_helper_wsr_lend(cpu_env, s);
gen_jumpi_check_loop_end(dc, 0);
}
@@ -497,7 +499,7 @@ static void gen_wsr_acchi(DisasContext *dc, uint32_t sr, TCGv_i32 s)
static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
{
- gen_helper_wsr_windowbase(v);
+ gen_helper_wsr_windowbase(cpu_env, v);
reset_used_window(dc);
}
@@ -514,7 +516,7 @@ static void gen_wsr_ptevaddr(DisasContext *dc, uint32_t sr, TCGv_i32 v)
static void gen_wsr_rasid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
{
- gen_helper_wsr_rasid(v);
+ gen_helper_wsr_rasid(cpu_env, v);
/* This can change tb->flags, so exit tb */
gen_jumpi_check_loop_end(dc, -1);
}
@@ -526,7 +528,7 @@ static void gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v)
static void gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
{
- gen_helper_wsr_ibreakenable(v);
+ gen_helper_wsr_ibreakenable(cpu_env, v);
gen_jumpi_check_loop_end(dc, 0);
}
@@ -536,7 +538,7 @@ static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
if (id < dc->config->nibreak) {
TCGv_i32 tmp = tcg_const_i32(id);
- gen_helper_wsr_ibreaka(tmp, v);
+ gen_helper_wsr_ibreaka(cpu_env, tmp, v);
tcg_temp_free(tmp);
gen_jumpi_check_loop_end(dc, 0);
}
@@ -548,7 +550,7 @@ static void gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
if (id < dc->config->ndbreak) {
TCGv_i32 tmp = tcg_const_i32(id);
- gen_helper_wsr_dbreaka(tmp, v);
+ gen_helper_wsr_dbreaka(cpu_env, tmp, v);
tcg_temp_free(tmp);
}
}
@@ -559,7 +561,7 @@ static void gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v)
if (id < dc->config->ndbreak) {
TCGv_i32 tmp = tcg_const_i32(id);
- gen_helper_wsr_dbreakc(tmp, v);
+ gen_helper_wsr_dbreakc(cpu_env, tmp, v);
tcg_temp_free(tmp);
}
}
@@ -712,7 +714,7 @@ static void gen_waiti(DisasContext *dc, uint32_t imm4)
TCGv_i32 pc = tcg_const_i32(dc->next_pc);
TCGv_i32 intlevel = tcg_const_i32(imm4);
gen_advance_ccount(dc);
- gen_helper_waiti(pc, intlevel);
+ gen_helper_waiti(cpu_env, pc, intlevel);
tcg_temp_free(pc);
tcg_temp_free(intlevel);
}
@@ -729,7 +731,7 @@ static void gen_window_check1(DisasContext *dc, unsigned r1)
dc->used_window = r1 / 4;
gen_advance_ccount(dc);
- gen_helper_window_check(pc, w);
+ gen_helper_window_check(cpu_env, pc, w);
tcg_temp_free(w);
tcg_temp_free(pc);
@@ -849,8 +851,8 @@ static void disas_xtensa_insn(DisasContext *dc)
#define RSR_SR (b1)
- uint8_t b0 = ldub_code(dc->pc);
- uint8_t b1 = ldub_code(dc->pc + 1);
+ uint8_t b0 = cpu_ldub_code(cpu_single_env, dc->pc);
+ uint8_t b1 = cpu_ldub_code(cpu_single_env, dc->pc + 1);
uint8_t b2 = 0;
static const uint32_t B4CONST[] = {
@@ -866,7 +868,7 @@ static void disas_xtensa_insn(DisasContext *dc)
HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
} else {
dc->next_pc = dc->pc + 3;
- b2 = ldub_code(dc->pc + 2);
+ b2 = cpu_ldub_code(cpu_single_env, dc->pc + 2);
}
switch (OP0) {
@@ -903,7 +905,7 @@ static void disas_xtensa_insn(DisasContext *dc)
{
TCGv_i32 tmp = tcg_const_i32(dc->pc);
gen_advance_ccount(dc);
- gen_helper_retw(tmp, tmp);
+ gen_helper_retw(tmp, cpu_env, tmp);
gen_jump(dc, tmp);
tcg_temp_free(tmp);
}
@@ -951,7 +953,7 @@ static void disas_xtensa_insn(DisasContext *dc)
{
TCGv_i32 pc = tcg_const_i32(dc->pc);
gen_advance_ccount(dc);
- gen_helper_movsp(pc);
+ gen_helper_movsp(cpu_env, pc);
tcg_gen_mov_i32(cpu_R[RRR_T], cpu_R[RRR_S]);
tcg_temp_free(pc);
}
@@ -1031,7 +1033,7 @@ static void disas_xtensa_insn(DisasContext *dc)
cpu_SR[WINDOW_START], tmp);
}
- gen_helper_restore_owb();
+ gen_helper_restore_owb(cpu_env);
gen_helper_check_interrupts(cpu_env);
gen_jump(dc, cpu_SR[EPC1]);
@@ -1219,7 +1221,7 @@ static void disas_xtensa_insn(DisasContext *dc)
{
TCGv_i32 tmp = tcg_const_i32(
RRR_T | ((RRR_T & 8) ? 0xfffffff0 : 0));
- gen_helper_rotw(tmp);
+ gen_helper_rotw(cpu_env, tmp);
tcg_temp_free(tmp);
reset_used_window(dc);
}
@@ -1255,28 +1257,32 @@ static void disas_xtensa_insn(DisasContext *dc)
switch (RRR_R & 7) {
case 3: /*RITLB0*/ /*RDTLB0*/
- gen_helper_rtlb0(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+ gen_helper_rtlb0(cpu_R[RRR_T],
+ cpu_env, cpu_R[RRR_S], dtlb);
break;
case 4: /*IITLB*/ /*IDTLB*/
- gen_helper_itlb(cpu_R[RRR_S], dtlb);
+ gen_helper_itlb(cpu_env, cpu_R[RRR_S], dtlb);
/* This could change memory mapping, so exit tb */
gen_jumpi_check_loop_end(dc, -1);
break;
case 5: /*PITLB*/ /*PDTLB*/
tcg_gen_movi_i32(cpu_pc, dc->pc);
- gen_helper_ptlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+ gen_helper_ptlb(cpu_R[RRR_T],
+ cpu_env, cpu_R[RRR_S], dtlb);
break;
case 6: /*WITLB*/ /*WDTLB*/
- gen_helper_wtlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+ gen_helper_wtlb(
+ cpu_env, cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
/* This could change memory mapping, so exit tb */
gen_jumpi_check_loop_end(dc, -1);
break;
case 7: /*RITLB1*/ /*RDTLB1*/
- gen_helper_rtlb1(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+ gen_helper_rtlb1(cpu_R[RRR_T],
+ cpu_env, cpu_R[RRR_S], dtlb);
break;
default:
@@ -2244,7 +2250,7 @@ static void disas_xtensa_insn(DisasContext *dc)
TCGv_i32 s = tcg_const_i32(BRI12_S);
TCGv_i32 imm = tcg_const_i32(BRI12_IMM12);
gen_advance_ccount(dc);
- gen_helper_entry(pc, s, imm);
+ gen_helper_entry(cpu_env, pc, s, imm);
tcg_temp_free(imm);
tcg_temp_free(s);
tcg_temp_free(pc);
@@ -2278,7 +2284,7 @@ static void disas_xtensa_insn(DisasContext *dc)
tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[RRI8_S], 1);
tcg_gen_movi_i32(cpu_SR[LBEG], dc->next_pc);
- gen_helper_wsr_lend(tmp);
+ gen_helper_wsr_lend(cpu_env, tmp);
tcg_temp_free(tmp);
if (BRI8_R > 8) {
@@ -2447,7 +2453,7 @@ static void disas_xtensa_insn(DisasContext *dc)
{
TCGv_i32 tmp = tcg_const_i32(dc->pc);
gen_advance_ccount(dc);
- gen_helper_retw(tmp, tmp);
+ gen_helper_retw(tmp, cpu_env, tmp);
gen_jump(dc, tmp);
tcg_temp_free(tmp);
}
diff --git a/xtensa-semi.c b/target-xtensa/xtensa-semi.c
index b7c8c34564..1c8a19ed56 100644
--- a/xtensa-semi.c
+++ b/target-xtensa/xtensa-semi.c
@@ -30,7 +30,6 @@
#include <string.h>
#include <stddef.h>
#include "cpu.h"
-#include "dyngen-exec.h"
#include "helper.h"
#include "qemu-log.h"
diff --git a/tests/Makefile b/tests/Makefile
index ab7f667009..d66ab196a7 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -13,6 +13,7 @@ check-unit-y += tests/test-qmp-commands$(EXESUF)
check-unit-y += tests/test-string-input-visitor$(EXESUF)
check-unit-y += tests/test-string-output-visitor$(EXESUF)
check-unit-y += tests/test-coroutine$(EXESUF)
+check-unit-y += tests/test-visitor-serialization$(EXESUF)
check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
@@ -31,13 +32,12 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
tests/test-coroutine.o tests/test-string-output-visitor.o \
tests/test-string-input-visitor.o tests/test-qmp-output-visitor.o \
tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
- tests/test-qmp-commands.o
+ tests/test-qmp-commands.o tests/test-visitor-serialization.o
test-qapi-obj-y = $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y)
test-qapi-obj-y += tests/test-qapi-visit.o tests/test-qapi-types.o
test-qapi-obj-y += module.o
-$(test-obj-y): $(GENERATED_HEADERS)
$(test-obj-y): QEMU_INCLUDES += -Itests
tests/check-qint$(EXESUF): tests/check-qint.o qint.o $(tools-obj-y)
@@ -65,6 +65,7 @@ tests/test-qmp-output-visitor$(EXESUF): tests/test-qmp-output-visitor.o $(test-q
tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qapi-obj-y)
tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y)
tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
+tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
tests/rtc-test$(EXESUF): tests/rtc-test.o $(trace-obj-y)
tests/m48t59-test$(EXESUF): tests/m48t59-test.o $(trace-obj-y)
diff --git a/tests/tcg/xtensa/test_mmu.S b/tests/tcg/xtensa/test_mmu.S
index 52d5774212..5d87fbb703 100644
--- a/tests/tcg/xtensa/test_mmu.S
+++ b/tests/tcg/xtensa/test_mmu.S
@@ -293,26 +293,219 @@ test store_prohibited
assert eq, a2, a3
test_end
-test dtlb_autoload
- set_vector kernel, 0
-
- movi a2, 0xd4000000
+/* Set up page table entry vaddr->paddr, ring=pte_ring, attr=pte_attr
+ * and DTLB way 7 to cover this PTE, ring=pt_ring, attr=pt_attr
+ */
+.macro pt_setup pt_ring, pt_attr, pte_ring, vaddr, paddr, pte_attr
+ movi a2, 0x80000000
wsr a2, ptevaddr
- movi a3, 0x00001013
- s32i a3, a2, 4
+
+ movi a3, 0x80000007 | (((\vaddr) >> 10) & 0xfffff000) /* way 7 */
+ movi a4, 0x04000003 | ((\pt_ring) << 4) /* PADDR 64M */
+ wdtlb a4, a3
+ isync
+
+ movi a3, ((\paddr) & 0xfffff000) | ((\pte_ring) << 4) | (\pte_attr)
+ movi a1, ((\vaddr) >> 12) << 2
+ add a2, a1, a2
+ s32i a3, a2, 0
+
+ movi a3, 0x80000007 | (((\vaddr) >> 10) & 0xfffff000) /* way 7 */
+ movi a4, 0x04000000 | ((\pt_ring) << 4) | (\pt_attr) /* PADDR 64M */
+ wdtlb a4, a3
+ isync
+
+ movi a3, (\vaddr)
+.endm
+
+/* out: PS.RING=ring, PS.EXCM=excm, a3=vaddr */
+.macro go_ring ring, excm, vaddr
+ movi a3, 10f
+ pitlb a3, a3
+ ritlb1 a2, a3
+ movi a1, 0x10
+ or a2, a2, a1
+ movi a1, 0x000ff000
+ and a3, a3, a1
+ movi a1, 4
+ or a3, a3, a1
+ witlb a2, a3
+ movi a3, 10f
+ movi a1, 0x000fffff
+ and a1, a3, a1
+
+ movi a2, 0
+ wsr a2, excvaddr
+
+ movi a3, \vaddr
+ movi a2, 0x4000f | ((\ring) << 6) | ((\excm) << 4)
+ jx a1
+10:
+ wsr a2, ps
+ isync
+.endm
+
+/* in: a3 -- virtual address to test */
+.macro assert_auto_tlb
+ movi a2, 0x4000f
+ wsr a2, ps
+ isync
+ pdtlb a2, a3
+ movi a1, 0xfffff01f
+ and a2, a2, a1
+ movi a1, 0xfffff000
+ and a1, a1, a3
+ xor a1, a1, a2
+ assert gei, a1, 0x10
+ movi a2, 0x14
+ assert lt, a1, a2
+.endm
+
+/* in: a3 -- virtual address to test */
+.macro assert_no_auto_tlb
+ movi a2, 0x4000f
+ wsr a2, ps
+ isync
pdtlb a2, a3
movi a1, 0x10
and a1, a1, a2
assert eqi, a1, 0
- l8ui a1, a3, 0
- pdtlb a2, a3
- movi a1, 0xfffff010
- and a1, a1, a2
- movi a3, 0x00001010
- assert eq, a1, a3
- movi a1, 0xf
+.endm
+
+.macro assert_sr sr, v
+ rsr a2, \sr
+ movi a1, (\v)
+ assert eq, a1, a2
+.endm
+
+.macro assert_epc1_1m vaddr
+ movi a2, (\vaddr)
+ movi a1, 0xfffff
and a1, a1, a2
- assert lti, a1, 4
+ rsr a2, epc1
+ assert eq, a1, a2
+.endm
+
+test dtlb_autoload
+ set_vector kernel, 0
+
+ pt_setup 0, 3, 1, 0x1000, 0x1000, 3
+ assert_no_auto_tlb
+
+ l8ui a1, a3, 0
+
+ rsr a2, excvaddr
+ assert eq, a2, a3
+
+ assert_auto_tlb
+test_end
+
+test autoload_load_store_privilege
+ set_vector kernel, 0
+ set_vector double, 2f
+
+ pt_setup 0, 3, 0, 0x2000, 0x2000, 3
+ movi a3, 0x2004
+ assert_no_auto_tlb
+
+ movi a2, 0x4005f /* ring 1 + excm => cring == 0 */
+ wsr a2, ps
+ isync
+1:
+ l32e a2, a3, -4 /* ring used */
+ test_fail
+2:
+ rsr a2, excvaddr
+ addi a1, a3, -4
+ assert eq, a1, a2
+
+ assert_auto_tlb
+ assert_sr depc, 1b
+ assert_sr exccause, 26
+test_end
+
+test autoload_pte_load_prohibited
+ set_vector kernel, 2f
+
+ pt_setup 0, 3, 0, 0x3000, 0, 0xc
+ assert_no_auto_tlb
+1:
+ l32i a2, a3, 0
+ test_fail
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+
+ assert_auto_tlb
+ assert_sr epc1, 1b
+ assert_sr exccause, 28
+test_end
+
+test autoload_pt_load_prohibited
+ set_vector kernel, 2f
+
+ pt_setup 0, 0xc, 0, 0x4000, 0x4000, 3
+ assert_no_auto_tlb
+1:
+ l32i a2, a3, 0
+ test_fail
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+
+ assert_no_auto_tlb
+ assert_sr epc1, 1b
+ assert_sr exccause, 24
+test_end
+
+test autoload_pt_privilege
+ set_vector kernel, 2f
+ pt_setup 0, 3, 1, 0x5000, 0, 3
+ go_ring 1, 0, 0x5001
+
+ l8ui a2, a3, 0
+1:
+ syscall
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+
+ assert_auto_tlb
+ assert_epc1_1m 1b
+ assert_sr exccause, 1
+test_end
+
+test autoload_pte_privilege
+ set_vector kernel, 2f
+ pt_setup 0, 3, 0, 0x6000, 0, 3
+ go_ring 1, 0, 0x6001
+1:
+ l8ui a2, a3, 0
+ syscall
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+
+ assert_auto_tlb
+ assert_epc1_1m 1b
+ assert_sr exccause, 26
+test_end
+
+test autoload_3_level_pt
+ set_vector kernel, 2f
+ pt_setup 1, 3, 1, 0x00400000, 0, 3
+ pt_setup 1, 3, 1, 0x80001000, 0x2000000, 3
+ go_ring 1, 0, 0x00400001
+1:
+ l8ui a2, a3, 0
+ syscall
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+
+ assert_no_auto_tlb
+ assert_epc1_1m 1b
+ assert_sr exccause, 24
test_end
test_suite_end
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index 22909b84ef..608f14a5de 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -84,7 +84,7 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
str = string_output_get_string(data->sov);
g_assert(str != NULL);
- g_assert_cmpstr(str, ==, "3.14");
+ g_assert_cmpstr(str, ==, "3.140000");
g_free(str);
}
diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
new file mode 100644
index 0000000000..b8ad16fc9e
--- /dev/null
+++ b/tests/test-visitor-serialization.c
@@ -0,0 +1,784 @@
+/*
+ * Unit-tests for visitor-based serialization
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ * Michael Roth <mdroth@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <float.h>
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+#include "qapi/qmp-input-visitor.h"
+#include "qapi/qmp-output-visitor.h"
+#include "qapi/string-input-visitor.h"
+#include "qapi/string-output-visitor.h"
+
+typedef struct PrimitiveType {
+ union {
+ const char *string;
+ bool boolean;
+ double number;
+ int64_t integer;
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ uint64_t u64;
+ int8_t s8;
+ int16_t s16;
+ int32_t s32;
+ int64_t s64;
+ intmax_t max;
+ } value;
+ enum {
+ PTYPE_STRING = 0,
+ PTYPE_BOOLEAN,
+ PTYPE_NUMBER,
+ PTYPE_INTEGER,
+ PTYPE_U8,
+ PTYPE_U16,
+ PTYPE_U32,
+ PTYPE_U64,
+ PTYPE_S8,
+ PTYPE_S16,
+ PTYPE_S32,
+ PTYPE_S64,
+ PTYPE_EOL,
+ } type;
+ const char *description;
+} PrimitiveType;
+
+/* test helpers */
+
+static void visit_primitive_type(Visitor *v, void **native, Error **errp)
+{
+ PrimitiveType *pt = *native;
+ switch(pt->type) {
+ case PTYPE_STRING:
+ visit_type_str(v, (char **)&pt->value.string, NULL, errp);
+ break;
+ case PTYPE_BOOLEAN:
+ visit_type_bool(v, &pt->value.boolean, NULL, errp);
+ break;
+ case PTYPE_NUMBER:
+ visit_type_number(v, &pt->value.number, NULL, errp);
+ break;
+ case PTYPE_INTEGER:
+ visit_type_int(v, &pt->value.integer, NULL, errp);
+ break;
+ case PTYPE_U8:
+ visit_type_uint8(v, &pt->value.u8, NULL, errp);
+ break;
+ case PTYPE_U16:
+ visit_type_uint16(v, &pt->value.u16, NULL, errp);
+ break;
+ case PTYPE_U32:
+ visit_type_uint32(v, &pt->value.u32, NULL, errp);
+ break;
+ case PTYPE_U64:
+ visit_type_uint64(v, &pt->value.u64, NULL, errp);
+ break;
+ case PTYPE_S8:
+ visit_type_int8(v, &pt->value.s8, NULL, errp);
+ break;
+ case PTYPE_S16:
+ visit_type_int16(v, &pt->value.s16, NULL, errp);
+ break;
+ case PTYPE_S32:
+ visit_type_int32(v, &pt->value.s32, NULL, errp);
+ break;
+ case PTYPE_S64:
+ visit_type_int64(v, &pt->value.s64, NULL, errp);
+ break;
+ case PTYPE_EOL:
+ g_assert(false);
+ }
+}
+
+typedef struct TestStruct
+{
+ int64_t integer;
+ bool boolean;
+ char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+ const char *name, Error **errp)
+{
+ visit_start_struct(v, (void **)obj, NULL, name, sizeof(TestStruct), errp);
+
+ visit_type_int(v, &(*obj)->integer, "integer", errp);
+ visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+ visit_type_str(v, &(*obj)->string, "string", errp);
+
+ visit_end_struct(v, errp);
+}
+
+static TestStruct *struct_create(void)
+{
+ TestStruct *ts = g_malloc0(sizeof(*ts));
+ ts->integer = -42;
+ ts->boolean = true;
+ ts->string = strdup("test string");
+ return ts;
+}
+
+static void struct_compare(TestStruct *ts1, TestStruct *ts2)
+{
+ g_assert(ts1);
+ g_assert(ts2);
+ g_assert_cmpint(ts1->integer, ==, ts2->integer);
+ g_assert(ts1->boolean == ts2->boolean);
+ g_assert_cmpstr(ts1->string, ==, ts2->string);
+}
+
+static void struct_cleanup(TestStruct *ts)
+{
+ g_free(ts->string);
+ g_free(ts);
+}
+
+static void visit_struct(Visitor *v, void **native, Error **errp)
+{
+ visit_type_TestStruct(v, (TestStruct **)native, NULL, errp);
+}
+
+static UserDefNested *nested_struct_create(void)
+{
+ UserDefNested *udnp = g_malloc0(sizeof(*udnp));
+ udnp->string0 = strdup("test_string0");
+ udnp->dict1.string1 = strdup("test_string1");
+ udnp->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
+ udnp->dict1.dict2.userdef1->integer = 42;
+ udnp->dict1.dict2.userdef1->string = strdup("test_string");
+ udnp->dict1.dict2.string2 = strdup("test_string2");
+ udnp->dict1.has_dict3 = true;
+ udnp->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
+ udnp->dict1.dict3.userdef2->integer = 43;
+ udnp->dict1.dict3.userdef2->string = strdup("test_string");
+ udnp->dict1.dict3.string3 = strdup("test_string3");
+ return udnp;
+}
+
+static void nested_struct_compare(UserDefNested *udnp1, UserDefNested *udnp2)
+{
+ g_assert(udnp1);
+ g_assert(udnp2);
+ g_assert_cmpstr(udnp1->string0, ==, udnp2->string0);
+ g_assert_cmpstr(udnp1->dict1.string1, ==, udnp2->dict1.string1);
+ g_assert_cmpint(udnp1->dict1.dict2.userdef1->integer, ==,
+ udnp2->dict1.dict2.userdef1->integer);
+ g_assert_cmpstr(udnp1->dict1.dict2.userdef1->string, ==,
+ udnp2->dict1.dict2.userdef1->string);
+ g_assert_cmpstr(udnp1->dict1.dict2.string2, ==, udnp2->dict1.dict2.string2);
+ g_assert(udnp1->dict1.has_dict3 == udnp2->dict1.has_dict3);
+ g_assert_cmpint(udnp1->dict1.dict3.userdef2->integer, ==,
+ udnp2->dict1.dict3.userdef2->integer);
+ g_assert_cmpstr(udnp1->dict1.dict3.userdef2->string, ==,
+ udnp2->dict1.dict3.userdef2->string);
+ g_assert_cmpstr(udnp1->dict1.dict3.string3, ==, udnp2->dict1.dict3.string3);
+}
+
+static void nested_struct_cleanup(UserDefNested *udnp)
+{
+ qapi_free_UserDefNested(udnp);
+}
+
+static void visit_nested_struct(Visitor *v, void **native, Error **errp)
+{
+ visit_type_UserDefNested(v, (UserDefNested **)native, NULL, errp);
+}
+
+static void visit_nested_struct_list(Visitor *v, void **native, Error **errp)
+{
+ visit_type_UserDefNestedList(v, (UserDefNestedList **)native, NULL, errp);
+}
+
+/* test cases */
+
+typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
+
+typedef enum VisitorCapabilities {
+ VCAP_PRIMITIVES = 1,
+ VCAP_STRUCTURES = 2,
+ VCAP_LISTS = 4,
+} VisitorCapabilities;
+
+typedef struct SerializeOps {
+ void (*serialize)(void *native_in, void **datap,
+ VisitorFunc visit, Error **errp);
+ void (*deserialize)(void **native_out, void *datap,
+ VisitorFunc visit, Error **errp);
+ void (*cleanup)(void *datap);
+ const char *type;
+ VisitorCapabilities caps;
+} SerializeOps;
+
+typedef struct TestArgs {
+ const SerializeOps *ops;
+ void *test_data;
+} TestArgs;
+
+#define FLOAT_STRING_PRECISION 6 /* corresponding to n in %.nf formatting */
+static gsize calc_float_string_storage(double value)
+{
+ int whole_value = value;
+ gsize i = 0;
+ do {
+ i++;
+ } while (whole_value /= 10);
+ return i + 2 + FLOAT_STRING_PRECISION;
+}
+
+static void test_primitives(gconstpointer opaque)
+{
+ TestArgs *args = (TestArgs *) opaque;
+ const SerializeOps *ops = args->ops;
+ PrimitiveType *pt = args->test_data;
+ PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
+ Error *err = NULL;
+ void *serialize_data;
+ char *double1, *double2;
+
+ pt_copy->type = pt->type;
+ ops->serialize(pt, &serialize_data, visit_primitive_type, &err);
+ ops->deserialize((void **)&pt_copy, serialize_data, visit_primitive_type, &err);
+
+ g_assert(err == NULL);
+ g_assert(pt_copy != NULL);
+ if (pt->type == PTYPE_STRING) {
+ g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
+ } else if (pt->type == PTYPE_NUMBER) {
+ /* we serialize with %f for our reference visitors, so rather than fuzzy
+ * floating math to test "equality", just compare the formatted values
+ */
+ double1 = g_malloc0(calc_float_string_storage(pt->value.number));
+ double2 = g_malloc0(calc_float_string_storage(pt_copy->value.number));
+ g_assert_cmpstr(double1, ==, double2);
+ g_free(double1);
+ g_free(double2);
+ } else if (pt->type == PTYPE_BOOLEAN) {
+ g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max);
+ } else {
+ g_assert_cmpint(pt->value.max, ==, pt_copy->value.max);
+ }
+
+ ops->cleanup(serialize_data);
+ g_free(args);
+}
+
+static void test_struct(gconstpointer opaque)
+{
+ TestArgs *args = (TestArgs *) opaque;
+ const SerializeOps *ops = args->ops;
+ TestStruct *ts = struct_create();
+ TestStruct *ts_copy = NULL;
+ Error *err = NULL;
+ void *serialize_data;
+
+ ops->serialize(ts, &serialize_data, visit_struct, &err);
+ ops->deserialize((void **)&ts_copy, serialize_data, visit_struct, &err);
+
+ g_assert(err == NULL);
+ struct_compare(ts, ts_copy);
+
+ struct_cleanup(ts);
+ struct_cleanup(ts_copy);
+
+ ops->cleanup(serialize_data);
+ g_free(args);
+}
+
+static void test_nested_struct(gconstpointer opaque)
+{
+ TestArgs *args = (TestArgs *) opaque;
+ const SerializeOps *ops = args->ops;
+ UserDefNested *udnp = nested_struct_create();
+ UserDefNested *udnp_copy = NULL;
+ Error *err = NULL;
+ void *serialize_data;
+
+ ops->serialize(udnp, &serialize_data, visit_nested_struct, &err);
+ ops->deserialize((void **)&udnp_copy, serialize_data, visit_nested_struct, &err);
+
+ g_assert(err == NULL);
+ nested_struct_compare(udnp, udnp_copy);
+
+ nested_struct_cleanup(udnp);
+ nested_struct_cleanup(udnp_copy);
+
+ ops->cleanup(serialize_data);
+ g_free(args);
+}
+
+static void test_nested_struct_list(gconstpointer opaque)
+{
+ TestArgs *args = (TestArgs *) opaque;
+ const SerializeOps *ops = args->ops;
+ UserDefNestedList *listp = NULL, *tmp, *tmp_copy, *listp_copy = NULL;
+ Error *err = NULL;
+ void *serialize_data;
+ int i = 0;
+
+ for (i = 0; i < 8; i++) {
+ tmp = g_malloc0(sizeof(UserDefNestedList));
+ tmp->value = nested_struct_create();
+ tmp->next = listp;
+ listp = tmp;
+ }
+
+ ops->serialize(listp, &serialize_data, visit_nested_struct_list, &err);
+ ops->deserialize((void **)&listp_copy, serialize_data,
+ visit_nested_struct_list, &err);
+
+ g_assert(err == NULL);
+
+ tmp = listp;
+ tmp_copy = listp_copy;
+ while (listp_copy) {
+ g_assert(listp);
+ nested_struct_compare(listp->value, listp_copy->value);
+ listp = listp->next;
+ listp_copy = listp_copy->next;
+ }
+
+ qapi_free_UserDefNestedList(tmp);
+ qapi_free_UserDefNestedList(tmp_copy);
+
+ ops->cleanup(serialize_data);
+ g_free(args);
+}
+
+PrimitiveType pt_values[] = {
+ /* string tests */
+ {
+ .description = "string_empty",
+ .type = PTYPE_STRING,
+ .value.string = "",
+ },
+ {
+ .description = "string_whitespace",
+ .type = PTYPE_STRING,
+ .value.string = "a b c\td",
+ },
+ {
+ .description = "string_newlines",
+ .type = PTYPE_STRING,
+ .value.string = "a\nb\n",
+ },
+ {
+ .description = "string_commas",
+ .type = PTYPE_STRING,
+ .value.string = "a,b, c,d",
+ },
+ {
+ .description = "string_single_quoted",
+ .type = PTYPE_STRING,
+ .value.string = "'a b',cd",
+ },
+ {
+ .description = "string_double_quoted",
+ .type = PTYPE_STRING,
+ .value.string = "\"a b\",cd",
+ },
+ /* boolean tests */
+ {
+ .description = "boolean_true1",
+ .type = PTYPE_BOOLEAN,
+ .value.boolean = true,
+ },
+ {
+ .description = "boolean_true2",
+ .type = PTYPE_BOOLEAN,
+ .value.boolean = 8,
+ },
+ {
+ .description = "boolean_true3",
+ .type = PTYPE_BOOLEAN,
+ .value.boolean = -1,
+ },
+ {
+ .description = "boolean_false1",
+ .type = PTYPE_BOOLEAN,
+ .value.boolean = false,
+ },
+ {
+ .description = "boolean_false2",
+ .type = PTYPE_BOOLEAN,
+ .value.boolean = 0,
+ },
+ /* number tests (double) */
+ /* note: we format these to %.6f before comparing, since that's how
+ * we serialize them and it doesn't make sense to check precision
+ * beyond that.
+ */
+ {
+ .description = "number_sanity1",
+ .type = PTYPE_NUMBER,
+ .value.number = -1,
+ },
+ {
+ .description = "number_sanity2",
+ .type = PTYPE_NUMBER,
+ .value.number = 3.14159265,
+ },
+ {
+ .description = "number_min",
+ .type = PTYPE_NUMBER,
+ .value.number = DBL_MIN,
+ },
+ {
+ .description = "number_max",
+ .type = PTYPE_NUMBER,
+ .value.number = DBL_MAX,
+ },
+ /* integer tests (int64) */
+ {
+ .description = "integer_sanity1",
+ .type = PTYPE_INTEGER,
+ .value.integer = -1,
+ },
+ {
+ .description = "integer_sanity2",
+ .type = PTYPE_INTEGER,
+ .value.integer = INT64_MAX / 2 + 1,
+ },
+ {
+ .description = "integer_min",
+ .type = PTYPE_INTEGER,
+ .value.integer = INT64_MIN,
+ },
+ {
+ .description = "integer_max",
+ .type = PTYPE_INTEGER,
+ .value.integer = INT64_MAX,
+ },
+ /* uint8 tests */
+ {
+ .description = "uint8_sanity1",
+ .type = PTYPE_U8,
+ .value.u8 = 1,
+ },
+ {
+ .description = "uint8_sanity2",
+ .type = PTYPE_U8,
+ .value.u8 = UINT8_MAX / 2 + 1,
+ },
+ {
+ .description = "uint8_min",
+ .type = PTYPE_U8,
+ .value.u8 = 0,
+ },
+ {
+ .description = "uint8_max",
+ .type = PTYPE_U8,
+ .value.u8 = UINT8_MAX,
+ },
+ /* uint16 tests */
+ {
+ .description = "uint16_sanity1",
+ .type = PTYPE_U16,
+ .value.u16 = 1,
+ },
+ {
+ .description = "uint16_sanity2",
+ .type = PTYPE_U16,
+ .value.u16 = UINT16_MAX / 2 + 1,
+ },
+ {
+ .description = "uint16_min",
+ .type = PTYPE_U16,
+ .value.u16 = 0,
+ },
+ {
+ .description = "uint16_max",
+ .type = PTYPE_U16,
+ .value.u16 = UINT16_MAX,
+ },
+ /* uint32 tests */
+ {
+ .description = "uint32_sanity1",
+ .type = PTYPE_U32,
+ .value.u32 = 1,
+ },
+ {
+ .description = "uint32_sanity2",
+ .type = PTYPE_U32,
+ .value.u32 = UINT32_MAX / 2 + 1,
+ },
+ {
+ .description = "uint32_min",
+ .type = PTYPE_U32,
+ .value.u32 = 0,
+ },
+ {
+ .description = "uint32_max",
+ .type = PTYPE_U32,
+ .value.u32 = UINT32_MAX,
+ },
+ /* uint64 tests */
+ {
+ .description = "uint64_sanity1",
+ .type = PTYPE_U64,
+ .value.u64 = 1,
+ },
+ {
+ .description = "uint64_sanity2",
+ .type = PTYPE_U64,
+ .value.u64 = UINT64_MAX / 2 + 1,
+ },
+ {
+ .description = "uint64_min",
+ .type = PTYPE_U64,
+ .value.u64 = 0,
+ },
+ {
+ .description = "uint64_max",
+ .type = PTYPE_U64,
+ .value.u64 = UINT64_MAX,
+ },
+ /* int8 tests */
+ {
+ .description = "int8_sanity1",
+ .type = PTYPE_S8,
+ .value.s8 = -1,
+ },
+ {
+ .description = "int8_sanity2",
+ .type = PTYPE_S8,
+ .value.s8 = INT8_MAX / 2 + 1,
+ },
+ {
+ .description = "int8_min",
+ .type = PTYPE_S8,
+ .value.s8 = INT8_MIN,
+ },
+ {
+ .description = "int8_max",
+ .type = PTYPE_S8,
+ .value.s8 = INT8_MAX,
+ },
+ /* int16 tests */
+ {
+ .description = "int16_sanity1",
+ .type = PTYPE_S16,
+ .value.s16 = -1,
+ },
+ {
+ .description = "int16_sanity2",
+ .type = PTYPE_S16,
+ .value.s16 = INT16_MAX / 2 + 1,
+ },
+ {
+ .description = "int16_min",
+ .type = PTYPE_S16,
+ .value.s16 = INT16_MIN,
+ },
+ {
+ .description = "int16_max",
+ .type = PTYPE_S16,
+ .value.s16 = INT16_MAX,
+ },
+ /* int32 tests */
+ {
+ .description = "int32_sanity1",
+ .type = PTYPE_S32,
+ .value.s32 = -1,
+ },
+ {
+ .description = "int32_sanity2",
+ .type = PTYPE_S32,
+ .value.s32 = INT32_MAX / 2 + 1,
+ },
+ {
+ .description = "int32_min",
+ .type = PTYPE_S32,
+ .value.s32 = INT32_MIN,
+ },
+ {
+ .description = "int32_max",
+ .type = PTYPE_S32,
+ .value.s32 = INT32_MAX,
+ },
+ /* int64 tests */
+ {
+ .description = "int64_sanity1",
+ .type = PTYPE_S64,
+ .value.s64 = -1,
+ },
+ {
+ .description = "int64_sanity2",
+ .type = PTYPE_S64,
+ .value.s64 = INT64_MAX / 2 + 1,
+ },
+ {
+ .description = "int64_min",
+ .type = PTYPE_S64,
+ .value.s64 = INT64_MIN,
+ },
+ {
+ .description = "int64_max",
+ .type = PTYPE_S64,
+ .value.s64 = INT64_MAX,
+ },
+ { .type = PTYPE_EOL }
+};
+
+/* visitor-specific op implementations */
+
+typedef struct QmpSerializeData {
+ QmpOutputVisitor *qov;
+ QmpInputVisitor *qiv;
+} QmpSerializeData;
+
+static void qmp_serialize(void *native_in, void **datap,
+ VisitorFunc visit, Error **errp)
+{
+ QmpSerializeData *d = g_malloc0(sizeof(*d));
+
+ d->qov = qmp_output_visitor_new();
+ visit(qmp_output_get_visitor(d->qov), &native_in, errp);
+ *datap = d;
+}
+
+static void qmp_deserialize(void **native_out, void *datap,
+ VisitorFunc visit, Error **errp)
+{
+ QmpSerializeData *d = datap;
+ QString *output_json = qobject_to_json(qmp_output_get_qobject(d->qov));
+ QObject *obj = qobject_from_json(qstring_get_str(output_json));
+
+ QDECREF(output_json);
+ d->qiv = qmp_input_visitor_new(obj);
+ visit(qmp_input_get_visitor(d->qiv), native_out, errp);
+}
+
+static void qmp_cleanup(void *datap)
+{
+ QmpSerializeData *d = datap;
+ qmp_output_visitor_cleanup(d->qov);
+ qmp_input_visitor_cleanup(d->qiv);
+}
+
+typedef struct StringSerializeData {
+ StringOutputVisitor *sov;
+ StringInputVisitor *siv;
+} StringSerializeData;
+
+static void string_serialize(void *native_in, void **datap,
+ VisitorFunc visit, Error **errp)
+{
+ StringSerializeData *d = g_malloc0(sizeof(*d));
+
+ d->sov = string_output_visitor_new();
+ visit(string_output_get_visitor(d->sov), &native_in, errp);
+ *datap = d;
+}
+
+static void string_deserialize(void **native_out, void *datap,
+ VisitorFunc visit, Error **errp)
+{
+ StringSerializeData *d = datap;
+
+ d->siv = string_input_visitor_new(string_output_get_string(d->sov));
+ visit(string_input_get_visitor(d->siv), native_out, errp);
+}
+
+static void string_cleanup(void *datap)
+{
+ StringSerializeData *d = datap;
+ string_output_visitor_cleanup(d->sov);
+ string_input_visitor_cleanup(d->siv);
+}
+
+/* visitor registration, test harness */
+
+/* note: to function interchangeably as a serialization mechanism your
+ * visitor test implementation should pass the test cases for all visitor
+ * capabilities: primitives, structures, and lists
+ */
+static const SerializeOps visitors[] = {
+ {
+ .type = "QMP",
+ .serialize = qmp_serialize,
+ .deserialize = qmp_deserialize,
+ .cleanup = qmp_cleanup,
+ .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS
+ },
+ {
+ .type = "String",
+ .serialize = string_serialize,
+ .deserialize = string_deserialize,
+ .cleanup = string_cleanup,
+ .caps = VCAP_PRIMITIVES
+ },
+ { NULL }
+};
+
+static void add_visitor_type(const SerializeOps *ops)
+{
+ char testname_prefix[128];
+ char testname[128];
+ TestArgs *args;
+ int i = 0;
+
+ sprintf(testname_prefix, "/visitor/serialization/%s", ops->type);
+
+ if (ops->caps & VCAP_PRIMITIVES) {
+ while (pt_values[i].type != PTYPE_EOL) {
+ sprintf(testname, "%s/primitives/%s", testname_prefix,
+ pt_values[i].description);
+ args = g_malloc0(sizeof(*args));
+ args->ops = ops;
+ args->test_data = &pt_values[i];
+ g_test_add_data_func(testname, args, test_primitives);
+ i++;
+ }
+ }
+
+ if (ops->caps & VCAP_STRUCTURES) {
+ sprintf(testname, "%s/struct", testname_prefix);
+ args = g_malloc0(sizeof(*args));
+ args->ops = ops;
+ args->test_data = NULL;
+ g_test_add_data_func(testname, args, test_struct);
+
+ sprintf(testname, "%s/nested_struct", testname_prefix);
+ args = g_malloc0(sizeof(*args));
+ args->ops = ops;
+ args->test_data = NULL;
+ g_test_add_data_func(testname, args, test_nested_struct);
+ }
+
+ if (ops->caps & VCAP_LISTS) {
+ sprintf(testname, "%s/nested_struct_list", testname_prefix);
+ args = g_malloc0(sizeof(*args));
+ args->ops = ops;
+ args->test_data = NULL;
+ g_test_add_data_func(testname, args, test_nested_struct_list);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int i = 0;
+
+ g_test_init(&argc, &argv, NULL);
+
+ while (visitors[i].type != NULL) {
+ add_visitor_type(&visitors[i]);
+ i++;
+ }
+
+ g_test_run();
+
+ return 0;
+}
diff --git a/trace-events b/trace-events
index 45c6bc1271..f70523c47e 100644
--- a/trace-events
+++ b/trace-events
@@ -257,19 +257,20 @@ usb_ehci_port_detach(uint32_t port) "detach port #%d"
usb_ehci_port_reset(uint32_t port, int enable) "reset port #%d - %d"
usb_ehci_data(int rw, uint32_t cpage, uint32_t offset, uint32_t addr, uint32_t len, uint32_t bufpos) "write %d, cpage %d, offset 0x%03x, addr 0x%08x, len %d, bufpos %d"
usb_ehci_queue_action(void *q, const char *action) "q %p: %s"
+usb_ehci_packet_action(void *q, void *p, const char *action) "q %p p %p: %s"
# hw/usb/hcd-uhci.c
usb_uhci_reset(void) "=== RESET ==="
usb_uhci_schedule_start(void) ""
usb_uhci_schedule_stop(void) ""
usb_uhci_frame_start(uint32_t num) "nr %d"
+usb_uhci_frame_stop_bandwidth(void) ""
usb_uhci_frame_loop_stop_idle(void) ""
-usb_uhci_frame_loop_stop_bandwidth(void) ""
usb_uhci_frame_loop_continue(void) ""
-usb_uhci_mmio_readw(uint32_t addr, uint32_t val) "addr %04x, ret 0x04%x"
-usb_uhci_mmio_writew(uint32_t addr, uint32_t val) "addr %04x, val 0x04%x"
-usb_uhci_mmio_readl(uint32_t addr, uint32_t val) "addr %04x, ret 0x08%x"
-usb_uhci_mmio_writel(uint32_t addr, uint32_t val) "addr %04x, val 0x08%x"
+usb_uhci_mmio_readw(uint32_t addr, uint32_t val) "addr 0x%04x, ret 0x%04x"
+usb_uhci_mmio_writew(uint32_t addr, uint32_t val) "addr 0x%04x, val 0x%04x"
+usb_uhci_mmio_readl(uint32_t addr, uint32_t val) "addr 0x%04x, ret 0x%08x"
+usb_uhci_mmio_writel(uint32_t addr, uint32_t val) "addr 0x%04x, val 0x%08x"
usb_uhci_queue_add(uint32_t token) "token 0x%x"
usb_uhci_queue_del(uint32_t token) "token 0x%x"
usb_uhci_packet_add(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
@@ -289,6 +290,41 @@ usb_uhci_td_nextqh(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
usb_uhci_td_async(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
usb_uhci_td_complete(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
+# hw/usb/hcd-xhci.c
+usb_xhci_reset(void) "=== RESET ==="
+usb_xhci_run(void) ""
+usb_xhci_stop(void) ""
+usb_xhci_cap_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
+usb_xhci_oper_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
+usb_xhci_port_read(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, ret 0x%08x"
+usb_xhci_runtime_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
+usb_xhci_doorbell_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
+usb_xhci_oper_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
+usb_xhci_port_write(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, val 0x%08x"
+usb_xhci_runtime_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
+usb_xhci_doorbell_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
+usb_xhci_irq_intx(uint32_t level) "level %d"
+usb_xhci_irq_msi(uint32_t nr) "nr %d"
+usb_xhci_queue_event(uint32_t idx, const char *name, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, p %016" PRIx64 ", s %08x, c 0x%08x"
+usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x"
+usb_xhci_slot_enable(uint32_t slotid) "slotid %d"
+usb_xhci_slot_disable(uint32_t slotid) "slotid %d"
+usb_xhci_slot_address(uint32_t slotid) "slotid %d"
+usb_xhci_slot_configure(uint32_t slotid) "slotid %d"
+usb_xhci_slot_evaluate(uint32_t slotid) "slotid %d"
+usb_xhci_slot_reset(uint32_t slotid) "slotid %d"
+usb_xhci_ep_enable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
+usb_xhci_ep_disable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
+usb_xhci_ep_kick(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
+usb_xhci_ep_stop(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
+usb_xhci_ep_reset(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
+usb_xhci_xfer_start(void *xfer, uint32_t slotid, uint32_t epid, uint32_t length) "%p: slotid %d, epid %d, length %d"
+usb_xhci_xfer_async(void *xfer) "%p"
+usb_xhci_xfer_nak(void *xfer) "%p"
+usb_xhci_xfer_retry(void *xfer) "%p"
+usb_xhci_xfer_success(void *xfer, uint32_t bytes) "%p: len %d"
+usb_xhci_xfer_error(void *xfer, uint32_t ret) "%p: ret %d"
+
# hw/usb/desc.c
usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d"
diff --git a/trace/simple.c b/trace/simple.c
index 33ae48696d..b4a3c6e950 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -161,8 +161,11 @@ static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3,
}
timestamp = get_clock();
-
+#if GLIB_CHECK_VERSION(2, 30, 0)
+ idx = g_atomic_int_add((gint *)&trace_idx, 1) % TRACE_BUF_LEN;
+#else
idx = g_atomic_int_exchange_and_add((gint *)&trace_idx, 1) % TRACE_BUF_LEN;
+#endif
trace_buf[idx] = (TraceRecord){
.event = event,
.timestamp_ns = timestamp,
diff --git a/ui/Makefile.objs b/ui/Makefile.objs
new file mode 100644
index 0000000000..3687c8a518
--- /dev/null
+++ b/ui/Makefile.objs
@@ -0,0 +1,18 @@
+vnc-obj-y += vnc.o d3des.o
+vnc-obj-y += vnc-enc-zlib.o vnc-enc-hextile.o
+vnc-obj-y += vnc-enc-tight.o vnc-palette.o
+vnc-obj-y += vnc-enc-zrle.o
+vnc-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
+vnc-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
+ifdef CONFIG_VNC_THREAD
+vnc-obj-y += vnc-jobs-async.o
+else
+vnc-obj-y += vnc-jobs-sync.o
+endif
+
+common-obj-y += keymaps.o
+common-obj-$(CONFIG_SPICE) += spice-core.o spice-input.o spice-display.o
+common-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o
+common-obj-$(CONFIG_COCOA) += cocoa.o
+common-obj-$(CONFIG_CURSES) += curses.o
+common-obj-$(CONFIG_VNC) += $(vnc-obj-y)
diff --git a/vl.c b/vl.c
index 23ab3a34d0..204d85bcf6 100644
--- a/vl.c
+++ b/vl.c
@@ -51,14 +51,12 @@
#ifdef CONFIG_BSD
#include <sys/stat.h>
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-#include <libutil.h>
#include <sys/sysctl.h>
#else
#include <util.h>
#endif
#else
#ifdef __linux__
-#include <pty.h>
#include <malloc.h>
#include <linux/ppdev.h>
@@ -81,10 +79,6 @@
#endif
#endif
-#if defined(__OpenBSD__)
-#include <util.h>
-#endif
-
#if defined(CONFIG_VDE)
#include <libvdeplug.h>
#endif
@@ -1786,7 +1780,7 @@ static int balloon_parse(const char *arg)
return -1;
} else {
/* create empty opts */
- opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+ opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL);
}
qemu_opt_set(opts, "driver", "virtio-balloon");
return 0;
@@ -1921,7 +1915,7 @@ static void monitor_parse(const char *optarg, const char *mode)
}
}
- opts = qemu_opts_create(qemu_find_opts("mon"), label, 1);
+ opts = qemu_opts_create(qemu_find_opts("mon"), label, 1, NULL);
if (!opts) {
fprintf(stderr, "duplicate chardev: %s\n", label);
exit(1);
@@ -2035,14 +2029,14 @@ static int virtcon_parse(const char *devname)
exit(1);
}
- bus_opts = qemu_opts_create(device, NULL, 0);
+ bus_opts = qemu_opts_create(device, NULL, 0, NULL);
if (arch_type == QEMU_ARCH_S390X) {
qemu_opt_set(bus_opts, "driver", "virtio-serial-s390");
} else {
qemu_opt_set(bus_opts, "driver", "virtio-serial-pci");
}
- dev_opts = qemu_opts_create(device, NULL, 0);
+ dev_opts = qemu_opts_create(device, NULL, 0, NULL);
qemu_opt_set(dev_opts, "driver", "virtconsole");
snprintf(label, sizeof(label), "virtcon%d", index);
@@ -2065,7 +2059,7 @@ static int debugcon_parse(const char *devname)
if (!qemu_chr_new("debugcon", devname, NULL)) {
exit(1);
}
- opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1);
+ opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1, NULL);
if (!opts) {
fprintf(stderr, "qemu: already have a debugcon device\n");
exit(1);
@@ -2813,7 +2807,8 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
- qemu_opt_get(opts, "mount_tag"), 1);
+ qemu_opt_get(opts, "mount_tag"),
+ 1, NULL);
if (!fsdev) {
fprintf(stderr, "duplicate fsdev id: %s\n",
qemu_opt_get(opts, "mount_tag"));
@@ -2845,7 +2840,8 @@ int main(int argc, char **argv, char **envp)
qemu_opt_set_bool(fsdev, "readonly",
qemu_opt_get_bool(opts, "readonly", 0));
- device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+ device = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
+ NULL);
qemu_opt_set(device, "driver", "virtio-9p-pci");
qemu_opt_set(device, "fsdev",
qemu_opt_get(opts, "mount_tag"));
@@ -2857,14 +2853,16 @@ int main(int argc, char **argv, char **envp)
QemuOpts *fsdev;
QemuOpts *device;
- fsdev = qemu_opts_create(qemu_find_opts("fsdev"), "v_synth", 1);
+ fsdev = qemu_opts_create(qemu_find_opts("fsdev"), "v_synth",
+ 1, NULL);
if (!fsdev) {
fprintf(stderr, "duplicate option: %s\n", "virtfs_synth");
exit(1);
}
qemu_opt_set(fsdev, "fsdriver", "synth");
- device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+ device = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
+ NULL);
qemu_opt_set(device, "driver", "virtio-9p-pci");
qemu_opt_set(device, "fsdev", "v_synth");
qemu_opt_set(device, "mount_tag", "v_synth");