summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--.gitmodules3
-rw-r--r--Makefile21
-rw-r--r--Makefile.objs12
-rw-r--r--Makefile.target10
-rw-r--r--acl.c1
-rw-r--r--arch_init.h2
-rw-r--r--arm-semi.c1
-rw-r--r--balloon.c1
-rw-r--r--block-migration.c23
-rw-r--r--block/nbd.c4
-rw-r--r--block/qed-check.c4
-rw-r--r--block/qed.h2
-rw-r--r--bt-host.c1
-rw-r--r--bt-vhci.c1
-rw-r--r--buffered_file.c1
-rwxr-xr-xconfigure38
-rw-r--r--cpu-all.h24
-rw-r--r--cpu-exec.c10
-rw-r--r--cpus.c13
-rw-r--r--cpus.h4
-rw-r--r--darwin-user/commpage.c2
-rw-r--r--device_tree.c1
-rw-r--r--docs/tracing.txt23
-rw-r--r--exec-all.h7
-rw-r--r--exec.c27
-rw-r--r--fpu/softfloat-macros.h29
-rw-r--r--fpu/softfloat-native.c26
-rw-r--r--fpu/softfloat-native.h63
-rw-r--r--fpu/softfloat-specialize.h23
-rw-r--r--fpu/softfloat.c410
-rw-r--r--fpu/softfloat.h30
-rw-r--r--fsdev/file-op-9p.h (renamed from hw/file-op-9p.h)0
-rw-r--r--fsdev/qemu-fsdev.h2
-rw-r--r--hw/9pfs/virtio-9p-debug.c (renamed from hw/virtio-9p-debug.c)0
-rw-r--r--hw/9pfs/virtio-9p-debug.h (renamed from hw/virtio-9p-debug.h)0
-rw-r--r--hw/9pfs/virtio-9p-local.c (renamed from hw/virtio-9p-local.c)2
-rw-r--r--hw/9pfs/virtio-9p-posix-acl.c (renamed from hw/virtio-9p-posix-acl.c)17
-rw-r--r--hw/9pfs/virtio-9p-xattr-user.c (renamed from hw/virtio-9p-xattr-user.c)2
-rw-r--r--hw/9pfs/virtio-9p-xattr.c (renamed from hw/virtio-9p-xattr.c)2
-rw-r--r--hw/9pfs/virtio-9p-xattr.h (renamed from hw/virtio-9p-xattr.h)0
-rw-r--r--hw/9pfs/virtio-9p.c (renamed from hw/virtio-9p.c)14
-rw-r--r--hw/9pfs/virtio-9p.h (renamed from hw/virtio-9p.h)4
-rw-r--r--hw/adb.c83
-rw-r--r--hw/ads7846.c41
-rw-r--r--hw/an5206.c1
-rw-r--r--hw/arm_boot.c2
-rw-r--r--hw/arm_timer.c66
-rw-r--r--hw/armv7m.c1
-rw-r--r--hw/armv7m_nvic.c39
-rw-r--r--hw/axis_dev88.c1
-rw-r--r--hw/blizzard.c1
-rw-r--r--hw/bt-hci-csr.c1
-rw-r--r--hw/collie.c69
-rw-r--r--hw/cris-boot.c1
-rw-r--r--hw/cuda.c116
-rw-r--r--hw/dummy_m68k.c1
-rw-r--r--hw/e1000.c2
-rw-r--r--hw/eepro100.c2
-rw-r--r--hw/empty_slot.c21
-rw-r--r--hw/etraxfs.c1
-rw-r--r--hw/flash.h4
-rw-r--r--hw/grlib_apbuart.c2
-rw-r--r--hw/grlib_gptimer.c29
-rw-r--r--hw/grlib_irqmp.c4
-rw-r--r--hw/gumstix.c1
-rw-r--r--hw/heathrow_pic.c62
-rw-r--r--hw/hw.h17
-rw-r--r--hw/ide/atapi.c1138
-rw-r--r--hw/ide/core.c1067
-rw-r--r--hw/ide/ich.c1
-rw-r--r--hw/ide/internal.h10
-rw-r--r--hw/ide/isa.c1
-rw-r--r--hw/ide/macio.c1
-rw-r--r--hw/ide/microdrive.c1
-rw-r--r--hw/ide/mmio.c1
-rw-r--r--hw/ide/pci.c1
-rw-r--r--hw/integratorcp.c1
-rw-r--r--hw/ioapic.c5
-rw-r--r--hw/isa-bus.c1
-rw-r--r--hw/kvmclock.c6
-rw-r--r--hw/lm32_boards.c1
-rw-r--r--hw/m48t59.c36
-rw-r--r--hw/mac_dbdma.c83
-rw-r--r--hw/mac_nvram.c32
-rw-r--r--hw/mainstone.c1
-rw-r--r--hw/max111x.c51
-rw-r--r--hw/milkymist-hw.h20
-rw-r--r--hw/milkymist-minimac2.c (renamed from hw/milkymist-minimac.c)297
-rw-r--r--hw/milkymist-sysctl.c26
-rw-r--r--hw/milkymist-vgafb.c3
-rw-r--r--hw/milkymist.c2
-rw-r--r--hw/mipsnet.c53
-rw-r--r--hw/nand.c79
-rw-r--r--hw/ne2000.c2
-rw-r--r--hw/omap_sx1.c1
-rw-r--r--hw/pcie.c3
-rw-r--r--hw/pcnet-pci.c2
-rw-r--r--hw/pflash_cfi02.c12
-rw-r--r--hw/piix4.c44
-rw-r--r--hw/pl011.c76
-rw-r--r--hw/pl022.c84
-rw-r--r--hw/ppc440_bamboo.c1
-rw-r--r--hw/ppc4xx_devs.c1
-rw-r--r--hw/ppc4xx_pci.c80
-rw-r--r--hw/ppce500_pci.c87
-rw-r--r--hw/ptimer.c59
-rw-r--r--hw/pxa2xx.c158
-rw-r--r--hw/pxa2xx_keypad.c53
-rw-r--r--hw/pxa2xx_lcd.c138
-rw-r--r--hw/qdev-properties.c4
-rw-r--r--hw/rtl8139.c440
-rw-r--r--hw/s390-virtio-bus.c10
-rw-r--r--hw/s390-virtio.c21
-rw-r--r--hw/stellaris.c324
-rw-r--r--hw/stellaris_input.c50
-rw-r--r--hw/strongarm.c1598
-rw-r--r--hw/strongarm.h64
-rw-r--r--hw/syborg.c1
-rw-r--r--hw/syborg_keyboard.c57
-rw-r--r--hw/syborg_pointer.c73
-rw-r--r--hw/syborg_rtc.c34
-rw-r--r--hw/syborg_serial.c60
-rw-r--r--hw/syborg_timer.c46
-rw-r--r--hw/syborg_virtio.c1
-rw-r--r--hw/sysbus.c1
-rw-r--r--hw/tc58128.c1
-rw-r--r--hw/tosa.c1
-rw-r--r--hw/twl92230.c1
-rw-r--r--hw/usb-hid.c2
-rw-r--r--hw/usb-msd.c4
-rw-r--r--hw/virtio-balloon.c1
-rw-r--r--hw/virtio-console.c18
-rw-r--r--hw/virtio-pci.c2
-rw-r--r--hw/virtio-serial-bus.c23
-rw-r--r--hw/virtio.c1
-rw-r--r--hw/vmport.c1
-rw-r--r--hw/xen_console.c1
-rw-r--r--hw/xen_domainbuild.c1
-rw-r--r--hw/xen_machine_pv.c1
-rw-r--r--hw/xenfb.c1
-rw-r--r--hw/xilinx_timer.c1
-rw-r--r--json-lexer.c6
-rw-r--r--kvm-all.c14
-rw-r--r--kvm-stub.c1
-rw-r--r--libcacard/vcard_emul_nss.c4
-rw-r--r--linux-user/alpha/syscall_nr.h7
-rw-r--r--linux-user/arm/nwfpe/fpa11.c2
-rw-r--r--linux-user/arm/nwfpe/fpa11.h2
-rw-r--r--linux-user/arm/nwfpe/fpa11_cpdt.c8
-rw-r--r--linux-user/arm/nwfpe/fpa11_cprt.c2
-rw-r--r--linux-user/ioctls.h4
-rw-r--r--linux-user/strace.c173
-rw-r--r--linux-user/strace.list12
-rw-r--r--linux-user/syscall.c167
-rw-r--r--linux-user/syscall_defs.h8
-rw-r--r--migration-exec.c1
-rw-r--r--migration-fd.c1
-rw-r--r--migration-tcp.c1
-rw-r--r--migration-unix.c1
-rw-r--r--migration.h9
-rw-r--r--net.c1
-rw-r--r--net/dump.c2
-rw-r--r--net/slirp.c1
-rw-r--r--net/vde.c1
-rw-r--r--osdep.c1
-rw-r--r--pc-bios/README19
-rw-r--r--pc-bios/gpxe-eepro100-80861209.rombin56832 -> 0 bytes
-rw-r--r--pc-bios/pxe-e1000.binbin72192 -> 0 bytes
-rw-r--r--pc-bios/pxe-e1000.rombin0 -> 67072 bytes
-rw-r--r--pc-bios/pxe-eepro100.rombin0 -> 61440 bytes
-rw-r--r--pc-bios/pxe-ne2k_pci.binbin56320 -> 0 bytes
-rw-r--r--pc-bios/pxe-ne2k_pci.rombin0 -> 61440 bytes
-rw-r--r--pc-bios/pxe-pcnet.binbin56832 -> 0 bytes
-rw-r--r--pc-bios/pxe-pcnet.rombin0 -> 61440 bytes
-rw-r--r--pc-bios/pxe-rtl8139.binbin56320 -> 0 bytes
-rw-r--r--pc-bios/pxe-rtl8139.rombin0 -> 61440 bytes
-rw-r--r--pc-bios/pxe-virtio.binbin56320 -> 0 bytes
-rw-r--r--pc-bios/pxe-virtio.rombin0 -> 60416 bytes
-rw-r--r--qemu-char.c24
-rw-r--r--qemu-char.h6
-rw-r--r--qemu-common.h20
-rw-r--r--qemu-config.c1
-rw-r--r--qemu-error.c1
-rw-r--r--qemu-img.c15
-rw-r--r--qemu-options.hx8
-rw-r--r--qemu-os-win32.h3
-rw-r--r--qemu-progress.c64
-rw-r--r--qemu-timer.c324
-rw-r--r--qemu-timer.h10
-rw-r--r--qemu-tool.c1
m---------roms/ipxe0
-rw-r--r--savevm.c3
-rwxr-xr-xscripts/refresh-pxe-roms.sh99
-rwxr-xr-xscripts/tracetool9
-rw-r--r--spice-qemu-char.c14
-rw-r--r--sysemu.h34
-rw-r--r--target-alpha/op_helper.c11
-rw-r--r--target-alpha/translate.c3
-rw-r--r--target-arm/cpu.h3
-rw-r--r--target-arm/helper.c22
-rw-r--r--target-arm/helper.h (renamed from target-arm/helpers.h)0
-rw-r--r--target-arm/iwmmxt_helper.c2
-rw-r--r--target-arm/neon_helper.c2
-rw-r--r--target-arm/op_helper.c4
-rw-r--r--target-arm/translate.c89
-rw-r--r--target-cris/op_helper.c2
-rw-r--r--target-cris/translate.c3
-rw-r--r--target-i386/cpuid.c16
-rw-r--r--target-i386/exec.h53
-rw-r--r--target-i386/helper.c12
-rw-r--r--target-i386/kvm.c80
-rw-r--r--target-i386/op_helper.c225
-rw-r--r--target-i386/ops_sse.h48
-rw-r--r--target-i386/translate.c7
-rw-r--r--target-lm32/helper.c6
-rw-r--r--target-lm32/op_helper.c2
-rw-r--r--target-lm32/translate.c29
-rw-r--r--target-m68k/op_helper.c2
-rw-r--r--target-m68k/translate.c3
-rw-r--r--target-microblaze/op_helper.c6
-rw-r--r--target-microblaze/translate.c3
-rw-r--r--target-mips/op_helper.c248
-rw-r--r--target-mips/translate.c3
-rw-r--r--target-ppc/op_helper.c28
-rw-r--r--target-ppc/translate.c3
-rw-r--r--target-s390x/cpu.h774
-rw-r--r--target-s390x/exec.h11
-rw-r--r--target-s390x/helper.c4
-rw-r--r--target-s390x/kvm.c17
-rw-r--r--target-s390x/op_helper.c2
-rw-r--r--target-s390x/translate.c5
-rw-r--r--target-sh4/op_helper.c2
-rw-r--r--target-sh4/translate.c3
-rw-r--r--target-sparc/op_helper.c2
-rw-r--r--target-sparc/translate.c3
-rw-r--r--target-unicore32/translate.c3
-rw-r--r--tests/test-mmap.c2
-rw-r--r--trace-events37
-rw-r--r--translate-all.c5
-rw-r--r--usb-linux.c5
-rw-r--r--vl.c58
242 files changed, 7111 insertions, 3815 deletions
diff --git a/.gitignore b/.gitignore
index 4833233e8..113876e81 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,9 @@ QMP/qmp-commands.txt
*.ky
*.log
*.pdf
+*.cps
+*.fns
+*.kys
*.pg
*.pyc
*.toc
diff --git a/.gitmodules b/.gitmodules
index 4ec9b844c..e37e437cc 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,3 +7,6 @@
[submodule "roms/SLOF"]
path = roms/SLOF
url = git://git.qemu.org/SLOF.git
+[submodule "roms/ipxe"]
+ path = roms/ipxe
+ url = git://git.qemu.org/ipxe.git
diff --git a/Makefile b/Makefile
index 5fbd45806..89ce7d6b5 100644
--- a/Makefile
+++ b/Makefile
@@ -163,7 +163,10 @@ distclean: clean
rm -f config-host.mak config-host.h* config-host.ld $(DOCS) qemu-options.texi qemu-img-cmds.texi qemu-monitor.texi
rm -f config-all-devices.mak
rm -f roms/seabios/config.mak roms/vgabios/config.mak
- rm -f qemu-doc.info qemu-doc.aux qemu-doc.cp qemu-doc.dvi qemu-doc.fn qemu-doc.info qemu-doc.ky qemu-doc.log qemu-doc.pdf qemu-doc.pg qemu-doc.toc qemu-doc.tp qemu-doc.vr
+ rm -f qemu-doc.info qemu-doc.aux qemu-doc.cp qemu-doc.cps qemu-doc.dvi
+ rm -f qemu-doc.fn qemu-doc.fns qemu-doc.info qemu-doc.ky qemu-doc.kys
+ rm -f qemu-doc.log qemu-doc.pdf qemu-doc.pg qemu-doc.toc qemu-doc.tp
+ rm -f qemu-doc.vr
rm -f qemu-tech.info qemu-tech.aux qemu-tech.cp qemu-tech.dvi qemu-tech.fn qemu-tech.info qemu-tech.ky qemu-tech.log qemu-tech.pdf qemu-tech.pg qemu-tech.toc qemu-tech.tp qemu-tech.vr
for d in $(TARGET_DIRS) $(QEMULIBS); do \
rm -rf $$d || exit 1 ; \
@@ -177,10 +180,8 @@ ifdef INSTALL_BLOBS
BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \
vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \
-gpxe-eepro100-80861209.rom \
-pxe-e1000.bin \
-pxe-ne2k_pci.bin pxe-pcnet.bin \
-pxe-rtl8139.bin pxe-virtio.bin \
+pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
+pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
multiboot.bin linuxboot.bin \
s390-zipl.rom \
@@ -333,10 +334,12 @@ tarbin:
$(datadir)/openbios-sparc32 \
$(datadir)/openbios-sparc64 \
$(datadir)/openbios-ppc \
- $(datadir)/pxe-ne2k_pci.bin \
- $(datadir)/pxe-rtl8139.bin \
- $(datadir)/pxe-pcnet.bin \
- $(datadir)/pxe-e1000.bin \
+ $(datadir)/pxe-e1000.rom \
+ $(datadir)/pxe-eepro100.rom \
+ $(datadir)/pxe-ne2k_pci.rom \
+ $(datadir)/pxe-pcnet.rom \
+ $(datadir)/pxe-rtl8139.rom \
+ $(datadir)/pxe-virtio.rom \
$(datadir)/extboot.bin \
$(docdir)/qemu-doc.html \
$(docdir)/qemu-tech.html \
diff --git a/Makefile.objs b/Makefile.objs
index 895d416b2..6c50e7c1f 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -245,7 +245,7 @@ hw-obj-$(CONFIG_LAN9118) += lan9118.o
hw-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o
# IDE
-hw-obj-$(CONFIG_IDE_CORE) += ide/core.o
+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
@@ -288,9 +288,13 @@ 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)
-hw-obj-$(CONFIG_REALLY_VIRTFS) += virtio-9p-debug.o
-hw-obj-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o
-hw-obj-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
+9pfs-nested-$(CONFIG_REALLY_VIRTFS) = virtio-9p-debug.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
+
+hw-obj-$(CONFIG_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
+$(addprefix 9pfs/, $(9pfs-nested-y)): CFLAGS += -I$(SRC_PATH)/hw/
+
######################################################################
# libdis
diff --git a/Makefile.target b/Makefile.target
index 3a3720541..fa2f7912a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -204,7 +204,7 @@ obj-$(CONFIG_VIRTIO) += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial
obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
obj-y += vhost_net.o
obj-$(CONFIG_VHOST_NET) += vhost.o
-obj-$(CONFIG_REALLY_VIRTFS) += virtio-9p.o
+obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p.o
obj-y += rwhandler.o
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
obj-$(CONFIG_NO_KVM) += kvm-stub.o
@@ -296,7 +296,7 @@ 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-minimac.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
@@ -379,6 +379,8 @@ obj-arm-y += syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
obj-arm-y += syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
obj-arm-y += syborg_virtio.o
obj-arm-y += vexpress.o
+obj-arm-y += strongarm.o
+obj-arm-y += collie.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
@@ -431,9 +433,11 @@ hmp-commands.h: $(SRC_PATH)/hmp-commands.hx
qmp-commands.h: $(SRC_PATH)/qmp-commands.hx
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
+9pfs/virtio-9p.o: CFLAGS += -I$(SRC_PATH)/hw/
+
clean:
rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
- rm -f *.d */*.d tcg/*.o ide/*.o
+ rm -f *.d */*.d tcg/*.o ide/*.o 9pfs/*.o
rm -f hmp-commands.h qmp-commands.h gdbstub-xml.c
ifdef CONFIG_SYSTEMTAP_TRACE
rm -f *.stp
diff --git a/acl.c b/acl.c
index 311dade4e..82c27043c 100644
--- a/acl.c
+++ b/acl.c
@@ -24,7 +24,6 @@
#include "qemu-common.h"
-#include "sysemu.h"
#include "acl.h"
#ifdef CONFIG_FNMATCH
diff --git a/arch_init.h b/arch_init.h
index c83360c3a..86ebc149b 100644
--- a/arch_init.h
+++ b/arch_init.h
@@ -22,8 +22,6 @@ enum {
extern const uint32_t arch_type;
void select_soundhw(const char *optarg);
-int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque);
-int ram_load(QEMUFile *f, void *opaque, int version_id);
void do_acpitable_option(const char *optarg);
void do_smbios_option(const char *optarg);
void cpudef_init(void);
diff --git a/arm-semi.c b/arm-semi.c
index 1d5179b60..e9e6f8993 100644
--- a/arm-semi.c
+++ b/arm-semi.c
@@ -33,7 +33,6 @@
#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
#else
#include "qemu-common.h"
-#include "sysemu.h"
#include "gdbstub.h"
#endif
diff --git a/balloon.c b/balloon.c
index 0021fef4b..248c1b50a 100644
--- a/balloon.c
+++ b/balloon.c
@@ -22,7 +22,6 @@
* THE SOFTWARE.
*/
-#include "sysemu.h"
#include "monitor.h"
#include "qjson.h"
#include "qint.h"
diff --git a/block-migration.c b/block-migration.c
index 576e55a6a..8d06a2364 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -62,7 +62,6 @@ typedef struct BlkMigBlock {
QEMUIOVector qiov;
BlockDriverAIOCB *aiocb;
int ret;
- int64_t time;
QSIMPLEQ_ENTRY(BlkMigBlock) entry;
} BlkMigBlock;
@@ -78,6 +77,7 @@ typedef struct BlkMigState {
int prev_progress;
int bulk_completed;
long double total_time;
+ long double prev_time_offset;
int reads;
} BlkMigState;
@@ -131,12 +131,6 @@ uint64_t blk_mig_bytes_total(void)
return sum << BDRV_SECTOR_BITS;
}
-static inline void add_avg_read_time(int64_t time)
-{
- block_mig_state.reads++;
- block_mig_state.total_time += time;
-}
-
static inline long double compute_read_bwidth(void)
{
assert(block_mig_state.total_time != 0);
@@ -191,13 +185,14 @@ static void alloc_aio_bitmap(BlkMigDevState *bmds)
static void blk_mig_read_cb(void *opaque, int ret)
{
+ long double curr_time = qemu_get_clock_ns(rt_clock);
BlkMigBlock *blk = opaque;
blk->ret = ret;
- blk->time = qemu_get_clock_ns(rt_clock) - blk->time;
-
- add_avg_read_time(blk->time);
+ block_mig_state.reads++;
+ block_mig_state.total_time += (curr_time - block_mig_state.prev_time_offset);
+ block_mig_state.prev_time_offset = curr_time;
QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
bmds_set_aio_inflight(blk->bmds, blk->sector, blk->nr_sectors, 0);
@@ -250,7 +245,9 @@ static int mig_save_device_bulk(Monitor *mon, QEMUFile *f,
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
- blk->time = qemu_get_clock_ns(rt_clock);
+ if (block_mig_state.submitted == 0) {
+ block_mig_state.prev_time_offset = qemu_get_clock_ns(rt_clock);
+ }
blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
nr_sectors, blk_mig_read_cb, blk);
@@ -409,7 +406,9 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
- blk->time = qemu_get_clock_ns(rt_clock);
+ if (block_mig_state.submitted == 0) {
+ block_mig_state.prev_time_offset = qemu_get_clock_ns(rt_clock);
+ }
blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
nr_sectors, blk_mig_read_cb, blk);
diff --git a/block/nbd.c b/block/nbd.c
index 1d6b22561..7a52f62e7 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -239,6 +239,10 @@ static int nbd_write(BlockDriverState *bs, int64_t sector_num,
static void nbd_close(BlockDriverState *bs)
{
+ BDRVNBDState *s = bs->opaque;
+ qemu_free(s->export_name);
+ qemu_free(s->host_spec);
+
nbd_teardown_connection(bs);
}
diff --git a/block/qed-check.c b/block/qed-check.c
index ea4ebc8e2..22cd07fa1 100644
--- a/block/qed-check.c
+++ b/block/qed-check.c
@@ -18,7 +18,7 @@ typedef struct {
BdrvCheckResult *result;
bool fix; /* whether to fix invalid offsets */
- size_t nclusters;
+ uint64_t nclusters;
uint32_t *used_clusters; /* referenced cluster bitmap */
QEDRequest request;
@@ -177,7 +177,7 @@ static int qed_check_l1_table(QEDCheck *check, QEDTable *table)
static void qed_check_for_leaks(QEDCheck *check)
{
BDRVQEDState *s = check->s;
- size_t i;
+ uint64_t i;
for (i = s->header.header_size; i < check->nclusters; i++) {
if (!qed_test_bit(check->used_clusters, i)) {
diff --git a/block/qed.h b/block/qed.h
index 3e1ab8478..1d1421fee 100644
--- a/block/qed.h
+++ b/block/qed.h
@@ -252,7 +252,7 @@ static inline uint64_t qed_offset_into_cluster(BDRVQEDState *s, uint64_t offset)
return offset & (s->header.cluster_size - 1);
}
-static inline unsigned int qed_bytes_to_clusters(BDRVQEDState *s, size_t bytes)
+static inline uint64_t qed_bytes_to_clusters(BDRVQEDState *s, uint64_t bytes)
{
return qed_start_of_cluster(s, bytes + (s->header.cluster_size - 1)) /
(s->header.cluster_size - 1);
diff --git a/bt-host.c b/bt-host.c
index 6931e7cc6..095254ddc 100644
--- a/bt-host.c
+++ b/bt-host.c
@@ -19,7 +19,6 @@
#include "qemu-common.h"
#include "qemu-char.h"
-#include "sysemu.h"
#include "net.h"
#include "bt-host.h"
diff --git a/bt-vhci.c b/bt-vhci.c
index 679c5e05d..3c5772093 100644
--- a/bt-vhci.c
+++ b/bt-vhci.c
@@ -19,7 +19,6 @@
#include "qemu-common.h"
#include "qemu-char.h"
-#include "sysemu.h"
#include "net.h"
#include "hw/bt.h"
diff --git a/buffered_file.c b/buffered_file.c
index b5e2baff4..41b42c3d5 100644
--- a/buffered_file.c
+++ b/buffered_file.c
@@ -14,7 +14,6 @@
#include "qemu-common.h"
#include "hw/hw.h"
#include "qemu-timer.h"
-#include "sysemu.h"
#include "qemu-char.h"
#include "buffered_file.h"
diff --git a/configure b/configure
index ea8b6760d..75071adef 100755
--- a/configure
+++ b/configure
@@ -190,7 +190,7 @@ spice=""
rbd=""
smartcard=""
smartcard_nss=""
-opengl="no"
+opengl=""
# parse CC options first
for opt do
@@ -2067,11 +2067,11 @@ int main(void) { return 0; }
EOF
if compile_prog "" "$fdt_libs" ; then
fdt=yes
- libs_softmmu="$fdt_libs $libs_softmmu"
else
if test "$fdt" = "yes" ; then
feature_not_found "fdt"
fi
+ fdt_libs=
fdt=no
fi
fi
@@ -2088,11 +2088,11 @@ int main(void) { GL_VERSION; return 0; }
EOF
if compile_prog "" "-lGL" ; then
opengl=yes
- libs_softmmu="$opengl_libs $libs_softmmu"
else
if test "$opengl" = "yes" ; then
feature_not_found "opengl"
fi
+ opengl_libs=
opengl=no
fi
fi
@@ -2346,7 +2346,15 @@ cat > $TMPC << EOF
int main(void)
{
- epoll_create1(0);
+ /* Note that we use epoll_create1 as a value, not as
+ * a function being called. This is necessary so that on
+ * old SPARC glibc versions where the function was present in
+ * the library but not declared in the header file we will
+ * fail the configure check. (Otherwise we will get a compiler
+ * warning but not an error, and will proceed to fail the
+ * qemu compile where we compile with -Werror.)
+ */
+ epoll_create1;
return 0;
}
EOF
@@ -3183,6 +3191,7 @@ mkdir -p $target_dir
mkdir -p $target_dir/fpu
mkdir -p $target_dir/tcg
mkdir -p $target_dir/ide
+mkdir -p $target_dir/9pfs
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
@@ -3200,6 +3209,7 @@ target_short_alignment=2
target_int_alignment=4
target_long_alignment=4
target_llong_alignment=8
+target_libs_softmmu=
TARGET_ARCH="$target_arch2"
TARGET_BASE_ARCH=""
@@ -3236,6 +3246,7 @@ case "$target_arch2" in
;;
lm32)
target_phys_bits=32
+ target_libs_softmmu="$opengl_libs"
;;
m68k)
bflt="yes"
@@ -3250,6 +3261,7 @@ case "$target_arch2" in
bflt="yes"
target_nptl="yes"
target_phys_bits=32
+ target_libs_softmmu="$fdt_libs"
;;
mips|mipsel)
TARGET_ARCH=mips
@@ -3274,6 +3286,7 @@ case "$target_arch2" in
gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
target_phys_bits=32
target_nptl="yes"
+ target_libs_softmmu="$fdt_libs"
;;
ppcemb)
TARGET_BASE_ARCH=ppc
@@ -3281,6 +3294,7 @@ case "$target_arch2" in
gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
target_phys_bits=64
target_nptl="yes"
+ target_libs_softmmu="$fdt_libs"
;;
ppc64)
TARGET_BASE_ARCH=ppc
@@ -3288,6 +3302,7 @@ case "$target_arch2" in
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
target_phys_bits=64
target_long_alignment=8
+ target_libs_softmmu="$fdt_libs"
;;
ppc64abi32)
TARGET_ARCH=ppc64
@@ -3296,6 +3311,7 @@ case "$target_arch2" in
echo "TARGET_ABI32=y" >> $config_target_mak
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
target_phys_bits=64
+ target_libs_softmmu="$fdt_libs"
;;
sh4|sh4eb)
TARGET_ARCH=sh4
@@ -3387,7 +3403,7 @@ fi
if test "$target_softmmu" = "yes" ; then
echo "TARGET_PHYS_ADDR_BITS=$target_phys_bits" >> $config_target_mak
echo "CONFIG_SOFTMMU=y" >> $config_target_mak
- echo "LIBS+=$libs_softmmu" >> $config_target_mak
+ echo "LIBS+=$libs_softmmu $target_libs_softmmu" >> $config_target_mak
echo "HWDIR=../libhw$target_phys_bits" >> $config_target_mak
echo "subdir-$target: subdir-libhw$target_phys_bits" >> $config_host_mak
fi
@@ -3413,14 +3429,7 @@ if test ! -z "$gdb_xml_files" ; then
echo "TARGET_XML_FILES=$list" >> $config_target_mak
fi
-case "$target_arch2" in
- i386|x86_64)
- echo "CONFIG_NOSOFTFLOAT=y" >> $config_target_mak
- ;;
- *)
- echo "CONFIG_SOFTFLOAT=y" >> $config_target_mak
- ;;
-esac
+echo "CONFIG_SOFTFLOAT=y" >> $config_target_mak
if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
echo "TARGET_HAS_BFLT=y" >> $config_target_mak
@@ -3592,7 +3601,7 @@ FILES="Makefile tests/Makefile"
FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
-for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
+for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.rom $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
FILES="$FILES pc-bios/`basename $bios_file`"
done
mkdir -p $DIRS
@@ -3618,6 +3627,7 @@ for hwlib in 32 64; do
mkdir -p $d
mkdir -p $d/ide
symlink $source_path/Makefile.hw $d/Makefile
+ mkdir -p $d/9pfs
echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak
done
diff --git a/cpu-all.h b/cpu-all.h
index dc0f2f02a..88126ea65 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -138,6 +138,16 @@ typedef union {
uint64_t ll;
} CPU_DoubleU;
+#if defined(FLOATX80)
+typedef union {
+ floatx80 d;
+ struct {
+ uint64_t lower;
+ uint16_t upper;
+ } l;
+} CPU_LDoubleU;
+#endif
+
#if defined(CONFIG_SOFTFLOAT)
typedef union {
float128 q;
@@ -789,7 +799,19 @@ extern CPUState *cpu_single_env;
#define CPU_INTERRUPT_SIPI 0x800 /* SIPI pending. */
#define CPU_INTERRUPT_MCE 0x1000 /* (x86 only) MCE pending. */
-void cpu_interrupt(CPUState *s, int mask);
+#ifndef CONFIG_USER_ONLY
+typedef void (*CPUInterruptHandler)(CPUState *, int);
+
+extern CPUInterruptHandler cpu_interrupt_handler;
+
+static inline void cpu_interrupt(CPUState *s, int mask)
+{
+ cpu_interrupt_handler(s, mask);
+}
+#else /* USER_ONLY */
+void cpu_interrupt(CPUState *env, int mask);
+#endif /* USER_ONLY */
+
void cpu_reset_interrupt(CPUState *env, int mask);
void cpu_exit(CPUState *s);
diff --git a/cpu-exec.c b/cpu-exec.c
index 277609f1d..b9b04aec7 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -353,6 +353,8 @@ int cpu_exec(CPUState *env1)
do_interrupt(0);
#elif defined(TARGET_IA64)
do_interrupt(env);
+#elif defined(TARGET_S390X)
+ do_interrupt(env);
#endif
env->exception_index = -1;
#endif
@@ -567,6 +569,12 @@ int cpu_exec(CPUState *env1)
do_interrupt(1);
next_tb = 0;
}
+#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
+ if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+ (env->psw.mask & PSW_MASK_EXT)) {
+ do_interrupt(env);
+ next_tb = 0;
+ }
#endif
/* Don't use the cached interupt_request value,
do_interrupt may have updated the EXITTB flag. */
@@ -808,7 +816,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, puc);
+ cpu_restore_state(tb, env, pc);
}
/* we restore the process signal mask as the sigreturn should
diff --git a/cpus.c b/cpus.c
index 52e4fd784..5d1c39680 100644
--- a/cpus.c
+++ b/cpus.c
@@ -155,7 +155,7 @@ static bool cpu_thread_is_idle(CPUState *env)
return true;
}
-static bool all_cpu_threads_idle(void)
+bool all_cpu_threads_idle(void)
{
CPUState *env;
@@ -745,6 +745,9 @@ static void qemu_tcg_wait_io_event(void)
CPUState *env;
while (all_cpu_threads_idle()) {
+ /* Start accounting real time to the virtual clock if the CPUs
+ are idle. */
+ qemu_clock_warp(vm_clock);
qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
}
@@ -836,6 +839,9 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
while (1) {
cpu_exec_all();
+ if (use_icount && qemu_next_icount_deadline() <= 0) {
+ qemu_notify_event();
+ }
qemu_tcg_wait_io_event();
}
@@ -1050,7 +1056,7 @@ static int tcg_cpu_exec(CPUState *env)
qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
env->icount_decr.u16.low = 0;
env->icount_extra = 0;
- count = qemu_icount_round (qemu_next_deadline());
+ count = qemu_icount_round(qemu_next_icount_deadline());
qemu_icount += count;
decr = (count > 0xffff) ? 0xffff : count;
count -= decr;
@@ -1076,6 +1082,9 @@ bool cpu_exec_all(void)
{
int r;
+ /* Account partial waits to the vm_clock. */
+ qemu_clock_warp(vm_clock);
+
if (next_cpu == NULL) {
next_cpu = first_cpu;
}
diff --git a/cpus.h b/cpus.h
index e0211260c..6fdeb0d8f 100644
--- a/cpus.h
+++ b/cpus.h
@@ -8,6 +8,10 @@ void resume_all_vcpus(void);
void pause_all_vcpus(void);
void cpu_stop_current(void);
+void cpu_synchronize_all_states(void);
+void cpu_synchronize_all_post_reset(void);
+void cpu_synchronize_all_post_init(void);
+
/* vl.c */
extern int smp_cores;
extern int smp_threads;
diff --git a/darwin-user/commpage.c b/darwin-user/commpage.c
index f6aa71e05..cc29bddd9 100644
--- a/darwin-user/commpage.c
+++ b/darwin-user/commpage.c
@@ -211,7 +211,7 @@ void do_compare_and_swap32(void *cpu_env, int num)
uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_ECX];
DPRINTF("commpage: compare_and_swap32(%x,new,%p)\n", old, value);
- if(value && old == tswap32(*value))
+ if(old == tswap32(*value))
{
uint32_t new = ((CPUX86State*)cpu_env)->regs[R_EDX];
*value = tswap32(new);
diff --git a/device_tree.c b/device_tree.c
index 21be07075..f5d5eb1bc 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -20,7 +20,6 @@
#include "config.h"
#include "qemu-common.h"
-#include "sysemu.h"
#include "device_tree.h"
#include "hw/loader.h"
diff --git a/docs/tracing.txt b/docs/tracing.txt
index f15069c96..c99a0f27c 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -26,14 +26,14 @@ for debugging, profiling, and observing execution.
== Trace events ==
-There is a set of static trace events declared in the trace-events source
+There is a set of static trace events declared in the "trace-events" source
file. Each trace event declaration names the event, its arguments, and the
format string which can be used for pretty-printing:
qemu_malloc(size_t size, void *ptr) "size %zu ptr %p"
qemu_free(void *ptr) "ptr %p"
-The trace-events file is processed by the tracetool script during build to
+The "trace-events" file is processed by the "tracetool" script during build to
generate code for the trace events. Trace events are invoked directly from
source code like this:
@@ -52,10 +52,10 @@ source code like this:
=== Declaring trace events ===
-The tracetool script produces the trace.h header file which is included by
+The "tracetool" script produces the trace.h header file which is included by
every source file that uses trace events. Since many source files include
-trace.h, it uses a minimum of types and other header files included to keep
-the namespace clean and compile times and dependencies down.
+trace.h, it uses a minimum of types and other header files included to keep the
+namespace clean and compile times and dependencies down.
Trace events should use types as follows:
@@ -69,6 +69,11 @@ Trace events should use types as follows:
cannot include all user-defined struct declarations and it is therefore
necessary to use void * for pointers to structs.
+ Pointers (including char *) cannot be dereferenced easily (or at all) in
+ some trace backends. If pointers are used, ensure they are meaningful by
+ themselves and do not assume the data they point to will be traced. Do
+ not pass in string arguments.
+
* For everything else, use primitive scalar types (char, int, long) with the
appropriate signedness.
@@ -105,10 +110,10 @@ portability macros, ensure they are preceded and followed by double quotes:
== Trace backends ==
-The tracetool script automates tedious trace event code generation and also
+The "tracetool" script automates tedious trace event code generation and also
keeps the trace event declarations independent of the trace backend. The trace
events are not tightly coupled to a specific trace backend, such as LTTng or
-SystemTap. Support for trace backends can be added by extending the tracetool
+SystemTap. Support for trace backends can be added by extending the "tracetool"
script.
The trace backend is chosen at configure time and only one trace backend can
@@ -176,12 +181,12 @@ events at runtime inside QEMU:
==== Analyzing trace files ====
The "simple" backend produces binary trace files that can be formatted with the
-simpletrace.py script. The script takes the trace-events file and the binary
+simpletrace.py script. The script takes the "trace-events" file and the binary
trace:
./simpletrace.py trace-events trace-12345
-You must ensure that the same trace-events file was used to build QEMU,
+You must ensure that the same "trace-events" file was used to build QEMU,
otherwise trace event declarations may have changed and output will not be
consistent.
diff --git a/exec-all.h b/exec-all.h
index 496c001c0..7c2d29ff9 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -77,15 +77,14 @@ extern uint16_t gen_opc_icount[OPC_BUF_SIZE];
void gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
void gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
-void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc);
+void restore_state_to_opc(CPUState *env, struct TranslationBlock *tb,
+ int pc_pos);
void cpu_gen_init(void);
int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
int *gen_code_size_ptr);
int cpu_restore_state(struct TranslationBlock *tb,
- CPUState *env, unsigned long searched_pc,
- void *puc);
+ CPUState *env, unsigned long searched_pc);
void cpu_resume_from_signal(CPUState *env1, void *puc);
void cpu_io_recompile(CPUState *env, void *retaddr);
TranslationBlock *tb_gen_code(CPUState *env,
diff --git a/exec.c b/exec.c
index 594dfcbbd..169f9f48c 100644
--- a/exec.c
+++ b/exec.c
@@ -1079,8 +1079,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
restore the CPU state */
current_tb_modified = 1;
- cpu_restore_state(current_tb, env,
- env->mem_io_pc, NULL);
+ cpu_restore_state(current_tb, env, env->mem_io_pc);
cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
&current_flags);
}
@@ -1188,7 +1187,7 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr,
restore the CPU state */
current_tb_modified = 1;
- cpu_restore_state(current_tb, env, pc, puc);
+ cpu_restore_state(current_tb, env, pc);
cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
&current_flags);
}
@@ -1639,8 +1638,9 @@ static void cpu_unlink_tb(CPUState *env)
spin_unlock(&interrupt_lock);
}
+#ifndef CONFIG_USER_ONLY
/* mask must never be zero, except for A20 change call */
-void cpu_interrupt(CPUState *env, int mask)
+static void tcg_handle_interrupt(CPUState *env, int mask)
{
int old_mask;
@@ -1649,7 +1649,6 @@ void cpu_interrupt(CPUState *env, int mask)
if (kvm_enabled() && !kvm_irqchip_in_kernel())
kvm_update_interrupt_request(env);
-#ifndef CONFIG_USER_ONLY
/*
* If called from iothread context, wake the target cpu in
* case its halted.
@@ -1658,21 +1657,29 @@ void cpu_interrupt(CPUState *env, int mask)
qemu_cpu_kick(env);
return;
}
-#endif
if (use_icount) {
env->icount_decr.u16.high = 0xffff;
-#ifndef CONFIG_USER_ONLY
if (!can_do_io(env)
&& (mask & ~old_mask) != 0) {
cpu_abort(env, "Raised interrupt while not in I/O function");
}
-#endif
} else {
cpu_unlink_tb(env);
}
}
+CPUInterruptHandler cpu_interrupt_handler = tcg_handle_interrupt;
+
+#else /* CONFIG_USER_ONLY */
+
+void cpu_interrupt(CPUState *env, int mask)
+{
+ env->interrupt_request |= mask;
+ cpu_unlink_tb(env);
+}
+#endif /* CONFIG_USER_ONLY */
+
void cpu_reset_interrupt(CPUState *env, int mask)
{
env->interrupt_request &= ~mask;
@@ -3290,7 +3297,7 @@ static void check_watchpoint(int offset, int len_mask, int flags)
cpu_abort(env, "check_watchpoint: could not find TB for "
"pc=%p", (void *)env->mem_io_pc);
}
- cpu_restore_state(tb, env, env->mem_io_pc, NULL);
+ cpu_restore_state(tb, env, env->mem_io_pc);
tb_phys_invalidate(tb, -1);
if (wp->flags & BP_STOP_BEFORE_ACCESS) {
env->exception_index = EXCP_DEBUG;
@@ -4334,7 +4341,7 @@ void cpu_io_recompile(CPUState *env, void *retaddr)
retaddr);
}
n = env->icount_decr.u16.low + tb->icount;
- cpu_restore_state(tb, env, (unsigned long)retaddr, NULL);
+ cpu_restore_state(tb, env, (unsigned long)retaddr);
/* Calculate how many instructions had been executed before the fault
occurred. */
n = n - env->icount_decr.u16.low;
diff --git a/fpu/softfloat-macros.h b/fpu/softfloat-macros.h
index 3128e60cb..e82ce2332 100644
--- a/fpu/softfloat-macros.h
+++ b/fpu/softfloat-macros.h
@@ -36,6 +36,17 @@ these four paragraphs for those parts of this code that are retained.
=============================================================================*/
/*----------------------------------------------------------------------------
+| This macro tests for minimum version of the GNU C compiler.
+*----------------------------------------------------------------------------*/
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define SOFTFLOAT_GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+# define SOFTFLOAT_GNUC_PREREQ(maj, min) 0
+#endif
+
+
+/*----------------------------------------------------------------------------
| Shifts `a' right by the number of bits given in `count'. If any nonzero
| bits are shifted off, they are ``jammed'' into the least significant bit of
| the result by setting the least significant bit to 1. The value of `count'
@@ -616,6 +627,13 @@ static uint32_t estimateSqrt32( int16 aExp, uint32_t a )
static int8 countLeadingZeros32( uint32_t a )
{
+#if SOFTFLOAT_GNUC_PREREQ(3, 4)
+ if (a) {
+ return __builtin_clz(a);
+ } else {
+ return 32;
+ }
+#else
static const int8 countLeadingZerosHigh[] = {
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
@@ -647,7 +665,7 @@ static int8 countLeadingZeros32( uint32_t a )
}
shiftCount += countLeadingZerosHigh[ a>>24 ];
return shiftCount;
-
+#endif
}
/*----------------------------------------------------------------------------
@@ -657,6 +675,13 @@ static int8 countLeadingZeros32( uint32_t a )
static int8 countLeadingZeros64( uint64_t a )
{
+#if SOFTFLOAT_GNUC_PREREQ(3, 4)
+ if (a) {
+ return __builtin_clzll(a);
+ } else {
+ return 64;
+ }
+#else
int8 shiftCount;
shiftCount = 0;
@@ -668,7 +693,7 @@ static int8 countLeadingZeros64( uint64_t a )
}
shiftCount += countLeadingZeros32( a );
return shiftCount;
-
+#endif
}
/*----------------------------------------------------------------------------
diff --git a/fpu/softfloat-native.c b/fpu/softfloat-native.c
index a47b0d48e..3bb38860a 100644
--- a/fpu/softfloat-native.c
+++ b/fpu/softfloat-native.c
@@ -264,6 +264,15 @@ int float32_is_quiet_nan( float32 a1 )
return ( 0xFF800000 < ( a<<1 ) );
}
+int float32_is_any_nan( float32 a1 )
+{
+ float32u u;
+ uint32_t a;
+ u.f = a1;
+ a = u.i;
+ return (a & ~(1 << 31)) > 0x7f800000U;
+}
+
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
@@ -423,6 +432,16 @@ int float64_is_quiet_nan( float64 a1 )
}
+int float64_is_any_nan( float64 a1 )
+{
+ float64u u;
+ uint64_t a;
+ u.f = a1;
+ a = u.i;
+
+ return (a & ~(1ULL << 63)) > LIT64 (0x7FF0000000000000 );
+}
+
#ifdef FLOATX80
/*----------------------------------------------------------------------------
@@ -512,4 +531,11 @@ int floatx80_is_quiet_nan( floatx80 a1 )
return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (uint64_t) ( u.i.low<<1 );
}
+int floatx80_is_any_nan( floatx80 a1 )
+{
+ floatx80u u;
+ u.f = a1;
+ return ((u.i.high & 0x7FFF) == 0x7FFF) && ( u.i.low<<1 );
+}
+
#endif
diff --git a/fpu/softfloat-native.h b/fpu/softfloat-native.h
index 80b5f288e..6afb74a15 100644
--- a/fpu/softfloat-native.h
+++ b/fpu/softfloat-native.h
@@ -172,6 +172,15 @@ float128 int64_to_float128( int64_t STATUS_PARAM);
#endif
/*----------------------------------------------------------------------------
+| Software IEC/IEEE single-precision conversion constants.
+*----------------------------------------------------------------------------*/
+#define float32_zero (0.0)
+#define float32_one (1.0)
+#define float32_ln2 (0.6931471)
+#define float32_pi (3.1415926)
+#define float32_half (0.5)
+
+/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
int float32_to_int32( float32 STATUS_PARAM);
@@ -210,7 +219,7 @@ INLINE float32 float32_div( float32 a, float32 b STATUS_PARAM)
}
float32 float32_rem( float32, float32 STATUS_PARAM);
float32 float32_sqrt( float32 STATUS_PARAM);
-INLINE int float32_eq( float32 a, float32 b STATUS_PARAM)
+INLINE int float32_eq_quiet( float32 a, float32 b STATUS_PARAM)
{
return a == b;
}
@@ -222,7 +231,7 @@ INLINE int float32_lt( float32 a, float32 b STATUS_PARAM)
{
return a < b;
}
-INLINE int float32_eq_signaling( float32 a, float32 b STATUS_PARAM)
+INLINE int float32_eq( float32 a, float32 b STATUS_PARAM)
{
return a <= b && a >= b;
}
@@ -237,12 +246,16 @@ INLINE int float32_lt_quiet( float32 a, float32 b STATUS_PARAM)
INLINE int float32_unordered( float32 a, float32 b STATUS_PARAM)
{
return isunordered(a, b);
-
+}
+INLINE int float32_unordered_quiet( float32 a, float32 b STATUS_PARAM)
+{
+ return isunordered(a, b);
}
int float32_compare( float32, float32 STATUS_PARAM );
int float32_compare_quiet( float32, float32 STATUS_PARAM );
int float32_is_signaling_nan( float32 );
int float32_is_quiet_nan( float32 );
+int float32_is_any_nan( float32 );
INLINE float32 float32_abs(float32 a)
{
@@ -271,12 +284,21 @@ INLINE float32 float32_is_zero(float32 a)
return fpclassify(a) == FP_ZERO;
}
-INLINE float32 float32_scalbn(float32 a, int n)
+INLINE float32 float32_scalbn(float32 a, int n STATUS_PARAM)
{
return scalbnf(a, n);
}
/*----------------------------------------------------------------------------
+| Software IEC/IEEE double-precision conversion constants.
+*----------------------------------------------------------------------------*/
+#define float64_zero (0.0)
+#define float64_one (1.0)
+#define float64_ln2 (0.693147180559945)
+#define float64_pi (3.141592653589793)
+#define float64_half (0.5)
+
+/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
int float64_to_int32( float64 STATUS_PARAM );
@@ -318,7 +340,7 @@ INLINE float64 float64_div( float64 a, float64 b STATUS_PARAM)
}
float64 float64_rem( float64, float64 STATUS_PARAM );
float64 float64_sqrt( float64 STATUS_PARAM );
-INLINE int float64_eq( float64 a, float64 b STATUS_PARAM)
+INLINE int float64_eq_quiet( float64 a, float64 b STATUS_PARAM)
{
return a == b;
}
@@ -330,7 +352,7 @@ INLINE int float64_lt( float64 a, float64 b STATUS_PARAM)
{
return a < b;
}
-INLINE int float64_eq_signaling( float64 a, float64 b STATUS_PARAM)
+INLINE int float64_eq( float64 a, float64 b STATUS_PARAM)
{
return a <= b && a >= b;
}
@@ -346,11 +368,15 @@ INLINE int float64_lt_quiet( float64 a, float64 b STATUS_PARAM)
INLINE int float64_unordered( float64 a, float64 b STATUS_PARAM)
{
return isunordered(a, b);
-
+}
+INLINE int float64_unordered_quiet( float64 a, float64 b STATUS_PARAM)
+{
+ return isunordered(a, b);
}
int float64_compare( float64, float64 STATUS_PARAM );
int float64_compare_quiet( float64, float64 STATUS_PARAM );
int float64_is_signaling_nan( float64 );
+int float64_is_any_nan( float64 );
int float64_is_quiet_nan( float64 );
INLINE float64 float64_abs(float64 a)
@@ -380,7 +406,7 @@ INLINE float64 float64_is_zero(float64 a)
return fpclassify(a) == FP_ZERO;
}
-INLINE float64 float64_scalbn(float64 a, int n)
+INLINE float64 float64_scalbn(float64 a, int n STATUS_PARAM)
{
return scalbn(a, n);
}
@@ -388,6 +414,15 @@ INLINE float64 float64_scalbn(float64 a, int n)
#ifdef FLOATX80
/*----------------------------------------------------------------------------
+| Software IEC/IEEE extended double-precision conversion constants.
+*----------------------------------------------------------------------------*/
+#define floatx80_zero (0.0L)
+#define floatx80_one (1.0L)
+#define floatx80_ln2 (0.69314718055994530943L)
+#define floatx80_pi (3.14159265358979323851L)
+#define floatx80_half (0.5L)
+
+/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision conversion routines.
*----------------------------------------------------------------------------*/
int floatx80_to_int32( floatx80 STATUS_PARAM );
@@ -422,7 +457,7 @@ INLINE floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM)
}
floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
-INLINE int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
+INLINE int floatx80_eq_quiet( floatx80 a, floatx80 b STATUS_PARAM)
{
return a == b;
}
@@ -434,7 +469,7 @@ INLINE int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM)
{
return a < b;
}
-INLINE int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM)
+INLINE int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
{
return a <= b && a >= b;
}
@@ -450,12 +485,16 @@ INLINE int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM)
INLINE int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
{
return isunordered(a, b);
-
+}
+INLINE int floatx80_unordered_quiet( floatx80 a, floatx80 b STATUS_PARAM)
+{
+ return isunordered(a, b);
}
int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_is_signaling_nan( floatx80 );
int floatx80_is_quiet_nan( floatx80 );
+int floatx80_is_any_nan( floatx80 );
INLINE floatx80 floatx80_abs(floatx80 a)
{
@@ -484,7 +523,7 @@ INLINE floatx80 floatx80_is_zero(floatx80 a)
return fpclassify(a) == FP_ZERO;
}
-INLINE floatx80 floatx80_scalbn(floatx80 a, int n)
+INLINE floatx80 floatx80_scalbn(floatx80 a, int n STATUS_PARAM)
{
return scalbnl(a, n);
}
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index b1101872a..9d68aae9d 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -603,9 +603,15 @@ static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
commonNaNT z;
if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
- z.sign = a.high>>15;
- z.low = 0;
- z.high = a.low;
+ if ( a.low >> 63 ) {
+ z.sign = a.high >> 15;
+ z.low = 0;
+ z.high = a.low << 1;
+ } else {
+ z.sign = floatx80_default_nan_high >> 15;
+ z.low = 0;
+ z.high = floatx80_default_nan_low << 1;
+ }
return z;
}
@@ -624,11 +630,14 @@ static floatx80 commonNaNToFloatx80( commonNaNT a STATUS_PARAM)
return z;
}
- if (a.high)
- z.low = a.high;
- else
+ if (a.high >> 1) {
+ z.low = LIT64( 0x8000000000000000 ) | a.high >> 1;
+ z.high = ( ( (uint16_t) a.sign )<<15 ) | 0x7FFF;
+ } else {
z.low = floatx80_default_nan_low;
- z.high = ( ( (uint16_t) a.sign )<<15 ) | 0x7FFF;
+ z.high = floatx80_default_nan_high;
+ }
+
return z;
}
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 03fb9487b..baba1dc44 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2314,33 +2314,33 @@ float32 float32_log2( float32 a STATUS_PARAM )
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise. The comparison is performed
+| the corresponding value `b', and 0 otherwise. The invalid exception is
+| raised if either operand is a NaN. Otherwise, the comparison is performed
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
int float32_eq( float32 a, float32 b STATUS_PARAM )
{
+ uint32_t av, bv;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
) {
- if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
- float_raise( float_flag_invalid STATUS_VAR);
- }
+ float_raise( float_flag_invalid STATUS_VAR);
return 0;
}
- return ( float32_val(a) == float32_val(b) ) ||
- ( (uint32_t) ( ( float32_val(a) | float32_val(b) )<<1 ) == 0 );
-
+ av = float32_val(a);
+ bv = float32_val(b);
+ return ( av == bv ) || ( (uint32_t) ( ( av | bv )<<1 ) == 0 );
}
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is less than
-| or equal to the corresponding value `b', and 0 otherwise. The comparison
-| is performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
+| or equal to the corresponding value `b', and 0 otherwise. The invalid
+| exception is raised if either operand is a NaN. The comparison is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
int float32_le( float32 a, float32 b STATUS_PARAM )
@@ -2367,8 +2367,9 @@ int float32_le( float32 a, float32 b STATUS_PARAM )
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is less than
-| the corresponding value `b', and 0 otherwise. The comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| the corresponding value `b', and 0 otherwise. The invalid exception is
+| raised if either operand is a NaN. The comparison is performed according
+| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
int float32_lt( float32 a, float32 b STATUS_PARAM )
@@ -2394,15 +2395,14 @@ int float32_lt( float32 a, float32 b STATUS_PARAM )
}
/*----------------------------------------------------------------------------
-| Returns 1 if the single-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise. The invalid exception is
-| raised if either operand is a NaN. Otherwise, the comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| Returns 1 if the single-precision floating-point values `a' and `b' cannot
+| be compared, and 0 otherwise. The invalid exception is raised if either
+| operand is a NaN. The comparison is performed according to the IEC/IEEE
+| Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-int float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
+int float32_unordered( float32 a, float32 b STATUS_PARAM )
{
- uint32_t av, bv;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
@@ -2410,12 +2410,33 @@ int float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
) {
float_raise( float_flag_invalid STATUS_VAR);
- return 0;
+ return 1;
}
- av = float32_val(a);
- bv = float32_val(b);
- return ( av == bv ) || ( (uint32_t) ( ( av | bv )<<1 ) == 0 );
+ return 0;
+}
+/*----------------------------------------------------------------------------
+| Returns 1 if the single-precision floating-point value `a' is equal to
+| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
+| exception. The comparison is performed according to the IEC/IEEE Standard
+| for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+int float32_eq_quiet( float32 a, float32 b STATUS_PARAM )
+{
+ a = float32_squash_input_denormal(a STATUS_VAR);
+ b = float32_squash_input_denormal(b STATUS_VAR);
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid STATUS_VAR);
+ }
+ return 0;
+ }
+ return ( float32_val(a) == float32_val(b) ) ||
+ ( (uint32_t) ( ( float32_val(a) | float32_val(b) )<<1 ) == 0 );
}
/*----------------------------------------------------------------------------
@@ -2481,6 +2502,29 @@ int float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
}
/*----------------------------------------------------------------------------
+| Returns 1 if the single-precision floating-point values `a' and `b' cannot
+| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The
+| comparison is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+int float32_unordered_quiet( float32 a, float32 b STATUS_PARAM )
+{
+ a = float32_squash_input_denormal(a STATUS_VAR);
+ b = float32_squash_input_denormal(b STATUS_VAR);
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid STATUS_VAR);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
| Returns the result of converting the double-precision floating-point value
| `a' to the 32-bit two's complement integer format. The conversion is
| performed according to the IEC/IEEE Standard for Binary Floating-Point
@@ -3536,7 +3580,8 @@ float64 float64_log2( float64 a STATUS_PARAM )
/*----------------------------------------------------------------------------
| Returns 1 if the double-precision floating-point value `a' is equal to the
-| corresponding value `b', and 0 otherwise. The comparison is performed
+| corresponding value `b', and 0 otherwise. The invalid exception is raised
+| if either operand is a NaN. Otherwise, the comparison is performed
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
@@ -3549,9 +3594,7 @@ int float64_eq( float64 a, float64 b STATUS_PARAM )
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
) {
- if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
- float_raise( float_flag_invalid STATUS_VAR);
- }
+ float_raise( float_flag_invalid STATUS_VAR);
return 0;
}
av = float64_val(a);
@@ -3562,9 +3605,9 @@ int float64_eq( float64 a, float64 b STATUS_PARAM )
/*----------------------------------------------------------------------------
| Returns 1 if the double-precision floating-point value `a' is less than or
-| equal to the corresponding value `b', and 0 otherwise. The comparison is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
+| equal to the corresponding value `b', and 0 otherwise. The invalid
+| exception is raised if either operand is a NaN. The comparison is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
int float64_le( float64 a, float64 b STATUS_PARAM )
@@ -3591,8 +3634,9 @@ int float64_le( float64 a, float64 b STATUS_PARAM )
/*----------------------------------------------------------------------------
| Returns 1 if the double-precision floating-point value `a' is less than
-| the corresponding value `b', and 0 otherwise. The comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| the corresponding value `b', and 0 otherwise. The invalid exception is
+| raised if either operand is a NaN. The comparison is performed according
+| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
int float64_lt( float64 a, float64 b STATUS_PARAM )
@@ -3618,13 +3662,34 @@ int float64_lt( float64 a, float64 b STATUS_PARAM )
}
/*----------------------------------------------------------------------------
+| Returns 1 if the double-precision floating-point values `a' and `b' cannot
+| be compared, and 0 otherwise. The invalid exception is raised if either
+| operand is a NaN. The comparison is performed according to the IEC/IEEE
+| Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+int float64_unordered( float64 a, float64 b STATUS_PARAM )
+{
+ a = float64_squash_input_denormal(a STATUS_VAR);
+ b = float64_squash_input_denormal(b STATUS_VAR);
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+ ) {
+ float_raise( float_flag_invalid STATUS_VAR);
+ return 1;
+ }
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
| Returns 1 if the double-precision floating-point value `a' is equal to the
-| corresponding value `b', and 0 otherwise. The invalid exception is raised
-| if either operand is a NaN. Otherwise, the comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
+| exception.The comparison is performed according to the IEC/IEEE Standard
+| for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-int float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
+int float64_eq_quiet( float64 a, float64 b STATUS_PARAM )
{
uint64_t av, bv;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -3633,7 +3698,9 @@ int float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
) {
- float_raise( float_flag_invalid STATUS_VAR);
+ if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid STATUS_VAR);
+ }
return 0;
}
av = float64_val(a);
@@ -3704,6 +3771,29 @@ int float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
}
+/*----------------------------------------------------------------------------
+| Returns 1 if the double-precision floating-point values `a' and `b' cannot
+| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The
+| comparison is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+int float64_unordered_quiet( float64 a, float64 b STATUS_PARAM )
+{
+ a = float64_squash_input_denormal(a STATUS_VAR);
+ b = float64_squash_input_denormal(b STATUS_VAR);
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+ ) {
+ if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid STATUS_VAR);
+ }
+ return 1;
+ }
+ return 0;
+}
+
#ifdef FLOATX80
/*----------------------------------------------------------------------------
@@ -4501,10 +4591,10 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM )
}
/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is
-| equal to the corresponding value `b', and 0 otherwise. The comparison is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
+| Returns 1 if the extended double-precision floating-point value `a' is equal
+| to the corresponding value `b', and 0 otherwise. The invalid exception is
+| raised if either operand is a NaN. Otherwise, the comparison is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
@@ -4515,10 +4605,7 @@ int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
) {
- if ( floatx80_is_signaling_nan( a )
- || floatx80_is_signaling_nan( b ) ) {
- float_raise( float_flag_invalid STATUS_VAR);
- }
+ float_raise( float_flag_invalid STATUS_VAR);
return 0;
}
return
@@ -4533,8 +4620,9 @@ int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is
| less than or equal to the corresponding value `b', and 0 otherwise. The
-| comparison is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
+| invalid exception is raised if either operand is a NaN. The comparison is
+| performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic.
*----------------------------------------------------------------------------*/
int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
@@ -4565,9 +4653,9 @@ int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is
-| less than the corresponding value `b', and 0 otherwise. The comparison
-| is performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
+| less than the corresponding value `b', and 0 otherwise. The invalid
+| exception is raised if either operand is a NaN. The comparison is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
@@ -4597,13 +4685,32 @@ int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
}
/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is equal
-| to the corresponding value `b', and 0 otherwise. The invalid exception is
-| raised if either operand is a NaN. Otherwise, the comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| Returns 1 if the extended double-precision floating-point values `a' and `b'
+| cannot be compared, and 0 otherwise. The invalid exception is raised if
+| either operand is a NaN. The comparison is performed according to the
+| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM )
+{
+ if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
+ && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
+ || ( ( extractFloatx80Exp( b ) == 0x7FFF )
+ && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
+ ) {
+ float_raise( float_flag_invalid STATUS_VAR);
+ return 1;
+ }
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the extended double-precision floating-point value `a' is
+| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
+| cause an exception. The comparison is performed according to the IEC/IEEE
+| Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM )
+int floatx80_eq_quiet( floatx80 a, floatx80 b STATUS_PARAM )
{
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
@@ -4611,7 +4718,10 @@ int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
) {
- float_raise( float_flag_invalid STATUS_VAR);
+ if ( floatx80_is_signaling_nan( a )
+ || floatx80_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid STATUS_VAR);
+ }
return 0;
}
return
@@ -4695,6 +4805,28 @@ int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM )
}
+/*----------------------------------------------------------------------------
+| Returns 1 if the extended double-precision floating-point values `a' and `b'
+| cannot be compared, and 0 otherwise. Quiet NaNs do not cause an exception.
+| The comparison is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+int floatx80_unordered_quiet( floatx80 a, floatx80 b STATUS_PARAM )
+{
+ if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
+ && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
+ || ( ( extractFloatx80Exp( b ) == 0x7FFF )
+ && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
+ ) {
+ if ( floatx80_is_signaling_nan( a )
+ || floatx80_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid STATUS_VAR);
+ }
+ return 1;
+ }
+ return 0;
+}
+
#endif
#ifdef FLOAT128
@@ -5625,7 +5757,8 @@ float128 float128_sqrt( float128 a STATUS_PARAM )
/*----------------------------------------------------------------------------
| Returns 1 if the quadruple-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise. The comparison is performed
+| the corresponding value `b', and 0 otherwise. The invalid exception is
+| raised if either operand is a NaN. Otherwise, the comparison is performed
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
@@ -5637,10 +5770,7 @@ int float128_eq( float128 a, float128 b STATUS_PARAM )
|| ( ( extractFloat128Exp( b ) == 0x7FFF )
&& ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
) {
- if ( float128_is_signaling_nan( a )
- || float128_is_signaling_nan( b ) ) {
- float_raise( float_flag_invalid STATUS_VAR);
- }
+ float_raise( float_flag_invalid STATUS_VAR);
return 0;
}
return
@@ -5654,9 +5784,9 @@ int float128_eq( float128 a, float128 b STATUS_PARAM )
/*----------------------------------------------------------------------------
| Returns 1 if the quadruple-precision floating-point value `a' is less than
-| or equal to the corresponding value `b', and 0 otherwise. The comparison
-| is performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
+| or equal to the corresponding value `b', and 0 otherwise. The invalid
+| exception is raised if either operand is a NaN. The comparison is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
int float128_le( float128 a, float128 b STATUS_PARAM )
@@ -5687,8 +5817,9 @@ int float128_le( float128 a, float128 b STATUS_PARAM )
/*----------------------------------------------------------------------------
| Returns 1 if the quadruple-precision floating-point value `a' is less than
-| the corresponding value `b', and 0 otherwise. The comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| the corresponding value `b', and 0 otherwise. The invalid exception is
+| raised if either operand is a NaN. The comparison is performed according
+| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
int float128_lt( float128 a, float128 b STATUS_PARAM )
@@ -5718,13 +5849,33 @@ int float128_lt( float128 a, float128 b STATUS_PARAM )
}
/*----------------------------------------------------------------------------
+| Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot
+| be compared, and 0 otherwise. The invalid exception is raised if either
+| operand is a NaN. The comparison is performed according to the IEC/IEEE
+| Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+int float128_unordered( float128 a, float128 b STATUS_PARAM )
+{
+ if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
+ && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+ || ( ( extractFloat128Exp( b ) == 0x7FFF )
+ && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+ ) {
+ float_raise( float_flag_invalid STATUS_VAR);
+ return 1;
+ }
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
| Returns 1 if the quadruple-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise. The invalid exception is
-| raised if either operand is a NaN. Otherwise, the comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
+| exception. The comparison is performed according to the IEC/IEEE Standard
+| for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-int float128_eq_signaling( float128 a, float128 b STATUS_PARAM )
+int float128_eq_quiet( float128 a, float128 b STATUS_PARAM )
{
if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
@@ -5732,7 +5883,10 @@ int float128_eq_signaling( float128 a, float128 b STATUS_PARAM )
|| ( ( extractFloat128Exp( b ) == 0x7FFF )
&& ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
) {
- float_raise( float_flag_invalid STATUS_VAR);
+ if ( float128_is_signaling_nan( a )
+ || float128_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid STATUS_VAR);
+ }
return 0;
}
return
@@ -5816,6 +5970,29 @@ int float128_lt_quiet( float128 a, float128 b STATUS_PARAM )
}
+/*----------------------------------------------------------------------------
+| Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot
+| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The
+| comparison is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+int float128_unordered_quiet( float128 a, float128 b STATUS_PARAM )
+{
+ if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
+ && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+ || ( ( extractFloat128Exp( b ) == 0x7FFF )
+ && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+ ) {
+ if ( float128_is_signaling_nan( a )
+ || float128_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid STATUS_VAR);
+ }
+ return 1;
+ }
+ return 0;
+}
+
#endif
/* misc functions */
@@ -6013,6 +6190,52 @@ int float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \
COMPARE(32, 0xff)
COMPARE(64, 0x7ff)
+INLINE int floatx80_compare_internal( floatx80 a, floatx80 b,
+ int is_quiet STATUS_PARAM )
+{
+ flag aSign, bSign;
+
+ if (( ( extractFloatx80Exp( a ) == 0x7fff ) &&
+ ( extractFloatx80Frac( a )<<1 ) ) ||
+ ( ( extractFloatx80Exp( b ) == 0x7fff ) &&
+ ( extractFloatx80Frac( b )<<1 ) )) {
+ if (!is_quiet ||
+ floatx80_is_signaling_nan( a ) ||
+ floatx80_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid STATUS_VAR);
+ }
+ return float_relation_unordered;
+ }
+ aSign = extractFloatx80Sign( a );
+ bSign = extractFloatx80Sign( b );
+ if ( aSign != bSign ) {
+
+ if ( ( ( (uint16_t) ( ( a.high | b.high ) << 1 ) ) == 0) &&
+ ( ( a.low | b.low ) == 0 ) ) {
+ /* zero case */
+ return float_relation_equal;
+ } else {
+ return 1 - (2 * aSign);
+ }
+ } else {
+ if (a.low == b.low && a.high == b.high) {
+ return float_relation_equal;
+ } else {
+ return 1 - 2 * (aSign ^ ( lt128( a.high, a.low, b.high, b.low ) ));
+ }
+ }
+}
+
+int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
+{
+ return floatx80_compare_internal(a, b, 0 STATUS_VAR);
+}
+
+int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
+{
+ return floatx80_compare_internal(a, b, 1 STATUS_VAR);
+}
+
INLINE int float128_compare_internal( float128 a, float128 b,
int is_quiet STATUS_PARAM )
{
@@ -6110,7 +6333,7 @@ MINMAX(64, 0x7ff)
float32 float32_scalbn( float32 a, int n STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int16_t aExp;
uint32_t aSig;
a = float32_squash_input_denormal(a STATUS_VAR);
@@ -6119,6 +6342,9 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
aSign = extractFloat32Sign( a );
if ( aExp == 0xFF ) {
+ if ( aSig ) {
+ return propagateFloat32NaN( a, a STATUS_VAR );
+ }
return a;
}
if ( aExp != 0 )
@@ -6126,6 +6352,12 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
else if ( aSig == 0 )
return a;
+ if (n > 0x200) {
+ n = 0x200;
+ } else if (n < -0x200) {
+ n = -0x200;
+ }
+
aExp += n - 1;
aSig <<= 7;
return normalizeRoundAndPackFloat32( aSign, aExp, aSig STATUS_VAR );
@@ -6134,7 +6366,7 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
float64 float64_scalbn( float64 a, int n STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int16_t aExp;
uint64_t aSig;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -6143,6 +6375,9 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
aSign = extractFloat64Sign( a );
if ( aExp == 0x7FF ) {
+ if ( aSig ) {
+ return propagateFloat64NaN( a, a STATUS_VAR );
+ }
return a;
}
if ( aExp != 0 )
@@ -6150,6 +6385,12 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
else if ( aSig == 0 )
return a;
+ if (n > 0x1000) {
+ n = 0x1000;
+ } else if (n < -0x1000) {
+ n = -0x1000;
+ }
+
aExp += n - 1;
aSig <<= 10;
return normalizeRoundAndPackFloat64( aSign, aExp, aSig STATUS_VAR );
@@ -6159,19 +6400,29 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int32_t aExp;
uint64_t aSig;
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
- if ( aExp == 0x7FF ) {
+ if ( aExp == 0x7FFF ) {
+ if ( aSig<<1 ) {
+ return propagateFloatx80NaN( a, a STATUS_VAR );
+ }
return a;
}
+
if (aExp == 0 && aSig == 0)
return a;
+ if (n > 0x10000) {
+ n = 0x10000;
+ } else if (n < -0x10000) {
+ n = -0x10000;
+ }
+
aExp += n;
return normalizeRoundAndPackFloatx80( STATUS(floatx80_rounding_precision),
aSign, aExp, aSig, 0 STATUS_VAR );
@@ -6182,7 +6433,7 @@ floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
float128 float128_scalbn( float128 a, int n STATUS_PARAM )
{
flag aSign;
- int32 aExp;
+ int32_t aExp;
uint64_t aSig0, aSig1;
aSig1 = extractFloat128Frac1( a );
@@ -6190,6 +6441,9 @@ float128 float128_scalbn( float128 a, int n STATUS_PARAM )
aExp = extractFloat128Exp( a );
aSign = extractFloat128Sign( a );
if ( aExp == 0x7FFF ) {
+ if ( aSig0 | aSig1 ) {
+ return propagateFloat128NaN( a, a STATUS_VAR );
+ }
return a;
}
if ( aExp != 0 )
@@ -6197,6 +6451,12 @@ float128 float128_scalbn( float128 a, int n STATUS_PARAM )
else if ( aSig0 == 0 && aSig1 == 0 )
return a;
+ if (n > 0x10000) {
+ n = 0x10000;
+ } else if (n < -0x10000) {
+ n = -0x10000;
+ }
+
aExp += n - 1;
return normalizeRoundAndPackFloat128( aSign, aExp, aSig0, aSig1
STATUS_VAR );
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index c7654d4c6..5eff0858f 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -154,6 +154,7 @@ typedef struct {
uint64_t low;
uint16_t high;
} floatx80;
+#define make_floatx80(exp, mant) ((floatx80) { mant, exp })
#endif
#ifdef FLOAT128
typedef struct {
@@ -323,9 +324,11 @@ float32 float32_log2( float32 STATUS_PARAM );
int float32_eq( float32, float32 STATUS_PARAM );
int float32_le( float32, float32 STATUS_PARAM );
int float32_lt( float32, float32 STATUS_PARAM );
-int float32_eq_signaling( float32, float32 STATUS_PARAM );
+int float32_unordered( float32, float32 STATUS_PARAM );
+int float32_eq_quiet( float32, float32 STATUS_PARAM );
int float32_le_quiet( float32, float32 STATUS_PARAM );
int float32_lt_quiet( float32, float32 STATUS_PARAM );
+int float32_unordered_quiet( float32, float32 STATUS_PARAM );
int float32_compare( float32, float32 STATUS_PARAM );
int float32_compare_quiet( float32, float32 STATUS_PARAM );
float32 float32_min(float32, float32 STATUS_PARAM);
@@ -384,6 +387,7 @@ INLINE float32 float32_set_sign(float32 a, int sign)
#define float32_zero make_float32(0)
#define float32_one make_float32(0x3f800000)
#define float32_ln2 make_float32(0x3f317218)
+#define float32_pi make_float32(0x40490fdb)
#define float32_half make_float32(0x3f000000)
#define float32_infinity make_float32(0x7f800000)
@@ -437,9 +441,11 @@ float64 float64_log2( float64 STATUS_PARAM );
int float64_eq( float64, float64 STATUS_PARAM );
int float64_le( float64, float64 STATUS_PARAM );
int float64_lt( float64, float64 STATUS_PARAM );
-int float64_eq_signaling( float64, float64 STATUS_PARAM );
+int float64_unordered( float64, float64 STATUS_PARAM );
+int float64_eq_quiet( float64, float64 STATUS_PARAM );
int float64_le_quiet( float64, float64 STATUS_PARAM );
int float64_lt_quiet( float64, float64 STATUS_PARAM );
+int float64_unordered_quiet( float64, float64 STATUS_PARAM );
int float64_compare( float64, float64 STATUS_PARAM );
int float64_compare_quiet( float64, float64 STATUS_PARAM );
float64 float64_min(float64, float64 STATUS_PARAM);
@@ -494,6 +500,7 @@ INLINE float64 float64_set_sign(float64 a, int sign)
#define float64_zero make_float64(0)
#define float64_one make_float64(0x3ff0000000000000LL)
#define float64_ln2 make_float64(0x3fe62e42fefa39efLL)
+#define float64_pi make_float64(0x400921fb54442d18LL)
#define float64_half make_float64(0x3fe0000000000000LL)
#define float64_infinity make_float64(0x7ff0000000000000LL)
@@ -538,9 +545,13 @@ floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
int floatx80_eq( floatx80, floatx80 STATUS_PARAM );
int floatx80_le( floatx80, floatx80 STATUS_PARAM );
int floatx80_lt( floatx80, floatx80 STATUS_PARAM );
-int floatx80_eq_signaling( floatx80, floatx80 STATUS_PARAM );
+int floatx80_unordered( floatx80, floatx80 STATUS_PARAM );
+int floatx80_eq_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
+int floatx80_unordered_quiet( floatx80, floatx80 STATUS_PARAM );
+int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
+int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_is_quiet_nan( floatx80 );
int floatx80_is_signaling_nan( floatx80 );
floatx80 floatx80_maybe_silence_nan( floatx80 );
@@ -560,7 +571,7 @@ INLINE floatx80 floatx80_chs(floatx80 a)
INLINE int floatx80_is_infinity(floatx80 a)
{
- return (a.high & 0x7fff) == 0x7fff && a.low == 0;
+ return (a.high & 0x7fff) == 0x7fff && a.low == 0x8000000000000000LL;
}
INLINE int floatx80_is_neg(floatx80 a)
@@ -578,6 +589,13 @@ INLINE int floatx80_is_any_nan(floatx80 a)
return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
}
+#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
+#define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL)
+#define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL)
+#define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL)
+#define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL)
+#define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)
+
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN. The
| `high' and `low' values hold the most- and least-significant bits,
@@ -621,9 +639,11 @@ float128 float128_sqrt( float128 STATUS_PARAM );
int float128_eq( float128, float128 STATUS_PARAM );
int float128_le( float128, float128 STATUS_PARAM );
int float128_lt( float128, float128 STATUS_PARAM );
-int float128_eq_signaling( float128, float128 STATUS_PARAM );
+int float128_unordered( float128, float128 STATUS_PARAM );
+int float128_eq_quiet( float128, float128 STATUS_PARAM );
int float128_le_quiet( float128, float128 STATUS_PARAM );
int float128_lt_quiet( float128, float128 STATUS_PARAM );
+int float128_unordered_quiet( float128, float128 STATUS_PARAM );
int float128_compare( float128, float128 STATUS_PARAM );
int float128_compare_quiet( float128, float128 STATUS_PARAM );
int float128_is_quiet_nan( float128 );
diff --git a/hw/file-op-9p.h b/fsdev/file-op-9p.h
index 126e60e27..126e60e27 100644
--- a/hw/file-op-9p.h
+++ b/fsdev/file-op-9p.h
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
index a704043be..f9f08d3e1 100644
--- a/fsdev/qemu-fsdev.h
+++ b/fsdev/qemu-fsdev.h
@@ -13,7 +13,7 @@
#ifndef QEMU_FSDEV_H
#define QEMU_FSDEV_H
#include "qemu-option.h"
-#include "hw/file-op-9p.h"
+#include "file-op-9p.h"
/*
diff --git a/hw/virtio-9p-debug.c b/hw/9pfs/virtio-9p-debug.c
index 6b18842fd..6b18842fd 100644
--- a/hw/virtio-9p-debug.c
+++ b/hw/9pfs/virtio-9p-debug.c
diff --git a/hw/virtio-9p-debug.h b/hw/9pfs/virtio-9p-debug.h
index d9a249118..d9a249118 100644
--- a/hw/virtio-9p-debug.h
+++ b/hw/9pfs/virtio-9p-debug.h
diff --git a/hw/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index a8e7525bf..0a015de9a 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -370,7 +370,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
return fd;
}
/* Write the oldpath (target) to the file. */
- oldpath_size = strlen(oldpath) + 1;
+ oldpath_size = strlen(oldpath);
do {
write_size = write(fd, (void *)oldpath, oldpath_size);
} while (write_size == -1 && errno == EINTR);
diff --git a/hw/virtio-9p-posix-acl.c b/hw/9pfs/virtio-9p-posix-acl.c
index 3978d0cf7..575abe86b 100644
--- a/hw/virtio-9p-posix-acl.c
+++ b/hw/9pfs/virtio-9p-posix-acl.c
@@ -15,7 +15,7 @@
#include <attr/xattr.h>
#include "virtio.h"
#include "virtio-9p.h"
-#include "file-op-9p.h"
+#include "fsdev/file-op-9p.h"
#include "virtio-9p-xattr.h"
#define MAP_ACL_ACCESS "user.virtfs.system.posix_acl_access"
@@ -60,7 +60,7 @@ static int mp_pacl_removexattr(FsContext *ctx,
ret = lremovexattr(rpath(ctx, path), MAP_ACL_ACCESS);
if (ret == -1 && errno == ENODATA) {
/*
- * We don't get ENODATA error when trying to remote a
+ * We don't get ENODATA error when trying to remove a
* posix acl that is not present. So don't throw the error
* even in case of mapped security model
*/
@@ -103,7 +103,18 @@ static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
static int mp_dacl_removexattr(FsContext *ctx,
const char *path, const char *name)
{
- return lremovexattr(rpath(ctx, path), MAP_ACL_DEFAULT);
+ int ret;
+ ret = lremovexattr(rpath(ctx, path), MAP_ACL_DEFAULT);
+ if (ret == -1 && errno == ENODATA) {
+ /*
+ * We don't get ENODATA error when trying to remove a
+ * posix acl that is not present. So don't throw the error
+ * even in case of mapped security model
+ */
+ errno = 0;
+ ret = 0;
+ }
+ return ret;
}
diff --git a/hw/virtio-9p-xattr-user.c b/hw/9pfs/virtio-9p-xattr-user.c
index faa02a191..bba13ce64 100644
--- a/hw/virtio-9p-xattr-user.c
+++ b/hw/9pfs/virtio-9p-xattr-user.c
@@ -14,7 +14,7 @@
#include <sys/types.h>
#include "virtio.h"
#include "virtio-9p.h"
-#include "file-op-9p.h"
+#include "fsdev/file-op-9p.h"
#include "virtio-9p-xattr.h"
diff --git a/hw/virtio-9p-xattr.c b/hw/9pfs/virtio-9p-xattr.c
index 1aab081de..03c3d3f6b 100644
--- a/hw/virtio-9p-xattr.c
+++ b/hw/9pfs/virtio-9p-xattr.c
@@ -13,7 +13,7 @@
#include "virtio.h"
#include "virtio-9p.h"
-#include "file-op-9p.h"
+#include "fsdev/file-op-9p.h"
#include "virtio-9p-xattr.h"
diff --git a/hw/virtio-9p-xattr.h b/hw/9pfs/virtio-9p-xattr.h
index 2bbae2dcb..2bbae2dcb 100644
--- a/hw/virtio-9p-xattr.h
+++ b/hw/9pfs/virtio-9p-xattr.h
diff --git a/hw/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 7e2953567..b5fc52b3e 100644
--- a/hw/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -596,7 +596,10 @@ static V9fsPDU *alloc_pdu(V9fsState *s)
static void free_pdu(V9fsState *s, V9fsPDU *pdu)
{
if (pdu) {
- QLIST_INSERT_HEAD(&s->free_list, pdu, next);
+ if (debug_9p_pdu) {
+ pprint_pdu(pdu);
+ }
+ QLIST_INSERT_HEAD(&s->free_list, pdu, next);
}
}
@@ -1479,7 +1482,7 @@ static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err)
{
complete_pdu(s, vs->pdu, err);
- if (vs->nwnames) {
+ if (vs->nwnames && vs->nwnames <= P9_MAXWELEM) {
for (vs->name_idx = 0; vs->name_idx < vs->nwnames; vs->name_idx++) {
v9fs_string_free(&vs->wnames[vs->name_idx]);
}
@@ -1575,7 +1578,7 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "ddw", &fid,
&newfid, &vs->nwnames);
- if (vs->nwnames) {
+ if (vs->nwnames && vs->nwnames <= P9_MAXWELEM) {
vs->wnames = qemu_mallocz(sizeof(vs->wnames[0]) * vs->nwnames);
vs->qids = qemu_mallocz(sizeof(vs->qids[0]) * vs->nwnames);
@@ -1584,6 +1587,9 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "s",
&vs->wnames[i]);
}
+ } else if (vs->nwnames > P9_MAXWELEM) {
+ err = -EINVAL;
+ goto out;
}
vs->fidp = lookup_fid(s, fid);
@@ -1768,7 +1774,7 @@ static void v9fs_post_lcreate(V9fsState *s, V9fsLcreateState *vs, int err)
v9fs_string_copy(&vs->fidp->path, &vs->fullname);
stat_to_qid(&vs->stbuf, &vs->qid);
vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid,
- &vs->iounit);
+ vs->iounit);
err = vs->offset;
} else {
vs->fidp->fid_type = P9_FID_NONE;
diff --git a/hw/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 2ae4ce718..622928fce 100644
--- a/hw/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -6,7 +6,7 @@
#include <sys/time.h>
#include <utime.h>
-#include "file-op-9p.h"
+#include "fsdev/file-op-9p.h"
/* The feature bitmap for virtio 9P */
/* The mount point is specified in a config variable */
@@ -282,7 +282,7 @@ typedef struct V9fsStatStateDotl {
typedef struct V9fsWalkState {
V9fsPDU *pdu;
size_t offset;
- int16_t nwnames;
+ uint16_t nwnames;
int name_idx;
V9fsQID *qids;
V9fsFidState *fidp;
diff --git a/hw/adb.c b/hw/adb.c
index 99b30f6bc..7499cdcef 100644
--- a/hw/adb.c
+++ b/hw/adb.c
@@ -261,30 +261,19 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
return olen;
}
-static void adb_kbd_save(QEMUFile *f, void *opaque)
-{
- KBDState *s = (KBDState *)opaque;
-
- qemu_put_buffer(f, s->data, sizeof(s->data));
- qemu_put_sbe32s(f, &s->rptr);
- qemu_put_sbe32s(f, &s->wptr);
- qemu_put_sbe32s(f, &s->count);
-}
-
-static int adb_kbd_load(QEMUFile *f, void *opaque, int version_id)
-{
- KBDState *s = (KBDState *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_buffer(f, s->data, sizeof(s->data));
- qemu_get_sbe32s(f, &s->rptr);
- qemu_get_sbe32s(f, &s->wptr);
- qemu_get_sbe32s(f, &s->count);
-
- return 0;
-}
+static const VMStateDescription vmstate_adb_kbd = {
+ .name = "adb_kbd",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_BUFFER(data, KBDState),
+ VMSTATE_INT32(rptr, KBDState),
+ VMSTATE_INT32(wptr, KBDState),
+ VMSTATE_INT32(count, KBDState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int adb_kbd_reset(ADBDevice *d)
{
@@ -305,8 +294,7 @@ void adb_kbd_init(ADBBusState *bus)
d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
adb_kbd_reset, s);
qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
- register_savevm(NULL, "adb_kbd", -1, 1, adb_kbd_save,
- adb_kbd_load, s);
+ vmstate_register(NULL, -1, &vmstate_adb_kbd, s);
}
/***************************************************************/
@@ -439,32 +427,20 @@ static int adb_mouse_reset(ADBDevice *d)
return 0;
}
-static void adb_mouse_save(QEMUFile *f, void *opaque)
-{
- MouseState *s = (MouseState *)opaque;
-
- qemu_put_sbe32s(f, &s->buttons_state);
- qemu_put_sbe32s(f, &s->last_buttons_state);
- qemu_put_sbe32s(f, &s->dx);
- qemu_put_sbe32s(f, &s->dy);
- qemu_put_sbe32s(f, &s->dz);
-}
-
-static int adb_mouse_load(QEMUFile *f, void *opaque, int version_id)
-{
- MouseState *s = (MouseState *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_sbe32s(f, &s->buttons_state);
- qemu_get_sbe32s(f, &s->last_buttons_state);
- qemu_get_sbe32s(f, &s->dx);
- qemu_get_sbe32s(f, &s->dy);
- qemu_get_sbe32s(f, &s->dz);
-
- return 0;
-}
+static const VMStateDescription vmstate_adb_mouse = {
+ .name = "adb_mouse",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(buttons_state, MouseState),
+ VMSTATE_INT32(last_buttons_state, MouseState),
+ VMSTATE_INT32(dx, MouseState),
+ VMSTATE_INT32(dy, MouseState),
+ VMSTATE_INT32(dz, MouseState),
+ VMSTATE_END_OF_LIST()
+ }
+};
void adb_mouse_init(ADBBusState *bus)
{
@@ -475,6 +451,5 @@ void adb_mouse_init(ADBBusState *bus)
d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
adb_mouse_reset, s);
qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
- register_savevm(NULL, "adb_mouse", -1, 1, adb_mouse_save,
- adb_mouse_load, s);
+ vmstate_register(NULL, -1, &vmstate_adb_mouse, s);
}
diff --git a/hw/ads7846.c b/hw/ads7846.c
index b3bbeaf68..9c58a5f59 100644
--- a/hw/ads7846.c
+++ b/hw/ads7846.c
@@ -105,35 +105,30 @@ static void ads7846_ts_event(void *opaque,
}
}
-static void ads7846_save(QEMUFile *f, void *opaque)
+static int ads7856_post_load(void *opaque, int version_id)
{
- ADS7846State *s = (ADS7846State *) opaque;
- int i;
-
- for (i = 0; i < 8; i ++)
- qemu_put_be32(f, s->input[i]);
- qemu_put_be32(f, s->noise);
- qemu_put_be32(f, s->cycle);
- qemu_put_be32(f, s->output);
-}
-
-static int ads7846_load(QEMUFile *f, void *opaque, int version_id)
-{
- ADS7846State *s = (ADS7846State *) opaque;
- int i;
-
- for (i = 0; i < 8; i ++)
- s->input[i] = qemu_get_be32(f);
- s->noise = qemu_get_be32(f);
- s->cycle = qemu_get_be32(f);
- s->output = qemu_get_be32(f);
+ ADS7846State *s = opaque;
s->pressure = 0;
ads7846_int_update(s);
-
return 0;
}
+static const VMStateDescription vmstate_ads7846 = {
+ .name = "ads7846",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = ads7856_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32_ARRAY(input, ADS7846State, 8),
+ VMSTATE_INT32(noise, ADS7846State),
+ VMSTATE_INT32(cycle, ADS7846State),
+ VMSTATE_INT32(output, ADS7846State),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static int ads7846_init(SSISlave *dev)
{
ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, dev);
@@ -151,7 +146,7 @@ static int ads7846_init(SSISlave *dev)
ads7846_int_update(s);
- register_savevm(NULL, "ads7846", -1, 0, ads7846_save, ads7846_load, s);
+ vmstate_register(NULL, -1, &vmstate_ads7846, s);
return 0;
}
diff --git a/hw/an5206.c b/hw/an5206.c
index b9f19a994..42a0163fb 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -9,7 +9,6 @@
#include "hw.h"
#include "pc.h"
#include "mcf.h"
-#include "sysemu.h"
#include "boards.h"
#include "loader.h"
#include "elf.h"
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 41e99d133..bfac982e6 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -15,7 +15,7 @@
#define KERNEL_ARGS_ADDR 0x100
#define KERNEL_LOAD_ADDR 0x00010000
-#define INITRD_LOAD_ADDR 0x00800000
+#define INITRD_LOAD_ADDR 0x00d00000
/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */
static uint32_t bootloader[] = {
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 82f05dec8..dac9e7075 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -140,28 +140,19 @@ static void arm_timer_tick(void *opaque)
arm_timer_update(s);
}
-static void arm_timer_save(QEMUFile *f, void *opaque)
-{
- arm_timer_state *s = (arm_timer_state *)opaque;
- qemu_put_be32(f, s->control);
- qemu_put_be32(f, s->limit);
- qemu_put_be32(f, s->int_level);
- qemu_put_ptimer(f, s->timer);
-}
-
-static int arm_timer_load(QEMUFile *f, void *opaque, int version_id)
-{
- arm_timer_state *s = (arm_timer_state *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->control = qemu_get_be32(f);
- s->limit = qemu_get_be32(f);
- s->int_level = qemu_get_be32(f);
- qemu_get_ptimer(f, s->timer);
- return 0;
-}
+static const VMStateDescription vmstate_arm_timer = {
+ .name = "arm_timer",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(control, arm_timer_state),
+ VMSTATE_UINT32(limit, arm_timer_state),
+ VMSTATE_INT32(int_level, arm_timer_state),
+ VMSTATE_PTIMER(timer, arm_timer_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
static arm_timer_state *arm_timer_init(uint32_t freq)
{
@@ -174,7 +165,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
bh = qemu_bh_new(arm_timer_tick, s);
s->timer = ptimer_init(bh);
- register_savevm(NULL, "arm_timer", -1, 1, arm_timer_save, arm_timer_load, s);
+ vmstate_register(NULL, -1, &vmstate_arm_timer, s);
return s;
}
@@ -235,24 +226,17 @@ static CPUWriteMemoryFunc * const sp804_writefn[] = {
sp804_write
};
-static void sp804_save(QEMUFile *f, void *opaque)
-{
- sp804_state *s = (sp804_state *)opaque;
- qemu_put_be32(f, s->level[0]);
- qemu_put_be32(f, s->level[1]);
-}
-
-static int sp804_load(QEMUFile *f, void *opaque, int version_id)
-{
- sp804_state *s = (sp804_state *)opaque;
- if (version_id != 1)
- return -EINVAL;
-
- s->level[0] = qemu_get_be32(f);
- s->level[1] = qemu_get_be32(f);
- return 0;
-}
+static const VMStateDescription vmstate_sp804 = {
+ .name = "sp804",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32_ARRAY(level, sp804_state, 2),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int sp804_init(SysBusDevice *dev)
{
@@ -271,7 +255,7 @@ static int sp804_init(SysBusDevice *dev)
iomemtype = cpu_register_io_memory(sp804_readfn,
sp804_writefn, s, DEVICE_NATIVE_ENDIAN);
sysbus_init_mmio(dev, 0x1000, iomemtype);
- register_savevm(&dev->qdev, "sp804", -1, 1, sp804_save, sp804_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_sp804, s);
return 0;
}
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 304cd34bc..72d010a63 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -9,7 +9,6 @@
#include "sysbus.h"
#include "arm-misc.h"
-#include "sysemu.h"
#include "loader.h"
#include "elf.h"
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index ffe16b8a6..d06eec9b3 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -365,30 +365,19 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value)
}
}
-static void nvic_save(QEMUFile *f, void *opaque)
-{
- nvic_state *s = (nvic_state *)opaque;
-
- qemu_put_be32(f, s->systick.control);
- qemu_put_be32(f, s->systick.reload);
- qemu_put_be64(f, s->systick.tick);
- qemu_put_timer(f, s->systick.timer);
-}
-
-static int nvic_load(QEMUFile *f, void *opaque, int version_id)
-{
- nvic_state *s = (nvic_state *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->systick.control = qemu_get_be32(f);
- s->systick.reload = qemu_get_be32(f);
- s->systick.tick = qemu_get_be64(f);
- qemu_get_timer(f, s->systick.timer);
-
- return 0;
-}
+static const VMStateDescription vmstate_nvic = {
+ .name = "armv7m_nvic",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(systick.control, nvic_state),
+ VMSTATE_UINT32(systick.reload, nvic_state),
+ VMSTATE_INT64(systick.tick, nvic_state),
+ VMSTATE_TIMER(systick.timer, nvic_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int armv7m_nvic_init(SysBusDevice *dev)
{
@@ -397,7 +386,7 @@ static int armv7m_nvic_init(SysBusDevice *dev)
gic_init(&s->gic);
cpu_register_physical_memory(0xe000e000, 0x1000, s->gic.iomemtype);
s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
- register_savevm(&dev->qdev, "armv7m_nvic", -1, 1, nvic_save, nvic_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
return 0;
}
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 57b5e2f04..0e2135afd 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -26,7 +26,6 @@
#include "net.h"
#include "flash.h"
#include "boards.h"
-#include "sysemu.h"
#include "etraxfs.h"
#include "loader.h"
#include "elf.h"
diff --git a/hw/blizzard.c b/hw/blizzard.c
index 5f329ad13..c5245504a 100644
--- a/hw/blizzard.c
+++ b/hw/blizzard.c
@@ -19,7 +19,6 @@
*/
#include "qemu-common.h"
-#include "sysemu.h"
#include "console.h"
#include "devices.h"
#include "vga_int.h"
diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c
index 65ffa37fd..d135ef479 100644
--- a/hw/bt-hci-csr.c
+++ b/hw/bt-hci-csr.c
@@ -22,7 +22,6 @@
#include "qemu-char.h"
#include "qemu-timer.h"
#include "irq.h"
-#include "sysemu.h"
#include "net.h"
#include "bt.h"
diff --git a/hw/collie.c b/hw/collie.c
new file mode 100644
index 000000000..156404d9f
--- /dev/null
+++ b/hw/collie.c
@@ -0,0 +1,69 @@
+/*
+ * SA-1110-based Sharp Zaurus SL-5500 platform.
+ *
+ * Copyright (C) 2011 Dmitry Eremin-Solenikov
+ *
+ * This code is licensed under GNU GPL v2.
+ */
+#include "hw.h"
+#include "sysbus.h"
+#include "boards.h"
+#include "devices.h"
+#include "strongarm.h"
+#include "arm-misc.h"
+#include "flash.h"
+#include "blockdev.h"
+
+static struct arm_boot_info collie_binfo = {
+ .loader_start = SA_SDCS0,
+ .ram_size = 0x20000000,
+};
+
+static void collie_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)
+{
+ StrongARMState *s;
+ DriveInfo *dinfo;
+ ram_addr_t phys_flash;
+
+ if (!cpu_model) {
+ cpu_model = "sa1110";
+ }
+
+ s = sa1110_init(collie_binfo.ram_size, cpu_model);
+
+ phys_flash = qemu_ram_alloc(NULL, "collie.fl1", 0x02000000);
+ dinfo = drive_get(IF_PFLASH, 0, 0);
+ pflash_cfi01_register(SA_CS0, phys_flash,
+ dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+ 512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+
+ phys_flash = qemu_ram_alloc(NULL, "collie.fl2", 0x02000000);
+ dinfo = drive_get(IF_PFLASH, 0, 1);
+ pflash_cfi01_register(SA_CS1, phys_flash,
+ dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+ 512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+
+ sysbus_create_simple("scoop", 0x40800000, NULL);
+
+ collie_binfo.kernel_filename = kernel_filename;
+ collie_binfo.kernel_cmdline = kernel_cmdline;
+ collie_binfo.initrd_filename = initrd_filename;
+ collie_binfo.board_id = 0x208;
+ arm_load_kernel(s->env, &collie_binfo);
+}
+
+static QEMUMachine collie_machine = {
+ .name = "collie",
+ .desc = "Collie PDA (SA-1110)",
+ .init = collie_init,
+};
+
+static void collie_machine_init(void)
+{
+ qemu_register_machine(&collie_machine);
+}
+
+machine_init(collie_machine_init)
diff --git a/hw/cris-boot.c b/hw/cris-boot.c
index 2ef17f606..37894f8b5 100644
--- a/hw/cris-boot.c
+++ b/hw/cris-boot.c
@@ -23,7 +23,6 @@
*/
#include "hw.h"
-#include "sysemu.h"
#include "loader.h"
#include "elf.h"
#include "cris-boot.h"
diff --git a/hw/cuda.c b/hw/cuda.c
index 37aa3f47f..065c362ae 100644
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -644,80 +644,56 @@ static CPUReadMemoryFunc * const cuda_read[] = {
&cuda_readl,
};
-static void cuda_save_timer(QEMUFile *f, CUDATimer *s)
+static bool cuda_timer_exist(void *opaque, int version_id)
{
- qemu_put_be16s(f, &s->latch);
- qemu_put_be16s(f, &s->counter_value);
- qemu_put_sbe64s(f, &s->load_time);
- qemu_put_sbe64s(f, &s->next_irq_time);
- if (s->timer)
- qemu_put_timer(f, s->timer);
-}
-
-static void cuda_save(QEMUFile *f, void *opaque)
-{
- CUDAState *s = (CUDAState *)opaque;
-
- qemu_put_ubyte(f, s->b);
- qemu_put_ubyte(f, s->a);
- qemu_put_ubyte(f, s->dirb);
- qemu_put_ubyte(f, s->dira);
- qemu_put_ubyte(f, s->sr);
- qemu_put_ubyte(f, s->acr);
- qemu_put_ubyte(f, s->pcr);
- qemu_put_ubyte(f, s->ifr);
- qemu_put_ubyte(f, s->ier);
- qemu_put_ubyte(f, s->anh);
- qemu_put_sbe32s(f, &s->data_in_size);
- qemu_put_sbe32s(f, &s->data_in_index);
- qemu_put_sbe32s(f, &s->data_out_index);
- qemu_put_ubyte(f, s->autopoll);
- qemu_put_buffer(f, s->data_in, sizeof(s->data_in));
- qemu_put_buffer(f, s->data_out, sizeof(s->data_out));
- qemu_put_be32s(f, &s->tick_offset);
- cuda_save_timer(f, &s->timers[0]);
- cuda_save_timer(f, &s->timers[1]);
-}
+ CUDATimer *s = opaque;
-static void cuda_load_timer(QEMUFile *f, CUDATimer *s)
-{
- qemu_get_be16s(f, &s->latch);
- qemu_get_be16s(f, &s->counter_value);
- qemu_get_sbe64s(f, &s->load_time);
- qemu_get_sbe64s(f, &s->next_irq_time);
- if (s->timer)
- qemu_get_timer(f, s->timer);
+ return s->timer != NULL;
}
-static int cuda_load(QEMUFile *f, void *opaque, int version_id)
-{
- CUDAState *s = (CUDAState *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->b = qemu_get_ubyte(f);
- s->a = qemu_get_ubyte(f);
- s->dirb = qemu_get_ubyte(f);
- s->dira = qemu_get_ubyte(f);
- s->sr = qemu_get_ubyte(f);
- s->acr = qemu_get_ubyte(f);
- s->pcr = qemu_get_ubyte(f);
- s->ifr = qemu_get_ubyte(f);
- s->ier = qemu_get_ubyte(f);
- s->anh = qemu_get_ubyte(f);
- qemu_get_sbe32s(f, &s->data_in_size);
- qemu_get_sbe32s(f, &s->data_in_index);
- qemu_get_sbe32s(f, &s->data_out_index);
- s->autopoll = qemu_get_ubyte(f);
- qemu_get_buffer(f, s->data_in, sizeof(s->data_in));
- qemu_get_buffer(f, s->data_out, sizeof(s->data_out));
- qemu_get_be32s(f, &s->tick_offset);
- cuda_load_timer(f, &s->timers[0]);
- cuda_load_timer(f, &s->timers[1]);
+static const VMStateDescription vmstate_cuda_timer = {
+ .name = "cuda_timer",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT16(latch, CUDATimer),
+ VMSTATE_UINT16(counter_value, CUDATimer),
+ VMSTATE_INT64(load_time, CUDATimer),
+ VMSTATE_INT64(next_irq_time, CUDATimer),
+ VMSTATE_TIMER_TEST(timer, CUDATimer, cuda_timer_exist),
+ VMSTATE_END_OF_LIST()
+ }
+};
- return 0;
-}
+static const VMStateDescription vmstate_cuda = {
+ .name = "cuda",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(a, CUDAState),
+ VMSTATE_UINT8(b, CUDAState),
+ VMSTATE_UINT8(dira, CUDAState),
+ VMSTATE_UINT8(dirb, CUDAState),
+ VMSTATE_UINT8(sr, CUDAState),
+ VMSTATE_UINT8(acr, CUDAState),
+ VMSTATE_UINT8(pcr, CUDAState),
+ VMSTATE_UINT8(ifr, CUDAState),
+ VMSTATE_UINT8(ier, CUDAState),
+ VMSTATE_UINT8(anh, CUDAState),
+ VMSTATE_INT32(data_in_size, CUDAState),
+ VMSTATE_INT32(data_in_index, CUDAState),
+ VMSTATE_INT32(data_out_index, CUDAState),
+ VMSTATE_UINT8(autopoll, CUDAState),
+ VMSTATE_BUFFER(data_in, CUDAState),
+ VMSTATE_BUFFER(data_out, CUDAState),
+ VMSTATE_UINT32(tick_offset, CUDAState),
+ VMSTATE_STRUCT_ARRAY(timers, CUDAState, 2, 1,
+ vmstate_cuda_timer, CUDATimer),
+ VMSTATE_END_OF_LIST()
+ }
+};
static void cuda_reset(void *opaque)
{
@@ -764,6 +740,6 @@ void cuda_init (int *cuda_mem_index, qemu_irq irq)
s->adb_poll_timer = qemu_new_timer_ns(vm_clock, cuda_adb_poll, s);
*cuda_mem_index = cpu_register_io_memory(cuda_read, cuda_write, s,
DEVICE_NATIVE_ENDIAN);
- register_savevm(NULL, "cuda", -1, 1, cuda_save, cuda_load, s);
+ vmstate_register(NULL, -1, &vmstate_cuda, s);
qemu_register_reset(cuda_reset, s);
}
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
index 61efb3989..cec1cc8e8 100644
--- a/hw/dummy_m68k.c
+++ b/hw/dummy_m68k.c
@@ -7,7 +7,6 @@
*/
#include "hw.h"
-#include "sysemu.h"
#include "boards.h"
#include "loader.h"
#include "elf.h"
diff --git a/hw/e1000.c b/hw/e1000.c
index fe3e81261..f160bfc2a 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1220,7 +1220,7 @@ static PCIDeviceInfo e1000_info = {
.qdev.vmsd = &vmstate_e1000,
.init = pci_e1000_init,
.exit = pci_e1000_uninit,
- .romfile = "pxe-e1000.bin",
+ .romfile = "pxe-e1000.rom",
.qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(E1000State, conf),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/eepro100.c b/hw/eepro100.c
index edf48f61d..369ad7f84 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -2054,7 +2054,7 @@ static void eepro100_register_devices(void)
PCIDeviceInfo *pci_dev = &e100_devices[i].pci;
/* We use the same rom file for all device ids.
QEMU fixes the device id during rom load. */
- pci_dev->romfile = "gpxe-eepro100-80861209.rom";
+ pci_dev->romfile = "pxe-eepro100.rom";
pci_dev->init = e100_nic_init;
pci_dev->exit = pci_nic_uninit;
pci_dev->qdev.props = e100_properties;
diff --git a/hw/empty_slot.c b/hw/empty_slot.c
index 664b8d9c4..da8adc4d0 100644
--- a/hw/empty_slot.c
+++ b/hw/empty_slot.c
@@ -53,18 +53,21 @@ static CPUWriteMemoryFunc * const empty_slot_write[3] = {
void empty_slot_init(target_phys_addr_t addr, uint64_t slot_size)
{
- DeviceState *dev;
- SysBusDevice *s;
- EmptySlot *e;
+ if (slot_size > 0) {
+ /* Only empty slots larger than 0 byte need handling. */
+ DeviceState *dev;
+ SysBusDevice *s;
+ EmptySlot *e;
- dev = qdev_create(NULL, "empty_slot");
- s = sysbus_from_qdev(dev);
- e = FROM_SYSBUS(EmptySlot, s);
- e->size = slot_size;
+ dev = qdev_create(NULL, "empty_slot");
+ s = sysbus_from_qdev(dev);
+ e = FROM_SYSBUS(EmptySlot, s);
+ e->size = slot_size;
- qdev_init_nofail(dev);
+ qdev_init_nofail(dev);
- sysbus_mmio_map(s, 0, addr);
+ sysbus_mmio_map(s, 0, addr);
+ }
}
static int empty_slot_init1(SysBusDevice *dev)
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index 5ee5f979a..b84d74a11 100644
--- a/hw/etraxfs.c
+++ b/hw/etraxfs.c
@@ -24,7 +24,6 @@
#include "sysbus.h"
#include "boards.h"
-#include "sysemu.h"
#include "net.h"
#include "flash.h"
#include "etraxfs.h"
diff --git a/hw/flash.h b/hw/flash.h
index d7d103e66..c22e1a922 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -21,8 +21,8 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
typedef struct NANDFlashState NANDFlashState;
NANDFlashState *nand_init(int manf_id, int chip_id);
void nand_done(NANDFlashState *s);
-void nand_setpins(NANDFlashState *s,
- int cle, int ale, int ce, int wp, int gnd);
+void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
+ uint8_t ce, uint8_t wp, uint8_t gnd);
void nand_getpins(NANDFlashState *s, int *rb);
void nand_setio(NANDFlashState *s, uint8_t value);
uint8_t nand_getio(NANDFlashState *s);
diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
index 101b150aa..169a56eb1 100644
--- a/hw/grlib_apbuart.c
+++ b/hw/grlib_apbuart.c
@@ -133,7 +133,7 @@ grlib_apbuart_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
break;
}
- trace_grlib_apbuart_unknown_register("write", addr);
+ trace_grlib_apbuart_writel_unknown(addr, value);
}
static CPUReadMemoryFunc * const grlib_apbuart_read[] = {
diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c
index 596a9000a..99e90336b 100644
--- a/hw/grlib_gptimer.c
+++ b/hw/grlib_gptimer.c
@@ -165,15 +165,15 @@ static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr)
/* Unit registers */
switch (addr) {
case SCALER_OFFSET:
- trace_grlib_gptimer_readl(-1, "scaler:", unit->scaler);
+ trace_grlib_gptimer_readl(-1, addr, unit->scaler);
return unit->scaler;
case SCALER_RELOAD_OFFSET:
- trace_grlib_gptimer_readl(-1, "reload:", unit->reload);
+ trace_grlib_gptimer_readl(-1, addr, unit->reload);
return unit->reload;
case CONFIG_OFFSET:
- trace_grlib_gptimer_readl(-1, "config:", unit->config);
+ trace_grlib_gptimer_readl(-1, addr, unit->config);
return unit->config;
default:
@@ -189,17 +189,16 @@ static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr)
switch (timer_addr) {
case COUNTER_OFFSET:
value = ptimer_get_count(unit->timers[id].ptimer);
- trace_grlib_gptimer_readl(id, "counter value:", value);
+ trace_grlib_gptimer_readl(id, addr, value);
return value;
case COUNTER_RELOAD_OFFSET:
value = unit->timers[id].reload;
- trace_grlib_gptimer_readl(id, "reload value:", value);
+ trace_grlib_gptimer_readl(id, addr, value);
return value;
case CONFIG_OFFSET:
- trace_grlib_gptimer_readl(id, "scaler value:",
- unit->timers[id].config);
+ trace_grlib_gptimer_readl(id, addr, unit->timers[id].config);
return unit->timers[id].config;
default:
@@ -208,7 +207,7 @@ static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr)
}
- trace_grlib_gptimer_unknown_register("read", addr);
+ trace_grlib_gptimer_readl(-1, addr, 0);
return 0;
}
@@ -226,19 +225,19 @@ grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
case SCALER_OFFSET:
value &= 0xFFFF; /* clean up the value */
unit->scaler = value;
- trace_grlib_gptimer_writel(-1, "scaler:", unit->scaler);
+ trace_grlib_gptimer_writel(-1, addr, unit->scaler);
return;
case SCALER_RELOAD_OFFSET:
value &= 0xFFFF; /* clean up the value */
unit->reload = value;
- trace_grlib_gptimer_writel(-1, "reload:", unit->reload);
+ trace_grlib_gptimer_writel(-1, addr, unit->reload);
grlib_gptimer_set_scaler(unit, value);
return;
case CONFIG_OFFSET:
/* Read Only (disable timer freeze not supported) */
- trace_grlib_gptimer_writel(-1, "config (Read Only):", 0);
+ trace_grlib_gptimer_writel(-1, addr, 0);
return;
default:
@@ -253,18 +252,18 @@ grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
/* GPTimer registers */
switch (timer_addr) {
case COUNTER_OFFSET:
- trace_grlib_gptimer_writel(id, "counter:", value);
+ trace_grlib_gptimer_writel(id, addr, value);
unit->timers[id].counter = value;
grlib_gptimer_enable(&unit->timers[id]);
return;
case COUNTER_RELOAD_OFFSET:
- trace_grlib_gptimer_writel(id, "reload:", value);
+ trace_grlib_gptimer_writel(id, addr, value);
unit->timers[id].reload = value;
return;
case CONFIG_OFFSET:
- trace_grlib_gptimer_writel(id, "config:", value);
+ trace_grlib_gptimer_writel(id, addr, value);
if (value & GPTIMER_INT_PENDING) {
/* clear pending bit */
@@ -297,7 +296,7 @@ grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
}
- trace_grlib_gptimer_unknown_register("write", addr);
+ trace_grlib_gptimer_writel(-1, addr, value);
}
static CPUReadMemoryFunc * const grlib_gptimer_read[] = {
diff --git a/hw/grlib_irqmp.c b/hw/grlib_irqmp.c
index f47c491a4..b8738fc04 100644
--- a/hw/grlib_irqmp.c
+++ b/hw/grlib_irqmp.c
@@ -220,7 +220,7 @@ static uint32_t grlib_irqmp_readl(void *opaque, target_phys_addr_t addr)
return state->extended[cpu];
}
- trace_grlib_irqmp_unknown_register("read", addr);
+ trace_grlib_irqmp_readl_unknown(addr);
return 0;
}
@@ -308,7 +308,7 @@ grlib_irqmp_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
return;
}
- trace_grlib_irqmp_unknown_register("write", addr);
+ trace_grlib_irqmp_writel_unknown(addr, value);
}
static CPUReadMemoryFunc * const grlib_irqmp_read[] = {
diff --git a/hw/gumstix.c b/hw/gumstix.c
index ee63f634c..853f7e1ee 100644
--- a/hw/gumstix.c
+++ b/hw/gumstix.c
@@ -35,7 +35,6 @@
#include "pxa.h"
#include "net.h"
#include "flash.h"
-#include "sysemu.h"
#include "devices.h"
#include "boards.h"
#include "blockdev.h"
diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c
index b19b754b3..5fd71a0f7 100644
--- a/hw/heathrow_pic.c
+++ b/hw/heathrow_pic.c
@@ -159,42 +159,31 @@ static void heathrow_pic_set_irq(void *opaque, int num, int level)
heathrow_pic_update(s);
}
-static void heathrow_pic_save_one(QEMUFile *f, HeathrowPIC *s)
-{
- qemu_put_be32s(f, &s->events);
- qemu_put_be32s(f, &s->mask);
- qemu_put_be32s(f, &s->levels);
- qemu_put_be32s(f, &s->level_triggered);
-}
-
-static void heathrow_pic_save(QEMUFile *f, void *opaque)
-{
- HeathrowPICS *s = (HeathrowPICS *)opaque;
-
- heathrow_pic_save_one(f, &s->pics[0]);
- heathrow_pic_save_one(f, &s->pics[1]);
-}
-
-static void heathrow_pic_load_one(QEMUFile *f, HeathrowPIC *s)
-{
- qemu_get_be32s(f, &s->events);
- qemu_get_be32s(f, &s->mask);
- qemu_get_be32s(f, &s->levels);
- qemu_get_be32s(f, &s->level_triggered);
-}
-
-static int heathrow_pic_load(QEMUFile *f, void *opaque, int version_id)
-{
- HeathrowPICS *s = (HeathrowPICS *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- heathrow_pic_load_one(f, &s->pics[0]);
- heathrow_pic_load_one(f, &s->pics[1]);
+static const VMStateDescription vmstate_heathrow_pic_one = {
+ .name = "heathrow_pic_one",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(events, HeathrowPIC),
+ VMSTATE_UINT32(mask, HeathrowPIC),
+ VMSTATE_UINT32(levels, HeathrowPIC),
+ VMSTATE_UINT32(level_triggered, HeathrowPIC),
+ VMSTATE_END_OF_LIST()
+ }
+};
- return 0;
-}
+static const VMStateDescription vmstate_heathrow_pic = {
+ .name = "heathrow_pic",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT_ARRAY(pics, HeathrowPICS, 2, 1,
+ vmstate_heathrow_pic_one, HeathrowPIC),
+ VMSTATE_END_OF_LIST()
+ }
+};
static void heathrow_pic_reset_one(HeathrowPIC *s)
{
@@ -223,8 +212,7 @@ qemu_irq *heathrow_pic_init(int *pmem_index,
*pmem_index = cpu_register_io_memory(pic_read, pic_write, s,
DEVICE_LITTLE_ENDIAN);
- register_savevm(NULL, "heathrow_pic", -1, 1, heathrow_pic_save,
- heathrow_pic_load, s);
+ vmstate_register(NULL, -1, &vmstate_heathrow_pic, s);
qemu_register_reset(heathrow_pic_reset, s);
return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64);
}
diff --git a/hw/hw.h b/hw/hw.h
index 87b0328b9..2ca601d49 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -693,6 +693,17 @@ extern const VMStateDescription vmstate_usb_device;
.offset = vmstate_offset_macaddr(_state, _field), \
}
+extern const VMStateDescription vmstate_ptimer;
+
+#define VMSTATE_PTIMER(_field, _state) { \
+ .name = (stringify(_field)), \
+ .version_id = (1), \
+ .vmsd = &vmstate_ptimer, \
+ .size = sizeof(ptimer_state *), \
+ .flags = VMS_STRUCT|VMS_POINTER, \
+ .offset = vmstate_offset_pointer(_state, _field, ptimer_state), \
+}
+
/* _f : field name
_f_n : num of elements field_name
_n : num of elements
@@ -797,12 +808,6 @@ extern const VMStateDescription vmstate_usb_device;
#define VMSTATE_TIMER_ARRAY(_f, _s, _n) \
VMSTATE_ARRAY_OF_POINTER(_f, _s, _n, 0, vmstate_info_timer, QEMUTimer *)
-#define VMSTATE_PTIMER_V(_f, _s, _v) \
- VMSTATE_POINTER(_f, _s, _v, vmstate_info_ptimer, ptimer_state *)
-
-#define VMSTATE_PTIMER(_f, _s) \
- VMSTATE_PTIMER_V(_f, _s, 0)
-
#define VMSTATE_BOOL_ARRAY_V(_f, _s, _n, _v) \
VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_bool, bool)
diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
new file mode 100644
index 000000000..fe2fb0b80
--- /dev/null
+++ b/hw/ide/atapi.c
@@ -0,0 +1,1138 @@
+/*
+ * QEMU ATAPI Emulation
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ * Copyright (c) 2006 Openedhand Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/ide/internal.h"
+#include "hw/scsi.h"
+
+static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
+
+static void padstr8(uint8_t *buf, int buf_size, const char *src)
+{
+ int i;
+ for(i = 0; i < buf_size; i++) {
+ if (*src)
+ buf[i] = *src++;
+ else
+ buf[i] = ' ';
+ }
+}
+
+static inline void cpu_to_ube16(uint8_t *buf, int val)
+{
+ buf[0] = val >> 8;
+ buf[1] = val & 0xff;
+}
+
+static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)
+{
+ buf[0] = val >> 24;
+ buf[1] = val >> 16;
+ buf[2] = val >> 8;
+ buf[3] = val & 0xff;
+}
+
+static inline int ube16_to_cpu(const uint8_t *buf)
+{
+ return (buf[0] << 8) | buf[1];
+}
+
+static inline int ube32_to_cpu(const uint8_t *buf)
+{
+ return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+}
+
+static void lba_to_msf(uint8_t *buf, int lba)
+{
+ lba += 150;
+ buf[0] = (lba / 75) / 60;
+ buf[1] = (lba / 75) % 60;
+ buf[2] = lba % 75;
+}
+
+static inline int media_present(IDEState *s)
+{
+ return (s->nb_sectors > 0);
+}
+
+/* XXX: DVDs that could fit on a CD will be reported as a CD */
+static inline int media_is_dvd(IDEState *s)
+{
+ return (media_present(s) && s->nb_sectors > CD_MAX_SECTORS);
+}
+
+static inline int media_is_cd(IDEState *s)
+{
+ return (media_present(s) && s->nb_sectors <= CD_MAX_SECTORS);
+}
+
+static void cd_data_to_raw(uint8_t *buf, int lba)
+{
+ /* sync bytes */
+ buf[0] = 0x00;
+ memset(buf + 1, 0xff, 10);
+ buf[11] = 0x00;
+ buf += 12;
+ /* MSF */
+ lba_to_msf(buf, lba);
+ buf[3] = 0x01; /* mode 1 data */
+ buf += 4;
+ /* data */
+ buf += 2048;
+ /* XXX: ECC not computed */
+ memset(buf, 0, 288);
+}
+
+static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf,
+ int sector_size)
+{
+ int ret;
+
+ switch(sector_size) {
+ case 2048:
+ ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4);
+ break;
+ case 2352:
+ ret = bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4);
+ if (ret < 0)
+ return ret;
+ cd_data_to_raw(buf, lba);
+ break;
+ default:
+ ret = -EIO;
+ break;
+ }
+ return ret;
+}
+
+void ide_atapi_cmd_ok(IDEState *s)
+{
+ s->error = 0;
+ s->status = READY_STAT | SEEK_STAT;
+ s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
+ ide_set_irq(s->bus);
+}
+
+void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc)
+{
+#ifdef DEBUG_IDE_ATAPI
+ printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);
+#endif
+ s->error = sense_key << 4;
+ s->status = READY_STAT | ERR_STAT;
+ s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
+ s->sense_key = sense_key;
+ s->asc = asc;
+ ide_set_irq(s->bus);
+}
+
+void ide_atapi_io_error(IDEState *s, int ret)
+{
+ /* XXX: handle more errors */
+ if (ret == -ENOMEDIUM) {
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ASC_MEDIUM_NOT_PRESENT);
+ } else {
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_LOGICAL_BLOCK_OOR);
+ }
+}
+
+/* The whole ATAPI transfer logic is handled in this function */
+void ide_atapi_cmd_reply_end(IDEState *s)
+{
+ int byte_count_limit, size, ret;
+#ifdef DEBUG_IDE_ATAPI
+ printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",
+ s->packet_transfer_size,
+ s->elementary_transfer_size,
+ s->io_buffer_index);
+#endif
+ if (s->packet_transfer_size <= 0) {
+ /* end of transfer */
+ ide_transfer_stop(s);
+ s->status = READY_STAT | SEEK_STAT;
+ s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
+ ide_set_irq(s->bus);
+#ifdef DEBUG_IDE_ATAPI
+ printf("status=0x%x\n", s->status);
+#endif
+ } else {
+ /* see if a new sector must be read */
+ if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {
+ ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);
+ if (ret < 0) {
+ ide_transfer_stop(s);
+ ide_atapi_io_error(s, ret);
+ return;
+ }
+ s->lba++;
+ s->io_buffer_index = 0;
+ }
+ if (s->elementary_transfer_size > 0) {
+ /* there are some data left to transmit in this elementary
+ transfer */
+ size = s->cd_sector_size - s->io_buffer_index;
+ if (size > s->elementary_transfer_size)
+ size = s->elementary_transfer_size;
+ s->packet_transfer_size -= size;
+ s->elementary_transfer_size -= size;
+ s->io_buffer_index += size;
+ ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,
+ size, ide_atapi_cmd_reply_end);
+ } else {
+ /* a new transfer is needed */
+ s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
+ byte_count_limit = s->lcyl | (s->hcyl << 8);
+#ifdef DEBUG_IDE_ATAPI
+ printf("byte_count_limit=%d\n", byte_count_limit);
+#endif
+ if (byte_count_limit == 0xffff)
+ byte_count_limit--;
+ size = s->packet_transfer_size;
+ if (size > byte_count_limit) {
+ /* byte count limit must be even if this case */
+ if (byte_count_limit & 1)
+ byte_count_limit--;
+ size = byte_count_limit;
+ }
+ s->lcyl = size;
+ s->hcyl = size >> 8;
+ s->elementary_transfer_size = size;
+ /* we cannot transmit more than one sector at a time */
+ if (s->lba != -1) {
+ if (size > (s->cd_sector_size - s->io_buffer_index))
+ size = (s->cd_sector_size - s->io_buffer_index);
+ }
+ s->packet_transfer_size -= size;
+ s->elementary_transfer_size -= size;
+ s->io_buffer_index += size;
+ ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,
+ size, ide_atapi_cmd_reply_end);
+ ide_set_irq(s->bus);
+#ifdef DEBUG_IDE_ATAPI
+ printf("status=0x%x\n", s->status);
+#endif
+ }
+ }
+}
+
+/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */
+static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
+{
+ if (size > max_size)
+ size = max_size;
+ s->lba = -1; /* no sector read */
+ s->packet_transfer_size = size;
+ s->io_buffer_size = size; /* dma: send the reply data as one chunk */
+ s->elementary_transfer_size = 0;
+ s->io_buffer_index = 0;
+
+ if (s->atapi_dma) {
+ s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
+ s->bus->dma->ops->start_dma(s->bus->dma, s,
+ ide_atapi_cmd_read_dma_cb);
+ } else {
+ s->status = READY_STAT | SEEK_STAT;
+ ide_atapi_cmd_reply_end(s);
+ }
+}
+
+/* start a CD-CDROM read command */
+static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors,
+ int sector_size)
+{
+ s->lba = lba;
+ s->packet_transfer_size = nb_sectors * sector_size;
+ s->elementary_transfer_size = 0;
+ s->io_buffer_index = sector_size;
+ s->cd_sector_size = sector_size;
+
+ s->status = READY_STAT | SEEK_STAT;
+ ide_atapi_cmd_reply_end(s);
+}
+
+static void ide_atapi_cmd_check_status(IDEState *s)
+{
+#ifdef DEBUG_IDE_ATAPI
+ printf("atapi_cmd_check_status\n");
+#endif
+ s->error = MC_ERR | (SENSE_UNIT_ATTENTION << 4);
+ s->status = ERR_STAT;
+ s->nsector = 0;
+ ide_set_irq(s->bus);
+}
+/* ATAPI DMA support */
+
+/* XXX: handle read errors */
+static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
+{
+ IDEState *s = opaque;
+ int data_offset, n;
+
+ if (ret < 0) {
+ ide_atapi_io_error(s, ret);
+ goto eot;
+ }
+
+ if (s->io_buffer_size > 0) {
+ /*
+ * For a cdrom read sector command (s->lba != -1),
+ * adjust the lba for the next s->io_buffer_size chunk
+ * and dma the current chunk.
+ * For a command != read (s->lba == -1), just transfer
+ * the reply data.
+ */
+ if (s->lba != -1) {
+ if (s->cd_sector_size == 2352) {
+ n = 1;
+ cd_data_to_raw(s->io_buffer, s->lba);
+ } else {
+ n = s->io_buffer_size >> 11;
+ }
+ s->lba += n;
+ }
+ s->packet_transfer_size -= s->io_buffer_size;
+ if (s->bus->dma->ops->rw_buf(s->bus->dma, 1) == 0)
+ goto eot;
+ }
+
+ if (s->packet_transfer_size <= 0) {
+ s->status = READY_STAT | SEEK_STAT;
+ s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
+ ide_set_irq(s->bus);
+ eot:
+ s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT);
+ ide_set_inactive(s);
+ return;
+ }
+
+ s->io_buffer_index = 0;
+ if (s->cd_sector_size == 2352) {
+ n = 1;
+ s->io_buffer_size = s->cd_sector_size;
+ data_offset = 16;
+ } else {
+ n = s->packet_transfer_size >> 11;
+ if (n > (IDE_DMA_BUF_SECTORS / 4))
+ n = (IDE_DMA_BUF_SECTORS / 4);
+ s->io_buffer_size = n * 2048;
+ data_offset = 0;
+ }
+#ifdef DEBUG_AIO
+ printf("aio_read_cd: lba=%u n=%d\n", s->lba, n);
+#endif
+ s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset);
+ s->bus->dma->iov.iov_len = n * 4 * 512;
+ qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1);
+ s->bus->dma->aiocb = bdrv_aio_readv(s->bs, (int64_t)s->lba << 2,
+ &s->bus->dma->qiov, n * 4,
+ ide_atapi_cmd_read_dma_cb, s);
+ if (!s->bus->dma->aiocb) {
+ /* Note: media not present is the most likely case */
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ASC_MEDIUM_NOT_PRESENT);
+ goto eot;
+ }
+}
+
+/* start a CD-CDROM read command with DMA */
+/* XXX: test if DMA is available */
+static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,
+ int sector_size)
+{
+ s->lba = lba;
+ s->packet_transfer_size = nb_sectors * sector_size;
+ s->io_buffer_index = 0;
+ s->io_buffer_size = 0;
+ s->cd_sector_size = sector_size;
+
+ /* XXX: check if BUSY_STAT should be set */
+ s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
+ s->bus->dma->ops->start_dma(s->bus->dma, s,
+ ide_atapi_cmd_read_dma_cb);
+}
+
+static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
+ int sector_size)
+{
+#ifdef DEBUG_IDE_ATAPI
+ printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio",
+ lba, nb_sectors);
+#endif
+ if (s->atapi_dma) {
+ ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
+ } else {
+ ide_atapi_cmd_read_pio(s, lba, nb_sectors, sector_size);
+ }
+}
+
+static inline uint8_t ide_atapi_set_profile(uint8_t *buf, uint8_t *index,
+ uint16_t profile)
+{
+ uint8_t *buf_profile = buf + 12; /* start of profiles */
+
+ buf_profile += ((*index) * 4); /* start of indexed profile */
+ cpu_to_ube16 (buf_profile, profile);
+ buf_profile[2] = ((buf_profile[0] == buf[6]) && (buf_profile[1] == buf[7]));
+
+ /* each profile adds 4 bytes to the response */
+ (*index)++;
+ buf[11] += 4; /* Additional Length */
+
+ return 4;
+}
+
+static int ide_dvd_read_structure(IDEState *s, int format,
+ const uint8_t *packet, uint8_t *buf)
+{
+ switch (format) {
+ case 0x0: /* Physical format information */
+ {
+ int layer = packet[6];
+ uint64_t total_sectors;
+
+ if (layer != 0)
+ return -ASC_INV_FIELD_IN_CMD_PACKET;
+
+ total_sectors = s->nb_sectors >> 2;
+ if (total_sectors == 0) {
+ return -ASC_MEDIUM_NOT_PRESENT;
+ }
+
+ buf[4] = 1; /* DVD-ROM, part version 1 */
+ buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
+ buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */
+ buf[7] = 0; /* default densities */
+
+ /* FIXME: 0x30000 per spec? */
+ cpu_to_ube32(buf + 8, 0); /* start sector */
+ cpu_to_ube32(buf + 12, total_sectors - 1); /* end sector */
+ cpu_to_ube32(buf + 16, total_sectors - 1); /* l0 end sector */
+
+ /* Size of buffer, not including 2 byte size field */
+ cpu_to_be16wu((uint16_t *)buf, 2048 + 2);
+
+ /* 2k data + 4 byte header */
+ return (2048 + 4);
+ }
+
+ case 0x01: /* DVD copyright information */
+ buf[4] = 0; /* no copyright data */
+ buf[5] = 0; /* no region restrictions */
+
+ /* Size of buffer, not including 2 byte size field */
+ cpu_to_be16wu((uint16_t *)buf, 4 + 2);
+
+ /* 4 byte header + 4 byte data */
+ return (4 + 4);
+
+ case 0x03: /* BCA information - invalid field for no BCA info */
+ return -ASC_INV_FIELD_IN_CMD_PACKET;
+
+ case 0x04: /* DVD disc manufacturing information */
+ /* Size of buffer, not including 2 byte size field */
+ cpu_to_be16wu((uint16_t *)buf, 2048 + 2);
+
+ /* 2k data + 4 byte header */
+ return (2048 + 4);
+
+ case 0xff:
+ /*
+ * This lists all the command capabilities above. Add new ones
+ * in order and update the length and buffer return values.
+ */
+
+ buf[4] = 0x00; /* Physical format */
+ buf[5] = 0x40; /* Not writable, is readable */
+ cpu_to_be16wu((uint16_t *)(buf + 6), 2048 + 4);
+
+ buf[8] = 0x01; /* Copyright info */
+ buf[9] = 0x40; /* Not writable, is readable */
+ cpu_to_be16wu((uint16_t *)(buf + 10), 4 + 4);
+
+ buf[12] = 0x03; /* BCA info */
+ buf[13] = 0x40; /* Not writable, is readable */
+ cpu_to_be16wu((uint16_t *)(buf + 14), 188 + 4);
+
+ buf[16] = 0x04; /* Manufacturing info */
+ buf[17] = 0x40; /* Not writable, is readable */
+ cpu_to_be16wu((uint16_t *)(buf + 18), 2048 + 4);
+
+ /* Size of buffer, not including 2 byte size field */
+ cpu_to_be16wu((uint16_t *)buf, 16 + 2);
+
+ /* data written + 4 byte header */
+ return (16 + 4);
+
+ default: /* TODO: formats beyond DVD-ROM requires */
+ return -ASC_INV_FIELD_IN_CMD_PACKET;
+ }
+}
+
+static unsigned int event_status_media(IDEState *s,
+ uint8_t *buf)
+{
+ enum media_event_code {
+ MEC_NO_CHANGE = 0, /* Status unchanged */
+ MEC_EJECT_REQUESTED, /* received a request from user to eject */
+ MEC_NEW_MEDIA, /* new media inserted and ready for access */
+ MEC_MEDIA_REMOVAL, /* only for media changers */
+ MEC_MEDIA_CHANGED, /* only for media changers */
+ MEC_BG_FORMAT_COMPLETED, /* MRW or DVD+RW b/g format completed */
+ MEC_BG_FORMAT_RESTARTED, /* MRW or DVD+RW b/g format restarted */
+ };
+ enum media_status {
+ MS_TRAY_OPEN = 1,
+ MS_MEDIA_PRESENT = 2,
+ };
+ uint8_t event_code, media_status;
+
+ media_status = 0;
+ if (s->bs->tray_open) {
+ media_status = MS_TRAY_OPEN;
+ } else if (bdrv_is_inserted(s->bs)) {
+ media_status = MS_MEDIA_PRESENT;
+ }
+
+ /* Event notification descriptor */
+ event_code = MEC_NO_CHANGE;
+ if (media_status != MS_TRAY_OPEN && s->events.new_media) {
+ event_code = MEC_NEW_MEDIA;
+ s->events.new_media = false;
+ }
+
+ buf[4] = event_code;
+ buf[5] = media_status;
+
+ /* These fields are reserved, just clear them. */
+ buf[6] = 0;
+ buf[7] = 0;
+
+ return 8; /* We wrote to 4 extra bytes from the header */
+}
+
+static void cmd_get_event_status_notification(IDEState *s,
+ uint8_t *buf)
+{
+ const uint8_t *packet = buf;
+
+ struct {
+ uint8_t opcode;
+ uint8_t polled; /* lsb bit is polled; others are reserved */
+ uint8_t reserved2[2];
+ uint8_t class;
+ uint8_t reserved3[2];
+ uint16_t len;
+ uint8_t control;
+ } __attribute__((packed)) *gesn_cdb;
+
+ struct {
+ uint16_t len;
+ uint8_t notification_class;
+ uint8_t supported_events;
+ } __attribute((packed)) *gesn_event_header;
+
+ enum notification_class_request_type {
+ NCR_RESERVED1 = 1 << 0,
+ NCR_OPERATIONAL_CHANGE = 1 << 1,
+ NCR_POWER_MANAGEMENT = 1 << 2,
+ NCR_EXTERNAL_REQUEST = 1 << 3,
+ NCR_MEDIA = 1 << 4,
+ NCR_MULTI_HOST = 1 << 5,
+ NCR_DEVICE_BUSY = 1 << 6,
+ NCR_RESERVED2 = 1 << 7,
+ };
+ enum event_notification_class_field {
+ ENC_NO_EVENTS = 0,
+ ENC_OPERATIONAL_CHANGE,
+ ENC_POWER_MANAGEMENT,
+ ENC_EXTERNAL_REQUEST,
+ ENC_MEDIA,
+ ENC_MULTIPLE_HOSTS,
+ ENC_DEVICE_BUSY,
+ ENC_RESERVED,
+ };
+ unsigned int max_len, used_len;
+
+ gesn_cdb = (void *)packet;
+ gesn_event_header = (void *)buf;
+
+ max_len = be16_to_cpu(gesn_cdb->len);
+
+ /* It is fine by the MMC spec to not support async mode operations */
+ if (!(gesn_cdb->polled & 0x01)) { /* asynchronous mode */
+ /* Only polling is supported, asynchronous mode is not. */
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ return;
+ }
+
+ /* polling mode operation */
+
+ /*
+ * These are the supported events.
+ *
+ * We currently only support requests of the 'media' type.
+ */
+ gesn_event_header->supported_events = NCR_MEDIA;
+
+ /*
+ * We use |= below to set the class field; other bits in this byte
+ * are reserved now but this is useful to do if we have to use the
+ * reserved fields later.
+ */
+ gesn_event_header->notification_class = 0;
+
+ /*
+ * Responses to requests are to be based on request priority. The
+ * notification_class_request_type enum above specifies the
+ * priority: upper elements are higher prio than lower ones.
+ */
+ if (gesn_cdb->class & NCR_MEDIA) {
+ gesn_event_header->notification_class |= ENC_MEDIA;
+ used_len = event_status_media(s, buf);
+ } else {
+ gesn_event_header->notification_class = 0x80; /* No event available */
+ used_len = sizeof(*gesn_event_header);
+ }
+ gesn_event_header->len = cpu_to_be16(used_len
+ - sizeof(*gesn_event_header));
+ ide_atapi_cmd_reply(s, used_len, max_len);
+}
+
+static void cmd_request_sense(IDEState *s, uint8_t *buf)
+{
+ int max_len = buf[4];
+
+ memset(buf, 0, 18);
+ buf[0] = 0x70 | (1 << 7);
+ buf[2] = s->sense_key;
+ buf[7] = 10;
+ buf[12] = s->asc;
+
+ if (s->sense_key == SENSE_UNIT_ATTENTION) {
+ s->sense_key = SENSE_NONE;
+ }
+
+ ide_atapi_cmd_reply(s, 18, max_len);
+}
+
+static void cmd_inquiry(IDEState *s, uint8_t *buf)
+{
+ int max_len = buf[4];
+
+ buf[0] = 0x05; /* CD-ROM */
+ buf[1] = 0x80; /* removable */
+ buf[2] = 0x00; /* ISO */
+ buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */
+ buf[4] = 31; /* additional length */
+ buf[5] = 0; /* reserved */
+ buf[6] = 0; /* reserved */
+ buf[7] = 0; /* reserved */
+ padstr8(buf + 8, 8, "QEMU");
+ padstr8(buf + 16, 16, "QEMU DVD-ROM");
+ padstr8(buf + 32, 4, s->version);
+ ide_atapi_cmd_reply(s, 36, max_len);
+}
+
+static void cmd_get_configuration(IDEState *s, uint8_t *buf)
+{
+ uint32_t len;
+ uint8_t index = 0;
+ int max_len;
+
+ /* only feature 0 is supported */
+ if (buf[2] != 0 || buf[3] != 0) {
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ return;
+ }
+
+ /* XXX: could result in alignment problems in some architectures */
+ max_len = ube16_to_cpu(buf + 7);
+
+ /*
+ * XXX: avoid overflow for io_buffer if max_len is bigger than
+ * the size of that buffer (dimensioned to max number of
+ * sectors to transfer at once)
+ *
+ * Only a problem if the feature/profiles grow.
+ */
+ if (max_len > 512) {
+ /* XXX: assume 1 sector */
+ max_len = 512;
+ }
+
+ memset(buf, 0, max_len);
+ /*
+ * the number of sectors from the media tells us which profile
+ * to use as current. 0 means there is no media
+ */
+ if (media_is_dvd(s)) {
+ cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM);
+ } else if (media_is_cd(s)) {
+ cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM);
+ }
+
+ buf[10] = 0x02 | 0x01; /* persistent and current */
+ len = 12; /* headers: 8 + 4 */
+ len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_DVD_ROM);
+ len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_CD_ROM);
+ cpu_to_ube32(buf, len - 4); /* data length */
+
+ ide_atapi_cmd_reply(s, len, max_len);
+}
+
+static void cmd_mode_sense(IDEState *s, uint8_t *buf)
+{
+ int action, code;
+ int max_len;
+
+ if (buf[0] == GPCMD_MODE_SENSE_10) {
+ max_len = ube16_to_cpu(buf + 7);
+ } else {
+ max_len = buf[4];
+ }
+
+ action = buf[2] >> 6;
+ code = buf[2] & 0x3f;
+
+ switch(action) {
+ case 0: /* current values */
+ switch(code) {
+ case GPMODE_R_W_ERROR_PAGE: /* error recovery */
+ cpu_to_ube16(&buf[0], 16 + 6);
+ buf[2] = 0x70;
+ buf[3] = 0;
+ buf[4] = 0;
+ buf[5] = 0;
+ buf[6] = 0;
+ buf[7] = 0;
+
+ buf[8] = 0x01;
+ buf[9] = 0x06;
+ buf[10] = 0x00;
+ buf[11] = 0x05;
+ buf[12] = 0x00;
+ buf[13] = 0x00;
+ buf[14] = 0x00;
+ buf[15] = 0x00;
+ ide_atapi_cmd_reply(s, 16, max_len);
+ break;
+ case GPMODE_AUDIO_CTL_PAGE:
+ cpu_to_ube16(&buf[0], 24 + 6);
+ buf[2] = 0x70;
+ buf[3] = 0;
+ buf[4] = 0;
+ buf[5] = 0;
+ buf[6] = 0;
+ buf[7] = 0;
+
+ /* Fill with CDROM audio volume */
+ buf[17] = 0;
+ buf[19] = 0;
+ buf[21] = 0;
+ buf[23] = 0;
+
+ ide_atapi_cmd_reply(s, 24, max_len);
+ break;
+ case GPMODE_CAPABILITIES_PAGE:
+ cpu_to_ube16(&buf[0], 28 + 6);
+ buf[2] = 0x70;
+ buf[3] = 0;
+ buf[4] = 0;
+ buf[5] = 0;
+ buf[6] = 0;
+ buf[7] = 0;
+
+ buf[8] = 0x2a;
+ buf[9] = 0x12;
+ buf[10] = 0x00;
+ buf[11] = 0x00;
+
+ /* Claim PLAY_AUDIO capability (0x01) since some Linux
+ code checks for this to automount media. */
+ buf[12] = 0x71;
+ buf[13] = 3 << 5;
+ buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
+ if (bdrv_is_locked(s->bs))
+ buf[6] |= 1 << 1;
+ buf[15] = 0x00;
+ cpu_to_ube16(&buf[16], 706);
+ buf[18] = 0;
+ buf[19] = 2;
+ cpu_to_ube16(&buf[20], 512);
+ cpu_to_ube16(&buf[22], 706);
+ buf[24] = 0;
+ buf[25] = 0;
+ buf[26] = 0;
+ buf[27] = 0;
+ ide_atapi_cmd_reply(s, 28, max_len);
+ break;
+ default:
+ goto error_cmd;
+ }
+ break;
+ case 1: /* changeable values */
+ goto error_cmd;
+ case 2: /* default values */
+ goto error_cmd;
+ default:
+ case 3: /* saved values */
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
+ break;
+ }
+ return;
+
+error_cmd:
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
+}
+
+static void cmd_test_unit_ready(IDEState *s, uint8_t *buf)
+{
+ /* Not Ready Conditions are already handled in ide_atapi_cmd(), so if we
+ * come here, we know that it's ready. */
+ ide_atapi_cmd_ok(s);
+}
+
+static void cmd_prevent_allow_medium_removal(IDEState *s, uint8_t* buf)
+{
+ bdrv_set_locked(s->bs, buf[4] & 1);
+ ide_atapi_cmd_ok(s);
+}
+
+static void cmd_read(IDEState *s, uint8_t* buf)
+{
+ int nb_sectors, lba;
+
+ if (buf[0] == GPCMD_READ_10) {
+ nb_sectors = ube16_to_cpu(buf + 7);
+ } else {
+ nb_sectors = ube32_to_cpu(buf + 6);
+ }
+
+ lba = ube32_to_cpu(buf + 2);
+ if (nb_sectors == 0) {
+ ide_atapi_cmd_ok(s);
+ return;
+ }
+
+ ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
+}
+
+static void cmd_read_cd(IDEState *s, uint8_t* buf)
+{
+ int nb_sectors, lba, transfer_request;
+
+ nb_sectors = (buf[6] << 16) | (buf[7] << 8) | buf[8];
+ lba = ube32_to_cpu(buf + 2);
+
+ if (nb_sectors == 0) {
+ ide_atapi_cmd_ok(s);
+ return;
+ }
+
+ transfer_request = buf[9];
+ switch(transfer_request & 0xf8) {
+ case 0x00:
+ /* nothing */
+ ide_atapi_cmd_ok(s);
+ break;
+ case 0x10:
+ /* normal read */
+ ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
+ break;
+ case 0xf8:
+ /* read all data */
+ ide_atapi_cmd_read(s, lba, nb_sectors, 2352);
+ break;
+ default:
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ break;
+ }
+}
+
+static void cmd_seek(IDEState *s, uint8_t* buf)
+{
+ unsigned int lba;
+ uint64_t total_sectors = s->nb_sectors >> 2;
+
+ lba = ube32_to_cpu(buf + 2);
+ if (lba >= total_sectors) {
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
+ return;
+ }
+
+ ide_atapi_cmd_ok(s);
+}
+
+static void cmd_start_stop_unit(IDEState *s, uint8_t* buf)
+{
+ int start, eject, sense, err = 0;
+ start = buf[4] & 1;
+ eject = (buf[4] >> 1) & 1;
+
+ if (eject) {
+ err = bdrv_eject(s->bs, !start);
+ }
+
+ switch (err) {
+ case 0:
+ ide_atapi_cmd_ok(s);
+ break;
+ case -EBUSY:
+ sense = SENSE_NOT_READY;
+ if (bdrv_is_inserted(s->bs)) {
+ sense = SENSE_ILLEGAL_REQUEST;
+ }
+ ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED);
+ break;
+ default:
+ ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+ break;
+ }
+}
+
+static void cmd_mechanism_status(IDEState *s, uint8_t* buf)
+{
+ int max_len = ube16_to_cpu(buf + 8);
+
+ cpu_to_ube16(buf, 0);
+ /* no current LBA */
+ buf[2] = 0;
+ buf[3] = 0;
+ buf[4] = 0;
+ buf[5] = 1;
+ cpu_to_ube16(buf + 6, 0);
+ ide_atapi_cmd_reply(s, 8, max_len);
+}
+
+static void cmd_read_toc_pma_atip(IDEState *s, uint8_t* buf)
+{
+ int format, msf, start_track, len;
+ int max_len;
+ uint64_t total_sectors = s->nb_sectors >> 2;
+
+ max_len = ube16_to_cpu(buf + 7);
+ format = buf[9] >> 6;
+ msf = (buf[1] >> 1) & 1;
+ start_track = buf[6];
+
+ switch(format) {
+ case 0:
+ len = cdrom_read_toc(total_sectors, buf, msf, start_track);
+ if (len < 0)
+ goto error_cmd;
+ ide_atapi_cmd_reply(s, len, max_len);
+ break;
+ case 1:
+ /* multi session : only a single session defined */
+ memset(buf, 0, 12);
+ buf[1] = 0x0a;
+ buf[2] = 0x01;
+ buf[3] = 0x01;
+ ide_atapi_cmd_reply(s, 12, max_len);
+ break;
+ case 2:
+ len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track);
+ if (len < 0)
+ goto error_cmd;
+ ide_atapi_cmd_reply(s, len, max_len);
+ break;
+ default:
+ error_cmd:
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ }
+}
+
+static void cmd_read_cdvd_capacity(IDEState *s, uint8_t* buf)
+{
+ uint64_t total_sectors = s->nb_sectors >> 2;
+
+ /* NOTE: it is really the number of sectors minus 1 */
+ cpu_to_ube32(buf, total_sectors - 1);
+ cpu_to_ube32(buf + 4, 2048);
+ ide_atapi_cmd_reply(s, 8, 8);
+}
+
+static void cmd_read_dvd_structure(IDEState *s, uint8_t* buf)
+{
+ int max_len;
+ int media = buf[1];
+ int format = buf[7];
+ int ret;
+
+ max_len = ube16_to_cpu(buf + 8);
+
+ if (format < 0xff) {
+ if (media_is_cd(s)) {
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INCOMPATIBLE_FORMAT);
+ return;
+ } else if (!media_present(s)) {
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ return;
+ }
+ }
+
+ memset(buf, 0, max_len > IDE_DMA_BUF_SECTORS * 512 + 4 ?
+ IDE_DMA_BUF_SECTORS * 512 + 4 : max_len);
+
+ switch (format) {
+ case 0x00 ... 0x7f:
+ case 0xff:
+ if (media == 0) {
+ ret = ide_dvd_read_structure(s, format, buf, buf);
+
+ if (ret < 0) {
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, -ret);
+ } else {
+ ide_atapi_cmd_reply(s, ret, max_len);
+ }
+
+ break;
+ }
+ /* TODO: BD support, fall through for now */
+
+ /* Generic disk structures */
+ case 0x80: /* TODO: AACS volume identifier */
+ case 0x81: /* TODO: AACS media serial number */
+ case 0x82: /* TODO: AACS media identifier */
+ case 0x83: /* TODO: AACS media key block */
+ case 0x90: /* TODO: List of recognized format layers */
+ case 0xc0: /* TODO: Write protection status */
+ default:
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ break;
+ }
+}
+
+static void cmd_set_speed(IDEState *s, uint8_t* buf)
+{
+ ide_atapi_cmd_ok(s);
+}
+
+enum {
+ /*
+ * Only commands flagged as ALLOW_UA are allowed to run under a
+ * unit attention condition. (See MMC-5, section 4.1.6.1)
+ */
+ ALLOW_UA = 0x01,
+
+ /*
+ * Commands flagged with CHECK_READY can only execute if a medium is present.
+ * Otherwise they report the Not Ready Condition. (See MMC-5, section
+ * 4.1.8)
+ */
+ CHECK_READY = 0x02,
+};
+
+static const struct {
+ void (*handler)(IDEState *s, uint8_t *buf);
+ int flags;
+} atapi_cmd_table[0x100] = {
+ [ 0x00 ] = { cmd_test_unit_ready, CHECK_READY },
+ [ 0x03 ] = { cmd_request_sense, ALLOW_UA },
+ [ 0x12 ] = { cmd_inquiry, ALLOW_UA },
+ [ 0x1a ] = { cmd_mode_sense, /* (6) */ 0 },
+ [ 0x1b ] = { cmd_start_stop_unit, 0 },
+ [ 0x1e ] = { cmd_prevent_allow_medium_removal, 0 },
+ [ 0x25 ] = { cmd_read_cdvd_capacity, CHECK_READY },
+ [ 0x28 ] = { cmd_read, /* (10) */ 0 },
+ [ 0x2b ] = { cmd_seek, CHECK_READY },
+ [ 0x43 ] = { cmd_read_toc_pma_atip, CHECK_READY },
+ [ 0x46 ] = { cmd_get_configuration, ALLOW_UA },
+ [ 0x4a ] = { cmd_get_event_status_notification, ALLOW_UA },
+ [ 0x5a ] = { cmd_mode_sense, /* (10) */ 0 },
+ [ 0xa8 ] = { cmd_read, /* (12) */ 0 },
+ [ 0xad ] = { cmd_read_dvd_structure, 0 },
+ [ 0xbb ] = { cmd_set_speed, 0 },
+ [ 0xbd ] = { cmd_mechanism_status, 0 },
+ [ 0xbe ] = { cmd_read_cd, 0 },
+};
+
+void ide_atapi_cmd(IDEState *s)
+{
+ uint8_t *buf;
+
+ buf = s->io_buffer;
+#ifdef DEBUG_IDE_ATAPI
+ {
+ int i;
+ printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
+ for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
+ printf(" %02x", buf[i]);
+ }
+ printf("\n");
+ }
+#endif
+ /*
+ * If there's a UNIT_ATTENTION condition pending, only command flagged with
+ * ALLOW_UA are allowed to complete. with other commands getting a CHECK
+ * condition response unless a higher priority status, defined by the drive
+ * here, is pending.
+ */
+ if (s->sense_key == SENSE_UNIT_ATTENTION &&
+ !(atapi_cmd_table[s->io_buffer[0]].flags & ALLOW_UA)) {
+ ide_atapi_cmd_check_status(s);
+ return;
+ }
+ /*
+ * When a CD gets changed, we have to report an ejected state and
+ * then a loaded state to guests so that they detect tray
+ * open/close and media change events. Guests that do not use
+ * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close
+ * states rely on this behavior.
+ */
+ if (bdrv_is_inserted(s->bs) && s->cdrom_changed) {
+ ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+
+ s->cdrom_changed = 0;
+ s->sense_key = SENSE_UNIT_ATTENTION;
+ s->asc = ASC_MEDIUM_MAY_HAVE_CHANGED;
+ return;
+ }
+
+ /* Report a Not Ready condition if appropriate for the command */
+ if ((atapi_cmd_table[s->io_buffer[0]].flags & CHECK_READY) &&
+ (!media_present(s) || !bdrv_is_inserted(s->bs)))
+ {
+ ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+ return;
+ }
+
+ /* Execute the command */
+ if (atapi_cmd_table[s->io_buffer[0]].handler) {
+ atapi_cmd_table[s->io_buffer[0]].handler(s, buf);
+ return;
+ }
+
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE);
+}
diff --git a/hw/ide/core.c b/hw/ide/core.c
index f028ddb49..90f553b69 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -25,7 +25,6 @@
#include <hw/hw.h>
#include <hw/pc.h>
#include <hw/pci.h>
-#include <hw/scsi.h>
#include "qemu-error.h"
#include "qemu-timer.h"
#include "sysemu.h"
@@ -56,23 +55,6 @@ static const int smart_attributes[][12] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
};
-/* XXX: DVDs that could fit on a CD will be reported as a CD */
-static inline int media_present(IDEState *s)
-{
- return (s->nb_sectors > 0);
-}
-
-static inline int media_is_dvd(IDEState *s)
-{
- return (media_present(s) && s->nb_sectors > CD_MAX_SECTORS);
-}
-
-static inline int media_is_cd(IDEState *s)
-{
- return (media_present(s) && s->nb_sectors <= CD_MAX_SECTORS);
-}
-
-static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
static int ide_handle_rw_error(IDEState *s, int error, int op);
static void padstr(char *str, const char *src, int len)
@@ -87,17 +69,6 @@ static void padstr(char *str, const char *src, int len)
}
}
-static void padstr8(uint8_t *buf, int buf_size, const char *src)
-{
- int i;
- for(i = 0; i < buf_size; i++) {
- if (*src)
- buf[i] = *src++;
- else
- buf[i] = ' ';
- }
-}
-
static void put_le16(uint16_t *p, unsigned int v)
{
*p = cpu_to_le16(v);
@@ -335,8 +306,8 @@ static inline void ide_abort_command(IDEState *s)
}
/* prepare data transfer and tell what to do after */
-static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
- EndTransferFunc *end_transfer_func)
+void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
+ EndTransferFunc *end_transfer_func)
{
s->end_transfer_func = end_transfer_func;
s->data_ptr = buf;
@@ -347,7 +318,7 @@ static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
s->bus->dma->ops->start_transfer(s->bus->dma);
}
-static void ide_transfer_stop(IDEState *s)
+void ide_transfer_stop(IDEState *s)
{
s->end_transfer_func = ide_transfer_stop;
s->data_ptr = s->io_buffer;
@@ -447,7 +418,7 @@ static void dma_buf_commit(IDEState *s, int is_write)
qemu_sglist_destroy(&s->sg);
}
-static void ide_set_inactive(IDEState *s)
+void ide_set_inactive(IDEState *s)
{
s->bus->dma->aiocb = NULL;
s->bus->dma->ops->set_inactive(s->bus->dma);
@@ -617,38 +588,6 @@ void ide_sector_write(IDEState *s)
}
}
-void ide_atapi_cmd_ok(IDEState *s)
-{
- s->error = 0;
- s->status = READY_STAT | SEEK_STAT;
- s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
- ide_set_irq(s->bus);
-}
-
-void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc)
-{
-#ifdef DEBUG_IDE_ATAPI
- printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);
-#endif
- s->error = sense_key << 4;
- s->status = READY_STAT | ERR_STAT;
- s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
- s->sense_key = sense_key;
- s->asc = asc;
- ide_set_irq(s->bus);
-}
-
-static void ide_atapi_cmd_check_status(IDEState *s)
-{
-#ifdef DEBUG_IDE_ATAPI
- printf("atapi_cmd_check_status\n");
-#endif
- s->error = MC_ERR | (SENSE_UNIT_ATTENTION << 4);
- s->status = ERR_STAT;
- s->nsector = 0;
- ide_set_irq(s->bus);
-}
-
static void ide_flush_cb(void *opaque, int ret)
{
IDEState *s = opaque;
@@ -679,995 +618,6 @@ void ide_flush_cache(IDEState *s)
}
}
-static inline void cpu_to_ube16(uint8_t *buf, int val)
-{
- buf[0] = val >> 8;
- buf[1] = val & 0xff;
-}
-
-static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)
-{
- buf[0] = val >> 24;
- buf[1] = val >> 16;
- buf[2] = val >> 8;
- buf[3] = val & 0xff;
-}
-
-static inline int ube16_to_cpu(const uint8_t *buf)
-{
- return (buf[0] << 8) | buf[1];
-}
-
-static inline int ube32_to_cpu(const uint8_t *buf)
-{
- return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
-}
-
-static void lba_to_msf(uint8_t *buf, int lba)
-{
- lba += 150;
- buf[0] = (lba / 75) / 60;
- buf[1] = (lba / 75) % 60;
- buf[2] = lba % 75;
-}
-
-static void cd_data_to_raw(uint8_t *buf, int lba)
-{
- /* sync bytes */
- buf[0] = 0x00;
- memset(buf + 1, 0xff, 10);
- buf[11] = 0x00;
- buf += 12;
- /* MSF */
- lba_to_msf(buf, lba);
- buf[3] = 0x01; /* mode 1 data */
- buf += 4;
- /* data */
- buf += 2048;
- /* XXX: ECC not computed */
- memset(buf, 0, 288);
-}
-
-static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf,
- int sector_size)
-{
- int ret;
-
- switch(sector_size) {
- case 2048:
- ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4);
- break;
- case 2352:
- ret = bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4);
- if (ret < 0)
- return ret;
- cd_data_to_raw(buf, lba);
- break;
- default:
- ret = -EIO;
- break;
- }
- return ret;
-}
-
-void ide_atapi_io_error(IDEState *s, int ret)
-{
- /* XXX: handle more errors */
- if (ret == -ENOMEDIUM) {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- } else {
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_LOGICAL_BLOCK_OOR);
- }
-}
-
-/* The whole ATAPI transfer logic is handled in this function */
-static void ide_atapi_cmd_reply_end(IDEState *s)
-{
- int byte_count_limit, size, ret;
-#ifdef DEBUG_IDE_ATAPI
- printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",
- s->packet_transfer_size,
- s->elementary_transfer_size,
- s->io_buffer_index);
-#endif
- if (s->packet_transfer_size <= 0) {
- /* end of transfer */
- ide_transfer_stop(s);
- s->status = READY_STAT | SEEK_STAT;
- s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
- ide_set_irq(s->bus);
-#ifdef DEBUG_IDE_ATAPI
- printf("status=0x%x\n", s->status);
-#endif
- } else {
- /* see if a new sector must be read */
- if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {
- ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);
- if (ret < 0) {
- ide_transfer_stop(s);
- ide_atapi_io_error(s, ret);
- return;
- }
- s->lba++;
- s->io_buffer_index = 0;
- }
- if (s->elementary_transfer_size > 0) {
- /* there are some data left to transmit in this elementary
- transfer */
- size = s->cd_sector_size - s->io_buffer_index;
- if (size > s->elementary_transfer_size)
- size = s->elementary_transfer_size;
- s->packet_transfer_size -= size;
- s->elementary_transfer_size -= size;
- s->io_buffer_index += size;
- ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,
- size, ide_atapi_cmd_reply_end);
- } else {
- /* a new transfer is needed */
- s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
- byte_count_limit = s->lcyl | (s->hcyl << 8);
-#ifdef DEBUG_IDE_ATAPI
- printf("byte_count_limit=%d\n", byte_count_limit);
-#endif
- if (byte_count_limit == 0xffff)
- byte_count_limit--;
- size = s->packet_transfer_size;
- if (size > byte_count_limit) {
- /* byte count limit must be even if this case */
- if (byte_count_limit & 1)
- byte_count_limit--;
- size = byte_count_limit;
- }
- s->lcyl = size;
- s->hcyl = size >> 8;
- s->elementary_transfer_size = size;
- /* we cannot transmit more than one sector at a time */
- if (s->lba != -1) {
- if (size > (s->cd_sector_size - s->io_buffer_index))
- size = (s->cd_sector_size - s->io_buffer_index);
- }
- s->packet_transfer_size -= size;
- s->elementary_transfer_size -= size;
- s->io_buffer_index += size;
- ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,
- size, ide_atapi_cmd_reply_end);
- ide_set_irq(s->bus);
-#ifdef DEBUG_IDE_ATAPI
- printf("status=0x%x\n", s->status);
-#endif
- }
- }
-}
-
-/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */
-static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
-{
- if (size > max_size)
- size = max_size;
- s->lba = -1; /* no sector read */
- s->packet_transfer_size = size;
- s->io_buffer_size = size; /* dma: send the reply data as one chunk */
- s->elementary_transfer_size = 0;
- s->io_buffer_index = 0;
-
- if (s->atapi_dma) {
- s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
- s->bus->dma->ops->start_dma(s->bus->dma, s,
- ide_atapi_cmd_read_dma_cb);
- } else {
- s->status = READY_STAT | SEEK_STAT;
- ide_atapi_cmd_reply_end(s);
- }
-}
-
-/* start a CD-CDROM read command */
-static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors,
- int sector_size)
-{
- s->lba = lba;
- s->packet_transfer_size = nb_sectors * sector_size;
- s->elementary_transfer_size = 0;
- s->io_buffer_index = sector_size;
- s->cd_sector_size = sector_size;
-
- s->status = READY_STAT | SEEK_STAT;
- ide_atapi_cmd_reply_end(s);
-}
-
-/* ATAPI DMA support */
-
-/* XXX: handle read errors */
-static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
-{
- IDEState *s = opaque;
- int data_offset, n;
-
- if (ret < 0) {
- ide_atapi_io_error(s, ret);
- goto eot;
- }
-
- if (s->io_buffer_size > 0) {
- /*
- * For a cdrom read sector command (s->lba != -1),
- * adjust the lba for the next s->io_buffer_size chunk
- * and dma the current chunk.
- * For a command != read (s->lba == -1), just transfer
- * the reply data.
- */
- if (s->lba != -1) {
- if (s->cd_sector_size == 2352) {
- n = 1;
- cd_data_to_raw(s->io_buffer, s->lba);
- } else {
- n = s->io_buffer_size >> 11;
- }
- s->lba += n;
- }
- s->packet_transfer_size -= s->io_buffer_size;
- if (s->bus->dma->ops->rw_buf(s->bus->dma, 1) == 0)
- goto eot;
- }
-
- if (s->packet_transfer_size <= 0) {
- s->status = READY_STAT | SEEK_STAT;
- s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
- ide_set_irq(s->bus);
- eot:
- s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT);
- ide_set_inactive(s);
- return;
- }
-
- s->io_buffer_index = 0;
- if (s->cd_sector_size == 2352) {
- n = 1;
- s->io_buffer_size = s->cd_sector_size;
- data_offset = 16;
- } else {
- n = s->packet_transfer_size >> 11;
- if (n > (IDE_DMA_BUF_SECTORS / 4))
- n = (IDE_DMA_BUF_SECTORS / 4);
- s->io_buffer_size = n * 2048;
- data_offset = 0;
- }
-#ifdef DEBUG_AIO
- printf("aio_read_cd: lba=%u n=%d\n", s->lba, n);
-#endif
- s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset);
- s->bus->dma->iov.iov_len = n * 4 * 512;
- qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1);
- s->bus->dma->aiocb = bdrv_aio_readv(s->bs, (int64_t)s->lba << 2,
- &s->bus->dma->qiov, n * 4,
- ide_atapi_cmd_read_dma_cb, s);
- if (!s->bus->dma->aiocb) {
- /* Note: media not present is the most likely case */
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- goto eot;
- }
-}
-
-/* start a CD-CDROM read command with DMA */
-/* XXX: test if DMA is available */
-static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,
- int sector_size)
-{
- s->lba = lba;
- s->packet_transfer_size = nb_sectors * sector_size;
- s->io_buffer_index = 0;
- s->io_buffer_size = 0;
- s->cd_sector_size = sector_size;
-
- /* XXX: check if BUSY_STAT should be set */
- s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
- s->bus->dma->ops->start_dma(s->bus->dma, s,
- ide_atapi_cmd_read_dma_cb);
-}
-
-static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
- int sector_size)
-{
-#ifdef DEBUG_IDE_ATAPI
- printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio",
- lba, nb_sectors);
-#endif
- if (s->atapi_dma) {
- ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
- } else {
- ide_atapi_cmd_read_pio(s, lba, nb_sectors, sector_size);
- }
-}
-
-static inline uint8_t ide_atapi_set_profile(uint8_t *buf, uint8_t *index,
- uint16_t profile)
-{
- uint8_t *buf_profile = buf + 12; /* start of profiles */
-
- buf_profile += ((*index) * 4); /* start of indexed profile */
- cpu_to_ube16 (buf_profile, profile);
- buf_profile[2] = ((buf_profile[0] == buf[6]) && (buf_profile[1] == buf[7]));
-
- /* each profile adds 4 bytes to the response */
- (*index)++;
- buf[11] += 4; /* Additional Length */
-
- return 4;
-}
-
-static int ide_dvd_read_structure(IDEState *s, int format,
- const uint8_t *packet, uint8_t *buf)
-{
- switch (format) {
- case 0x0: /* Physical format information */
- {
- int layer = packet[6];
- uint64_t total_sectors;
-
- if (layer != 0)
- return -ASC_INV_FIELD_IN_CMD_PACKET;
-
- bdrv_get_geometry(s->bs, &total_sectors);
- total_sectors >>= 2;
- if (total_sectors == 0)
- return -ASC_MEDIUM_NOT_PRESENT;
-
- buf[4] = 1; /* DVD-ROM, part version 1 */
- buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
- buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */
- buf[7] = 0; /* default densities */
-
- /* FIXME: 0x30000 per spec? */
- cpu_to_ube32(buf + 8, 0); /* start sector */
- cpu_to_ube32(buf + 12, total_sectors - 1); /* end sector */
- cpu_to_ube32(buf + 16, total_sectors - 1); /* l0 end sector */
-
- /* Size of buffer, not including 2 byte size field */
- cpu_to_be16wu((uint16_t *)buf, 2048 + 2);
-
- /* 2k data + 4 byte header */
- return (2048 + 4);
- }
-
- case 0x01: /* DVD copyright information */
- buf[4] = 0; /* no copyright data */
- buf[5] = 0; /* no region restrictions */
-
- /* Size of buffer, not including 2 byte size field */
- cpu_to_be16wu((uint16_t *)buf, 4 + 2);
-
- /* 4 byte header + 4 byte data */
- return (4 + 4);
-
- case 0x03: /* BCA information - invalid field for no BCA info */
- return -ASC_INV_FIELD_IN_CMD_PACKET;
-
- case 0x04: /* DVD disc manufacturing information */
- /* Size of buffer, not including 2 byte size field */
- cpu_to_be16wu((uint16_t *)buf, 2048 + 2);
-
- /* 2k data + 4 byte header */
- return (2048 + 4);
-
- case 0xff:
- /*
- * This lists all the command capabilities above. Add new ones
- * in order and update the length and buffer return values.
- */
-
- buf[4] = 0x00; /* Physical format */
- buf[5] = 0x40; /* Not writable, is readable */
- cpu_to_be16wu((uint16_t *)(buf + 6), 2048 + 4);
-
- buf[8] = 0x01; /* Copyright info */
- buf[9] = 0x40; /* Not writable, is readable */
- cpu_to_be16wu((uint16_t *)(buf + 10), 4 + 4);
-
- buf[12] = 0x03; /* BCA info */
- buf[13] = 0x40; /* Not writable, is readable */
- cpu_to_be16wu((uint16_t *)(buf + 14), 188 + 4);
-
- buf[16] = 0x04; /* Manufacturing info */
- buf[17] = 0x40; /* Not writable, is readable */
- cpu_to_be16wu((uint16_t *)(buf + 18), 2048 + 4);
-
- /* Size of buffer, not including 2 byte size field */
- cpu_to_be16wu((uint16_t *)buf, 16 + 2);
-
- /* data written + 4 byte header */
- return (16 + 4);
-
- default: /* TODO: formats beyond DVD-ROM requires */
- return -ASC_INV_FIELD_IN_CMD_PACKET;
- }
-}
-
-static unsigned int event_status_media(IDEState *s,
- uint8_t *buf)
-{
- enum media_event_code {
- MEC_NO_CHANGE = 0, /* Status unchanged */
- MEC_EJECT_REQUESTED, /* received a request from user to eject */
- MEC_NEW_MEDIA, /* new media inserted and ready for access */
- MEC_MEDIA_REMOVAL, /* only for media changers */
- MEC_MEDIA_CHANGED, /* only for media changers */
- MEC_BG_FORMAT_COMPLETED, /* MRW or DVD+RW b/g format completed */
- MEC_BG_FORMAT_RESTARTED, /* MRW or DVD+RW b/g format restarted */
- };
- enum media_status {
- MS_TRAY_OPEN = 1,
- MS_MEDIA_PRESENT = 2,
- };
- uint8_t event_code, media_status;
-
- media_status = 0;
- if (s->bs->tray_open) {
- media_status = MS_TRAY_OPEN;
- } else if (bdrv_is_inserted(s->bs)) {
- media_status = MS_MEDIA_PRESENT;
- }
-
- /* Event notification descriptor */
- event_code = MEC_NO_CHANGE;
- if (media_status != MS_TRAY_OPEN && s->events.new_media) {
- event_code = MEC_NEW_MEDIA;
- s->events.new_media = false;
- }
-
- buf[4] = event_code;
- buf[5] = media_status;
-
- /* These fields are reserved, just clear them. */
- buf[6] = 0;
- buf[7] = 0;
-
- return 8; /* We wrote to 4 extra bytes from the header */
-}
-
-static void handle_get_event_status_notification(IDEState *s,
- uint8_t *buf,
- const uint8_t *packet)
-{
- struct {
- uint8_t opcode;
- uint8_t polled; /* lsb bit is polled; others are reserved */
- uint8_t reserved2[2];
- uint8_t class;
- uint8_t reserved3[2];
- uint16_t len;
- uint8_t control;
- } __attribute__((packed)) *gesn_cdb;
-
- struct {
- uint16_t len;
- uint8_t notification_class;
- uint8_t supported_events;
- } __attribute((packed)) *gesn_event_header;
-
- enum notification_class_request_type {
- NCR_RESERVED1 = 1 << 0,
- NCR_OPERATIONAL_CHANGE = 1 << 1,
- NCR_POWER_MANAGEMENT = 1 << 2,
- NCR_EXTERNAL_REQUEST = 1 << 3,
- NCR_MEDIA = 1 << 4,
- NCR_MULTI_HOST = 1 << 5,
- NCR_DEVICE_BUSY = 1 << 6,
- NCR_RESERVED2 = 1 << 7,
- };
- enum event_notification_class_field {
- ENC_NO_EVENTS = 0,
- ENC_OPERATIONAL_CHANGE,
- ENC_POWER_MANAGEMENT,
- ENC_EXTERNAL_REQUEST,
- ENC_MEDIA,
- ENC_MULTIPLE_HOSTS,
- ENC_DEVICE_BUSY,
- ENC_RESERVED,
- };
- unsigned int max_len, used_len;
-
- gesn_cdb = (void *)packet;
- gesn_event_header = (void *)buf;
-
- max_len = be16_to_cpu(gesn_cdb->len);
-
- /* It is fine by the MMC spec to not support async mode operations */
- if (!(gesn_cdb->polled & 0x01)) { /* asynchronous mode */
- /* Only polling is supported, asynchronous mode is not. */
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- return;
- }
-
- /* polling mode operation */
-
- /*
- * These are the supported events.
- *
- * We currently only support requests of the 'media' type.
- */
- gesn_event_header->supported_events = NCR_MEDIA;
-
- /*
- * We use |= below to set the class field; other bits in this byte
- * are reserved now but this is useful to do if we have to use the
- * reserved fields later.
- */
- gesn_event_header->notification_class = 0;
-
- /*
- * Responses to requests are to be based on request priority. The
- * notification_class_request_type enum above specifies the
- * priority: upper elements are higher prio than lower ones.
- */
- if (gesn_cdb->class & NCR_MEDIA) {
- gesn_event_header->notification_class |= ENC_MEDIA;
- used_len = event_status_media(s, buf);
- } else {
- gesn_event_header->notification_class = 0x80; /* No event available */
- used_len = sizeof(*gesn_event_header);
- }
- gesn_event_header->len = cpu_to_be16(used_len
- - sizeof(*gesn_event_header));
- ide_atapi_cmd_reply(s, used_len, max_len);
-}
-
-static void ide_atapi_cmd(IDEState *s)
-{
- const uint8_t *packet;
- uint8_t *buf;
- int max_len;
-
- packet = s->io_buffer;
- buf = s->io_buffer;
-#ifdef DEBUG_IDE_ATAPI
- {
- int i;
- printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
- for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
- printf(" %02x", packet[i]);
- }
- printf("\n");
- }
-#endif
- /*
- * If there's a UNIT_ATTENTION condition pending, only
- * REQUEST_SENSE, INQUIRY, GET_CONFIGURATION and
- * GET_EVENT_STATUS_NOTIFICATION commands are allowed to complete.
- * MMC-5, section 4.1.6.1 lists only these commands being allowed
- * to complete, with other commands getting a CHECK condition
- * response unless a higher priority status, defined by the drive
- * here, is pending.
- */
- if (s->sense_key == SENSE_UNIT_ATTENTION &&
- s->io_buffer[0] != GPCMD_REQUEST_SENSE &&
- s->io_buffer[0] != GPCMD_INQUIRY &&
- s->io_buffer[0] != GPCMD_GET_EVENT_STATUS_NOTIFICATION) {
- ide_atapi_cmd_check_status(s);
- return;
- }
- switch(s->io_buffer[0]) {
- case GPCMD_TEST_UNIT_READY:
- if (bdrv_is_inserted(s->bs) && !s->cdrom_changed) {
- ide_atapi_cmd_ok(s);
- } else {
- s->cdrom_changed = 0;
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- }
- break;
- case GPCMD_MODE_SENSE_6:
- case GPCMD_MODE_SENSE_10:
- {
- int action, code;
- if (packet[0] == GPCMD_MODE_SENSE_10)
- max_len = ube16_to_cpu(packet + 7);
- else
- max_len = packet[4];
- action = packet[2] >> 6;
- code = packet[2] & 0x3f;
- switch(action) {
- case 0: /* current values */
- switch(code) {
- case GPMODE_R_W_ERROR_PAGE: /* error recovery */
- cpu_to_ube16(&buf[0], 16 + 6);
- buf[2] = 0x70;
- buf[3] = 0;
- buf[4] = 0;
- buf[5] = 0;
- buf[6] = 0;
- buf[7] = 0;
-
- buf[8] = 0x01;
- buf[9] = 0x06;
- buf[10] = 0x00;
- buf[11] = 0x05;
- buf[12] = 0x00;
- buf[13] = 0x00;
- buf[14] = 0x00;
- buf[15] = 0x00;
- ide_atapi_cmd_reply(s, 16, max_len);
- break;
- case GPMODE_AUDIO_CTL_PAGE:
- cpu_to_ube16(&buf[0], 24 + 6);
- buf[2] = 0x70;
- buf[3] = 0;
- buf[4] = 0;
- buf[5] = 0;
- buf[6] = 0;
- buf[7] = 0;
-
- /* Fill with CDROM audio volume */
- buf[17] = 0;
- buf[19] = 0;
- buf[21] = 0;
- buf[23] = 0;
-
- ide_atapi_cmd_reply(s, 24, max_len);
- break;
- case GPMODE_CAPABILITIES_PAGE:
- cpu_to_ube16(&buf[0], 28 + 6);
- buf[2] = 0x70;
- buf[3] = 0;
- buf[4] = 0;
- buf[5] = 0;
- buf[6] = 0;
- buf[7] = 0;
-
- buf[8] = 0x2a;
- buf[9] = 0x12;
- buf[10] = 0x00;
- buf[11] = 0x00;
-
- /* Claim PLAY_AUDIO capability (0x01) since some Linux
- code checks for this to automount media. */
- buf[12] = 0x71;
- buf[13] = 3 << 5;
- buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
- if (bdrv_is_locked(s->bs))
- buf[6] |= 1 << 1;
- buf[15] = 0x00;
- cpu_to_ube16(&buf[16], 706);
- buf[18] = 0;
- buf[19] = 2;
- cpu_to_ube16(&buf[20], 512);
- cpu_to_ube16(&buf[22], 706);
- buf[24] = 0;
- buf[25] = 0;
- buf[26] = 0;
- buf[27] = 0;
- ide_atapi_cmd_reply(s, 28, max_len);
- break;
- default:
- goto error_cmd;
- }
- break;
- case 1: /* changeable values */
- goto error_cmd;
- case 2: /* default values */
- goto error_cmd;
- default:
- case 3: /* saved values */
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
- break;
- }
- }
- break;
- case GPCMD_REQUEST_SENSE:
- max_len = packet[4];
- memset(buf, 0, 18);
- buf[0] = 0x70 | (1 << 7);
- buf[2] = s->sense_key;
- buf[7] = 10;
- buf[12] = s->asc;
- if (s->sense_key == SENSE_UNIT_ATTENTION)
- s->sense_key = SENSE_NONE;
- ide_atapi_cmd_reply(s, 18, max_len);
- break;
- case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
- bdrv_set_locked(s->bs, packet[4] & 1);
- ide_atapi_cmd_ok(s);
- break;
- case GPCMD_READ_10:
- case GPCMD_READ_12:
- {
- int nb_sectors, lba;
-
- if (packet[0] == GPCMD_READ_10)
- nb_sectors = ube16_to_cpu(packet + 7);
- else
- nb_sectors = ube32_to_cpu(packet + 6);
- lba = ube32_to_cpu(packet + 2);
- if (nb_sectors == 0) {
- ide_atapi_cmd_ok(s);
- break;
- }
- ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
- }
- break;
- case GPCMD_READ_CD:
- {
- int nb_sectors, lba, transfer_request;
-
- nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8];
- lba = ube32_to_cpu(packet + 2);
- if (nb_sectors == 0) {
- ide_atapi_cmd_ok(s);
- break;
- }
- transfer_request = packet[9];
- switch(transfer_request & 0xf8) {
- case 0x00:
- /* nothing */
- ide_atapi_cmd_ok(s);
- break;
- case 0x10:
- /* normal read */
- ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
- break;
- case 0xf8:
- /* read all data */
- ide_atapi_cmd_read(s, lba, nb_sectors, 2352);
- break;
- default:
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- break;
- }
- }
- break;
- case GPCMD_SEEK:
- {
- unsigned int lba;
- uint64_t total_sectors;
-
- bdrv_get_geometry(s->bs, &total_sectors);
- total_sectors >>= 2;
- if (total_sectors == 0) {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- break;
- }
- lba = ube32_to_cpu(packet + 2);
- if (lba >= total_sectors) {
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_LOGICAL_BLOCK_OOR);
- break;
- }
- ide_atapi_cmd_ok(s);
- }
- break;
- case GPCMD_START_STOP_UNIT:
- {
- int start, eject, sense, err = 0;
- start = packet[4] & 1;
- eject = (packet[4] >> 1) & 1;
-
- if (eject) {
- err = bdrv_eject(s->bs, !start);
- }
-
- switch (err) {
- case 0:
- ide_atapi_cmd_ok(s);
- break;
- case -EBUSY:
- sense = SENSE_NOT_READY;
- if (bdrv_is_inserted(s->bs)) {
- sense = SENSE_ILLEGAL_REQUEST;
- }
- ide_atapi_cmd_error(s, sense,
- ASC_MEDIA_REMOVAL_PREVENTED);
- break;
- default:
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- break;
- }
- }
- break;
- case GPCMD_MECHANISM_STATUS:
- {
- max_len = ube16_to_cpu(packet + 8);
- cpu_to_ube16(buf, 0);
- /* no current LBA */
- buf[2] = 0;
- buf[3] = 0;
- buf[4] = 0;
- buf[5] = 1;
- cpu_to_ube16(buf + 6, 0);
- ide_atapi_cmd_reply(s, 8, max_len);
- }
- break;
- case GPCMD_READ_TOC_PMA_ATIP:
- {
- int format, msf, start_track, len;
- uint64_t total_sectors;
-
- bdrv_get_geometry(s->bs, &total_sectors);
- total_sectors >>= 2;
- if (total_sectors == 0) {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- break;
- }
- max_len = ube16_to_cpu(packet + 7);
- format = packet[9] >> 6;
- msf = (packet[1] >> 1) & 1;
- start_track = packet[6];
- switch(format) {
- case 0:
- len = cdrom_read_toc(total_sectors, buf, msf, start_track);
- if (len < 0)
- goto error_cmd;
- ide_atapi_cmd_reply(s, len, max_len);
- break;
- case 1:
- /* multi session : only a single session defined */
- memset(buf, 0, 12);
- buf[1] = 0x0a;
- buf[2] = 0x01;
- buf[3] = 0x01;
- ide_atapi_cmd_reply(s, 12, max_len);
- break;
- case 2:
- len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track);
- if (len < 0)
- goto error_cmd;
- ide_atapi_cmd_reply(s, len, max_len);
- break;
- default:
- error_cmd:
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- break;
- }
- }
- break;
- case GPCMD_READ_CDVD_CAPACITY:
- {
- uint64_t total_sectors;
-
- bdrv_get_geometry(s->bs, &total_sectors);
- total_sectors >>= 2;
- if (total_sectors == 0) {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- break;
- }
- /* NOTE: it is really the number of sectors minus 1 */
- cpu_to_ube32(buf, total_sectors - 1);
- cpu_to_ube32(buf + 4, 2048);
- ide_atapi_cmd_reply(s, 8, 8);
- }
- break;
- case GPCMD_READ_DVD_STRUCTURE:
- {
- int media = packet[1];
- int format = packet[7];
- int ret;
-
- max_len = ube16_to_cpu(packet + 8);
-
- if (format < 0xff) {
- if (media_is_cd(s)) {
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_INCOMPATIBLE_FORMAT);
- break;
- } else if (!media_present(s)) {
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- break;
- }
- }
-
- memset(buf, 0, max_len > IDE_DMA_BUF_SECTORS * 512 + 4 ?
- IDE_DMA_BUF_SECTORS * 512 + 4 : max_len);
-
- switch (format) {
- case 0x00 ... 0x7f:
- case 0xff:
- if (media == 0) {
- ret = ide_dvd_read_structure(s, format, packet, buf);
-
- if (ret < 0)
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, -ret);
- else
- ide_atapi_cmd_reply(s, ret, max_len);
-
- break;
- }
- /* TODO: BD support, fall through for now */
-
- /* Generic disk structures */
- case 0x80: /* TODO: AACS volume identifier */
- case 0x81: /* TODO: AACS media serial number */
- case 0x82: /* TODO: AACS media identifier */
- case 0x83: /* TODO: AACS media key block */
- case 0x90: /* TODO: List of recognized format layers */
- case 0xc0: /* TODO: Write protection status */
- default:
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- break;
- }
- }
- break;
- case GPCMD_SET_SPEED:
- ide_atapi_cmd_ok(s);
- break;
- case GPCMD_INQUIRY:
- max_len = packet[4];
- buf[0] = 0x05; /* CD-ROM */
- buf[1] = 0x80; /* removable */
- buf[2] = 0x00; /* ISO */
- buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */
- buf[4] = 31; /* additional length */
- buf[5] = 0; /* reserved */
- buf[6] = 0; /* reserved */
- buf[7] = 0; /* reserved */
- padstr8(buf + 8, 8, "QEMU");
- padstr8(buf + 16, 16, "QEMU DVD-ROM");
- padstr8(buf + 32, 4, s->version);
- ide_atapi_cmd_reply(s, 36, max_len);
- break;
- case GPCMD_GET_CONFIGURATION:
- {
- uint32_t len;
- uint8_t index = 0;
-
- /* only feature 0 is supported */
- if (packet[2] != 0 || packet[3] != 0) {
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- break;
- }
-
- /* XXX: could result in alignment problems in some architectures */
- max_len = ube16_to_cpu(packet + 7);
-
- /*
- * XXX: avoid overflow for io_buffer if max_len is bigger than
- * the size of that buffer (dimensioned to max number of
- * sectors to transfer at once)
- *
- * Only a problem if the feature/profiles grow.
- */
- if (max_len > 512) /* XXX: assume 1 sector */
- max_len = 512;
-
- memset(buf, 0, max_len);
- /*
- * the number of sectors from the media tells us which profile
- * to use as current. 0 means there is no media
- */
- if (media_is_dvd(s))
- cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM);
- else if (media_is_cd(s))
- cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM);
-
- buf[10] = 0x02 | 0x01; /* persistent and current */
- len = 12; /* headers: 8 + 4 */
- len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_DVD_ROM);
- len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_CD_ROM);
- cpu_to_ube32(buf, len - 4); /* data length */
-
- ide_atapi_cmd_reply(s, len, max_len);
- break;
- }
- case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
- handle_get_event_status_notification(s, buf, packet);
- break;
- default:
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_ILLEGAL_OPCODE);
- break;
- }
-}
-
static void ide_cfata_metadata_inquiry(IDEState *s)
{
uint16_t *p;
@@ -1734,8 +684,13 @@ static void cdrom_change_cb(void *opaque, int reason)
bdrv_get_geometry(s->bs, &nb_sectors);
s->nb_sectors = nb_sectors;
- s->sense_key = SENSE_UNIT_ATTENTION;
- s->asc = ASC_MEDIUM_MAY_HAVE_CHANGED;
+ /*
+ * First indicate to the guest that a CD has been removed. That's
+ * done on the next command the guest sends us.
+ *
+ * Then we set SENSE_UNIT_ATTENTION, by which the guest will
+ * detect a new CD in the drive. See ide_atapi_cmd() for details.
+ */
s->cdrom_changed = 1;
s->events.new_media = true;
ide_set_irq(s->bus);
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index f242d7a81..a3d475c59 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -67,7 +67,6 @@
#include <hw/isa.h>
#include "block.h"
#include "block_int.h"
-#include "sysemu.h"
#include "dma.h"
#include <hw/ide/pci.h>
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index ba7e9a8ee..aa198b6b1 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -9,6 +9,7 @@
#include <hw/ide.h>
#include "block_int.h"
#include "iorange.h"
+#include "dma.h"
/* debug IDE devices */
//#define DEBUG_IDE
@@ -570,6 +571,15 @@ void ide_sector_write(IDEState *s);
void ide_sector_read(IDEState *s);
void ide_flush_cache(IDEState *s);
+void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
+ EndTransferFunc *end_transfer_func);
+void ide_transfer_stop(IDEState *s);
+void ide_set_inactive(IDEState *s);
+
+/* hw/ide/atapi.c */
+void ide_atapi_cmd(IDEState *s);
+void ide_atapi_cmd_reply_end(IDEState *s);
+
/* hw/ide/qdev.c */
void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id);
IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive);
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index 8c59c5a47..4ac745324 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -27,7 +27,6 @@
#include <hw/isa.h>
#include "block.h"
#include "block_int.h"
-#include "sysemu.h"
#include "dma.h"
#include <hw/ide/internal.h>
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index c1b4caab5..7107f6b3c 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -27,7 +27,6 @@
#include <hw/mac_dbdma.h>
#include "block.h"
#include "block_int.h"
-#include "sysemu.h"
#include "dma.h"
#include <hw/ide/internal.h>
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index 2ceeb87c0..9fbbf0e78 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -27,7 +27,6 @@
#include <hw/pcmcia.h>
#include "block.h"
#include "block_int.h"
-#include "sysemu.h"
#include "dma.h"
#include <hw/ide/internal.h>
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index 82b24b673..10f6f4063 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -25,7 +25,6 @@
#include <hw/hw.h>
#include "block.h"
#include "block_int.h"
-#include "sysemu.h"
#include "dma.h"
#include <hw/ide/internal.h>
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 35168cb46..65cb56c38 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -28,7 +28,6 @@
#include <hw/isa.h>
#include "block.h"
#include "block_int.h"
-#include "sysemu.h"
#include "dma.h"
#include <hw/ide/pci.h>
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index b04994082..a6c27be82 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -10,7 +10,6 @@
#include "sysbus.h"
#include "primecell.h"
#include "devices.h"
-#include "sysemu.h"
#include "boards.h"
#include "arm-misc.h"
#include "net.h"
diff --git a/hw/ioapic.c b/hw/ioapic.c
index e806822d9..2ac612711 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -163,8 +163,9 @@ static void ioapic_set_irq(void *opaque, int vector, int level)
s->irr &= ~mask;
}
} else {
- /* edge triggered */
- if (level) {
+ /* According to the 82093AA manual, we must ignore edge requests
+ * if the input pin is masked. */
+ if (level && !(entry & IOAPIC_LVT_MASKED)) {
s->irr |= mask;
ioapic_service(s);
}
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index d07aa410f..27655436a 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -17,7 +17,6 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "hw.h"
-#include "sysemu.h"
#include "monitor.h"
#include "sysbus.h"
#include "isa.h"
diff --git a/hw/kvmclock.c b/hw/kvmclock.c
index b6ceddfba..004c4add8 100644
--- a/hw/kvmclock.c
+++ b/hw/kvmclock.c
@@ -103,7 +103,11 @@ static SysBusDeviceInfo kvmclock_info = {
void kvmclock_create(void)
{
if (kvm_enabled() &&
- first_cpu->cpuid_kvm_features & (1ULL << KVM_FEATURE_CLOCKSOURCE)) {
+ first_cpu->cpuid_kvm_features & ((1ULL << KVM_FEATURE_CLOCKSOURCE)
+#ifdef KVM_FEATURE_CLOCKSOURCE2
+ || (1ULL << KVM_FEATURE_CLOCKSOURCE2)
+#endif
+ )) {
sysbus_create_simple("kvmclock", -1, NULL);
}
}
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index 85190f0bf..64629230c 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -21,7 +21,6 @@
#include "hw.h"
#include "net.h"
#include "flash.h"
-#include "sysemu.h"
#include "devices.h"
#include "boards.h"
#include "loader.h"
diff --git a/hw/m48t59.c b/hw/m48t59.c
index 9f39d6bbf..537c0f7b1 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -585,28 +585,18 @@ static CPUReadMemoryFunc * const nvram_read[] = {
&nvram_readl,
};
-static void m48t59_save(QEMUFile *f, void *opaque)
-{
- M48t59State *s = opaque;
-
- qemu_put_8s(f, &s->lock);
- qemu_put_be16s(f, &s->addr);
- qemu_put_buffer(f, s->buffer, s->size);
-}
-
-static int m48t59_load(QEMUFile *f, void *opaque, int version_id)
-{
- M48t59State *s = opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_8s(f, &s->lock);
- qemu_get_be16s(f, &s->addr);
- qemu_get_buffer(f, s->buffer, s->size);
-
- return 0;
-}
+static const VMStateDescription vmstate_m48t59 = {
+ .name = "m48t59",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(lock, M48t59State),
+ VMSTATE_UINT16(addr, M48t59State),
+ VMSTATE_VBUFFER_UINT32(buffer, M48t59State, 0, NULL, 0, size),
+ VMSTATE_END_OF_LIST()
+ }
+};
static void m48t59_reset_common(M48t59State *NVRAM)
{
@@ -696,7 +686,7 @@ static void m48t59_init_common(M48t59State *s)
}
qemu_get_timedate(&s->alarm, 0);
- register_savevm(NULL, "m48t59", -1, 1, m48t59_save, m48t59_load, s);
+ vmstate_register(NULL, -1, &vmstate_m48t59, s);
}
static int m48t59_init_isa1(ISADevice *dev)
diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c
index 5680fa9c1..ed4458e3b 100644
--- a/hw/mac_dbdma.c
+++ b/hw/mac_dbdma.c
@@ -165,6 +165,10 @@ typedef struct DBDMA_channel {
int processing;
} DBDMA_channel;
+typedef struct {
+ DBDMA_channel channels[DBDMA_CHANNELS];
+} DBDMAState;
+
#ifdef DEBUG_DBDMA
static void dump_dbdma_cmd(dbdma_cmd *cmd)
{
@@ -617,31 +621,34 @@ static void channel_run(DBDMA_channel *ch)
}
}
-static void DBDMA_run (DBDMA_channel *ch)
+static void DBDMA_run(DBDMAState *s)
{
int channel;
- for (channel = 0; channel < DBDMA_CHANNELS; channel++, ch++) {
- uint32_t status = ch->regs[DBDMA_STATUS];
- if (!ch->processing && (status & RUN) && (status & ACTIVE))
- channel_run(ch);
+ for (channel = 0; channel < DBDMA_CHANNELS; channel++) {
+ DBDMA_channel *ch = &s->channels[channel];
+ uint32_t status = ch->regs[DBDMA_STATUS];
+ if (!ch->processing && (status & RUN) && (status & ACTIVE)) {
+ channel_run(ch);
+ }
}
}
static void DBDMA_run_bh(void *opaque)
{
- DBDMA_channel *ch = opaque;
+ DBDMAState *s = opaque;
DBDMA_DPRINTF("DBDMA_run_bh\n");
- DBDMA_run(ch);
+ DBDMA_run(s);
}
void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
DBDMA_rw rw, DBDMA_flush flush,
void *opaque)
{
- DBDMA_channel *ch = ( DBDMA_channel *)dbdma + nchan;
+ DBDMAState *s = dbdma;
+ DBDMA_channel *ch = &s->channels[nchan];
DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan);
@@ -700,7 +707,8 @@ static void dbdma_writel (void *opaque,
target_phys_addr_t addr, uint32_t value)
{
int channel = addr >> DBDMA_CHANNEL_SHIFT;
- DBDMA_channel *ch = (DBDMA_channel *)opaque + channel;
+ DBDMAState *s = opaque;
+ DBDMA_channel *ch = &s->channels[channel];
int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08x\n", addr, value);
@@ -749,7 +757,8 @@ static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
{
uint32_t value;
int channel = addr >> DBDMA_CHANNEL_SHIFT;
- DBDMA_channel *ch = (DBDMA_channel *)opaque + channel;
+ DBDMAState *s = opaque;
+ DBDMA_channel *ch = &s->channels[channel];
int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
value = ch->regs[reg];
@@ -801,49 +810,47 @@ static CPUReadMemoryFunc * const dbdma_read[] = {
dbdma_readl,
};
-static void dbdma_save(QEMUFile *f, void *opaque)
-{
- DBDMA_channel *s = opaque;
- unsigned int i, j;
-
- for (i = 0; i < DBDMA_CHANNELS; i++)
- for (j = 0; j < DBDMA_REGS; j++)
- qemu_put_be32s(f, &s[i].regs[j]);
-}
-
-static int dbdma_load(QEMUFile *f, void *opaque, int version_id)
-{
- DBDMA_channel *s = opaque;
- unsigned int i, j;
-
- if (version_id != 2)
- return -EINVAL;
-
- for (i = 0; i < DBDMA_CHANNELS; i++)
- for (j = 0; j < DBDMA_REGS; j++)
- qemu_get_be32s(f, &s[i].regs[j]);
+static const VMStateDescription vmstate_dbdma_channel = {
+ .name = "dbdma_channel",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS),
+ VMSTATE_END_OF_LIST()
+ }
+};
- return 0;
-}
+static const VMStateDescription vmstate_dbdma = {
+ .name = "dbdma",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1,
+ vmstate_dbdma_channel, DBDMA_channel),
+ VMSTATE_END_OF_LIST()
+ }
+};
static void dbdma_reset(void *opaque)
{
- DBDMA_channel *s = opaque;
+ DBDMAState *s = opaque;
int i;
for (i = 0; i < DBDMA_CHANNELS; i++)
- memset(s[i].regs, 0, DBDMA_SIZE);
+ memset(s->channels[i].regs, 0, DBDMA_SIZE);
}
void* DBDMA_init (int *dbdma_mem_index)
{
- DBDMA_channel *s;
+ DBDMAState *s;
- s = qemu_mallocz(sizeof(DBDMA_channel) * DBDMA_CHANNELS);
+ s = qemu_mallocz(sizeof(DBDMAState));
*dbdma_mem_index = cpu_register_io_memory(dbdma_read, dbdma_write, s,
DEVICE_LITTLE_ENDIAN);
- register_savevm(NULL, "dbdma", -1, 1, dbdma_save, dbdma_load, s);
+ vmstate_register(NULL, -1, &vmstate_dbdma, s);
qemu_register_reset(dbdma_reset, s);
dbdma_bh = qemu_bh_new(DBDMA_run_bh, s);
diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c
index c2a2fc21e..61e53d28b 100644
--- a/hw/mac_nvram.c
+++ b/hw/mac_nvram.c
@@ -38,7 +38,7 @@
#endif
struct MacIONVRAMState {
- target_phys_addr_t size;
+ uint32_t size;
int mem_index;
unsigned int it_shift;
uint8_t *data;
@@ -105,24 +105,17 @@ static CPUReadMemoryFunc * const nvram_read[] = {
&macio_nvram_readb,
};
-static void macio_nvram_save(QEMUFile *f, void *opaque)
-{
- MacIONVRAMState *s = (MacIONVRAMState *)opaque;
-
- qemu_put_buffer(f, s->data, s->size);
-}
-
-static int macio_nvram_load(QEMUFile *f, void *opaque, int version_id)
-{
- MacIONVRAMState *s = (MacIONVRAMState *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_buffer(f, s->data, s->size);
+static const VMStateDescription vmstate_macio_nvram = {
+ .name = "macio_nvram",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_VBUFFER_UINT32(data, MacIONVRAMState, 0, NULL, 0, size),
+ VMSTATE_END_OF_LIST()
+ }
+};
- return 0;
-}
static void macio_nvram_reset(void *opaque)
{
@@ -141,8 +134,7 @@ MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size,
s->mem_index = cpu_register_io_memory(nvram_read, nvram_write, s,
DEVICE_NATIVE_ENDIAN);
*mem_index = s->mem_index;
- register_savevm(NULL, "macio_nvram", -1, 1, macio_nvram_save,
- macio_nvram_load, s);
+ vmstate_register(NULL, -1, &vmstate_macio_nvram, s);
qemu_register_reset(macio_nvram_reset, s);
return s;
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 50691ca41..4792f0e3e 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -14,7 +14,6 @@
#include "net.h"
#include "devices.h"
#include "boards.h"
-#include "sysemu.h"
#include "flash.h"
#include "blockdev.h"
#include "sysbus.h"
diff --git a/hw/max111x.c b/hw/max111x.c
index 2844665ba..70cd1af24 100644
--- a/hw/max111x.c
+++ b/hw/max111x.c
@@ -15,7 +15,7 @@ typedef struct {
uint8_t tb1, rb2, rb3;
int cycle;
- int input[8];
+ uint8_t input[8];
int inputs, com;
} MAX111xState;
@@ -94,36 +94,22 @@ static uint32_t max111x_transfer(SSISlave *dev, uint32_t value)
return max111x_read(s);
}
-static void max111x_save(QEMUFile *f, void *opaque)
-{
- MAX111xState *s = (MAX111xState *) opaque;
- int i;
-
- qemu_put_8s(f, &s->tb1);
- qemu_put_8s(f, &s->rb2);
- qemu_put_8s(f, &s->rb3);
- qemu_put_be32(f, s->inputs);
- qemu_put_be32(f, s->com);
- for (i = 0; i < s->inputs; i ++)
- qemu_put_byte(f, s->input[i]);
-}
-
-static int max111x_load(QEMUFile *f, void *opaque, int version_id)
-{
- MAX111xState *s = (MAX111xState *) opaque;
- int i;
-
- qemu_get_8s(f, &s->tb1);
- qemu_get_8s(f, &s->rb2);
- qemu_get_8s(f, &s->rb3);
- if (s->inputs != qemu_get_be32(f))
- return -EINVAL;
- s->com = qemu_get_be32(f);
- for (i = 0; i < s->inputs; i ++)
- s->input[i] = qemu_get_byte(f);
-
- return 0;
-}
+static const VMStateDescription vmstate_max111x = {
+ .name = "max111x",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(tb1, MAX111xState),
+ VMSTATE_UINT8(rb2, MAX111xState),
+ VMSTATE_UINT8(rb3, MAX111xState),
+ VMSTATE_INT32_EQUAL(inputs, MAX111xState),
+ VMSTATE_INT32(com, MAX111xState),
+ VMSTATE_ARRAY_INT32_UNSAFE(input, MAX111xState, inputs,
+ vmstate_info_uint8, uint8_t),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int max111x_init(SSISlave *dev, int inputs)
{
@@ -143,8 +129,7 @@ static int max111x_init(SSISlave *dev, int inputs)
s->input[7] = 0x80;
s->com = 0;
- register_savevm(&dev->qdev, "max111x", -1, 0,
- max111x_save, max111x_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_max111x, s);
return 0;
}
diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h
index 15acdbccd..20de68ecc 100644
--- a/hw/milkymist-hw.h
+++ b/hw/milkymist-hw.h
@@ -1,6 +1,9 @@
#ifndef QEMU_HW_MILKYMIST_H
#define QEMU_HW_MILKYMIST_H
+#include "qdev.h"
+#include "qdev-addr.h"
+
static inline DeviceState *milkymist_uart_create(target_phys_addr_t base,
qemu_irq rx_irq, qemu_irq tx_irq)
{
@@ -183,6 +186,23 @@ static inline DeviceState *milkymist_minimac_create(target_phys_addr_t base,
return dev;
}
+static inline DeviceState *milkymist_minimac2_create(target_phys_addr_t base,
+ target_phys_addr_t buffers_base, qemu_irq rx_irq, qemu_irq tx_irq)
+{
+ DeviceState *dev;
+
+ qemu_check_nic_model(&nd_table[0], "minimac2");
+ dev = qdev_create(NULL, "milkymist-minimac2");
+ qdev_prop_set_taddr(dev, "buffers_base", buffers_base);
+ qdev_set_nic_properties(dev, &nd_table[0]);
+ qdev_init_nofail(dev);
+ sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 0, rx_irq);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 1, tx_irq);
+
+ return dev;
+}
+
static inline DeviceState *milkymist_softusb_create(target_phys_addr_t base,
qemu_irq irq, uint32_t pmem_base, uint32_t pmem_size,
uint32_t dmem_base, uint32_t dmem_size)
diff --git a/hw/milkymist-minimac.c b/hw/milkymist-minimac2.c
index b07f18d8a..c4e28187b 100644
--- a/hw/milkymist-minimac.c
+++ b/hw/milkymist-minimac2.c
@@ -1,7 +1,7 @@
/*
- * QEMU model of the Milkymist minimac block.
+ * QEMU model of the Milkymist minimac2 block.
*
- * Copyright (c) 2010 Michael Walle <michael@walle.cc>
+ * Copyright (c) 2011 Michael Walle <michael@walle.cc>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,7 +18,7 @@
*
*
* Specification available at:
- * http://www.milkymist.org/socdoc/minimac.pdf
+ * not available yet
*
*/
@@ -27,6 +27,7 @@
#include "trace.h"
#include "net.h"
#include "qemu-error.h"
+#include "qdev-addr.h"
#include <zlib.h>
@@ -34,25 +35,15 @@ enum {
R_SETUP = 0,
R_MDIO,
R_STATE0,
- R_ADDR0,
R_COUNT0,
R_STATE1,
- R_ADDR1,
R_COUNT1,
- R_STATE2,
- R_ADDR2,
- R_COUNT2,
- R_STATE3,
- R_ADDR3,
- R_COUNT3,
- R_TXADDR,
R_TXCOUNT,
R_MAX
};
enum {
- SETUP_RX_RST = (1<<0),
- SETUP_TX_RST = (1<<2),
+ SETUP_PHY_RST = (1<<0),
};
enum {
@@ -85,9 +76,10 @@ enum {
R_PHY_MAX = 32
};
-#define MINIMAC_MTU 1530
+#define MINIMAC2_MTU 1530
+#define MINIMAC2_BUFFER_SIZE 2048
-struct MilkymistMinimacMdioState {
+struct MilkymistMinimac2MdioState {
int last_clk;
int count;
uint32_t data;
@@ -97,50 +89,55 @@ struct MilkymistMinimacMdioState {
uint8_t phy_addr;
uint8_t reg_addr;
};
-typedef struct MilkymistMinimacMdioState MilkymistMinimacMdioState;
+typedef struct MilkymistMinimac2MdioState MilkymistMinimac2MdioState;
-struct MilkymistMinimacState {
+struct MilkymistMinimac2State {
SysBusDevice busdev;
NICState *nic;
NICConf conf;
char *phy_model;
+ target_phys_addr_t buffers_base;
qemu_irq rx_irq;
qemu_irq tx_irq;
uint32_t regs[R_MAX];
- MilkymistMinimacMdioState mdio;
+ MilkymistMinimac2MdioState mdio;
uint16_t phy_regs[R_PHY_MAX];
+
+ uint8_t *rx0_buf;
+ uint8_t *rx1_buf;
+ uint8_t *tx_buf;
};
-typedef struct MilkymistMinimacState MilkymistMinimacState;
+typedef struct MilkymistMinimac2State MilkymistMinimac2State;
static const uint8_t preamble_sfd[] = {
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5
};
-static void minimac_mdio_write_reg(MilkymistMinimacState *s,
+static void minimac2_mdio_write_reg(MilkymistMinimac2State *s,
uint8_t phy_addr, uint8_t reg_addr, uint16_t value)
{
- trace_milkymist_minimac_mdio_write(phy_addr, reg_addr, value);
+ trace_milkymist_minimac2_mdio_write(phy_addr, reg_addr, value);
/* nop */
}
-static uint16_t minimac_mdio_read_reg(MilkymistMinimacState *s,
+static uint16_t minimac2_mdio_read_reg(MilkymistMinimac2State *s,
uint8_t phy_addr, uint8_t reg_addr)
{
uint16_t r = s->phy_regs[reg_addr];
- trace_milkymist_minimac_mdio_read(phy_addr, reg_addr, r);
+ trace_milkymist_minimac2_mdio_read(phy_addr, reg_addr, r);
return r;
}
-static void minimac_update_mdio(MilkymistMinimacState *s)
+static void minimac2_update_mdio(MilkymistMinimac2State *s)
{
- MilkymistMinimacMdioState *m = &s->mdio;
+ MilkymistMinimac2MdioState *m = &s->mdio;
/* detect rising clk edge */
if (m->last_clk == 0 && (s->regs[R_MDIO] & MDIO_CLK)) {
@@ -173,7 +170,7 @@ static void minimac_update_mdio(MilkymistMinimacState *s)
}
if (m->state == MDIO_STATE_READING) {
- m->data_out = minimac_mdio_read_reg(s, m->phy_addr,
+ m->data_out = minimac2_mdio_read_reg(s, m->phy_addr,
m->reg_addr);
}
}
@@ -192,7 +189,7 @@ static void minimac_update_mdio(MilkymistMinimacState *s)
if (m->count == 0 && m->state) {
if (m->state == MDIO_STATE_WRITING) {
uint16_t data = m->data & 0xffff;
- minimac_mdio_write_reg(s, m->phy_addr, m->reg_addr, data);
+ minimac2_mdio_write_reg(s, m->phy_addr, m->reg_addr, data);
}
m->state = MDIO_STATE_IDLE;
}
@@ -208,7 +205,7 @@ static size_t assemble_frame(uint8_t *buf, size_t size,
uint32_t crc;
if (size < payload_size + 12) {
- error_report("milkymist_minimac: received too big ethernet frame");
+ error_report("milkymist_minimac2: received too big ethernet frame");
return 0;
}
@@ -231,115 +228,102 @@ static size_t assemble_frame(uint8_t *buf, size_t size,
return payload_size + 12;
}
-static void minimac_tx(MilkymistMinimacState *s)
+static void minimac2_tx(MilkymistMinimac2State *s)
{
- uint8_t buf[MINIMAC_MTU];
uint32_t txcount = s->regs[R_TXCOUNT];
-
- /* do nothing if transmission logic is in reset */
- if (s->regs[R_SETUP] & SETUP_TX_RST) {
- return;
- }
+ uint8_t *buf = s->tx_buf;
if (txcount < 64) {
- error_report("milkymist_minimac: ethernet frame too small (%u < %u)\n",
+ error_report("milkymist_minimac2: ethernet frame too small (%u < %u)\n",
txcount, 64);
- return;
+ goto err;
}
- if (txcount > MINIMAC_MTU) {
- error_report("milkymist_minimac: MTU exceeded (%u > %u)\n",
- txcount, MINIMAC_MTU);
- return;
+ if (txcount > MINIMAC2_MTU) {
+ error_report("milkymist_minimac2: MTU exceeded (%u > %u)\n",
+ txcount, MINIMAC2_MTU);
+ goto err;
}
- /* dma */
- cpu_physical_memory_read(s->regs[R_TXADDR], buf, txcount);
-
if (memcmp(buf, preamble_sfd, 8) != 0) {
- error_report("milkymist_minimac: frame doesn't contain the preamble "
+ error_report("milkymist_minimac2: frame doesn't contain the preamble "
"and/or the SFD (%02x %02x %02x %02x %02x %02x %02x %02x)\n",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
- return;
+ goto err;
}
- trace_milkymist_minimac_tx_frame(txcount - 12);
+ trace_milkymist_minimac2_tx_frame(txcount - 12);
/* send packet, skipping preamble and sfd */
qemu_send_packet_raw(&s->nic->nc, buf + 8, txcount - 12);
s->regs[R_TXCOUNT] = 0;
- trace_milkymist_minimac_pulse_irq_tx();
+err:
+ trace_milkymist_minimac2_pulse_irq_tx();
qemu_irq_pulse(s->tx_irq);
}
-static ssize_t minimac_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+static void update_rx_interrupt(MilkymistMinimac2State *s)
+{
+ if (s->regs[R_STATE0] == STATE_PENDING
+ || s->regs[R_STATE1] == STATE_PENDING) {
+ trace_milkymist_minimac2_raise_irq_rx();
+ qemu_irq_raise(s->rx_irq);
+ } else {
+ trace_milkymist_minimac2_lower_irq_rx();
+ qemu_irq_lower(s->rx_irq);
+ }
+}
+
+static ssize_t minimac2_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
{
- MilkymistMinimacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+ MilkymistMinimac2State *s = DO_UPCAST(NICState, nc, nc)->opaque;
- uint32_t r_addr;
uint32_t r_count;
uint32_t r_state;
+ uint8_t *rx_buf;
- uint8_t frame_buf[MINIMAC_MTU];
size_t frame_size;
- trace_milkymist_minimac_rx_frame(buf, size);
-
- /* discard frames if nic is in reset */
- if (s->regs[R_SETUP] & SETUP_RX_RST) {
- return size;
- }
+ trace_milkymist_minimac2_rx_frame(buf, size);
/* choose appropriate slot */
if (s->regs[R_STATE0] == STATE_LOADED) {
- r_addr = R_ADDR0;
r_count = R_COUNT0;
r_state = R_STATE0;
+ rx_buf = s->rx0_buf;
} else if (s->regs[R_STATE1] == STATE_LOADED) {
- r_addr = R_ADDR1;
r_count = R_COUNT1;
r_state = R_STATE1;
- } else if (s->regs[R_STATE2] == STATE_LOADED) {
- r_addr = R_ADDR2;
- r_count = R_COUNT2;
- r_state = R_STATE2;
- } else if (s->regs[R_STATE3] == STATE_LOADED) {
- r_addr = R_ADDR3;
- r_count = R_COUNT3;
- r_state = R_STATE3;
+ rx_buf = s->rx1_buf;
} else {
- trace_milkymist_minimac_drop_rx_frame(buf);
+ trace_milkymist_minimac2_drop_rx_frame(buf);
return size;
}
/* assemble frame */
- frame_size = assemble_frame(frame_buf, sizeof(frame_buf), buf, size);
+ frame_size = assemble_frame(rx_buf, MINIMAC2_BUFFER_SIZE, buf, size);
if (frame_size == 0) {
return size;
}
- trace_milkymist_minimac_rx_transfer(buf, frame_size);
-
- /* do dma */
- cpu_physical_memory_write(s->regs[r_addr], frame_buf, frame_size);
+ trace_milkymist_minimac2_rx_transfer(rx_buf, frame_size);
/* update slot */
s->regs[r_count] = frame_size;
s->regs[r_state] = STATE_PENDING;
- trace_milkymist_minimac_pulse_irq_rx();
- qemu_irq_pulse(s->rx_irq);
+ update_rx_interrupt(s);
return size;
}
static uint32_t
-minimac_read(void *opaque, target_phys_addr_t addr)
+minimac2_read(void *opaque, target_phys_addr_t addr)
{
- MilkymistMinimacState *s = opaque;
+ MilkymistMinimac2State *s = opaque;
uint32_t r = 0;
addr >>= 2;
@@ -347,39 +331,30 @@ minimac_read(void *opaque, target_phys_addr_t addr)
case R_SETUP:
case R_MDIO:
case R_STATE0:
- case R_ADDR0:
case R_COUNT0:
case R_STATE1:
- case R_ADDR1:
case R_COUNT1:
- case R_STATE2:
- case R_ADDR2:
- case R_COUNT2:
- case R_STATE3:
- case R_ADDR3:
- case R_COUNT3:
- case R_TXADDR:
case R_TXCOUNT:
r = s->regs[addr];
break;
default:
- error_report("milkymist_minimac: read access to unknown register 0x"
+ error_report("milkymist_minimac2: read access to unknown register 0x"
TARGET_FMT_plx, addr << 2);
break;
}
- trace_milkymist_minimac_memory_read(addr << 2, r);
+ trace_milkymist_minimac2_memory_read(addr << 2, r);
return r;
}
static void
-minimac_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+minimac2_write(void *opaque, target_phys_addr_t addr, uint32_t value)
{
- MilkymistMinimacState *s = opaque;
+ MilkymistMinimac2State *s = opaque;
- trace_milkymist_minimac_memory_read(addr, value);
+ trace_milkymist_minimac2_memory_read(addr, value);
addr >>= 2;
switch (addr) {
@@ -394,58 +369,47 @@ minimac_write(void *opaque, target_phys_addr_t addr, uint32_t value)
s->regs[R_MDIO] &= ~mdio_di;
}
- minimac_update_mdio(s);
+ minimac2_update_mdio(s);
} break;
case R_TXCOUNT:
s->regs[addr] = value;
if (value > 0) {
- minimac_tx(s);
+ minimac2_tx(s);
}
break;
- case R_SETUP:
case R_STATE0:
- case R_ADDR0:
- case R_COUNT0:
case R_STATE1:
- case R_ADDR1:
+ s->regs[addr] = value;
+ update_rx_interrupt(s);
+ break;
+ case R_SETUP:
+ case R_COUNT0:
case R_COUNT1:
- case R_STATE2:
- case R_ADDR2:
- case R_COUNT2:
- case R_STATE3:
- case R_ADDR3:
- case R_COUNT3:
- case R_TXADDR:
s->regs[addr] = value;
break;
default:
- error_report("milkymist_minimac: write access to unknown register 0x"
+ error_report("milkymist_minimac2: write access to unknown register 0x"
TARGET_FMT_plx, addr << 2);
break;
}
}
-static CPUReadMemoryFunc * const minimac_read_fn[] = {
+static CPUReadMemoryFunc * const minimac2_read_fn[] = {
NULL,
NULL,
- &minimac_read,
+ &minimac2_read,
};
-static CPUWriteMemoryFunc * const minimac_write_fn[] = {
+static CPUWriteMemoryFunc * const minimac2_write_fn[] = {
NULL,
NULL,
- &minimac_write,
+ &minimac2_write,
};
-static int minimac_can_rx(VLANClientState *nc)
+static int minimac2_can_rx(VLANClientState *nc)
{
- MilkymistMinimacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
-
- /* discard frames if nic is in reset */
- if (s->regs[R_SETUP] & SETUP_RX_RST) {
- return 1;
- }
+ MilkymistMinimac2State *s = DO_UPCAST(NICState, nc, nc)->opaque;
if (s->regs[R_STATE0] == STATE_LOADED) {
return 1;
@@ -453,27 +417,21 @@ static int minimac_can_rx(VLANClientState *nc)
if (s->regs[R_STATE1] == STATE_LOADED) {
return 1;
}
- if (s->regs[R_STATE2] == STATE_LOADED) {
- return 1;
- }
- if (s->regs[R_STATE3] == STATE_LOADED) {
- return 1;
- }
return 0;
}
-static void minimac_cleanup(VLANClientState *nc)
+static void minimac2_cleanup(VLANClientState *nc)
{
- MilkymistMinimacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+ MilkymistMinimac2State *s = DO_UPCAST(NICState, nc, nc)->opaque;
s->nic = NULL;
}
-static void milkymist_minimac_reset(DeviceState *d)
+static void milkymist_minimac2_reset(DeviceState *d)
{
- MilkymistMinimacState *s =
- container_of(d, MilkymistMinimacState, busdev.qdev);
+ MilkymistMinimac2State *s =
+ container_of(d, MilkymistMinimac2State, busdev.qdev);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -488,81 +446,94 @@ static void milkymist_minimac_reset(DeviceState *d)
s->phy_regs[R_PHY_ID2] = 0x161a;
}
-static NetClientInfo net_milkymist_minimac_info = {
+static NetClientInfo net_milkymist_minimac2_info = {
.type = NET_CLIENT_TYPE_NIC,
.size = sizeof(NICState),
- .can_receive = minimac_can_rx,
- .receive = minimac_rx,
- .cleanup = minimac_cleanup,
+ .can_receive = minimac2_can_rx,
+ .receive = minimac2_rx,
+ .cleanup = minimac2_cleanup,
};
-static int milkymist_minimac_init(SysBusDevice *dev)
+static int milkymist_minimac2_init(SysBusDevice *dev)
{
- MilkymistMinimacState *s = FROM_SYSBUS(typeof(*s), dev);
+ MilkymistMinimac2State *s = FROM_SYSBUS(typeof(*s), dev);
int regs;
+ ram_addr_t buffers;
+ size_t buffers_size = TARGET_PAGE_ALIGN(3 * MINIMAC2_BUFFER_SIZE);
sysbus_init_irq(dev, &s->rx_irq);
sysbus_init_irq(dev, &s->tx_irq);
- regs = cpu_register_io_memory(minimac_read_fn, minimac_write_fn, s,
+ regs = cpu_register_io_memory(minimac2_read_fn, minimac2_write_fn, s,
DEVICE_NATIVE_ENDIAN);
sysbus_init_mmio(dev, R_MAX * 4, regs);
+ /* register buffers memory */
+ buffers = qemu_ram_alloc(NULL, "milkymist_minimac2.buffers", buffers_size);
+ s->rx0_buf = qemu_get_ram_ptr(buffers);
+ s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE;
+ s->tx_buf = s->rx1_buf + MINIMAC2_BUFFER_SIZE;
+
+ cpu_register_physical_memory(s->buffers_base, buffers_size,
+ buffers | IO_MEM_RAM);
+
qemu_macaddr_default_if_unset(&s->conf.macaddr);
- s->nic = qemu_new_nic(&net_milkymist_minimac_info, &s->conf,
+ s->nic = qemu_new_nic(&net_milkymist_minimac2_info, &s->conf,
dev->qdev.info->name, dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
return 0;
}
-static const VMStateDescription vmstate_milkymist_minimac_mdio = {
- .name = "milkymist_minimac_mdio",
+static const VMStateDescription vmstate_milkymist_minimac2_mdio = {
+ .name = "milkymist-minimac2-mdio",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
- VMSTATE_INT32(last_clk, MilkymistMinimacMdioState),
- VMSTATE_INT32(count, MilkymistMinimacMdioState),
- VMSTATE_UINT32(data, MilkymistMinimacMdioState),
- VMSTATE_UINT16(data_out, MilkymistMinimacMdioState),
- VMSTATE_INT32(state, MilkymistMinimacMdioState),
- VMSTATE_UINT8(phy_addr, MilkymistMinimacMdioState),
- VMSTATE_UINT8(reg_addr, MilkymistMinimacMdioState),
+ VMSTATE_INT32(last_clk, MilkymistMinimac2MdioState),
+ VMSTATE_INT32(count, MilkymistMinimac2MdioState),
+ VMSTATE_UINT32(data, MilkymistMinimac2MdioState),
+ VMSTATE_UINT16(data_out, MilkymistMinimac2MdioState),
+ VMSTATE_INT32(state, MilkymistMinimac2MdioState),
+ VMSTATE_UINT8(phy_addr, MilkymistMinimac2MdioState),
+ VMSTATE_UINT8(reg_addr, MilkymistMinimac2MdioState),
VMSTATE_END_OF_LIST()
}
};
-static const VMStateDescription vmstate_milkymist_minimac = {
- .name = "milkymist-minimac",
+static const VMStateDescription vmstate_milkymist_minimac2 = {
+ .name = "milkymist-minimac2",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
- VMSTATE_UINT32_ARRAY(regs, MilkymistMinimacState, R_MAX),
- VMSTATE_UINT16_ARRAY(phy_regs, MilkymistMinimacState, R_PHY_MAX),
- VMSTATE_STRUCT(mdio, MilkymistMinimacState, 0,
- vmstate_milkymist_minimac_mdio, MilkymistMinimacMdioState),
+ VMSTATE_UINT32_ARRAY(regs, MilkymistMinimac2State, R_MAX),
+ VMSTATE_UINT16_ARRAY(phy_regs, MilkymistMinimac2State, R_PHY_MAX),
+ VMSTATE_STRUCT(mdio, MilkymistMinimac2State, 0,
+ vmstate_milkymist_minimac2_mdio, MilkymistMinimac2MdioState),
VMSTATE_END_OF_LIST()
}
};
-static SysBusDeviceInfo milkymist_minimac_info = {
- .init = milkymist_minimac_init,
- .qdev.name = "milkymist-minimac",
- .qdev.size = sizeof(MilkymistMinimacState),
- .qdev.vmsd = &vmstate_milkymist_minimac,
- .qdev.reset = milkymist_minimac_reset,
+static SysBusDeviceInfo milkymist_minimac2_info = {
+ .init = milkymist_minimac2_init,
+ .qdev.name = "milkymist-minimac2",
+ .qdev.size = sizeof(MilkymistMinimac2State),
+ .qdev.vmsd = &vmstate_milkymist_minimac2,
+ .qdev.reset = milkymist_minimac2_reset,
.qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(MilkymistMinimacState, conf),
- DEFINE_PROP_STRING("phy_model", MilkymistMinimacState, phy_model),
+ DEFINE_PROP_TADDR("buffers_base", MilkymistMinimac2State,
+ buffers_base, 0),
+ DEFINE_NIC_PROPERTIES(MilkymistMinimac2State, conf),
+ DEFINE_PROP_STRING("phy_model", MilkymistMinimac2State, phy_model),
DEFINE_PROP_END_OF_LIST(),
}
};
-static void milkymist_minimac_register(void)
+static void milkymist_minimac2_register(void)
{
- sysbus_register_withprop(&milkymist_minimac_info);
+ sysbus_register_withprop(&milkymist_minimac2_info);
}
-device_init(milkymist_minimac_register)
+device_init(milkymist_minimac2_register)
diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c
index eaea543bf..6bd0cb974 100644
--- a/hw/milkymist-sysctl.c
+++ b/hw/milkymist-sysctl.c
@@ -140,24 +140,8 @@ static void sysctl_write(void *opaque, target_phys_addr_t addr, uint32_t value)
case R_GPIO_OUT:
case R_GPIO_INTEN:
case R_TIMER0_COUNTER:
- if (value > s->regs[R_TIMER0_COUNTER]) {
- value = s->regs[R_TIMER0_COUNTER];
- error_report("milkymist_sysctl: timer0: trying to write a "
- "value greater than the limit. Clipping.");
- }
- /* milkymist timer counts up */
- value = s->regs[R_TIMER0_COUNTER] - value;
- ptimer_set_count(s->ptimer0, value);
- break;
case R_TIMER1_COUNTER:
- if (value > s->regs[R_TIMER1_COUNTER]) {
- value = s->regs[R_TIMER1_COUNTER];
- error_report("milkymist_sysctl: timer1: trying to write a "
- "value greater than the limit. Clipping.");
- }
- /* milkymist timer counts up */
- value = s->regs[R_TIMER1_COUNTER] - value;
- ptimer_set_count(s->ptimer1, value);
+ s->regs[addr] = value;
break;
case R_TIMER0_COMPARE:
ptimer_set_limit(s->ptimer0, value, 0);
@@ -170,10 +154,12 @@ static void sysctl_write(void *opaque, target_phys_addr_t addr, uint32_t value)
case R_TIMER0_CONTROL:
s->regs[addr] = value;
if (s->regs[R_TIMER0_CONTROL] & CTRL_ENABLE) {
- trace_milkymist_sysctl_start_timer1();
+ trace_milkymist_sysctl_start_timer0();
+ ptimer_set_count(s->ptimer0,
+ s->regs[R_TIMER0_COMPARE] - s->regs[R_TIMER0_COUNTER]);
ptimer_run(s->ptimer0, 0);
} else {
- trace_milkymist_sysctl_stop_timer1();
+ trace_milkymist_sysctl_stop_timer0();
ptimer_stop(s->ptimer0);
}
break;
@@ -181,6 +167,8 @@ static void sysctl_write(void *opaque, target_phys_addr_t addr, uint32_t value)
s->regs[addr] = value;
if (s->regs[R_TIMER1_CONTROL] & CTRL_ENABLE) {
trace_milkymist_sysctl_start_timer1();
+ ptimer_set_count(s->ptimer1,
+ s->regs[R_TIMER1_COMPARE] - s->regs[R_TIMER1_COUNTER]);
ptimer_run(s->ptimer1, 0);
} else {
trace_milkymist_sysctl_stop_timer1();
diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 892273151..2e55e42e3 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/milkymist-vgafb.c
@@ -199,6 +199,9 @@ vgafb_write(void *opaque, target_phys_addr_t addr, uint32_t value)
addr >>= 2;
switch (addr) {
case R_CTRL:
+ s->regs[addr] = value;
+ vgafb_resize(s);
+ break;
case R_HSYNC_START:
case R_HSYNC_END:
case R_HSCAN:
diff --git a/hw/milkymist.c b/hw/milkymist.c
index 8defad802..787984040 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -156,7 +156,7 @@ milkymist_init(ram_addr_t ram_size_not_used,
milkymist_ac97_create(0x60005000, irq[5], irq[6], irq[7], irq[8]);
milkymist_pfpu_create(0x60006000, irq[9]);
milkymist_tmu2_create(0x60007000, irq[10]);
- milkymist_minimac_create(0x60008000, irq[11], irq[12]);
+ milkymist_minimac2_create(0x60008000, 0x30000000, irq[11], irq[12]);
milkymist_softusb_create(0x6000f000, irq[17],
0x20000000, 0x1000, 0x20020000, 0x2000);
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index c5e54ffc3..26aad51ea 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -202,44 +202,29 @@ static void mipsnet_ioport_write(void *opaque, uint32_t addr, uint32_t val)
}
}
-static void mipsnet_save(QEMUFile *f, void *opaque)
-{
- MIPSnetState *s = opaque;
-
- qemu_put_be32s(f, &s->busy);
- qemu_put_be32s(f, &s->rx_count);
- qemu_put_be32s(f, &s->rx_read);
- qemu_put_be32s(f, &s->tx_count);
- qemu_put_be32s(f, &s->tx_written);
- qemu_put_be32s(f, &s->intctl);
- qemu_put_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
- qemu_put_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
-}
-
-static int mipsnet_load(QEMUFile *f, void *opaque, int version_id)
-{
- MIPSnetState *s = opaque;
-
- if (version_id > 0)
- return -EINVAL;
-
- qemu_get_be32s(f, &s->busy);
- qemu_get_be32s(f, &s->rx_count);
- qemu_get_be32s(f, &s->rx_read);
- qemu_get_be32s(f, &s->tx_count);
- qemu_get_be32s(f, &s->tx_written);
- qemu_get_be32s(f, &s->intctl);
- qemu_get_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
- qemu_get_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
-
- return 0;
-}
+static const VMStateDescription vmstate_mipsnet = {
+ .name = "mipsnet",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(busy, MIPSnetState),
+ VMSTATE_UINT32(rx_count, MIPSnetState),
+ VMSTATE_UINT32(rx_read, MIPSnetState),
+ VMSTATE_UINT32(tx_count, MIPSnetState),
+ VMSTATE_UINT32(tx_written, MIPSnetState),
+ VMSTATE_UINT32(intctl, MIPSnetState),
+ VMSTATE_BUFFER(rx_buffer, MIPSnetState),
+ VMSTATE_BUFFER(tx_buffer, MIPSnetState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static void mipsnet_cleanup(VLANClientState *nc)
{
MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
- unregister_savevm(NULL, "mipsnet", s);
+ vmstate_unregister(NULL, &vmstate_mipsnet, s);
isa_unassign_ioport(s->io_base, 36);
@@ -284,5 +269,5 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
}
mipsnet_reset(s);
- register_savevm(NULL, "mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
+ vmstate_register(NULL, 0, &vmstate_mipsnet, s);
}
diff --git a/hw/nand.c b/hw/nand.c
index f414aa139..37e51d714 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -52,7 +52,7 @@ struct NANDFlashState {
BlockDriverState *bdrv;
int mem_oob;
- int cle, ale, ce, wp, gnd;
+ uint8_t cle, ale, ce, wp, gnd;
uint8_t io[MAX_PAGE + MAX_OOB + 0x400];
uint8_t *ioaddr;
@@ -66,6 +66,8 @@ struct NANDFlashState {
void (*blk_write)(NANDFlashState *s);
void (*blk_erase)(NANDFlashState *s);
void (*blk_load)(NANDFlashState *s, uint32_t addr, int offset);
+
+ uint32_t ioaddr_vmstate;
};
# define NAND_NO_AUTOINCR 0x00000001
@@ -281,56 +283,59 @@ static void nand_command(NANDFlashState *s)
}
}
-static void nand_save(QEMUFile *f, void *opaque)
+static void nand_pre_save(void *opaque)
{
- NANDFlashState *s = (NANDFlashState *) opaque;
- qemu_put_byte(f, s->cle);
- qemu_put_byte(f, s->ale);
- qemu_put_byte(f, s->ce);
- qemu_put_byte(f, s->wp);
- qemu_put_byte(f, s->gnd);
- qemu_put_buffer(f, s->io, sizeof(s->io));
- qemu_put_be32(f, s->ioaddr - s->io);
- qemu_put_be32(f, s->iolen);
-
- qemu_put_be32s(f, &s->cmd);
- qemu_put_be32s(f, &s->addr);
- qemu_put_be32(f, s->addrlen);
- qemu_put_be32(f, s->status);
- qemu_put_be32(f, s->offset);
- /* XXX: do we want to save s->storage too? */
+ NANDFlashState *s = opaque;
+
+ s->ioaddr_vmstate = s->ioaddr - s->io;
}
-static int nand_load(QEMUFile *f, void *opaque, int version_id)
+static int nand_post_load(void *opaque, int version_id)
{
- NANDFlashState *s = (NANDFlashState *) opaque;
- s->cle = qemu_get_byte(f);
- s->ale = qemu_get_byte(f);
- s->ce = qemu_get_byte(f);
- s->wp = qemu_get_byte(f);
- s->gnd = qemu_get_byte(f);
- qemu_get_buffer(f, s->io, sizeof(s->io));
- s->ioaddr = s->io + qemu_get_be32(f);
- s->iolen = qemu_get_be32(f);
- if (s->ioaddr >= s->io + sizeof(s->io) || s->ioaddr < s->io)
+ NANDFlashState *s = opaque;
+
+ if (s->ioaddr_vmstate > sizeof(s->io)) {
return -EINVAL;
+ }
+ s->ioaddr = s->io + s->ioaddr_vmstate;
- qemu_get_be32s(f, &s->cmd);
- qemu_get_be32s(f, &s->addr);
- s->addrlen = qemu_get_be32(f);
- s->status = qemu_get_be32(f);
- s->offset = qemu_get_be32(f);
return 0;
}
+static const VMStateDescription vmstate_nand = {
+ .name = "nand",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .pre_save = nand_pre_save,
+ .post_load = nand_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(cle, NANDFlashState),
+ VMSTATE_UINT8(ale, NANDFlashState),
+ VMSTATE_UINT8(ce, NANDFlashState),
+ VMSTATE_UINT8(wp, NANDFlashState),
+ VMSTATE_UINT8(gnd, NANDFlashState),
+ VMSTATE_BUFFER(io, NANDFlashState),
+ VMSTATE_UINT32(ioaddr_vmstate, NANDFlashState),
+ VMSTATE_INT32(iolen, NANDFlashState),
+ VMSTATE_UINT32(cmd, NANDFlashState),
+ VMSTATE_UINT32(addr, NANDFlashState),
+ VMSTATE_INT32(addrlen, NANDFlashState),
+ VMSTATE_INT32(status, NANDFlashState),
+ VMSTATE_INT32(offset, NANDFlashState),
+ /* XXX: do we want to save s->storage too? */
+ VMSTATE_END_OF_LIST()
+ }
+};
+
/*
* Chip inputs are CLE, ALE, CE, WP, GND and eight I/O pins. Chip
* outputs are R/B and eight I/O pins.
*
* CE, WP and R/B are active low.
*/
-void nand_setpins(NANDFlashState *s,
- int cle, int ale, int ce, int wp, int gnd)
+void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
+ uint8_t ce, uint8_t wp, uint8_t gnd)
{
s->cle = cle;
s->ale = ale;
@@ -502,7 +507,7 @@ NANDFlashState *nand_init(int manf_id, int chip_id)
is used. */
s->ioaddr = s->io;
- register_savevm(NULL, "nand", -1, 0, nand_save, nand_load, s);
+ vmstate_register(NULL, -1, &vmstate_nand, s);
return s;
}
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 596635985..b668ad107 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -742,7 +742,7 @@ static int pci_ne2000_init(PCIDevice *pci_dev)
if (!pci_dev->qdev.hotplugged) {
static int loaded = 0;
if (!loaded) {
- rom_add_option("pxe-ne2k_pci.bin", -1);
+ rom_add_option("pxe-ne2k_pci.rom", -1);
loaded = 1;
}
}
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index 06bccbdc4..a7b687bc4 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -26,7 +26,6 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "hw.h"
-#include "sysemu.h"
#include "console.h"
#include "omap.h"
#include "boards.h"
diff --git a/hw/pcie.c b/hw/pcie.c
index 6a113a932..9de614904 100644
--- a/hw/pcie.c
+++ b/hw/pcie.c
@@ -18,8 +18,7 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "sysemu.h"
-#include "range.h"
+#include "qemu-common.h"
#include "pci_bridge.h"
#include "pcie.h"
#include "msix.h"
diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index 339a40196..40ee29d38 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -310,7 +310,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
if (!pci_dev->qdev.hotplugged) {
static int loaded = 0;
if (!loaded) {
- rom_add_option("pxe-pcnet.bin", -1);
+ rom_add_option("pxe-pcnet.rom", -1);
loaded = 1;
}
}
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index 370c5eef7..14bbc34e1 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -50,6 +50,8 @@ do { \
#define DPRINTF(fmt, ...) do { } while (0)
#endif
+#define PFLASH_LAZY_ROMD_THRESHOLD 42
+
struct pflash_t {
BlockDriverState *bs;
target_phys_addr_t base;
@@ -70,6 +72,7 @@ struct pflash_t {
ram_addr_t off;
int fl_mem;
int rom_mode;
+ int read_counter; /* used for lazy switch-back to rom mode */
void *storage;
};
@@ -112,10 +115,10 @@ static uint32_t pflash_read (pflash_t *pfl, target_phys_addr_t offset,
DPRINTF("%s: offset " TARGET_FMT_plx "\n", __func__, offset);
ret = -1;
- if (!pfl->rom_mode) {
- /* Lazy reset of to ROMD mode */
- if (pfl->wcycle == 0)
- pflash_register_memory(pfl, 1);
+ /* Lazy reset to ROMD mode after a certain amount of read accesses */
+ if (!pfl->rom_mode && pfl->wcycle == 0 &&
+ ++pfl->read_counter > PFLASH_LAZY_ROMD_THRESHOLD) {
+ pflash_register_memory(pfl, 1);
}
offset &= pfl->chip_len - 1;
boff = offset & 0xFF;
@@ -254,6 +257,7 @@ static void pflash_write (pflash_t *pfl, target_phys_addr_t offset,
/* Set the device in I/O access mode if required */
if (pfl->rom_mode)
pflash_register_memory(pfl, 0);
+ pfl->read_counter = 0;
/* We're in read mode */
check_unlock0:
if (boff == 0x55 && cmd == 0x98) {
diff --git a/hw/piix4.c b/hw/piix4.c
index 72073cd0a..71f1f84dc 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -30,10 +30,14 @@
PCIDevice *piix4_dev;
+typedef struct PIIX4State {
+ PCIDevice dev;
+} PIIX4State;
+
static void piix4_reset(void *opaque)
{
- PCIDevice *d = opaque;
- uint8_t *pci_conf = d->config;
+ PIIX4State *d = opaque;
+ uint8_t *pci_conf = d->dev.config;
pci_conf[0x04] = 0x07; // master, memory and I/O
pci_conf[0x05] = 0x00;
@@ -68,33 +72,30 @@ static void piix4_reset(void *opaque)
pci_conf[0xae] = 0x00;
}
-static void piix_save(QEMUFile* f, void *opaque)
-{
- PCIDevice *d = opaque;
- pci_device_save(d, f);
-}
-
-static int piix_load(QEMUFile* f, void *opaque, int version_id)
-{
- PCIDevice *d = opaque;
- if (version_id != 2)
- return -EINVAL;
- return pci_device_load(d, f);
-}
+static const VMStateDescription vmstate_piix4 = {
+ .name = "PIIX4",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE(dev, PIIX4State),
+ VMSTATE_END_OF_LIST()
+ }
+};
-static int piix4_initfn(PCIDevice *d)
+static int piix4_initfn(PCIDevice *dev)
{
+ PIIX4State *d = DO_UPCAST(PIIX4State, dev, dev);
uint8_t *pci_conf;
- isa_bus_new(&d->qdev);
- register_savevm(&d->qdev, "PIIX4", 0, 2, piix_save, piix_load, d);
+ isa_bus_new(&d->dev.qdev);
- pci_conf = d->config;
+ pci_conf = d->dev.config;
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_0); // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
- piix4_dev = d;
+ piix4_dev = &d->dev;
qemu_register_reset(piix4_reset, d);
return 0;
}
@@ -111,7 +112,8 @@ static PCIDeviceInfo piix4_info[] = {
{
.qdev.name = "PIIX4",
.qdev.desc = "ISA bridge",
- .qdev.size = sizeof(PCIDevice),
+ .qdev.size = sizeof(PIIX4State),
+ .qdev.vmsd = &vmstate_piix4,
.qdev.no_user = 1,
.no_hotplug = 1,
.init = piix4_initfn,
diff --git a/hw/pl011.c b/hw/pl011.c
index 77f0dbf13..3b94b14cb 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -235,56 +235,30 @@ static CPUWriteMemoryFunc * const pl011_writefn[] = {
pl011_write
};
-static void pl011_save(QEMUFile *f, void *opaque)
-{
- pl011_state *s = (pl011_state *)opaque;
- int i;
-
- qemu_put_be32(f, s->readbuff);
- qemu_put_be32(f, s->flags);
- qemu_put_be32(f, s->lcr);
- qemu_put_be32(f, s->cr);
- qemu_put_be32(f, s->dmacr);
- qemu_put_be32(f, s->int_enabled);
- qemu_put_be32(f, s->int_level);
- for (i = 0; i < 16; i++)
- qemu_put_be32(f, s->read_fifo[i]);
- qemu_put_be32(f, s->ilpr);
- qemu_put_be32(f, s->ibrd);
- qemu_put_be32(f, s->fbrd);
- qemu_put_be32(f, s->ifl);
- qemu_put_be32(f, s->read_pos);
- qemu_put_be32(f, s->read_count);
- qemu_put_be32(f, s->read_trigger);
-}
-
-static int pl011_load(QEMUFile *f, void *opaque, int version_id)
-{
- pl011_state *s = (pl011_state *)opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->readbuff = qemu_get_be32(f);
- s->flags = qemu_get_be32(f);
- s->lcr = qemu_get_be32(f);
- s->cr = qemu_get_be32(f);
- s->dmacr = qemu_get_be32(f);
- s->int_enabled = qemu_get_be32(f);
- s->int_level = qemu_get_be32(f);
- for (i = 0; i < 16; i++)
- s->read_fifo[i] = qemu_get_be32(f);
- s->ilpr = qemu_get_be32(f);
- s->ibrd = qemu_get_be32(f);
- s->fbrd = qemu_get_be32(f);
- s->ifl = qemu_get_be32(f);
- s->read_pos = qemu_get_be32(f);
- s->read_count = qemu_get_be32(f);
- s->read_trigger = qemu_get_be32(f);
-
- return 0;
-}
+static const VMStateDescription vmstate_pl011 = {
+ .name = "pl011",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(readbuff, pl011_state),
+ VMSTATE_UINT32(flags, pl011_state),
+ VMSTATE_UINT32(lcr, pl011_state),
+ VMSTATE_UINT32(cr, pl011_state),
+ VMSTATE_UINT32(dmacr, pl011_state),
+ VMSTATE_UINT32(int_enabled, pl011_state),
+ VMSTATE_UINT32(int_level, pl011_state),
+ VMSTATE_UINT32_ARRAY(read_fifo, pl011_state, 16),
+ VMSTATE_UINT32(ilpr, pl011_state),
+ VMSTATE_UINT32(ibrd, pl011_state),
+ VMSTATE_UINT32(fbrd, pl011_state),
+ VMSTATE_UINT32(ifl, pl011_state),
+ VMSTATE_INT32(read_pos, pl011_state),
+ VMSTATE_INT32(read_count, pl011_state),
+ VMSTATE_INT32(read_trigger, pl011_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int pl011_init(SysBusDevice *dev, const unsigned char *id)
{
@@ -307,7 +281,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
pl011_event, s);
}
- register_savevm(&dev->qdev, "pl011_uart", -1, 1, pl011_save, pl011_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_pl011, s);
return 0;
}
diff --git a/hw/pl022.c b/hw/pl022.c
index ffe05ab74..00e494a0d 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -239,54 +239,42 @@ static CPUWriteMemoryFunc * const pl022_writefn[] = {
pl022_write
};
-static void pl022_save(QEMUFile *f, void *opaque)
-{
- pl022_state *s = (pl022_state *)opaque;
- int i;
-
- qemu_put_be32(f, s->cr0);
- qemu_put_be32(f, s->cr1);
- qemu_put_be32(f, s->bitmask);
- qemu_put_be32(f, s->sr);
- qemu_put_be32(f, s->cpsr);
- qemu_put_be32(f, s->is);
- qemu_put_be32(f, s->im);
- qemu_put_be32(f, s->tx_fifo_head);
- qemu_put_be32(f, s->rx_fifo_head);
- qemu_put_be32(f, s->tx_fifo_len);
- qemu_put_be32(f, s->rx_fifo_len);
- for (i = 0; i < 8; i++) {
- qemu_put_be16(f, s->tx_fifo[i]);
- qemu_put_be16(f, s->rx_fifo[i]);
- }
-}
-
-static int pl022_load(QEMUFile *f, void *opaque, int version_id)
-{
- pl022_state *s = (pl022_state *)opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->cr0 = qemu_get_be32(f);
- s->cr1 = qemu_get_be32(f);
- s->bitmask = qemu_get_be32(f);
- s->sr = qemu_get_be32(f);
- s->cpsr = qemu_get_be32(f);
- s->is = qemu_get_be32(f);
- s->im = qemu_get_be32(f);
- s->tx_fifo_head = qemu_get_be32(f);
- s->rx_fifo_head = qemu_get_be32(f);
- s->tx_fifo_len = qemu_get_be32(f);
- s->rx_fifo_len = qemu_get_be32(f);
- for (i = 0; i < 8; i++) {
- s->tx_fifo[i] = qemu_get_be16(f);
- s->rx_fifo[i] = qemu_get_be16(f);
+static const VMStateDescription vmstate_pl022 = {
+ .name = "pl022_ssp",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(cr0, pl022_state),
+ VMSTATE_UINT32(cr1, pl022_state),
+ VMSTATE_UINT32(bitmask, pl022_state),
+ VMSTATE_UINT32(sr, pl022_state),
+ VMSTATE_UINT32(cpsr, pl022_state),
+ VMSTATE_UINT32(is, pl022_state),
+ VMSTATE_UINT32(im, pl022_state),
+ VMSTATE_INT32(tx_fifo_head, pl022_state),
+ VMSTATE_INT32(rx_fifo_head, pl022_state),
+ VMSTATE_INT32(tx_fifo_len, pl022_state),
+ VMSTATE_INT32(rx_fifo_len, pl022_state),
+ VMSTATE_UINT16(tx_fifo[0], pl022_state),
+ VMSTATE_UINT16(rx_fifo[0], pl022_state),
+ VMSTATE_UINT16(tx_fifo[1], pl022_state),
+ VMSTATE_UINT16(rx_fifo[1], pl022_state),
+ VMSTATE_UINT16(tx_fifo[2], pl022_state),
+ VMSTATE_UINT16(rx_fifo[2], pl022_state),
+ VMSTATE_UINT16(tx_fifo[3], pl022_state),
+ VMSTATE_UINT16(rx_fifo[3], pl022_state),
+ VMSTATE_UINT16(tx_fifo[4], pl022_state),
+ VMSTATE_UINT16(rx_fifo[4], pl022_state),
+ VMSTATE_UINT16(tx_fifo[5], pl022_state),
+ VMSTATE_UINT16(rx_fifo[5], pl022_state),
+ VMSTATE_UINT16(tx_fifo[6], pl022_state),
+ VMSTATE_UINT16(rx_fifo[6], pl022_state),
+ VMSTATE_UINT16(tx_fifo[7], pl022_state),
+ VMSTATE_UINT16(rx_fifo[7], pl022_state),
+ VMSTATE_END_OF_LIST()
}
-
- return 0;
-}
+};
static int pl022_init(SysBusDevice *dev)
{
@@ -300,7 +288,7 @@ static int pl022_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq);
s->ssi = ssi_create_bus(&dev->qdev, "ssi");
pl022_reset(s);
- register_savevm(&dev->qdev, "pl022_ssp", -1, 1, pl022_save, pl022_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_pl022, s);
return 0;
}
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index db1f84abe..6627cd8aa 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -17,7 +17,6 @@
#include "hw.h"
#include "pci.h"
#include "boards.h"
-#include "sysemu.h"
#include "ppc440.h"
#include "kvm.h"
#include "kvm_ppc.h"
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 5f581fe2c..7f9ed1713 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -24,7 +24,6 @@
#include "hw.h"
#include "ppc.h"
#include "ppc4xx.h"
-#include "sysemu.h"
#include "qemu-log.h"
//#define DEBUG_MMIO
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index f62f1f91d..299473c4b 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -285,50 +285,48 @@ static void ppc4xx_pci_set_irq(void *opaque, int irq_num, int level)
qemu_set_irq(pci_irqs[irq_num], level);
}
-static void ppc4xx_pci_save(QEMUFile *f, void *opaque)
-{
- PPC4xxPCIState *controller = opaque;
- int i;
-
- pci_device_save(controller->pci_dev, f);
-
- for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) {
- qemu_put_be32s(f, &controller->pmm[i].la);
- qemu_put_be32s(f, &controller->pmm[i].ma);
- qemu_put_be32s(f, &controller->pmm[i].pcila);
- qemu_put_be32s(f, &controller->pmm[i].pciha);
- }
-
- for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) {
- qemu_put_be32s(f, &controller->ptm[i].ms);
- qemu_put_be32s(f, &controller->ptm[i].la);
+static const VMStateDescription vmstate_pci_master_map = {
+ .name = "pci_master_map",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(la, struct PCIMasterMap),
+ VMSTATE_UINT32(ma, struct PCIMasterMap),
+ VMSTATE_UINT32(pcila, struct PCIMasterMap),
+ VMSTATE_UINT32(pciha, struct PCIMasterMap),
+ VMSTATE_END_OF_LIST()
}
-}
-
-static int ppc4xx_pci_load(QEMUFile *f, void *opaque, int version_id)
-{
- PPC4xxPCIState *controller = opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- pci_device_load(controller->pci_dev, f);
+};
- for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) {
- qemu_get_be32s(f, &controller->pmm[i].la);
- qemu_get_be32s(f, &controller->pmm[i].ma);
- qemu_get_be32s(f, &controller->pmm[i].pcila);
- qemu_get_be32s(f, &controller->pmm[i].pciha);
+static const VMStateDescription vmstate_pci_target_map = {
+ .name = "pci_target_map",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(ms, struct PCITargetMap),
+ VMSTATE_UINT32(la, struct PCITargetMap),
+ VMSTATE_END_OF_LIST()
}
+};
- for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) {
- qemu_get_be32s(f, &controller->ptm[i].ms);
- qemu_get_be32s(f, &controller->ptm[i].la);
+static const VMStateDescription vmstate_ppc4xx_pci = {
+ .name = "ppc4xx_pci",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPC4xxPCIState),
+ VMSTATE_STRUCT_ARRAY(pmm, PPC4xxPCIState, PPC4xx_PCI_NR_PMMS, 1,
+ vmstate_pci_master_map,
+ struct PCIMasterMap),
+ VMSTATE_STRUCT_ARRAY(ptm, PPC4xxPCIState, PPC4xx_PCI_NR_PTMS, 1,
+ vmstate_pci_target_map,
+ struct PCITargetMap),
+ VMSTATE_END_OF_LIST()
}
-
- return 0;
-}
+};
/* XXX Interrupt acknowledge cycles not supported. */
PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
@@ -381,8 +379,8 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
qemu_register_reset(ppc4xx_pci_reset, controller);
/* XXX load/save code not tested. */
- register_savevm(&controller->pci_dev->qdev, "ppc4xx_pci", ppc4xx_pci_id++,
- 1, ppc4xx_pci_save, ppc4xx_pci_load, controller);
+ vmstate_register(&controller->pci_dev->qdev, ppc4xx_pci_id++,
+ &vmstate_ppc4xx_pci, controller);
return controller->pci_state.bus;
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 2fc879236..83a20e462 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -216,56 +216,49 @@ static void mpc85xx_pci_set_irq(void *opaque, int irq_num, int level)
qemu_set_irq(pic[irq_num], level);
}
-static void ppce500_pci_save(QEMUFile *f, void *opaque)
-{
- PPCE500PCIState *controller = opaque;
- int i;
-
- pci_device_save(controller->pci_dev, f);
-
- for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
- qemu_put_be32s(f, &controller->pob[i].potar);
- qemu_put_be32s(f, &controller->pob[i].potear);
- qemu_put_be32s(f, &controller->pob[i].powbar);
- qemu_put_be32s(f, &controller->pob[i].powar);
- }
-
- for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
- qemu_put_be32s(f, &controller->pib[i].pitar);
- qemu_put_be32s(f, &controller->pib[i].piwbar);
- qemu_put_be32s(f, &controller->pib[i].piwbear);
- qemu_put_be32s(f, &controller->pib[i].piwar);
+static const VMStateDescription vmstate_pci_outbound = {
+ .name = "pci_outbound",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(potar, struct pci_outbound),
+ VMSTATE_UINT32(potear, struct pci_outbound),
+ VMSTATE_UINT32(powbar, struct pci_outbound),
+ VMSTATE_UINT32(powar, struct pci_outbound),
+ VMSTATE_END_OF_LIST()
}
- qemu_put_be32s(f, &controller->gasket_time);
-}
-
-static int ppce500_pci_load(QEMUFile *f, void *opaque, int version_id)
-{
- PPCE500PCIState *controller = opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- pci_device_load(controller->pci_dev, f);
+};
- for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
- qemu_get_be32s(f, &controller->pob[i].potar);
- qemu_get_be32s(f, &controller->pob[i].potear);
- qemu_get_be32s(f, &controller->pob[i].powbar);
- qemu_get_be32s(f, &controller->pob[i].powar);
+static const VMStateDescription vmstate_pci_inbound = {
+ .name = "pci_inbound",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(pitar, struct pci_inbound),
+ VMSTATE_UINT32(piwbar, struct pci_inbound),
+ VMSTATE_UINT32(piwbear, struct pci_inbound),
+ VMSTATE_UINT32(piwar, struct pci_inbound),
+ VMSTATE_END_OF_LIST()
}
+};
- for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
- qemu_get_be32s(f, &controller->pib[i].pitar);
- qemu_get_be32s(f, &controller->pib[i].piwbar);
- qemu_get_be32s(f, &controller->pib[i].piwbear);
- qemu_get_be32s(f, &controller->pib[i].piwar);
+static const VMStateDescription vmstate_ppce500_pci = {
+ .name = "ppce500_pci",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPCE500PCIState),
+ VMSTATE_STRUCT_ARRAY(pob, PPCE500PCIState, PPCE500_PCI_NR_POBS, 1,
+ vmstate_pci_outbound, struct pci_outbound),
+ VMSTATE_STRUCT_ARRAY(pib, PPCE500PCIState, PPCE500_PCI_NR_PIBS, 1,
+ vmstate_pci_outbound, struct pci_inbound),
+ VMSTATE_UINT32(gasket_time, PPCE500PCIState),
+ VMSTATE_END_OF_LIST()
}
- qemu_get_be32s(f, &controller->gasket_time);
-
- return 0;
-}
+};
PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
{
@@ -314,8 +307,8 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
PCIE500_REG_SIZE, index);
/* XXX load/save code not tested. */
- register_savevm(&d->qdev, "ppce500_pci", ppce500_pci_id++,
- 1, ppce500_pci_save, ppce500_pci_load, controller);
+ vmstate_register(&d->qdev, ppce500_pci_id++, &vmstate_ppce500_pci,
+ controller);
return controller->pci_state.bus;
diff --git a/hw/ptimer.c b/hw/ptimer.c
index e68c1d141..47964a67e 100644
--- a/hw/ptimer.c
+++ b/hw/ptimer.c
@@ -11,7 +11,7 @@
struct ptimer_state
{
- int enabled; /* 0 = disabled, 1 = periodic, 2 = oneshot. */
+ uint8_t enabled; /* 0 = disabled, 1 = periodic, 2 = oneshot. */
uint64_t limit;
uint64_t delta;
uint32_t period_frac;
@@ -188,49 +188,22 @@ void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
}
}
-void qemu_put_ptimer(QEMUFile *f, ptimer_state *s)
-{
- qemu_put_byte(f, s->enabled);
- qemu_put_be64s(f, &s->limit);
- qemu_put_be64s(f, &s->delta);
- qemu_put_be32s(f, &s->period_frac);
- qemu_put_sbe64s(f, &s->period);
- qemu_put_sbe64s(f, &s->last_event);
- qemu_put_sbe64s(f, &s->next_event);
- qemu_put_timer(f, s->timer);
-}
-
-void qemu_get_ptimer(QEMUFile *f, ptimer_state *s)
-{
- s->enabled = qemu_get_byte(f);
- qemu_get_be64s(f, &s->limit);
- qemu_get_be64s(f, &s->delta);
- qemu_get_be32s(f, &s->period_frac);
- qemu_get_sbe64s(f, &s->period);
- qemu_get_sbe64s(f, &s->last_event);
- qemu_get_sbe64s(f, &s->next_event);
- qemu_get_timer(f, s->timer);
-}
-
-static int get_ptimer(QEMUFile *f, void *pv, size_t size)
-{
- ptimer_state *v = pv;
-
- qemu_get_ptimer(f, v);
- return 0;
-}
-
-static void put_ptimer(QEMUFile *f, void *pv, size_t size)
-{
- ptimer_state *v = pv;
-
- qemu_put_ptimer(f, v);
-}
-
-const VMStateInfo vmstate_info_ptimer = {
+const VMStateDescription vmstate_ptimer = {
.name = "ptimer",
- .get = get_ptimer,
- .put = put_ptimer,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(enabled, ptimer_state),
+ VMSTATE_UINT64(limit, ptimer_state),
+ VMSTATE_UINT64(delta, ptimer_state),
+ VMSTATE_UINT32(period_frac, ptimer_state),
+ VMSTATE_INT64(period, ptimer_state),
+ VMSTATE_INT64(last_event, ptimer_state),
+ VMSTATE_INT64(next_event, ptimer_state),
+ VMSTATE_TIMER(timer, ptimer_state),
+ VMSTATE_END_OF_LIST()
+ }
};
ptimer_state *ptimer_init(QEMUBH *bh)
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 9b95e2c8e..ac5d95d71 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -146,25 +146,16 @@ static CPUWriteMemoryFunc * const pxa2xx_pm_writefn[] = {
pxa2xx_pm_write,
};
-static void pxa2xx_pm_save(QEMUFile *f, void *opaque)
-{
- PXA2xxState *s = (PXA2xxState *) opaque;
- int i;
-
- for (i = 0; i < 0x40; i ++)
- qemu_put_be32s(f, &s->pm_regs[i]);
-}
-
-static int pxa2xx_pm_load(QEMUFile *f, void *opaque, int version_id)
-{
- PXA2xxState *s = (PXA2xxState *) opaque;
- int i;
-
- for (i = 0; i < 0x40; i ++)
- qemu_get_be32s(f, &s->pm_regs[i]);
-
- return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_pm = {
+ .name = "pxa2xx_pm",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(pm_regs, PXA2xxState, 0x40),
+ VMSTATE_END_OF_LIST()
+ }
+};
#define CCCR 0x00 /* Core Clock Configuration register */
#define CKEN 0x04 /* Clock Enable register */
@@ -227,29 +218,18 @@ static CPUWriteMemoryFunc * const pxa2xx_cm_writefn[] = {
pxa2xx_cm_write,
};
-static void pxa2xx_cm_save(QEMUFile *f, void *opaque)
-{
- PXA2xxState *s = (PXA2xxState *) opaque;
- int i;
-
- for (i = 0; i < 4; i ++)
- qemu_put_be32s(f, &s->cm_regs[i]);
- qemu_put_be32s(f, &s->clkcfg);
- qemu_put_be32s(f, &s->pmnc);
-}
-
-static int pxa2xx_cm_load(QEMUFile *f, void *opaque, int version_id)
-{
- PXA2xxState *s = (PXA2xxState *) opaque;
- int i;
-
- for (i = 0; i < 4; i ++)
- qemu_get_be32s(f, &s->cm_regs[i]);
- qemu_get_be32s(f, &s->clkcfg);
- qemu_get_be32s(f, &s->pmnc);
-
- return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_cm = {
+ .name = "pxa2xx_cm",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(cm_regs, PXA2xxState, 4),
+ VMSTATE_UINT32(clkcfg, PXA2xxState),
+ VMSTATE_UINT32(pmnc, PXA2xxState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static uint32_t pxa2xx_clkpwr_read(void *opaque, int op2, int reg, int crm)
{
@@ -527,25 +507,16 @@ static CPUWriteMemoryFunc * const pxa2xx_mm_writefn[] = {
pxa2xx_mm_write,
};
-static void pxa2xx_mm_save(QEMUFile *f, void *opaque)
-{
- PXA2xxState *s = (PXA2xxState *) opaque;
- int i;
-
- for (i = 0; i < 0x1a; i ++)
- qemu_put_be32s(f, &s->mm_regs[i]);
-}
-
-static int pxa2xx_mm_load(QEMUFile *f, void *opaque, int version_id)
-{
- PXA2xxState *s = (PXA2xxState *) opaque;
- int i;
-
- for (i = 0; i < 0x1a; i ++)
- qemu_get_be32s(f, &s->mm_regs[i]);
-
- return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_mm = {
+ .name = "pxa2xx_mm",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(mm_regs, PXA2xxState, 0x1a),
+ VMSTATE_END_OF_LIST()
+ }
+};
/* Synchronous Serial Ports */
typedef struct {
@@ -1748,39 +1719,23 @@ static CPUWriteMemoryFunc * const pxa2xx_i2s_writefn[] = {
pxa2xx_i2s_write,
};
-static void pxa2xx_i2s_save(QEMUFile *f, void *opaque)
-{
- PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
-
- qemu_put_be32s(f, &s->control[0]);
- qemu_put_be32s(f, &s->control[1]);
- qemu_put_be32s(f, &s->status);
- qemu_put_be32s(f, &s->mask);
- qemu_put_be32s(f, &s->clk);
-
- qemu_put_be32(f, s->enable);
- qemu_put_be32(f, s->rx_len);
- qemu_put_be32(f, s->tx_len);
- qemu_put_be32(f, s->fifo_len);
-}
-
-static int pxa2xx_i2s_load(QEMUFile *f, void *opaque, int version_id)
-{
- PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
-
- qemu_get_be32s(f, &s->control[0]);
- qemu_get_be32s(f, &s->control[1]);
- qemu_get_be32s(f, &s->status);
- qemu_get_be32s(f, &s->mask);
- qemu_get_be32s(f, &s->clk);
-
- s->enable = qemu_get_be32(f);
- s->rx_len = qemu_get_be32(f);
- s->tx_len = qemu_get_be32(f);
- s->fifo_len = qemu_get_be32(f);
-
- return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_i2s = {
+ .name = "pxa2xx_i2s",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(control, PXA2xxI2SState, 2),
+ VMSTATE_UINT32(status, PXA2xxI2SState),
+ VMSTATE_UINT32(mask, PXA2xxI2SState),
+ VMSTATE_UINT32(clk, PXA2xxI2SState),
+ VMSTATE_INT32(enable, PXA2xxI2SState),
+ VMSTATE_INT32(rx_len, PXA2xxI2SState),
+ VMSTATE_INT32(tx_len, PXA2xxI2SState),
+ VMSTATE_INT32(fifo_len, PXA2xxI2SState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx)
{
@@ -1822,8 +1777,7 @@ static PXA2xxI2SState *pxa2xx_i2s_init(target_phys_addr_t base,
pxa2xx_i2s_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(base, 0x100000, iomemtype);
- register_savevm(NULL, "pxa2xx_i2s", base, 0,
- pxa2xx_i2s_save, pxa2xx_i2s_load, s);
+ vmstate_register(NULL, base, &vmstate_pxa2xx_i2s, s);
return s;
}
@@ -2188,7 +2142,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
pxa2xx_cm_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
- register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
@@ -2199,13 +2153,13 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
pxa2xx_mm_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
- register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
s->pm_base = 0x40f00000;
iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
pxa2xx_pm_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
- register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
for (i = 0; pxa27x_ssp[i].io_base; i ++);
s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i);
@@ -2324,7 +2278,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
pxa2xx_cm_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
- register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
@@ -2335,13 +2289,13 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
pxa2xx_mm_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
- register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
s->pm_base = 0x40f00000;
iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
pxa2xx_pm_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
- register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
for (i = 0; pxa255_ssp[i].io_base; i ++);
s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i);
diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index d77dbf179..10ef154aa 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -289,40 +289,22 @@ static CPUWriteMemoryFunc * const pxa2xx_keypad_writefn[] = {
pxa2xx_keypad_write
};
-static void pxa2xx_keypad_save(QEMUFile *f, void *opaque)
-{
- PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque;
-
- qemu_put_be32s(f, &s->kpc);
- qemu_put_be32s(f, &s->kpdk);
- qemu_put_be32s(f, &s->kprec);
- qemu_put_be32s(f, &s->kpmk);
- qemu_put_be32s(f, &s->kpas);
- qemu_put_be32s(f, &s->kpasmkp[0]);
- qemu_put_be32s(f, &s->kpasmkp[1]);
- qemu_put_be32s(f, &s->kpasmkp[2]);
- qemu_put_be32s(f, &s->kpasmkp[3]);
- qemu_put_be32s(f, &s->kpkdi);
-
-}
-
-static int pxa2xx_keypad_load(QEMUFile *f, void *opaque, int version_id)
-{
- PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque;
-
- qemu_get_be32s(f, &s->kpc);
- qemu_get_be32s(f, &s->kpdk);
- qemu_get_be32s(f, &s->kprec);
- qemu_get_be32s(f, &s->kpmk);
- qemu_get_be32s(f, &s->kpas);
- qemu_get_be32s(f, &s->kpasmkp[0]);
- qemu_get_be32s(f, &s->kpasmkp[1]);
- qemu_get_be32s(f, &s->kpasmkp[2]);
- qemu_get_be32s(f, &s->kpasmkp[3]);
- qemu_get_be32s(f, &s->kpkdi);
-
- return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_keypad = {
+ .name = "pxa2xx_keypad",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(kpc, PXA2xxKeyPadState),
+ VMSTATE_UINT32(kpdk, PXA2xxKeyPadState),
+ VMSTATE_UINT32(kprec, PXA2xxKeyPadState),
+ VMSTATE_UINT32(kpmk, PXA2xxKeyPadState),
+ VMSTATE_UINT32(kpas, PXA2xxKeyPadState),
+ VMSTATE_UINT32_ARRAY(kpasmkp, PXA2xxKeyPadState, 4),
+ VMSTATE_UINT32(kpkdi, PXA2xxKeyPadState),
+ VMSTATE_END_OF_LIST()
+ }
+};
PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
qemu_irq irq)
@@ -337,8 +319,7 @@ PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
pxa2xx_keypad_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(base, 0x00100000, iomemtype);
- register_savevm(NULL, "pxa2xx_keypad", 0, 0,
- pxa2xx_keypad_save, pxa2xx_keypad_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_keypad, s);
return s;
}
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 5b2b07e02..e5248023f 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -15,6 +15,20 @@
#include "sysemu.h"
#include "framebuffer.h"
+struct DMAChannel {
+ target_phys_addr_t branch;
+ uint8_t up;
+ uint8_t palette[1024];
+ uint8_t pbuffer[1024];
+ void (*redraw)(PXA2xxLCDState *s, target_phys_addr_t addr,
+ int *miny, int *maxy);
+
+ target_phys_addr_t descriptor;
+ target_phys_addr_t source;
+ uint32_t id;
+ uint32_t command;
+};
+
struct PXA2xxLCDState {
qemu_irq irq;
int irqlevel;
@@ -50,19 +64,7 @@ struct PXA2xxLCDState {
uint32_t liidr;
uint8_t bscntr;
- struct {
- target_phys_addr_t branch;
- int up;
- uint8_t palette[1024];
- uint8_t pbuffer[1024];
- void (*redraw)(PXA2xxLCDState *s, target_phys_addr_t addr,
- int *miny, int *maxy);
-
- target_phys_addr_t descriptor;
- target_phys_addr_t source;
- uint32_t id;
- uint32_t command;
- } dma_ch[7];
+ struct DMAChannel dma_ch[7];
qemu_irq vsync_cb;
int orientation;
@@ -831,74 +833,26 @@ static void pxa2xx_lcdc_orientation(void *opaque, int angle)
pxa2xx_lcdc_resize(s);
}
-static void pxa2xx_lcdc_save(QEMUFile *f, void *opaque)
-{
- PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
- int i;
-
- qemu_put_be32(f, s->irqlevel);
- qemu_put_be32(f, s->transp);
-
- for (i = 0; i < 6; i ++)
- qemu_put_be32s(f, &s->control[i]);
- for (i = 0; i < 2; i ++)
- qemu_put_be32s(f, &s->status[i]);
- for (i = 0; i < 2; i ++)
- qemu_put_be32s(f, &s->ovl1c[i]);
- for (i = 0; i < 2; i ++)
- qemu_put_be32s(f, &s->ovl2c[i]);
- qemu_put_be32s(f, &s->ccr);
- qemu_put_be32s(f, &s->cmdcr);
- qemu_put_be32s(f, &s->trgbr);
- qemu_put_be32s(f, &s->tcr);
- qemu_put_be32s(f, &s->liidr);
- qemu_put_8s(f, &s->bscntr);
-
- for (i = 0; i < 7; i ++) {
- qemu_put_betl(f, s->dma_ch[i].branch);
- qemu_put_byte(f, s->dma_ch[i].up);
- qemu_put_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer));
-
- qemu_put_betl(f, s->dma_ch[i].descriptor);
- qemu_put_betl(f, s->dma_ch[i].source);
- qemu_put_be32s(f, &s->dma_ch[i].id);
- qemu_put_be32s(f, &s->dma_ch[i].command);
+static const VMStateDescription vmstate_dma_channel = {
+ .name = "dma_channel",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINTTL(branch, struct DMAChannel),
+ VMSTATE_UINT8(up, struct DMAChannel),
+ VMSTATE_BUFFER(pbuffer, struct DMAChannel),
+ VMSTATE_UINTTL(descriptor, struct DMAChannel),
+ VMSTATE_UINTTL(source, struct DMAChannel),
+ VMSTATE_UINT32(id, struct DMAChannel),
+ VMSTATE_UINT32(command, struct DMAChannel),
+ VMSTATE_END_OF_LIST()
}
-}
+};
-static int pxa2xx_lcdc_load(QEMUFile *f, void *opaque, int version_id)
+static int pxa2xx_lcdc_post_load(void *opaque, int version_id)
{
- PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
- int i;
-
- s->irqlevel = qemu_get_be32(f);
- s->transp = qemu_get_be32(f);
-
- for (i = 0; i < 6; i ++)
- qemu_get_be32s(f, &s->control[i]);
- for (i = 0; i < 2; i ++)
- qemu_get_be32s(f, &s->status[i]);
- for (i = 0; i < 2; i ++)
- qemu_get_be32s(f, &s->ovl1c[i]);
- for (i = 0; i < 2; i ++)
- qemu_get_be32s(f, &s->ovl2c[i]);
- qemu_get_be32s(f, &s->ccr);
- qemu_get_be32s(f, &s->cmdcr);
- qemu_get_be32s(f, &s->trgbr);
- qemu_get_be32s(f, &s->tcr);
- qemu_get_be32s(f, &s->liidr);
- qemu_get_8s(f, &s->bscntr);
-
- for (i = 0; i < 7; i ++) {
- s->dma_ch[i].branch = qemu_get_betl(f);
- s->dma_ch[i].up = qemu_get_byte(f);
- qemu_get_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer));
-
- s->dma_ch[i].descriptor = qemu_get_betl(f);
- s->dma_ch[i].source = qemu_get_betl(f);
- qemu_get_be32s(f, &s->dma_ch[i].id);
- qemu_get_be32s(f, &s->dma_ch[i].command);
- }
+ PXA2xxLCDState *s = opaque;
s->bpp = LCCR3_BPP(s->control[3]);
s->xres = s->yres = s->pal_for = -1;
@@ -906,6 +860,31 @@ static int pxa2xx_lcdc_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
+static const VMStateDescription vmstate_pxa2xx_lcdc = {
+ .name = "pxa2xx_lcdc",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = pxa2xx_lcdc_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(irqlevel, PXA2xxLCDState),
+ VMSTATE_INT32(transp, PXA2xxLCDState),
+ VMSTATE_UINT32_ARRAY(control, PXA2xxLCDState, 6),
+ VMSTATE_UINT32_ARRAY(status, PXA2xxLCDState, 2),
+ VMSTATE_UINT32_ARRAY(ovl1c, PXA2xxLCDState, 2),
+ VMSTATE_UINT32_ARRAY(ovl2c, PXA2xxLCDState, 2),
+ VMSTATE_UINT32(ccr, PXA2xxLCDState),
+ VMSTATE_UINT32(cmdcr, PXA2xxLCDState),
+ VMSTATE_UINT32(trgbr, PXA2xxLCDState),
+ VMSTATE_UINT32(tcr, PXA2xxLCDState),
+ VMSTATE_UINT32(liidr, PXA2xxLCDState),
+ VMSTATE_UINT8(bscntr, PXA2xxLCDState),
+ VMSTATE_STRUCT_ARRAY(dma_ch, PXA2xxLCDState, 7, 0,
+ vmstate_dma_channel, struct DMAChannel),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
#define BITS 8
#include "pxa2xx_template.h"
#define BITS 15
@@ -970,8 +949,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq)
exit(1);
}
- register_savevm(NULL, "pxa2xx_lcdc", 0, 0,
- pxa2xx_lcdc_save, pxa2xx_lcdc_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_lcdc, s);
return s;
}
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 1088a26f8..eff2d2494 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -354,10 +354,10 @@ static int parse_chr(DeviceState *dev, Property *prop, const char *str)
if (*ptr == NULL) {
return -ENOENT;
}
- if ((*ptr)->assigned) {
+ if ((*ptr)->avail_connections < 1) {
return -EEXIST;
}
- (*ptr)->assigned = 1;
+ --(*ptr)->avail_connections;
return 0;
}
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index d5459336e..515652f27 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -85,9 +85,13 @@
#define VLAN_HLEN (ETHER_TYPE_LEN + VLAN_TCI_LEN)
#if defined (DEBUG_RTL8139)
-# define DEBUG_PRINT(x) do { printf x ; } while (0)
+# define DPRINTF(fmt, ...) \
+ do { fprintf(stderr, "RTL8139: " fmt, ## __VA_ARGS__); } while (0)
#else
-# define DEBUG_PRINT(x)
+static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...)
+{
+ return 0;
+}
#endif
/* Symbolic offsets to registers. */
@@ -510,7 +514,7 @@ static void rtl8139_set_next_tctr_time(RTL8139State *s, int64_t current_time);
static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
{
- DEBUG_PRINT(("RTL8139: eeprom command 0x%02x\n", command));
+ DPRINTF("eeprom command 0x%02x\n", command);
switch (command & Chip9346_op_mask)
{
@@ -521,8 +525,8 @@ static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
eeprom->eedo = 0;
eeprom->tick = 0;
eeprom->mode = Chip9346_data_read;
- DEBUG_PRINT(("RTL8139: eeprom read from address 0x%02x data=0x%04x\n",
- eeprom->address, eeprom->output));
+ DPRINTF("eeprom read from address 0x%02x data=0x%04x\n",
+ eeprom->address, eeprom->output);
}
break;
@@ -532,8 +536,8 @@ static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
eeprom->input = 0;
eeprom->tick = 0;
eeprom->mode = Chip9346_none; /* Chip9346_data_write */
- DEBUG_PRINT(("RTL8139: eeprom begin write to address 0x%02x\n",
- eeprom->address));
+ DPRINTF("eeprom begin write to address 0x%02x\n",
+ eeprom->address);
}
break;
default:
@@ -541,13 +545,13 @@ static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
switch (command & Chip9346_op_ext_mask)
{
case Chip9346_op_write_enable:
- DEBUG_PRINT(("RTL8139: eeprom write enabled\n"));
+ DPRINTF("eeprom write enabled\n");
break;
case Chip9346_op_write_all:
- DEBUG_PRINT(("RTL8139: eeprom begin write all\n"));
+ DPRINTF("eeprom begin write all\n");
break;
case Chip9346_op_write_disable:
- DEBUG_PRINT(("RTL8139: eeprom write disabled\n"));
+ DPRINTF("eeprom write disabled\n");
break;
}
break;
@@ -560,7 +564,8 @@ static void prom9346_shift_clock(EEprom9346 *eeprom)
++ eeprom->tick;
- DEBUG_PRINT(("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, eeprom->eedo));
+ DPRINTF("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi,
+ eeprom->eedo);
switch (eeprom->mode)
{
@@ -570,7 +575,7 @@ static void prom9346_shift_clock(EEprom9346 *eeprom)
eeprom->mode = Chip9346_read_command;
eeprom->tick = 0;
eeprom->input = 0;
- DEBUG_PRINT(("eeprom: +++ synchronized, begin command read\n"));
+ DPRINTF("eeprom: +++ synchronized, begin command read\n");
}
break;
@@ -595,7 +600,7 @@ static void prom9346_shift_clock(EEprom9346 *eeprom)
eeprom->input = 0;
eeprom->tick = 0;
- DEBUG_PRINT(("eeprom: +++ end of read, awaiting next command\n"));
+ DPRINTF("eeprom: +++ end of read, awaiting next command\n");
#else
// original behaviour
++eeprom->address;
@@ -603,8 +608,8 @@ static void prom9346_shift_clock(EEprom9346 *eeprom)
eeprom->output = eeprom->contents[eeprom->address];
eeprom->tick = 0;
- DEBUG_PRINT(("eeprom: +++ read next address 0x%02x data=0x%04x\n",
- eeprom->address, eeprom->output));
+ DPRINTF("eeprom: +++ read next address 0x%02x data=0x%04x\n",
+ eeprom->address, eeprom->output);
#endif
}
break;
@@ -613,8 +618,8 @@ static void prom9346_shift_clock(EEprom9346 *eeprom)
eeprom->input = (eeprom->input << 1) | (bit & 1);
if (eeprom->tick == 16)
{
- DEBUG_PRINT(("RTL8139: eeprom write to address 0x%02x data=0x%04x\n",
- eeprom->address, eeprom->input));
+ DPRINTF("eeprom write to address 0x%02x data=0x%04x\n",
+ eeprom->address, eeprom->input);
eeprom->contents[eeprom->address] = eeprom->input;
eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */
@@ -632,8 +637,7 @@ static void prom9346_shift_clock(EEprom9346 *eeprom)
{
eeprom->contents[i] = eeprom->input;
}
- DEBUG_PRINT(("RTL8139: eeprom filled with data=0x%04x\n",
- eeprom->input));
+ DPRINTF("eeprom filled with data=0x%04x\n", eeprom->input);
eeprom->mode = Chip9346_enter_command_mode;
eeprom->tick = 0;
@@ -666,8 +670,8 @@ static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi)
eeprom->eesk = eesk;
eeprom->eedi = eedi;
- DEBUG_PRINT(("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n",
- eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo));
+ DPRINTF("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n", eeprom->eecs,
+ eeprom->eesk, eeprom->eedi, eeprom->eedo);
if (!old_eecs && eecs)
{
@@ -677,12 +681,12 @@ static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi)
eeprom->output = 0;
eeprom->mode = Chip9346_enter_command_mode;
- DEBUG_PRINT(("=== eeprom: begin access, enter command mode\n"));
+ DPRINTF("=== eeprom: begin access, enter command mode\n");
}
if (!eecs)
{
- DEBUG_PRINT(("=== eeprom: end access\n"));
+ DPRINTF("=== eeprom: end access\n");
return;
}
@@ -698,8 +702,8 @@ static void rtl8139_update_irq(RTL8139State *s)
int isr;
isr = (s->IntrStatus & s->IntrMask) & 0xffff;
- DEBUG_PRINT(("RTL8139: Set IRQ to %d (%04x %04x)\n",
- isr ? 1 : 0, s->IntrStatus, s->IntrMask));
+ DPRINTF("Set IRQ to %d (%04x %04x)\n", isr ? 1 : 0, s->IntrStatus,
+ s->IntrMask);
qemu_set_irq(s->dev.irq[0], (isr != 0));
}
@@ -763,7 +767,7 @@ static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size)
/* write packet data */
if (wrapped && !(s->RxBufferSize < 65536 && rtl8139_RxWrap(s)))
{
- DEBUG_PRINT((">>> RTL8139: rx packet wrapped in buffer at %d\n", size-wrapped));
+ DPRINTF(">>> rx packet wrapped in buffer at %d\n", size - wrapped);
if (size > wrapped)
{
@@ -834,12 +838,12 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
static const uint8_t broadcast_macaddr[6] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- DEBUG_PRINT((">>> RTL8139: received len=%d\n", size));
+ DPRINTF(">>> received len=%d\n", size);
/* test if board clock is stopped */
if (!s->clock_enabled)
{
- DEBUG_PRINT(("RTL8139: stopped ==========================\n"));
+ DPRINTF("stopped ==========================\n");
return -1;
}
@@ -847,21 +851,21 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
if (!rtl8139_receiver_enabled(s))
{
- DEBUG_PRINT(("RTL8139: receiver disabled ================\n"));
+ DPRINTF("receiver disabled ================\n");
return -1;
}
/* XXX: check this */
if (s->RxConfig & AcceptAllPhys) {
/* promiscuous: receive all */
- DEBUG_PRINT((">>> RTL8139: packet received in promiscuous mode\n"));
+ DPRINTF(">>> packet received in promiscuous mode\n");
} else {
if (!memcmp(buf, broadcast_macaddr, 6)) {
/* broadcast address */
if (!(s->RxConfig & AcceptBroadcast))
{
- DEBUG_PRINT((">>> RTL8139: broadcast packet rejected\n"));
+ DPRINTF(">>> broadcast packet rejected\n");
/* update tally counter */
++s->tally_counters.RxERR;
@@ -871,7 +875,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
packet_header |= RxBroadcast;
- DEBUG_PRINT((">>> RTL8139: broadcast packet received\n"));
+ DPRINTF(">>> broadcast packet received\n");
/* update tally counter */
++s->tally_counters.RxOkBrd;
@@ -880,7 +884,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
/* multicast */
if (!(s->RxConfig & AcceptMulticast))
{
- DEBUG_PRINT((">>> RTL8139: multicast packet rejected\n"));
+ DPRINTF(">>> multicast packet rejected\n");
/* update tally counter */
++s->tally_counters.RxERR;
@@ -892,7 +896,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
{
- DEBUG_PRINT((">>> RTL8139: multicast address mismatch\n"));
+ DPRINTF(">>> multicast address mismatch\n");
/* update tally counter */
++s->tally_counters.RxERR;
@@ -902,7 +906,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
packet_header |= RxMulticast;
- DEBUG_PRINT((">>> RTL8139: multicast packet received\n"));
+ DPRINTF(">>> multicast packet received\n");
/* update tally counter */
++s->tally_counters.RxOkMul;
@@ -916,7 +920,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
/* match */
if (!(s->RxConfig & AcceptMyPhys))
{
- DEBUG_PRINT((">>> RTL8139: rejecting physical address matching packet\n"));
+ DPRINTF(">>> rejecting physical address matching packet\n");
/* update tally counter */
++s->tally_counters.RxERR;
@@ -926,14 +930,14 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
packet_header |= RxPhysical;
- DEBUG_PRINT((">>> RTL8139: physical address matching packet received\n"));
+ DPRINTF(">>> physical address matching packet received\n");
/* update tally counter */
++s->tally_counters.RxOkPhy;
} else {
- DEBUG_PRINT((">>> RTL8139: unknown packet\n"));
+ DPRINTF(">>> unknown packet\n");
/* update tally counter */
++s->tally_counters.RxERR;
@@ -955,7 +959,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
if (rtl8139_cp_receiver_enabled(s))
{
- DEBUG_PRINT(("RTL8139: in C+ Rx mode ================\n"));
+ DPRINTF("in C+ Rx mode ================\n");
/* begin C+ receiver mode */
@@ -978,8 +982,9 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI);
cplus_rx_ring_desc += 16 * descriptor;
- DEBUG_PRINT(("RTL8139: +++ C+ mode reading RX descriptor %d from host memory at %08x %08x = %016" PRIx64 "\n",
- descriptor, s->RxRingAddrHI, s->RxRingAddrLO, (uint64_t)cplus_rx_ring_desc));
+ DPRINTF("+++ C+ mode reading RX descriptor %d from host memory at "
+ "%08x %08x = "TARGET_FMT_plx"\n", descriptor, s->RxRingAddrHI,
+ s->RxRingAddrLO, cplus_rx_ring_desc);
uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI;
@@ -992,13 +997,13 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
cpu_physical_memory_read(cplus_rx_ring_desc+12, (uint8_t *)&val, 4);
rxbufHI = le32_to_cpu(val);
- DEBUG_PRINT(("RTL8139: +++ C+ mode RX descriptor %d %08x %08x %08x %08x\n",
- descriptor,
- rxdw0, rxdw1, rxbufLO, rxbufHI));
+ DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n",
+ descriptor, rxdw0, rxdw1, rxbufLO, rxbufHI);
if (!(rxdw0 & CP_RX_OWN))
{
- DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d is owned by host\n", descriptor));
+ DPRINTF("C+ Rx mode : descriptor %d is owned by host\n",
+ descriptor);
s->IntrStatus |= RxOverflow;
++s->RxMissed;
@@ -1028,9 +1033,8 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
rxdw1 |= CP_RX_TAVA | le16_to_cpup((uint16_t *)
&dot1q_buf[ETHER_TYPE_LEN]);
- DEBUG_PRINT(("RTL8139: C+ Rx mode : extracted vlan tag with tci: "
- "%u\n", be16_to_cpup((uint16_t *)
- &dot1q_buf[ETHER_TYPE_LEN])));
+ DPRINTF("C+ Rx mode : extracted vlan tag with tci: ""%u\n",
+ be16_to_cpup((uint16_t *)&dot1q_buf[ETHER_TYPE_LEN]));
} else {
/* reset VLAN tag flag */
rxdw1 &= ~CP_RX_TAVA;
@@ -1040,8 +1044,8 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
if (size+4 > rx_space)
{
- DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d size %d received %d + 4\n",
- descriptor, rx_space, size));
+ DPRINTF("C+ Rx mode : descriptor %d size %d received %d + 4\n",
+ descriptor, rx_space, size);
s->IntrStatus |= RxOverflow;
++s->RxMissed;
@@ -1136,12 +1140,12 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
++s->currCPlusRxDesc;
}
- DEBUG_PRINT(("RTL8139: done C+ Rx mode ----------------\n"));
+ DPRINTF("done C+ Rx mode ----------------\n");
}
else
{
- DEBUG_PRINT(("RTL8139: in ring Rx mode ================\n"));
+ DPRINTF("in ring Rx mode ================\n");
/* begin ring receiver mode */
int avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize);
@@ -1150,8 +1154,9 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
if (avail != 0 && size + 8 >= avail)
{
- DEBUG_PRINT(("rx overflow: rx buffer length %d head 0x%04x read 0x%04x === available 0x%04x need 0x%04x\n",
- s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8));
+ DPRINTF("rx overflow: rx buffer length %d head 0x%04x "
+ "read 0x%04x === available 0x%04x need 0x%04x\n",
+ s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8);
s->IntrStatus |= RxOverflow;
++s->RxMissed;
@@ -1179,8 +1184,8 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
/* now we can signal we have received something */
- DEBUG_PRINT((" received: rx buffer length %d head 0x%04x read 0x%04x\n",
- s->RxBufferSize, s->RxBufAddr, s->RxBufPtr));
+ DPRINTF("received: rx buffer length %d head 0x%04x read 0x%04x\n",
+ s->RxBufferSize, s->RxBufAddr, s->RxBufPtr);
}
s->IntrStatus |= RxOK;
@@ -1374,22 +1379,22 @@ static void rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val)
{
val &= 0xff;
- DEBUG_PRINT(("RTL8139: ChipCmd write val=0x%08x\n", val));
+ DPRINTF("ChipCmd write val=0x%08x\n", val);
if (val & CmdReset)
{
- DEBUG_PRINT(("RTL8139: ChipCmd reset\n"));
+ DPRINTF("ChipCmd reset\n");
rtl8139_reset(&s->dev.qdev);
}
if (val & CmdRxEnb)
{
- DEBUG_PRINT(("RTL8139: ChipCmd enable receiver\n"));
+ DPRINTF("ChipCmd enable receiver\n");
s->currCPlusRxDesc = 0;
}
if (val & CmdTxEnb)
{
- DEBUG_PRINT(("RTL8139: ChipCmd enable transmitter\n"));
+ DPRINTF("ChipCmd enable transmitter\n");
s->currCPlusTxDesc = 0;
}
@@ -1409,11 +1414,11 @@ static int rtl8139_RxBufferEmpty(RTL8139State *s)
if (unread != 0)
{
- DEBUG_PRINT(("RTL8139: receiver buffer data available 0x%04x\n", unread));
+ DPRINTF("receiver buffer data available 0x%04x\n", unread);
return 0;
}
- DEBUG_PRINT(("RTL8139: receiver buffer is empty\n"));
+ DPRINTF("receiver buffer is empty\n");
return 1;
}
@@ -1425,7 +1430,7 @@ static uint32_t rtl8139_ChipCmd_read(RTL8139State *s)
if (rtl8139_RxBufferEmpty(s))
ret |= RxBufEmpty;
- DEBUG_PRINT(("RTL8139: ChipCmd read val=0x%04x\n", ret));
+ DPRINTF("ChipCmd read val=0x%04x\n", ret);
return ret;
}
@@ -1434,7 +1439,7 @@ static void rtl8139_CpCmd_write(RTL8139State *s, uint32_t val)
{
val &= 0xffff;
- DEBUG_PRINT(("RTL8139C+ command register write(w) val=0x%04x\n", val));
+ DPRINTF("C+ command register write(w) val=0x%04x\n", val);
s->cplus_enabled = 1;
@@ -1448,21 +1453,21 @@ static uint32_t rtl8139_CpCmd_read(RTL8139State *s)
{
uint32_t ret = s->CpCmd;
- DEBUG_PRINT(("RTL8139C+ command register read(w) val=0x%04x\n", ret));
+ DPRINTF("C+ command register read(w) val=0x%04x\n", ret);
return ret;
}
static void rtl8139_IntrMitigate_write(RTL8139State *s, uint32_t val)
{
- DEBUG_PRINT(("RTL8139C+ IntrMitigate register write(w) val=0x%04x\n", val));
+ DPRINTF("C+ IntrMitigate register write(w) val=0x%04x\n", val);
}
static uint32_t rtl8139_IntrMitigate_read(RTL8139State *s)
{
uint32_t ret = 0;
- DEBUG_PRINT(("RTL8139C+ IntrMitigate register read(w) val=0x%04x\n", ret));
+ DPRINTF("C+ IntrMitigate register read(w) val=0x%04x\n", ret);
return ret;
}
@@ -1474,7 +1479,7 @@ static int rtl8139_config_writeable(RTL8139State *s)
return 1;
}
- DEBUG_PRINT(("RTL8139: Configuration registers are write-protected\n"));
+ DPRINTF("Configuration registers are write-protected\n");
return 0;
}
@@ -1483,7 +1488,7 @@ static void rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val)
{
val &= 0xffff;
- DEBUG_PRINT(("RTL8139: BasicModeCtrl register write(w) val=0x%04x\n", val));
+ DPRINTF("BasicModeCtrl register write(w) val=0x%04x\n", val);
/* mask unwriteable bits */
uint32_t mask = 0x4cff;
@@ -1505,7 +1510,7 @@ static uint32_t rtl8139_BasicModeCtrl_read(RTL8139State *s)
{
uint32_t ret = s->BasicModeCtrl;
- DEBUG_PRINT(("RTL8139: BasicModeCtrl register read(w) val=0x%04x\n", ret));
+ DPRINTF("BasicModeCtrl register read(w) val=0x%04x\n", ret);
return ret;
}
@@ -1514,7 +1519,7 @@ static void rtl8139_BasicModeStatus_write(RTL8139State *s, uint32_t val)
{
val &= 0xffff;
- DEBUG_PRINT(("RTL8139: BasicModeStatus register write(w) val=0x%04x\n", val));
+ DPRINTF("BasicModeStatus register write(w) val=0x%04x\n", val);
/* mask unwriteable bits */
val = SET_MASKED(val, 0xff3f, s->BasicModeStatus);
@@ -1526,7 +1531,7 @@ static uint32_t rtl8139_BasicModeStatus_read(RTL8139State *s)
{
uint32_t ret = s->BasicModeStatus;
- DEBUG_PRINT(("RTL8139: BasicModeStatus register read(w) val=0x%04x\n", ret));
+ DPRINTF("BasicModeStatus register read(w) val=0x%04x\n", ret);
return ret;
}
@@ -1535,7 +1540,7 @@ static void rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val)
{
val &= 0xff;
- DEBUG_PRINT(("RTL8139: Cfg9346 write val=0x%02x\n", val));
+ DPRINTF("Cfg9346 write val=0x%02x\n", val);
/* mask unwriteable bits */
val = SET_MASKED(val, 0x31, s->Cfg9346);
@@ -1578,7 +1583,7 @@ static uint32_t rtl8139_Cfg9346_read(RTL8139State *s)
}
}
- DEBUG_PRINT(("RTL8139: Cfg9346 read val=0x%02x\n", ret));
+ DPRINTF("Cfg9346 read val=0x%02x\n", ret);
return ret;
}
@@ -1587,7 +1592,7 @@ static void rtl8139_Config0_write(RTL8139State *s, uint32_t val)
{
val &= 0xff;
- DEBUG_PRINT(("RTL8139: Config0 write val=0x%02x\n", val));
+ DPRINTF("Config0 write val=0x%02x\n", val);
if (!rtl8139_config_writeable(s))
return;
@@ -1602,7 +1607,7 @@ static uint32_t rtl8139_Config0_read(RTL8139State *s)
{
uint32_t ret = s->Config0;
- DEBUG_PRINT(("RTL8139: Config0 read val=0x%02x\n", ret));
+ DPRINTF("Config0 read val=0x%02x\n", ret);
return ret;
}
@@ -1611,7 +1616,7 @@ static void rtl8139_Config1_write(RTL8139State *s, uint32_t val)
{
val &= 0xff;
- DEBUG_PRINT(("RTL8139: Config1 write val=0x%02x\n", val));
+ DPRINTF("Config1 write val=0x%02x\n", val);
if (!rtl8139_config_writeable(s))
return;
@@ -1626,7 +1631,7 @@ static uint32_t rtl8139_Config1_read(RTL8139State *s)
{
uint32_t ret = s->Config1;
- DEBUG_PRINT(("RTL8139: Config1 read val=0x%02x\n", ret));
+ DPRINTF("Config1 read val=0x%02x\n", ret);
return ret;
}
@@ -1635,7 +1640,7 @@ static void rtl8139_Config3_write(RTL8139State *s, uint32_t val)
{
val &= 0xff;
- DEBUG_PRINT(("RTL8139: Config3 write val=0x%02x\n", val));
+ DPRINTF("Config3 write val=0x%02x\n", val);
if (!rtl8139_config_writeable(s))
return;
@@ -1650,7 +1655,7 @@ static uint32_t rtl8139_Config3_read(RTL8139State *s)
{
uint32_t ret = s->Config3;
- DEBUG_PRINT(("RTL8139: Config3 read val=0x%02x\n", ret));
+ DPRINTF("Config3 read val=0x%02x\n", ret);
return ret;
}
@@ -1659,7 +1664,7 @@ static void rtl8139_Config4_write(RTL8139State *s, uint32_t val)
{
val &= 0xff;
- DEBUG_PRINT(("RTL8139: Config4 write val=0x%02x\n", val));
+ DPRINTF("Config4 write val=0x%02x\n", val);
if (!rtl8139_config_writeable(s))
return;
@@ -1674,7 +1679,7 @@ static uint32_t rtl8139_Config4_read(RTL8139State *s)
{
uint32_t ret = s->Config4;
- DEBUG_PRINT(("RTL8139: Config4 read val=0x%02x\n", ret));
+ DPRINTF("Config4 read val=0x%02x\n", ret);
return ret;
}
@@ -1683,7 +1688,7 @@ static void rtl8139_Config5_write(RTL8139State *s, uint32_t val)
{
val &= 0xff;
- DEBUG_PRINT(("RTL8139: Config5 write val=0x%02x\n", val));
+ DPRINTF("Config5 write val=0x%02x\n", val);
/* mask unwriteable bits */
val = SET_MASKED(val, 0x80, s->Config5);
@@ -1695,7 +1700,7 @@ static uint32_t rtl8139_Config5_read(RTL8139State *s)
{
uint32_t ret = s->Config5;
- DEBUG_PRINT(("RTL8139: Config5 read val=0x%02x\n", ret));
+ DPRINTF("Config5 read val=0x%02x\n", ret);
return ret;
}
@@ -1704,11 +1709,11 @@ static void rtl8139_TxConfig_write(RTL8139State *s, uint32_t val)
{
if (!rtl8139_transmitter_enabled(s))
{
- DEBUG_PRINT(("RTL8139: transmitter disabled; no TxConfig write val=0x%08x\n", val));
+ DPRINTF("transmitter disabled; no TxConfig write val=0x%08x\n", val);
return;
}
- DEBUG_PRINT(("RTL8139: TxConfig write val=0x%08x\n", val));
+ DPRINTF("TxConfig write val=0x%08x\n", val);
val = SET_MASKED(val, TxVersionMask | 0x8070f80f, s->TxConfig);
@@ -1717,7 +1722,7 @@ static void rtl8139_TxConfig_write(RTL8139State *s, uint32_t val)
static void rtl8139_TxConfig_writeb(RTL8139State *s, uint32_t val)
{
- DEBUG_PRINT(("RTL8139C TxConfig via write(b) val=0x%02x\n", val));
+ DPRINTF("RTL8139C TxConfig via write(b) val=0x%02x\n", val);
uint32_t tc = s->TxConfig;
tc &= 0xFFFFFF00;
@@ -1729,14 +1734,14 @@ static uint32_t rtl8139_TxConfig_read(RTL8139State *s)
{
uint32_t ret = s->TxConfig;
- DEBUG_PRINT(("RTL8139: TxConfig read val=0x%04x\n", ret));
+ DPRINTF("TxConfig read val=0x%04x\n", ret);
return ret;
}
static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val)
{
- DEBUG_PRINT(("RTL8139: RxConfig write val=0x%08x\n", val));
+ DPRINTF("RxConfig write val=0x%08x\n", val);
/* mask unwriteable bits */
val = SET_MASKED(val, 0xf0fc0040, s->RxConfig);
@@ -1746,14 +1751,14 @@ static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val)
/* reset buffer size and read/write pointers */
rtl8139_reset_rxring(s, 8192 << ((s->RxConfig >> 11) & 0x3));
- DEBUG_PRINT(("RTL8139: RxConfig write reset buffer size to %d\n", s->RxBufferSize));
+ DPRINTF("RxConfig write reset buffer size to %d\n", s->RxBufferSize);
}
static uint32_t rtl8139_RxConfig_read(RTL8139State *s)
{
uint32_t ret = s->RxConfig;
- DEBUG_PRINT(("RTL8139: RxConfig read val=0x%08x\n", ret));
+ DPRINTF("RxConfig read val=0x%08x\n", ret);
return ret;
}
@@ -1765,7 +1770,7 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size,
if (!size)
{
- DEBUG_PRINT(("RTL8139: +++ empty ethernet frame\n"));
+ DPRINTF("+++ empty ethernet frame\n");
return;
}
@@ -1790,7 +1795,7 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size,
buf = buf2;
}
- DEBUG_PRINT(("RTL8139: +++ transmit loopback mode\n"));
+ DPRINTF("+++ transmit loopback mode\n");
rtl8139_do_receive(&s->nic->nc, buf, size, do_interrupt);
if (iov) {
@@ -1811,25 +1816,25 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor)
{
if (!rtl8139_transmitter_enabled(s))
{
- DEBUG_PRINT(("RTL8139: +++ cannot transmit from descriptor %d: transmitter disabled\n",
- descriptor));
+ DPRINTF("+++ cannot transmit from descriptor %d: transmitter "
+ "disabled\n", descriptor);
return 0;
}
if (s->TxStatus[descriptor] & TxHostOwns)
{
- DEBUG_PRINT(("RTL8139: +++ cannot transmit from descriptor %d: owned by host (%08x)\n",
- descriptor, s->TxStatus[descriptor]));
+ DPRINTF("+++ cannot transmit from descriptor %d: owned by host "
+ "(%08x)\n", descriptor, s->TxStatus[descriptor]);
return 0;
}
- DEBUG_PRINT(("RTL8139: +++ transmitting from descriptor %d\n", descriptor));
+ DPRINTF("+++ transmitting from descriptor %d\n", descriptor);
int txsize = s->TxStatus[descriptor] & 0x1fff;
uint8_t txbuffer[0x2000];
- DEBUG_PRINT(("RTL8139: +++ transmit reading %d bytes from host memory at 0x%08x\n",
- txsize, s->TxAddr[descriptor]));
+ DPRINTF("+++ transmit reading %d bytes from host memory at 0x%08x\n",
+ txsize, s->TxAddr[descriptor]);
cpu_physical_memory_read(s->TxAddr[descriptor], txbuffer, txsize);
@@ -1839,7 +1844,8 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor)
rtl8139_transfer_frame(s, txbuffer, txsize, 0, NULL);
- DEBUG_PRINT(("RTL8139: +++ transmitted %d bytes from descriptor %d\n", txsize, descriptor));
+ DPRINTF("+++ transmitted %d bytes from descriptor %d\n", txsize,
+ descriptor);
/* update interrupt */
s->IntrStatus |= TxOK;
@@ -1939,13 +1945,13 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
{
if (!rtl8139_transmitter_enabled(s))
{
- DEBUG_PRINT(("RTL8139: +++ C+ mode: transmitter disabled\n"));
+ DPRINTF("+++ C+ mode: transmitter disabled\n");
return 0;
}
if (!rtl8139_cp_transmitter_enabled(s))
{
- DEBUG_PRINT(("RTL8139: +++ C+ mode: C+ transmitter disabled\n"));
+ DPRINTF("+++ C+ mode: C+ transmitter disabled\n");
return 0 ;
}
@@ -1957,8 +1963,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
/* Normal priority ring */
cplus_tx_ring_desc += 16 * descriptor;
- DEBUG_PRINT(("RTL8139: +++ C+ mode reading TX descriptor %d from host memory at %08x0x%08x = 0x%8lx\n",
- descriptor, s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc));
+ DPRINTF("+++ C+ mode reading TX descriptor %d from host memory at "
+ "%08x0x%08x = 0x"TARGET_FMT_plx"\n", descriptor, s->TxAddr[1],
+ s->TxAddr[0], cplus_tx_ring_desc);
uint32_t val, txdw0,txdw1,txbufLO,txbufHI;
@@ -1971,9 +1978,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
cpu_physical_memory_read(cplus_tx_ring_desc+12, (uint8_t *)&val, 4);
txbufHI = le32_to_cpu(val);
- DEBUG_PRINT(("RTL8139: +++ C+ mode TX descriptor %d %08x %08x %08x %08x\n",
- descriptor,
- txdw0, txdw1, txbufLO, txbufHI));
+ DPRINTF("+++ C+ mode TX descriptor %d %08x %08x %08x %08x\n", descriptor,
+ txdw0, txdw1, txbufLO, txbufHI);
/* w0 ownership flag */
#define CP_TX_OWN (1<<31)
@@ -2019,15 +2025,16 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
if (!(txdw0 & CP_TX_OWN))
{
- DEBUG_PRINT(("RTL8139: C+ Tx mode : descriptor %d is owned by host\n", descriptor));
+ DPRINTF("C+ Tx mode : descriptor %d is owned by host\n", descriptor);
return 0 ;
}
- DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : transmitting from descriptor %d\n", descriptor));
+ DPRINTF("+++ C+ Tx mode : transmitting from descriptor %d\n", descriptor);
if (txdw0 & CP_TX_FS)
{
- DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is first segment descriptor\n", descriptor));
+ DPRINTF("+++ C+ Tx mode : descriptor %d is first segment "
+ "descriptor\n", descriptor);
/* reset internal buffer offset */
s->cplus_txbuffer_offset = 0;
@@ -2043,7 +2050,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
s->cplus_txbuffer = qemu_malloc(s->cplus_txbuffer_len);
s->cplus_txbuffer_offset = 0;
- DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer allocated space %d\n", s->cplus_txbuffer_len));
+ DPRINTF("+++ C+ mode transmission buffer allocated space %d\n",
+ s->cplus_txbuffer_len);
}
while (s->cplus_txbuffer && s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len)
@@ -2051,14 +2059,16 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
s->cplus_txbuffer_len += CP_TX_BUFFER_SIZE;
s->cplus_txbuffer = qemu_realloc(s->cplus_txbuffer, s->cplus_txbuffer_len);
- DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer space changed to %d\n", s->cplus_txbuffer_len));
+ DPRINTF("+++ C+ mode transmission buffer space changed to %d\n",
+ s->cplus_txbuffer_len);
}
if (!s->cplus_txbuffer)
{
/* out of memory */
- DEBUG_PRINT(("RTL8139: +++ C+ mode transmiter failed to reallocate %d bytes\n", s->cplus_txbuffer_len));
+ DPRINTF("+++ C+ mode transmiter failed to reallocate %d bytes\n",
+ s->cplus_txbuffer_len);
/* update tally counter */
++s->tally_counters.TxERR;
@@ -2069,8 +2079,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
/* append more data to the packet */
- DEBUG_PRINT(("RTL8139: +++ C+ mode transmit reading %d bytes from host memory at %016" PRIx64 " to offset %d\n",
- txsize, (uint64_t)tx_addr, s->cplus_txbuffer_offset));
+ DPRINTF("+++ C+ mode transmit reading %d bytes from host memory at "
+ TARGET_FMT_plx" to offset %d\n", txsize, tx_addr,
+ s->cplus_txbuffer_offset);
cpu_physical_memory_read(tx_addr, s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize);
s->cplus_txbuffer_offset += txsize;
@@ -2107,7 +2118,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
uint8_t dot1q_buffer_space[VLAN_HLEN];
uint16_t *dot1q_buffer;
- DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is last segment descriptor\n", descriptor));
+ DPRINTF("+++ C+ Tx mode : descriptor %d is last segment descriptor\n",
+ descriptor);
/* can transfer fully assembled packet */
@@ -2119,8 +2131,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
if (txdw1 & CP_TX_TAGC) {
/* the vlan tag is in BE byte order in the descriptor
* BE + le_to_cpu() + ~swap()~ = cpu */
- DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : inserting vlan tag with "
- "tci: %u\n", bswap16(txdw1 & CP_TX_VLAN_TAG_MASK)));
+ DPRINTF("+++ C+ Tx mode : inserting vlan tag with ""tci: %u\n",
+ bswap16(txdw1 & CP_TX_VLAN_TAG_MASK));
dot1q_buffer = (uint16_t *) dot1q_buffer_space;
dot1q_buffer[0] = cpu_to_be16(ETH_P_8021Q);
@@ -2137,7 +2149,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
if (txdw0 & (CP_TX_IPCS | CP_TX_UDPCS | CP_TX_TCPCS | CP_TX_LGSEN))
{
- DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task checksum\n"));
+ DPRINTF("+++ C+ mode offloaded task checksum\n");
/* ip packet header */
ip_header *ip = NULL;
@@ -2151,7 +2163,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
if (proto == ETH_P_IP)
{
- DEBUG_PRINT(("RTL8139: +++ C+ mode has IP packet\n"));
+ DPRINTF("+++ C+ mode has IP packet\n");
/* not aligned */
eth_payload_data = saved_buffer + ETH_HLEN;
@@ -2160,7 +2172,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
ip = (ip_header*)eth_payload_data;
if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
- DEBUG_PRINT(("RTL8139: +++ C+ mode packet has bad IP version %d expected %d\n", IP_HEADER_VERSION(ip), IP_HEADER_VERSION_4));
+ DPRINTF("+++ C+ mode packet has bad IP version %d "
+ "expected %d\n", IP_HEADER_VERSION(ip),
+ IP_HEADER_VERSION_4);
ip = NULL;
} else {
hlen = IP_HEADER_LENGTH(ip);
@@ -2173,7 +2187,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
{
if (txdw0 & CP_TX_IPCS)
{
- DEBUG_PRINT(("RTL8139: +++ C+ mode need IP checksum\n"));
+ DPRINTF("+++ C+ mode need IP checksum\n");
if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
/* bad packet header len */
@@ -2183,17 +2197,18 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
{
ip->ip_sum = 0;
ip->ip_sum = ip_checksum(ip, hlen);
- DEBUG_PRINT(("RTL8139: +++ C+ mode IP header len=%d checksum=%04x\n", hlen, ip->ip_sum));
+ DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
+ hlen, ip->ip_sum);
}
}
if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
{
-#if defined (DEBUG_RTL8139)
int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
-#endif
- DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task TSO MTU=%d IP data %d frame data %d specified MSS=%d\n",
- ETH_MTU, ip_data_len, saved_size - ETH_HLEN, large_send_mss));
+
+ DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
+ "frame data %d specified MSS=%d\n", ETH_MTU,
+ ip_data_len, saved_size - ETH_HLEN, large_send_mss);
int tcp_send_offset = 0;
int send_count = 0;
@@ -2217,8 +2232,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
int tcp_data_len = ip_data_len - tcp_hlen;
int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP data len %d TCP hlen %d TCP data len %d TCP chunk size %d\n",
- ip_data_len, tcp_hlen, tcp_data_len, tcp_chunk_size));
+ DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP "
+ "data len %d TCP chunk size %d\n", ip_data_len,
+ tcp_hlen, tcp_data_len, tcp_chunk_size);
/* note the cycle below overwrites IP header data,
but restores it from saved_ip_header before sending packet */
@@ -2236,13 +2252,16 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
chunk_size = tcp_data_len - tcp_send_offset;
}
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP seqno %08x\n", be32_to_cpu(p_tcp_hdr->th_seq)));
+ DPRINTF("+++ C+ mode TSO TCP seqno %08x\n",
+ be32_to_cpu(p_tcp_hdr->th_seq));
/* add 4 TCP pseudoheader fields */
/* copy IP source and destination fields */
memcpy(data_to_checksum, saved_ip_header + 12, 8);
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO calculating TCP checksum for packet with %d bytes data\n", tcp_hlen + chunk_size));
+ DPRINTF("+++ C+ mode TSO calculating TCP checksum for "
+ "packet with %d bytes data\n", tcp_hlen +
+ chunk_size);
if (tcp_send_offset)
{
@@ -2264,7 +2283,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
p_tcp_hdr->th_sum = 0;
int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP checksum %04x\n", tcp_checksum));
+ DPRINTF("+++ C+ mode TSO TCP checksum %04x\n",
+ tcp_checksum);
p_tcp_hdr->th_sum = tcp_checksum;
@@ -2279,10 +2299,12 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
ip->ip_sum = 0;
ip->ip_sum = ip_checksum(eth_payload_data, hlen);
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP header len=%d checksum=%04x\n", hlen, ip->ip_sum));
+ DPRINTF("+++ C+ mode TSO IP header len=%d "
+ "checksum=%04x\n", hlen, ip->ip_sum);
int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO transferring packet size %d\n", tso_send_size));
+ DPRINTF("+++ C+ mode TSO transferring packet size "
+ "%d\n", tso_send_size);
rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
0, (uint8_t *) dot1q_buffer);
@@ -2296,7 +2318,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
}
else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
{
- DEBUG_PRINT(("RTL8139: +++ C+ mode need TCP or UDP checksum\n"));
+ DPRINTF("+++ C+ mode need TCP or UDP checksum\n");
/* maximum IP header length is 60 bytes */
uint8_t saved_ip_header[60];
@@ -2311,7 +2333,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
{
- DEBUG_PRINT(("RTL8139: +++ C+ mode calculating TCP checksum for packet with %d bytes data\n", ip_data_len));
+ DPRINTF("+++ C+ mode calculating TCP checksum for "
+ "packet with %d bytes data\n", ip_data_len);
ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
p_tcpip_hdr->zeros = 0;
@@ -2323,13 +2346,15 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
p_tcp_hdr->th_sum = 0;
int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
- DEBUG_PRINT(("RTL8139: +++ C+ mode TCP checksum %04x\n", tcp_checksum));
+ DPRINTF("+++ C+ mode TCP checksum %04x\n",
+ tcp_checksum);
p_tcp_hdr->th_sum = tcp_checksum;
}
else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
{
- DEBUG_PRINT(("RTL8139: +++ C+ mode calculating UDP checksum for packet with %d bytes data\n", ip_data_len));
+ DPRINTF("+++ C+ mode calculating UDP checksum for "
+ "packet with %d bytes data\n", ip_data_len);
ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
p_udpip_hdr->zeros = 0;
@@ -2341,7 +2366,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
p_udp_hdr->uh_sum = 0;
int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
- DEBUG_PRINT(("RTL8139: +++ C+ mode UDP checksum %04x\n", udp_checksum));
+ DPRINTF("+++ C+ mode UDP checksum %04x\n",
+ udp_checksum);
p_udp_hdr->uh_sum = udp_checksum;
}
@@ -2355,7 +2381,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
/* update tally counter */
++s->tally_counters.TxOk;
- DEBUG_PRINT(("RTL8139: +++ C+ mode transmitting %d bytes packet\n", saved_size));
+ DPRINTF("+++ C+ mode transmitting %d bytes packet\n", saved_size);
rtl8139_transfer_frame(s, saved_buffer, saved_size, 1,
(uint8_t *) dot1q_buffer);
@@ -2374,7 +2400,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
}
else
{
- DEBUG_PRINT(("RTL8139: +++ C+ mode transmission continue to next descriptor\n"));
+ DPRINTF("+++ C+ mode transmission continue to next descriptor\n");
}
return 1;
@@ -2392,8 +2418,8 @@ static void rtl8139_cplus_transmit(RTL8139State *s)
/* Mark transfer completed */
if (!txcount)
{
- DEBUG_PRINT(("RTL8139: C+ mode : transmitter queue stalled, current TxDesc = %d\n",
- s->currCPlusTxDesc));
+ DPRINTF("C+ mode : transmitter queue stalled, current TxDesc = %d\n",
+ s->currCPlusTxDesc);
}
else
{
@@ -2418,7 +2444,8 @@ static void rtl8139_transmit(RTL8139State *s)
/* Mark transfer completed */
if (!txcount)
{
- DEBUG_PRINT(("RTL8139: transmitter queue stalled, current TxDesc = %d\n", s->currTxDesc));
+ DPRINTF("transmitter queue stalled, current TxDesc = %d\n",
+ s->currTxDesc);
}
}
@@ -2431,7 +2458,8 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32
if (s->cplus_enabled)
{
- DEBUG_PRINT(("RTL8139C+ DTCCR write offset=0x%x val=0x%08x descriptor=%d\n", txRegOffset, val, descriptor));
+ DPRINTF("RTL8139C+ DTCCR write offset=0x%x val=0x%08x "
+ "descriptor=%d\n", txRegOffset, val, descriptor);
/* handle Dump Tally Counters command */
s->TxStatus[descriptor] = val;
@@ -2450,7 +2478,8 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32
return;
}
- DEBUG_PRINT(("RTL8139: TxStatus write offset=0x%x val=0x%08x descriptor=%d\n", txRegOffset, val, descriptor));
+ DPRINTF("TxStatus write offset=0x%x val=0x%08x descriptor=%d\n",
+ txRegOffset, val, descriptor);
/* mask only reserved bits */
val &= ~0xff00c000; /* these bits are reset on write */
@@ -2466,7 +2495,7 @@ static uint32_t rtl8139_TxStatus_read(RTL8139State *s, uint32_t txRegOffset)
{
uint32_t ret = s->TxStatus[txRegOffset/4];
- DEBUG_PRINT(("RTL8139: TxStatus read offset=0x%x val=0x%08x\n", txRegOffset, ret));
+ DPRINTF("TxStatus read offset=0x%x val=0x%08x\n", txRegOffset, ret);
return ret;
}
@@ -2498,7 +2527,7 @@ static uint16_t rtl8139_TSAD_read(RTL8139State *s)
|((s->TxStatus[0] & TxHostOwns )?TSAD_OWN0:0) ;
- DEBUG_PRINT(("RTL8139: TSAD read val=0x%04x\n", ret));
+ DPRINTF("TSAD read val=0x%04x\n", ret);
return ret;
}
@@ -2507,14 +2536,14 @@ static uint16_t rtl8139_CSCR_read(RTL8139State *s)
{
uint16_t ret = s->CSCR;
- DEBUG_PRINT(("RTL8139: CSCR read val=0x%04x\n", ret));
+ DPRINTF("CSCR read val=0x%04x\n", ret);
return ret;
}
static void rtl8139_TxAddr_write(RTL8139State *s, uint32_t txAddrOffset, uint32_t val)
{
- DEBUG_PRINT(("RTL8139: TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val));
+ DPRINTF("TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val);
s->TxAddr[txAddrOffset/4] = val;
}
@@ -2523,20 +2552,20 @@ static uint32_t rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset)
{
uint32_t ret = s->TxAddr[txAddrOffset/4];
- DEBUG_PRINT(("RTL8139: TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret));
+ DPRINTF("TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret);
return ret;
}
static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val)
{
- DEBUG_PRINT(("RTL8139: RxBufPtr write val=0x%04x\n", val));
+ DPRINTF("RxBufPtr write val=0x%04x\n", val);
/* this value is off by 16 */
s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize);
- DEBUG_PRINT((" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
- s->RxBufferSize, s->RxBufAddr, s->RxBufPtr));
+ DPRINTF(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
+ s->RxBufferSize, s->RxBufAddr, s->RxBufPtr);
}
static uint32_t rtl8139_RxBufPtr_read(RTL8139State *s)
@@ -2544,7 +2573,7 @@ static uint32_t rtl8139_RxBufPtr_read(RTL8139State *s)
/* this value is off by 16 */
uint32_t ret = s->RxBufPtr - 0x10;
- DEBUG_PRINT(("RTL8139: RxBufPtr read val=0x%04x\n", ret));
+ DPRINTF("RxBufPtr read val=0x%04x\n", ret);
return ret;
}
@@ -2554,14 +2583,14 @@ static uint32_t rtl8139_RxBufAddr_read(RTL8139State *s)
/* this value is NOT off by 16 */
uint32_t ret = s->RxBufAddr;
- DEBUG_PRINT(("RTL8139: RxBufAddr read val=0x%04x\n", ret));
+ DPRINTF("RxBufAddr read val=0x%04x\n", ret);
return ret;
}
static void rtl8139_RxBuf_write(RTL8139State *s, uint32_t val)
{
- DEBUG_PRINT(("RTL8139: RxBuf write val=0x%08x\n", val));
+ DPRINTF("RxBuf write val=0x%08x\n", val);
s->RxBuf = val;
@@ -2572,14 +2601,14 @@ static uint32_t rtl8139_RxBuf_read(RTL8139State *s)
{
uint32_t ret = s->RxBuf;
- DEBUG_PRINT(("RTL8139: RxBuf read val=0x%08x\n", ret));
+ DPRINTF("RxBuf read val=0x%08x\n", ret);
return ret;
}
static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val)
{
- DEBUG_PRINT(("RTL8139: IntrMask write(w) val=0x%04x\n", val));
+ DPRINTF("IntrMask write(w) val=0x%04x\n", val);
/* mask unwriteable bits */
val = SET_MASKED(val, 0x1e00, s->IntrMask);
@@ -2595,14 +2624,14 @@ static uint32_t rtl8139_IntrMask_read(RTL8139State *s)
{
uint32_t ret = s->IntrMask;
- DEBUG_PRINT(("RTL8139: IntrMask read(w) val=0x%04x\n", ret));
+ DPRINTF("IntrMask read(w) val=0x%04x\n", ret);
return ret;
}
static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val)
{
- DEBUG_PRINT(("RTL8139: IntrStatus write(w) val=0x%04x\n", val));
+ DPRINTF("IntrStatus write(w) val=0x%04x\n", val);
#if 0
@@ -2639,7 +2668,7 @@ static uint32_t rtl8139_IntrStatus_read(RTL8139State *s)
uint32_t ret = s->IntrStatus;
- DEBUG_PRINT(("RTL8139: IntrStatus read(w) val=0x%04x\n", ret));
+ DPRINTF("IntrStatus read(w) val=0x%04x\n", ret);
#if 0
@@ -2655,7 +2684,7 @@ static uint32_t rtl8139_IntrStatus_read(RTL8139State *s)
static void rtl8139_MultiIntr_write(RTL8139State *s, uint32_t val)
{
- DEBUG_PRINT(("RTL8139: MultiIntr write(w) val=0x%04x\n", val));
+ DPRINTF("MultiIntr write(w) val=0x%04x\n", val);
/* mask unwriteable bits */
val = SET_MASKED(val, 0xf000, s->MultiIntr);
@@ -2667,7 +2696,7 @@ static uint32_t rtl8139_MultiIntr_read(RTL8139State *s)
{
uint32_t ret = s->MultiIntr;
- DEBUG_PRINT(("RTL8139: MultiIntr read(w) val=0x%04x\n", ret));
+ DPRINTF("MultiIntr read(w) val=0x%04x\n", ret);
return ret;
}
@@ -2715,11 +2744,12 @@ static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val)
break;
case MediaStatus:
/* ignore */
- DEBUG_PRINT(("RTL8139: not implemented write(b) to MediaStatus val=0x%02x\n", val));
+ DPRINTF("not implemented write(b) to MediaStatus val=0x%02x\n",
+ val);
break;
case HltClk:
- DEBUG_PRINT(("RTL8139: HltClk write val=0x%08x\n", val));
+ DPRINTF("HltClk write val=0x%08x\n", val);
if (val == 'R')
{
s->clock_enabled = 1;
@@ -2731,27 +2761,29 @@ static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val)
break;
case TxThresh:
- DEBUG_PRINT(("RTL8139C+ TxThresh write(b) val=0x%02x\n", val));
+ DPRINTF("C+ TxThresh write(b) val=0x%02x\n", val);
s->TxThresh = val;
break;
case TxPoll:
- DEBUG_PRINT(("RTL8139C+ TxPoll write(b) val=0x%02x\n", val));
+ DPRINTF("C+ TxPoll write(b) val=0x%02x\n", val);
if (val & (1 << 7))
{
- DEBUG_PRINT(("RTL8139C+ TxPoll high priority transmission (not implemented)\n"));
+ DPRINTF("C+ TxPoll high priority transmission (not "
+ "implemented)\n");
//rtl8139_cplus_transmit(s);
}
if (val & (1 << 6))
{
- DEBUG_PRINT(("RTL8139C+ TxPoll normal priority transmission\n"));
+ DPRINTF("C+ TxPoll normal priority transmission\n");
rtl8139_cplus_transmit(s);
}
break;
default:
- DEBUG_PRINT(("RTL8139: not implemented write(b) addr=0x%x val=0x%02x\n", addr, val));
+ DPRINTF("not implemented write(b) addr=0x%x val=0x%02x\n", addr,
+ val);
break;
}
}
@@ -2787,14 +2819,14 @@ static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val)
rtl8139_BasicModeStatus_write(s, val);
break;
case NWayAdvert:
- DEBUG_PRINT(("RTL8139: NWayAdvert write(w) val=0x%04x\n", val));
+ DPRINTF("NWayAdvert write(w) val=0x%04x\n", val);
s->NWayAdvert = val;
break;
case NWayLPAR:
- DEBUG_PRINT(("RTL8139: forbidden NWayLPAR write(w) val=0x%04x\n", val));
+ DPRINTF("forbidden NWayLPAR write(w) val=0x%04x\n", val);
break;
case NWayExpansion:
- DEBUG_PRINT(("RTL8139: NWayExpansion write(w) val=0x%04x\n", val));
+ DPRINTF("NWayExpansion write(w) val=0x%04x\n", val);
s->NWayExpansion = val;
break;
@@ -2807,7 +2839,8 @@ static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val)
break;
default:
- DEBUG_PRINT(("RTL8139: ioport write(w) addr=0x%x val=0x%04x via write(b)\n", addr, val));
+ DPRINTF("ioport write(w) addr=0x%x val=0x%04x via write(b)\n",
+ addr, val);
rtl8139_io_writeb(opaque, addr, val & 0xff);
rtl8139_io_writeb(opaque, addr + 1, (val >> 8) & 0xff);
@@ -2820,7 +2853,7 @@ static void rtl8139_set_next_tctr_time(RTL8139State *s, int64_t current_time)
int64_t pci_time, next_time;
uint32_t low_pci;
- DEBUG_PRINT(("RTL8139: entered rtl8139_set_next_tctr_time\n"));
+ DPRINTF("entered rtl8139_set_next_tctr_time\n");
if (s->TimerExpire && current_time >= s->TimerExpire) {
s->IntrStatus |= PCSTimeout;
@@ -2864,7 +2897,7 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
switch (addr)
{
case RxMissed:
- DEBUG_PRINT(("RTL8139: RxMissed clearing on write\n"));
+ DPRINTF("RxMissed clearing on write\n");
s->RxMissed = 0;
break;
@@ -2889,23 +2922,23 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
break;
case RxRingAddrLO:
- DEBUG_PRINT(("RTL8139: C+ RxRing low bits write val=0x%08x\n", val));
+ DPRINTF("C+ RxRing low bits write val=0x%08x\n", val);
s->RxRingAddrLO = val;
break;
case RxRingAddrHI:
- DEBUG_PRINT(("RTL8139: C+ RxRing high bits write val=0x%08x\n", val));
+ DPRINTF("C+ RxRing high bits write val=0x%08x\n", val);
s->RxRingAddrHI = val;
break;
case Timer:
- DEBUG_PRINT(("RTL8139: TCTR Timer reset on write\n"));
+ DPRINTF("TCTR Timer reset on write\n");
s->TCTR_base = qemu_get_clock_ns(vm_clock);
rtl8139_set_next_tctr_time(s, s->TCTR_base);
break;
case FlashReg:
- DEBUG_PRINT(("RTL8139: FlashReg TimerInt write val=0x%08x\n", val));
+ DPRINTF("FlashReg TimerInt write val=0x%08x\n", val);
if (s->TimerInt != val) {
s->TimerInt = val;
rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
@@ -2913,7 +2946,8 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
break;
default:
- DEBUG_PRINT(("RTL8139: ioport write(l) addr=0x%x val=0x%08x via write(b)\n", addr, val));
+ DPRINTF("ioport write(l) addr=0x%x val=0x%08x via write(b)\n",
+ addr, val);
rtl8139_io_writeb(opaque, addr, val & 0xff);
rtl8139_io_writeb(opaque, addr + 1, (val >> 8) & 0xff);
rtl8139_io_writeb(opaque, addr + 2, (val >> 16) & 0xff);
@@ -2964,31 +2998,31 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr)
case MediaStatus:
ret = 0xd0;
- DEBUG_PRINT(("RTL8139: MediaStatus read 0x%x\n", ret));
+ DPRINTF("MediaStatus read 0x%x\n", ret);
break;
case HltClk:
ret = s->clock_enabled;
- DEBUG_PRINT(("RTL8139: HltClk read 0x%x\n", ret));
+ DPRINTF("HltClk read 0x%x\n", ret);
break;
case PCIRevisionID:
ret = RTL8139_PCI_REVID;
- DEBUG_PRINT(("RTL8139: PCI Revision ID read 0x%x\n", ret));
+ DPRINTF("PCI Revision ID read 0x%x\n", ret);
break;
case TxThresh:
ret = s->TxThresh;
- DEBUG_PRINT(("RTL8139C+ TxThresh read(b) val=0x%02x\n", ret));
+ DPRINTF("C+ TxThresh read(b) val=0x%02x\n", ret);
break;
case 0x43: /* Part of TxConfig register. Windows driver tries to read it */
ret = s->TxConfig >> 24;
- DEBUG_PRINT(("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret));
+ DPRINTF("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret);
break;
default:
- DEBUG_PRINT(("RTL8139: not implemented read(b) addr=0x%x\n", addr));
+ DPRINTF("not implemented read(b) addr=0x%x\n", addr);
ret = 0;
break;
}
@@ -3033,15 +3067,15 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr)
break;
case NWayAdvert:
ret = s->NWayAdvert;
- DEBUG_PRINT(("RTL8139: NWayAdvert read(w) val=0x%04x\n", ret));
+ DPRINTF("NWayAdvert read(w) val=0x%04x\n", ret);
break;
case NWayLPAR:
ret = s->NWayLPAR;
- DEBUG_PRINT(("RTL8139: NWayLPAR read(w) val=0x%04x\n", ret));
+ DPRINTF("NWayLPAR read(w) val=0x%04x\n", ret);
break;
case NWayExpansion:
ret = s->NWayExpansion;
- DEBUG_PRINT(("RTL8139: NWayExpansion read(w) val=0x%04x\n", ret));
+ DPRINTF("NWayExpansion read(w) val=0x%04x\n", ret);
break;
case CpCmd:
@@ -3061,12 +3095,12 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr)
break;
default:
- DEBUG_PRINT(("RTL8139: ioport read(w) addr=0x%x via read(b)\n", addr));
+ DPRINTF("ioport read(w) addr=0x%x via read(b)\n", addr);
ret = rtl8139_io_readb(opaque, addr);
ret |= rtl8139_io_readb(opaque, addr + 1) << 8;
- DEBUG_PRINT(("RTL8139: ioport read(w) addr=0x%x val=0x%04x\n", addr, ret));
+ DPRINTF("ioport read(w) addr=0x%x val=0x%04x\n", addr, ret);
break;
}
@@ -3085,7 +3119,7 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
case RxMissed:
ret = s->RxMissed;
- DEBUG_PRINT(("RTL8139: RxMissed read val=0x%08x\n", ret));
+ DPRINTF("RxMissed read val=0x%08x\n", ret);
break;
case TxConfig:
@@ -3110,34 +3144,34 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
case RxRingAddrLO:
ret = s->RxRingAddrLO;
- DEBUG_PRINT(("RTL8139: C+ RxRing low bits read val=0x%08x\n", ret));
+ DPRINTF("C+ RxRing low bits read val=0x%08x\n", ret);
break;
case RxRingAddrHI:
ret = s->RxRingAddrHI;
- DEBUG_PRINT(("RTL8139: C+ RxRing high bits read val=0x%08x\n", ret));
+ DPRINTF("C+ RxRing high bits read val=0x%08x\n", ret);
break;
case Timer:
ret = muldiv64(qemu_get_clock_ns(vm_clock) - s->TCTR_base,
PCI_FREQUENCY, get_ticks_per_sec());
- DEBUG_PRINT(("RTL8139: TCTR Timer read val=0x%08x\n", ret));
+ DPRINTF("TCTR Timer read val=0x%08x\n", ret);
break;
case FlashReg:
ret = s->TimerInt;
- DEBUG_PRINT(("RTL8139: FlashReg TimerInt read val=0x%08x\n", ret));
+ DPRINTF("FlashReg TimerInt read val=0x%08x\n", ret);
break;
default:
- DEBUG_PRINT(("RTL8139: ioport read(l) addr=0x%x via read(b)\n", addr));
+ DPRINTF("ioport read(l) addr=0x%x via read(b)\n", addr);
ret = rtl8139_io_readb(opaque, addr);
ret |= rtl8139_io_readb(opaque, addr + 1) << 8;
ret |= rtl8139_io_readb(opaque, addr + 2) << 16;
ret |= rtl8139_io_readb(opaque, addr + 3) << 24;
- DEBUG_PRINT(("RTL8139: read(l) addr=0x%x val=%08x\n", addr, ret));
+ DPRINTF("read(l) addr=0x%x val=%08x\n", addr, ret);
break;
}
@@ -3382,7 +3416,7 @@ static void rtl8139_timer(void *opaque)
if (!s->clock_enabled)
{
- DEBUG_PRINT(("RTL8139: >>> timer: clock is not running\n"));
+ DPRINTF(">>> timer: clock is not running\n");
return;
}
@@ -3484,7 +3518,7 @@ static PCIDeviceInfo rtl8139_info = {
.qdev.vmsd = &vmstate_rtl8139,
.init = pci_rtl8139_init,
.exit = pci_rtl8139_uninit,
- .romfile = "pxe-rtl8139.bin",
+ .romfile = "pxe-rtl8139.rom",
.qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(RTL8139State, conf),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 175e5cb3a..bb49e393e 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -43,6 +43,8 @@
do { } while (0)
#endif
+#define VIRTIO_EXT_CODE 0x2603
+
struct BusInfo s390_virtio_bus_info = {
.name = "s390-virtio",
.size = sizeof(VirtIOS390Bus),
@@ -305,9 +307,13 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
{
VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
uint64_t token = s390_virtio_device_vq_token(dev, vector);
+ CPUState *env = s390_cpu_addr2state(0);
- /* XXX kvm dependency! */
- kvm_s390_virtio_irq(s390_cpu_addr2state(0), 0, token);
+ if (kvm_enabled()) {
+ kvm_s390_virtio_irq(env, 0, token);
+ } else {
+ cpu_inject_ext(env, VIRTIO_EXT_CODE, 0, token);
+ }
}
static unsigned virtio_s390_get_features(void *opaque)
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index d429f10d5..698ff6f34 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -82,13 +82,12 @@ CPUState *s390_cpu_addr2state(uint16_t cpu_addr)
return ipi_states[cpu_addr];
}
-int s390_virtio_hypercall(CPUState *env)
+int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall)
{
int r = 0, i;
- target_ulong mem = env->regs[2];
- dprintf("KVM hypercall: %ld\n", env->regs[1]);
- switch (env->regs[1]) {
+ dprintf("KVM hypercall: %ld\n", hypercall);
+ switch (hypercall) {
case KVM_S390_VIRTIO_NOTIFY:
if (mem > ram_size) {
VirtIOS390Device *dev = s390_virtio_bus_find_vring(s390_bus,
@@ -128,8 +127,7 @@ int s390_virtio_hypercall(CPUState *env)
break;
}
- env->regs[2] = r;
- return 0;
+ return r;
}
/* PC hardware initialisation */
@@ -145,14 +143,9 @@ static void s390_init(ram_addr_t ram_size,
ram_addr_t kernel_size = 0;
ram_addr_t initrd_offset;
ram_addr_t initrd_size = 0;
+ uint8_t *storage_keys;
int i;
- /* XXX we only work on KVM for now */
-
- if (!kvm_enabled()) {
- fprintf(stderr, "The S390 target only works with KVM enabled\n");
- exit(1);
- }
/* get a BUS */
s390_bus = s390_virtio_bus_init(&ram_size);
@@ -161,6 +154,9 @@ static void s390_init(ram_addr_t ram_size,
ram_addr = qemu_ram_alloc(NULL, "s390.ram", ram_size);
cpu_register_physical_memory(0, ram_size, ram_addr);
+ /* allocate storage keys */
+ storage_keys = qemu_mallocz(ram_size / TARGET_PAGE_SIZE);
+
/* init CPUs */
if (cpu_model == NULL) {
cpu_model = "host";
@@ -178,6 +174,7 @@ static void s390_init(ram_addr_t ram_size,
ipi_states[i] = tmp_env;
tmp_env->halted = 1;
tmp_env->exception_index = EXCP_HLT;
+ tmp_env->storage_keys = storage_keys;
}
env->halted = 0;
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 0d5292688..ac9fcc1f3 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -14,7 +14,6 @@
#include "qemu-timer.h"
#include "i2c.h"
#include "net.h"
-#include "sysemu.h"
#include "boards.h"
#define GPIO_A 0
@@ -280,64 +279,28 @@ static CPUWriteMemoryFunc * const gptm_writefn[] = {
gptm_write
};
-static void gptm_save(QEMUFile *f, void *opaque)
-{
- gptm_state *s = (gptm_state *)opaque;
-
- qemu_put_be32(f, s->config);
- qemu_put_be32(f, s->mode[0]);
- qemu_put_be32(f, s->mode[1]);
- qemu_put_be32(f, s->control);
- qemu_put_be32(f, s->state);
- qemu_put_be32(f, s->mask);
- qemu_put_be32(f, s->mode[0]);
- qemu_put_be32(f, s->mode[0]);
- qemu_put_be32(f, s->load[0]);
- qemu_put_be32(f, s->load[1]);
- qemu_put_be32(f, s->match[0]);
- qemu_put_be32(f, s->match[1]);
- qemu_put_be32(f, s->prescale[0]);
- qemu_put_be32(f, s->prescale[1]);
- qemu_put_be32(f, s->match_prescale[0]);
- qemu_put_be32(f, s->match_prescale[1]);
- qemu_put_be32(f, s->rtc);
- qemu_put_be64(f, s->tick[0]);
- qemu_put_be64(f, s->tick[1]);
- qemu_put_timer(f, s->timer[0]);
- qemu_put_timer(f, s->timer[1]);
-}
-
-static int gptm_load(QEMUFile *f, void *opaque, int version_id)
-{
- gptm_state *s = (gptm_state *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->config = qemu_get_be32(f);
- s->mode[0] = qemu_get_be32(f);
- s->mode[1] = qemu_get_be32(f);
- s->control = qemu_get_be32(f);
- s->state = qemu_get_be32(f);
- s->mask = qemu_get_be32(f);
- s->mode[0] = qemu_get_be32(f);
- s->mode[0] = qemu_get_be32(f);
- s->load[0] = qemu_get_be32(f);
- s->load[1] = qemu_get_be32(f);
- s->match[0] = qemu_get_be32(f);
- s->match[1] = qemu_get_be32(f);
- s->prescale[0] = qemu_get_be32(f);
- s->prescale[1] = qemu_get_be32(f);
- s->match_prescale[0] = qemu_get_be32(f);
- s->match_prescale[1] = qemu_get_be32(f);
- s->rtc = qemu_get_be32(f);
- s->tick[0] = qemu_get_be64(f);
- s->tick[1] = qemu_get_be64(f);
- qemu_get_timer(f, s->timer[0]);
- qemu_get_timer(f, s->timer[1]);
-
- return 0;
-}
+static const VMStateDescription vmstate_stellaris_gptm = {
+ .name = "stellaris_gptm",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(config, gptm_state),
+ VMSTATE_UINT32_ARRAY(mode, gptm_state, 2),
+ VMSTATE_UINT32(control, gptm_state),
+ VMSTATE_UINT32(state, gptm_state),
+ VMSTATE_UINT32(mask, gptm_state),
+ VMSTATE_UNUSED(8),
+ VMSTATE_UINT32_ARRAY(load, gptm_state, 2),
+ VMSTATE_UINT32_ARRAY(match, gptm_state, 2),
+ VMSTATE_UINT32_ARRAY(prescale, gptm_state, 2),
+ VMSTATE_UINT32_ARRAY(match_prescale, gptm_state, 2),
+ VMSTATE_UINT32(rtc, gptm_state),
+ VMSTATE_INT64_ARRAY(tick, gptm_state, 2),
+ VMSTATE_TIMER_ARRAY(timer, gptm_state, 2),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int stellaris_gptm_init(SysBusDevice *dev)
{
@@ -355,8 +318,7 @@ static int stellaris_gptm_init(SysBusDevice *dev)
s->opaque[0] = s->opaque[1] = s;
s->timer[0] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[0]);
s->timer[1] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[1]);
- register_savevm(&dev->qdev, "stellaris_gptm", -1, 1,
- gptm_save, gptm_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_stellaris_gptm, s);
return 0;
}
@@ -605,58 +567,37 @@ static void ssys_reset(void *opaque)
s->dcgc[0] = 1;
}
-static void ssys_save(QEMUFile *f, void *opaque)
-{
- ssys_state *s = (ssys_state *)opaque;
-
- qemu_put_be32(f, s->pborctl);
- qemu_put_be32(f, s->ldopctl);
- qemu_put_be32(f, s->int_mask);
- qemu_put_be32(f, s->int_status);
- qemu_put_be32(f, s->resc);
- qemu_put_be32(f, s->rcc);
- qemu_put_be32(f, s->rcgc[0]);
- qemu_put_be32(f, s->rcgc[1]);
- qemu_put_be32(f, s->rcgc[2]);
- qemu_put_be32(f, s->scgc[0]);
- qemu_put_be32(f, s->scgc[1]);
- qemu_put_be32(f, s->scgc[2]);
- qemu_put_be32(f, s->dcgc[0]);
- qemu_put_be32(f, s->dcgc[1]);
- qemu_put_be32(f, s->dcgc[2]);
- qemu_put_be32(f, s->clkvclr);
- qemu_put_be32(f, s->ldoarst);
-}
-
-static int ssys_load(QEMUFile *f, void *opaque, int version_id)
+static int stellaris_sys_post_load(void *opaque, int version_id)
{
- ssys_state *s = (ssys_state *)opaque;
+ ssys_state *s = opaque;
- if (version_id != 1)
- return -EINVAL;
-
- s->pborctl = qemu_get_be32(f);
- s->ldopctl = qemu_get_be32(f);
- s->int_mask = qemu_get_be32(f);
- s->int_status = qemu_get_be32(f);
- s->resc = qemu_get_be32(f);
- s->rcc = qemu_get_be32(f);
- s->rcgc[0] = qemu_get_be32(f);
- s->rcgc[1] = qemu_get_be32(f);
- s->rcgc[2] = qemu_get_be32(f);
- s->scgc[0] = qemu_get_be32(f);
- s->scgc[1] = qemu_get_be32(f);
- s->scgc[2] = qemu_get_be32(f);
- s->dcgc[0] = qemu_get_be32(f);
- s->dcgc[1] = qemu_get_be32(f);
- s->dcgc[2] = qemu_get_be32(f);
- s->clkvclr = qemu_get_be32(f);
- s->ldoarst = qemu_get_be32(f);
ssys_calculate_system_clock(s);
return 0;
}
+static const VMStateDescription vmstate_stellaris_sys = {
+ .name = "stellaris_sys",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .post_load = stellaris_sys_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(pborctl, ssys_state),
+ VMSTATE_UINT32(ldopctl, ssys_state),
+ VMSTATE_UINT32(int_mask, ssys_state),
+ VMSTATE_UINT32(int_status, ssys_state),
+ VMSTATE_UINT32(resc, ssys_state),
+ VMSTATE_UINT32(rcc, ssys_state),
+ VMSTATE_UINT32_ARRAY(rcgc, ssys_state, 3),
+ VMSTATE_UINT32_ARRAY(scgc, ssys_state, 3),
+ VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3),
+ VMSTATE_UINT32(clkvclr, ssys_state),
+ VMSTATE_UINT32(ldoarst, ssys_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static int stellaris_sys_init(uint32_t base, qemu_irq irq,
stellaris_board_info * board,
uint8_t *macaddr)
@@ -676,7 +617,7 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(base, 0x00001000, iomemtype);
ssys_reset(s);
- register_savevm(NULL, "stellaris_sys", -1, 1, ssys_save, ssys_load, s);
+ vmstate_register(NULL, -1, &vmstate_stellaris_sys, s);
return 0;
}
@@ -844,36 +785,22 @@ static CPUWriteMemoryFunc * const stellaris_i2c_writefn[] = {
stellaris_i2c_write
};
-static void stellaris_i2c_save(QEMUFile *f, void *opaque)
-{
- stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
-
- qemu_put_be32(f, s->msa);
- qemu_put_be32(f, s->mcs);
- qemu_put_be32(f, s->mdr);
- qemu_put_be32(f, s->mtpr);
- qemu_put_be32(f, s->mimr);
- qemu_put_be32(f, s->mris);
- qemu_put_be32(f, s->mcr);
-}
-
-static int stellaris_i2c_load(QEMUFile *f, void *opaque, int version_id)
-{
- stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->msa = qemu_get_be32(f);
- s->mcs = qemu_get_be32(f);
- s->mdr = qemu_get_be32(f);
- s->mtpr = qemu_get_be32(f);
- s->mimr = qemu_get_be32(f);
- s->mris = qemu_get_be32(f);
- s->mcr = qemu_get_be32(f);
-
- return 0;
-}
+static const VMStateDescription vmstate_stellaris_i2c = {
+ .name = "stellaris_i2c",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(msa, stellaris_i2c_state),
+ VMSTATE_UINT32(mcs, stellaris_i2c_state),
+ VMSTATE_UINT32(mdr, stellaris_i2c_state),
+ VMSTATE_UINT32(mtpr, stellaris_i2c_state),
+ VMSTATE_UINT32(mimr, stellaris_i2c_state),
+ VMSTATE_UINT32(mris, stellaris_i2c_state),
+ VMSTATE_UINT32(mcr, stellaris_i2c_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int stellaris_i2c_init(SysBusDevice * dev)
{
@@ -891,8 +818,7 @@ static int stellaris_i2c_init(SysBusDevice * dev)
sysbus_init_mmio(dev, 0x1000, iomemtype);
/* ??? For now we only implement the master interface. */
stellaris_i2c_reset(s);
- register_savevm(&dev->qdev, "stellaris_i2c", -1, 1,
- stellaris_i2c_save, stellaris_i2c_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_stellaris_i2c, s);
return 0;
}
@@ -1130,60 +1056,40 @@ static CPUWriteMemoryFunc * const stellaris_adc_writefn[] = {
stellaris_adc_write
};
-static void stellaris_adc_save(QEMUFile *f, void *opaque)
-{
- stellaris_adc_state *s = (stellaris_adc_state *)opaque;
- int i;
- int j;
-
- qemu_put_be32(f, s->actss);
- qemu_put_be32(f, s->ris);
- qemu_put_be32(f, s->im);
- qemu_put_be32(f, s->emux);
- qemu_put_be32(f, s->ostat);
- qemu_put_be32(f, s->ustat);
- qemu_put_be32(f, s->sspri);
- qemu_put_be32(f, s->sac);
- for (i = 0; i < 4; i++) {
- qemu_put_be32(f, s->fifo[i].state);
- for (j = 0; j < 16; j++) {
- qemu_put_be32(f, s->fifo[i].data[j]);
- }
- qemu_put_be32(f, s->ssmux[i]);
- qemu_put_be32(f, s->ssctl[i]);
- }
- qemu_put_be32(f, s->noise);
-}
-
-static int stellaris_adc_load(QEMUFile *f, void *opaque, int version_id)
-{
- stellaris_adc_state *s = (stellaris_adc_state *)opaque;
- int i;
- int j;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->actss = qemu_get_be32(f);
- s->ris = qemu_get_be32(f);
- s->im = qemu_get_be32(f);
- s->emux = qemu_get_be32(f);
- s->ostat = qemu_get_be32(f);
- s->ustat = qemu_get_be32(f);
- s->sspri = qemu_get_be32(f);
- s->sac = qemu_get_be32(f);
- for (i = 0; i < 4; i++) {
- s->fifo[i].state = qemu_get_be32(f);
- for (j = 0; j < 16; j++) {
- s->fifo[i].data[j] = qemu_get_be32(f);
- }
- s->ssmux[i] = qemu_get_be32(f);
- s->ssctl[i] = qemu_get_be32(f);
+static const VMStateDescription vmstate_stellaris_adc = {
+ .name = "stellaris_adc",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(actss, stellaris_adc_state),
+ VMSTATE_UINT32(ris, stellaris_adc_state),
+ VMSTATE_UINT32(im, stellaris_adc_state),
+ VMSTATE_UINT32(emux, stellaris_adc_state),
+ VMSTATE_UINT32(ostat, stellaris_adc_state),
+ VMSTATE_UINT32(ustat, stellaris_adc_state),
+ VMSTATE_UINT32(sspri, stellaris_adc_state),
+ VMSTATE_UINT32(sac, stellaris_adc_state),
+ VMSTATE_UINT32(fifo[0].state, stellaris_adc_state),
+ VMSTATE_UINT32_ARRAY(fifo[0].data, stellaris_adc_state, 16),
+ VMSTATE_UINT32(ssmux[0], stellaris_adc_state),
+ VMSTATE_UINT32(ssctl[0], stellaris_adc_state),
+ VMSTATE_UINT32(fifo[1].state, stellaris_adc_state),
+ VMSTATE_UINT32_ARRAY(fifo[1].data, stellaris_adc_state, 16),
+ VMSTATE_UINT32(ssmux[1], stellaris_adc_state),
+ VMSTATE_UINT32(ssctl[1], stellaris_adc_state),
+ VMSTATE_UINT32(fifo[2].state, stellaris_adc_state),
+ VMSTATE_UINT32_ARRAY(fifo[2].data, stellaris_adc_state, 16),
+ VMSTATE_UINT32(ssmux[2], stellaris_adc_state),
+ VMSTATE_UINT32(ssctl[2], stellaris_adc_state),
+ VMSTATE_UINT32(fifo[3].state, stellaris_adc_state),
+ VMSTATE_UINT32_ARRAY(fifo[3].data, stellaris_adc_state, 16),
+ VMSTATE_UINT32(ssmux[3], stellaris_adc_state),
+ VMSTATE_UINT32(ssctl[3], stellaris_adc_state),
+ VMSTATE_UINT32(noise, stellaris_adc_state),
+ VMSTATE_END_OF_LIST()
}
- s->noise = qemu_get_be32(f);
-
- return 0;
-}
+};
static int stellaris_adc_init(SysBusDevice *dev)
{
@@ -1201,8 +1107,7 @@ static int stellaris_adc_init(SysBusDevice *dev)
sysbus_init_mmio(dev, 0x1000, iomemtype);
stellaris_adc_reset(s);
qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
- register_savevm(&dev->qdev, "stellaris_adc", -1, 1,
- stellaris_adc_save, stellaris_adc_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_stellaris_adc, s);
return 0;
}
@@ -1234,24 +1139,16 @@ static uint32_t stellaris_ssi_bus_transfer(SSISlave *dev, uint32_t val)
return ssi_transfer(s->bus[s->current_dev], val);
}
-static void stellaris_ssi_bus_save(QEMUFile *f, void *opaque)
-{
- stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
-
- qemu_put_be32(f, s->current_dev);
-}
-
-static int stellaris_ssi_bus_load(QEMUFile *f, void *opaque, int version_id)
-{
- stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->current_dev = qemu_get_be32(f);
-
- return 0;
-}
+static const VMStateDescription vmstate_stellaris_ssi_bus = {
+ .name = "stellaris_ssi_bus",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(current_dev, stellaris_ssi_bus_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int stellaris_ssi_bus_init(SSISlave *dev)
{
@@ -1261,8 +1158,7 @@ static int stellaris_ssi_bus_init(SSISlave *dev)
s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
qdev_init_gpio_in(&dev->qdev, stellaris_ssi_bus_select, 1);
- register_savevm(&dev->qdev, "stellaris_ssi_bus", -1, 1,
- stellaris_ssi_bus_save, stellaris_ssi_bus_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_stellaris_ssi_bus, s);
return 0;
}
diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c
index 16aae96f2..06c5f9d95 100644
--- a/hw/stellaris_input.c
+++ b/hw/stellaris_input.c
@@ -13,7 +13,7 @@
typedef struct {
qemu_irq irq;
int keycode;
- int pressed;
+ uint8_t pressed;
} gamepad_button;
typedef struct {
@@ -47,30 +47,29 @@ static void stellaris_gamepad_put_key(void * opaque, int keycode)
s->extension = 0;
}
-static void stellaris_gamepad_save(QEMUFile *f, void *opaque)
-{
- gamepad_state *s = (gamepad_state *)opaque;
- int i;
-
- qemu_put_be32(f, s->extension);
- for (i = 0; i < s->num_buttons; i++)
- qemu_put_byte(f, s->buttons[i].pressed);
-}
-
-static int stellaris_gamepad_load(QEMUFile *f, void *opaque, int version_id)
-{
- gamepad_state *s = (gamepad_state *)opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->extension = qemu_get_be32(f);
- for (i = 0; i < s->num_buttons; i++)
- s->buttons[i].pressed = qemu_get_byte(f);
+static const VMStateDescription vmstate_stellaris_button = {
+ .name = "stellaris_button",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(pressed, gamepad_button),
+ VMSTATE_END_OF_LIST()
+ }
+};
- return 0;
-}
+static const VMStateDescription vmstate_stellaris_gamepad = {
+ .name = "stellaris_gamepad",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(extension, gamepad_state),
+ VMSTATE_STRUCT_VARRAY_INT32(buttons, gamepad_state, num_buttons, 0,
+ vmstate_stellaris_button, gamepad_button),
+ VMSTATE_END_OF_LIST()
+ }
+};
/* Returns an array 5 ouput slots. */
void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
@@ -86,6 +85,5 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
}
s->num_buttons = n;
qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s);
- register_savevm(NULL, "stellaris_gamepad", -1, 1,
- stellaris_gamepad_save, stellaris_gamepad_load, s);
+ vmstate_register(NULL, -1, &vmstate_stellaris_gamepad, s);
}
diff --git a/hw/strongarm.c b/hw/strongarm.c
new file mode 100644
index 000000000..de08bdf67
--- /dev/null
+++ b/hw/strongarm.c
@@ -0,0 +1,1598 @@
+/*
+ * StrongARM SA-1100/SA-1110 emulation
+ *
+ * Copyright (C) 2011 Dmitry Eremin-Solenikov
+ *
+ * Largely based on StrongARM emulation:
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * UART code based on QEMU 16550A UART emulation
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2008 Citrix Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "sysbus.h"
+#include "strongarm.h"
+#include "qemu-error.h"
+#include "arm-misc.h"
+#include "sysemu.h"
+#include "ssi.h"
+
+//#define DEBUG
+
+/*
+ TODO
+ - Implement cp15, c14 ?
+ - Implement cp15, c15 !!! (idle used in L)
+ - Implement idle mode handling/DIM
+ - Implement sleep mode/Wake sources
+ - Implement reset control
+ - Implement memory control regs
+ - PCMCIA handling
+ - Maybe support MBGNT/MBREQ
+ - DMA channels
+ - GPCLK
+ - IrDA
+ - MCP
+ - Enhance UART with modem signals
+ */
+
+#ifdef DEBUG
+# define DPRINTF(format, ...) printf(format , ## __VA_ARGS__)
+#else
+# define DPRINTF(format, ...) do { } while (0)
+#endif
+
+static struct {
+ target_phys_addr_t io_base;
+ int irq;
+} sa_serial[] = {
+ { 0x80010000, SA_PIC_UART1 },
+ { 0x80030000, SA_PIC_UART2 },
+ { 0x80050000, SA_PIC_UART3 },
+ { 0, 0 }
+};
+
+/* Interrupt Controller */
+typedef struct {
+ SysBusDevice busdev;
+ qemu_irq irq;
+ qemu_irq fiq;
+
+ uint32_t pending;
+ uint32_t enabled;
+ uint32_t is_fiq;
+ uint32_t int_idle;
+} StrongARMPICState;
+
+#define ICIP 0x00
+#define ICMR 0x04
+#define ICLR 0x08
+#define ICFP 0x10
+#define ICPR 0x20
+#define ICCR 0x0c
+
+#define SA_PIC_SRCS 32
+
+
+static void strongarm_pic_update(void *opaque)
+{
+ StrongARMPICState *s = opaque;
+
+ /* FIXME: reflect DIM */
+ qemu_set_irq(s->fiq, s->pending & s->enabled & s->is_fiq);
+ qemu_set_irq(s->irq, s->pending & s->enabled & ~s->is_fiq);
+}
+
+static void strongarm_pic_set_irq(void *opaque, int irq, int level)
+{
+ StrongARMPICState *s = opaque;
+
+ if (level) {
+ s->pending |= 1 << irq;
+ } else {
+ s->pending &= ~(1 << irq);
+ }
+
+ strongarm_pic_update(s);
+}
+
+static uint32_t strongarm_pic_mem_read(void *opaque, target_phys_addr_t offset)
+{
+ StrongARMPICState *s = opaque;
+
+ switch (offset) {
+ case ICIP:
+ return s->pending & ~s->is_fiq & s->enabled;
+ case ICMR:
+ return s->enabled;
+ case ICLR:
+ return s->is_fiq;
+ case ICCR:
+ return s->int_idle == 0;
+ case ICFP:
+ return s->pending & s->is_fiq & s->enabled;
+ case ICPR:
+ return s->pending;
+ default:
+ printf("%s: Bad register offset 0x" TARGET_FMT_plx "\n",
+ __func__, offset);
+ return 0;
+ }
+}
+
+static void strongarm_pic_mem_write(void *opaque, target_phys_addr_t offset,
+ uint32_t value)
+{
+ StrongARMPICState *s = opaque;
+
+ switch (offset) {
+ case ICMR:
+ s->enabled = value;
+ break;
+ case ICLR:
+ s->is_fiq = value;
+ break;
+ case ICCR:
+ s->int_idle = (value & 1) ? 0 : ~0;
+ break;
+ default:
+ printf("%s: Bad register offset 0x" TARGET_FMT_plx "\n",
+ __func__, offset);
+ break;
+ }
+ strongarm_pic_update(s);
+}
+
+static CPUReadMemoryFunc * const strongarm_pic_readfn[] = {
+ strongarm_pic_mem_read,
+ strongarm_pic_mem_read,
+ strongarm_pic_mem_read,
+};
+
+static CPUWriteMemoryFunc * const strongarm_pic_writefn[] = {
+ strongarm_pic_mem_write,
+ strongarm_pic_mem_write,
+ strongarm_pic_mem_write,
+};
+
+static int strongarm_pic_initfn(SysBusDevice *dev)
+{
+ StrongARMPICState *s = FROM_SYSBUS(StrongARMPICState, dev);
+ int iomemtype;
+
+ qdev_init_gpio_in(&dev->qdev, strongarm_pic_set_irq, SA_PIC_SRCS);
+ iomemtype = cpu_register_io_memory(strongarm_pic_readfn,
+ strongarm_pic_writefn, s, DEVICE_NATIVE_ENDIAN);
+ sysbus_init_mmio(dev, 0x1000, iomemtype);
+ sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(dev, &s->fiq);
+
+ return 0;
+}
+
+static int strongarm_pic_post_load(void *opaque, int version_id)
+{
+ strongarm_pic_update(opaque);
+ return 0;
+}
+
+static VMStateDescription vmstate_strongarm_pic_regs = {
+ .name = "strongarm_pic",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = strongarm_pic_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(pending, StrongARMPICState),
+ VMSTATE_UINT32(enabled, StrongARMPICState),
+ VMSTATE_UINT32(is_fiq, StrongARMPICState),
+ VMSTATE_UINT32(int_idle, StrongARMPICState),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo strongarm_pic_info = {
+ .init = strongarm_pic_initfn,
+ .qdev.name = "strongarm_pic",
+ .qdev.desc = "StrongARM PIC",
+ .qdev.size = sizeof(StrongARMPICState),
+ .qdev.vmsd = &vmstate_strongarm_pic_regs,
+};
+
+/* Real-Time Clock */
+#define RTAR 0x00 /* RTC Alarm register */
+#define RCNR 0x04 /* RTC Counter register */
+#define RTTR 0x08 /* RTC Timer Trim register */
+#define RTSR 0x10 /* RTC Status register */
+
+#define RTSR_AL (1 << 0) /* RTC Alarm detected */
+#define RTSR_HZ (1 << 1) /* RTC 1Hz detected */
+#define RTSR_ALE (1 << 2) /* RTC Alarm enable */
+#define RTSR_HZE (1 << 3) /* RTC 1Hz enable */
+
+/* 16 LSB of RTTR are clockdiv for internal trim logic,
+ * trim delete isn't emulated, so
+ * f = 32 768 / (RTTR_trim + 1) */
+
+typedef struct {
+ SysBusDevice busdev;
+ uint32_t rttr;
+ uint32_t rtsr;
+ uint32_t rtar;
+ uint32_t last_rcnr;
+ int64_t last_hz;
+ QEMUTimer *rtc_alarm;
+ QEMUTimer *rtc_hz;
+ qemu_irq rtc_irq;
+ qemu_irq rtc_hz_irq;
+} StrongARMRTCState;
+
+static inline void strongarm_rtc_int_update(StrongARMRTCState *s)
+{
+ qemu_set_irq(s->rtc_irq, s->rtsr & RTSR_AL);
+ qemu_set_irq(s->rtc_hz_irq, s->rtsr & RTSR_HZ);
+}
+
+static void strongarm_rtc_hzupdate(StrongARMRTCState *s)
+{
+ int64_t rt = qemu_get_clock_ms(rt_clock);
+ s->last_rcnr += ((rt - s->last_hz) << 15) /
+ (1000 * ((s->rttr & 0xffff) + 1));
+ s->last_hz = rt;
+}
+
+static inline void strongarm_rtc_timer_update(StrongARMRTCState *s)
+{
+ if ((s->rtsr & RTSR_HZE) && !(s->rtsr & RTSR_HZ)) {
+ qemu_mod_timer(s->rtc_hz, s->last_hz + 1000);
+ } else {
+ qemu_del_timer(s->rtc_hz);
+ }
+
+ if ((s->rtsr & RTSR_ALE) && !(s->rtsr & RTSR_AL)) {
+ qemu_mod_timer(s->rtc_alarm, s->last_hz +
+ (((s->rtar - s->last_rcnr) * 1000 *
+ ((s->rttr & 0xffff) + 1)) >> 15));
+ } else {
+ qemu_del_timer(s->rtc_alarm);
+ }
+}
+
+static inline void strongarm_rtc_alarm_tick(void *opaque)
+{
+ StrongARMRTCState *s = opaque;
+ s->rtsr |= RTSR_AL;
+ strongarm_rtc_timer_update(s);
+ strongarm_rtc_int_update(s);
+}
+
+static inline void strongarm_rtc_hz_tick(void *opaque)
+{
+ StrongARMRTCState *s = opaque;
+ s->rtsr |= RTSR_HZ;
+ strongarm_rtc_timer_update(s);
+ strongarm_rtc_int_update(s);
+}
+
+static uint32_t strongarm_rtc_read(void *opaque, target_phys_addr_t addr)
+{
+ StrongARMRTCState *s = opaque;
+
+ switch (addr) {
+ case RTTR:
+ return s->rttr;
+ case RTSR:
+ return s->rtsr;
+ case RTAR:
+ return s->rtar;
+ case RCNR:
+ return s->last_rcnr +
+ ((qemu_get_clock_ms(rt_clock) - s->last_hz) << 15) /
+ (1000 * ((s->rttr & 0xffff) + 1));
+ default:
+ printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+ return 0;
+ }
+}
+
+static void strongarm_rtc_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ StrongARMRTCState *s = opaque;
+ uint32_t old_rtsr;
+
+ switch (addr) {
+ case RTTR:
+ strongarm_rtc_hzupdate(s);
+ s->rttr = value;
+ strongarm_rtc_timer_update(s);
+ break;
+
+ case RTSR:
+ old_rtsr = s->rtsr;
+ s->rtsr = (value & (RTSR_ALE | RTSR_HZE)) |
+ (s->rtsr & ~(value & (RTSR_AL | RTSR_HZ)));
+
+ if (s->rtsr != old_rtsr) {
+ strongarm_rtc_timer_update(s);
+ }
+
+ strongarm_rtc_int_update(s);
+ break;
+
+ case RTAR:
+ s->rtar = value;
+ strongarm_rtc_timer_update(s);
+ break;
+
+ case RCNR:
+ strongarm_rtc_hzupdate(s);
+ s->last_rcnr = value;
+ strongarm_rtc_timer_update(s);
+ break;
+
+ default:
+ printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+ }
+}
+
+static CPUReadMemoryFunc * const strongarm_rtc_readfn[] = {
+ strongarm_rtc_read,
+ strongarm_rtc_read,
+ strongarm_rtc_read,
+};
+
+static CPUWriteMemoryFunc * const strongarm_rtc_writefn[] = {
+ strongarm_rtc_write,
+ strongarm_rtc_write,
+ strongarm_rtc_write,
+};
+
+static int strongarm_rtc_init(SysBusDevice *dev)
+{
+ StrongARMRTCState *s = FROM_SYSBUS(StrongARMRTCState, dev);
+ struct tm tm;
+ int iomemtype;
+
+ s->rttr = 0x0;
+ s->rtsr = 0;
+
+ qemu_get_timedate(&tm, 0);
+
+ s->last_rcnr = (uint32_t) mktimegm(&tm);
+ s->last_hz = qemu_get_clock_ms(rt_clock);
+
+ s->rtc_alarm = qemu_new_timer_ms(rt_clock, strongarm_rtc_alarm_tick, s);
+ s->rtc_hz = qemu_new_timer_ms(rt_clock, strongarm_rtc_hz_tick, s);
+
+ sysbus_init_irq(dev, &s->rtc_irq);
+ sysbus_init_irq(dev, &s->rtc_hz_irq);
+
+ iomemtype = cpu_register_io_memory(strongarm_rtc_readfn,
+ strongarm_rtc_writefn, s, DEVICE_NATIVE_ENDIAN);
+ sysbus_init_mmio(dev, 0x10000, iomemtype);
+
+ return 0;
+}
+
+static void strongarm_rtc_pre_save(void *opaque)
+{
+ StrongARMRTCState *s = opaque;
+
+ strongarm_rtc_hzupdate(s);
+}
+
+static int strongarm_rtc_post_load(void *opaque, int version_id)
+{
+ StrongARMRTCState *s = opaque;
+
+ strongarm_rtc_timer_update(s);
+ strongarm_rtc_int_update(s);
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_strongarm_rtc_regs = {
+ .name = "strongarm-rtc",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .pre_save = strongarm_rtc_pre_save,
+ .post_load = strongarm_rtc_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(rttr, StrongARMRTCState),
+ VMSTATE_UINT32(rtsr, StrongARMRTCState),
+ VMSTATE_UINT32(rtar, StrongARMRTCState),
+ VMSTATE_UINT32(last_rcnr, StrongARMRTCState),
+ VMSTATE_INT64(last_hz, StrongARMRTCState),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo strongarm_rtc_sysbus_info = {
+ .init = strongarm_rtc_init,
+ .qdev.name = "strongarm-rtc",
+ .qdev.desc = "StrongARM RTC Controller",
+ .qdev.size = sizeof(StrongARMRTCState),
+ .qdev.vmsd = &vmstate_strongarm_rtc_regs,
+};
+
+/* GPIO */
+#define GPLR 0x00
+#define GPDR 0x04
+#define GPSR 0x08
+#define GPCR 0x0c
+#define GRER 0x10
+#define GFER 0x14
+#define GEDR 0x18
+#define GAFR 0x1c
+
+typedef struct StrongARMGPIOInfo StrongARMGPIOInfo;
+struct StrongARMGPIOInfo {
+ SysBusDevice busdev;
+ qemu_irq handler[28];
+ qemu_irq irqs[11];
+ qemu_irq irqX;
+
+ uint32_t ilevel;
+ uint32_t olevel;
+ uint32_t dir;
+ uint32_t rising;
+ uint32_t falling;
+ uint32_t status;
+ uint32_t gpsr;
+ uint32_t gafr;
+
+ uint32_t prev_level;
+};
+
+
+static void strongarm_gpio_irq_update(StrongARMGPIOInfo *s)
+{
+ int i;
+ for (i = 0; i < 11; i++) {
+ qemu_set_irq(s->irqs[i], s->status & (1 << i));
+ }
+
+ qemu_set_irq(s->irqX, (s->status & ~0x7ff));
+}
+
+static void strongarm_gpio_set(void *opaque, int line, int level)
+{
+ StrongARMGPIOInfo *s = opaque;
+ uint32_t mask;
+
+ mask = 1 << line;
+
+ if (level) {
+ s->status |= s->rising & mask &
+ ~s->ilevel & ~s->dir;
+ s->ilevel |= mask;
+ } else {
+ s->status |= s->falling & mask &
+ s->ilevel & ~s->dir;
+ s->ilevel &= ~mask;
+ }
+
+ if (s->status & mask) {
+ strongarm_gpio_irq_update(s);
+ }
+}
+
+static void strongarm_gpio_handler_update(StrongARMGPIOInfo *s)
+{
+ uint32_t level, diff;
+ int bit;
+
+ level = s->olevel & s->dir;
+
+ for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
+ bit = ffs(diff) - 1;
+ qemu_set_irq(s->handler[bit], (level >> bit) & 1);
+ }
+
+ s->prev_level = level;
+}
+
+static uint32_t strongarm_gpio_read(void *opaque, target_phys_addr_t offset)
+{
+ StrongARMGPIOInfo *s = opaque;
+
+ switch (offset) {
+ case GPDR: /* GPIO Pin-Direction registers */
+ return s->dir;
+
+ case GPSR: /* GPIO Pin-Output Set registers */
+ DPRINTF("%s: Read from a write-only register 0x" TARGET_FMT_plx "\n",
+ __func__, offset);
+ return s->gpsr; /* Return last written value. */
+
+ case GPCR: /* GPIO Pin-Output Clear registers */
+ DPRINTF("%s: Read from a write-only register 0x" TARGET_FMT_plx "\n",
+ __func__, offset);
+ return 31337; /* Specified as unpredictable in the docs. */
+
+ case GRER: /* GPIO Rising-Edge Detect Enable registers */
+ return s->rising;
+
+ case GFER: /* GPIO Falling-Edge Detect Enable registers */
+ return s->falling;
+
+ case GAFR: /* GPIO Alternate Function registers */
+ return s->gafr;
+
+ case GPLR: /* GPIO Pin-Level registers */
+ return (s->olevel & s->dir) |
+ (s->ilevel & ~s->dir);
+
+ case GEDR: /* GPIO Edge Detect Status registers */
+ return s->status;
+
+ default:
+ printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
+ }
+
+ return 0;
+}
+
+static void strongarm_gpio_write(void *opaque,
+ target_phys_addr_t offset, uint32_t value)
+{
+ StrongARMGPIOInfo *s = opaque;
+
+ switch (offset) {
+ case GPDR: /* GPIO Pin-Direction registers */
+ s->dir = value;
+ strongarm_gpio_handler_update(s);
+ break;
+
+ case GPSR: /* GPIO Pin-Output Set registers */
+ s->olevel |= value;
+ strongarm_gpio_handler_update(s);
+ s->gpsr = value;
+ break;
+
+ case GPCR: /* GPIO Pin-Output Clear registers */
+ s->olevel &= ~value;
+ strongarm_gpio_handler_update(s);
+ break;
+
+ case GRER: /* GPIO Rising-Edge Detect Enable registers */
+ s->rising = value;
+ break;
+
+ case GFER: /* GPIO Falling-Edge Detect Enable registers */
+ s->falling = value;
+ break;
+
+ case GAFR: /* GPIO Alternate Function registers */
+ s->gafr = value;
+ break;
+
+ case GEDR: /* GPIO Edge Detect Status registers */
+ s->status &= ~value;
+ strongarm_gpio_irq_update(s);
+ break;
+
+ default:
+ printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
+ }
+}
+
+static CPUReadMemoryFunc * const strongarm_gpio_readfn[] = {
+ strongarm_gpio_read,
+ strongarm_gpio_read,
+ strongarm_gpio_read
+};
+
+static CPUWriteMemoryFunc * const strongarm_gpio_writefn[] = {
+ strongarm_gpio_write,
+ strongarm_gpio_write,
+ strongarm_gpio_write
+};
+
+static DeviceState *strongarm_gpio_init(target_phys_addr_t base,
+ DeviceState *pic)
+{
+ DeviceState *dev;
+ int i;
+
+ dev = qdev_create(NULL, "strongarm-gpio");
+ qdev_init_nofail(dev);
+
+ sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+ for (i = 0; i < 12; i++)
+ sysbus_connect_irq(sysbus_from_qdev(dev), i,
+ qdev_get_gpio_in(pic, SA_PIC_GPIO0_EDGE + i));
+
+ return dev;
+}
+
+static int strongarm_gpio_initfn(SysBusDevice *dev)
+{
+ int iomemtype;
+ StrongARMGPIOInfo *s;
+ int i;
+
+ s = FROM_SYSBUS(StrongARMGPIOInfo, dev);
+
+ qdev_init_gpio_in(&dev->qdev, strongarm_gpio_set, 28);
+ qdev_init_gpio_out(&dev->qdev, s->handler, 28);
+
+ iomemtype = cpu_register_io_memory(strongarm_gpio_readfn,
+ strongarm_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
+
+ sysbus_init_mmio(dev, 0x1000, iomemtype);
+ for (i = 0; i < 11; i++) {
+ sysbus_init_irq(dev, &s->irqs[i]);
+ }
+ sysbus_init_irq(dev, &s->irqX);
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_strongarm_gpio_regs = {
+ .name = "strongarm-gpio",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(ilevel, StrongARMGPIOInfo),
+ VMSTATE_UINT32(olevel, StrongARMGPIOInfo),
+ VMSTATE_UINT32(dir, StrongARMGPIOInfo),
+ VMSTATE_UINT32(rising, StrongARMGPIOInfo),
+ VMSTATE_UINT32(falling, StrongARMGPIOInfo),
+ VMSTATE_UINT32(status, StrongARMGPIOInfo),
+ VMSTATE_UINT32(gafr, StrongARMGPIOInfo),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo strongarm_gpio_info = {
+ .init = strongarm_gpio_initfn,
+ .qdev.name = "strongarm-gpio",
+ .qdev.desc = "StrongARM GPIO controller",
+ .qdev.size = sizeof(StrongARMGPIOInfo),
+};
+
+/* Peripheral Pin Controller */
+#define PPDR 0x00
+#define PPSR 0x04
+#define PPAR 0x08
+#define PSDR 0x0c
+#define PPFR 0x10
+
+typedef struct StrongARMPPCInfo StrongARMPPCInfo;
+struct StrongARMPPCInfo {
+ SysBusDevice busdev;
+ qemu_irq handler[28];
+
+ uint32_t ilevel;
+ uint32_t olevel;
+ uint32_t dir;
+ uint32_t ppar;
+ uint32_t psdr;
+ uint32_t ppfr;
+
+ uint32_t prev_level;
+};
+
+static void strongarm_ppc_set(void *opaque, int line, int level)
+{
+ StrongARMPPCInfo *s = opaque;
+
+ if (level) {
+ s->ilevel |= 1 << line;
+ } else {
+ s->ilevel &= ~(1 << line);
+ }
+}
+
+static void strongarm_ppc_handler_update(StrongARMPPCInfo *s)
+{
+ uint32_t level, diff;
+ int bit;
+
+ level = s->olevel & s->dir;
+
+ for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
+ bit = ffs(diff) - 1;
+ qemu_set_irq(s->handler[bit], (level >> bit) & 1);
+ }
+
+ s->prev_level = level;
+}
+
+static uint32_t strongarm_ppc_read(void *opaque, target_phys_addr_t offset)
+{
+ StrongARMPPCInfo *s = opaque;
+
+ switch (offset) {
+ case PPDR: /* PPC Pin Direction registers */
+ return s->dir | ~0x3fffff;
+
+ case PPSR: /* PPC Pin State registers */
+ return (s->olevel & s->dir) |
+ (s->ilevel & ~s->dir) |
+ ~0x3fffff;
+
+ case PPAR:
+ return s->ppar | ~0x41000;
+
+ case PSDR:
+ return s->psdr;
+
+ case PPFR:
+ return s->ppfr | ~0x7f001;
+
+ default:
+ printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
+ }
+
+ return 0;
+}
+
+static void strongarm_ppc_write(void *opaque,
+ target_phys_addr_t offset, uint32_t value)
+{
+ StrongARMPPCInfo *s = opaque;
+
+ switch (offset) {
+ case PPDR: /* PPC Pin Direction registers */
+ s->dir = value & 0x3fffff;
+ strongarm_ppc_handler_update(s);
+ break;
+
+ case PPSR: /* PPC Pin State registers */
+ s->olevel = value & s->dir & 0x3fffff;
+ strongarm_ppc_handler_update(s);
+ break;
+
+ case PPAR:
+ s->ppar = value & 0x41000;
+ break;
+
+ case PSDR:
+ s->psdr = value & 0x3fffff;
+ break;
+
+ case PPFR:
+ s->ppfr = value & 0x7f001;
+ break;
+
+ default:
+ printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
+ }
+}
+
+static CPUReadMemoryFunc * const strongarm_ppc_readfn[] = {
+ strongarm_ppc_read,
+ strongarm_ppc_read,
+ strongarm_ppc_read
+};
+
+static CPUWriteMemoryFunc * const strongarm_ppc_writefn[] = {
+ strongarm_ppc_write,
+ strongarm_ppc_write,
+ strongarm_ppc_write
+};
+
+static int strongarm_ppc_init(SysBusDevice *dev)
+{
+ int iomemtype;
+ StrongARMPPCInfo *s;
+
+ s = FROM_SYSBUS(StrongARMPPCInfo, dev);
+
+ qdev_init_gpio_in(&dev->qdev, strongarm_ppc_set, 22);
+ qdev_init_gpio_out(&dev->qdev, s->handler, 22);
+
+ iomemtype = cpu_register_io_memory(strongarm_ppc_readfn,
+ strongarm_ppc_writefn, s, DEVICE_NATIVE_ENDIAN);
+
+ sysbus_init_mmio(dev, 0x1000, iomemtype);
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_strongarm_ppc_regs = {
+ .name = "strongarm-ppc",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(ilevel, StrongARMPPCInfo),
+ VMSTATE_UINT32(olevel, StrongARMPPCInfo),
+ VMSTATE_UINT32(dir, StrongARMPPCInfo),
+ VMSTATE_UINT32(ppar, StrongARMPPCInfo),
+ VMSTATE_UINT32(psdr, StrongARMPPCInfo),
+ VMSTATE_UINT32(ppfr, StrongARMPPCInfo),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo strongarm_ppc_info = {
+ .init = strongarm_ppc_init,
+ .qdev.name = "strongarm-ppc",
+ .qdev.desc = "StrongARM PPC controller",
+ .qdev.size = sizeof(StrongARMPPCInfo),
+};
+
+/* UART Ports */
+#define UTCR0 0x00
+#define UTCR1 0x04
+#define UTCR2 0x08
+#define UTCR3 0x0c
+#define UTDR 0x14
+#define UTSR0 0x1c
+#define UTSR1 0x20
+
+#define UTCR0_PE (1 << 0) /* Parity enable */
+#define UTCR0_OES (1 << 1) /* Even parity */
+#define UTCR0_SBS (1 << 2) /* 2 stop bits */
+#define UTCR0_DSS (1 << 3) /* 8-bit data */
+
+#define UTCR3_RXE (1 << 0) /* Rx enable */
+#define UTCR3_TXE (1 << 1) /* Tx enable */
+#define UTCR3_BRK (1 << 2) /* Force Break */
+#define UTCR3_RIE (1 << 3) /* Rx int enable */
+#define UTCR3_TIE (1 << 4) /* Tx int enable */
+#define UTCR3_LBM (1 << 5) /* Loopback */
+
+#define UTSR0_TFS (1 << 0) /* Tx FIFO nearly empty */
+#define UTSR0_RFS (1 << 1) /* Rx FIFO nearly full */
+#define UTSR0_RID (1 << 2) /* Receiver Idle */
+#define UTSR0_RBB (1 << 3) /* Receiver begin break */
+#define UTSR0_REB (1 << 4) /* Receiver end break */
+#define UTSR0_EIF (1 << 5) /* Error in FIFO */
+
+#define UTSR1_RNE (1 << 1) /* Receive FIFO not empty */
+#define UTSR1_TNF (1 << 2) /* Transmit FIFO not full */
+#define UTSR1_PRE (1 << 3) /* Parity error */
+#define UTSR1_FRE (1 << 4) /* Frame error */
+#define UTSR1_ROR (1 << 5) /* Receive Over Run */
+
+#define RX_FIFO_PRE (1 << 8)
+#define RX_FIFO_FRE (1 << 9)
+#define RX_FIFO_ROR (1 << 10)
+
+typedef struct {
+ SysBusDevice busdev;
+ CharDriverState *chr;
+ qemu_irq irq;
+
+ uint8_t utcr0;
+ uint16_t brd;
+ uint8_t utcr3;
+ uint8_t utsr0;
+ uint8_t utsr1;
+
+ uint8_t tx_fifo[8];
+ uint8_t tx_start;
+ uint8_t tx_len;
+ uint16_t rx_fifo[12]; /* value + error flags in high bits */
+ uint8_t rx_start;
+ uint8_t rx_len;
+
+ uint64_t char_transmit_time; /* time to transmit a char in ticks*/
+ bool wait_break_end;
+ QEMUTimer *rx_timeout_timer;
+ QEMUTimer *tx_timer;
+} StrongARMUARTState;
+
+static void strongarm_uart_update_status(StrongARMUARTState *s)
+{
+ uint16_t utsr1 = 0;
+
+ if (s->tx_len != 8) {
+ utsr1 |= UTSR1_TNF;
+ }
+
+ if (s->rx_len != 0) {
+ uint16_t ent = s->rx_fifo[s->rx_start];
+
+ utsr1 |= UTSR1_RNE;
+ if (ent & RX_FIFO_PRE) {
+ s->utsr1 |= UTSR1_PRE;
+ }
+ if (ent & RX_FIFO_FRE) {
+ s->utsr1 |= UTSR1_FRE;
+ }
+ if (ent & RX_FIFO_ROR) {
+ s->utsr1 |= UTSR1_ROR;
+ }
+ }
+
+ s->utsr1 = utsr1;
+}
+
+static void strongarm_uart_update_int_status(StrongARMUARTState *s)
+{
+ uint16_t utsr0 = s->utsr0 &
+ (UTSR0_REB | UTSR0_RBB | UTSR0_RID);
+ int i;
+
+ if ((s->utcr3 & UTCR3_TXE) &&
+ (s->utcr3 & UTCR3_TIE) &&
+ s->tx_len <= 4) {
+ utsr0 |= UTSR0_TFS;
+ }
+
+ if ((s->utcr3 & UTCR3_RXE) &&
+ (s->utcr3 & UTCR3_RIE) &&
+ s->rx_len > 4) {
+ utsr0 |= UTSR0_RFS;
+ }
+
+ for (i = 0; i < s->rx_len && i < 4; i++)
+ if (s->rx_fifo[(s->rx_start + i) % 12] & ~0xff) {
+ utsr0 |= UTSR0_EIF;
+ break;
+ }
+
+ s->utsr0 = utsr0;
+ qemu_set_irq(s->irq, utsr0);
+}
+
+static void strongarm_uart_update_parameters(StrongARMUARTState *s)
+{
+ int speed, parity, data_bits, stop_bits, frame_size;
+ QEMUSerialSetParams ssp;
+
+ /* Start bit. */
+ frame_size = 1;
+ if (s->utcr0 & UTCR0_PE) {
+ /* Parity bit. */
+ frame_size++;
+ if (s->utcr0 & UTCR0_OES) {
+ parity = 'E';
+ } else {
+ parity = 'O';
+ }
+ } else {
+ parity = 'N';
+ }
+ if (s->utcr0 & UTCR0_SBS) {
+ stop_bits = 2;
+ } else {
+ stop_bits = 1;
+ }
+
+ data_bits = (s->utcr0 & UTCR0_DSS) ? 8 : 7;
+ frame_size += data_bits + stop_bits;
+ speed = 3686400 / 16 / (s->brd + 1);
+ ssp.speed = speed;
+ ssp.parity = parity;
+ ssp.data_bits = data_bits;
+ ssp.stop_bits = stop_bits;
+ s->char_transmit_time = (get_ticks_per_sec() / speed) * frame_size;
+ if (s->chr) {
+ qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+ }
+
+ DPRINTF(stderr, "%s speed=%d parity=%c data=%d stop=%d\n", s->chr->label,
+ speed, parity, data_bits, stop_bits);
+}
+
+static void strongarm_uart_rx_to(void *opaque)
+{
+ StrongARMUARTState *s = opaque;
+
+ if (s->rx_len) {
+ s->utsr0 |= UTSR0_RID;
+ strongarm_uart_update_int_status(s);
+ }
+}
+
+static void strongarm_uart_rx_push(StrongARMUARTState *s, uint16_t c)
+{
+ if ((s->utcr3 & UTCR3_RXE) == 0) {
+ /* rx disabled */
+ return;
+ }
+
+ if (s->wait_break_end) {
+ s->utsr0 |= UTSR0_REB;
+ s->wait_break_end = false;
+ }
+
+ if (s->rx_len < 12) {
+ s->rx_fifo[(s->rx_start + s->rx_len) % 12] = c;
+ s->rx_len++;
+ } else
+ s->rx_fifo[(s->rx_start + 11) % 12] |= RX_FIFO_ROR;
+}
+
+static int strongarm_uart_can_receive(void *opaque)
+{
+ StrongARMUARTState *s = opaque;
+
+ if (s->rx_len == 12) {
+ return 0;
+ }
+ /* It's best not to get more than 2/3 of RX FIFO, so advertise that much */
+ if (s->rx_len < 8) {
+ return 8 - s->rx_len;
+ }
+ return 1;
+}
+
+static void strongarm_uart_receive(void *opaque, const uint8_t *buf, int size)
+{
+ StrongARMUARTState *s = opaque;
+ int i;
+
+ for (i = 0; i < size; i++) {
+ strongarm_uart_rx_push(s, buf[i]);
+ }
+
+ /* call the timeout receive callback in 3 char transmit time */
+ qemu_mod_timer(s->rx_timeout_timer,
+ qemu_get_clock_ns(vm_clock) + s->char_transmit_time * 3);
+
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+}
+
+static void strongarm_uart_event(void *opaque, int event)
+{
+ StrongARMUARTState *s = opaque;
+ if (event == CHR_EVENT_BREAK) {
+ s->utsr0 |= UTSR0_RBB;
+ strongarm_uart_rx_push(s, RX_FIFO_FRE);
+ s->wait_break_end = true;
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+ }
+}
+
+static void strongarm_uart_tx(void *opaque)
+{
+ StrongARMUARTState *s = opaque;
+ uint64_t new_xmit_ts = qemu_get_clock_ns(vm_clock);
+
+ if (s->utcr3 & UTCR3_LBM) /* loopback */ {
+ strongarm_uart_receive(s, &s->tx_fifo[s->tx_start], 1);
+ } else if (s->chr) {
+ qemu_chr_write(s->chr, &s->tx_fifo[s->tx_start], 1);
+ }
+
+ s->tx_start = (s->tx_start + 1) % 8;
+ s->tx_len--;
+ if (s->tx_len) {
+ qemu_mod_timer(s->tx_timer, new_xmit_ts + s->char_transmit_time);
+ }
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+}
+
+static uint32_t strongarm_uart_read(void *opaque, target_phys_addr_t addr)
+{
+ StrongARMUARTState *s = opaque;
+ uint16_t ret;
+
+ switch (addr) {
+ case UTCR0:
+ return s->utcr0;
+
+ case UTCR1:
+ return s->brd >> 8;
+
+ case UTCR2:
+ return s->brd & 0xff;
+
+ case UTCR3:
+ return s->utcr3;
+
+ case UTDR:
+ if (s->rx_len != 0) {
+ ret = s->rx_fifo[s->rx_start];
+ s->rx_start = (s->rx_start + 1) % 12;
+ s->rx_len--;
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+ return ret;
+ }
+ return 0;
+
+ case UTSR0:
+ return s->utsr0;
+
+ case UTSR1:
+ return s->utsr1;
+
+ default:
+ printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+ return 0;
+ }
+}
+
+static void strongarm_uart_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ StrongARMUARTState *s = opaque;
+
+ switch (addr) {
+ case UTCR0:
+ s->utcr0 = value & 0x7f;
+ strongarm_uart_update_parameters(s);
+ break;
+
+ case UTCR1:
+ s->brd = (s->brd & 0xff) | ((value & 0xf) << 8);
+ strongarm_uart_update_parameters(s);
+ break;
+
+ case UTCR2:
+ s->brd = (s->brd & 0xf00) | (value & 0xff);
+ strongarm_uart_update_parameters(s);
+ break;
+
+ case UTCR3:
+ s->utcr3 = value & 0x3f;
+ if ((s->utcr3 & UTCR3_RXE) == 0) {
+ s->rx_len = 0;
+ }
+ if ((s->utcr3 & UTCR3_TXE) == 0) {
+ s->tx_len = 0;
+ }
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+ break;
+
+ case UTDR:
+ if ((s->utcr3 & UTCR3_TXE) && s->tx_len != 8) {
+ s->tx_fifo[(s->tx_start + s->tx_len) % 8] = value;
+ s->tx_len++;
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+ if (s->tx_len == 1) {
+ strongarm_uart_tx(s);
+ }
+ }
+ break;
+
+ case UTSR0:
+ s->utsr0 = s->utsr0 & ~(value &
+ (UTSR0_REB | UTSR0_RBB | UTSR0_RID));
+ strongarm_uart_update_int_status(s);
+ break;
+
+ default:
+ printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+ }
+}
+
+static CPUReadMemoryFunc * const strongarm_uart_readfn[] = {
+ strongarm_uart_read,
+ strongarm_uart_read,
+ strongarm_uart_read,
+};
+
+static CPUWriteMemoryFunc * const strongarm_uart_writefn[] = {
+ strongarm_uart_write,
+ strongarm_uart_write,
+ strongarm_uart_write,
+};
+
+static int strongarm_uart_init(SysBusDevice *dev)
+{
+ StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
+ int iomemtype;
+
+ iomemtype = cpu_register_io_memory(strongarm_uart_readfn,
+ strongarm_uart_writefn, s, DEVICE_NATIVE_ENDIAN);
+ sysbus_init_mmio(dev, 0x10000, iomemtype);
+ sysbus_init_irq(dev, &s->irq);
+
+ s->rx_timeout_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_rx_to, s);
+ s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s);
+
+ if (s->chr) {
+ qemu_chr_add_handlers(s->chr,
+ strongarm_uart_can_receive,
+ strongarm_uart_receive,
+ strongarm_uart_event,
+ s);
+ }
+
+ return 0;
+}
+
+static void strongarm_uart_reset(DeviceState *dev)
+{
+ StrongARMUARTState *s = DO_UPCAST(StrongARMUARTState, busdev.qdev, dev);
+
+ s->utcr0 = UTCR0_DSS; /* 8 data, no parity */
+ s->brd = 23; /* 9600 */
+ /* enable send & recv - this actually violates spec */
+ s->utcr3 = UTCR3_TXE | UTCR3_RXE;
+
+ s->rx_len = s->tx_len = 0;
+
+ strongarm_uart_update_parameters(s);
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+}
+
+static int strongarm_uart_post_load(void *opaque, int version_id)
+{
+ StrongARMUARTState *s = opaque;
+
+ strongarm_uart_update_parameters(s);
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+
+ /* tx and restart timer */
+ if (s->tx_len) {
+ strongarm_uart_tx(s);
+ }
+
+ /* restart rx timeout timer */
+ if (s->rx_len) {
+ qemu_mod_timer(s->rx_timeout_timer,
+ qemu_get_clock_ns(vm_clock) + s->char_transmit_time * 3);
+ }
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_strongarm_uart_regs = {
+ .name = "strongarm-uart",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = strongarm_uart_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(utcr0, StrongARMUARTState),
+ VMSTATE_UINT16(brd, StrongARMUARTState),
+ VMSTATE_UINT8(utcr3, StrongARMUARTState),
+ VMSTATE_UINT8(utsr0, StrongARMUARTState),
+ VMSTATE_UINT8_ARRAY(tx_fifo, StrongARMUARTState, 8),
+ VMSTATE_UINT8(tx_start, StrongARMUARTState),
+ VMSTATE_UINT8(tx_len, StrongARMUARTState),
+ VMSTATE_UINT16_ARRAY(rx_fifo, StrongARMUARTState, 12),
+ VMSTATE_UINT8(rx_start, StrongARMUARTState),
+ VMSTATE_UINT8(rx_len, StrongARMUARTState),
+ VMSTATE_BOOL(wait_break_end, StrongARMUARTState),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo strongarm_uart_info = {
+ .init = strongarm_uart_init,
+ .qdev.name = "strongarm-uart",
+ .qdev.desc = "StrongARM UART controller",
+ .qdev.size = sizeof(StrongARMUARTState),
+ .qdev.reset = strongarm_uart_reset,
+ .qdev.vmsd = &vmstate_strongarm_uart_regs,
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_CHR("chardev", StrongARMUARTState, chr),
+ DEFINE_PROP_END_OF_LIST(),
+ }
+};
+
+/* Synchronous Serial Ports */
+typedef struct {
+ SysBusDevice busdev;
+ qemu_irq irq;
+ SSIBus *bus;
+
+ uint16_t sscr[2];
+ uint16_t sssr;
+
+ uint16_t rx_fifo[8];
+ uint8_t rx_level;
+ uint8_t rx_start;
+} StrongARMSSPState;
+
+#define SSCR0 0x60 /* SSP Control register 0 */
+#define SSCR1 0x64 /* SSP Control register 1 */
+#define SSDR 0x6c /* SSP Data register */
+#define SSSR 0x74 /* SSP Status register */
+
+/* Bitfields for above registers */
+#define SSCR0_SPI(x) (((x) & 0x30) == 0x00)
+#define SSCR0_SSP(x) (((x) & 0x30) == 0x10)
+#define SSCR0_UWIRE(x) (((x) & 0x30) == 0x20)
+#define SSCR0_PSP(x) (((x) & 0x30) == 0x30)
+#define SSCR0_SSE (1 << 7)
+#define SSCR0_DSS(x) (((x) & 0xf) + 1)
+#define SSCR1_RIE (1 << 0)
+#define SSCR1_TIE (1 << 1)
+#define SSCR1_LBM (1 << 2)
+#define SSSR_TNF (1 << 2)
+#define SSSR_RNE (1 << 3)
+#define SSSR_TFS (1 << 5)
+#define SSSR_RFS (1 << 6)
+#define SSSR_ROR (1 << 7)
+#define SSSR_RW 0x0080
+
+static void strongarm_ssp_int_update(StrongARMSSPState *s)
+{
+ int level = 0;
+
+ level |= (s->sssr & SSSR_ROR);
+ level |= (s->sssr & SSSR_RFS) && (s->sscr[1] & SSCR1_RIE);
+ level |= (s->sssr & SSSR_TFS) && (s->sscr[1] & SSCR1_TIE);
+ qemu_set_irq(s->irq, level);
+}
+
+static void strongarm_ssp_fifo_update(StrongARMSSPState *s)
+{
+ s->sssr &= ~SSSR_TFS;
+ s->sssr &= ~SSSR_TNF;
+ if (s->sscr[0] & SSCR0_SSE) {
+ if (s->rx_level >= 4) {
+ s->sssr |= SSSR_RFS;
+ } else {
+ s->sssr &= ~SSSR_RFS;
+ }
+ if (s->rx_level) {
+ s->sssr |= SSSR_RNE;
+ } else {
+ s->sssr &= ~SSSR_RNE;
+ }
+ /* TX FIFO is never filled, so it is always in underrun
+ condition if SSP is enabled */
+ s->sssr |= SSSR_TFS;
+ s->sssr |= SSSR_TNF;
+ }
+
+ strongarm_ssp_int_update(s);
+}
+
+static uint32_t strongarm_ssp_read(void *opaque, target_phys_addr_t addr)
+{
+ StrongARMSSPState *s = opaque;
+ uint32_t retval;
+
+ switch (addr) {
+ case SSCR0:
+ return s->sscr[0];
+ case SSCR1:
+ return s->sscr[1];
+ case SSSR:
+ return s->sssr;
+ case SSDR:
+ if (~s->sscr[0] & SSCR0_SSE) {
+ return 0xffffffff;
+ }
+ if (s->rx_level < 1) {
+ printf("%s: SSP Rx Underrun\n", __func__);
+ return 0xffffffff;
+ }
+ s->rx_level--;
+ retval = s->rx_fifo[s->rx_start++];
+ s->rx_start &= 0x7;
+ strongarm_ssp_fifo_update(s);
+ return retval;
+ default:
+ printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+ break;
+ }
+ return 0;
+}
+
+static void strongarm_ssp_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ StrongARMSSPState *s = opaque;
+
+ switch (addr) {
+ case SSCR0:
+ s->sscr[0] = value & 0xffbf;
+ if ((s->sscr[0] & SSCR0_SSE) && SSCR0_DSS(value) < 4) {
+ printf("%s: Wrong data size: %i bits\n", __func__,
+ SSCR0_DSS(value));
+ }
+ if (!(value & SSCR0_SSE)) {
+ s->sssr = 0;
+ s->rx_level = 0;
+ }
+ strongarm_ssp_fifo_update(s);
+ break;
+
+ case SSCR1:
+ s->sscr[1] = value & 0x2f;
+ if (value & SSCR1_LBM) {
+ printf("%s: Attempt to use SSP LBM mode\n", __func__);
+ }
+ strongarm_ssp_fifo_update(s);
+ break;
+
+ case SSSR:
+ s->sssr &= ~(value & SSSR_RW);
+ strongarm_ssp_int_update(s);
+ break;
+
+ case SSDR:
+ if (SSCR0_UWIRE(s->sscr[0])) {
+ value &= 0xff;
+ } else
+ /* Note how 32bits overflow does no harm here */
+ value &= (1 << SSCR0_DSS(s->sscr[0])) - 1;
+
+ /* Data goes from here to the Tx FIFO and is shifted out from
+ * there directly to the slave, no need to buffer it.
+ */
+ if (s->sscr[0] & SSCR0_SSE) {
+ uint32_t readval;
+ if (s->sscr[1] & SSCR1_LBM) {
+ readval = value;
+ } else {
+ readval = ssi_transfer(s->bus, value);
+ }
+
+ if (s->rx_level < 0x08) {
+ s->rx_fifo[(s->rx_start + s->rx_level++) & 0x7] = readval;
+ } else {
+ s->sssr |= SSSR_ROR;
+ }
+ }
+ strongarm_ssp_fifo_update(s);
+ break;
+
+ default:
+ printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+ break;
+ }
+}
+
+static CPUReadMemoryFunc * const strongarm_ssp_readfn[] = {
+ strongarm_ssp_read,
+ strongarm_ssp_read,
+ strongarm_ssp_read,
+};
+
+static CPUWriteMemoryFunc * const strongarm_ssp_writefn[] = {
+ strongarm_ssp_write,
+ strongarm_ssp_write,
+ strongarm_ssp_write,
+};
+
+static int strongarm_ssp_post_load(void *opaque, int version_id)
+{
+ StrongARMSSPState *s = opaque;
+
+ strongarm_ssp_fifo_update(s);
+
+ return 0;
+}
+
+static int strongarm_ssp_init(SysBusDevice *dev)
+{
+ int iomemtype;
+ StrongARMSSPState *s = FROM_SYSBUS(StrongARMSSPState, dev);
+
+ sysbus_init_irq(dev, &s->irq);
+
+ iomemtype = cpu_register_io_memory(strongarm_ssp_readfn,
+ strongarm_ssp_writefn, s,
+ DEVICE_NATIVE_ENDIAN);
+ sysbus_init_mmio(dev, 0x1000, iomemtype);
+
+ s->bus = ssi_create_bus(&dev->qdev, "ssi");
+ return 0;
+}
+
+static void strongarm_ssp_reset(DeviceState *dev)
+{
+ StrongARMSSPState *s = DO_UPCAST(StrongARMSSPState, busdev.qdev, dev);
+ s->sssr = 0x03; /* 3 bit data, SPI, disabled */
+ s->rx_start = 0;
+ s->rx_level = 0;
+}
+
+static const VMStateDescription vmstate_strongarm_ssp_regs = {
+ .name = "strongarm-ssp",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = strongarm_ssp_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT16_ARRAY(sscr, StrongARMSSPState, 2),
+ VMSTATE_UINT16(sssr, StrongARMSSPState),
+ VMSTATE_UINT16_ARRAY(rx_fifo, StrongARMSSPState, 8),
+ VMSTATE_UINT8(rx_start, StrongARMSSPState),
+ VMSTATE_UINT8(rx_level, StrongARMSSPState),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo strongarm_ssp_info = {
+ .init = strongarm_ssp_init,
+ .qdev.name = "strongarm-ssp",
+ .qdev.desc = "StrongARM SSP controller",
+ .qdev.size = sizeof(StrongARMSSPState),
+ .qdev.reset = strongarm_ssp_reset,
+ .qdev.vmsd = &vmstate_strongarm_ssp_regs,
+};
+
+/* Main CPU functions */
+StrongARMState *sa1110_init(unsigned int sdram_size, const char *rev)
+{
+ StrongARMState *s;
+ qemu_irq *pic;
+ int i;
+
+ s = qemu_mallocz(sizeof(StrongARMState));
+
+ if (!rev) {
+ rev = "sa1110-b5";
+ }
+
+ if (strncmp(rev, "sa1110", 6)) {
+ error_report("Machine requires a SA1110 processor.\n");
+ exit(1);
+ }
+
+ s->env = cpu_init(rev);
+
+ if (!s->env) {
+ error_report("Unable to find CPU definition\n");
+ exit(1);
+ }
+
+ cpu_register_physical_memory(SA_SDCS0,
+ sdram_size, qemu_ram_alloc(NULL, "strongarm.sdram",
+ sdram_size) | IO_MEM_RAM);
+
+ pic = arm_pic_init_cpu(s->env);
+ s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000,
+ pic[ARM_PIC_CPU_IRQ], pic[ARM_PIC_CPU_FIQ], NULL);
+
+ sysbus_create_varargs("pxa25x-timer", 0x90000000,
+ qdev_get_gpio_in(s->pic, SA_PIC_OSTC0),
+ qdev_get_gpio_in(s->pic, SA_PIC_OSTC1),
+ qdev_get_gpio_in(s->pic, SA_PIC_OSTC2),
+ qdev_get_gpio_in(s->pic, SA_PIC_OSTC3),
+ NULL);
+
+ sysbus_create_simple("strongarm-rtc", 0x90010000,
+ qdev_get_gpio_in(s->pic, SA_PIC_RTC_ALARM));
+
+ s->gpio = strongarm_gpio_init(0x90040000, s->pic);
+
+ s->ppc = sysbus_create_varargs("strongarm-ppc", 0x90060000, NULL);
+
+ for (i = 0; sa_serial[i].io_base; i++) {
+ DeviceState *dev = qdev_create(NULL, "strongarm-uart");
+ qdev_prop_set_chr(dev, "chardev", serial_hds[i]);
+ qdev_init_nofail(dev);
+ sysbus_mmio_map(sysbus_from_qdev(dev), 0,
+ sa_serial[i].io_base);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 0,
+ qdev_get_gpio_in(s->pic, sa_serial[i].irq));
+ }
+
+ s->ssp = sysbus_create_varargs("strongarm-ssp", 0x80070000,
+ qdev_get_gpio_in(s->pic, SA_PIC_SSP), NULL);
+ s->ssp_bus = (SSIBus *)qdev_get_child_bus(s->ssp, "ssi");
+
+ return s;
+}
+
+static void strongarm_register_devices(void)
+{
+ sysbus_register_withprop(&strongarm_pic_info);
+ sysbus_register_withprop(&strongarm_rtc_sysbus_info);
+ sysbus_register_withprop(&strongarm_gpio_info);
+ sysbus_register_withprop(&strongarm_ppc_info);
+ sysbus_register_withprop(&strongarm_uart_info);
+ sysbus_register_withprop(&strongarm_ssp_info);
+}
+device_init(strongarm_register_devices)
diff --git a/hw/strongarm.h b/hw/strongarm.h
new file mode 100644
index 000000000..a81b110e2
--- /dev/null
+++ b/hw/strongarm.h
@@ -0,0 +1,64 @@
+#ifndef _STRONGARM_H
+#define _STRONGARM_H
+
+#define SA_CS0 0x00000000
+#define SA_CS1 0x08000000
+#define SA_CS2 0x10000000
+#define SA_CS3 0x18000000
+#define SA_PCMCIA_CS0 0x20000000
+#define SA_PCMCIA_CS1 0x30000000
+#define SA_CS4 0x40000000
+#define SA_CS5 0x48000000
+/* system registers here */
+#define SA_SDCS0 0xc0000000
+#define SA_SDCS1 0xc8000000
+#define SA_SDCS2 0xd0000000
+#define SA_SDCS3 0xd8000000
+
+enum {
+ SA_PIC_GPIO0_EDGE = 0,
+ SA_PIC_GPIO1_EDGE,
+ SA_PIC_GPIO2_EDGE,
+ SA_PIC_GPIO3_EDGE,
+ SA_PIC_GPIO4_EDGE,
+ SA_PIC_GPIO5_EDGE,
+ SA_PIC_GPIO6_EDGE,
+ SA_PIC_GPIO7_EDGE,
+ SA_PIC_GPIO8_EDGE,
+ SA_PIC_GPIO9_EDGE,
+ SA_PIC_GPIO10_EDGE,
+ SA_PIC_GPIOX_EDGE,
+ SA_PIC_LCD,
+ SA_PIC_UDC,
+ SA_PIC_RSVD1,
+ SA_PIC_UART1,
+ SA_PIC_UART2,
+ SA_PIC_UART3,
+ SA_PIC_MCP,
+ SA_PIC_SSP,
+ SA_PIC_DMA_CH0,
+ SA_PIC_DMA_CH1,
+ SA_PIC_DMA_CH2,
+ SA_PIC_DMA_CH3,
+ SA_PIC_DMA_CH4,
+ SA_PIC_DMA_CH5,
+ SA_PIC_OSTC0,
+ SA_PIC_OSTC1,
+ SA_PIC_OSTC2,
+ SA_PIC_OSTC3,
+ SA_PIC_RTC_HZ,
+ SA_PIC_RTC_ALARM,
+};
+
+typedef struct {
+ CPUState *env;
+ DeviceState *pic;
+ DeviceState *gpio;
+ DeviceState *ppc;
+ DeviceState *ssp;
+ SSIBus *ssp_bus;
+} StrongARMState;
+
+StrongARMState *sa1110_init(unsigned int sdram_size, const char *rev);
+
+#endif
diff --git a/hw/syborg.c b/hw/syborg.c
index 758c69a9c..bc200e48a 100644
--- a/hw/syborg.c
+++ b/hw/syborg.c
@@ -25,7 +25,6 @@
#include "sysbus.h"
#include "boards.h"
#include "arm-misc.h"
-#include "sysemu.h"
#include "net.h"
static struct arm_boot_info syborg_binfo;
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index d295e99eb..706a03966 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -51,11 +51,11 @@ enum {
typedef struct {
SysBusDevice busdev;
- int int_enabled;
+ uint32_t int_enabled;
int extension_bit;
uint32_t fifo_size;
uint32_t *key_fifo;
- int read_pos, read_count;
+ uint32_t read_pos, read_count;
qemu_irq irq;
} SyborgKeyboardState;
@@ -165,43 +165,21 @@ static void syborg_keyboard_event(void *opaque, int keycode)
syborg_keyboard_update(s);
}
-static void syborg_keyboard_save(QEMUFile *f, void *opaque)
-{
- SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
- int i;
-
- qemu_put_be32(f, s->fifo_size);
- qemu_put_be32(f, s->int_enabled);
- qemu_put_be32(f, s->extension_bit);
- qemu_put_be32(f, s->read_pos);
- qemu_put_be32(f, s->read_count);
- for (i = 0; i < s->fifo_size; i++) {
- qemu_put_be32(f, s->key_fifo[i]);
- }
-}
-
-static int syborg_keyboard_load(QEMUFile *f, void *opaque, int version_id)
-{
- SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
- uint32_t val;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- val = qemu_get_be32(f);
- if (val != s->fifo_size)
- return -EINVAL;
-
- s->int_enabled = qemu_get_be32(f);
- s->extension_bit = qemu_get_be32(f);
- s->read_pos = qemu_get_be32(f);
- s->read_count = qemu_get_be32(f);
- for (i = 0; i < s->fifo_size; i++) {
- s->key_fifo[i] = qemu_get_be32(f);
+static const VMStateDescription vmstate_syborg_keyboard = {
+ .name = "syborg_keyboard",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_EQUAL(fifo_size, SyborgKeyboardState),
+ VMSTATE_UINT32(int_enabled, SyborgKeyboardState),
+ VMSTATE_UINT32(read_pos, SyborgKeyboardState),
+ VMSTATE_UINT32(read_count, SyborgKeyboardState),
+ VMSTATE_VARRAY_UINT32(key_fifo, SyborgKeyboardState, fifo_size, 1,
+ vmstate_info_uint32, uint32),
+ VMSTATE_END_OF_LIST()
}
- return 0;
-}
+};
static int syborg_keyboard_init(SysBusDevice *dev)
{
@@ -221,8 +199,7 @@ static int syborg_keyboard_init(SysBusDevice *dev)
qemu_add_kbd_event_handler(syborg_keyboard_event, s);
- register_savevm(&dev->qdev, "syborg_keyboard", -1, 1,
- syborg_keyboard_save, syborg_keyboard_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_syborg_keyboard, s);
return 0;
}
diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
index a88688846..2f9970704 100644
--- a/hw/syborg_pointer.c
+++ b/hw/syborg_pointer.c
@@ -152,52 +152,36 @@ static void syborg_pointer_event(void *opaque, int dx, int dy, int dz,
syborg_pointer_update(s);
}
-static void syborg_pointer_save(QEMUFile *f, void *opaque)
-{
- SyborgPointerState *s = (SyborgPointerState *)opaque;
- int i;
-
- qemu_put_be32(f, s->fifo_size);
- qemu_put_be32(f, s->absolute);
- qemu_put_be32(f, s->int_enabled);
- qemu_put_be32(f, s->read_pos);
- qemu_put_be32(f, s->read_count);
- for (i = 0; i < s->fifo_size; i++) {
- qemu_put_be32(f, s->event_fifo[i].x);
- qemu_put_be32(f, s->event_fifo[i].y);
- qemu_put_be32(f, s->event_fifo[i].z);
- qemu_put_be32(f, s->event_fifo[i].pointer_buttons);
+static const VMStateDescription vmstate_event_data = {
+ .name = "dbma_channel",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(x, event_data),
+ VMSTATE_INT32(y, event_data),
+ VMSTATE_INT32(z, event_data),
+ VMSTATE_INT32(pointer_buttons, event_data),
+ VMSTATE_END_OF_LIST()
}
-}
+};
-static int syborg_pointer_load(QEMUFile *f, void *opaque, int version_id)
-{
- SyborgPointerState *s = (SyborgPointerState *)opaque;
- uint32_t val;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- val = qemu_get_be32(f);
- if (val != s->fifo_size)
- return -EINVAL;
-
- val = qemu_get_be32(f);
- if (val != s->absolute)
- return -EINVAL;
-
- s->int_enabled = qemu_get_be32(f);
- s->read_pos = qemu_get_be32(f);
- s->read_count = qemu_get_be32(f);
- for (i = 0; i < s->fifo_size; i++) {
- s->event_fifo[i].x = qemu_get_be32(f);
- s->event_fifo[i].y = qemu_get_be32(f);
- s->event_fifo[i].z = qemu_get_be32(f);
- s->event_fifo[i].pointer_buttons = qemu_get_be32(f);
+static const VMStateDescription vmstate_syborg_pointer = {
+ .name = "syborg_pointer",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_EQUAL(fifo_size, SyborgPointerState),
+ VMSTATE_UINT32_EQUAL(absolute, SyborgPointerState),
+ VMSTATE_INT32(int_enabled, SyborgPointerState),
+ VMSTATE_INT32(read_pos, SyborgPointerState),
+ VMSTATE_INT32(read_count, SyborgPointerState),
+ VMSTATE_STRUCT_VARRAY_UINT32(event_fifo, SyborgPointerState, fifo_size,
+ 1, vmstate_event_data, event_data),
+ VMSTATE_END_OF_LIST()
}
- return 0;
-}
+};
static int syborg_pointer_init(SysBusDevice *dev)
{
@@ -219,8 +203,7 @@ static int syborg_pointer_init(SysBusDevice *dev)
qemu_add_mouse_event_handler(syborg_pointer_event, s, s->absolute,
"Syborg Pointer");
- register_savevm(&dev->qdev, "syborg_pointer", -1, 1,
- syborg_pointer_save, syborg_pointer_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_syborg_pointer, s);
return 0;
}
diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
index 16d8f9edb..69f6ccf29 100644
--- a/hw/syborg_rtc.c
+++ b/hw/syborg_rtc.c
@@ -102,26 +102,17 @@ static CPUWriteMemoryFunc * const syborg_rtc_writefn[] = {
syborg_rtc_write
};
-static void syborg_rtc_save(QEMUFile *f, void *opaque)
-{
- SyborgRTCState *s = opaque;
-
- qemu_put_be64(f, s->offset);
- qemu_put_be64(f, s->data);
-}
-
-static int syborg_rtc_load(QEMUFile *f, void *opaque, int version_id)
-{
- SyborgRTCState *s = opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->offset = qemu_get_be64(f);
- s->data = qemu_get_be64(f);
-
- return 0;
-}
+static const VMStateDescription vmstate_syborg_rtc = {
+ .name = "syborg_keyboard",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT64(offset, SyborgRTCState),
+ VMSTATE_INT64(data, SyborgRTCState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int syborg_rtc_init(SysBusDevice *dev)
{
@@ -137,8 +128,7 @@ static int syborg_rtc_init(SysBusDevice *dev)
qemu_get_timedate(&tm, 0);
s->offset = (uint64_t)mktime(&tm) * 1000000000;
- register_savevm(&dev->qdev, "syborg_rtc", -1, 1,
- syborg_rtc_save, syborg_rtc_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_syborg_rtc, s);
return 0;
}
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index 34ce076d4..df2950fe8 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -273,47 +273,24 @@ static CPUWriteMemoryFunc * const syborg_serial_writefn[] = {
syborg_serial_write
};
-static void syborg_serial_save(QEMUFile *f, void *opaque)
-{
- SyborgSerialState *s = opaque;
- int i;
-
- qemu_put_be32(f, s->fifo_size);
- qemu_put_be32(f, s->int_enable);
- qemu_put_be32(f, s->read_pos);
- qemu_put_be32(f, s->read_count);
- qemu_put_be32(f, s->dma_tx_ptr);
- qemu_put_be32(f, s->dma_rx_ptr);
- qemu_put_be32(f, s->dma_rx_size);
- for (i = 0; i < s->fifo_size; i++) {
- qemu_put_be32(f, s->read_fifo[i]);
- }
-}
-
-static int syborg_serial_load(QEMUFile *f, void *opaque, int version_id)
-{
- SyborgSerialState *s = opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- i = qemu_get_be32(f);
- if (s->fifo_size != i)
- return -EINVAL;
-
- s->int_enable = qemu_get_be32(f);
- s->read_pos = qemu_get_be32(f);
- s->read_count = qemu_get_be32(f);
- s->dma_tx_ptr = qemu_get_be32(f);
- s->dma_rx_ptr = qemu_get_be32(f);
- s->dma_rx_size = qemu_get_be32(f);
- for (i = 0; i < s->fifo_size; i++) {
- s->read_fifo[i] = qemu_get_be32(f);
+static const VMStateDescription vmstate_syborg_serial = {
+ .name = "syborg_serial",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_EQUAL(fifo_size, SyborgSerialState),
+ VMSTATE_UINT32(int_enable, SyborgSerialState),
+ VMSTATE_INT32(read_pos, SyborgSerialState),
+ VMSTATE_INT32(read_count, SyborgSerialState),
+ VMSTATE_UINT32(dma_tx_ptr, SyborgSerialState),
+ VMSTATE_UINT32(dma_rx_ptr, SyborgSerialState),
+ VMSTATE_UINT32(dma_rx_size, SyborgSerialState),
+ VMSTATE_VARRAY_UINT32(read_fifo, SyborgSerialState, fifo_size, 1,
+ vmstate_info_uint32, uint32),
+ VMSTATE_END_OF_LIST()
}
-
- return 0;
-}
+};
static int syborg_serial_init(SysBusDevice *dev)
{
@@ -336,8 +313,6 @@ static int syborg_serial_init(SysBusDevice *dev)
}
s->read_fifo = qemu_mallocz(s->fifo_size * sizeof(s->read_fifo[0]));
- register_savevm(&dev->qdev, "syborg_serial", -1, 1,
- syborg_serial_save, syborg_serial_load, s);
return 0;
}
@@ -345,6 +320,7 @@ static SysBusDeviceInfo syborg_serial_info = {
.init = syborg_serial_init,
.qdev.name = "syborg,serial",
.qdev.size = sizeof(SyborgSerialState),
+ .qdev.vmsd = &vmstate_syborg_serial,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("fifo-size", SyborgSerialState, fifo_size, 16),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index cedcd8ed4..50c813e96 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -174,34 +174,21 @@ static CPUWriteMemoryFunc * const syborg_timer_writefn[] = {
syborg_timer_write
};
-static void syborg_timer_save(QEMUFile *f, void *opaque)
-{
- SyborgTimerState *s = opaque;
-
- qemu_put_be32(f, s->running);
- qemu_put_be32(f, s->oneshot);
- qemu_put_be32(f, s->limit);
- qemu_put_be32(f, s->int_level);
- qemu_put_be32(f, s->int_enabled);
- qemu_put_ptimer(f, s->timer);
-}
-
-static int syborg_timer_load(QEMUFile *f, void *opaque, int version_id)
-{
- SyborgTimerState *s = opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->running = qemu_get_be32(f);
- s->oneshot = qemu_get_be32(f);
- s->limit = qemu_get_be32(f);
- s->int_level = qemu_get_be32(f);
- s->int_enabled = qemu_get_be32(f);
- qemu_get_ptimer(f, s->timer);
-
- return 0;
-}
+static const VMStateDescription vmstate_syborg_timer = {
+ .name = "syborg_timer",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(running, SyborgTimerState),
+ VMSTATE_INT32(oneshot, SyborgTimerState),
+ VMSTATE_UINT32(limit, SyborgTimerState),
+ VMSTATE_UINT32(int_level, SyborgTimerState),
+ VMSTATE_UINT32(int_enabled, SyborgTimerState),
+ VMSTATE_PTIMER(timer, SyborgTimerState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int syborg_timer_init(SysBusDevice *dev)
{
@@ -222,8 +209,7 @@ static int syborg_timer_init(SysBusDevice *dev)
bh = qemu_bh_new(syborg_timer_tick, s);
s->timer = ptimer_init(bh);
ptimer_set_freq(s->timer, s->freq);
- register_savevm(&dev->qdev, "syborg_timer", -1, 1,
- syborg_timer_save, syborg_timer_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_syborg_timer, s);
return 0;
}
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index ee08c4910..2f3e6da4e 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -26,7 +26,6 @@
#include "sysbus.h"
#include "virtio.h"
#include "virtio-net.h"
-#include "sysemu.h"
//#define DEBUG_SYBORG_VIRTIO
diff --git a/hw/sysbus.c b/hw/sysbus.c
index acad72abe..2e22be7b2 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -18,7 +18,6 @@
*/
#include "sysbus.h"
-#include "sysemu.h"
#include "monitor.h"
static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
diff --git a/hw/tc58128.c b/hw/tc58128.c
index 672a01c46..61b99dd4d 100644
--- a/hw/tc58128.c
+++ b/hw/tc58128.c
@@ -1,6 +1,5 @@
#include "hw.h"
#include "sh.h"
-#include "sysemu.h"
#include "loader.h"
#define CE1 0x0100
diff --git a/hw/tosa.c b/hw/tosa.c
index b8b6c4f39..a7967a286 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -11,7 +11,6 @@
#include "hw.h"
#include "pxa.h"
#include "arm-misc.h"
-#include "sysemu.h"
#include "devices.h"
#include "sharpsl.h"
#include "pcmcia.h"
diff --git a/hw/twl92230.c b/hw/twl92230.c
index 8e74acc05..a75448f06 100644
--- a/hw/twl92230.c
+++ b/hw/twl92230.c
@@ -22,7 +22,6 @@
#include "hw.h"
#include "qemu-timer.h"
#include "i2c.h"
-#include "sysemu.h"
#include "console.h"
#define VERBOSE 1
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index c25362cc9..89c293c46 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -26,7 +26,7 @@
#include "console.h"
#include "usb.h"
#include "usb-desc.h"
-#include "sysemu.h"
+#include "qemu-timer.h"
/* HID interface requests */
#define GET_REPORT 0xa101
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 76f5b027b..947fd3f83 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -33,7 +33,7 @@ do { printf("usb-msd: " fmt , ## __VA_ARGS__); } while (0)
enum USBMSDMode {
USB_MSDM_CBW, /* Command Block. */
- USB_MSDM_DATAOUT, /* Tranfer data to device. */
+ USB_MSDM_DATAOUT, /* Transfer data to device. */
USB_MSDM_DATAIN, /* Transfer data from device. */
USB_MSDM_CSW /* Command Status. */
};
@@ -253,7 +253,7 @@ static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
usb_msd_copy_data(s);
if (s->usb_len == 0) {
/* Set s->packet to NULL before calling usb_packet_complete
- because annother request may be issued before
+ because another request may be issued before
usb_packet_complete returns. */
DPRINTF("Packet complete %p\n", p);
s->packet = NULL;
diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index f9add1cd4..447b337e0 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -15,7 +15,6 @@
#include "qemu-common.h"
#include "virtio.h"
#include "pc.h"
-#include "sysemu.h"
#include "cpu.h"
#include "monitor.h"
#include "balloon.h"
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index 6b5237b3c..de539c4ea 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -28,6 +28,22 @@ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
return qemu_chr_write(vcon->chr, buf, len);
}
+/* Callback function that's called when the guest opens the port */
+static void guest_open(VirtIOSerialPort *port)
+{
+ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
+
+ qemu_chr_guest_open(vcon->chr);
+}
+
+/* Callback function that's called when the guest closes the port */
+static void guest_close(VirtIOSerialPort *port)
+{
+ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
+
+ qemu_chr_guest_close(vcon->chr);
+}
+
/* Readiness of the guest to accept data on a port */
static int chr_can_read(void *opaque)
{
@@ -64,6 +80,8 @@ static int generic_port_init(VirtConsole *vcon, VirtIOSerialPort *port)
qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
vcon);
vcon->port.info->have_data = flush_buf;
+ vcon->port.info->guest_open = guest_open;
+ vcon->port.info->guest_close = guest_close;
}
return 0;
}
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 5236470ba..991005bca 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -961,7 +961,7 @@ static PCIDeviceInfo virtio_info[] = {
.qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_net_init_pci,
.exit = virtio_net_exit_pci,
- .romfile = "pxe-virtio.bin",
+ .romfile = "pxe-virtio.rom",
.qdev.props = (Property[]) {
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 62273799b..f10d48fdb 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -494,7 +494,7 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
VirtIOSerial *s = opaque;
VirtIOSerialPort *port;
uint32_t nr_active_ports;
- unsigned int i;
+ unsigned int i, max_nr_ports;
/* The virtio device */
virtio_save(&s->vdev, f);
@@ -506,8 +506,8 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
qemu_put_be32s(f, &s->config.max_nr_ports);
/* The ports map */
-
- for (i = 0; i < (s->config.max_nr_ports + 31) / 32; i++) {
+ max_nr_ports = tswap32(s->config.max_nr_ports);
+ for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
qemu_put_be32s(f, &s->ports_map[i]);
}
@@ -568,7 +568,8 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_be16s(f, &s->config.rows);
qemu_get_be32s(f, &max_nr_ports);
- if (max_nr_ports > s->config.max_nr_ports) {
+ tswap32s(&max_nr_ports);
+ if (max_nr_ports > tswap32(s->config.max_nr_ports)) {
/* Source could have had more ports than us. Fail migration. */
return -EINVAL;
}
@@ -670,9 +671,10 @@ static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
/* This function is only used if a port id is not provided by the user */
static uint32_t find_free_port_id(VirtIOSerial *vser)
{
- unsigned int i;
+ unsigned int i, max_nr_ports;
- for (i = 0; i < (vser->config.max_nr_ports + 31) / 32; i++) {
+ max_nr_ports = tswap32(vser->config.max_nr_ports);
+ for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
uint32_t map, bit;
map = vser->ports_map[i];
@@ -720,7 +722,7 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
VirtIOSerialPortInfo *info = DO_UPCAST(VirtIOSerialPortInfo, qdev, base);
VirtIOSerialBus *bus = DO_UPCAST(VirtIOSerialBus, qbus, qdev->parent_bus);
- int ret;
+ int ret, max_nr_ports;
bool plugging_port0;
port->vser = bus->vser;
@@ -750,9 +752,10 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
}
}
- if (port->id >= port->vser->config.max_nr_ports) {
+ max_nr_ports = tswap32(port->vser->config.max_nr_ports);
+ if (port->id >= max_nr_ports) {
error_report("virtio-serial-bus: Out-of-range port id specified, max. allowed: %u\n",
- port->vser->config.max_nr_ports - 1);
+ max_nr_ports - 1);
return -1;
}
@@ -863,7 +866,7 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output);
}
- vser->config.max_nr_ports = conf->max_virtserial_ports;
+ vser->config.max_nr_ports = tswap32(conf->max_virtserial_ports);
vser->ports_map = qemu_mallocz(((conf->max_virtserial_ports + 31) / 32)
* sizeof(vser->ports_map[0]));
/*
diff --git a/hw/virtio.c b/hw/virtio.c
index 31bd9e32d..6e8814cb6 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -16,7 +16,6 @@
#include "trace.h"
#include "qemu-error.h"
#include "virtio.h"
-#include "sysemu.h"
/* The alignment to use between consumer and producer parts of vring.
* x86 pagesize again. */
diff --git a/hw/vmport.c b/hw/vmport.c
index 19010e484..c8aefaabb 100644
--- a/hw/vmport.c
+++ b/hw/vmport.c
@@ -24,7 +24,6 @@
#include "hw.h"
#include "isa.h"
#include "pc.h"
-#include "sysemu.h"
#include "kvm.h"
#include "qdev.h"
diff --git a/hw/xen_console.c b/hw/xen_console.c
index d2261f413..c6c816381 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -33,7 +33,6 @@
#include <xenctrl.h>
#include "hw.h"
-#include "sysemu.h"
#include "qemu-char.h"
#include "xen_backend.h"
diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c
index 371c56206..4093587df 100644
--- a/hw/xen_domainbuild.c
+++ b/hw/xen_domainbuild.c
@@ -1,7 +1,6 @@
#include <signal.h>
#include "xen_backend.h"
#include "xen_domainbuild.h"
-#include "sysemu.h"
#include "qemu-timer.h"
#include "qemu-log.h"
diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
index 77a34bf11..0d7f73ed8 100644
--- a/hw/xen_machine_pv.c
+++ b/hw/xen_machine_pv.c
@@ -24,7 +24,6 @@
#include "hw.h"
#include "pc.h"
-#include "sysemu.h"
#include "boards.h"
#include "xen_backend.h"
#include "xen_domainbuild.h"
diff --git a/hw/xenfb.c b/hw/xenfb.c
index da5297b49..1db75fbe4 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -44,7 +44,6 @@
#include <xen/io/protocols.h>
#include "hw.h"
-#include "sysemu.h"
#include "console.h"
#include "qemu-char.h"
#include "xen_backend.h"
diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c
index 30827b03c..d398c18e9 100644
--- a/hw/xilinx_timer.c
+++ b/hw/xilinx_timer.c
@@ -23,7 +23,6 @@
*/
#include "sysbus.h"
-#include "sysemu.h"
#include "qemu-timer.h"
#define D(x)
diff --git a/json-lexer.c b/json-lexer.c
index c736f4290..65c9720d6 100644
--- a/json-lexer.c
+++ b/json-lexer.c
@@ -28,7 +28,7 @@
*/
enum json_lexer_state {
- ERROR = 0,
+ IN_ERROR = 0,
IN_DQ_UCODE3,
IN_DQ_UCODE2,
IN_DQ_UCODE1,
@@ -150,7 +150,7 @@ static const uint8_t json_lexer[][256] = {
/* Zero */
[IN_ZERO] = {
TERMINAL(JSON_INTEGER),
- ['0' ... '9'] = ERROR,
+ ['0' ... '9'] = IN_ERROR,
['.'] = IN_MANTISSA,
},
@@ -302,7 +302,7 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch)
lexer->token = qstring_new();
new_state = IN_START;
break;
- case ERROR:
+ case IN_ERROR:
return -EINVAL;
default:
break;
diff --git a/kvm-all.c b/kvm-all.c
index d0438d96a..693bb4a20 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -681,6 +681,14 @@ void kvm_cpu_register_phys_memory_client(void)
}
#ifdef OBSOLETE_KVM_IMPL
+static void kvm_handle_interrupt(CPUState *env, int mask)
+{
+ env->interrupt_request |= mask;
+
+ if (!qemu_cpu_is_self(env)) {
+ qemu_cpu_kick(env);
+ }
+}
int kvm_init(void)
{
@@ -790,6 +798,8 @@ int kvm_init(void)
s->many_ioeventfds = kvm_check_many_ioeventfds();
+ cpu_interrupt_handler = kvm_handle_interrupt;
+
return 0;
err:
@@ -1206,7 +1216,7 @@ int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
bp->use_count = 1;
err = kvm_arch_insert_sw_breakpoint(current_env, bp);
if (err) {
- free(bp);
+ qemu_free(bp);
return err;
}
@@ -1330,7 +1340,7 @@ int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset)
sigmask->len = 8;
memcpy(sigmask->sigset, sigset, sizeof(*sigset));
r = kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, sigmask);
- free(sigmask);
+ qemu_free(sigmask);
return r;
}
diff --git a/kvm-stub.c b/kvm-stub.c
index fc2b81006..31bd77b3a 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -11,7 +11,6 @@
*/
#include "qemu-common.h"
-#include "sysemu.h"
#include "hw/hw.h"
#include "exec-all.h"
#include "gdbstub.h"
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 71f2ba3ae..baada52a3 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -955,7 +955,7 @@ count_tokens(const char *str, char token, char token_end)
static const char *
strip(const char *str)
{
- for (; *str && !isspace(*str); str++) {
+ for (; *str && isspace(*str); str++) {
}
return str;
}
@@ -963,7 +963,7 @@ strip(const char *str)
static const char *
find_blank(const char *str)
{
- for (; *str && isspace(*str); str++) {
+ for (; *str && !isspace(*str); str++) {
}
return str;
}
diff --git a/linux-user/alpha/syscall_nr.h b/linux-user/alpha/syscall_nr.h
index 718222338..e3127df4a 100644
--- a/linux-user/alpha/syscall_nr.h
+++ b/linux-user/alpha/syscall_nr.h
@@ -412,10 +412,3 @@
#define TARGET_NR_timerfd 477
#define TARGET_NR_eventfd 478
-/* The following aliases are defined in order to match up with the
- standard i386 syscalls implemented in syscalls.c. */
-#define TARGET_NR_chown32 TARGET_NR_chown
-#define TARGET_NR_setuid32 TARGET_NR_setuid
-#define TARGET_NR_setgid32 TARGET_NR_setgid
-#define TARGET_NR_setfsuid32 TARGET_NR_setfsuid
-#define TARGET_NR_setfsgid32 TARGET_NR_setfsgid
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
index 0a87c4313..eebd93fc0 100644
--- a/linux-user/arm/nwfpe/fpa11.c
+++ b/linux-user/arm/nwfpe/fpa11.c
@@ -144,7 +144,7 @@ unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, CPUARMState* qregs)
#if 0
fprintf(stderr,"emulating FP insn 0x%08x, PC=0x%08x\n",
- opcode, qregs[REG_PC]);
+ opcode, qregs[ARM_REG_PC]);
#endif
fpa11 = GET_FPA11();
diff --git a/linux-user/arm/nwfpe/fpa11.h b/linux-user/arm/nwfpe/fpa11.h
index f17647bdb..002b3cbb8 100644
--- a/linux-user/arm/nwfpe/fpa11.h
+++ b/linux-user/arm/nwfpe/fpa11.h
@@ -111,7 +111,7 @@ static inline void writeConditionCodes(unsigned int x)
cpsr_write(user_registers,x,CPSR_NZCV);
}
-#define REG_PC 15
+#define ARM_REG_PC 15
unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, CPUARMState* qregs);
diff --git a/linux-user/arm/nwfpe/fpa11_cpdt.c b/linux-user/arm/nwfpe/fpa11_cpdt.c
index b12e27dcb..3e7a93825 100644
--- a/linux-user/arm/nwfpe/fpa11_cpdt.c
+++ b/linux-user/arm/nwfpe/fpa11_cpdt.c
@@ -220,7 +220,7 @@ static unsigned int PerformLDF(const unsigned int opcode)
//printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
pBase = readRegister(getRn(opcode));
- if (REG_PC == getRn(opcode))
+ if (ARM_REG_PC == getRn(opcode))
{
pBase += 8;
write_back = 0;
@@ -256,7 +256,7 @@ static unsigned int PerformSTF(const unsigned int opcode)
SetRoundingMode(ROUND_TO_NEAREST);
pBase = readRegister(getRn(opcode));
- if (REG_PC == getRn(opcode))
+ if (ARM_REG_PC == getRn(opcode))
{
pBase += 8;
write_back = 0;
@@ -289,7 +289,7 @@ static unsigned int PerformLFM(const unsigned int opcode)
target_ulong pBase, pAddress, pFinal;
pBase = readRegister(getRn(opcode));
- if (REG_PC == getRn(opcode))
+ if (ARM_REG_PC == getRn(opcode))
{
pBase += 8;
write_back = 0;
@@ -322,7 +322,7 @@ static unsigned int PerformSFM(const unsigned int opcode)
target_ulong pBase, pAddress, pFinal;
pBase = readRegister(getRn(opcode));
- if (REG_PC == getRn(opcode))
+ if (ARM_REG_PC == getRn(opcode))
{
pBase += 8;
write_back = 0;
diff --git a/linux-user/arm/nwfpe/fpa11_cprt.c b/linux-user/arm/nwfpe/fpa11_cprt.c
index be54e9515..801189798 100644
--- a/linux-user/arm/nwfpe/fpa11_cprt.c
+++ b/linux-user/arm/nwfpe/fpa11_cprt.c
@@ -159,7 +159,7 @@ PerformComparisonOperation(floatx80 Fn, floatx80 Fm)
}
/* test for equal condition */
- if (floatx80_eq(Fn,Fm, &fpa11->fp_status))
+ if (floatx80_eq_quiet(Fn,Fm, &fpa11->fp_status))
{
flags |= CC_ZERO;
}
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 526aaa2a7..42b3ae372 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -112,7 +112,8 @@
IOCTL(SIOCADDMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCDELMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCSIFLINK, 0, TYPE_NULL)
- IOCTL(SIOCGIFCONF, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_ifconf)))
+ IOCTL_SPECIAL(SIOCGIFCONF, IOC_W | IOC_R, do_ioctl_ifconf,
+ MK_PTR(MK_STRUCT(STRUCT_ifconf)))
IOCTL(SIOCGIFENCAP, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SIOCSIFENCAP, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SIOCDARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
@@ -121,6 +122,7 @@
IOCTL(SIOCDRARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
IOCTL(SIOCSRARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
IOCTL(SIOCGRARP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
+ IOCTL(SIOCGIWNAME, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_char_ifreq)))
IOCTL(CDROMPAUSE, 0, TYPE_NULL)
IOCTL(CDROMSTART, 0, TYPE_NULL)
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 8dd398b9f..fe9326aa7 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -9,6 +9,7 @@
#include <sys/mount.h>
#include <sys/mman.h>
#include <unistd.h>
+#include <sched.h>
#include "qemu.h"
int do_strace=0;
@@ -63,6 +64,7 @@ UNUSED static void print_string(abi_long, int);
UNUSED static void print_raw_param(const char *, abi_long, int);
UNUSED static void print_timeval(abi_ulong, int);
UNUSED static void print_number(abi_long, int);
+UNUSED static void print_signal(abi_ulong, int);
/*
* Utility functions
@@ -117,6 +119,37 @@ if( cmd == val ) { \
gemu_log("%d",cmd);
}
+static void
+print_signal(abi_ulong arg, int last)
+{
+ const char *signal_name = NULL;
+ switch(arg) {
+ case TARGET_SIGHUP: signal_name = "SIGHUP"; break;
+ case TARGET_SIGINT: signal_name = "SIGINT"; break;
+ case TARGET_SIGQUIT: signal_name = "SIGQUIT"; break;
+ case TARGET_SIGILL: signal_name = "SIGILL"; break;
+ case TARGET_SIGABRT: signal_name = "SIGABRT"; break;
+ case TARGET_SIGFPE: signal_name = "SIGFPE"; break;
+ case TARGET_SIGKILL: signal_name = "SIGKILL"; break;
+ case TARGET_SIGSEGV: signal_name = "SIGSEGV"; break;
+ case TARGET_SIGPIPE: signal_name = "SIGPIPE"; break;
+ case TARGET_SIGALRM: signal_name = "SIGALRM"; break;
+ case TARGET_SIGTERM: signal_name = "SIGTERM"; break;
+ case TARGET_SIGUSR1: signal_name = "SIGUSR1"; break;
+ case TARGET_SIGUSR2: signal_name = "SIGUSR2"; break;
+ case TARGET_SIGCHLD: signal_name = "SIGCHLD"; break;
+ case TARGET_SIGCONT: signal_name = "SIGCONT"; break;
+ case TARGET_SIGSTOP: signal_name = "SIGSTOP"; break;
+ case TARGET_SIGTTIN: signal_name = "SIGTTIN"; break;
+ case TARGET_SIGTTOU: signal_name = "SIGTTOU"; break;
+ }
+ if (signal_name == NULL) {
+ print_raw_param("%ld", arg, 1);
+ return;
+ }
+ gemu_log("%s%s", signal_name, get_comma(last));
+}
+
#ifdef TARGET_NR__newselect
static void
print_fdset(int n, abi_ulong target_fds_addr)
@@ -427,6 +460,44 @@ UNUSED static struct flags fcntl_flags[] = {
FLAG_END,
};
+UNUSED static struct flags clone_flags[] = {
+ FLAG_GENERIC(CLONE_VM),
+ FLAG_GENERIC(CLONE_FS),
+ FLAG_GENERIC(CLONE_FILES),
+ FLAG_GENERIC(CLONE_SIGHAND),
+ FLAG_GENERIC(CLONE_PTRACE),
+ FLAG_GENERIC(CLONE_VFORK),
+ FLAG_GENERIC(CLONE_PARENT),
+ FLAG_GENERIC(CLONE_THREAD),
+ FLAG_GENERIC(CLONE_NEWNS),
+ FLAG_GENERIC(CLONE_SYSVSEM),
+ FLAG_GENERIC(CLONE_SETTLS),
+ FLAG_GENERIC(CLONE_PARENT_SETTID),
+ FLAG_GENERIC(CLONE_CHILD_CLEARTID),
+ FLAG_GENERIC(CLONE_DETACHED),
+ FLAG_GENERIC(CLONE_UNTRACED),
+ FLAG_GENERIC(CLONE_CHILD_SETTID),
+#if defined(CLONE_NEWUTS)
+ FLAG_GENERIC(CLONE_NEWUTS),
+#endif
+#if defined(CLONE_NEWIPC)
+ FLAG_GENERIC(CLONE_NEWIPC),
+#endif
+#if defined(CLONE_NEWUSER)
+ FLAG_GENERIC(CLONE_NEWUSER),
+#endif
+#if defined(CLONE_NEWPID)
+ FLAG_GENERIC(CLONE_NEWPID),
+#endif
+#if defined(CLONE_NEWNET)
+ FLAG_GENERIC(CLONE_NEWNET),
+#endif
+#if defined(CLONE_IO)
+ FLAG_GENERIC(CLONE_IO),
+#endif
+ FLAG_END,
+};
+
/*
* print_xxx utility functions. These are used to print syscall
* parameters in certain format. All of these have parameter
@@ -669,6 +740,39 @@ print_chmod(const struct syscallname *name,
}
#endif
+#ifdef TARGET_NR_clone
+static void
+print_clone(const struct syscallname *name,
+ abi_long arg0, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ print_syscall_prologue(name);
+#if defined(TARGET_M68K)
+ print_flags(clone_flags, arg0, 0);
+ print_raw_param("newsp=0x" TARGET_ABI_FMT_lx, arg1, 1);
+#elif defined(TARGET_SH4) || defined(TARGET_ALPHA)
+ print_flags(clone_flags, arg0, 0);
+ print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg1, 0);
+ print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0);
+ print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg3, 0);
+ print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg4, 1);
+#elif defined(TARGET_CRIS)
+ print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg0, 0);
+ print_flags(clone_flags, arg1, 0);
+ print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0);
+ print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg3, 0);
+ print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg4, 1);
+#else
+ print_flags(clone_flags, arg0, 0);
+ print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg1, 0);
+ print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0);
+ print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg3, 0);
+ print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg4, 1);
+#endif
+ print_syscall_epilogue(name);
+}
+#endif
+
#ifdef TARGET_NR_creat
static void
print_creat(const struct syscallname *name,
@@ -805,6 +909,28 @@ print_linkat(const struct syscallname *name,
}
#endif
+#ifdef TARGET_NR__llseek
+static void
+print__llseek(const struct syscallname *name,
+ abi_long arg0, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ const char *whence = "UNKNOWN";
+ print_syscall_prologue(name);
+ print_raw_param("%d", arg0, 0);
+ print_raw_param("%ld", arg1, 0);
+ print_raw_param("%ld", arg2, 0);
+ print_pointer(arg3, 0);
+ switch(arg4) {
+ case SEEK_SET: whence = "SEEK_SET"; break;
+ case SEEK_CUR: whence = "SEEK_CUR"; break;
+ case SEEK_END: whence = "SEEK_END"; break;
+ }
+ gemu_log("%s",whence);
+ print_syscall_epilogue(name);
+}
+#endif
+
#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) || \
defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64)
static void
@@ -875,6 +1001,40 @@ print_rmdir(const struct syscallname *name,
}
#endif
+#ifdef TARGET_NR_rt_sigaction
+static void
+print_rt_sigaction(const struct syscallname *name,
+ abi_long arg0, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ print_syscall_prologue(name);
+ print_signal(arg0, 0);
+ print_pointer(arg1, 0);
+ print_pointer(arg2, 1);
+ print_syscall_epilogue(name);
+}
+#endif
+
+#ifdef TARGET_NR_rt_sigprocmask
+static void
+print_rt_sigprocmask(const struct syscallname *name,
+ abi_long arg0, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ const char *how = "UNKNOWN";
+ print_syscall_prologue(name);
+ switch(arg0) {
+ case TARGET_SIG_BLOCK: how = "SIG_BLOCK"; break;
+ case TARGET_SIG_UNBLOCK: how = "SIG_UNBLOCK"; break;
+ case TARGET_SIG_SETMASK: how = "SIG_SETMASK"; break;
+ }
+ gemu_log("%s,",how);
+ print_pointer(arg1, 0);
+ print_pointer(arg2, 1);
+ print_syscall_epilogue(name);
+}
+#endif
+
#ifdef TARGET_NR_mknod
static void
print_mknod(const struct syscallname *name,
@@ -1298,6 +1458,19 @@ print_futex(const struct syscallname *name,
}
#endif
+#ifdef TARGET_NR_kill
+static void
+print_kill(const struct syscallname *name,
+ abi_long arg0, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ print_syscall_prologue(name);
+ print_raw_param("%d", arg0, 0);
+ print_signal(arg1, 1);
+ print_syscall_epilogue(name);
+}
+#endif
+
/*
* An array of all of the syscalls we know about
*/
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 563a67f0a..a7eeaef99 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -85,7 +85,7 @@
{ TARGET_NR_clock_settime, "clock_settime" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_clone
-{ TARGET_NR_clone, "clone" , NULL, NULL, NULL },
+{ TARGET_NR_clone, "clone" , NULL, print_clone, NULL },
#endif
#ifdef TARGET_NR_close
{ TARGET_NR_close, "close" , "%s(%d)", NULL, NULL },
@@ -292,7 +292,7 @@
{ TARGET_NR_getpgrp, "getpgrp" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_getpid
-{ TARGET_NR_getpid, "getpid" , NULL, NULL, NULL },
+{ TARGET_NR_getpid, "getpid" , "%s()", NULL, NULL },
#endif
#ifdef TARGET_NR_getpmsg
{ TARGET_NR_getpmsg, "getpmsg" , NULL, NULL, NULL },
@@ -418,7 +418,7 @@
{ TARGET_NR_keyctl, "keyctl" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_kill
-{ TARGET_NR_kill, "kill" , NULL, NULL, NULL },
+{ TARGET_NR_kill, "kill", NULL, print_kill, NULL },
#endif
#ifdef TARGET_NR_lchown
{ TARGET_NR_lchown, "lchown" , NULL, NULL, NULL },
@@ -448,7 +448,7 @@
{ TARGET_NR_llistxattr, "llistxattr" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR__llseek
-{ TARGET_NR__llseek, "_llseek" , NULL, NULL, NULL },
+{ TARGET_NR__llseek, "_llseek" , NULL, print__llseek, NULL },
#endif
#ifdef TARGET_NR_lock
{ TARGET_NR_lock, "lock" , NULL, NULL, NULL },
@@ -1063,13 +1063,13 @@
{ TARGET_NR_rmdir, "rmdir" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_rt_sigaction
-{ TARGET_NR_rt_sigaction, "rt_sigaction" , NULL, NULL, NULL },
+{ TARGET_NR_rt_sigaction, "rt_sigaction" , NULL, print_rt_sigaction, NULL },
#endif
#ifdef TARGET_NR_rt_sigpending
{ TARGET_NR_rt_sigpending, "rt_sigpending" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_rt_sigprocmask
-{ TARGET_NR_rt_sigprocmask, "rt_sigprocmask" , NULL, NULL, NULL },
+{ TARGET_NR_rt_sigprocmask, "rt_sigprocmask" , NULL, print_rt_sigprocmask, NULL },
#endif
#ifdef TARGET_NR_rt_sigqueueinfo
{ TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, NULL, NULL },
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index bb0999d1a..279cef3cd 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -59,6 +59,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
//#include <sys/user.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
+#include <linux/wireless.h>
#include <qemu-common.h>
#ifdef TARGET_GPROF
#include <sys/gmon.h>
@@ -196,7 +197,8 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
-#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
+#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || \
+ defined(__s390x__)
#define __NR__llseek __NR_lseek
#endif
@@ -326,7 +328,7 @@ static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode)
return (fchmodat(dirfd, pathname, mode, 0));
}
#endif
-#if defined(TARGET_NR_fchownat) && defined(USE_UID16)
+#if defined(TARGET_NR_fchownat)
static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
gid_t group, int flags)
{
@@ -435,7 +437,7 @@ _syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)
#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
_syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)
#endif
-#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
+#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
uid_t,owner,gid_t,group,int,flags)
#endif
@@ -2970,7 +2972,6 @@ static abi_long do_ipc(unsigned int call, int first,
#endif
/* kernel structure types definitions */
-#define IFNAMSIZ 16
#define STRUCT(name, ...) STRUCT_ ## name,
#define STRUCT_SPECIAL(name) STRUCT_ ## name,
@@ -3095,6 +3096,100 @@ static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
}
#endif
+static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, abi_long cmd, abi_long arg)
+{
+ const argtype *arg_type = ie->arg_type;
+ int target_size;
+ void *argptr;
+ int ret;
+ struct ifconf *host_ifconf;
+ uint32_t outbufsz;
+ const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
+ int target_ifreq_size;
+ int nb_ifreq;
+ int free_buf = 0;
+ int i;
+ int target_ifc_len;
+ abi_long target_ifc_buf;
+ int host_ifc_len;
+ char *host_ifc_buf;
+
+ assert(arg_type[0] == TYPE_PTR);
+ assert(ie->access == IOC_RW);
+
+ arg_type++;
+ target_size = thunk_type_size(arg_type, 0);
+
+ argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+ if (!argptr)
+ return -TARGET_EFAULT;
+ thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+ unlock_user(argptr, arg, 0);
+
+ host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
+ target_ifc_len = host_ifconf->ifc_len;
+ target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
+
+ target_ifreq_size = thunk_type_size(ifreq_arg_type, 0);
+ nb_ifreq = target_ifc_len / target_ifreq_size;
+ host_ifc_len = nb_ifreq * sizeof(struct ifreq);
+
+ outbufsz = sizeof(*host_ifconf) + host_ifc_len;
+ if (outbufsz > MAX_STRUCT_SIZE) {
+ /* We can't fit all the extents into the fixed size buffer.
+ * Allocate one that is large enough and use it instead.
+ */
+ host_ifconf = malloc(outbufsz);
+ if (!host_ifconf) {
+ return -TARGET_ENOMEM;
+ }
+ memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
+ free_buf = 1;
+ }
+ host_ifc_buf = (char*)host_ifconf + sizeof(*host_ifconf);
+
+ host_ifconf->ifc_len = host_ifc_len;
+ host_ifconf->ifc_buf = host_ifc_buf;
+
+ ret = get_errno(ioctl(fd, ie->host_cmd, host_ifconf));
+ if (!is_error(ret)) {
+ /* convert host ifc_len to target ifc_len */
+
+ nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
+ target_ifc_len = nb_ifreq * target_ifreq_size;
+ host_ifconf->ifc_len = target_ifc_len;
+
+ /* restore target ifc_buf */
+
+ host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
+
+ /* copy struct ifconf to target user */
+
+ argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
+ if (!argptr)
+ return -TARGET_EFAULT;
+ thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
+ unlock_user(argptr, arg, target_size);
+
+ /* copy ifreq[] to target user */
+
+ argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
+ for (i = 0; i < nb_ifreq ; i++) {
+ thunk_convert(argptr + i * target_ifreq_size,
+ host_ifc_buf + i * sizeof(struct ifreq),
+ ifreq_arg_type, THUNK_TARGET);
+ }
+ unlock_user(argptr, target_ifc_buf, target_ifc_len);
+ }
+
+ if (free_buf) {
+ free(host_ifconf);
+ }
+
+ return ret;
+}
+
static IOCTLEntry ioctl_entries[] = {
#define IOCTL(cmd, access, ...) \
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
@@ -3690,9 +3785,9 @@ static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
#endif /* defined(TARGET_I386) */
-#if defined(CONFIG_USE_NPTL)
+#define NEW_STACK_SIZE 0x40000
-#define NEW_STACK_SIZE PTHREAD_STACK_MIN
+#if defined(CONFIG_USE_NPTL)
static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
typedef struct {
@@ -3736,9 +3831,6 @@ static void *clone_func(void *arg)
return NULL;
}
#else
-/* this stack is the equivalent of the kernel stack associated with a
- thread/process */
-#define NEW_STACK_SIZE 8192
static int clone_func(void *arg)
{
@@ -4072,7 +4164,31 @@ static inline int low2highgid(int gid)
else
return gid;
}
-
+static inline int tswapid(int id)
+{
+ return tswap16(id);
+}
+#else /* !USE_UID16 */
+static inline int high2lowuid(int uid)
+{
+ return uid;
+}
+static inline int high2lowgid(int gid)
+{
+ return gid;
+}
+static inline int low2highuid(int uid)
+{
+ return uid;
+}
+static inline int low2highgid(int gid)
+{
+ return gid;
+}
+static inline int tswapid(int id)
+{
+ return tswap32(id);
+}
#endif /* USE_UID16 */
void syscall_init(void)
@@ -6384,20 +6500,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
if (!is_error(ret)) {
- if (arg2 > ret) {
- /* Zero out any extra space kernel didn't fill */
- unsigned long zero = arg2 - ret;
- p = alloca(zero);
- memset(p, 0, zero);
- if (copy_to_user(arg3 + zero, p, zero)) {
- goto efault;
- }
- arg2 = ret;
- }
- if (copy_to_user(arg3, mask, arg2)) {
+ if (copy_to_user(arg3, mask, ret)) {
goto efault;
}
- ret = arg2;
}
}
break;
@@ -6673,25 +6778,32 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = host_to_target_stat64(cpu_env, arg3, &st);
break;
#endif
-#ifdef USE_UID16
case TARGET_NR_lchown:
if (!(p = lock_user_string(arg1)))
goto efault;
ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
unlock_user(p, arg1, 0);
break;
+#ifdef TARGET_NR_getuid
case TARGET_NR_getuid:
ret = get_errno(high2lowuid(getuid()));
break;
+#endif
+#ifdef TARGET_NR_getgid
case TARGET_NR_getgid:
ret = get_errno(high2lowgid(getgid()));
break;
+#endif
+#ifdef TARGET_NR_geteuid
case TARGET_NR_geteuid:
ret = get_errno(high2lowuid(geteuid()));
break;
+#endif
+#ifdef TARGET_NR_getegid
case TARGET_NR_getegid:
ret = get_errno(high2lowgid(getegid()));
break;
+#endif
case TARGET_NR_setreuid:
ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
break;
@@ -6701,7 +6813,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_getgroups:
{
int gidsetsize = arg1;
- uint16_t *target_grouplist;
+ target_id *target_grouplist;
gid_t *grouplist;
int i;
@@ -6714,7 +6826,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!target_grouplist)
goto efault;
for(i = 0;i < ret; i++)
- target_grouplist[i] = tswap16(grouplist[i]);
+ target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
unlock_user(target_grouplist, arg2, gidsetsize * 2);
}
}
@@ -6722,7 +6834,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_setgroups:
{
int gidsetsize = arg1;
- uint16_t *target_grouplist;
+ target_id *target_grouplist;
gid_t *grouplist;
int i;
@@ -6733,7 +6845,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
goto fail;
}
for(i = 0;i < gidsetsize; i++)
- grouplist[i] = tswap16(target_grouplist[i]);
+ grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
unlock_user(target_grouplist, arg2, 0);
ret = get_errno(setgroups(gidsetsize, grouplist));
}
@@ -6809,7 +6921,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_setfsgid:
ret = get_errno(setfsgid(arg1));
break;
-#endif /* USE_UID16 */
#ifdef TARGET_NR_lchown32
case TARGET_NR_lchown32:
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index bde89213d..e05ddf912 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -49,9 +49,12 @@
#define TARGET_IOC_TYPEBITS 8
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
- || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS) || defined(TARGET_PPC) || defined(TARGET_MIPS)
+ || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
/* 16 bit uid wrappers emulation */
#define USE_UID16
+#define target_id uint16_t
+#else
+#define target_id uint32_t
#endif
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
@@ -765,6 +768,9 @@ struct target_pollfd {
#define TARGET_SIOCADDDLCI 0x8980 /* Create new DLCI device */
#define TARGET_SIOCDELDLCI 0x8981 /* Delete DLCI device */
+/* From <linux/wireless.h> */
+
+#define TARGET_SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
/* From <linux/fs.h> */
diff --git a/migration-exec.c b/migration-exec.c
index 14718dd1d..4b7aad8b6 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -17,7 +17,6 @@
#include "qemu_socket.h"
#include "migration.h"
#include "qemu-char.h"
-#include "sysemu.h"
#include "buffered_file.h"
#include "block.h"
#include <sys/types.h>
diff --git a/migration-fd.c b/migration-fd.c
index 6d1450563..66d51c1cc 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -16,7 +16,6 @@
#include "migration.h"
#include "monitor.h"
#include "qemu-char.h"
-#include "sysemu.h"
#include "buffered_file.h"
#include "block.h"
#include "qemu_socket.h"
diff --git a/migration-tcp.c b/migration-tcp.c
index e8dff9d71..d3d80c970 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -15,7 +15,6 @@
#include "qemu_socket.h"
#include "migration.h"
#include "qemu-char.h"
-#include "sysemu.h"
#include "buffered_file.h"
#include "block.h"
diff --git a/migration-unix.c b/migration-unix.c
index 8b967f293..c8625c7f6 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -15,7 +15,6 @@
#include "qemu_socket.h"
#include "migration.h"
#include "qemu-char.h"
-#include "sysemu.h"
#include "buffered_file.h"
#include "block.h"
diff --git a/migration.h b/migration.h
index 21707922e..050c56c5a 100644
--- a/migration.h
+++ b/migration.h
@@ -139,4 +139,13 @@ void add_migration_state_change_notifier(Notifier *notify);
void remove_migration_state_change_notifier(Notifier *notify);
int get_migration_state(void);
+uint64_t ram_bytes_remaining(void);
+uint64_t ram_bytes_transferred(void);
+uint64_t ram_bytes_total(void);
+
+int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque);
+int ram_load(QEMUFile *f, void *opaque, int version_id);
+
+extern int incoming_expected;
+
#endif
diff --git a/net.c b/net.c
index 8d6a55537..4f777c3da 100644
--- a/net.c
+++ b/net.c
@@ -32,7 +32,6 @@
#include "net/vde.h"
#include "net/util.h"
#include "monitor.h"
-#include "sysemu.h"
#include "qemu-common.h"
#include "qemu_socket.h"
#include "hw/qdev.h"
diff --git a/net/dump.c b/net/dump.c
index 83eda0fcc..0d0cbb259 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -24,9 +24,9 @@
#include "dump.h"
#include "qemu-common.h"
-#include "sysemu.h"
#include "qemu-error.h"
#include "qemu-log.h"
+#include "qemu-timer.h"
typedef struct DumpState {
VLANClientState nc;
diff --git a/net/slirp.c b/net/slirp.c
index b41c60a39..e387a116a 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -30,7 +30,6 @@
#endif
#include "net.h"
#include "monitor.h"
-#include "sysemu.h"
#include "qemu_socket.h"
#include "slirp/libslirp.h"
diff --git a/net/vde.c b/net/vde.c
index 0b46fa640..ac48ab2f0 100644
--- a/net/vde.c
+++ b/net/vde.c
@@ -31,7 +31,6 @@
#include "qemu-char.h"
#include "qemu-common.h"
#include "qemu-option.h"
-#include "sysemu.h"
typedef struct VDEState {
VLANClientState nc;
diff --git a/osdep.c b/osdep.c
index 327583baf..56e6963f1 100644
--- a/osdep.c
+++ b/osdep.c
@@ -46,7 +46,6 @@ extern int madvise(caddr_t, size_t, int);
#include "qemu-common.h"
#include "trace.h"
-#include "sysemu.h"
#include "qemu_socket.h"
int qemu_madvise(void *addr, size_t len, int advice)
diff --git a/pc-bios/README b/pc-bios/README
index 646a31a31..fe221a940 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -18,16 +18,15 @@
https://github.com/dgibson/SLOF, and the image currently in qemu is
built from git tag qemu-slof-20110323.
-- The PXE roms come from Rom-o-Matic gPXE 0.9.9 with BANNER_TIMEOUT=0
-
- e1000 8086:100E
- eepro100 8086:1209 (also used for 8086:1229 and 8086:2449)
- ns8390 1050:0940
- pcnet32 1022:2000
- rtl8139 10ec:8139
- virtio 1af4:1000
-
- http://rom-o-matic.net/
+- The PXE roms come from the iPXE project. Built with BANNER_TIME 0.
+ Sources available at http://ipxe.org. Vendor:Device ID -> ROM mapping:
+
+ 8086:100e -> pxe-e1000.rom
+ 8086:1209 -> pxe-eepro100.rom
+ 1050:0940 -> pxe-ne2k_pci.rom
+ 1022:2000 -> pxe-pcnet.rom
+ 10ec:8139 -> pxe-rtl8139.rom
+ 1af4:1000 -> pxe-virtio.rom
- The S390 zipl loader is an addition to the official IBM s390-tools
package. That fork is maintained in its own git repository at:
diff --git a/pc-bios/gpxe-eepro100-80861209.rom b/pc-bios/gpxe-eepro100-80861209.rom
deleted file mode 100644
index 2ca59ec36..000000000
--- a/pc-bios/gpxe-eepro100-80861209.rom
+++ /dev/null
Binary files differ
diff --git a/pc-bios/pxe-e1000.bin b/pc-bios/pxe-e1000.bin
deleted file mode 100644
index 7ac744eb3..000000000
--- a/pc-bios/pxe-e1000.bin
+++ /dev/null
Binary files differ
diff --git a/pc-bios/pxe-e1000.rom b/pc-bios/pxe-e1000.rom
new file mode 100644
index 000000000..2e5f8b28a
--- /dev/null
+++ b/pc-bios/pxe-e1000.rom
Binary files differ
diff --git a/pc-bios/pxe-eepro100.rom b/pc-bios/pxe-eepro100.rom
new file mode 100644
index 000000000..d292e8fec
--- /dev/null
+++ b/pc-bios/pxe-eepro100.rom
Binary files differ
diff --git a/pc-bios/pxe-ne2k_pci.bin b/pc-bios/pxe-ne2k_pci.bin
deleted file mode 100644
index 5cb68ab2d..000000000
--- a/pc-bios/pxe-ne2k_pci.bin
+++ /dev/null
Binary files differ
diff --git a/pc-bios/pxe-ne2k_pci.rom b/pc-bios/pxe-ne2k_pci.rom
new file mode 100644
index 000000000..62010cbc7
--- /dev/null
+++ b/pc-bios/pxe-ne2k_pci.rom
Binary files differ
diff --git a/pc-bios/pxe-pcnet.bin b/pc-bios/pxe-pcnet.bin
deleted file mode 100644
index 7a54baba1..000000000
--- a/pc-bios/pxe-pcnet.bin
+++ /dev/null
Binary files differ
diff --git a/pc-bios/pxe-pcnet.rom b/pc-bios/pxe-pcnet.rom
new file mode 100644
index 000000000..512d6d433
--- /dev/null
+++ b/pc-bios/pxe-pcnet.rom
Binary files differ
diff --git a/pc-bios/pxe-rtl8139.bin b/pc-bios/pxe-rtl8139.bin
deleted file mode 100644
index db7d76d9c..000000000
--- a/pc-bios/pxe-rtl8139.bin
+++ /dev/null
Binary files differ
diff --git a/pc-bios/pxe-rtl8139.rom b/pc-bios/pxe-rtl8139.rom
new file mode 100644
index 000000000..67c77fbf7
--- /dev/null
+++ b/pc-bios/pxe-rtl8139.rom
Binary files differ
diff --git a/pc-bios/pxe-virtio.bin b/pc-bios/pxe-virtio.bin
deleted file mode 100644
index 6dde514c7..000000000
--- a/pc-bios/pxe-virtio.bin
+++ /dev/null
Binary files differ
diff --git a/pc-bios/pxe-virtio.rom b/pc-bios/pxe-virtio.rom
new file mode 100644
index 000000000..b1ec90962
--- /dev/null
+++ b/pc-bios/pxe-virtio.rom
Binary files differ
diff --git a/qemu-char.c b/qemu-char.c
index 03858d4ef..5e04a20b8 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -197,9 +197,9 @@ void qemu_chr_add_handlers(CharDriverState *s,
IOEventHandler *fd_event,
void *opaque)
{
- if (!opaque) {
+ if (!opaque && !fd_can_read && !fd_read && !fd_event) {
/* chr driver being released. */
- s->assigned = 0;
+ ++s->avail_connections;
}
s->chr_can_read = fd_can_read;
s->chr_read = fd_read;
@@ -480,6 +480,9 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
chr->chr_write = mux_chr_write;
chr->chr_update_read_handler = mux_chr_update_read_handler;
chr->chr_accept_input = mux_chr_accept_input;
+ /* Frontend guest-open / -close notification is not support with muxes */
+ chr->chr_guest_open = NULL;
+ chr->chr_guest_close = NULL;
/* Muxes are always open on creation */
qemu_chr_generic_open(chr);
@@ -2544,7 +2547,10 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
snprintf(base->label, len, "%s-base", qemu_opts_id(opts));
chr = qemu_chr_open_mux(base);
chr->filename = base->filename;
+ chr->avail_connections = MAX_MUX;
QTAILQ_INSERT_TAIL(&chardevs, chr, next);
+ } else {
+ chr->avail_connections = 1;
}
chr->label = qemu_strdup(qemu_opts_id(opts));
return chr;
@@ -2579,6 +2585,20 @@ void qemu_chr_set_echo(struct CharDriverState *chr, bool echo)
}
}
+void qemu_chr_guest_open(struct CharDriverState *chr)
+{
+ if (chr->chr_guest_open) {
+ chr->chr_guest_open(chr);
+ }
+}
+
+void qemu_chr_guest_close(struct CharDriverState *chr)
+{
+ if (chr->chr_guest_close) {
+ chr->chr_guest_close(chr);
+ }
+}
+
void qemu_chr_close(CharDriverState *chr)
{
QTAILQ_REMOVE(&chardevs, chr, next);
diff --git a/qemu-char.h b/qemu-char.h
index fb96eef3d..892c6da9a 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -65,12 +65,14 @@ struct CharDriverState {
void (*chr_close)(struct CharDriverState *chr);
void (*chr_accept_input)(struct CharDriverState *chr);
void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
+ void (*chr_guest_open)(struct CharDriverState *chr);
+ void (*chr_guest_close)(struct CharDriverState *chr);
void *opaque;
QEMUBH *bh;
char *label;
char *filename;
int opened;
- int assigned; /* chardev assigned to a device */
+ int avail_connections;
QTAILQ_ENTRY(CharDriverState) next;
};
@@ -79,6 +81,8 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
void (*init)(struct CharDriverState *s));
CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s));
void qemu_chr_set_echo(struct CharDriverState *chr, bool echo);
+void qemu_chr_guest_open(struct CharDriverState *chr);
+void qemu_chr_guest_close(struct CharDriverState *chr);
void qemu_chr_close(CharDriverState *chr);
void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
GCC_FMT_ATTR(2, 3);
diff --git a/qemu-common.h b/qemu-common.h
index 82e27c18d..f9f705da8 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -12,6 +12,7 @@
#endif
#define QEMU_BUILD_BUG_ON(x) typedef char __build_bug_on__##__LINE__[(x)?-1:1];
+#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
typedef struct QEMUTimer QEMUTimer;
typedef struct QEMUFile QEMUFile;
@@ -39,6 +40,14 @@ typedef struct Monitor Monitor;
#include <sys/time.h>
#include <assert.h>
+#ifdef _WIN32
+#include "qemu-os-win32.h"
+#endif
+
+#ifdef CONFIG_POSIX
+#include "qemu-os-posix.h"
+#endif
+
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
@@ -298,6 +307,7 @@ void qemu_notify_event(void);
void qemu_cpu_kick(void *env);
void qemu_cpu_kick_self(void);
int qemu_cpu_is_self(void *env);
+bool all_cpu_threads_idle(void);
/* work queue */
struct qemu_work_item {
@@ -338,6 +348,16 @@ void qemu_progress_init(int enabled, float min_skip);
void qemu_progress_end(void);
void qemu_progress_print(float percent, int max);
+#define QEMU_FILE_TYPE_BIOS 0
+#define QEMU_FILE_TYPE_KEYMAP 1
+char *qemu_find_file(int type, const char *name);
+
+/* OS specific functions */
+void os_setup_early_signal_handling(void);
+char *os_find_datadir(const char *argv0);
+void os_parse_cmd_args(int index, const char *optarg);
+void os_pidfile_error(void);
+
/* Convert a byte between binary and BCD. */
static inline uint8_t to_bcd(uint8_t val)
{
diff --git a/qemu-config.c b/qemu-config.c
index 6d9c23881..844c62deb 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -2,7 +2,6 @@
#include "qemu-error.h"
#include "qemu-option.h"
#include "qemu-config.h"
-#include "sysemu.h"
#include "hw/qdev.h"
static QemuOptsList qemu_drive_opts = {
diff --git a/qemu-error.c b/qemu-error.c
index 5a35e7c1c..41c191d52 100644
--- a/qemu-error.c
+++ b/qemu-error.c
@@ -12,7 +12,6 @@
#include <stdio.h>
#include "monitor.h"
-#include "sysemu.h"
/*
* Print to current monitor if we have one, else to stderr.
diff --git a/qemu-img.c b/qemu-img.c
index d9c2c12fa..e8251234b 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1240,7 +1240,7 @@ static int img_rebase(int argc, char **argv)
}
}
- if ((optind >= argc) || !out_baseimg) {
+ if ((optind >= argc) || (!unsafe && !out_baseimg)) {
help();
}
filename = argv[optind++];
@@ -1442,6 +1442,16 @@ static int img_resize(int argc, char **argv)
{ NULL }
};
+ /* Remove size from argv manually so that negative numbers are not treated
+ * as options by getopt. */
+ if (argc < 3) {
+ help();
+ return 1;
+ }
+
+ size = argv[--argc];
+
+ /* Parse getopt arguments */
fmt = NULL;
for(;;) {
c = getopt(argc, argv, "f:h");
@@ -1458,11 +1468,10 @@ static int img_resize(int argc, char **argv)
break;
}
}
- if (optind + 1 >= argc) {
+ if (optind >= argc) {
help();
}
filename = argv[optind++];
- size = argv[optind++];
/* Choose grow, shrink, or absolute resize mode */
switch (size[0]) {
diff --git a/qemu-options.hx b/qemu-options.hx
index 66fffe30f..443ed65c7 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -939,8 +939,8 @@ a lot of bandwidth at the expense of quality.
Disable adaptive encodings. Adaptive encodings are enabled by default.
An adaptive encoding will try to detect frequently updated screen regions,
and send updates in these regions using a lossy encoding (like JPEG).
-This can be really helpfull to save bandwidth when playing videos. Disabling
-adaptive encodings allow to restore the original static behavior of encodings
+This can be really helpful to save bandwidth when playing videos. Disabling
+adaptive encodings allows to restore the original static behavior of encodings
like Tight.
@end table
@@ -1154,7 +1154,7 @@ Assign symbolic name for use in monitor commands.
@item net=@var{addr}[/@var{mask}]
Set IP network address the guest will see. Optionally specify the netmask,
either in the form a.b.c.d or as number of valid top-most bits. Default is
-10.0.2.0/8.
+10.0.2.0/24.
@item host=@var{addr}
Specify the guest-visible address of the host. Default is the 2nd IP in the
@@ -1170,7 +1170,7 @@ Specifies the client hostname reported by the builtin DHCP server.
@item dhcpstart=@var{addr}
Specify the first of the 16 IPs the built-in DHCP server can assign. Default
-is the 16th to 31st IP in the guest network, i.e. x.x.x.16 to x.x.x.31.
+is the 15th to 31st IP in the guest network, i.e. x.x.x.15 to x.x.x.31.
@item dns=@var{addr}
Specify the guest-visible address of the virtual nameserver. The address must
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 1a07e5e26..ed2753d1b 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -26,6 +26,9 @@
#ifndef QEMU_OS_WIN32_H
#define QEMU_OS_WIN32_H
+#include <windows.h>
+#include <winsock2.h>
+
/* Polling handling */
/* return TRUE if no sleep should be done afterwards */
diff --git a/qemu-progress.c b/qemu-progress.c
index 656e065b1..a4894c0df 100644
--- a/qemu-progress.c
+++ b/qemu-progress.c
@@ -26,15 +26,18 @@
#include "osdep.h"
#include "sysemu.h"
#include <stdio.h>
+#include <signal.h>
struct progress_state {
- int enabled;
float current;
float last_print;
float min_skip;
+ void (*print)(void);
+ void (*end)(void);
};
static struct progress_state state;
+static volatile sig_atomic_t print_pending;
/*
* Simple progress print function.
@@ -43,28 +46,69 @@ static struct progress_state state;
*/
static void progress_simple_print(void)
{
- if (state.enabled) {
- printf(" (%3.2f/100%%)\r", state.current);
- fflush(stdout);
- }
+ printf(" (%3.2f/100%%)\r", state.current);
+ fflush(stdout);
}
static void progress_simple_end(void)
{
- if (state.enabled) {
- printf("\n");
+ printf("\n");
+}
+
+static void progress_simple_init(void)
+{
+ state.print = progress_simple_print;
+ state.end = progress_simple_end;
+}
+
+#ifdef CONFIG_POSIX
+static void sigusr_print(int signal)
+{
+ print_pending = 1;
+}
+#endif
+
+static void progress_dummy_print(void)
+{
+ if (print_pending) {
+ fprintf(stderr, " (%3.2f/100%%)\n", state.current);
+ print_pending = 0;
}
}
+static void progress_dummy_end(void)
+{
+}
+
+static void progress_dummy_init(void)
+{
+#ifdef CONFIG_POSIX
+ struct sigaction action;
+
+ memset(&action, 0, sizeof(action));
+ sigfillset(&action.sa_mask);
+ action.sa_handler = sigusr_print;
+ action.sa_flags = 0;
+ sigaction(SIGUSR1, &action, NULL);
+#endif
+
+ state.print = progress_dummy_print;
+ state.end = progress_dummy_end;
+}
+
void qemu_progress_init(int enabled, float min_skip)
{
- state.enabled = enabled;
state.min_skip = min_skip;
+ if (enabled) {
+ progress_simple_init();
+ } else {
+ progress_dummy_init();
+ }
}
void qemu_progress_end(void)
{
- progress_simple_end();
+ state.end();
}
void qemu_progress_print(float percent, int max)
@@ -84,6 +128,6 @@ void qemu_progress_print(float percent, int max)
if (current > (state.last_print + state.min_skip) ||
(current == 100) || (current == 0)) {
state.last_print = state.current;
- progress_simple_print();
+ state.print();
}
}
diff --git a/qemu-timer.c b/qemu-timer.c
index 50f1943af..4141b6edb 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -110,9 +110,12 @@ static int64_t cpu_get_clock(void)
}
}
+#ifndef CONFIG_IOTHREAD
static int64_t qemu_icount_delta(void)
{
- if (use_icount == 1) {
+ if (!use_icount) {
+ return 5000 * (int64_t) 1000000;
+ } else if (use_icount == 1) {
/* When not using an adaptive execution frequency
we tend to get badly out of sync with real time,
so just delay for a reasonable amount of time. */
@@ -121,6 +124,7 @@ static int64_t qemu_icount_delta(void)
return cpu_get_icount() - cpu_get_clock();
}
}
+#endif
/* enable cpu_get_ticks() */
void cpu_enable_ticks(void)
@@ -153,6 +157,8 @@ void cpu_disable_ticks(void)
struct QEMUClock {
int type;
int enabled;
+
+ QEMUTimer *warp_timer;
};
struct QEMUTimer {
@@ -169,14 +175,23 @@ struct qemu_alarm_timer {
int (*start)(struct qemu_alarm_timer *t);
void (*stop)(struct qemu_alarm_timer *t);
void (*rearm)(struct qemu_alarm_timer *t);
- void *priv;
-
+#if defined(__linux__)
+ int fd;
+ timer_t timer;
+#elif defined(_WIN32)
+ HANDLE timer;
+#endif
char expired;
char pending;
};
static struct qemu_alarm_timer *alarm_timer;
+static bool qemu_timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
+{
+ return timer_head && (timer_head->expire_time <= current_time);
+}
+
int qemu_alarm_pending(void)
{
return alarm_timer->pending;
@@ -200,6 +215,10 @@ static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
#ifdef _WIN32
+static int mm_start_timer(struct qemu_alarm_timer *t);
+static void mm_stop_timer(struct qemu_alarm_timer *t);
+static void mm_rearm_timer(struct qemu_alarm_timer *t);
+
static int win32_start_timer(struct qemu_alarm_timer *t);
static void win32_stop_timer(struct qemu_alarm_timer *t);
static void win32_rearm_timer(struct qemu_alarm_timer *t);
@@ -284,18 +303,18 @@ static struct qemu_alarm_timer alarm_timers[] = {
#ifndef _WIN32
#ifdef __linux__
{"dynticks", dynticks_start_timer,
- dynticks_stop_timer, dynticks_rearm_timer, NULL},
+ dynticks_stop_timer, dynticks_rearm_timer},
/* HPET - if available - is preferred */
- {"hpet", hpet_start_timer, hpet_stop_timer, NULL, NULL},
+ {"hpet", hpet_start_timer, hpet_stop_timer, NULL},
/* ...otherwise try RTC */
- {"rtc", rtc_start_timer, rtc_stop_timer, NULL, NULL},
+ {"rtc", rtc_start_timer, rtc_stop_timer, NULL},
#endif
- {"unix", unix_start_timer, unix_stop_timer, NULL, NULL},
+ {"unix", unix_start_timer, unix_stop_timer, NULL},
#else
- {"dynticks", win32_start_timer,
- win32_stop_timer, win32_rearm_timer, NULL},
- {"win32", win32_start_timer,
- win32_stop_timer, NULL, NULL},
+ {"mmtimer", mm_start_timer, mm_stop_timer, NULL},
+ {"mmtimer2", mm_start_timer, mm_stop_timer, mm_rearm_timer},
+ {"dynticks", win32_start_timer, win32_stop_timer, win32_rearm_timer},
+ {"win32", win32_start_timer, win32_stop_timer, NULL},
#endif
{NULL, }
};
@@ -386,6 +405,90 @@ void qemu_clock_enable(QEMUClock *clock, int enabled)
clock->enabled = enabled;
}
+static int64_t vm_clock_warp_start;
+
+static void icount_warp_rt(void *opaque)
+{
+ if (vm_clock_warp_start == -1) {
+ return;
+ }
+
+ if (vm_running) {
+ int64_t clock = qemu_get_clock_ns(rt_clock);
+ int64_t warp_delta = clock - vm_clock_warp_start;
+ if (use_icount == 1) {
+ qemu_icount_bias += warp_delta;
+ } else {
+ /*
+ * In adaptive mode, do not let the vm_clock run too
+ * far ahead of real time.
+ */
+ int64_t cur_time = cpu_get_clock();
+ int64_t cur_icount = qemu_get_clock_ns(vm_clock);
+ int64_t delta = cur_time - cur_icount;
+ qemu_icount_bias += MIN(warp_delta, delta);
+ }
+ if (qemu_timer_expired(active_timers[QEMU_CLOCK_VIRTUAL],
+ qemu_get_clock_ns(vm_clock))) {
+ qemu_notify_event();
+ }
+ }
+ vm_clock_warp_start = -1;
+}
+
+void qemu_clock_warp(QEMUClock *clock)
+{
+ int64_t deadline;
+
+ if (!clock->warp_timer) {
+ return;
+ }
+
+ /*
+ * There are too many global variables to make the "warp" behavior
+ * applicable to other clocks. But a clock argument removes the
+ * need for if statements all over the place.
+ */
+ assert(clock == vm_clock);
+
+ /*
+ * If the CPUs have been sleeping, advance the vm_clock timer now. This
+ * ensures that the deadline for the timer is computed correctly below.
+ * This also makes sure that the insn counter is synchronized before the
+ * CPU starts running, in case the CPU is woken by an event other than
+ * the earliest vm_clock timer.
+ */
+ icount_warp_rt(NULL);
+ if (!all_cpu_threads_idle() || !active_timers[clock->type]) {
+ qemu_del_timer(clock->warp_timer);
+ return;
+ }
+
+ vm_clock_warp_start = qemu_get_clock_ns(rt_clock);
+ deadline = qemu_next_icount_deadline();
+ if (deadline > 0) {
+ /*
+ * Ensure the vm_clock proceeds even when the virtual CPU goes to
+ * sleep. Otherwise, the CPU might be waiting for a future timer
+ * interrupt to wake it up, but the interrupt never comes because
+ * the vCPU isn't running any insns and thus doesn't advance the
+ * vm_clock.
+ *
+ * An extreme solution for this problem would be to never let VCPUs
+ * sleep in icount mode if there is a pending vm_clock timer; rather
+ * time could just advance to the next vm_clock event. Instead, we
+ * do stop VCPUs and only advance vm_clock after some "real" time,
+ * (related to the time left until the next event) has passed. This
+ * rt_clock timer will do this. This avoids that the warps are too
+ * visible externally---for example, you will not be sending network
+ * packets continously instead of every 100ms.
+ */
+ qemu_mod_timer(clock->warp_timer, vm_clock_warp_start + deadline);
+ } else {
+ qemu_notify_event();
+ }
+}
+
QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
QEMUTimerCB *cb, void *opaque)
{
@@ -438,10 +541,9 @@ static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
pt = &active_timers[ts->clock->type];
for(;;) {
t = *pt;
- if (!t)
- break;
- if (t->expire_time > expire_time)
+ if (!qemu_timer_expired_ns(t, expire_time)) {
break;
+ }
pt = &t->next;
}
ts->expire_time = expire_time;
@@ -454,8 +556,10 @@ static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
qemu_rearm_alarm_timer(alarm_timer);
}
/* Interrupt execution to force deadline recalculation. */
- if (use_icount)
+ qemu_clock_warp(ts->clock);
+ if (use_icount) {
qemu_notify_event();
+ }
}
}
@@ -478,9 +582,7 @@ int qemu_timer_pending(QEMUTimer *ts)
int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
{
- if (!timer_head)
- return 0;
- return (timer_head->expire_time <= current_time * timer_head->scale);
+ return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);
}
static void qemu_run_timers(QEMUClock *clock)
@@ -495,8 +597,9 @@ static void qemu_run_timers(QEMUClock *clock)
ptimer_head = &active_timers[clock->type];
for(;;) {
ts = *ptimer_head;
- if (!ts || ts->expire_time > current_time)
+ if (!qemu_timer_expired_ns(ts, current_time)) {
break;
+ }
/* remove timer from the list before calling the callback */
*ptimer_head = ts->next;
ts->next = NULL;
@@ -576,6 +679,10 @@ void configure_icount(const char *option)
if (!option)
return;
+#ifdef CONFIG_IOTHREAD
+ vm_clock->warp_timer = qemu_new_timer_ns(rt_clock, icount_warp_rt, NULL);
+#endif
+
if (strcmp(option, "auto") != 0) {
icount_time_shift = strtol(option, NULL, 0);
use_icount = 1;
@@ -669,21 +776,16 @@ static void host_alarm_handler(int host_signum)
}
}
-int64_t qemu_next_deadline(void)
+int64_t qemu_next_icount_deadline(void)
{
/* To avoid problems with overflow limit this to 2^32. */
int64_t delta = INT32_MAX;
+ assert(use_icount);
if (active_timers[QEMU_CLOCK_VIRTUAL]) {
delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
qemu_get_clock_ns(vm_clock);
}
- if (active_timers[QEMU_CLOCK_HOST]) {
- int64_t hdelta = active_timers[QEMU_CLOCK_HOST]->expire_time -
- qemu_get_clock_ns(host_clock);
- if (hdelta < delta)
- delta = hdelta;
- }
if (delta < 0)
delta = 0;
@@ -770,7 +872,7 @@ static int hpet_start_timer(struct qemu_alarm_timer *t)
goto fail;
enable_sigio_timer(fd);
- t->priv = (void *)(long)fd;
+ t->fd = fd;
return 0;
fail:
@@ -780,7 +882,7 @@ fail:
static void hpet_stop_timer(struct qemu_alarm_timer *t)
{
- int fd = (long)t->priv;
+ int fd = t->fd;
close(fd);
}
@@ -809,14 +911,14 @@ static int rtc_start_timer(struct qemu_alarm_timer *t)
enable_sigio_timer(rtc_fd);
- t->priv = (void *)(long)rtc_fd;
+ t->fd = rtc_fd;
return 0;
}
static void rtc_stop_timer(struct qemu_alarm_timer *t)
{
- int rtc_fd = (long)t->priv;
+ int rtc_fd = t->fd;
close(rtc_fd);
}
@@ -851,21 +953,21 @@ static int dynticks_start_timer(struct qemu_alarm_timer *t)
return -1;
}
- t->priv = (void *)(long)host_timer;
+ t->timer = host_timer;
return 0;
}
static void dynticks_stop_timer(struct qemu_alarm_timer *t)
{
- timer_t host_timer = (timer_t)(long)t->priv;
+ timer_t host_timer = t->timer;
timer_delete(host_timer);
}
static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
{
- timer_t host_timer = (timer_t)(long)t->priv;
+ timer_t host_timer = t->timer;
struct itimerspec timeout;
int64_t nearest_delta_ns = INT64_MAX;
int64_t current_ns;
@@ -944,6 +1046,96 @@ static void unix_stop_timer(struct qemu_alarm_timer *t)
#ifdef _WIN32
+static MMRESULT mm_timer;
+static unsigned mm_period;
+
+static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
+ DWORD_PTR dwUser, DWORD_PTR dw1,
+ DWORD_PTR dw2)
+{
+ struct qemu_alarm_timer *t = alarm_timer;
+ if (!t) {
+ return;
+ }
+ if (alarm_has_dynticks(t) || qemu_next_alarm_deadline() <= 0) {
+ t->expired = alarm_has_dynticks(t);
+ t->pending = 1;
+ qemu_notify_event();
+ }
+}
+
+static int mm_start_timer(struct qemu_alarm_timer *t)
+{
+ TIMECAPS tc;
+ UINT flags;
+
+ memset(&tc, 0, sizeof(tc));
+ timeGetDevCaps(&tc, sizeof(tc));
+
+ mm_period = tc.wPeriodMin;
+ timeBeginPeriod(mm_period);
+
+ flags = TIME_CALLBACK_FUNCTION;
+ if (alarm_has_dynticks(t)) {
+ flags |= TIME_ONESHOT;
+ } else {
+ flags |= TIME_PERIODIC;
+ }
+
+ mm_timer = timeSetEvent(1, /* interval (ms) */
+ mm_period, /* resolution */
+ mm_alarm_handler, /* function */
+ (DWORD_PTR)t, /* parameter */
+ flags);
+
+ if (!mm_timer) {
+ fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
+ GetLastError());
+ timeEndPeriod(mm_period);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void mm_stop_timer(struct qemu_alarm_timer *t)
+{
+ timeKillEvent(mm_timer);
+ timeEndPeriod(mm_period);
+}
+
+static void mm_rearm_timer(struct qemu_alarm_timer *t)
+{
+ int nearest_delta_ms;
+
+ assert(alarm_has_dynticks(t));
+ if (!active_timers[QEMU_CLOCK_REALTIME] &&
+ !active_timers[QEMU_CLOCK_VIRTUAL] &&
+ !active_timers[QEMU_CLOCK_HOST]) {
+ return;
+ }
+
+ timeKillEvent(mm_timer);
+
+ nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
+ if (nearest_delta_ms < 1) {
+ nearest_delta_ms = 1;
+ }
+ mm_timer = timeSetEvent(nearest_delta_ms,
+ mm_period,
+ mm_alarm_handler,
+ (DWORD_PTR)t,
+ TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
+
+ if (!mm_timer) {
+ fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n",
+ GetLastError());
+
+ timeEndPeriod(mm_period);
+ exit(1);
+ }
+}
+
static int win32_start_timer(struct qemu_alarm_timer *t)
{
HANDLE hTimer;
@@ -967,13 +1159,13 @@ static int win32_start_timer(struct qemu_alarm_timer *t)
return -1;
}
- t->priv = (PVOID) hTimer;
+ t->timer = hTimer;
return 0;
}
static void win32_stop_timer(struct qemu_alarm_timer *t)
{
- HANDLE hTimer = t->priv;
+ HANDLE hTimer = t->timer;
if (hTimer) {
DeleteTimerQueueTimer(NULL, hTimer, NULL);
@@ -982,7 +1174,7 @@ static void win32_stop_timer(struct qemu_alarm_timer *t)
static void win32_rearm_timer(struct qemu_alarm_timer *t)
{
- HANDLE hTimer = t->priv;
+ HANDLE hTimer = t->timer;
int nearest_delta_ms;
BOOLEAN success;
@@ -1055,39 +1247,41 @@ void quit_timers(void)
int qemu_calculate_timeout(void)
{
+#ifndef CONFIG_IOTHREAD
int timeout;
- int64_t add;
- int64_t delta;
- /* When using icount, making forward progress with qemu_icount when the
- guest CPU is idle is critical. We only use the static io-thread timeout
- for non icount runs. */
- if (!use_icount || !vm_running) {
- return 5000;
- }
-
- /* Advance virtual time to the next event. */
- delta = qemu_icount_delta();
- if (delta > 0) {
- /* If virtual time is ahead of real time then just
- wait for IO. */
- timeout = (delta + 999999) / 1000000;
- } else {
- /* Wait for either IO to occur or the next
- timer event. */
- add = qemu_next_deadline();
- /* We advance the timer before checking for IO.
- Limit the amount we advance so that early IO
- activity won't get the guest too far ahead. */
- if (add > 10000000)
- add = 10000000;
- delta += add;
- qemu_icount += qemu_icount_round (add);
- timeout = delta / 1000000;
- if (timeout < 0)
- timeout = 0;
+ if (!vm_running)
+ timeout = 5000;
+ else {
+ /* XXX: use timeout computed from timers */
+ int64_t add;
+ int64_t delta;
+ /* Advance virtual time to the next event. */
+ delta = qemu_icount_delta();
+ if (delta > 0) {
+ /* If virtual time is ahead of real time then just
+ wait for IO. */
+ timeout = (delta + 999999) / 1000000;
+ } else {
+ /* Wait for either IO to occur or the next
+ timer event. */
+ add = qemu_next_icount_deadline();
+ /* We advance the timer before checking for IO.
+ Limit the amount we advance so that early IO
+ activity won't get the guest too far ahead. */
+ if (add > 10000000)
+ add = 10000000;
+ delta += add;
+ qemu_icount += qemu_icount_round (add);
+ timeout = delta / 1000000;
+ if (timeout < 0)
+ timeout = 0;
+ }
}
return timeout;
+#else /* CONFIG_IOTHREAD */
+ return 1000;
+#endif
}
diff --git a/qemu-timer.h b/qemu-timer.h
index 75d567578..06cbe2091 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -7,7 +7,6 @@
#ifdef _WIN32
#include <windows.h>
-#include <mmsystem.h>
#endif
/* timers */
@@ -39,6 +38,7 @@ extern QEMUClock *host_clock;
int64_t qemu_get_clock_ns(QEMUClock *clock);
void qemu_clock_enable(QEMUClock *clock, int enabled);
+void qemu_clock_warp(QEMUClock *clock);
QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
QEMUTimerCB *cb, void *opaque);
@@ -50,7 +50,7 @@ int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
void qemu_run_all_timers(void);
int qemu_alarm_pending(void);
-int64_t qemu_next_deadline(void);
+int64_t qemu_next_icount_deadline(void);
void configure_alarms(char const *opt);
void configure_icount(const char *option);
int qemu_calculate_timeout(void);
@@ -58,6 +58,10 @@ void init_clocks(void);
int init_timer_alarm(void);
void quit_timers(void);
+int64_t cpu_get_ticks(void);
+void cpu_enable_ticks(void);
+void cpu_disable_ticks(void);
+
static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb,
void *opaque)
{
@@ -139,8 +143,6 @@ uint64_t ptimer_get_count(ptimer_state *s);
void ptimer_set_count(ptimer_state *s, uint64_t count);
void ptimer_run(ptimer_state *s, int oneshot);
void ptimer_stop(ptimer_state *s);
-void qemu_put_ptimer(QEMUFile *f, ptimer_state *s);
-void qemu_get_ptimer(QEMUFile *f, ptimer_state *s);
/* icount */
int64_t qemu_icount_round(int64_t count);
diff --git a/qemu-tool.c b/qemu-tool.c
index d45840de2..f4a6ad081 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -15,7 +15,6 @@
#include "monitor.h"
#include "qemu-timer.h"
#include "qemu-log.h"
-#include "sysemu.h"
#include <sys/time.h>
diff --git a/roms/ipxe b/roms/ipxe
new file mode 160000
+Subproject 7aee315f61aaf1be6d2fff26339f28a1137231a
diff --git a/savevm.c b/savevm.c
index 936f619d5..e26bf6e0c 100644
--- a/savevm.c
+++ b/savevm.c
@@ -82,6 +82,7 @@
#include "migration.h"
#include "qemu_socket.h"
#include "qemu-queue.h"
+#include "cpus.h"
#define SELF_ANNOUNCE_ROUNDS 5
@@ -1030,7 +1031,7 @@ const VMStateInfo vmstate_info_buffer = {
};
/* unused buffers: space that was used for some fields that are
- not usefull anymore */
+ not useful anymore */
static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
{
diff --git a/scripts/refresh-pxe-roms.sh b/scripts/refresh-pxe-roms.sh
new file mode 100755
index 000000000..14d586070
--- /dev/null
+++ b/scripts/refresh-pxe-roms.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+
+# PXE ROM build script
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# Copyright (C) 2011 Red Hat, Inc.
+# Authors: Alex Williamson <alex.williamson@redhat.com>
+#
+# Usage: Run from root of qemu tree
+# ./scripts/refresh-pxe-roms.sh
+
+QEMU_DIR=$PWD
+ROM_DIR="pc-bios"
+BUILD_DIR="roms/ipxe"
+LOCAL_CONFIG="src/config/local/general.h"
+
+function cleanup ()
+{
+ if [ -n "$SAVED_CONFIG" ]; then
+ cp "$SAVED_CONFIG" "$BUILD_DIR"/"$LOCAL_CONFIG"
+ rm "$SAVED_CONFIG"
+ fi
+ cd "$QEMU_DIR"
+}
+
+function make_rom ()
+{
+ cd "$BUILD_DIR"/src
+
+ BUILD_LOG=$(mktemp)
+
+ echo Building "$2"...
+ make bin/"$1".rom > "$BUILD_LOG" 2>&1
+ if [ $? -ne 0 ]; then
+ echo Build failed
+ tail --lines=100 "$BUILD_LOG"
+ rm "$BUILD_LOG"
+ cleanup
+ exit 1
+ fi
+ rm "$BUILD_LOG"
+
+ cp bin/"$1".rom "$QEMU_DIR"/"$ROM_DIR"/"$2"
+
+ cd "$QEMU_DIR"
+}
+
+if [ ! -d "$QEMU_DIR"/"$ROM_DIR" ]; then
+ echo "error: can't find $ROM_DIR directory," \
+ "run me from the root of the qemu tree"
+ exit 1
+fi
+
+if [ ! -d "$BUILD_DIR"/src ]; then
+ echo "error: $BUILD_DIR not populated, try:"
+ echo " git submodule init $BUILD_DIR"
+ echo " git submodule update $BUILD_DIR"
+ exit 1
+fi
+
+if [ -e "$BUILD_DIR"/"$LOCAL_CONFIG" ]; then
+ SAVED_CONFIG=$(mktemp)
+ cp "$BUILD_DIR"/"$LOCAL_CONFIG" "$SAVED_CONFIG"
+fi
+
+echo "#undef BANNER_TIMEOUT" > "$BUILD_DIR"/"$LOCAL_CONFIG"
+echo "#define BANNER_TIMEOUT 0" >> "$BUILD_DIR"/"$LOCAL_CONFIG"
+
+IPXE_VERSION=$(cd "$BUILD_DIR" && git describe --tags)
+if [ -z "$IPXE_VERSION" ]; then
+ echo "error: unable to retrieve git version"
+ cleanup
+ exit 1
+fi
+
+echo "#undef PRODUCT_NAME" >> "$BUILD_DIR"/"$LOCAL_CONFIG"
+echo "#define PRODUCT_NAME \"iPXE $IPXE_VERSION\"" >> "$BUILD_DIR"/"$LOCAL_CONFIG"
+
+make_rom 8086100e pxe-e1000.rom
+make_rom 80861209 pxe-eepro100.rom
+make_rom 10500940 pxe-ne2k_pci.rom
+make_rom 10222000 pxe-pcnet.rom
+make_rom 10ec8139 pxe-rtl8139.rom
+make_rom 1af41000 pxe-virtio.rom
+
+echo done
+cleanup
diff --git a/scripts/tracetool b/scripts/tracetool
index 412f69586..2155a57df 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -51,7 +51,7 @@ get_args()
{
local args
args=${1#*\(}
- args=${args%\)*}
+ args=${args%%\)*}
echo "$args"
}
@@ -338,6 +338,7 @@ linetoc_ust()
name=$(get_name "$1")
args=$(get_args "$1")
argnames=$(get_argnames "$1", ",")
+ [ -z "$argnames" ] || argnames=", $argnames"
fmt=$(get_fmt "$1")
cat <<EOF
@@ -345,7 +346,7 @@ DEFINE_TRACE(ust_$name);
static void ust_${name}_probe($args)
{
- trace_mark(ust, $name, "$fmt", $argnames);
+ trace_mark(ust, $name, "$fmt"$argnames);
}
EOF
@@ -488,7 +489,7 @@ EOF
cat <<EOF
$arg = \$arg$i;
EOF
- i="$((i+1))"
+ i="$((i+1))"
done
cat <<EOF
@@ -585,7 +586,7 @@ tracetostap()
exit 1
fi
if [ -z "$probeprefix" ]; then
- probeprefix="qemu.$targettype.$targetarch";
+ probeprefix="qemu.$targettype.$targetarch";
fi
echo "/* This file is autogenerated by tracetool, do not edit. */"
convert stap
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 517f337c4..fa15a71e1 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -131,6 +131,18 @@ static void spice_chr_close(struct CharDriverState *chr)
qemu_free(s);
}
+static void spice_chr_guest_open(struct CharDriverState *chr)
+{
+ SpiceCharDriver *s = chr->opaque;
+ vmc_register_interface(s);
+}
+
+static void spice_chr_guest_close(struct CharDriverState *chr)
+{
+ SpiceCharDriver *s = chr->opaque;
+ vmc_unregister_interface(s);
+}
+
static void print_allowed_subtypes(void)
{
const char** psubtype;
@@ -183,6 +195,8 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
chr->opaque = s;
chr->chr_write = spice_chr_write;
chr->chr_close = spice_chr_close;
+ chr->chr_guest_open = spice_chr_guest_open;
+ chr->chr_guest_close = spice_chr_guest_close;
qemu_chr_generic_open(chr);
diff --git a/sysemu.h b/sysemu.h
index 07d85cd44..d58bec116 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -8,22 +8,9 @@
#include "qemu-timer.h"
#include "notify.h"
-#ifdef _WIN32
-#include <windows.h>
-#include "qemu-os-win32.h"
-#endif
-
-#ifdef CONFIG_POSIX
-#include "qemu-os-posix.h"
-#endif
-
/* vl.c */
extern const char *bios_name;
-#define QEMU_FILE_TYPE_BIOS 0
-#define QEMU_FILE_TYPE_KEYMAP 1
-char *qemu_find_file(int type, const char *name);
-
extern int vm_running;
extern const char *qemu_name;
extern uint8_t qemu_uuid[];
@@ -50,14 +37,6 @@ void qemu_del_vm_change_state_handler(VMChangeStateEntry *e);
void vm_start(void);
void vm_stop(int reason);
-uint64_t ram_bytes_remaining(void);
-uint64_t ram_bytes_transferred(void);
-uint64_t ram_bytes_total(void);
-
-int64_t cpu_get_ticks(void);
-void cpu_enable_ticks(void);
-void cpu_disable_ticks(void);
-
void qemu_system_reset_request(void);
void qemu_system_shutdown_request(void);
void qemu_system_powerdown_request(void);
@@ -82,10 +61,6 @@ int load_vmstate(const char *name);
void do_delvm(Monitor *mon, const QDict *qdict);
void do_info_snapshots(Monitor *mon);
-void cpu_synchronize_all_states(void);
-void cpu_synchronize_all_post_reset(void);
-void cpu_synchronize_all_post_init(void);
-
void qemu_announce_self(void);
void main_loop_wait(int nonblocking);
@@ -101,12 +76,6 @@ int qemu_loadvm_state(QEMUFile *f);
/* SLIRP */
void do_info_slirp(Monitor *mon);
-/* OS specific functions */
-void os_setup_early_signal_handling(void);
-char *os_find_datadir(const char *argv0);
-void os_parse_cmd_args(int index, const char *optarg);
-void os_pidfile_error(void);
-
typedef enum DisplayType
{
DT_DEFAULT,
@@ -117,7 +86,6 @@ typedef enum DisplayType
} DisplayType;
extern int autostart;
-extern int incoming_expected;
extern int bios_size;
typedef enum {
@@ -196,8 +164,6 @@ extern CharDriverState *serial_hds[MAX_SERIAL_PORTS];
extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
-#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
-
void do_usb_add(Monitor *mon, const QDict *qdict);
void do_usb_del(Monitor *mon, const QDict *qdict);
void usb_info(Monitor *mon);
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 6c2ae2061..4ccb10b0f 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -904,10 +904,11 @@ uint64_t helper_cmptun (uint64_t a, uint64_t b)
fa = t_to_float64(a);
fb = t_to_float64(b);
- if (float64_is_quiet_nan(fa) || float64_is_quiet_nan(fb))
+ if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
return 0x4000000000000000ULL;
- else
+ } else {
return 0;
+ }
}
uint64_t helper_cmpteq(uint64_t a, uint64_t b)
@@ -917,7 +918,7 @@ uint64_t helper_cmpteq(uint64_t a, uint64_t b)
fa = t_to_float64(a);
fb = t_to_float64(b);
- if (float64_eq(fa, fb, &FP_STATUS))
+ if (float64_eq_quiet(fa, fb, &FP_STATUS))
return 0x4000000000000000ULL;
else
return 0;
@@ -956,7 +957,7 @@ uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
fa = g_to_float64(a);
fb = g_to_float64(b);
- if (float64_eq(fa, fb, &FP_STATUS))
+ if (float64_eq_quiet(fa, fb, &FP_STATUS))
return 0x4000000000000000ULL;
else
return 0;
@@ -1373,7 +1374,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (likely(tb)) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
/* Exception index and error code are already set */
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 96e922b56..456ba51ac 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3367,8 +3367,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
return env;
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->pc = gen_opc_pc[pc_pos];
}
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index e247a7ade..d5af64465 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -363,6 +363,7 @@ enum arm_features {
ARM_FEATURE_V7MP, /* v7 Multiprocessing Extensions */
ARM_FEATURE_V4T,
ARM_FEATURE_V5,
+ ARM_FEATURE_STRONGARM,
};
static inline int arm_feature(CPUARMState *env, int feature)
@@ -393,6 +394,8 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
#define ARM_CPUID_ARM946 0x41059461
#define ARM_CPUID_TI915T 0x54029152
#define ARM_CPUID_TI925T 0x54029252
+#define ARM_CPUID_SA1100 0x4401A11B
+#define ARM_CPUID_SA1110 0x6901B119
#define ARM_CPUID_PXA250 0x69052100
#define ARM_CPUID_PXA255 0x69052d00
#define ARM_CPUID_PXA260 0x69052903
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 9172fc727..62ae72ec2 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -5,7 +5,7 @@
#include "cpu.h"
#include "exec-all.h"
#include "gdbstub.h"
-#include "helpers.h"
+#include "helper.h"
#include "qemu-common.h"
#include "host-utils.h"
#if !defined(CONFIG_USER_ONLY)
@@ -214,6 +214,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
env->cp15.c0_cachetype = 0xd172172;
env->cp15.c1_sys = 0x00000078;
break;
+ case ARM_CPUID_SA1100:
+ case ARM_CPUID_SA1110:
+ set_feature(env, ARM_FEATURE_STRONGARM);
+ env->cp15.c1_sys = 0x00000070;
+ break;
default:
cpu_abort(env, "Bad CPU ID: %x\n", id);
break;
@@ -378,6 +383,8 @@ static const struct arm_cpu_t arm_cpu_names[] = {
{ ARM_CPUID_CORTEXA9, "cortex-a9"},
{ ARM_CPUID_TI925T, "ti925t" },
{ ARM_CPUID_PXA250, "pxa250" },
+ { ARM_CPUID_SA1100, "sa1100" },
+ { ARM_CPUID_SA1110, "sa1110" },
{ ARM_CPUID_PXA255, "pxa255" },
{ ARM_CPUID_PXA260, "pxa260" },
{ ARM_CPUID_PXA261, "pxa261" },
@@ -1378,7 +1385,7 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
/* This may enable/disable the MMU, so do a TLB flush. */
tlb_flush(env, 1);
break;
- case 1: /* Auxiliary cotrol register. */
+ case 1: /* Auxiliary control register. */
if (arm_feature(env, ARM_FEATURE_XSCALE)) {
env->cp15.c1_xscaleauxcr = val;
break;
@@ -1553,6 +1560,8 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
case 9:
if (arm_feature(env, ARM_FEATURE_OMAPCP))
break;
+ if (arm_feature(env, ARM_FEATURE_STRONGARM))
+ break; /* Ignore ReadBuffer access */
switch (crm) {
case 0: /* Cache lockdown. */
switch (op1) {
@@ -2542,6 +2551,7 @@ float64 VFP_HELPER(sito, d)(uint32_t x, CPUState *env)
uint32_t VFP_HELPER(toui, s)(float32 x, CPUState *env)
{
if (float32_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float32_to_uint32(x, &env->vfp.fp_status);
@@ -2550,6 +2560,7 @@ uint32_t VFP_HELPER(toui, s)(float32 x, CPUState *env)
uint32_t VFP_HELPER(toui, d)(float64 x, CPUState *env)
{
if (float64_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float64_to_uint32(x, &env->vfp.fp_status);
@@ -2558,6 +2569,7 @@ uint32_t VFP_HELPER(toui, d)(float64 x, CPUState *env)
uint32_t VFP_HELPER(tosi, s)(float32 x, CPUState *env)
{
if (float32_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float32_to_int32(x, &env->vfp.fp_status);
@@ -2566,6 +2578,7 @@ uint32_t VFP_HELPER(tosi, s)(float32 x, CPUState *env)
uint32_t VFP_HELPER(tosi, d)(float64 x, CPUState *env)
{
if (float64_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float64_to_int32(x, &env->vfp.fp_status);
@@ -2574,6 +2587,7 @@ uint32_t VFP_HELPER(tosi, d)(float64 x, CPUState *env)
uint32_t VFP_HELPER(touiz, s)(float32 x, CPUState *env)
{
if (float32_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float32_to_uint32_round_to_zero(x, &env->vfp.fp_status);
@@ -2582,6 +2596,7 @@ uint32_t VFP_HELPER(touiz, s)(float32 x, CPUState *env)
uint32_t VFP_HELPER(touiz, d)(float64 x, CPUState *env)
{
if (float64_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float64_to_uint32_round_to_zero(x, &env->vfp.fp_status);
@@ -2590,6 +2605,7 @@ uint32_t VFP_HELPER(touiz, d)(float64 x, CPUState *env)
uint32_t VFP_HELPER(tosiz, s)(float32 x, CPUState *env)
{
if (float32_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float32_to_int32_round_to_zero(x, &env->vfp.fp_status);
@@ -2598,6 +2614,7 @@ uint32_t VFP_HELPER(tosiz, s)(float32 x, CPUState *env)
uint32_t VFP_HELPER(tosiz, d)(float64 x, CPUState *env)
{
if (float64_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float64_to_int32_round_to_zero(x, &env->vfp.fp_status);
@@ -2636,6 +2653,7 @@ uint##fsz##_t VFP_HELPER(to##name, p)(float##fsz x, uint32_t shift, \
{ \
float##fsz tmp; \
if (float##fsz##_is_any_nan(x)) { \
+ float_raise(float_flag_invalid, &env->vfp.fp_status); \
return 0; \
} \
tmp = float##fsz##_scalbn(x, shift, &env->vfp.fp_status); \
diff --git a/target-arm/helpers.h b/target-arm/helper.h
index ae701e845..ae701e845 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helper.h
diff --git a/target-arm/iwmmxt_helper.c b/target-arm/iwmmxt_helper.c
index 3941f1fd8..ebe6eb9fa 100644
--- a/target-arm/iwmmxt_helper.c
+++ b/target-arm/iwmmxt_helper.c
@@ -24,7 +24,7 @@
#include "cpu.h"
#include "exec.h"
-#include "helpers.h"
+#include "helper.h"
/* iwMMXt macros extracted from GNU gdb. */
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 7df925ad3..f5b173aa7 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -11,7 +11,7 @@
#include "cpu.h"
#include "exec.h"
-#include "helpers.h"
+#include "helper.h"
#define SIGNBIT (uint32_t)0x80000000
#define SIGNBIT64 ((uint64_t)1 << 63)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 3de261034..8334fbcf6 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -17,7 +17,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "exec.h"
-#include "helpers.h"
+#include "helper.h"
#define SIGNBIT (uint32_t)0x80000000
#define SIGNBIT64 ((uint64_t)1 << 63)
@@ -90,7 +90,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
raise_exception(env->exception_index);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 6190028d0..a1af436e3 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -30,9 +30,9 @@
#include "tcg-op.h"
#include "qemu-log.h"
-#include "helpers.h"
+#include "helper.h"
#define GEN_HELPER 1
-#include "helpers.h"
+#include "helper.h"
#define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T)
#define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5)
@@ -129,7 +129,7 @@ void arm_translate_init(void)
#endif
#define GEN_HELPER 2
-#include "helpers.h"
+#include "helper.h"
}
static inline TCGv load_cpu_offset(int offset)
@@ -3830,6 +3830,21 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
size = (insn >> 6) & 3;
if (op > 10)
return 1;
+ /* Catch UNDEF cases for bad values of align field */
+ switch (op & 0xc) {
+ case 4:
+ if (((insn >> 5) & 1) == 1) {
+ return 1;
+ }
+ break;
+ case 8:
+ if (((insn >> 4) & 3) == 3) {
+ return 1;
+ }
+ break;
+ default:
+ break;
+ }
nregs = neon_ls_element_type[op].nregs;
interleave = neon_ls_element_type[op].interleave;
spacing = neon_ls_element_type[op].spacing;
@@ -3975,6 +3990,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
stride = (1 << size) * nregs;
} else {
/* Single element. */
+ int idx = (insn >> 4) & 0xf;
pass = (insn >> 7) & 1;
switch (size) {
case 0:
@@ -3993,6 +4009,39 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
abort();
}
nregs = ((insn >> 8) & 3) + 1;
+ /* Catch the UNDEF cases. This is unavoidably a bit messy. */
+ switch (nregs) {
+ case 1:
+ if (((idx & (1 << size)) != 0) ||
+ (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
+ return 1;
+ }
+ break;
+ case 3:
+ if ((idx & 1) != 0) {
+ return 1;
+ }
+ /* fall through */
+ case 2:
+ if (size == 2 && (idx & 2) != 0) {
+ return 1;
+ }
+ break;
+ case 4:
+ if ((size == 2) && ((idx & 3) == 3)) {
+ return 1;
+ }
+ break;
+ default:
+ abort();
+ }
+ if ((rd + stride * (nregs - 1)) > 31) {
+ /* Attempts to write off the end of the register file
+ * are UNPREDICTABLE; we choose to UNDEF because otherwise
+ * the neon_load_reg() would write off the end of the array.
+ */
+ return 1;
+ }
addr = tcg_temp_new_i32();
load_reg_var(s, addr, rn);
for (reg = 0; reg < nregs; reg++) {
@@ -7967,7 +8016,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
}
}
} else {
- int i;
+ int i, loaded_base = 0;
+ TCGv loaded_var;
/* Load/store multiple. */
addr = load_reg(s, rn);
offset = 0;
@@ -7979,6 +8029,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
tcg_gen_addi_i32(addr, addr, -offset);
}
+ TCGV_UNUSED(loaded_var);
for (i = 0; i < 16; i++) {
if ((insn & (1 << i)) == 0)
continue;
@@ -7987,6 +8038,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
tmp = gen_ld32(addr, IS_USER(s));
if (i == 15) {
gen_bx(s, tmp);
+ } else if (i == rn) {
+ loaded_var = tmp;
+ loaded_base = 1;
} else {
store_reg(s, i, tmp);
}
@@ -7997,6 +8051,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
}
tcg_gen_addi_i32(addr, addr, 4);
}
+ if (loaded_base) {
+ store_reg(s, rn, loaded_var);
+ }
if (insn & (1 << 21)) {
/* Base register writeback. */
if (insn & (1 << 24)) {
@@ -9397,7 +9454,10 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
break;
case 12:
+ {
/* load/store multiple */
+ TCGv loaded_var;
+ TCGV_UNUSED(loaded_var);
rn = (insn >> 8) & 0x7;
addr = load_reg(s, rn);
for (i = 0; i < 8; i++) {
@@ -9405,7 +9465,11 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* load */
tmp = gen_ld32(addr, IS_USER(s));
- store_reg(s, i, tmp);
+ if (i == rn) {
+ loaded_var = tmp;
+ } else {
+ store_reg(s, i, tmp);
+ }
} else {
/* store */
tmp = load_reg(s, i);
@@ -9415,14 +9479,18 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
tcg_gen_addi_i32(addr, addr, 4);
}
}
- /* Base register writeback. */
if ((insn & (1 << rn)) == 0) {
+ /* base reg not in list: base register writeback */
store_reg(s, rn, addr);
} else {
+ /* base reg in list: if load, complete it now */
+ if (insn & (1 << 11)) {
+ store_reg(s, rn, loaded_var);
+ }
tcg_temp_free_i32(addr);
}
break;
-
+ }
case 13:
/* conditional branch or swi */
cond = (insn >> 8) & 0xf;
@@ -9551,8 +9619,8 @@ static inline void gen_intermediate_code_internal(CPUState *env,
* This is handled in the same way as restoration of the
* PC in these situations: we will be called again with search_pc=1
* and generate a mapping of the condexec bits for each PC in
- * gen_opc_condexec_bits[]. gen_pc_load[] then uses this to restore
- * the condexec bits.
+ * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
+ * this to restore the condexec bits.
*
* Note that there are no instructions which can read the condexec
* bits, and none which can write non-static values to them, so
@@ -9817,8 +9885,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
#endif
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->regs[15] = gen_opc_pc[pc_pos];
env->condexec_bits = gen_opc_condexec_bits[pc_pos];
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
index be9eb06fd..34329e2a6 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -77,7 +77,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
/* Evaluate flags after retranslation. */
helper_top_evaluate_flags();
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 1c03fa5fb..e2607d64c 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3604,8 +3604,7 @@ void cpu_reset (CPUCRISState *env)
#endif
}
-void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->pc = gen_opc_pc[pc_pos];
}
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 997751126..091d81239 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -73,7 +73,7 @@ static const char *ext3_feature_name[] = {
};
static const char *kvm_feature_name[] = {
- "kvmclock", "kvm_nopiodelay", "kvm_mmu", NULL, "kvm_asyncpf", NULL, NULL, NULL,
+ "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock", "kvm_asyncpf", NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -182,20 +182,22 @@ static int altcmp(const char *s, const char *e, const char *altstr)
}
/* search featureset for flag *[s..e), if found set corresponding bit in
- * *pval and return success, otherwise return zero
+ * *pval and return true, otherwise return false
*/
-static int lookup_feature(uint32_t *pval, const char *s, const char *e,
- const char **featureset)
+static bool lookup_feature(uint32_t *pval, const char *s, const char *e,
+ const char **featureset)
{
uint32_t mask;
const char **ppc;
+ bool found = false;
- for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc)
+ for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc) {
if (*ppc && !altcmp(s, e, *ppc)) {
*pval |= mask;
- break;
+ found = true;
}
- return (mask ? 1 : 0);
+ }
+ return found;
}
static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
diff --git a/target-i386/exec.h b/target-i386/exec.h
index 6f9f709d8..ee36a7181 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -110,11 +110,24 @@ static inline void svm_check_intercept(uint32_t type)
#define float64_to_floatx float64_to_floatx80
#define floatx_to_float32 floatx80_to_float32
#define floatx_to_float64 floatx80_to_float64
+#define floatx_add floatx80_add
+#define floatx_div floatx80_div
+#define floatx_mul floatx80_mul
+#define floatx_sub floatx80_sub
+#define floatx_sqrt floatx80_sqrt
#define floatx_abs floatx80_abs
#define floatx_chs floatx80_chs
+#define floatx_scalbn floatx80_scalbn
#define floatx_round_to_int floatx80_round_to_int
#define floatx_compare floatx80_compare
#define floatx_compare_quiet floatx80_compare_quiet
+#define floatx_is_any_nan floatx80_is_any_nan
+#define floatx_is_neg floatx80_is_neg
+#define floatx_is_zero floatx80_is_zero
+#define floatx_zero floatx80_zero
+#define floatx_one floatx80_one
+#define floatx_ln2 floatx80_ln2
+#define floatx_pi floatx80_pi
#else
#define floatx_to_int32 float64_to_int32
#define floatx_to_int64 float64_to_int64
@@ -126,11 +139,24 @@ static inline void svm_check_intercept(uint32_t type)
#define float64_to_floatx(x, e) (x)
#define floatx_to_float32 float64_to_float32
#define floatx_to_float64(x, e) (x)
+#define floatx_add float64_add
+#define floatx_div float64_div
+#define floatx_mul float64_mul
+#define floatx_sub float64_sub
+#define floatx_sqrt float64_sqrt
#define floatx_abs float64_abs
#define floatx_chs float64_chs
+#define floatx_scalbn float64_scalbn
#define floatx_round_to_int float64_round_to_int
#define floatx_compare float64_compare
#define floatx_compare_quiet float64_compare_quiet
+#define floatx_is_any_nan float64_is_any_nan
+#define floatx_is_neg float64_is_neg
+#define floatx_is_zero float64_is_zero
+#define floatx_zero float64_zero
+#define floatx_one float64_one
+#define floatx_ln2 float64_ln2
+#define floatx_pi float64_pi
#endif
#define RC_MASK 0xc00
@@ -144,13 +170,7 @@ static inline void svm_check_intercept(uint32_t type)
#ifdef USE_X86LDOUBLE
/* only for x86 */
-typedef union {
- long double d;
- struct {
- unsigned long long lower;
- unsigned short upper;
- } l;
-} CPU86_LDoubleU;
+typedef CPU_LDoubleU CPU86_LDoubleU;
/* the following deal with x86 long double-precision numbers */
#define MAXEXPD 0x7fff
@@ -162,24 +182,7 @@ typedef union {
#else
-/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
-typedef union {
- double d;
-#if !defined(HOST_WORDS_BIGENDIAN) && !defined(__arm__)
- struct {
- uint32_t lower;
- int32_t upper;
- } l;
-#else
- struct {
- int32_t upper;
- uint32_t lower;
- } l;
-#endif
-#ifndef __arm__
- int64_t ll;
-#endif
-} CPU86_LDoubleU;
+typedef CPU_DoubleU CPU86_LDoubleU;
/* the following deal with IEEE double-precision numbers */
#define MAXEXPD 0x7ff
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 3fdbe68f3..4ab5241eb 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -409,16 +409,10 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
env->mxcsr);
for(i=0;i<8;i++) {
#if defined(USE_X86LDOUBLE)
- union {
- long double d;
- struct {
- uint64_t lower;
- uint16_t upper;
- } l;
- } tmp;
- tmp.d = env->fpregs[i].d;
+ CPU_LDoubleU u;
+ u.d = env->fpregs[i].d;
cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
- i, tmp.l.lower, tmp.l.upper);
+ i, u.l.lower, u.l.upper);
#else
cpu_fprintf(f, "FPR%d=%016" PRIx64,
i, env->fpregs[i].mmx.q);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index a3587edab..48d4f9710 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -94,6 +94,35 @@ static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
return cpuid;
}
+#ifdef CONFIG_KVM_PARA
+struct kvm_para_features {
+ int cap;
+ int feature;
+} para_features[] = {
+ { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
+ { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
+ { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
+#ifdef KVM_CAP_ASYNC_PF
+ { KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF },
+#endif
+ { -1, -1 }
+};
+
+static int get_para_features(CPUState *env)
+{
+ int i, features = 0;
+
+ for (i = 0; i < ARRAY_SIZE(para_features) - 1; i++) {
+ if (kvm_check_extension(env->kvm_state, para_features[i].cap)) {
+ features |= (1 << para_features[i].feature);
+ }
+ }
+
+ return features;
+}
+#endif
+
+
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
uint32_t index, int reg)
{
@@ -101,6 +130,9 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
int i, max;
uint32_t ret = 0;
uint32_t cpuid_1_edx;
+#ifdef CONFIG_KVM_PARA
+ int has_kvm_features = 0;
+#endif
max = 1;
while ((cpuid = try_get_cpuid(env->kvm_state, max)) == NULL) {
@@ -110,6 +142,11 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
for (i = 0; i < cpuid->nent; ++i) {
if (cpuid->entries[i].function == function &&
cpuid->entries[i].index == index) {
+#ifdef CONFIG_KVM_PARA
+ if (cpuid->entries[i].function == KVM_CPUID_FEATURES) {
+ has_kvm_features = 1;
+ }
+#endif
switch (reg) {
case R_EAX:
ret = cpuid->entries[i].eax;
@@ -142,38 +179,15 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
qemu_free(cpuid);
- return ret;
-}
-
#ifdef CONFIG_KVM_PARA
-struct kvm_para_features {
- int cap;
- int feature;
-} para_features[] = {
- { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
- { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
- { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
-#ifdef KVM_CAP_ASYNC_PF
- { KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF },
-#endif
- { -1, -1 }
-};
-
-static int get_para_features(CPUState *env)
-{
- int i, features = 0;
-
- for (i = 0; i < ARRAY_SIZE(para_features) - 1; i++) {
- if (kvm_check_extension(env->kvm_state, para_features[i].cap)) {
- features |= (1 << para_features[i].feature);
- }
+ /* fallback for older kernels */
+ if (!has_kvm_features && (function == KVM_CPUID_FEATURES)) {
+ ret = get_para_features(env);
}
-#ifdef KVM_CAP_ASYNC_PF
- has_msr_async_pf_en = features & (1 << KVM_FEATURE_ASYNC_PF);
#endif
- return features;
+
+ return ret;
}
-#endif /* CONFIG_KVM_PARA */
typedef struct HWPoisonPage {
ram_addr_t ram_addr;
@@ -411,7 +425,13 @@ int kvm_arch_init_vcpu(CPUState *env)
c = &cpuid_data.entries[cpuid_i++];
memset(c, 0, sizeof(*c));
c->function = KVM_CPUID_FEATURES;
- c->eax = env->cpuid_kvm_features & get_para_features(env);
+ c->eax = env->cpuid_kvm_features & kvm_arch_get_supported_cpuid(env,
+ KVM_CPUID_FEATURES, 0, R_EAX);
+
+#ifdef KVM_CAP_ASYNC_PF
+ has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF);
+#endif
+
#endif
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
@@ -579,7 +599,7 @@ static int kvm_get_supported_msrs(KVMState *s)
}
}
- free(kvm_msr_list);
+ qemu_free(kvm_msr_list);
}
return ret;
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 43fbd0c77..3c539f37c 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -17,6 +17,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+#include <math.h>
#include "exec.h"
#include "exec-all.h"
#include "host-utils.h"
@@ -94,15 +95,25 @@ static const uint8_t rclb_table[32] = {
6, 7, 8, 0, 1, 2, 3, 4,
};
+#if defined(CONFIG_SOFTFLOAT)
+# define floatx_lg2 make_floatx80( 0x3ffd, 0x9a209a84fbcff799LL )
+# define floatx_l2e make_floatx80( 0x3fff, 0xb8aa3b295c17f0bcLL )
+# define floatx_l2t make_floatx80( 0x4000, 0xd49a784bcd1b8afeLL )
+#else
+# define floatx_lg2 (0.30102999566398119523L)
+# define floatx_l2e (1.44269504088896340739L)
+# define floatx_l2t (3.32192809488736234781L)
+#endif
+
static const CPU86_LDouble f15rk[7] =
{
- 0.00000000000000000000L,
- 1.00000000000000000000L,
- 3.14159265358979323851L, /*pi*/
- 0.30102999566398119523L, /*lg2*/
- 0.69314718055994530943L, /*ln2*/
- 1.44269504088896340739L, /*l2e*/
- 3.32192809488736234781L, /*l2t*/
+ floatx_zero,
+ floatx_one,
+ floatx_pi,
+ floatx_lg2,
+ floatx_ln2,
+ floatx_l2e,
+ floatx_l2t,
};
/* broken thread support */
@@ -3431,6 +3442,28 @@ void helper_verw(target_ulong selector1)
/* x87 FPU helpers */
+static inline double CPU86_LDouble_to_double(CPU86_LDouble a)
+{
+ union {
+ float64 f64;
+ double d;
+ } u;
+
+ u.f64 = floatx_to_float64(a, &env->fp_status);
+ return u.d;
+}
+
+static inline CPU86_LDouble double_to_CPU86_LDouble(double a)
+{
+ union {
+ float64 f64;
+ double d;
+ } u;
+
+ u.d = a;
+ return float64_to_floatx(u.f64, &env->fp_status);
+}
+
static void fpu_set_exception(int mask)
{
env->fpus |= mask;
@@ -3440,9 +3473,10 @@ static void fpu_set_exception(int mask)
static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
{
- if (b == 0.0)
+ if (floatx_is_zero(b)) {
fpu_set_exception(FPUS_ZE);
- return a / b;
+ }
+ return floatx_div(a, b, &env->fp_status);
}
static void fpu_raise_exception(void)
@@ -3711,22 +3745,22 @@ void helper_fucomi_ST0_FT0(void)
void helper_fadd_ST0_FT0(void)
{
- ST0 += FT0;
+ ST0 = floatx_add(ST0, FT0, &env->fp_status);
}
void helper_fmul_ST0_FT0(void)
{
- ST0 *= FT0;
+ ST0 = floatx_mul(ST0, FT0, &env->fp_status);
}
void helper_fsub_ST0_FT0(void)
{
- ST0 -= FT0;
+ ST0 = floatx_sub(ST0, FT0, &env->fp_status);
}
void helper_fsubr_ST0_FT0(void)
{
- ST0 = FT0 - ST0;
+ ST0 = floatx_sub(FT0, ST0, &env->fp_status);
}
void helper_fdiv_ST0_FT0(void)
@@ -3743,24 +3777,22 @@ void helper_fdivr_ST0_FT0(void)
void helper_fadd_STN_ST0(int st_index)
{
- ST(st_index) += ST0;
+ ST(st_index) = floatx_add(ST(st_index), ST0, &env->fp_status);
}
void helper_fmul_STN_ST0(int st_index)
{
- ST(st_index) *= ST0;
+ ST(st_index) = floatx_mul(ST(st_index), ST0, &env->fp_status);
}
void helper_fsub_STN_ST0(int st_index)
{
- ST(st_index) -= ST0;
+ ST(st_index) = floatx_sub(ST(st_index), ST0, &env->fp_status);
}
void helper_fsubr_STN_ST0(int st_index)
{
- CPU86_LDouble *p;
- p = &ST(st_index);
- *p = ST0 - *p;
+ ST(st_index) = floatx_sub(ST0, ST(st_index), &env->fp_status);
}
void helper_fdiv_STN_ST0(int st_index)
@@ -3922,9 +3954,10 @@ void helper_fbld_ST0(target_ulong ptr)
v = ldub(ptr + i);
val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
}
- tmp = val;
- if (ldub(ptr + 9) & 0x80)
- tmp = -tmp;
+ tmp = int64_to_floatx(val, &env->fp_status);
+ if (ldub(ptr + 9) & 0x80) {
+ floatx_chs(tmp);
+ }
fpush();
ST0 = tmp;
}
@@ -3959,17 +3992,19 @@ void helper_fbst_ST0(target_ulong ptr)
void helper_f2xm1(void)
{
- ST0 = pow(2.0,ST0) - 1.0;
+ double val = CPU86_LDouble_to_double(ST0);
+ val = pow(2.0, val) - 1.0;
+ ST0 = double_to_CPU86_LDouble(val);
}
void helper_fyl2x(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = CPU86_LDouble_to_double(ST0);
- fptemp = ST0;
if (fptemp>0.0){
- fptemp = log(fptemp)/log(2.0); /* log2(ST) */
- ST1 *= fptemp;
+ fptemp = log(fptemp)/log(2.0); /* log2(ST) */
+ fptemp *= CPU86_LDouble_to_double(ST1);
+ ST1 = double_to_CPU86_LDouble(fptemp);
fpop();
} else {
env->fpus &= (~0x4700);
@@ -3979,15 +4014,15 @@ void helper_fyl2x(void)
void helper_fptan(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = CPU86_LDouble_to_double(ST0);
- fptemp = ST0;
if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
env->fpus |= 0x400;
} else {
- ST0 = tan(fptemp);
+ fptemp = tan(fptemp);
+ ST0 = double_to_CPU86_LDouble(fptemp);
fpush();
- ST0 = 1.0;
+ ST0 = floatx_one;
env->fpus &= (~0x400); /* C2 <-- 0 */
/* the above code is for |arg| < 2**52 only */
}
@@ -3995,45 +4030,57 @@ void helper_fptan(void)
void helper_fpatan(void)
{
- CPU86_LDouble fptemp, fpsrcop;
+ double fptemp, fpsrcop;
- fpsrcop = ST1;
- fptemp = ST0;
- ST1 = atan2(fpsrcop,fptemp);
+ fpsrcop = CPU86_LDouble_to_double(ST1);
+ fptemp = CPU86_LDouble_to_double(ST0);
+ ST1 = double_to_CPU86_LDouble(atan2(fpsrcop, fptemp));
fpop();
}
void helper_fxtract(void)
{
CPU86_LDoubleU temp;
- unsigned int expdif;
temp.d = ST0;
- expdif = EXPD(temp) - EXPBIAS;
- /*DP exponent bias*/
- ST0 = expdif;
- fpush();
- BIASEXPONENT(temp);
- ST0 = temp.d;
+
+ if (floatx_is_zero(ST0)) {
+ /* Easy way to generate -inf and raising division by 0 exception */
+ ST0 = floatx_div(floatx_chs(floatx_one), floatx_zero, &env->fp_status);
+ fpush();
+ ST0 = temp.d;
+ } else {
+ int expdif;
+
+ expdif = EXPD(temp) - EXPBIAS;
+ /*DP exponent bias*/
+ ST0 = int32_to_floatx(expdif, &env->fp_status);
+ fpush();
+ BIASEXPONENT(temp);
+ ST0 = temp.d;
+ }
}
void helper_fprem1(void)
{
- CPU86_LDouble dblq, fpsrcop, fptemp;
+ double st0, st1, dblq, fpsrcop, fptemp;
CPU86_LDoubleU fpsrcop1, fptemp1;
int expdif;
signed long long int q;
- if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
- ST0 = 0.0 / 0.0; /* NaN */
+ st0 = CPU86_LDouble_to_double(ST0);
+ st1 = CPU86_LDouble_to_double(ST1);
+
+ if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
+ ST0 = double_to_CPU86_LDouble(0.0 / 0.0); /* NaN */
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
return;
}
- fpsrcop = ST0;
- fptemp = ST1;
- fpsrcop1.d = fpsrcop;
- fptemp1.d = fptemp;
+ fpsrcop = st0;
+ fptemp = st1;
+ fpsrcop1.d = ST0;
+ fptemp1.d = ST1;
expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
if (expdif < 0) {
@@ -4047,7 +4094,7 @@ void helper_fprem1(void)
dblq = fpsrcop / fptemp;
/* round dblq towards nearest integer */
dblq = rint(dblq);
- ST0 = fpsrcop - fptemp * dblq;
+ st0 = fpsrcop - fptemp * dblq;
/* convert dblq to q by truncating towards zero */
if (dblq < 0.0)
@@ -4063,31 +4110,35 @@ void helper_fprem1(void)
} else {
env->fpus |= 0x400; /* C2 <-- 1 */
fptemp = pow(2.0, expdif - 50);
- fpsrcop = (ST0 / ST1) / fptemp;
+ fpsrcop = (st0 / st1) / fptemp;
/* fpsrcop = integer obtained by chopping */
fpsrcop = (fpsrcop < 0.0) ?
-(floor(fabs(fpsrcop))) : floor(fpsrcop);
- ST0 -= (ST1 * fpsrcop * fptemp);
+ st0 -= (st1 * fpsrcop * fptemp);
}
+ ST0 = double_to_CPU86_LDouble(st0);
}
void helper_fprem(void)
{
- CPU86_LDouble dblq, fpsrcop, fptemp;
+ double st0, st1, dblq, fpsrcop, fptemp;
CPU86_LDoubleU fpsrcop1, fptemp1;
int expdif;
signed long long int q;
- if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
- ST0 = 0.0 / 0.0; /* NaN */
+ st0 = CPU86_LDouble_to_double(ST0);
+ st1 = CPU86_LDouble_to_double(ST1);
+
+ if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
+ ST0 = double_to_CPU86_LDouble(0.0 / 0.0); /* NaN */
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
return;
}
- fpsrcop = (CPU86_LDouble)ST0;
- fptemp = (CPU86_LDouble)ST1;
- fpsrcop1.d = fpsrcop;
- fptemp1.d = fptemp;
+ fpsrcop = st0;
+ fptemp = st1;
+ fpsrcop1.d = ST0;
+ fptemp1.d = ST1;
expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
if (expdif < 0) {
@@ -4101,7 +4152,7 @@ void helper_fprem(void)
dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
/* round dblq towards zero */
dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
- ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
+ st0 = fpsrcop/*ST0*/ - fptemp * dblq;
/* convert dblq to q by truncating towards zero */
if (dblq < 0.0)
@@ -4118,22 +4169,23 @@ void helper_fprem(void)
int N = 32 + (expdif % 32); /* as per AMD docs */
env->fpus |= 0x400; /* C2 <-- 1 */
fptemp = pow(2.0, (double)(expdif - N));
- fpsrcop = (ST0 / ST1) / fptemp;
+ fpsrcop = (st0 / st1) / fptemp;
/* fpsrcop = integer obtained by chopping */
fpsrcop = (fpsrcop < 0.0) ?
-(floor(fabs(fpsrcop))) : floor(fpsrcop);
- ST0 -= (ST1 * fpsrcop * fptemp);
+ st0 -= (st1 * fpsrcop * fptemp);
}
+ ST0 = double_to_CPU86_LDouble(st0);
}
void helper_fyl2xp1(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = CPU86_LDouble_to_double(ST0);
- fptemp = ST0;
if ((fptemp+1.0)>0.0) {
fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
- ST1 *= fptemp;
+ fptemp *= CPU86_LDouble_to_double(ST1);
+ ST1 = double_to_CPU86_LDouble(fptemp);
fpop();
} else {
env->fpus &= (~0x4700);
@@ -4143,27 +4195,23 @@ void helper_fyl2xp1(void)
void helper_fsqrt(void)
{
- CPU86_LDouble fptemp;
-
- fptemp = ST0;
- if (fptemp<0.0) {
+ if (floatx_is_neg(ST0)) {
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
env->fpus |= 0x400;
}
- ST0 = sqrt(fptemp);
+ ST0 = floatx_sqrt(ST0, &env->fp_status);
}
void helper_fsincos(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = CPU86_LDouble_to_double(ST0);
- fptemp = ST0;
if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
env->fpus |= 0x400;
} else {
- ST0 = sin(fptemp);
+ ST0 = double_to_CPU86_LDouble(sin(fptemp));
fpush();
- ST0 = cos(fptemp);
+ ST0 = double_to_CPU86_LDouble(cos(fptemp));
env->fpus &= (~0x400); /* C2 <-- 0 */
/* the above code is for |arg| < 2**63 only */
}
@@ -4176,18 +4224,22 @@ void helper_frndint(void)
void helper_fscale(void)
{
- ST0 = ldexp (ST0, (int)(ST1));
+ if (floatx_is_any_nan(ST1)) {
+ ST0 = ST1;
+ } else {
+ int n = floatx_to_int32_round_to_zero(ST1, &env->fp_status);
+ ST0 = floatx_scalbn(ST0, n, &env->fp_status);
+ }
}
void helper_fsin(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = CPU86_LDouble_to_double(ST0);
- fptemp = ST0;
if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
env->fpus |= 0x400;
} else {
- ST0 = sin(fptemp);
+ ST0 = double_to_CPU86_LDouble(sin(fptemp));
env->fpus &= (~0x400); /* C2 <-- 0 */
/* the above code is for |arg| < 2**53 only */
}
@@ -4195,13 +4247,12 @@ void helper_fsin(void)
void helper_fcos(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = CPU86_LDouble_to_double(ST0);
- fptemp = ST0;
if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
env->fpus |= 0x400;
} else {
- ST0 = cos(fptemp);
+ ST0 = double_to_CPU86_LDouble(cos(fptemp));
env->fpus &= (~0x400); /* C2 <-- 0 */
/* the above code is for |arg5 < 2**63 only */
}
@@ -4783,16 +4834,6 @@ void helper_boundl(target_ulong a0, int v)
}
}
-static float approx_rsqrt(float a)
-{
- return 1.0 / sqrt(a);
-}
-
-static float approx_rcp(float a)
-{
- return 1.0 / a;
-}
-
#if !defined(CONFIG_USER_ONLY)
#define MMUSUFFIX _mmu
@@ -4837,7 +4878,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 3232abd96..703be99cd 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -778,28 +778,38 @@ int64_t helper_cvttsd2sq(XMMReg *s)
void helper_rsqrtps(XMMReg *d, XMMReg *s)
{
- d->XMM_S(0) = approx_rsqrt(s->XMM_S(0));
- d->XMM_S(1) = approx_rsqrt(s->XMM_S(1));
- d->XMM_S(2) = approx_rsqrt(s->XMM_S(2));
- d->XMM_S(3) = approx_rsqrt(s->XMM_S(3));
+ d->XMM_S(0) = float32_div(float32_one,
+ float32_sqrt(s->XMM_S(0), &env->sse_status),
+ &env->sse_status);
+ d->XMM_S(1) = float32_div(float32_one,
+ float32_sqrt(s->XMM_S(1), &env->sse_status),
+ &env->sse_status);
+ d->XMM_S(2) = float32_div(float32_one,
+ float32_sqrt(s->XMM_S(2), &env->sse_status),
+ &env->sse_status);
+ d->XMM_S(3) = float32_div(float32_one,
+ float32_sqrt(s->XMM_S(3), &env->sse_status),
+ &env->sse_status);
}
void helper_rsqrtss(XMMReg *d, XMMReg *s)
{
- d->XMM_S(0) = approx_rsqrt(s->XMM_S(0));
+ d->XMM_S(0) = float32_div(float32_one,
+ float32_sqrt(s->XMM_S(0), &env->sse_status),
+ &env->sse_status);
}
void helper_rcpps(XMMReg *d, XMMReg *s)
{
- d->XMM_S(0) = approx_rcp(s->XMM_S(0));
- d->XMM_S(1) = approx_rcp(s->XMM_S(1));
- d->XMM_S(2) = approx_rcp(s->XMM_S(2));
- d->XMM_S(3) = approx_rcp(s->XMM_S(3));
+ d->XMM_S(0) = float32_div(float32_one, s->XMM_S(0), &env->sse_status);
+ d->XMM_S(1) = float32_div(float32_one, s->XMM_S(1), &env->sse_status);
+ d->XMM_S(2) = float32_div(float32_one, s->XMM_S(2), &env->sse_status);
+ d->XMM_S(3) = float32_div(float32_one, s->XMM_S(3), &env->sse_status);
}
void helper_rcpss(XMMReg *d, XMMReg *s)
{
- d->XMM_S(0) = approx_rcp(s->XMM_S(0));
+ d->XMM_S(0) = float32_div(float32_one, s->XMM_S(0), &env->sse_status);
}
static inline uint64_t helper_extrq(uint64_t src, int shift, int len)
@@ -921,14 +931,14 @@ void helper_ ## name ## sd (Reg *d, Reg *s)\
d->XMM_Q(0) = F(64, d->XMM_D(0), s->XMM_D(0));\
}
-#define FPU_CMPEQ(size, a, b) float ## size ## _eq(a, b, &env->sse_status) ? -1 : 0
+#define FPU_CMPEQ(size, a, b) float ## size ## _eq_quiet(a, b, &env->sse_status) ? -1 : 0
#define FPU_CMPLT(size, a, b) float ## size ## _lt(a, b, &env->sse_status) ? -1 : 0
#define FPU_CMPLE(size, a, b) float ## size ## _le(a, b, &env->sse_status) ? -1 : 0
-#define FPU_CMPUNORD(size, a, b) float ## size ## _unordered(a, b, &env->sse_status) ? - 1 : 0
-#define FPU_CMPNEQ(size, a, b) float ## size ## _eq(a, b, &env->sse_status) ? 0 : -1
+#define FPU_CMPUNORD(size, a, b) float ## size ## _unordered_quiet(a, b, &env->sse_status) ? - 1 : 0
+#define FPU_CMPNEQ(size, a, b) float ## size ## _eq_quiet(a, b, &env->sse_status) ? 0 : -1
#define FPU_CMPNLT(size, a, b) float ## size ## _lt(a, b, &env->sse_status) ? 0 : -1
#define FPU_CMPNLE(size, a, b) float ## size ## _le(a, b, &env->sse_status) ? 0 : -1
-#define FPU_CMPORD(size, a, b) float ## size ## _unordered(a, b, &env->sse_status) ? 0 : -1
+#define FPU_CMPORD(size, a, b) float ## size ## _unordered_quiet(a, b, &env->sse_status) ? 0 : -1
SSE_HELPER_CMP(cmpeq, FPU_CMPEQ)
SSE_HELPER_CMP(cmplt, FPU_CMPLT)
@@ -1216,8 +1226,8 @@ void helper_pfadd(MMXReg *d, MMXReg *s)
void helper_pfcmpeq(MMXReg *d, MMXReg *s)
{
- d->MMX_L(0) = float32_eq(d->MMX_S(0), s->MMX_S(0), &env->mmx_status) ? -1 : 0;
- d->MMX_L(1) = float32_eq(d->MMX_S(1), s->MMX_S(1), &env->mmx_status) ? -1 : 0;
+ d->MMX_L(0) = float32_eq_quiet(d->MMX_S(0), s->MMX_S(0), &env->mmx_status) ? -1 : 0;
+ d->MMX_L(1) = float32_eq_quiet(d->MMX_S(1), s->MMX_S(1), &env->mmx_status) ? -1 : 0;
}
void helper_pfcmpge(MMXReg *d, MMXReg *s)
@@ -1272,14 +1282,16 @@ void helper_pfpnacc(MMXReg *d, MMXReg *s)
void helper_pfrcp(MMXReg *d, MMXReg *s)
{
- d->MMX_S(0) = approx_rcp(s->MMX_S(0));
+ d->MMX_S(0) = float32_div(float32_one, s->MMX_S(0), &env->mmx_status);
d->MMX_S(1) = d->MMX_S(0);
}
void helper_pfrsqrt(MMXReg *d, MMXReg *s)
{
d->MMX_L(1) = s->MMX_L(0) & 0x7fffffff;
- d->MMX_S(1) = approx_rsqrt(d->MMX_S(1));
+ d->MMX_S(1) = float32_div(float32_one,
+ float32_sqrt(d->MMX_S(1), &env->mmx_status),
+ &env->mmx_status);
d->MMX_L(1) |= s->MMX_L(0) & 0x80000000;
d->MMX_L(0) = d->MMX_L(1);
}
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 7d1340ed0..199302e51 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7890,8 +7890,7 @@ void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
gen_intermediate_code_internal(env, tb, 1);
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
int cc_op;
#ifdef DEBUG_DISAS
@@ -7903,8 +7902,8 @@ void gen_pc_load(CPUState *env, TranslationBlock *tb,
qemu_log("0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
}
}
- qemu_log("spc=0x%08lx pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
- searched_pc, pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
+ qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
+ pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
(uint32_t)tb->cs_base);
}
#endif
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 318e2cf6e..4f3e7e0fc 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -76,11 +76,7 @@ void do_interrupt(CPUState *env)
env->regs[R_BA] = env->pc;
env->ie |= (env->ie & IE_IE) ? IE_BIE : 0;
env->ie &= ~IE_IE;
- if (env->dc & DC_RE) {
- env->pc = env->deba + (env->exception_index * 32);
- } else {
- env->pc = env->eba + (env->exception_index * 32);
- }
+ env->pc = env->deba + (env->exception_index * 32);
log_cpu_state_mask(CPU_LOG_INT, env, 0);
break;
default:
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index e84ba488b..c72b1df47 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -95,7 +95,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
cpu_loop_exit();
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index efc9b5a85..bcd52fe73 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -598,36 +598,10 @@ static void dec_scall(DisasContext *dc)
t0 = tcg_temp_new();
l1 = gen_new_label();
- /* save IE.IE */
- tcg_gen_andi_tl(t0, cpu_ie, IE_IE);
-
- /* IE.IE = 0 */
- tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE);
-
if (dc->imm5 == 7) {
- /* IE.EIE = IE.IE */
- tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_EIE);
- tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_IE, l1);
- tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_EIE);
- gen_set_label(l1);
-
- /* gpr[ea] = PC */
- tcg_gen_movi_tl(cpu_R[R_EA], dc->pc);
- tcg_temp_free(t0);
-
tcg_gen_movi_tl(cpu_pc, dc->pc);
t_gen_raise_exception(dc, EXCP_SYSTEMCALL);
} else {
- /* IE.BIE = IE.IE */
- tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_BIE);
- tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_IE, l1);
- tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_BIE);
- gen_set_label(l1);
-
- /* gpr[ba] = PC */
- tcg_gen_movi_tl(cpu_R[R_BA], dc->pc);
- tcg_temp_free(t0);
-
tcg_gen_movi_tl(cpu_pc, dc->pc);
t_gen_raise_exception(dc, EXCP_BREAKPOINT);
}
@@ -1212,8 +1186,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "\n\n");
}
-void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->pc = gen_opc_pc[pc_pos];
}
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 07111073f..9b13bdbcc 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -68,7 +68,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
cpu_loop_exit();
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 038c0af3e..9e5578d45 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3113,8 +3113,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->pc = gen_opc_pc[pc_pos];
}
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 39b8ec1e1..c7b2f97d9 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -60,7 +60,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
cpu_loop_exit();
@@ -338,7 +338,7 @@ uint32_t helper_fcmp_eq(uint32_t a, uint32_t b)
set_float_exception_flags(0, &env->fp_status);
fa.l = a;
fb.l = b;
- r = float32_eq(fa.f, fb.f, &env->fp_status);
+ r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
update_fpu_flags(flags & float_flag_invalid);
@@ -384,7 +384,7 @@ uint32_t helper_fcmp_ne(uint32_t a, uint32_t b)
fa.l = a;
fb.l = b;
set_float_exception_flags(0, &env->fp_status);
- r = !float32_eq(fa.f, fb.f, &env->fp_status);
+ r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
update_fpu_flags(flags & float_flag_invalid);
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index bff3a11bc..b47b92e90 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1940,8 +1940,7 @@ void cpu_reset (CPUState *env)
#endif
}
-void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->sregs[SR_PC] = gen_opc_pc[pc_pos];
}
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index bd16ce354..b8e4991f3 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -54,7 +54,7 @@ static void do_restore_state (void *pc_ptr)
tb = tb_find_pc (pc);
if (tb) {
- cpu_restore_state (tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
#endif
@@ -1972,7 +1972,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
helper_raise_exception_err(env->exception_index, env->error_code);
@@ -2077,22 +2077,27 @@ void helper_ctc1 (target_ulong arg1, uint32_t reg)
helper_raise_exception(EXCP_FPE);
}
-static inline char ieee_ex_to_mips(char xcpt)
+static inline int ieee_ex_to_mips(int xcpt)
{
- return (xcpt & float_flag_inexact) >> 5 |
- (xcpt & float_flag_underflow) >> 3 |
- (xcpt & float_flag_overflow) >> 1 |
- (xcpt & float_flag_divbyzero) << 1 |
- (xcpt & float_flag_invalid) << 4;
-}
-
-static inline char mips_ex_to_ieee(char xcpt)
-{
- return (xcpt & FP_INEXACT) << 5 |
- (xcpt & FP_UNDERFLOW) << 3 |
- (xcpt & FP_OVERFLOW) << 1 |
- (xcpt & FP_DIV0) >> 1 |
- (xcpt & FP_INVALID) >> 4;
+ int ret = 0;
+ if (xcpt) {
+ if (xcpt & float_flag_invalid) {
+ ret |= FP_INVALID;
+ }
+ if (xcpt & float_flag_overflow) {
+ ret |= FP_OVERFLOW;
+ }
+ if (xcpt & float_flag_underflow) {
+ ret |= FP_UNDERFLOW;
+ }
+ if (xcpt & float_flag_divbyzero) {
+ ret |= FP_DIV0;
+ }
+ if (xcpt & float_flag_inexact) {
+ ret |= FP_INEXACT;
+ }
+ }
+ return ret;
}
static inline void update_fcr31(void)
@@ -2869,7 +2874,9 @@ uint64_t helper_float_mulr_ps(uint64_t fdt0, uint64_t fdt1)
#define FOP_COND_D(op, cond) \
void helper_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
{ \
- int c = cond; \
+ int c; \
+ set_float_exception_flags(0, &env->active_fpu.fp_status); \
+ c = cond; \
update_fcr31(); \
if (c) \
SET_FP_COND(cc, env->active_fpu); \
@@ -2879,6 +2886,7 @@ void helper_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
void helper_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
{ \
int c; \
+ set_float_exception_flags(0, &env->active_fpu.fp_status); \
fdt0 = float64_abs(fdt0); \
fdt1 = float64_abs(fdt1); \
c = cond; \
@@ -2889,45 +2897,33 @@ void helper_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
CLEAR_FP_COND(cc, env->active_fpu); \
}
-static int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
-{
- if (float64_is_signaling_nan(a) ||
- float64_is_signaling_nan(b) ||
- (sig && (float64_is_quiet_nan(a) || float64_is_quiet_nan(b)))) {
- float_raise(float_flag_invalid, status);
- return 1;
- } else if (float64_is_quiet_nan(a) || float64_is_quiet_nan(b)) {
- return 1;
- } else {
- return 0;
- }
-}
-
/* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called. */
-FOP_COND_D(f, (float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status), 0))
-FOP_COND_D(un, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status))
-FOP_COND_D(eq, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ueq, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(olt, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ult, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ole, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ule, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
+ * but float64_unordered_quiet() is still called. */
+FOP_COND_D(f, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0))
+FOP_COND_D(un, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status))
+FOP_COND_D(eq, float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(olt, float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ole, float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) || float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
/* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called. */
-FOP_COND_D(sf, (float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status), 0))
-FOP_COND_D(ngle,float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status))
-FOP_COND_D(seq, !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ngl, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(lt, !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(nge, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(le, !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ngt, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
+ * but float64_unordered() is still called. */
+FOP_COND_D(sf, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0))
+FOP_COND_D(ngle,float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status))
+FOP_COND_D(seq, float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(lt, float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(nge, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(le, float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ngt, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
#define FOP_COND_S(op, cond) \
void helper_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
{ \
- int c = cond; \
+ int c; \
+ set_float_exception_flags(0, &env->active_fpu.fp_status); \
+ c = cond; \
update_fcr31(); \
if (c) \
SET_FP_COND(cc, env->active_fpu); \
@@ -2937,6 +2933,7 @@ void helper_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
void helper_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
{ \
int c; \
+ set_float_exception_flags(0, &env->active_fpu.fp_status); \
fst0 = float32_abs(fst0); \
fst1 = float32_abs(fst1); \
c = cond; \
@@ -2947,51 +2944,39 @@ void helper_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
CLEAR_FP_COND(cc, env->active_fpu); \
}
-static flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
-{
- if (float32_is_signaling_nan(a) ||
- float32_is_signaling_nan(b) ||
- (sig && (float32_is_quiet_nan(a) || float32_is_quiet_nan(b)))) {
- float_raise(float_flag_invalid, status);
- return 1;
- } else if (float32_is_quiet_nan(a) || float32_is_quiet_nan(b)) {
- return 1;
- } else {
- return 0;
- }
-}
-
/* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called. */
-FOP_COND_S(f, (float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status), 0))
-FOP_COND_S(un, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status))
-FOP_COND_S(eq, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ueq, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(olt, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ult, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ole, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ule, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status))
+ * but float32_unordered_quiet() is still called. */
+FOP_COND_S(f, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0))
+FOP_COND_S(un, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status))
+FOP_COND_S(eq, float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
/* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called. */
-FOP_COND_S(sf, (float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status), 0))
-FOP_COND_S(ngle,float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status))
-FOP_COND_S(seq, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ngl, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(lt, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(nge, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(le, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ngt, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status))
+ * but float32_unordered() is still called. */
+FOP_COND_S(sf, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0))
+FOP_COND_S(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status))
+FOP_COND_S(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(lt, float32_lt(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(le, float32_le(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status))
#define FOP_COND_PS(op, condl, condh) \
void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
{ \
- uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \
- uint32_t fsth0 = float32_abs(fdt0 >> 32); \
- uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \
- uint32_t fsth1 = float32_abs(fdt1 >> 32); \
- int cl = condl; \
- int ch = condh; \
- \
+ uint32_t fst0, fsth0, fst1, fsth1; \
+ int ch, cl; \
+ set_float_exception_flags(0, &env->active_fpu.fp_status); \
+ fst0 = fdt0 & 0XFFFFFFFF; \
+ fsth0 = fdt0 >> 32; \
+ fst1 = fdt1 & 0XFFFFFFFF; \
+ fsth1 = fdt1 >> 32; \
+ cl = condl; \
+ ch = condh; \
update_fcr31(); \
if (cl) \
SET_FP_COND(cc, env->active_fpu); \
@@ -3004,13 +2989,14 @@ void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
} \
void helper_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
{ \
- uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \
- uint32_t fsth0 = float32_abs(fdt0 >> 32); \
- uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \
- uint32_t fsth1 = float32_abs(fdt1 >> 32); \
- int cl = condl; \
- int ch = condh; \
- \
+ uint32_t fst0, fsth0, fst1, fsth1; \
+ int ch, cl; \
+ fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \
+ fsth0 = float32_abs(fdt0 >> 32); \
+ fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \
+ fsth1 = float32_abs(fdt1 >> 32); \
+ cl = condl; \
+ ch = condh; \
update_fcr31(); \
if (cl) \
SET_FP_COND(cc, env->active_fpu); \
@@ -3023,38 +3009,38 @@ void helper_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
}
/* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called. */
-FOP_COND_PS(f, (float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status), 0),
- (float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status), 0))
-FOP_COND_PS(un, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status),
- float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status))
-FOP_COND_PS(eq, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
- !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ueq, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
- float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(olt, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
- !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ult, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
- float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ole, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status),
- !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ule, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status),
- float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
+ * but float32_unordered_quiet() is still called. */
+FOP_COND_PS(f, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0),
+ (float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status), 0))
+FOP_COND_PS(un, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status),
+ float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status))
+FOP_COND_PS(eq, float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
+ float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
+ float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) || float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
+ float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
+ float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) || float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
+ float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
+ float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) || float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
/* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called. */
-FOP_COND_PS(sf, (float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status), 0),
- (float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status), 0))
-FOP_COND_PS(ngle,float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status),
- float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status))
-FOP_COND_PS(seq, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
- !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ngl, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
- float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(lt, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
- !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(nge, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
- float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(le, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status),
- !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ngt, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status),
- float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
+ * but float32_unordered() is still called. */
+FOP_COND_PS(sf, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0),
+ (float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status), 0))
+FOP_COND_PS(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status),
+ float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status))
+FOP_COND_PS(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status),
+ float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
+ float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(lt, float32_lt(fst0, fst1, &env->active_fpu.fp_status),
+ float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
+ float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(le, float32_le(fst0, fst1, &env->active_fpu.fp_status),
+ float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status),
+ float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 953c52806..4eaa8261c 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -12737,8 +12737,7 @@ void cpu_reset (CPUMIPSState *env)
env->exception_index = EXCP_NONE;
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->active_tc.PC = gen_opc_pc[pc_pos];
env->hflags &= ~MIPS_HFLAG_BMASK;
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 8c993a1cf..d5db484b4 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3343,7 +3343,7 @@ HELPER_SPE_VECTOR_ARITH(fsmul);
HELPER_SPE_VECTOR_ARITH(fsdiv);
/* Single-precision floating-point comparisons */
-static inline uint32_t efststlt(uint32_t op1, uint32_t op2)
+static inline uint32_t efscmplt(uint32_t op1, uint32_t op2)
{
CPU_FloatU u1, u2;
u1.l = op1;
@@ -3351,7 +3351,7 @@ static inline uint32_t efststlt(uint32_t op1, uint32_t op2)
return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
}
-static inline uint32_t efststgt(uint32_t op1, uint32_t op2)
+static inline uint32_t efscmpgt(uint32_t op1, uint32_t op2)
{
CPU_FloatU u1, u2;
u1.l = op1;
@@ -3359,7 +3359,7 @@ static inline uint32_t efststgt(uint32_t op1, uint32_t op2)
return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
}
-static inline uint32_t efststeq(uint32_t op1, uint32_t op2)
+static inline uint32_t efscmpeq(uint32_t op1, uint32_t op2)
{
CPU_FloatU u1, u2;
u1.l = op1;
@@ -3367,22 +3367,22 @@ static inline uint32_t efststeq(uint32_t op1, uint32_t op2)
return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
}
-static inline uint32_t efscmplt(uint32_t op1, uint32_t op2)
+static inline uint32_t efststlt(uint32_t op1, uint32_t op2)
{
- /* XXX: TODO: test special values (NaN, infinites, ...) */
- return efststlt(op1, op2);
+ /* XXX: TODO: ignore special values (NaN, infinites, ...) */
+ return efscmplt(op1, op2);
}
-static inline uint32_t efscmpgt(uint32_t op1, uint32_t op2)
+static inline uint32_t efststgt(uint32_t op1, uint32_t op2)
{
- /* XXX: TODO: test special values (NaN, infinites, ...) */
- return efststgt(op1, op2);
+ /* XXX: TODO: ignore special values (NaN, infinites, ...) */
+ return efscmpgt(op1, op2);
}
-static inline uint32_t efscmpeq(uint32_t op1, uint32_t op2)
+static inline uint32_t efststeq(uint32_t op1, uint32_t op2)
{
- /* XXX: TODO: test special values (NaN, infinites, ...) */
- return efststeq(op1, op2);
+ /* XXX: TODO: ignore special values (NaN, infinites, ...) */
+ return efscmpeq(op1, op2);
}
#define HELPER_SINGLE_SPE_CMP(name) \
@@ -3678,7 +3678,7 @@ uint32_t helper_efdtsteq (uint64_t op1, uint64_t op2)
CPU_DoubleU u1, u2;
u1.ll = op1;
u2.ll = op2;
- return float64_eq(u1.d, u2.d, &env->vec_status) ? 4 : 0;
+ return float64_eq_quiet(u1.d, u2.d, &env->vec_status) ? 4 : 0;
}
uint32_t helper_efdcmplt (uint64_t op1, uint64_t op2)
@@ -3741,7 +3741,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (likely(tb)) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
helper_raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 3c3ee24c9..a943dbcf8 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9367,8 +9367,7 @@ void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
gen_intermediate_code_internal(env, tb, 1);
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->nip = gen_opc_pc[pc_pos];
}
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index e47c372fb..a84b3ee18 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -26,24 +26,35 @@
#define CPUState struct CPUS390XState
#include "cpu-defs.h"
+#define TARGET_PAGE_BITS 12
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 64
+#define TARGET_VIRT_ADDR_SPACE_BITS 64
+
+#include "cpu-all.h"
#include "softfloat.h"
-#define NB_MMU_MODES 2
+#define NB_MMU_MODES 3
-typedef union FPReg {
- struct {
-#ifdef WORDS_BIGENDIAN
- float32 e;
- int32_t __pad;
-#else
- int32_t __pad;
- float32 e;
-#endif
- };
- float64 d;
- uint64_t i;
-} FPReg;
+#define MMU_MODE0_SUFFIX _primary
+#define MMU_MODE1_SUFFIX _secondary
+#define MMU_MODE2_SUFFIX _home
+
+#define MMU_USER_IDX 1
+
+#define MAX_EXT_QUEUE 16
+
+typedef struct PSW {
+ uint64_t mask;
+ uint64_t addr;
+} PSW;
+
+typedef struct ExtQueue {
+ uint32_t code;
+ uint32_t param;
+ uint32_t param64;
+} ExtQueue;
typedef struct CPUS390XState {
uint64_t regs[16]; /* GP registers */
@@ -51,17 +62,42 @@ typedef struct CPUS390XState {
uint32_t aregs[16]; /* access registers */
uint32_t fpc; /* floating-point control register */
- FPReg fregs[16]; /* FP registers */
+ CPU_DoubleU fregs[16]; /* FP registers */
float_status fpu_status; /* passed to softfloat lib */
- struct {
- uint64_t mask;
- uint64_t addr;
- } psw;
+ PSW psw;
- int cc; /* condition code (0-3) */
+ uint32_t cc;
+ uint32_t cc_op;
+ uint64_t cc_src;
+ uint64_t cc_dst;
+ uint64_t cc_vr;
uint64_t __excp_addr;
+ uint64_t psa;
+
+ uint32_t int_pgm_code;
+ uint32_t int_pgm_ilc;
+
+ uint32_t int_svc_code;
+ uint32_t int_svc_ilc;
+
+ uint64_t cregs[16]; /* control registers */
+
+ int pending_int;
+ ExtQueue ext_queue[MAX_EXT_QUEUE];
+
+ /* reset does memset(0) up to here */
+
+ int ext_index;
+ int cpu_num;
+ uint8_t *storage_keys;
+
+ uint64_t tod_offset;
+ uint64_t tod_basetime;
+ QEMUTimer *tod_timer;
+
+ QEMUTimer *cpu_timer;
CPU_COMMON
} CPUS390XState;
@@ -69,24 +105,174 @@ typedef struct CPUS390XState {
#if defined(CONFIG_USER_ONLY)
static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
{
- if (newsp)
+ if (newsp) {
env->regs[15] = newsp;
+ }
env->regs[0] = 0;
}
#endif
-#define MMU_MODE0_SUFFIX _kernel
-#define MMU_MODE1_SUFFIX _user
-#define MMU_USER_IDX 1
+/* Interrupt Codes */
+/* Program Interrupts */
+#define PGM_OPERATION 0x0001
+#define PGM_PRIVILEGED 0x0002
+#define PGM_EXECUTE 0x0003
+#define PGM_PROTECTION 0x0004
+#define PGM_ADDRESSING 0x0005
+#define PGM_SPECIFICATION 0x0006
+#define PGM_DATA 0x0007
+#define PGM_FIXPT_OVERFLOW 0x0008
+#define PGM_FIXPT_DIVIDE 0x0009
+#define PGM_DEC_OVERFLOW 0x000a
+#define PGM_DEC_DIVIDE 0x000b
+#define PGM_HFP_EXP_OVERFLOW 0x000c
+#define PGM_HFP_EXP_UNDERFLOW 0x000d
+#define PGM_HFP_SIGNIFICANCE 0x000e
+#define PGM_HFP_DIVIDE 0x000f
+#define PGM_SEGMENT_TRANS 0x0010
+#define PGM_PAGE_TRANS 0x0011
+#define PGM_TRANS_SPEC 0x0012
+#define PGM_SPECIAL_OP 0x0013
+#define PGM_OPERAND 0x0015
+#define PGM_TRACE_TABLE 0x0016
+#define PGM_SPACE_SWITCH 0x001c
+#define PGM_HFP_SQRT 0x001d
+#define PGM_PC_TRANS_SPEC 0x001f
+#define PGM_AFX_TRANS 0x0020
+#define PGM_ASX_TRANS 0x0021
+#define PGM_LX_TRANS 0x0022
+#define PGM_EX_TRANS 0x0023
+#define PGM_PRIM_AUTH 0x0024
+#define PGM_SEC_AUTH 0x0025
+#define PGM_ALET_SPEC 0x0028
+#define PGM_ALEN_SPEC 0x0029
+#define PGM_ALE_SEQ 0x002a
+#define PGM_ASTE_VALID 0x002b
+#define PGM_ASTE_SEQ 0x002c
+#define PGM_EXT_AUTH 0x002d
+#define PGM_STACK_FULL 0x0030
+#define PGM_STACK_EMPTY 0x0031
+#define PGM_STACK_SPEC 0x0032
+#define PGM_STACK_TYPE 0x0033
+#define PGM_STACK_OP 0x0034
+#define PGM_ASCE_TYPE 0x0038
+#define PGM_REG_FIRST_TRANS 0x0039
+#define PGM_REG_SEC_TRANS 0x003a
+#define PGM_REG_THIRD_TRANS 0x003b
+#define PGM_MONITOR 0x0040
+#define PGM_PER 0x0080
+#define PGM_CRYPTO 0x0119
+
+/* External Interrupts */
+#define EXT_INTERRUPT_KEY 0x0040
+#define EXT_CLOCK_COMP 0x1004
+#define EXT_CPU_TIMER 0x1005
+#define EXT_MALFUNCTION 0x1200
+#define EXT_EMERGENCY 0x1201
+#define EXT_EXTERNAL_CALL 0x1202
+#define EXT_ETR 0x1406
+#define EXT_SERVICE 0x2401
+#define EXT_VIRTIO 0x2603
+
+/* PSW defines */
+#undef PSW_MASK_PER
+#undef PSW_MASK_DAT
+#undef PSW_MASK_IO
+#undef PSW_MASK_EXT
+#undef PSW_MASK_KEY
+#undef PSW_SHIFT_KEY
+#undef PSW_MASK_MCHECK
+#undef PSW_MASK_WAIT
+#undef PSW_MASK_PSTATE
+#undef PSW_MASK_ASC
+#undef PSW_MASK_CC
+#undef PSW_MASK_PM
+#undef PSW_MASK_64
+
+#define PSW_MASK_PER 0x4000000000000000ULL
+#define PSW_MASK_DAT 0x0400000000000000ULL
+#define PSW_MASK_IO 0x0200000000000000ULL
+#define PSW_MASK_EXT 0x0100000000000000ULL
+#define PSW_MASK_KEY 0x00F0000000000000ULL
+#define PSW_SHIFT_KEY 56
+#define PSW_MASK_MCHECK 0x0004000000000000ULL
+#define PSW_MASK_WAIT 0x0002000000000000ULL
+#define PSW_MASK_PSTATE 0x0001000000000000ULL
+#define PSW_MASK_ASC 0x0000C00000000000ULL
+#define PSW_MASK_CC 0x0000300000000000ULL
+#define PSW_MASK_PM 0x00000F0000000000ULL
+#define PSW_MASK_64 0x0000000100000000ULL
+#define PSW_MASK_32 0x0000000080000000ULL
+
+#undef PSW_ASC_PRIMARY
+#undef PSW_ASC_ACCREG
+#undef PSW_ASC_SECONDARY
+#undef PSW_ASC_HOME
+
+#define PSW_ASC_PRIMARY 0x0000000000000000ULL
+#define PSW_ASC_ACCREG 0x0000400000000000ULL
+#define PSW_ASC_SECONDARY 0x0000800000000000ULL
+#define PSW_ASC_HOME 0x0000C00000000000ULL
+
+/* tb flags */
+
+#define FLAG_MASK_PER (PSW_MASK_PER >> 32)
+#define FLAG_MASK_DAT (PSW_MASK_DAT >> 32)
+#define FLAG_MASK_IO (PSW_MASK_IO >> 32)
+#define FLAG_MASK_EXT (PSW_MASK_EXT >> 32)
+#define FLAG_MASK_KEY (PSW_MASK_KEY >> 32)
+#define FLAG_MASK_MCHECK (PSW_MASK_MCHECK >> 32)
+#define FLAG_MASK_WAIT (PSW_MASK_WAIT >> 32)
+#define FLAG_MASK_PSTATE (PSW_MASK_PSTATE >> 32)
+#define FLAG_MASK_ASC (PSW_MASK_ASC >> 32)
+#define FLAG_MASK_CC (PSW_MASK_CC >> 32)
+#define FLAG_MASK_PM (PSW_MASK_PM >> 32)
+#define FLAG_MASK_64 (PSW_MASK_64 >> 32)
+#define FLAG_MASK_32 0x00001000
+
static inline int cpu_mmu_index (CPUState *env)
{
- /* XXX: Currently we don't implement virtual memory */
+ if (env->psw.mask & PSW_MASK_PSTATE) {
+ return 1;
+ }
+
return 0;
}
+static inline void cpu_get_tb_cpu_state(CPUState* env, target_ulong *pc,
+ target_ulong *cs_base, int *flags)
+{
+ *pc = env->psw.addr;
+ *cs_base = 0;
+ *flags = ((env->psw.mask >> 32) & ~FLAG_MASK_CC) |
+ ((env->psw.mask & PSW_MASK_32) ? FLAG_MASK_32 : 0);
+}
+
+static inline int get_ilc(uint8_t opc)
+{
+ switch (opc >> 6) {
+ case 0:
+ return 1;
+ case 1:
+ case 2:
+ return 2;
+ case 3:
+ return 3;
+ }
+
+ return 0;
+}
+
+#define ILC_LATER 0x20
+#define ILC_LATER_INC 0x21
+#define ILC_LATER_INC_2 0x22
+
+
CPUS390XState *cpu_s390x_init(const char *cpu_model);
+void s390x_translate_init(void);
int cpu_s390x_exec(CPUS390XState *s);
void cpu_s390x_close(CPUS390XState *s);
+void do_interrupt (CPUState *env);
/* you can call this signal handler from your SIGBUS and SIGSEGV
signal handlers to inform the virtual CPU of exceptions. non zero
@@ -97,41 +283,61 @@ int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw
int mmu_idx, int is_softmuu);
#define cpu_handle_mmu_fault cpu_s390x_handle_mmu_fault
-#define TARGET_PAGE_BITS 12
-
-/* ??? This is certainly wrong for 64-bit s390x, but given that only KVM
- emulation actually works, this is good enough for a placeholder. */
-#define TARGET_PHYS_ADDR_SPACE_BITS 32
-#define TARGET_VIRT_ADDR_SPACE_BITS 32
#ifndef CONFIG_USER_ONLY
-int s390_virtio_hypercall(CPUState *env);
+int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall);
+
+void kvm_s390_interrupt(CPUState *env, int type, uint32_t code);
void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token);
+void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
+ uint64_t parm64, int vm);
CPUState *s390_cpu_addr2state(uint16_t cpu_addr);
+
+#ifndef KVM_S390_SIGP_STOP
+#define KVM_S390_SIGP_STOP 0
+#define KVM_S390_PROGRAM_INT 0
+#define KVM_S390_SIGP_SET_PREFIX 0
+#define KVM_S390_RESTART 0
+#define KVM_S390_INT_VIRTIO 0
+#define KVM_S390_INT_SERVICE 0
+#define KVM_S390_INT_EMERGENCY 0
+#endif
+
#endif
+void cpu_lock(void);
+void cpu_unlock(void);
+static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
+{
+ env->aregs[0] = newtls >> 32;
+ env->aregs[1] = newtls & 0xffffffffULL;
+}
#define cpu_init cpu_s390x_init
#define cpu_exec cpu_s390x_exec
#define cpu_gen_code cpu_s390x_gen_code
+#define cpu_signal_handler cpu_s390x_signal_handler
-#include "cpu-all.h"
+#include "exec-all.h"
+
+#ifdef CONFIG_USER_ONLY
#define EXCP_OPEX 1 /* operation exception (sigill) */
#define EXCP_SVC 2 /* supervisor call (syscall) */
#define EXCP_ADDR 5 /* addressing exception */
-#define EXCP_EXECUTE_SVC 0xff00000 /* supervisor call via execute insn */
+#define EXCP_SPEC 6 /* specification exception */
-static inline void cpu_get_tb_cpu_state(CPUState* env, target_ulong *pc,
- target_ulong *cs_base, int *flags)
-{
- *pc = env->psw.addr;
- /* XXX this is correct for user-mode emulation, but needs
- * the asce register information as well when softmmu
- * is implemented in the future */
- *cs_base = 0;
- *flags = env->psw.mask;
-}
+#else
+
+#define EXCP_EXT 1 /* external interrupt */
+#define EXCP_SVC 2 /* supervisor call (syscall) */
+#define EXCP_PGM 3 /* program interruption */
+
+#endif /* CONFIG_USER_ONLY */
+
+#define INTERRUPT_EXT (1 << 0)
+#define INTERRUPT_TOD (1 << 1)
+#define INTERRUPT_CPUTIMER (1 << 2)
/* Program Status Word. */
#define S390_PSWM_REGNUM 0
@@ -265,5 +471,485 @@ static inline void cpu_get_tb_cpu_state(CPUState* env, target_ulong *pc,
#define S390_NUM_PSEUDO_REGS 2
#define S390_NUM_TOTAL_REGS (S390_NUM_REGS+2)
+/* CC optimization */
+
+enum cc_op {
+ CC_OP_CONST0 = 0, /* CC is 0 */
+ CC_OP_CONST1, /* CC is 1 */
+ CC_OP_CONST2, /* CC is 2 */
+ CC_OP_CONST3, /* CC is 3 */
+
+ CC_OP_DYNAMIC, /* CC calculation defined by env->cc_op */
+ CC_OP_STATIC, /* CC value is env->cc_op */
+
+ CC_OP_NZ, /* env->cc_dst != 0 */
+ CC_OP_LTGT_32, /* signed less/greater than (32bit) */
+ CC_OP_LTGT_64, /* signed less/greater than (64bit) */
+ CC_OP_LTUGTU_32, /* unsigned less/greater than (32bit) */
+ CC_OP_LTUGTU_64, /* unsigned less/greater than (64bit) */
+ CC_OP_LTGT0_32, /* signed less/greater than 0 (32bit) */
+ CC_OP_LTGT0_64, /* signed less/greater than 0 (64bit) */
+
+ CC_OP_ADD_64, /* overflow on add (64bit) */
+ CC_OP_ADDU_64, /* overflow on unsigned add (64bit) */
+ CC_OP_SUB_64, /* overflow on substraction (64bit) */
+ CC_OP_SUBU_64, /* overflow on unsigned substraction (64bit) */
+ CC_OP_ABS_64, /* sign eval on abs (64bit) */
+ CC_OP_NABS_64, /* sign eval on nabs (64bit) */
+
+ CC_OP_ADD_32, /* overflow on add (32bit) */
+ CC_OP_ADDU_32, /* overflow on unsigned add (32bit) */
+ CC_OP_SUB_32, /* overflow on substraction (32bit) */
+ CC_OP_SUBU_32, /* overflow on unsigned substraction (32bit) */
+ CC_OP_ABS_32, /* sign eval on abs (64bit) */
+ CC_OP_NABS_32, /* sign eval on nabs (64bit) */
+
+ CC_OP_COMP_32, /* complement */
+ CC_OP_COMP_64, /* complement */
+
+ CC_OP_TM_32, /* test under mask (32bit) */
+ CC_OP_TM_64, /* test under mask (64bit) */
+
+ CC_OP_LTGT_F32, /* FP compare (32bit) */
+ CC_OP_LTGT_F64, /* FP compare (64bit) */
+
+ CC_OP_NZ_F32, /* FP dst != 0 (32bit) */
+ CC_OP_NZ_F64, /* FP dst != 0 (64bit) */
+
+ CC_OP_ICM, /* insert characters under mask */
+ CC_OP_SLAG, /* Calculate shift left signed */
+ CC_OP_MAX
+};
+
+static const char *cc_names[] = {
+ [CC_OP_CONST0] = "CC_OP_CONST0",
+ [CC_OP_CONST1] = "CC_OP_CONST1",
+ [CC_OP_CONST2] = "CC_OP_CONST2",
+ [CC_OP_CONST3] = "CC_OP_CONST3",
+ [CC_OP_DYNAMIC] = "CC_OP_DYNAMIC",
+ [CC_OP_STATIC] = "CC_OP_STATIC",
+ [CC_OP_NZ] = "CC_OP_NZ",
+ [CC_OP_LTGT_32] = "CC_OP_LTGT_32",
+ [CC_OP_LTGT_64] = "CC_OP_LTGT_64",
+ [CC_OP_LTUGTU_32] = "CC_OP_LTUGTU_32",
+ [CC_OP_LTUGTU_64] = "CC_OP_LTUGTU_64",
+ [CC_OP_LTGT0_32] = "CC_OP_LTGT0_32",
+ [CC_OP_LTGT0_64] = "CC_OP_LTGT0_64",
+ [CC_OP_ADD_64] = "CC_OP_ADD_64",
+ [CC_OP_ADDU_64] = "CC_OP_ADDU_64",
+ [CC_OP_SUB_64] = "CC_OP_SUB_64",
+ [CC_OP_SUBU_64] = "CC_OP_SUBU_64",
+ [CC_OP_ABS_64] = "CC_OP_ABS_64",
+ [CC_OP_NABS_64] = "CC_OP_NABS_64",
+ [CC_OP_ADD_32] = "CC_OP_ADD_32",
+ [CC_OP_ADDU_32] = "CC_OP_ADDU_32",
+ [CC_OP_SUB_32] = "CC_OP_SUB_32",
+ [CC_OP_SUBU_32] = "CC_OP_SUBU_32",
+ [CC_OP_ABS_32] = "CC_OP_ABS_32",
+ [CC_OP_NABS_32] = "CC_OP_NABS_32",
+ [CC_OP_COMP_32] = "CC_OP_COMP_32",
+ [CC_OP_COMP_64] = "CC_OP_COMP_64",
+ [CC_OP_TM_32] = "CC_OP_TM_32",
+ [CC_OP_TM_64] = "CC_OP_TM_64",
+ [CC_OP_LTGT_F32] = "CC_OP_LTGT_F32",
+ [CC_OP_LTGT_F64] = "CC_OP_LTGT_F64",
+ [CC_OP_NZ_F32] = "CC_OP_NZ_F32",
+ [CC_OP_NZ_F64] = "CC_OP_NZ_F64",
+ [CC_OP_ICM] = "CC_OP_ICM",
+ [CC_OP_SLAG] = "CC_OP_SLAG",
+};
+
+static inline const char *cc_name(int cc_op)
+{
+ return cc_names[cc_op];
+}
+
+/* SCLP PV interface defines */
+#define SCLP_CMDW_READ_SCP_INFO 0x00020001
+#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
+
+#define SCP_LENGTH 0x00
+#define SCP_FUNCTION_CODE 0x02
+#define SCP_CONTROL_MASK 0x03
+#define SCP_RESPONSE_CODE 0x06
+#define SCP_MEM_CODE 0x08
+#define SCP_INCREMENT 0x0a
+
+typedef struct LowCore
+{
+ /* prefix area: defined by architecture */
+ uint32_t ccw1[2]; /* 0x000 */
+ uint32_t ccw2[4]; /* 0x008 */
+ uint8_t pad1[0x80-0x18]; /* 0x018 */
+ uint32_t ext_params; /* 0x080 */
+ uint16_t cpu_addr; /* 0x084 */
+ uint16_t ext_int_code; /* 0x086 */
+ uint16_t svc_ilc; /* 0x088 */
+ uint16_t svc_code; /* 0x08a */
+ uint16_t pgm_ilc; /* 0x08c */
+ uint16_t pgm_code; /* 0x08e */
+ uint32_t data_exc_code; /* 0x090 */
+ uint16_t mon_class_num; /* 0x094 */
+ uint16_t per_perc_atmid; /* 0x096 */
+ uint64_t per_address; /* 0x098 */
+ uint8_t exc_access_id; /* 0x0a0 */
+ uint8_t per_access_id; /* 0x0a1 */
+ uint8_t op_access_id; /* 0x0a2 */
+ uint8_t ar_access_id; /* 0x0a3 */
+ uint8_t pad2[0xA8-0xA4]; /* 0x0a4 */
+ uint64_t trans_exc_code; /* 0x0a8 */
+ uint64_t monitor_code; /* 0x0b0 */
+ uint16_t subchannel_id; /* 0x0b8 */
+ uint16_t subchannel_nr; /* 0x0ba */
+ uint32_t io_int_parm; /* 0x0bc */
+ uint32_t io_int_word; /* 0x0c0 */
+ uint8_t pad3[0xc8-0xc4]; /* 0x0c4 */
+ uint32_t stfl_fac_list; /* 0x0c8 */
+ uint8_t pad4[0xe8-0xcc]; /* 0x0cc */
+ uint32_t mcck_interruption_code[2]; /* 0x0e8 */
+ uint8_t pad5[0xf4-0xf0]; /* 0x0f0 */
+ uint32_t external_damage_code; /* 0x0f4 */
+ uint64_t failing_storage_address; /* 0x0f8 */
+ uint8_t pad6[0x120-0x100]; /* 0x100 */
+ PSW restart_old_psw; /* 0x120 */
+ PSW external_old_psw; /* 0x130 */
+ PSW svc_old_psw; /* 0x140 */
+ PSW program_old_psw; /* 0x150 */
+ PSW mcck_old_psw; /* 0x160 */
+ PSW io_old_psw; /* 0x170 */
+ uint8_t pad7[0x1a0-0x180]; /* 0x180 */
+ PSW restart_psw; /* 0x1a0 */
+ PSW external_new_psw; /* 0x1b0 */
+ PSW svc_new_psw; /* 0x1c0 */
+ PSW program_new_psw; /* 0x1d0 */
+ PSW mcck_new_psw; /* 0x1e0 */
+ PSW io_new_psw; /* 0x1f0 */
+ PSW return_psw; /* 0x200 */
+ uint8_t irb[64]; /* 0x210 */
+ uint64_t sync_enter_timer; /* 0x250 */
+ uint64_t async_enter_timer; /* 0x258 */
+ uint64_t exit_timer; /* 0x260 */
+ uint64_t last_update_timer; /* 0x268 */
+ uint64_t user_timer; /* 0x270 */
+ uint64_t system_timer; /* 0x278 */
+ uint64_t last_update_clock; /* 0x280 */
+ uint64_t steal_clock; /* 0x288 */
+ PSW return_mcck_psw; /* 0x290 */
+ uint8_t pad8[0xc00-0x2a0]; /* 0x2a0 */
+ /* System info area */
+ uint64_t save_area[16]; /* 0xc00 */
+ uint8_t pad9[0xd40-0xc80]; /* 0xc80 */
+ uint64_t kernel_stack; /* 0xd40 */
+ uint64_t thread_info; /* 0xd48 */
+ uint64_t async_stack; /* 0xd50 */
+ uint64_t kernel_asce; /* 0xd58 */
+ uint64_t user_asce; /* 0xd60 */
+ uint64_t panic_stack; /* 0xd68 */
+ uint64_t user_exec_asce; /* 0xd70 */
+ uint8_t pad10[0xdc0-0xd78]; /* 0xd78 */
+
+ /* SMP info area: defined by DJB */
+ uint64_t clock_comparator; /* 0xdc0 */
+ uint64_t ext_call_fast; /* 0xdc8 */
+ uint64_t percpu_offset; /* 0xdd0 */
+ uint64_t current_task; /* 0xdd8 */
+ uint32_t softirq_pending; /* 0xde0 */
+ uint32_t pad_0x0de4; /* 0xde4 */
+ uint64_t int_clock; /* 0xde8 */
+ uint8_t pad12[0xe00-0xdf0]; /* 0xdf0 */
+
+ /* 0xe00 is used as indicator for dump tools */
+ /* whether the kernel died with panic() or not */
+ uint32_t panic_magic; /* 0xe00 */
+
+ uint8_t pad13[0x11b8-0xe04]; /* 0xe04 */
+
+ /* 64 bit extparam used for pfault, diag 250 etc */
+ uint64_t ext_params2; /* 0x11B8 */
+
+ uint8_t pad14[0x1200-0x11C0]; /* 0x11C0 */
+
+ /* System info area */
+
+ uint64_t floating_pt_save_area[16]; /* 0x1200 */
+ uint64_t gpregs_save_area[16]; /* 0x1280 */
+ uint32_t st_status_fixed_logout[4]; /* 0x1300 */
+ uint8_t pad15[0x1318-0x1310]; /* 0x1310 */
+ uint32_t prefixreg_save_area; /* 0x1318 */
+ uint32_t fpt_creg_save_area; /* 0x131c */
+ uint8_t pad16[0x1324-0x1320]; /* 0x1320 */
+ uint32_t tod_progreg_save_area; /* 0x1324 */
+ uint32_t cpu_timer_save_area[2]; /* 0x1328 */
+ uint32_t clock_comp_save_area[2]; /* 0x1330 */
+ uint8_t pad17[0x1340-0x1338]; /* 0x1338 */
+ uint32_t access_regs_save_area[16]; /* 0x1340 */
+ uint64_t cregs_save_area[16]; /* 0x1380 */
+
+ /* align to the top of the prefix area */
+
+ uint8_t pad18[0x2000-0x1400]; /* 0x1400 */
+} __attribute__((packed)) LowCore;
+
+/* STSI */
+#define STSI_LEVEL_MASK 0x00000000f0000000ULL
+#define STSI_LEVEL_CURRENT 0x0000000000000000ULL
+#define STSI_LEVEL_1 0x0000000010000000ULL
+#define STSI_LEVEL_2 0x0000000020000000ULL
+#define STSI_LEVEL_3 0x0000000030000000ULL
+#define STSI_R0_RESERVED_MASK 0x000000000fffff00ULL
+#define STSI_R0_SEL1_MASK 0x00000000000000ffULL
+#define STSI_R1_RESERVED_MASK 0x00000000ffff0000ULL
+#define STSI_R1_SEL2_MASK 0x000000000000ffffULL
+
+/* Basic Machine Configuration */
+struct sysib_111 {
+ uint32_t res1[8];
+ uint8_t manuf[16];
+ uint8_t type[4];
+ uint8_t res2[12];
+ uint8_t model[16];
+ uint8_t sequence[16];
+ uint8_t plant[4];
+ uint8_t res3[156];
+};
+
+/* Basic Machine CPU */
+struct sysib_121 {
+ uint32_t res1[80];
+ uint8_t sequence[16];
+ uint8_t plant[4];
+ uint8_t res2[2];
+ uint16_t cpu_addr;
+ uint8_t res3[152];
+};
+
+/* Basic Machine CPUs */
+struct sysib_122 {
+ uint8_t res1[32];
+ uint32_t capability;
+ uint16_t total_cpus;
+ uint16_t active_cpus;
+ uint16_t standby_cpus;
+ uint16_t reserved_cpus;
+ uint16_t adjustments[2026];
+};
+
+/* LPAR CPU */
+struct sysib_221 {
+ uint32_t res1[80];
+ uint8_t sequence[16];
+ uint8_t plant[4];
+ uint16_t cpu_id;
+ uint16_t cpu_addr;
+ uint8_t res3[152];
+};
+
+/* LPAR CPUs */
+struct sysib_222 {
+ uint32_t res1[32];
+ uint16_t lpar_num;
+ uint8_t res2;
+ uint8_t lcpuc;
+ uint16_t total_cpus;
+ uint16_t conf_cpus;
+ uint16_t standby_cpus;
+ uint16_t reserved_cpus;
+ uint8_t name[8];
+ uint32_t caf;
+ uint8_t res3[16];
+ uint16_t dedicated_cpus;
+ uint16_t shared_cpus;
+ uint8_t res4[180];
+};
+
+/* VM CPUs */
+struct sysib_322 {
+ uint8_t res1[31];
+ uint8_t count;
+ struct {
+ uint8_t res2[4];
+ uint16_t total_cpus;
+ uint16_t conf_cpus;
+ uint16_t standby_cpus;
+ uint16_t reserved_cpus;
+ uint8_t name[8];
+ uint32_t caf;
+ uint8_t cpi[16];
+ uint8_t res3[24];
+ } vm[8];
+ uint8_t res4[3552];
+};
+
+/* MMU defines */
+#define _ASCE_ORIGIN ~0xfffULL /* segment table origin */
+#define _ASCE_SUBSPACE 0x200 /* subspace group control */
+#define _ASCE_PRIVATE_SPACE 0x100 /* private space control */
+#define _ASCE_ALT_EVENT 0x80 /* storage alteration event control */
+#define _ASCE_SPACE_SWITCH 0x40 /* space switch event */
+#define _ASCE_REAL_SPACE 0x20 /* real space control */
+#define _ASCE_TYPE_MASK 0x0c /* asce table type mask */
+#define _ASCE_TYPE_REGION1 0x0c /* region first table type */
+#define _ASCE_TYPE_REGION2 0x08 /* region second table type */
+#define _ASCE_TYPE_REGION3 0x04 /* region third table type */
+#define _ASCE_TYPE_SEGMENT 0x00 /* segment table type */
+#define _ASCE_TABLE_LENGTH 0x03 /* region table length */
+
+#define _REGION_ENTRY_ORIGIN ~0xfffULL /* region/segment table origin */
+#define _REGION_ENTRY_INV 0x20 /* invalid region table entry */
+#define _REGION_ENTRY_TYPE_MASK 0x0c /* region/segment table type mask */
+#define _REGION_ENTRY_TYPE_R1 0x0c /* region first table type */
+#define _REGION_ENTRY_TYPE_R2 0x08 /* region second table type */
+#define _REGION_ENTRY_TYPE_R3 0x04 /* region third table type */
+#define _REGION_ENTRY_LENGTH 0x03 /* region third length */
+
+#define _SEGMENT_ENTRY_ORIGIN ~0x7ffULL /* segment table origin */
+#define _SEGMENT_ENTRY_RO 0x200 /* page protection bit */
+#define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */
+
+#define _PAGE_RO 0x200 /* HW read-only bit */
+#define _PAGE_INVALID 0x400 /* HW invalid bit */
+
+
+
+/* EBCDIC handling */
+static const uint8_t ebcdic2ascii[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
+ 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
+ 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
+ 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
+ 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
+ 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
+ 0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21,
+ 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
+ 0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
+ 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
+ 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+ 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+ 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
+ 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
+ 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
+ 0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
+ 0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07,
+ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
+ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
+ 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07,
+};
+
+static const uint8_t ascii2ebcdic [] = {
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
+ 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
+ 0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
+ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
+ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+ 0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,
+ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
+};
+
+static inline void ebcdic_put(uint8_t *p, const char *ascii, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ p[i] = ascii2ebcdic[(int)ascii[i]];
+ }
+}
+
+#define SIGP_SENSE 0x01
+#define SIGP_EXTERNAL_CALL 0x02
+#define SIGP_EMERGENCY 0x03
+#define SIGP_START 0x04
+#define SIGP_STOP 0x05
+#define SIGP_RESTART 0x06
+#define SIGP_STOP_STORE_STATUS 0x09
+#define SIGP_INITIAL_CPU_RESET 0x0b
+#define SIGP_CPU_RESET 0x0c
+#define SIGP_SET_PREFIX 0x0d
+#define SIGP_STORE_STATUS_ADDR 0x0e
+#define SIGP_SET_ARCH 0x12
+
+/* cpu status bits */
+#define SIGP_STAT_EQUIPMENT_CHECK 0x80000000UL
+#define SIGP_STAT_INCORRECT_STATE 0x00000200UL
+#define SIGP_STAT_INVALID_PARAMETER 0x00000100UL
+#define SIGP_STAT_EXT_CALL_PENDING 0x00000080UL
+#define SIGP_STAT_STOPPED 0x00000040UL
+#define SIGP_STAT_OPERATOR_INTERV 0x00000020UL
+#define SIGP_STAT_CHECK_STOP 0x00000010UL
+#define SIGP_STAT_INOPERATIVE 0x00000004UL
+#define SIGP_STAT_INVALID_ORDER 0x00000002UL
+#define SIGP_STAT_RECEIVER_CHECK 0x00000001UL
+
+void load_psw(CPUState *env, uint64_t mask, uint64_t addr);
+int mmu_translate(CPUState *env, target_ulong vaddr, int rw, uint64_t asc,
+ target_ulong *raddr, int *flags);
+int sclp_service_call(CPUState *env, uint32_t sccb, uint64_t code);
+uint32_t calc_cc(CPUState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
+ uint64_t vr);
+
+#define TARGET_HAS_ICE 1
+
+/* The value of the TOD clock for 1.1.1970. */
+#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
+
+/* Converts ns to s390's clock format */
+static inline uint64_t time2tod(uint64_t ns) {
+ return (ns << 9) / 125;
+}
+
+static inline void cpu_inject_ext(CPUState *env, uint32_t code, uint32_t param,
+ uint64_t param64)
+{
+ if (env->ext_index == MAX_EXT_QUEUE - 1) {
+ /* ugh - can't queue anymore. Let's drop. */
+ return;
+ }
+
+ env->ext_index++;
+ assert(env->ext_index < MAX_EXT_QUEUE);
+
+ env->ext_queue[env->ext_index].code = code;
+ env->ext_queue[env->ext_index].param = param;
+ env->ext_queue[env->ext_index].param64 = param64;
+
+ env->pending_int |= INTERRUPT_EXT;
+ cpu_interrupt(env, CPU_INTERRUPT_HARD);
+}
#endif
diff --git a/target-s390x/exec.h b/target-s390x/exec.h
index f7893f387..7a87fffca 100644
--- a/target-s390x/exec.h
+++ b/target-s390x/exec.h
@@ -31,7 +31,16 @@ register struct CPUS390XState *env asm(AREG0);
static inline int cpu_has_work(CPUState *env)
{
- return env->interrupt_request & CPU_INTERRUPT_HARD; // guess
+ return ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+ (env->psw.mask & PSW_MASK_EXT));
+}
+
+static inline void regs_to_env(void)
+{
+}
+
+static inline void env_to_regs(void)
+{
}
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock* tb)
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 4a5297be1..629dfd970 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -82,3 +82,7 @@ int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
return 0;
}
#endif /* CONFIG_USER_ONLY */
+
+void do_interrupt (CPUState *env)
+{
+}
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index ae7dc561b..264346072 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -182,8 +182,8 @@ int kvm_arch_process_async_events(CPUState *env)
return 0;
}
-static void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
- uint64_t parm64, int vm)
+void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
+ uint64_t parm64, int vm)
{
struct kvm_s390_interrupt kvmint;
int r;
@@ -218,7 +218,7 @@ void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token)
token, 1);
}
-static void kvm_s390_interrupt(CPUState *env, int type, uint32_t code)
+void kvm_s390_interrupt(CPUState *env, int type, uint32_t code)
{
kvm_s390_interrupt_internal(env, type, code, 0, 0);
}
@@ -237,7 +237,8 @@ static void setcc(CPUState *env, uint64_t cc)
env->psw.mask |= (cc & 3) << 44;
}
-static int sclp_service_call(CPUState *env, struct kvm_run *run, uint16_t ipbh0)
+static int kvm_sclp_service_call(CPUState *env, struct kvm_run *run,
+ uint16_t ipbh0)
{
uint32_t sccb;
uint64_t code;
@@ -287,7 +288,7 @@ static int handle_priv(CPUState *env, struct kvm_run *run, uint8_t ipa1)
dprintf("KVM: PRIV: %d\n", ipa1);
switch (ipa1) {
case PRIV_SCLP_CALL:
- r = sclp_service_call(env, run, ipbh0);
+ r = kvm_sclp_service_call(env, run, ipbh0);
break;
default:
dprintf("KVM: unknown PRIV: 0x%x\n", ipa1);
@@ -300,12 +301,10 @@ static int handle_priv(CPUState *env, struct kvm_run *run, uint8_t ipa1)
static int handle_hypercall(CPUState *env, struct kvm_run *run)
{
- int r;
-
cpu_synchronize_state(env);
- r = s390_virtio_hypercall(env);
+ env->regs[2] = s390_virtio_hypercall(env, env->regs[2], env->regs[1]);
- return r;
+ return 0;
}
static int handle_diag(CPUState *env, struct kvm_run *run, int ipb_code)
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 402df2d85..be455b9de 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -61,7 +61,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (likely(tb)) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
/* XXX */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index d33bfb1f3..4d45e3261 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -36,7 +36,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
}
}
for (i = 0; i < 16; i++) {
- cpu_fprintf(f, "F%02d=%016lx", i, (long)env->fregs[i].i);
+ cpu_fprintf(f, "F%02d=%016" PRIx64, i, *(uint64_t *)&env->fregs[i]);
if ((i % 4) == 3) {
cpu_fprintf(f, "\n");
} else {
@@ -54,8 +54,7 @@ void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
{
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->psw.addr = gen_opc_pc[pc_pos];
}
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index c127860cd..b909d18bc 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -32,7 +32,7 @@ static void cpu_restore_state_from_retaddr(void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
}
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 88098d7c2..93c863650 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -2069,8 +2069,7 @@ void gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb)
gen_intermediate_code_internal(env, tb, 1);
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->pc = gen_opc_pc[pc_pos];
env->flags = gen_opc_hflags[pc_pos];
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 854f168c6..ffffb8c0b 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -4375,7 +4375,7 @@ static void cpu_restore_state2(void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
+ cpu_restore_state(tb, env, pc);
}
}
}
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 883ecd2d2..3c958b26d 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5080,8 +5080,7 @@ void gen_intermediate_code_init(CPUSPARCState *env)
}
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
target_ulong npc;
env->pc = gen_opc_pc[pc_pos];
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index a6ba991e9..98eaeb3d4 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -2098,8 +2098,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
#endif
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->regs[31] = gen_opc_pc[pc_pos];
}
diff --git a/tests/test-mmap.c b/tests/test-mmap.c
index fcb365f40..c578e2572 100644
--- a/tests/test-mmap.c
+++ b/tests/test-mmap.c
@@ -164,6 +164,7 @@ void check_aligned_anonymous_unfixed_colliding_mmaps(void)
nlen = pagesize * 8;
p3 = mmap(NULL, nlen, PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ fail_unless (p3 != MAP_FAILED);
/* Check if the mmaped areas collide. */
if (p3 < p2
@@ -174,7 +175,6 @@ void check_aligned_anonymous_unfixed_colliding_mmaps(void)
/* Make sure we get pages aligned with the pagesize. The
target expects this. */
- fail_unless (p3 != MAP_FAILED);
p = (uintptr_t) p3;
fail_unless ((p & pagemask) == 0);
munmap (p2, pagesize);
diff --git a/trace-events b/trace-events
index 703b745bc..4f965e2eb 100644
--- a/trace-events
+++ b/trace-events
@@ -235,27 +235,27 @@ disable grlib_gptimer_disabled(int id, uint32_t config) "timer:%d Timer disable
disable grlib_gptimer_restart(int id, uint32_t reload) "timer:%d reload val: 0x%x"
disable grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) "scaler:0x%x freq: 0x%x"
disable grlib_gptimer_hit(int id) "timer:%d HIT"
-disable grlib_gptimer_readl(int id, const char *s, uint32_t val) "timer:%d %s 0x%x"
-disable grlib_gptimer_writel(int id, const char *s, uint32_t val) "timer:%d %s 0x%x"
-disable grlib_gptimer_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
+disable grlib_gptimer_readl(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x"
+disable grlib_gptimer_writel(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x"
# hw/grlib_irqmp.c
disable grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uint32_t lvl1, uint32_t lvl2) "pend:0x%04x force:0x%04x mask:0x%04x lvl1:0x%04x lvl0:0x%04x\n"
disable grlib_irqmp_ack(int intno) "interrupt:%d"
disable grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d"
-disable grlib_irqmp_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
+disable grlib_irqmp_readl_unknown(uint64_t addr) "addr 0x%"PRIx64""
+disable grlib_irqmp_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x"
# hw/grlib_apbuart.c
disable grlib_apbuart_event(int event) "event:%d"
-disable grlib_apbuart_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
+disable grlib_apbuart_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x"
# hw/leon3.c
disable leon3_set_irq(int intno) "Set CPU IRQ %d"
disable leon3_reset_irq(int intno) "Reset CPU IRQ %d"
# spice-qemu-char.c
-disable spice_vmc_write(ssize_t out, int len) "spice wrottn %lu of requested %zd"
-disable spice_vmc_read(int bytes, int len) "spice read %lu of requested %zd"
+disable spice_vmc_write(ssize_t out, int len) "spice wrottn %zd of requested %d"
+disable spice_vmc_read(int bytes, int len) "spice read %d of requested %d"
disable spice_vmc_register_interface(void *scd) "spice vmc registered interface %p"
disable spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p"
@@ -308,17 +308,18 @@ disable milkymist_hpdmc_memory_write(uint32_t addr, uint32_t value) "addr=%08x v
disable milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
disable milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
-# hw/milkymist-minimac.c
-disable milkymist_minimac_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
-disable milkymist_minimac_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
-disable milkymist_minimac_mdio_write(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x"
-disable milkymist_minimac_mdio_read(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x"
-disable milkymist_minimac_tx_frame(uint32_t length) "length %u"
-disable milkymist_minimac_rx_frame(const void *buf, uint32_t length) "buf %p length %u"
-disable milkymist_minimac_drop_rx_frame(const void *buf) "buf %p"
-disable milkymist_minimac_rx_transfer(const void *buf, uint32_t length) "buf %p length %d"
-disable milkymist_minimac_pulse_irq_rx(void) "Pulse IRQ RX"
-disable milkymist_minimac_pulse_irq_tx(void) "Pulse IRQ TX"
+# hw/milkymist-minimac2.c
+disable milkymist_minimac2_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_minimac2_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_minimac2_mdio_write(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x"
+disable milkymist_minimac2_mdio_read(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x"
+disable milkymist_minimac2_tx_frame(uint32_t length) "length %u"
+disable milkymist_minimac2_rx_frame(const void *buf, uint32_t length) "buf %p length %u"
+disable milkymist_minimac2_drop_rx_frame(const void *buf) "buf %p"
+disable milkymist_minimac2_rx_transfer(const void *buf, uint32_t length) "buf %p length %d"
+disable milkymist_minimac2_raise_irq_rx(void) "Raise IRQ RX"
+disable milkymist_minimac2_lower_irq_rx(void) "Lower IRQ RX"
+disable milkymist_minimac2_pulse_irq_tx(void) "Pulse IRQ TX"
# hw/milkymist-pfpu.c
disable milkymist_pfpu_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
diff --git a/translate-all.c b/translate-all.c
index efcfb9adc..2ca190ca8 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -112,8 +112,7 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr)
/* The cpu state corresponding to 'searched_pc' is restored.
*/
int cpu_restore_state(TranslationBlock *tb,
- CPUState *env, unsigned long searched_pc,
- void *puc)
+ CPUState *env, unsigned long searched_pc)
{
TCGContext *s = &tcg_ctx;
int j;
@@ -157,7 +156,7 @@ int cpu_restore_state(TranslationBlock *tb,
j--;
env->icount_decr.u16.low -= gen_opc_icount[j];
- gen_pc_load(env, tb, searched_pc, j, puc);
+ restore_state_to_opc(env, tb, j);
#ifdef CONFIG_PROFILER
s->restore_time += profile_getclock() - ti;
diff --git a/usb-linux.c b/usb-linux.c
index 255009f53..1f33c2c23 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -107,7 +107,7 @@ enum {
/*
* Control transfer state.
* Note that 'buffer' _must_ follow 'req' field because
- * we need contigious buffer when we submit control URB.
+ * we need contiguous buffer when we submit control URB.
*/
struct ctrl_struct {
uint16_t len;
@@ -344,6 +344,7 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
for (interface = 0; interface < nb_interfaces; interface++) {
ctrl.ioctl_code = USBDEVFS_DISCONNECT;
ctrl.ifno = interface;
+ ctrl.data = 0;
ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
if (ret < 0 && errno != ENODATA) {
perror("USBDEVFS_DISCONNECT");
@@ -579,7 +580,7 @@ static int usb_host_handle_control(USBHostDevice *s, USBPacket *p)
/*
* Setup ctrl transfer.
*
- * s->ctrl is layed out such that data buffer immediately follows
+ * s->ctrl is laid out such that data buffer immediately follows
* 'req' struct which is exactly what usbdevfs expects.
*/
urb = &aurb->urb;
diff --git a/vl.c b/vl.c
index 0c24e074f..a143250d5 100644
--- a/vl.c
+++ b/vl.c
@@ -760,7 +760,7 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev,
/*
* This function returns null terminated string that consist of new line
- * separated device pathes.
+ * separated device paths.
*
* memory pointed by "size" is assigned total length of the array in bytes
*
@@ -2468,9 +2468,8 @@ int main(int argc, char **argv, char **envp)
}
break;
case QEMU_OPTION_virtfs: {
- char *arg_fsdev = NULL;
- char *arg_9p = NULL;
- int len = 0;
+ QemuOpts *fsdev;
+ QemuOpts *device;
olist = qemu_find_opts("virtfs");
if (!olist) {
@@ -2489,45 +2488,28 @@ int main(int argc, char **argv, char **envp)
qemu_opt_get(opts, "security_model") == NULL) {
fprintf(stderr, "Usage: -virtfs fstype,path=/share_path/,"
"security_model=[mapped|passthrough|none],"
- "mnt_tag=tag.\n");
+ "mount_tag=tag.\n");
exit(1);
}
- len = strlen(",id=,path=,security_model=");
- len += strlen(qemu_opt_get(opts, "fstype"));
- len += strlen(qemu_opt_get(opts, "mount_tag"));
- len += strlen(qemu_opt_get(opts, "path"));
- len += strlen(qemu_opt_get(opts, "security_model"));
- arg_fsdev = qemu_malloc((len + 1) * sizeof(*arg_fsdev));
-
- snprintf(arg_fsdev, (len + 1) * sizeof(*arg_fsdev),
- "%s,id=%s,path=%s,security_model=%s",
- qemu_opt_get(opts, "fstype"),
- qemu_opt_get(opts, "mount_tag"),
- qemu_opt_get(opts, "path"),
- qemu_opt_get(opts, "security_model"));
-
- len = strlen("virtio-9p,fsdev=,mount_tag=");
- len += 2*strlen(qemu_opt_get(opts, "mount_tag"));
- arg_9p = qemu_malloc((len + 1) * sizeof(*arg_9p));
-
- snprintf(arg_9p, (len + 1) * sizeof(*arg_9p),
- "virtio-9p,fsdev=%s,mount_tag=%s",
- qemu_opt_get(opts, "mount_tag"),
- qemu_opt_get(opts, "mount_tag"));
-
- if (!qemu_opts_parse(qemu_find_opts("fsdev"), arg_fsdev, 1)) {
- fprintf(stderr, "parse error [fsdev]: %s\n", optarg);
+ fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
+ qemu_opt_get(opts, "mount_tag"), 1);
+ if (!fsdev) {
+ fprintf(stderr, "duplicate fsdev id: %s\n",
+ qemu_opt_get(opts, "mount_tag"));
exit(1);
}
-
- if (!qemu_opts_parse(qemu_find_opts("device"), arg_9p, 1)) {
- fprintf(stderr, "parse error [device]: %s\n", optarg);
- exit(1);
- }
-
- qemu_free(arg_fsdev);
- qemu_free(arg_9p);
+ qemu_opt_set(fsdev, "fstype", qemu_opt_get(opts, "fstype"));
+ qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path"));
+ qemu_opt_set(fsdev, "security_model",
+ qemu_opt_get(opts, "security_model"));
+
+ device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+ qemu_opt_set(device, "driver", "virtio-9p-pci");
+ qemu_opt_set(device, "fsdev",
+ qemu_opt_get(opts, "mount_tag"));
+ qemu_opt_set(device, "mount_tag",
+ qemu_opt_get(opts, "mount_tag"));
break;
}
case QEMU_OPTION_serial: