]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Merge remote-tracking branch 'pm-arm/for-upstream' into pm
authorEdgar E. Iglesias <edgar.iglesias@gmail.com>
Tue, 9 Aug 2011 17:16:43 +0000 (19:16 +0200)
committerEdgar E. Iglesias <edgar.iglesias@gmail.com>
Tue, 9 Aug 2011 17:16:43 +0000 (19:16 +0200)
291 files changed:
.gitignore
CODING_STYLE
MAINTAINERS
Makefile
Makefile.hw
Makefile.objs
Makefile.target
async.c
balloon.c
balloon.h
block.c
block.h
block/qcow.c
block/qcow2-cluster.c
block/qcow2-snapshot.c
block/qcow2.c
block/qcow2.h
block/qed-table.c
block/qed.c
block/raw-posix.c
block/raw-win32.c
block/raw.c
block/vpc.c
block_int.h
blockdev.c
bsd-user/main.c
bswap.h
configure
coroutine-gthread.c [new file with mode: 0644]
coroutine-ucontext.c [new file with mode: 0644]
coroutine-win32.c [new file with mode: 0644]
cpu-all.h
cpu-common.h
cutils.c
darwin-user/main.c
darwin-user/signal.c
dma.h
docs/memory.txt [new file with mode: 0644]
dyngen-exec.h
exec-memory.h [new file with mode: 0644]
exec.c
fpu/softfloat-specialize.h
fpu/softfloat.h
hmp-commands.hx
hw/ac97.c
hw/acpi.c
hw/apb_pci.c
hw/axis_dev88.c
hw/bonito.c
hw/bt-hid.c
hw/cirrus_vga.c
hw/cuda.c
hw/e1000.c
hw/eepro100.c
hw/es1370.c
hw/escc.c
hw/escc.h
hw/etraxfs.c [deleted file]
hw/etraxfs.h
hw/etraxfs_eth.c
hw/flash.h
hw/fw_cfg.c
hw/grackle_pci.c
hw/gt64xxx.c
hw/heathrow_pic.c
hw/hid.c [new file with mode: 0644]
hw/hid.h [new file with mode: 0644]
hw/hw.h
hw/i2c.h
hw/ide.h
hw/ide/ahci.c
hw/ide/ahci.h
hw/ide/cmd646.c
hw/ide/ich.c
hw/ide/macio.c
hw/ide/pci.c
hw/ide/pci.h
hw/ide/piix.c
hw/ide/via.c
hw/intel-hda.c
hw/isa.h
hw/isa_mmio.c
hw/ivshmem.c
hw/kvmclock.c
hw/lance.c
hw/lm832x.c
hw/lsi53c895a.c
hw/mac_dbdma.c
hw/mac_dbdma.h
hw/mac_nvram.c
hw/macio.c
hw/milkymist-softusb.c
hw/msix.c
hw/msix.h
hw/multiboot.c
hw/nand.c
hw/ne2000-isa.c
hw/ne2000.c
hw/ne2000.h
hw/nseries.c
hw/omap.h
hw/omap1.c
hw/omap2.c
hw/omap_clk.c
hw/omap_gpio.c
hw/omap_l4.c
hw/onenand.c
hw/openpic.c
hw/openpic.h
hw/palm.c
hw/pc.c
hw/pc.h
hw/pc_piix.c
hw/pci.c
hw/pci.h
hw/pci_host.c
hw/pci_host.h
hw/pci_internals.h
hw/pcie_host.c
hw/pcnet-pci.c
hw/pcnet.h
hw/piix_pci.c
hw/ppc4xx_pci.c
hw/ppc_mac.h
hw/ppc_newworld.c
hw/ppc_oldworld.c
hw/ppc_prep.c
hw/ppce500_pci.c
hw/prep_pci.c
hw/prep_pci.h
hw/qdev.c
hw/qxl-render.c
hw/qxl.c
hw/qxl.h
hw/rtl8139.c
hw/scsi-bus.c
hw/scsi-defs.h
hw/scsi-disk.c
hw/scsi-generic.c
hw/sd.c
hw/sh_pci.c
hw/spapr_hcall.c
hw/spitz.c
hw/sun4u.c
hw/sysbus.c
hw/sysbus.h
hw/tc6393xb.c
hw/unin_pci.c
hw/usb-bt.c
hw/usb-ccid.c
hw/usb-ehci.c
hw/usb-hid.c
hw/usb-hub.c
hw/usb-libhw.c [new file with mode: 0644]
hw/usb-msd.c
hw/usb-musb.c
hw/usb-net.c
hw/usb-ohci.c
hw/usb-serial.c
hw/usb-uhci.c
hw/usb-wacom.c
hw/usb.c
hw/usb.h
hw/versatile_pci.c
hw/vga-isa-mm.c
hw/vga-isa.c
hw/vga-pci.c
hw/vga.c
hw/vga_int.h
hw/vhost.c
hw/virtio-balloon.c
hw/virtio-blk.c
hw/virtio-net.c
hw/virtio-pci.c
hw/virtio-pci.h
hw/virtio.c
hw/virtio.h
hw/vmware_vga.c
hw/wdt_i6300esb.c
hw/xen.h
hw/xen_platform.c
hw/z2.c [new file with mode: 0644]
ioport.c
iov.c
iov.h
kvm-all.c
libcacard/Makefile
libcacard/libcacard.pc.in [new file with mode: 0644]
libcacard/vcard_emul_nss.c
linux-aio.c
linux-user/main.c
memory.c [new file with mode: 0644]
memory.h [new file with mode: 0644]
migration.c
monitor.c
net.c
net/socket.c
net/tap-bsd.c
oslib-posix.c
posix-aio-compat.c
qemu-common.h
qemu-config.c
qemu-coroutine-int.h [new file with mode: 0644]
qemu-coroutine-lock.c [new file with mode: 0644]
qemu-coroutine.c [new file with mode: 0644]
qemu-coroutine.h [new file with mode: 0644]
qemu-doc.texi
qemu-options.hx
qmp-commands.hx
savevm.c
slirp/arp_table.c [new file with mode: 0644]
slirp/bootp.c
slirp/if.c
slirp/ip_input.c
slirp/main.h
slirp/mbuf.c
slirp/mbuf.h
slirp/slirp.c
slirp/slirp.h
sysemu.h
target-alpha/cpu.h
target-alpha/exec.h [deleted file]
target-alpha/helper.c
target-alpha/op_helper.c
target-arm/cpu.h
target-arm/exec.h [deleted file]
target-arm/helper.c
target-arm/op_helper.c
target-cris/cpu.h
target-cris/exec.h [deleted file]
target-cris/helper.c
target-cris/op_helper.c
target-i386/cpu.h
target-i386/cpuid.c
target-i386/exec.h [deleted file]
target-i386/helper.c
target-i386/kvm.c
target-i386/op_helper.c
target-lm32/cpu.h
target-lm32/exec.h [deleted file]
target-lm32/helper.c
target-lm32/op_helper.c
target-m68k/cpu.h
target-m68k/exec.h [deleted file]
target-m68k/helper.c
target-m68k/op_helper.c
target-microblaze/cpu.h
target-microblaze/exec.h [deleted file]
target-microblaze/helper.c
target-microblaze/op_helper.c
target-microblaze/translate.c
target-mips/cpu.h
target-mips/exec.h [deleted file]
target-mips/helper.c
target-mips/op_helper.c
target-ppc/cpu.h
target-ppc/exec.h [deleted file]
target-ppc/helper.c
target-ppc/op_helper.c
target-s390x/cpu.h
target-s390x/exec.h [deleted file]
target-s390x/helper.c
target-s390x/op_helper.c
target-sh4/cpu.h
target-sh4/exec.h [deleted file]
target-sh4/helper.c
target-sh4/op_helper.c
target-sparc/cpu.h
target-sparc/exec.h [deleted file]
target-sparc/helper.c
target-sparc/op_helper.c
target-sparc/translate.c
target-unicore32/cpu.h
target-unicore32/exec.h [deleted file]
target-unicore32/helper.c
target-unicore32/op_helper.c
tcg/optimize.c [new file with mode: 0644]
tcg/tcg.c
tcg/tcg.h
test-coroutine.c [new file with mode: 0644]
trace-events
ui/sdl.c
ui/spice-display.c
ui/spice-display.h
usb-bsd.c
usb-linux.c
usb-redir.c
user-exec.c
vl.c
xen-all.c
xen-mapcache.c

index 54835bcb97206eba654bd0a107c9625394c253cb..59c343c4149b78876c433b340c6496bc8c6cc598 100644 (file)
@@ -36,6 +36,7 @@ qemu-io
 qemu-ga
 qemu-monitor.texi
 QMP/qmp-commands.txt
+test-coroutine
 .gdbinit
 *.a
 *.aux
index 5ecfa2216109963cb646b5fcf00a10c85d3d0655..6e61c490894e244e7b8bc3c8553de9cae8cc9ead 100644 (file)
@@ -68,6 +68,10 @@ keyword.  Example:
         printf("a was something else entirely.\n");
     }
 
+Note that 'else if' is considered a single statement; otherwise a long if/
+else if/else if/.../else sequence would need an indent for every else
+statement.
+
 An exception is the opening brace for a function; for reasons of tradition
 and clarity it comes on a line by itself:
 
index 6115e4ec08cf9f59b19555aabdb5c28d5292bc39..508ea1ee24758541ba91fcbc28ff24cee3fd1c7f 100644 (file)
@@ -143,6 +143,16 @@ L: kvm@vger.kernel.org
 S: Supported
 F: target-i386/kvm.c
 
+Guest CPU Cores (Xen):
+----------------------
+
+X86
+M: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+L: xen-devel@lists.xensource.com
+S: Supported
+F: xen-*
+F: */xen*
+
 ARM Machines
 ------------
 Gumstix
@@ -431,9 +441,10 @@ S: Maintained
 F: net/
 
 SLIRP
-M: qemu-devel@nongnu.org
-S: Orphan
+M: Jan Kiszka <jan.kiszka@siemens.com>
+S: Maintained
 F: slirp/
+T: git://git.kiszka.org/qemu.git queues/slirp
 
 Usermode Emulation
 ------------------
index daa3aa09b52a64ff1b83ca6abce84750f3edc25b..9e5871bb603a810ad740e092f01e4450674dc995 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -151,7 +151,7 @@ qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trac
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
        $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $@")
 
-check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o: $(GENERATED_HEADERS)
+check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o test-coroutine.o: $(GENERATED_HEADERS)
 
 CHECK_PROG_DEPS = qemu-malloc.o $(oslib-obj-y) $(trace-obj-y) qemu-tool.o
 
@@ -161,6 +161,7 @@ check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(C
 check-qlist: check-qlist.o qlist.o qint.o $(CHECK_PROG_DEPS)
 check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS)
 check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o error.o qerror.o qemu-error.o $(CHECK_PROG_DEPS)
+test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(CHECK_PROG_DEPS)
 
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := qapi-generated
@@ -192,8 +193,10 @@ test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types
 test-qmp-commands: test-qmp-commands.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
 
 QGALIB=qga/guest-agent-command-state.o qga/guest-agent-commands.o
+QGALIB_GEN=$(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c)
 
-qemu-ga.o: $(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c) $(qapi-obj-y)
+$(QGALIB_GEN): $(GENERATED_HEADERS)
+$(QGALIB) qemu-ga.o: $(QGALIB_GEN) $(qapi-obj-y)
 qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o qapi/qmp-dispatch.o qapi/qmp-registry.o $(qapi-dir)/qga-qapi-visit.o $(qapi-dir)/qga-qapi-types.o $(qapi-dir)/qga-qmp-marshal.o
 
 QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
@@ -224,6 +227,7 @@ distclean: clean
        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 config.log
        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 ; \
@@ -291,7 +295,7 @@ TAGS:
 
 cscope:
        rm -f ./cscope.*
-       find . -name "*.[ch]" -print | sed 's,^\./,,' > ./cscope.files
+       find "$(SRC_PATH)" -name "*.[chsS]" -print | sed 's,^\./,,' > ./cscope.files
        cscope -b
 
 # documentation
index b9181ab122b2d73bc66d8762eea460f47d5931b1..659e441992e1ca84c32a3d03975e5204b0939a7c 100644 (file)
@@ -9,7 +9,7 @@ include $(SRC_PATH)/rules.mak
 
 $(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw)
 
-QEMU_CFLAGS+=-I.. -I$(SRC_PATH)/fpu
+QEMU_CFLAGS+=-I..
 
 include $(SRC_PATH)/Makefile.objs
 
index 6991a9f52acce561eb4c4bba236f69ca2d00a666..432b6198e998606b655866bc220b66c0febda76b 100644 (file)
@@ -10,11 +10,22 @@ oslib-obj-y = osdep.o
 oslib-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o
 oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o
 
+#######################################################################
+# coroutines
+coroutine-obj-y = qemu-coroutine.o qemu-coroutine-lock.o
+ifeq ($(CONFIG_UCONTEXT_COROUTINE),y)
+coroutine-obj-$(CONFIG_POSIX) += coroutine-ucontext.o
+else
+coroutine-obj-$(CONFIG_POSIX) += coroutine-gthread.o
+endif
+coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o
+
 #######################################################################
 # block-obj-y is code used by both qemu system emulation and qemu-img
 
 block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o async.o
 block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o qemu-sockets.o
+block-obj-y += $(coroutine-obj-y)
 block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 
@@ -89,6 +100,7 @@ common-obj-y += i2c.o smbus.o smbus_eeprom.o
 common-obj-y += eeprom93xx.o
 common-obj-y += scsi-disk.o cdrom.o
 common-obj-y += scsi-generic.o scsi-bus.o
+common-obj-y += hid.o
 common-obj-y += usb.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o
 common-obj-y += usb-serial.o usb-net.o usb-bus.o usb-desc.o
 common-obj-$(CONFIG_SSI) += ssi.o
@@ -151,7 +163,7 @@ common-obj-y += qemu-timer.o qemu-timer-common.o
 
 slirp-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o
 slirp-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
-slirp-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o
+slirp-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o
 common-obj-$(CONFIG_SLIRP) += $(addprefix slirp/, $(slirp-obj-y))
 
 # xen backend driver support
@@ -172,6 +184,7 @@ user-obj-y += cutils.o cache-utils.o
 hw-obj-y =
 hw-obj-y += vl.o loader.o
 hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
+hw-obj-y += usb-libhw.o
 hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
 hw-obj-y += fw_cfg.o
 hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
index cde509ba76168fbdef0026902c1e18ceeb18d427..096214a511ed2595a4e037dbb5ef7c9101232786 100644 (file)
@@ -72,7 +72,7 @@ all: $(PROGS) stap
 #########################################################
 # cpu emulator library
 libobj-y = exec.o translate-all.o cpu-exec.o translate.o
-libobj-y += tcg/tcg.o
+libobj-y += tcg/tcg.o tcg/optimize.o
 libobj-y += fpu/softfloat.o
 libobj-y += op_helper.o helper.o
 ifeq ($(TARGET_BASE_ARCH), i386)
@@ -198,6 +198,7 @@ obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
 obj-y += rwhandler.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
+obj-y += memory.o
 LIBS+=-lz
 
 QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
@@ -309,7 +310,6 @@ obj-microblaze-$(CONFIG_FDT) += device_tree.o
 # Boards
 obj-cris-y = cris_pic_cpu.o
 obj-cris-y += cris-boot.o
-obj-cris-y += etraxfs.o axis_dev88.o
 obj-cris-y += axis_dev88.o
 
 # IO blocks
@@ -351,6 +351,7 @@ obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
 obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 obj-arm-y += mst_fpga.o mainstone.o
+obj-arm-y += z2.o
 obj-arm-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
 obj-arm-y += framebuffer.o
 obj-arm-y += syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
diff --git a/async.c b/async.c
index fd313dffb7acc40bd79acfab3dc28e06c49f8596..3fe70b9debb37fef3d6c9d567f09a3fe1bc2881c 100644 (file)
--- a/async.c
+++ b/async.c
 #include "qemu-common.h"
 #include "qemu-aio.h"
 
-/*
- * An AsyncContext protects the callbacks of AIO requests and Bottom Halves
- * against interfering with each other. A typical example is qcow2 that accepts
- * asynchronous requests, but relies for manipulation of its metadata on
- * synchronous bdrv_read/write that doesn't trigger any callbacks.
- *
- * However, these functions are often emulated using AIO which means that AIO
- * callbacks must be run - but at the same time we must not run callbacks of
- * other requests as they might start to modify metadata and corrupt the
- * internal state of the caller of bdrv_read/write.
- *
- * To achieve the desired semantics we switch into a new AsyncContext.
- * Callbacks must only be run if they belong to the current AsyncContext.
- * Otherwise they need to be queued until their own context is active again.
- * This is how you can make qemu_aio_wait() wait only for your own callbacks.
- *
- * The AsyncContexts form a stack. When you leave a AsyncContexts, you always
- * return to the old ("parent") context.
- */
-struct AsyncContext {
-    /* Consecutive number of the AsyncContext (position in the stack) */
-    int id;
-
-    /* Anchor of the list of Bottom Halves belonging to the context */
-    struct QEMUBH *first_bh;
-
-    /* Link to parent context */
-    struct AsyncContext *parent;
-};
-
-/* The currently active AsyncContext */
-static struct AsyncContext *async_context = &(struct AsyncContext) { 0 };
-
-/*
- * Enter a new AsyncContext. Already scheduled Bottom Halves and AIO callbacks
- * won't be called until this context is left again.
- */
-void async_context_push(void)
-{
-    struct AsyncContext *new = qemu_mallocz(sizeof(*new));
-    new->parent = async_context;
-    new->id = async_context->id + 1;
-    async_context = new;
-}
-
-/* Run queued AIO completions and destroy Bottom Half */
-static void bh_run_aio_completions(void *opaque)
-{
-    QEMUBH **bh = opaque;
-    qemu_bh_delete(*bh);
-    qemu_free(bh);
-    qemu_aio_process_queue();
-}
-/*
- * Leave the currently active AsyncContext. All Bottom Halves belonging to the
- * old context are executed before changing the context.
- */
-void async_context_pop(void)
-{
-    struct AsyncContext *old = async_context;
-    QEMUBH **bh;
-
-    /* Flush the bottom halves, we don't want to lose them */
-    while (qemu_bh_poll());
-
-    /* Switch back to the parent context */
-    async_context = async_context->parent;
-    qemu_free(old);
-
-    if (async_context == NULL) {
-        abort();
-    }
-
-    /* Schedule BH to run any queued AIO completions as soon as possible */
-    bh = qemu_malloc(sizeof(*bh));
-    *bh = qemu_bh_new(bh_run_aio_completions, bh);
-    qemu_bh_schedule(*bh);
-}
-
-/*
- * Returns the ID of the currently active AsyncContext
- */
-int get_async_context_id(void)
-{
-    return async_context->id;
-}
+/* Anchor of the list of Bottom Halves belonging to the context */
+static struct QEMUBH *first_bh;
 
 /***********************************************************/
 /* bottom halves (can be seen as timers which expire ASAP) */
@@ -130,8 +46,8 @@ QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
     bh = qemu_mallocz(sizeof(QEMUBH));
     bh->cb = cb;
     bh->opaque = opaque;
-    bh->next = async_context->first_bh;
-    async_context->first_bh = bh;
+    bh->next = first_bh;
+    first_bh = bh;
     return bh;
 }
 
@@ -141,7 +57,7 @@ int qemu_bh_poll(void)
     int ret;
 
     ret = 0;
-    for (bh = async_context->first_bh; bh; bh = next) {
+    for (bh = first_bh; bh; bh = next) {
         next = bh->next;
         if (!bh->deleted && bh->scheduled) {
             bh->scheduled = 0;
@@ -153,7 +69,7 @@ int qemu_bh_poll(void)
     }
 
     /* remove deleted bhs */
-    bhp = &async_context->first_bh;
+    bhp = &first_bh;
     while (*bhp) {
         bh = *bhp;
         if (bh->deleted) {
@@ -199,7 +115,7 @@ void qemu_bh_update_timeout(int *timeout)
 {
     QEMUBH *bh;
 
-    for (bh = async_context->first_bh; bh; bh = bh->next) {
+    for (bh = first_bh; bh; bh = bh->next) {
         if (!bh->deleted && bh->scheduled) {
             if (bh->idle) {
                 /* idle bottom halves will be polled at least
index 248c1b50a97ed0ef71415cf9d43d65a1f291522a..f56fdc1c4b5018d1cf3fec1132e122d78e6940c5 100644 (file)
--- a/balloon.c
+++ b/balloon.c
@@ -1,7 +1,9 @@
 /*
- * QEMU System Emulator
+ * Generic Balloon handlers and management
  *
  * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011 Amit Shah <amit.shah@redhat.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 #include "balloon.h"
 #include "trace.h"
 
+static QEMUBalloonEvent *balloon_event_fn;
+static QEMUBalloonStatus *balloon_stat_fn;
+static void *balloon_opaque;
 
-static QEMUBalloonEvent *qemu_balloon_event;
-void *qemu_balloon_event_opaque;
-
-void qemu_add_balloon_handler(QEMUBalloonEvent *func, void *opaque)
+int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
+                             QEMUBalloonStatus *stat_func, void *opaque)
 {
-    qemu_balloon_event = func;
-    qemu_balloon_event_opaque = opaque;
+    if (balloon_event_fn || balloon_stat_fn || balloon_opaque) {
+        /* We're already registered one balloon handler.  How many can
+         * a guest really have?
+         */
+        error_report("Another balloon device already registered");
+        return -1;
+    }
+    balloon_event_fn = event_func;
+    balloon_stat_fn = stat_func;
+    balloon_opaque = opaque;
+    return 0;
 }
 
-int qemu_balloon(ram_addr_t target, MonitorCompletion cb, void *opaque)
+static int qemu_balloon(ram_addr_t target)
 {
-    if (qemu_balloon_event) {
-        trace_balloon_event(qemu_balloon_event_opaque, target);
-        qemu_balloon_event(qemu_balloon_event_opaque, target, cb, opaque);
-        return 1;
-    } else {
+    if (!balloon_event_fn) {
         return 0;
     }
+    trace_balloon_event(balloon_opaque, target);
+    balloon_event_fn(balloon_opaque, target);
+    return 1;
 }
 
-int qemu_balloon_status(MonitorCompletion cb, void *opaque)
+static int qemu_balloon_status(MonitorCompletion cb, void *opaque)
 {
-    if (qemu_balloon_event) {
-        qemu_balloon_event(qemu_balloon_event_opaque, 0, cb, opaque);
-        return 1;
-    } else {
+    if (!balloon_stat_fn) {
         return 0;
     }
+    balloon_stat_fn(balloon_opaque, cb, opaque);
+    return 1;
 }
 
 static void print_balloon_stat(const char *key, QObject *obj, void *opaque)
 {
     Monitor *mon = opaque;
 
-    if (strcmp(key, "actual"))
+    if (strcmp(key, "actual")) {
         monitor_printf(mon, ",%s=%" PRId64, key,
                        qint_get_int(qobject_to_qint(obj)));
+    }
 }
 
 void monitor_print_balloon(Monitor *mon, const QObject *data)
@@ -75,9 +86,9 @@ void monitor_print_balloon(Monitor *mon, const QObject *data)
     QDict *qdict;
 
     qdict = qobject_to_qdict(data);
-    if (!qdict_haskey(qdict, "actual"))
+    if (!qdict_haskey(qdict, "actual")) {
         return;
-
+    }
     monitor_printf(mon, "balloon: actual=%" PRId64,
                    qdict_get_int(qdict, "actual") >> 20);
     qdict_iter(qdict, print_balloon_stat, mon);
@@ -129,6 +140,7 @@ int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque)
 int do_balloon(Monitor *mon, const QDict *params,
               MonitorCompletion cb, void *opaque)
 {
+    int64_t target;
     int ret;
 
     if (kvm_enabled() && !kvm_has_sync_mmu()) {
@@ -136,7 +148,12 @@ int do_balloon(Monitor *mon, const QDict *params,
         return -1;
     }
 
-    ret = qemu_balloon(qdict_get_int(params, "value"), cb, opaque);
+    target = qdict_get_int(params, "value");
+    if (target <= 0) {
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "target", "a size");
+        return -1;
+    }
+    ret = qemu_balloon(target);
     if (ret == 0) {
         qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
         return -1;
index d478e2847503a2ebff8757a812497c9d87eb77e5..3df14e645a7f02e3104fc7643040012357b753db 100644 (file)
--- a/balloon.h
+++ b/balloon.h
 
 #include "monitor.h"
 
-typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target,
-                                MonitorCompletion cb, void *cb_data);
+typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target);
+typedef void (QEMUBalloonStatus)(void *opaque, MonitorCompletion cb,
+                                 void *cb_data);
 
-void qemu_add_balloon_handler(QEMUBalloonEvent *func, void *opaque);
-
-int qemu_balloon(ram_addr_t target, MonitorCompletion cb, void *opaque);
-
-int qemu_balloon_status(MonitorCompletion cb, void *opaque);
+int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
+                            QEMUBalloonStatus *stat_func, void *opaque);
 
 void monitor_print_balloon(Monitor *mon, const QObject *data);
 int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque);
diff --git a/block.c b/block.c
index 9549b9eff9f3034fdfae86e239851db459b9c0da..26910ca14301e51174bce04b686f0be5cb6bf9d7 100644 (file)
--- a/block.c
+++ b/block.c
@@ -28,6 +28,7 @@
 #include "block_int.h"
 #include "module.h"
 #include "qemu-objects.h"
+#include "qemu-coroutine.h"
 
 #ifdef CONFIG_BSD
 #include <sys/types.h>
@@ -57,6 +58,19 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
                         uint8_t *buf, int nb_sectors);
 static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
                          const uint8_t *buf, int nb_sectors);
+static BlockDriverAIOCB *bdrv_co_aio_readv_em(BlockDriverState *bs,
+        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
+static BlockDriverAIOCB *bdrv_co_aio_writev_em(BlockDriverState *bs,
+        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
+static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs,
+                                         int64_t sector_num, int nb_sectors,
+                                         QEMUIOVector *iov);
+static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs,
+                                         int64_t sector_num, int nb_sectors,
+                                         QEMUIOVector *iov);
+static int coroutine_fn bdrv_co_flush_em(BlockDriverState *bs);
 
 static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
     QTAILQ_HEAD_INITIALIZER(bdrv_states);
@@ -169,14 +183,25 @@ void path_combine(char *dest, int dest_size,
 
 void bdrv_register(BlockDriver *bdrv)
 {
-    if (!bdrv->bdrv_aio_readv) {
-        /* add AIO emulation layer */
-        bdrv->bdrv_aio_readv = bdrv_aio_readv_em;
-        bdrv->bdrv_aio_writev = bdrv_aio_writev_em;
-    } else if (!bdrv->bdrv_read) {
-        /* add synchronous IO emulation layer */
+    if (bdrv->bdrv_co_readv) {
+        /* Emulate AIO by coroutines, and sync by AIO */
+        bdrv->bdrv_aio_readv = bdrv_co_aio_readv_em;
+        bdrv->bdrv_aio_writev = bdrv_co_aio_writev_em;
         bdrv->bdrv_read = bdrv_read_em;
         bdrv->bdrv_write = bdrv_write_em;
+     } else {
+        bdrv->bdrv_co_readv = bdrv_co_readv_em;
+        bdrv->bdrv_co_writev = bdrv_co_writev_em;
+
+        if (!bdrv->bdrv_aio_readv) {
+            /* add AIO emulation layer */
+            bdrv->bdrv_aio_readv = bdrv_aio_readv_em;
+            bdrv->bdrv_aio_writev = bdrv_aio_writev_em;
+        } else if (!bdrv->bdrv_read) {
+            /* add synchronous IO emulation layer */
+            bdrv->bdrv_read = bdrv_read_em;
+            bdrv->bdrv_write = bdrv_write_em;
+        }
     }
 
     if (!bdrv->bdrv_aio_flush)
@@ -730,6 +755,8 @@ void bdrv_detach(BlockDriverState *bs, DeviceState *qdev)
 {
     assert(bs->peer == qdev);
     bs->peer = NULL;
+    bs->change_cb = NULL;
+    bs->change_opaque = NULL;
 }
 
 DeviceState *bdrv_get_attached(BlockDriverState *bs)
@@ -920,6 +947,17 @@ static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
                                    nb_sectors * BDRV_SECTOR_SIZE);
 }
 
+static inline bool bdrv_has_async_rw(BlockDriver *drv)
+{
+    return drv->bdrv_co_readv != bdrv_co_readv_em
+        || drv->bdrv_aio_readv != bdrv_aio_readv_em;
+}
+
+static inline bool bdrv_has_async_flush(BlockDriver *drv)
+{
+    return drv->bdrv_aio_flush != bdrv_aio_flush_em;
+}
+
 /* return < 0 if error. See bdrv_write() for the return codes */
 int bdrv_read(BlockDriverState *bs, int64_t sector_num,
               uint8_t *buf, int nb_sectors)
@@ -928,6 +966,18 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num,
 
     if (!drv)
         return -ENOMEDIUM;
+
+    if (bdrv_has_async_rw(drv) && qemu_in_coroutine()) {
+        QEMUIOVector qiov;
+        struct iovec iov = {
+            .iov_base = (void *)buf,
+            .iov_len = nb_sectors * BDRV_SECTOR_SIZE,
+        };
+
+        qemu_iovec_init_external(&qiov, &iov, 1);
+        return bdrv_co_readv(bs, sector_num, nb_sectors, &qiov);
+    }
+
     if (bdrv_check_request(bs, sector_num, nb_sectors))
         return -EIO;
 
@@ -972,8 +1022,21 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
                const uint8_t *buf, int nb_sectors)
 {
     BlockDriver *drv = bs->drv;
+
     if (!bs->drv)
         return -ENOMEDIUM;
+
+    if (bdrv_has_async_rw(drv) && qemu_in_coroutine()) {
+        QEMUIOVector qiov;
+        struct iovec iov = {
+            .iov_base = (void *)buf,
+            .iov_len = nb_sectors * BDRV_SECTOR_SIZE,
+        };
+
+        qemu_iovec_init_external(&qiov, &iov, 1);
+        return bdrv_co_writev(bs, sector_num, nb_sectors, &qiov);
+    }
+
     if (bs->read_only)
         return -EACCES;
     if (bdrv_check_request(bs, sector_num, nb_sectors))
@@ -1108,17 +1171,49 @@ int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset,
     return 0;
 }
 
-/*
- * Writes to the file and ensures that no writes are reordered across this
- * request (acts as a barrier)
- *
- * Returns 0 on success, -errno in error cases.
- */
-int bdrv_write_sync(BlockDriverState *bs, int64_t sector_num,
-    const uint8_t *buf, int nb_sectors)
+int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num,
+    int nb_sectors, QEMUIOVector *qiov)
+{
+    BlockDriver *drv = bs->drv;
+
+    trace_bdrv_co_readv(bs, sector_num, nb_sectors);
+
+    if (!drv) {
+        return -ENOMEDIUM;
+    }
+    if (bdrv_check_request(bs, sector_num, nb_sectors)) {
+        return -EIO;
+    }
+
+    return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
+}
+
+int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num,
+    int nb_sectors, QEMUIOVector *qiov)
 {
-    return bdrv_pwrite_sync(bs, BDRV_SECTOR_SIZE * sector_num,
-        buf, BDRV_SECTOR_SIZE * nb_sectors);
+    BlockDriver *drv = bs->drv;
+
+    trace_bdrv_co_writev(bs, sector_num, nb_sectors);
+
+    if (!bs->drv) {
+        return -ENOMEDIUM;
+    }
+    if (bs->read_only) {
+        return -EACCES;
+    }
+    if (bdrv_check_request(bs, sector_num, nb_sectors)) {
+        return -EIO;
+    }
+
+    if (bs->dirty_bitmap) {
+        set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
+    }
+
+    if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
+        bs->wr_highest_sector = sector_num + nb_sectors - 1;
+    }
+
+    return drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
 }
 
 /**
@@ -1591,6 +1686,10 @@ int bdrv_flush(BlockDriverState *bs)
         return 0;
     }
 
+    if (bs->drv && bdrv_has_async_flush(bs->drv) && qemu_in_coroutine()) {
+        return bdrv_co_flush_em(bs);
+    }
+
     if (bs->drv && bs->drv->bdrv_flush) {
         return bs->drv->bdrv_flush(bs);
     }
@@ -2580,6 +2679,89 @@ static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
     return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
 }
 
+
+typedef struct BlockDriverAIOCBCoroutine {
+    BlockDriverAIOCB common;
+    BlockRequest req;
+    bool is_write;
+    QEMUBH* bh;
+} BlockDriverAIOCBCoroutine;
+
+static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb)
+{
+    qemu_aio_flush();
+}
+
+static AIOPool bdrv_em_co_aio_pool = {
+    .aiocb_size         = sizeof(BlockDriverAIOCBCoroutine),
+    .cancel             = bdrv_aio_co_cancel_em,
+};
+
+static void bdrv_co_rw_bh(void *opaque)
+{
+    BlockDriverAIOCBCoroutine *acb = opaque;
+
+    acb->common.cb(acb->common.opaque, acb->req.error);
+    qemu_bh_delete(acb->bh);
+    qemu_aio_release(acb);
+}
+
+static void coroutine_fn bdrv_co_rw(void *opaque)
+{
+    BlockDriverAIOCBCoroutine *acb = opaque;
+    BlockDriverState *bs = acb->common.bs;
+
+    if (!acb->is_write) {
+        acb->req.error = bs->drv->bdrv_co_readv(bs, acb->req.sector,
+            acb->req.nb_sectors, acb->req.qiov);
+    } else {
+        acb->req.error = bs->drv->bdrv_co_writev(bs, acb->req.sector,
+            acb->req.nb_sectors, acb->req.qiov);
+    }
+
+    acb->bh = qemu_bh_new(bdrv_co_rw_bh, acb);
+    qemu_bh_schedule(acb->bh);
+}
+
+static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
+                                               int64_t sector_num,
+                                               QEMUIOVector *qiov,
+                                               int nb_sectors,
+                                               BlockDriverCompletionFunc *cb,
+                                               void *opaque,
+                                               bool is_write)
+{
+    Coroutine *co;
+    BlockDriverAIOCBCoroutine *acb;
+
+    acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque);
+    acb->req.sector = sector_num;
+    acb->req.nb_sectors = nb_sectors;
+    acb->req.qiov = qiov;
+    acb->is_write = is_write;
+
+    co = qemu_coroutine_create(bdrv_co_rw);
+    qemu_coroutine_enter(co, acb);
+
+    return &acb->common;
+}
+
+static BlockDriverAIOCB *bdrv_co_aio_readv_em(BlockDriverState *bs,
+        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque,
+                                 false);
+}
+
+static BlockDriverAIOCB *bdrv_co_aio_writev_em(BlockDriverState *bs,
+        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque,
+                                 true);
+}
+
 static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
         BlockDriverCompletionFunc *cb, void *opaque)
 {
@@ -2636,8 +2818,6 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
     struct iovec iov;
     QEMUIOVector qiov;
 
-    async_context_push();
-
     async_ret = NOT_DONE;
     iov.iov_base = (void *)buf;
     iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
@@ -2655,7 +2835,6 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
 
 
 fail:
-    async_context_pop();
     return async_ret;
 }
 
@@ -2667,8 +2846,6 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
     struct iovec iov;
     QEMUIOVector qiov;
 
-    async_context_push();
-
     async_ret = NOT_DONE;
     iov.iov_base = (void *)buf;
     iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
@@ -2684,7 +2861,6 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
     }
 
 fail:
-    async_context_pop();
     return async_ret;
 }
 
@@ -2725,6 +2901,77 @@ void qemu_aio_release(void *p)
     pool->free_aiocb = acb;
 }
 
+/**************************************************************/
+/* Coroutine block device emulation */
+
+typedef struct CoroutineIOCompletion {
+    Coroutine *coroutine;
+    int ret;
+} CoroutineIOCompletion;
+
+static void bdrv_co_io_em_complete(void *opaque, int ret)
+{
+    CoroutineIOCompletion *co = opaque;
+
+    co->ret = ret;
+    qemu_coroutine_enter(co->coroutine, NULL);
+}
+
+static int coroutine_fn bdrv_co_io_em(BlockDriverState *bs, int64_t sector_num,
+                                      int nb_sectors, QEMUIOVector *iov,
+                                      bool is_write)
+{
+    CoroutineIOCompletion co = {
+        .coroutine = qemu_coroutine_self(),
+    };
+    BlockDriverAIOCB *acb;
+
+    if (is_write) {
+        acb = bdrv_aio_writev(bs, sector_num, iov, nb_sectors,
+                              bdrv_co_io_em_complete, &co);
+    } else {
+        acb = bdrv_aio_readv(bs, sector_num, iov, nb_sectors,
+                             bdrv_co_io_em_complete, &co);
+    }
+
+    trace_bdrv_co_io(is_write, acb);
+    if (!acb) {
+        return -EIO;
+    }
+    qemu_coroutine_yield();
+
+    return co.ret;
+}
+
+static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs,
+                                         int64_t sector_num, int nb_sectors,
+                                         QEMUIOVector *iov)
+{
+    return bdrv_co_io_em(bs, sector_num, nb_sectors, iov, false);
+}
+
+static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs,
+                                         int64_t sector_num, int nb_sectors,
+                                         QEMUIOVector *iov)
+{
+    return bdrv_co_io_em(bs, sector_num, nb_sectors, iov, true);
+}
+
+static int coroutine_fn bdrv_co_flush_em(BlockDriverState *bs)
+{
+    CoroutineIOCompletion co = {
+        .coroutine = qemu_coroutine_self(),
+    };
+    BlockDriverAIOCB *acb;
+
+    acb = bdrv_aio_flush(bs, bdrv_co_io_em_complete, &co);
+    if (!acb) {
+        return -EIO;
+    }
+    qemu_coroutine_yield();
+    return co.ret;
+}
+
 /**************************************************************/
 /* removable device support */
 
@@ -2768,25 +3015,16 @@ int bdrv_media_changed(BlockDriverState *bs)
 int bdrv_eject(BlockDriverState *bs, int eject_flag)
 {
     BlockDriver *drv = bs->drv;
-    int ret;
 
-    if (bs->locked) {
+    if (eject_flag && bs->locked) {
         return -EBUSY;
     }
 
-    if (!drv || !drv->bdrv_eject) {
-        ret = -ENOTSUP;
-    } else {
-        ret = drv->bdrv_eject(bs, eject_flag);
-    }
-    if (ret == -ENOTSUP) {
-        ret = 0;
+    if (drv && drv->bdrv_eject) {
+        drv->bdrv_eject(bs, eject_flag);
     }
-    if (ret >= 0) {
-        bs->tray_open = eject_flag;
-    }
-
-    return ret;
+    bs->tray_open = eject_flag;
+    return 0;
 }
 
 int bdrv_is_locked(BlockDriverState *bs)
diff --git a/block.h b/block.h
index 59cc410e3b1915b2944445824cbabe4cc22f96fd..a3bfaafef05ac5e98e4edbc6d9de1208cd34a33b 100644 (file)
--- a/block.h
+++ b/block.h
@@ -4,6 +4,7 @@
 #include "qemu-aio.h"
 #include "qemu-common.h"
 #include "qemu-option.h"
+#include "qemu-coroutine.h"
 #include "qobject.h"
 
 /* block.c */
@@ -85,8 +86,10 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
                 const void *buf, int count);
 int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset,
     const void *buf, int count);
-int bdrv_write_sync(BlockDriverState *bs, int64_t sector_num,
-    const uint8_t *buf, int nb_sectors);
+int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num,
+    int nb_sectors, QEMUIOVector *qiov);
+int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num,
+    int nb_sectors, QEMUIOVector *qiov);
 int bdrv_truncate(BlockDriverState *bs, int64_t offset);
 int64_t bdrv_getlength(BlockDriverState *bs);
 int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
index 227b104e36dc3752cad4f1f3046f9fb37ba27c35..6447c2a1c0677c064caddedb1818e15dd5565552 100644 (file)
@@ -73,6 +73,7 @@ typedef struct BDRVQcowState {
     uint32_t crypt_method_header;
     AES_KEY aes_encrypt_key;
     AES_KEY aes_decrypt_key;
+    CoMutex lock;
 } BDRVQcowState;
 
 static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
@@ -517,11 +518,11 @@ static AIOPool qcow_aio_pool = {
 
 static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque, int is_write)
+        int is_write)
 {
     QCowAIOCB *acb;
 
-    acb = qemu_aio_get(&qcow_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&qcow_aio_pool, bs, NULL, NULL);
     if (!acb)
         return NULL;
     acb->hd_aiocb = NULL;
@@ -542,48 +543,15 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
     return acb;
 }
 
-static void qcow_aio_read_cb(void *opaque, int ret);
-static void qcow_aio_write_cb(void *opaque, int ret);
-
-static void qcow_aio_rw_bh(void *opaque)
-{
-    QCowAIOCB *acb = opaque;
-    qemu_bh_delete(acb->bh);
-    acb->bh = NULL;
-
-    if (acb->is_write) {
-        qcow_aio_write_cb(opaque, 0);
-    } else {
-        qcow_aio_read_cb(opaque, 0);
-    }
-}
-
-static int qcow_schedule_bh(QEMUBHFunc *cb, QCowAIOCB *acb)
-{
-    if (acb->bh) {
-        return -EIO;
-    }
-
-    acb->bh = qemu_bh_new(cb, acb);
-    if (!acb->bh) {
-        return -EIO;
-    }
-
-    qemu_bh_schedule(acb->bh);
-
-    return 0;
-}
-
-static void qcow_aio_read_cb(void *opaque, int ret)
+static int qcow_aio_read_cb(void *opaque)
 {
     QCowAIOCB *acb = opaque;
     BlockDriverState *bs = acb->common.bs;
     BDRVQcowState *s = bs->opaque;
     int index_in_cluster;
+    int ret;
 
     acb->hd_aiocb = NULL;
-    if (ret < 0)
-        goto done;
 
  redo:
     /* post process the read buffer */
@@ -605,8 +573,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
 
     if (acb->nb_sectors == 0) {
         /* request completed */
-        ret = 0;
-        goto done;
+        return 0;
     }
 
     /* prepare next AIO request */
@@ -623,11 +590,12 @@ static void qcow_aio_read_cb(void *opaque, int ret)
             acb->hd_iov.iov_base = (void *)acb->buf;
             acb->hd_iov.iov_len = acb->n * 512;
             qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-            acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
-                &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
-            if (acb->hd_aiocb == NULL) {
-                ret = -EIO;
-                goto done;
+            qemu_co_mutex_unlock(&s->lock);
+            ret = bdrv_co_readv(bs->backing_hd, acb->sector_num,
+                                acb->n, &acb->hd_qiov);
+            qemu_co_mutex_lock(&s->lock);
+            if (ret < 0) {
+                return -EIO;
             }
         } else {
             /* Note: in this case, no need to wait */
@@ -637,64 +605,56 @@ static void qcow_aio_read_cb(void *opaque, int ret)
     } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
         /* add AIO support for compressed blocks ? */
         if (decompress_cluster(bs, acb->cluster_offset) < 0) {
-            ret = -EIO;
-            goto done;
+            return -EIO;
         }
         memcpy(acb->buf,
                s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
         goto redo;
     } else {
         if ((acb->cluster_offset & 511) != 0) {
-            ret = -EIO;
-            goto done;
+            return -EIO;
         }
         acb->hd_iov.iov_base = (void *)acb->buf;
         acb->hd_iov.iov_len = acb->n * 512;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        acb->hd_aiocb = bdrv_aio_readv(bs->file,
+        qemu_co_mutex_unlock(&s->lock);
+        ret = bdrv_co_readv(bs->file,
                             (acb->cluster_offset >> 9) + index_in_cluster,
-                            &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
-        if (acb->hd_aiocb == NULL) {
-            ret = -EIO;
-            goto done;
+                            acb->n, &acb->hd_qiov);
+        qemu_co_mutex_lock(&s->lock);
+        if (ret < 0) {
+            return ret;
         }
     }
 
-    return;
-
-done:
-    if (acb->qiov->niov > 1) {
-        qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size);
-        qemu_vfree(acb->orig_buf);
-    }
-    acb->common.cb(acb->common.opaque, ret);
-    qemu_aio_release(acb);
+    return 1;
 }
 
-static BlockDriverAIOCB *qcow_aio_readv(BlockDriverState *bs,
-        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+static int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
+                         int nb_sectors, QEMUIOVector *qiov)
 {
+    BDRVQcowState *s = bs->opaque;
     QCowAIOCB *acb;
     int ret;
 
-    acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
-    if (!acb)
-        return NULL;
+    acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, 0);
 
-    ret = qcow_schedule_bh(qcow_aio_rw_bh, acb);
-    if (ret < 0) {
-        if (acb->qiov->niov > 1) {
-            qemu_vfree(acb->orig_buf);
-        }
-        qemu_aio_release(acb);
-        return NULL;
+    qemu_co_mutex_lock(&s->lock);
+    do {
+        ret = qcow_aio_read_cb(acb);
+    } while (ret > 0);
+    qemu_co_mutex_unlock(&s->lock);
+
+    if (acb->qiov->niov > 1) {
+        qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size);
+        qemu_vfree(acb->orig_buf);
     }
+    qemu_aio_release(acb);
 
-    return &acb->common;
+    return ret;
 }
 
-static void qcow_aio_write_cb(void *opaque, int ret)
+static int qcow_aio_write_cb(void *opaque)
 {
     QCowAIOCB *acb = opaque;
     BlockDriverState *bs = acb->common.bs;
@@ -702,20 +662,17 @@ static void qcow_aio_write_cb(void *opaque, int ret)
     int index_in_cluster;
     uint64_t cluster_offset;
     const uint8_t *src_buf;
+    int ret;
 
     acb->hd_aiocb = NULL;
 
-    if (ret < 0)
-        goto done;
-
     acb->nb_sectors -= acb->n;
     acb->sector_num += acb->n;
     acb->buf += acb->n * 512;
 
     if (acb->nb_sectors == 0) {
         /* request completed */
-        ret = 0;
-        goto done;
+        return 0;
     }
 
     index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
@@ -726,16 +683,11 @@ static void qcow_aio_write_cb(void *opaque, int ret)
                                         index_in_cluster,
                                         index_in_cluster + acb->n);
     if (!cluster_offset || (cluster_offset & 511) != 0) {
-        ret = -EIO;
-        goto done;
+        return -EIO;
     }
     if (s->crypt_method) {
         if (!acb->cluster_data) {
             acb->cluster_data = qemu_mallocz(s->cluster_size);
-            if (!acb->cluster_data) {
-                ret = -ENOMEM;
-                goto done;
-            }
         }
         encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf,
                         acb->n, 1, &s->aes_encrypt_key);
@@ -747,26 +699,19 @@ static void qcow_aio_write_cb(void *opaque, int ret)
     acb->hd_iov.iov_base = (void *)src_buf;
     acb->hd_iov.iov_len = acb->n * 512;
     qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-    acb->hd_aiocb = bdrv_aio_writev(bs->file,
-                                    (cluster_offset >> 9) + index_in_cluster,
-                                    &acb->hd_qiov, acb->n,
-                                    qcow_aio_write_cb, acb);
-    if (acb->hd_aiocb == NULL) {
-        ret = -EIO;
-        goto done;
+    qemu_co_mutex_unlock(&s->lock);
+    ret = bdrv_co_writev(bs->file,
+                         (cluster_offset >> 9) + index_in_cluster,
+                         acb->n, &acb->hd_qiov);
+    qemu_co_mutex_lock(&s->lock);
+    if (ret < 0) {
+        return ret;
     }
-    return;
-
-done:
-    if (acb->qiov->niov > 1)
-        qemu_vfree(acb->orig_buf);
-    acb->common.cb(acb->common.opaque, ret);
-    qemu_aio_release(acb);
+    return 1;
 }
 
-static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs,
-        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+static int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
+                          int nb_sectors, QEMUIOVector *qiov)
 {
     BDRVQcowState *s = bs->opaque;
     QCowAIOCB *acb;
@@ -774,21 +719,20 @@ static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs,
 
     s->cluster_cache_offset = -1; /* disable compressed cache */
 
-    acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
-    if (!acb)
-        return NULL;
+    acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, 1);
 
+    qemu_co_mutex_lock(&s->lock);
+    do {
+        ret = qcow_aio_write_cb(acb);
+    } while (ret > 0);
+    qemu_co_mutex_unlock(&s->lock);
 
-    ret = qcow_schedule_bh(qcow_aio_rw_bh, acb);
-    if (ret < 0) {
-        if (acb->qiov->niov > 1) {
-            qemu_vfree(acb->orig_buf);
-        }
-        qemu_aio_release(acb);
-        return NULL;
+    if (acb->qiov->niov > 1) {
+        qemu_vfree(acb->orig_buf);
     }
+    qemu_aio_release(acb);
 
-    return &acb->common;
+    return ret;
 }
 
 static void qcow_close(BlockDriverState *bs)
@@ -1020,8 +964,8 @@ static BlockDriver bdrv_qcow = {
     .bdrv_is_allocated = qcow_is_allocated,
     .bdrv_set_key      = qcow_set_key,
     .bdrv_make_empty   = qcow_make_empty,
-    .bdrv_aio_readv    = qcow_aio_readv,
-    .bdrv_aio_writev   = qcow_aio_writev,
+    .bdrv_co_readv  = qcow_co_readv,
+    .bdrv_co_writev = qcow_co_writev,
     .bdrv_aio_flush    = qcow_aio_flush,
     .bdrv_write_compressed = qcow_write_compressed,
     .bdrv_get_info     = qcow_get_info,
index 882f50a80b64137b75221b8c9fd8e1e6761b8641..81cf77d83cb285c973f8c8aabc6d6b84c38bb1d7 100644 (file)
@@ -697,12 +697,12 @@ err:
  * m->depends_on is set to NULL and the other fields in m are meaningless.
  *
  * If the cluster is newly allocated, m->nb_clusters is set to the number of
- * contiguous clusters that have been allocated. This may be 0 if the request
- * conflict with another write request in flight; in this case, m->depends_on
- * is set and the remaining fields of m are meaningless.
+ * contiguous clusters that have been allocated. In this case, the other
+ * fields of m are valid and contain information about the first allocated
+ * cluster.
  *
- * If m->nb_clusters is non-zero, the other fields of m are valid and contain
- * information about the first allocated cluster.
+ * If the request conflicts with another write request in flight, the coroutine
+ * is queued and will be reentered when the dependency has completed.
  *
  * Return 0 on success and -errno in error cases
  */
@@ -721,6 +721,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
         return ret;
     }
 
+again:
     nb_clusters = size_to_clusters(s, n_end << 9);
 
     nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
@@ -792,12 +793,12 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
             }
 
             if (nb_clusters == 0) {
-                /* Set dependency and wait for a callback */
-                m->depends_on = old_alloc;
-                m->nb_clusters = 0;
-                *num = 0;
-
-                goto out_wait_dependency;
+                /* Wait for the dependency to complete. We need to recheck
+                 * the free/allocated clusters when we continue. */
+                qemu_co_mutex_unlock(&s->lock);
+                qemu_co_queue_wait(&old_alloc->dependent_requests);
+                qemu_co_mutex_lock(&s->lock);
+                goto again;
             }
         }
     }
@@ -834,9 +835,6 @@ out:
 
     return 0;
 
-out_wait_dependency:
-    return qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
-
 fail:
     qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
 fail_put:
index 74823a5ebfc2d47efe5d4429f8a447a46ca9cdf3..e32bcf084cda44fdff6838d6bb6bf3eb631e3cfc 100644 (file)
@@ -317,7 +317,8 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
 {
     BDRVQcowState *s = bs->opaque;
     QCowSnapshot *sn;
-    int i, snapshot_index, l1_size2;
+    int i, snapshot_index;
+    int cur_l1_bytes, sn_l1_bytes;
 
     snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
     if (snapshot_index < 0)
@@ -330,14 +331,19 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     if (qcow2_grow_l1_table(bs, sn->l1_size, true) < 0)
         goto fail;
 
-    s->l1_size = sn->l1_size;
-    l1_size2 = s->l1_size * sizeof(uint64_t);
+    cur_l1_bytes = s->l1_size * sizeof(uint64_t);
+    sn_l1_bytes = sn->l1_size * sizeof(uint64_t);
+
+    if (cur_l1_bytes > sn_l1_bytes) {
+        memset(s->l1_table + sn->l1_size, 0, cur_l1_bytes - sn_l1_bytes);
+    }
+
     /* copy the snapshot l1 table to the current l1 table */
     if (bdrv_pread(bs->file, sn->l1_table_offset,
-                   s->l1_table, l1_size2) != l1_size2)
+                   s->l1_table, sn_l1_bytes) < 0)
         goto fail;
     if (bdrv_pwrite_sync(bs->file, s->l1_table_offset,
-                    s->l1_table, l1_size2) < 0)
+                    s->l1_table, cur_l1_bytes) < 0)
         goto fail;
     for(i = 0;i < s->l1_size; i++) {
         be64_to_cpus(&s->l1_table[i]);
index 48e1b956896841aa62544c07d151e04b918e8d74..f07d550a96c230328bdbbaad16032dd163d2f435 100644 (file)
@@ -276,6 +276,9 @@ static int qcow2_open(BlockDriverState *bs, int flags)
         goto fail;
     }
 
+    /* Initialise locks */
+    qemu_co_mutex_init(&s->lock);
+
 #ifdef DEBUG_ALLOC
     qcow2_check_refcounts(bs);
 #endif
@@ -379,7 +382,6 @@ typedef struct QCowAIOCB {
     uint64_t cluster_offset;
     uint8_t *cluster_data;
     bool is_write;
-    BlockDriverAIOCB *hd_aiocb;
     QEMUIOVector hd_qiov;
     QEMUBH *bh;
     QCowL2Meta l2meta;
@@ -389,8 +391,6 @@ typedef struct QCowAIOCB {
 static void qcow2_aio_cancel(BlockDriverAIOCB *blockacb)
 {
     QCowAIOCB *acb = container_of(blockacb, QCowAIOCB, common);
-    if (acb->hd_aiocb)
-        bdrv_aio_cancel(acb->hd_aiocb);
     qemu_aio_release(acb);
 }
 
@@ -399,46 +399,16 @@ static AIOPool qcow2_aio_pool = {
     .cancel             = qcow2_aio_cancel,
 };
 
-static void qcow2_aio_read_cb(void *opaque, int ret);
-static void qcow2_aio_write_cb(void *opaque, int ret);
-
-static void qcow2_aio_rw_bh(void *opaque)
-{
-    QCowAIOCB *acb = opaque;
-    qemu_bh_delete(acb->bh);
-    acb->bh = NULL;
-
-    if (acb->is_write) {
-        qcow2_aio_write_cb(opaque, 0);
-    } else {
-        qcow2_aio_read_cb(opaque, 0);
-    }
-}
-
-static int qcow2_schedule_bh(QEMUBHFunc *cb, QCowAIOCB *acb)
-{
-    if (acb->bh)
-        return -EIO;
-
-    acb->bh = qemu_bh_new(cb, acb);
-    if (!acb->bh)
-        return -EIO;
-
-    qemu_bh_schedule(acb->bh);
-
-    return 0;
-}
-
-static void qcow2_aio_read_cb(void *opaque, int ret)
+/*
+ * Returns 0 when the request is completed successfully, 1 when there is still
+ * a part left to do and -errno in error cases.
+ */
+static int qcow2_aio_read_cb(QCowAIOCB *acb)
 {
-    QCowAIOCB *acb = opaque;
     BlockDriverState *bs = acb->common.bs;
     BDRVQcowState *s = bs->opaque;
     int index_in_cluster, n1;
-
-    acb->hd_aiocb = NULL;
-    if (ret < 0)
-        goto done;
+    int ret;
 
     /* post process the read buffer */
     if (!acb->cluster_offset) {
@@ -463,8 +433,7 @@ static void qcow2_aio_read_cb(void *opaque, int ret)
 
     if (acb->remaining_sectors == 0) {
         /* request completed */
-        ret = 0;
-        goto done;
+        return 0;
     }
 
     /* prepare next AIO request */
@@ -477,7 +446,7 @@ static void qcow2_aio_read_cb(void *opaque, int ret)
     ret = qcow2_get_cluster_offset(bs, acb->sector_num << 9,
         &acb->cur_nr_sectors, &acb->cluster_offset);
     if (ret < 0) {
-        goto done;
+        return ret;
     }
 
     index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
@@ -494,42 +463,35 @@ static void qcow2_aio_read_cb(void *opaque, int ret)
                 acb->sector_num, acb->cur_nr_sectors);
             if (n1 > 0) {
                 BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
-                acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
-                                    &acb->hd_qiov, n1, qcow2_aio_read_cb, acb);
-                if (acb->hd_aiocb == NULL) {
-                    ret = -EIO;
-                    goto done;
+                qemu_co_mutex_unlock(&s->lock);
+                ret = bdrv_co_readv(bs->backing_hd, acb->sector_num,
+                                    n1, &acb->hd_qiov);
+                qemu_co_mutex_lock(&s->lock);
+                if (ret < 0) {
+                    return ret;
                 }
-            } else {
-                ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb);
-                if (ret < 0)
-                    goto done;
             }
+            return 1;
         } else {
             /* Note: in this case, no need to wait */
             qemu_iovec_memset(&acb->hd_qiov, 0, 512 * acb->cur_nr_sectors);
-            ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb);
-            if (ret < 0)
-                goto done;
+            return 1;
         }
     } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
         /* add AIO support for compressed blocks ? */
         ret = qcow2_decompress_cluster(bs, acb->cluster_offset);
         if (ret < 0) {
-            goto done;
+            return ret;
         }
 
         qemu_iovec_from_buffer(&acb->hd_qiov,
             s->cluster_cache + index_in_cluster * 512,
             512 * acb->cur_nr_sectors);
 
-        ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb);
-        if (ret < 0)
-            goto done;
+        return 1;
     } else {
         if ((acb->cluster_offset & 511) != 0) {
-            ret = -EIO;
-            goto done;
+            return -EIO;
         }
 
         if (s->crypt_method) {
@@ -550,21 +512,17 @@ static void qcow2_aio_read_cb(void *opaque, int ret)
         }
 
         BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
-        acb->hd_aiocb = bdrv_aio_readv(bs->file,
+        qemu_co_mutex_unlock(&s->lock);
+        ret = bdrv_co_readv(bs->file,
                             (acb->cluster_offset >> 9) + index_in_cluster,
-                            &acb->hd_qiov, acb->cur_nr_sectors,
-                            qcow2_aio_read_cb, acb);
-        if (acb->hd_aiocb == NULL) {
-            ret = -EIO;
-            goto done;
+                            acb->cur_nr_sectors, &acb->hd_qiov);
+        qemu_co_mutex_lock(&s->lock);
+        if (ret < 0) {
+            return ret;
         }
     }
 
-    return;
-done:
-    acb->common.cb(acb->common.opaque, ret);
-    qemu_iovec_destroy(&acb->hd_qiov);
-    qemu_aio_release(acb);
+    return 1;
 }
 
 static QCowAIOCB *qcow2_aio_setup(BlockDriverState *bs, int64_t sector_num,
@@ -577,7 +535,6 @@ static QCowAIOCB *qcow2_aio_setup(BlockDriverState *bs, int64_t sector_num,
     acb = qemu_aio_get(&qcow2_aio_pool, bs, cb, opaque);
     if (!acb)
         return NULL;
-    acb->hd_aiocb = NULL;
     acb->sector_num = sector_num;
     acb->qiov = qiov;
     acb->is_write = is_write;
@@ -589,70 +546,65 @@ static QCowAIOCB *qcow2_aio_setup(BlockDriverState *bs, int64_t sector_num,
     acb->cur_nr_sectors = 0;
     acb->cluster_offset = 0;
     acb->l2meta.nb_clusters = 0;
-    QLIST_INIT(&acb->l2meta.dependent_requests);
+    qemu_co_queue_init(&acb->l2meta.dependent_requests);
     return acb;
 }
 
-static BlockDriverAIOCB *qcow2_aio_readv(BlockDriverState *bs,
-                                         int64_t sector_num,
-                                         QEMUIOVector *qiov, int nb_sectors,
-                                         BlockDriverCompletionFunc *cb,
-                                         void *opaque)
+static int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num,
+                          int nb_sectors, QEMUIOVector *qiov)
 {
+    BDRVQcowState *s = bs->opaque;
     QCowAIOCB *acb;
     int ret;
 
-    acb = qcow2_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
-    if (!acb)
-        return NULL;
+    acb = qcow2_aio_setup(bs, sector_num, qiov, nb_sectors, NULL, NULL, 0);
 
-    ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb);
-    if (ret < 0) {
-        qemu_iovec_destroy(&acb->hd_qiov);
-        qemu_aio_release(acb);
-        return NULL;
-    }
+    qemu_co_mutex_lock(&s->lock);
+    do {
+        ret = qcow2_aio_read_cb(acb);
+    } while (ret > 0);
+    qemu_co_mutex_unlock(&s->lock);
 
-    return &acb->common;
+    qemu_iovec_destroy(&acb->hd_qiov);
+    qemu_aio_release(acb);
+
+    return ret;
 }
 
-static void run_dependent_requests(QCowL2Meta *m)
+static void run_dependent_requests(BDRVQcowState *s, QCowL2Meta *m)
 {
-    QCowAIOCB *req;
-    QCowAIOCB *next;
-
     /* Take the request off the list of running requests */
     if (m->nb_clusters != 0) {
         QLIST_REMOVE(m, next_in_flight);
     }
 
     /* Restart all dependent requests */
-    QLIST_FOREACH_SAFE(req, &m->dependent_requests, next_depend, next) {
-        qcow2_aio_write_cb(req, 0);
+    if (!qemu_co_queue_empty(&m->dependent_requests)) {
+        qemu_co_mutex_unlock(&s->lock);
+        while(qemu_co_queue_next(&m->dependent_requests));
+        qemu_co_mutex_lock(&s->lock);
     }
-
-    /* Empty the list for the next part of the request */
-    QLIST_INIT(&m->dependent_requests);
 }
 
-static void qcow2_aio_write_cb(void *opaque, int ret)
+/*
+ * Returns 0 when the request is completed successfully, 1 when there is still
+ * a part left to do and -errno in error cases.
+ */
+static int qcow2_aio_write_cb(QCowAIOCB *acb)
 {
-    QCowAIOCB *acb = opaque;
     BlockDriverState *bs = acb->common.bs;
     BDRVQcowState *s = bs->opaque;
     int index_in_cluster;
     int n_end;
+    int ret;
 
-    acb->hd_aiocb = NULL;
-
-    if (ret >= 0) {
-        ret = qcow2_alloc_cluster_link_l2(bs, &acb->l2meta);
-    }
+    ret = qcow2_alloc_cluster_link_l2(bs, &acb->l2meta);
 
-    run_dependent_requests(&acb->l2meta);
+    run_dependent_requests(s, &acb->l2meta);
 
-    if (ret < 0)
-        goto done;
+    if (ret < 0) {
+        return ret;
+    }
 
     acb->remaining_sectors -= acb->cur_nr_sectors;
     acb->sector_num += acb->cur_nr_sectors;
@@ -660,8 +612,7 @@ static void qcow2_aio_write_cb(void *opaque, int ret)
 
     if (acb->remaining_sectors == 0) {
         /* request completed */
-        ret = 0;
-        goto done;
+        return 0;
     }
 
     index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
@@ -673,18 +624,10 @@ static void qcow2_aio_write_cb(void *opaque, int ret)
     ret = qcow2_alloc_cluster_offset(bs, acb->sector_num << 9,
         index_in_cluster, n_end, &acb->cur_nr_sectors, &acb->l2meta);
     if (ret < 0) {
-        goto done;
+        return ret;
     }
 
     acb->cluster_offset = acb->l2meta.cluster_offset;
-
-    /* Need to wait for another request? If so, we are done for now. */
-    if (acb->l2meta.nb_clusters == 0 && acb->l2meta.depends_on != NULL) {
-        QLIST_INSERT_HEAD(&acb->l2meta.depends_on->dependent_requests,
-            acb, next_depend);
-        return;
-    }
-
     assert((acb->cluster_offset & 511) == 0);
 
     qemu_iovec_reset(&acb->hd_qiov);
@@ -709,51 +652,40 @@ static void qcow2_aio_write_cb(void *opaque, int ret)
     }
 
     BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
-    acb->hd_aiocb = bdrv_aio_writev(bs->file,
-                                    (acb->cluster_offset >> 9) + index_in_cluster,
-                                    &acb->hd_qiov, acb->cur_nr_sectors,
-                                    qcow2_aio_write_cb, acb);
-    if (acb->hd_aiocb == NULL) {
-        ret = -EIO;
-        goto fail;
+    qemu_co_mutex_unlock(&s->lock);
+    ret = bdrv_co_writev(bs->file,
+                         (acb->cluster_offset >> 9) + index_in_cluster,
+                         acb->cur_nr_sectors, &acb->hd_qiov);
+    qemu_co_mutex_lock(&s->lock);
+    if (ret < 0) {
+        return ret;
     }
 
-    return;
-
-fail:
-    if (acb->l2meta.nb_clusters != 0) {
-        QLIST_REMOVE(&acb->l2meta, next_in_flight);
-    }
-done:
-    acb->common.cb(acb->common.opaque, ret);
-    qemu_iovec_destroy(&acb->hd_qiov);
-    qemu_aio_release(acb);
+    return 1;
 }
 
-static BlockDriverAIOCB *qcow2_aio_writev(BlockDriverState *bs,
-                                          int64_t sector_num,
-                                          QEMUIOVector *qiov, int nb_sectors,
-                                          BlockDriverCompletionFunc *cb,
-                                          void *opaque)
+static int qcow2_co_writev(BlockDriverState *bs,
+                           int64_t sector_num,
+                           int nb_sectors,
+                           QEMUIOVector *qiov)
 {
     BDRVQcowState *s = bs->opaque;
     QCowAIOCB *acb;
     int ret;
 
+    acb = qcow2_aio_setup(bs, sector_num, qiov, nb_sectors, NULL, NULL, 1);
     s->cluster_cache_offset = -1; /* disable compressed cache */
 
-    acb = qcow2_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
-    if (!acb)
-        return NULL;
+    qemu_co_mutex_lock(&s->lock);
+    do {
+        ret = qcow2_aio_write_cb(acb);
+    } while (ret > 0);
+    qemu_co_mutex_unlock(&s->lock);
 
-    ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb);
-    if (ret < 0) {
-        qemu_iovec_destroy(&acb->hd_qiov);
-        qemu_aio_release(acb);
-        return NULL;
-    }
+    qemu_iovec_destroy(&acb->hd_qiov);
+    qemu_aio_release(acb);
 
-    return &acb->common;
+    return ret;
 }
 
 static void qcow2_close(BlockDriverState *bs)
@@ -881,7 +813,7 @@ static int preallocate(BlockDriverState *bs)
 
     nb_sectors = bdrv_getlength(bs) >> 9;
     offset = 0;
-    QLIST_INIT(&meta.dependent_requests);
+    qemu_co_queue_init(&meta.dependent_requests);
     meta.cluster_offset = 0;
 
     while (nb_sectors) {
@@ -899,7 +831,7 @@ static int preallocate(BlockDriverState *bs)
 
         /* There are no dependent requests, but we need to remove our request
          * from the list of in-flight requests */
-        run_dependent_requests(&meta);
+        run_dependent_requests(bs->opaque, &meta);
 
         /* TODO Preallocate data if requested */
 
@@ -1387,8 +1319,8 @@ static BlockDriver bdrv_qcow2 = {
     .bdrv_set_key       = qcow2_set_key,
     .bdrv_make_empty    = qcow2_make_empty,
 
-    .bdrv_aio_readv     = qcow2_aio_readv,
-    .bdrv_aio_writev    = qcow2_aio_writev,
+    .bdrv_co_readv      = qcow2_co_readv,
+    .bdrv_co_writev     = qcow2_co_writev,
     .bdrv_aio_flush     = qcow2_aio_flush,
 
     .bdrv_discard           = qcow2_discard,
index 6a0a21b69443cc49252ea65dea7ee29f8251b83e..de23abe1a4991ad406536d12fa2f37f11e137735 100644 (file)
@@ -26,6 +26,7 @@
 #define BLOCK_QCOW2_H
 
 #include "aes.h"
+#include "qemu-coroutine.h"
 
 //#define DEBUG_ALLOC
 //#define DEBUG_ALLOC2
@@ -114,6 +115,8 @@ typedef struct BDRVQcowState {
     int64_t free_cluster_index;
     int64_t free_byte_offset;
 
+    CoMutex lock;
+
     uint32_t crypt_method; /* current crypt method, 0 if no key yet */
     uint32_t crypt_method_header;
     AES_KEY aes_encrypt_key;
@@ -146,7 +149,7 @@ typedef struct QCowL2Meta
     int nb_available;
     int nb_clusters;
     struct QCowL2Meta *depends_on;
-    QLIST_HEAD(QCowAioDependencies, QCowAIOCB) dependent_requests;
+    CoQueue dependent_requests;
 
     QLIST_ENTRY(QCowL2Meta) next_in_flight;
 } QCowL2Meta;
index d38c673547e32368fa3a52615e98ba08f52967cc..d96afa81d7cbc9b96d0273a32d5753b4d4cf30c1 100644 (file)
@@ -179,16 +179,12 @@ int qed_read_l1_table_sync(BDRVQEDState *s)
 {
     int ret = -EINPROGRESS;
 
-    async_context_push();
-
     qed_read_table(s, s->header.l1_table_offset,
                    s->l1_table, qed_sync_cb, &ret);
     while (ret == -EINPROGRESS) {
         qemu_aio_wait();
     }
 
-    async_context_pop();
-
     return ret;
 }
 
@@ -205,15 +201,11 @@ int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
 {
     int ret = -EINPROGRESS;
 
-    async_context_push();
-
     qed_write_l1_table(s, index, n, qed_sync_cb, &ret);
     while (ret == -EINPROGRESS) {
         qemu_aio_wait();
     }
 
-    async_context_pop();
-
     return ret;
 }
 
@@ -282,14 +274,11 @@ int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset
 {
     int ret = -EINPROGRESS;
 
-    async_context_push();
-
     qed_read_l2_table(s, request, offset, qed_sync_cb, &ret);
     while (ret == -EINPROGRESS) {
         qemu_aio_wait();
     }
 
-    async_context_pop();
     return ret;
 }
 
@@ -307,13 +296,10 @@ int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
 {
     int ret = -EINPROGRESS;
 
-    async_context_push();
-
     qed_write_l2_table(s, request, index, n, flush, qed_sync_cb, &ret);
     while (ret == -EINPROGRESS) {
         qemu_aio_wait();
     }
 
-    async_context_pop();
     return ret;
 }
index 39703793e9f9e281b9d9b36697a446df5488b665..333f067582e79e23cf7df615b2435461a7ea44e8 100644 (file)
@@ -680,16 +680,12 @@ static int bdrv_qed_is_allocated(BlockDriverState *bs, int64_t sector_num,
     };
     QEDRequest request = { .l2_table = NULL };
 
-    async_context_push();
-
     qed_find_cluster(s, &request, pos, len, qed_is_allocated_cb, &cb);
 
     while (cb.is_allocated == -1) {
         qemu_aio_wait();
     }
 
-    async_context_pop();
-
     qed_unref_l2_cache_entry(request.l2_table);
 
     return cb.is_allocated;
index cd89c8312af1d8c7b4f71777bbc73cb720e161f3..c5c99446c06908c66efc6ec77ac67e2e35d590af 100644 (file)
@@ -230,13 +230,15 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
         }
     }
 
+    /* We're falling back to POSIX AIO in some cases so init always */
+    if (paio_init() < 0) {
+        goto out_free_buf;
+    }
+
 #ifdef CONFIG_LINUX_AIO
     if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
                       (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {
 
-        /* We're falling back to POSIX AIO in some cases */
-        paio_init();
-
         s->aio_ctx = laio_init();
         if (!s->aio_ctx) {
             goto out_free_buf;
@@ -245,9 +247,6 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
     } else
 #endif
     {
-        if (paio_init() < 0) {
-            goto out_free_buf;
-        }
 #ifdef CONFIG_LINUX_AIO
         s->use_aio = 0;
 #endif
@@ -587,7 +586,7 @@ static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
 
     /*
      * If O_DIRECT is used the buffer needs to be aligned on a sector
-     * boundary.  Check if this is the case or telll the low-level
+     * boundary.  Check if this is the case or tell the low-level
      * driver that it needs to copy the buffer.
      */
     if (s->aligned_buf) {
@@ -1254,7 +1253,7 @@ static int floppy_media_changed(BlockDriverState *bs)
     return ret;
 }
 
-static int floppy_eject(BlockDriverState *bs, int eject_flag)
+static void floppy_eject(BlockDriverState *bs, int eject_flag)
 {
     BDRVRawState *s = bs->opaque;
     int fd;
@@ -1269,8 +1268,6 @@ static int floppy_eject(BlockDriverState *bs, int eject_flag)
             perror("FDEJECT");
         close(fd);
     }
-
-    return 0;
 }
 
 static BlockDriver bdrv_host_floppy = {
@@ -1348,7 +1345,7 @@ static int cdrom_is_inserted(BlockDriverState *bs)
     return 0;
 }
 
-static int cdrom_eject(BlockDriverState *bs, int eject_flag)
+static void cdrom_eject(BlockDriverState *bs, int eject_flag)
 {
     BDRVRawState *s = bs->opaque;
 
@@ -1359,11 +1356,9 @@ static int cdrom_eject(BlockDriverState *bs, int eject_flag)
         if (ioctl(s->fd, CDROMCLOSETRAY, NULL) < 0)
             perror("CDROMEJECT");
     }
-
-    return 0;
 }
 
-static int cdrom_set_locked(BlockDriverState *bs, int locked)
+static void cdrom_set_locked(BlockDriverState *bs, int locked)
 {
     BDRVRawState *s = bs->opaque;
 
@@ -1374,8 +1369,6 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked)
          */
         /* perror("CDROM_LOCKDOOR"); */
     }
-
-    return 0;
 }
 
 static BlockDriver bdrv_host_cdrom = {
@@ -1464,12 +1457,12 @@ static int cdrom_is_inserted(BlockDriverState *bs)
     return raw_getlength(bs) > 0;
 }
 
-static int cdrom_eject(BlockDriverState *bs, int eject_flag)
+static void cdrom_eject(BlockDriverState *bs, int eject_flag)
 {
     BDRVRawState *s = bs->opaque;
 
     if (s->fd < 0)
-        return -ENOTSUP;
+        return;
 
     (void) ioctl(s->fd, CDIOCALLOW);
 
@@ -1481,17 +1474,15 @@ static int cdrom_eject(BlockDriverState *bs, int eject_flag)
             perror("CDIOCCLOSE");
     }
 
-    if (cdrom_reopen(bs) < 0)
-        return -ENOTSUP;
-    return 0;
+    cdrom_reopen(bs);
 }
 
-static int cdrom_set_locked(BlockDriverState *bs, int locked)
+static void cdrom_set_locked(BlockDriverState *bs, int locked)
 {
     BDRVRawState *s = bs->opaque;
 
     if (s->fd < 0)
-        return -ENOTSUP;
+        return;
     if (ioctl(s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
         /*
          * Note: an error can happen if the distribution automatically
@@ -1499,8 +1490,6 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked)
          */
         /* perror("CDROM_LOCKDOOR"); */
     }
-
-    return 0;
 }
 
 static BlockDriver bdrv_host_cdrom = {
index 91067e75954c13402bc70b2cc88454b8d84168b9..e47cfe0f4a47afa9e0b3c564c9aee4d113a4bfef 100644 (file)
@@ -393,41 +393,6 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
     return 0;
 }
 
-#if 0
-/***********************************************/
-/* removable device additional commands */
-
-static int raw_is_inserted(BlockDriverState *bs)
-{
-    return 1;
-}
-
-static int raw_media_changed(BlockDriverState *bs)
-{
-    return -ENOTSUP;
-}
-
-static int raw_eject(BlockDriverState *bs, int eject_flag)
-{
-    DWORD ret_count;
-
-    if (s->type == FTYPE_FILE)
-        return -ENOTSUP;
-    if (eject_flag) {
-        DeviceIoControl(s->hfile, IOCTL_STORAGE_EJECT_MEDIA,
-                        NULL, 0, NULL, 0, &lpBytesReturned, NULL);
-    } else {
-        DeviceIoControl(s->hfile, IOCTL_STORAGE_LOAD_MEDIA,
-                        NULL, 0, NULL, 0, &lpBytesReturned, NULL);
-    }
-}
-
-static int raw_set_locked(BlockDriverState *bs, int locked)
-{
-    return -ENOTSUP;
-}
-#endif
-
 static int hdev_has_zero_init(BlockDriverState *bs)
 {
     return 0;
index b0f72d6a62cb29c3d177c811c8f29deadbf43e4f..cb6203eeca576b91e5155daca6923d52ccebeece 100644 (file)
@@ -75,15 +75,14 @@ static int raw_is_inserted(BlockDriverState *bs)
     return bdrv_is_inserted(bs->file);
 }
 
-static int raw_eject(BlockDriverState *bs, int eject_flag)
+static void raw_eject(BlockDriverState *bs, int eject_flag)
 {
-    return bdrv_eject(bs->file, eject_flag);
+    bdrv_eject(bs->file, eject_flag);
 }
 
-static int raw_set_locked(BlockDriverState *bs, int locked)
+static void raw_set_locked(BlockDriverState *bs, int locked)
 {
     bdrv_set_locked(bs->file, locked);
-    return 0;
 }
 
 static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
index 56865da5bc414cd168fac1ae2f0dc96563e961b9..fdd5236892f0629c175a4bb2f01677cccd29491b 100644 (file)
@@ -156,6 +156,7 @@ static int vpc_open(BlockDriverState *bs, int flags)
     struct vhd_dyndisk_header* dyndisk_header;
     uint8_t buf[HEADER_SIZE];
     uint32_t checksum;
+    int err = -1;
 
     if (bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE) != HEADER_SIZE)
         goto fail;
@@ -176,6 +177,11 @@ static int vpc_open(BlockDriverState *bs, int flags)
     bs->total_sectors = (int64_t)
         be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl;
 
+    if (bs->total_sectors >= 65535 * 16 * 255) {
+        err = -EFBIG;
+        goto fail;
+    }
+
     if (bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf, HEADER_SIZE)
             != HEADER_SIZE)
         goto fail;
@@ -222,7 +228,7 @@ static int vpc_open(BlockDriverState *bs, int flags)
 
     return 0;
  fail:
-    return -1;
+    return err;
 }
 
 /*
index efb68038c4c6cc79b85c055cdd92cd4d8fd7f962..f6d02b38a767d24fa5300818ee2a43b78f7c4a6d 100644 (file)
@@ -27,6 +27,7 @@
 #include "block.h"
 #include "qemu-option.h"
 #include "qemu-queue.h"
+#include "qemu-coroutine.h"
 
 #define BLOCK_FLAG_ENCRYPT     1
 #define BLOCK_FLAG_COMPAT6     4
@@ -77,6 +78,11 @@ struct BlockDriver {
     int (*bdrv_discard)(BlockDriverState *bs, int64_t sector_num,
                         int nb_sectors);
 
+    int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
+    int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
+
     int (*bdrv_aio_multiwrite)(BlockDriverState *bs, BlockRequest *reqs,
         int num_reqs);
     int (*bdrv_merge_requests)(BlockDriverState *bs, BlockRequest* a,
@@ -112,8 +118,8 @@ struct BlockDriver {
     /* removable device specific */
     int (*bdrv_is_inserted)(BlockDriverState *bs);
     int (*bdrv_media_changed)(BlockDriverState *bs);
-    int (*bdrv_eject)(BlockDriverState *bs, int eject_flag);
-    int (*bdrv_set_locked)(BlockDriverState *bs, int locked);
+    void (*bdrv_eject)(BlockDriverState *bs, int eject_flag);
+    void (*bdrv_set_locked)(BlockDriverState *bs, int locked);
 
     /* to control generic scsi devices */
     int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf);
index 0b8d3a4f83b645134c3a770a80d2f5c43587e85c..a25367a9e3c2f1744c464f1a4fd27b407b06fe11 100644 (file)
@@ -646,16 +646,13 @@ out:
 
 static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
 {
-    if (!force) {
-        if (!bdrv_is_removable(bs)) {
-            qerror_report(QERR_DEVICE_NOT_REMOVABLE,
-                           bdrv_get_device_name(bs));
-            return -1;
-        }
-        if (bdrv_is_locked(bs)) {
-            qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
-            return -1;
-        }
+    if (!bdrv_is_removable(bs)) {
+        qerror_report(QERR_DEVICE_NOT_REMOVABLE, bdrv_get_device_name(bs));
+        return -1;
+    }
+    if (!force && bdrv_is_locked(bs)) {
+        qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
+        return -1;
     }
     bdrv_close(bs);
     return 0;
index 6018a419ed5819464c64aa791838301962eaee4b..cc7d4a37adb40d5a283e6d15f6bdd0d3cbf7163b 100644 (file)
@@ -856,9 +856,6 @@ int main(int argc, char **argv)
             usage();
         }
     }
-    if (optind >= argc)
-        usage();
-    filename = argv[optind];
 
     /* init debug */
     cpu_set_log_filename(log_file);
@@ -877,6 +874,11 @@ int main(int argc, char **argv)
         cpu_set_log(mask);
     }
 
+    if (optind >= argc) {
+        usage();
+    }
+    filename = argv[optind];
+
     /* Zero out regs */
     memset(regs, 0, sizeof(struct target_pt_regs));
 
@@ -903,7 +905,8 @@ int main(int argc, char **argv)
         cpu_model = "any";
 #endif
     }
-    cpu_exec_init_all(0);
+    tcg_exec_init(0);
+    cpu_exec_init_all();
     /* NOTE: we need to init the CPU at this stage to get
        qemu_host_page_size */
     env = cpu_init(cpu_model);
diff --git a/bswap.h b/bswap.h
index 82a79517db971137f72d6c160b5721af131e6721..f41bebed83026ccf5698706343605b553f2e8b14 100644 (file)
--- a/bswap.h
+++ b/bswap.h
@@ -11,6 +11,8 @@
 #include <machine/bswap.h>
 #else
 
+#include "softfloat.h"
+
 #ifdef CONFIG_BYTESWAP_H
 #include <byteswap.h>
 #else
@@ -237,4 +239,476 @@ static inline uint32_t qemu_bswap_len(uint32_t value, int len)
     return bswap32(value) >> (32 - 8 * len);
 }
 
+typedef union {
+    float32 f;
+    uint32_t l;
+} CPU_FloatU;
+
+typedef union {
+    float64 d;
+#if defined(HOST_WORDS_BIGENDIAN)
+    struct {
+        uint32_t upper;
+        uint32_t lower;
+    } l;
+#else
+    struct {
+        uint32_t lower;
+        uint32_t upper;
+    } l;
+#endif
+    uint64_t ll;
+} CPU_DoubleU;
+
+typedef union {
+     floatx80 d;
+     struct {
+         uint64_t lower;
+         uint16_t upper;
+     } l;
+} CPU_LDoubleU;
+
+typedef union {
+    float128 q;
+#if defined(HOST_WORDS_BIGENDIAN)
+    struct {
+        uint32_t upmost;
+        uint32_t upper;
+        uint32_t lower;
+        uint32_t lowest;
+    } l;
+    struct {
+        uint64_t upper;
+        uint64_t lower;
+    } ll;
+#else
+    struct {
+        uint32_t lowest;
+        uint32_t lower;
+        uint32_t upper;
+        uint32_t upmost;
+    } l;
+    struct {
+        uint64_t lower;
+        uint64_t upper;
+    } ll;
+#endif
+} CPU_QuadU;
+
+/* unaligned/endian-independent pointer access */
+
+/*
+ * the generic syntax is:
+ *
+ * load: ld{type}{sign}{size}{endian}_p(ptr)
+ *
+ * store: st{type}{size}{endian}_p(ptr, val)
+ *
+ * Note there are small differences with the softmmu access API!
+ *
+ * type is:
+ * (empty): integer access
+ *   f    : float access
+ *
+ * sign is:
+ * (empty): for floats or 32 bit size
+ *   u    : unsigned
+ *   s    : signed
+ *
+ * size is:
+ *   b: 8 bits
+ *   w: 16 bits
+ *   l: 32 bits
+ *   q: 64 bits
+ *
+ * endian is:
+ * (empty): 8 bit access
+ *   be   : big endian
+ *   le   : little endian
+ */
+static inline int ldub_p(const void *ptr)
+{
+    return *(uint8_t *)ptr;
+}
+
+static inline int ldsb_p(const void *ptr)
+{
+    return *(int8_t *)ptr;
+}
+
+static inline void stb_p(void *ptr, int v)
+{
+    *(uint8_t *)ptr = v;
+}
+
+/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
+   kernel handles unaligned load/stores may give better results, but
+   it is a system wide setting : bad */
+#if defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
+
+/* conservative code for little endian unaligned accesses */
+static inline int lduw_le_p(const void *ptr)
+{
+#ifdef _ARCH_PPC
+    int val;
+    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
+    return val;
+#else
+    const uint8_t *p = ptr;
+    return p[0] | (p[1] << 8);
+#endif
+}
+
+static inline int ldsw_le_p(const void *ptr)
+{
+#ifdef _ARCH_PPC
+    int val;
+    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
+    return (int16_t)val;
+#else
+    const uint8_t *p = ptr;
+    return (int16_t)(p[0] | (p[1] << 8));
+#endif
+}
+
+static inline int ldl_le_p(const void *ptr)
+{
+#ifdef _ARCH_PPC
+    int val;
+    __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
+    return val;
+#else
+    const uint8_t *p = ptr;
+    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+#endif
+}
+
+static inline uint64_t ldq_le_p(const void *ptr)
+{
+    const uint8_t *p = ptr;
+    uint32_t v1, v2;
+    v1 = ldl_le_p(p);
+    v2 = ldl_le_p(p + 4);
+    return v1 | ((uint64_t)v2 << 32);
+}
+
+static inline void stw_le_p(void *ptr, int v)
+{
+#ifdef _ARCH_PPC
+    __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
+#else
+    uint8_t *p = ptr;
+    p[0] = v;
+    p[1] = v >> 8;
+#endif
+}
+
+static inline void stl_le_p(void *ptr, int v)
+{
+#ifdef _ARCH_PPC
+    __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
+#else
+    uint8_t *p = ptr;
+    p[0] = v;
+    p[1] = v >> 8;
+    p[2] = v >> 16;
+    p[3] = v >> 24;
+#endif
+}
+
+static inline void stq_le_p(void *ptr, uint64_t v)
+{
+    uint8_t *p = ptr;
+    stl_le_p(p, (uint32_t)v);
+    stl_le_p(p + 4, v >> 32);
+}
+
+/* float access */
+
+static inline float32 ldfl_le_p(const void *ptr)
+{
+    union {
+        float32 f;
+        uint32_t i;
+    } u;
+    u.i = ldl_le_p(ptr);
+    return u.f;
+}
+
+static inline void stfl_le_p(void *ptr, float32 v)
+{
+    union {
+        float32 f;
+        uint32_t i;
+    } u;
+    u.f = v;
+    stl_le_p(ptr, u.i);
+}
+
+static inline float64 ldfq_le_p(const void *ptr)
+{
+    CPU_DoubleU u;
+    u.l.lower = ldl_le_p(ptr);
+    u.l.upper = ldl_le_p(ptr + 4);
+    return u.d;
+}
+
+static inline void stfq_le_p(void *ptr, float64 v)
+{
+    CPU_DoubleU u;
+    u.d = v;
+    stl_le_p(ptr, u.l.lower);
+    stl_le_p(ptr + 4, u.l.upper);
+}
+
+#else
+
+static inline int lduw_le_p(const void *ptr)
+{
+    return *(uint16_t *)ptr;
+}
+
+static inline int ldsw_le_p(const void *ptr)
+{
+    return *(int16_t *)ptr;
+}
+
+static inline int ldl_le_p(const void *ptr)
+{
+    return *(uint32_t *)ptr;
+}
+
+static inline uint64_t ldq_le_p(const void *ptr)
+{
+    return *(uint64_t *)ptr;
+}
+
+static inline void stw_le_p(void *ptr, int v)
+{
+    *(uint16_t *)ptr = v;
+}
+
+static inline void stl_le_p(void *ptr, int v)
+{
+    *(uint32_t *)ptr = v;
+}
+
+static inline void stq_le_p(void *ptr, uint64_t v)
+{
+    *(uint64_t *)ptr = v;
+}
+
+/* float access */
+
+static inline float32 ldfl_le_p(const void *ptr)
+{
+    return *(float32 *)ptr;
+}
+
+static inline float64 ldfq_le_p(const void *ptr)
+{
+    return *(float64 *)ptr;
+}
+
+static inline void stfl_le_p(void *ptr, float32 v)
+{
+    *(float32 *)ptr = v;
+}
+
+static inline void stfq_le_p(void *ptr, float64 v)
+{
+    *(float64 *)ptr = v;
+}
+#endif
+
+#if !defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
+
+static inline int lduw_be_p(const void *ptr)
+{
+#if defined(__i386__)
+    int val;
+    asm volatile ("movzwl %1, %0\n"
+                  "xchgb %b0, %h0\n"
+                  : "=q" (val)
+                  : "m" (*(uint16_t *)ptr));
+    return val;
+#else
+    const uint8_t *b = ptr;
+    return ((b[0] << 8) | b[1]);
+#endif
+}
+
+static inline int ldsw_be_p(const void *ptr)
+{
+#if defined(__i386__)
+    int val;
+    asm volatile ("movzwl %1, %0\n"
+                  "xchgb %b0, %h0\n"
+                  : "=q" (val)
+                  : "m" (*(uint16_t *)ptr));
+    return (int16_t)val;
+#else
+    const uint8_t *b = ptr;
+    return (int16_t)((b[0] << 8) | b[1]);
+#endif
+}
+
+static inline int ldl_be_p(const void *ptr)
+{
+#if defined(__i386__) || defined(__x86_64__)
+    int val;
+    asm volatile ("movl %1, %0\n"
+                  "bswap %0\n"
+                  : "=r" (val)
+                  : "m" (*(uint32_t *)ptr));
+    return val;
+#else
+    const uint8_t *b = ptr;
+    return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
+#endif
+}
+
+static inline uint64_t ldq_be_p(const void *ptr)
+{
+    uint32_t a,b;
+    a = ldl_be_p(ptr);
+    b = ldl_be_p((uint8_t *)ptr + 4);
+    return (((uint64_t)a<<32)|b);
+}
+
+static inline void stw_be_p(void *ptr, int v)
+{
+#if defined(__i386__)
+    asm volatile ("xchgb %b0, %h0\n"
+                  "movw %w0, %1\n"
+                  : "=q" (v)
+                  : "m" (*(uint16_t *)ptr), "0" (v));
+#else
+    uint8_t *d = (uint8_t *) ptr;
+    d[0] = v >> 8;
+    d[1] = v;
+#endif
+}
+
+static inline void stl_be_p(void *ptr, int v)
+{
+#if defined(__i386__) || defined(__x86_64__)
+    asm volatile ("bswap %0\n"
+                  "movl %0, %1\n"
+                  : "=r" (v)
+                  : "m" (*(uint32_t *)ptr), "0" (v));
+#else
+    uint8_t *d = (uint8_t *) ptr;
+    d[0] = v >> 24;
+    d[1] = v >> 16;
+    d[2] = v >> 8;
+    d[3] = v;
+#endif
+}
+
+static inline void stq_be_p(void *ptr, uint64_t v)
+{
+    stl_be_p(ptr, v >> 32);
+    stl_be_p((uint8_t *)ptr + 4, v);
+}
+
+/* float access */
+
+static inline float32 ldfl_be_p(const void *ptr)
+{
+    union {
+        float32 f;
+        uint32_t i;
+    } u;
+    u.i = ldl_be_p(ptr);
+    return u.f;
+}
+
+static inline void stfl_be_p(void *ptr, float32 v)
+{
+    union {
+        float32 f;
+        uint32_t i;
+    } u;
+    u.f = v;
+    stl_be_p(ptr, u.i);
+}
+
+static inline float64 ldfq_be_p(const void *ptr)
+{
+    CPU_DoubleU u;
+    u.l.upper = ldl_be_p(ptr);
+    u.l.lower = ldl_be_p((uint8_t *)ptr + 4);
+    return u.d;
+}
+
+static inline void stfq_be_p(void *ptr, float64 v)
+{
+    CPU_DoubleU u;
+    u.d = v;
+    stl_be_p(ptr, u.l.upper);
+    stl_be_p((uint8_t *)ptr + 4, u.l.lower);
+}
+
+#else
+
+static inline int lduw_be_p(const void *ptr)
+{
+    return *(uint16_t *)ptr;
+}
+
+static inline int ldsw_be_p(const void *ptr)
+{
+    return *(int16_t *)ptr;
+}
+
+static inline int ldl_be_p(const void *ptr)
+{
+    return *(uint32_t *)ptr;
+}
+
+static inline uint64_t ldq_be_p(const void *ptr)
+{
+    return *(uint64_t *)ptr;
+}
+
+static inline void stw_be_p(void *ptr, int v)
+{
+    *(uint16_t *)ptr = v;
+}
+
+static inline void stl_be_p(void *ptr, int v)
+{
+    *(uint32_t *)ptr = v;
+}
+
+static inline void stq_be_p(void *ptr, uint64_t v)
+{
+    *(uint64_t *)ptr = v;
+}
+
+/* float access */
+
+static inline float32 ldfl_be_p(const void *ptr)
+{
+    return *(float32 *)ptr;
+}
+
+static inline float64 ldfq_be_p(const void *ptr)
+{
+    return *(float64 *)ptr;
+}
+
+static inline void stfl_be_p(void *ptr, float32 v)
+{
+    *(float32 *)ptr = v;
+}
+
+static inline void stfq_be_p(void *ptr, float64 v)
+{
+    *(float64 *)ptr = v;
+}
+
+#endif
+
 #endif /* BSWAP_H */
index 38e3724f3371bf398c5a596bdd088b7aacb82cc4..0c67a4abd9dab5a87add368c7395ca016b0fefd7 100755 (executable)
--- a/configure
+++ b/configure
@@ -113,7 +113,6 @@ curl=""
 curses=""
 docs=""
 fdt=""
-kvm=""
 nptl=""
 sdl=""
 vnc="yes"
@@ -129,9 +128,10 @@ xen=""
 xen_ctrl_version=""
 linux_aio=""
 attr=""
-vhost_net=""
 xfs=""
 
+vhost_net="no"
+kvm="no"
 gprof="no"
 debug_tcg="no"
 debug_mon="no"
@@ -146,6 +146,7 @@ datadir="\${prefix}/share/qemu"
 docdir="\${prefix}/share/doc/qemu"
 bindir="\${prefix}/bin"
 libdir="\${prefix}/lib"
+includedir="\${prefix}/include"
 sysconfdir="\${prefix}/etc"
 confsuffix="/qemu"
 slirp="yes"
@@ -179,6 +180,8 @@ smartcard=""
 smartcard_nss=""
 usb_redir=""
 opengl=""
+zlib="yes"
+guest_agent="yes"
 
 # parse CC options first
 for opt do
@@ -217,14 +220,14 @@ done
 # Using uname is really, really broken.  Once we have the right set of checks
 # we can eliminate it's usage altogether
 
-cc="${cross_prefix}${CC-gcc}"
-ar="${cross_prefix}${AR-ar}"
-objcopy="${cross_prefix}${OBJCOPY-objcopy}"
-ld="${cross_prefix}${LD-ld}"
-strip="${cross_prefix}${STRIP-strip}"
-windres="${cross_prefix}${WINDRES-windres}"
-pkg_config="${cross_prefix}${PKG_CONFIG-pkg-config}"
-sdl_config="${cross_prefix}${SDL_CONFIG-sdl-config}"
+cc="${CC-${cross_prefix}gcc}"
+ar="${AR-${cross_prefix}ar}"
+objcopy="${OBJCOPY-${cross_prefix}objcopy}"
+ld="${LD-${cross_prefix}ld}"
+strip="${STRIP-${cross_prefix}strip}"
+windres="${WINDRES-${cross_prefix}windres}"
+pkg_config="${PKG_CONFIG-${cross_prefix}pkg-config}"
+sdl_config="${SDL_CONFIG-${cross_prefix}sdl-config}"
 
 # default flags for all hosts
 QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS"
@@ -233,7 +236,7 @@ QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
 QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
 QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
 QEMU_CFLAGS="-D_FORTIFY_SOURCE=2 $QEMU_CFLAGS"
-QEMU_INCLUDES="-I. -I\$(SRC_PATH)"
+QEMU_INCLUDES="-I. -I\$(SRC_PATH) -I\$(SRC_PATH)/fpu"
 LDFLAGS="-g $LDFLAGS"
 
 # make source path absolute
@@ -543,6 +546,8 @@ for opt do
   ;;
   --libdir=*) libdir="$optarg"
   ;;
+  --includedir=*) includedir="$optarg"
+  ;;
   --datadir=*) datadir="$optarg"
   ;;
   --docdir=*) docdir="$optarg"
@@ -751,6 +756,12 @@ for opt do
   ;;
   --enable-usb-redir) usb_redir="yes"
   ;;
+  --disable-zlib-test) zlib="no"
+  ;;
+  --enable-guest-agent) guest_agent="yes"
+  ;;
+  --disable-guest-agent) guest_agent="no"
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -840,7 +851,6 @@ if [ "$softmmu" = "yes" ] ; then
     default_target_list="\
 i386-softmmu \
 x86_64-softmmu \
-alpha-softmmu \
 arm-softmmu \
 cris-softmmu \
 lm32-softmmu \
@@ -1029,6 +1039,8 @@ echo "  --disable-smartcard-nss  disable smartcard nss support"
 echo "  --enable-smartcard-nss   enable smartcard nss support"
 echo "  --disable-usb-redir      disable usb network redirection support"
 echo "  --enable-usb-redir       enable usb network redirection support"
+echo "  --disable-guest-agent    disable building of the QEMU Guest Agent"
+echo "  --enable-guest-agent     enable building of the QEMU Guest Agent"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -1088,11 +1100,13 @@ if test "$solaris" = "yes" ; then
   fi
 fi
 
-if has $python; then
-  :
-else
-  echo "Python not found. Use --python=/path/to/python"
-  exit 1
+if test "$guest_agent" != "no" ; then
+  if has $python; then
+    :
+  else
+    echo "Python not found. Use --python=/path/to/python"
+    exit 1
+  fi
 fi
 
 if test -z "$target_list" ; then
@@ -1190,18 +1204,20 @@ fi
 ##########################################
 # zlib check
 
-cat > $TMPC << EOF
+if test "$zlib" != "no" ; then
+    cat > $TMPC << EOF
 #include <zlib.h>
 int main(void) { zlibVersion(); return 0; }
 EOF
-if compile_prog "" "-lz" ; then
-    :
-else
-    echo
-    echo "Error: zlib check failed"
-    echo "Make sure to have the zlib libs and headers installed."
-    echo
-    exit 1
+    if compile_prog "" "-lz" ; then
+        :
+    else
+        echo
+        echo "Error: zlib check failed"
+        echo "Make sure to have the zlib libs and headers installed."
+        echo
+        exit 1
+    fi
 fi
 
 ##########################################
@@ -1505,11 +1521,17 @@ int main(void) {
     return 0;
 }
 EOF
+  if $pkg_config libpng --modversion >/dev/null 2>&1; then
+    vnc_png_cflags=`$pkg_config libpng --cflags 2> /dev/null`
+    vnc_png_libs=`$pkg_config libpng --libs 2> /dev/null`
+  else
     vnc_png_cflags=""
     vnc_png_libs="-lpng"
+  fi
   if compile_prog "$vnc_png_cflags" "$vnc_png_libs" ; then
     vnc_png=yes
     libs_softmmu="$vnc_png_libs $libs_softmmu"
+    QEMU_CFLAGS="$QEMU_CFLAGS $vnc_png_cflags"
   else
     if test "$vnc_png" = "yes" ; then
       feature_not_found "vnc-png"
@@ -1822,14 +1844,16 @@ fi
 
 ##########################################
 # glib support probe
-if $pkg_config --modversion glib-2.0 > /dev/null 2>&1 ; then
-    glib_cflags=`$pkg_config --cflags glib-2.0 2>/dev/null`
-    glib_libs=`$pkg_config --libs glib-2.0 2>/dev/null`
-    libs_softmmu="$glib_libs $libs_softmmu"
-    libs_tools="$glib_libs $libs_tools"
-else
-    echo "glib-2.0 required to compile QEMU"
-    exit 1
+if test "$guest_agent" != "no" ; then
+    if $pkg_config --modversion glib-2.0 > /dev/null 2>&1 ; then
+        glib_cflags=`$pkg_config --cflags glib-2.0 2>/dev/null`
+        glib_libs=`$pkg_config --libs glib-2.0 2>/dev/null`
+        libs_softmmu="$glib_libs $libs_softmmu"
+        libs_tools="$glib_libs $libs_tools"
+    else
+        echo "glib-2.0 required to compile QEMU"
+        exit 1
+    fi
 fi
 
 ##########################################
@@ -2509,6 +2533,43 @@ if test "$trace_backend" = "dtrace"; then
   fi
 fi
 
+##########################################
+# __sync_fetch_and_and requires at least -march=i486. Many toolchains
+# use i686 as default anyway, but for those that don't, an explicit
+# specification is necessary
+if test "$vhost_net" = "yes" && test "$cpu" = "i386"; then
+  cat > $TMPC << EOF
+int sfaa(unsigned *ptr)
+{
+  return __sync_fetch_and_and(ptr, 0);
+}
+
+int main(int argc, char **argv)
+{
+  int val = 42;
+  sfaa(&val);
+  return val;
+}
+EOF
+  if ! compile_prog "" "" ; then
+    CFLAGS+="-march=i486"
+  fi
+fi
+
+##########################################
+# check if we have makecontext
+
+ucontext_coroutine=no
+if test "$darwin" != "yes"; then
+  cat > $TMPC << EOF
+#include <ucontext.h>
+int main(void) { makecontext(0, 0, 0); }
+EOF
+  if compile_prog "" "" ; then
+      ucontext_coroutine=yes
+  fi
+fi
+
 ##########################################
 # End of CC checks
 # After here, no more $cc or $ld runs
@@ -2566,7 +2627,9 @@ if test "$softmmu" = yes ; then
   tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
   if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
       tools="qemu-nbd\$(EXESUF) $tools"
+    if [ "$guest_agent" = "yes" ]; then
       tools="qemu-ga\$(EXESUF) $tools"
+    fi
     if [ "$check_utests" = "yes" ]; then
       tools="check-qint check-qstring check-qdict check-qlist $tools"
       tools="check-qfloat check-qjson $tools"
@@ -2589,6 +2652,7 @@ echo "Install prefix    $prefix"
 echo "BIOS directory    `eval echo $datadir`"
 echo "binary directory  `eval echo $bindir`"
 echo "library directory `eval echo $libdir`"
+echo "include directory `eval echo $includedir`"
 echo "config directory  `eval echo $sysconfdir`"
 if test "$mingw32" = "no" ; then
 echo "Manual directory  `eval echo $mandir`"
@@ -2667,8 +2731,9 @@ echo "xfsctl support    $xfs"
 echo "nss used          $smartcard_nss"
 echo "usb net redir     $usb_redir"
 echo "OpenGL support    $opengl"
+echo "build guest agent $guest_agent"
 
-if test $sdl_too_old = "yes"; then
+if test "$sdl_too_old" = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
 fi
 
@@ -2684,6 +2749,7 @@ echo all: >> $config_host_mak
 echo "prefix=$prefix" >> $config_host_mak
 echo "bindir=$bindir" >> $config_host_mak
 echo "libdir=$libdir" >> $config_host_mak
+echo "includedir=$includedir" >> $config_host_mak
 echo "mandir=$mandir" >> $config_host_mak
 echo "datadir=$datadir" >> $config_host_mak
 echo "sysconfdir=$sysconfdir" >> $config_host_mak
@@ -2755,7 +2821,7 @@ fi
 if test "$static" = "yes" ; then
   echo "CONFIG_STATIC=y" >> $config_host_mak
 fi
-if test $profiler = "yes" ; then
+if test "$profiler" = "yes" ; then
   echo "CONFIG_PROFILER=y" >> $config_host_mak
 fi
 if test "$slirp" = "yes" ; then
@@ -2982,6 +3048,10 @@ if test "$rbd" = "yes" ; then
   echo "CONFIG_RBD=y" >> $config_host_mak
 fi
 
+if test "$ucontext_coroutine" = "yes" ; then
+  echo "CONFIG_UCONTEXT_COROUTINE=y" >> $config_host_mak
+fi
+
 # USB host support
 case "$usb" in
 linux)
@@ -3290,10 +3360,12 @@ case "$target_arch2" in
     if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
       target_phys_bits=64
       echo "CONFIG_XEN=y" >> $config_target_mak
-      if test "$cpu" = "i386" -o "$cpu" = "x86_64"; then
-          echo "CONFIG_XEN_MAPCACHE=y" >> $config_target_mak
-      fi
+    else
+      echo "CONFIG_NO_XEN=y" >> $config_target_mak
     fi
+    ;;
+  *)
+    echo "CONFIG_NO_XEN=y" >> $config_target_mak
 esac
 case "$target_arch2" in
   i386|x86_64|ppcemb|ppc|ppc64|s390x)
@@ -3307,7 +3379,7 @@ case "$target_arch2" in
       \( "$target_arch2" = "x86_64" -a "$cpu" = "i386"   \) -o \
       \( "$target_arch2" = "i386"   -a "$cpu" = "x86_64" \) \) ; then
       echo "CONFIG_KVM=y" >> $config_target_mak
-      if test $vhost_net = "yes" ; then
+      if test "$vhost_net" = "yes" ; then
         echo "CONFIG_VHOST_NET=y" >> $config_target_mak
       fi
     fi
@@ -3374,7 +3446,6 @@ else
   includes="-I\$(SRC_PATH)/tcg/\$(ARCH) $includes"
 fi
 includes="-I\$(SRC_PATH)/tcg $includes"
-includes="-I\$(SRC_PATH)/fpu $includes"
 
 if test "$target_user_only" = "yes" ; then
     libdis_config_mak=libdis-user/config.mak
diff --git a/coroutine-gthread.c b/coroutine-gthread.c
new file mode 100644 (file)
index 0000000..f09877e
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * GThread coroutine initialization code
+ *
+ * Copyright (C) 2006  Anthony Liguori <anthony@codemonkey.ws>
+ * Copyright (C) 2011  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.0 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include "qemu-common.h"
+#include "qemu-coroutine-int.h"
+
+typedef struct {
+    Coroutine base;
+    GThread *thread;
+    bool runnable;
+    CoroutineAction action;
+} CoroutineGThread;
+
+static GCond *coroutine_cond;
+static GStaticMutex coroutine_lock = G_STATIC_MUTEX_INIT;
+static GStaticPrivate coroutine_key = G_STATIC_PRIVATE_INIT;
+
+static void __attribute__((constructor)) coroutine_init(void)
+{
+    if (!g_thread_supported()) {
+        g_thread_init(NULL);
+    }
+
+    coroutine_cond = g_cond_new();
+}
+
+static void coroutine_wait_runnable_locked(CoroutineGThread *co)
+{
+    while (!co->runnable) {
+        g_cond_wait(coroutine_cond, g_static_mutex_get_mutex(&coroutine_lock));
+    }
+}
+
+static void coroutine_wait_runnable(CoroutineGThread *co)
+{
+    g_static_mutex_lock(&coroutine_lock);
+    coroutine_wait_runnable_locked(co);
+    g_static_mutex_unlock(&coroutine_lock);
+}
+
+static gpointer coroutine_thread(gpointer opaque)
+{
+    CoroutineGThread *co = opaque;
+
+    g_static_private_set(&coroutine_key, co, NULL);
+    coroutine_wait_runnable(co);
+    co->base.entry(co->base.entry_arg);
+    qemu_coroutine_switch(&co->base, co->base.caller, COROUTINE_TERMINATE);
+    return NULL;
+}
+
+Coroutine *qemu_coroutine_new(void)
+{
+    CoroutineGThread *co;
+
+    co = qemu_mallocz(sizeof(*co));
+    co->thread = g_thread_create_full(coroutine_thread, co, 0, TRUE, TRUE,
+                                      G_THREAD_PRIORITY_NORMAL, NULL);
+    if (!co->thread) {
+        qemu_free(co);
+        return NULL;
+    }
+    return &co->base;
+}
+
+void qemu_coroutine_delete(Coroutine *co_)
+{
+    CoroutineGThread *co = DO_UPCAST(CoroutineGThread, base, co_);
+
+    g_thread_join(co->thread);
+    qemu_free(co);
+}
+
+CoroutineAction qemu_coroutine_switch(Coroutine *from_,
+                                      Coroutine *to_,
+                                      CoroutineAction action)
+{
+    CoroutineGThread *from = DO_UPCAST(CoroutineGThread, base, from_);
+    CoroutineGThread *to = DO_UPCAST(CoroutineGThread, base, to_);
+
+    g_static_mutex_lock(&coroutine_lock);
+    from->runnable = false;
+    from->action = action;
+    to->runnable = true;
+    to->action = action;
+    g_cond_broadcast(coroutine_cond);
+
+    if (action != COROUTINE_TERMINATE) {
+        coroutine_wait_runnable_locked(from);
+    }
+    g_static_mutex_unlock(&coroutine_lock);
+    return from->action;
+}
+
+Coroutine *qemu_coroutine_self(void)
+{
+    CoroutineGThread *co = g_static_private_get(&coroutine_key);
+
+    if (!co) {
+        co = qemu_mallocz(sizeof(*co));
+        co->runnable = true;
+        g_static_private_set(&coroutine_key, co, (GDestroyNotify)qemu_free);
+    }
+
+    return &co->base;
+}
+
+bool qemu_in_coroutine(void)
+{
+    CoroutineGThread *co = g_static_private_get(&coroutine_key);
+
+    return co && co->base.caller;
+}
diff --git a/coroutine-ucontext.c b/coroutine-ucontext.c
new file mode 100644 (file)
index 0000000..42dc3e2
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * ucontext coroutine initialization code
+ *
+ * Copyright (C) 2006  Anthony Liguori <anthony@codemonkey.ws>
+ * Copyright (C) 2011  Kevin Wolf <kwolf@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.0 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* XXX Is there a nicer way to disable glibc's stack check for longjmp? */
+#ifdef _FORTIFY_SOURCE
+#undef _FORTIFY_SOURCE
+#endif
+#include <stdlib.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <pthread.h>
+#include <ucontext.h>
+#include "qemu-common.h"
+#include "qemu-coroutine-int.h"
+
+enum {
+    /* Maximum free pool size prevents holding too many freed coroutines */
+    POOL_MAX_SIZE = 64,
+};
+
+typedef struct {
+    Coroutine base;
+    void *stack;
+    jmp_buf env;
+} CoroutineUContext;
+
+/**
+ * Per-thread coroutine bookkeeping
+ */
+typedef struct {
+    /** Currently executing coroutine */
+    Coroutine *current;
+
+    /** Free list to speed up creation */
+    QLIST_HEAD(, Coroutine) pool;
+    unsigned int pool_size;
+
+    /** The default coroutine */
+    CoroutineUContext leader;
+} CoroutineThreadState;
+
+static pthread_key_t thread_state_key;
+
+/*
+ * va_args to makecontext() must be type 'int', so passing
+ * the pointer we need may require several int args. This
+ * union is a quick hack to let us do that
+ */
+union cc_arg {
+    void *p;
+    int i[2];
+};
+
+static CoroutineThreadState *coroutine_get_thread_state(void)
+{
+    CoroutineThreadState *s = pthread_getspecific(thread_state_key);
+
+    if (!s) {
+        s = qemu_mallocz(sizeof(*s));
+        s->current = &s->leader.base;
+        QLIST_INIT(&s->pool);
+        pthread_setspecific(thread_state_key, s);
+    }
+    return s;
+}
+
+static void qemu_coroutine_thread_cleanup(void *opaque)
+{
+    CoroutineThreadState *s = opaque;
+    Coroutine *co;
+    Coroutine *tmp;
+
+    QLIST_FOREACH_SAFE(co, &s->pool, pool_next, tmp) {
+        qemu_free(DO_UPCAST(CoroutineUContext, base, co)->stack);
+        qemu_free(co);
+    }
+    qemu_free(s);
+}
+
+static void __attribute__((constructor)) coroutine_init(void)
+{
+    int ret;
+
+    ret = pthread_key_create(&thread_state_key, qemu_coroutine_thread_cleanup);
+    if (ret != 0) {
+        fprintf(stderr, "unable to create leader key: %s\n", strerror(errno));
+        abort();
+    }
+}
+
+static void coroutine_trampoline(int i0, int i1)
+{
+    union cc_arg arg;
+    CoroutineUContext *self;
+    Coroutine *co;
+
+    arg.i[0] = i0;
+    arg.i[1] = i1;
+    self = arg.p;
+    co = &self->base;
+
+    /* Initialize longjmp environment and switch back the caller */
+    if (!setjmp(self->env)) {
+        longjmp(*(jmp_buf *)co->entry_arg, 1);
+    }
+
+    while (true) {
+        co->entry(co->entry_arg);
+        qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE);
+    }
+}
+
+static Coroutine *coroutine_new(void)
+{
+    const size_t stack_size = 1 << 20;
+    CoroutineUContext *co;
+    ucontext_t old_uc, uc;
+    jmp_buf old_env;
+    union cc_arg arg = {0};
+
+    /* The ucontext functions preserve signal masks which incurs a system call
+     * overhead.  setjmp()/longjmp() does not preserve signal masks but only
+     * works on the current stack.  Since we need a way to create and switch to
+     * a new stack, use the ucontext functions for that but setjmp()/longjmp()
+     * for everything else.
+     */
+
+    if (getcontext(&uc) == -1) {
+        abort();
+    }
+
+    co = qemu_mallocz(sizeof(*co));
+    co->stack = qemu_malloc(stack_size);
+    co->base.entry_arg = &old_env; /* stash away our jmp_buf */
+
+    uc.uc_link = &old_uc;
+    uc.uc_stack.ss_sp = co->stack;
+    uc.uc_stack.ss_size = stack_size;
+    uc.uc_stack.ss_flags = 0;
+
+    arg.p = co;
+
+    makecontext(&uc, (void (*)(void))coroutine_trampoline,
+                2, arg.i[0], arg.i[1]);
+
+    /* swapcontext() in, longjmp() back out */
+    if (!setjmp(old_env)) {
+        swapcontext(&old_uc, &uc);
+    }
+    return &co->base;
+}
+
+Coroutine *qemu_coroutine_new(void)
+{
+    CoroutineThreadState *s = coroutine_get_thread_state();
+    Coroutine *co;
+
+    co = QLIST_FIRST(&s->pool);
+    if (co) {
+        QLIST_REMOVE(co, pool_next);
+        s->pool_size--;
+    } else {
+        co = coroutine_new();
+    }
+    return co;
+}
+
+void qemu_coroutine_delete(Coroutine *co_)
+{
+    CoroutineThreadState *s = coroutine_get_thread_state();
+    CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
+
+    if (s->pool_size < POOL_MAX_SIZE) {
+        QLIST_INSERT_HEAD(&s->pool, &co->base, pool_next);
+        co->base.caller = NULL;
+        s->pool_size++;
+        return;
+    }
+
+    qemu_free(co->stack);
+    qemu_free(co);
+}
+
+CoroutineAction qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
+                                      CoroutineAction action)
+{
+    CoroutineUContext *from = DO_UPCAST(CoroutineUContext, base, from_);
+    CoroutineUContext *to = DO_UPCAST(CoroutineUContext, base, to_);
+    CoroutineThreadState *s = coroutine_get_thread_state();
+    int ret;
+
+    s->current = to_;
+
+    ret = setjmp(from->env);
+    if (ret == 0) {
+        longjmp(to->env, action);
+    }
+    return ret;
+}
+
+Coroutine *qemu_coroutine_self(void)
+{
+    CoroutineThreadState *s = coroutine_get_thread_state();
+
+    return s->current;
+}
+
+bool qemu_in_coroutine(void)
+{
+    CoroutineThreadState *s = pthread_getspecific(thread_state_key);
+
+    return s && s->current->caller;
+}
diff --git a/coroutine-win32.c b/coroutine-win32.c
new file mode 100644 (file)
index 0000000..0e29448
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Win32 coroutine initialization code
+ *
+ * Copyright (c) 2011 Kevin Wolf <kwolf@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "qemu-coroutine-int.h"
+
+typedef struct
+{
+    Coroutine base;
+
+    LPVOID fiber;
+    CoroutineAction action;
+} CoroutineWin32;
+
+static __thread CoroutineWin32 leader;
+static __thread Coroutine *current;
+
+CoroutineAction qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
+                                      CoroutineAction action)
+{
+    CoroutineWin32 *from = DO_UPCAST(CoroutineWin32, base, from_);
+    CoroutineWin32 *to = DO_UPCAST(CoroutineWin32, base, to_);
+
+    current = to_;
+
+    to->action = action;
+    SwitchToFiber(to->fiber);
+    return from->action;
+}
+
+static void CALLBACK coroutine_trampoline(void *co_)
+{
+    Coroutine *co = co_;
+
+    while (true) {
+        co->entry(co->entry_arg);
+        qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE);
+    }
+}
+
+Coroutine *qemu_coroutine_new(void)
+{
+    const size_t stack_size = 1 << 20;
+    CoroutineWin32 *co;
+
+    co = qemu_mallocz(sizeof(*co));
+    co->fiber = CreateFiber(stack_size, coroutine_trampoline, &co->base);
+    return &co->base;
+}
+
+void qemu_coroutine_delete(Coroutine *co_)
+{
+    CoroutineWin32 *co = DO_UPCAST(CoroutineWin32, base, co_);
+
+    DeleteFiber(co->fiber);
+    qemu_free(co);
+}
+
+Coroutine *qemu_coroutine_self(void)
+{
+    if (!current) {
+        current = &leader.base;
+        leader.fiber = ConvertThreadToFiber(NULL);
+    }
+    return current;
+}
+
+bool qemu_in_coroutine(void)
+{
+    return current && current->caller;
+}
index e8391009a36e4de3accd1ac2feb0a2ac28cb18de..fa0205c28fe629c65813e31aa52faf4e52bb49de 100644 (file)
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -35,8 +35,6 @@
  * TARGET_WORDS_BIGENDIAN : same for target cpu
  */
 
-#include "softfloat.h"
-
 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
 #define BSWAP_NEEDED
 #endif
@@ -114,64 +112,6 @@ static inline void tswap64s(uint64_t *s)
 #define bswaptls(s) bswap64s(s)
 #endif
 
-typedef union {
-    float32 f;
-    uint32_t l;
-} CPU_FloatU;
-
-/* NOTE: arm FPA is horrible as double 32 bit words are stored in big
-   endian ! */
-typedef union {
-    float64 d;
-#if defined(HOST_WORDS_BIGENDIAN)
-    struct {
-        uint32_t upper;
-        uint32_t lower;
-    } l;
-#else
-    struct {
-        uint32_t lower;
-        uint32_t upper;
-    } l;
-#endif
-    uint64_t ll;
-} CPU_DoubleU;
-
-typedef union {
-     floatx80 d;
-     struct {
-         uint64_t lower;
-         uint16_t upper;
-     } l;
-} CPU_LDoubleU;
-
-typedef union {
-    float128 q;
-#if defined(HOST_WORDS_BIGENDIAN)
-    struct {
-        uint32_t upmost;
-        uint32_t upper;
-        uint32_t lower;
-        uint32_t lowest;
-    } l;
-    struct {
-        uint64_t upper;
-        uint64_t lower;
-    } ll;
-#else
-    struct {
-        uint32_t lowest;
-        uint32_t lower;
-        uint32_t upper;
-        uint32_t upmost;
-    } l;
-    struct {
-        uint64_t lower;
-        uint64_t upper;
-    } ll;
-#endif
-} CPU_QuadU;
-
 /* CPU memory access without any memory or io remapping */
 
 /*
@@ -207,392 +147,8 @@ typedef union {
  *   user   : user mode access using soft MMU
  *   kernel : kernel mode access using soft MMU
  */
-static inline int ldub_p(const void *ptr)
-{
-    return *(uint8_t *)ptr;
-}
-
-static inline int ldsb_p(const void *ptr)
-{
-    return *(int8_t *)ptr;
-}
-
-static inline void stb_p(void *ptr, int v)
-{
-    *(uint8_t *)ptr = v;
-}
-
-/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
-   kernel handles unaligned load/stores may give better results, but
-   it is a system wide setting : bad */
-#if defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
-
-/* conservative code for little endian unaligned accesses */
-static inline int lduw_le_p(const void *ptr)
-{
-#ifdef _ARCH_PPC
-    int val;
-    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
-    return val;
-#else
-    const uint8_t *p = ptr;
-    return p[0] | (p[1] << 8);
-#endif
-}
-
-static inline int ldsw_le_p(const void *ptr)
-{
-#ifdef _ARCH_PPC
-    int val;
-    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
-    return (int16_t)val;
-#else
-    const uint8_t *p = ptr;
-    return (int16_t)(p[0] | (p[1] << 8));
-#endif
-}
-
-static inline int ldl_le_p(const void *ptr)
-{
-#ifdef _ARCH_PPC
-    int val;
-    __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
-    return val;
-#else
-    const uint8_t *p = ptr;
-    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-#endif
-}
-
-static inline uint64_t ldq_le_p(const void *ptr)
-{
-    const uint8_t *p = ptr;
-    uint32_t v1, v2;
-    v1 = ldl_le_p(p);
-    v2 = ldl_le_p(p + 4);
-    return v1 | ((uint64_t)v2 << 32);
-}
-
-static inline void stw_le_p(void *ptr, int v)
-{
-#ifdef _ARCH_PPC
-    __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
-#else
-    uint8_t *p = ptr;
-    p[0] = v;
-    p[1] = v >> 8;
-#endif
-}
-
-static inline void stl_le_p(void *ptr, int v)
-{
-#ifdef _ARCH_PPC
-    __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
-#else
-    uint8_t *p = ptr;
-    p[0] = v;
-    p[1] = v >> 8;
-    p[2] = v >> 16;
-    p[3] = v >> 24;
-#endif
-}
-
-static inline void stq_le_p(void *ptr, uint64_t v)
-{
-    uint8_t *p = ptr;
-    stl_le_p(p, (uint32_t)v);
-    stl_le_p(p + 4, v >> 32);
-}
-
-/* float access */
-
-static inline float32 ldfl_le_p(const void *ptr)
-{
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
-    u.i = ldl_le_p(ptr);
-    return u.f;
-}
-
-static inline void stfl_le_p(void *ptr, float32 v)
-{
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
-    u.f = v;
-    stl_le_p(ptr, u.i);
-}
-
-static inline float64 ldfq_le_p(const void *ptr)
-{
-    CPU_DoubleU u;
-    u.l.lower = ldl_le_p(ptr);
-    u.l.upper = ldl_le_p(ptr + 4);
-    return u.d;
-}
-
-static inline void stfq_le_p(void *ptr, float64 v)
-{
-    CPU_DoubleU u;
-    u.d = v;
-    stl_le_p(ptr, u.l.lower);
-    stl_le_p(ptr + 4, u.l.upper);
-}
-
-#else
-
-static inline int lduw_le_p(const void *ptr)
-{
-    return *(uint16_t *)ptr;
-}
-
-static inline int ldsw_le_p(const void *ptr)
-{
-    return *(int16_t *)ptr;
-}
-
-static inline int ldl_le_p(const void *ptr)
-{
-    return *(uint32_t *)ptr;
-}
-
-static inline uint64_t ldq_le_p(const void *ptr)
-{
-    return *(uint64_t *)ptr;
-}
-
-static inline void stw_le_p(void *ptr, int v)
-{
-    *(uint16_t *)ptr = v;
-}
-
-static inline void stl_le_p(void *ptr, int v)
-{
-    *(uint32_t *)ptr = v;
-}
-
-static inline void stq_le_p(void *ptr, uint64_t v)
-{
-    *(uint64_t *)ptr = v;
-}
-
-/* float access */
-
-static inline float32 ldfl_le_p(const void *ptr)
-{
-    return *(float32 *)ptr;
-}
-
-static inline float64 ldfq_le_p(const void *ptr)
-{
-    return *(float64 *)ptr;
-}
-
-static inline void stfl_le_p(void *ptr, float32 v)
-{
-    *(float32 *)ptr = v;
-}
-
-static inline void stfq_le_p(void *ptr, float64 v)
-{
-    *(float64 *)ptr = v;
-}
-#endif
-
-#if !defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
-
-static inline int lduw_be_p(const void *ptr)
-{
-#if defined(__i386__)
-    int val;
-    asm volatile ("movzwl %1, %0\n"
-                  "xchgb %b0, %h0\n"
-                  : "=q" (val)
-                  : "m" (*(uint16_t *)ptr));
-    return val;
-#else
-    const uint8_t *b = ptr;
-    return ((b[0] << 8) | b[1]);
-#endif
-}
-
-static inline int ldsw_be_p(const void *ptr)
-{
-#if defined(__i386__)
-    int val;
-    asm volatile ("movzwl %1, %0\n"
-                  "xchgb %b0, %h0\n"
-                  : "=q" (val)
-                  : "m" (*(uint16_t *)ptr));
-    return (int16_t)val;
-#else
-    const uint8_t *b = ptr;
-    return (int16_t)((b[0] << 8) | b[1]);
-#endif
-}
-
-static inline int ldl_be_p(const void *ptr)
-{
-#if defined(__i386__) || defined(__x86_64__)
-    int val;
-    asm volatile ("movl %1, %0\n"
-                  "bswap %0\n"
-                  : "=r" (val)
-                  : "m" (*(uint32_t *)ptr));
-    return val;
-#else
-    const uint8_t *b = ptr;
-    return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
-#endif
-}
-
-static inline uint64_t ldq_be_p(const void *ptr)
-{
-    uint32_t a,b;
-    a = ldl_be_p(ptr);
-    b = ldl_be_p((uint8_t *)ptr + 4);
-    return (((uint64_t)a<<32)|b);
-}
-
-static inline void stw_be_p(void *ptr, int v)
-{
-#if defined(__i386__)
-    asm volatile ("xchgb %b0, %h0\n"
-                  "movw %w0, %1\n"
-                  : "=q" (v)
-                  : "m" (*(uint16_t *)ptr), "0" (v));
-#else
-    uint8_t *d = (uint8_t *) ptr;
-    d[0] = v >> 8;
-    d[1] = v;
-#endif
-}
-
-static inline void stl_be_p(void *ptr, int v)
-{
-#if defined(__i386__) || defined(__x86_64__)
-    asm volatile ("bswap %0\n"
-                  "movl %0, %1\n"
-                  : "=r" (v)
-                  : "m" (*(uint32_t *)ptr), "0" (v));
-#else
-    uint8_t *d = (uint8_t *) ptr;
-    d[0] = v >> 24;
-    d[1] = v >> 16;
-    d[2] = v >> 8;
-    d[3] = v;
-#endif
-}
-
-static inline void stq_be_p(void *ptr, uint64_t v)
-{
-    stl_be_p(ptr, v >> 32);
-    stl_be_p((uint8_t *)ptr + 4, v);
-}
-
-/* float access */
-
-static inline float32 ldfl_be_p(const void *ptr)
-{
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
-    u.i = ldl_be_p(ptr);
-    return u.f;
-}
-
-static inline void stfl_be_p(void *ptr, float32 v)
-{
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
-    u.f = v;
-    stl_be_p(ptr, u.i);
-}
-
-static inline float64 ldfq_be_p(const void *ptr)
-{
-    CPU_DoubleU u;
-    u.l.upper = ldl_be_p(ptr);
-    u.l.lower = ldl_be_p((uint8_t *)ptr + 4);
-    return u.d;
-}
-
-static inline void stfq_be_p(void *ptr, float64 v)
-{
-    CPU_DoubleU u;
-    u.d = v;
-    stl_be_p(ptr, u.l.upper);
-    stl_be_p((uint8_t *)ptr + 4, u.l.lower);
-}
-
-#else
-
-static inline int lduw_be_p(const void *ptr)
-{
-    return *(uint16_t *)ptr;
-}
-
-static inline int ldsw_be_p(const void *ptr)
-{
-    return *(int16_t *)ptr;
-}
-
-static inline int ldl_be_p(const void *ptr)
-{
-    return *(uint32_t *)ptr;
-}
-
-static inline uint64_t ldq_be_p(const void *ptr)
-{
-    return *(uint64_t *)ptr;
-}
-
-static inline void stw_be_p(void *ptr, int v)
-{
-    *(uint16_t *)ptr = v;
-}
-
-static inline void stl_be_p(void *ptr, int v)
-{
-    *(uint32_t *)ptr = v;
-}
-
-static inline void stq_be_p(void *ptr, uint64_t v)
-{
-    *(uint64_t *)ptr = v;
-}
-
-/* float access */
-
-static inline float32 ldfl_be_p(const void *ptr)
-{
-    return *(float32 *)ptr;
-}
-
-static inline float64 ldfq_be_p(const void *ptr)
-{
-    return *(float64 *)ptr;
-}
-
-static inline void stfl_be_p(void *ptr, float32 v)
-{
-    *(float32 *)ptr = v;
-}
-
-static inline void stfq_be_p(void *ptr, float64 v)
-{
-    *(float64 *)ptr = v;
-}
-
-#endif
 
-/* target CPU memory access functions */
+/* target-endianness CPU memory access functions */
 #if defined(TARGET_WORDS_BIGENDIAN)
 #define lduw_p(p) lduw_be_p(p)
 #define ldsw_p(p) ldsw_be_p(p)
index 44b04b383917e62b9791020d0e22fe962989351d..c9878ba4743f7ee8ece0de2aba2446eda24f1464 100644 (file)
@@ -3,10 +3,6 @@
 
 /* CPU interfaces that are target indpendent.  */
 
-#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__ia64__)
-#define WORDS_ALIGNED
-#endif
-
 #ifdef TARGET_PHYS_ADDR_BITS
 #include "targphys.h"
 #endif
@@ -27,7 +23,15 @@ enum device_endian {
 };
 
 /* address in the RAM (different from a physical address) */
+#if defined(CONFIG_XEN_BACKEND) && TARGET_PHYS_ADDR_BITS == 64
+typedef uint64_t ram_addr_t;
+#  define RAM_ADDR_MAX UINT64_MAX
+#  define RAM_ADDR_FMT "%" PRIx64
+#else
 typedef unsigned long ram_addr_t;
+#  define RAM_ADDR_MAX ULONG_MAX
+#  define RAM_ADDR_FMT "%lx"
+#endif
 
 /* memory API */
 
index f9a7e3689e04605beebabef940f280e1a8fca572..28049e06992b435cac494eb5e10d055b96456375 100644 (file)
--- a/cutils.c
+++ b/cutils.c
@@ -322,7 +322,8 @@ int fcntl_setfl(int fd, int flag)
  * value must be terminated by whitespace, ',' or '\0'. Return -1 on
  * error.
  */
-int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
+int64_t strtosz_suffix_unit(const char *nptr, char **end,
+                            const char default_suffix, int64_t unit)
 {
     int64_t retval = -1;
     char *endptr;
@@ -362,20 +363,20 @@ int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
         }
         break;
     case STRTOSZ_DEFSUFFIX_KB:
-        mul = 1 << 10;
+        mul = unit;
         break;
     case 0:
         if (mul_required) {
             goto fail;
         }
     case STRTOSZ_DEFSUFFIX_MB:
-        mul = 1ULL << 20;
+        mul = unit * unit;
         break;
     case STRTOSZ_DEFSUFFIX_GB:
-        mul = 1ULL << 30;
+        mul = unit * unit * unit;
         break;
     case STRTOSZ_DEFSUFFIX_TB:
-        mul = 1ULL << 40;
+        mul = unit * unit * unit * unit;
         break;
     default:
         goto fail;
@@ -405,6 +406,11 @@ fail:
     return retval;
 }
 
+int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
+{
+        return strtosz_suffix_unit(nptr, end, default_suffix, 1024);
+}
+
 int64_t strtosz(const char *nptr, char **end)
 {
     return strtosz_suffix(nptr, end, STRTOSZ_DEFSUFFIX_MB);
index 35196a12ccf36d999191f060fba40b7e89ac9129..1a881a0a6014a38b865791714184172e7b8c3627 100644 (file)
@@ -809,9 +809,6 @@ int main(int argc, char **argv)
             usage();
         }
     }
-    if (optind >= argc)
-        usage();
-    filename = argv[optind];
 
     /* init debug */
     cpu_set_log_filename(log_file);
@@ -830,6 +827,11 @@ int main(int argc, char **argv)
         cpu_set_log(mask);
     }
 
+    if (optind >= argc) {
+        usage();
+    }
+    filename = argv[optind];
+
     /* Zero out regs */
     memset(regs, 0, sizeof(struct target_pt_regs));
 
@@ -850,8 +852,8 @@ int main(int argc, char **argv)
 #error unsupported CPU
 #endif
     }
-    
-    cpu_exec_init_all(0);
+    tcg_exec_init(0);
+    cpu_exec_init_all();
     /* NOTE: we need to init the CPU at this stage to get
        qemu_host_page_size */
     env = cpu_init(cpu_model);
index e2adca3918aca91f3654bb90016e0a91b76fc406..c530227f1ca45b72fba74447f738ae5ef847431d 100644 (file)
@@ -319,7 +319,6 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
                        void *set, CPUState *env)
 {
        void *frame;
-       int i, err = 0;
 
     fprintf(stderr, "setup_frame %d\n", sig);
        frame = get_sigframe(ka, env, sizeof(*frame));
diff --git a/dma.h b/dma.h
index 3d8324bb54aa9c5cfc4d54456a10859c998ef64f..a6db5bacbb703bd081539625b3628d2afaa64510 100644 (file)
--- a/dma.h
+++ b/dma.h
@@ -20,12 +20,12 @@ typedef struct {
     target_phys_addr_t len;
 } ScatterGatherEntry;
 
-typedef struct {
+struct QEMUSGList {
     ScatterGatherEntry *sg;
     int nsg;
     int nalloc;
     target_phys_addr_t size;
-} QEMUSGList;
+};
 
 void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint);
 void qemu_sglist_add(QEMUSGList *qsg, target_phys_addr_t base,
diff --git a/docs/memory.txt b/docs/memory.txt
new file mode 100644 (file)
index 0000000..4460c06
--- /dev/null
@@ -0,0 +1,172 @@
+The memory API
+==============
+
+The memory API models the memory and I/O buses and controllers of a QEMU
+machine.  It attempts to allow modelling of:
+
+ - ordinary RAM
+ - memory-mapped I/O (MMIO)
+ - memory controllers that can dynamically reroute physical memory regions
+  to different destinations
+
+The memory model provides support for
+
+ - tracking RAM changes by the guest
+ - setting up coalesced memory for kvm
+ - setting up ioeventfd regions for kvm
+
+Memory is modelled as an tree (really acyclic graph) of MemoryRegion objects.
+The root of the tree is memory as seen from the CPU's viewpoint (the system
+bus).  Nodes in the tree represent other buses, memory controllers, and
+memory regions that have been rerouted.  Leaves are RAM and MMIO regions.
+
+Types of regions
+----------------
+
+There are four types of memory regions (all represented by a single C type
+MemoryRegion):
+
+- RAM: a RAM region is simply a range of host memory that can be made available
+  to the guest.
+
+- MMIO: a range of guest memory that is implemented by host callbacks;
+  each read or write causes a callback to be called on the host.
+
+- container: a container simply includes other memory regions, each at
+  a different offset.  Containers are useful for grouping several regions
+  into one unit.  For example, a PCI BAR may be composed of a RAM region
+  and an MMIO region.
+
+  A container's subregions are usually non-overlapping.  In some cases it is
+  useful to have overlapping regions; for example a memory controller that
+  can overlay a subregion of RAM with MMIO or ROM, or a PCI controller
+  that does not prevent card from claiming overlapping BARs.
+
+- alias: a subsection of another region.  Aliases allow a region to be
+  split apart into discontiguous regions.  Examples of uses are memory banks
+  used when the guest address space is smaller than the amount of RAM
+  addressed, or a memory controller that splits main memory to expose a "PCI
+  hole".  Aliases may point to any type of region, including other aliases,
+  but an alias may not point back to itself, directly or indirectly.
+
+
+Region names
+------------
+
+Regions are assigned names by the constructor.  For most regions these are
+only used for debugging purposes, but RAM regions also use the name to identify
+live migration sections.  This means that RAM region names need to have ABI
+stability.
+
+Region lifecycle
+----------------
+
+A region is created by one of the constructor functions (memory_region_init*())
+and destroyed by the destructor (memory_region_destroy()).  In between,
+a region can be added to an address space by using memory_region_add_subregion()
+and removed using memory_region_del_subregion().  Region attributes may be
+changed at any point; they take effect once the region becomes exposed to the
+guest.
+
+Overlapping regions and priority
+--------------------------------
+Usually, regions may not overlap each other; a memory address decodes into
+exactly one target.  In some cases it is useful to allow regions to overlap,
+and sometimes to control which of an overlapping regions is visible to the
+guest.  This is done with memory_region_add_subregion_overlap(), which
+allows the region to overlap any other region in the same container, and
+specifies a priority that allows the core to decide which of two regions at
+the same address are visible (highest wins).
+
+Visibility
+----------
+The memory core uses the following rules to select a memory region when the
+guest accesses an address:
+
+- all direct subregions of the root region are matched against the address, in
+  descending priority order
+  - if the address lies outside the region offset/size, the subregion is
+    discarded
+  - if the subregion is a leaf (RAM or MMIO), the seach terminates
+  - if the subregion is a container, the same algorithm is used within the
+    subregion (after the address is adjusted by the subregion offset)
+  - if the subregion is an alias, the search is continues at the alias target
+    (after the address is adjusted by the subregion offset and alias offset)
+
+Example memory map
+------------------
+
+system_memory: container@0-2^48-1
+ |
+ +---- lomem: alias@0-0xdfffffff ---> #ram (0-0xdfffffff)
+ |
+ +---- himem: alias@0x100000000-0x11fffffff ---> #ram (0xe0000000-0xffffffff)
+ |
+ +---- vga-window: alias@0xa0000-0xbfffff ---> #pci (0xa0000-0xbffff)
+ |      (prio 1)
+ |
+ +---- pci-hole: alias@0xe0000000-0xffffffff ---> #pci (0xe0000000-0xffffffff)
+
+pci (0-2^32-1)
+ |
+ +--- vga-area: container@0xa0000-0xbffff
+ |      |
+ |      +--- alias@0x00000-0x7fff  ---> #vram (0x010000-0x017fff)
+ |      |
+ |      +--- alias@0x08000-0xffff  ---> #vram (0x020000-0x027fff)
+ |
+ +---- vram: ram@0xe1000000-0xe1ffffff
+ |
+ +---- vga-mmio: mmio@0xe2000000-0xe200ffff
+
+ram: ram@0x00000000-0xffffffff
+
+The is a (simplified) PC memory map. The 4GB RAM block is mapped into the
+system address space via two aliases: "lomem" is a 1:1 mapping of the first
+3.5GB; "himem" maps the last 0.5GB at address 4GB.  This leaves 0.5GB for the
+so-called PCI hole, that allows a 32-bit PCI bus to exist in a system with
+4GB of memory.
+
+The memory controller diverts addresses in the range 640K-768K to the PCI
+address space.  This is modeled using the "vga-window" alias, mapped at a
+higher priority so it obscures the RAM at the same addresses.  The vga window
+can be removed by programming the memory controller; this is modelled by
+removing the alias and exposing the RAM underneath.
+
+The pci address space is not a direct child of the system address space, since
+we only want parts of it to be visible (we accomplish this using aliases).
+It has two subregions: vga-area models the legacy vga window and is occupied
+by two 32K memory banks pointing at two sections of the framebuffer.
+In addition the vram is mapped as a BAR at address e1000000, and an additional
+BAR containing MMIO registers is mapped after it.
+
+Note that if the guest maps a BAR outside the PCI hole, it would not be
+visible as the pci-hole alias clips it to a 0.5GB range.
+
+Attributes
+----------
+
+Various region attributes (read-only, dirty logging, coalesced mmio, ioeventfd)
+can be changed during the region lifecycle.  They take effect once the region
+is made visible (which can be immediately, later, or never).
+
+MMIO Operations
+---------------
+
+MMIO regions are provided with ->read() and ->write() callbacks; in addition
+various constraints can be supplied to control how these callbacks are called:
+
+ - .valid.min_access_size, .valid.max_access_size define the access sizes
+   (in bytes) which the device accepts; accesses outside this range will
+   have device and bus specific behaviour (ignored, or machine check)
+ - .valid.aligned specifies that the device only accepts naturally aligned
+   accesses.  Unaligned accesses invoke device and bus specific behaviour.
+ - .impl.min_access_size, .impl.max_access_size define the access sizes
+   (in bytes) supported by the *implementation*; other access sizes will be
+   emulated using the ones available.  For example a 4-byte write will be
+   emulated using four 1-byte write, is .impl.max_access_size = 1.
+ - .impl.valid specifies that the *implementation* only supports unaligned
+   accesses; unaligned accesses will be emulated by two aligned accesses.
+ - .old_portio and .old_mmio can be used to ease porting from code using
+   cpu_register_io_memory() and register_ioport().  They should not be used
+   in new code.
index db00fbae04e20eec0c9bdd84700d5eff336dd2cc..cc1e4fb09d50082bf258b859c113cd4554ee00fb 100644 (file)
@@ -64,6 +64,8 @@ typedef void * host_reg_t;
 #error unsupported CPU
 #endif
 
+register CPUState *env asm(AREG0);
+
 #define xglue(x, y) x ## y
 #define glue(x, y) xglue(x, y)
 #define stringify(s)   tostring(s)
diff --git a/exec-memory.h b/exec-memory.h
new file mode 100644 (file)
index 0000000..334219f
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Internal memory managment interfaces
+ *
+ * Copyright 2011 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *  Avi Kivity <avi@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef EXEC_MEMORY_H
+#define EXEC_MEMORY_H
+
+/*
+ * Internal interfaces between memory.c/exec.c/vl.c.  Do not #include unless
+ * you're one of them.
+ */
+
+#include "memory.h"
+
+#ifndef CONFIG_USER_ONLY
+
+/* Get the root memory region.  This interface should only be used temporarily
+ * until a proper bus interface is available.
+ */
+MemoryRegion *get_system_memory(void);
+
+/* Get the root I/O port region.  This interface should only be used
+ * temporarily until a proper bus interface is available.
+ */
+MemoryRegion *get_system_io(void);
+
+/* Set the root memory region.  This region is the system memory map. */
+void set_system_memory_map(MemoryRegion *mr);
+
+/* Set the I/O memory region.  This region is the I/O memory map. */
+void set_system_io_map(MemoryRegion *mr);
+
+#endif
+
+#endif
diff --git a/exec.c b/exec.c
index 2160ded4017f9f3f820360cb5a388bb5facdc8c2..be7e4b24512e10e2ae14be13432c8b5f5155afdd 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -33,6 +33,8 @@
 #include "kvm.h"
 #include "hw/xen.h"
 #include "qemu-timer.h"
+#include "memory.h"
+#include "exec-memory.h"
 #if defined(CONFIG_USER_ONLY)
 #include <qemu.h>
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
@@ -109,6 +111,10 @@ int phys_ram_fd;
 static int in_migration;
 
 RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list) };
+
+static MemoryRegion *system_memory;
+static MemoryRegion *system_io;
+
 #endif
 
 CPUState *first_cpu;
@@ -197,6 +203,7 @@ typedef struct PhysPageDesc {
 static void *l1_phys_map[P_L1_SIZE];
 
 static void io_mem_init(void);
+static void memory_map_init(void);
 
 /* io memory support */
 CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
@@ -520,7 +527,8 @@ static void code_gen_alloc(unsigned long tb_size)
         }
     }
 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
-    || defined(__DragonFly__) || defined(__OpenBSD__)
+    || defined(__DragonFly__) || defined(__OpenBSD__) \
+    || defined(__NetBSD__)
     {
         int flags;
         void *addr = NULL;
@@ -564,15 +572,12 @@ static void code_gen_alloc(unsigned long tb_size)
 /* Must be called before using the QEMU cpus. 'tb_size' is the size
    (in bytes) allocated to the translation buffer. Zero means default
    size. */
-void cpu_exec_init_all(unsigned long tb_size)
+void tcg_exec_init(unsigned long tb_size)
 {
     cpu_gen_init();
     code_gen_alloc(tb_size);
     code_gen_ptr = code_gen_buffer;
     page_init();
-#if !defined(CONFIG_USER_ONLY)
-    io_mem_init();
-#endif
 #if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE)
     /* There's no guest base to take into account, so go ahead and
        initialize the prologue now.  */
@@ -580,6 +585,19 @@ void cpu_exec_init_all(unsigned long tb_size)
 #endif
 }
 
+bool tcg_enabled(void)
+{
+    return code_gen_buffer != NULL;
+}
+
+void cpu_exec_init_all(void)
+{
+#if !defined(CONFIG_USER_ONLY)
+    memory_map_init();
+    io_mem_init();
+#endif
+}
+
 #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
 
 static int cpu_common_post_load(void *opaque, int version_id)
@@ -2863,13 +2881,13 @@ static void *file_ram_alloc(RAMBlock *block,
 static ram_addr_t find_ram_offset(ram_addr_t size)
 {
     RAMBlock *block, *next_block;
-    ram_addr_t offset = 0, mingap = ULONG_MAX;
+    ram_addr_t offset = 0, mingap = RAM_ADDR_MAX;
 
     if (QLIST_EMPTY(&ram_list.blocks))
         return 0;
 
     QLIST_FOREACH(block, &ram_list.blocks, next) {
-        ram_addr_t end, next = ULONG_MAX;
+        ram_addr_t end, next = RAM_ADDR_MAX;
 
         end = block->offset + block->length;
 
@@ -3081,7 +3099,8 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
 #endif
                 }
                 if (area != vaddr) {
-                    fprintf(stderr, "Could not remap addr: %lx@%lx\n",
+                    fprintf(stderr, "Could not remap addr: "
+                            RAM_ADDR_FMT "@" RAM_ADDR_FMT "\n",
                             length, addr);
                     exit(1);
                 }
@@ -3807,6 +3826,27 @@ static void io_mem_init(void)
                                           DEVICE_NATIVE_ENDIAN);
 }
 
+static void memory_map_init(void)
+{
+    system_memory = qemu_malloc(sizeof(*system_memory));
+    memory_region_init(system_memory, "system", INT64_MAX);
+    set_system_memory_map(system_memory);
+
+    system_io = qemu_malloc(sizeof(*system_io));
+    memory_region_init(system_io, "io", 65536);
+    set_system_io_map(system_io);
+}
+
+MemoryRegion *get_system_memory(void)
+{
+    return system_memory;
+}
+
+MemoryRegion *get_system_io(void)
+{
+    return system_io;
+}
+
 #endif /* !defined(CONFIG_USER_ONLY) */
 
 /* physical memory access (slow version, mainly for debug) */
@@ -3858,7 +3898,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
     uint8_t *ptr;
     uint32_t val;
     target_phys_addr_t page;
-    unsigned long pd;
+    ram_addr_t pd;
     PhysPageDesc *p;
 
     while (len > 0) {
@@ -3898,7 +3938,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                     l = 1;
                 }
             } else {
-                unsigned long addr1;
+                ram_addr_t addr1;
                 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
                 /* RAM case */
                 ptr = qemu_get_ram_ptr(addr1);
@@ -4052,7 +4092,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
     target_phys_addr_t page;
     unsigned long pd;
     PhysPageDesc *p;
-    ram_addr_t raddr = ULONG_MAX;
+    ram_addr_t raddr = RAM_ADDR_MAX;
     ram_addr_t rlen;
     void *ret;
 
index c7d35a161d4b01a916e3e29dcf88592dcb60ec14..c165205a49bebb377de55aa42241de5a68b9c515 100644 (file)
@@ -35,6 +35,78 @@ these four paragraphs for those parts of this code that are retained.
 
 =============================================================================*/
 
+#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#define SNAN_BIT_IS_ONE                1
+#else
+#define SNAN_BIT_IS_ONE                0
+#endif
+
+/*----------------------------------------------------------------------------
+| The pattern for a default generated half-precision NaN.
+*----------------------------------------------------------------------------*/
+#if defined(TARGET_ARM)
+const float16 float16_default_nan = const_float16(0x7E00);
+#elif SNAN_BIT_IS_ONE
+const float16 float16_default_nan = const_float16(0x7DFF);
+#else
+const float16 float16_default_nan = const_float16(0xFE00);
+#endif
+
+/*----------------------------------------------------------------------------
+| The pattern for a default generated single-precision NaN.
+*----------------------------------------------------------------------------*/
+#if defined(TARGET_SPARC)
+const float32 float32_default_nan = const_float32(0x7FFFFFFF);
+#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
+const float32 float32_default_nan = const_float32(0x7FC00000);
+#elif SNAN_BIT_IS_ONE
+const float32 float32_default_nan = const_float32(0x7FBFFFFF);
+#else
+const float32 float32_default_nan = const_float32(0xFFC00000);
+#endif
+
+/*----------------------------------------------------------------------------
+| The pattern for a default generated double-precision NaN.
+*----------------------------------------------------------------------------*/
+#if defined(TARGET_SPARC)
+const float64 float64_default_nan = const_float64(LIT64( 0x7FFFFFFFFFFFFFFF ));
+#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
+const float64 float64_default_nan = const_float64(LIT64( 0x7FF8000000000000 ));
+#elif SNAN_BIT_IS_ONE
+const float64 float64_default_nan = const_float64(LIT64( 0x7FF7FFFFFFFFFFFF ));
+#else
+const float64 float64_default_nan = const_float64(LIT64( 0xFFF8000000000000 ));
+#endif
+
+/*----------------------------------------------------------------------------
+| The pattern for a default generated extended double-precision NaN.
+*----------------------------------------------------------------------------*/
+#if SNAN_BIT_IS_ONE
+#define floatx80_default_nan_high 0x7FFF
+#define floatx80_default_nan_low  LIT64( 0xBFFFFFFFFFFFFFFF )
+#else
+#define floatx80_default_nan_high 0xFFFF
+#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
+#endif
+
+const floatx80 floatx80_default_nan = make_floatx80(floatx80_default_nan_high,
+                                                    floatx80_default_nan_low);
+
+/*----------------------------------------------------------------------------
+| The pattern for a default generated quadruple-precision NaN.  The `high' and
+| `low' values hold the most- and least-significant bits, respectively.
+*----------------------------------------------------------------------------*/
+#if SNAN_BIT_IS_ONE
+#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
+#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
+#else
+#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
+#define float128_default_nan_low  LIT64( 0x0000000000000000 )
+#endif
+
+const float128 float128_default_nan = make_float128(float128_default_nan_high,
+                                                    float128_default_nan_low);
+
 /*----------------------------------------------------------------------------
 | Raises the exceptions specified by `flags'.  Floating-point traps can be
 | defined here if desired.  It is currently not possible for such a trap
index bde250087be38888d767694eac53eb2eca464ec6..3bb7d8fa6d9e8e0b7e22969fb36dbd37ff0e64d0 100644 (file)
@@ -43,7 +43,7 @@ these four paragraphs for those parts of this code that are retained.
 #endif
 
 #include <inttypes.h>
-#include "config.h"
+#include "config-host.h"
 
 /*----------------------------------------------------------------------------
 | Each of the following `typedef's defines the most convenient type that holds
@@ -68,12 +68,6 @@ typedef int64_t int64;
 #define LIT64( a ) a##LL
 #define INLINE static inline
 
-#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-#define SNAN_BIT_IS_ONE                1
-#else
-#define SNAN_BIT_IS_ONE                0
-#endif
-
 #define STATUS_PARAM , float_status *status
 #define STATUS(field) status->field
 #define STATUS_VAR , status
@@ -142,6 +136,7 @@ typedef struct {
     uint64_t low, high;
 #endif
 } float128;
+#define make_float128(high_, low_) ((float128) { .high = high_, .low = low_ })
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE floating-point underflow tininess-detection mode.
@@ -248,13 +243,7 @@ float16 float16_maybe_silence_nan( float16 );
 /*----------------------------------------------------------------------------
 | The pattern for a default generated half-precision NaN.
 *----------------------------------------------------------------------------*/
-#if defined(TARGET_ARM)
-#define float16_default_nan make_float16(0x7E00)
-#elif SNAN_BIT_IS_ONE
-#define float16_default_nan make_float16(0x7DFF)
-#else
-#define float16_default_nan make_float16(0xFE00)
-#endif
+extern const float16 float16_default_nan;
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE single-precision conversion routines.
@@ -357,15 +346,7 @@ INLINE float32 float32_set_sign(float32 a, int sign)
 /*----------------------------------------------------------------------------
 | The pattern for a default generated single-precision NaN.
 *----------------------------------------------------------------------------*/
-#if defined(TARGET_SPARC)
-#define float32_default_nan make_float32(0x7FFFFFFF)
-#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
-#define float32_default_nan make_float32(0x7FC00000)
-#elif SNAN_BIT_IS_ONE
-#define float32_default_nan make_float32(0x7FBFFFFF)
-#else
-#define float32_default_nan make_float32(0xFFC00000)
-#endif
+extern const float32 float32_default_nan;
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision conversion routines.
@@ -470,15 +451,7 @@ INLINE float64 float64_set_sign(float64 a, int sign)
 /*----------------------------------------------------------------------------
 | The pattern for a default generated double-precision NaN.
 *----------------------------------------------------------------------------*/
-#if defined(TARGET_SPARC)
-#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
-#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
-#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
-#elif SNAN_BIT_IS_ONE
-#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
-#else
-#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
-#endif
+extern const float64 float64_default_nan;
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE extended double-precision conversion routines.
@@ -561,17 +534,9 @@ INLINE int floatx80_is_any_nan(floatx80 a)
 #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,
-| respectively.
+| The pattern for a default generated extended double-precision NaN.
 *----------------------------------------------------------------------------*/
-#if SNAN_BIT_IS_ONE
-#define floatx80_default_nan_high 0x7FFF
-#define floatx80_default_nan_low  LIT64( 0xBFFFFFFFFFFFFFFF )
-#else
-#define floatx80_default_nan_high 0xFFFF
-#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
-#endif
+extern const floatx80 floatx80_default_nan;
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE quadruple-precision conversion routines.
@@ -648,15 +613,8 @@ INLINE int float128_is_any_nan(float128 a)
 }
 
 /*----------------------------------------------------------------------------
-| The pattern for a default generated quadruple-precision NaN.  The `high' and
-| `low' values hold the most- and least-significant bits, respectively.
+| The pattern for a default generated quadruple-precision NaN.
 *----------------------------------------------------------------------------*/
-#if SNAN_BIT_IS_ONE
-#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
-#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
-#else
-#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
-#define float128_default_nan_low  LIT64( 0x0000000000000000 )
-#endif
+extern const float128 float128_default_nan;
 
 #endif /* !SOFTFLOAT_H */
index c8578276187f69da19bb11c3d1015cbb0d65737c..0ccfb2867f475f197e8df293dcd965a2a1935781 100644 (file)
@@ -1311,8 +1311,6 @@ show virtual to physical memory mappings (i386, SH4 and SPARC only)
 show the active virtual memory mappings (i386 only)
 @item info jit
 show dynamic compiler info
-@item info kvm
-show KVM information
 @item info numa
 show NUMA information
 @item info kvm
index 0b59896fbbc79a4e17ebfe794250e933240530e7..541d9a4b97f321650effaa9b81b3e122f49eb19a 100644 (file)
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -160,8 +160,9 @@ typedef struct AC97LinkState {
     SWVoiceIn *voice_mc;
     int invalid_freq[3];
     uint8_t silence[128];
-    uint32_t base[2];
     int bup_flag;
+    MemoryRegion io_nam;
+    MemoryRegion io_nabm;
 } AC97LinkState;
 
 enum {
@@ -583,7 +584,7 @@ static uint32_t nam_readw (void *opaque, uint32_t addr)
 {
     AC97LinkState *s = opaque;
     uint32_t val = ~0U;
-    uint32_t index = addr - s->base[0];
+    uint32_t index = addr;
     s->cas = 0;
     val = mixer_load (s, index);
     return val;
@@ -611,7 +612,7 @@ static void nam_writeb (void *opaque, uint32_t addr, uint32_t val)
 static void nam_writew (void *opaque, uint32_t addr, uint32_t val)
 {
     AC97LinkState *s = opaque;
-    uint32_t index = addr - s->base[0];
+    uint32_t index = addr;
     s->cas = 0;
     switch (index) {
     case AC97_Reset:
@@ -714,7 +715,7 @@ static uint32_t nabm_readb (void *opaque, uint32_t addr)
 {
     AC97LinkState *s = opaque;
     AC97BusMasterRegs *r = NULL;
-    uint32_t index = addr - s->base[1];
+    uint32_t index = addr;
     uint32_t val = ~0U;
 
     switch (index) {
@@ -769,7 +770,7 @@ static uint32_t nabm_readw (void *opaque, uint32_t addr)
 {
     AC97LinkState *s = opaque;
     AC97BusMasterRegs *r = NULL;
-    uint32_t index = addr - s->base[1];
+    uint32_t index = addr;
     uint32_t val = ~0U;
 
     switch (index) {
@@ -798,7 +799,7 @@ static uint32_t nabm_readl (void *opaque, uint32_t addr)
 {
     AC97LinkState *s = opaque;
     AC97BusMasterRegs *r = NULL;
-    uint32_t index = addr - s->base[1];
+    uint32_t index = addr;
     uint32_t val = ~0U;
 
     switch (index) {
@@ -848,7 +849,7 @@ static void nabm_writeb (void *opaque, uint32_t addr, uint32_t val)
 {
     AC97LinkState *s = opaque;
     AC97BusMasterRegs *r = NULL;
-    uint32_t index = addr - s->base[1];
+    uint32_t index = addr;
     switch (index) {
     case PI_LVI:
     case PO_LVI:
@@ -904,7 +905,7 @@ static void nabm_writew (void *opaque, uint32_t addr, uint32_t val)
 {
     AC97LinkState *s = opaque;
     AC97BusMasterRegs *r = NULL;
-    uint32_t index = addr - s->base[1];
+    uint32_t index = addr;
     switch (index) {
     case PI_SR:
     case PO_SR:
@@ -924,7 +925,7 @@ static void nabm_writel (void *opaque, uint32_t addr, uint32_t val)
 {
     AC97LinkState *s = opaque;
     AC97BusMasterRegs *r = NULL;
-    uint32_t index = addr - s->base[1];
+    uint32_t index = addr;
     switch (index) {
     case PI_BDBAR:
     case PO_BDBAR:
@@ -1230,31 +1231,33 @@ static const VMStateDescription vmstate_ac97 = {
     }
 };
 
-static void ac97_map (PCIDevice *pci_dev, int region_num,
-                      pcibus_t addr, pcibus_t size, int type)
-{
-    AC97LinkState *s = DO_UPCAST (AC97LinkState, dev, pci_dev);
-    PCIDevice *d = &s->dev;
-
-    if (!region_num) {
-        s->base[0] = addr;
-        register_ioport_read (addr, 256 * 1, 1, nam_readb, d);
-        register_ioport_read (addr, 256 * 2, 2, nam_readw, d);
-        register_ioport_read (addr, 256 * 4, 4, nam_readl, d);
-        register_ioport_write (addr, 256 * 1, 1, nam_writeb, d);
-        register_ioport_write (addr, 256 * 2, 2, nam_writew, d);
-        register_ioport_write (addr, 256 * 4, 4, nam_writel, d);
-    }
-    else {
-        s->base[1] = addr;
-        register_ioport_read (addr, 64 * 1, 1, nabm_readb, d);
-        register_ioport_read (addr, 64 * 2, 2, nabm_readw, d);
-        register_ioport_read (addr, 64 * 4, 4, nabm_readl, d);
-        register_ioport_write (addr, 64 * 1, 1, nabm_writeb, d);
-        register_ioport_write (addr, 64 * 2, 2, nabm_writew, d);
-        register_ioport_write (addr, 64 * 4, 4, nabm_writel, d);
-    }
-}
+static const MemoryRegionPortio nam_portio[] = {
+    { 0, 256 * 1, 1, .read = nam_readb, },
+    { 0, 256 * 2, 2, .read = nam_readw, },
+    { 0, 256 * 4, 4, .read = nam_readl, },
+    { 0, 256 * 1, 1, .write = nam_writeb, },
+    { 0, 256 * 2, 2, .write = nam_writew, },
+    { 0, 256 * 4, 4, .write = nam_writel, },
+    PORTIO_END_OF_LIST(),
+};
+
+static const MemoryRegionOps ac97_io_nam_ops = {
+    .old_portio = nam_portio,
+};
+
+static const MemoryRegionPortio nabm_portio[] = {
+    { 0, 64 * 1, 1, .read = nabm_readb, },
+    { 0, 64 * 2, 2, .read = nabm_readw, },
+    { 0, 64 * 4, 4, .read = nabm_readl, },
+    { 0, 64 * 1, 1, .write = nabm_writeb, },
+    { 0, 64 * 2, 2, .write = nabm_writew, },
+    { 0, 64 * 4, 4, .write = nabm_writel, },
+    PORTIO_END_OF_LIST()
+};
+
+static const MemoryRegionOps ac97_io_nabm_ops = {
+    .old_portio = nabm_portio,
+};
 
 static void ac97_on_reset (void *opaque)
 {
@@ -1311,15 +1314,25 @@ static int ac97_initfn (PCIDevice *dev)
     /* TODO: RST# value should be 0. */
     c[PCI_INTERRUPT_PIN] = 0x01;      /* intr_pn interrupt pin ro */
 
-    pci_register_bar (&s->dev, 0, 256 * 4, PCI_BASE_ADDRESS_SPACE_IO,
-                      ac97_map);
-    pci_register_bar (&s->dev, 1, 64 * 4, PCI_BASE_ADDRESS_SPACE_IO, ac97_map);
+    memory_region_init_io (&s->io_nam, &ac97_io_nam_ops, s, "ac97-nam", 1024);
+    memory_region_init_io (&s->io_nabm, &ac97_io_nabm_ops, s, "ac97-nabm", 256);
+    pci_register_bar (&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nam);
+    pci_register_bar (&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nabm);
     qemu_register_reset (ac97_on_reset, s);
     AUD_register_card ("ac97", &s->card);
     ac97_on_reset (s);
     return 0;
 }
 
+static int ac97_exitfn (PCIDevice *dev)
+{
+    AC97LinkState *s = DO_UPCAST (AC97LinkState, dev, dev);
+
+    memory_region_destroy (&s->io_nam);
+    memory_region_destroy (&s->io_nabm);
+    return 0;
+}
+
 int ac97_init (PCIBus *bus)
 {
     pci_create_simple (bus, -1, "AC97");
@@ -1332,6 +1345,7 @@ static PCIDeviceInfo ac97_info = {
     .qdev.size    = sizeof (AC97LinkState),
     .qdev.vmsd    = &vmstate_ac97,
     .init         = ac97_initfn,
+    .exit         = ac97_exitfn,
     .vendor_id    = PCI_VENDOR_ID_INTEL,
     .device_id    = PCI_DEVICE_ID_INTEL_82801AA_5,
     .revision     = 0x01,
index ad40fb4c3cdca06afcd88d61c1a4d5272bc64ecf..79ec66c1478638d90a81387b437a4599889c4159 100644 (file)
--- a/hw/acpi.c
+++ b/hw/acpi.c
 #include "pc.h"
 #include "acpi.h"
 
-struct acpi_table_header
-{
-    char signature [4];    /* ACPI signature (4 ASCII characters) */
+struct acpi_table_header {
+    uint16_t _length;         /* our length, not actual part of the hdr */
+                              /* XXX why we have 2 length fields here? */
+    char sig[4];              /* ACPI signature (4 ASCII characters) */
     uint32_t length;          /* Length of table, in bytes, including header */
     uint8_t revision;         /* ACPI Specification minor version # */
     uint8_t checksum;         /* To make sum of entire table == 0 */
-    char oem_id [6];       /* OEM identification */
-    char oem_table_id [8]; /* OEM table identification */
+    char oem_id[6];           /* OEM identification */
+    char oem_table_id[8];     /* OEM table identification */
     uint32_t oem_revision;    /* OEM revision number */
-    char asl_compiler_id [4]; /* ASL compiler vendor ID */
+    char asl_compiler_id[4];  /* ASL compiler vendor ID */
     uint32_t asl_compiler_revision; /* ASL compiler revision number */
 } __attribute__((packed));
 
+#define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header)
+#define ACPI_TABLE_PFX_SIZE sizeof(uint16_t)  /* size of the extra prefix */
+
+static const char dfl_hdr[ACPI_TABLE_HDR_SIZE] =
+    "\0\0"                   /* fake _length (2) */
+    "QEMU\0\0\0\0\1\0"       /* sig (4), len(4), revno (1), csum (1) */
+    "QEMUQEQEMUQEMU\1\0\0\0" /* OEM id (6), table (8), revno (4) */
+    "QEMU\1\0\0\0"           /* ASL compiler ID (4), version (4) */
+    ;
+
 char *acpi_tables;
 size_t acpi_tables_len;
 
@@ -40,163 +51,198 @@ static int acpi_checksum(const uint8_t *data, int len)
 {
     int sum, i;
     sum = 0;
-    for(i = 0; i < len; i++)
+    for (i = 0; i < len; i++) {
         sum += data[i];
+    }
     return (-sum) & 0xff;
 }
 
+/* like strncpy() but zero-fills the tail of destination */
+static void strzcpy(char *dst, const char *src, size_t size)
+{
+    size_t len = strlen(src);
+    if (len >= size) {
+        len = size;
+    } else {
+      memset(dst + len, 0, size - len);
+    }
+    memcpy(dst, src, len);
+}
+
+/* XXX fixme: this function uses obsolete argument parsing interface */
 int acpi_table_add(const char *t)
 {
-    static const char *dfl_id = "QEMUQEMU";
     char buf[1024], *p, *f;
-    struct acpi_table_header acpi_hdr;
     unsigned long val;
-    uint32_t length;
-    struct acpi_table_header *acpi_hdr_p;
-    size_t off;
+    size_t len, start, allen;
+    bool has_header;
+    int changed;
+    int r;
+    struct acpi_table_header hdr;
+
+    r = 0;
+    r |= get_param_value(buf, sizeof(buf), "data", t) ? 1 : 0;
+    r |= get_param_value(buf, sizeof(buf), "file", t) ? 2 : 0;
+    switch (r) {
+    case 0:
+        buf[0] = '\0';
+        /* fallthrough for default behavior */
+    case 1:
+        has_header = false;
+        break;
+    case 2:
+        has_header = true;
+        break;
+    default:
+        fprintf(stderr, "acpitable: both data and file are specified\n");
+        return -1;
+    }
 
-    memset(&acpi_hdr, 0, sizeof(acpi_hdr));
-  
-    if (get_param_value(buf, sizeof(buf), "sig", t)) {
-        strncpy(acpi_hdr.signature, buf, 4);
+    if (!acpi_tables) {
+        allen = sizeof(uint16_t);
+        acpi_tables = qemu_mallocz(allen);
     } else {
-        strncpy(acpi_hdr.signature, dfl_id, 4);
+        allen = acpi_tables_len;
     }
+
+    start = allen;
+    acpi_tables = qemu_realloc(acpi_tables, start + ACPI_TABLE_HDR_SIZE);
+    allen += has_header ? ACPI_TABLE_PFX_SIZE : ACPI_TABLE_HDR_SIZE;
+
+    /* now read in the data files, reallocating buffer as needed */
+
+    for (f = strtok(buf, ":"); f; f = strtok(NULL, ":")) {
+        int fd = open(f, O_RDONLY);
+
+        if (fd < 0) {
+            fprintf(stderr, "can't open file %s: %s\n", f, strerror(errno));
+            return -1;
+        }
+
+        for (;;) {
+            char data[8192];
+            r = read(fd, data, sizeof(data));
+            if (r == 0) {
+                break;
+            } else if (r > 0) {
+                acpi_tables = qemu_realloc(acpi_tables, allen + r);
+                memcpy(acpi_tables + allen, data, r);
+                allen += r;
+            } else if (errno != EINTR) {
+                fprintf(stderr, "can't read file %s: %s\n",
+                        f, strerror(errno));
+                close(fd);
+                return -1;
+            }
+        }
+
+        close(fd);
+    }
+
+    /* now fill in the header fields */
+
+    f = acpi_tables + start;   /* start of the table */
+    changed = 0;
+
+    /* copy the header to temp place to align the fields */
+    memcpy(&hdr, has_header ? f : dfl_hdr, ACPI_TABLE_HDR_SIZE);
+
+    /* length of the table minus our prefix */
+    len = allen - start - ACPI_TABLE_PFX_SIZE;
+
+    hdr._length = cpu_to_le16(len);
+
+    if (get_param_value(buf, sizeof(buf), "sig", t)) {
+        strzcpy(hdr.sig, buf, sizeof(hdr.sig));
+        ++changed;
+    }
+
+    /* length of the table including header, in bytes */
+    if (has_header) {
+        /* check if actual length is correct */
+        val = le32_to_cpu(hdr.length);
+        if (val != len) {
+            fprintf(stderr,
+                "warning: acpitable has wrong length,"
+                " header says %lu, actual size %zu bytes\n",
+                val, len);
+            ++changed;
+        }
+    }
+    /* we may avoid putting length here if has_header is true */
+    hdr.length = cpu_to_le32(len);
+
     if (get_param_value(buf, sizeof(buf), "rev", t)) {
-        val = strtoul(buf, &p, 10);
-        if (val > 255 || *p != '\0')
-            goto out;
-    } else {
-        val = 1;
+        val = strtoul(buf, &p, 0);
+        if (val > 255 || *p) {
+            fprintf(stderr, "acpitable: \"rev=%s\" is invalid\n", buf);
+            return -1;
+        }
+        hdr.revision = (uint8_t)val;
+        ++changed;
     }
-    acpi_hdr.revision = (int8_t)val;
 
     if (get_param_value(buf, sizeof(buf), "oem_id", t)) {
-        strncpy(acpi_hdr.oem_id, buf, 6);
-    } else {
-        strncpy(acpi_hdr.oem_id, dfl_id, 6);
+        strzcpy(hdr.oem_id, buf, sizeof(hdr.oem_id));
+        ++changed;
     }
 
     if (get_param_value(buf, sizeof(buf), "oem_table_id", t)) {
-        strncpy(acpi_hdr.oem_table_id, buf, 8);
-    } else {
-        strncpy(acpi_hdr.oem_table_id, dfl_id, 8);
+        strzcpy(hdr.oem_table_id, buf, sizeof(hdr.oem_table_id));
+        ++changed;
     }
 
     if (get_param_value(buf, sizeof(buf), "oem_rev", t)) {
-        val = strtol(buf, &p, 10);
-        if(*p != '\0')
-            goto out;
-    } else {
-        val = 1;
+        val = strtol(buf, &p, 0);
+        if (*p) {
+            fprintf(stderr, "acpitable: \"oem_rev=%s\" is invalid\n", buf);
+            return -1;
+        }
+        hdr.oem_revision = cpu_to_le32(val);
+        ++changed;
     }
-    acpi_hdr.oem_revision = cpu_to_le32(val);
 
     if (get_param_value(buf, sizeof(buf), "asl_compiler_id", t)) {
-        strncpy(acpi_hdr.asl_compiler_id, buf, 4);
-    } else {
-        strncpy(acpi_hdr.asl_compiler_id, dfl_id, 4);
+        strzcpy(hdr.asl_compiler_id, buf, sizeof(hdr.asl_compiler_id));
+        ++changed;
     }
 
     if (get_param_value(buf, sizeof(buf), "asl_compiler_rev", t)) {
-        val = strtol(buf, &p, 10);
-        if(*p != '\0')
-            goto out;
-    } else {
-        val = 1;
-    }
-    acpi_hdr.asl_compiler_revision = cpu_to_le32(val);
-    
-    if (!get_param_value(buf, sizeof(buf), "data", t)) {
-         buf[0] = '\0';
-    }
-
-    length = sizeof(acpi_hdr);
-
-    f = buf;
-    while (buf[0]) {
-        struct stat s;
-        char *n = strchr(f, ':');
-        if (n)
-            *n = '\0';
-        if(stat(f, &s) < 0) {
-            fprintf(stderr, "Can't stat file '%s': %s\n", f, strerror(errno));
-            goto out;
+        val = strtol(buf, &p, 0);
+        if (*p) {
+            fprintf(stderr, "acpitable: \"%s=%s\" is invalid\n",
+                    "asl_compiler_rev", buf);
+            return -1;
         }
-        length += s.st_size;
-        if (!n)
-            break;
-        *n = ':';
-        f = n + 1;
+        hdr.asl_compiler_revision = cpu_to_le32(val);
+        ++changed;
     }
 
-    if (!acpi_tables) {
-        acpi_tables_len = sizeof(uint16_t);
-        acpi_tables = qemu_mallocz(acpi_tables_len);
+    if (!has_header && !changed) {
+        fprintf(stderr, "warning: acpitable: no table headers are specified\n");
     }
-    acpi_tables = qemu_realloc(acpi_tables,
-                               acpi_tables_len + sizeof(uint16_t) + length);
-    p = acpi_tables + acpi_tables_len;
-    acpi_tables_len += sizeof(uint16_t) + length;
-
-    *(uint16_t*)p = cpu_to_le32(length);
-    p += sizeof(uint16_t);
-    memcpy(p, &acpi_hdr, sizeof(acpi_hdr));
-    off = sizeof(acpi_hdr);
-
-    f = buf;
-    while (buf[0]) {
-        struct stat s;
-        int fd;
-        char *n = strchr(f, ':');
-        if (n)
-            *n = '\0';
-        fd = open(f, O_RDONLY);
-
-        if(fd < 0)
-            goto out;
-        if(fstat(fd, &s) < 0) {
-            close(fd);
-            goto out;
-        }
 
-        /* off < length is necessary because file size can be changed
-           under our foot */
-        while(s.st_size && off < length) {
-            int r;
-            r = read(fd, p + off, s.st_size);
-            if (r > 0) {
-                off += r;
-                s.st_size -= r;
-            } else if ((r < 0 && errno != EINTR) || r == 0) {
-                close(fd);
-                goto out;
-            }
-        }
 
-        close(fd);
-        if (!n)
-            break;
-        f = n + 1;
-    }
-    if (off < length) {
-        /* don't pass random value in process to guest */
-        memset(p + off, 0, length - off);
+    /* now calculate checksum of the table, complete with the header */
+    /* we may as well leave checksum intact if has_header is true */
+    /* alternatively there may be a way to set cksum to a given value */
+    hdr.checksum = 0;    /* for checksum calculation */
+
+    /* put header back */
+    memcpy(f, &hdr, sizeof(hdr));
+
+    if (changed || !has_header || 1) {
+        ((struct acpi_table_header *)f)->checksum =
+            acpi_checksum((uint8_t *)f + ACPI_TABLE_PFX_SIZE, len);
     }
 
-    acpi_hdr_p = (struct acpi_table_header*)p;
-    acpi_hdr_p->length = cpu_to_le32(length);
-    acpi_hdr_p->checksum = acpi_checksum((uint8_t*)p, length);
     /* increase number of tables */
-    (*(uint16_t*)acpi_tables) =
-           cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_tables) + 1);
+    (*(uint16_t *)acpi_tables) =
+        cpu_to_le32(le32_to_cpu(*(uint16_t *)acpi_tables) + 1);
+
+    acpi_tables_len = allen;
     return 0;
-out:
-    if (acpi_tables) {
-        qemu_free(acpi_tables);
-        acpi_tables = NULL;
-    }
-    return -1;
+
 }
 
 /* ACPI PM1a EVT */
index 974c87a8ce7955ba84e2a8d4711e2182450b33c4..163822617bc878699e338ee8dba888c6e6d1a22b 100644 (file)
@@ -34,6 +34,7 @@
 #include "rwhandler.h"
 #include "apb_pci.h"
 #include "sysemu.h"
+#include "exec-memory.h"
 
 /* debug APB */
 //#define DEBUG_APB
@@ -346,6 +347,8 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
 
     d->bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_apb_set_irq, pci_pbm_map_irq, d,
+                                         get_system_memory(),
+                                         get_system_io(),
                                          0, 32);
     pci_bus_set_mem_base(d->bus, mem_base);
 
index 0e2135afd082ae41f07652fffc1abd8ad036f58d..d9002a5e2c09a11b7a11f8b6d5f753c3528c0a82 100644 (file)
 #include "loader.h"
 #include "elf.h"
 #include "cris-boot.h"
+#include "blockdev.h"
 
 #define D(x)
 #define DNAND(x)
 
 struct nand_state_t
 {
-    NANDFlashState *nand;
+    DeviceState *nand;
     unsigned int rdy:1;
     unsigned int ale:1;
     unsigned int cle:1;
@@ -251,9 +252,10 @@ void axisdev88_init (ram_addr_t ram_size,
     CPUState *env;
     DeviceState *dev;
     SysBusDevice *s;
+    DriveInfo *nand;
     qemu_irq irq[30], nmi[2], *cpu_irq;
     void *etraxfs_dmac;
-    struct etraxfs_dma_client *eth[2] = {NULL, NULL};
+    struct etraxfs_dma_client *dma_eth;
     int i;
     int nand_regs;
     int gpio_regs;
@@ -278,7 +280,9 @@ void axisdev88_init (ram_addr_t ram_size,
 
 
       /* Attach a NAND flash to CS1.  */
-    nand_state.nand = nand_init(NAND_MFR_STMICRO, 0x39);
+    nand = drive_get(IF_MTD, 0, 0);
+    nand_state.nand = nand_init(nand ? nand->bdrv : NULL,
+                                NAND_MFR_STMICRO, 0x39);
     nand_regs = cpu_register_io_memory(nand_read, nand_write, &nand_state,
                                        DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(0x10000000, 0x05000000, nand_regs);
@@ -311,16 +315,18 @@ void axisdev88_init (ram_addr_t ram_size,
     }
 
     /* Add the two ethernet blocks.  */
-    eth[0] = etraxfs_eth_init(&nd_table[0], 0x30034000, 1);
-    if (nb_nics > 1)
-        eth[1] = etraxfs_eth_init(&nd_table[1], 0x30036000, 2);
+    dma_eth = qemu_mallocz(sizeof dma_eth[0] * 4); /* Allocate 4 channels.  */
+    etraxfs_eth_init(&nd_table[0], 0x30034000, 1, &dma_eth[0], &dma_eth[1]);
+    if (nb_nics > 1) {
+        etraxfs_eth_init(&nd_table[1], 0x30036000, 2, &dma_eth[2], &dma_eth[3]);
+    }
 
     /* The DMA Connector block is missing, hardwire things for now.  */
-    etraxfs_dmac_connect_client(etraxfs_dmac, 0, eth[0]);
-    etraxfs_dmac_connect_client(etraxfs_dmac, 1, eth[0] + 1);
-    if (eth[1]) {
-        etraxfs_dmac_connect_client(etraxfs_dmac, 6, eth[1]);
-        etraxfs_dmac_connect_client(etraxfs_dmac, 7, eth[1] + 1);
+    etraxfs_dmac_connect_client(etraxfs_dmac, 0, &dma_eth[0]);
+    etraxfs_dmac_connect_client(etraxfs_dmac, 1, &dma_eth[1]);
+    if (nb_nics > 1) {
+        etraxfs_dmac_connect_client(etraxfs_dmac, 6, &dma_eth[2]);
+        etraxfs_dmac_connect_client(etraxfs_dmac, 7, &dma_eth[3]);
     }
 
     /* 2 timers.  */
@@ -346,6 +352,7 @@ static QEMUMachine axisdev88_machine = {
     .name = "axis-dev88",
     .desc = "AXIS devboard 88",
     .init = axisdev88_init,
+    .is_default = 1,
 };
 
 static void axisdev88_machine_init(void)
index e8c57a36ff3e4f3d39a06e5f75cac27bcd3376bb..8708e956887cf24927a3adaeb0db123da9d88ee5 100644 (file)
@@ -42,6 +42,7 @@
 #include "mips.h"
 #include "pci_host.h"
 #include "sysemu.h"
+#include "exec-memory.h"
 
 //#define DEBUG_BONITO
 
@@ -773,7 +774,9 @@ PCIBus *bonito_init(qemu_irq *pic)
     dev = qdev_create(NULL, "Bonito-pcihost");
     pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev));
     b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq,
-                         pci_bonito_map_irq, pic, 0x28, 32);
+                         pci_bonito_map_irq, pic, get_system_memory(),
+                         get_system_io(),
+                         0x28, 32);
     pcihost->bus = b;
     qdev_init_nofail(dev);
 
index 09120af0745ce86a7434ee6ba355c226da33d9c4..5f1afe3e89abf28a1e0098aeb15276c16bc3fdf1 100644 (file)
@@ -19,7 +19,9 @@
  */
 
 #include "qemu-common.h"
-#include "usb.h"
+#include "qemu-timer.h"
+#include "console.h"
+#include "hid.h"
 #include "bt.h"
 
 enum hid_transaction_req {
@@ -86,7 +88,7 @@ struct bt_hid_device_s {
     struct bt_l2cap_device_s btdev;
     struct bt_l2cap_conn_params_s *control;
     struct bt_l2cap_conn_params_s *interrupt;
-    USBDevice *usbdev;
+    HIDState hid;
 
     int proto;
     int connected;
@@ -111,7 +113,7 @@ static void bt_hid_reset(struct bt_hid_device_s *s)
     bt_l2cap_device_done(&s->btdev);
     bt_l2cap_device_init(&s->btdev, net);
 
-    s->usbdev->info->handle_reset(s->usbdev);
+    hid_reset(&s->hid);
     s->proto = BT_HID_PROTO_REPORT;
     s->state = bt_state_ready;
     s->dataother.len = 0;
@@ -124,23 +126,16 @@ static void bt_hid_reset(struct bt_hid_device_s *s)
 
 static int bt_hid_out(struct bt_hid_device_s *s)
 {
-    USBPacket p;
-
     if (s->data_type == BT_DATA_OUTPUT) {
-        p.pid = USB_TOKEN_OUT;
-        p.devep = 1;
-        p.data = s->dataout.buffer;
-        p.len = s->dataout.len;
-        s->dataout.len = s->usbdev->info->handle_data(s->usbdev, &p);
-
-        return s->dataout.len;
+        /* nothing */
+        ;
     }
 
     if (s->data_type == BT_DATA_FEATURE) {
         /* XXX:
          * does this send a USB_REQ_CLEAR_FEATURE/USB_REQ_SET_FEATURE
          * or a SET_REPORT? */
-        p.devep = 0;
+        ;
     }
 
     return -1;
@@ -148,14 +143,8 @@ static int bt_hid_out(struct bt_hid_device_s *s)
 
 static int bt_hid_in(struct bt_hid_device_s *s)
 {
-    USBPacket p;
-
-    p.pid = USB_TOKEN_IN;
-    p.devep = 1;
-    p.data = s->datain.buffer;
-    p.len = sizeof(s->datain.buffer);
-    s->datain.len = s->usbdev->info->handle_data(s->usbdev, &p);
-
+    s->datain.len = hid_keyboard_poll(&s->hid, s->datain.buffer,
+                                      sizeof(s->datain.buffer));
     return s->datain.len;
 }
 
@@ -323,8 +312,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
             break;
         }
         s->proto = parameter;
-        s->usbdev->info->handle_control(s->usbdev, NULL, SET_PROTOCOL, s->proto, 0, 0,
-                                        NULL);
+        s->hid.protocol = parameter;
         ret = BT_HS_SUCCESSFUL;
         break;
 
@@ -333,8 +321,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
             ret = BT_HS_ERR_INVALID_PARAMETER;
             break;
         }
-        s->usbdev->info->handle_control(s->usbdev, NULL, GET_IDLE, 0, 0, 1,
-                        s->control->sdu_out(s->control, 1));
+        *s->control->sdu_out(s->control, 1) = s->hid.idle;
         s->control->sdu_submit(s->control);
         break;
 
@@ -344,11 +331,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
             break;
         }
 
-        /* We don't need to know about the Idle Rate here really,
-         * so just pass it on to the device.  */
-        ret = s->usbdev->info->handle_control(s->usbdev, NULL,
-                        SET_IDLE, data[1], 0, 0, NULL) ?
-                BT_HS_SUCCESSFUL : BT_HS_ERR_INVALID_PARAMETER;
+        s->hid.idle = data[1];
         /* XXX: Does this generate a handshake? */
         break;
 
@@ -385,9 +368,10 @@ static void bt_hid_control_sdu(void *opaque, const uint8_t *data, int len)
     bt_hid_control_transaction(hid, data, len);
 }
 
-static void bt_hid_datain(void *opaque)
+static void bt_hid_datain(HIDState *hs)
 {
-    struct bt_hid_device_s *hid = opaque;
+    struct bt_hid_device_s *hid =
+        container_of(hs, struct bt_hid_device_s, hid);
 
     /* If suspended, wake-up and send a wake-up event first.  We might
      * want to also inspect the input report and ignore event like
@@ -450,7 +434,7 @@ static void bt_hid_connected_update(struct bt_hid_device_s *hid)
     hid->btdev.device.inquiry_scan = !hid->connected;
 
     if (hid->connected && !prev) {
-        hid->usbdev->info->handle_reset(hid->usbdev);
+        hid_reset(&hid->hid);
         hid->proto = BT_HID_PROTO_REPORT;
     }
 
@@ -518,7 +502,7 @@ static void bt_hid_destroy(struct bt_device_s *dev)
         bt_hid_send_control(hid, BT_HC_VIRTUAL_CABLE_UNPLUG);
     bt_l2cap_device_done(&hid->btdev);
 
-    hid->usbdev->info->handle_destroy(hid->usbdev);
+    hid_free(&hid->hid);
 
     qemu_free(hid);
 }
@@ -531,7 +515,7 @@ enum peripheral_minor_class {
 };
 
 static struct bt_device_s *bt_hid_init(struct bt_scatternet_s *net,
-                USBDevice *dev, enum peripheral_minor_class minor)
+                                       enum peripheral_minor_class minor)
 {
     struct bt_hid_device_s *s = qemu_mallocz(sizeof(*s));
     uint32_t class =
@@ -551,9 +535,8 @@ static struct bt_device_s *bt_hid_init(struct bt_scatternet_s *net,
     bt_l2cap_psm_register(&s->btdev, BT_PSM_HID_INTR,
                     BT_HID_MTU, bt_hid_new_interrupt_ch);
 
-    s->usbdev = dev;
-    s->btdev.device.lmp_name = s->usbdev->product_desc;
-    usb_hid_datain_cb(s->usbdev, s, bt_hid_datain);
+    hid_init(&s->hid, HID_KEYBOARD, bt_hid_datain);
+    s->btdev.device.lmp_name = "BT Keyboard";
 
     s->btdev.device.handle_destroy = bt_hid_destroy;
 
@@ -566,6 +549,5 @@ static struct bt_device_s *bt_hid_init(struct bt_scatternet_s *net,
 
 struct bt_device_s *bt_keyboard_init(struct bt_scatternet_s *net)
 {
-    USBDevice *dev = usb_create_simple(NULL /* FIXME */, "usb-kbd");
-    return bt_hid_init(net, dev, class_keyboard);
+    return bt_hid_init(net, class_keyboard);
 }
index f39d1f82ff71272ece7b0a655d19cfab599b2442..b48930994a3c3f8d107323f0b074617436ad79e2 100644 (file)
@@ -32,6 +32,7 @@
 #include "console.h"
 #include "vga_int.h"
 #include "loader.h"
+#include "exec-memory.h"
 
 /*
  * TODO:
@@ -200,9 +201,14 @@ typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
 typedef struct CirrusVGAState {
     VGACommonState vga;
 
-    int cirrus_linear_io_addr;
-    int cirrus_linear_bitblt_io_addr;
-    int cirrus_mmio_io_addr;
+    MemoryRegion cirrus_linear_io;
+    MemoryRegion cirrus_linear_bitblt_io;
+    MemoryRegion cirrus_mmio_io;
+    MemoryRegion pci_bar;
+    bool linear_vram;  /* vga.vram mapped over cirrus_linear_io */
+    MemoryRegion low_mem_container; /* container for 0xa0000-0xc0000 */
+    MemoryRegion low_mem;           /* always mapped, overridden by: */
+    MemoryRegion *cirrus_bank[2];   /*   aliases at 0xa0000-0xb0000  */
     uint32_t cirrus_addr_mask;
     uint32_t linear_mmio_mask;
     uint8_t cirrus_shadow_gr0;
@@ -612,7 +618,7 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
        off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
        off_cur &= TARGET_PAGE_MASK;
        while (off_cur < off_cur_end) {
-           cpu_physical_memory_set_dirty(s->vga.vram_offset + off_cur);
+           memory_region_set_dirty(&s->vga.vram, off_cur);
            off_cur += TARGET_PAGE_SIZE;
        }
        off_begin += off_pitch;
@@ -1177,12 +1183,6 @@ static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
     }
 
     if (limit > 0) {
-        /* Thinking about changing bank base? First, drop the dirty bitmap information
-         * on the current location, otherwise we lose this pointer forever */
-        if (s->vga.lfb_vram_mapped) {
-            target_phys_addr_t base_addr = isa_mem_base + 0xa0000 + bank_index * 0x8000;
-            cpu_physical_sync_dirty_bitmap(base_addr, base_addr + 0x8000);
-        }
        s->cirrus_bank_base[bank_index] = offset;
        s->cirrus_bank_limit[bank_index] = limit;
     } else {
@@ -1921,8 +1921,8 @@ static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
        val <<= 1;
        dst++;
     }
-    cpu_physical_memory_set_dirty(s->vga.vram_offset + offset);
-    cpu_physical_memory_set_dirty(s->vga.vram_offset + offset + 7);
+    memory_region_set_dirty(&s->vga.vram, offset);
+    memory_region_set_dirty(&s->vga.vram, offset + 7);
 }
 
 static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
@@ -1946,8 +1946,8 @@ static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
        val <<= 1;
        dst += 2;
     }
-    cpu_physical_memory_set_dirty(s->vga.vram_offset + offset);
-    cpu_physical_memory_set_dirty(s->vga.vram_offset + offset + 15);
+    memory_region_set_dirty(&s->vga.vram, offset);
+    memory_region_set_dirty(&s->vga.vram, offset + 15);
 }
 
 /***************************************
@@ -1956,7 +1956,9 @@ static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
  *
  ***************************************/
 
-static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t cirrus_vga_mem_read(void *opaque,
+                                    target_phys_addr_t addr,
+                                    uint32_t size)
 {
     CirrusVGAState *s = opaque;
     unsigned bank_index;
@@ -1964,11 +1966,9 @@ static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
     uint32_t val;
 
     if ((s->vga.sr[0x07] & 0x01) == 0) {
-       return vga_mem_readb(s, addr);
+        return vga_mem_readb(&s->vga, addr);
     }
 
-    addr &= 0x1ffff;
-
     if (addr < 0x10000) {
        /* XXX handle bitblt */
        /* video memory */
@@ -2000,28 +2000,10 @@ static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
     return val;
 }
 
-static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_vga_mem_readb(opaque, addr);
-    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_vga_mem_readb(opaque, addr);
-    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
-    v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
-    v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                  uint32_t mem_value)
+static void cirrus_vga_mem_write(void *opaque,
+                                 target_phys_addr_t addr,
+                                 uint64_t mem_value,
+                                 uint32_t size)
 {
     CirrusVGAState *s = opaque;
     unsigned bank_index;
@@ -2029,12 +2011,10 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
     unsigned mode;
 
     if ((s->vga.sr[0x07] & 0x01) == 0) {
-       vga_mem_writeb(s, addr, mem_value);
+        vga_mem_writeb(&s->vga, addr, mem_value);
         return;
     }
 
-    addr &= 0x1ffff;
-
     if (addr < 0x10000) {
        if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
            /* bitblt */
@@ -2057,8 +2037,7 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
                mode = s->vga.gr[0x05] & 0x7;
                if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
                    *(s->vga.vram_ptr + bank_offset) = mem_value;
-                   cpu_physical_memory_set_dirty(s->vga.vram_offset +
-                                                 bank_offset);
+                   memory_region_set_dirty(&s->vga.vram, bank_offset);
                } else {
                    if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
                        cirrus_mem_writeb_mode4and5_8bpp(s, mode,
@@ -2085,30 +2064,14 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
-    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
-    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-static CPUReadMemoryFunc * const cirrus_vga_mem_read[3] = {
-    cirrus_vga_mem_readb,
-    cirrus_vga_mem_readw,
-    cirrus_vga_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const cirrus_vga_mem_write[3] = {
-    cirrus_vga_mem_writeb,
-    cirrus_vga_mem_writew,
-    cirrus_vga_mem_writel,
+static const MemoryRegionOps cirrus_vga_mem_ops = {
+    .read = cirrus_vga_mem_read,
+    .write = cirrus_vga_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 /***************************************
@@ -2287,7 +2250,8 @@ static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
  *
  ***************************************/
 
-static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t cirrus_linear_read(void *opaque, target_phys_addr_t addr,
+                                   unsigned size)
 {
     CirrusVGAState *s = opaque;
     uint32_t ret;
@@ -2315,28 +2279,8 @@ static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_linear_readb(opaque, addr);
-    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_linear_readb(opaque, addr);
-    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
-    v |= cirrus_linear_readb(opaque, addr + 2) << 16;
-    v |= cirrus_linear_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
+static void cirrus_linear_write(void *opaque, target_phys_addr_t addr,
+                                uint64_t val, unsigned size)
 {
     CirrusVGAState *s = opaque;
     unsigned mode;
@@ -2365,7 +2309,7 @@ static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
        mode = s->vga.gr[0x05] & 0x7;
        if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
            *(s->vga.vram_ptr + addr) = (uint8_t) val;
-           cpu_physical_memory_set_dirty(s->vga.vram_offset + addr);
+           memory_region_set_dirty(&s->vga.vram, addr);
        } else {
            if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
                cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
@@ -2376,35 +2320,6 @@ static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
-{
-    cirrus_linear_writeb(opaque, addr, val & 0xff);
-    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
-{
-    cirrus_linear_writeb(opaque, addr, val & 0xff);
-    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-
-static CPUReadMemoryFunc * const cirrus_linear_read[3] = {
-    cirrus_linear_readb,
-    cirrus_linear_readw,
-    cirrus_linear_readl,
-};
-
-static CPUWriteMemoryFunc * const cirrus_linear_write[3] = {
-    cirrus_linear_writeb,
-    cirrus_linear_writew,
-    cirrus_linear_writel,
-};
-
 /***************************************
  *
  *  system to screen memory access
@@ -2412,37 +2327,23 @@ static CPUWriteMemoryFunc * const cirrus_linear_write[3] = {
  ***************************************/
 
 
-static uint32_t cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t cirrus_linear_bitblt_read(void *opaque,
+                                          target_phys_addr_t addr,
+                                          unsigned size)
 {
+    CirrusVGAState *s = opaque;
     uint32_t ret;
 
     /* XXX handle bitblt */
+    (void)s;
     ret = 0xff;
     return ret;
 }
 
-static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_linear_bitblt_readb(opaque, addr);
-    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_linear_bitblt_readb(opaque, addr);
-    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
-    v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16;
-    v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
+static void cirrus_linear_bitblt_write(void *opaque,
+                                       target_phys_addr_t addr,
+                                       uint64_t val,
+                                       unsigned size)
 {
     CirrusVGAState *s = opaque;
 
@@ -2455,83 +2356,70 @@ static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
-{
-    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
-    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
-{
-    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
-    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-
-static CPUReadMemoryFunc * const cirrus_linear_bitblt_read[3] = {
-    cirrus_linear_bitblt_readb,
-    cirrus_linear_bitblt_readw,
-    cirrus_linear_bitblt_readl,
-};
-
-static CPUWriteMemoryFunc * const cirrus_linear_bitblt_write[3] = {
-    cirrus_linear_bitblt_writeb,
-    cirrus_linear_bitblt_writew,
-    cirrus_linear_bitblt_writel,
+static const MemoryRegionOps cirrus_linear_bitblt_io_ops = {
+    .read = cirrus_linear_bitblt_read,
+    .write = cirrus_linear_bitblt_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
-static void map_linear_vram(CirrusVGAState *s)
+static void unmap_bank(CirrusVGAState *s, unsigned bank)
 {
-    if (!s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
-        s->vga.map_addr = s->vga.lfb_addr;
-        s->vga.map_end = s->vga.lfb_end;
-        cpu_register_physical_memory_log(s->vga.map_addr,
-                                        s->vga.map_end - s->vga.map_addr,
-                                        s->vga.vram_offset, 0, true);
+    if (s->cirrus_bank[bank]) {
+        memory_region_del_subregion(&s->low_mem_container,
+                                    s->cirrus_bank[bank]);
+        memory_region_destroy(s->cirrus_bank[bank]);
+        qemu_free(s->cirrus_bank[bank]);
+        s->cirrus_bank[bank] = NULL;
     }
+}
 
-    if (!s->vga.map_addr)
-        return;
-
-    s->vga.lfb_vram_mapped = 0;
+static void map_linear_vram_bank(CirrusVGAState *s, unsigned bank)
+{
+    MemoryRegion *mr;
+    static const char *names[] = { "vga.bank0", "vga.bank1" };
 
     if (!(s->cirrus_srcptr != s->cirrus_srcptr_end)
         && !((s->vga.sr[0x07] & 0x01) == 0)
         && !((s->vga.gr[0x0B] & 0x14) == 0x14)
         && !(s->vga.gr[0x0B] & 0x02)) {
 
-        cpu_register_physical_memory_log(isa_mem_base + 0xa0000, 0x8000,
-                                        (s->vga.vram_offset +
-                                         s->cirrus_bank_base[0]) |
-                                        IO_MEM_RAM, 0, true);
-        cpu_register_physical_memory_log(isa_mem_base + 0xa8000, 0x8000,
-                                        (s->vga.vram_offset +
-                                         s->cirrus_bank_base[1]) |
-                                        IO_MEM_RAM, 0, true);
-
-        s->vga.lfb_vram_mapped = 1;
-    }
-    else {
-        cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
-                                     s->vga.vga_io_memory);
+        mr = qemu_malloc(sizeof(*mr));
+        memory_region_init_alias(mr, names[bank], &s->vga.vram,
+                                 s->cirrus_bank_base[bank], 0x8000);
+        memory_region_add_subregion_overlap(
+            &s->low_mem_container,
+            0x8000 * bank,
+            mr,
+            1);
+        unmap_bank(s, bank);
+        s->cirrus_bank[bank] = mr;
+    } else {
+        unmap_bank(s, bank);
     }
+}
 
-    vga_dirty_log_start(&s->vga);
+static void map_linear_vram(CirrusVGAState *s)
+{
+    if (!s->linear_vram) {
+        s->linear_vram = true;
+        memory_region_add_subregion_overlap(&s->pci_bar, 0, &s->vga.vram, 1);
+    }
+    map_linear_vram_bank(s, 0);
+    map_linear_vram_bank(s, 1);
 }
 
 static void unmap_linear_vram(CirrusVGAState *s)
 {
-    if (s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
-        s->vga.map_addr = s->vga.map_end = 0;
-         cpu_register_physical_memory(s->vga.lfb_addr, s->vga.vram_size,
-                                      s->cirrus_linear_io_addr);
+    if (s->linear_vram) {
+        s->linear_vram = false;
+        memory_region_del_subregion(&s->pci_bar, &s->vga.vram);
     }
-    cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
-                                 s->vga.vga_io_memory);
+    unmap_bank(s, 0);
+    unmap_bank(s, 1);
 }
 
 /* Compute the memory access functions */
@@ -2765,12 +2653,11 @@ static void cirrus_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
  *
  ***************************************/
 
-static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t cirrus_mmio_read(void *opaque, target_phys_addr_t addr,
+                                 unsigned size)
 {
     CirrusVGAState *s = opaque;
 
-    addr &= CIRRUS_PNPMMIO_SIZE - 1;
-
     if (addr >= 0x100) {
         return cirrus_mmio_blt_read(s, addr - 0x100);
     } else {
@@ -2778,33 +2665,11 @@ static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_mmio_readb(opaque, addr);
-    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_mmio_readb(opaque, addr);
-    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
-    v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
-    v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
-                              uint32_t val)
+static void cirrus_mmio_write(void *opaque, target_phys_addr_t addr,
+                              uint64_t val, unsigned size)
 {
     CirrusVGAState *s = opaque;
 
-    addr &= CIRRUS_PNPMMIO_SIZE - 1;
-
     if (addr >= 0x100) {
        cirrus_mmio_blt_write(s, addr - 0x100, val);
     } else {
@@ -2812,33 +2677,14 @@ static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
-                              uint32_t val)
-{
-    cirrus_mmio_writeb(opaque, addr, val & 0xff);
-    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
-                              uint32_t val)
-{
-    cirrus_mmio_writeb(opaque, addr, val & 0xff);
-    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-
-static CPUReadMemoryFunc * const cirrus_mmio_read[3] = {
-    cirrus_mmio_readb,
-    cirrus_mmio_readw,
-    cirrus_mmio_readl,
-};
-
-static CPUWriteMemoryFunc * const cirrus_mmio_write[3] = {
-    cirrus_mmio_writeb,
-    cirrus_mmio_writew,
-    cirrus_mmio_writel,
+static const MemoryRegionOps cirrus_mmio_io_ops = {
+    .read = cirrus_mmio_read,
+    .write = cirrus_mmio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 /* load/save state */
@@ -2947,6 +2793,16 @@ static void cirrus_reset(void *opaque)
     s->cirrus_hidden_dac_data = 0;
 }
 
+static const MemoryRegionOps cirrus_linear_io_ops = {
+    .read = cirrus_linear_read,
+    .write = cirrus_linear_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
 static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
 {
     int i;
@@ -2993,28 +2849,33 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
     register_ioport_read(0x3ba, 1, 1, cirrus_vga_ioport_read, s);
     register_ioport_read(0x3da, 1, 1, cirrus_vga_ioport_read, s);
 
-    s->vga.vga_io_memory = cpu_register_io_memory(cirrus_vga_mem_read,
-                                                  cirrus_vga_mem_write, s,
-                                                  DEVICE_LITTLE_ENDIAN);
-    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
-                                 s->vga.vga_io_memory);
-    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
+    memory_region_init(&s->low_mem_container,
+                       "cirrus-lowmem-container",
+                       0x20000);
+
+    memory_region_init_io(&s->low_mem, &cirrus_vga_mem_ops, s,
+                          "cirrus-low-memory", 0x20000);
+    memory_region_add_subregion(&s->low_mem_container, 0, &s->low_mem);
+    memory_region_add_subregion_overlap(get_system_memory(),
+                                        isa_mem_base + 0x000a0000,
+                                        &s->low_mem_container,
+                                        1);
+    memory_region_set_coalescing(&s->low_mem);
 
     /* I/O handler for LFB */
-    s->cirrus_linear_io_addr =
-        cpu_register_io_memory(cirrus_linear_read, cirrus_linear_write, s,
-                               DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&s->cirrus_linear_io, &cirrus_linear_io_ops, s,
+                          "cirrus-linear-io", VGA_RAM_SIZE);
 
     /* I/O handler for LFB */
-    s->cirrus_linear_bitblt_io_addr =
-        cpu_register_io_memory(cirrus_linear_bitblt_read,
-                               cirrus_linear_bitblt_write, s,
-                               DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&s->cirrus_linear_bitblt_io,
+                          &cirrus_linear_bitblt_io_ops,
+                          s,
+                          "cirrus-bitblt-mmio",
+                          0x400000);
 
     /* I/O handler for memory-mapped I/O */
-    s->cirrus_mmio_io_addr =
-        cpu_register_io_memory(cirrus_mmio_read, cirrus_mmio_write, s,
-                               DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&s->cirrus_mmio_io, &cirrus_mmio_io_ops, s,
+                          "cirrus-mmio", CIRRUS_PNPMMIO_SIZE);
 
     s->real_vram_size =
         (s->device_id == CIRRUS_ID_CLGD5446) ? 4096 * 1024 : 2048 * 1024;
@@ -3060,42 +2921,6 @@ void isa_cirrus_vga_init(void)
  *
  ***************************************/
 
-static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
-                              pcibus_t addr, pcibus_t size, int type)
-{
-    CirrusVGAState *s = &DO_UPCAST(PCICirrusVGAState, dev, d)->cirrus_vga;
-
-    /* XXX: add byte swapping apertures */
-    cpu_register_physical_memory(addr, s->vga.vram_size,
-                                s->cirrus_linear_io_addr);
-    cpu_register_physical_memory(addr + 0x1000000, 0x400000,
-                                s->cirrus_linear_bitblt_io_addr);
-
-    s->vga.map_addr = s->vga.map_end = 0;
-    s->vga.lfb_addr = addr & TARGET_PAGE_MASK;
-    s->vga.lfb_end = ((addr + VGA_RAM_SIZE) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
-    /* account for overflow */
-    if (s->vga.lfb_end < addr + VGA_RAM_SIZE)
-        s->vga.lfb_end = addr + VGA_RAM_SIZE;
-
-    vga_dirty_log_start(&s->vga);
-}
-
-static void pci_cirrus_write_config(PCIDevice *d,
-                                    uint32_t address, uint32_t val, int len)
-{
-    PCICirrusVGAState *pvs = DO_UPCAST(PCICirrusVGAState, dev, d);
-    CirrusVGAState *s = &pvs->cirrus_vga;
-
-    pci_default_write_config(d, address, val, len);
-    if (s->vga.map_addr && d->io_regions[0].addr == PCI_BAR_UNMAPPED) {
-        s->vga.map_addr = 0;
-        s->vga.lfb_addr = 0;
-        s->vga.lfb_end = 0;
-    }
-    cirrus_update_memory_access(s);
-}
-
 static int pci_cirrus_vga_initfn(PCIDevice *dev)
 {
      PCICirrusVGAState *d = DO_UPCAST(PCICirrusVGAState, dev, dev);
@@ -3112,15 +2937,20 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
 
      /* setup PCI */
 
+    memory_region_init(&s->pci_bar, "cirrus-pci-bar0", 0x2000000);
+
+    /* XXX: add byte swapping apertures */
+    memory_region_add_subregion(&s->pci_bar, 0, &s->cirrus_linear_io);
+    memory_region_add_subregion(&s->pci_bar, 0x1000000,
+                                &s->cirrus_linear_bitblt_io);
+
      /* setup memory space */
      /* memory #0 LFB */
      /* memory #1 memory-mapped I/O */
      /* XXX: s->vga.vram_size must be a power of two */
-     pci_register_bar(&d->dev, 0, 0x2000000,
-                      PCI_BASE_ADDRESS_MEM_PREFETCH, cirrus_pci_lfb_map);
+     pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->pci_bar);
      if (device_id == CIRRUS_ID_CLGD5446) {
-         pci_register_bar_simple(&d->dev, 1, CIRRUS_PNPMMIO_SIZE, 0,
-                                 s->cirrus_mmio_io_addr);
+         pci_register_bar(&d->dev, 1, 0, &s->cirrus_mmio_io);
      }
      return 0;
 }
@@ -3138,7 +2968,6 @@ static PCIDeviceInfo cirrus_vga_info = {
     .no_hotplug   = 1,
     .init         = pci_cirrus_vga_initfn,
     .romfile      = VGABIOS_CIRRUS_FILENAME,
-    .config_write = pci_cirrus_write_config,
     .vendor_id    = PCI_VENDOR_ID_CIRRUS,
     .device_id    = CIRRUS_ID_CLGD5446,
     .class_id     = PCI_CLASS_DISPLAY_VGA,
index 065c362aefb9898f1d4447b70e2bddb1bfe9274b..5c92d81b4b2af5d82b25e053bc8a6f027b83b691 100644 (file)
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -117,6 +117,7 @@ typedef struct CUDATimer {
 } CUDATimer;
 
 typedef struct CUDAState {
+    MemoryRegion mem;
     /* cuda registers */
     uint8_t b;      /* B-side data */
     uint8_t a;      /* A-side data */
@@ -722,7 +723,7 @@ static void cuda_reset(void *opaque)
     set_counter(s, &s->timers[1], 0xffff);
 }
 
-void cuda_init (int *cuda_mem_index, qemu_irq irq)
+void cuda_init (MemoryRegion **cuda_mem, qemu_irq irq)
 {
     struct tm tm;
     CUDAState *s = &cuda_state;
@@ -738,8 +739,9 @@ void cuda_init (int *cuda_mem_index, qemu_irq irq)
     s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
 
     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,
+    cpu_register_io_memory(cuda_read, cuda_write, s,
                                              DEVICE_NATIVE_ENDIAN);
+    *cuda_mem = &s->mem;
     vmstate_register(NULL, -1, &vmstate_cuda, s);
     qemu_register_reset(cuda_reset, s);
 }
index 96d84f91ae1633fda0c4c3402e943ec94de4967c..29b453f7b122422def5099fd2611f72d7bb9511a 100644 (file)
@@ -82,7 +82,8 @@ typedef struct E1000State_st {
     PCIDevice dev;
     NICState *nic;
     NICConf conf;
-    int mmio_index;
+    MemoryRegion mmio;
+    MemoryRegion io;
 
     uint32_t mac_reg[0x8000];
     uint16_t phy_reg[0x20];
@@ -150,14 +151,6 @@ static const char phy_regcap[0x20] = {
     [PHY_ID2] = PHY_R,         [M88E1000_PHY_SPEC_STATUS] = PHY_R
 };
 
-static void
-ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr,
-           pcibus_t size, int type)
-{
-    DBGOUT(IO, "e1000_ioport_map addr=0x%04"FMT_PCIBUS
-           " size=0x%08"FMT_PCIBUS"\n", addr, size);
-}
-
 static void
 set_interrupt_cause(E1000State *s, int index, uint32_t val)
 {
@@ -905,7 +898,8 @@ static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
 enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) };
 
 static void
-e1000_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+e1000_mmio_write(void *opaque, target_phys_addr_t addr, uint64_t val,
+                 unsigned size)
 {
     E1000State *s = opaque;
     unsigned int index = (addr & 0x1ffff) >> 2;
@@ -913,31 +907,15 @@ e1000_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     if (index < NWRITEOPS && macreg_writeops[index]) {
         macreg_writeops[index](s, index, val);
     } else if (index < NREADOPS && macreg_readops[index]) {
-        DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04x\n", index<<2, val);
+        DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04"PRIx64"\n", index<<2, val);
     } else {
-        DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08x\n",
+        DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08"PRIx64"\n",
                index<<2, val);
     }
 }
 
-static void
-e1000_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    // emulate hw without byte enables: no RMW
-    e1000_mmio_writel(opaque, addr & ~3,
-                      (val & 0xffff) << (8*(addr & 3)));
-}
-
-static void
-e1000_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    // emulate hw without byte enables: no RMW
-    e1000_mmio_writel(opaque, addr & ~3,
-                      (val & 0xff) << (8*(addr & 3)));
-}
-
-static uint32_t
-e1000_mmio_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t
+e1000_mmio_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     E1000State *s = opaque;
     unsigned int index = (addr & 0x1ffff) >> 2;
@@ -950,20 +928,39 @@ e1000_mmio_readl(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static uint32_t
-e1000_mmio_readb(void *opaque, target_phys_addr_t addr)
+static const MemoryRegionOps e1000_mmio_ops = {
+    .read = e1000_mmio_read,
+    .write = e1000_mmio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static uint64_t e1000_io_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
-    return ((e1000_mmio_readl(opaque, addr & ~3)) >>
-            (8 * (addr & 3))) & 0xff;
+    E1000State *s = opaque;
+
+    (void)s;
+    return 0;
 }
 
-static uint32_t
-e1000_mmio_readw(void *opaque, target_phys_addr_t addr)
+static void e1000_io_write(void *opaque, target_phys_addr_t addr,
+                           uint64_t val, unsigned size)
 {
-    return ((e1000_mmio_readl(opaque, addr & ~3)) >>
-            (8 * (addr & 3))) & 0xffff;
+    E1000State *s = opaque;
+
+    (void)s;
 }
 
+static const MemoryRegionOps e1000_io_ops = {
+    .read = e1000_io_read,
+    .write = e1000_io_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 static bool is_version_1(void *opaque, int version_id)
 {
     return version_id == 1;
@@ -1083,36 +1080,22 @@ static const uint32_t mac_reg_init[] = {
 
 /* PCI interface */
 
-static CPUWriteMemoryFunc * const e1000_mmio_write[] = {
-    e1000_mmio_writeb, e1000_mmio_writew,      e1000_mmio_writel
-};
-
-static CPUReadMemoryFunc * const e1000_mmio_read[] = {
-    e1000_mmio_readb,  e1000_mmio_readw,       e1000_mmio_readl
-};
-
 static void
-e1000_mmio_map(PCIDevice *pci_dev, int region_num,
-                pcibus_t addr, pcibus_t size, int type)
+e1000_mmio_setup(E1000State *d)
 {
-    E1000State *d = DO_UPCAST(E1000State, dev, pci_dev);
     int i;
     const uint32_t excluded_regs[] = {
         E1000_MDIC, E1000_ICR, E1000_ICS, E1000_IMS,
         E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE
     };
 
-
-    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
-           addr, size);
-
-    cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);
-    qemu_register_coalesced_mmio(addr, excluded_regs[0]);
-
+    memory_region_init_io(&d->mmio, &e1000_mmio_ops, d, "e1000-mmio",
+                          PNPMMIO_SIZE);
+    memory_region_add_coalescing(&d->mmio, 0, excluded_regs[0]);
     for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++)
-        qemu_register_coalesced_mmio(addr + excluded_regs[i] + 4,
-                                     excluded_regs[i + 1] -
-                                     excluded_regs[i] - 4);
+        memory_region_add_coalescing(&d->mmio, excluded_regs[i] + 4,
+                                     excluded_regs[i+1] - excluded_regs[i] - 4);
+    memory_region_init_io(&d->io, &e1000_io_ops, d, "e1000-io", IOPORT_SIZE);
 }
 
 static void
@@ -1128,7 +1111,8 @@ pci_e1000_uninit(PCIDevice *dev)
 {
     E1000State *d = DO_UPCAST(E1000State, dev, dev);
 
-    cpu_unregister_io_memory(d->mmio_index);
+    memory_region_destroy(&d->mmio);
+    memory_region_destroy(&d->io);
     qemu_del_vlan_client(&d->nic->nc);
     return 0;
 }
@@ -1172,14 +1156,11 @@ static int pci_e1000_init(PCIDevice *pci_dev)
     /* TODO: RST# value should be 0 if programmable, PCI spec 6.2.4 */
     pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0
 
-    d->mmio_index = cpu_register_io_memory(e1000_mmio_read,
-            e1000_mmio_write, d, DEVICE_LITTLE_ENDIAN);
+    e1000_mmio_setup(d);
 
-    pci_register_bar(&d->dev, 0, PNPMMIO_SIZE,
-                           PCI_BASE_ADDRESS_SPACE_MEMORY, e1000_mmio_map);
+    pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
 
-    pci_register_bar(&d->dev, 1, IOPORT_SIZE,
-                           PCI_BASE_ADDRESS_SPACE_IO, ioport_map);
+    pci_register_bar(&d->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io);
 
     memmove(d->eeprom_data, e1000_eeprom_template,
         sizeof e1000_eeprom_template);
index 9b6f4a5cd818da51033da53a4349203de85dac79..a636d309bef74b6d31908cca111460c43695bce4 100644 (file)
@@ -228,13 +228,14 @@ typedef struct {
     PCIDevice dev;
     /* Hash register (multicast mask array, multiple individual addresses). */
     uint8_t mult[8];
-    int mmio_index;
+    MemoryRegion mmio_bar;
+    MemoryRegion io_bar;
+    MemoryRegion flash_bar;
     NICState *nic;
     NICConf conf;
     uint8_t scb_stat;           /* SCB stat/ack byte */
     uint8_t int_stat;           /* PCI interrupt status */
     /* region must not be saved by nic_save. */
-    uint32_t region1;           /* PCI region 1 address */
     uint16_t mdimem[32];
     eeprom_t *eeprom;
     uint32_t device;            /* device variant */
@@ -1584,147 +1585,36 @@ static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
     }
 }
 
-/*****************************************************************************
- *
- * Port mapped I/O.
- *
- ****************************************************************************/
-
-static uint32_t ioport_read1(void *opaque, uint32_t addr)
-{
-    EEPRO100State *s = opaque;
-#if 0
-    logout("addr=%s\n", regname(addr));
-#endif
-    return eepro100_read1(s, addr - s->region1);
-}
-
-static uint32_t ioport_read2(void *opaque, uint32_t addr)
-{
-    EEPRO100State *s = opaque;
-    return eepro100_read2(s, addr - s->region1);
-}
-
-static uint32_t ioport_read4(void *opaque, uint32_t addr)
-{
-    EEPRO100State *s = opaque;
-    return eepro100_read4(s, addr - s->region1);
-}
-
-static void ioport_write1(void *opaque, uint32_t addr, uint32_t val)
-{
-    EEPRO100State *s = opaque;
-#if 0
-    logout("addr=%s val=0x%02x\n", regname(addr), val);
-#endif
-    eepro100_write1(s, addr - s->region1, val);
-}
-
-static void ioport_write2(void *opaque, uint32_t addr, uint32_t val)
-{
-    EEPRO100State *s = opaque;
-    eepro100_write2(s, addr - s->region1, val);
-}
-
-static void ioport_write4(void *opaque, uint32_t addr, uint32_t val)
-{
-    EEPRO100State *s = opaque;
-    eepro100_write4(s, addr - s->region1, val);
-}
-
-/***********************************************************/
-/* PCI EEPRO100 definitions */
-
-static void pci_map(PCIDevice * pci_dev, int region_num,
-                    pcibus_t addr, pcibus_t size, int type)
-{
-    EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
-
-    TRACE(OTHER, logout("region %d, addr=0x%08"FMT_PCIBUS", "
-          "size=0x%08"FMT_PCIBUS", type=%d\n",
-          region_num, addr, size, type));
-
-    assert(region_num == 1);
-    register_ioport_write(addr, size, 1, ioport_write1, s);
-    register_ioport_read(addr, size, 1, ioport_read1, s);
-    register_ioport_write(addr, size, 2, ioport_write2, s);
-    register_ioport_read(addr, size, 2, ioport_read2, s);
-    register_ioport_write(addr, size, 4, ioport_write4, s);
-    register_ioport_read(addr, size, 4, ioport_read4, s);
-
-    s->region1 = addr;
-}
-
-/*****************************************************************************
- *
- * Memory mapped I/O.
- *
- ****************************************************************************/
-
-static void pci_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    EEPRO100State *s = opaque;
-#if 0
-    logout("addr=%s val=0x%02x\n", regname(addr), val);
-#endif
-    eepro100_write1(s, addr, val);
-}
-
-static void pci_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+static uint64_t eepro100_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     EEPRO100State *s = opaque;
-#if 0
-    logout("addr=%s val=0x%02x\n", regname(addr), val);
-#endif
-    eepro100_write2(s, addr, val);
-}
 
-static void pci_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    EEPRO100State *s = opaque;
-#if 0
-    logout("addr=%s val=0x%02x\n", regname(addr), val);
-#endif
-    eepro100_write4(s, addr, val);
-}
-
-static uint32_t pci_mmio_readb(void *opaque, target_phys_addr_t addr)
-{
-    EEPRO100State *s = opaque;
-#if 0
-    logout("addr=%s\n", regname(addr));
-#endif
-    return eepro100_read1(s, addr);
+    switch (size) {
+    case 1: return eepro100_read1(s, addr);
+    case 2: return eepro100_read2(s, addr);
+    case 4: return eepro100_read4(s, addr);
+    default: abort();
+    }
 }
 
-static uint32_t pci_mmio_readw(void *opaque, target_phys_addr_t addr)
+static void eepro100_write(void *opaque, target_phys_addr_t addr,
+                           uint64_t data, unsigned size)
 {
     EEPRO100State *s = opaque;
-#if 0
-    logout("addr=%s\n", regname(addr));
-#endif
-    return eepro100_read2(s, addr);
-}
 
-static uint32_t pci_mmio_readl(void *opaque, target_phys_addr_t addr)
-{
-    EEPRO100State *s = opaque;
-#if 0
-    logout("addr=%s\n", regname(addr));
-#endif
-    return eepro100_read4(s, addr);
+    switch (size) {
+    case 1: return eepro100_write1(s, addr, data);
+    case 2: return eepro100_write2(s, addr, data);
+    case 4: return eepro100_write4(s, addr, data);
+    default: abort();
+    }
 }
 
-static CPUWriteMemoryFunc * const pci_mmio_write[] = {
-    pci_mmio_writeb,
-    pci_mmio_writew,
-    pci_mmio_writel
-};
-
-static CPUReadMemoryFunc * const pci_mmio_read[] = {
-    pci_mmio_readb,
-    pci_mmio_readw,
-    pci_mmio_readl
+static const MemoryRegionOps eepro100_ops = {
+    .read = eepro100_read,
+    .write = eepro100_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static int nic_can_receive(VLANClientState *nc)
@@ -1953,7 +1843,9 @@ static int pci_nic_uninit(PCIDevice *pci_dev)
 {
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
-    cpu_unregister_io_memory(s->mmio_index);
+    memory_region_destroy(&s->mmio_bar);
+    memory_region_destroy(&s->io_bar);
+    memory_region_destroy(&s->flash_bar);
     vmstate_unregister(&pci_dev->qdev, s->vmstate, s);
     eeprom93xx_free(&pci_dev->qdev, s->eeprom);
     qemu_del_vlan_client(&s->nic->nc);
@@ -1985,20 +1877,19 @@ static int e100_nic_init(PCIDevice *pci_dev)
     s->eeprom = eeprom93xx_new(&pci_dev->qdev, EEPROM_SIZE);
 
     /* Handler for memory-mapped I/O */
-    s->mmio_index =
-        cpu_register_io_memory(pci_mmio_read, pci_mmio_write, s,
-                               DEVICE_LITTLE_ENDIAN);
-
-    pci_register_bar_simple(&s->dev, 0, PCI_MEM_SIZE,
-                            PCI_BASE_ADDRESS_MEM_PREFETCH, s->mmio_index);
-
-    pci_register_bar(&s->dev, 1, PCI_IO_SIZE, PCI_BASE_ADDRESS_SPACE_IO,
-                           pci_map);
-    pci_register_bar_simple(&s->dev, 2, PCI_FLASH_SIZE, 0, s->mmio_index);
+    memory_region_init_io(&s->mmio_bar, &eepro100_ops, s, "eepro100-mmio",
+                          PCI_MEM_SIZE);
+    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->mmio_bar);
+    memory_region_init_io(&s->io_bar, &eepro100_ops, s, "eepro100-io",
+                          PCI_IO_SIZE);
+    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
+    /* FIXME: flash aliases to mmio?! */
+    memory_region_init_io(&s->flash_bar, &eepro100_ops, s, "eepro100-flash",
+                          PCI_FLASH_SIZE);
+    pci_register_bar(&s->dev, 2, 0, &s->flash_bar);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     logout("macaddr: %s\n", nic_dump(&s->conf.macaddr.a[0], 6));
-    assert(s->region1 == 0);
 
     nic_reset(s);
 
index 1ed62b7da3a66c3cb6e638acc40510dfb0370fc2..a9387d15cc25597321e0555e4c815a34a79674a4 100644 (file)
@@ -268,6 +268,7 @@ struct chan {
 typedef struct ES1370State {
     PCIDevice dev;
     QEMUSoundCard card;
+    MemoryRegion io;
     struct chan chan[NB_CHANNELS];
     SWVoiceOut *dac_voice[2];
     SWVoiceIn *adc_voice;
@@ -775,7 +776,6 @@ IO_READ_PROTO (es1370_readl)
     return val;
 }
 
-
 static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
                                    int max, int *irq)
 {
@@ -906,23 +906,20 @@ static void es1370_adc_callback (void *opaque, int avail)
     es1370_run_channel (s, ADC_CHANNEL, avail);
 }
 
-static void es1370_map (PCIDevice *pci_dev, int region_num,
-                        pcibus_t addr, pcibus_t size, int type)
-{
-    ES1370State *s = DO_UPCAST (ES1370State, dev, pci_dev);
-
-    (void) region_num;
-    (void) size;
-    (void) type;
-
-    register_ioport_write (addr, 0x40 * 4, 1, es1370_writeb, s);
-    register_ioport_write (addr, 0x40 * 2, 2, es1370_writew, s);
-    register_ioport_write (addr, 0x40, 4, es1370_writel, s);
+static const MemoryRegionPortio es1370_portio[] = {
+    { 0, 0x40 * 4, 1, .write = es1370_writeb, },
+    { 0, 0x40 * 2, 2, .write = es1370_writew, },
+    { 0, 0x40, 4, .write = es1370_writel, },
+    { 0, 0x40 * 4, 1, .read = es1370_readb, },
+    { 0, 0x40 * 2, 2, .read = es1370_readw, },
+    { 0, 0x40, 4, .read = es1370_readl, },
+    PORTIO_END_OF_LIST()
+};
 
-    register_ioport_read (addr, 0x40 * 4, 1, es1370_readb, s);
-    register_ioport_read (addr, 0x40 * 2, 2, es1370_readw, s);
-    register_ioport_read (addr, 0x40, 4, es1370_readl, s);
-}
+static const MemoryRegionOps es1370_io_ops = {
+    .old_portio = es1370_portio,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
 
 static const VMStateDescription vmstate_es1370_channel = {
     .name = "es1370_channel",
@@ -1011,7 +1008,8 @@ static int es1370_initfn (PCIDevice *dev)
     c[PCI_MIN_GNT] = 0x0c;
     c[PCI_MAX_LAT] = 0x80;
 
-    pci_register_bar (&s->dev, 0, 256, PCI_BASE_ADDRESS_SPACE_IO, es1370_map);
+    memory_region_init_io (&s->io, &es1370_io_ops, s, "es1370", 256);
+    pci_register_bar (&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
     qemu_register_reset (es1370_on_reset, s);
 
     AUD_register_card ("es1370", &s->card);
@@ -1019,6 +1017,14 @@ static int es1370_initfn (PCIDevice *dev)
     return 0;
 }
 
+static int es1370_exitfn(PCIDevice *dev)
+{
+    ES1370State *s = DO_UPCAST (ES1370State, dev, dev);
+
+    memory_region_destroy (&s->io);
+    return 0;
+}
+
 int es1370_init (PCIBus *bus)
 {
     pci_create_simple (bus, -1, "ES1370");
@@ -1031,6 +1037,7 @@ static PCIDeviceInfo es1370_info = {
     .qdev.size    = sizeof (ES1370State),
     .qdev.vmsd    = &vmstate_es1370,
     .init         = es1370_initfn,
+    .exit         = es1370_exitfn,
     .vendor_id    = PCI_VENDOR_ID_ENSONIQ,
     .device_id    = PCI_DEVICE_ID_ENSONIQ_ES1370,
     .class_id     = PCI_CLASS_MULTIMEDIA_AUDIO,
index f6fd9192eaf28f3ca53a92f04f7848e7f81788c5..bea5873a02cddc55be2b699d51bcdc61ca9e6159 100644 (file)
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -126,7 +126,7 @@ struct SerialState {
     SysBusDevice busdev;
     struct ChannelState chn[2];
     uint32_t it_shift;
-    int mmio_index;
+    MemoryRegion mmio;
     uint32_t disabled;
     uint32_t frequency;
 };
@@ -490,7 +490,8 @@ static void escc_update_parameters(ChannelState *s)
     qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
 }
 
-static void escc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void escc_mem_write(void *opaque, target_phys_addr_t addr,
+                           uint64_t val, unsigned size)
 {
     SerialState *serial = opaque;
     ChannelState *s;
@@ -592,7 +593,8 @@ static void escc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static uint32_t escc_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t escc_mem_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     SerialState *serial = opaque;
     ChannelState *s;
@@ -627,6 +629,16 @@ static uint32_t escc_mem_readb(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
+static const MemoryRegionOps escc_mem_ops = {
+    .read = escc_mem_read,
+    .write = escc_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
 static int serial_can_receive(void *opaque)
 {
     ChannelState *s = opaque;
@@ -668,18 +680,6 @@ static void serial_event(void *opaque, int event)
         serial_receive_break(s);
 }
 
-static CPUReadMemoryFunc * const escc_mem_read[3] = {
-    escc_mem_readb,
-    NULL,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const escc_mem_write[3] = {
-    escc_mem_writeb,
-    NULL,
-    NULL,
-};
-
 static const VMStateDescription vmstate_escc_chn = {
     .name ="escc_chn",
     .version_id = 2,
@@ -712,7 +712,7 @@ static const VMStateDescription vmstate_escc = {
     }
 };
 
-int escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB,
+MemoryRegion *escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB,
               CharDriverState *chrA, CharDriverState *chrB,
               int clock, int it_shift)
 {
@@ -737,7 +737,7 @@ int escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB,
     }
 
     d = FROM_SYSBUS(SerialState, s);
-    return d->mmio_index;
+    return &d->mmio;
 }
 
 static const uint8_t keycodes[128] = {
@@ -901,7 +901,6 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
 static int escc_init1(SysBusDevice *dev)
 {
     SerialState *s = FROM_SYSBUS(SerialState, dev);
-    int io;
     unsigned int i;
 
     s->chn[0].disabled = s->disabled;
@@ -918,10 +917,9 @@ static int escc_init1(SysBusDevice *dev)
     s->chn[0].otherchn = &s->chn[1];
     s->chn[1].otherchn = &s->chn[0];
 
-    io = cpu_register_io_memory(escc_mem_read, escc_mem_write, s,
-                                DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, ESCC_SIZE << s->it_shift, io);
-    s->mmio_index = io;
+    memory_region_init_io(&s->mmio, &escc_mem_ops, s, "escc",
+                          ESCC_SIZE << s->it_shift);
+    sysbus_init_mmio_region(dev, &s->mmio);
 
     if (s->chn[0].type == mouse) {
         qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
index 015b9d0089ebd0ec779d780d62a9aa4dc30d6109..d1da46fd06c7bff4d6add21fad20d487af4284e0 100644 (file)
--- a/hw/escc.h
+++ b/hw/escc.h
@@ -1,6 +1,6 @@
 /* escc.c */
 #define ESCC_SIZE 4
-int escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB,
+MemoryRegion *escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB,
               CharDriverState *chrA, CharDriverState *chrB,
               int clock, int it_shift);
 
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
deleted file mode 100644 (file)
index b84d74a..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * QEMU ETRAX System Emulator
- *
- * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
- *
- * 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 "sysbus.h"
-#include "boards.h"
-#include "net.h"
-#include "flash.h"
-#include "etraxfs.h"
-#include "loader.h"
-#include "elf.h"
-#include "cris-boot.h"
-#include "blockdev.h"
-
-#define FLASH_SIZE 0x2000000
-#define INTMEM_SIZE (128 * 1024)
-
-static struct cris_load_info li;
-
-static void flash_cpu_reset(void *opaque)
-{
-    CPUState *env = opaque;
-    cpu_reset(env);
-}
-
-static
-void bareetraxfs_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)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    CPUState *env;
-    qemu_irq irq[30], nmi[2], *cpu_irq; 
-    void *etraxfs_dmac;
-    struct etraxfs_dma_client *eth[2] = {NULL, NULL};
-    DriveInfo *dinfo;
-    int i;
-    ram_addr_t phys_ram;
-    ram_addr_t phys_flash;
-    ram_addr_t phys_intmem;
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-        cpu_model = "crisv32";
-    }
-    env = cpu_init(cpu_model);
-
-    /* allocate RAM */
-    phys_ram = qemu_ram_alloc(NULL, "etraxfs.ram", ram_size);
-    cpu_register_physical_memory(0x40000000, ram_size, phys_ram | IO_MEM_RAM);
-
-    /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
-       internal memory.  */
-    phys_intmem = qemu_ram_alloc(NULL, "etraxfs.chipram", INTMEM_SIZE);
-    cpu_register_physical_memory(0x38000000, INTMEM_SIZE,
-                                 phys_intmem | IO_MEM_RAM);
-
-
-    phys_flash = qemu_ram_alloc(NULL, "etraxfs.flash", FLASH_SIZE);
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi02_register(0x0, phys_flash,
-                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                          FLASH_SIZE >> 16,
-                          1, 2, 0x0000, 0x0000, 0x0000, 0x0000,
-                          0x555, 0x2aa, 0);
-    cpu_irq = cris_pic_init_cpu(env);
-    dev = qdev_create(NULL, "etraxfs,pic");
-    /* FIXME: Is there a proper way to signal vectors to the CPU core?  */
-    qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector);
-    qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
-    sysbus_mmio_map(s, 0, 0x3001c000);
-    sysbus_connect_irq(s, 0, cpu_irq[0]);
-    sysbus_connect_irq(s, 1, cpu_irq[1]);
-    for (i = 0; i < 30; i++) {
-        irq[i] = qdev_get_gpio_in(dev, i);
-    }
-    nmi[0] = qdev_get_gpio_in(dev, 30);
-    nmi[1] = qdev_get_gpio_in(dev, 31);
-
-    etraxfs_dmac = etraxfs_dmac_init(0x30000000, 10);
-    for (i = 0; i < 10; i++) {
-        /* On ETRAX, odd numbered channels are inputs.  */
-        etraxfs_dmac_connect(etraxfs_dmac, i, irq + 7 + i, i & 1);
-    }
-
-    /* Add the two ethernet blocks.  */
-    eth[0] = etraxfs_eth_init(&nd_table[0], 0x30034000, 1);
-    if (nb_nics > 1)
-        eth[1] = etraxfs_eth_init(&nd_table[1], 0x30036000, 2);
-
-    /* The DMA Connector block is missing, hardwire things for now.  */
-    etraxfs_dmac_connect_client(etraxfs_dmac, 0, eth[0]);
-    etraxfs_dmac_connect_client(etraxfs_dmac, 1, eth[0] + 1);
-    if (eth[1]) {
-        etraxfs_dmac_connect_client(etraxfs_dmac, 6, eth[1]);
-        etraxfs_dmac_connect_client(etraxfs_dmac, 7, eth[1] + 1);
-    }
-
-    /* 2 timers.  */
-    sysbus_create_varargs("etraxfs,timer", 0x3001e000, irq[0x1b], nmi[1], NULL);
-    sysbus_create_varargs("etraxfs,timer", 0x3005e000, irq[0x1b], nmi[1], NULL);
-
-    for (i = 0; i < 4; i++) {
-        sysbus_create_simple("etraxfs,serial", 0x30026000 + i * 0x2000,
-                             irq[0x14 + i]); 
-    }
-
-    if (kernel_filename) {
-        li.image_filename = kernel_filename;
-        li.cmdline = kernel_cmdline;
-        cris_load_image(env, &li);
-    } else {
-        if (!dinfo) {
-            fprintf(stderr,
-                    "Provide a kernel image or a flash image to boot from.\n");
-           exit(1);
-        }
-
-        /* Nothing more to do for flash images, those boot from addr 0.  */
-        qemu_register_reset(flash_cpu_reset, env);
-    }
-}
-
-static QEMUMachine bareetraxfs_machine = {
-    .name = "bareetraxfs",
-    .desc = "Bare ETRAX FS board",
-    .init = bareetraxfs_init,
-    .is_default = 1,
-};
-
-static void bareetraxfs_machine_init(void)
-{
-    qemu_register_machine(&bareetraxfs_machine);
-}
-
-machine_init(bareetraxfs_machine_init);
index 01fb9d3e8280e2b7c9b3f83a77fda086892901b5..5c61f1b41b33af617a47b3c33e0650187f7bfc07 100644 (file)
@@ -25,4 +25,6 @@
 #include "etraxfs_dma.h"
 
 qemu_irq *cris_pic_init_cpu(CPUState *env);
-void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr);
+void etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr,
+                      struct etraxfs_dma_client *dma_out,
+                      struct etraxfs_dma_client *dma_in);
index dff5f55f3316ebf5df65707723f25dca8008bcdb..645307705681e1fec97443afae91adbb364ea708 100644 (file)
@@ -562,7 +562,11 @@ static void eth_cleanup(VLANClientState *nc)
 
         cpu_unregister_io_memory(eth->ethregs);
 
-        qemu_free(eth->dma_out);
+       /* Disconnect the client.  */
+       eth->dma_out->client.push = NULL;
+       eth->dma_out->client.opaque = NULL;
+       eth->dma_in->client.opaque = NULL;
+       eth->dma_in->client.pull = NULL;
         qemu_free(eth);
 }
 
@@ -575,23 +579,23 @@ static NetClientInfo net_etraxfs_info = {
        .link_status_changed = eth_set_link,
 };
 
-void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr)
+void etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr,
+                       struct etraxfs_dma_client *dma_out,
+                       struct etraxfs_dma_client *dma_in)
 {
-       struct etraxfs_dma_client *dma = NULL;  
        struct fs_eth *eth = NULL;
 
        qemu_check_nic_model(nd, "fseth");
 
-       dma = qemu_mallocz(sizeof *dma * 2);
        eth = qemu_mallocz(sizeof *eth);
 
-       dma[0].client.push = eth_tx_push;
-       dma[0].client.opaque = eth;
-       dma[1].client.opaque = eth;
-       dma[1].client.pull = NULL;
+       dma_out->client.push = eth_tx_push;
+       dma_out->client.opaque = eth;
+       dma_in->client.opaque = eth;
+       dma_in->client.pull = NULL;
 
-       eth->dma_out = dma;
-       eth->dma_in = dma + 1;
+       eth->dma_out = dma_out;
+       eth->dma_in = dma_in;
 
        /* Connect the phy.  */
        eth->phyaddr = phyaddr & 0x1f;
@@ -608,6 +612,4 @@ void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr)
 
        eth->nic = qemu_new_nic(&net_etraxfs_info, &eth->conf,
                                nd->model, nd->name, eth);
-
-       return dma;
 }
index c22e1a922c34fbc430b9c55343f5bd0930f75e7a..140ae398019613eef5958e4c0e497a0c09eae513 100644 (file)
@@ -18,14 +18,13 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
                                 int be);
 
 /* nand.c */
-typedef struct NANDFlashState NANDFlashState;
-NANDFlashState *nand_init(int manf_id, int chip_id);
-void nand_done(NANDFlashState *s);
-void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
+DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id);
+void nand_setpins(DeviceState *dev, 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);
+void nand_getpins(DeviceState *dev, int *rb);
+void nand_setio(DeviceState *dev, uint32_t value);
+uint32_t nand_getio(DeviceState *dev);
+uint32_t nand_getbuswidth(DeviceState *dev);
 
 #define NAND_MFR_TOSHIBA       0x98
 #define NAND_MFR_SAMSUNG       0xec
@@ -39,7 +38,9 @@ uint8_t nand_getio(NANDFlashState *s);
 /* onenand.c */
 void onenand_base_update(void *opaque, target_phys_addr_t new);
 void onenand_base_unmap(void *opaque);
-void *onenand_init(uint32_t id, int regshift, qemu_irq irq);
+void *onenand_init(BlockDriverState *bdrv,
+                uint16_t man_id, uint16_t dev_id, uint16_t ver_id,
+                int regshift, qemu_irq irq);
 void *onenand_raw_otp(void *opaque);
 
 /* ecc.c */
index 34e7526d59d361f610b1bf680dd32496c279ed25..e4847b7f93732f2108871372c3b1dda149735524 100644 (file)
@@ -26,6 +26,7 @@
 #include "isa.h"
 #include "fw_cfg.h"
 #include "sysbus.h"
+#include "qemu-error.h"
 
 /* debug firmware config */
 //#define DEBUG_FW_CFG
@@ -56,6 +57,156 @@ struct FWCfgState {
     Notifier machine_ready;
 };
 
+#define JPG_FILE 0
+#define BMP_FILE 1
+
+static FILE *probe_splashfile(char *filename, int *file_sizep, int *file_typep)
+{
+    FILE *fp = NULL;
+    int fop_ret;
+    int file_size;
+    int file_type = -1;
+    unsigned char buf[2] = {0, 0};
+    unsigned int filehead_value = 0;
+    int bmp_bpp;
+
+    fp = fopen(filename, "rb");
+    if (fp == NULL) {
+        error_report("failed to open file '%s'.", filename);
+        return fp;
+    }
+    /* check file size */
+    fseek(fp, 0L, SEEK_END);
+    file_size = ftell(fp);
+    if (file_size < 2) {
+        error_report("file size is less than 2 bytes '%s'.", filename);
+        fclose(fp);
+        fp = NULL;
+        return fp;
+    }
+    /* check magic ID */
+    fseek(fp, 0L, SEEK_SET);
+    fop_ret = fread(buf, 1, 2, fp);
+    if (fop_ret != 2) {
+        error_report("Could not read header from '%s': %s",
+                     filename, strerror(errno));
+        fclose(fp);
+        fp = NULL;
+        return fp;
+    }
+    filehead_value = (buf[0] + (buf[1] << 8)) & 0xffff;
+    if (filehead_value == 0xd8ff) {
+        file_type = JPG_FILE;
+    } else {
+        if (filehead_value == 0x4d42) {
+            file_type = BMP_FILE;
+        }
+    }
+    if (file_type < 0) {
+        error_report("'%s' not jpg/bmp file,head:0x%x.",
+                         filename, filehead_value);
+        fclose(fp);
+        fp = NULL;
+        return fp;
+    }
+    /* check BMP bpp */
+    if (file_type == BMP_FILE) {
+        fseek(fp, 28, SEEK_SET);
+        fop_ret = fread(buf, 1, 2, fp);
+        bmp_bpp = (buf[0] + (buf[1] << 8)) & 0xffff;
+        if (bmp_bpp != 24) {
+            error_report("only 24bpp bmp file is supported.");
+            fclose(fp);
+            fp = NULL;
+            return fp;
+        }
+    }
+    /* return values */
+    *file_sizep = file_size;
+    *file_typep = file_type;
+    return fp;
+}
+
+static void fw_cfg_bootsplash(FWCfgState *s)
+{
+    int boot_splash_time = -1;
+    const char *boot_splash_filename = NULL;
+    char *p;
+    char *filename;
+    FILE *fp;
+    int fop_ret;
+    int file_size;
+    int file_type = -1;
+    const char *temp;
+
+    /* get user configuration */
+    QemuOptsList *plist = qemu_find_opts("boot-opts");
+    QemuOpts *opts = QTAILQ_FIRST(&plist->head);
+    if (opts != NULL) {
+        temp = qemu_opt_get(opts, "splash");
+        if (temp != NULL) {
+            boot_splash_filename = temp;
+        }
+        temp = qemu_opt_get(opts, "splash-time");
+        if (temp != NULL) {
+            p = (char *)temp;
+            boot_splash_time = strtol(p, (char **)&p, 10);
+        }
+    }
+
+    /* insert splash time if user configurated */
+    if (boot_splash_time >= 0) {
+        /* validate the input */
+        if (boot_splash_time > 0xffff) {
+            error_report("splash time is big than 65535, force it to 65535.");
+            boot_splash_time = 0xffff;
+        }
+        /* use little endian format */
+        qemu_extra_params_fw[0] = (uint8_t)(boot_splash_time & 0xff);
+        qemu_extra_params_fw[1] = (uint8_t)((boot_splash_time >> 8) & 0xff);
+        fw_cfg_add_file(s, "etc/boot-menu-wait", qemu_extra_params_fw, 2);
+    }
+
+    /* insert splash file if user configurated */
+    if (boot_splash_filename != NULL) {
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, boot_splash_filename);
+        if (filename == NULL) {
+            error_report("failed to find file '%s'.", boot_splash_filename);
+            return;
+        }
+        /* probing the file */
+        fp = probe_splashfile(filename, &file_size, &file_type);
+        if (fp == NULL) {
+            qemu_free(filename);
+            return;
+        }
+        /* loading file data */
+        if (boot_splash_filedata != NULL) {
+            qemu_free(boot_splash_filedata);
+        }
+        boot_splash_filedata = qemu_malloc(file_size);
+        boot_splash_filedata_size = file_size;
+        fseek(fp, 0L, SEEK_SET);
+        fop_ret = fread(boot_splash_filedata, 1, file_size, fp);
+        if (fop_ret != file_size) {
+            error_report("failed to read data from '%s'.",
+                         boot_splash_filename);
+            fclose(fp);
+            return;
+        }
+        fclose(fp);
+        /* insert data */
+        if (file_type == JPG_FILE) {
+            fw_cfg_add_file(s, "bootsplash.jpg",
+                    boot_splash_filedata, boot_splash_filedata_size);
+        } else {
+            fw_cfg_add_file(s, "bootsplash.bmp",
+                    boot_splash_filedata, boot_splash_filedata_size);
+        }
+        qemu_free(filename);
+    }
+}
+
 static void fw_cfg_write(FWCfgState *s, uint8_t value)
 {
     int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL);
@@ -352,7 +503,7 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
     fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
     fw_cfg_add_i16(s, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
     fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);
-
+    fw_cfg_bootsplash(s);
 
     s->machine_ready.notify = fw_cfg_machine_ready;
     qemu_add_machine_init_done_notifier(&s->machine_ready);
index cee07e06c77cfdfd06dc78a607c6b4cbbd1e785c..9a823e1c068f4f8b0497c6ca66899f9bb002032b 100644 (file)
@@ -61,7 +61,9 @@ static void pci_grackle_reset(void *opaque)
 {
 }
 
-PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -74,7 +76,10 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_grackle_set_irq,
                                          pci_grackle_map_irq,
-                                         pic, 0, 4);
+                                         pic,
+                                         address_space_mem,
+                                         address_space_io,
+                                         0, 4);
 
     pci_create_simple(d->host_state.bus, 0, "grackle");
 
index 8e1f6a069dcd27a19bf7d4caf0abdbc2d48d39b4..d5415580e44328ace7b65f26e6b39973ff1848a1 100644 (file)
@@ -27,6 +27,7 @@
 #include "pci.h"
 #include "pci_host.h"
 #include "pc.h"
+#include "exec-memory.h"
 
 //#define DEBUG
 
@@ -1092,7 +1093,10 @@ PCIBus *gt64120_register(qemu_irq *pic)
     d = FROM_SYSBUS(GT64120State, s);
     d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                   gt64120_pci_set_irq, gt64120_pci_map_irq,
-                                  pic, PCI_DEVFN(18, 0), 4);
+                                  pic,
+                                  get_system_memory(),
+                                  get_system_io(),
+                                  PCI_DEVFN(18, 0), 4);
     d->ISD_handle = cpu_register_io_memory(gt64120_read, gt64120_write, d,
                                            DEVICE_NATIVE_ENDIAN);
 
index 5fd71a0f71e258212a07aec75ef369d4b16575b1..3ba0b0e0fbffd5764b1a84785c4ac1d3a791b5ed 100644 (file)
@@ -43,6 +43,7 @@ typedef struct HeathrowPIC {
 } HeathrowPIC;
 
 typedef struct HeathrowPICS {
+    MemoryRegion mem;
     HeathrowPIC pics[2];
     qemu_irq *irqs;
 } HeathrowPICS;
@@ -62,7 +63,8 @@ static void heathrow_pic_update(HeathrowPICS *s)
     }
 }
 
-static void pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+static void pic_write(void *opaque, target_phys_addr_t addr,
+                      uint64_t value, unsigned size)
 {
     HeathrowPICS *s = opaque;
     HeathrowPIC *pic;
@@ -89,7 +91,8 @@ static void pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
+static uint64_t pic_read(void *opaque, target_phys_addr_t addr,
+                         unsigned size)
 {
     HeathrowPICS *s = opaque;
     HeathrowPIC *pic;
@@ -120,19 +123,12 @@ static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
     return value;
 }
 
-static CPUWriteMemoryFunc * const pic_write[] = {
-    &pic_writel,
-    &pic_writel,
-    &pic_writel,
+static const MemoryRegionOps heathrow_pic_ops = {
+    .read = pic_read,
+    .write = pic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUReadMemoryFunc * const pic_read[] = {
-    &pic_readl,
-    &pic_readl,
-    &pic_readl,
-};
-
-
 static void heathrow_pic_set_irq(void *opaque, int num, int level)
 {
     HeathrowPICS *s = opaque;
@@ -201,7 +197,7 @@ static void heathrow_pic_reset(void *opaque)
     s->pics[1].level_triggered = 0x1ff00000;
 }
 
-qemu_irq *heathrow_pic_init(int *pmem_index,
+qemu_irq *heathrow_pic_init(MemoryRegion **pmem,
                             int nb_cpus, qemu_irq **irqs)
 {
     HeathrowPICS *s;
@@ -209,8 +205,9 @@ qemu_irq *heathrow_pic_init(int *pmem_index,
     s = qemu_mallocz(sizeof(HeathrowPICS));
     /* only 1 CPU */
     s->irqs = irqs[0];
-    *pmem_index = cpu_register_io_memory(pic_read, pic_write, s,
-                                         DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&s->mem, &heathrow_pic_ops, s,
+                          "heathrow-pic", 0x1000);
+    *pmem = &s->mem;
 
     vmstate_register(NULL, -1, &vmstate_heathrow_pic, s);
     qemu_register_reset(heathrow_pic_reset, s);
diff --git a/hw/hid.c b/hw/hid.c
new file mode 100644 (file)
index 0000000..7b5ef5f
--- /dev/null
+++ b/hw/hid.c
@@ -0,0 +1,403 @@
+/*
+ * QEMU HID devices
+ *
+ * Copyright (c) 2005 Fabrice Bellard
+ * Copyright (c) 2007 OpenMoko, Inc.  (andrew@openedhand.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw.h"
+#include "console.h"
+#include "qemu-timer.h"
+#include "hid.h"
+
+#define HID_USAGE_ERROR_ROLLOVER        0x01
+#define HID_USAGE_POSTFAIL              0x02
+#define HID_USAGE_ERROR_UNDEFINED       0x03
+
+/* Indices are QEMU keycodes, values are from HID Usage Table.  Indices
+ * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d.  */
+static const uint8_t hid_usage_keys[0x100] = {
+    0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+    0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
+    0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
+    0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
+    0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
+    0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
+    0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
+    0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+    0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
+    0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
+    0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
+    0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
+    0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
+
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
+    0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
+    0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
+    0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+bool hid_has_events(HIDState *hs)
+{
+    return hs->n > 0;
+}
+
+void hid_set_next_idle(HIDState *hs, int64_t curtime)
+{
+    hs->next_idle_clock = curtime + (get_ticks_per_sec() * hs->idle * 4) / 1000;
+}
+
+static void hid_pointer_event_clear(HIDPointerEvent *e, int buttons)
+{
+    e->xdx = e->ydy = e->dz = 0;
+    e->buttons_state = buttons;
+}
+
+static void hid_pointer_event_combine(HIDPointerEvent *e, int xyrel,
+                                      int x1, int y1, int z1) {
+    if (xyrel) {
+        e->xdx += x1;
+        e->ydy += y1;
+    } else {
+        e->xdx = x1;
+        e->ydy = y1;
+        /* Windows drivers do not like the 0/0 position and ignore such
+         * events. */
+        if (!(x1 | y1)) {
+            x1 = 1;
+        }
+    }
+    e->dz += z1;
+}
+
+static void hid_pointer_event(void *opaque,
+                              int x1, int y1, int z1, int buttons_state)
+{
+    HIDState *hs = opaque;
+    unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
+    unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
+
+    /* We combine events where feasible to keep the queue small.  We shouldn't
+     * combine anything with the first event of a particular button state, as
+     * that would change the location of the button state change.  When the
+     * queue is empty, a second event is needed because we don't know if
+     * the first event changed the button state.  */
+    if (hs->n == QUEUE_LENGTH) {
+        /* Queue full.  Discard old button state, combine motion normally.  */
+        hs->ptr.queue[use_slot].buttons_state = buttons_state;
+    } else if (hs->n < 2 ||
+               hs->ptr.queue[use_slot].buttons_state != buttons_state ||
+               hs->ptr.queue[previous_slot].buttons_state !=
+               hs->ptr.queue[use_slot].buttons_state) {
+        /* Cannot or should not combine, so add an empty item to the queue.  */
+        QUEUE_INCR(use_slot);
+        hs->n++;
+        hid_pointer_event_clear(&hs->ptr.queue[use_slot], buttons_state);
+    }
+    hid_pointer_event_combine(&hs->ptr.queue[use_slot],
+                              hs->kind == HID_MOUSE,
+                              x1, y1, z1);
+    hs->event(hs);
+}
+
+static void hid_keyboard_event(void *opaque, int keycode)
+{
+    HIDState *hs = opaque;
+    int slot;
+
+    if (hs->n == QUEUE_LENGTH) {
+        fprintf(stderr, "usb-kbd: warning: key event queue full\n");
+        return;
+    }
+    slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
+    hs->kbd.keycodes[slot] = keycode;
+    hs->event(hs);
+}
+
+static void hid_keyboard_process_keycode(HIDState *hs)
+{
+    uint8_t hid_code, key;
+    int i, keycode, slot;
+
+    if (hs->n == 0) {
+        return;
+    }
+    slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
+    keycode = hs->kbd.keycodes[slot];
+
+    key = keycode & 0x7f;
+    hid_code = hid_usage_keys[key | ((hs->kbd.modifiers >> 1) & (1 << 7))];
+    hs->kbd.modifiers &= ~(1 << 8);
+
+    switch (hid_code) {
+    case 0x00:
+        return;
+
+    case 0xe0:
+        if (hs->kbd.modifiers & (1 << 9)) {
+            hs->kbd.modifiers ^= 3 << 8;
+            return;
+        }
+    case 0xe1 ... 0xe7:
+        if (keycode & (1 << 7)) {
+            hs->kbd.modifiers &= ~(1 << (hid_code & 0x0f));
+            return;
+        }
+    case 0xe8 ... 0xef:
+        hs->kbd.modifiers |= 1 << (hid_code & 0x0f);
+        return;
+    }
+
+    if (keycode & (1 << 7)) {
+        for (i = hs->kbd.keys - 1; i >= 0; i--) {
+            if (hs->kbd.key[i] == hid_code) {
+                hs->kbd.key[i] = hs->kbd.key[-- hs->kbd.keys];
+                hs->kbd.key[hs->kbd.keys] = 0x00;
+                break;
+            }
+        }
+        if (i < 0) {
+            return;
+        }
+    } else {
+        for (i = hs->kbd.keys - 1; i >= 0; i--) {
+            if (hs->kbd.key[i] == hid_code) {
+                break;
+            }
+        }
+        if (i < 0) {
+            if (hs->kbd.keys < sizeof(hs->kbd.key)) {
+                hs->kbd.key[hs->kbd.keys++] = hid_code;
+            }
+        } else {
+            return;
+        }
+    }
+}
+
+static inline int int_clamp(int val, int vmin, int vmax)
+{
+    if (val < vmin) {
+        return vmin;
+    } else if (val > vmax) {
+        return vmax;
+    } else {
+        return val;
+    }
+}
+
+int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
+{
+    int dx, dy, dz, b, l;
+    int index;
+    HIDPointerEvent *e;
+
+    if (!hs->ptr.mouse_grabbed) {
+        qemu_activate_mouse_event_handler(hs->ptr.eh_entry);
+        hs->ptr.mouse_grabbed = 1;
+    }
+
+    /* When the buffer is empty, return the last event.  Relative
+       movements will all be zero.  */
+    index = (hs->n ? hs->head : hs->head - 1);
+    e = &hs->ptr.queue[index & QUEUE_MASK];
+
+    if (hs->kind == HID_MOUSE) {
+        dx = int_clamp(e->xdx, -127, 127);
+        dy = int_clamp(e->ydy, -127, 127);
+        e->xdx -= dx;
+        e->ydy -= dy;
+    } else {
+        dx = e->xdx;
+        dy = e->ydy;
+    }
+    dz = int_clamp(e->dz, -127, 127);
+    e->dz -= dz;
+
+    b = 0;
+    if (e->buttons_state & MOUSE_EVENT_LBUTTON) {
+        b |= 0x01;
+    }
+    if (e->buttons_state & MOUSE_EVENT_RBUTTON) {
+        b |= 0x02;
+    }
+    if (e->buttons_state & MOUSE_EVENT_MBUTTON) {
+        b |= 0x04;
+    }
+
+    if (hs->n &&
+        !e->dz &&
+        (hs->kind == HID_TABLET || (!e->xdx && !e->ydy))) {
+        /* that deals with this event */
+        QUEUE_INCR(hs->head);
+        hs->n--;
+    }
+
+    /* Appears we have to invert the wheel direction */
+    dz = 0 - dz;
+    l = 0;
+    switch (hs->kind) {
+    case HID_MOUSE:
+        if (len > l) {
+            buf[l++] = b;
+        }
+        if (len > l) {
+            buf[l++] = dx;
+        }
+        if (len > l) {
+            buf[l++] = dy;
+        }
+        if (len > l) {
+            buf[l++] = dz;
+        }
+        break;
+
+    case HID_TABLET:
+        if (len > l) {
+            buf[l++] = b;
+        }
+        if (len > l) {
+            buf[l++] = dx & 0xff;
+        }
+        if (len > l) {
+            buf[l++] = dx >> 8;
+        }
+        if (len > l) {
+            buf[l++] = dy & 0xff;
+        }
+        if (len > l) {
+            buf[l++] = dy >> 8;
+        }
+        if (len > l) {
+            buf[l++] = dz;
+        }
+        break;
+
+    default:
+        abort();
+    }
+
+    return l;
+}
+
+int hid_keyboard_poll(HIDState *hs, uint8_t *buf, int len)
+{
+    if (len < 2) {
+        return 0;
+    }
+
+    hid_keyboard_process_keycode(hs);
+
+    buf[0] = hs->kbd.modifiers & 0xff;
+    buf[1] = 0;
+    if (hs->kbd.keys > 6) {
+        memset(buf + 2, HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
+    } else {
+        memcpy(buf + 2, hs->kbd.key, MIN(8, len) - 2);
+    }
+
+    return MIN(8, len);
+}
+
+int hid_keyboard_write(HIDState *hs, uint8_t *buf, int len)
+{
+    if (len > 0) {
+        int ledstate = 0;
+        /* 0x01: Num Lock LED
+         * 0x02: Caps Lock LED
+         * 0x04: Scroll Lock LED
+         * 0x08: Compose LED
+         * 0x10: Kana LED */
+        hs->kbd.leds = buf[0];
+        if (hs->kbd.leds & 0x04) {
+            ledstate |= QEMU_SCROLL_LOCK_LED;
+        }
+        if (hs->kbd.leds & 0x01) {
+            ledstate |= QEMU_NUM_LOCK_LED;
+        }
+        if (hs->kbd.leds & 0x02) {
+            ledstate |= QEMU_CAPS_LOCK_LED;
+        }
+        kbd_put_ledstate(ledstate);
+    }
+    return 0;
+}
+
+void hid_reset(HIDState *hs)
+{
+    switch (hs->kind) {
+    case HID_KEYBOARD:
+        qemu_add_kbd_event_handler(hid_keyboard_event, hs);
+        memset(hs->kbd.keycodes, 0, sizeof(hs->kbd.keycodes));
+        memset(hs->kbd.key, 0, sizeof(hs->kbd.key));
+        hs->kbd.keys = 0;
+        break;
+    case HID_MOUSE:
+    case HID_TABLET:
+        memset(hs->ptr.queue, 0, sizeof(hs->ptr.queue));
+        break;
+    }
+    hs->head = 0;
+    hs->n = 0;
+    hs->protocol = 1;
+    hs->idle = 0;
+}
+
+void hid_free(HIDState *hs)
+{
+    switch (hs->kind) {
+    case HID_KEYBOARD:
+        qemu_remove_kbd_event_handler();
+        break;
+    case HID_MOUSE:
+    case HID_TABLET:
+        qemu_remove_mouse_event_handler(hs->ptr.eh_entry);
+        break;
+    }
+}
+
+void hid_init(HIDState *hs, int kind, HIDEventFunc event)
+{
+    hs->kind = kind;
+    hs->event = event;
+
+    if (hs->kind == HID_MOUSE) {
+        hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
+                                                        0, "QEMU HID Mouse");
+    } else if (hs->kind == HID_TABLET) {
+        hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
+                                                        1, "QEMU HID Tablet");
+    }
+}
diff --git a/hw/hid.h b/hw/hid.h
new file mode 100644 (file)
index 0000000..4a8fa5b
--- /dev/null
+++ b/hw/hid.h
@@ -0,0 +1,58 @@
+#ifndef QEMU_HID_H
+#define QEMU_HID_H
+
+#define HID_MOUSE     1
+#define HID_TABLET    2
+#define HID_KEYBOARD  3
+
+typedef struct HIDPointerEvent {
+    int32_t xdx, ydy; /* relative iff it's a mouse, otherwise absolute */
+    int32_t dz, buttons_state;
+} HIDPointerEvent;
+
+#define QUEUE_LENGTH    16 /* should be enough for a triple-click */
+#define QUEUE_MASK      (QUEUE_LENGTH-1u)
+#define QUEUE_INCR(v)   ((v)++, (v) &= QUEUE_MASK)
+
+typedef struct HIDState HIDState;
+typedef void (*HIDEventFunc)(HIDState *s);
+
+typedef struct HIDMouseState {
+    HIDPointerEvent queue[QUEUE_LENGTH];
+    int mouse_grabbed;
+    QEMUPutMouseEntry *eh_entry;
+} HIDMouseState;
+
+typedef struct HIDKeyboardState {
+    uint32_t keycodes[QUEUE_LENGTH];
+    uint16_t modifiers;
+    uint8_t leds;
+    uint8_t key[16];
+    int32_t keys;
+} HIDKeyboardState;
+
+struct HIDState {
+    union {
+        HIDMouseState ptr;
+        HIDKeyboardState kbd;
+    };
+    uint32_t head; /* index into circular queue */
+    uint32_t n;
+    int kind;
+    int32_t protocol;
+    uint8_t idle;
+    int64_t next_idle_clock;
+    HIDEventFunc event;
+};
+
+void hid_init(HIDState *hs, int kind, HIDEventFunc event);
+void hid_reset(HIDState *hs);
+void hid_free(HIDState *hs);
+
+bool hid_has_events(HIDState *hs);
+void hid_set_next_idle(HIDState *hs, int64_t curtime);
+int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len);
+int hid_keyboard_poll(HIDState *hs, uint8_t *buf, int len);
+int hid_keyboard_write(HIDState *hs, uint8_t *buf, int len);
+
+#endif /* QEMU_HID_H */
diff --git a/hw/hw.h b/hw/hw.h
index 9dd7096fc27f9780e618f8a6d395d023b3fa8f31..df6ca650580a6884896016399cfe17ca73f514b0 100644 (file)
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -324,6 +324,7 @@ typedef struct VMStateSubsection {
 
 struct VMStateDescription {
     const char *name;
+    int unmigratable;
     int version_id;
     int minimum_version_id;
     int minimum_version_id_old;
index 551440202933f3d6626184f492950cbdc70c5dac..9381d01589d6d815a0c14987e360e14b640e0868 100644 (file)
--- a/hw/i2c.h
+++ b/hw/i2c.h
@@ -72,6 +72,6 @@ void wm8750_set_bclk_in(void *opaque, int new_hz);
 void tmp105_set(i2c_slave *i2c, int temp);
 
 /* lm832x.c */
-void lm832x_key_event(i2c_slave *i2c, int key, int state);
+void lm832x_key_event(DeviceState *dev, int key, int state);
 
 #endif
index 34d9394bcce3803398874f103c307920fa57848f..9059aae28933bb8d5563e0fc7391a58d7901620b 100644 (file)
--- a/hw/ide.h
+++ b/hw/ide.h
@@ -13,12 +13,13 @@ ISADevice *isa_ide_init(int iobase, int iobase2, int isairq,
 /* ide-pci.c */
 void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table,
                          int secondary_ide_enabled);
+PCIDevice *pci_piix3_xen_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
 PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
 PCIDevice *pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
 void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
 
 /* ide-macio.c */
-int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
+MemoryRegion *pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
                   void *dbdma, int channel, qemu_irq dma_irq);
 
 /* ide-mmio.c */
index 1f008a3dda9aad5659503c41af6e9062512f0d71..e207ca08941f6866b5447e8cabe0590073362af5 100644 (file)
@@ -276,12 +276,12 @@ static void  ahci_port_write(AHCIState *s, int port, int offset, uint32_t val)
     }
 }
 
-static uint32_t ahci_mem_readl(void *ptr, target_phys_addr_t addr)
+static uint64_t ahci_mem_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
-    AHCIState *s = ptr;
+    AHCIState *s = opaque;
     uint32_t val = 0;
 
-    addr = addr & 0xfff;
     if (addr < AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR) {
         switch (addr) {
         case HOST_CAP:
@@ -314,10 +314,10 @@ static uint32_t ahci_mem_readl(void *ptr, target_phys_addr_t addr)
 
 
 
-static void ahci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
+static void ahci_mem_write(void *opaque, target_phys_addr_t addr,
+                           uint64_t val, unsigned size)
 {
-    AHCIState *s = ptr;
-    addr = addr & 0xfff;
+    AHCIState *s = opaque;
 
     /* Only aligned reads are allowed on AHCI */
     if (addr & 3) {
@@ -364,16 +364,10 @@ static void ahci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
 
 }
 
-static CPUReadMemoryFunc * const ahci_readfn[3]={
-    ahci_mem_readl,
-    ahci_mem_readl,
-    ahci_mem_readl
-};
-
-static CPUWriteMemoryFunc * const ahci_writefn[3]={
-    ahci_mem_writel,
-    ahci_mem_writel,
-    ahci_mem_writel
+static MemoryRegionOps ahci_mem_ops = {
+    .read = ahci_mem_read,
+    .write = ahci_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void ahci_reg_init(AHCIState *s)
@@ -1131,8 +1125,8 @@ void ahci_init(AHCIState *s, DeviceState *qdev, int ports)
     s->ports = ports;
     s->dev = qemu_mallocz(sizeof(AHCIDevice) * ports);
     ahci_reg_init(s);
-    s->mem = cpu_register_io_memory(ahci_readfn, ahci_writefn, s,
-                                    DEVICE_LITTLE_ENDIAN);
+    /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
+    memory_region_init_io(&s->mem, &ahci_mem_ops, s, "ahci", 0x1000);
     irqs = qemu_allocate_irqs(ahci_irq_set, s, s->ports);
 
     for (i = 0; i < s->ports; i++) {
@@ -1151,6 +1145,7 @@ void ahci_init(AHCIState *s, DeviceState *qdev, int ports)
 
 void ahci_uninit(AHCIState *s)
 {
+    memory_region_destroy(&s->mem);
     qemu_free(s->dev);
 }
 
index dc86951ebfd52e6709c9e8c589ccc56dec3ead64..e456193b2b9d448f46b7a3545513b991f18b9d33 100644 (file)
@@ -289,7 +289,7 @@ struct AHCIDevice {
 typedef struct AHCIState {
     AHCIDevice *dev;
     AHCIControlRegs control_regs;
-    int mem;
+    MemoryRegion mem;
     int ports;
     qemu_irq irq;
 } AHCIState;
index 56302b506090f5fae842870c67fe59a1a56b3939..4d91e2c6429ea6b66b1c63b2bf0deed15919f117 100644 (file)
 
 static void cmd646_update_irq(PCIIDEState *d);
 
-static void ide_map(PCIDevice *pci_dev, int region_num,
-                    pcibus_t addr, pcibus_t size, int type)
+static uint64_t cmd646_cmd_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
 {
-    PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, pci_dev);
-    IDEBus *bus;
-
-    if (region_num <= 3) {
-        bus = &d->bus[(region_num >> 1)];
-        if (region_num & 1) {
-            register_ioport_read(addr + 2, 1, 1, ide_status_read, bus);
-            register_ioport_write(addr + 2, 1, 1, ide_cmd_write, bus);
+    CMD646BAR *cmd646bar = opaque;
+
+    if (addr != 2 || size != 1) {
+        return ((uint64_t)1 << (size * 8)) - 1;
+    }
+    return ide_status_read(cmd646bar->bus, addr + 2);
+}
+
+static void cmd646_cmd_write(void *opaque, target_phys_addr_t addr,
+                             uint64_t data, unsigned size)
+{
+    CMD646BAR *cmd646bar = opaque;
+
+    if (addr != 2 || size != 1) {
+        return;
+    }
+    ide_cmd_write(cmd646bar->bus, addr + 2, data);
+}
+
+static MemoryRegionOps cmd646_cmd_ops = {
+    .read = cmd646_cmd_read,
+    .write = cmd646_cmd_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static uint64_t cmd646_data_read(void *opaque, target_phys_addr_t addr,
+                                 unsigned size)
+{
+    CMD646BAR *cmd646bar = opaque;
+
+    if (size == 1) {
+        return ide_ioport_read(cmd646bar->bus, addr);
+    } else if (addr == 0) {
+        if (size == 2) {
+            return ide_data_readw(cmd646bar->bus, addr);
         } else {
-            register_ioport_write(addr, 8, 1, ide_ioport_write, bus);
-            register_ioport_read(addr, 8, 1, ide_ioport_read, bus);
-
-            /* data ports */
-            register_ioport_write(addr, 2, 2, ide_data_writew, bus);
-            register_ioport_read(addr, 2, 2, ide_data_readw, bus);
-            register_ioport_write(addr, 4, 4, ide_data_writel, bus);
-            register_ioport_read(addr, 4, 4, ide_data_readl, bus);
+            return ide_data_readl(cmd646bar->bus, addr);
         }
     }
+    return ((uint64_t)1 << (size * 8)) - 1;
 }
 
-static uint32_t bmdma_readb_common(PCIIDEState *pci_dev, BMDMAState *bm,
-                                   uint32_t addr)
+static void cmd646_data_write(void *opaque, target_phys_addr_t addr,
+                             uint64_t data, unsigned size)
 {
+    CMD646BAR *cmd646bar = opaque;
+
+    if (size == 1) {
+        return ide_ioport_write(cmd646bar->bus, addr, data);
+    } else if (addr == 0) {
+        if (size == 2) {
+            return ide_data_writew(cmd646bar->bus, addr, data);
+        } else {
+            return ide_data_writel(cmd646bar->bus, addr, data);
+        }
+    }
+}
+
+static MemoryRegionOps cmd646_data_ops = {
+    .read = cmd646_data_read,
+    .write = cmd646_data_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void setup_cmd646_bar(PCIIDEState *d, int bus_num)
+{
+    IDEBus *bus = &d->bus[bus_num];
+    CMD646BAR *bar = &d->cmd646_bar[bus_num];
+
+    bar->bus = bus;
+    bar->pci_dev = d;
+    memory_region_init_io(&bar->cmd, &cmd646_cmd_ops, bar, "cmd646-cmd", 4);
+    memory_region_init_io(&bar->data, &cmd646_data_ops, bar, "cmd646-data", 8);
+}
+
+static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr,
+                           unsigned size)
+{
+    BMDMAState *bm = opaque;
+    PCIIDEState *pci_dev = bm->pci_dev;
     uint32_t val;
 
+    if (size != 1) {
+        return ((uint64_t)1 << (size * 8)) - 1;
+    }
+
     switch(addr & 3) {
     case 0:
         val = bm->cmd;
@@ -100,31 +160,22 @@ static uint32_t bmdma_readb_common(PCIIDEState *pci_dev, BMDMAState *bm,
     return val;
 }
 
-static uint32_t bmdma_readb_0(void *opaque, uint32_t addr)
+static void bmdma_write(void *opaque, target_phys_addr_t addr,
+                        uint64_t val, unsigned size)
 {
-    PCIIDEState *pci_dev = opaque;
-    BMDMAState *bm = &pci_dev->bmdma[0];
-
-    return bmdma_readb_common(pci_dev, bm, addr);
-}
+    BMDMAState *bm = opaque;
+    PCIIDEState *pci_dev = bm->pci_dev;
 
-static uint32_t bmdma_readb_1(void *opaque, uint32_t addr)
-{
-    PCIIDEState *pci_dev = opaque;
-    BMDMAState *bm = &pci_dev->bmdma[1];
-
-    return bmdma_readb_common(pci_dev, bm, addr);
-}
+    if (size != 1) {
+        return;
+    }
 
-static void bmdma_writeb_common(PCIIDEState *pci_dev, BMDMAState *bm,
-                                uint32_t addr, uint32_t val)
-{
 #ifdef DEBUG_IDE
     printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
 #endif
     switch(addr & 3) {
     case 0:
-        bmdma_cmd_writeb(bm, addr, val);
+        bmdma_cmd_writeb(bm, val);
         break;
     case 1:
         pci_dev->dev.config[MRDMODE] =
@@ -143,42 +194,25 @@ static void bmdma_writeb_common(PCIIDEState *pci_dev, BMDMAState *bm,
     }
 }
 
-static void bmdma_writeb_0(void *opaque, uint32_t addr, uint32_t val)
-{
-    PCIIDEState *pci_dev = opaque;
-    BMDMAState *bm = &pci_dev->bmdma[0];
-
-    bmdma_writeb_common(pci_dev, bm, addr, val);
-}
-
-static void bmdma_writeb_1(void *opaque, uint32_t addr, uint32_t val)
-{
-    PCIIDEState *pci_dev = opaque;
-    BMDMAState *bm = &pci_dev->bmdma[1];
-
-    bmdma_writeb_common(pci_dev, bm, addr, val);
-}
+static MemoryRegionOps cmd646_bmdma_ops = {
+    .read = bmdma_read,
+    .write = bmdma_write,
+};
 
-static void bmdma_map(PCIDevice *pci_dev, int region_num,
-                    pcibus_t addr, pcibus_t size, int type)
+static void bmdma_setup_bar(PCIIDEState *d)
 {
-    PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, pci_dev);
+    BMDMAState *bm;
     int i;
 
+    memory_region_init(&d->bmdma_bar, "cmd646-bmdma", 16);
     for(i = 0;i < 2; i++) {
-        BMDMAState *bm = &d->bmdma[i];
-
-        if (i == 0) {
-            register_ioport_write(addr, 4, 1, bmdma_writeb_0, d);
-            register_ioport_read(addr, 4, 1, bmdma_readb_0, d);
-        } else {
-            register_ioport_write(addr, 4, 1, bmdma_writeb_1, d);
-            register_ioport_read(addr, 4, 1, bmdma_readb_1, d);
-        }
-
-        iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4);
-        ioport_register(&bm->addr_ioport);
-        addr += 8;
+        bm = &d->bmdma[i];
+        memory_region_init_io(&bm->extra_io, &cmd646_bmdma_ops, bm,
+                              "cmd646-bmdma-bus", 4);
+        memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io);
+        memory_region_init_io(&bm->addr_ioport, &bmdma_addr_ioport_ops, bm,
+                              "cmd646-bmdma-ioport", 4);
+        memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport);
     }
 }
 
@@ -234,11 +268,14 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
         pci_conf[0x51] |= 0x08; /* enable IDE1 */
     }
 
-    pci_register_bar(dev, 0, 0x8, PCI_BASE_ADDRESS_SPACE_IO, ide_map);
-    pci_register_bar(dev, 1, 0x4, PCI_BASE_ADDRESS_SPACE_IO, ide_map);
-    pci_register_bar(dev, 2, 0x8, PCI_BASE_ADDRESS_SPACE_IO, ide_map);
-    pci_register_bar(dev, 3, 0x4, PCI_BASE_ADDRESS_SPACE_IO, ide_map);
-    pci_register_bar(dev, 4, 0x10, PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
+    setup_cmd646_bar(d, 0);
+    setup_cmd646_bar(d, 1);
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd646_bar[0].data);
+    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd646_bar[0].cmd);
+    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd646_bar[1].data);
+    pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd646_bar[1].cmd);
+    bmdma_setup_bar(d);
+    pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar);
 
     /* TODO: RST# value should be 0 */
     pci_conf[PCI_INTERRUPT_PIN] = 0x01; // interrupt on pin 1
@@ -248,7 +285,7 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
         ide_bus_new(&d->bus[i], &d->dev.qdev, i);
         ide_init2(&d->bus[i], irq[i]);
 
-        bmdma_init(&d->bus[i], &d->bmdma[i]);
+        bmdma_init(&d->bus[i], &d->bmdma[i], d);
         d->bmdma[i].bus = &d->bus[i];
         qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb,
                                          &d->bmdma[i].dma);
@@ -259,6 +296,24 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
     return 0;
 }
 
+static int pci_cmd646_ide_exitfn(PCIDevice *dev)
+{
+    PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
+    unsigned i;
+
+    for (i = 0; i < 2; ++i) {
+        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
+        memory_region_destroy(&d->bmdma[i].extra_io);
+        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
+        memory_region_destroy(&d->bmdma[i].addr_ioport);
+        memory_region_destroy(&d->cmd646_bar[i].cmd);
+        memory_region_destroy(&d->cmd646_bar[i].data);
+    }
+    memory_region_destroy(&d->bmdma_bar);
+
+    return 0;
+}
+
 void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table,
                          int secondary_ide_enabled)
 {
@@ -276,6 +331,7 @@ static PCIDeviceInfo cmd646_ide_info[] = {
         .qdev.name    = "cmd646-ide",
         .qdev.size    = sizeof(PCIIDEState),
         .init         = pci_cmd646_ide_initfn,
+        .exit         = pci_cmd646_ide_exitfn,
         .vendor_id    = PCI_VENDOR_ID_CMD,
         .device_id    = PCI_DEVICE_ID_CMD_646,
         .revision     = 0x07, // IDE controller revision
index 054e0734e43342c29e7320c39614dc454794a737..5278bc4d6cbd8d7939f19b7113a84259ebcdd60b 100644 (file)
 #include <hw/ide/pci.h>
 #include <hw/ide/ahci.h>
 
+static const VMStateDescription vmstate_ahci = {
+    .name = "ahci",
+    .unmigratable = 1,
+};
+
 static int pci_ich9_ahci_init(PCIDevice *dev)
 {
     struct AHCIPCIState *d;
@@ -93,8 +98,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
     msi_init(dev, 0x50, 1, true, false);
     d->ahci.irq = d->card.irq[0];
 
-    /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
-    pci_register_bar_simple(&d->card, 5, 0x1000, 0, d->ahci.mem);
+    pci_register_bar(&d->card, 5, 0, &d->ahci.mem);
 
     return 0;
 }
@@ -123,6 +127,7 @@ static PCIDeviceInfo ich_ahci_info[] = {
         .qdev.name    = "ich9-ahci",
         .qdev.alias   = "ahci",
         .qdev.size    = sizeof(AHCIPCIState),
+        .qdev.vmsd    = &vmstate_ahci,
         .init         = pci_ich9_ahci_init,
         .exit         = pci_ich9_uninit,
         .config_write = pci_ich9_write_config,
index 7daeb31ec3e34bdf00c0347550e3f92f8a183232..7ee35e9bd9471148cf84186e863d9eec36020882 100644 (file)
@@ -35,6 +35,7 @@
 /* MacIO based PowerPC IDE */
 
 typedef struct MACIOIDEState {
+    MemoryRegion mem;
     IDEBus bus;
     BlockDriverAIOCB *aiocb;
 } MACIOIDEState;
@@ -281,16 +282,20 @@ static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr)
     return retval;
 }
 
-static CPUWriteMemoryFunc * const pmac_ide_write[] = {
-    pmac_ide_writeb,
-    pmac_ide_writew,
-    pmac_ide_writel,
-};
-
-static CPUReadMemoryFunc * const pmac_ide_read[] = {
-    pmac_ide_readb,
-    pmac_ide_readw,
-    pmac_ide_readl,
+static MemoryRegionOps pmac_ide_ops = {
+    .old_mmio = {
+        .write = {
+            pmac_ide_writeb,
+            pmac_ide_writew,
+            pmac_ide_writel,
+        },
+        .read = {
+            pmac_ide_readb,
+            pmac_ide_readw,
+            pmac_ide_readl,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_pmac = {
@@ -315,11 +320,10 @@ static void pmac_ide_reset(void *opaque)
 /* hd_table must contain 4 block drivers */
 /* PowerMac uses memory mapped registers, not I/O. Return the memory
    I/O index to access the ide. */
-int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
-                  void *dbdma, int channel, qemu_irq dma_irq)
+MemoryRegion *pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
+                             void *dbdma, int channel, qemu_irq dma_irq)
 {
     MACIOIDEState *d;
-    int pmac_ide_memory;
 
     d = qemu_mallocz(sizeof(MACIOIDEState));
     ide_init2_with_non_qdev_drives(&d->bus, hd_table[0], hd_table[1], irq);
@@ -327,11 +331,9 @@ int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
     if (dbdma)
         DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, pmac_ide_flush, d);
 
-    pmac_ide_memory = cpu_register_io_memory(pmac_ide_read,
-                                             pmac_ide_write, d,
-                                             DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&d->mem, &pmac_ide_ops, d, "pmac-ide", 0x1000);
     vmstate_register(NULL, 0, &vmstate_pmac, d);
     qemu_register_reset(pmac_ide_reset, d);
 
-    return pmac_ide_memory;
+    return &d->mem;
 }
index 9f3050a15e9cd571773778ff15383533a729798b..d1a14d7cc1cbaddb6f6627dfaeebe49f80f027c5 100644 (file)
@@ -287,9 +287,8 @@ static void bmdma_irq(void *opaque, int n, int level)
     qemu_set_irq(bm->irq, level);
 }
 
-void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
+void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val)
 {
-    BMDMAState *bm = opaque;
 #ifdef DEBUG_IDE
     printf("%s: 0x%08x\n", __func__, val);
 #endif
@@ -328,22 +327,24 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
     bm->cmd = val & 0x09;
 }
 
-static void bmdma_addr_read(IORange *ioport, uint64_t addr,
-                            unsigned width, uint64_t *data)
+static uint64_t bmdma_addr_read(void *opaque, target_phys_addr_t addr,
+                                unsigned width)
 {
-    BMDMAState *bm = container_of(ioport, BMDMAState, addr_ioport);
+    BMDMAState *bm = opaque;
     uint32_t mask = (1ULL << (width * 8)) - 1;
+    uint64_t data;
 
-    *data = (bm->addr >> (addr * 8)) & mask;
+    data = (bm->addr >> (addr * 8)) & mask;
 #ifdef DEBUG_IDE
     printf("%s: 0x%08x\n", __func__, (unsigned)*data);
 #endif
+    return data;
 }
 
-static void bmdma_addr_write(IORange *ioport, uint64_t addr,
-                             unsigned width, uint64_t data)
+static void bmdma_addr_write(void *opaque, target_phys_addr_t addr,
+                             uint64_t data, unsigned width)
 {
-    BMDMAState *bm = container_of(ioport, BMDMAState, addr_ioport);
+    BMDMAState *bm = opaque;
     int shift = addr * 8;
     uint32_t mask = (1ULL << (width * 8)) - 1;
 
@@ -354,9 +355,10 @@ static void bmdma_addr_write(IORange *ioport, uint64_t addr,
     bm->addr |= ((data & mask) << shift) & ~3;
 }
 
-const IORangeOps bmdma_addr_ioport_ops = {
+MemoryRegionOps bmdma_addr_ioport_ops = {
     .read = bmdma_addr_read,
     .write = bmdma_addr_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static bool ide_bmdma_current_needed(void *opaque)
@@ -514,7 +516,7 @@ static const struct IDEDMAOps bmdma_ops = {
     .reset = bmdma_reset,
 };
 
-void bmdma_init(IDEBus *bus, BMDMAState *bm)
+void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d)
 {
     qemu_irq *irq;
 
@@ -527,4 +529,5 @@ void bmdma_init(IDEBus *bus, BMDMAState *bm)
     bm->irq = bus->irq;
     irq = qemu_allocate_irqs(bmdma_irq, bm, 1);
     bus->irq = *irq;
+    bm->pci_dev = d;
 }
index b4f3691a5cd1c0977fca01af837c4d59225908eb..a694e546d7cda3951cd9bf8ea0143c78e7dd8acb 100644 (file)
@@ -19,20 +19,31 @@ typedef struct BMDMAState {
     BlockDriverCompletionFunc *dma_cb;
     int64_t sector_num;
     uint32_t nsector;
-    IORange addr_ioport;
+    MemoryRegion addr_ioport;
+    MemoryRegion extra_io;
     QEMUBH *bh;
     qemu_irq irq;
 
     /* Bit 0-2 and 7:   BM status register
      * Bit 3-6:         bus->error_status */
     uint8_t migration_compat_status;
+    struct PCIIDEState *pci_dev;
 } BMDMAState;
 
+typedef struct CMD646BAR {
+    MemoryRegion cmd;
+    MemoryRegion data;
+    IDEBus *bus;
+    struct PCIIDEState *pci_dev;
+} CMD646BAR;
+
 typedef struct PCIIDEState {
     PCIDevice dev;
     IDEBus bus[2];
     BMDMAState bmdma[2];
     uint32_t secondary; /* used only for cmd646 */
+    MemoryRegion bmdma_bar;
+    CMD646BAR cmd646_bar[2]; /* used only for cmd646 */
 } PCIIDEState;
 
 
@@ -43,9 +54,9 @@ static inline IDEState *bmdma_active_if(BMDMAState *bmdma)
 }
 
 
-void bmdma_init(IDEBus *bus, BMDMAState *bm);
-void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val);
-extern const IORangeOps bmdma_addr_ioport_ops;
+void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d);
+void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val);
+extern MemoryRegionOps bmdma_addr_ioport_ops;
 void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table);
 
 extern const VMStateDescription vmstate_ide_pci;
index 84f72b0a66e5fccccfc4a9261220c376ac14c439..8525336075a7f7b1af3642596ea1e37842bed80f 100644 (file)
 
 #include <hw/ide/pci.h>
 
-static uint32_t bmdma_readb(void *opaque, uint32_t addr)
+static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     BMDMAState *bm = opaque;
     uint32_t val;
 
+    if (size != 1) {
+        return ((uint64_t)1 << (size * 8)) - 1;
+    }
+
     switch(addr & 3) {
     case 0:
         val = bm->cmd;
@@ -55,36 +59,46 @@ static uint32_t bmdma_readb(void *opaque, uint32_t addr)
     return val;
 }
 
-static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void bmdma_write(void *opaque, target_phys_addr_t addr,
+                        uint64_t val, unsigned size)
 {
     BMDMAState *bm = opaque;
+
+    if (size != 1) {
+        return;
+    }
+
 #ifdef DEBUG_IDE
     printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
 #endif
     switch(addr & 3) {
+    case 0:
+        return bmdma_cmd_writeb(bm, val);
     case 2:
         bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06);
         break;
     }
 }
 
-static void bmdma_map(PCIDevice *pci_dev, int region_num,
-                    pcibus_t addr, pcibus_t size, int type)
+static MemoryRegionOps piix_bmdma_ops = {
+    .read = bmdma_read,
+    .write = bmdma_write,
+};
+
+static void bmdma_setup_bar(PCIIDEState *d)
 {
-    PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, pci_dev);
     int i;
 
+    memory_region_init(&d->bmdma_bar, "piix-bmdma-container", 16);
     for(i = 0;i < 2; i++) {
         BMDMAState *bm = &d->bmdma[i];
 
-        register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm);
-
-        register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm);
-        register_ioport_read(addr, 4, 1, bmdma_readb, bm);
-
-        iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4);
-        ioport_register(&bm->addr_ioport);
-        addr += 8;
+        memory_region_init_io(&bm->extra_io, &piix_bmdma_ops, bm,
+                              "piix-bmdma", 4);
+        memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io);
+        memory_region_init_io(&bm->addr_ioport, &bmdma_addr_ioport_ops, bm,
+                              "bmdma", 4);
+        memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport);
     }
 }
 
@@ -124,7 +138,7 @@ static void pci_piix_init_ports(PCIIDEState *d) {
         ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2);
         ide_init2(&d->bus[i], isa_get_irq(port_info[i].isairq));
 
-        bmdma_init(&d->bus[i], &d->bmdma[i]);
+        bmdma_init(&d->bus[i], &d->bmdma[i], d);
         d->bmdma[i].bus = &d->bus[i];
         qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb,
                                          &d->bmdma[i].dma);
@@ -140,7 +154,8 @@ static int pci_piix_ide_initfn(PCIDevice *dev)
 
     qemu_register_reset(piix3_reset, d);
 
-    pci_register_bar(&d->dev, 4, 0x10, PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
+    bmdma_setup_bar(d);
+    pci_register_bar(&d->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar);
 
     vmstate_register(&d->dev.qdev, 0, &vmstate_ide_pci, d);
 
@@ -149,6 +164,58 @@ static int pci_piix_ide_initfn(PCIDevice *dev)
     return 0;
 }
 
+static int pci_piix3_xen_ide_unplug(DeviceState *dev)
+{
+    PCIDevice *pci_dev;
+    PCIIDEState *pci_ide;
+    DriveInfo *di;
+    int i = 0;
+
+    pci_dev = DO_UPCAST(PCIDevice, qdev, dev);
+    pci_ide = DO_UPCAST(PCIIDEState, dev, pci_dev);
+
+    for (; i < 3; i++) {
+        di = drive_get_by_index(IF_IDE, i);
+        if (di != NULL && di->bdrv != NULL && !di->bdrv->removable) {
+            DeviceState *ds = bdrv_get_attached(di->bdrv);
+            if (ds) {
+                bdrv_detach(di->bdrv, ds);
+            }
+            bdrv_close(di->bdrv);
+            pci_ide->bus[di->bus].ifs[di->unit].bs = NULL;
+            drive_put_ref(di);
+        }
+    }
+    qdev_reset_all(&(pci_ide->dev.qdev));
+    return 0;
+}
+
+PCIDevice *pci_piix3_xen_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
+{
+    PCIDevice *dev;
+
+    dev = pci_create_simple(bus, devfn, "piix3-ide-xen");
+    dev->qdev.info->unplug = pci_piix3_xen_ide_unplug;
+    pci_ide_create_devs(dev, hd_table);
+    return dev;
+}
+
+static int pci_piix_ide_exitfn(PCIDevice *dev)
+{
+    PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
+    unsigned i;
+
+    for (i = 0; i < 2; ++i) {
+        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
+        memory_region_destroy(&d->bmdma[i].extra_io);
+        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
+        memory_region_destroy(&d->bmdma[i].addr_ioport);
+    }
+    memory_region_destroy(&d->bmdma_bar);
+
+    return 0;
+}
+
 /* hd_table must contain 4 block drivers */
 /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
 PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
@@ -178,6 +245,15 @@ static PCIDeviceInfo piix_ide_info[] = {
         .qdev.no_user = 1,
         .no_hotplug   = 1,
         .init         = pci_piix_ide_initfn,
+        .exit         = pci_piix_ide_exitfn,
+        .vendor_id    = PCI_VENDOR_ID_INTEL,
+        .device_id    = PCI_DEVICE_ID_INTEL_82371SB_1,
+        .class_id     = PCI_CLASS_STORAGE_IDE,
+    },{
+        .qdev.name    = "piix3-ide-xen",
+        .qdev.size    = sizeof(PCIIDEState),
+        .qdev.no_user = 1,
+        .init         = pci_piix_ide_initfn,
         .vendor_id    = PCI_VENDOR_ID_INTEL,
         .device_id    = PCI_DEVICE_ID_INTEL_82371SB_1,
         .class_id     = PCI_CLASS_STORAGE_IDE,
@@ -187,6 +263,7 @@ static PCIDeviceInfo piix_ide_info[] = {
         .qdev.no_user = 1,
         .no_hotplug   = 1,
         .init         = pci_piix_ide_initfn,
+        .exit         = pci_piix_ide_exitfn,
         .vendor_id    = PCI_VENDOR_ID_INTEL,
         .device_id    = PCI_DEVICE_ID_INTEL_82371AB,
         .class_id     = PCI_CLASS_STORAGE_IDE,
index 3474c37ff795ac6e65ed1eb9c902c3cf79a7b1d6..c0b9d43827158636f3016201bff7979f70052e4f 100644 (file)
 
 #include <hw/ide/pci.h>
 
-static uint32_t bmdma_readb(void *opaque, uint32_t addr)
+static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr,
+                           unsigned size)
 {
     BMDMAState *bm = opaque;
     uint32_t val;
 
+    if (size != 1) {
+        return ((uint64_t)1 << (size * 8)) - 1;
+    }
+
     switch (addr & 3) {
     case 0:
         val = bm->cmd;
@@ -56,13 +61,21 @@ static uint32_t bmdma_readb(void *opaque, uint32_t addr)
     return val;
 }
 
-static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void bmdma_write(void *opaque, target_phys_addr_t addr,
+                        uint64_t val, unsigned size)
 {
     BMDMAState *bm = opaque;
+
+    if (size != 1) {
+        return;
+    }
+
 #ifdef DEBUG_IDE
     printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
 #endif
     switch (addr & 3) {
+    case 0:
+        return bmdma_cmd_writeb(bm, val);
     case 2:
         bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06);
         break;
@@ -70,23 +83,25 @@ static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val)
     }
 }
 
-static void bmdma_map(PCIDevice *pci_dev, int region_num,
-                    pcibus_t addr, pcibus_t size, int type)
+static MemoryRegionOps via_bmdma_ops = {
+    .read = bmdma_read,
+    .write = bmdma_write,
+};
+
+static void bmdma_setup_bar(PCIIDEState *d)
 {
-    PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, pci_dev);
     int i;
 
+    memory_region_init(&d->bmdma_bar, "via-bmdma-container", 16);
     for(i = 0;i < 2; i++) {
         BMDMAState *bm = &d->bmdma[i];
 
-        register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm);
-
-        register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm);
-        register_ioport_read(addr, 4, 1, bmdma_readb, bm);
-
-        iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4);
-        ioport_register(&bm->addr_ioport);
-        addr += 8;
+        memory_region_init_io(&bm->extra_io, &via_bmdma_ops, bm,
+                              "via-bmdma", 4);
+        memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io);
+        memory_region_init_io(&bm->addr_ioport, &bmdma_addr_ioport_ops, bm,
+                              "bmdma", 4);
+        memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport);
     }
 }
 
@@ -147,7 +162,7 @@ static void vt82c686b_init_ports(PCIIDEState *d) {
         ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2);
         ide_init2(&d->bus[i], isa_get_irq(port_info[i].isairq));
 
-        bmdma_init(&d->bus[i], &d->bmdma[i]);
+        bmdma_init(&d->bus[i], &d->bmdma[i], d);
         d->bmdma[i].bus = &d->bus[i];
         qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb,
                                          &d->bmdma[i].dma);
@@ -164,8 +179,8 @@ static int vt82c686b_ide_initfn(PCIDevice *dev)
     pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0);
 
     qemu_register_reset(via_reset, d);
-    pci_register_bar(&d->dev, 4, 0x10,
-                           PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
+    bmdma_setup_bar(d);
+    pci_register_bar(&d->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar);
 
     vmstate_register(&dev->qdev, 0, &vmstate_ide_pci, d);
 
@@ -174,6 +189,22 @@ static int vt82c686b_ide_initfn(PCIDevice *dev)
     return 0;
 }
 
+static int vt82c686b_ide_exitfn(PCIDevice *dev)
+{
+    PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
+    unsigned i;
+
+    for (i = 0; i < 2; ++i) {
+        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
+        memory_region_destroy(&d->bmdma[i].extra_io);
+        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
+        memory_region_destroy(&d->bmdma[i].addr_ioport);
+    }
+    memory_region_destroy(&d->bmdma_bar);
+
+    return 0;
+}
+
 void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
 {
     PCIDevice *dev;
@@ -187,6 +218,7 @@ static PCIDeviceInfo via_ide_info = {
     .qdev.size    = sizeof(PCIIDEState),
     .qdev.no_user = 1,
     .init         = vt82c686b_ide_initfn,
+    .exit         = vt82c686b_ide_exitfn,
     .vendor_id    = PCI_VENDOR_ID_VIA,
     .device_id    = PCI_DEVICE_ID_VIA_IDE,
     .revision     = 0x06,
index 5a2bc3aaa9ca66619630fc18ac2770e165bb53ba..fa56a922152f2c2a363d42983f1931d732797677 100644 (file)
@@ -177,7 +177,7 @@ struct IntelHDAState {
     IntelHDAStream st[8];
 
     /* state */
-    int mmio_addr;
+    MemoryRegion mmio;
     uint32_t rirb_count;
     int64_t wall_base_ns;
 
@@ -1084,16 +1084,20 @@ static uint32_t intel_hda_mmio_readl(void *opaque, target_phys_addr_t addr)
     return intel_hda_reg_read(d, reg, 0xffffffff);
 }
 
-static CPUReadMemoryFunc * const intel_hda_mmio_read[3] = {
-    intel_hda_mmio_readb,
-    intel_hda_mmio_readw,
-    intel_hda_mmio_readl,
-};
-
-static CPUWriteMemoryFunc * const intel_hda_mmio_write[3] = {
-    intel_hda_mmio_writeb,
-    intel_hda_mmio_writew,
-    intel_hda_mmio_writel,
+static const MemoryRegionOps intel_hda_mmio_ops = {
+    .old_mmio = {
+        .read = {
+            intel_hda_mmio_readb,
+            intel_hda_mmio_readw,
+            intel_hda_mmio_readl,
+        },
+        .write = {
+            intel_hda_mmio_writeb,
+            intel_hda_mmio_writew,
+            intel_hda_mmio_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 /* --------------------------------------------------------------------- */
@@ -1130,10 +1134,9 @@ static int intel_hda_init(PCIDevice *pci)
     /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
     conf[0x40] = 0x01;
 
-    d->mmio_addr = cpu_register_io_memory(intel_hda_mmio_read,
-                                          intel_hda_mmio_write, d,
-                                          DEVICE_NATIVE_ENDIAN);
-    pci_register_bar_simple(&d->pci, 0, 0x4000, 0, d->mmio_addr);
+    memory_region_init_io(&d->mmio, &intel_hda_mmio_ops, d,
+                          "intel-hda", 0x4000);
+    pci_register_bar(&d->pci, 0, 0, &d->mmio);
     if (d->msi) {
         msi_init(&d->pci, 0x50, 1, true, false);
     }
@@ -1149,7 +1152,7 @@ static int intel_hda_exit(PCIDevice *pci)
     IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
 
     msi_uninit(&d->pci);
-    cpu_unregister_io_memory(d->mmio_addr);
+    memory_region_destroy(&d->mmio);
     return 0;
 }
 
index d2b6126602a5f932c2ce6516a4c98006b238a60c..f1f21812d6e9943b1b0ad904022a4c00b1474522 100644 (file)
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -4,6 +4,7 @@
 /* ISA bus */
 
 #include "ioport.h"
+#include "memory.h"
 #include "qdev.h"
 
 typedef struct ISABus ISABus;
@@ -37,6 +38,7 @@ ISADevice *isa_create_simple(const char *name);
 
 extern target_phys_addr_t isa_mem_base;
 
+void isa_mmio_setup(MemoryRegion *mr, target_phys_addr_t size);
 void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size);
 
 /* dma.c */
index ca957fb0101d1e2dfd35ab2938d97d823bf0e109..3d2af1a63c3d04d94f6d070c00d92ab9ce0e3142 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "hw.h"
 #include "isa.h"
+#include "exec-memory.h"
 
 static void isa_mmio_writeb (void *opaque, target_phys_addr_t addr,
                                   uint32_t val)
@@ -58,25 +59,23 @@ static uint32_t isa_mmio_readl(void *opaque, target_phys_addr_t addr)
     return cpu_inl(addr & IOPORTS_MASK);
 }
 
-static CPUWriteMemoryFunc * const isa_mmio_write[] = {
-    &isa_mmio_writeb,
-    &isa_mmio_writew,
-    &isa_mmio_writel,
+static const MemoryRegionOps isa_mmio_ops = {
+    .old_mmio = {
+        .write = { isa_mmio_writeb, isa_mmio_writew, isa_mmio_writel },
+        .read = { isa_mmio_readb, isa_mmio_readw, isa_mmio_readl, },
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-static CPUReadMemoryFunc * const isa_mmio_read[] = {
-    &isa_mmio_readb,
-    &isa_mmio_readw,
-    &isa_mmio_readl,
-};
+void isa_mmio_setup(MemoryRegion *mr, target_phys_addr_t size)
+{
+    memory_region_init_io(mr, &isa_mmio_ops, NULL, "isa-mmio", size);
+}
 
 void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size)
 {
-    int isa_mmio_iomemtype;
+    MemoryRegion *mr = qemu_malloc(sizeof(*mr));
 
-    isa_mmio_iomemtype = cpu_register_io_memory(isa_mmio_read,
-                                                isa_mmio_write,
-                                                NULL,
-                                                DEVICE_LITTLE_ENDIAN);
-    cpu_register_physical_memory(base, size, isa_mmio_iomemtype);
+    isa_mmio_setup(mr, size);
+    memory_region_add_subregion(get_system_memory(), base, mr);
 }
index 3055dd2a5031f9c838514bcd0013e13eea3ac6d3..42a58770320cfcb88e21142c8ff96458fc98477f 100644 (file)
@@ -56,11 +56,16 @@ typedef struct IVShmemState {
 
     CharDriverState **eventfd_chr;
     CharDriverState *server_chr;
-    int ivshmem_mmio_io_addr;
+    MemoryRegion ivshmem_mmio;
 
     pcibus_t mmio_addr;
-    pcibus_t shm_pci_addr;
-    uint64_t ivshmem_offset;
+    /* We might need to register the BAR before we actually have the memory.
+     * So prepare a container MemoryRegion for the BAR immediately and
+     * add a subregion when we have the memory.
+     */
+    MemoryRegion bar;
+    MemoryRegion ivshmem;
+    MemoryRegion msix_bar;
     uint64_t ivshmem_size; /* size of shared memory region */
     int shm_fd; /* shared memory file descriptor */
 
@@ -96,23 +101,6 @@ static inline bool is_power_of_two(uint64_t x) {
     return (x & (x - 1)) == 0;
 }
 
-static void ivshmem_map(PCIDevice *pci_dev, int region_num,
-                    pcibus_t addr, pcibus_t size, int type)
-{
-    IVShmemState *s = DO_UPCAST(IVShmemState, dev, pci_dev);
-
-    s->shm_pci_addr = addr;
-
-    if (s->ivshmem_offset > 0) {
-        cpu_register_physical_memory(s->shm_pci_addr, s->ivshmem_size,
-                                                            s->ivshmem_offset);
-    }
-
-    IVSHMEM_DPRINTF("guest pci addr = %" FMT_PCIBUS ", guest h/w addr = %"
-        PRIu64 ", size = %" FMT_PCIBUS "\n", addr, s->ivshmem_offset, size);
-
-}
-
 /* accessing registers - based on rtl8139 */
 static void ivshmem_update_irq(IVShmemState *s, int val)
 {
@@ -168,15 +156,8 @@ static uint32_t ivshmem_IntrStatus_read(IVShmemState *s)
     return ret;
 }
 
-static void ivshmem_io_writew(void *opaque, target_phys_addr_t addr,
-                                                            uint32_t val)
-{
-
-    IVSHMEM_DPRINTF("We shouldn't be writing words\n");
-}
-
-static void ivshmem_io_writel(void *opaque, target_phys_addr_t addr,
-                                                            uint32_t val)
+static void ivshmem_io_write(void *opaque, target_phys_addr_t addr,
+                             uint64_t val, unsigned size)
 {
     IVShmemState *s = opaque;
 
@@ -219,20 +200,8 @@ static void ivshmem_io_writel(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void ivshmem_io_writeb(void *opaque, target_phys_addr_t addr,
-                                                                uint32_t val)
-{
-    IVSHMEM_DPRINTF("We shouldn't be writing bytes\n");
-}
-
-static uint32_t ivshmem_io_readw(void *opaque, target_phys_addr_t addr)
-{
-
-    IVSHMEM_DPRINTF("We shouldn't be reading words\n");
-    return 0;
-}
-
-static uint32_t ivshmem_io_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t ivshmem_io_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
 {
 
     IVShmemState *s = opaque;
@@ -265,23 +234,14 @@ static uint32_t ivshmem_io_readl(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static uint32_t ivshmem_io_readb(void *opaque, target_phys_addr_t addr)
-{
-    IVSHMEM_DPRINTF("We shouldn't be reading bytes\n");
-
-    return 0;
-}
-
-static CPUReadMemoryFunc * const ivshmem_mmio_read[3] = {
-    ivshmem_io_readb,
-    ivshmem_io_readw,
-    ivshmem_io_readl,
-};
-
-static CPUWriteMemoryFunc * const ivshmem_mmio_write[3] = {
-    ivshmem_io_writeb,
-    ivshmem_io_writew,
-    ivshmem_io_writel,
+static const MemoryRegionOps ivshmem_mmio_ops = {
+    .read = ivshmem_io_read,
+    .write = ivshmem_io_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static void ivshmem_receive(void *opaque, const uint8_t *buf, int size)
@@ -371,12 +331,12 @@ static void create_shared_memory_BAR(IVShmemState *s, int fd) {
 
     ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
 
-    s->ivshmem_offset = qemu_ram_alloc_from_ptr(&s->dev.qdev, "ivshmem.bar2",
-                                                        s->ivshmem_size, ptr);
+    memory_region_init_ram_ptr(&s->ivshmem, &s->dev.qdev, "ivshmem.bar2",
+                               s->ivshmem_size, ptr);
+    memory_region_add_subregion(&s->bar, 0, &s->ivshmem);
 
     /* region for shared memory */
-    pci_register_bar(&s->dev, 2, s->ivshmem_size,
-                                PCI_BASE_ADDRESS_SPACE_MEMORY, ivshmem_map);
+    pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
 }
 
 static void close_guest_eventfds(IVShmemState *s, int posn)
@@ -401,8 +361,12 @@ static void setup_ioeventfds(IVShmemState *s) {
 
     for (i = 0; i <= s->max_peer; i++) {
         for (j = 0; j < s->peers[i].nb_eventfds; j++) {
-            kvm_set_ioeventfd_mmio_long(s->peers[i].eventfds[j],
-                    s->mmio_addr + DOORBELL, (i << 16) | j, 1);
+            memory_region_add_eventfd(&s->ivshmem_mmio,
+                                      DOORBELL,
+                                      4,
+                                      true,
+                                      (i << 16) | j,
+                                      s->peers[i].eventfds[j]);
         }
     }
 }
@@ -483,18 +447,13 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags)
         /* mmap the region and map into the BAR2 */
         map_ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED,
                                                             incoming_fd, 0);
-        s->ivshmem_offset = qemu_ram_alloc_from_ptr(&s->dev.qdev,
-                                    "ivshmem.bar2", s->ivshmem_size, map_ptr);
+        memory_region_init_ram_ptr(&s->ivshmem, &s->dev.qdev,
+                                   "ivshmem.bar2", s->ivshmem_size, map_ptr);
 
-        IVSHMEM_DPRINTF("guest pci addr = %" FMT_PCIBUS ", guest h/w addr = %"
-                         PRIu64 ", size = %" PRIu64 "\n", s->shm_pci_addr,
+        IVSHMEM_DPRINTF("guest h/w addr = %" PRIu64 ", size = %" PRIu64 "\n",
                          s->ivshmem_offset, s->ivshmem_size);
 
-        if (s->shm_pci_addr > 0) {
-            /* map memory into BAR2 */
-            cpu_register_physical_memory(s->shm_pci_addr, s->ivshmem_size,
-                                                            s->ivshmem_offset);
-        }
+        memory_region_add_subregion(&s->bar, 0, &s->ivshmem);
 
         /* only store the fd if it is successfully mapped */
         s->shm_fd = incoming_fd;
@@ -549,20 +508,6 @@ static void ivshmem_reset(DeviceState *d)
     return;
 }
 
-static void ivshmem_mmio_map(PCIDevice *pci_dev, int region_num,
-                       pcibus_t addr, pcibus_t size, int type)
-{
-    IVShmemState *s = DO_UPCAST(IVShmemState, dev, pci_dev);
-
-    s->mmio_addr = addr;
-    cpu_register_physical_memory(addr + 0, IVSHMEM_REG_BAR_SIZE,
-                                                s->ivshmem_mmio_io_addr);
-
-    if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) {
-        setup_ioeventfds(s);
-    }
-}
-
 static uint64_t ivshmem_get_size(IVShmemState * s) {
 
     uint64_t value;
@@ -596,11 +541,10 @@ static void ivshmem_setup_msi(IVShmemState * s) {
 
     /* allocate the MSI-X vectors */
 
-    if (!msix_init(&s->dev, s->vectors, 1, 0)) {
-        pci_register_bar(&s->dev, 1,
-                         msix_bar_size(&s->dev),
-                         PCI_BASE_ADDRESS_SPACE_MEMORY,
-                         msix_mmio_map);
+    memory_region_init(&s->msix_bar, "ivshmem-msix", 4096);
+    if (!msix_init(&s->dev, s->vectors, &s->msix_bar, 1, 0)) {
+        pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
+                         &s->msix_bar);
         IVSHMEM_DPRINTF("msix initialized (%d vectors)\n", s->vectors);
     } else {
         IVSHMEM_DPRINTF("msix initialization failed\n");
@@ -710,15 +654,20 @@ static int pci_ivshmem_init(PCIDevice *dev)
 
     pci_config_set_interrupt_pin(pci_conf, 1);
 
-    s->shm_pci_addr = 0;
-    s->ivshmem_offset = 0;
     s->shm_fd = 0;
 
-    s->ivshmem_mmio_io_addr = cpu_register_io_memory(ivshmem_mmio_read,
-                                    ivshmem_mmio_write, s, DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&s->ivshmem_mmio, &ivshmem_mmio_ops, s,
+                          "ivshmem-mmio", IVSHMEM_REG_BAR_SIZE);
+
+    if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) {
+        setup_ioeventfds(s);
+    }
+
     /* region for registers*/
-    pci_register_bar(&s->dev, 0, IVSHMEM_REG_BAR_SIZE,
-                           PCI_BASE_ADDRESS_SPACE_MEMORY, ivshmem_mmio_map);
+    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
+                     &s->ivshmem_mmio);
+
+    memory_region_init(&s->bar, "ivshmem-bar2-container", s->ivshmem_size);
 
     if ((s->server_chr != NULL) &&
                         (strncmp(s->server_chr->filename, "unix:", 5) == 0)) {
@@ -744,8 +693,8 @@ static int pci_ivshmem_init(PCIDevice *dev)
         /* allocate/initialize space for interrupt handling */
         s->peers = qemu_mallocz(s->nb_peers * sizeof(Peer));
 
-        pci_register_bar(&s->dev, 2, s->ivshmem_size,
-                                PCI_BASE_ADDRESS_SPACE_MEMORY, ivshmem_map);
+        pci_register_bar(&s->dev, 2,
+                         PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ivshmem);
 
         s->eventfd_chr = qemu_mallocz(s->vectors * sizeof(CharDriverState *));
 
@@ -792,7 +741,10 @@ static int pci_ivshmem_uninit(PCIDevice *dev)
 {
     IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
 
-    cpu_unregister_io_memory(s->ivshmem_mmio_io_addr);
+    memory_region_destroy(&s->ivshmem_mmio);
+    memory_region_del_subregion(&s->bar, &s->ivshmem);
+    memory_region_destroy(&s->ivshmem);
+    memory_region_destroy(&s->bar);
     unregister_savevm(&dev->qdev, "ivshmem", s);
 
     return 0;
index 692ad182f01da9f6160c158c05a69547889cb4f7..b73aec409c53e9a7c0d15c2e37560f6c6d28307a 100644 (file)
@@ -101,11 +101,8 @@ static SysBusDeviceInfo kvmclock_info = {
 void kvmclock_create(void)
 {
     if (kvm_enabled() &&
-        first_cpu->cpuid_kvm_features & ((1ULL << KVM_FEATURE_CLOCKSOURCE)
-#ifdef KVM_FEATURE_CLOCKSOURCE2
-        || (1ULL << KVM_FEATURE_CLOCKSOURCE2)
-#endif
-    )) {
+        first_cpu->cpuid_kvm_features & ((1ULL << KVM_FEATURE_CLOCKSOURCE) |
+                                         (1ULL << KVM_FEATURE_CLOCKSOURCE2))) {
         sysbus_create_simple("kvmclock", -1, NULL);
     }
 }
index ddb1cbb7a42d6943ae5c5252ab076bea4eb6c9d3..d83e7f57a9161741165043491d43c2f4ef8cb8a3 100644 (file)
@@ -55,8 +55,8 @@ static void parent_lance_reset(void *opaque, int irq, int level)
         pcnet_h_reset(&d->state);
 }
 
-static void lance_mem_writew(void *opaque, target_phys_addr_t addr,
-                             uint32_t val)
+static void lance_mem_write(void *opaque, target_phys_addr_t addr,
+                            uint64_t val, unsigned size)
 {
     SysBusPCNetState *d = opaque;
 
@@ -64,7 +64,8 @@ static void lance_mem_writew(void *opaque, target_phys_addr_t addr,
     pcnet_ioport_writew(&d->state, addr, val & 0xffff);
 }
 
-static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
+static uint64_t lance_mem_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     SysBusPCNetState *d = opaque;
     uint32_t val;
@@ -74,16 +75,14 @@ static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
     return val & 0xffff;
 }
 
-static CPUReadMemoryFunc * const lance_mem_read[3] = {
-    NULL,
-    lance_mem_readw,
-    NULL,
-};
-
-static CPUWriteMemoryFunc * const lance_mem_write[3] = {
-    NULL,
-    lance_mem_writew,
-    NULL,
+static const MemoryRegionOps lance_mem_ops = {
+    .read = lance_mem_read,
+    .write = lance_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 2,
+        .max_access_size = 2,
+    },
 };
 
 static void lance_cleanup(VLANClientState *nc)
@@ -117,13 +116,11 @@ static int lance_init(SysBusDevice *dev)
     SysBusPCNetState *d = FROM_SYSBUS(SysBusPCNetState, dev);
     PCNetState *s = &d->state;
 
-    s->mmio_index =
-        cpu_register_io_memory(lance_mem_read, lance_mem_write, d,
-                               DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&s->mmio, &lance_mem_ops, d, "lance-mmio", 4);
 
     qdev_init_gpio_in(&dev->qdev, parent_lance_reset, 1);
 
-    sysbus_init_mmio(dev, 4, s->mmio_index);
+    sysbus_init_mmio_region(dev, &s->mmio);
 
     sysbus_init_irq(dev, &s->irq);
 
index 590a4ccff92104de8db149989ac85b70f269d71f..992ce49729d3d1f93510e2bf5a9ea134654a2cd3 100644 (file)
@@ -474,9 +474,9 @@ static int lm8323_init(i2c_slave *i2c)
     return 0;
 }
 
-void lm832x_key_event(struct i2c_slave *i2c, int key, int state)
+void lm832x_key_event(DeviceState *dev, int key, int state)
 {
-    LM823KbdState *s = (LM823KbdState *) i2c;
+    LM823KbdState *s = FROM_I2C_SLAVE(LM823KbdState, I2C_SLAVE_FROM_QDEV(dev));
 
     if ((s->status & INT_ERROR) && (s->error & ERR_FIFOOVR))
         return;
index e9904c49d9297d4250420ab42e0ed662e3b70591..d067a0227e11e6b7b5d9f760abc55f833e58fae8 100644 (file)
@@ -185,9 +185,9 @@ typedef struct lsi_request {
 
 typedef struct {
     PCIDevice dev;
-    int mmio_io_addr;
-    int ram_io_addr;
-    uint32_t script_ram_base;
+    MemoryRegion mmio_io;
+    MemoryRegion ram_io;
+    MemoryRegion io_io;
 
     int carry; /* ??? Should this be an a visible register somewhere?  */
     int status;
@@ -391,10 +391,9 @@ static inline uint32_t read_dword(LSIState *s, uint32_t addr)
 {
     uint32_t buf;
 
-    /* Optimize reading from SCRIPTS RAM.  */
-    if ((addr & 0xffffe000) == s->script_ram_base) {
-        return s->script_ram[(addr & 0x1fff) >> 2];
-    }
+    /* XXX: an optimization here used to fast-path the read from scripts
+     * memory.  But that bypasses any iommu.
+     */
     cpu_physical_memory_read(addr, (uint8_t *)&buf, 4);
     return cpu_to_le32(buf);
 }
@@ -1899,232 +1898,90 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
 #undef CASE_SET_REG32
 }
 
-static void lsi_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void lsi_mmio_write(void *opaque, target_phys_addr_t addr,
+                           uint64_t val, unsigned size)
 {
     LSIState *s = opaque;
 
     lsi_reg_writeb(s, addr & 0xff, val);
 }
 
-static void lsi_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    LSIState *s = opaque;
-
-    addr &= 0xff;
-    lsi_reg_writeb(s, addr, val & 0xff);
-    lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
-}
-
-static void lsi_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    LSIState *s = opaque;
-
-    addr &= 0xff;
-    lsi_reg_writeb(s, addr, val & 0xff);
-    lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
-    lsi_reg_writeb(s, addr + 2, (val >> 16) & 0xff);
-    lsi_reg_writeb(s, addr + 3, (val >> 24) & 0xff);
-}
-
-static uint32_t lsi_mmio_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t lsi_mmio_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     LSIState *s = opaque;
 
     return lsi_reg_readb(s, addr & 0xff);
 }
 
-static uint32_t lsi_mmio_readw(void *opaque, target_phys_addr_t addr)
-{
-    LSIState *s = opaque;
-    uint32_t val;
-
-    addr &= 0xff;
-    val = lsi_reg_readb(s, addr);
-    val |= lsi_reg_readb(s, addr + 1) << 8;
-    return val;
-}
-
-static uint32_t lsi_mmio_readl(void *opaque, target_phys_addr_t addr)
-{
-    LSIState *s = opaque;
-    uint32_t val;
-    addr &= 0xff;
-    val = lsi_reg_readb(s, addr);
-    val |= lsi_reg_readb(s, addr + 1) << 8;
-    val |= lsi_reg_readb(s, addr + 2) << 16;
-    val |= lsi_reg_readb(s, addr + 3) << 24;
-    return val;
-}
-
-static CPUReadMemoryFunc * const lsi_mmio_readfn[3] = {
-    lsi_mmio_readb,
-    lsi_mmio_readw,
-    lsi_mmio_readl,
-};
-
-static CPUWriteMemoryFunc * const lsi_mmio_writefn[3] = {
-    lsi_mmio_writeb,
-    lsi_mmio_writew,
-    lsi_mmio_writel,
+static const MemoryRegionOps lsi_mmio_ops = {
+    .read = lsi_mmio_read,
+    .write = lsi_mmio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
-static void lsi_ram_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void lsi_ram_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t val, unsigned size)
 {
     LSIState *s = opaque;
     uint32_t newval;
+    uint32_t mask;
     int shift;
 
-    addr &= 0x1fff;
     newval = s->script_ram[addr >> 2];
     shift = (addr & 3) * 8;
-    newval &= ~(0xff << shift);
+    mask = ((uint64_t)1 << (size * 8)) - 1;
+    newval &= ~(mask << shift);
     newval |= val << shift;
     s->script_ram[addr >> 2] = newval;
 }
 
-static void lsi_ram_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    LSIState *s = opaque;
-    uint32_t newval;
-
-    addr &= 0x1fff;
-    newval = s->script_ram[addr >> 2];
-    if (addr & 2) {
-        newval = (newval & 0xffff) | (val << 16);
-    } else {
-        newval = (newval & 0xffff0000) | val;
-    }
-    s->script_ram[addr >> 2] = newval;
-}
-
-
-static void lsi_ram_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    LSIState *s = opaque;
-
-    addr &= 0x1fff;
-    s->script_ram[addr >> 2] = val;
-}
-
-static uint32_t lsi_ram_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t lsi_ram_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     LSIState *s = opaque;
     uint32_t val;
+    uint32_t mask;
 
-    addr &= 0x1fff;
     val = s->script_ram[addr >> 2];
+    mask = ((uint64_t)1 << (size * 8)) - 1;
     val >>= (addr & 3) * 8;
-    return val & 0xff;
-}
-
-static uint32_t lsi_ram_readw(void *opaque, target_phys_addr_t addr)
-{
-    LSIState *s = opaque;
-    uint32_t val;
-
-    addr &= 0x1fff;
-    val = s->script_ram[addr >> 2];
-    if (addr & 2)
-        val >>= 16;
-    return val;
-}
-
-static uint32_t lsi_ram_readl(void *opaque, target_phys_addr_t addr)
-{
-    LSIState *s = opaque;
-
-    addr &= 0x1fff;
-    return s->script_ram[addr >> 2];
+    return val & mask;
 }
 
-static CPUReadMemoryFunc * const lsi_ram_readfn[3] = {
-    lsi_ram_readb,
-    lsi_ram_readw,
-    lsi_ram_readl,
+static const MemoryRegionOps lsi_ram_ops = {
+    .read = lsi_ram_read,
+    .write = lsi_ram_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const lsi_ram_writefn[3] = {
-    lsi_ram_writeb,
-    lsi_ram_writew,
-    lsi_ram_writel,
-};
-
-static uint32_t lsi_io_readb(void *opaque, uint32_t addr)
+static uint64_t lsi_io_read(void *opaque, target_phys_addr_t addr,
+                            unsigned size)
 {
     LSIState *s = opaque;
     return lsi_reg_readb(s, addr & 0xff);
 }
 
-static uint32_t lsi_io_readw(void *opaque, uint32_t addr)
-{
-    LSIState *s = opaque;
-    uint32_t val;
-    addr &= 0xff;
-    val = lsi_reg_readb(s, addr);
-    val |= lsi_reg_readb(s, addr + 1) << 8;
-    return val;
-}
-
-static uint32_t lsi_io_readl(void *opaque, uint32_t addr)
-{
-    LSIState *s = opaque;
-    uint32_t val;
-    addr &= 0xff;
-    val = lsi_reg_readb(s, addr);
-    val |= lsi_reg_readb(s, addr + 1) << 8;
-    val |= lsi_reg_readb(s, addr + 2) << 16;
-    val |= lsi_reg_readb(s, addr + 3) << 24;
-    return val;
-}
-
-static void lsi_io_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void lsi_io_write(void *opaque, target_phys_addr_t addr,
+                         uint64_t val, unsigned size)
 {
     LSIState *s = opaque;
     lsi_reg_writeb(s, addr & 0xff, val);
 }
 
-static void lsi_io_writew(void *opaque, uint32_t addr, uint32_t val)
-{
-    LSIState *s = opaque;
-    addr &= 0xff;
-    lsi_reg_writeb(s, addr, val & 0xff);
-    lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
-}
-
-static void lsi_io_writel(void *opaque, uint32_t addr, uint32_t val)
-{
-    LSIState *s = opaque;
-    addr &= 0xff;
-    lsi_reg_writeb(s, addr, val & 0xff);
-    lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
-    lsi_reg_writeb(s, addr + 2, (val >> 16) & 0xff);
-    lsi_reg_writeb(s, addr + 3, (val >> 24) & 0xff);
-}
-
-static void lsi_io_mapfunc(PCIDevice *pci_dev, int region_num,
-                           pcibus_t addr, pcibus_t size, int type)
-{
-    LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
-
-    DPRINTF("Mapping IO at %08"FMT_PCIBUS"\n", addr);
-
-    register_ioport_write(addr, 256, 1, lsi_io_writeb, s);
-    register_ioport_read(addr, 256, 1, lsi_io_readb, s);
-    register_ioport_write(addr, 256, 2, lsi_io_writew, s);
-    register_ioport_read(addr, 256, 2, lsi_io_readw, s);
-    register_ioport_write(addr, 256, 4, lsi_io_writel, s);
-    register_ioport_read(addr, 256, 4, lsi_io_readl, s);
-}
-
-static void lsi_ram_mapfunc(PCIDevice *pci_dev, int region_num,
-                            pcibus_t addr, pcibus_t size, int type)
-{
-    LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
-
-    DPRINTF("Mapping ram at %08"FMT_PCIBUS"\n", addr);
-    s->script_ram_base = addr;
-    cpu_register_physical_memory(addr + 0, 0x2000, s->ram_io_addr);
-}
+static const MemoryRegionOps lsi_io_ops = {
+    .read = lsi_io_read,
+    .write = lsi_io_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
 
 static void lsi_scsi_reset(DeviceState *dev)
 {
@@ -2231,8 +2088,9 @@ static int lsi_scsi_uninit(PCIDevice *d)
 {
     LSIState *s = DO_UPCAST(LSIState, dev, d);
 
-    cpu_unregister_io_memory(s->mmio_io_addr);
-    cpu_unregister_io_memory(s->ram_io_addr);
+    memory_region_destroy(&s->mmio_io);
+    memory_region_destroy(&s->ram_io);
+    memory_region_destroy(&s->io_io);
 
     return 0;
 }
@@ -2256,18 +2114,13 @@ static int lsi_scsi_init(PCIDevice *dev)
     /* Interrupt pin 1 */
     pci_conf[PCI_INTERRUPT_PIN] = 0x01;
 
-    s->mmio_io_addr = cpu_register_io_memory(lsi_mmio_readfn,
-                                             lsi_mmio_writefn, s,
-                                             DEVICE_NATIVE_ENDIAN);
-    s->ram_io_addr = cpu_register_io_memory(lsi_ram_readfn,
-                                            lsi_ram_writefn, s,
-                                            DEVICE_NATIVE_ENDIAN);
-
-    pci_register_bar(&s->dev, 0, 256,
-                           PCI_BASE_ADDRESS_SPACE_IO, lsi_io_mapfunc);
-    pci_register_bar_simple(&s->dev, 1, 0x400, 0, s->mmio_io_addr);
-    pci_register_bar(&s->dev, 2, 0x2000,
-                           PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_ram_mapfunc);
+    memory_region_init_io(&s->mmio_io, &lsi_mmio_ops, s, "lsi-mmio", 0x400);
+    memory_region_init_io(&s->ram_io, &lsi_ram_ops, s, "lsi-ram", 0x2000);
+    memory_region_init_io(&s->io_io, &lsi_io_ops, s, "lsi-io", 256);
+
+    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_io);
+    pci_register_bar(&s->dev, 1, 0, &s->mmio_io);
+    pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_io);
     QTAILQ_INIT(&s->queue);
 
     scsi_bus_new(&s->bus, &dev->qdev, 1, LSI_MAX_DEVS, &lsi_scsi_ops);
index ed4458e3bb93f53a86f7191b42a90bbbf6da6c23..350d901edc62767e3fa48fb2265cfb3306dc4f94 100644 (file)
@@ -166,6 +166,7 @@ typedef struct DBDMA_channel {
 } DBDMA_channel;
 
 typedef struct {
+    MemoryRegion mem;
     DBDMA_channel channels[DBDMA_CHANNELS];
 } DBDMAState;
 
@@ -703,8 +704,8 @@ dbdma_control_write(DBDMA_channel *ch)
         ch->flush(&ch->io);
 }
 
-static void dbdma_writel (void *opaque,
-                          target_phys_addr_t addr, uint32_t value)
+static void dbdma_write(void *opaque, target_phys_addr_t addr,
+                        uint64_t value, unsigned size)
 {
     int channel = addr >> DBDMA_CHANNEL_SHIFT;
     DBDMAState *s = opaque;
@@ -753,7 +754,8 @@ static void dbdma_writel (void *opaque,
     }
 }
 
-static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
+static uint64_t dbdma_read(void *opaque, target_phys_addr_t addr,
+                           unsigned size)
 {
     uint32_t value;
     int channel = addr >> DBDMA_CHANNEL_SHIFT;
@@ -798,16 +800,14 @@ static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
     return value;
 }
 
-static CPUWriteMemoryFunc * const dbdma_write[] = {
-    NULL,
-    NULL,
-    dbdma_writel,
-};
-
-static CPUReadMemoryFunc * const dbdma_read[] = {
-    NULL,
-    NULL,
-    dbdma_readl,
+static const MemoryRegionOps dbdma_ops = {
+    .read = dbdma_read,
+    .write = dbdma_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static const VMStateDescription vmstate_dbdma_channel = {
@@ -842,14 +842,14 @@ static void dbdma_reset(void *opaque)
         memset(s->channels[i].regs, 0, DBDMA_SIZE);
 }
 
-void* DBDMA_init (int *dbdma_mem_index)
+void* DBDMA_init (MemoryRegion **dbdma_mem)
 {
     DBDMAState *s;
 
     s = qemu_mallocz(sizeof(DBDMAState));
 
-    *dbdma_mem_index = cpu_register_io_memory(dbdma_read, dbdma_write, s,
-                                              DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&s->mem, &dbdma_ops, s, "dbdma", 0x1000);
+    *dbdma_mem = &s->mem;
     vmstate_register(NULL, -1, &vmstate_dbdma, s);
     qemu_register_reset(dbdma_reset, s);
 
index d236c5b3f29eead8b849e85ba23d4f332d2482f9..933e17c5b953e14535e7acd369cda08d72088c25 100644 (file)
@@ -20,6 +20,8 @@
  * THE SOFTWARE.
  */
 
+#include "memory.h"
+
 typedef struct DBDMA_io DBDMA_io;
 
 typedef void (*DBDMA_flush)(DBDMA_io *io);
@@ -40,4 +42,4 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
                             DBDMA_rw rw, DBDMA_flush flush,
                             void *opaque);
 void DBDMA_schedule(void);
-void* DBDMA_init (int *dbdma_mem_index);
+void* DBDMA_init (MemoryRegion **dbdma_mem);
index 61e53d28b4d2bdaeec422f4b05d63e92a450ccf6..ced1e585da9b6b6e2f9c96e639eed5a4b8557063 100644 (file)
@@ -39,7 +39,7 @@
 
 struct MacIONVRAMState {
     uint32_t size;
-    int mem_index;
+    MemoryRegion mem;
     unsigned int it_shift;
     uint8_t *data;
 };
@@ -71,8 +71,8 @@ void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val)
 }
 
 /* macio style NVRAM device */
-static void macio_nvram_writeb (void *opaque,
-                                target_phys_addr_t addr, uint32_t value)
+static void macio_nvram_writeb(void *opaque, target_phys_addr_t addr,
+                               uint64_t value, unsigned size)
 {
     MacIONVRAMState *s = opaque;
 
@@ -81,7 +81,8 @@ static void macio_nvram_writeb (void *opaque,
     NVR_DPRINTF("writeb addr %04x val %x\n", (int)addr, value);
 }
 
-static uint32_t macio_nvram_readb (void *opaque, target_phys_addr_t addr)
+static uint64_t macio_nvram_readb(void *opaque, target_phys_addr_t addr,
+                                  unsigned size)
 {
     MacIONVRAMState *s = opaque;
     uint32_t value;
@@ -93,16 +94,10 @@ static uint32_t macio_nvram_readb (void *opaque, target_phys_addr_t addr)
     return value;
 }
 
-static CPUWriteMemoryFunc * const nvram_write[] = {
-    &macio_nvram_writeb,
-    &macio_nvram_writeb,
-    &macio_nvram_writeb,
-};
-
-static CPUReadMemoryFunc * const nvram_read[] = {
-    &macio_nvram_readb,
-    &macio_nvram_readb,
-    &macio_nvram_readb,
+static const MemoryRegionOps macio_nvram_ops = {
+    .read = macio_nvram_readb,
+    .write = macio_nvram_writeb,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_macio_nvram = {
@@ -121,7 +116,7 @@ static void macio_nvram_reset(void *opaque)
 {
 }
 
-MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size,
+MacIONVRAMState *macio_nvram_init (target_phys_addr_t size,
                                    unsigned int it_shift)
 {
     MacIONVRAMState *s;
@@ -131,22 +126,18 @@ MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size,
     s->size = size;
     s->it_shift = it_shift;
 
-    s->mem_index = cpu_register_io_memory(nvram_read, nvram_write, s,
-                                          DEVICE_NATIVE_ENDIAN);
-    *mem_index = s->mem_index;
+    memory_region_init_io(&s->mem, &macio_nvram_ops, s, "macio-nvram",
+                          size << it_shift);
     vmstate_register(NULL, -1, &vmstate_macio_nvram, s);
     qemu_register_reset(macio_nvram_reset, s);
 
     return s;
 }
 
-void macio_nvram_map (void *opaque, target_phys_addr_t mem_base)
+void macio_nvram_setup_bar(MacIONVRAMState *s, MemoryRegion *bar,
+                           target_phys_addr_t mem_base)
 {
-    MacIONVRAMState *s;
-
-    s = opaque;
-    cpu_register_physical_memory(mem_base, s->size << s->it_shift,
-                                 s->mem_index);
+    memory_region_add_subregion(bar, mem_base, &s->mem);
 }
 
 /* Set up a system OpenBIOS NVRAM partition */
index 789ca5529d2125a5224976da72a09c0a0fe8326e..cc6ae400505e84ee9b3f8030c07ce0cf78aa084f 100644 (file)
 typedef struct macio_state_t macio_state_t;
 struct macio_state_t {
     int is_oldworld;
-    int pic_mem_index;
-    int dbdma_mem_index;
-    int cuda_mem_index;
-    int escc_mem_index;
+    MemoryRegion bar;
+    MemoryRegion *pic_mem;
+    MemoryRegion *dbdma_mem;
+    MemoryRegion *cuda_mem;
+    MemoryRegion *escc_mem;
     void *nvram;
     int nb_ide;
-    int ide_mem_index[4];
+    MemoryRegion *ide_mem[4];
 };
 
-static void macio_map (PCIDevice *pci_dev, int region_num,
-                       pcibus_t addr, pcibus_t size, int type)
+static void macio_bar_setup(macio_state_t *macio_state)
 {
-    macio_state_t *macio_state;
     int i;
+    MemoryRegion *bar = &macio_state->bar;
 
-    macio_state = (macio_state_t *)(pci_dev + 1);
-    if (macio_state->pic_mem_index >= 0) {
+    memory_region_init(bar, "macio", 0x80000);
+    if (macio_state->pic_mem) {
         if (macio_state->is_oldworld) {
             /* Heathrow PIC */
-            cpu_register_physical_memory(addr + 0x00000, 0x1000,
-                                         macio_state->pic_mem_index);
+            memory_region_add_subregion(bar, 0x00000, macio_state->pic_mem);
         } else {
             /* OpenPIC */
-            cpu_register_physical_memory(addr + 0x40000, 0x40000,
-                                         macio_state->pic_mem_index);
+            memory_region_add_subregion(bar, 0x40000, macio_state->pic_mem);
         }
     }
-    if (macio_state->dbdma_mem_index >= 0) {
-        cpu_register_physical_memory(addr + 0x08000, 0x1000,
-                                     macio_state->dbdma_mem_index);
+    if (macio_state->dbdma_mem) {
+        memory_region_add_subregion(bar, 0x08000, macio_state->dbdma_mem);
     }
-    if (macio_state->escc_mem_index >= 0) {
-        cpu_register_physical_memory(addr + 0x13000, ESCC_SIZE << 4,
-                                     macio_state->escc_mem_index);
+    if (macio_state->escc_mem) {
+        memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem);
     }
-    if (macio_state->cuda_mem_index >= 0) {
-        cpu_register_physical_memory(addr + 0x16000, 0x2000,
-                                     macio_state->cuda_mem_index);
+    if (macio_state->cuda_mem) {
+        memory_region_add_subregion(bar, 0x16000, macio_state->cuda_mem);
     }
     for (i = 0; i < macio_state->nb_ide; i++) {
-        if (macio_state->ide_mem_index[i] >= 0) {
-            cpu_register_physical_memory(addr + 0x1f000 + (i * 0x1000), 0x1000,
-                                         macio_state->ide_mem_index[i]);
+        if (macio_state->ide_mem[i]) {
+            memory_region_add_subregion(bar, 0x1f000 + (i * 0x1000),
+                                        macio_state->ide_mem[i]);
         }
     }
     if (macio_state->nvram != NULL)
-        macio_nvram_map(macio_state->nvram, addr + 0x60000);
+        macio_nvram_setup_bar(macio_state->nvram, bar, 0x60000);
 }
 
-void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
-                 int dbdma_mem_index, int cuda_mem_index, void *nvram,
-                 int nb_ide, int *ide_mem_index, int escc_mem_index)
+void macio_init (PCIBus *bus, int device_id, int is_oldworld,
+                 MemoryRegion *pic_mem, MemoryRegion *dbdma_mem,
+                 MemoryRegion *cuda_mem, void *nvram,
+                 int nb_ide, MemoryRegion **ide_mem,
+                 MemoryRegion *escc_mem)
 {
     PCIDevice *d;
     macio_state_t *macio_state;
@@ -92,18 +89,18 @@ void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
                             -1, NULL, NULL);
     macio_state = (macio_state_t *)(d + 1);
     macio_state->is_oldworld = is_oldworld;
-    macio_state->pic_mem_index = pic_mem_index;
-    macio_state->dbdma_mem_index = dbdma_mem_index;
-    macio_state->cuda_mem_index = cuda_mem_index;
-    macio_state->escc_mem_index = escc_mem_index;
+    macio_state->pic_mem = pic_mem;
+    macio_state->dbdma_mem = dbdma_mem;
+    macio_state->cuda_mem = cuda_mem;
+    macio_state->escc_mem = escc_mem;
     macio_state->nvram = nvram;
     if (nb_ide > 4)
         nb_ide = 4;
     macio_state->nb_ide = nb_ide;
     for (i = 0; i < nb_ide; i++)
-        macio_state->ide_mem_index[i] = ide_mem_index[i];
+        macio_state->ide_mem[i] = ide_mem[i];
     for (; i < 4; i++)
-        macio_state->ide_mem_index[i] = -1;
+        macio_state->ide_mem[i] = NULL;
     /* Note: this code is strongly inspirated from the corresponding code
        in PearPC */
 
@@ -113,6 +110,6 @@ void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
 
     d->config[0x3d] = 0x01; // interrupt on pin 1
 
-    pci_register_bar(d, 0, 0x80000,
-                           PCI_BASE_ADDRESS_SPACE_MEMORY, macio_map);
+    macio_bar_setup(macio_state);
+    pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &macio_state->bar);
 }
index ce2bfc60f28e9c729f5dde966aada06120b52e3d..75c85aeb6f2dd068e5a738a844bea8d9c7a07ad0 100644 (file)
@@ -234,11 +234,11 @@ static void softusb_usbdev_datain(void *opaque)
 
     USBPacket p;
 
-    p.pid = USB_TOKEN_IN;
-    p.devep = 1;
-    p.data = s->kbd_usb_buffer;
-    p.len = sizeof(s->kbd_usb_buffer);
+    usb_packet_init(&p);
+    usb_packet_setup(&p, USB_TOKEN_IN, 0, 1);
+    usb_packet_addbuf(&p, s->kbd_usb_buffer, sizeof(s->kbd_usb_buffer));
     s->usbdev->info->handle_data(s->usbdev, &p);
+    usb_packet_cleanup(&p);
 
     softusb_kbd_changed(s);
 }
@@ -310,10 +310,12 @@ static int milkymist_softusb_init(SysBusDevice *dev)
     usb_bus_new(&s->usbbus, &softusb_bus_ops, NULL);
 
     /* our two ports */
+    /* FIXME: claim to support full speed devices. qemu mouse and keyboard
+     * report themselves as full speed devices. */
     usb_register_port(&s->usbbus, &s->usbport[0], NULL, 0, &softusb_ops,
-            USB_SPEED_MASK_LOW);
+            USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
     usb_register_port(&s->usbbus, &s->usbport[1], NULL, 1, &softusb_ops,
-            USB_SPEED_MASK_LOW);
+            USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
 
     /* and finally create an usb keyboard */
     s->usbdev = usb_create_simple(&s->usbbus, "usb-kbd");
index e67e700a33bd1d3a059e1f59197ca8f575674f22..8536c3fc8049374fc427a3989c1523cd8fdf2aef 100644 (file)
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -82,7 +82,8 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries,
     return 0;
 }
 
-static uint32_t msix_mmio_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t msix_mmio_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     PCIDevice *dev = opaque;
     unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3;
@@ -91,12 +92,6 @@ static uint32_t msix_mmio_readl(void *opaque, target_phys_addr_t addr)
     return pci_get_long(page + offset);
 }
 
-static uint32_t msix_mmio_read_unallowed(void *opaque, target_phys_addr_t addr)
-{
-    fprintf(stderr, "MSI-X: only dword read is allowed!\n");
-    return 0;
-}
-
 static uint8_t msix_pending_mask(int vector)
 {
     return 1 << (vector % 8);
@@ -169,8 +164,8 @@ void msix_write_config(PCIDevice *dev, uint32_t addr,
     }
 }
 
-static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
-                             uint32_t val)
+static void msix_mmio_write(void *opaque, target_phys_addr_t addr,
+                            uint64_t val, unsigned size)
 {
     PCIDevice *dev = opaque;
     unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3;
@@ -179,37 +174,25 @@ static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
     msix_handle_mask_update(dev, vector);
 }
 
-static void msix_mmio_write_unallowed(void *opaque, target_phys_addr_t addr,
-                                      uint32_t val)
-{
-    fprintf(stderr, "MSI-X: only dword write is allowed!\n");
-}
-
-static CPUWriteMemoryFunc * const msix_mmio_write[] = {
-    msix_mmio_write_unallowed, msix_mmio_write_unallowed, msix_mmio_writel
-};
-
-static CPUReadMemoryFunc * const msix_mmio_read[] = {
-    msix_mmio_read_unallowed, msix_mmio_read_unallowed, msix_mmio_readl
+static const MemoryRegionOps msix_mmio_ops = {
+    .read = msix_mmio_read,
+    .write = msix_mmio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
-/* Should be called from device's map method. */
-void msix_mmio_map(PCIDevice *d, int region_num,
-                   pcibus_t addr, pcibus_t size, int type)
+static void msix_mmio_setup(PCIDevice *d, MemoryRegion *bar)
 {
     uint8_t *config = d->config + d->msix_cap;
     uint32_t table = pci_get_long(config + PCI_MSIX_TABLE);
     uint32_t offset = table & ~(MSIX_PAGE_SIZE - 1);
     /* TODO: for assigned devices, we'll want to make it possible to map
      * pending bits separately in case they are in a separate bar. */
-    int table_bir = table & PCI_MSIX_FLAGS_BIRMASK;
 
-    if (table_bir != region_num)
-        return;
-    if (size <= offset)
-        return;
-    cpu_register_physical_memory(addr + offset, size - offset,
-                                 d->msix_mmio_index);
+    memory_region_add_subregion(bar, offset, &d->msix_mmio);
 }
 
 static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
@@ -225,6 +208,7 @@ static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
 /* Initialize the MSI-X structures. Note: if MSI-X is supported, BAR size is
  * modified, it should be retrieved with msix_bar_size. */
 int msix_init(struct PCIDevice *dev, unsigned short nentries,
+              MemoryRegion *bar,
               unsigned bar_nr, unsigned bar_size)
 {
     int ret;
@@ -241,13 +225,8 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
     dev->msix_table_page = qemu_mallocz(MSIX_PAGE_SIZE);
     msix_mask_all(dev, nentries);
 
-    dev->msix_mmio_index = cpu_register_io_memory(msix_mmio_read,
-                                                  msix_mmio_write, dev,
-                                                  DEVICE_NATIVE_ENDIAN);
-    if (dev->msix_mmio_index == -1) {
-        ret = -EBUSY;
-        goto err_index;
-    }
+    memory_region_init_io(&dev->msix_mmio, &msix_mmio_ops, dev,
+                          "msix", MSIX_PAGE_SIZE);
 
     dev->msix_entries_nr = nentries;
     ret = msix_add_config(dev, nentries, bar_nr, bar_size);
@@ -255,12 +234,12 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
         goto err_config;
 
     dev->cap_present |= QEMU_PCI_CAP_MSIX;
+    msix_mmio_setup(dev, bar);
     return 0;
 
 err_config:
     dev->msix_entries_nr = 0;
-    cpu_unregister_io_memory(dev->msix_mmio_index);
-err_index:
+    memory_region_destroy(&dev->msix_mmio);
     qemu_free(dev->msix_table_page);
     dev->msix_table_page = NULL;
     qemu_free(dev->msix_entry_used);
@@ -279,7 +258,7 @@ static void msix_free_irq_entries(PCIDevice *dev)
 }
 
 /* Clean up resources for the device. */
-int msix_uninit(PCIDevice *dev)
+int msix_uninit(PCIDevice *dev, MemoryRegion *bar)
 {
     if (!(dev->cap_present & QEMU_PCI_CAP_MSIX))
         return 0;
@@ -287,7 +266,8 @@ int msix_uninit(PCIDevice *dev)
     dev->msix_cap = 0;
     msix_free_irq_entries(dev);
     dev->msix_entries_nr = 0;
-    cpu_unregister_io_memory(dev->msix_mmio_index);
+    memory_region_del_subregion(bar, &dev->msix_mmio);
+    memory_region_destroy(&dev->msix_mmio);
     qemu_free(dev->msix_table_page);
     dev->msix_table_page = NULL;
     qemu_free(dev->msix_entry_used);
index a9f7993c396a5923b147526793e8ba7613c77747..7e04336618a44b1ec17cdda89d63bb783b60544b 100644 (file)
--- a/hw/msix.h
+++ b/hw/msix.h
@@ -5,15 +5,13 @@
 #include "pci.h"
 
 int msix_init(PCIDevice *pdev, unsigned short nentries,
+              MemoryRegion *bar,
               unsigned bar_nr, unsigned bar_size);
 
 void msix_write_config(PCIDevice *pci_dev, uint32_t address,
                        uint32_t val, int len);
 
-void msix_mmio_map(PCIDevice *pci_dev, int region_num,
-                   pcibus_t addr, pcibus_t size, int type);
-
-int msix_uninit(PCIDevice *d);
+int msix_uninit(PCIDevice *d, MemoryRegion *bar);
 
 void msix_save(PCIDevice *dev, QEMUFile *f);
 void msix_load(PCIDevice *dev, QEMUFile *f);
index 2426e8483394617bc3be184d78431e4b5f19b3ac..a1d3f4129320f0257ce8ac8114730cf11c945cdb 100644 (file)
@@ -198,11 +198,14 @@ int load_multiboot(void *fw_cfg,
     } else {
         /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_ADDR. */
         uint32_t mh_header_addr = ldl_p(header+i+12);
+        uint32_t mh_load_end_addr = ldl_p(header+i+20);
+        uint32_t mh_bss_end_addr = ldl_p(header+i+24);
         mh_load_addr = ldl_p(header+i+16);
         uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr);
+        uint32_t mb_load_size = mh_load_end_addr - mh_load_addr;
 
         mh_entry_addr = ldl_p(header+i+28);
-        mb_kernel_size = kernel_file_size - mb_kernel_text_offset;
+        mb_kernel_size = mh_bss_end_addr - mh_load_addr;
 
         /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE.
         uint32_t mh_mode_type = ldl_p(header+i+32);
@@ -212,17 +215,18 @@ int load_multiboot(void *fw_cfg,
 
         mb_debug("multiboot: mh_header_addr = %#x\n", mh_header_addr);
         mb_debug("multiboot: mh_load_addr = %#x\n", mh_load_addr);
-        mb_debug("multiboot: mh_load_end_addr = %#x\n", ldl_p(header+i+20));
-        mb_debug("multiboot: mh_bss_end_addr = %#x\n", ldl_p(header+i+24));
+        mb_debug("multiboot: mh_load_end_addr = %#x\n", mh_load_end_addr);
+        mb_debug("multiboot: mh_bss_end_addr = %#x\n", mh_bss_end_addr);
         mb_debug("qemu: loading multiboot kernel (%#x bytes) at %#x\n",
-                 mb_kernel_size, mh_load_addr);
+                 mb_load_size, mh_load_addr);
 
         mbs.mb_buf = qemu_malloc(mb_kernel_size);
         fseek(f, mb_kernel_text_offset, SEEK_SET);
-        if (fread(mbs.mb_buf, 1, mb_kernel_size, f) != mb_kernel_size) {
+        if (fread(mbs.mb_buf, 1, mb_load_size, f) != mb_load_size) {
             fprintf(stderr, "fread() failed\n");
             exit(1);
         }
+        memset(mbs.mb_buf + mb_load_size, 0, mb_kernel_size - mb_load_size);
         fclose(f);
     }
 
index 37e51d7140e1983f12529f7da225485464a00339..28d9f0b60d82b8381a362955c49a97433eb2062c 100644 (file)
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -6,6 +6,10 @@
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog@zabor.org>
  *
+ * Support for additional features based on "MT29F2G16ABCWP 2Gx16"
+ * datasheet from Micron Technology and "NAND02G-B2C" datasheet
+ * from ST Microelectronics.
+ *
  * This code is licensed under the GNU GPL v2.
  */
 
@@ -14,7 +18,7 @@
 # include "hw.h"
 # include "flash.h"
 # include "blockdev.h"
-/* FIXME: Pass block device as an argument.  */
+# include "sysbus.h"
 
 # define NAND_CMD_READ0                0x00
 # define NAND_CMD_READ1                0x01
 # define MAX_PAGE              0x800
 # define MAX_OOB               0x40
 
+typedef struct NANDFlashState NANDFlashState;
 struct NANDFlashState {
+    SysBusDevice busdev;
     uint8_t manf_id, chip_id;
+    uint8_t buswidth; /* in BYTES */
     int size, pages;
     int page_shift, oob_shift, erase_shift, addr_shift;
     uint8_t *storage;
@@ -58,18 +65,28 @@ struct NANDFlashState {
     uint8_t *ioaddr;
     int iolen;
 
-    uint32_t cmd, addr;
+    uint32_t cmd;
+    uint64_t addr;
     int addrlen;
     int status;
     int offset;
 
     void (*blk_write)(NANDFlashState *s);
     void (*blk_erase)(NANDFlashState *s);
-    void (*blk_load)(NANDFlashState *s, uint32_t addr, int offset);
+    void (*blk_load)(NANDFlashState *s, uint64_t addr, int offset);
 
     uint32_t ioaddr_vmstate;
 };
 
+static void mem_and(uint8_t *dest, const uint8_t *src, size_t n)
+{
+    /* Like memcpy() but we logical-AND the data into the destination */
+    int i;
+    for (i = 0; i < n; i++) {
+        dest[i] &= src[i];
+    }
+}
+
 # define NAND_NO_AUTOINCR      0x00000001
 # define NAND_BUSWIDTH_16      0x00000002
 # define NAND_NO_PADDING       0x00000004
@@ -201,8 +218,9 @@ static const struct {
     [0xc5] = { 2048,   16,     0, 0, LP_OPTIONS16 },
 };
 
-static void nand_reset(NANDFlashState *s)
+static void nand_reset(DeviceState *dev)
 {
+    NANDFlashState *s = FROM_SYSBUS(NANDFlashState, sysbus_from_qdev(dev));
     s->cmd = NAND_CMD_READ0;
     s->addr = 0;
     s->addrlen = 0;
@@ -211,6 +229,14 @@ static void nand_reset(NANDFlashState *s)
     s->status &= NAND_IOSTATUS_UNPROTCT;
 }
 
+static inline void nand_pushio_byte(NANDFlashState *s, uint8_t value)
+{
+    s->ioaddr[s->iolen++] = value;
+    for (value = s->buswidth; --value;) {
+        s->ioaddr[s->iolen++] = 0;
+    }
+}
+
 static void nand_command(NANDFlashState *s)
 {
     unsigned int offset;
@@ -220,15 +246,19 @@ static void nand_command(NANDFlashState *s)
         break;
 
     case NAND_CMD_READID:
-        s->io[0] = s->manf_id;
-        s->io[1] = s->chip_id;
-        s->io[2] = 'Q';                /* Don't-care byte (often 0xa5) */
-        if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
-            s->io[3] = 0x15;   /* Page Size, Block Size, Spare Size.. */
-        else
-            s->io[3] = 0xc0;   /* Multi-plane */
         s->ioaddr = s->io;
-        s->iolen = 4;
+        s->iolen = 0;
+        nand_pushio_byte(s, s->manf_id);
+        nand_pushio_byte(s, s->chip_id);
+        nand_pushio_byte(s, 'Q'); /* Don't-care byte (often 0xa5) */
+        if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
+            /* Page Size, Block Size, Spare Size; bit 6 indicates
+             * 8 vs 16 bit width NAND.
+             */
+            nand_pushio_byte(s, (s->buswidth == 2) ? 0x55 : 0x15);
+        } else {
+            nand_pushio_byte(s, 0xc0); /* Multi-plane */
+        }
         break;
 
     case NAND_CMD_RANDOMREAD2:
@@ -244,7 +274,7 @@ static void nand_command(NANDFlashState *s)
         break;
 
     case NAND_CMD_RESET:
-        nand_reset(s);
+        nand_reset(&s->busdev.qdev);
         break;
 
     case NAND_CMD_PAGEPROGRAM1:
@@ -273,9 +303,9 @@ static void nand_command(NANDFlashState *s)
         break;
 
     case NAND_CMD_READSTATUS:
-        s->io[0] = s->status;
         s->ioaddr = s->io;
-        s->iolen = 1;
+        s->iolen = 0;
+        nand_pushio_byte(s, s->status);
         break;
 
     default:
@@ -304,9 +334,9 @@ static int nand_post_load(void *opaque, int version_id)
 
 static const VMStateDescription vmstate_nand = {
     .name = "nand",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
     .pre_save = nand_pre_save,
     .post_load = nand_post_load,
     .fields      = (VMStateField[]) {
@@ -319,7 +349,7 @@ static const VMStateDescription vmstate_nand = {
         VMSTATE_UINT32(ioaddr_vmstate, NANDFlashState),
         VMSTATE_INT32(iolen, NANDFlashState),
         VMSTATE_UINT32(cmd, NANDFlashState),
-        VMSTATE_UINT32(addr, NANDFlashState),
+        VMSTATE_UINT64(addr, NANDFlashState),
         VMSTATE_INT32(addrlen, NANDFlashState),
         VMSTATE_INT32(status, NANDFlashState),
         VMSTATE_INT32(offset, NANDFlashState),
@@ -328,15 +358,85 @@ static const VMStateDescription vmstate_nand = {
     }
 };
 
+static int nand_device_init(SysBusDevice *dev)
+{
+    int pagesize;
+    NANDFlashState *s = FROM_SYSBUS(NANDFlashState, dev);
+
+    s->buswidth = nand_flash_ids[s->chip_id].width >> 3;
+    s->size = nand_flash_ids[s->chip_id].size << 20;
+    if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
+        s->page_shift = 11;
+        s->erase_shift = 6;
+    } else {
+        s->page_shift = nand_flash_ids[s->chip_id].page_shift;
+        s->erase_shift = nand_flash_ids[s->chip_id].erase_shift;
+    }
+
+    switch (1 << s->page_shift) {
+    case 256:
+        nand_init_256(s);
+        break;
+    case 512:
+        nand_init_512(s);
+        break;
+    case 2048:
+        nand_init_2048(s);
+        break;
+    default:
+        hw_error("%s: Unsupported NAND block size.\n", __func__);
+    }
+
+    pagesize = 1 << s->oob_shift;
+    s->mem_oob = 1;
+    if (s->bdrv && bdrv_getlength(s->bdrv) >=
+            (s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
+        pagesize = 0;
+        s->mem_oob = 0;
+    }
+
+    if (!s->bdrv) {
+        pagesize += 1 << s->page_shift;
+    }
+    if (pagesize) {
+        s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize),
+                        0xff, s->pages * pagesize);
+    }
+    /* Give s->ioaddr a sane value in case we save state before it is used. */
+    s->ioaddr = s->io;
+
+    return 0;
+}
+
+static SysBusDeviceInfo nand_info = {
+    .init = nand_device_init,
+    .qdev.name = "nand",
+    .qdev.size = sizeof(NANDFlashState),
+    .qdev.reset = nand_reset,
+    .qdev.vmsd = &vmstate_nand,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT8("manufacturer_id", NANDFlashState, manf_id, 0),
+        DEFINE_PROP_UINT8("chip_id", NANDFlashState, chip_id, 0),
+        DEFINE_PROP_DRIVE("drive", NANDFlashState, bdrv),
+        DEFINE_PROP_END_OF_LIST()
+    }
+};
+
+static void nand_create_device(void)
+{
+    sysbus_register_withprop(&nand_info);
+}
+
 /*
  * 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, uint8_t cle, uint8_t ale,
+void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,
                   uint8_t ce, uint8_t wp, uint8_t gnd)
 {
+    NANDFlashState *s = (NANDFlashState *) dev;
     s->cle = cle;
     s->ale = ale;
     s->ce = ce;
@@ -348,13 +448,15 @@ void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
         s->status &= ~NAND_IOSTATUS_UNPROTCT;
 }
 
-void nand_getpins(NANDFlashState *s, int *rb)
+void nand_getpins(DeviceState *dev, int *rb)
 {
     *rb = 1;
 }
 
-void nand_setio(NANDFlashState *s, uint8_t value)
+void nand_setio(DeviceState *dev, uint32_t value)
 {
+    int i;
+    NANDFlashState *s = (NANDFlashState *) dev;
     if (!s->ce && s->cle) {
         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
             if (s->cmd == NAND_CMD_READ0 && value == NAND_CMD_LPREAD2)
@@ -400,40 +502,69 @@ void nand_setio(NANDFlashState *s, uint8_t value)
         s->addr = (s->addr & mask) | v;
         s->addrlen ++;
 
-        if (s->addrlen == 1 && s->cmd == NAND_CMD_READID)
-            nand_command(s);
-
-        if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
-                s->addrlen == 3 && (
-                    s->cmd == NAND_CMD_READ0 ||
-                    s->cmd == NAND_CMD_PAGEPROGRAM1))
-            nand_command(s);
-        if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
-               s->addrlen == 4 && (
-                    s->cmd == NAND_CMD_READ0 ||
-                    s->cmd == NAND_CMD_PAGEPROGRAM1))
-            nand_command(s);
+        switch (s->addrlen) {
+        case 1:
+            if (s->cmd == NAND_CMD_READID) {
+                nand_command(s);
+            }
+            break;
+        case 2: /* fix cache address as a byte address */
+            s->addr <<= (s->buswidth - 1);
+            break;
+        case 3:
+            if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
+                    (s->cmd == NAND_CMD_READ0 ||
+                     s->cmd == NAND_CMD_PAGEPROGRAM1)) {
+                nand_command(s);
+            }
+            break;
+        case 4:
+            if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
+                    nand_flash_ids[s->chip_id].size < 256 && /* 1Gb or less */
+                    (s->cmd == NAND_CMD_READ0 ||
+                     s->cmd == NAND_CMD_PAGEPROGRAM1)) {
+                nand_command(s);
+            }
+            break;
+        case 5:
+            if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
+                    nand_flash_ids[s->chip_id].size >= 256 && /* 2Gb or more */
+                    (s->cmd == NAND_CMD_READ0 ||
+                     s->cmd == NAND_CMD_PAGEPROGRAM1)) {
+                nand_command(s);
+            }
+            break;
+        default:
+            break;
+        }
     }
 
     if (!s->cle && !s->ale && s->cmd == NAND_CMD_PAGEPROGRAM1) {
-        if (s->iolen < (1 << s->page_shift) + (1 << s->oob_shift))
-            s->io[s->iolen ++] = value;
+        if (s->iolen < (1 << s->page_shift) + (1 << s->oob_shift)) {
+            for (i = s->buswidth; i--; value >>= 8) {
+                s->io[s->iolen ++] = (uint8_t) (value & 0xff);
+            }
+        }
     } else if (!s->cle && !s->ale && s->cmd == NAND_CMD_COPYBACKPRG1) {
         if ((s->addr & ((1 << s->addr_shift) - 1)) <
                 (1 << s->page_shift) + (1 << s->oob_shift)) {
-            s->io[s->iolen + (s->addr & ((1 << s->addr_shift) - 1))] = value;
-            s->addr ++;
+            for (i = s->buswidth; i--; s->addr++, value >>= 8) {
+                s->io[s->iolen + (s->addr & ((1 << s->addr_shift) - 1))] =
+                    (uint8_t) (value & 0xff);
+            }
         }
     }
 }
 
-uint8_t nand_getio(NANDFlashState *s)
+uint32_t nand_getio(DeviceState *dev)
 {
     int offset;
+    uint32_t x = 0;
+    NANDFlashState *s = (NANDFlashState *) dev;
 
     /* Allow sequential reading */
     if (!s->iolen && s->cmd == NAND_CMD_READ0) {
-        offset = (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
+        offset = (int) (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
         s->offset = 0;
 
         s->blk_load(s, s->addr, offset);
@@ -446,129 +577,90 @@ uint8_t nand_getio(NANDFlashState *s)
     if (s->ce || s->iolen <= 0)
         return 0;
 
-    s->iolen --;
-    s->addr++;
-    return *(s->ioaddr ++);
+    for (offset = s->buswidth; offset--;) {
+        x |= s->ioaddr[offset] << (offset << 3);
+    }
+    /* after receiving READ STATUS command all subsequent reads will
+     * return the status register value until another command is issued
+     */
+    if (s->cmd != NAND_CMD_READSTATUS) {
+        s->addr   += s->buswidth;
+        s->ioaddr += s->buswidth;
+        s->iolen  -= s->buswidth;
+    }
+    return x;
+}
+
+uint32_t nand_getbuswidth(DeviceState *dev)
+{
+    NANDFlashState *s = (NANDFlashState *) dev;
+    return s->buswidth << 3;
 }
 
-NANDFlashState *nand_init(int manf_id, int chip_id)
+DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
 {
-    int pagesize;
-    NANDFlashState *s;
-    DriveInfo *dinfo;
+    DeviceState *dev;
 
     if (nand_flash_ids[chip_id].size == 0) {
         hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__);
     }
-
-    s = (NANDFlashState *) qemu_mallocz(sizeof(NANDFlashState));
-    dinfo = drive_get(IF_MTD, 0, 0);
-    if (dinfo)
-        s->bdrv = dinfo->bdrv;
-    s->manf_id = manf_id;
-    s->chip_id = chip_id;
-    s->size = nand_flash_ids[s->chip_id].size << 20;
-    if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
-        s->page_shift = 11;
-        s->erase_shift = 6;
-    } else {
-        s->page_shift = nand_flash_ids[s->chip_id].page_shift;
-        s->erase_shift = nand_flash_ids[s->chip_id].erase_shift;
+    dev = qdev_create(NULL, "nand");
+    qdev_prop_set_uint8(dev, "manufacturer_id", manf_id);
+    qdev_prop_set_uint8(dev, "chip_id", chip_id);
+    if (bdrv) {
+        qdev_prop_set_drive_nofail(dev, "drive", bdrv);
     }
 
-    switch (1 << s->page_shift) {
-    case 256:
-        nand_init_256(s);
-        break;
-    case 512:
-        nand_init_512(s);
-        break;
-    case 2048:
-        nand_init_2048(s);
-        break;
-    default:
-        hw_error("%s: Unsupported NAND block size.\n", __FUNCTION__);
-    }
-
-    pagesize = 1 << s->oob_shift;
-    s->mem_oob = 1;
-    if (s->bdrv && bdrv_getlength(s->bdrv) >=
-                    (s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
-        pagesize = 0;
-        s->mem_oob = 0;
-    }
-
-    if (!s->bdrv)
-        pagesize += 1 << s->page_shift;
-    if (pagesize)
-        s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize),
-                        0xff, s->pages * pagesize);
-    /* Give s->ioaddr a sane value in case we save state before it
-       is used.  */
-    s->ioaddr = s->io;
-
-    vmstate_register(NULL, -1, &vmstate_nand, s);
-
-    return s;
+    qdev_init_nofail(dev);
+    return dev;
 }
 
-void nand_done(NANDFlashState *s)
-{
-    if (s->bdrv) {
-        bdrv_close(s->bdrv);
-        bdrv_delete(s->bdrv);
-    }
-
-    if (!s->bdrv || s->mem_oob)
-        qemu_free(s->storage);
-
-    qemu_free(s);
-}
+device_init(nand_create_device)
 
 #else
 
 /* Program a single page */
 static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
 {
-    uint32_t off, page, sector, soff;
+    uint64_t off, page, sector, soff;
     uint8_t iobuf[(PAGE_SECTORS + 2) * 0x200];
     if (PAGE(s->addr) >= s->pages)
         return;
 
     if (!s->bdrv) {
-        memcpy(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) +
+        mem_and(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) +
                         s->offset, s->io, s->iolen);
     } else if (s->mem_oob) {
         sector = SECTOR(s->addr);
         off = (s->addr & PAGE_MASK) + s->offset;
         soff = SECTOR_OFFSET(s->addr);
         if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1) {
-            printf("%s: read error in sector %i\n", __FUNCTION__, sector);
+            printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
             return;
         }
 
-        memcpy(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off));
+        mem_and(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off));
         if (off + s->iolen > PAGE_SIZE) {
             page = PAGE(s->addr);
-            memcpy(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off,
+            mem_and(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off,
                             MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE));
         }
 
         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1)
-            printf("%s: write error in sector %i\n", __FUNCTION__, sector);
+            printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
     } else {
         off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset;
         sector = off >> 9;
         soff = off & 0x1ff;
         if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1) {
-            printf("%s: read error in sector %i\n", __FUNCTION__, sector);
+            printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
             return;
         }
 
-        memcpy(iobuf + soff, s->io, s->iolen);
+        mem_and(iobuf + soff, s->io, s->iolen);
 
         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1)
-            printf("%s: write error in sector %i\n", __FUNCTION__, sector);
+            printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
     }
     s->offset = 0;
 }
@@ -576,7 +668,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
 /* Erase a single block */
 static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
 {
-    uint32_t i, page, addr;
+    uint64_t i, page, addr;
     uint8_t iobuf[0x200] = { [0 ... 0x1ff] = 0xff, };
     addr = s->addr & ~((1 << (ADDR_SHIFT + s->erase_shift)) - 1);
 
@@ -593,34 +685,35 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
         page = SECTOR(addr + (ADDR_SHIFT + s->erase_shift));
         for (; i < page; i ++)
             if (bdrv_write(s->bdrv, i, iobuf, 1) == -1)
-                printf("%s: write error in sector %i\n", __FUNCTION__, i);
+                printf("%s: write error in sector %" PRIu64 "\n", __func__, i);
     } else {
         addr = PAGE_START(addr);
         page = addr >> 9;
         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
-            printf("%s: read error in sector %i\n", __FUNCTION__, page);
+            printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
         memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
-            printf("%s: write error in sector %i\n", __FUNCTION__, page);
+            printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
 
         memset(iobuf, 0xff, 0x200);
         i = (addr & ~0x1ff) + 0x200;
         for (addr += ((PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200;
                         i < addr; i += 0x200)
             if (bdrv_write(s->bdrv, i >> 9, iobuf, 1) == -1)
-                printf("%s: write error in sector %i\n", __FUNCTION__, i >> 9);
+                printf("%s: write error in sector %" PRIu64 "\n",
+                       __func__, i >> 9);
 
         page = i >> 9;
         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
-            printf("%s: read error in sector %i\n", __FUNCTION__, page);
+            printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
         memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
-            printf("%s: write error in sector %i\n", __FUNCTION__, page);
+            printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
     }
 }
 
 static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
-                uint32_t addr, int offset)
+                uint64_t addr, int offset)
 {
     if (PAGE(addr) >= s->pages)
         return;
@@ -628,8 +721,8 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
     if (s->bdrv) {
         if (s->mem_oob) {
             if (bdrv_read(s->bdrv, SECTOR(addr), s->io, PAGE_SECTORS) == -1)
-                printf("%s: read error in sector %i\n",
-                                __FUNCTION__, SECTOR(addr));
+                printf("%s: read error in sector %" PRIu64 "\n",
+                                __func__, SECTOR(addr));
             memcpy(s->io + SECTOR_OFFSET(s->addr) + PAGE_SIZE,
                             s->storage + (PAGE(s->addr) << OOB_SHIFT),
                             OOB_SIZE);
@@ -637,8 +730,8 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
         } else {
             if (bdrv_read(s->bdrv, PAGE_START(addr) >> 9,
                                     s->io, (PAGE_SECTORS + 2)) == -1)
-                printf("%s: read error in sector %i\n",
-                                __FUNCTION__, PAGE_START(addr) >> 9);
+                printf("%s: read error in sector %" PRIu64 "\n",
+                                __func__, PAGE_START(addr) >> 9);
             s->ioaddr = s->io + (PAGE_START(addr) & 0x1ff) + offset;
         }
     } else {
index e41dbbaa79be900dcd2c9375e05b56fc44066485..756ed5ca46d58e74d3fa1a677554e27fb48b550d 100644 (file)
@@ -27,6 +27,7 @@
 #include "qdev.h"
 #include "net.h"
 #include "ne2000.h"
+#include "exec-memory.h"
 
 typedef struct ISANE2000State {
     ISADevice dev;
@@ -66,19 +67,11 @@ static int isa_ne2000_initfn(ISADevice *dev)
     ISANE2000State *isa = DO_UPCAST(ISANE2000State, dev, dev);
     NE2000State *s = &isa->ne2000;
 
-    register_ioport_write(isa->iobase, 16, 1, ne2000_ioport_write, s);
-    register_ioport_read(isa->iobase, 16, 1, ne2000_ioport_read, s);
+    ne2000_setup_io(s, 0x20);
     isa_init_ioport_range(dev, isa->iobase, 16);
-
-    register_ioport_write(isa->iobase + 0x10, 1, 1, ne2000_asic_ioport_write, s);
-    register_ioport_read(isa->iobase + 0x10, 1, 1, ne2000_asic_ioport_read, s);
-    register_ioport_write(isa->iobase + 0x10, 2, 2, ne2000_asic_ioport_write, s);
-    register_ioport_read(isa->iobase + 0x10, 2, 2, ne2000_asic_ioport_read, s);
     isa_init_ioport_range(dev, isa->iobase + 0x10, 2);
-
-    register_ioport_write(isa->iobase + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
-    register_ioport_read(isa->iobase + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
     isa_init_ioport(dev, isa->iobase + 0x1f);
+    memory_region_add_subregion(get_system_io(), isa->iobase, &s->io);
 
     isa_init_irq(dev, &s->irq, isa->isairq);
 
index f8acaaeeb641d7882bca6bb0fe2eb6fb33f0f2be..a035a852441a65ad664b8034fcc13bc12dda5090 100644 (file)
@@ -297,7 +297,7 @@ ssize_t ne2000_receive(VLANClientState *nc, const uint8_t *buf, size_t size_)
     return size_;
 }
 
-void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
     NE2000State *s = opaque;
     int offset, page, index;
@@ -394,7 +394,7 @@ void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     }
 }
 
-uint32_t ne2000_ioport_read(void *opaque, uint32_t addr)
+static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr)
 {
     NE2000State *s = opaque;
     int offset, page, ret;
@@ -544,7 +544,7 @@ static inline void ne2000_dma_update(NE2000State *s, int len)
     }
 }
 
-void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
     NE2000State *s = opaque;
 
@@ -564,7 +564,7 @@ void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     }
 }
 
-uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr)
+static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr)
 {
     NE2000State *s = opaque;
     int ret;
@@ -612,12 +612,12 @@ static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr)
     return ret;
 }
 
-void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+static void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
     /* nothing to do (end of reset pulse) */
 }
 
-uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr)
+static uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr)
 {
     NE2000State *s = opaque;
     ne2000_reset(s);
@@ -676,27 +676,55 @@ static const VMStateDescription vmstate_pci_ne2000 = {
     }
 };
 
-/***********************************************************/
-/* PCI NE2000 definitions */
+static uint64_t ne2000_read(void *opaque, target_phys_addr_t addr,
+                            unsigned size)
+{
+    NE2000State *s = opaque;
 
-static void ne2000_map(PCIDevice *pci_dev, int region_num,
-                       pcibus_t addr, pcibus_t size, int type)
+    if (addr < 0x10 && size == 1) {
+        return ne2000_ioport_read(s, addr);
+    } else if (addr == 0x10) {
+        if (size <= 2) {
+            return ne2000_asic_ioport_read(s, addr);
+        } else {
+            return ne2000_asic_ioport_readl(s, addr);
+        }
+    } else if (addr == 0x1f && size == 1) {
+        return ne2000_reset_ioport_read(s, addr);
+    }
+    return ((uint64_t)1 << (size * 8)) - 1;
+}
+
+static void ne2000_write(void *opaque, target_phys_addr_t addr,
+                         uint64_t data, unsigned size)
 {
-    PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev);
-    NE2000State *s = &d->ne2000;
+    NE2000State *s = opaque;
+
+    if (addr < 0x10 && size == 1) {
+        return ne2000_ioport_write(s, addr, data);
+    } else if (addr == 0x10) {
+        if (size <= 2) {
+            return ne2000_asic_ioport_write(s, addr, data);
+        } else {
+            return ne2000_asic_ioport_writel(s, addr, data);
+        }
+    } else if (addr == 0x1f && size == 1) {
+        return ne2000_reset_ioport_write(s, addr, data);
+    }
+}
 
-    register_ioport_write(addr, 16, 1, ne2000_ioport_write, s);
-    register_ioport_read(addr, 16, 1, ne2000_ioport_read, s);
+static const MemoryRegionOps ne2000_ops = {
+    .read = ne2000_read,
+    .write = ne2000_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
 
-    register_ioport_write(addr + 0x10, 1, 1, ne2000_asic_ioport_write, s);
-    register_ioport_read(addr + 0x10, 1, 1, ne2000_asic_ioport_read, s);
-    register_ioport_write(addr + 0x10, 2, 2, ne2000_asic_ioport_write, s);
-    register_ioport_read(addr + 0x10, 2, 2, ne2000_asic_ioport_read, s);
-    register_ioport_write(addr + 0x10, 4, 4, ne2000_asic_ioport_writel, s);
-    register_ioport_read(addr + 0x10, 4, 4, ne2000_asic_ioport_readl, s);
+/***********************************************************/
+/* PCI NE2000 definitions */
 
-    register_ioport_write(addr + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
-    register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
+void ne2000_setup_io(NE2000State *s, unsigned size)
+{
+    memory_region_init_io(&s->io, &ne2000_ops, s, "ne2000", size);
 }
 
 static void ne2000_cleanup(VLANClientState *nc)
@@ -724,9 +752,9 @@ static int pci_ne2000_init(PCIDevice *pci_dev)
     /* TODO: RST# value should be 0. PCI spec 6.2.4 */
     pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0
 
-    pci_register_bar(&d->dev, 0, 0x100,
-                           PCI_BASE_ADDRESS_SPACE_IO, ne2000_map);
     s = &d->ne2000;
+    ne2000_setup_io(s, 0x100);
+    pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
     s->irq = d->dev.irq[0];
 
     qemu_macaddr_default_if_unset(&s->c.macaddr);
@@ -754,6 +782,7 @@ static int pci_ne2000_exit(PCIDevice *pci_dev)
     PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev);
     NE2000State *s = &d->ne2000;
 
+    memory_region_destroy(&s->io);
     qemu_del_vlan_client(&s->nic->nc);
     return 0;
 }
index 54fdfca1339371eb59cc5dc227a8b90ee13cf4f5..5fee052194c21894983d7ca239b6a43a64cf2fbc 100644 (file)
@@ -4,6 +4,7 @@
 #define NE2000_MEM_SIZE     NE2000_PMEM_END
 
 typedef struct NE2000State {
+    MemoryRegion io;
     uint8_t cmd;
     uint32_t start;
     uint32_t stop;
@@ -27,12 +28,7 @@ typedef struct NE2000State {
     uint8_t mem[NE2000_MEM_SIZE];
 } NE2000State;
 
-void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val);
-uint32_t ne2000_ioport_read(void *opaque, uint32_t addr);
-void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val);
-uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr);
-void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val);
-uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr);
+void ne2000_setup_io(NE2000State *s, unsigned size);
 extern const VMStateDescription vmstate_ne2000;
 void ne2000_reset(NE2000State *s);
 int ne2000_can_receive(VLANClientState *vc);
index 2f84f5305b71b5cec12301482d99b85de8ee480c..6a5575e78e7cdf556f756ab5335cf20a815def7a 100644 (file)
@@ -31,6 +31,7 @@
 #include "hw.h"
 #include "bt.h"
 #include "loader.h"
+#include "blockdev.h"
 
 /* Nokia N8x0 support */
 struct n800_s {
@@ -45,7 +46,7 @@ struct n800_s {
     i2c_bus *i2c;
 
     int keymap[0x80];
-    i2c_slave *kbd;
+    DeviceState *kbd;
 
     TUSBState *usb;
     void *retu;
@@ -134,9 +135,9 @@ static void n800_mmc_cs_cb(void *opaque, int line, int level)
 static void n8x0_gpio_setup(struct n800_s *s)
 {
     qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->cpu->mmc, 1);
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_MMC_CS_GPIO, mmc_cs[0]);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]);
 
-    qemu_irq_lower(omap2_gpio_in_get(s->cpu->gpif, N800_BAT_COVER_GPIO)[0]);
+    qemu_irq_lower(qdev_get_gpio_in(s->cpu->gpio, N800_BAT_COVER_GPIO));
 }
 
 #define MAEMO_CAL_HEADER(...)                          \
@@ -163,13 +164,15 @@ static const uint8_t n8x0_cal_bt_id[] = {
 static void n8x0_nand_setup(struct n800_s *s)
 {
     char *otp_region;
+    DriveInfo *dinfo;
 
-    /* Either ec40xx or ec48xx are OK for the ID */
+    dinfo = drive_get(IF_MTD, 0, 0);
+    /* Either 0x40 or 0x48 are OK for the device ID */
+    s->nand = onenand_init(dinfo ? dinfo->bdrv : 0,
+                    NAND_MFR_SAMSUNG, 0x48, 0, 1,
+                    qdev_get_gpio_in(s->cpu->gpio, N8X0_ONENAND_GPIO));
     omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update,
-                    onenand_base_unmap,
-                    (s->nand = onenand_init(0xec4800, 1,
-                                            omap2_gpio_in_get(s->cpu->gpif,
-                                                    N8X0_ONENAND_GPIO)[0])));
+                    onenand_base_unmap, s->nand);
     otp_region = onenand_raw_otp(s->nand);
 
     memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
@@ -180,7 +183,7 @@ static void n8x0_nand_setup(struct n800_s *s)
 static void n8x0_i2c_setup(struct n800_s *s)
 {
     DeviceState *dev;
-    qemu_irq tmp_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TMP105_GPIO)[0];
+    qemu_irq tmp_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TMP105_GPIO);
 
     /* Attach the CPU on one end of our I2C bus.  */
     s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
@@ -249,8 +252,8 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
     /* XXX: are the three pins inverted inside the chip between the
      * tsc and the cpu (N4111)?  */
     qemu_irq penirq = NULL;    /* NC */
-    qemu_irq kbirq = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_KP_IRQ_GPIO)[0];
-    qemu_irq dav = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_TS_GPIO)[0];
+    qemu_irq kbirq = qdev_get_gpio_in(s->cpu->gpio, N800_TSC_KP_IRQ_GPIO);
+    qemu_irq dav = qdev_get_gpio_in(s->cpu->gpio, N800_TSC_TS_GPIO);
 
     s->ts.chip = tsc2301_init(penirq, kbirq, dav);
     s->ts.opaque = s->ts.chip->opaque;
@@ -269,7 +272,7 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
 
 static void n810_tsc_setup(struct n800_s *s)
 {
-    qemu_irq pintdav = omap2_gpio_in_get(s->cpu->gpif, N810_TSC_TS_GPIO)[0];
+    qemu_irq pintdav = qdev_get_gpio_in(s->cpu->gpio, N810_TSC_TS_GPIO);
 
     s->ts.opaque = tsc2005_init(pintdav);
     s->ts.txrx = tsc2005_txrx;
@@ -361,8 +364,7 @@ static int n810_keys[0x80] = {
 
 static void n810_kbd_setup(struct n800_s *s)
 {
-    qemu_irq kbd_irq = omap2_gpio_in_get(s->cpu->gpif, N810_KEYBOARD_GPIO)[0];
-    DeviceState *dev;
+    qemu_irq kbd_irq = qdev_get_gpio_in(s->cpu->gpio, N810_KEYBOARD_GPIO);
     int i;
 
     for (i = 0; i < 0x80; i ++)
@@ -375,8 +377,8 @@ static void n810_kbd_setup(struct n800_s *s)
 
     /* Attach the LM8322 keyboard to the I2C bus,
      * should happen in n8x0_i2c_setup and s->kbd be initialised here.  */
-    dev = i2c_create_slave(s->i2c, "lm8323", N810_LM8323_ADDR);
-    qdev_connect_gpio_out(dev, 0, kbd_irq);
+    s->kbd = i2c_create_slave(s->i2c, "lm8323", N810_LM8323_ADDR);
+    qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
 }
 
 /* LCD MIPI DBI-C controller (URAL) */
@@ -726,15 +728,15 @@ static void n8x0_dss_setup(struct n800_s *s)
 
 static void n8x0_cbus_setup(struct n800_s *s)
 {
-    qemu_irq dat_out = omap2_gpio_in_get(s->cpu->gpif, N8X0_CBUS_DAT_GPIO)[0];
-    qemu_irq retu_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_RETU_GPIO)[0];
-    qemu_irq tahvo_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TAHVO_GPIO)[0];
+    qemu_irq dat_out = qdev_get_gpio_in(s->cpu->gpio, N8X0_CBUS_DAT_GPIO);
+    qemu_irq retu_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_RETU_GPIO);
+    qemu_irq tahvo_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TAHVO_GPIO);
 
     CBus *cbus = cbus_init(dat_out);
 
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_CLK_GPIO, cbus->clk);
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_DAT_GPIO, cbus->dat);
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_SEL_GPIO, cbus->sel);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
 
     cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
     cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
@@ -743,12 +745,11 @@ static void n8x0_cbus_setup(struct n800_s *s)
 static void n8x0_uart_setup(struct n800_s *s)
 {
     CharDriverState *radio = uart_hci_init(
-                    omap2_gpio_in_get(s->cpu->gpif,
-                            N8X0_BT_HOST_WKUP_GPIO)[0]);
+                    qdev_get_gpio_in(s->cpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
 
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_BT_RESET_GPIO,
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_BT_RESET_GPIO,
                     csrhci_pins_get(radio)[csrhci_pin_reset]);
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_BT_WKUP_GPIO,
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_BT_WKUP_GPIO,
                     csrhci_pins_get(radio)[csrhci_pin_wakeup]);
 
     omap_uart_attach(s->cpu->uart[BT_UART], radio);
@@ -763,7 +764,7 @@ static void n8x0_usb_power_cb(void *opaque, int line, int level)
 
 static void n8x0_usb_setup(struct n800_s *s)
 {
-    qemu_irq tusb_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TUSB_INT_GPIO)[0];
+    qemu_irq tusb_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TUSB_INT_GPIO);
     qemu_irq tusb_pwr = qemu_allocate_irqs(n8x0_usb_power_cb, s, 1)[0];
     TUSBState *tusb = tusb6010_init(tusb_irq);
 
@@ -774,7 +775,7 @@ static void n8x0_usb_setup(struct n800_s *s)
                     tusb6010_sync_io(tusb), NULL, NULL, tusb);
 
     s->usb = tusb;
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_TUSB_ENABLE_GPIO, tusb_pwr);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_TUSB_ENABLE_GPIO, tusb_pwr);
 }
 
 /* Setup done before the main bootloader starts by some early setup code
@@ -1020,7 +1021,7 @@ static void n8x0_boot_init(void *opaque)
 
     /* If the machine has a slided keyboard, open it */
     if (s->kbd)
-        qemu_irq_raise(omap2_gpio_in_get(s->cpu->gpif, N810_SLIDE_GPIO)[0]);
+        qemu_irq_raise(qdev_get_gpio_in(s->cpu->gpio, N810_SLIDE_GPIO));
 }
 
 #define OMAP_TAG_NOKIA_BT      0x4e01
index c227a82b2c12dac21854f01c1cdf78997ef0d1e9..a064353aba06ff3745c881a003c7b96921d54375 100644 (file)
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -93,6 +93,8 @@ struct omap_target_agent_s *omap_l4ta_get(
     int cs);
 target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
                 int iotype);
+target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta,
+                                       int region);
 int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
                 CPUWriteMemoryFunc * const *mem_write, void *opaque);
 
@@ -681,22 +683,6 @@ qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
 void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
 void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
 
-/* omap1 gpio module interface */
-struct omap_gpio_s;
-struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
-                qemu_irq irq, omap_clk clk);
-void omap_gpio_reset(struct omap_gpio_s *s);
-qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
-void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
-
-/* omap2 gpio interface */
-struct omap_gpif_s;
-struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
-                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules);
-void omap_gpif_reset(struct omap_gpif_s *s);
-qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start);
-void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler);
-
 struct uWireSlave {
     uint16_t (*receive)(void *opaque);
     void (*send)(void *opaque, uint16_t data);
@@ -850,7 +836,7 @@ struct omap_mpu_state_s {
     /* MPUI-TIPB peripherals */
     struct omap_uart_s *uart[3];
 
-    struct omap_gpio_s *gpio;
+    DeviceState *gpio;
 
     struct omap_mcbsp_s *mcbsp1;
     struct omap_mcbsp_s *mcbsp3;
@@ -948,8 +934,6 @@ struct omap_mpu_state_s {
     struct omap_gpmc_s *gpmc;
     struct omap_sysctl_s *sysc;
 
-    struct omap_gpif_s *gpif;
-
     struct omap_mcspi_s *mcspi[2];
 
     struct omap_dss_s *dss;
index 364c26f877b34fa9e5ede6cf286daae2e68e0747..400de475d9d4697d9a82aa66b6c35c285c0b724d 100644 (file)
@@ -27,6 +27,7 @@
 #include "pc.h"
 #include "blockdev.h"
 #include "range.h"
+#include "sysbus.h"
 
 /* Should signal the TCMI/GPMC */
 uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr)
@@ -3585,7 +3586,6 @@ static void omap1_mpu_reset(void *opaque)
     omap_uart_reset(mpu->uart[2]);
     omap_mmc_reset(mpu->mmc);
     omap_mpuio_reset(mpu->mpuio);
-    omap_gpio_reset(mpu->gpio);
     omap_uwire_reset(mpu->microwire);
     omap_pwl_reset(mpu);
     omap_pwt_reset(mpu);
@@ -3845,8 +3845,12 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
                     s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
                     s->wakeup, omap_findclk(s, "clk32-kHz"));
 
-    s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1],
-                    omap_findclk(s, "arm_gpio_ck"));
+    s->gpio = qdev_create(NULL, "omap-gpio");
+    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
+    qdev_init_nofail(s->gpio);
+    sysbus_connect_irq(sysbus_from_qdev(s->gpio), 0,
+                    s->irq[0][OMAP_INT_GPIO_BANK1]);
+    sysbus_mmio_map(sysbus_from_qdev(s->gpio), 0, 0xfffce000);
 
     s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
                     s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
index 0f13272c7b43536ba693402cab8734c83024b6f1..c9b35405ed386de1934c6e590d2a3a5cf08e391b 100644 (file)
@@ -27,6 +27,7 @@
 #include "qemu-char.h"
 #include "flash.h"
 #include "soc_dma.h"
+#include "sysbus.h"
 #include "audio/audio.h"
 
 /* Enhanced Audio Controller (CODEC only) */
@@ -2203,7 +2204,6 @@ static void omap2_mpu_reset(void *opaque)
     omap_uart_reset(mpu->uart[1]);
     omap_uart_reset(mpu->uart[2]);
     omap_mmc_reset(mpu->mmc);
-    omap_gpif_reset(mpu->gpif);
     omap_mcspi_reset(mpu->mcspi[0]);
     omap_mcspi_reset(mpu->mcspi[1]);
     omap_i2c_reset(mpu->i2c[0]);
@@ -2232,9 +2232,10 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
     ram_addr_t sram_base, q2_base;
     qemu_irq *cpu_irq;
     qemu_irq dma_irqs[4];
-    omap_clk gpio_clks[4];
     DriveInfo *dinfo;
     int i;
+    SysBusDevice *busdev;
+    struct omap_target_agent_s *ta;
 
     /* Core */
     s->mpu_model = omap2420;
@@ -2377,13 +2378,28 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
                     omap_findclk(s, "i2c2.fclk"),
                     omap_findclk(s, "i2c2.iclk"));
 
-    gpio_clks[0] = omap_findclk(s, "gpio1_dbclk");
-    gpio_clks[1] = omap_findclk(s, "gpio2_dbclk");
-    gpio_clks[2] = omap_findclk(s, "gpio3_dbclk");
-    gpio_clks[3] = omap_findclk(s, "gpio4_dbclk");
-    s->gpif = omap2_gpio_init(omap_l4ta(s->l4, 3),
-                    &s->irq[0][OMAP_INT_24XX_GPIO_BANK1],
-                    gpio_clks, omap_findclk(s, "gpio_iclk"), 4);
+    s->gpio = qdev_create(NULL, "omap2-gpio");
+    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
+    qdev_prop_set_ptr(s->gpio, "iclk", omap_findclk(s, "gpio_iclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk0", omap_findclk(s, "gpio1_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk1", omap_findclk(s, "gpio2_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk2", omap_findclk(s, "gpio3_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk3", omap_findclk(s, "gpio4_dbclk"));
+    if (s->mpu_model == omap2430) {
+        qdev_prop_set_ptr(s->gpio, "fclk4", omap_findclk(s, "gpio5_dbclk"));
+    }
+    qdev_init_nofail(s->gpio);
+    busdev = sysbus_from_qdev(s->gpio);
+    sysbus_connect_irq(busdev, 0, s->irq[0][OMAP_INT_24XX_GPIO_BANK1]);
+    sysbus_connect_irq(busdev, 3, s->irq[0][OMAP_INT_24XX_GPIO_BANK2]);
+    sysbus_connect_irq(busdev, 6, s->irq[0][OMAP_INT_24XX_GPIO_BANK3]);
+    sysbus_connect_irq(busdev, 9, s->irq[0][OMAP_INT_24XX_GPIO_BANK4]);
+    ta = omap_l4ta(s->l4, 3);
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(ta, 1));
+    sysbus_mmio_map(busdev, 1, omap_l4_region_base(ta, 0));
+    sysbus_mmio_map(busdev, 2, omap_l4_region_base(ta, 2));
+    sysbus_mmio_map(busdev, 3, omap_l4_region_base(ta, 4));
+    sysbus_mmio_map(busdev, 4, omap_l4_region_base(ta, 5));
 
     s->sdrc = omap_sdrc_init(0x68009000);
     s->gpmc = omap_gpmc_init(0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ]);
index 6bcabef8acb7112f6f44443820337a235e766ce4..577b326ae9c9298d489c4349ae708aea3ea82613 100644 (file)
@@ -836,7 +836,7 @@ static struct clk i2c2_iclk = {
     .parent    = &core_l4_iclk,
 };
 
-static struct clk gpio_dbclk[4] = {
+static struct clk gpio_dbclk[5] = {
     {
         .name  = "gpio1_dbclk",
         .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
@@ -853,6 +853,10 @@ static struct clk gpio_dbclk[4] = {
         .name  = "gpio4_dbclk",
         .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
         .parent        = &wu_32k_clk,
+    }, {
+        .name   = "gpio5_dbclk",
+        .flags  = CLOCK_IN_OMAP243X,
+        .parent = &wu_32k_clk,
     },
 };
 
index 478f7d9825318db66336f25e662e281cd499fe0d..c23964c66d0c650f39f37886e16ead59cc7eb33e 100644 (file)
 
 #include "hw.h"
 #include "omap.h"
-/* General-Purpose I/O */
+#include "sysbus.h"
+
 struct omap_gpio_s {
     qemu_irq irq;
-    qemu_irq *in;
     qemu_irq handler[16];
 
     uint16_t inputs;
@@ -35,9 +35,17 @@ struct omap_gpio_s {
     uint16_t pins;
 };
 
+struct omap_gpif_s {
+    SysBusDevice busdev;
+    int mpu_model;
+    void *clk;
+    struct omap_gpio_s omap1;
+};
+
+/* General-Purpose I/O of OMAP1 */
 static void omap_gpio_set(void *opaque, int line, int level)
 {
-    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
+    struct omap_gpio_s *s = &((struct omap_gpif_s *) opaque)->omap1;
     uint16_t prev = s->inputs;
 
     if (level)
@@ -160,7 +168,7 @@ static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
     omap_badwidth_write16,
 };
 
-void omap_gpio_reset(struct omap_gpio_s *s)
+static void omap_gpio_reset(struct omap_gpio_s *s)
 {
     s->inputs = 0;
     s->outputs = ~0;
@@ -171,43 +179,12 @@ void omap_gpio_reset(struct omap_gpio_s *s)
     s->pins = ~0;
 }
 
-struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
-                qemu_irq irq, omap_clk clk)
-{
-    int iomemtype;
-    struct omap_gpio_s *s = (struct omap_gpio_s *)
-            qemu_mallocz(sizeof(struct omap_gpio_s));
-
-    s->irq = irq;
-    s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
-    omap_gpio_reset(s);
-
-    iomemtype = cpu_register_io_memory(omap_gpio_readfn,
-                    omap_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x1000, iomemtype);
-
-    return s;
-}
-
-qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
-{
-    return s->in;
-}
-
-void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
-{
-    if (line >= 16 || line < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
-    s->handler[line] = handler;
-}
-
-/* General-Purpose Interface of OMAP2 */
 struct omap2_gpio_s {
     qemu_irq irq[2];
     qemu_irq wkup;
-    qemu_irq *in;
-    qemu_irq handler[32];
+    qemu_irq *handler;
 
+    uint8_t revision;
     uint8_t config[2];
     uint32_t inputs;
     uint32_t outputs;
@@ -221,8 +198,21 @@ struct omap2_gpio_s {
     uint8_t delay;
 };
 
+struct omap2_gpif_s {
+    SysBusDevice busdev;
+    int mpu_model;
+    void *iclk;
+    void *fclk[6];
+    int modulecount;
+    struct omap2_gpio_s *modules;
+    qemu_irq *handler;
+    int autoidle;
+    int gpo;
+};
+
+/* General-Purpose Interface of OMAP2/3 */
 static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
-                int line)
+                                                int line)
 {
     qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
 }
@@ -269,10 +259,12 @@ static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
     omap2_gpio_module_wake(s, line);
 }
 
-static void omap2_gpio_module_set(void *opaque, int line, int level)
+static void omap2_gpio_set(void *opaque, int line, int level)
 {
-    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
+    struct omap2_gpif_s *p = opaque;
+    struct omap2_gpio_s *s = &p->modules[line >> 5];
 
+    line &= 31;
     if (level) {
         if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
             omap2_gpio_module_int(s, line);
@@ -308,7 +300,7 @@ static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr)
 
     switch (addr) {
     case 0x00: /* GPIO_REVISION */
-        return 0x18;
+        return s->revision;
 
     case 0x10: /* GPIO_SYSCONFIG */
         return s->config[0];
@@ -583,45 +575,28 @@ static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
     omap2_gpio_module_write,
 };
 
-static void omap2_gpio_module_init(struct omap2_gpio_s *s,
-                struct omap_target_agent_s *ta, int region,
-                qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
-                omap_clk fclk, omap_clk iclk)
+static void omap_gpif_reset(DeviceState *dev)
 {
-    int iomemtype;
-
-    s->irq[0] = mpu;
-    s->irq[1] = dsp;
-    s->wkup = wkup;
-    s->in = qemu_allocate_irqs(omap2_gpio_module_set, s, 32);
-
-    iomemtype = l4_register_io_memory(omap2_gpio_module_readfn,
-                    omap2_gpio_module_writefn, s);
-    omap_l4_attach(ta, region, iomemtype);
+    struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s,
+                    sysbus_from_qdev(dev));
+    omap_gpio_reset(&s->omap1);
 }
 
-struct omap_gpif_s {
-    struct omap2_gpio_s module[5];
-    int modules;
-
-    int autoidle;
-    int gpo;
-};
-
-void omap_gpif_reset(struct omap_gpif_s *s)
+static void omap2_gpif_reset(DeviceState *dev)
 {
     int i;
-
-    for (i = 0; i < s->modules; i ++)
-        omap2_gpio_module_reset(s->module + i);
-
+    struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s,
+                    sysbus_from_qdev(dev));
+    for (i = 0; i < s->modulecount; i++) {
+        omap2_gpio_module_reset(&s->modules[i]);
+    }
     s->autoidle = 0;
     s->gpo = 0;
 }
 
-static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
+static uint32_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr)
 {
-    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
+    struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
 
     switch (addr) {
     case 0x00: /* IPGENERICOCPSPL_REVISION */
@@ -647,10 +622,10 @@ static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
+static void omap2_gpif_top_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
-    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
+    struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
 
     switch (addr) {
     case 0x00: /* IPGENERICOCPSPL_REVISION */
@@ -662,7 +637,7 @@ static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
 
     case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
         if (value & (1 << 1))                                  /* SOFTRESET */
-            omap_gpif_reset(s);
+            omap2_gpif_reset(&s->busdev.qdev);
         s->autoidle = value & 1;
         break;
 
@@ -676,50 +651,119 @@ static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_gpif_top_readfn[] = {
-    omap_gpif_top_read,
-    omap_gpif_top_read,
-    omap_gpif_top_read,
+static CPUReadMemoryFunc * const omap2_gpif_top_readfn[] = {
+    omap2_gpif_top_read,
+    omap2_gpif_top_read,
+    omap2_gpif_top_read,
 };
 
-static CPUWriteMemoryFunc * const omap_gpif_top_writefn[] = {
-    omap_gpif_top_write,
-    omap_gpif_top_write,
-    omap_gpif_top_write,
+static CPUWriteMemoryFunc * const omap2_gpif_top_writefn[] = {
+    omap2_gpif_top_write,
+    omap2_gpif_top_write,
+    omap2_gpif_top_write,
 };
 
-struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
-                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
+static int omap_gpio_init(SysBusDevice *dev)
 {
-    int iomemtype, i;
-    struct omap_gpif_s *s = (struct omap_gpif_s *)
-            qemu_mallocz(sizeof(struct omap_gpif_s));
-    int region[4] = { 0, 2, 4, 5 };
+    struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s, dev);
+    if (!s->clk) {
+        hw_error("omap-gpio: clk not connected\n");
+    }
+    qdev_init_gpio_in(&dev->qdev, omap_gpio_set, 16);
+    qdev_init_gpio_out(&dev->qdev, s->omap1.handler, 16);
+    sysbus_init_irq(dev, &s->omap1.irq);
+    sysbus_init_mmio(dev, 0x1000,
+                    cpu_register_io_memory(omap_gpio_readfn,
+                                    omap_gpio_writefn,
+                                    &s->omap1,
+                                    DEVICE_NATIVE_ENDIAN));
+    return 0;
+}
 
-    s->modules = modules;
-    for (i = 0; i < modules; i ++)
-        omap2_gpio_module_init(s->module + i, ta, region[i],
-                              irq[i], NULL, NULL, fclk[i], iclk);
+static int omap2_gpio_init(SysBusDevice *dev)
+{
+    int i;
+    struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s, dev);
+    if (!s->iclk) {
+        hw_error("omap2-gpio: iclk not connected\n");
+    }
+    if (s->mpu_model < omap3430) {
+        s->modulecount = (s->mpu_model < omap2430) ? 4 : 5;
+        sysbus_init_mmio(dev, 0x1000,
+                        cpu_register_io_memory(omap2_gpif_top_readfn,
+                                        omap2_gpif_top_writefn, s,
+                                        DEVICE_NATIVE_ENDIAN));
+    } else {
+        s->modulecount = 6;
+    }
+    s->modules = qemu_mallocz(s->modulecount * sizeof(struct omap2_gpio_s));
+    s->handler = qemu_mallocz(s->modulecount * 32 * sizeof(qemu_irq));
+    qdev_init_gpio_in(&dev->qdev, omap2_gpio_set, s->modulecount * 32);
+    qdev_init_gpio_out(&dev->qdev, s->handler, s->modulecount * 32);
+    for (i = 0; i < s->modulecount; i++) {
+        struct omap2_gpio_s *m = &s->modules[i];
+        if (!s->fclk[i]) {
+            hw_error("omap2-gpio: fclk%d not connected\n", i);
+        }
+        m->revision = (s->mpu_model < omap3430) ? 0x18 : 0x25;
+        m->handler = &s->handler[i * 32];
+        sysbus_init_irq(dev, &m->irq[0]); /* mpu irq */
+        sysbus_init_irq(dev, &m->irq[1]); /* dsp irq */
+        sysbus_init_irq(dev, &m->wkup);
+        sysbus_init_mmio(dev, 0x1000,
+                        cpu_register_io_memory(omap2_gpio_module_readfn,
+                                        omap2_gpio_module_writefn,
+                                        m, DEVICE_NATIVE_ENDIAN));
+    }
+    return 0;
+}
 
-    omap_gpif_reset(s);
+/* Using qdev pointer properties for the clocks is not ideal.
+ * qdev should support a generic means of defining a 'port' with
+ * an arbitrary interface for connecting two devices. Then we
+ * could reframe the omap clock API in terms of clock ports,
+ * and get some type safety. For now the best qdev provides is
+ * passing an arbitrary pointer.
+ * (It's not possible to pass in the string which is the clock
+ * name, because this device does not have the necessary information
+ * (ie the struct omap_mpu_state_s*) to do the clockname to pointer
+ * translation.)
+ */
 
-    iomemtype = l4_register_io_memory(omap_gpif_top_readfn,
-                    omap_gpif_top_writefn, s);
-    omap_l4_attach(ta, 1, iomemtype);
+static SysBusDeviceInfo omap_gpio_info = {
+    .init = omap_gpio_init,
+    .qdev.name = "omap-gpio",
+    .qdev.size = sizeof(struct omap_gpif_s),
+    .qdev.reset = omap_gpif_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0),
+        DEFINE_PROP_PTR("clk", struct omap_gpif_s, clk),
+        DEFINE_PROP_END_OF_LIST()
+    }
+};
 
-    return s;
-}
+static SysBusDeviceInfo omap2_gpio_info = {
+    .init = omap2_gpio_init,
+    .qdev.name = "omap2-gpio",
+    .qdev.size = sizeof(struct omap2_gpif_s),
+    .qdev.reset = omap2_gpif_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0),
+        DEFINE_PROP_PTR("iclk", struct omap2_gpif_s, iclk),
+        DEFINE_PROP_PTR("fclk0", struct omap2_gpif_s, fclk[0]),
+        DEFINE_PROP_PTR("fclk1", struct omap2_gpif_s, fclk[1]),
+        DEFINE_PROP_PTR("fclk2", struct omap2_gpif_s, fclk[2]),
+        DEFINE_PROP_PTR("fclk3", struct omap2_gpif_s, fclk[3]),
+        DEFINE_PROP_PTR("fclk4", struct omap2_gpif_s, fclk[4]),
+        DEFINE_PROP_PTR("fclk5", struct omap2_gpif_s, fclk[5]),
+        DEFINE_PROP_END_OF_LIST()
+    }
+};
 
-qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
+static void omap_gpio_register_device(void)
 {
-    if (start >= s->modules * 32 || start < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, start);
-    return s->module[start >> 5].in + (start & 31);
+    sysbus_register_withprop(&omap_gpio_info);
+    sysbus_register_withprop(&omap2_gpio_info);
 }
 
-void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler)
-{
-    if (line >= s->modules * 32 || line < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
-    s->module[line >> 5].handler[line & 31] = handler;
-}
+device_init(omap_gpio_register_device)
index 4af0ca8ea611549151f61dfd686ec680d820f47e..59c84b19a2369a6ea5ba5c5315ea3508c0ff5d9a 100644 (file)
@@ -146,6 +146,12 @@ struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
     return bus;
 }
 
+target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta,
+                                       int region)
+{
+    return ta->bus->base + ta->start[region].offset;
+}
+
 static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
index 71c1ab40b49ff5464174deb457f899a2c84a3601..b0cbebc1783ecaf33c8302f6f474543e1879f3c6 100644 (file)
 #define BLOCK_SHIFT    (PAGE_SHIFT + 6)
 
 typedef struct {
-    uint32_t id;
+    struct {
+        uint16_t man;
+        uint16_t dev;
+        uint16_t ver;
+    } id;
     int shift;
     target_phys_addr_t base;
     qemu_irq intr;
@@ -175,14 +179,39 @@ static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
 static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
                 void *src)
 {
-    if (s->bdrv_cur)
-        return bdrv_write(s->bdrv_cur, sec, src, secn) < 0;
-    else if (sec + secn > s->secs_cur)
-        return 1;
-
-    memcpy(s->current + (sec << 9), src, secn << 9);
+    int result = 0;
+
+    if (secn > 0) {
+        uint32_t size = (uint32_t) secn * 512;
+        const uint8_t *sp = (const uint8_t *) src;
+        uint8_t *dp = 0;
+        if (s->bdrv_cur) {
+            dp = qemu_malloc(size);
+            if (!dp || bdrv_read(s->bdrv_cur, sec, dp, secn) < 0) {
+                result = 1;
+            }
+        } else {
+            if (sec + secn > s->secs_cur) {
+                result = 1;
+            } else {
+                dp = (uint8_t *) s->current + (sec << 9);
+            }
+        }
+        if (!result) {
+            uint32_t i;
+            for (i = 0; i < size; i++) {
+                dp[i] &= sp[i];
+            }
+            if (s->bdrv_cur) {
+                result = bdrv_write(s->bdrv_cur, sec, dp, secn) < 0;
+            }
+        }
+        if (dp && s->bdrv_cur) {
+            qemu_free(dp);
+        }
+    }
 
-    return 0;
+    return result;
 }
 
 static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
@@ -205,35 +234,87 @@ static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
 static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
                 void *src)
 {
-    uint8_t buf[512];
-
-    if (s->bdrv_cur) {
-        if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
-            return 1;
-        memcpy(buf + ((sec & 31) << 4), src, secn << 4);
-        return bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0;
-    } else if (sec + secn > s->secs_cur)
-        return 1;
-
-    memcpy(s->current + (s->secs_cur << 9) + (sec << 4), src, secn << 4);
-    return 0;
+    int result = 0;
+    if (secn > 0) {
+        const uint8_t *sp = (const uint8_t *) src;
+        uint8_t *dp = 0, *dpp = 0;
+        if (s->bdrv_cur) {
+            dp = qemu_malloc(512);
+            if (!dp || bdrv_read(s->bdrv_cur,
+                                s->secs_cur + (sec >> 5),
+                                dp, 1) < 0) {
+                result = 1;
+            } else {
+                dpp = dp + ((sec & 31) << 4);
+            }
+        } else {
+            if (sec + secn > s->secs_cur) {
+                result = 1;
+            } else {
+                dpp = s->current + (s->secs_cur << 9) + (sec << 4);
+            }
+        }
+        if (!result) {
+            uint32_t i;
+            for (i = 0; i < (secn << 4); i++) {
+                dpp[i] &= sp[i];
+            }
+            if (s->bdrv_cur) {
+                result = bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5),
+                                dp, 1) < 0;
+            }
+        }
+        if (dp) {
+            qemu_free(dp);
+        }
+    }
+    return result;
 }
 
 static inline int onenand_erase(OneNANDState *s, int sec, int num)
 {
-    /* TODO: optimise */
-    uint8_t buf[512];
-
-    memset(buf, 0xff, sizeof(buf));
-    for (; num > 0; num --, sec ++) {
-        if (onenand_prog_main(s, sec, 1, buf))
-            return 1;
-        if (onenand_prog_spare(s, sec, 1, buf))
-            return 1;
+    uint8_t *blankbuf, *tmpbuf;
+    blankbuf = qemu_malloc(512);
+    if (!blankbuf) {
+        return 1;
+    }
+    tmpbuf = qemu_malloc(512);
+    if (!tmpbuf) {
+        qemu_free(blankbuf);
+        return 1;
+    }
+    memset(blankbuf, 0xff, 512);
+    for (; num > 0; num--, sec++) {
+        if (s->bdrv_cur) {
+            int erasesec = s->secs_cur + (sec >> 5);
+            if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1)) {
+                goto fail;
+            }
+            if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
+                goto fail;
+            }
+            memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
+            if (bdrv_write(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
+                goto fail;
+            }
+        } else {
+            if (sec + 1 > s->secs_cur) {
+                goto fail;
+            }
+            memcpy(s->current + (sec << 9), blankbuf, 512);
+            memcpy(s->current + (s->secs_cur << 9) + (sec << 4),
+                   blankbuf, 1 << 4);
+        }
     }
 
+    qemu_free(tmpbuf);
+    qemu_free(blankbuf);
     return 0;
+
+fail:
+    qemu_free(tmpbuf);
+    qemu_free(blankbuf);
+    return 1;
 }
 
 static void onenand_command(OneNANDState *s, int cmd)
@@ -453,12 +534,12 @@ static uint32_t onenand_read(void *opaque, target_phys_addr_t addr)
         return lduw_le_p(s->boot[0] + addr);
 
     case 0xf000:       /* Manufacturer ID */
-        return (s->id >> 16) & 0xff;
+        return s->id.man;
     case 0xf001:       /* Device ID */
-        return (s->id >>  8) & 0xff;
-    /* TODO: get the following values from a real chip!  */
+        return s->id.dev;
     case 0xf002:       /* Version ID */
-        return (s->id >>  0) & 0xff;
+        return s->id.ver;
+    /* TODO: get the following values from a real chip!  */
     case 0xf003:       /* Data Buffer size */
         return 1 << PAGE_SHIFT;
     case 0xf004:       /* Boot Buffer size */
@@ -541,8 +622,8 @@ static void onenand_write(void *opaque, target_phys_addr_t addr,
 
         case 0x0090:   /* Read Identification Data */
             memset(s->boot[0], 0, 3 << s->shift);
-            s->boot[0][0 << s->shift] = (s->id >> 16) & 0xff;
-            s->boot[0][1 << s->shift] = (s->id >>  8) & 0xff;
+            s->boot[0][0 << s->shift] = s->id.man & 0xff;
+            s->boot[0][1 << s->shift] = s->id.dev & 0xff;
             s->boot[0][2 << s->shift] = s->wpstatus & 0xff;
             break;
 
@@ -615,28 +696,31 @@ static CPUWriteMemoryFunc * const onenand_writefn[] = {
     onenand_write,
 };
 
-void *onenand_init(uint32_t id, int regshift, qemu_irq irq)
+void *onenand_init(BlockDriverState *bdrv,
+                uint16_t man_id, uint16_t dev_id, uint16_t ver_id,
+                int regshift, qemu_irq irq)
 {
     OneNANDState *s = (OneNANDState *) qemu_mallocz(sizeof(*s));
-    DriveInfo *dinfo = drive_get(IF_MTD, 0, 0);
-    uint32_t size = 1 << (24 + ((id >> 12) & 7));
+    uint32_t size = 1 << (24 + ((dev_id >> 4) & 7));
     void *ram;
 
     s->shift = regshift;
     s->intr = irq;
     s->rdy = NULL;
-    s->id = id;
+    s->id.man = man_id;
+    s->id.dev = dev_id;
+    s->id.ver = ver_id;
     s->blocks = size >> BLOCK_SHIFT;
     s->secs = size >> 9;
     s->blockwp = qemu_malloc(s->blocks);
-    s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0;
+    s->density_mask = (dev_id & 0x08) ? (1 << (6 + ((dev_id >> 4) & 7))) : 0;
     s->iomemtype = cpu_register_io_memory(onenand_readfn,
                     onenand_writefn, s, DEVICE_NATIVE_ENDIAN);
-    if (!dinfo)
+    s->bdrv = bdrv;
+    if (!s->bdrv) {
         s->image = memset(qemu_malloc(size + (size >> 5)),
                         0xff, size + (size >> 5));
-    else
-        s->bdrv = dinfo->bdrv;
+    }
     s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT),
                     0xff, (64 + 2) << PAGE_SHIFT);
     s->ram = qemu_ram_alloc(NULL, "onenand.ram", 0xc000 << s->shift);
index 6d2cf994ba6072c2c2fecf650fdb3ecfb0c75861..ccd4a14f817bfaa44c6a8233fe0b217bd2d47df3 100644 (file)
@@ -205,7 +205,7 @@ typedef struct IRQ_dst_t {
 
 typedef struct openpic_t {
     PCIDevice pci_dev;
-    int mem_index;
+    MemoryRegion mem;
     /* Global registers */
     uint32_t frep; /* Feature reporting register */
     uint32_t glbc; /* Global configuration register  */
@@ -984,47 +984,34 @@ static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr)
     return retval;
 }
 
-static CPUWriteMemoryFunc * const openpic_write[] = {
-    &openpic_buggy_write,
-    &openpic_buggy_write,
-    &openpic_writel,
-};
+static uint64_t openpic_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
+{
+    openpic_t *opp = opaque;
 
-static CPUReadMemoryFunc * const openpic_read[] = {
-    &openpic_buggy_read,
-    &openpic_buggy_read,
-    &openpic_readl,
-};
+    switch (size) {
+    case 4: return openpic_readl(opp, addr);
+    default: return openpic_buggy_read(opp, addr);
+    }
+}
 
-static void openpic_map(PCIDevice *pci_dev, int region_num,
-                        pcibus_t addr, pcibus_t size, int type)
+static void openpic_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t data, unsigned size)
 {
-    openpic_t *opp;
+    openpic_t *opp = opaque;
 
-    DPRINTF("Map OpenPIC\n");
-    opp = (openpic_t *)pci_dev;
-    /* Global registers */
-    DPRINTF("Register OPENPIC gbl   %08x => %08x\n",
-            addr + 0x1000, addr + 0x1000 + 0x100);
-    /* Timer registers */
-    DPRINTF("Register OPENPIC timer %08x => %08x\n",
-            addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR);
-    /* Interrupt source registers */
-    DPRINTF("Register OPENPIC src   %08x => %08x\n",
-            addr + 0x10000, addr + 0x10000 + 0x20 * (OPENPIC_EXT_IRQ + 2));
-    /* Per CPU registers */
-    DPRINTF("Register OPENPIC dst   %08x => %08x\n",
-            addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU);
-    cpu_register_physical_memory(addr, 0x40000, opp->mem_index);
-#if 0 // Don't implement ISU for now
-    opp_io_memory = cpu_register_io_memory(openpic_src_read,
-                                           openpic_src_write, NULL
-                                           DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
-                                 opp_io_memory);
-#endif
+    switch (size) {
+    case 4: return openpic_writel(opp, addr, data);
+    default: return openpic_buggy_write(opp, addr, data);
+    }
 }
 
+static const MemoryRegionOps openpic_ops = {
+    .read = openpic_read,
+    .write = openpic_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
 {
     unsigned int i;
@@ -1161,7 +1148,7 @@ static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
     qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
 }
 
-qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
+qemu_irq *openpic_init (PCIBus *bus, MemoryRegion **pmem, int nb_cpus,
                         qemu_irq **irqs, qemu_irq irq_out)
 {
     openpic_t *opp;
@@ -1180,14 +1167,22 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
         pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER); // FIXME?
         pci_conf[0x3d] = 0x00; // no interrupt pin
 
+        memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
+#if 0 // Don't implement ISU for now
+        opp_io_memory = cpu_register_io_memory(openpic_src_read,
+                                               openpic_src_write, NULL
+                                               DEVICE_NATIVE_ENDIAN);
+        cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
+                                     opp_io_memory);
+#endif
+
         /* Register I/O spaces */
-        pci_register_bar(&opp->pci_dev, 0, 0x40000,
-                               PCI_BASE_ADDRESS_SPACE_MEMORY, &openpic_map);
+        pci_register_bar(&opp->pci_dev, 0,
+                         PCI_BASE_ADDRESS_SPACE_MEMORY, &opp->mem);
     } else {
         opp = qemu_mallocz(sizeof(openpic_t));
+        memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
     }
-    opp->mem_index = cpu_register_io_memory(openpic_read, openpic_write, opp,
-                                            DEVICE_LITTLE_ENDIAN);
 
     //    isu_base &= 0xFFFC0000;
     opp->nb_cpus = nb_cpus;
@@ -1223,8 +1218,8 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
     opp->irq_raise = openpic_irq_raise;
     opp->reset = openpic_reset;
 
-    if (pmem_index)
-        *pmem_index = opp->mem_index;
+    if (pmem)
+        *pmem = &opp->mem;
 
     return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
 }
index 0957c1ff009ee4f36e71cc672040874524d76826..75de3616ada1ec1e5c2e367d8faddc046975a802 100644 (file)
@@ -11,7 +11,7 @@ enum {
     OPENPIC_OUTPUT_NB,
 };
 
-qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
+qemu_irq *openpic_init (PCIBus *bus, MemoryRegion **pmem, int nb_cpus,
                         qemu_irq **irqs, qemu_irq irq_out);
 qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
                         qemu_irq **irqs, qemu_irq irq_out);
index f22d7775eebff9af40d5646c7335a27c955fba63..4c67e75c833cf8cfdea7c80e7ded5a98621d2047 100644 (file)
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -94,7 +94,7 @@ static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
 {
     uWireSlave *tsc;
 
-    tsc = tsc2102_init(omap_gpio_in_get(cpu->gpio)[PALMTE_PINTDAV_GPIO]);
+    tsc = tsc2102_init(qdev_get_gpio_in(cpu->gpio, PALMTE_PINTDAV_GPIO));
 
     omap_uwire_attach(cpu->microwire, tsc, 0);
     omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc));
@@ -163,24 +163,24 @@ static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
     qemu_irq *misc_gpio;
 
     omap_mmc_handlers(cpu->mmc,
-                    omap_gpio_in_get(cpu->gpio)[PALMTE_MMC_WP_GPIO],
+                    qdev_get_gpio_in(cpu->gpio, PALMTE_MMC_WP_GPIO),
                     qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
                             [PALMTE_MMC_SWITCH_GPIO]));
 
     misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7);
-    omap_gpio_out_set(cpu->gpio, PALMTE_MMC_POWER_GPIO,        misc_gpio[0]);
-    omap_gpio_out_set(cpu->gpio, PALMTE_SPEAKER_GPIO,  misc_gpio[1]);
-    omap_gpio_out_set(cpu->gpio, 11,                   misc_gpio[2]);
-    omap_gpio_out_set(cpu->gpio, 12,                   misc_gpio[3]);
-    omap_gpio_out_set(cpu->gpio, 13,                   misc_gpio[4]);
-    omap_mpuio_out_set(cpu->mpuio, 1,                  misc_gpio[5]);
-    omap_mpuio_out_set(cpu->mpuio, 3,                  misc_gpio[6]);
+    qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO,    misc_gpio[0]);
+    qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO,      misc_gpio[1]);
+    qdev_connect_gpio_out(cpu->gpio, 11,                       misc_gpio[2]);
+    qdev_connect_gpio_out(cpu->gpio, 12,                       misc_gpio[3]);
+    qdev_connect_gpio_out(cpu->gpio, 13,                       misc_gpio[4]);
+    omap_mpuio_out_set(cpu->mpuio, 1,                          misc_gpio[5]);
+    omap_mpuio_out_set(cpu->mpuio, 3,                          misc_gpio[6]);
 
     /* Reset some inputs to initial state.  */
-    qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_USBDETECT_GPIO]);
-    qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_USB_OR_DC_GPIO]);
-    qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[4]);
-    qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_HEADPHONES_GPIO]);
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USBDETECT_GPIO));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USB_OR_DC_GPIO));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, 4));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_HEADPHONES_GPIO));
     qemu_irq_lower(omap_mpuio_in_get(cpu->mpuio)[PALMTE_DC_GPIO]);
     qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[6]);
     qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[7]);
diff --git a/hw/pc.c b/hw/pc.c
index a3e8539dc6887078c25884b2242310c9e821d2f8..1c9d89a4b881db0d9d123ebd6d59688862a5943a 100644 (file)
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -41,6 +41,7 @@
 #include "sysemu.h"
 #include "blockdev.h"
 #include "ui/qemu-spice.h"
+#include "memory.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -957,7 +958,8 @@ void pc_cpus_init(const char *cpu_model)
     }
 }
 
-void pc_memory_init(const char *kernel_filename,
+void pc_memory_init(MemoryRegion *system_memory,
+                    const char *kernel_filename,
                     const char *kernel_cmdline,
                     const char *initrd_filename,
                     ram_addr_t below_4g_mem_size,
@@ -965,22 +967,30 @@ void pc_memory_init(const char *kernel_filename,
 {
     char *filename;
     int ret, linux_boot, i;
-    ram_addr_t ram_addr, bios_offset, option_rom_offset;
+    MemoryRegion *ram, *bios, *isa_bios, *option_rom_mr;
+    MemoryRegion *ram_below_4g, *ram_above_4g;
     int bios_size, isa_bios_size;
     void *fw_cfg;
 
     linux_boot = (kernel_filename != NULL);
 
-    /* allocate RAM */
-    ram_addr = qemu_ram_alloc(NULL, "pc.ram",
-                              below_4g_mem_size + above_4g_mem_size);
-    cpu_register_physical_memory(0, 0xa0000, ram_addr);
-    cpu_register_physical_memory(0x100000,
-                 below_4g_mem_size - 0x100000,
-                 ram_addr + 0x100000);
+    /* Allocate RAM.  We allocate it as a single memory region and use
+     * aliases to address portions of it, mostly for backwards compatiblity
+     * with older qemus that used qemu_ram_alloc().
+     */
+    ram = qemu_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, NULL, "pc.ram",
+                           below_4g_mem_size + above_4g_mem_size);
+    ram_below_4g = qemu_malloc(sizeof(*ram_below_4g));
+    memory_region_init_alias(ram_below_4g, "ram-below-4g", ram,
+                             0, below_4g_mem_size);
+    memory_region_add_subregion(system_memory, 0, ram_below_4g);
     if (above_4g_mem_size > 0) {
-        cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
-                                     ram_addr + below_4g_mem_size);
+        ram_above_4g = qemu_malloc(sizeof(*ram_above_4g));
+        memory_region_init_alias(ram_above_4g, "ram-above-4g", ram,
+                                 below_4g_mem_size, above_4g_mem_size);
+        memory_region_add_subregion(system_memory, 0x100000000ULL,
+                                    ram_above_4g);
     }
 
     /* BIOS load */
@@ -996,7 +1006,9 @@ void pc_memory_init(const char *kernel_filename,
         (bios_size % 65536) != 0) {
         goto bios_error;
     }
-    bios_offset = qemu_ram_alloc(NULL, "pc.bios", bios_size);
+    bios = qemu_malloc(sizeof(*bios));
+    memory_region_init_ram(bios, NULL, "pc.bios", bios_size);
+    memory_region_set_readonly(bios, true);
     ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
     if (ret != 0) {
     bios_error:
@@ -1010,16 +1022,26 @@ void pc_memory_init(const char *kernel_filename,
     isa_bios_size = bios_size;
     if (isa_bios_size > (128 * 1024))
         isa_bios_size = 128 * 1024;
-    cpu_register_physical_memory(0x100000 - isa_bios_size,
-                                 isa_bios_size,
-                                 (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
-
-    option_rom_offset = qemu_ram_alloc(NULL, "pc.rom", PC_ROM_SIZE);
-    cpu_register_physical_memory(PC_ROM_MIN_VGA, PC_ROM_SIZE, option_rom_offset);
+    isa_bios = qemu_malloc(sizeof(*isa_bios));
+    memory_region_init_alias(isa_bios, "isa-bios", bios,
+                             bios_size - isa_bios_size, isa_bios_size);
+    memory_region_add_subregion_overlap(system_memory,
+                                        0x100000 - isa_bios_size,
+                                        isa_bios,
+                                        1);
+    memory_region_set_readonly(isa_bios, true);
+
+    option_rom_mr = qemu_malloc(sizeof(*option_rom_mr));
+    memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE);
+    memory_region_add_subregion_overlap(system_memory,
+                                        PC_ROM_MIN_VGA,
+                                        option_rom_mr,
+                                        1);
 
     /* map all the bios at the top of memory */
-    cpu_register_physical_memory((uint32_t)(-bios_size),
-                                 bios_size, bios_offset | IO_MEM_ROM);
+    memory_region_add_subregion(system_memory,
+                                (uint32_t)(-bios_size),
+                                bios);
 
     fw_cfg = bochs_bios_init();
     rom_set_fw(fw_cfg);
diff --git a/hw/pc.h b/hw/pc.h
index 6d5730b26be23159b7c9c5f6d30dd56eb2e647ec..ec34db73853f4ddf0ed754acf16366233555c04f 100644 (file)
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -2,10 +2,12 @@
 #define HW_PC_H
 
 #include "qemu-common.h"
+#include "memory.h"
 #include "ioport.h"
 #include "isa.h"
 #include "fdc.h"
 #include "net.h"
+#include "memory.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
@@ -129,7 +131,8 @@ void pc_cmos_set_s3_resume(void *opaque, int irq, int level);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
 void pc_cpus_init(const char *cpu_model);
-void pc_memory_init(const char *kernel_filename,
+void pc_memory_init(MemoryRegion *system_memory,
+                    const char *kernel_filename,
                     const char *kernel_cmdline,
                     const char *initrd_filename,
                     ram_addr_t below_4g_mem_size,
@@ -175,7 +178,11 @@ int pcspk_audio_init(qemu_irq *pic);
 struct PCII440FXState;
 typedef struct PCII440FXState PCII440FXState;
 
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, ram_addr_t ram_size);
+PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
+                    qemu_irq *pic,
+                    MemoryRegion *address_space_mem,
+                    MemoryRegion *address_space_io,
+                    ram_addr_t ram_size);
 void i440fx_init_memory_mappings(PCII440FXState *d);
 
 /* piix4.c */
index c5c16b45718ada66fabfc02298494fabc65c03bc..7dd5008dce9d510a973a15a8531c2e3e85d69715 100644 (file)
@@ -39,6 +39,8 @@
 #include "blockdev.h"
 #include "smbus.h"
 #include "xen.h"
+#include "memory.h"
+#include "exec-memory.h"
 #ifdef CONFIG_XEN
 #  include <xen/hvm/hvm_info_table.h>
 #endif
@@ -66,7 +68,9 @@ static void ioapic_init(IsaIrqState *isa_irq_state)
 }
 
 /* PC hardware initialisation */
-static void pc_init1(ram_addr_t ram_size,
+static void pc_init1(MemoryRegion *system_memory,
+                     MemoryRegion *system_io,
+                     ram_addr_t ram_size,
                      const char *boot_device,
                      const char *kernel_filename,
                      const char *kernel_cmdline,
@@ -106,7 +110,8 @@ static void pc_init1(ram_addr_t ram_size,
 
     /* allocate ram and load rom/bios */
     if (!xen_enabled()) {
-        pc_memory_init(kernel_filename, kernel_cmdline, initrd_filename,
+        pc_memory_init(system_memory,
+                       kernel_filename, kernel_cmdline, initrd_filename,
                        below_4g_mem_size, above_4g_mem_size);
     }
 
@@ -124,7 +129,8 @@ static void pc_init1(ram_addr_t ram_size,
     isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
 
     if (pci_enabled) {
-        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
+        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq,
+                              system_memory, system_io, ram_size);
     } else {
         pci_bus = NULL;
         i440fx_state = NULL;
@@ -155,7 +161,11 @@ static void pc_init1(ram_addr_t ram_size,
     ide_drive_get(hd, MAX_IDE_BUS);
     if (pci_enabled) {
         PCIDevice *dev;
-        dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
+        if (xen_enabled()) {
+            dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
+        } else {
+            dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
+        }
         idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
         idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
     } else {
@@ -208,7 +218,9 @@ static void pc_init_pci(ram_addr_t ram_size,
                         const char *initrd_filename,
                         const char *cpu_model)
 {
-    pc_init1(ram_size, boot_device,
+    pc_init1(get_system_memory(),
+             get_system_io(),
+             ram_size, boot_device,
              kernel_filename, kernel_cmdline,
              initrd_filename, cpu_model, 1, 1);
 }
@@ -220,7 +232,9 @@ static void pc_init_pci_no_kvmclock(ram_addr_t ram_size,
                                     const char *initrd_filename,
                                     const char *cpu_model)
 {
-    pc_init1(ram_size, boot_device,
+    pc_init1(get_system_memory(),
+             get_system_io(),
+             ram_size, boot_device,
              kernel_filename, kernel_cmdline,
              initrd_filename, cpu_model, 1, 0);
 }
@@ -234,7 +248,9 @@ static void pc_init_isa(ram_addr_t ram_size,
 {
     if (cpu_model == NULL)
         cpu_model = "486";
-    pc_init1(ram_size, boot_device,
+    pc_init1(get_system_memory(),
+             get_system_io(),
+             ram_size, boot_device,
              kernel_filename, kernel_cmdline,
              initrd_filename, cpu_model, 0, 1);
 }
index b904a4ecb63d1730f750cd2d6722fa316f9ad1bd..dc7271a19f21430418be3dffed1440048259ef0c 100644 (file)
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -263,11 +263,16 @@ int pci_find_domain(const PCIBus *bus)
 }
 
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name, uint8_t devfn_min)
+                         const char *name,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io,
+                         uint8_t devfn_min)
 {
     qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
     assert(PCI_FUNC(devfn_min) == 0);
     bus->devfn_min = devfn_min;
+    bus->address_space_mem = address_space_mem;
+    bus->address_space_io = address_space_io;
 
     /* host bridge */
     QLIST_INIT(&bus->child);
@@ -276,13 +281,17 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
     vmstate_register(NULL, -1, &vmstate_pcibus, bus);
 }
 
-PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min)
+PCIBus *pci_bus_new(DeviceState *parent, const char *name,
+                    MemoryRegion *address_space_mem,
+                    MemoryRegion *address_space_io,
+                    uint8_t devfn_min)
 {
     PCIBus *bus;
 
     bus = qemu_mallocz(sizeof(*bus));
     bus->qbus.qdev_allocated = 1;
-    pci_bus_new_inplace(bus, parent, name, devfn_min);
+    pci_bus_new_inplace(bus, parent, name, address_space_mem,
+                        address_space_io, devfn_min);
     return bus;
 }
 
@@ -310,11 +319,15 @@ void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base)
 
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque, uint8_t devfn_min, int nirq)
+                         void *irq_opaque,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io,
+                         uint8_t devfn_min, int nirq)
 {
     PCIBus *bus;
 
-    bus = pci_bus_new(parent, name, devfn_min);
+    bus = pci_bus_new(parent, name, address_space_mem,
+                      address_space_io, devfn_min);
     pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
     return bus;
 }
@@ -835,14 +848,7 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
         r = &pci_dev->io_regions[i];
         if (!r->size || r->addr == PCI_BAR_UNMAPPED)
             continue;
-        if (r->type == PCI_BASE_ADDRESS_SPACE_IO) {
-            isa_unassign_ioport(r->addr, r->filtered_size);
-        } else {
-            cpu_register_physical_memory(pci_to_cpu_addr(pci_dev->bus,
-                                                         r->addr),
-                                         r->filtered_size,
-                                         IO_MEM_UNASSIGNED);
-        }
+        memory_region_del_subregion(r->address_space, r->memory);
     }
 }
 
@@ -865,12 +871,12 @@ static int pci_unregister_device(DeviceState *dev)
 }
 
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
-                            pcibus_t size, uint8_t type,
-                            PCIMapIORegionFunc *map_func)
+                      uint8_t type, MemoryRegion *memory)
 {
     PCIIORegion *r;
     uint32_t addr;
     uint64_t wmask;
+    pcibus_t size = memory_region_size(memory);
 
     assert(region_num >= 0);
     assert(region_num < PCI_NUM_REGIONS);
@@ -885,8 +891,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     r->size = size;
     r->filtered_size = size;
     r->type = type;
-    r->map_func = map_func;
-    r->ram_addr = IO_MEM_UNASSIGNED;
+    r->memory = NULL;
 
     wmask = ~(size - 1);
     addr = pci_bar(pci_dev, region_num);
@@ -903,22 +908,16 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
         pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
         pci_set_long(pci_dev->cmask + addr, 0xffffffff);
     }
+    pci_dev->io_regions[region_num].memory = memory;
+    pci_dev->io_regions[region_num].address_space
+        = type & PCI_BASE_ADDRESS_SPACE_IO
+        ? pci_dev->bus->address_space_io
+        : pci_dev->bus->address_space_mem;
 }
 
-static void pci_simple_bar_mapfunc(PCIDevice *pci_dev, int region_num,
-                                   pcibus_t addr, pcibus_t size, int type)
+pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num)
 {
-    cpu_register_physical_memory(addr, size,
-                                 pci_dev->io_regions[region_num].ram_addr);
-}
-
-void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
-                             pcibus_t size,  uint8_t attr, ram_addr_t ram_addr)
-{
-    pci_register_bar(pci_dev, region_num, size,
-                     PCI_BASE_ADDRESS_SPACE_MEMORY | attr,
-                     pci_simple_bar_mapfunc);
-    pci_dev->io_regions[region_num].ram_addr = ram_addr;
+    return pci_dev->io_regions[region_num].addr;
 }
 
 static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size,
@@ -1048,22 +1047,7 @@ static void pci_update_mappings(PCIDevice *d)
 
         /* now do the real mapping */
         if (r->addr != PCI_BAR_UNMAPPED) {
-            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
-                int class;
-                /* NOTE: specific hack for IDE in PC case:
-                   only one byte must be mapped. */
-                class = pci_get_word(d->config + PCI_CLASS_DEVICE);
-                if (class == 0x0101 && r->size == 4) {
-                    isa_unassign_ioport(r->addr + 2, 1);
-                } else {
-                    isa_unassign_ioport(r->addr, r->filtered_size);
-                }
-            } else {
-                cpu_register_physical_memory(pci_to_cpu_addr(d->bus, r->addr),
-                                             r->filtered_size,
-                                             IO_MEM_UNASSIGNED);
-                qemu_unregister_coalesced_mmio(r->addr, r->filtered_size);
-            }
+            memory_region_del_subregion(r->address_space, r->memory);
         }
         r->addr = new_addr;
         r->filtered_size = filtered_size;
@@ -1076,10 +1060,16 @@ static void pci_update_mappings(PCIDevice *d)
              * addr & (size - 1) != 0.
              */
             if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
-                r->map_func(d, i, r->addr, r->filtered_size, r->type);
+                memory_region_add_subregion_overlap(r->address_space,
+                                                    r->addr,
+                                                    r->memory,
+                                                    1);
             } else {
-                r->map_func(d, i, pci_to_cpu_addr(d->bus, r->addr),
-                            r->filtered_size, r->type);
+                memory_region_add_subregion_overlap(r->address_space,
+                                                    pci_to_cpu_addr(d->bus,
+                                                                    r->addr),
+                                                    r->memory,
+                                                    1);
             }
         }
     }
@@ -1108,8 +1098,7 @@ uint32_t pci_default_read_config(PCIDevice *d,
                                  uint32_t address, int len)
 {
     uint32_t val = 0;
-    assert(len == 1 || len == 2 || len == 4);
-    len = MIN(len, pci_config_size(d) - address);
+
     memcpy(&val, d->config + address, len);
     return le32_to_cpu(val);
 }
@@ -1117,9 +1106,8 @@ uint32_t pci_default_read_config(PCIDevice *d,
 void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
 {
     int i, was_irq_disabled = pci_irq_disabled(d);
-    uint32_t config_size = pci_config_size(d);
 
-    for (i = 0; i < l && addr + i < config_size; val >>= 8, ++i) {
+    for (i = 0; i < l; val >>= 8, ++i) {
         uint8_t wmask = d->wmask[addr + i];
         uint8_t w1cmask = d->w1cmask[addr + i];
         assert(!(wmask & w1cmask));
@@ -1823,11 +1811,6 @@ static uint8_t pci_find_capability_list(PCIDevice *pdev, uint8_t cap_id,
     return next;
 }
 
-static void pci_map_option_rom(PCIDevice *pdev, int region_num, pcibus_t addr, pcibus_t size, int type)
-{
-    cpu_register_physical_memory(addr, size, pdev->rom_offset);
-}
-
 /* Patch the PCI vendor and device ids in a PCI rom image if necessary.
    This is needed for an option rom which is used for more than one device. */
 static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size)
@@ -1931,9 +1914,9 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
         snprintf(name, sizeof(name), "%s.rom", pdev->qdev.info->vmsd->name);
     else
         snprintf(name, sizeof(name), "%s.rom", pdev->qdev.info->name);
-    pdev->rom_offset = qemu_ram_alloc(&pdev->qdev, name, size);
-
-    ptr = qemu_get_ram_ptr(pdev->rom_offset);
+    pdev->has_rom = true;
+    memory_region_init_ram(&pdev->rom, &pdev->qdev, name, size);
+    ptr = memory_region_get_ram_ptr(&pdev->rom);
     load_image(path, ptr);
     qemu_free(path);
 
@@ -1944,19 +1927,18 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
 
     qemu_put_ram_ptr(ptr);
 
-    pci_register_bar(pdev, PCI_ROM_SLOT, size,
-                     0, pci_map_option_rom);
+    pci_register_bar(pdev, PCI_ROM_SLOT, 0, &pdev->rom);
 
     return 0;
 }
 
 static void pci_del_option_rom(PCIDevice *pdev)
 {
-    if (!pdev->rom_offset)
+    if (!pdev->has_rom)
         return;
 
-    qemu_ram_free(pdev->rom_offset);
-    pdev->rom_offset = 0;
+    memory_region_destroy(&pdev->rom);
+    pdev->has_rom = false;
 }
 
 /*
index c220745c98837ee5e9af668d63c76ca347c341cb..d7ad7fb95fe0cad29d03e762e148f307dfeac5c4 100644 (file)
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -5,6 +5,7 @@
 #include "qobject.h"
 
 #include "qdev.h"
+#include "memory.h"
 
 /* PCI includes legacy ISA access.  */
 #include "isa.h"
@@ -91,8 +92,8 @@ typedef struct PCIIORegion {
     pcibus_t size;
     pcibus_t filtered_size;
     uint8_t type;
-    PCIMapIORegionFunc *map_func;
-    ram_addr_t ram_addr;
+    MemoryRegion *memory;
+    MemoryRegion *address_space;
 } PCIIORegion;
 
 #define PCI_ROM_SLOT 6
@@ -173,7 +174,7 @@ struct PCIDevice {
     /* Space to store MSIX table */
     uint8_t *msix_table_page;
     /* MMIO index used to map MSIX table and pending bit entries. */
-    int msix_mmio_index;
+    MemoryRegion msix_mmio;
     /* Reference-count for entries actually in use by driver. */
     unsigned *msix_entry_used;
     /* Region including the MSI-X table */
@@ -189,7 +190,8 @@ struct PCIDevice {
 
     /* Location of option rom */
     char *romfile;
-    ram_addr_t rom_offset;
+    bool has_rom;
+    MemoryRegion rom;
     uint32_t rom_bar;
 };
 
@@ -199,10 +201,8 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
                                PCIConfigWriteFunc *config_write);
 
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
-                            pcibus_t size, uint8_t type,
-                            PCIMapIORegionFunc *map_func);
-void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
-                             pcibus_t size, uint8_t attr, ram_addr_t ram_addr);
+                      uint8_t attr, MemoryRegion *memory);
+pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
 
 int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
                        uint8_t offset, uint8_t size);
@@ -233,15 +233,24 @@ typedef enum {
 typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
                               PCIHotplugState state);
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name, uint8_t devfn_min);
-PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min);
+                         const char *name,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io,
+                         uint8_t devfn_min);
+PCIBus *pci_bus_new(DeviceState *parent, const char *name,
+                    MemoryRegion *address_space_mem,
+                    MemoryRegion *address_space_io,
+                    uint8_t devfn_min);
 void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                   void *irq_opaque, int nirq);
 int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
 void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque, uint8_t devfn_min, int nirq);
+                         void *irq_opaque,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io,
+                         uint8_t devfn_min, int nirq);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
index 728e2d4ce50ca46f4a3b4cd06194ab16ea769aa9..2e8a29f1e3d3aa4d6c30a2a11db361b272f62a46 100644 (file)
@@ -47,17 +47,33 @@ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr)
     return pci_find_device(bus, bus_num, devfn);
 }
 
+void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
+                                  uint32_t limit, uint32_t val, uint32_t len)
+{
+    assert(len <= 4);
+    pci_dev->config_write(pci_dev, addr, val, MIN(len, limit - addr));
+}
+
+uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
+                                     uint32_t limit, uint32_t len)
+{
+    assert(len <= 4);
+    return pci_dev->config_read(pci_dev, addr, MIN(len, limit - addr));
+}
+
 void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
 {
     PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr);
     uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
 
-    if (!pci_dev)
+    if (!pci_dev) {
         return;
+    }
 
     PCI_DPRINTF("%s: %s: addr=%02" PRIx32 " val=%08" PRIx32 " len=%d\n",
                 __func__, pci_dev->name, config_addr, val, len);
-    pci_dev->config_write(pci_dev, config_addr, val, len);
+    pci_host_config_write_common(pci_dev, config_addr, PCI_CONFIG_SPACE_SIZE,
+                                 val, len);
 }
 
 uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
@@ -66,12 +82,12 @@ uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
     uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
     uint32_t val;
 
-    assert(len == 1 || len == 2 || len == 4);
     if (!pci_dev) {
         return ~0x0;
     }
 
-    val = pci_dev->config_read(pci_dev, config_addr, len);
+    val = pci_host_config_read_common(pci_dev, config_addr,
+                                      PCI_CONFIG_SPACE_SIZE, len);
     PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
                 __func__, pci_dev->name, config_addr, val, len);
 
index 0a585951e07b7b2bdb51cbe6e450b67979a1ae25..7f551143bb273e32210be23857d75c6ae3f94c8c 100644 (file)
@@ -35,10 +35,17 @@ struct PCIHostState {
     SysBusDevice busdev;
     ReadWriteHandler conf_handler;
     ReadWriteHandler data_handler;
+    MemoryRegion *address_space;
     uint32_t config_reg;
     PCIBus *bus;
 };
 
+/* common internal helpers for PCI/PCIe hosts, cut off overflows */
+void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
+                                  uint32_t limit, uint32_t val, uint32_t len);
+uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
+                                     uint32_t limit, uint32_t len);
+
 void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len);
 uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len);
 
index fbe186680877850ba3e219ce04993943474268b6..c7fd23dc543603bd344b76101ea26422bb6ee056 100644 (file)
@@ -25,6 +25,8 @@ struct PCIBus {
     PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
     PCIDevice *parent_dev;
     target_phys_addr_t mem_base;
+    MemoryRegion *address_space_mem;
+    MemoryRegion *address_space_io;
 
     QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
     QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
index b7498656f24fa9134529c9ee4988c908bbc98b36..f9fea3d91829fe90663d923395eda245d5be85dc 100644 (file)
@@ -56,23 +56,39 @@ static void pcie_mmcfg_data_write(PCIBus *s,
                                   uint32_t mmcfg_addr, uint32_t val, int len)
 {
     PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, mmcfg_addr);
+    uint32_t addr;
+    uint32_t limit;
 
-    if (!pci_dev)
+    if (!pci_dev) {
         return;
-
-    pci_dev->config_write(pci_dev,
-                          PCIE_MMCFG_CONFOFFSET(mmcfg_addr), val, len);
+    }
+    addr = PCIE_MMCFG_CONFOFFSET(mmcfg_addr);
+    limit = pci_config_size(pci_dev);
+    if (limit <= addr) {
+        /* conventional pci device can be behind pcie-to-pci bridge.
+           256 <= addr < 4K has no effects. */
+        return;
+    }
+    pci_host_config_write_common(pci_dev, addr, limit, val, len);
 }
 
-static uint32_t pcie_mmcfg_data_read(PCIBus *s, uint32_t addr, int len)
+static uint32_t pcie_mmcfg_data_read(PCIBus *s, uint32_t mmcfg_addr, int len)
 {
-    PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, addr);
+    PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, mmcfg_addr);
+    uint32_t addr;
+    uint32_t limit;
 
-    assert(len == 1 || len == 2 || len == 4);
     if (!pci_dev) {
         return ~0x0;
     }
-    return pci_dev->config_read(pci_dev, PCIE_MMCFG_CONFOFFSET(addr), len);
+    addr = PCIE_MMCFG_CONFOFFSET(mmcfg_addr);
+    limit = pci_config_size(pci_dev);
+    if (limit <= addr) {
+        /* conventional pci device can be behind pcie-to-pci bridge.
+           256 <= addr < 4K has no effects. */
+        return ~0x0;
+    }
+    return pci_host_config_read_common(pci_dev, addr, limit, len);
 }
 
 static void pcie_mmcfg_data_writeb(void *opaque,
index 216cf81492114d0722369f35961bc9d486ea8b1e..13d9380b006a66ac51058267baa3be36be32fe8b 100644 (file)
@@ -46,6 +46,7 @@
 typedef struct {
     PCIDevice pci_dev;
     PCNetState state;
+    MemoryRegion io_bar;
 } PCIPCNetState;
 
 static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
@@ -69,25 +70,41 @@ static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
     return val;
 }
 
-static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
-                             pcibus_t addr, pcibus_t size, int type)
+static uint64_t pcnet_ioport_read(void *opaque, target_phys_addr_t addr,
+                                  unsigned size)
 {
-    PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state;
+    PCNetState *d = opaque;
 
-#ifdef PCNET_DEBUG_IO
-    printf("pcnet_ioport_map addr=0x%04"FMT_PCIBUS" size=0x%04"FMT_PCIBUS"\n",
-           addr, size);
-#endif
+    if (addr < 16 && size == 1) {
+        return pcnet_aprom_readb(d, addr);
+    } else if (addr >= 0x10 && addr < 0x20 && size == 2) {
+        return pcnet_ioport_readw(d, addr);
+    } else if (addr >= 0x10 && addr < 0x20 && size == 4) {
+        return pcnet_ioport_readl(d, addr);
+    }
+    return ((uint64_t)1 << (size * 8)) - 1;
+}
 
-    register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
-    register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
+static void pcnet_ioport_write(void *opaque, target_phys_addr_t addr,
+                               uint64_t data, unsigned size)
+{
+    PCNetState *d = opaque;
 
-    register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
-    register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
-    register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
-    register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
+    if (addr < 16 && size == 1) {
+        return pcnet_aprom_writeb(d, addr, data);
+    } else if (addr >= 0x10 && addr < 0x20 && size == 2) {
+        return pcnet_ioport_writew(d, addr, data);
+    } else if (addr >= 0x10 && addr < 0x20 && size == 4) {
+        return pcnet_ioport_writel(d, addr, data);
+    }
 }
 
+static const MemoryRegionOps pcnet_io_ops = {
+    .read = pcnet_ioport_read,
+    .write = pcnet_ioport_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
 static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     PCNetState *d = opaque;
@@ -202,16 +219,12 @@ static const VMStateDescription vmstate_pci_pcnet = {
 
 /* PCI interface */
 
-static CPUWriteMemoryFunc * const pcnet_mmio_write[] = {
-    &pcnet_mmio_writeb,
-    &pcnet_mmio_writew,
-    &pcnet_mmio_writel
-};
-
-static CPUReadMemoryFunc * const pcnet_mmio_read[] = {
-    &pcnet_mmio_readb,
-    &pcnet_mmio_readw,
-    &pcnet_mmio_readl
+static const MemoryRegionOps pcnet_mmio_ops = {
+    .old_mmio = {
+        .read = { pcnet_mmio_readb, pcnet_mmio_readw, pcnet_mmio_readl },
+        .write = { pcnet_mmio_writeb, pcnet_mmio_writew, pcnet_mmio_writel },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
@@ -237,7 +250,8 @@ static int pci_pcnet_uninit(PCIDevice *dev)
 {
     PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, dev);
 
-    cpu_unregister_io_memory(d->state.mmio_index);
+    memory_region_destroy(&d->state.mmio);
+    memory_region_destroy(&d->io_bar);
     qemu_del_timer(d->state.poll_timer);
     qemu_free_timer(d->state.poll_timer);
     qemu_del_vlan_client(&d->state.nic->nc);
@@ -276,14 +290,14 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
     pci_conf[PCI_MAX_LAT] = 0xff;
 
     /* Handler for memory-mapped I/O */
-    s->mmio_index =
-      cpu_register_io_memory(pcnet_mmio_read, pcnet_mmio_write, &d->state,
-                             DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&d->state.mmio, &pcnet_mmio_ops, d, "pcnet-mmio",
+                          PCNET_PNPMMIO_SIZE);
 
-    pci_register_bar(pci_dev, 0, PCNET_IOPORT_SIZE,
-                           PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map);
+    memory_region_init_io(&d->io_bar, &pcnet_io_ops, d, "pcnet-io",
+                          PCNET_IOPORT_SIZE);
+    pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->io_bar);
 
-    pci_register_bar_simple(pci_dev, 1, PCNET_PNPMMIO_SIZE, 0, s->mmio_index);
+    pci_register_bar(pci_dev, 1, 0, &s->mmio);
 
     s->irq = pci_dev->irq[0];
     s->phys_mem_read = pci_physical_memory_read;
index 534bdf9c2be32f839652f7ba7762a905c6dd267e..7e1c6853ddd2caaa27041e26473931e95d6f04f7 100644 (file)
@@ -4,6 +4,7 @@
 #define PCNET_LOOPTEST_CRC     1
 #define PCNET_LOOPTEST_NOCRC   2
 
+#include "memory.h"
 
 typedef struct PCNetState_st PCNetState;
 
@@ -17,7 +18,8 @@ struct PCNetState_st {
     uint16_t csr[128];
     uint16_t bcr[32];
     uint64_t timer;
-    int mmio_index, xmit_pos;
+    MemoryRegion mmio;
+    int xmit_pos;
     uint8_t buffer[4096];
     int tx_busy;
     qemu_irq irq;
index d08b31a266b88a6018108687b58f8d8e229dae59..28a3ee2e9c5e42662ef8943bfdb7b87b975f4536 100644 (file)
@@ -241,7 +241,10 @@ static int i440fx_initfn(PCIDevice *dev)
 static PCIBus *i440fx_common_init(const char *device_name,
                                   PCII440FXState **pi440fx_state,
                                   int *piix3_devfn,
-                                  qemu_irq *pic, ram_addr_t ram_size)
+                                  qemu_irq *pic,
+                                  MemoryRegion *address_space_mem,
+                                  MemoryRegion *address_space_io,
+                                  ram_addr_t ram_size)
 {
     DeviceState *dev;
     PCIBus *b;
@@ -251,7 +254,9 @@ static PCIBus *i440fx_common_init(const char *device_name,
 
     dev = qdev_create(NULL, "i440FX-pcihost");
     s = FROM_SYSBUS(I440FXState, sysbus_from_qdev(dev));
-    b = pci_bus_new(&s->busdev.qdev, NULL, 0);
+    s->address_space = address_space_mem;
+    b = pci_bus_new(&s->busdev.qdev, NULL, s->address_space,
+                    address_space_io, 0);
     s->bus = b;
     qdev_init_nofail(dev);
 
@@ -288,11 +293,15 @@ static PCIBus *i440fx_common_init(const char *device_name,
 }
 
 PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
-                    qemu_irq *pic, ram_addr_t ram_size)
+                    qemu_irq *pic,
+                    MemoryRegion *address_space_mem,
+                    MemoryRegion *address_space_io,
+                    ram_addr_t ram_size)
 {
     PCIBus *b;
 
-    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic, ram_size);
+    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic,
+                           address_space_mem, address_space_io, ram_size);
     return b;
 }
 
index 299473c4b5179764a35492971e33aaa72067b723..c7696b07d5079b9189b3b9416c00bb8bab8020fc 100644 (file)
@@ -24,6 +24,7 @@
 #include "ppc4xx.h"
 #include "pci.h"
 #include "pci_host.h"
+#include "exec-memory.h"
 
 #undef DEBUG
 #ifdef DEBUG
@@ -345,7 +346,10 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     controller->pci_state.bus = pci_register_bus(NULL, "pci",
                                                  ppc4xx_pci_set_irq,
                                                  ppc4xx_pci_map_irq,
-                                                 pci_irqs, 0, 4);
+                                                 pci_irqs,
+                                                 get_system_memory(),
+                                                 get_system_io(),
+                                                 0, 4);
 
     controller->pci_dev = pci_register_device(controller->pci_state.bus,
                                               "host bridge", sizeof(PCIDevice),
index 68dade7e40b4162b5006760b8caaf38e7a3b71e9..7351bb6d37867e1b16751ab49eb15fc198716306 100644 (file)
@@ -25,6 +25,8 @@
 #if !defined(__PPC_MAC_H__)
 #define __PPC_MAC_H__
 
+#include "memory.h"
+
 /* SMP is not enabled, for now */
 #define MAX_CPUS 1
 
 #define ESCC_CLOCK 3686400
 
 /* Cuda */
-void cuda_init (int *cuda_mem_index, qemu_irq irq);
+void cuda_init (MemoryRegion **cuda_mem, qemu_irq irq);
 
 /* MacIO */
-void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
-                 int dbdma_mem_index, int cuda_mem_index, void *nvram,
-                 int nb_ide, int *ide_mem_index, int escc_mem_index);
+void macio_init (PCIBus *bus, int device_id, int is_oldworld,
+                 MemoryRegion *pic_mem, MemoryRegion *dbdma_mem,
+                 MemoryRegion *cuda_mem, void *nvram,
+                 int nb_ide, MemoryRegion **ide_mem, MemoryRegion *escc_mem);
 
 /* Heathrow PIC */
-qemu_irq *heathrow_pic_init(int *pmem_index,
+qemu_irq *heathrow_pic_init(MemoryRegion **pmem,
                             int nb_cpus, qemu_irq **irqs);
 
 /* Grackle PCI */
-PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic);
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io);
 
 /* UniNorth PCI */
-PCIBus *pci_pmac_init(qemu_irq *pic);
-PCIBus *pci_pmac_u3_init(qemu_irq *pic);
+PCIBus *pci_pmac_init(qemu_irq *pic,
+                      MemoryRegion *address_space_mem,
+                      MemoryRegion *address_space_io);
+PCIBus *pci_pmac_u3_init(qemu_irq *pic,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io);
 
 /* Mac NVRAM */
 typedef struct MacIONVRAMState MacIONVRAMState;
 
-MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size,
+MacIONVRAMState *macio_nvram_init (target_phys_addr_t size,
                                    unsigned int it_shift);
-void macio_nvram_map (void *opaque, target_phys_addr_t mem_base);
+void macio_nvram_setup_bar(MacIONVRAMState *s, MemoryRegion *bar,
+                           target_phys_addr_t mem_base);
 void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len);
 uint32_t macio_nvram_read (void *opaque, uint32_t addr);
 void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val);
index 5bce709bab8642fe76922bc33616da34ed203a2e..303902290b4f9643fcc5dd3c68ed50cd0a09322e 100644 (file)
@@ -67,6 +67,7 @@
 #include "kvm_ppc.h"
 #include "hw/usb.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define MAX_IDE_BUS 2
 #define CFG_ADDR 0xf0000510
@@ -143,10 +144,9 @@ static void ppc_core99_init (ram_addr_t ram_size,
     long kernel_size, initrd_size;
     PCIBus *pci_bus;
     MacIONVRAMState *nvr;
-    int nvram_mem_index;
     int bios_size;
-    int pic_mem_index, dbdma_mem_index, cuda_mem_index, escc_mem_index;
-    int ide_mem_index[3];
+    MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem, *escc_mem;
+    MemoryRegion *ide_mem[3];
     int ppc_boot_device;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     void *fw_cfg;
@@ -314,44 +314,43 @@ static void ppc_core99_init (ram_addr_t ram_size,
             exit(1);
         }
     }
-    pic = openpic_init(NULL, &pic_mem_index, smp_cpus, openpic_irqs, NULL);
+    pic = openpic_init(NULL, &pic_mem, smp_cpus, openpic_irqs, NULL);
     if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
         /* 970 gets a U3 bus */
-        pci_bus = pci_pmac_u3_init(pic);
+        pci_bus = pci_pmac_u3_init(pic, get_system_memory(), get_system_io());
         machine_arch = ARCH_MAC99_U3;
     } else {
-        pci_bus = pci_pmac_init(pic);
+        pci_bus = pci_pmac_init(pic, get_system_memory(), get_system_io());
         machine_arch = ARCH_MAC99;
     }
     /* init basic PC hardware */
     pci_vga_init(pci_bus);
 
-    escc_mem_index = escc_init(0x80013000, pic[0x25], pic[0x24],
-                               serial_hds[0], serial_hds[1], ESCC_CLOCK, 4);
+    escc_mem = escc_init(0x80013000, pic[0x25], pic[0x24],
+                         serial_hds[0], serial_hds[1], ESCC_CLOCK, 4);
 
     for(i = 0; i < nb_nics; i++)
         pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
 
     ide_drive_get(hd, MAX_IDE_BUS);
-    dbdma = DBDMA_init(&dbdma_mem_index);
+    dbdma = DBDMA_init(&dbdma_mem);
 
     /* We only emulate 2 out of 3 IDE controllers for now */
-    ide_mem_index[0] = -1;
-    ide_mem_index[1] = pmac_ide_init(hd, pic[0x0d], dbdma, 0x16, pic[0x02]);
-    ide_mem_index[2] = pmac_ide_init(&hd[MAX_IDE_DEVS], pic[0x0e], dbdma, 0x1a, pic[0x02]);
+    ide_mem[0] = NULL;
+    ide_mem[1] = pmac_ide_init(hd, pic[0x0d], dbdma, 0x16, pic[0x02]);
+    ide_mem[2] = pmac_ide_init(&hd[MAX_IDE_DEVS], pic[0x0e], dbdma, 0x1a, pic[0x02]);
 
     /* cuda also initialize ADB */
     if (machine_arch == ARCH_MAC99_U3) {
         usb_enabled = 1;
     }
-    cuda_init(&cuda_mem_index, pic[0x19]);
+    cuda_init(&cuda_mem, pic[0x19]);
 
     adb_kbd_init(&adb_bus);
     adb_mouse_init(&adb_bus);
 
-    macio_init(pci_bus, PCI_DEVICE_ID_APPLE_UNI_N_KEYL, 0, pic_mem_index,
-               dbdma_mem_index, cuda_mem_index, NULL, 3, ide_mem_index,
-               escc_mem_index);
+    macio_init(pci_bus, PCI_DEVICE_ID_APPLE_UNI_N_KEYL, 0, pic_mem,
+               dbdma_mem, cuda_mem, NULL, 3, ide_mem, escc_mem);
 
     if (usb_enabled) {
         usb_ohci_init_pci(pci_bus, -1);
@@ -368,9 +367,9 @@ static void ppc_core99_init (ram_addr_t ram_size,
         graphic_depth = 15;
 
     /* The NewWorld NVRAM is not located in the MacIO device */
-    nvr = macio_nvram_init(&nvram_mem_index, 0x2000, 1);
+    nvr = macio_nvram_init(0x2000, 1);
     pmac_format_nvram_partition(nvr, 0x2000);
-    macio_nvram_map(nvr, 0xFFF04000);
+    macio_nvram_setup_bar(nvr, get_system_memory(), 0xFFF04000);
     /* No PCI init: the BIOS will do it */
 
     fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
index 20cd8e1a8de6ad0d74b14fcb3bb5ef61f7f5e60f..41703a7e2cefe0559819a028e5250affcbb0f93b 100644 (file)
@@ -43,6 +43,7 @@
 #include "kvm.h"
 #include "kvm_ppc.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define MAX_IDE_BUS 2
 #define CFG_ADDR 0xf0000510
@@ -81,8 +82,8 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     PCIBus *pci_bus;
     MacIONVRAMState *nvr;
     int bios_size;
-    int pic_mem_index, nvram_mem_index, dbdma_mem_index, cuda_mem_index;
-    int escc_mem_index, ide_mem_index[2];
+    MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem;
+    MemoryRegion *escc_mem, *ide_mem[2];
     uint16_t ppc_boot_device;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     void *fw_cfg;
@@ -232,11 +233,13 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
         hw_error("Only 6xx bus is supported on heathrow machine\n");
     }
-    pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs);
-    pci_bus = pci_grackle_init(0xfec00000, pic);
+    pic = heathrow_pic_init(&pic_mem, 1, heathrow_irqs);
+    pci_bus = pci_grackle_init(0xfec00000, pic,
+                               get_system_memory(),
+                               get_system_io());
     pci_vga_init(pci_bus);
 
-    escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
+    escc_mem = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
                                serial_hds[1], ESCC_CLOCK, 4);
 
     for(i = 0; i < nb_nics; i++)
@@ -246,9 +249,9 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     ide_drive_get(hd, MAX_IDE_BUS);
 
     /* First IDE channel is a MAC IDE on the MacIO bus */
-    dbdma = DBDMA_init(&dbdma_mem_index);
-    ide_mem_index[0] = -1;
-    ide_mem_index[1] = pmac_ide_init(hd, pic[0x0D], dbdma, 0x16, pic[0x02]);
+    dbdma = DBDMA_init(&dbdma_mem);
+    ide_mem[0] = NULL;
+    ide_mem[1] = pmac_ide_init(hd, pic[0x0D], dbdma, 0x16, pic[0x02]);
 
     /* Second IDE channel is a CMD646 on the PCI bus */
     hd[0] = hd[MAX_IDE_DEVS];
@@ -257,17 +260,16 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     pci_cmd646_ide_init(pci_bus, hd, 0);
 
     /* cuda also initialize ADB */
-    cuda_init(&cuda_mem_index, pic[0x12]);
+    cuda_init(&cuda_mem, pic[0x12]);
 
     adb_kbd_init(&adb_bus);
     adb_mouse_init(&adb_bus);
 
-    nvr = macio_nvram_init(&nvram_mem_index, 0x2000, 4);
+    nvr = macio_nvram_init(0x2000, 4);
     pmac_format_nvram_partition(nvr, 0x2000);
 
-    macio_init(pci_bus, PCI_DEVICE_ID_APPLE_343S1201, 1, pic_mem_index,
-               dbdma_mem_index, cuda_mem_index, nvr, 2, ide_mem_index,
-               escc_mem_index);
+    macio_init(pci_bus, PCI_DEVICE_ID_APPLE_343S1201, 1, pic_mem,
+               dbdma_mem, cuda_mem, nvr, 2, ide_mem, escc_mem);
 
     if (usb_enabled) {
         usb_ohci_init_pci(pci_bus, -1);
index 0e9cfc24cda129e16f89f7f7709b2651b1b524d0..38d8573d14d91c44ced7dad1029eeb7a1fcac89c 100644 (file)
@@ -38,6 +38,7 @@
 #include "loader.h"
 #include "mc146818rtc.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 //#define HARD_DEBUG_PPC_IO
 //#define DEBUG_PPC_IO
@@ -648,7 +649,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
         hw_error("Only 6xx bus is supported on PREP machine\n");
     }
     i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
-    pci_bus = pci_prep_init(i8259);
+    pci_bus = pci_prep_init(i8259, get_system_memory(), get_system_io());
     /* Hmm, prep has no pci-isa bridge ??? */
     isa_bus_new(NULL);
     isa_bus_irqs(i8259);
index fc11af437442dfc040f08ec9d13792d3f534058f..6a9f97975d922032ddcf9650f80c7c8ec1bf5533 100644 (file)
@@ -274,12 +274,16 @@ static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base)
                                  s->reg);
 }
 
+#include "exec-memory.h"
+
 static int e500_pcihost_initfn(SysBusDevice *dev)
 {
     PCIHostState *h;
     PPCE500PCIState *s;
     PCIBus *b;
     int i;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *address_space_io = get_system_io();
 
     h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
     s = DO_UPCAST(PPCE500PCIState, pci_state, h);
@@ -289,7 +293,8 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
     }
 
     b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq,
-                         mpc85xx_pci_map_irq, s->irq, PCI_DEVFN(0x11, 0), 4);
+                         mpc85xx_pci_map_irq, s->irq, address_space_mem,
+                         address_space_io, PCI_DEVFN(0x11, 0), 4);
     s->pci_state.bus = b;
 
     pci_create_simple(b, 0, "e500-host-bridge");
index f88b8254c2749d47036b70938173a4f88c5a748c..58619ddf746204e22a739df2398c6dc7849dbc0c 100644 (file)
@@ -110,7 +110,9 @@ static void prep_set_irq(void *opaque, int irq_num, int level)
     qemu_set_irq(pic[(irq_num & 1) ? 11 : 9] , level);
 }
 
-PCIBus *pci_prep_init(qemu_irq *pic)
+PCIBus *pci_prep_init(qemu_irq *pic,
+                      MemoryRegion *address_space_mem,
+                      MemoryRegion *address_space_io)
 {
     PREPPCIState *s;
     PCIDevice *d;
@@ -118,7 +120,10 @@ PCIBus *pci_prep_init(qemu_irq *pic)
 
     s = qemu_mallocz(sizeof(PREPPCIState));
     s->bus = pci_register_bus(NULL, "pci",
-                              prep_set_irq, prep_map_irq, pic, 0, 4);
+                              prep_set_irq, prep_map_irq, pic,
+                              address_space_mem,
+                              address_space_io,
+                              0, 4);
 
     pci_host_conf_register_ioport(0xcf8, s);
 
index cd6851288c794b7b8ad8040b210333080133fa28..b6b481a51702fe3127dcf19377a1e7a4c9bcad42 100644 (file)
@@ -2,7 +2,10 @@
 #define QEMU_PREP_PCI_H
 
 #include "qemu-common.h"
+#include "memory.h"
 
-PCIBus *pci_prep_init(qemu_irq *pic);
+PCIBus *pci_prep_init(qemu_irq *pic,
+                      MemoryRegion *address_space_mem,
+                      MemoryRegion *address_space_io);
 
 #endif
index a0fcd0609424ec468e843219cdac2c87e82aed06..6819537648f22694a9d14e1379b309706c0dd546 100644 (file)
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -36,6 +36,7 @@ static bool qdev_hot_removed = false;
 
 /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
 static BusState *main_system_bus;
+static void main_system_bus_create(void);
 
 DeviceInfo *device_info_list;
 
@@ -289,6 +290,9 @@ int qdev_init(DeviceState *dev)
                                        dev->alias_required_for_version);
     }
     dev->state = DEV_STATE_INITIALIZED;
+    if (dev->hotplugged && dev->info->reset) {
+        dev->info->reset(dev);
+    }
     return 0;
 }
 
@@ -325,8 +329,7 @@ static int qdev_reset_one(DeviceState *dev, void *opaque)
 BusState *sysbus_get_default(void)
 {
     if (!main_system_bus) {
-        main_system_bus = qbus_create(&system_bus_info, NULL,
-                                      "main-system-bus");
+        main_system_bus_create();
     }
     return main_system_bus;
 }
@@ -781,6 +784,16 @@ BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
     return bus;
 }
 
+static void main_system_bus_create(void)
+{
+    /* assign main_system_bus before qbus_create_inplace()
+     * in order to make "if (bus != main_system_bus)" work */
+    main_system_bus = qemu_mallocz(system_bus_info.size);
+    main_system_bus->qdev_allocated = 1;
+    qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
+                        "main-system-bus");
+}
+
 void qbus_free(BusState *bus)
 {
     DeviceState *dev;
index 1316066599b93cfe559957e065390c6d5b3d9f67..1b775770ce26304631ae6aa6fc55bbb157741724 100644 (file)
@@ -86,7 +86,7 @@ void qxl_render_update(PCIQXLDevice *qxl)
         }
         qemu_free_displaysurface(vga->ds);
 
-        qxl->guest_primary.data = qemu_get_ram_ptr(qxl->vga.vram_offset);
+        qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
         if (qxl->guest_primary.stride < 0) {
             /* spice surface is upside down -> need extra buffer to flip */
             qxl->guest_primary.stride = -qxl->guest_primary.stride;
@@ -124,8 +124,8 @@ void qxl_render_update(PCIQXLDevice *qxl)
     update.bottom = qxl->guest_primary.surface.height;
 
     memset(dirty, 0, sizeof(dirty));
-    qxl->ssd.worker->update_area(qxl->ssd.worker, 0, &update,
-                                 dirty, ARRAY_SIZE(dirty), 1);
+    qxl_spice_update_area(qxl, 0, &update,
+                          dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC);
 
     for (i = 0; i < ARRAY_SIZE(dirty); i++) {
         if (qemu_spice_rect_is_empty(dirty+i)) {
index a6fb7f0acb716e030b8825178e56a3fac0b26665..db7ae7a8ff6300b7d496ee7b75e4055ac6e37910 100644 (file)
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -120,11 +120,127 @@ static QXLMode qxl_modes[] = {
 static PCIQXLDevice *qxl0;
 
 static void qxl_send_events(PCIQXLDevice *d, uint32_t events);
-static void qxl_destroy_primary(PCIQXLDevice *d);
+static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async);
 static void qxl_reset_memslots(PCIQXLDevice *d);
 static void qxl_reset_surfaces(PCIQXLDevice *d);
 static void qxl_ring_set_dirty(PCIQXLDevice *qxl);
 
+void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...)
+{
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+    qxl_send_events(qxl, QXL_INTERRUPT_ERROR);
+#endif
+    if (qxl->guestdebug) {
+        va_list ap;
+        va_start(ap, msg);
+        fprintf(stderr, "qxl-%d: guest bug: ", qxl->id);
+        vfprintf(stderr, msg, ap);
+        fprintf(stderr, "\n");
+        va_end(ap);
+    }
+}
+
+
+void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
+                           struct QXLRect *area, struct QXLRect *dirty_rects,
+                           uint32_t num_dirty_rects,
+                           uint32_t clear_dirty_region,
+                           qxl_async_io async)
+{
+    if (async == QXL_SYNC) {
+        qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area,
+                        dirty_rects, num_dirty_rects, clear_dirty_region);
+    } else {
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+        spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area,
+                                    clear_dirty_region, 0);
+#else
+        abort();
+#endif
+    }
+}
+
+static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl,
+                                                    uint32_t id)
+{
+    qemu_mutex_lock(&qxl->track_lock);
+    qxl->guest_surfaces.cmds[id] = 0;
+    qxl->guest_surfaces.count--;
+    qemu_mutex_unlock(&qxl->track_lock);
+}
+
+static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
+                                           qxl_async_io async)
+{
+    if (async) {
+#if SPICE_INTERFACE_QXL_MINOR < 1
+        abort();
+#else
+        spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id,
+                                        (uint64_t)id);
+#endif
+    } else {
+        qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
+        qxl_spice_destroy_surface_wait_complete(qxl, id);
+    }
+}
+
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
+{
+    spice_qxl_flush_surfaces_async(&qxl->ssd.qxl, 0);
+}
+#endif
+
+void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
+                               uint32_t count)
+{
+    qxl->ssd.worker->loadvm_commands(qxl->ssd.worker, ext, count);
+}
+
+void qxl_spice_oom(PCIQXLDevice *qxl)
+{
+    qxl->ssd.worker->oom(qxl->ssd.worker);
+}
+
+void qxl_spice_reset_memslots(PCIQXLDevice *qxl)
+{
+    qxl->ssd.worker->reset_memslots(qxl->ssd.worker);
+}
+
+static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
+{
+    qemu_mutex_lock(&qxl->track_lock);
+    memset(&qxl->guest_surfaces.cmds, 0, sizeof(qxl->guest_surfaces.cmds));
+    qxl->guest_surfaces.count = 0;
+    qemu_mutex_unlock(&qxl->track_lock);
+}
+
+static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
+{
+    if (async) {
+#if SPICE_INTERFACE_QXL_MINOR < 1
+        abort();
+#else
+        spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl, 0);
+#endif
+    } else {
+        qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
+        qxl_spice_destroy_surfaces_complete(qxl);
+    }
+}
+
+void qxl_spice_reset_image_cache(PCIQXLDevice *qxl)
+{
+    qxl->ssd.worker->reset_image_cache(qxl->ssd.worker);
+}
+
+void qxl_spice_reset_cursor(PCIQXLDevice *qxl)
+{
+    qxl->ssd.worker->reset_cursor(qxl->ssd.worker);
+}
+
+
 static inline uint32_t msb_mask(uint32_t val)
 {
     uint32_t mask;
@@ -147,7 +263,7 @@ static ram_addr_t qxl_rom_size(void)
 
 static void init_qxl_rom(PCIQXLDevice *d)
 {
-    QXLRom *rom = qemu_get_ram_ptr(d->rom_offset);
+    QXLRom *rom = memory_region_get_ram_ptr(&d->rom_bar);
     QXLModes *modes = (QXLModes *)(rom + 1);
     uint32_t ram_header_size;
     uint32_t surface0_area_size;
@@ -223,39 +339,37 @@ static void init_qxl_ram(PCIQXLDevice *d)
 }
 
 /* can be called from spice server thread context */
-static void qxl_set_dirty(ram_addr_t addr, ram_addr_t end)
+static void qxl_set_dirty(MemoryRegion *mr, ram_addr_t addr, ram_addr_t end)
 {
     while (addr < end) {
-        cpu_physical_memory_set_dirty(addr);
+        memory_region_set_dirty(mr, addr);
         addr += TARGET_PAGE_SIZE;
     }
 }
 
 static void qxl_rom_set_dirty(PCIQXLDevice *qxl)
 {
-    ram_addr_t addr = qxl->rom_offset;
-    qxl_set_dirty(addr, addr + qxl->rom_size);
+    qxl_set_dirty(&qxl->rom_bar, 0, qxl->rom_size);
 }
 
 /* called from spice server thread context only */
 static void qxl_ram_set_dirty(PCIQXLDevice *qxl, void *ptr)
 {
-    ram_addr_t addr = qxl->vga.vram_offset;
     void *base = qxl->vga.vram_ptr;
     intptr_t offset;
 
     offset = ptr - base;
     offset &= ~(TARGET_PAGE_SIZE-1);
     assert(offset < qxl->vga.vram_size);
-    qxl_set_dirty(addr + offset, addr + offset + TARGET_PAGE_SIZE);
+    qxl_set_dirty(&qxl->vga.vram, offset, offset + TARGET_PAGE_SIZE);
 }
 
 /* can be called from spice server thread context */
 static void qxl_ring_set_dirty(PCIQXLDevice *qxl)
 {
-    ram_addr_t addr = qxl->vga.vram_offset + qxl->shadow_rom.ram_header_offset;
-    ram_addr_t end  = qxl->vga.vram_offset + qxl->vga.vram_size;
-    qxl_set_dirty(addr, end);
+    ram_addr_t addr = qxl->shadow_rom.ram_header_offset;
+    ram_addr_t end  = qxl->vga.vram_size;
+    qxl_set_dirty(&qxl->vga.vram, addr, end);
 }
 
 /*
@@ -270,6 +384,7 @@ static void qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext)
         QXLSurfaceCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
         uint32_t id = le32_to_cpu(cmd->surface_id);
         PANIC_ON(id >= NUM_SURFACES);
+        qemu_mutex_lock(&qxl->track_lock);
         if (cmd->type == QXL_SURFACE_CMD_CREATE) {
             qxl->guest_surfaces.cmds[id] = ext->cmd.data;
             qxl->guest_surfaces.count++;
@@ -280,6 +395,7 @@ static void qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext)
             qxl->guest_surfaces.cmds[id] = 0;
             qxl->guest_surfaces.count--;
         }
+        qemu_mutex_unlock(&qxl->track_lock);
         break;
     }
     case QXL_CMD_CURSOR:
@@ -351,6 +467,43 @@ static const char *qxl_mode_to_string(int mode)
     return "INVALID";
 }
 
+static const char *io_port_to_string(uint32_t io_port)
+{
+    if (io_port >= QXL_IO_RANGE_SIZE) {
+        return "out of range";
+    }
+    static const char *io_port_to_string[QXL_IO_RANGE_SIZE + 1] = {
+        [QXL_IO_NOTIFY_CMD]             = "QXL_IO_NOTIFY_CMD",
+        [QXL_IO_NOTIFY_CURSOR]          = "QXL_IO_NOTIFY_CURSOR",
+        [QXL_IO_UPDATE_AREA]            = "QXL_IO_UPDATE_AREA",
+        [QXL_IO_UPDATE_IRQ]             = "QXL_IO_UPDATE_IRQ",
+        [QXL_IO_NOTIFY_OOM]             = "QXL_IO_NOTIFY_OOM",
+        [QXL_IO_RESET]                  = "QXL_IO_RESET",
+        [QXL_IO_SET_MODE]               = "QXL_IO_SET_MODE",
+        [QXL_IO_LOG]                    = "QXL_IO_LOG",
+        [QXL_IO_MEMSLOT_ADD]            = "QXL_IO_MEMSLOT_ADD",
+        [QXL_IO_MEMSLOT_DEL]            = "QXL_IO_MEMSLOT_DEL",
+        [QXL_IO_DETACH_PRIMARY]         = "QXL_IO_DETACH_PRIMARY",
+        [QXL_IO_ATTACH_PRIMARY]         = "QXL_IO_ATTACH_PRIMARY",
+        [QXL_IO_CREATE_PRIMARY]         = "QXL_IO_CREATE_PRIMARY",
+        [QXL_IO_DESTROY_PRIMARY]        = "QXL_IO_DESTROY_PRIMARY",
+        [QXL_IO_DESTROY_SURFACE_WAIT]   = "QXL_IO_DESTROY_SURFACE_WAIT",
+        [QXL_IO_DESTROY_ALL_SURFACES]   = "QXL_IO_DESTROY_ALL_SURFACES",
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+        [QXL_IO_UPDATE_AREA_ASYNC]      = "QXL_IO_UPDATE_AREA_ASYNC",
+        [QXL_IO_MEMSLOT_ADD_ASYNC]      = "QXL_IO_MEMSLOT_ADD_ASYNC",
+        [QXL_IO_CREATE_PRIMARY_ASYNC]   = "QXL_IO_CREATE_PRIMARY_ASYNC",
+        [QXL_IO_DESTROY_PRIMARY_ASYNC]  = "QXL_IO_DESTROY_PRIMARY_ASYNC",
+        [QXL_IO_DESTROY_SURFACE_ASYNC]  = "QXL_IO_DESTROY_SURFACE_ASYNC",
+        [QXL_IO_DESTROY_ALL_SURFACES_ASYNC]
+                                        = "QXL_IO_DESTROY_ALL_SURFACES_ASYNC",
+        [QXL_IO_FLUSH_SURFACES_ASYNC]   = "QXL_IO_FLUSH_SURFACES_ASYNC",
+        [QXL_IO_FLUSH_RELEASE]          = "QXL_IO_FLUSH_RELEASE",
+#endif
+    };
+    return io_port_to_string[io_port];
+}
+
 /* called from spice server thread context only */
 static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
 {
@@ -579,6 +732,38 @@ static int interface_flush_resources(QXLInstance *sin)
     return ret;
 }
 
+static void qxl_create_guest_primary_complete(PCIQXLDevice *d);
+
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+
+/* called from spice server thread context only */
+static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
+{
+    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+    uint32_t current_async;
+
+    qemu_mutex_lock(&qxl->async_lock);
+    current_async = qxl->current_async;
+    qxl->current_async = QXL_UNDEFINED_IO;
+    qemu_mutex_unlock(&qxl->async_lock);
+
+    dprint(qxl, 2, "async_complete: %d (%ld) done\n", current_async, cookie);
+    switch (current_async) {
+    case QXL_IO_CREATE_PRIMARY_ASYNC:
+        qxl_create_guest_primary_complete(qxl);
+        break;
+    case QXL_IO_DESTROY_ALL_SURFACES_ASYNC:
+        qxl_spice_destroy_surfaces_complete(qxl);
+        break;
+    case QXL_IO_DESTROY_SURFACE_ASYNC:
+        qxl_spice_destroy_surface_wait_complete(qxl, (uint32_t)cookie);
+        break;
+    }
+    qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
+}
+
+#endif
+
 static const QXLInterface qxl_interface = {
     .base.type               = SPICE_INTERFACE_QXL,
     .base.description        = "qxl gpu",
@@ -598,6 +783,9 @@ static const QXLInterface qxl_interface = {
     .req_cursor_notification = interface_req_cursor_notification,
     .notify_update           = interface_notify_update,
     .flush_resources         = interface_flush_resources,
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+    .async_complete          = interface_async_complete,
+#endif
 };
 
 static void qxl_enter_vga_mode(PCIQXLDevice *d)
@@ -617,7 +805,7 @@ static void qxl_exit_vga_mode(PCIQXLDevice *d)
         return;
     }
     dprint(d, 1, "%s\n", __FUNCTION__);
-    qxl_destroy_primary(d);
+    qxl_destroy_primary(d, QXL_SYNC);
 }
 
 static void qxl_set_irq(PCIQXLDevice *d)
@@ -629,20 +817,6 @@ static void qxl_set_irq(PCIQXLDevice *d)
     qxl_ring_set_dirty(d);
 }
 
-static void qxl_write_config(PCIDevice *d, uint32_t address,
-                             uint32_t val, int len)
-{
-    PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, d);
-    VGACommonState *vga = &qxl->vga;
-
-    vga_dirty_log_stop(vga);
-    pci_default_write_config(d, address, val, len);
-    if (vga->map_addr && qxl->pci.io_regions[0].addr == -1) {
-        vga->map_addr = 0;
-    }
-    vga_dirty_log_start(vga);
-}
-
 static void qxl_check_state(PCIQXLDevice *d)
 {
     QXLRam *ram = d->ram;
@@ -684,8 +858,8 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
     dprint(d, 1, "%s: start%s\n", __FUNCTION__,
            loadvm ? " (loadvm)" : "");
 
-    d->ssd.worker->reset_cursor(d->ssd.worker);
-    d->ssd.worker->reset_image_cache(d->ssd.worker);
+    qxl_spice_reset_cursor(d);
+    qxl_spice_reset_image_cache(d);
     qxl_reset_surfaces(d);
     qxl_reset_memslots(d);
 
@@ -714,13 +888,14 @@ static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 
     if (qxl->mode != QXL_MODE_VGA) {
         dprint(qxl, 1, "%s\n", __FUNCTION__);
-        qxl_destroy_primary(qxl);
+        qxl_destroy_primary(qxl, QXL_SYNC);
         qxl_soft_reset(qxl);
     }
     vga_ioport_write(opaque, addr, val);
 }
 
-static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta)
+static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
+                            qxl_async_io async)
 {
     static const int regions[] = {
         QXL_RAM_RANGE_INDEX,
@@ -768,10 +943,10 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta)
 
     switch (pci_region) {
     case QXL_RAM_RANGE_INDEX:
-        virt_start = (intptr_t)qemu_get_ram_ptr(d->vga.vram_offset);
+        virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vga.vram);
         break;
     case QXL_VRAM_RANGE_INDEX:
-        virt_start = (intptr_t)qemu_get_ram_ptr(d->vram_offset);
+        virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vram_bar);
         break;
     default:
         /* should not happen */
@@ -790,7 +965,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta)
            __FUNCTION__, memslot.slot_id,
            memslot.virt_start, memslot.virt_end);
 
-    d->ssd.worker->add_memslot(d->ssd.worker, &memslot);
+    qemu_spice_add_memslot(&d->ssd, &memslot, async);
     d->guest_slots[slot_id].ptr = (void*)memslot.virt_start;
     d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start;
     d->guest_slots[slot_id].delta = delta;
@@ -800,14 +975,14 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta)
 static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id)
 {
     dprint(d, 1, "%s: slot %d\n", __FUNCTION__, slot_id);
-    d->ssd.worker->del_memslot(d->ssd.worker, MEMSLOT_GROUP_HOST, slot_id);
+    qemu_spice_del_memslot(&d->ssd, MEMSLOT_GROUP_HOST, slot_id);
     d->guest_slots[slot_id].active = 0;
 }
 
 static void qxl_reset_memslots(PCIQXLDevice *d)
 {
     dprint(d, 1, "%s:\n", __FUNCTION__);
-    d->ssd.worker->reset_memslots(d->ssd.worker);
+    qxl_spice_reset_memslots(d);
     memset(&d->guest_slots, 0, sizeof(d->guest_slots));
 }
 
@@ -815,8 +990,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
 {
     dprint(d, 1, "%s:\n", __FUNCTION__);
     d->mode = QXL_MODE_UNDEFINED;
-    d->ssd.worker->destroy_surfaces(d->ssd.worker);
-    memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds));
+    qxl_spice_destroy_surfaces(d, QXL_SYNC);
 }
 
 /* called from spice server thread context only */
@@ -841,7 +1015,14 @@ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
     }
 }
 
-static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm)
+static void qxl_create_guest_primary_complete(PCIQXLDevice *qxl)
+{
+    /* for local rendering */
+    qxl_render_resize(qxl);
+}
+
+static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
+                                     qxl_async_io async)
 {
     QXLDevSurfaceCreate surface;
     QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
@@ -869,22 +1050,26 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm)
 
     qxl->mode = QXL_MODE_NATIVE;
     qxl->cmdflags = 0;
-    qxl->ssd.worker->create_primary_surface(qxl->ssd.worker, 0, &surface);
+    qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface, async);
 
-    /* for local rendering */
-    qxl_render_resize(qxl);
+    if (async == QXL_SYNC) {
+        qxl_create_guest_primary_complete(qxl);
+    }
 }
 
-static void qxl_destroy_primary(PCIQXLDevice *d)
+/* return 1 if surface destoy was initiated (in QXL_ASYNC case) or
+ * done (in QXL_SYNC case), 0 otherwise. */
+static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async)
 {
     if (d->mode == QXL_MODE_UNDEFINED) {
-        return;
+        return 0;
     }
 
     dprint(d, 1, "%s\n", __FUNCTION__);
 
     d->mode = QXL_MODE_UNDEFINED;
-    d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0);
+    qemu_spice_destroy_primary_surface(&d->ssd, 0, async);
+    return 1;
 }
 
 static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
@@ -914,10 +1099,10 @@ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
     }
 
     d->guest_slots[0].slot = slot;
-    qxl_add_memslot(d, 0, devmem);
+    qxl_add_memslot(d, 0, devmem, QXL_SYNC);
 
     d->guest_primary.surface = surface;
-    qxl_create_guest_primary(d, 0);
+    qxl_create_guest_primary(d, 0, QXL_SYNC);
 
     d->mode = QXL_MODE_COMPAT;
     d->cmdflags = QXL_COMMAND_FLAG_COMPAT;
@@ -931,10 +1116,15 @@ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
     qxl_rom_set_dirty(d);
 }
 
-static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
+static void ioport_write(void *opaque, target_phys_addr_t addr,
+                         uint64_t val, unsigned size)
 {
     PCIQXLDevice *d = opaque;
-    uint32_t io_port = addr - d->io_base;
+    uint32_t io_port = addr;
+    qxl_async_io async = QXL_SYNC;
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+    uint32_t orig_io_port = io_port;
+#endif
 
     switch (io_port) {
     case QXL_IO_RESET:
@@ -944,27 +1134,81 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
     case QXL_IO_CREATE_PRIMARY:
     case QXL_IO_UPDATE_IRQ:
     case QXL_IO_LOG:
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+    case QXL_IO_MEMSLOT_ADD_ASYNC:
+    case QXL_IO_CREATE_PRIMARY_ASYNC:
+#endif
         break;
     default:
-        if (d->mode == QXL_MODE_NATIVE || d->mode == QXL_MODE_COMPAT)
+        if (d->mode != QXL_MODE_VGA) {
             break;
-        dprint(d, 1, "%s: unexpected port 0x%x in vga mode\n", __FUNCTION__, io_port);
+        }
+        dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n",
+            __func__, io_port, io_port_to_string(io_port));
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+        /* be nice to buggy guest drivers */
+        if (io_port >= QXL_IO_UPDATE_AREA_ASYNC &&
+            io_port <= QXL_IO_DESTROY_ALL_SURFACES_ASYNC) {
+            qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
+        }
+#endif
         return;
     }
 
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+    /* we change the io_port to avoid ifdeffery in the main switch */
+    orig_io_port = io_port;
+    switch (io_port) {
+    case QXL_IO_UPDATE_AREA_ASYNC:
+        io_port = QXL_IO_UPDATE_AREA;
+        goto async_common;
+    case QXL_IO_MEMSLOT_ADD_ASYNC:
+        io_port = QXL_IO_MEMSLOT_ADD;
+        goto async_common;
+    case QXL_IO_CREATE_PRIMARY_ASYNC:
+        io_port = QXL_IO_CREATE_PRIMARY;
+        goto async_common;
+    case QXL_IO_DESTROY_PRIMARY_ASYNC:
+        io_port = QXL_IO_DESTROY_PRIMARY;
+        goto async_common;
+    case QXL_IO_DESTROY_SURFACE_ASYNC:
+        io_port = QXL_IO_DESTROY_SURFACE_WAIT;
+        goto async_common;
+    case QXL_IO_DESTROY_ALL_SURFACES_ASYNC:
+        io_port = QXL_IO_DESTROY_ALL_SURFACES;
+        goto async_common;
+    case QXL_IO_FLUSH_SURFACES_ASYNC:
+async_common:
+        async = QXL_ASYNC;
+        qemu_mutex_lock(&d->async_lock);
+        if (d->current_async != QXL_UNDEFINED_IO) {
+            qxl_guest_bug(d, "%d async started before last (%d) complete",
+                io_port, d->current_async);
+            qemu_mutex_unlock(&d->async_lock);
+            return;
+        }
+        d->current_async = orig_io_port;
+        qemu_mutex_unlock(&d->async_lock);
+        dprint(d, 2, "start async %d (%d)\n", io_port, val);
+        break;
+    default:
+        break;
+    }
+#endif
+
     switch (io_port) {
     case QXL_IO_UPDATE_AREA:
     {
         QXLRect update = d->ram->update_area;
-        d->ssd.worker->update_area(d->ssd.worker, d->ram->update_surface,
-                                   &update, NULL, 0, 0);
+        qxl_spice_update_area(d, d->ram->update_surface,
+                              &update, NULL, 0, 0, async);
         break;
     }
     case QXL_IO_NOTIFY_CMD:
-        d->ssd.worker->wakeup(d->ssd.worker);
+        qemu_spice_wakeup(&d->ssd);
         break;
     case QXL_IO_NOTIFY_CURSOR:
-        d->ssd.worker->wakeup(d->ssd.worker);
+        qemu_spice_wakeup(&d->ssd);
         break;
     case QXL_IO_UPDATE_IRQ:
         qxl_set_irq(d);
@@ -978,11 +1222,11 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
             break;
         }
         d->oom_running = 1;
-        d->ssd.worker->oom(d->ssd.worker);
+        qxl_spice_oom(d);
         d->oom_running = 0;
         break;
     case QXL_IO_SET_MODE:
-        dprint(d, 1, "QXL_SET_MODE %d\n", val);
+        dprint(d, 1, "QXL_SET_MODE %d\n", (int)val);
         qxl_set_mode(d, val, 0);
         break;
     case QXL_IO_LOG:
@@ -996,38 +1240,101 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
         qxl_hard_reset(d, 0);
         break;
     case QXL_IO_MEMSLOT_ADD:
-        PANIC_ON(val >= NUM_MEMSLOTS);
-        PANIC_ON(d->guest_slots[val].active);
+        if (val >= NUM_MEMSLOTS) {
+            qxl_guest_bug(d, "QXL_IO_MEMSLOT_ADD: val out of range");
+            break;
+        }
+        if (d->guest_slots[val].active) {
+            qxl_guest_bug(d, "QXL_IO_MEMSLOT_ADD: memory slot already active");
+            break;
+        }
         d->guest_slots[val].slot = d->ram->mem_slot;
-        qxl_add_memslot(d, val, 0);
+        qxl_add_memslot(d, val, 0, async);
         break;
     case QXL_IO_MEMSLOT_DEL:
+        if (val >= NUM_MEMSLOTS) {
+            qxl_guest_bug(d, "QXL_IO_MEMSLOT_DEL: val out of range");
+            break;
+        }
         qxl_del_memslot(d, val);
         break;
     case QXL_IO_CREATE_PRIMARY:
-        PANIC_ON(val != 0);
-        dprint(d, 1, "QXL_IO_CREATE_PRIMARY\n");
+        if (val != 0) {
+            qxl_guest_bug(d, "QXL_IO_CREATE_PRIMARY (async=%d): val != 0",
+                          async);
+            goto cancel_async;
+        }
+        dprint(d, 1, "QXL_IO_CREATE_PRIMARY async=%d\n", async);
         d->guest_primary.surface = d->ram->create_surface;
-        qxl_create_guest_primary(d, 0);
+        qxl_create_guest_primary(d, 0, async);
         break;
     case QXL_IO_DESTROY_PRIMARY:
-        PANIC_ON(val != 0);
-        dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (%s)\n", qxl_mode_to_string(d->mode));
-        qxl_destroy_primary(d);
+        if (val != 0) {
+            qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY (async=%d): val != 0",
+                          async);
+            goto cancel_async;
+        }
+        dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (async=%d) (%s)\n", async,
+               qxl_mode_to_string(d->mode));
+        if (!qxl_destroy_primary(d, async)) {
+            dprint(d, 1, "QXL_IO_DESTROY_PRIMARY_ASYNC in %s, ignored\n",
+                    qxl_mode_to_string(d->mode));
+            goto cancel_async;
+        }
         break;
     case QXL_IO_DESTROY_SURFACE_WAIT:
-        d->ssd.worker->destroy_surface_wait(d->ssd.worker, val);
+        if (val >= NUM_SURFACES) {
+            qxl_guest_bug(d, "QXL_IO_DESTROY_SURFACE (async=%d):"
+                             "%d >= NUM_SURFACES", async, val);
+            goto cancel_async;
+        }
+        qxl_spice_destroy_surface_wait(d, val, async);
         break;
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+    case QXL_IO_FLUSH_RELEASE: {
+        QXLReleaseRing *ring = &d->ram->release_ring;
+        if (ring->prod - ring->cons + 1 == ring->num_items) {
+            fprintf(stderr,
+                "ERROR: no flush, full release ring [p%d,%dc]\n",
+                ring->prod, ring->cons);
+        }
+        qxl_push_free_res(d, 1 /* flush */);
+        dprint(d, 1, "QXL_IO_FLUSH_RELEASE exit (%s, s#=%d, res#=%d,%p)\n",
+            qxl_mode_to_string(d->mode), d->guest_surfaces.count,
+            d->num_free_res, d->last_release);
+        break;
+    }
+    case QXL_IO_FLUSH_SURFACES_ASYNC:
+        dprint(d, 1, "QXL_IO_FLUSH_SURFACES_ASYNC (%d) (%s, s#=%d, res#=%d)\n",
+               val, qxl_mode_to_string(d->mode), d->guest_surfaces.count,
+               d->num_free_res);
+        qxl_spice_flush_surfaces_async(d);
+        break;
+#endif
     case QXL_IO_DESTROY_ALL_SURFACES:
-        d->ssd.worker->destroy_surfaces(d->ssd.worker);
+        d->mode = QXL_MODE_UNDEFINED;
+        qxl_spice_destroy_surfaces(d, async);
         break;
     default:
         fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port);
         abort();
     }
+    return;
+cancel_async:
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+    if (async) {
+        qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
+        qemu_mutex_lock(&d->async_lock);
+        d->current_async = QXL_UNDEFINED_IO;
+        qemu_mutex_unlock(&d->async_lock);
+    }
+#else
+    return;
+#endif
 }
 
-static uint32_t ioport_read(void *opaque, uint32_t addr)
+static uint64_t ioport_read(void *opaque, target_phys_addr_t addr,
+                            unsigned size)
 {
     PCIQXLDevice *d = opaque;
 
@@ -1035,42 +1342,14 @@ static uint32_t ioport_read(void *opaque, uint32_t addr)
     return 0xff;
 }
 
-static void qxl_map(PCIDevice *pci, int region_num,
-                    pcibus_t addr, pcibus_t size, int type)
-{
-    static const char *names[] = {
-        [ QXL_IO_RANGE_INDEX ]   = "ioports",
-        [ QXL_RAM_RANGE_INDEX ]  = "devram",
-        [ QXL_ROM_RANGE_INDEX ]  = "rom",
-        [ QXL_VRAM_RANGE_INDEX ] = "vram",
-    };
-    PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, pci);
-
-    dprint(qxl, 1, "%s: bar %d [%s] addr 0x%lx size 0x%lx\n", __FUNCTION__,
-            region_num, names[region_num], addr, size);
-
-    switch (region_num) {
-    case QXL_IO_RANGE_INDEX:
-        register_ioport_write(addr, size, 1, ioport_write, pci);
-        register_ioport_read(addr, size, 1, ioport_read, pci);
-        qxl->io_base = addr;
-        break;
-    case QXL_RAM_RANGE_INDEX:
-        cpu_register_physical_memory(addr, size, qxl->vga.vram_offset | IO_MEM_RAM);
-        qxl->vga.map_addr = addr;
-        qxl->vga.map_end = addr + size;
-        if (qxl->id == 0) {
-            vga_dirty_log_start(&qxl->vga);
-        }
-        break;
-    case QXL_ROM_RANGE_INDEX:
-        cpu_register_physical_memory(addr, size, qxl->rom_offset | IO_MEM_ROM);
-        break;
-    case QXL_VRAM_RANGE_INDEX:
-        cpu_register_physical_memory(addr, size, qxl->vram_offset | IO_MEM_RAM);
-        break;
-    }
-}
+static const MemoryRegionOps qxl_io_ops = {
+    .read = ioport_read,
+    .write = ioport_write,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
 
 static void pipe_read(void *opaque)
 {
@@ -1190,10 +1469,9 @@ static void qxl_vm_change_state_handler(void *opaque, int running, int reason)
          * to make sure they are saved */
         /* FIXME #1: should go out during "live" stage */
         /* FIXME #2: we only need to save the areas which are actually used */
-        ram_addr_t vram_addr = qxl->vram_offset;
-        ram_addr_t surface0_addr = qxl->vga.vram_offset + qxl->shadow_rom.draw_area_offset;
-        qxl_set_dirty(vram_addr, vram_addr + qxl->vram_size);
-        qxl_set_dirty(surface0_addr, surface0_addr + qxl->shadow_rom.surface0_area_size);
+        qxl_set_dirty(&qxl->vram_bar, 0, qxl->vram_size);
+        qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
+                      qxl->shadow_rom.surface0_area_size);
     }
 }
 
@@ -1236,22 +1514,31 @@ static int qxl_init_common(PCIQXLDevice *qxl)
     qxl->generation = 1;
     qxl->num_memslots = NUM_MEMSLOTS;
     qxl->num_surfaces = NUM_SURFACES;
+    qemu_mutex_init(&qxl->track_lock);
+    qemu_mutex_init(&qxl->async_lock);
+    qxl->current_async = QXL_UNDEFINED_IO;
 
     switch (qxl->revision) {
     case 1: /* spice 0.4 -- qxl-1 */
         pci_device_rev = QXL_REVISION_STABLE_V04;
         break;
     case 2: /* spice 0.6 -- qxl-2 */
-    default:
         pci_device_rev = QXL_REVISION_STABLE_V06;
         break;
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+    case 3: /* qxl-3 */
+#endif
+    default:
+        pci_device_rev = QXL_DEFAULT_REVISION;
+        break;
     }
 
     pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev);
     pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
 
     qxl->rom_size = qxl_rom_size();
-    qxl->rom_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vrom", qxl->rom_size);
+    memory_region_init_ram(&qxl->rom_bar, &qxl->pci.qdev, "qxl.vrom",
+                           qxl->rom_size);
     init_qxl_rom(qxl);
     init_qxl_ram(qxl);
 
@@ -1262,26 +1549,32 @@ static int qxl_init_common(PCIQXLDevice *qxl)
         qxl->vram_size = 4096;
     }
     qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
-    qxl->vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vram", qxl->vram_size);
+    memory_region_init_ram(&qxl->vram_bar, &qxl->pci.qdev, "qxl.vram",
+                           qxl->vram_size);
 
     io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1);
     if (qxl->revision == 1) {
         io_size = 8;
     }
 
+    memory_region_init_io(&qxl->io_bar, &qxl_io_ops, qxl,
+                          "qxl-ioports", io_size);
+    if (qxl->id == 0) {
+        vga_dirty_log_start(&qxl->vga);
+    }
+
+
     pci_register_bar(&qxl->pci, QXL_IO_RANGE_INDEX,
-                     io_size, PCI_BASE_ADDRESS_SPACE_IO, qxl_map);
+                     PCI_BASE_ADDRESS_SPACE_IO, &qxl->io_bar);
 
     pci_register_bar(&qxl->pci, QXL_ROM_RANGE_INDEX,
-                     qxl->rom_size, PCI_BASE_ADDRESS_SPACE_MEMORY,
-                     qxl_map);
+                     PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->rom_bar);
 
     pci_register_bar(&qxl->pci, QXL_RAM_RANGE_INDEX,
-                     qxl->vga.vram_size, PCI_BASE_ADDRESS_SPACE_MEMORY,
-                     qxl_map);
+                     PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vga.vram);
 
-    pci_register_bar(&qxl->pci, QXL_VRAM_RANGE_INDEX, qxl->vram_size,
-                     PCI_BASE_ADDRESS_SPACE_MEMORY, qxl_map);
+    pci_register_bar(&qxl->pci, QXL_VRAM_RANGE_INDEX,
+                     PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vram_bar);
 
     qxl->ssd.qxl.base.sif = &qxl_interface.base;
     qxl->ssd.qxl.id = qxl->id;
@@ -1315,12 +1608,7 @@ static int qxl_init_primary(PCIDevice *dev)
 
     vga->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
                                    qxl_hw_screen_dump, qxl_hw_text_update, qxl);
-    qxl->ssd.ds = vga->ds;
-    qemu_mutex_init(&qxl->ssd.lock);
-    qxl->ssd.mouse_x = -1;
-    qxl->ssd.mouse_y = -1;
-    qxl->ssd.bufsize = (16 * 1024 * 1024);
-    qxl->ssd.buf = qemu_malloc(qxl->ssd.bufsize);
+    qemu_spice_display_init_common(&qxl->ssd, vga->ds);
 
     qxl0 = qxl;
     register_displaychangelistener(vga->ds, &display_listener);
@@ -1340,9 +1628,9 @@ static int qxl_init_secondary(PCIDevice *dev)
         ram_size = 16 * 1024 * 1024;
     }
     qxl->vga.vram_size = ram_size;
-    qxl->vga.vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vgavram",
-                                          qxl->vga.vram_size);
-    qxl->vga.vram_ptr = qemu_get_ram_ptr(qxl->vga.vram_offset);
+    memory_region_init_ram(&qxl->vga.vram, &qxl->pci.qdev, "qxl.vgavram",
+                           qxl->vga.vram_size);
+    qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
 
     return qxl_init_common(qxl);
 }
@@ -1405,9 +1693,9 @@ static int qxl_post_load(void *opaque, int version)
             if (!d->guest_slots[i].active) {
                 continue;
             }
-            qxl_add_memslot(d, i, 0);
+            qxl_add_memslot(d, i, 0, QXL_SYNC);
         }
-        qxl_create_guest_primary(d, 1);
+        qxl_create_guest_primary(d, 1, QXL_SYNC);
 
         /* replay surface-create and cursor-set commands */
         cmds = qemu_mallocz(sizeof(QXLCommandExt) * (NUM_SURFACES + 1));
@@ -1424,7 +1712,7 @@ static int qxl_post_load(void *opaque, int version)
         cmds[out].cmd.type = QXL_CMD_CURSOR;
         cmds[out].group_id = MEMSLOT_GROUP_GUEST;
         out++;
-        d->ssd.worker->loadvm_commands(d->ssd.worker, cmds, out);
+        qxl_spice_loadvm_commands(d, cmds, out);
         qemu_free(cmds);
 
         break;
@@ -1505,15 +1793,17 @@ static PCIDeviceInfo qxl_info_primary = {
     .qdev.vmsd    = &qxl_vmstate,
     .no_hotplug   = 1,
     .init         = qxl_init_primary,
-    .config_write = qxl_write_config,
     .romfile      = "vgabios-qxl.bin",
     .vendor_id    = REDHAT_PCI_VENDOR_ID,
     .device_id    = QXL_DEVICE_ID_STABLE,
     .class_id     = PCI_CLASS_DISPLAY_VGA,
     .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),
-        DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024),
-        DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 2),
+        DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size,
+                           64 * 1024 * 1024),
+        DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size,
+                           64 * 1024 * 1024),
+        DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision,
+                           QXL_DEFAULT_REVISION),
         DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
         DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
         DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
@@ -1532,9 +1822,12 @@ static PCIDeviceInfo qxl_info_secondary = {
     .device_id    = QXL_DEVICE_ID_STABLE,
     .class_id     = PCI_CLASS_DISPLAY_OTHER,
     .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),
-        DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024),
-        DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 2),
+        DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size,
+                           64 * 1024 * 1024),
+        DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size,
+                           64 * 1024 * 1024),
+        DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision,
+                           QXL_DEFAULT_REVISION),
         DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
         DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
         DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
index f6c450d32d6c4f2c0983301a740dbd913deb00aa..868db813f91a3719c80122fab1501c655a1c7b57 100644 (file)
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -15,6 +15,8 @@ enum qxl_mode {
     QXL_MODE_NATIVE,
 };
 
+#define QXL_UNDEFINED_IO UINT32_MAX
+
 typedef struct PCIQXLDevice {
     PCIDevice          pci;
     SimpleSpiceDisplay ssd;
@@ -30,6 +32,9 @@ typedef struct PCIQXLDevice {
     int32_t            num_memslots;
     int32_t            num_surfaces;
 
+    uint32_t           current_async;
+    QemuMutex          async_lock;
+
     struct guest_slots {
         QXLMemSlot     slot;
         void           *ptr;
@@ -55,6 +60,8 @@ typedef struct PCIQXLDevice {
     } guest_surfaces;
     QXLPHYSICAL        guest_cursor;
 
+    QemuMutex          track_lock;
+
     /* thread signaling */
     pthread_t          main;
     int                pipe[2];
@@ -72,19 +79,19 @@ typedef struct PCIQXLDevice {
     QXLRom             *rom;
     QXLModes           *modes;
     uint32_t           rom_size;
-    uint64_t           rom_offset;
+    MemoryRegion       rom_bar;
 
     /* vram pci bar */
     uint32_t           vram_size;
-    uint64_t           vram_offset;
+    MemoryRegion       vram_bar;
 
     /* io bar */
-    uint32_t           io_base;
+    MemoryRegion       io_bar;
 } PCIQXLDevice;
 
 #define PANIC_ON(x) if ((x)) {                         \
     printf("%s: PANIC %s failed\n", __FUNCTION__, #x); \
-    exit(-1);                                          \
+    abort();                                           \
 }
 
 #define dprint(_qxl, _level, _fmt, ...)                                 \
@@ -95,8 +102,27 @@ typedef struct PCIQXLDevice {
         }                                                               \
     } while (0)
 
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V10
+#else
+#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V06
+#endif
+
 /* qxl.c */
 void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
+void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...);
+
+void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
+                           struct QXLRect *area, struct QXLRect *dirty_rects,
+                           uint32_t num_dirty_rects,
+                           uint32_t clear_dirty_region,
+                           qxl_async_io async);
+void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
+                               uint32_t count);
+void qxl_spice_oom(PCIQXLDevice *qxl);
+void qxl_spice_reset_memslots(PCIQXLDevice *qxl);
+void qxl_spice_reset_image_cache(PCIQXLDevice *qxl);
+void qxl_spice_reset_cursor(PCIQXLDevice *qxl);
 
 /* qxl-logger.c */
 void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id);
@@ -106,3 +132,9 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
 void qxl_render_resize(PCIQXLDevice *qxl);
 void qxl_render_update(PCIQXLDevice *qxl);
 void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+void qxl_spice_update_area_async(PCIQXLDevice *qxl, uint32_t surface_id,
+                                 struct QXLRect *area,
+                                 uint32_t clear_dirty_region,
+                                 int is_vga);
+#endif
index 5214b8cb7c2feaaf891f533050e027caab315a79..c6cafc251316d83656860bcff89f5416f2a1942a 100644 (file)
@@ -474,7 +474,6 @@ typedef struct RTL8139State {
 
     NICState *nic;
     NICConf conf;
-    int rtl8139_mmio_io_addr;
 
     /* C ring mode */
     uint32_t   currTxDesc;
@@ -506,6 +505,9 @@ typedef struct RTL8139State {
     QEMUTimer *timer;
     int64_t TimerExpire;
 
+    MemoryRegion bar_io;
+    MemoryRegion bar_mem;
+
     /* Support migration to/from old versions */
     int rtl8139_mmio_io_addr_dummy;
 } RTL8139State;
@@ -3283,7 +3285,7 @@ static void rtl8139_pre_save(void *opaque)
     rtl8139_set_next_tctr_time(s, current_time);
     s->TCTR = muldiv64(current_time - s->TCTR_base, PCI_FREQUENCY,
                        get_ticks_per_sec());
-    s->rtl8139_mmio_io_addr_dummy = s->rtl8139_mmio_io_addr;
+    s->rtl8139_mmio_io_addr_dummy = 0;
 }
 
 static const VMStateDescription vmstate_rtl8139 = {
@@ -3379,31 +3381,35 @@ static const VMStateDescription vmstate_rtl8139 = {
 /***********************************************************/
 /* PCI RTL8139 definitions */
 
-static void rtl8139_ioport_map(PCIDevice *pci_dev, int region_num,
-                       pcibus_t addr, pcibus_t size, int type)
-{
-    RTL8139State *s = DO_UPCAST(RTL8139State, dev, pci_dev);
-
-    register_ioport_write(addr, 0x100, 1, rtl8139_ioport_writeb, s);
-    register_ioport_read( addr, 0x100, 1, rtl8139_ioport_readb,  s);
-
-    register_ioport_write(addr, 0x100, 2, rtl8139_ioport_writew, s);
-    register_ioport_read( addr, 0x100, 2, rtl8139_ioport_readw,  s);
-
-    register_ioport_write(addr, 0x100, 4, rtl8139_ioport_writel, s);
-    register_ioport_read( addr, 0x100, 4, rtl8139_ioport_readl,  s);
-}
+static const MemoryRegionPortio rtl8139_portio[] = {
+    { 0, 0x100, 1, .read = rtl8139_ioport_readb, },
+    { 0, 0x100, 1, .write = rtl8139_ioport_writeb, },
+    { 0, 0x100, 2, .read = rtl8139_ioport_readw, },
+    { 0, 0x100, 2, .write = rtl8139_ioport_writew, },
+    { 0, 0x100, 4, .read = rtl8139_ioport_readl, },
+    { 0, 0x100, 4, .write = rtl8139_ioport_writel, },
+    PORTIO_END_OF_LIST()
+};
 
-static CPUReadMemoryFunc * const rtl8139_mmio_read[3] = {
-    rtl8139_mmio_readb,
-    rtl8139_mmio_readw,
-    rtl8139_mmio_readl,
+static const MemoryRegionOps rtl8139_io_ops = {
+    .old_portio = rtl8139_portio,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const rtl8139_mmio_write[3] = {
-    rtl8139_mmio_writeb,
-    rtl8139_mmio_writew,
-    rtl8139_mmio_writel,
+static const MemoryRegionOps rtl8139_mmio_ops = {
+    .old_mmio = {
+        .read = {
+            rtl8139_mmio_readb,
+            rtl8139_mmio_readw,
+            rtl8139_mmio_readl,
+        },
+        .write = {
+            rtl8139_mmio_writeb,
+            rtl8139_mmio_writew,
+            rtl8139_mmio_writel,
+        },
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void rtl8139_timer(void *opaque)
@@ -3432,7 +3438,8 @@ static int pci_rtl8139_uninit(PCIDevice *dev)
 {
     RTL8139State *s = DO_UPCAST(RTL8139State, dev, dev);
 
-    cpu_unregister_io_memory(s->rtl8139_mmio_io_addr);
+    memory_region_destroy(&s->bar_io);
+    memory_region_destroy(&s->bar_mem);
     if (s->cplus_txbuffer) {
         qemu_free(s->cplus_txbuffer);
         s->cplus_txbuffer = NULL;
@@ -3462,15 +3469,10 @@ static int pci_rtl8139_init(PCIDevice *dev)
      * list bit in status register, and offset 0xdc seems unused. */
     pci_conf[PCI_CAPABILITY_LIST] = 0xdc;
 
-    /* I/O handler for memory-mapped I/O */
-    s->rtl8139_mmio_io_addr =
-        cpu_register_io_memory(rtl8139_mmio_read, rtl8139_mmio_write, s,
-                               DEVICE_LITTLE_ENDIAN);
-
-    pci_register_bar(&s->dev, 0, 0x100,
-                           PCI_BASE_ADDRESS_SPACE_IO,  rtl8139_ioport_map);
-
-    pci_register_bar_simple(&s->dev, 1, 0x100, 0, s->rtl8139_mmio_io_addr);
+    memory_region_init_io(&s->bar_io, &rtl8139_io_ops, s, "rtl8139", 0x100);
+    memory_region_init_io(&s->bar_mem, &rtl8139_mmio_ops, s, "rtl8139", 0x100);
+    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->bar_io);
+    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar_mem);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
 
index 8b1a4122106e30d9a1e43bb19361ef660dd7e3c7..0b0344c1fd2ce34e0b5692dc72bf73ab679f6a14 100644 (file)
@@ -223,7 +223,7 @@ static int scsi_req_length(SCSIRequest *req, uint8_t *cmd)
 
     switch(cmd[0]) {
     case TEST_UNIT_READY:
-    case REZERO_UNIT:
+    case REWIND:
     case START_STOP:
     case SEEK_6:
     case WRITE_FILEMARKS:
@@ -232,24 +232,24 @@ static int scsi_req_length(SCSIRequest *req, uint8_t *cmd)
     case RELEASE:
     case ERASE:
     case ALLOW_MEDIUM_REMOVAL:
-    case VERIFY:
+    case VERIFY_10:
     case SEEK_10:
     case SYNCHRONIZE_CACHE:
     case LOCK_UNLOCK_CACHE:
     case LOAD_UNLOAD:
     case SET_CD_SPEED:
     case SET_LIMITS:
-    case WRITE_LONG:
+    case WRITE_LONG_10:
     case MOVE_MEDIUM:
     case UPDATE_BLOCK:
         req->cmd.xfer = 0;
         break;
     case MODE_SENSE:
         break;
-    case WRITE_SAME:
+    case WRITE_SAME_10:
         req->cmd.xfer = 1;
         break;
-    case READ_CAPACITY:
+    case READ_CAPACITY_10:
         req->cmd.xfer = 8;
         break;
     case READ_BLOCK_LIMITS:
@@ -265,7 +265,7 @@ static int scsi_req_length(SCSIRequest *req, uint8_t *cmd)
         req->cmd.xfer *= 8;
         break;
     case WRITE_10:
-    case WRITE_VERIFY:
+    case WRITE_VERIFY_10:
     case WRITE_6:
     case WRITE_12:
     case WRITE_VERIFY_12:
@@ -325,7 +325,7 @@ static void scsi_req_xfer_mode(SCSIRequest *req)
     switch (req->cmd.buf[0]) {
     case WRITE_6:
     case WRITE_10:
-    case WRITE_VERIFY:
+    case WRITE_VERIFY_10:
     case WRITE_12:
     case WRITE_VERIFY_12:
     case WRITE_16:
@@ -345,15 +345,13 @@ static void scsi_req_xfer_mode(SCSIRequest *req)
     case SEARCH_HIGH:
     case SEARCH_LOW:
     case UPDATE_BLOCK:
-    case WRITE_LONG:
-    case WRITE_SAME:
+    case WRITE_LONG_10:
+    case WRITE_SAME_10:
     case SEARCH_HIGH_12:
     case SEARCH_EQUAL_12:
     case SEARCH_LOW_12:
-    case SET_WINDOW:
     case MEDIUM_SCAN:
     case SEND_VOLUME_TAG:
-    case WRITE_LONG_2:
     case PERSISTENT_RESERVE_OUT:
     case MAINTENANCE_OUT:
         req->cmd.mode = SCSI_XFER_TO_DEV;
@@ -517,8 +515,7 @@ static const char *scsi_command_name(uint8_t cmd)
 {
     static const char *names[] = {
         [ TEST_UNIT_READY          ] = "TEST_UNIT_READY",
-        [ REZERO_UNIT              ] = "REZERO_UNIT",
-        /* REWIND and REZERO_UNIT use the same operation code */
+        [ REWIND                   ] = "REWIND",
         [ REQUEST_SENSE            ] = "REQUEST_SENSE",
         [ FORMAT_UNIT              ] = "FORMAT_UNIT",
         [ READ_BLOCK_LIMITS        ] = "READ_BLOCK_LIMITS",
@@ -543,14 +540,12 @@ static const char *scsi_command_name(uint8_t cmd)
         [ RECEIVE_DIAGNOSTIC       ] = "RECEIVE_DIAGNOSTIC",
         [ SEND_DIAGNOSTIC          ] = "SEND_DIAGNOSTIC",
         [ ALLOW_MEDIUM_REMOVAL     ] = "ALLOW_MEDIUM_REMOVAL",
-
-        [ SET_WINDOW               ] = "SET_WINDOW",
-        [ READ_CAPACITY            ] = "READ_CAPACITY",
+        [ READ_CAPACITY_10         ] = "READ_CAPACITY_10",
         [ READ_10                  ] = "READ_10",
         [ WRITE_10                 ] = "WRITE_10",
         [ SEEK_10                  ] = "SEEK_10",
-        [ WRITE_VERIFY             ] = "WRITE_VERIFY",
-        [ VERIFY                   ] = "VERIFY",
+        [ WRITE_VERIFY_10          ] = "WRITE_VERIFY_10",
+        [ VERIFY_10                ] = "VERIFY_10",
         [ SEARCH_HIGH              ] = "SEARCH_HIGH",
         [ SEARCH_EQUAL             ] = "SEARCH_EQUAL",
         [ SEARCH_LOW               ] = "SEARCH_LOW",
@@ -566,11 +561,14 @@ static const char *scsi_command_name(uint8_t cmd)
         [ WRITE_BUFFER             ] = "WRITE_BUFFER",
         [ READ_BUFFER              ] = "READ_BUFFER",
         [ UPDATE_BLOCK             ] = "UPDATE_BLOCK",
-        [ READ_LONG                ] = "READ_LONG",
-        [ WRITE_LONG               ] = "WRITE_LONG",
+        [ READ_LONG_10             ] = "READ_LONG_10",
+        [ WRITE_LONG_10            ] = "WRITE_LONG_10",
         [ CHANGE_DEFINITION        ] = "CHANGE_DEFINITION",
-        [ WRITE_SAME               ] = "WRITE_SAME",
+        [ WRITE_SAME_10            ] = "WRITE_SAME_10",
+        [ UNMAP                    ] = "UNMAP",
         [ READ_TOC                 ] = "READ_TOC",
+        [ REPORT_DENSITY_SUPPORT   ] = "REPORT_DENSITY_SUPPORT",
+        [ GET_CONFIGURATION        ] = "GET_CONFIGURATION",
         [ LOG_SELECT               ] = "LOG_SELECT",
         [ LOG_SENSE                ] = "LOG_SENSE",
         [ MODE_SELECT_10           ] = "MODE_SELECT_10",
@@ -579,27 +577,39 @@ static const char *scsi_command_name(uint8_t cmd)
         [ MODE_SENSE_10            ] = "MODE_SENSE_10",
         [ PERSISTENT_RESERVE_IN    ] = "PERSISTENT_RESERVE_IN",
         [ PERSISTENT_RESERVE_OUT   ] = "PERSISTENT_RESERVE_OUT",
+        [ WRITE_FILEMARKS_16       ] = "WRITE_FILEMARKS_16",
+        [ EXTENDED_COPY            ] = "EXTENDED_COPY",
+        [ ATA_PASSTHROUGH          ] = "ATA_PASSTHROUGH",
+        [ ACCESS_CONTROL_IN        ] = "ACCESS_CONTROL_IN",
+        [ ACCESS_CONTROL_OUT       ] = "ACCESS_CONTROL_OUT",
+        [ READ_16                  ] = "READ_16",
+        [ COMPARE_AND_WRITE        ] = "COMPARE_AND_WRITE",
+        [ WRITE_16                 ] = "WRITE_16",
+        [ WRITE_VERIFY_16          ] = "WRITE_VERIFY_16",
+        [ VERIFY_16                ] = "VERIFY_16",
+        [ SYNCHRONIZE_CACHE_16     ] = "SYNCHRONIZE_CACHE_16",
+        [ LOCATE_16                ] = "LOCATE_16",
+        [ WRITE_SAME_16            ] = "WRITE_SAME_16",
+        [ ERASE_16                 ] = "ERASE_16",
+        [ SERVICE_ACTION_IN        ] = "SERVICE_ACTION_IN",
+        [ WRITE_LONG_16            ] = "WRITE_LONG_16",
+        [ REPORT_LUNS              ] = "REPORT_LUNS",
+        [ BLANK                    ] = "BLANK",
+        [ MAINTENANCE_IN           ] = "MAINTENANCE_IN",
+        [ MAINTENANCE_OUT          ] = "MAINTENANCE_OUT",
         [ MOVE_MEDIUM              ] = "MOVE_MEDIUM",
+        [ LOAD_UNLOAD              ] = "LOAD_UNLOAD",
         [ READ_12                  ] = "READ_12",
         [ WRITE_12                 ] = "WRITE_12",
         [ WRITE_VERIFY_12          ] = "WRITE_VERIFY_12",
+        [ VERIFY_12                ] = "VERIFY_12",
         [ SEARCH_HIGH_12           ] = "SEARCH_HIGH_12",
         [ SEARCH_EQUAL_12          ] = "SEARCH_EQUAL_12",
         [ SEARCH_LOW_12            ] = "SEARCH_LOW_12",
         [ READ_ELEMENT_STATUS      ] = "READ_ELEMENT_STATUS",
         [ SEND_VOLUME_TAG          ] = "SEND_VOLUME_TAG",
-        [ WRITE_LONG_2             ] = "WRITE_LONG_2",
-
-        [ REPORT_DENSITY_SUPPORT   ] = "REPORT_DENSITY_SUPPORT",
-        [ GET_CONFIGURATION        ] = "GET_CONFIGURATION",
-        [ READ_16                  ] = "READ_16",
-        [ WRITE_16                 ] = "WRITE_16",
-        [ WRITE_VERIFY_16          ] = "WRITE_VERIFY_16",
-        [ SERVICE_ACTION_IN        ] = "SERVICE_ACTION_IN",
-        [ REPORT_LUNS              ] = "REPORT_LUNS",
-        [ LOAD_UNLOAD              ] = "LOAD_UNLOAD",
+        [ READ_DEFECT_DATA_12      ] = "READ_DEFECT_DATA_12",
         [ SET_CD_SPEED             ] = "SET_CD_SPEED",
-        [ BLANK                    ] = "BLANK",
     };
 
     if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL)
index 413cce07b5a4084d1fdd7d3bc931583600e4d311..27010b74c072d2c2ff36fd6d6e6dd0baa36f6855 100644 (file)
@@ -25,7 +25,7 @@
  */
 
 #define TEST_UNIT_READY       0x00
-#define REZERO_UNIT           0x01
+#define REWIND                0x01
 #define REQUEST_SENSE         0x03
 #define FORMAT_UNIT           0x04
 #define READ_BLOCK_LIMITS     0x05
 #define RECEIVE_DIAGNOSTIC    0x1c
 #define SEND_DIAGNOSTIC       0x1d
 #define ALLOW_MEDIUM_REMOVAL  0x1e
-
-#define SET_WINDOW            0x24
-#define READ_CAPACITY         0x25
+#define READ_CAPACITY_10      0x25
 #define READ_10               0x28
 #define WRITE_10              0x2a
 #define SEEK_10               0x2b
-#define WRITE_VERIFY          0x2e
-#define VERIFY                0x2f
+#define LOCATE_10             0x2b
+#define WRITE_VERIFY_10       0x2e
+#define VERIFY_10             0x2f
 #define SEARCH_HIGH           0x30
 #define SEARCH_EQUAL          0x31
 #define SEARCH_LOW            0x32
 #define WRITE_BUFFER          0x3b
 #define READ_BUFFER           0x3c
 #define UPDATE_BLOCK          0x3d
-#define READ_LONG             0x3e
-#define WRITE_LONG            0x3f
+#define READ_LONG_10          0x3e
+#define WRITE_LONG_10         0x3f
 #define CHANGE_DEFINITION     0x40
-#define WRITE_SAME            0x41
+#define WRITE_SAME_10         0x41
+#define UNMAP                 0x42
 #define READ_TOC              0x43
+#define REPORT_DENSITY_SUPPORT 0x44
+#define GET_CONFIGURATION     0x46
 #define LOG_SELECT            0x4c
 #define LOG_SENSE             0x4d
 #define MODE_SELECT_10        0x55
 #define MODE_SENSE_10         0x5a
 #define PERSISTENT_RESERVE_IN 0x5e
 #define PERSISTENT_RESERVE_OUT 0x5f
+#define VARLENGTH_CDB         0x7f
+#define WRITE_FILEMARKS_16    0x80
+#define EXTENDED_COPY         0x83
+#define ATA_PASSTHROUGH       0x85
+#define ACCESS_CONTROL_IN     0x86
+#define ACCESS_CONTROL_OUT    0x87
+#define READ_16               0x88
+#define COMPARE_AND_WRITE     0x89
+#define WRITE_16              0x8a
+#define WRITE_VERIFY_16       0x8e
+#define VERIFY_16             0x8f
+#define SYNCHRONIZE_CACHE_16  0x91
+#define LOCATE_16             0x92
 #define WRITE_SAME_16         0x93
+#define ERASE_16              0x93
+#define SERVICE_ACTION_IN     0x9e
+#define WRITE_LONG_16         0x9f
+#define REPORT_LUNS           0xa0
+#define BLANK                 0xa1
 #define MAINTENANCE_IN        0xa3
 #define MAINTENANCE_OUT       0xa4
 #define MOVE_MEDIUM           0xa5
+#define LOAD_UNLOAD           0xa6
 #define READ_12               0xa8
 #define WRITE_12              0xaa
 #define WRITE_VERIFY_12       0xae
+#define VERIFY_12             0xaf
 #define SEARCH_HIGH_12        0xb0
 #define SEARCH_EQUAL_12       0xb1
 #define SEARCH_LOW_12         0xb2
 #define READ_ELEMENT_STATUS   0xb8
 #define SEND_VOLUME_TAG       0xb6
-#define WRITE_LONG_2          0xea
-
-/* from hw/scsi-generic.c */
-#define REWIND 0x01
-#define REPORT_DENSITY_SUPPORT 0x44
-#define GET_CONFIGURATION 0x46
-#define READ_16 0x88
-#define WRITE_16 0x8a
-#define WRITE_VERIFY_16 0x8e
-#define SERVICE_ACTION_IN 0x9e
-#define REPORT_LUNS 0xa0
-#define LOAD_UNLOAD 0xa6
-#define SET_CD_SPEED 0xbb
-#define BLANK 0xa1
+#define READ_DEFECT_DATA_12   0xb7
+#define SET_CD_SPEED          0xbb
 
 /*
  *  SAM Status codes
 
 #define TYPE_DISK           0x00
 #define TYPE_TAPE           0x01
+#define TYPE_PRINTER        0x02
 #define TYPE_PROCESSOR      0x03    /* HP scanners use this */
 #define TYPE_WORM           0x04    /* Treated as ROM by our system */
 #define TYPE_ROM            0x05
 #define TYPE_MOD            0x07    /* Magneto-optical disk -
                                     * - treated as TYPE_DISK */
 #define TYPE_MEDIUM_CHANGER 0x08
-#define TYPE_ENCLOSURE     0x0d    /* Enclosure Services Device */
+#define TYPE_STORAGE_ARRAY  0x0c    /* Storage array device */
+#define TYPE_ENCLOSURE      0x0d    /* Enclosure Services Device */
+#define TYPE_RBC            0x0e    /* Simplified Direct-Access Device */
+#define TYPE_OSD            0x11    /* Object-storage Device */
 #define TYPE_NO_LUN         0x7f
 
index f42a5d1f855e6c6a4cac6406b18f2da819208290..fa198f928cdeb2ca9f2158a250300f8bf5234fc5 100644 (file)
@@ -59,8 +59,6 @@ typedef struct SCSIDiskReq {
     uint32_t status;
 } SCSIDiskReq;
 
-typedef enum { SCSI_HD, SCSI_CD } SCSIDriveKind;
-
 struct SCSIDiskState
 {
     SCSIDevice qdev;
@@ -74,7 +72,6 @@ struct SCSIDiskState
     char *version;
     char *serial;
     SCSISense sense;
-    SCSIDriveKind drive_kind;
 };
 
 static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
@@ -382,7 +379,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
             return -1;
         }
 
-        if (s->drive_kind == SCSI_CD) {
+        if (s->qdev.type == TYPE_ROM) {
             outbuf[buflen++] = 5;
         } else {
             outbuf[buflen++] = 0;
@@ -401,7 +398,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
             if (s->serial)
                 outbuf[buflen++] = 0x80; // unit serial number
             outbuf[buflen++] = 0x83; // device identification
-            if (s->drive_kind == SCSI_HD) {
+            if (s->qdev.type == TYPE_DISK) {
                 outbuf[buflen++] = 0xb0; // block limits
                 outbuf[buflen++] = 0xb2; // thin provisioning
             }
@@ -460,7 +457,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
             unsigned int opt_io_size =
                     s->qdev.conf.opt_io_size / s->qdev.blocksize;
 
-            if (s->drive_kind == SCSI_CD) {
+            if (s->qdev.type == TYPE_ROM) {
                 DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
                         page_code);
                 return -1;
@@ -526,16 +523,15 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
     memset(outbuf, 0, buflen);
 
     if (req->lun) {
-        outbuf[0] = 0x7f;      /* LUN not supported */
+        outbuf[0] = 0x7f;       /* LUN not supported */
         return buflen;
     }
 
-    if (s->drive_kind == SCSI_CD) {
-        outbuf[0] = 5;
+    outbuf[0] = s->qdev.type & 0x1f;
+    if (s->qdev.type == TYPE_ROM) {
         outbuf[1] = 0x80;
         memcpy(&outbuf[16], "QEMU CD-ROM     ", 16);
     } else {
-        outbuf[0] = 0;
         outbuf[1] = s->removable ? 0x80 : 0;
         memcpy(&outbuf[16], "QEMU HARDDISK   ", 16);
     }
@@ -661,7 +657,7 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
         return p[1] + 2;
 
     case 0x2a: /* CD Capabilities and Mechanical Status page. */
-        if (s->drive_kind != SCSI_CD)
+        if (s->qdev.type != TYPE_ROM)
             return 0;
         p[0] = 0x2a;
         p[1] = 0x14;
@@ -836,7 +832,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
     case TEST_UNIT_READY:
         if (!bdrv_is_inserted(s->bs))
             goto not_ready;
-       break;
+        break;
     case REQUEST_SENSE:
         if (req->cmd.xfer < 4)
             goto illegal_request;
@@ -848,7 +844,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
         buflen = scsi_disk_emulate_inquiry(req, outbuf);
         if (buflen < 0)
             goto illegal_request;
-       break;
+        break;
     case MODE_SENSE:
     case MODE_SENSE_10:
         buflen = scsi_disk_emulate_mode_sense(req, outbuf);
@@ -877,18 +873,18 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
             goto illegal_request;
         break;
     case START_STOP:
-        if (s->drive_kind == SCSI_CD && (req->cmd.buf[4] & 2)) {
+        if (s->qdev.type == TYPE_ROM && (req->cmd.buf[4] & 2)) {
             /* load/eject medium */
             bdrv_eject(s->bs, !(req->cmd.buf[4] & 1));
         }
-       break;
+        break;
     case ALLOW_MEDIUM_REMOVAL:
         bdrv_set_locked(s->bs, req->cmd.buf[4] & 1);
-       break;
-    case READ_CAPACITY:
+        break;
+    case READ_CAPACITY_10:
         /* The normal LEN field for this command is zero.  */
-       memset(outbuf, 0, 8);
-       bdrv_get_geometry(s->bs, &nb_sectors);
+        memset(outbuf, 0, 8);
+        bdrv_get_geometry(s->bs, &nb_sectors);
         if (!nb_sectors)
             goto not_ready;
         nb_sectors /= s->cluster_size;
@@ -908,7 +904,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
         outbuf[6] = s->cluster_size * 2;
         outbuf[7] = 0;
         buflen = 8;
-       break;
+        break;
     case SYNCHRONIZE_CACHE:
         ret = bdrv_flush(s->bs);
         if (ret < 0) {
@@ -970,13 +966,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
         outbuf[3] = 8;
         buflen = 16;
         break;
-    case VERIFY:
-        break;
-    case REZERO_UNIT:
-        DPRINTF("Rezero Unit\n");
-        if (!bdrv_is_inserted(s->bs)) {
-            goto not_ready;
-        }
+    case VERIFY_10:
         break;
     default:
         scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE));
@@ -1052,14 +1042,13 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
     case RELEASE_10:
     case START_STOP:
     case ALLOW_MEDIUM_REMOVAL:
-    case READ_CAPACITY:
+    case READ_CAPACITY_10:
     case SYNCHRONIZE_CACHE:
     case READ_TOC:
     case GET_CONFIGURATION:
     case SERVICE_ACTION_IN:
     case REPORT_LUNS:
-    case VERIFY:
-    case REZERO_UNIT:
+    case VERIFY_10:
         rc = scsi_disk_emulate_command(r, outbuf);
         if (rc < 0) {
             return 0;
@@ -1082,7 +1071,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
     case WRITE_10:
     case WRITE_12:
     case WRITE_16:
-    case WRITE_VERIFY:
+    case WRITE_VERIFY_10:
     case WRITE_VERIFY_12:
     case WRITE_VERIFY_16:
         len = r->req.cmd.xfer / s->qdev.blocksize;
@@ -1190,7 +1179,7 @@ static void scsi_destroy(SCSIDevice *dev)
     blockdev_mark_auto_del(s->qdev.conf.bs);
 }
 
-static int scsi_initfn(SCSIDevice *dev, SCSIDriveKind kind)
+static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
     DriveInfo *dinfo;
@@ -1200,9 +1189,8 @@ static int scsi_initfn(SCSIDevice *dev, SCSIDriveKind kind)
         return -1;
     }
     s->bs = s->qdev.conf.bs;
-    s->drive_kind = kind;
 
-    if (kind == SCSI_HD && !bdrv_is_inserted(s->bs)) {
+    if (scsi_type == TYPE_DISK && !bdrv_is_inserted(s->bs)) {
         error_report("Device needs media, but drive is empty");
         return -1;
     }
@@ -1224,44 +1212,47 @@ static int scsi_initfn(SCSIDevice *dev, SCSIDriveKind kind)
         return -1;
     }
 
-    if (kind == SCSI_CD) {
+    if (scsi_type == TYPE_ROM) {
         s->qdev.blocksize = 2048;
-    } else {
+    } else if (scsi_type == TYPE_DISK) {
         s->qdev.blocksize = s->qdev.conf.logical_block_size;
+    } else {
+        error_report("scsi-disk: Unhandled SCSI type %02x", scsi_type);
+        return -1;
     }
     s->cluster_size = s->qdev.blocksize / 512;
     s->bs->buffer_alignment = s->qdev.blocksize;
 
-    s->qdev.type = TYPE_DISK;
+    s->qdev.type = scsi_type;
     qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
-    bdrv_set_removable(s->bs, kind == SCSI_CD);
+    bdrv_set_removable(s->bs, scsi_type == TYPE_ROM);
     add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
     return 0;
 }
 
 static int scsi_hd_initfn(SCSIDevice *dev)
 {
-    return scsi_initfn(dev, SCSI_HD);
+    return scsi_initfn(dev, TYPE_DISK);
 }
 
 static int scsi_cd_initfn(SCSIDevice *dev)
 {
-    return scsi_initfn(dev, SCSI_CD);
+    return scsi_initfn(dev, TYPE_ROM);
 }
 
 static int scsi_disk_initfn(SCSIDevice *dev)
 {
-    SCSIDriveKind kind;
     DriveInfo *dinfo;
+    uint8_t scsi_type;
 
     if (!dev->conf.bs) {
-        kind = SCSI_HD;         /* will die in scsi_initfn() */
+        scsi_type = TYPE_DISK;  /* will die in scsi_initfn() */
     } else {
         dinfo = drive_get_by_blockdev(dev->conf.bs);
-        kind = dinfo->media_cd ? SCSI_CD : SCSI_HD;
+        scsi_type = dinfo->media_cd ? TYPE_ROM : TYPE_DISK;
     }
 
-    return scsi_initfn(dev, kind);
+    return scsi_initfn(dev, scsi_type);
 }
 
 #define DEFINE_SCSI_DISK_PROPERTIES()                           \
index 63361b35429edd5022d514e231bb71ce9a3f2bb3..7b0026eb9823c71c5a03d6c8eae3ced7127bdfc7 100644 (file)
@@ -406,7 +406,7 @@ static int get_blocksize(BlockDriverState *bdrv)
 
     memset(cmd, 0, sizeof(cmd));
     memset(buf, 0, sizeof(buf));
-    cmd[0] = READ_CAPACITY;
+    cmd[0] = READ_CAPACITY_10;
 
     memset(&io_header, 0, sizeof(io_header));
     io_header.interface_id = 'S';
diff --git a/hw/sd.c b/hw/sd.c
index cedfb202490f87b2e6a11047268ce56f9c0a0135..c2c80ab7b891efd9af9dfce9efade09666fcd1b4 100644 (file)
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -393,9 +393,7 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv)
     } else {
         sect = 0;
     }
-    sect <<= 9;
-
-    size = sect + 1;
+    size = sect << 9;
 
     sect = (size >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)) + 1;
 
@@ -1450,14 +1448,8 @@ void sd_write_data(SDState *sd, uint8_t value)
         break;
 
     case 25:   /* CMD25:  WRITE_MULTIPLE_BLOCK */
-        sd->data[sd->data_offset ++] = value;
-        if (sd->data_offset >= sd->blk_len) {
-            /* TODO: Check CRC before committing */
-            sd->state = sd_programming_state;
-            BLK_WRITE_BLOCK(sd->data_start, sd->data_offset);
-            sd->blk_written ++;
-            sd->data_start += sd->blk_len;
-            sd->data_offset = 0;
+        if (sd->data_offset == 0) {
+            /* Start of the block - lets check the address is valid */
             if (sd->data_start + sd->blk_len > sd->size) {
                 sd->card_status |= ADDRESS_ERROR;
                 break;
@@ -1466,6 +1458,15 @@ void sd_write_data(SDState *sd, uint8_t value)
                 sd->card_status |= WP_VIOLATION;
                 break;
             }
+        }
+        sd->data[sd->data_offset++] = value;
+        if (sd->data_offset >= sd->blk_len) {
+            /* TODO: Check CRC before committing */
+            sd->state = sd_programming_state;
+            BLK_WRITE_BLOCK(sd->data_start, sd->data_offset);
+            sd->blk_written++;
+            sd->data_start += sd->blk_len;
+            sd->data_offset = 0;
             sd->csd[14] |= 0x40;
 
             /* Bzzzzzzztt .... Operation complete.  */
index a076cf2ff0eb717c3c56f072ebbef424cea8d6df..cd8650143cbf425a11c1b81381e0e95fb149ba81 100644 (file)
@@ -26,6 +26,7 @@
 #include "pci.h"
 #include "pci_host.h"
 #include "bswap.h"
+#include "exec-memory.h"
 
 typedef struct SHPCIState {
     SysBusDevice busdev;
@@ -127,7 +128,10 @@ static int sh_pci_init_device(SysBusDevice *dev)
     }
     s->bus = pci_register_bus(&s->busdev.qdev, "pci",
                               sh_pci_set_irq, sh_pci_map_irq,
-                              s->irq, PCI_DEVFN(0, 0), 4);
+                              s->irq,
+                              get_system_memory(),
+                              get_system_io(),
+                              PCI_DEVFN(0, 0), 4);
     s->memconfig = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w,
                                           s, DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio_cb(dev, 0x224, sh_pci_map);
index 5cd8d8f5ae1a60bbf8af0409eabf2c7e56f9dd9a..f7ead04a96b307628c70fe280340d413f4892800 100644 (file)
@@ -1,9 +1,9 @@
 #include "sysemu.h"
 #include "cpu.h"
+#include "dyngen-exec.h"
 #include "qemu-char.h"
 #include "sysemu.h"
 #include "qemu-char.h"
-#include "exec.h"
 #include "helper_regs.h"
 #include "hw/spapr.h"
 
index 006f7a97e379499e87d583d3b389ec02aaf30c0c..c05b5f7d56fa72167cc1700014e62a0b25f88af8 100644 (file)
@@ -48,7 +48,7 @@
 
 typedef struct {
     SysBusDevice busdev;
-    NANDFlashState *nand;
+    DeviceState *nand;
     uint8_t ctl;
     uint8_t manf_id;
     uint8_t chip_id;
@@ -169,11 +169,13 @@ static void sl_flash_register(PXA2xxState *cpu, int size)
 static int sl_nand_init(SysBusDevice *dev) {
     int iomemtype;
     SLNANDState *s;
+    DriveInfo *nand;
 
     s = FROM_SYSBUS(SLNANDState, dev);
 
     s->ctl = 0;
-    s->nand = nand_init(s->manf_id, s->chip_id);
+    nand = drive_get(IF_MTD, 0, 0);
+    s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id);
 
     iomemtype = cpu_register_io_memory(sl_readfn,
                     sl_writefn, s, DEVICE_NATIVE_ENDIAN);
index d7dcaf007dfb76753d4fcf7ae6ef9a3f991bfcb2..7b2d0b17e4933dafa5d1fc4922f63effc1c44651 100644 (file)
@@ -91,6 +91,12 @@ struct hwdef {
     uint64_t console_serial_base;
 };
 
+typedef struct EbusState {
+    PCIDevice pci_dev;
+    MemoryRegion bar0;
+    MemoryRegion bar1;
+} EbusState;
+
 int DMA_get_channel_mode (int nchan)
 {
     return 0;
@@ -518,21 +524,6 @@ void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
     }
 }
 
-static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
-                              pcibus_t addr, pcibus_t size, int type)
-{
-    EBUS_DPRINTF("Mapping region %d registers at %" FMT_PCIBUS "\n",
-                 region_num, addr);
-    switch (region_num) {
-    case 0:
-        isa_mmio_init(addr, 0x1000000);
-        break;
-    case 1:
-        isa_mmio_init(addr, 0x800000);
-        break;
-    }
-}
-
 static void dummy_isa_irq_handler(void *opaque, int n, int level)
 {
 }
@@ -549,27 +540,29 @@ pci_ebus_init(PCIBus *bus, int devfn)
 }
 
 static int
-pci_ebus_init1(PCIDevice *s)
+pci_ebus_init1(PCIDevice *pci_dev)
 {
-    isa_bus_new(&s->qdev);
+    EbusState *s = DO_UPCAST(EbusState, pci_dev, pci_dev);
+
+    isa_bus_new(&pci_dev->qdev);
 
-    s->config[0x04] = 0x06; // command = bus master, pci mem
-    s->config[0x05] = 0x00;
-    s->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
-    s->config[0x07] = 0x03; // status = medium devsel
-    s->config[0x09] = 0x00; // programming i/f
-    s->config[0x0D] = 0x0a; // latency_timer
+    pci_dev->config[0x04] = 0x06; // command = bus master, pci mem
+    pci_dev->config[0x05] = 0x00;
+    pci_dev->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
+    pci_dev->config[0x07] = 0x03; // status = medium devsel
+    pci_dev->config[0x09] = 0x00; // programming i/f
+    pci_dev->config[0x0D] = 0x0a; // latency_timer
 
-    pci_register_bar(s, 0, 0x1000000, PCI_BASE_ADDRESS_SPACE_MEMORY,
-                           ebus_mmio_mapfunc);
-    pci_register_bar(s, 1, 0x800000,  PCI_BASE_ADDRESS_SPACE_MEMORY,
-                           ebus_mmio_mapfunc);
+    isa_mmio_setup(&s->bar0, 0x1000000);
+    pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0);
+    isa_mmio_setup(&s->bar1, 0x800000);
+    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar1);
     return 0;
 }
 
 static PCIDeviceInfo ebus_info = {
     .qdev.name = "ebus",
-    .qdev.size = sizeof(PCIDevice),
+    .qdev.size = sizeof(EbusState),
     .init = pci_ebus_init1,
     .vendor_id = PCI_VENDOR_ID_SUN,
     .device_id = PCI_DEVICE_ID_SUN_EBUS,
index 2e22be7b25ba227f7c2bce122f950360c8179f2c..ea442acb50334bc2a04f3aabef09076db7b649f8 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "sysbus.h"
 #include "monitor.h"
+#include "exec-memory.h"
 
 static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
 static char *sysbus_get_fw_dev_path(DeviceState *dev);
@@ -49,11 +50,20 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
     }
     if (dev->mmio[n].addr != (target_phys_addr_t)-1) {
         /* Unregister previous mapping.  */
-        cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
-                                     IO_MEM_UNASSIGNED);
+        if (dev->mmio[n].memory) {
+            memory_region_del_subregion(get_system_memory(),
+                                        dev->mmio[n].memory);
+        } else {
+            cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
+                                         IO_MEM_UNASSIGNED);
+        }
     }
     dev->mmio[n].addr = addr;
-    if (dev->mmio[n].cb) {
+    if (dev->mmio[n].memory) {
+        memory_region_add_subregion(get_system_memory(),
+                                    addr,
+                                    dev->mmio[n].memory);
+    } else if (dev->mmio[n].cb) {
         dev->mmio[n].cb(dev, addr);
     } else {
         cpu_register_physical_memory(addr, dev->mmio[n].size,
@@ -107,6 +117,17 @@ void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
     dev->mmio[n].cb = cb;
 }
 
+void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory)
+{
+    int n;
+
+    assert(dev->num_mmio < QDEV_MAX_MMIO);
+    n = dev->num_mmio++;
+    dev->mmio[n].addr = -1;
+    dev->mmio[n].size = memory_region_size(memory);
+    dev->mmio[n].memory = memory;
+}
+
 void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size)
 {
     pio_addr_t i;
index 4e8cb16d4206d007fa52914932a68d0081273ac7..5f62e2da31cf0ba070d893521c37dbf59c61b443 100644 (file)
@@ -4,6 +4,7 @@
 /* Devices attached directly to the main system bus.  */
 
 #include "qdev.h"
+#include "memory.h"
 
 #define QDEV_MAX_MMIO 32
 #define QDEV_MAX_PIO 32
@@ -23,6 +24,7 @@ struct SysBusDevice {
         target_phys_addr_t size;
         mmio_mapfunc cb;
         ram_addr_t iofunc;
+        MemoryRegion *memory;
     } mmio[QDEV_MAX_MMIO];
     int num_pio;
     pio_addr_t pio[QDEV_MAX_PIO];
@@ -46,6 +48,7 @@ void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size,
                       ram_addr_t iofunc);
 void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
                             mmio_mapfunc cb);
+void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory);
 void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p);
 void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target);
 void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size);
index ed49e944df9743353561104970405784a972dab9..a1c48bf1d9a63ec20fc359332b47f2399d18515e 100644 (file)
@@ -12,6 +12,7 @@
 #include "flash.h"
 #include "console.h"
 #include "pixel_ops.h"
+#include "blockdev.h"
 
 #define IRQ_TC6393_NAND                0
 #define IRQ_TC6393_MMC         1
@@ -117,7 +118,7 @@ struct TC6393xbState {
     } nand;
     int nand_enable;
     uint32_t nand_phys;
-    NANDFlashState *flash;
+    DeviceState *flash;
     ECCState ecc;
 
     DisplayState *ds;
@@ -566,6 +567,7 @@ TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq)
 {
     int iomemtype;
     TC6393xbState *s;
+    DriveInfo *nand;
     CPUReadMemoryFunc * const tc6393xb_readfn[] = {
         tc6393xb_readb,
         tc6393xb_readw,
@@ -586,7 +588,8 @@ TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq)
 
     s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS);
 
-    s->flash = nand_init(NAND_MFR_TOSHIBA, 0x76);
+    nand = drive_get(IF_MTD, 0, 0);
+    s->flash = nand_init(nand ? nand->bdrv : NULL, NAND_MFR_TOSHIBA, 0x76);
 
     iomemtype = cpu_register_io_memory(tc6393xb_readfn,
                     tc6393xb_writefn, s, DEVICE_NATIVE_ENDIAN);
index d364daa53adb95232d9357a8693e0366878293e1..f896f8c76b3b10f2abac40c114a9a6047a2d461d 100644 (file)
@@ -201,7 +201,9 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
     return 0;
 }
 
-PCIBus *pci_pmac_init(qemu_irq *pic)
+PCIBus *pci_pmac_init(qemu_irq *pic,
+                      MemoryRegion *address_space_mem,
+                      MemoryRegion *address_space_io)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -215,7 +217,10 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
     d = FROM_SYSBUS(UNINState, s);
     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_unin_set_irq, pci_unin_map_irq,
-                                         pic, PCI_DEVFN(11, 0), 4);
+                                         pic,
+                                         address_space_mem,
+                                         address_space_io,
+                                         PCI_DEVFN(11, 0), 4);
 
 #if 0
     pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north");
@@ -252,7 +257,9 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
     return d->host_state.bus;
 }
 
-PCIBus *pci_pmac_u3_init(qemu_irq *pic)
+PCIBus *pci_pmac_u3_init(qemu_irq *pic,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -267,7 +274,10 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic)
 
     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_unin_set_irq, pci_unin_map_irq,
-                                         pic, PCI_DEVFN(11, 0), 4);
+                                         pic,
+                                         address_space_mem,
+                                         address_space_io,
+                                         PCI_DEVFN(11, 0), 4);
 
     sysbus_mmio_map(s, 0, 0xf0800000);
     sysbus_mmio_map(s, 1, 0xf0c00000);
index e364513a012a7d2e70dae5525432a99d871327c8..529fa3355d7698259ae8bacdb051a3557b0dabc2 100644 (file)
@@ -294,9 +294,9 @@ static inline int usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
     if (likely(!fifo->len))
         return USB_RET_STALL;
 
-    len = MIN(p->len, fifo->fifo[fifo->start].len);
-    memcpy(p->data, fifo->fifo[fifo->start].data, len);
-    if (len == p->len) {
+    len = MIN(p->iov.size, fifo->fifo[fifo->start].len);
+    usb_packet_copy(p, fifo->fifo[fifo->start].data, len);
+    if (len == p->iov.size) {
         fifo->fifo[fifo->start].len -= len;
         fifo->fifo[fifo->start].data += len;
     } else {
@@ -319,20 +319,13 @@ static inline void usb_bt_fifo_out_enqueue(struct USBBtState *s,
                 struct usb_hci_out_fifo_s *fifo,
                 void (*send)(struct HCIInfo *, const uint8_t *, int),
                 int (*complete)(const uint8_t *, int),
-                const uint8_t *data, int len)
+                USBPacket *p)
 {
-    if (fifo->len) {
-        memcpy(fifo->data + fifo->len, data, len);
-        fifo->len += len;
-        if (complete(fifo->data, fifo->len)) {
-            send(s->hci, fifo->data, fifo->len);
-            fifo->len = 0;
-        }
-    } else if (complete(data, len))
-        send(s->hci, data, len);
-    else {
-        memcpy(fifo->data, data, len);
-        fifo->len = len;
+    usb_packet_copy(p, fifo->data + fifo->len, p->iov.size);
+    fifo->len += p->iov.size;
+    if (complete(fifo->data, fifo->len)) {
+        send(s->hci, fifo->data, fifo->len);
+        fifo->len = 0;
     }
 
     /* TODO: do we need to loop? */
@@ -432,7 +425,7 @@ static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
     case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE) << 8):
         if (s->config)
             usb_bt_fifo_out_enqueue(s, &s->outcmd, s->hci->cmd_send,
-                            usb_bt_hci_cmd_complete, data, length);
+                            usb_bt_hci_cmd_complete, p);
         break;
     default:
     fail:
@@ -474,12 +467,12 @@ static int usb_bt_handle_data(USBDevice *dev, USBPacket *p)
         switch (p->devep & 0xf) {
         case USB_ACL_EP:
             usb_bt_fifo_out_enqueue(s, &s->outacl, s->hci->acl_send,
-                            usb_bt_hci_acl_complete, p->data, p->len);
+                            usb_bt_hci_acl_complete, p);
             break;
 
         case USB_SCO_EP:
             usb_bt_fifo_out_enqueue(s, &s->outsco, s->hci->sco_send,
-                            usb_bt_hci_sco_complete, p->data, p->len);
+                            usb_bt_hci_sco_complete, p);
             break;
 
         default:
@@ -548,10 +541,16 @@ USBDevice *usb_bt_init(HCIInfo *hci)
     return dev;
 }
 
+static const VMStateDescription vmstate_usb_bt = {
+    .name = "usb-bt",
+    .unmigratable = 1,
+};
+
 static struct USBDeviceInfo bt_info = {
     .product_desc   = "QEMU BT dongle",
     .qdev.name      = "usb-bt-dongle",
     .qdev.size      = sizeof(struct USBBtState),
+    .qdev.vmsd      = &vmstate_usb_bt,
     .usb_desc       = &desc_bluetooth,
     .init           = usb_bt_initfn,
     .handle_packet  = usb_generic_handle_packet,
index 4dda2c4833a82981344b9145fddb03be1573161d..66aeb211af4ba52f8dea593a15149455825862d4 100644 (file)
@@ -934,16 +934,16 @@ static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
 {
     CCID_Header *ccid_header;
 
-    if (p->len + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
+    if (p->iov.size + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
         return USB_RET_STALL;
     }
     ccid_header = (CCID_Header *)s->bulk_out_data;
-    memcpy(s->bulk_out_data + s->bulk_out_pos, p->data, p->len);
-    s->bulk_out_pos += p->len;
-    if (p->len == CCID_MAX_PACKET_SIZE) {
+    usb_packet_copy(p, s->bulk_out_data + s->bulk_out_pos, p->iov.size);
+    s->bulk_out_pos += p->iov.size;
+    if (p->iov.size == CCID_MAX_PACKET_SIZE) {
         DPRINTF(s, D_VERBOSE,
-            "usb-ccid: bulk_in: expecting more packets (%d/%d)\n",
-            p->len, ccid_header->dwLength);
+            "usb-ccid: bulk_in: expecting more packets (%zd/%d)\n",
+            p->iov.size, ccid_header->dwLength);
         return 0;
     }
     if (s->bulk_out_pos < 10) {
@@ -1006,15 +1006,17 @@ static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
     return 0;
 }
 
-static int ccid_bulk_in_copy_to_guest(USBCCIDState *s, uint8_t *data, int len)
+static int ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)
 {
     int ret = 0;
 
-    assert(len > 0);
+    assert(p->iov.size > 0);
     ccid_bulk_in_get(s);
     if (s->current_bulk_in != NULL) {
-        ret = MIN(s->current_bulk_in->len - s->current_bulk_in->pos, len);
-        memcpy(data, s->current_bulk_in->data + s->current_bulk_in->pos, ret);
+        ret = MIN(s->current_bulk_in->len - s->current_bulk_in->pos,
+                  p->iov.size);
+        usb_packet_copy(p, s->current_bulk_in->data +
+                        s->current_bulk_in->pos, ret);
         s->current_bulk_in->pos += ret;
         if (s->current_bulk_in->pos == s->current_bulk_in->len) {
             ccid_bulk_in_release(s);
@@ -1025,11 +1027,13 @@ static int ccid_bulk_in_copy_to_guest(USBCCIDState *s, uint8_t *data, int len)
     }
     if (ret > 0) {
         DPRINTF(s, D_MORE_INFO,
-                "%s: %d/%d req/act to guest (BULK_IN)\n", __func__, len, ret);
+                "%s: %zd/%d req/act to guest (BULK_IN)\n",
+                __func__, p->iov.size, ret);
     }
-    if (ret != USB_RET_NAK && ret < len) {
+    if (ret != USB_RET_NAK && ret < p->iov.size) {
         DPRINTF(s, 1,
-            "%s: returning short (EREMOTEIO) %d < %d\n", __func__, ret, len);
+                "%s: returning short (EREMOTEIO) %d < %zd\n",
+                __func__, ret, p->iov.size);
     }
     return ret;
 }
@@ -1038,8 +1042,7 @@ static int ccid_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
     int ret = 0;
-    uint8_t *data = p->data;
-    int len = p->len;
+    uint8_t buf[2];
 
     switch (p->pid) {
     case USB_TOKEN_OUT:
@@ -1049,24 +1052,25 @@ static int ccid_handle_data(USBDevice *dev, USBPacket *p)
     case USB_TOKEN_IN:
         switch (p->devep & 0xf) {
         case CCID_BULK_IN_EP:
-            if (!len) {
+            if (!p->iov.size) {
                 ret = USB_RET_NAK;
             } else {
-                ret = ccid_bulk_in_copy_to_guest(s, data, len);
+                ret = ccid_bulk_in_copy_to_guest(s, p);
             }
             break;
         case CCID_INT_IN_EP:
             if (s->notify_slot_change) {
                 /* page 56, RDR_to_PC_NotifySlotChange */
-                data[0] = CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange;
-                data[1] = s->bmSlotICCState;
+                buf[0] = CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange;
+                buf[1] = s->bmSlotICCState;
+                usb_packet_copy(p, buf, 2);
                 ret = 2;
                 s->notify_slot_change = false;
                 s->bmSlotICCState &= ~SLOT_0_CHANGED_MASK;
                 DPRINTF(s, D_INFO,
                         "handle_data: int_in: notify_slot_change %X, "
-                        "requested len %d\n",
-                        s->bmSlotICCState, len);
+                        "requested len %zd\n",
+                        s->bmSlotICCState, p->iov.size);
             }
             break;
         default:
index a4758f976e9d10c36daa88f295d71fbf874073c9..c9d0a692ed96d382947f1e9fbdc7e4b38bbc5bb7 100644 (file)
@@ -28,6 +28,7 @@
 #include "pci.h"
 #include "monitor.h"
 #include "trace.h"
+#include "dma.h"
 
 #define EHCI_DEBUG   0
 
@@ -269,6 +270,7 @@ typedef struct EHCIqtd {
 
     uint32_t bufptr[5];               // Standard buffer pointer
 #define QTD_BUFPTR_MASK               0xfffff000
+#define QTD_BUFPTR_SH                 12
 } EHCIqtd;
 
 /*  EHCI spec version 1.0 Section 3.6
@@ -357,7 +359,7 @@ struct EHCIQueue {
     uint32_t qtdaddr;      // address QTD read from
 
     USBPacket packet;
-    uint8_t buffer[BUFF_SIZE];
+    QEMUSGList sgl;
     int pid;
     uint32_t tbytes;
     enum async_state async;
@@ -368,8 +370,7 @@ struct EHCIState {
     PCIDevice dev;
     USBBus bus;
     qemu_irq irq;
-    target_phys_addr_t mem_base;
-    int mem;
+    MemoryRegion mem;
     int companion_count;
 
     /* properties */
@@ -414,7 +415,7 @@ struct EHCIState {
     uint32_t p_fetch_addr;   // which address to look at next
 
     USBPacket ipacket;
-    uint8_t ibuffer[BUFF_SIZE];
+    QEMUSGList isgl;
     int isoch_pause;
 
     uint64_t last_run_ns;
@@ -1165,58 +1166,56 @@ static int ehci_qh_do_overlay(EHCIQueue *q)
     return 0;
 }
 
-static int ehci_buffer_rw(EHCIQueue *q, int bytes, int rw)
+static int ehci_init_transfer(EHCIQueue *q)
 {
-    int bufpos = 0;
-    int cpage, offset;
-    uint32_t head;
-    uint32_t tail;
-
-
-    if (!bytes) {
-        return 0;
-    }
-
-    cpage = get_field(q->qh.token, QTD_TOKEN_CPAGE);
-    if (cpage > 4) {
-        fprintf(stderr, "cpage out of range (%d)\n", cpage);
-        return USB_RET_PROCERR;
-    }
+    uint32_t cpage, offset, bytes, plen;
+    target_phys_addr_t page;
 
+    cpage  = get_field(q->qh.token, QTD_TOKEN_CPAGE);
+    bytes  = get_field(q->qh.token, QTD_TOKEN_TBYTES);
     offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK;
+    qemu_sglist_init(&q->sgl, 5);
 
-    do {
-        /* start and end of this page */
-        head = q->qh.bufptr[cpage] & QTD_BUFPTR_MASK;
-        tail = head + ~QTD_BUFPTR_MASK + 1;
-        /* add offset into page */
-        head |= offset;
-
-        if (bytes <= (tail - head)) {
-            tail = head + bytes;
+    while (bytes > 0) {
+        if (cpage > 4) {
+            fprintf(stderr, "cpage out of range (%d)\n", cpage);
+            return USB_RET_PROCERR;
         }
 
-        trace_usb_ehci_data(rw, cpage, offset, head, tail-head, bufpos);
-        cpu_physical_memory_rw(head, q->buffer + bufpos, tail - head, rw);
-
-        bufpos += (tail - head);
-        offset += (tail - head);
-        bytes -= (tail - head);
-
-        if (bytes > 0) {
-            cpage++;
+        page  = q->qh.bufptr[cpage] & QTD_BUFPTR_MASK;
+        page += offset;
+        plen  = bytes;
+        if (plen > 4096 - offset) {
+            plen = 4096 - offset;
             offset = 0;
+            cpage++;
         }
-    } while (bytes > 0);
 
-    /* save cpage */
-    set_field(&q->qh.token, cpage, QTD_TOKEN_CPAGE);
+        qemu_sglist_add(&q->sgl, page, plen);
+        bytes -= plen;
+    }
+    return 0;
+}
+
+static void ehci_finish_transfer(EHCIQueue *q, int status)
+{
+    uint32_t cpage, offset;
 
-    /* save offset into cpage */
-    q->qh.bufptr[0] &= QTD_BUFPTR_MASK;
-    q->qh.bufptr[0] |= offset;
+    qemu_sglist_destroy(&q->sgl);
 
-    return 0;
+    if (status > 0) {
+        /* update cpage & offset */
+        cpage  = get_field(q->qh.token, QTD_TOKEN_CPAGE);
+        offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK;
+
+        offset += status;
+        cpage  += offset >> QTD_BUFPTR_SH;
+        offset &= ~QTD_BUFPTR_MASK;
+
+        set_field(&q->qh.token, cpage, QTD_TOKEN_CPAGE);
+        q->qh.bufptr[0] &= QTD_BUFPTR_MASK;
+        q->qh.bufptr[0] |= offset;
+    }
 }
 
 static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
@@ -1235,7 +1234,7 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
     trace_usb_ehci_queue_action(q, "wakeup");
     assert(q->async == EHCI_ASYNC_INFLIGHT);
     q->async = EHCI_ASYNC_FINISHED;
-    q->usb_status = packet->len;
+    q->usb_status = packet->result;
 }
 
 static void ehci_execute_complete(EHCIQueue *q)
@@ -1295,10 +1294,6 @@ err:
         }
 
         if (q->tbytes && q->pid == USB_TOKEN_IN) {
-            if (ehci_buffer_rw(q, q->usb_status, 1) != 0) {
-                q->usb_status = USB_RET_PROCERR;
-                return;
-            }
             q->tbytes -= q->usb_status;
         } else {
             q->tbytes = 0;
@@ -1307,6 +1302,8 @@ err:
         DPRINTF("updating tbytes to %d\n", q->tbytes);
         set_field(&q->qh.token, q->tbytes, QTD_TOKEN_TBYTES);
     }
+    ehci_finish_transfer(q, q->usb_status);
+    usb_packet_unmap(&q->packet);
 
     q->qh.token ^= QTD_TOKEN_DTOGGLE;
     q->qh.token &= ~QTD_TOKEN_ACTIVE;
@@ -1346,8 +1343,7 @@ static int ehci_execute(EHCIQueue *q)
         default: fprintf(stderr, "bad token\n"); break;
     }
 
-    if ((q->tbytes && q->pid != USB_TOKEN_IN) &&
-        (ehci_buffer_rw(q, q->tbytes, 0) != 0)) {
+    if (ehci_init_transfer(q) != 0) {
         return USB_RET_PROCERR;
     }
 
@@ -1356,6 +1352,9 @@ static int ehci_execute(EHCIQueue *q)
 
     ret = USB_RET_NODEV;
 
+    usb_packet_setup(&q->packet, q->pid, devadr, endp);
+    usb_packet_map(&q->packet, &q->sgl);
+
     // TO-DO: associating device with ehci port
     for(i = 0; i < NB_PORTS; i++) {
         port = &q->ehci->ports[i];
@@ -1367,17 +1366,12 @@ static int ehci_execute(EHCIQueue *q)
             continue;
         }
 
-        q->packet.pid = q->pid;
-        q->packet.devaddr = devadr;
-        q->packet.devep = endp;
-        q->packet.data = q->buffer;
-        q->packet.len = q->tbytes;
-
         ret = usb_handle_packet(dev, &q->packet);
 
-        DPRINTF("submit: qh %x next %x qtd %x pid %x len %d (total %d) endp %x ret %d\n",
+        DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
+                "(total %d) endp %x ret %d\n",
                 q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
-                q->packet.len, q->tbytes, endp, ret);
+                q->packet.iov.size, q->tbytes, endp, ret);
 
         if (ret != USB_RET_NODEV) {
             break;
@@ -1401,7 +1395,7 @@ static int ehci_process_itd(EHCIState *ehci,
     USBPort *port;
     USBDevice *dev;
     int ret;
-    uint32_t i, j, len, len1, len2, pid, dir, devaddr, endp;
+    uint32_t i, j, len, pid, dir, devaddr, endp;
     uint32_t pg, off, ptr1, ptr2, max, mult;
 
     dir =(itd->bufptr[1] & ITD_BUFPTR_DIRECTION);
@@ -1426,29 +1420,23 @@ static int ehci_process_itd(EHCIState *ehci,
                 return USB_RET_PROCERR;
             }
 
+            qemu_sglist_init(&ehci->isgl, 2);
             if (off + len > 4096) {
                 /* transfer crosses page border */
-                len2 = off + len - 4096;
-                len1 = len - len2;
+                uint32_t len2 = off + len - 4096;
+                uint32_t len1 = len - len2;
+                qemu_sglist_add(&ehci->isgl, ptr1 + off, len1);
+                qemu_sglist_add(&ehci->isgl, ptr2, len2);
             } else {
-                len1 = len;
-                len2 = 0;
+                qemu_sglist_add(&ehci->isgl, ptr1 + off, len);
             }
 
-            if (!dir) {
-                pid = USB_TOKEN_OUT;
-                trace_usb_ehci_data(0, pg, off, ptr1 + off, len1, 0);
-                cpu_physical_memory_rw(ptr1 + off, &ehci->ibuffer[0], len1, 0);
-                if (len2) {
-                    trace_usb_ehci_data(0, pg+1, 0, ptr2, len2, len1);
-                    cpu_physical_memory_rw(ptr2, &ehci->ibuffer[len1], len2, 0);
-                }
-            } else {
-                pid = USB_TOKEN_IN;
-            }
+            pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT;
 
-            ret = USB_RET_NODEV;
+            usb_packet_setup(&ehci->ipacket, pid, devaddr, endp);
+            usb_packet_map(&ehci->ipacket, &ehci->isgl);
 
+            ret = USB_RET_NODEV;
             for (j = 0; j < NB_PORTS; j++) {
                 port = &ehci->ports[j];
                 dev = port->dev;
@@ -1457,12 +1445,6 @@ static int ehci_process_itd(EHCIState *ehci,
                     continue;
                 }
 
-                ehci->ipacket.pid = pid;
-                ehci->ipacket.devaddr = devaddr;
-                ehci->ipacket.devep = endp;
-                ehci->ipacket.data = ehci->ibuffer;
-                ehci->ipacket.len = len;
-
                 ret = usb_handle_packet(dev, &ehci->ipacket);
 
                 if (ret != USB_RET_NODEV) {
@@ -1470,6 +1452,9 @@ static int ehci_process_itd(EHCIState *ehci,
                 }
             }
 
+            usb_packet_unmap(&ehci->ipacket);
+            qemu_sglist_destroy(&ehci->isgl);
+
 #if 0
             /*  In isoch, there is no facility to indicate a NAK so let's
              *  instead just complete a zero-byte transaction.  Setting
@@ -1507,20 +1492,6 @@ static int ehci_process_itd(EHCIState *ehci,
                     set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH);
                 } else {
                     /* IN */
-                    if (len1 > ret) {
-                        len1 = ret;
-                    }
-                    if (len2 > ret - len1) {
-                        len2 = ret - len1;
-                    }
-                    if (len1) {
-                        trace_usb_ehci_data(1, pg, off, ptr1 + off, len1, 0);
-                        cpu_physical_memory_rw(ptr1 + off, &ehci->ibuffer[0], len1, 1);
-                    }
-                    if (len2) {
-                        trace_usb_ehci_data(1, pg+1, 0, ptr2, len2, len1);
-                        cpu_physical_memory_rw(ptr2, &ehci->ibuffer[len1], len2, 1);
-                    }
                     set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
                 }
 
@@ -2207,29 +2178,15 @@ static void ehci_frame_timer(void *opaque)
     qemu_mod_timer(ehci->frame_timer, expire_time);
 }
 
-static CPUReadMemoryFunc *ehci_readfn[3]={
-    ehci_mem_readb,
-    ehci_mem_readw,
-    ehci_mem_readl
-};
 
-static CPUWriteMemoryFunc *ehci_writefn[3]={
-    ehci_mem_writeb,
-    ehci_mem_writew,
-    ehci_mem_writel
+static const MemoryRegionOps ehci_mem_ops = {
+    .old_mmio = {
+        .read = { ehci_mem_readb, ehci_mem_readw, ehci_mem_readl },
+        .write = { ehci_mem_writeb, ehci_mem_writew, ehci_mem_writel },
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-static void ehci_map(PCIDevice *pci_dev, int region_num,
-                     pcibus_t addr, pcibus_t size, int type)
-{
-    EHCIState *s =(EHCIState *)pci_dev;
-
-    DPRINTF("ehci_map: region %d, addr %08" PRIx64 ", size %" PRId64 ", s->mem %08X\n",
-            region_num, addr, size, s->mem);
-    s->mem_base = addr;
-    cpu_register_physical_memory(addr, size, s->mem);
-}
-
 static int usb_ehci_initfn(PCIDevice *dev);
 
 static USBPortOps ehci_port_ops = {
@@ -2244,6 +2201,11 @@ static USBBusOps ehci_bus_ops = {
     .register_companion = ehci_register_companion,
 };
 
+static const VMStateDescription vmstate_ehci = {
+    .name = "ehci",
+    .unmigratable = 1,
+};
+
 static Property ehci_properties[] = {
     DEFINE_PROP_UINT32("freq",      EHCIState, freq, FRAME_TIMER_FREQ),
     DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128),
@@ -2254,6 +2216,7 @@ static PCIDeviceInfo ehci_info[] = {
     {
         .qdev.name    = "usb-ehci",
         .qdev.size    = sizeof(EHCIState),
+        .qdev.vmsd    = &vmstate_ehci,
         .init         = usb_ehci_initfn,
         .vendor_id    = PCI_VENDOR_ID_INTEL,
         .device_id    = PCI_DEVICE_ID_INTEL_82801D, /* ich4 */
@@ -2263,6 +2226,7 @@ static PCIDeviceInfo ehci_info[] = {
     },{
         .qdev.name    = "ich9-usb-ehci1",
         .qdev.size    = sizeof(EHCIState),
+        .qdev.vmsd    = &vmstate_ehci,
         .init         = usb_ehci_initfn,
         .vendor_id    = PCI_VENDOR_ID_INTEL,
         .device_id    = PCI_DEVICE_ID_INTEL_82801I_EHCI1,
@@ -2337,11 +2301,8 @@ static int usb_ehci_initfn(PCIDevice *dev)
 
     qemu_register_reset(ehci_reset, s);
 
-    s->mem = cpu_register_io_memory(ehci_readfn, ehci_writefn, s,
-                                    DEVICE_LITTLE_ENDIAN);
-
-    pci_register_bar(&s->dev, 0, MMIO_SIZE, PCI_BASE_ADDRESS_SPACE_MEMORY,
-                                                            ehci_map);
+    memory_region_init_io(&s->mem, &ehci_mem_ops, s, "ehci", MMIO_SIZE);
+    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
 
     fprintf(stderr, "*** EHCI support is under development ***\n");
 
index b812da2a6a716d9d4a4b6a2af22cbeb3e940254f..e5d57de8889f6c5a44e743d6769eea6cb0d992b1 100644 (file)
@@ -27,6 +27,7 @@
 #include "usb.h"
 #include "usb-desc.h"
 #include "qemu-timer.h"
+#include "hid.h"
 
 /* HID interface requests */
 #define GET_REPORT   0xa101
 #define USB_DT_REPORT 0x22
 #define USB_DT_PHY    0x23
 
-#define USB_MOUSE     1
-#define USB_TABLET    2
-#define USB_KEYBOARD  3
-
-typedef struct USBPointerEvent {
-    int32_t xdx, ydy; /* relative iff it's a mouse, otherwise absolute */
-    int32_t dz, buttons_state;
-} USBPointerEvent;
-
-#define QUEUE_LENGTH    16 /* should be enough for a triple-click */
-#define QUEUE_MASK      (QUEUE_LENGTH-1u)
-#define QUEUE_INCR(v)   ((v)++, (v) &= QUEUE_MASK)
-
-typedef struct USBMouseState {
-    USBPointerEvent queue[QUEUE_LENGTH];
-    int mouse_grabbed;
-    QEMUPutMouseEntry *eh_entry;
-} USBMouseState;
-
-typedef struct USBKeyboardState {
-    uint32_t keycodes[QUEUE_LENGTH];
-    uint16_t modifiers;
-    uint8_t leds;
-    uint8_t key[16];
-    int32_t keys;
-} USBKeyboardState;
-
 typedef struct USBHIDState {
     USBDevice dev;
-    union {
-        USBMouseState ptr;
-        USBKeyboardState kbd;
-    };
-    uint32_t head; /* index into circular queue */
-    uint32_t n;
-    int kind;
-    int32_t protocol;
-    uint8_t idle;
-    int64_t next_idle_clock;
-    int changed;
+    HIDState hid;
     void *datain_opaque;
     void (*datain)(void *);
 } USBHIDState;
@@ -394,339 +358,29 @@ static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
     0xc0,              /* End Collection */
 };
 
-#define USB_HID_USAGE_ERROR_ROLLOVER   0x01
-#define USB_HID_USAGE_POSTFAIL         0x02
-#define USB_HID_USAGE_ERROR_UNDEFINED  0x03
-
-/* Indices are QEMU keycodes, values are from HID Usage Table.  Indices
- * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d.  */
-static const uint8_t usb_hid_usage_keys[0x100] = {
-    0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
-    0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
-    0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
-    0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
-    0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
-    0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
-    0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
-    0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
-    0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
-    0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
-    0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
-    0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
-    0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
-
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
-    0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
-    0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
-    0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-static void usb_hid_changed(USBHIDState *hs)
-{
-    hs->changed = 1;
-
-    if (hs->datain)
-        hs->datain(hs->datain_opaque);
-
-    usb_wakeup(&hs->dev);
-}
-
-static void usb_pointer_event_clear(USBPointerEvent *e, int buttons) {
-    e->xdx = e->ydy = e->dz = 0;
-    e->buttons_state = buttons;
-}
-
-static void usb_pointer_event_combine(USBPointerEvent *e, int xyrel,
-                                      int x1, int y1, int z1) {
-    if (xyrel) {
-        e->xdx += x1;
-        e->ydy += y1;
-    } else {
-        e->xdx = x1;
-        e->ydy = y1;
-    }
-    e->dz += z1;
-}
-
-static void usb_pointer_event(void *opaque,
-                              int x1, int y1, int z1, int buttons_state)
-{
-    USBHIDState *hs = opaque;
-    USBMouseState *s = &hs->ptr;
-    unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
-    unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
-
-    /* We combine events where feasible to keep the queue small.  We shouldn't
-     * combine anything with the first event of a particular button state, as
-     * that would change the location of the button state change.  When the
-     * queue is empty, a second event is needed because we don't know if
-     * the first event changed the button state.  */
-    if (hs->n == QUEUE_LENGTH) {
-        /* Queue full.  Discard old button state, combine motion normally.  */
-        s->queue[use_slot].buttons_state = buttons_state;
-    } else if (hs->n < 2 ||
-               s->queue[use_slot].buttons_state != buttons_state ||
-               s->queue[previous_slot].buttons_state != s->queue[use_slot].buttons_state) {
-        /* Cannot or should not combine, so add an empty item to the queue.  */
-        QUEUE_INCR(use_slot);
-        hs->n++;
-        usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
-    }
-    usb_pointer_event_combine(&s->queue[use_slot],
-                              hs->kind == USB_MOUSE,
-                              x1, y1, z1);
-    usb_hid_changed(hs);
-}
-
-static void usb_keyboard_event(void *opaque, int keycode)
-{
-    USBHIDState *hs = opaque;
-    USBKeyboardState *s = &hs->kbd;
-    int slot;
-
-    if (hs->n == QUEUE_LENGTH) {
-        fprintf(stderr, "usb-kbd: warning: key event queue full\n");
-        return;
-    }
-    slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
-    s->keycodes[slot] = keycode;
-    usb_hid_changed(hs);
-}
-
-static void usb_keyboard_process_keycode(USBHIDState *hs)
-{
-    USBKeyboardState *s = &hs->kbd;
-    uint8_t hid_code, key;
-    int i, keycode, slot;
-
-    if (hs->n == 0) {
-        return;
-    }
-    slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
-    keycode = s->keycodes[slot];
-
-    key = keycode & 0x7f;
-    hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
-    s->modifiers &= ~(1 << 8);
-
-    switch (hid_code) {
-    case 0x00:
-        return;
-
-    case 0xe0:
-        if (s->modifiers & (1 << 9)) {
-            s->modifiers ^= 3 << 8;
-            return;
-        }
-    case 0xe1 ... 0xe7:
-        if (keycode & (1 << 7)) {
-            s->modifiers &= ~(1 << (hid_code & 0x0f));
-            return;
-        }
-    case 0xe8 ... 0xef:
-        s->modifiers |= 1 << (hid_code & 0x0f);
-        return;
-    }
-
-    if (keycode & (1 << 7)) {
-        for (i = s->keys - 1; i >= 0; i --)
-            if (s->key[i] == hid_code) {
-                s->key[i] = s->key[-- s->keys];
-                s->key[s->keys] = 0x00;
-                break;
-            }
-        if (i < 0)
-            return;
-    } else {
-        for (i = s->keys - 1; i >= 0; i --)
-            if (s->key[i] == hid_code)
-                break;
-        if (i < 0) {
-            if (s->keys < sizeof(s->key))
-                s->key[s->keys ++] = hid_code;
-        } else
-            return;
-    }
-}
-
-static inline int int_clamp(int val, int vmin, int vmax)
-{
-    if (val < vmin)
-        return vmin;
-    else if (val > vmax)
-        return vmax;
-    else
-        return val;
-}
-
-static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
-{
-    int dx, dy, dz, b, l;
-    int index;
-    USBMouseState *s = &hs->ptr;
-    USBPointerEvent *e;
-
-    if (!s->mouse_grabbed) {
-        qemu_activate_mouse_event_handler(s->eh_entry);
-        s->mouse_grabbed = 1;
-    }
-
-    /* When the buffer is empty, return the last event.  Relative
-       movements will all be zero.  */
-    index = (hs->n ? hs->head : hs->head - 1);
-    e = &s->queue[index & QUEUE_MASK];
-
-    if (hs->kind == USB_MOUSE) {
-        dx = int_clamp(e->xdx, -127, 127);
-        dy = int_clamp(e->ydy, -127, 127);
-        e->xdx -= dx;
-        e->ydy -= dy;
-    } else {
-        dx = e->xdx;
-        dy = e->ydy;
-    }
-    dz = int_clamp(e->dz, -127, 127);
-    e->dz -= dz;
-
-    b = 0;
-    if (e->buttons_state & MOUSE_EVENT_LBUTTON)
-        b |= 0x01;
-    if (e->buttons_state & MOUSE_EVENT_RBUTTON)
-        b |= 0x02;
-    if (e->buttons_state & MOUSE_EVENT_MBUTTON)
-        b |= 0x04;
-
-    if (hs->n &&
-        !e->dz &&
-        (hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
-        /* that deals with this event */
-        QUEUE_INCR(hs->head);
-        hs->n--;
-    }
-
-    /* Appears we have to invert the wheel direction */
-    dz = 0 - dz;
-    l = 0;
-    switch (hs->kind) {
-    case USB_MOUSE:
-        if (len > l)
-            buf[l++] = b;
-        if (len > l)
-            buf[l++] = dx;
-        if (len > l)
-            buf[l++] = dy;
-        if (len > l)
-            buf[l++] = dz;
-        break;
-
-    case USB_TABLET:
-        if (len > l)
-            buf[l++] = b;
-        if (len > l)
-            buf[l++] = dx & 0xff;
-        if (len > l)
-            buf[l++] = dx >> 8;
-        if (len > l)
-            buf[l++] = dy & 0xff;
-        if (len > l)
-            buf[l++] = dy >> 8;
-        if (len > l)
-            buf[l++] = dz;
-        break;
-
-    default:
-        abort();
-    }
-
-    return l;
-}
-
-static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
+static void usb_hid_changed(HIDState *hs)
 {
-    USBKeyboardState *s = &hs->kbd;
-    if (len < 2)
-        return 0;
-
-    usb_keyboard_process_keycode(hs);
+    USBHIDState *us = container_of(hs, USBHIDState, hid);
 
-    buf[0] = s->modifiers & 0xff;
-    buf[1] = 0;
-    if (s->keys > 6)
-        memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
-    else
-        memcpy(buf + 2, s->key, MIN(8, len) - 2);
-
-    return MIN(8, len);
-}
-
-static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
-{
-    if (len > 0) {
-        int ledstate = 0;
-        /* 0x01: Num Lock LED
-         * 0x02: Caps Lock LED
-         * 0x04: Scroll Lock LED
-         * 0x08: Compose LED
-         * 0x10: Kana LED */
-        s->leds = buf[0];
-        if (s->leds & 0x04)
-            ledstate |= QEMU_SCROLL_LOCK_LED;
-        if (s->leds & 0x01)
-            ledstate |= QEMU_NUM_LOCK_LED;
-        if (s->leds & 0x02)
-            ledstate |= QEMU_CAPS_LOCK_LED;
-        kbd_put_ledstate(ledstate);
+    if (us->datain) {
+        us->datain(us->datain_opaque);
     }
-    return 0;
-}
 
-static void usb_mouse_handle_reset(USBDevice *dev)
-{
-    USBHIDState *s = (USBHIDState *)dev;
-
-    memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
-    s->head = 0;
-    s->n = 0;
-    s->protocol = 1;
+    usb_wakeup(&us->dev);
 }
 
-static void usb_keyboard_handle_reset(USBDevice *dev)
+static void usb_hid_handle_reset(USBDevice *dev)
 {
-    USBHIDState *s = (USBHIDState *)dev;
+    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
 
-    qemu_add_kbd_event_handler(usb_keyboard_event, s);
-    memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
-    s->head = 0;
-    s->n = 0;
-    memset(s->kbd.key, 0, sizeof (s->kbd.key));
-    s->kbd.keys = 0;
-    s->protocol = 1;
-}
-
-static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
-{
-    s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
+    hid_reset(&us->hid);
 }
 
 static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
                int request, int value, int index, int length, uint8_t *data)
 {
-    USBHIDState *s = (USBHIDState *)dev;
+    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+    HIDState *hs = &us->hid;
     int ret;
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
@@ -735,7 +389,7 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
     }
 
     ret = 0;
-    switch(request) {
+    switch (request) {
     case DeviceRequest | USB_REQ_GET_INTERFACE:
         data[0] = 0;
         ret = 1;
@@ -745,17 +399,17 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
         break;
         /* hid specific requests */
     case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
-        switch(value >> 8) {
+        switch (value >> 8) {
         case 0x22:
-           if (s->kind == USB_MOUSE) {
+            if (hs->kind == HID_MOUSE) {
                memcpy(data, qemu_mouse_hid_report_descriptor,
                       sizeof(qemu_mouse_hid_report_descriptor));
                ret = sizeof(qemu_mouse_hid_report_descriptor);
-           } else if (s->kind == USB_TABLET) {
-               memcpy(data, qemu_tablet_hid_report_descriptor,
+            } else if (hs->kind == HID_TABLET) {
+                memcpy(data, qemu_tablet_hid_report_descriptor,
                       sizeof(qemu_tablet_hid_report_descriptor));
                ret = sizeof(qemu_tablet_hid_report_descriptor);
-            } else if (s->kind == USB_KEYBOARD) {
+            } else if (hs->kind == HID_KEYBOARD) {
                 memcpy(data, qemu_keyboard_hid_report_descriptor,
                        sizeof(qemu_keyboard_hid_report_descriptor));
                 ret = sizeof(qemu_keyboard_hid_report_descriptor);
@@ -766,38 +420,40 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
         }
         break;
     case GET_REPORT:
-        if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
-            ret = usb_pointer_poll(s, data, length);
-        } else if (s->kind == USB_KEYBOARD) {
-            ret = usb_keyboard_poll(s, data, length);
+        if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
+            ret = hid_pointer_poll(hs, data, length);
+        } else if (hs->kind == HID_KEYBOARD) {
+            ret = hid_keyboard_poll(hs, data, length);
         }
-        s->changed = s->n > 0;
         break;
     case SET_REPORT:
-        if (s->kind == USB_KEYBOARD)
-            ret = usb_keyboard_write(&s->kbd, data, length);
-        else
+        if (hs->kind == HID_KEYBOARD) {
+            ret = hid_keyboard_write(hs, data, length);
+        } else {
             goto fail;
+        }
         break;
     case GET_PROTOCOL:
-        if (s->kind != USB_KEYBOARD && s->kind != USB_MOUSE)
+        if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
             goto fail;
+        }
         ret = 1;
-        data[0] = s->protocol;
+        data[0] = hs->protocol;
         break;
     case SET_PROTOCOL:
-        if (s->kind != USB_KEYBOARD && s->kind != USB_MOUSE)
+        if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
             goto fail;
+        }
         ret = 0;
-        s->protocol = value;
+        hs->protocol = value;
         break;
     case GET_IDLE:
         ret = 1;
-        data[0] = s->idle;
+        data[0] = hs->idle;
         break;
     case SET_IDLE:
-        s->idle = (uint8_t) (value >> 8);
-        usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
+        hs->idle = (uint8_t) (value >> 8);
+        hid_set_next_idle(hs, qemu_get_clock_ns(vm_clock));
         ret = 0;
         break;
     default:
@@ -810,23 +466,26 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
 
 static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
 {
-    USBHIDState *s = (USBHIDState *)dev;
+    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+    HIDState *hs = &us->hid;
+    uint8_t buf[p->iov.size];
     int ret = 0;
 
-    switch(p->pid) {
+    switch (p->pid) {
     case USB_TOKEN_IN:
         if (p->devep == 1) {
             int64_t curtime = qemu_get_clock_ns(vm_clock);
-            if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
+            if (!hid_has_events(hs) &&
+                (!hs->idle || hs->next_idle_clock - curtime > 0)) {
                 return USB_RET_NAK;
-            usb_hid_set_next_idle(s, curtime);
-            if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
-                ret = usb_pointer_poll(s, p->data, p->len);
             }
-            else if (s->kind == USB_KEYBOARD) {
-                ret = usb_keyboard_poll(s, p->data, p->len);
+            hid_set_next_idle(hs, curtime);
+            if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
+                ret = hid_pointer_poll(hs, buf, p->iov.size);
+            } else if (hs->kind == HID_KEYBOARD) {
+                ret = hid_keyboard_poll(hs, buf, p->iov.size);
             }
-            s->changed = s->n > 0;
+            usb_packet_copy(p, buf, ret);
         } else {
             goto fail;
         }
@@ -842,50 +501,33 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
 
 static void usb_hid_handle_destroy(USBDevice *dev)
 {
-    USBHIDState *s = (USBHIDState *)dev;
+    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
 
-    switch(s->kind) {
-    case USB_KEYBOARD:
-        qemu_remove_kbd_event_handler();
-        break;
-    default:
-        qemu_remove_mouse_event_handler(s->ptr.eh_entry);
-    }
+    hid_free(&us->hid);
 }
 
 static int usb_hid_initfn(USBDevice *dev, int kind)
 {
-    USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
+    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
 
     usb_desc_init(dev);
-    s->kind = kind;
-
-    if (s->kind == USB_MOUSE) {
-        s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
-                                                       0, "QEMU USB Mouse");
-    } else if (s->kind == USB_TABLET) {
-        s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
-                                                       1, "QEMU USB Tablet");
-    }
-
-    /* Force poll routine to be run and grab input the first time.  */
-    s->changed = 1;
+    hid_init(&us->hid, kind, usb_hid_changed);
     return 0;
 }
 
 static int usb_tablet_initfn(USBDevice *dev)
 {
-    return usb_hid_initfn(dev, USB_TABLET);
+    return usb_hid_initfn(dev, HID_TABLET);
 }
 
 static int usb_mouse_initfn(USBDevice *dev)
 {
-    return usb_hid_initfn(dev, USB_MOUSE);
+    return usb_hid_initfn(dev, HID_MOUSE);
 }
 
 static int usb_keyboard_initfn(USBDevice *dev)
 {
-    return usb_hid_initfn(dev, USB_KEYBOARD);
+    return usb_hid_initfn(dev, HID_KEYBOARD);
 }
 
 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
@@ -900,8 +542,8 @@ static int usb_hid_post_load(void *opaque, int version_id)
 {
     USBHIDState *s = opaque;
 
-    if (s->idle) {
-        usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
+    if (s->hid.idle) {
+        hid_set_next_idle(&s->hid, qemu_get_clock_ns(vm_clock));
     }
     return 0;
 }
@@ -911,10 +553,10 @@ static const VMStateDescription vmstate_usb_ptr_queue = {
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField []) {
-        VMSTATE_INT32(xdx, USBPointerEvent),
-        VMSTATE_INT32(ydy, USBPointerEvent),
-        VMSTATE_INT32(dz, USBPointerEvent),
-        VMSTATE_INT32(buttons_state, USBPointerEvent),
+        VMSTATE_INT32(xdx, HIDPointerEvent),
+        VMSTATE_INT32(ydy, HIDPointerEvent),
+        VMSTATE_INT32(dz, HIDPointerEvent),
+        VMSTATE_INT32(buttons_state, HIDPointerEvent),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -925,12 +567,12 @@ static const VMStateDescription vmstate_usb_ptr = {
     .post_load = usb_hid_post_load,
     .fields = (VMStateField []) {
         VMSTATE_USB_DEVICE(dev, USBHIDState),
-        VMSTATE_STRUCT_ARRAY(ptr.queue, USBHIDState, QUEUE_LENGTH, 0,
-                             vmstate_usb_ptr_queue, USBPointerEvent),
-        VMSTATE_UINT32(head, USBHIDState),
-        VMSTATE_UINT32(n, USBHIDState),
-        VMSTATE_INT32(protocol, USBHIDState),
-        VMSTATE_UINT8(idle, USBHIDState),
+        VMSTATE_STRUCT_ARRAY(hid.ptr.queue, USBHIDState, QUEUE_LENGTH, 0,
+                             vmstate_usb_ptr_queue, HIDPointerEvent),
+        VMSTATE_UINT32(hid.head, USBHIDState),
+        VMSTATE_UINT32(hid.n, USBHIDState),
+        VMSTATE_INT32(hid.protocol, USBHIDState),
+        VMSTATE_UINT8(hid.idle, USBHIDState),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -942,15 +584,15 @@ static const VMStateDescription vmstate_usb_kbd = {
     .post_load = usb_hid_post_load,
     .fields = (VMStateField []) {
         VMSTATE_USB_DEVICE(dev, USBHIDState),
-        VMSTATE_UINT32_ARRAY(kbd.keycodes, USBHIDState, QUEUE_LENGTH),
-        VMSTATE_UINT32(head, USBHIDState),
-        VMSTATE_UINT32(n, USBHIDState),
-        VMSTATE_UINT16(kbd.modifiers, USBHIDState),
-        VMSTATE_UINT8(kbd.leds, USBHIDState),
-        VMSTATE_UINT8_ARRAY(kbd.key, USBHIDState, 16),
-        VMSTATE_INT32(kbd.keys, USBHIDState),
-        VMSTATE_INT32(protocol, USBHIDState),
-        VMSTATE_UINT8(idle, USBHIDState),
+        VMSTATE_UINT32_ARRAY(hid.kbd.keycodes, USBHIDState, QUEUE_LENGTH),
+        VMSTATE_UINT32(hid.head, USBHIDState),
+        VMSTATE_UINT32(hid.n, USBHIDState),
+        VMSTATE_UINT16(hid.kbd.modifiers, USBHIDState),
+        VMSTATE_UINT8(hid.kbd.leds, USBHIDState),
+        VMSTATE_UINT8_ARRAY(hid.kbd.key, USBHIDState, 16),
+        VMSTATE_INT32(hid.kbd.keys, USBHIDState),
+        VMSTATE_INT32(hid.protocol, USBHIDState),
+        VMSTATE_UINT8(hid.idle, USBHIDState),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -965,7 +607,7 @@ static struct USBDeviceInfo hid_info[] = {
         .usb_desc       = &desc_tablet,
         .init           = usb_tablet_initfn,
         .handle_packet  = usb_generic_handle_packet,
-        .handle_reset   = usb_mouse_handle_reset,
+        .handle_reset   = usb_hid_handle_reset,
         .handle_control = usb_hid_handle_control,
         .handle_data    = usb_hid_handle_data,
         .handle_destroy = usb_hid_handle_destroy,
@@ -978,7 +620,7 @@ static struct USBDeviceInfo hid_info[] = {
         .usb_desc       = &desc_mouse,
         .init           = usb_mouse_initfn,
         .handle_packet  = usb_generic_handle_packet,
-        .handle_reset   = usb_mouse_handle_reset,
+        .handle_reset   = usb_hid_handle_reset,
         .handle_control = usb_hid_handle_control,
         .handle_data    = usb_hid_handle_data,
         .handle_destroy = usb_hid_handle_destroy,
@@ -991,7 +633,7 @@ static struct USBDeviceInfo hid_info[] = {
         .usb_desc       = &desc_keyboard,
         .init           = usb_keyboard_initfn,
         .handle_packet  = usb_generic_handle_packet,
-        .handle_reset   = usb_keyboard_handle_reset,
+        .handle_reset   = usb_hid_handle_reset,
         .handle_control = usb_hid_handle_control,
         .handle_data    = usb_hid_handle_data,
         .handle_destroy = usb_hid_handle_destroy,
index b49a2fe8826d90b7cc61ee1f4e1aa69cb13f5a85..c49c547d0cfaebef2a1a5533ec46f41df7ea2c5c 100644 (file)
@@ -394,11 +394,12 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
         if (p->devep == 1) {
             USBHubPort *port;
             unsigned int status;
+            uint8_t buf[4];
             int i, n;
             n = (NUM_PORTS + 1 + 7) / 8;
-            if (p->len == 1) { /* FreeBSD workaround */
+            if (p->iov.size == 1) { /* FreeBSD workaround */
                 n = 1;
-            } else if (n > p->len) {
+            } else if (n > p->iov.size) {
                 return USB_RET_BABBLE;
             }
             status = 0;
@@ -409,8 +410,9 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
             }
             if (status != 0) {
                 for(i = 0; i < n; i++) {
-                    p->data[i] = status >> (8 * i);
+                    buf[i] = status >> (8 * i);
                 }
+                usb_packet_copy(p, buf, n);
                 ret = n;
             } else {
                 ret = USB_RET_NAK; /* usb11 11.13.1 */
diff --git a/hw/usb-libhw.c b/hw/usb-libhw.c
new file mode 100644 (file)
index 0000000..162b42b
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * QEMU USB emulation, libhw bits.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu-common.h"
+#include "cpu-common.h"
+#include "usb.h"
+#include "dma.h"
+
+int usb_packet_map(USBPacket *p, QEMUSGList *sgl)
+{
+    int is_write = (p->pid == USB_TOKEN_IN);
+    target_phys_addr_t len;
+    void *mem;
+    int i;
+
+    for (i = 0; i < sgl->nsg; i++) {
+        len = sgl->sg[i].len;
+        mem = cpu_physical_memory_map(sgl->sg[i].base, &len,
+                                      is_write);
+        if (!mem) {
+            goto err;
+        }
+        qemu_iovec_add(&p->iov, mem, len);
+        if (len != sgl->sg[i].len) {
+            goto err;
+        }
+    }
+    return 0;
+
+err:
+    usb_packet_unmap(p);
+    return -1;
+}
+
+void usb_packet_unmap(USBPacket *p)
+{
+    int is_write = (p->pid == USB_TOKEN_IN);
+    int i;
+
+    for (i = 0; i < p->iov.niov; i++) {
+        cpu_physical_memory_unmap(p->iov.iov[i].iov_base,
+                                  p->iov.iov[i].iov_len, is_write,
+                                  p->iov.iov[i].iov_len);
+    }
+}
index 6391dad108ef58f8d16ecf947b5044c44e5ec1d0..90e57fbf6ba64ea069c2c9e139fe4b7ac1385451 100644 (file)
@@ -43,8 +43,6 @@ typedef struct {
     enum USBMSDMode mode;
     uint32_t scsi_len;
     uint8_t *scsi_buf;
-    uint32_t usb_len;
-    uint8_t *usb_buf;
     uint32_t data_len;
     uint32_t residue;
     uint32_t tag;
@@ -176,20 +174,14 @@ static const USBDesc desc = {
     .str  = desc_strings,
 };
 
-static void usb_msd_copy_data(MSDState *s)
+static void usb_msd_copy_data(MSDState *s, USBPacket *p)
 {
     uint32_t len;
-    len = s->usb_len;
+    len = p->iov.size - p->result;
     if (len > s->scsi_len)
         len = s->scsi_len;
-    if (s->mode == USB_MSDM_DATAIN) {
-        memcpy(s->usb_buf, s->scsi_buf, len);
-    } else {
-        memcpy(s->scsi_buf, s->usb_buf, len);
-    }
-    s->usb_len -= len;
+    usb_packet_copy(p, s->scsi_buf, len);
     s->scsi_len -= len;
-    s->usb_buf += len;
     s->scsi_buf += len;
     s->data_len -= len;
     if (s->scsi_len == 0 || s->data_len == 0) {
@@ -207,8 +199,9 @@ static void usb_msd_send_status(MSDState *s, USBPacket *p)
     csw.residue = s->residue;
     csw.status = s->result;
 
-    len = MIN(sizeof(csw), p->len);
-    memcpy(p->data, &csw, len);
+    len = MIN(sizeof(csw), p->iov.size);
+    usb_packet_copy(p, &csw, len);
+    p->result = len;
 }
 
 static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
@@ -220,8 +213,9 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
     s->scsi_len = len;
     s->scsi_buf = scsi_req_get_buf(req);
     if (p) {
-        usb_msd_copy_data(s);
-        if (s->packet && s->usb_len == 0) {
+        usb_msd_copy_data(s, p);
+        p = s->packet;
+        if (p && p->result == p->iov.size) {
             /* Set s->packet to NULL before calling usb_packet_complete
                because another request may be issued before
                usb_packet_complete returns.  */
@@ -248,11 +242,9 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status)
             s->mode = USB_MSDM_CBW;
         } else {
             if (s->data_len) {
-                s->data_len -= s->usb_len;
-                if (s->mode == USB_MSDM_DATAIN) {
-                    memset(s->usb_buf, 0, s->usb_len);
-                }
-                s->usb_len = 0;
+                int len = (p->iov.size - p->result);
+                usb_packet_skip(p, len);
+                s->data_len -= len;
             }
             if (s->data_len == 0) {
                 s->mode = USB_MSDM_CSW;
@@ -342,8 +334,6 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
     int ret = 0;
     struct usb_msd_cbw cbw;
     uint8_t devep = p->devep;
-    uint8_t *data = p->data;
-    int len = p->len;
 
     switch (p->pid) {
     case USB_TOKEN_OUT:
@@ -352,11 +342,11 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
 
         switch (s->mode) {
         case USB_MSDM_CBW:
-            if (len != 31) {
+            if (p->iov.size != 31) {
                 fprintf(stderr, "usb-msd: Bad CBW size");
                 goto fail;
             }
-            memcpy(&cbw, data, 31);
+            usb_packet_copy(p, &cbw, 31);
             if (le32_to_cpu(cbw.sig) != 0x43425355) {
                 fprintf(stderr, "usb-msd: Bad signature %08x\n",
                         le32_to_cpu(cbw.sig));
@@ -387,36 +377,39 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             if (s->mode != USB_MSDM_CSW && s->residue == 0) {
                 scsi_req_continue(s->req);
             }
-            ret = len;
+            ret = p->result;
             break;
 
         case USB_MSDM_DATAOUT:
-            DPRINTF("Data out %d/%d\n", len, s->data_len);
-            if (len > s->data_len)
+            DPRINTF("Data out %zd/%d\n", p->iov.size, s->data_len);
+            if (p->iov.size > s->data_len) {
                 goto fail;
+            }
 
-            s->usb_buf = data;
-            s->usb_len = len;
             if (s->scsi_len) {
-                usb_msd_copy_data(s);
+                usb_msd_copy_data(s, p);
             }
-            if (s->residue && s->usb_len) {
-                s->data_len -= s->usb_len;
-                if (s->data_len == 0)
-                    s->mode = USB_MSDM_CSW;
-                s->usb_len = 0;
+            if (s->residue) {
+                int len = p->iov.size - p->result;
+                if (len) {
+                    usb_packet_skip(p, len);
+                    s->data_len -= len;
+                    if (s->data_len == 0) {
+                        s->mode = USB_MSDM_CSW;
+                    }
+                }
             }
-            if (s->usb_len) {
+            if (p->result < p->iov.size) {
                 DPRINTF("Deferring packet %p\n", p);
                 s->packet = p;
                 ret = USB_RET_ASYNC;
             } else {
-                ret = len;
+                ret = p->result;
             }
             break;
 
         default:
-            DPRINTF("Unexpected write (len %d)\n", len);
+            DPRINTF("Unexpected write (len %zd)\n", p->iov.size);
             goto fail;
         }
         break;
@@ -427,18 +420,20 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
 
         switch (s->mode) {
         case USB_MSDM_DATAOUT:
-            if (s->data_len != 0 || len < 13)
+            if (s->data_len != 0 || p->iov.size < 13) {
                 goto fail;
+            }
             /* Waiting for SCSI write to complete.  */
             s->packet = p;
             ret = USB_RET_ASYNC;
             break;
 
         case USB_MSDM_CSW:
-            DPRINTF("Command status %d tag 0x%x, len %d\n",
-                    s->result, s->tag, len);
-            if (len < 13)
+            DPRINTF("Command status %d tag 0x%x, len %zd\n",
+                    s->result, s->tag, p->iov.size);
+            if (p->iov.size < 13) {
                 goto fail;
+            }
 
             usb_msd_send_status(s, p);
             s->mode = USB_MSDM_CBW;
@@ -446,32 +441,32 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             break;
 
         case USB_MSDM_DATAIN:
-            DPRINTF("Data in %d/%d, scsi_len %d\n", len, s->data_len, s->scsi_len);
-            if (len > s->data_len)
-                len = s->data_len;
-            s->usb_buf = data;
-            s->usb_len = len;
+            DPRINTF("Data in %zd/%d, scsi_len %d\n",
+                    p->iov.size, s->data_len, s->scsi_len);
             if (s->scsi_len) {
-                usb_msd_copy_data(s);
+                usb_msd_copy_data(s, p);
             }
-            if (s->residue && s->usb_len) {
-                s->data_len -= s->usb_len;
-                memset(s->usb_buf, 0, s->usb_len);
-                if (s->data_len == 0)
-                    s->mode = USB_MSDM_CSW;
-                s->usb_len = 0;
+            if (s->residue) {
+                int len = p->iov.size - p->result;
+                if (len) {
+                    usb_packet_skip(p, len);
+                    s->data_len -= len;
+                    if (s->data_len == 0) {
+                        s->mode = USB_MSDM_CSW;
+                    }
+                }
             }
-            if (s->usb_len) {
+            if (p->result < p->iov.size) {
                 DPRINTF("Deferring packet %p\n", p);
                 s->packet = p;
                 ret = USB_RET_ASYNC;
             } else {
-                ret = len;
+                ret = p->result;
             }
             break;
 
         default:
-            DPRINTF("Unexpected read (len %d)\n", len);
+            DPRINTF("Unexpected read (len %zd)\n", p->iov.size);
             goto fail;
         }
         break;
@@ -616,11 +611,23 @@ static USBDevice *usb_msd_init(const char *filename)
     return dev;
 }
 
+static const VMStateDescription vmstate_usb_msd = {
+    .name = "usb-storage",
+    .unmigratable = 1, /* FIXME: handle transactions which are in flight */
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_USB_DEVICE(dev, MSDState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static struct USBDeviceInfo msd_info = {
     .product_desc   = "QEMU USB MSD",
     .qdev.name      = "usb-storage",
     .qdev.fw_name      = "storage",
     .qdev.size      = sizeof(MSDState),
+    .qdev.vmsd      = &vmstate_usb_msd,
     .usb_desc       = &desc,
     .init           = usb_msd_initfn,
     .handle_packet  = usb_generic_handle_packet,
index 035dda83725fa96201a09342554507b88e24033d..d3ccde91996aaecf4b14b3900397586914413475 100644 (file)
@@ -365,6 +365,8 @@ struct MUSBState *musb_init(qemu_irq *irqs)
         s->ep[i].maxp[1] = 0x40;
         s->ep[i].musb = s;
         s->ep[i].epnum = i;
+        usb_packet_init(&s->ep[i].packey[0].p);
+        usb_packet_init(&s->ep[i].packey[1].p);
     }
 
     usb_bus_new(&s->bus, &musb_bus_ops, NULL /* FIXME */);
@@ -605,12 +607,10 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
     ep->interrupt[dir] = ttype == USB_ENDPOINT_XFER_INT;
     ep->delayed_cb[dir] = cb;
 
-    ep->packey[dir].p.pid = pid;
     /* A wild guess on the FADDR semantics... */
-    ep->packey[dir].p.devaddr = ep->faddr[idx];
-    ep->packey[dir].p.devep = ep->type[idx] & 0xf;
-    ep->packey[dir].p.data = (void *) ep->buf[idx];
-    ep->packey[dir].p.len = len;
+    usb_packet_setup(&ep->packey[dir].p, pid, ep->faddr[idx],
+                     ep->type[idx] & 0xf);
+    usb_packet_addbuf(&ep->packey[dir].p, ep->buf[idx], len);
     ep->packey[dir].ep = ep;
     ep->packey[dir].dir = dir;
 
@@ -738,7 +738,7 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
 
     if (ep->status[1] == USB_RET_STALL) {
         ep->status[1] = 0;
-        packey->len = 0;
+        packey->result = 0;
 
         ep->csr[1] |= MGC_M_RXCSR_H_RXSTALL;
         if (!epnum)
@@ -752,7 +752,7 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
          * Data-errors in Isochronous.  */
         if (ep->interrupt[1])
             return musb_packet(s, ep, epnum, USB_TOKEN_IN,
-                            packey->len, musb_rx_packet_complete, 1);
+                            packey->iov.size, musb_rx_packet_complete, 1);
 
         ep->csr[1] |= MGC_M_RXCSR_DATAERROR;
         if (!epnum)
@@ -777,14 +777,14 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
     /* TODO: check len for over/underruns of an OUT packet?  */
     /* TODO: perhaps make use of e->ext_size[1] here.  */
 
-    packey->len = ep->status[1];
+    packey->result = ep->status[1];
 
     if (!(ep->csr[1] & (MGC_M_RXCSR_H_RXSTALL | MGC_M_RXCSR_DATAERROR))) {
         ep->csr[1] |= MGC_M_RXCSR_FIFOFULL | MGC_M_RXCSR_RXPKTRDY;
         if (!epnum)
             ep->csr[0] |= MGC_M_CSR0_RXPKTRDY;
 
-        ep->rxcount = packey->len; /* XXX: MIN(packey->len, ep->maxp[1]); */
+        ep->rxcount = packey->result; /* XXX: MIN(packey->len, ep->maxp[1]); */
         /* In DMA mode: assert DMA request for this EP */
     }
 
@@ -856,12 +856,12 @@ static void musb_rx_req(MUSBState *s, int epnum)
      * 64 bytes of the FIFO, only move the FIFO start and return. (Obsolete) */
     if (ep->packey[1].p.pid == USB_TOKEN_IN && ep->status[1] >= 0 &&
                     (ep->fifostart[1]) + ep->rxcount <
-                    ep->packey[1].p.len) {
+                    ep->packey[1].p.iov.size) {
         TRACE("0x%08x, %d",  ep->fifostart[1], ep->rxcount );
         ep->fifostart[1] += ep->rxcount;
         ep->fifolen[1] = 0;
 
-        ep->rxcount = MIN(ep->packey[0].p.len - (ep->fifostart[1]),
+        ep->rxcount = MIN(ep->packey[0].p.iov.size - (ep->fifostart[1]),
                         ep->maxp[1]);
 
         ep->csr[1] &= ~MGC_M_RXCSR_H_REQPKT;
index 9be709f7cfdb762c60e1dec0ec3ff24590f33514..0cb47d63b33269fc0026e1898d7395ecfb143372 100644 (file)
@@ -29,6 +29,7 @@
 #include "net.h"
 #include "qemu-queue.h"
 #include "sysemu.h"
+#include "iov.h"
 
 /*#define TRAFFIC_DEBUG*/
 /* Thanks to NetChip Technologies for donating this product ID.
@@ -1121,28 +1122,23 @@ static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
 
 static int usb_net_handle_statusin(USBNetState *s, USBPacket *p)
 {
+    le32 buf[2];
     int ret = 8;
 
-    if (p->len < 8)
+    if (p->iov.size < 8) {
         return USB_RET_STALL;
+    }
 
-    ((le32 *) p->data)[0] = cpu_to_le32(1);
-    ((le32 *) p->data)[1] = cpu_to_le32(0);
+    buf[0] = cpu_to_le32(1);
+    buf[1] = cpu_to_le32(0);
+    usb_packet_copy(p, buf, 8);
     if (!s->rndis_resp.tqh_first)
         ret = USB_RET_NAK;
 
 #ifdef TRAFFIC_DEBUG
-    fprintf(stderr, "usbnet: interrupt poll len %u return %d", p->len, ret);
-    {
-        int i;
-        fprintf(stderr, ":");
-        for (i = 0; i < ret; i++) {
-            if (!(i & 15))
-                fprintf(stderr, "\n%04x:", i);
-            fprintf(stderr, " %02x", p->data[i]);
-        }
-        fprintf(stderr, "\n\n");
-    }
+    fprintf(stderr, "usbnet: interrupt poll len %zu return %d",
+            p->iov.size, ret);
+    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", ret);
 #endif
 
     return ret;
@@ -1162,9 +1158,10 @@ static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
         return ret;
     }
     ret = s->in_len - s->in_ptr;
-    if (ret > p->len)
-        ret = p->len;
-    memcpy(p->data, &s->in_buf[s->in_ptr], ret);
+    if (ret > p->iov.size) {
+        ret = p->iov.size;
+    }
+    usb_packet_copy(p, &s->in_buf[s->in_ptr], ret);
     s->in_ptr += ret;
     if (s->in_ptr >= s->in_len &&
                     (is_rndis(s) || (s->in_len & (64 - 1)) || !ret)) {
@@ -1173,17 +1170,8 @@ static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
     }
 
 #ifdef TRAFFIC_DEBUG
-    fprintf(stderr, "usbnet: data in len %u return %d", p->len, ret);
-    {
-        int i;
-        fprintf(stderr, ":");
-        for (i = 0; i < ret; i++) {
-            if (!(i & 15))
-                fprintf(stderr, "\n%04x:", i);
-            fprintf(stderr, " %02x", p->data[i]);
-        }
-        fprintf(stderr, "\n\n");
-    }
+    fprintf(stderr, "usbnet: data in len %zu return %d", p->iov.size, ret);
+    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", ret);
 #endif
 
     return ret;
@@ -1191,29 +1179,20 @@ static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
 
 static int usb_net_handle_dataout(USBNetState *s, USBPacket *p)
 {
-    int ret = p->len;
+    int ret = p->iov.size;
     int sz = sizeof(s->out_buf) - s->out_ptr;
     struct rndis_packet_msg_type *msg =
             (struct rndis_packet_msg_type *) s->out_buf;
     uint32_t len;
 
 #ifdef TRAFFIC_DEBUG
-    fprintf(stderr, "usbnet: data out len %u\n", p->len);
-    {
-        int i;
-        fprintf(stderr, ":");
-        for (i = 0; i < p->len; i++) {
-            if (!(i & 15))
-                fprintf(stderr, "\n%04x:", i);
-            fprintf(stderr, " %02x", p->data[i]);
-        }
-        fprintf(stderr, "\n\n");
-    }
+    fprintf(stderr, "usbnet: data out len %zu\n", p->iov.size);
+    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", p->iov.size);
 #endif
 
     if (sz > ret)
         sz = ret;
-    memcpy(&s->out_buf[s->out_ptr], p->data, sz);
+    usb_packet_copy(p, &s->out_buf[s->out_ptr], sz);
     s->out_ptr += sz;
 
     if (!is_rndis(s)) {
@@ -1277,8 +1256,8 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
     }
     if (ret == USB_RET_STALL)
         fprintf(stderr, "usbnet: failed data transaction: "
-                        "pid 0x%x ep 0x%x len 0x%x\n",
-                        p->pid, p->devep, p->len);
+                        "pid 0x%x ep 0x%x len 0x%zx\n",
+                        p->pid, p->devep, p->iov.size);
     return ret;
 }
 
@@ -1414,11 +1393,17 @@ static USBDevice *usb_net_init(const char *cmdline)
     return dev;
 }
 
+static const VMStateDescription vmstate_usb_net = {
+    .name = "usb-net",
+    .unmigratable = 1,
+};
+
 static struct USBDeviceInfo net_info = {
     .product_desc   = "QEMU USB Network Interface",
     .qdev.name      = "usb-net",
     .qdev.fw_name    = "network",
     .qdev.size      = sizeof(USBNetState),
+    .qdev.vmsd      = &vmstate_usb_net,
     .usb_desc       = &desc_net,
     .init           = usb_net_initfn,
     .handle_packet  = usb_generic_handle_packet,
index 8491d599280b55442975b79dd6e1cc401685899a..d30db3f92f069f47ce68cb5888fe6fe7c0dd90af 100644 (file)
@@ -62,7 +62,7 @@ typedef struct OHCIPort {
 typedef struct {
     USBBus bus;
     qemu_irq irq;
-    int mem;
+    MemoryRegion mem;
     int num_ports;
     const char *name;
 
@@ -777,18 +777,17 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
     }
 
     if (completion) {
-        ret = ohci->usb_packet.len;
+        ret = ohci->usb_packet.result;
     } else {
         ret = USB_RET_NODEV;
         for (i = 0; i < ohci->num_ports; i++) {
             dev = ohci->rhport[i].port.dev;
             if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0)
                 continue;
-            ohci->usb_packet.pid = pid;
-            ohci->usb_packet.devaddr = OHCI_BM(ed->flags, ED_FA);
-            ohci->usb_packet.devep = OHCI_BM(ed->flags, ED_EN);
-            ohci->usb_packet.data = ohci->usb_buf;
-            ohci->usb_packet.len = len;
+            usb_packet_setup(&ohci->usb_packet, pid,
+                             OHCI_BM(ed->flags, ED_FA),
+                             OHCI_BM(ed->flags, ED_EN));
+            usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
             ret = usb_handle_packet(dev, &ohci->usb_packet);
             if (ret != USB_RET_NODEV)
                 break;
@@ -959,7 +958,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
     }
 #endif
     if (completion) {
-        ret = ohci->usb_packet.len;
+        ret = ohci->usb_packet.result;
         ohci->async_td = 0;
         ohci->async_complete = 0;
     } else {
@@ -980,11 +979,10 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
 #endif
                 return 1;
             }
-            ohci->usb_packet.pid = pid;
-            ohci->usb_packet.devaddr = OHCI_BM(ed->flags, ED_FA);
-            ohci->usb_packet.devep = OHCI_BM(ed->flags, ED_EN);
-            ohci->usb_packet.data = ohci->usb_buf;
-            ohci->usb_packet.len = len;
+            usb_packet_setup(&ohci->usb_packet, pid,
+                             OHCI_BM(ed->flags, ED_FA),
+                             OHCI_BM(ed->flags, ED_EN));
+            usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
             ret = usb_handle_packet(dev, &ohci->usb_packet);
             if (ret != USB_RET_NODEV)
                 break;
@@ -1440,13 +1438,13 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
     return;
 }
 
-static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
+static uint64_t ohci_mem_read(void *opaque,
+                              target_phys_addr_t addr,
+                              unsigned size)
 {
-    OHCIState *ohci = ptr;
+    OHCIState *ohci = opaque;
     uint32_t retval;
 
-    addr &= 0xff;
-
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
         fprintf(stderr, "usb-ohci: Mis-aligned read\n");
@@ -1563,11 +1561,12 @@ static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
     return retval;
 }
 
-static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
+static void ohci_mem_write(void *opaque,
+                           target_phys_addr_t addr,
+                           uint64_t val,
+                           unsigned size)
 {
-    OHCIState *ohci = ptr;
-
-    addr &= 0xff;
+    OHCIState *ohci = opaque;
 
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
@@ -1697,18 +1696,10 @@ static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
     }
 }
 
-/* Only dword reads are defined on OHCI register space */
-static CPUReadMemoryFunc * const ohci_readfn[3]={
-    ohci_mem_read,
-    ohci_mem_read,
-    ohci_mem_read
-};
-
-/* Only dword writes are defined on OHCI register space */
-static CPUWriteMemoryFunc * const ohci_writefn[3]={
-    ohci_mem_write,
-    ohci_mem_write,
-    ohci_mem_write
+static const MemoryRegionOps ohci_mem_ops = {
+    .read = ohci_mem_read,
+    .write = ohci_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static USBPortOps ohci_port_ops = {
@@ -1764,11 +1755,11 @@ static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
         }
     }
 
-    ohci->mem = cpu_register_io_memory(ohci_readfn, ohci_writefn, ohci,
-                                       DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256);
     ohci->localmem_base = localmem_base;
 
     ohci->name = dev->info->name;
+    usb_packet_init(&ohci->usb_packet);
 
     ohci->async_td = 0;
     qemu_register_reset(ohci_reset, ohci);
@@ -1799,7 +1790,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
     ohci->state.irq = ohci->pci_dev.irq[0];
 
     /* TODO: avoid cast below by using dev */
-    pci_register_bar_simple(&ohci->pci_dev, 0, 256, 0, ohci->state.mem);
+    pci_register_bar(&ohci->pci_dev, 0, 0, &ohci->state.mem);
     return 0;
 }
 
@@ -1822,7 +1813,7 @@ static int ohci_init_pxa(SysBusDevice *dev)
     /* Cannot fail as we pass NULL for masterbus */
     usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0);
     sysbus_init_irq(dev, &s->ohci.irq);
-    sysbus_init_mmio(dev, 0x1000, s->ohci.mem);
+    sysbus_init_mmio_region(dev, &s->ohci.mem);
 
     return 0;
 }
index c69c4374e178dfad851a2ed56660c480b1923a92..bf2b775e83c7844d174a0020b8f1ed4a711ef716 100644 (file)
@@ -359,37 +359,42 @@ static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
 static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBSerialState *s = (USBSerialState *)dev;
-    int ret = 0;
+    int i, ret = 0;
     uint8_t devep = p->devep;
-    uint8_t *data = p->data;
-    int len = p->len;
-    int first_len;
+    struct iovec *iov;
+    uint8_t header[2];
+    int first_len, len;
 
     switch (p->pid) {
     case USB_TOKEN_OUT:
         if (devep != 2)
             goto fail;
-        qemu_chr_write(s->cs, data, len);
+        for (i = 0; i < p->iov.niov; i++) {
+            iov = p->iov.iov + i;
+            qemu_chr_write(s->cs, iov->iov_base, iov->iov_len);
+        }
         break;
 
     case USB_TOKEN_IN:
         if (devep != 1)
             goto fail;
         first_len = RECV_BUF - s->recv_ptr;
+        len = p->iov.size;
         if (len <= 2) {
             ret = USB_RET_NAK;
             break;
         }
-        *data++ = usb_get_modem_lines(s) | 1;
+        header[0] = usb_get_modem_lines(s) | 1;
         /* We do not have the uart details */
         /* handle serial break */
         if (s->event_trigger && s->event_trigger & FTDI_BI) {
             s->event_trigger &= ~FTDI_BI;
-            *data = FTDI_BI;
+            header[1] = FTDI_BI;
+            usb_packet_copy(p, header, 2);
             ret = 2;
             break;
         } else {
-            *data++ = 0;
+            header[1] = 0;
         }
         len -= 2;
         if (len > s->recv_used)
@@ -400,9 +405,10 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
         }
         if (first_len > len)
             first_len = len;
-        memcpy(data, s->recv_buf + s->recv_ptr, first_len);
+        usb_packet_copy(p, header, 2);
+        usb_packet_copy(p, s->recv_buf + s->recv_ptr, first_len);
         if (len > first_len)
-            memcpy(data + first_len, s->recv_buf, len - first_len);
+            usb_packet_copy(p, s->recv_buf, len - first_len);
         s->recv_used -= len;
         s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
         ret = len + 2;
@@ -566,10 +572,16 @@ static USBDevice *usb_braille_init(const char *unused)
     return dev;
 }
 
+static const VMStateDescription vmstate_usb_serial = {
+    .name = "usb-serial",
+    .unmigratable = 1,
+};
+
 static struct USBDeviceInfo serial_info = {
     .product_desc   = "QEMU USB Serial",
     .qdev.name      = "usb-serial",
     .qdev.size      = sizeof(USBSerialState),
+    .qdev.vmsd      = &vmstate_usb_serial,
     .usb_desc       = &desc_serial,
     .init           = usb_serial_initfn,
     .handle_packet  = usb_generic_handle_packet,
@@ -589,6 +601,7 @@ static struct USBDeviceInfo braille_info = {
     .product_desc   = "QEMU USB Braille",
     .qdev.name      = "usb-braille",
     .qdev.size      = sizeof(USBSerialState),
+    .qdev.vmsd      = &vmstate_usb_serial,
     .usb_desc       = &desc_braille,
     .init           = usb_serial_initfn,
     .handle_packet  = usb_generic_handle_packet,
index da74c57c626b5ef61761a8002d4d68d7f8b367b8..16088d7dcaaf46df1273482b3a9ea3416b4e1685 100644 (file)
@@ -30,6 +30,8 @@
 #include "pci.h"
 #include "qemu-timer.h"
 #include "usb-uhci.h"
+#include "iov.h"
+#include "dma.h"
 
 //#define DEBUG
 //#define DEBUG_DUMP_DATA
@@ -93,17 +95,12 @@ static const char *pid2str(int pid)
 #endif
 
 #ifdef DEBUG_DUMP_DATA
-static void dump_data(const uint8_t *data, int len)
+static void dump_data(USBPacket *p, int ret)
 {
-    int i;
-
-    printf("uhci: data: ");
-    for(i = 0; i < len; i++)
-        printf(" %02x", data[i]);
-    printf("\n");
+    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "uhci", ret);
 }
 #else
-static void dump_data(const uint8_t *data, int len) {}
+static void dump_data(USBPacket *p, int ret) {}
 #endif
 
 typedef struct UHCIState UHCIState;
@@ -115,6 +112,7 @@ typedef struct UHCIState UHCIState;
  */
 typedef struct UHCIAsync {
     USBPacket packet;
+    QEMUSGList sgl;
     UHCIState *uhci;
     QTAILQ_ENTRY(UHCIAsync) next;
     uint32_t  td;
@@ -122,7 +120,6 @@ typedef struct UHCIAsync {
     int8_t    valid;
     uint8_t   isoc;
     uint8_t   done;
-    uint8_t   buffer[2048];
 } UHCIAsync;
 
 typedef struct UHCIPort {
@@ -132,6 +129,7 @@ typedef struct UHCIPort {
 
 struct UHCIState {
     PCIDevice dev;
+    MemoryRegion io_bar;
     USBBus bus; /* Note unused when we're a companion controller */
     uint16_t cmd; /* cmd register */
     uint16_t status;
@@ -179,12 +177,16 @@ static UHCIAsync *uhci_async_alloc(UHCIState *s)
     async->token = 0;
     async->done  = 0;
     async->isoc  = 0;
+    usb_packet_init(&async->packet);
+    qemu_sglist_init(&async->sgl, 1);
 
     return async;
 }
 
 static void uhci_async_free(UHCIState *s, UHCIAsync *async)
 {
+    usb_packet_cleanup(&async->packet);
+    qemu_sglist_destroy(&async->sgl);
     qemu_free(async);
 }
 
@@ -648,10 +650,10 @@ static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
 {
     int i, ret;
 
-    DPRINTF("uhci: packet enter. pid %s addr 0x%02x ep %d len %d\n",
-           pid2str(p->pid), p->devaddr, p->devep, p->len);
+    DPRINTF("uhci: packet enter. pid %s addr 0x%02x ep %d len %zd\n",
+           pid2str(p->pid), p->devaddr, p->devep, p->iov.size);
     if (p->pid == USB_TOKEN_OUT || p->pid == USB_TOKEN_SETUP)
-        dump_data(p->data, p->len);
+        dump_data(p, 0);
 
     ret = USB_RET_NODEV;
     for (i = 0; i < NB_PORTS && ret == USB_RET_NODEV; i++) {
@@ -662,9 +664,9 @@ static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
             ret = usb_handle_packet(dev, p);
     }
 
-    DPRINTF("uhci: packet exit. ret %d len %d\n", ret, p->len);
+    DPRINTF("uhci: packet exit. ret %d len %zd\n", ret, p->iov.size);
     if (p->pid == USB_TOKEN_IN && ret > 0)
-        dump_data(p->data, ret);
+        dump_data(p, ret);
 
     return ret;
 }
@@ -684,7 +686,7 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
     max_len = ((td->token >> 21) + 1) & 0x7ff;
     pid = td->token & 0xff;
 
-    ret = async->packet.len;
+    ret = async->packet.result;
 
     if (td->ctrl & TD_CTRL_IOS)
         td->ctrl &= ~TD_CTRL_ACTIVE;
@@ -692,7 +694,7 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
     if (ret < 0)
         goto out;
 
-    len = async->packet.len;
+    len = async->packet.result;
     td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
 
     /* The NAK bit may have been set by a previous frame, so clear it
@@ -708,11 +710,6 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
             goto out;
         }
 
-        if (len > 0) {
-            /* write the data back */
-            cpu_physical_memory_write(td->buffer, async->buffer, len);
-        }
-
         if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {
             *int_mask |= 0x02;
             /* short packet: do not update QH */
@@ -827,16 +824,14 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
     max_len = ((td->token >> 21) + 1) & 0x7ff;
     pid = td->token & 0xff;
 
-    async->packet.pid     = pid;
-    async->packet.devaddr = (td->token >> 8) & 0x7f;
-    async->packet.devep   = (td->token >> 15) & 0xf;
-    async->packet.data    = async->buffer;
-    async->packet.len     = max_len;
+    usb_packet_setup(&async->packet, pid, (td->token >> 8) & 0x7f,
+                     (td->token >> 15) & 0xf);
+    qemu_sglist_add(&async->sgl, td->buffer, max_len);
+    usb_packet_map(&async->packet, &async->sgl);
 
     switch(pid) {
     case USB_TOKEN_OUT:
     case USB_TOKEN_SETUP:
-        cpu_physical_memory_read(td->buffer, async->buffer, max_len);
         len = uhci_broadcast_packet(s, &async->packet);
         if (len >= 0)
             len = max_len;
@@ -859,10 +854,11 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
         return 2;
     }
 
-    async->packet.len = len;
+    async->packet.result = len;
 
 done:
     len = uhci_complete_td(s, td, async, int_mask);
+    usb_packet_unmap(&async->packet);
     uhci_async_free(s, async);
     return len;
 }
@@ -1101,18 +1097,19 @@ static void uhci_frame_timer(void *opaque)
     qemu_mod_timer(s->frame_timer, s->expire_time);
 }
 
-static void uhci_map(PCIDevice *pci_dev, int region_num,
-                    pcibus_t addr, pcibus_t size, int type)
-{
-    UHCIState *s = (UHCIState *)pci_dev;
-
-    register_ioport_write(addr, 32, 2, uhci_ioport_writew, s);
-    register_ioport_read(addr, 32, 2, uhci_ioport_readw, s);
-    register_ioport_write(addr, 32, 4, uhci_ioport_writel, s);
-    register_ioport_read(addr, 32, 4, uhci_ioport_readl, s);
-    register_ioport_write(addr, 32, 1, uhci_ioport_writeb, s);
-    register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
-}
+static const MemoryRegionPortio uhci_portio[] = {
+    { 0, 32, 2, .write = uhci_ioport_writew, },
+    { 0, 32, 2, .read = uhci_ioport_readw, },
+    { 0, 32, 4, .write = uhci_ioport_writel, },
+    { 0, 32, 4, .read = uhci_ioport_readl, },
+    { 0, 32, 1, .write = uhci_ioport_writeb, },
+    { 0, 32, 1, .read = uhci_ioport_readb, },
+    PORTIO_END_OF_LIST()
+};
+
+static const MemoryRegionOps uhci_ioport_ops = {
+    .old_portio = uhci_portio,
+};
 
 static USBPortOps uhci_port_ops = {
     .attach = uhci_attach,
@@ -1159,10 +1156,10 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
 
     qemu_register_reset(uhci_reset, s);
 
+    memory_region_init_io(&s->io_bar, &uhci_ioport_ops, s, "uhci", 0x20);
     /* Use region 4 for consistency with real hardware.  BSD guests seem
        to rely on this.  */
-    pci_register_bar(&s->dev, 4, 0x20,
-                           PCI_BASE_ADDRESS_SPACE_IO, uhci_map);
+    pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
 
     return 0;
 }
@@ -1182,6 +1179,14 @@ static int usb_uhci_vt82c686b_initfn(PCIDevice *dev)
     return usb_uhci_common_initfn(dev);
 }
 
+static int usb_uhci_exit(PCIDevice *dev)
+{
+    UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
+
+    memory_region_destroy(&s->io_bar);
+    return 0;
+}
+
 static Property uhci_properties[] = {
     DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
     DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
@@ -1194,6 +1199,7 @@ static PCIDeviceInfo uhci_info[] = {
         .qdev.size    = sizeof(UHCIState),
         .qdev.vmsd    = &vmstate_uhci,
         .init         = usb_uhci_common_initfn,
+        .exit         = usb_uhci_exit,
         .vendor_id    = PCI_VENDOR_ID_INTEL,
         .device_id    = PCI_DEVICE_ID_INTEL_82371SB_2,
         .revision     = 0x01,
@@ -1204,6 +1210,7 @@ static PCIDeviceInfo uhci_info[] = {
         .qdev.size    = sizeof(UHCIState),
         .qdev.vmsd    = &vmstate_uhci,
         .init         = usb_uhci_common_initfn,
+        .exit         = usb_uhci_exit,
         .vendor_id    = PCI_VENDOR_ID_INTEL,
         .device_id    = PCI_DEVICE_ID_INTEL_82371AB_2,
         .revision     = 0x01,
@@ -1214,6 +1221,7 @@ static PCIDeviceInfo uhci_info[] = {
         .qdev.size    = sizeof(UHCIState),
         .qdev.vmsd    = &vmstate_uhci,
         .init         = usb_uhci_vt82c686b_initfn,
+        .exit         = usb_uhci_exit,
         .vendor_id    = PCI_VENDOR_ID_VIA,
         .device_id    = PCI_DEVICE_ID_VIA_UHCI,
         .revision     = 0x01,
index 9d348e170e8714a8912ff8d3c7864c019d3d0bc7..25580067f2e24ae6be54229e39ab5c4351f75020 100644 (file)
@@ -308,6 +308,7 @@ static int usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
 static int usb_wacom_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBWacomState *s = (USBWacomState *) dev;
+    uint8_t buf[p->iov.size];
     int ret = 0;
 
     switch (p->pid) {
@@ -317,9 +318,10 @@ static int usb_wacom_handle_data(USBDevice *dev, USBPacket *p)
                 return USB_RET_NAK;
             s->changed = 0;
             if (s->mode == WACOM_MODE_HID)
-                ret = usb_mouse_poll(s, p->data, p->len);
+                ret = usb_mouse_poll(s, buf, p->iov.size);
             else if (s->mode == WACOM_MODE_WACOM)
-                ret = usb_wacom_poll(s, p->data, p->len);
+                ret = usb_wacom_poll(s, buf, p->iov.size);
+            usb_packet_copy(p, buf, ret);
             break;
         }
         /* Fall through.  */
@@ -349,6 +351,11 @@ static int usb_wacom_initfn(USBDevice *dev)
     return 0;
 }
 
+static const VMStateDescription vmstate_usb_wacom = {
+    .name = "usb-wacom",
+    .unmigratable = 1,
+};
+
 static struct USBDeviceInfo wacom_info = {
     .product_desc   = "QEMU PenPartner Tablet",
     .qdev.name      = "usb-wacom-tablet",
@@ -356,6 +363,7 @@ static struct USBDeviceInfo wacom_info = {
     .usbdevice_name = "wacom-tablet",
     .usb_desc       = &desc_wacom,
     .qdev.size      = sizeof(USBWacomState),
+    .qdev.vmsd      = &vmstate_usb_wacom,
     .init           = usb_wacom_initfn,
     .handle_packet  = usb_generic_handle_packet,
     .handle_reset   = usb_wacom_handle_reset,
index 27a983ca5cfe20657d56a058e3542af40558cecb..685e775a004344a603386e62f972adb4f8e5bc82 100644 (file)
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -25,6 +25,7 @@
  */
 #include "qemu-common.h"
 #include "usb.h"
+#include "iov.h"
 
 void usb_attach(USBPort *port, USBDevice *dev)
 {
@@ -72,10 +73,11 @@ static int do_token_setup(USBDevice *s, USBPacket *p)
     int request, value, index;
     int ret = 0;
 
-    if (p->len != 8)
+    if (p->iov.size != 8) {
         return USB_RET_STALL;
-    memcpy(s->setup_buf, p->data, 8);
+    }
+
+    usb_packet_copy(p, s->setup_buf, p->iov.size);
     s->setup_len   = (s->setup_buf[7] << 8) | s->setup_buf[6];
     s->setup_index = 0;
 
@@ -144,9 +146,10 @@ static int do_token_in(USBDevice *s, USBPacket *p)
     case SETUP_STATE_DATA:
         if (s->setup_buf[0] & USB_DIR_IN) {
             int len = s->setup_len - s->setup_index;
-            if (len > p->len)
-                len = p->len;
-            memcpy(p->data, s->data_buf + s->setup_index, len);
+            if (len > p->iov.size) {
+                len = p->iov.size;
+            }
+            usb_packet_copy(p, s->data_buf + s->setup_index, len);
             s->setup_index += len;
             if (s->setup_index >= s->setup_len)
                 s->setup_state = SETUP_STATE_ACK;
@@ -179,9 +182,10 @@ static int do_token_out(USBDevice *s, USBPacket *p)
     case SETUP_STATE_DATA:
         if (!(s->setup_buf[0] & USB_DIR_IN)) {
             int len = s->setup_len - s->setup_index;
-            if (len > p->len)
-                len = p->len;
-            memcpy(s->data_buf + s->setup_index, p->data, len);
+            if (len > p->iov.size) {
+                len = p->iov.size;
+            }
+            usb_packet_copy(p, s->data_buf + s->setup_index, len);
             s->setup_index += len;
             if (s->setup_index >= s->setup_len)
                 s->setup_state = SETUP_STATE_ACK;
@@ -251,22 +255,22 @@ int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
    usb_packet_complete to complete their async control packets. */
 void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
 {
-    if (p->len < 0) {
+    if (p->result < 0) {
         s->setup_state = SETUP_STATE_IDLE;
     }
 
     switch (s->setup_state) {
     case SETUP_STATE_SETUP:
-        if (p->len < s->setup_len) {
-            s->setup_len = p->len;
+        if (p->result < s->setup_len) {
+            s->setup_len = p->result;
         }
         s->setup_state = SETUP_STATE_DATA;
-        p->len = 8;
+        p->result = 8;
         break;
 
     case SETUP_STATE_ACK:
         s->setup_state = SETUP_STATE_IDLE;
-        p->len = 0;
+        p->result = 0;
         break;
 
     default:
@@ -347,3 +351,57 @@ void usb_cancel_packet(USBPacket * p)
     p->owner->info->cancel_packet(p->owner, p);
     p->owner = NULL;
 }
+
+
+void usb_packet_init(USBPacket *p)
+{
+    qemu_iovec_init(&p->iov, 1);
+}
+
+void usb_packet_setup(USBPacket *p, int pid, uint8_t addr, uint8_t ep)
+{
+    p->pid = pid;
+    p->devaddr = addr;
+    p->devep = ep;
+    p->result = 0;
+    qemu_iovec_reset(&p->iov);
+}
+
+void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len)
+{
+    qemu_iovec_add(&p->iov, ptr, len);
+}
+
+void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes)
+{
+    assert(p->result >= 0);
+    assert(p->result + bytes <= p->iov.size);
+    switch (p->pid) {
+    case USB_TOKEN_SETUP:
+    case USB_TOKEN_OUT:
+        iov_to_buf(p->iov.iov, p->iov.niov, ptr, p->result, bytes);
+        break;
+    case USB_TOKEN_IN:
+        iov_from_buf(p->iov.iov, p->iov.niov, ptr, p->result, bytes);
+        break;
+    default:
+        fprintf(stderr, "%s: invalid pid: %x\n", __func__, p->pid);
+        abort();
+    }
+    p->result += bytes;
+}
+
+void usb_packet_skip(USBPacket *p, size_t bytes)
+{
+    assert(p->result >= 0);
+    assert(p->result + bytes <= p->iov.size);
+    if (p->pid == USB_TOKEN_IN) {
+        iov_clear(p->iov.iov, p->iov.niov, p->result, bytes);
+    }
+    p->result += bytes;
+}
+
+void usb_packet_cleanup(USBPacket *p)
+{
+    qemu_iovec_destroy(&p->iov);
+}
index ded2de29b9c02f6c4cc7867215f0158ebce99ad5..84d04df2e13d1a9ae195927612d806938ea42248 100644 (file)
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -285,12 +285,21 @@ struct USBPacket {
     int pid;
     uint8_t devaddr;
     uint8_t devep;
-    uint8_t *data;
-    int len;
+    QEMUIOVector iov;
+    int result; /* transfer length or USB_RET_* status code */
     /* Internal use by the USB layer.  */
     USBDevice *owner;
 };
 
+void usb_packet_init(USBPacket *p);
+void usb_packet_setup(USBPacket *p, int pid, uint8_t addr, uint8_t ep);
+void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len);
+int usb_packet_map(USBPacket *p, QEMUSGList *sgl);
+void usb_packet_unmap(USBPacket *p);
+void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes);
+void usb_packet_skip(USBPacket *p, size_t bytes);
+void usb_packet_cleanup(USBPacket *p);
+
 int usb_handle_packet(USBDevice *dev, USBPacket *p);
 void usb_packet_complete(USBDevice *dev, USBPacket *p);
 void usb_cancel_packet(USBPacket * p);
index 290a9009b261a6487cce1a9ae77291d13e26b7df..e1d5c0bf5a2f185831eecbd7459cc4330a9cc905 100644 (file)
@@ -10,6 +10,7 @@
 #include "sysbus.h"
 #include "pci.h"
 #include "pci_host.h"
+#include "exec-memory.h"
 
 typedef struct {
     SysBusDevice busdev;
@@ -111,6 +112,7 @@ static int pci_vpb_init(SysBusDevice *dev)
     }
     bus = pci_register_bus(&dev->qdev, "pci",
                            pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
+                           get_system_memory(), get_system_io(),
                            PCI_DEVFN(11, 0), 4);
 
     /* ??? Register memory space.  */
index 4954bb18be633bc4bb21a14b1bba3e9f498fa146..96e6e7dd21bde5aaf7cd63699fab1d9217559707 100644 (file)
@@ -27,6 +27,7 @@
 #include "vga_int.h"
 #include "pixel_ops.h"
 #include "qemu-timer.h"
+#include "exec-memory.h"
 
 typedef struct ISAVGAMMState {
     VGACommonState vga;
@@ -79,35 +80,44 @@ static void vga_mm_writel (void *opaque,
     vga_ioport_write(&s->vga, addr >> s->it_shift, value);
 }
 
-static CPUReadMemoryFunc * const vga_mm_read_ctrl[] = {
-    &vga_mm_readb,
-    &vga_mm_readw,
-    &vga_mm_readl,
-};
-
-static CPUWriteMemoryFunc * const vga_mm_write_ctrl[] = {
-    &vga_mm_writeb,
-    &vga_mm_writew,
-    &vga_mm_writel,
+static const MemoryRegionOps vga_mm_ctrl_ops = {
+    .old_mmio = {
+        .read = {
+            vga_mm_readb,
+            vga_mm_readw,
+            vga_mm_readl,
+        },
+        .write = {
+            vga_mm_writeb,
+            vga_mm_writew,
+            vga_mm_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void vga_mm_init(ISAVGAMMState *s, target_phys_addr_t vram_base,
                         target_phys_addr_t ctrl_base, int it_shift)
 {
-    int s_ioport_ctrl, vga_io_memory;
+    MemoryRegion *s_ioport_ctrl, *vga_io_memory;
 
     s->it_shift = it_shift;
-    s_ioport_ctrl = cpu_register_io_memory(vga_mm_read_ctrl, vga_mm_write_ctrl, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
+    s_ioport_ctrl = qemu_malloc(sizeof(*s_ioport_ctrl));
+    memory_region_init_io(s_ioport_ctrl, &vga_mm_ctrl_ops, s,
+                          "vga-mm-ctrl", 0x100000);
+
+    vga_io_memory = qemu_malloc(sizeof(*vga_io_memory));
+    /* XXX: endianness? */
+    memory_region_init_io(vga_io_memory, &vga_mem_ops, &s->vga,
+                          "vga-mem", 0x20000);
 
     vmstate_register(NULL, 0, &vmstate_vga_common, s);
 
-    cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
+    memory_region_add_subregion(get_system_memory(), ctrl_base, s_ioport_ctrl);
     s->vga.bank_offset = 0;
-    cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
-    qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
+    memory_region_add_subregion(get_system_memory(),
+                                vram_base + 0x000a0000, vga_io_memory);
+    memory_region_set_coalescing(vga_io_memory);
 }
 
 int isa_vga_mm_init(target_phys_addr_t vram_base,
index 245841f18b3f720e2074a333bb9866b9ce3a696b..fef7f58f28c1eaffd6762e22ce15bce3440e2f69 100644 (file)
@@ -28,6 +28,7 @@
 #include "pixel_ops.h"
 #include "qemu-timer.h"
 #include "loader.h"
+#include "exec-memory.h"
 
 typedef struct ISAVGAState {
     ISADevice dev;
@@ -46,13 +47,14 @@ static int vga_initfn(ISADevice *dev)
 {
     ISAVGAState *d = DO_UPCAST(ISAVGAState, dev, dev);
     VGACommonState *s = &d->state;
-    int vga_io_memory;
+    MemoryRegion *vga_io_memory;
 
     vga_common_init(s, VGA_RAM_SIZE);
     vga_io_memory = vga_init_io(s);
-    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
-                                 vga_io_memory);
-    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
+    memory_region_add_subregion_overlap(get_system_memory(),
+                                        isa_mem_base + 0x000a0000,
+                                        vga_io_memory, 1);
+    memory_region_set_coalescing(vga_io_memory);
     isa_init_ioport(dev, 0x3c0);
     isa_init_ioport(dev, 0x3b4);
     isa_init_ioport(dev, 0x3ba);
index 481f448e3fb4feb3cbe4a06dfbca9e046607d3c3..c67be0abebfef491db99726477c1289686ce187e 100644 (file)
@@ -47,29 +47,6 @@ static const VMStateDescription vmstate_vga_pci = {
     }
 };
 
-static void vga_map(PCIDevice *pci_dev, int region_num,
-                    pcibus_t addr, pcibus_t size, int type)
-{
-    PCIVGAState *d = (PCIVGAState *)pci_dev;
-    VGACommonState *s = &d->vga;
-
-    cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
-    s->map_addr = addr;
-    s->map_end = addr + s->vram_size;
-    vga_dirty_log_start(s);
-}
-
-static void pci_vga_write_config(PCIDevice *d,
-                                 uint32_t address, uint32_t val, int len)
-{
-    PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
-    VGACommonState *s = &pvs->vga;
-
-    pci_default_write_config(d, address, val, len);
-    if (s->map_addr && pvs->dev.io_regions[0].addr == -1)
-        s->map_addr = 0;
-}
-
 static int pci_vga_initfn(PCIDevice *dev)
 {
      PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
@@ -83,8 +60,7 @@ static int pci_vga_initfn(PCIDevice *dev)
                                   s->screen_dump, s->text_update, s);
 
      /* XXX: VGA_RAM_SIZE must be a power of two */
-     pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
-                      PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
+     pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
 
      if (!dev->rom_bar) {
          /* compatibility with pc-0.13 and older */
@@ -106,7 +82,6 @@ static PCIDeviceInfo vga_info = {
     .qdev.vmsd    = &vmstate_vga_pci,
     .no_hotplug   = 1,
     .init         = pci_vga_initfn,
-    .config_write = pci_vga_write_config,
     .romfile      = "vgabios-stdvga.bin",
 
     /* dummy VGA (same as Bochs ID) */
index 0f5473462494a484684ca1af0bea67b7d5b2e2ac..33dc478a7d64bfb4b1bb282749925f55239d5859 100644 (file)
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -28,6 +28,7 @@
 #include "vga_int.h"
 #include "pixel_ops.h"
 #include "qemu-timer.h"
+#include "exec-memory.h"
 
 //#define DEBUG_VGA
 //#define DEBUG_VGA_MEM
@@ -707,9 +708,8 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
 #endif
 
 /* called for accesses between 0xa0000 and 0xc0000 */
-uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
+uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr)
 {
-    VGACommonState *s = opaque;
     int memory_map_mode, plane;
     uint32_t ret;
 
@@ -763,28 +763,9 @@ uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-    v = vga_mem_readb(opaque, addr);
-    v |= vga_mem_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-    v = vga_mem_readb(opaque, addr);
-    v |= vga_mem_readb(opaque, addr + 1) << 8;
-    v |= vga_mem_readb(opaque, addr + 2) << 16;
-    v |= vga_mem_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
 /* called for accesses between 0xa0000 and 0xc0000 */
-void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
 {
-    VGACommonState *s = opaque;
     int memory_map_mode, plane, write_mode, b, func_select, mask;
     uint32_t write_mask, bit_mask, set_mask;
 
@@ -825,7 +806,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
             printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
 #endif
             s->plane_updated |= mask; /* only used to detect font change */
-            cpu_physical_memory_set_dirty(s->vram_offset + addr);
+            memory_region_set_dirty(&s->vram, addr);
         }
     } else if (s->gr[5] & 0x10) {
         /* odd/even mode (aka text mode mapping) */
@@ -838,7 +819,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
             printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
 #endif
             s->plane_updated |= mask; /* only used to detect font change */
-            cpu_physical_memory_set_dirty(s->vram_offset + addr);
+            memory_region_set_dirty(&s->vram, addr);
         }
     } else {
         /* standard VGA latched access */
@@ -912,24 +893,10 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
         printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
                addr * 4, write_mask, val);
 #endif
-        cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
+        memory_region_set_dirty(&s->vram, addr << 2);
     }
 }
 
-static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    vga_mem_writeb(opaque, addr, val & 0xff);
-    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    vga_mem_writeb(opaque, addr, val & 0xff);
-    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
                              const uint8_t *font_ptr, int h,
                              uint32_t fgcol, uint32_t bgcol);
@@ -1553,57 +1520,17 @@ void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
 
 static void vga_sync_dirty_bitmap(VGACommonState *s)
 {
-    if (s->map_addr)
-        cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
-
-    if (s->lfb_vram_mapped) {
-        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
-        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
-    }
-
-#ifdef CONFIG_BOCHS_VBE
-    if (s->vbe_mapped) {
-        cpu_physical_sync_dirty_bitmap(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
-                                       VBE_DISPI_LFB_PHYSICAL_ADDRESS + s->vram_size);
-    }
-#endif
-
+    memory_region_sync_dirty_bitmap(&s->vram);
 }
 
 void vga_dirty_log_start(VGACommonState *s)
 {
-    if (s->map_addr) {
-        cpu_physical_log_start(s->map_addr, s->map_end - s->map_addr);
-    }
-
-    if (s->lfb_vram_mapped) {
-        cpu_physical_log_start(isa_mem_base + 0xa0000, 0x8000);
-        cpu_physical_log_start(isa_mem_base + 0xa8000, 0x8000);
-    }
-
-#ifdef CONFIG_BOCHS_VBE
-    if (s->vbe_mapped) {
-        cpu_physical_log_start(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
-    }
-#endif
+    memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
 }
 
 void vga_dirty_log_stop(VGACommonState *s)
 {
-    if (s->map_addr) {
-        cpu_physical_log_stop(s->map_addr, s->map_end - s->map_addr);
-    }
-
-    if (s->lfb_vram_mapped) {
-        cpu_physical_log_stop(isa_mem_base + 0xa0000, 0x8000);
-        cpu_physical_log_stop(isa_mem_base + 0xa8000, 0x8000);
-    }
-
-#ifdef CONFIG_BOCHS_VBE
-    if (s->vbe_mapped) {
-        cpu_physical_log_stop(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
-    }
-#endif
+    memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
 }
 
 void vga_dirty_log_restart(VGACommonState *s)
@@ -1773,15 +1700,16 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
         if (!(s->cr[0x17] & 2)) {
             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
         }
-        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
-        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
+        page0 = addr & TARGET_PAGE_MASK;
+        page1 = (addr + bwidth - 1) & TARGET_PAGE_MASK;
         update = full_update |
-            cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
-            cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
+            memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) |
+            memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA);
         if ((page1 - page0) > TARGET_PAGE_SIZE) {
             /* if wide line, can use another page */
-            update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
-                                                    VGA_DIRTY_FLAG);
+            update |= memory_region_get_dirty(&s->vram,
+                                              page0 + TARGET_PAGE_SIZE,
+                                              DIRTY_MEMORY_VGA);
         }
         /* explicit invalidation for the hardware cursor */
         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
@@ -1826,8 +1754,10 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
     }
     /* reset modified pages */
     if (page_max >= page_min) {
-        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
-                                        VGA_DIRTY_FLAG);
+        memory_region_reset_dirty(&s->vram,
+                                  page_min,
+                                  page_max + TARGET_PAGE_SIZE - page_min,
+                                  DIRTY_MEMORY_VGA);
     }
     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
 }
@@ -1906,11 +1836,6 @@ static void vga_invalidate_display(void *opaque)
 
 void vga_common_reset(VGACommonState *s)
 {
-    s->lfb_addr = 0;
-    s->lfb_end = 0;
-    s->map_addr = 0;
-    s->map_end = 0;
-    s->lfb_vram_mapped = 0;
     s->sr_index = 0;
     memset(s->sr, '\0', sizeof(s->sr));
     s->gr_index = 0;
@@ -2141,16 +2066,30 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
     dpy_update(s->ds, 0, 0, s->last_width, height);
 }
 
-CPUReadMemoryFunc * const vga_mem_read[3] = {
-    vga_mem_readb,
-    vga_mem_readw,
-    vga_mem_readl,
-};
+static uint64_t vga_mem_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
+{
+    VGACommonState *s = opaque;
+
+    return vga_mem_readb(s, addr);
+}
+
+static void vga_mem_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t data, unsigned size)
+{
+    VGACommonState *s = opaque;
+
+    return vga_mem_writeb(s, addr, data);
+}
 
-CPUWriteMemoryFunc * const vga_mem_write[3] = {
-    vga_mem_writeb,
-    vga_mem_writew,
-    vga_mem_writel,
+const MemoryRegionOps vga_mem_ops = {
+    .read = vga_mem_read,
+    .write = vga_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static int vga_common_post_load(void *opaque, int version_id)
@@ -2236,8 +2175,8 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
 #else
     s->is_vbe_vmstate = 0;
 #endif
-    s->vram_offset = qemu_ram_alloc(NULL, "vga.vram", vga_ram_size);
-    s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
+    memory_region_init_ram(&s->vram, NULL, "vga.vram", vga_ram_size);
+    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
     s->vram_size = vga_ram_size;
     s->get_bpp = vga_get_bpp;
     s->get_offsets = vga_get_offsets;
@@ -2257,11 +2196,14 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
         s->update_retrace_info = vga_precise_update_retrace_info;
         break;
     }
+    vga_dirty_log_start(s);
 }
 
 /* used by both ISA and PCI */
-int vga_init_io(VGACommonState *s)
+MemoryRegion *vga_init_io(VGACommonState *s)
 {
+    MemoryRegion *vga_mem;
+
     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
 
     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
@@ -2292,30 +2234,36 @@ int vga_init_io(VGACommonState *s)
 #endif
 #endif /* CONFIG_BOCHS_VBE */
 
-    return cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
-                                  DEVICE_LITTLE_ENDIAN);
+    vga_mem = qemu_malloc(sizeof(*vga_mem));
+    memory_region_init_io(vga_mem, &vga_mem_ops, s,
+                          "vga-lowmem", 0x20000);
+
+    return vga_mem;
 }
 
 void vga_init(VGACommonState *s)
 {
-    int vga_io_memory;
+    MemoryRegion *vga_io_memory;
 
     qemu_register_reset(vga_reset, s);
 
     s->bank_offset = 0;
 
     vga_io_memory = vga_init_io(s);
-    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
-                                 vga_io_memory);
-    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
+    memory_region_add_subregion_overlap(get_system_memory(),
+                                        isa_mem_base + 0x000a0000,
+                                        vga_io_memory,
+                                        1);
+    memory_region_set_coalescing(vga_io_memory);
 }
 
 void vga_init_vbe(VGACommonState *s)
 {
 #ifdef CONFIG_BOCHS_VBE
     /* XXX: use optimized standard vga accesses */
-    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
-                                 VGA_RAM_SIZE, s->vram_offset);
+    memory_region_add_subregion(get_system_memory(),
+                                VBE_DISPI_LFB_PHYSICAL_ADDRESS,
+                                &s->vram);
     s->vbe_mapped = 1;
 #endif 
 }
index eee91a84f319ac6b3ab430451632aca4f2ccd54d..100d98c8bf5dab6e4c53b6ca07b1fe275f387a42 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <hw/hw.h>
+#include "memory.h"
 
 #define MSR_COLOR_EMULATION 0x01
 #define MSR_PAGE_SELECT     0x20
@@ -105,11 +106,7 @@ typedef void (* vga_update_retrace_info_fn)(struct VGACommonState *s);
 
 typedef struct VGACommonState {
     uint8_t *vram_ptr;
-    ram_addr_t vram_offset;
-    target_phys_addr_t lfb_addr;
-    target_phys_addr_t lfb_end;
-    target_phys_addr_t map_addr;
-    target_phys_addr_t map_end;
+    MemoryRegion vram;
     uint32_t vram_size;
     uint32_t latch;
     uint32_t lfb_vram_mapped; /* whether 0xa0000 is mapped as ram */
@@ -134,7 +131,7 @@ typedef struct VGACommonState {
     int dac_8bit;
     uint8_t palette[768];
     int32_t bank_offset;
-    int vga_io_memory;
+    MemoryRegion *vga_io_memory;
     int (*get_bpp)(struct VGACommonState *s);
     void (*get_offsets)(struct VGACommonState *s,
                         uint32_t *pline_offset,
@@ -191,7 +188,7 @@ static inline int c6_to_8(int v)
 
 void vga_common_init(VGACommonState *s, int vga_ram_size);
 void vga_init(VGACommonState *s);
-int vga_init_io(VGACommonState *s);
+MemoryRegion *vga_init_io(VGACommonState *s);
 void vga_common_reset(VGACommonState *s);
 
 void vga_dirty_log_start(VGACommonState *s);
@@ -201,8 +198,8 @@ void vga_dirty_log_restart(VGACommonState *s);
 extern const VMStateDescription vmstate_vga_common;
 uint32_t vga_ioport_read(void *opaque, uint32_t addr);
 void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val);
-uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr);
-void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val);
+uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr);
+void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val);
 void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2);
 int ppm_save(const char *filename, struct DisplaySurface *ds);
 
@@ -229,5 +226,4 @@ extern const uint8_t gr_mask[16];
 #define VGABIOS_FILENAME "vgabios.bin"
 #define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin"
 
-extern CPUReadMemoryFunc * const vga_mem_read[3];
-extern CPUWriteMemoryFunc * const vga_mem_write[3];
+extern const MemoryRegionOps vga_mem_ops;
index c3d88214fe0e5bf1271164e3c2c015fddc10ade5..19e72555c4b56ebd2130583e1c876f67f59a13a0 100644 (file)
@@ -120,7 +120,6 @@ static void vhost_dev_unassign_memory(struct vhost_dev *dev,
         if (start_addr <= reg->guest_phys_addr && memlast >= reglast) {
             --dev->mem->nregions;
             --to;
-            assert(to >= 0);
             ++overlap_middle;
             continue;
         }
index 70a87103439ac0205eedb88b244ca9d3aa759174..072a88a382ea2e80f387ea688007379b7c48b843 100644 (file)
@@ -1,7 +1,9 @@
 /*
- * Virtio Block Device
+ * Virtio Balloon Device
  *
  * Copyright IBM, Corp. 2008
+ * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011 Amit Shah <amit.shah@redhat.com>
  *
  * Authors:
  *  Anthony Liguori   <aliguori@us.ibm.com>
@@ -43,6 +45,7 @@ typedef struct VirtIOBalloon
     size_t stats_vq_offset;
     MonitorCompletion *stats_callback;
     void *stats_opaque_callback_data;
+    DeviceState *qdev;
 } VirtIOBalloon;
 
 static VirtIOBalloon *to_virtio_balloon(VirtIODevice *vdev)
@@ -199,36 +202,44 @@ static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f)
     return f;
 }
 
-static void virtio_balloon_to_target(void *opaque, ram_addr_t target,
-                                     MonitorCompletion cb, void *cb_data)
+static void virtio_balloon_stat(void *opaque, MonitorCompletion cb,
+                                void *cb_data)
 {
     VirtIOBalloon *dev = opaque;
 
-    if (target > ram_size)
-        target = ram_size;
+    /* For now, only allow one request at a time.  This restriction can be
+     * removed later by queueing callback and data pairs.
+     */
+    if (dev->stats_callback != NULL) {
+        return;
+    }
+    dev->stats_callback = cb;
+    dev->stats_opaque_callback_data = cb_data;
+
+    if (ENABLE_GUEST_STATS
+        && (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ))) {
+        virtqueue_push(dev->svq, &dev->stats_vq_elem, dev->stats_vq_offset);
+        virtio_notify(&dev->vdev, dev->svq);
+        return;
+    }
+
+    /* Stats are not supported.  Clear out any stale values that might
+     * have been set by a more featureful guest kernel.
+     */
+    reset_stats(dev);
+    complete_stats_request(dev);
+}
 
+static void virtio_balloon_to_target(void *opaque, ram_addr_t target)
+{
+    VirtIOBalloon *dev = opaque;
+
+    if (target > ram_size) {
+        target = ram_size;
+    }
     if (target) {
         dev->num_pages = (ram_size - target) >> VIRTIO_BALLOON_PFN_SHIFT;
         virtio_notify_config(&dev->vdev);
-    } else {
-        /* For now, only allow one request at a time.  This restriction can be
-         * removed later by queueing callback and data pairs.
-         */
-        if (dev->stats_callback != NULL) {
-            return;
-        }
-        dev->stats_callback = cb;
-        dev->stats_opaque_callback_data = cb_data; 
-        if (ENABLE_GUEST_STATS && (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ))) {
-            virtqueue_push(dev->svq, &dev->stats_vq_elem, dev->stats_vq_offset);
-            virtio_notify(&dev->vdev, dev->svq);
-        } else {
-            /* Stats are not supported.  Clear out any stale values that might
-             * have been set by a more featureful guest kernel.
-             */
-            reset_stats(dev);
-            complete_stats_request(dev);
-        }
     }
 }
 
@@ -259,6 +270,7 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
 VirtIODevice *virtio_balloon_init(DeviceState *dev)
 {
     VirtIOBalloon *s;
+    int ret;
 
     s = (VirtIOBalloon *)virtio_common_init("virtio-balloon",
                                             VIRTIO_ID_BALLOON,
@@ -268,15 +280,29 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev)
     s->vdev.set_config = virtio_balloon_set_config;
     s->vdev.get_features = virtio_balloon_get_features;
 
+    ret = qemu_add_balloon_handler(virtio_balloon_to_target,
+                                   virtio_balloon_stat, s);
+    if (ret < 0) {
+        virtio_cleanup(&s->vdev);
+        return NULL;
+    }
+
     s->ivq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output);
     s->dvq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output);
     s->svq = virtio_add_queue(&s->vdev, 128, virtio_balloon_receive_stats);
 
     reset_stats(s);
-    qemu_add_balloon_handler(virtio_balloon_to_target, s);
 
+    s->qdev = dev;
     register_savevm(dev, "virtio-balloon", -1, 1,
                     virtio_balloon_save, virtio_balloon_load, s);
 
     return &s->vdev;
 }
+
+void virtio_balloon_exit(VirtIODevice *vdev)
+{
+    VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev);
+    unregister_savevm(s->qdev, "virtio-balloon", s);
+    virtio_cleanup(vdev);
+}
index 6471ac85ab91a71debe5b5fcaafdd0d4b93ad0de..836dbc3c120faf57e176407a7802345291e7c1af 100644 (file)
@@ -594,4 +594,5 @@ void virtio_blk_exit(VirtIODevice *vdev)
 {
     VirtIOBlock *s = to_virtio_blk(vdev);
     unregister_savevm(s->qdev, "virtio-blk", s);
+    virtio_cleanup(vdev);
 }
index a32cc019b09b88664e90e9d91a22e8161ae391dd..3f10391f3e90a56c961c4e11e1f2345fefc5e71e 100644 (file)
@@ -1073,6 +1073,6 @@ void virtio_net_exit(VirtIODevice *vdev)
         qemu_bh_delete(n->tx_bh);
     }
 
-    virtio_cleanup(&n->vdev);
     qemu_del_vlan_client(&n->nic->nc);
+    virtio_cleanup(&n->vdev);
 }
index d685243728857c9bd5039501c9e5d3bb7a4a436e..df27c198b0938475a7c4e030bae79d40c0624975 100644 (file)
@@ -27,6 +27,7 @@
 #include "kvm.h"
 #include "blockdev.h"
 #include "virtio-pci.h"
+#include "range.h"
 
 /* from Linux's linux/virtio_pci.h */
 
@@ -161,7 +162,8 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
 {
     VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
     EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
-    int r;
+    int r = 0;
+
     if (assign) {
         r = event_notifier_init(notifier, 1);
         if (r < 0) {
@@ -169,24 +171,11 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
                          __func__, r);
             return r;
         }
-        r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
-                                       proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
-                                       n, assign);
-        if (r < 0) {
-            error_report("%s: unable to map ioeventfd: %d",
-                         __func__, r);
-            event_notifier_cleanup(notifier);
-        }
+        memory_region_add_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
+                                  true, n, event_notifier_get_fd(notifier));
     } else {
-        r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
-                                       proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
-                                       n, assign);
-        if (r < 0) {
-            error_report("%s: unable to unmap ioeventfd: %d",
-                         __func__, r);
-            return r;
-        }
-
+        memory_region_del_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
+                                  true, n, event_notifier_get_fd(notifier));
         /* Handle the race condition where the guest kicked and we deassigned
          * before we got around to handling the kick.
          */
@@ -423,7 +412,6 @@ static uint32_t virtio_pci_config_readb(void *opaque, uint32_t addr)
 {
     VirtIOPCIProxy *proxy = opaque;
     uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
-    addr -= proxy->addr;
     if (addr < config)
         return virtio_ioport_read(proxy, addr);
     addr -= config;
@@ -434,7 +422,6 @@ static uint32_t virtio_pci_config_readw(void *opaque, uint32_t addr)
 {
     VirtIOPCIProxy *proxy = opaque;
     uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
-    addr -= proxy->addr;
     if (addr < config)
         return virtio_ioport_read(proxy, addr);
     addr -= config;
@@ -445,7 +432,6 @@ static uint32_t virtio_pci_config_readl(void *opaque, uint32_t addr)
 {
     VirtIOPCIProxy *proxy = opaque;
     uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
-    addr -= proxy->addr;
     if (addr < config)
         return virtio_ioport_read(proxy, addr);
     addr -= config;
@@ -456,7 +442,6 @@ static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
     VirtIOPCIProxy *proxy = opaque;
     uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
-    addr -= proxy->addr;
     if (addr < config) {
         virtio_ioport_write(proxy, addr, val);
         return;
@@ -469,7 +454,6 @@ static void virtio_pci_config_writew(void *opaque, uint32_t addr, uint32_t val)
 {
     VirtIOPCIProxy *proxy = opaque;
     uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
-    addr -= proxy->addr;
     if (addr < config) {
         virtio_ioport_write(proxy, addr, val);
         return;
@@ -482,7 +466,6 @@ static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
 {
     VirtIOPCIProxy *proxy = opaque;
     uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
-    addr -= proxy->addr;
     if (addr < config) {
         virtio_ioport_write(proxy, addr, val);
         return;
@@ -491,42 +474,36 @@ static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
     virtio_config_writel(proxy->vdev, addr, val);
 }
 
-static void virtio_map(PCIDevice *pci_dev, int region_num,
-                       pcibus_t addr, pcibus_t size, int type)
-{
-    VirtIOPCIProxy *proxy = container_of(pci_dev, VirtIOPCIProxy, pci_dev);
-    VirtIODevice *vdev = proxy->vdev;
-    unsigned config_len = VIRTIO_PCI_REGION_SIZE(pci_dev) + vdev->config_len;
-
-    proxy->addr = addr;
-
-    register_ioport_write(addr, config_len, 1, virtio_pci_config_writeb, proxy);
-    register_ioport_write(addr, config_len, 2, virtio_pci_config_writew, proxy);
-    register_ioport_write(addr, config_len, 4, virtio_pci_config_writel, proxy);
-    register_ioport_read(addr, config_len, 1, virtio_pci_config_readb, proxy);
-    register_ioport_read(addr, config_len, 2, virtio_pci_config_readw, proxy);
-    register_ioport_read(addr, config_len, 4, virtio_pci_config_readl, proxy);
+const MemoryRegionPortio virtio_portio[] = {
+    { 0, 0x10000, 1, .write = virtio_pci_config_writeb, },
+    { 0, 0x10000, 2, .write = virtio_pci_config_writew, },
+    { 0, 0x10000, 4, .write = virtio_pci_config_writel, },
+    { 0, 0x10000, 1, .read = virtio_pci_config_readb, },
+    { 0, 0x10000, 2, .read = virtio_pci_config_readw, },
+    { 0, 0x10000, 4, .read = virtio_pci_config_readl, },
+    PORTIO_END_OF_LIST()
+};
 
-    if (vdev->config_len)
-        vdev->get_config(vdev, vdev->config);
-}
+static const MemoryRegionOps virtio_pci_config_ops = {
+    .old_portio = virtio_portio,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
 
 static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
                                 uint32_t val, int len)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
 
-    if (PCI_COMMAND == address) {
-        if (!(val & PCI_COMMAND_MASTER)) {
-            if (!(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
-                virtio_pci_stop_ioeventfd(proxy);
-                virtio_set_status(proxy->vdev,
-                                  proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
-            }
-        }
+    pci_default_write_config(pci_dev, address, val, len);
+
+    if (range_covers_byte(address, len, PCI_COMMAND) &&
+        !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
+        !(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
+        virtio_pci_stop_ioeventfd(proxy);
+        virtio_set_status(proxy->vdev,
+                          proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
     }
 
-    pci_default_write_config(pci_dev, address, val, len);
     msix_write_config(pci_dev, address, val, len);
 }
 
@@ -664,11 +641,11 @@ void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev)
     pci_set_word(config + 0x2e, vdev->device_id);
     config[0x3d] = 1;
 
-    if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors, 1, 0)) {
-        pci_register_bar(&proxy->pci_dev, 1,
-                         msix_bar_size(&proxy->pci_dev),
-                         PCI_BASE_ADDRESS_SPACE_MEMORY,
-                         msix_mmio_map);
+    memory_region_init(&proxy->msix_bar, "virtio-msix", 4096);
+    if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors,
+                                     &proxy->msix_bar, 1, 0)) {
+        pci_register_bar(&proxy->pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
+                         &proxy->msix_bar);
     } else
         vdev->nvectors = 0;
 
@@ -678,8 +655,10 @@ void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev)
     if (size & (size-1))
         size = 1 << qemu_fls(size);
 
-    pci_register_bar(&proxy->pci_dev, 0, size, PCI_BASE_ADDRESS_SPACE_IO,
-                           virtio_map);
+    memory_region_init_io(&proxy->bar, &virtio_pci_config_ops, proxy,
+                          "virtio-pci", size);
+    pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
+                     &proxy->bar);
 
     if (!kvm_has_many_ioeventfds()) {
         proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
@@ -714,7 +693,13 @@ static int virtio_blk_init_pci(PCIDevice *pci_dev)
 
 static int virtio_exit_pci(PCIDevice *pci_dev)
 {
-    return msix_uninit(pci_dev);
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+    int r;
+
+    memory_region_destroy(&proxy->bar);
+    r = msix_uninit(pci_dev, &proxy->msix_bar);
+    memory_region_destroy(&proxy->msix_bar);
+    return r;
 }
 
 static int virtio_blk_exit_pci(PCIDevice *pci_dev)
@@ -788,10 +773,22 @@ static int virtio_balloon_init_pci(PCIDevice *pci_dev)
     VirtIODevice *vdev;
 
     vdev = virtio_balloon_init(&pci_dev->qdev);
+    if (!vdev) {
+        return -1;
+    }
     virtio_init_pci(proxy, vdev);
     return 0;
 }
 
+static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+
+    virtio_pci_stop_ioeventfd(proxy);
+    virtio_balloon_exit(proxy->vdev);
+    return virtio_exit_pci(pci_dev);
+}
+
 static PCIDeviceInfo virtio_info[] = {
     {
         .qdev.name = "virtio-blk-pci",
@@ -866,7 +863,7 @@ static PCIDeviceInfo virtio_info[] = {
         .qdev.alias = "virtio-balloon",
         .qdev.size = sizeof(VirtIOPCIProxy),
         .init      = virtio_balloon_init_pci,
-        .exit      = virtio_exit_pci,
+        .exit      = virtio_balloon_exit_pci,
         .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
         .device_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
         .revision  = VIRTIO_PCI_ABI_VERSION,
index 1f0de5684d7bb7d37a01f919f134145be2bc5f5f..14c10f7d67c2be78ef434117f0e9c99bd607ea5b 100644 (file)
@@ -21,8 +21,9 @@
 typedef struct {
     PCIDevice pci_dev;
     VirtIODevice *vdev;
+    MemoryRegion bar;
+    MemoryRegion msix_bar;
     uint32_t flags;
-    uint32_t addr;
     uint32_t class_code;
     uint32_t nvectors;
     BlockConf block;
index a8f4940da2263c998b6d2373aeb24f3d1f4a0790..93dfb1e359cc3f827501422376011032b89d19ba 100644 (file)
@@ -834,6 +834,7 @@ void virtio_cleanup(VirtIODevice *vdev)
     if (vdev->config)
         qemu_free(vdev->config);
     qemu_free(vdev->vq);
+    qemu_free(vdev);
 }
 
 static void virtio_vmstate_change(void *opaque, int running, int reason)
index 0fd0bb0ac574ba788de55b108aeb4190971dca47..c1292647fe6c6d79a67ed343987b7e0f7578376b 100644 (file)
@@ -213,6 +213,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
 void virtio_net_exit(VirtIODevice *vdev);
 void virtio_blk_exit(VirtIODevice *vdev);
 void virtio_serial_exit(VirtIODevice *vdev);
+void virtio_balloon_exit(VirtIODevice *vdev);
 
 #define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
        DEFINE_PROP_BIT("indirect_desc", _state, _field, \
index 354c221720d4ec5cd423edc011ce22efca09902b..d5cfa70cba4d637ac03f22820fb6cc008f74740a 100644 (file)
@@ -52,8 +52,6 @@ struct vmsvga_state_s {
         int on;
     } cursor;
 
-    target_phys_addr_t vram_base;
-
     int index;
     int scratch_size;
     uint32_t *scratch;
@@ -67,10 +65,9 @@ struct vmsvga_state_s {
     int syncing;
     int fb_size;
 
-    ram_addr_t fifo_offset;
+    MemoryRegion fifo_ram;
     uint8_t *fifo_ptr;
     unsigned int fifo_size;
-    target_phys_addr_t fifo_base;
 
     union {
         uint32_t *fifo;
@@ -94,6 +91,7 @@ struct vmsvga_state_s {
 struct pci_vmsvga_state_s {
     PCIDevice card;
     struct vmsvga_state_s chip;
+    MemoryRegion io_bar;
 };
 
 #define SVGA_MAGIC             0x900000UL
@@ -761,8 +759,11 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
     case SVGA_REG_BYTES_PER_LINE:
         return ((s->depth + 7) >> 3) * s->new_width;
 
-    case SVGA_REG_FB_START:
-        return s->vram_base;
+    case SVGA_REG_FB_START: {
+        struct pci_vmsvga_state_s *pci_vmsvga
+            = container_of(s, struct pci_vmsvga_state_s, chip);
+        return pci_get_bar_addr(&pci_vmsvga->card, 1);
+    }
 
     case SVGA_REG_FB_OFFSET:
         return 0x0;
@@ -788,8 +789,11 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
 #endif
         return caps;
 
-    case SVGA_REG_MEM_START:
-        return s->fifo_base;
+    case SVGA_REG_MEM_START: {
+        struct pci_vmsvga_state_s *pci_vmsvga
+            = container_of(s, struct pci_vmsvga_state_s, chip);
+        return pci_get_bar_addr(&pci_vmsvga->card, 2);
+    }
 
     case SVGA_REG_MEM_SIZE:
         return s->fifo_size;
@@ -1134,17 +1138,22 @@ static void vmsvga_vram_writel(void *opaque, target_phys_addr_t addr,
         *(uint32_t *) (s->vram_ptr + addr) = value;
 }
 
-static CPUReadMemoryFunc * const vmsvga_vram_read[] = {
-    vmsvga_vram_readb,
-    vmsvga_vram_readw,
-    vmsvga_vram_readl,
-};
+static const MemoryRegionOps vmsvga_vram_io_ops = {
+    .old_mmio = {
+        .read = {
+            vmsvga_vram_readb,
+            vmsvga_vram_readw,
+            vmsvga_vram_readl,
+        },
+        .write = {
+            vmsvga_vram_writeb,
+            vmsvga_vram_writew,
+            vmsvga_vram_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+}
 
-static CPUWriteMemoryFunc * const vmsvga_vram_write[] = {
-    vmsvga_vram_writeb,
-    vmsvga_vram_writew,
-    vmsvga_vram_writel,
-};
 #endif
 
 static int vmsvga_post_load(void *opaque, int version_id)
@@ -1210,8 +1219,8 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
 
 
     s->fifo_size = SVGA_FIFO_SIZE;
-    s->fifo_offset = qemu_ram_alloc(NULL, "vmsvga.fifo", s->fifo_size);
-    s->fifo_ptr = qemu_get_ram_ptr(s->fifo_offset);
+    memory_region_init_ram(&s->fifo_ram, NULL, "vmsvga.fifo", s->fifo_size);
+    s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram);
 
     vga_common_init(&s->vga, vga_ram_size);
     vga_init(&s->vga);
@@ -1220,80 +1229,76 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
     vmsvga_reset(s);
 }
 
-static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
-                pcibus_t addr, pcibus_t size, int type)
+static uint64_t vmsvga_io_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
-    struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
-    struct vmsvga_state_s *s = &d->chip;
-
-    register_ioport_read(addr + SVGA_IO_MUL * SVGA_INDEX_PORT,
-                    1, 4, vmsvga_index_read, s);
-    register_ioport_write(addr + SVGA_IO_MUL * SVGA_INDEX_PORT,
-                    1, 4, vmsvga_index_write, s);
-    register_ioport_read(addr + SVGA_IO_MUL * SVGA_VALUE_PORT,
-                    1, 4, vmsvga_value_read, s);
-    register_ioport_write(addr + SVGA_IO_MUL * SVGA_VALUE_PORT,
-                    1, 4, vmsvga_value_write, s);
-    register_ioport_read(addr + SVGA_IO_MUL * SVGA_BIOS_PORT,
-                    1, 4, vmsvga_bios_read, s);
-    register_ioport_write(addr + SVGA_IO_MUL * SVGA_BIOS_PORT,
-                    1, 4, vmsvga_bios_write, s);
+    struct vmsvga_state_s *s = opaque;
+
+    switch (addr) {
+    case SVGA_IO_MUL * SVGA_INDEX_PORT: return vmsvga_index_read(s, addr);
+    case SVGA_IO_MUL * SVGA_VALUE_PORT: return vmsvga_value_read(s, addr);
+    case SVGA_IO_MUL * SVGA_BIOS_PORT: return vmsvga_bios_read(s, addr);
+    default: return -1u;
+    }
 }
 
-static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
-                pcibus_t addr, pcibus_t size, int type)
+static void vmsvga_io_write(void *opaque, target_phys_addr_t addr,
+                            uint64_t data, unsigned size)
 {
-    struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
-    struct vmsvga_state_s *s = &d->chip;
-    ram_addr_t iomemtype;
-
-    s->vram_base = addr;
-#ifdef DIRECT_VRAM
-    iomemtype = cpu_register_io_memory(vmsvga_vram_read,
-                    vmsvga_vram_write, s, DEVICE_NATIVE_ENDIAN);
-#else
-    iomemtype = s->vga.vram_offset | IO_MEM_RAM;
-#endif
-    cpu_register_physical_memory(s->vram_base, s->vga.vram_size,
-                    iomemtype);
+    struct vmsvga_state_s *s = opaque;
 
-    s->vga.map_addr = addr;
-    s->vga.map_end = addr + s->vga.vram_size;
-    vga_dirty_log_restart(&s->vga);
+    switch (addr) {
+    case SVGA_IO_MUL * SVGA_INDEX_PORT:
+        return vmsvga_index_write(s, addr, data);
+    case SVGA_IO_MUL * SVGA_VALUE_PORT:
+        return vmsvga_value_write(s, addr, data);
+    case SVGA_IO_MUL * SVGA_BIOS_PORT:
+        return vmsvga_bios_write(s, addr, data);
+    }
 }
 
-static void pci_vmsvga_map_fifo(PCIDevice *pci_dev, int region_num,
-                pcibus_t addr, pcibus_t size, int type)
-{
-    struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
-    struct vmsvga_state_s *s = &d->chip;
-    ram_addr_t iomemtype;
-
-    s->fifo_base = addr;
-    iomemtype = s->fifo_offset | IO_MEM_RAM;
-    cpu_register_physical_memory(s->fifo_base, s->fifo_size,
-                    iomemtype);
-}
+static const MemoryRegionOps vmsvga_io_ops = {
+    .read = vmsvga_io_read,
+    .write = vmsvga_io_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
 
 static int pci_vmsvga_initfn(PCIDevice *dev)
 {
     struct pci_vmsvga_state_s *s =
         DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
+    MemoryRegion *iomem;
+
+#ifdef DIRECT_VRAM
+    DirectMem *directmem = qemu_malloc(sizeof(*directmem));
+
+    iomem = &directmem->mr;
+    memory_region_init_io(iomem, &vmsvga_vram_io_ops, &s->chip, "vmsvga",
+                          memory_region_size(&s->chip.vga.vram));
+#else
+    iomem = &s->chip.vga.vram;
+#endif
+
+    vga_dirty_log_restart(&s->chip.vga);
 
     s->card.config[PCI_CACHE_LINE_SIZE]        = 0x08;         /* Cache line size */
     s->card.config[PCI_LATENCY_TIMER] = 0x40;          /* Latency timer */
     s->card.config[PCI_INTERRUPT_LINE] = 0xff;         /* End */
 
-    pci_register_bar(&s->card, 0, 0x10,
-                    PCI_BASE_ADDRESS_SPACE_IO, pci_vmsvga_map_ioport);
-    pci_register_bar(&s->card, 1, VGA_RAM_SIZE,
-                    PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_mem);
-
-    pci_register_bar(&s->card, 2, SVGA_FIFO_SIZE,
-                    PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_fifo);
+    memory_region_init_io(&s->io_bar, &vmsvga_io_ops, &s->chip,
+                          "vmsvga-io", 0x10);
+    pci_register_bar(&s->card, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
 
     vmsvga_init(&s->chip, VGA_RAM_SIZE);
 
+    pci_register_bar(&s->card, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, iomem);
+    pci_register_bar(&s->card, 2, PCI_BASE_ADDRESS_MEM_PREFETCH,
+                     &s->chip.fifo_ram);
+
     if (!dev->rom_bar) {
         /* compatibility with pc-0.13 and older */
         vga_init_vbe(&s->chip.vga);
index 53786ce8fa226fd8ee4041b117b3394d2bce2b07..20d86731865b20d9c663a5b8c0b95b041848eb7d 100644 (file)
@@ -66,6 +66,7 @@
 /* Device state. */
 struct I6300State {
     PCIDevice dev;
+    MemoryRegion io_mem;
 
     int reboot_enabled;         /* "Reboot" on timer expiry.  The real action
                                  * performed depends on the -watchdog-action
@@ -355,6 +356,22 @@ static void i6300esb_mem_writel(void *vp, target_phys_addr_t addr, uint32_t val)
     }
 }
 
+static const MemoryRegionOps i6300esb_ops = {
+    .old_mmio = {
+        .read = {
+            i6300esb_mem_readb,
+            i6300esb_mem_readw,
+            i6300esb_mem_readl,
+        },
+        .write = {
+            i6300esb_mem_writeb,
+            i6300esb_mem_writew,
+            i6300esb_mem_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
 static const VMStateDescription vmstate_i6300esb = {
     .name = "i6300esb_wdt",
     .version_id = sizeof(I6300State),
@@ -381,31 +398,28 @@ static const VMStateDescription vmstate_i6300esb = {
 static int i6300esb_init(PCIDevice *dev)
 {
     I6300State *d = DO_UPCAST(I6300State, dev, dev);
-    int io_mem;
-    static CPUReadMemoryFunc * const mem_read[3] = {
-        i6300esb_mem_readb,
-        i6300esb_mem_readw,
-        i6300esb_mem_readl,
-    };
-    static CPUWriteMemoryFunc * const mem_write[3] = {
-        i6300esb_mem_writeb,
-        i6300esb_mem_writew,
-        i6300esb_mem_writel,
-    };
 
     i6300esb_debug("I6300State = %p\n", d);
 
     d->timer = qemu_new_timer_ns(vm_clock, i6300esb_timer_expired, d);
     d->previous_reboot_flag = 0;
 
-    io_mem = cpu_register_io_memory(mem_read, mem_write, d,
-                                    DEVICE_NATIVE_ENDIAN);
-    pci_register_bar_simple(&d->dev, 0, 0x10, 0, io_mem);
+    memory_region_init_io(&d->io_mem, &i6300esb_ops, d, "i6300esb", 0x10);
+    pci_register_bar(&d->dev, 0, 0, &d->io_mem);
     /* qemu_register_coalesced_mmio (addr, 0x10); ? */
 
     return 0;
 }
 
+static int i6300esb_exit(PCIDevice *dev)
+{
+    I6300State *d = DO_UPCAST(I6300State, dev, dev);
+
+    memory_region_destroy(&d->io_mem);
+
+    return 0;
+}
+
 static WatchdogTimerModel model = {
     .wdt_name = "i6300esb",
     .wdt_description = "Intel 6300ESB",
@@ -419,6 +433,7 @@ static PCIDeviceInfo i6300esb_info = {
     .config_read  = i6300esb_config_read,
     .config_write = i6300esb_config_write,
     .init         = i6300esb_init,
+    .exit         = i6300esb_exit,
     .vendor_id    = PCI_VENDOR_ID_INTEL,
     .device_id    = PCI_DEVICE_ID_INTEL_ESB_9,
     .class_id     = PCI_CLASS_SYSTEM_OTHER,
index e432705f45601e6992dbb375b00d23ab144778f4..21621115e48624ef8a0c0f351cbdb7e9e8c9aafa 100644 (file)
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -24,7 +24,7 @@ extern int xen_allowed;
 
 static inline int xen_enabled(void)
 {
-#ifdef CONFIG_XEN
+#if defined(CONFIG_XEN_BACKEND) && !defined(CONFIG_NO_XEN)
     return xen_allowed;
 #else
     return 0;
index f43e175b4e2442cd7b5980641b1021007f2fc65a..6e3ba8b5076606d054bb1da7dd0659bbde9fd3c9 100644 (file)
@@ -32,8 +32,8 @@
 #include "xen_common.h"
 #include "net.h"
 #include "xen_backend.h"
-#include "rwhandler.h"
 #include "trace.h"
+#include "exec-memory.h"
 
 #include <xenguest.h>
 
@@ -51,6 +51,9 @@
 
 typedef struct PCIXenPlatformState {
     PCIDevice  pci_dev;
+    MemoryRegion fixed_io;
+    MemoryRegion bar;
+    MemoryRegion mmio_bar;
     uint8_t flags; /* used only for version_id == 2 */
     int drivers_blacklisted;
     uint16_t driver_product_version;
@@ -76,6 +79,35 @@ static void log_writeb(PCIXenPlatformState *s, char val)
 }
 
 /* Xen Platform, Fixed IOPort */
+#define UNPLUG_ALL_IDE_DISKS 1
+#define UNPLUG_ALL_NICS 2
+#define UNPLUG_AUX_IDE_DISKS 4
+
+static void unplug_nic(PCIBus *b, PCIDevice *d)
+{
+    if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
+            PCI_CLASS_NETWORK_ETHERNET) {
+        qdev_unplug(&(d->qdev));
+    }
+}
+
+static void pci_unplug_nics(PCIBus *bus)
+{
+    pci_for_each_device(bus, 0, unplug_nic);
+}
+
+static void unplug_disks(PCIBus *b, PCIDevice *d)
+{
+    if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
+            PCI_CLASS_STORAGE_IDE) {
+        qdev_unplug(&(d->qdev));
+    }
+}
+
+static void pci_unplug_disks(PCIBus *bus)
+{
+    pci_for_each_device(bus, 0, unplug_disks);
+}
 
 static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
 {
@@ -83,10 +115,22 @@ static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t v
 
     switch (addr - XEN_PLATFORM_IOPORT) {
     case 0:
-        /* TODO: */
         /* Unplug devices.  Value is a bitmask of which devices to
            unplug, with bit 0 the IDE devices, bit 1 the network
            devices, and bit 2 the non-primary-master IDE devices. */
+        if (val & UNPLUG_ALL_IDE_DISKS) {
+            DPRINTF("unplug disks\n");
+            qemu_aio_flush();
+            bdrv_flush_all();
+            pci_unplug_disks(s->pci_dev.bus);
+        }
+        if (val & UNPLUG_ALL_NICS) {
+            DPRINTF("unplug nics\n");
+            pci_unplug_nics(s->pci_dev.bus);
+        }
+        if (val & UNPLUG_AUX_IDE_DISKS) {
+            DPRINTF("unplug auxiliary disks not supported\n");
+        }
         break;
     case 2:
         switch (val) {
@@ -180,21 +224,32 @@ static void platform_fixed_ioport_reset(void *opaque)
     platform_fixed_ioport_writeb(s, XEN_PLATFORM_IOPORT, 0);
 }
 
+const MemoryRegionPortio xen_platform_ioport[] = {
+    { 0, 16, 4, .write = platform_fixed_ioport_writel, },
+    { 0, 16, 2, .write = platform_fixed_ioport_writew, },
+    { 0, 16, 1, .write = platform_fixed_ioport_writeb, },
+    { 0, 16, 2, .read = platform_fixed_ioport_readw, },
+    { 0, 16, 1, .read = platform_fixed_ioport_readb, },
+    PORTIO_END_OF_LIST()
+};
+
+static const MemoryRegionOps platform_fixed_io_ops = {
+    .old_portio = xen_platform_ioport,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
 static void platform_fixed_ioport_init(PCIXenPlatformState* s)
 {
-    register_ioport_write(XEN_PLATFORM_IOPORT, 16, 4, platform_fixed_ioport_writel, s);
-    register_ioport_write(XEN_PLATFORM_IOPORT, 16, 2, platform_fixed_ioport_writew, s);
-    register_ioport_write(XEN_PLATFORM_IOPORT, 16, 1, platform_fixed_ioport_writeb, s);
-    register_ioport_read(XEN_PLATFORM_IOPORT, 16, 2, platform_fixed_ioport_readw, s);
-    register_ioport_read(XEN_PLATFORM_IOPORT, 16, 1, platform_fixed_ioport_readb, s);
+    memory_region_init_io(&s->fixed_io, &platform_fixed_io_ops, s,
+                          "xen-fixed", 16);
+    memory_region_add_subregion(get_system_io(), XEN_PLATFORM_IOPORT,
+                                &s->fixed_io);
 }
 
 /* Xen Platform PCI Device */
 
 static uint32_t xen_platform_ioport_readb(void *opaque, uint32_t addr)
 {
-    addr &= 0xff;
-
     if (addr == 0) {
         return platform_fixed_ioport_readb(opaque, XEN_PLATFORM_IOPORT);
     } else {
@@ -206,9 +261,6 @@ static void xen_platform_ioport_writeb(void *opaque, uint32_t addr, uint32_t val
 {
     PCIXenPlatformState *s = opaque;
 
-    addr &= 0xff;
-    val  &= 0xff;
-
     switch (addr) {
     case 0: /* Platform flags */
         platform_fixed_ioport_writeb(opaque, XEN_PLATFORM_IOPORT, val);
@@ -221,15 +273,23 @@ static void xen_platform_ioport_writeb(void *opaque, uint32_t addr, uint32_t val
     }
 }
 
-static void platform_ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr, pcibus_t size, int type)
-{
-    PCIXenPlatformState *d = DO_UPCAST(PCIXenPlatformState, pci_dev, pci_dev);
+static MemoryRegionPortio xen_pci_portio[] = {
+    { 0, 0x100, 1, .read = xen_platform_ioport_readb, },
+    { 0, 0x100, 1, .write = xen_platform_ioport_writeb, },
+    PORTIO_END_OF_LIST()
+};
+
+static const MemoryRegionOps xen_pci_io_ops = {
+    .old_portio = xen_pci_portio,
+};
 
-    register_ioport_write(addr, size, 1, xen_platform_ioport_writeb, d);
-    register_ioport_read(addr, size, 1, xen_platform_ioport_readb, d);
+static void platform_ioport_bar_setup(PCIXenPlatformState *d)
+{
+    memory_region_init_io(&d->bar, &xen_pci_io_ops, d, "xen-pci", 0x100);
 }
 
-static uint32_t platform_mmio_read(ReadWriteHandler *handler, pcibus_t addr, int len)
+static uint64_t platform_mmio_read(void *opaque, target_phys_addr_t addr,
+                                   unsigned size)
 {
     DPRINTF("Warning: attempted read from physical address "
             "0x" TARGET_FMT_plx " in xen platform mmio space\n", addr);
@@ -237,28 +297,24 @@ static uint32_t platform_mmio_read(ReadWriteHandler *handler, pcibus_t addr, int
     return 0;
 }
 
-static void platform_mmio_write(ReadWriteHandler *handler, pcibus_t addr,
-                                uint32_t val, int len)
+static void platform_mmio_write(void *opaque, target_phys_addr_t addr,
+                                uint64_t val, unsigned size)
 {
-    DPRINTF("Warning: attempted write of 0x%x to physical "
+    DPRINTF("Warning: attempted write of 0x%"PRIx64" to physical "
             "address 0x" TARGET_FMT_plx " in xen platform mmio space\n",
             val, addr);
 }
 
-static ReadWriteHandler platform_mmio_handler = {
+static const MemoryRegionOps platform_mmio_handler = {
     .read = &platform_mmio_read,
     .write = &platform_mmio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void platform_mmio_map(PCIDevice *d, int region_num,
-                              pcibus_t addr, pcibus_t size, int type)
+static void platform_mmio_setup(PCIXenPlatformState *d)
 {
-    int mmio_io_addr;
-
-    mmio_io_addr = cpu_register_io_memory_simple(&platform_mmio_handler,
-                                                 DEVICE_NATIVE_ENDIAN);
-
-    cpu_register_physical_memory(addr, size, mmio_io_addr);
+    memory_region_init_io(&d->mmio_bar, &platform_mmio_handler, d,
+                          "xen-mmio", 0x1000000);
 }
 
 static int xen_platform_post_load(void *opaque, int version_id)
@@ -296,12 +352,13 @@ static int xen_platform_initfn(PCIDevice *dev)
 
     pci_conf[PCI_INTERRUPT_PIN] = 1;
 
-    pci_register_bar(&d->pci_dev, 0, 0x100,
-            PCI_BASE_ADDRESS_SPACE_IO, platform_ioport_map);
+    platform_ioport_bar_setup(d);
+    pci_register_bar(&d->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->bar);
 
     /* reserve 16MB mmio address for share memory*/
-    pci_register_bar(&d->pci_dev, 1, 0x1000000,
-            PCI_BASE_ADDRESS_MEM_PREFETCH, platform_mmio_map);
+    platform_mmio_setup(d);
+    pci_register_bar(&d->pci_dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
+                     &d->mmio_bar);
 
     platform_fixed_ioport_init(d);
 
diff --git a/hw/z2.c b/hw/z2.c
new file mode 100644 (file)
index 0000000..f93a1bf
--- /dev/null
+++ b/hw/z2.c
@@ -0,0 +1,358 @@
+/*
+ * PXA270-based Zipit Z2 device
+ *
+ * Copyright (c) 2011 by Vasily Khoruzhick <anarsoul@gmail.com>
+ *
+ * Code is based on mainstone platform.
+ *
+ * This code is licensed under the GNU GPL v2.
+ */
+
+#include "hw.h"
+#include "pxa.h"
+#include "arm-misc.h"
+#include "devices.h"
+#include "i2c.h"
+#include "ssi.h"
+#include "boards.h"
+#include "sysemu.h"
+#include "flash.h"
+#include "blockdev.h"
+#include "console.h"
+#include "audio/audio.h"
+
+#ifdef DEBUG_Z2
+#define DPRINTF(fmt, ...) \
+        printf(fmt, ## __VA_ARGS__)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+static struct keymap map[0x100] = {
+    [0 ... 0xff] = { -1, -1 },
+    [0x3b] = {0, 0}, /* Option = F1 */
+    [0xc8] = {0, 1}, /* Up */
+    [0xd0] = {0, 2}, /* Down */
+    [0xcb] = {0, 3}, /* Left */
+    [0xcd] = {0, 4}, /* Right */
+    [0xcf] = {0, 5}, /* End */
+    [0x0d] = {0, 6}, /* KPPLUS */
+    [0xc7] = {1, 0}, /* Home */
+    [0x10] = {1, 1}, /* Q */
+    [0x17] = {1, 2}, /* I */
+    [0x22] = {1, 3}, /* G */
+    [0x2d] = {1, 4}, /* X */
+    [0x1c] = {1, 5}, /* Enter */
+    [0x0c] = {1, 6}, /* KPMINUS */
+    [0xc9] = {2, 0}, /* PageUp */
+    [0x11] = {2, 1}, /* W */
+    [0x18] = {2, 2}, /* O */
+    [0x23] = {2, 3}, /* H */
+    [0x2e] = {2, 4}, /* C */
+    [0x38] = {2, 5}, /* LeftAlt */
+    [0xd1] = {3, 0}, /* PageDown */
+    [0x12] = {3, 1}, /* E */
+    [0x19] = {3, 2}, /* P */
+    [0x24] = {3, 3}, /* J */
+    [0x2f] = {3, 4}, /* V */
+    [0x2a] = {3, 5}, /* LeftShift */
+    [0x01] = {4, 0}, /* Esc */
+    [0x13] = {4, 1}, /* R */
+    [0x1e] = {4, 2}, /* A */
+    [0x25] = {4, 3}, /* K */
+    [0x30] = {4, 4}, /* B */
+    [0x1d] = {4, 5}, /* LeftCtrl */
+    [0x0f] = {5, 0}, /* Tab */
+    [0x14] = {5, 1}, /* T */
+    [0x1f] = {5, 2}, /* S */
+    [0x26] = {5, 3}, /* L */
+    [0x31] = {5, 4}, /* N */
+    [0x39] = {5, 5}, /* Space */
+    [0x3c] = {6, 0}, /* Stop = F2 */
+    [0x15] = {6, 1}, /* Y */
+    [0x20] = {6, 2}, /* D */
+    [0x0e] = {6, 3}, /* Backspace */
+    [0x32] = {6, 4}, /* M */
+    [0x33] = {6, 5}, /* Comma */
+    [0x3d] = {7, 0}, /* Play = F3 */
+    [0x16] = {7, 1}, /* U */
+    [0x21] = {7, 2}, /* F */
+    [0x2c] = {7, 3}, /* Z */
+    [0x27] = {7, 4}, /* Semicolon */
+    [0x34] = {7, 5}, /* Dot */
+};
+
+#define Z2_RAM_SIZE     0x02000000
+#define Z2_FLASH_BASE   0x00000000
+#define Z2_FLASH_SIZE   0x00800000
+
+static struct arm_boot_info z2_binfo = {
+    .loader_start   = PXA2XX_SDRAM_BASE,
+    .ram_size       = Z2_RAM_SIZE,
+};
+
+#define Z2_GPIO_SD_DETECT   96
+#define Z2_GPIO_AC_IN       0
+#define Z2_GPIO_KEY_ON      1
+#define Z2_GPIO_LCD_CS      88
+
+typedef struct {
+    SSISlave ssidev;
+    int32_t selected;
+    int32_t enabled;
+    uint8_t buf[3];
+    uint32_t cur_reg;
+    int pos;
+} ZipitLCD;
+
+static uint32_t zipit_lcd_transfer(SSISlave *dev, uint32_t value)
+{
+    ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
+    uint16_t val;
+    if (z->selected) {
+        z->buf[z->pos] = value & 0xff;
+        z->pos++;
+    }
+    if (z->pos == 3) {
+        switch (z->buf[0]) {
+        case 0x74:
+            DPRINTF("%s: reg: 0x%.2x\n", __func__, z->buf[2]);
+            z->cur_reg = z->buf[2];
+            break;
+        case 0x76:
+            val = z->buf[1] << 8 | z->buf[2];
+            DPRINTF("%s: value: 0x%.4x\n", __func__, val);
+            if (z->cur_reg == 0x22 && val == 0x0000) {
+                z->enabled = 1;
+                printf("%s: LCD enabled\n", __func__);
+            } else if (z->cur_reg == 0x10 && val == 0x0000) {
+                z->enabled = 0;
+                printf("%s: LCD disabled\n", __func__);
+            }
+            break;
+        default:
+            DPRINTF("%s: unknown command!\n", __func__);
+            break;
+        }
+        z->pos = 0;
+    }
+    return 0;
+}
+
+static void z2_lcd_cs(void *opaque, int line, int level)
+{
+    ZipitLCD *z2_lcd = opaque;
+    z2_lcd->selected = !level;
+}
+
+static int zipit_lcd_init(SSISlave *dev)
+{
+    ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
+    z->selected = 0;
+    z->enabled = 0;
+    z->pos = 0;
+
+    return 0;
+}
+
+static VMStateDescription vmstate_zipit_lcd_state = {
+    .name = "zipit-lcd",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT32(selected, ZipitLCD),
+        VMSTATE_INT32(enabled, ZipitLCD),
+        VMSTATE_BUFFER(buf, ZipitLCD),
+        VMSTATE_UINT32(cur_reg, ZipitLCD),
+        VMSTATE_INT32(pos, ZipitLCD),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static SSISlaveInfo zipit_lcd_info = {
+    .qdev.name = "zipit-lcd",
+    .qdev.size = sizeof(ZipitLCD),
+    .qdev.vmsd = &vmstate_zipit_lcd_state,
+    .init = zipit_lcd_init,
+    .transfer = zipit_lcd_transfer
+};
+
+typedef struct {
+    i2c_slave i2c;
+    int len;
+    uint8_t buf[3];
+} AER915State;
+
+static int aer915_send(i2c_slave *i2c, uint8_t data)
+{
+    AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
+    s->buf[s->len] = data;
+    if (s->len++ > 2) {
+        DPRINTF("%s: message too long (%i bytes)\n",
+            __func__, s->len);
+        return 1;
+    }
+
+    if (s->len == 2) {
+        DPRINTF("%s: reg %d value 0x%02x\n", __func__,
+                s->buf[0], s->buf[1]);
+    }
+
+    return 0;
+}
+
+static void aer915_event(i2c_slave *i2c, enum i2c_event event)
+{
+    AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
+    switch (event) {
+    case I2C_START_SEND:
+        s->len = 0;
+        break;
+    case I2C_START_RECV:
+        if (s->len != 1) {
+            DPRINTF("%s: short message!?\n", __func__);
+        }
+        break;
+    case I2C_FINISH:
+        break;
+    default:
+        break;
+    }
+}
+
+static int aer915_recv(i2c_slave *slave)
+{
+    int retval = 0x00;
+    AER915State *s = FROM_I2C_SLAVE(AER915State, slave);
+
+    switch (s->buf[0]) {
+    /* Return hardcoded battery voltage,
+     * 0xf0 means ~4.1V
+     */
+    case 0x02:
+        retval = 0xf0;
+        break;
+    /* Return 0x00 for other regs,
+     * we don't know what they are for,
+     * anyway they return 0x00 on real hardware.
+     */
+    default:
+        break;
+    }
+
+    return retval;
+}
+
+static int aer915_init(i2c_slave *i2c)
+{
+    /* Nothing to do.  */
+    return 0;
+}
+
+static VMStateDescription vmstate_aer915_state = {
+    .name = "aer915",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT32(len, AER915State),
+        VMSTATE_BUFFER(buf, AER915State),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static I2CSlaveInfo aer915_info = {
+    .qdev.name = "aer915",
+    .qdev.size = sizeof(AER915State),
+    .qdev.vmsd = &vmstate_aer915_state,
+    .init = aer915_init,
+    .event = aer915_event,
+    .recv = aer915_recv,
+    .send = aer915_send
+};
+
+static void z2_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)
+{
+    uint32_t sector_len = 0x10000;
+    PXA2xxState *cpu;
+    DriveInfo *dinfo;
+    int be;
+    void *z2_lcd;
+    i2c_bus *bus;
+    DeviceState *wm;
+
+    if (!cpu_model) {
+        cpu_model = "pxa270-c5";
+    }
+
+    /* Setup CPU & memory */
+    cpu = pxa270_init(z2_binfo.ram_size, cpu_model);
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "Flash image must be given with the "
+                "'pflash' parameter\n");
+        exit(1);
+    }
+
+    if (!pflash_cfi01_register(Z2_FLASH_BASE,
+                               qemu_ram_alloc(NULL, "z2.flash0", Z2_FLASH_SIZE),
+                               dinfo->bdrv, sector_len,
+                               Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
+                               be)) {
+        fprintf(stderr, "qemu: Error registering flash memory.\n");
+        exit(1);
+    }
+
+    /* setup keypad */
+    pxa27x_register_keypad(cpu->kp, map, 0x100);
+
+    /* MMC/SD host */
+    pxa2xx_mmci_handlers(cpu->mmc,
+        NULL,
+        qdev_get_gpio_in(cpu->gpio, Z2_GPIO_SD_DETECT));
+
+    ssi_register_slave(&zipit_lcd_info);
+    i2c_register_slave(&aer915_info);
+    z2_lcd = ssi_create_slave(cpu->ssp[1], "zipit-lcd");
+    bus = pxa2xx_i2c_bus(cpu->i2c[0]);
+    i2c_create_slave(bus, "aer915", 0x55);
+    wm = i2c_create_slave(bus, "wm8750", 0x1b);
+    cpu->i2s->opaque = wm;
+    cpu->i2s->codec_out = wm8750_dac_dat;
+    cpu->i2s->codec_in = wm8750_adc_dat;
+    wm8750_data_req_set(wm, cpu->i2s->data_req, cpu->i2s);
+
+    qdev_connect_gpio_out(cpu->gpio, Z2_GPIO_LCD_CS,
+        qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
+
+    if (kernel_filename) {
+        z2_binfo.kernel_filename = kernel_filename;
+        z2_binfo.kernel_cmdline = kernel_cmdline;
+        z2_binfo.initrd_filename = initrd_filename;
+        z2_binfo.board_id = 0x6dd;
+        arm_load_kernel(cpu->env, &z2_binfo);
+    }
+}
+
+static QEMUMachine z2_machine = {
+    .name = "z2",
+    .desc = "Zipit Z2 (PXA27x)",
+    .init = z2_init,
+};
+
+static void z2_machine_init(void)
+{
+    qemu_register_machine(&z2_machine);
+}
+
+machine_init(z2_machine_init);
index 0d2611d14298f7747b8b71aaad5a0d184584aad8..a32483ba8403f2adc1f05d1d9b2b5baa12ed02ee 100644 (file)
--- a/ioport.c
+++ b/ioport.c
@@ -146,7 +146,7 @@ int register_ioport_read(pio_addr_t start, int length, int size,
         hw_error("register_ioport_read: invalid size");
         return -1;
     }
-    for(i = start; i < start + length; i += size) {
+    for(i = start; i < start + length; ++i) {
         ioport_read_table[bsize][i] = func;
         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
             hw_error("register_ioport_read: invalid opaque for address 0x%x",
@@ -166,7 +166,7 @@ int register_ioport_write(pio_addr_t start, int length, int size,
         hw_error("register_ioport_write: invalid size");
         return -1;
     }
-    for(i = start; i < start + length; i += size) {
+    for(i = start; i < start + length; ++i) {
         ioport_write_table[bsize][i] = func;
         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
             hw_error("register_ioport_write: invalid opaque for address 0x%x",
diff --git a/iov.c b/iov.c
index 1e027914d4862c15255f91706d41f22b894d7d3f..e7385c41f4ecc55f0234ba1cafd78f2fa1df0bbb 100644 (file)
--- a/iov.c
+++ b/iov.c
@@ -62,6 +62,29 @@ size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
     return buf_off;
 }
 
+size_t iov_clear(const struct iovec *iov, const unsigned int iov_cnt,
+                 size_t iov_off, size_t size)
+{
+    size_t iovec_off, buf_off;
+    unsigned int i;
+
+    iovec_off = 0;
+    buf_off = 0;
+    for (i = 0; i < iov_cnt && size; i++) {
+        if (iov_off < (iovec_off + iov[i].iov_len)) {
+            size_t len = MIN((iovec_off + iov[i].iov_len) - iov_off , size);
+
+            memset(iov[i].iov_base + (iov_off - iovec_off), 0, len);
+
+            buf_off += len;
+            iov_off += len;
+            size -= len;
+        }
+        iovec_off += iov[i].iov_len;
+    }
+    return buf_off;
+}
+
 size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt)
 {
     size_t len;
@@ -73,3 +96,34 @@ size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt)
     }
     return len;
 }
+
+void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt,
+                 FILE *fp, const char *prefix, size_t limit)
+{
+    unsigned int i, v, b;
+    uint8_t *c;
+
+    c = iov[0].iov_base;
+    for (i = 0, v = 0, b = 0; b < limit; i++, b++) {
+        if (i == iov[v].iov_len) {
+            i = 0; v++;
+            if (v == iov_cnt) {
+                break;
+            }
+            c = iov[v].iov_base;
+        }
+        if ((b % 16) == 0) {
+            fprintf(fp, "%s: %04x:", prefix, b);
+        }
+        if ((b % 4) == 0) {
+            fprintf(fp, " ");
+        }
+        fprintf(fp, " %02x", c[i]);
+        if ((b % 16) == 15) {
+            fprintf(fp, "\n");
+        }
+    }
+    if ((b % 16) != 0) {
+        fprintf(fp, "\n");
+    }
+}
diff --git a/iov.h b/iov.h
index 110f67ab530f8b95faaff0adfe6f78c6de133f1c..94d2f7828433890d133d37fff8d2b1122450d267 100644 (file)
--- a/iov.h
+++ b/iov.h
@@ -17,3 +17,7 @@ size_t iov_from_buf(struct iovec *iov, unsigned int iov_cnt,
 size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
                   void *buf, size_t iov_off, size_t size);
 size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt);
+size_t iov_clear(const struct iovec *iov, const unsigned int iov_cnt,
+                 size_t iov_off, size_t size);
+void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt,
+                 FILE *fp, const char *prefix, size_t limit);
index cbc253235e02e7264f37eff96929ca94e8bc2edc..b9c172b66437e2665108232613099a78df3d468d 100644 (file)
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1328,7 +1328,6 @@ int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset)
 
 int kvm_set_ioeventfd_mmio_long(int fd, uint32_t addr, uint32_t val, bool assign)
 {
-#ifdef KVM_IOEVENTFD
     int ret;
     struct kvm_ioeventfd iofd;
 
@@ -1353,14 +1352,10 @@ int kvm_set_ioeventfd_mmio_long(int fd, uint32_t addr, uint32_t val, bool assign
     }
 
     return 0;
-#else
-    return -ENOSYS;
-#endif
 }
 
 int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
 {
-#ifdef KVM_IOEVENTFD
     struct kvm_ioeventfd kick = {
         .datamatch = val,
         .addr = addr,
@@ -1380,9 +1375,6 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
         return r;
     }
     return 0;
-#else
-    return -ENOSYS;
-#endif
 }
 
 int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr)
index 9802c37ee8d7a50e773de598a22798c84878cefe..5cd759444bf7c125834708abc02bc3044b70530b 100644 (file)
@@ -2,7 +2,10 @@
 -include $(SRC_PATH)/Makefile.objs
 -include $(SRC_PATH)/rules.mak
 
-$(call set-vpath, $(SRC_PATH):$(SRC_PATH)/libcacard)
+libcacard_srcpath=$(SRC_PATH)/libcacard
+libcacard_includedir=$(includedir)/cacard
+
+$(call set-vpath, $(SRC_PATH):$(libcacard_srcpath))
 
 # objects linked against normal qemu binaries, not compiled with libtool
 QEMU_OBJS=$(addprefix ../,$(oslib-obj-y) qemu-malloc.o qemu-timer-common.o $(trace-obj-y))
@@ -18,7 +21,7 @@ vscclient: $(libcacard-y) $(QEMU_OBJS) vscclient.o
        $(call quiet-command,$(CC) $(libcacard_libs) -lrt -o $@ $^,"  LINK  $@")
 
 clean:
-       rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~ vscclient *.lo .libs/* *.la
+       rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~ vscclient *.lo .libs/* *.la *.pc
        rm -Rf .libs
 
 all: vscclient
@@ -36,7 +39,24 @@ else
 libcacard.la: $(libcacard.lib-y) $(QEMU_OBJS_LIB)
        $(call quiet-command,libtool --mode=link --quiet --tag=CC $(CC) $(libcacard_libs) -lrt -rpath $(libdir) -o $@ $^,"  lt LINK $@")
 
-install-libcacard: libcacard.la
+libcacard.pc: $(libcacard_srcpath)/libcacard.pc.in
+       sed -e 's|@LIBDIR@|$(libdir)|' \
+               -e 's|@INCLUDEDIR@|$(libcacard_includedir)|' \
+           -e 's|@VERSION@|$(shell cat $(SRC_PATH)/VERSION)|' \
+               -e 's|@PREFIX@|$(prefix)|' \
+               < $(libcacard_srcpath)/libcacard.pc.in > libcacard.pc
+
+.PHONY: install-libcacard
+
+install-libcacard: libcacard.pc libcacard.la vscclient
        $(INSTALL_DIR) "$(DESTDIR)$(libdir)"
+       $(INSTALL_DIR) "$(DESTDIR)$(libdir)/pkgconfig"
+       $(INSTALL_DIR) "$(DESTDIR)$(libcacard_includedir)"
+       $(INSTALL_DIR) "$(DESTDIR)$(bindir)"
+       libtool --mode=install $(INSTALL_PROG) vscclient "$(DESTDIR)$(bindir)"
        libtool --mode=install $(INSTALL_PROG) libcacard.la "$(DESTDIR)$(libdir)"
+       libtool --mode=install $(INSTALL_DATA) libcacard.pc "$(DESTDIR)$(libdir)/pkgconfig"
+       for inc in *.h; do \
+               libtool --mode=install $(INSTALL_DATA) $(libcacard_srcpath)/$$inc "$(DESTDIR)$(libcacard_includedir)"; \
+       done
 endif
diff --git a/libcacard/libcacard.pc.in b/libcacard/libcacard.pc.in
new file mode 100644 (file)
index 0000000..b6859b0
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=@PREFIX@
+exec_prefix=${prefix}
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@
+
+Name: cacard
+Description: CA Card library
+Version: @VERSION@
+
+Requires:  nss
+Libs: -L${libdir} -lcacard
+Libs.private:
+Cflags: -I${includedir}
index f3db657d749900058978749c0a56b78c3fc219a1..84fc49026fc352a6abb60a4b1a928b691c3d99c3 100644 (file)
 #include "vreader.h"
 #include "vevent.h"
 
+typedef enum {
+    VCardEmulUnknown = -1,
+    VCardEmulFalse = 0,
+    VCardEmulTrue = 1
+} VCardEmulTriState;
+
 struct VCardKeyStruct {
     CERTCertificate *cert;
     PK11SlotInfo *slot;
     SECKEYPrivateKey *key;
+    VCardEmulTriState failedX509;
 };
 
 
@@ -140,6 +147,7 @@ vcard_emul_make_key(PK11SlotInfo *slot, CERTCertificate *cert)
     /* NOTE: the cert is a temp cert, not necessarily the cert in the token,
      * use the DER version of this function */
     key->key = PK11_FindKeyByDERCert(slot, cert, NULL);
+    key->failedX509 = VCardEmulUnknown;
     return key;
 }
 
@@ -208,13 +216,23 @@ vcard_emul_rsa_op(VCard *card, VCardKey *key,
 {
     SECKEYPrivateKey *priv_key;
     unsigned signature_len;
+    PK11SlotInfo *slot;
     SECStatus rv;
+    unsigned char buf[2048];
+    unsigned char *bp = NULL;
+    int pad_len;
+    vcard_7816_status_t ret = VCARD7816_STATUS_SUCCESS;
 
     if ((!nss_emul_init) || (key == NULL)) {
         /* couldn't get the key, indicate that we aren't logged in */
         return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
     }
     priv_key = vcard_emul_get_nss_key(key);
+    if (priv_key == NULL) {
+        /* couldn't get the key, indicate that we aren't logged in */
+        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
+    }
+    slot = vcard_emul_card_get_slot(card);
 
     /*
      * this is only true of the rsa signature
@@ -223,13 +241,116 @@ vcard_emul_rsa_op(VCard *card, VCardKey *key,
     if (buffer_size != signature_len) {
         return  VCARD7816_STATUS_ERROR_DATA_INVALID;
     }
-    rv = PK11_PrivDecryptRaw(priv_key, buffer, &signature_len, signature_len,
-                             buffer, buffer_size);
-    if (rv != SECSuccess) {
-        return vcard_emul_map_error(PORT_GetError());
+    /* be able to handle larger keys if necessariy */
+    bp = &buf[0];
+    if (sizeof(buf) < signature_len) {
+        bp = qemu_malloc(signature_len);
+    }
+
+    /*
+     * do the raw operations. Some tokens claim to do CKM_RSA_X_509, but then
+     * choke when they try to do the actual operations. Try to detect
+     * those cases and treat them as if the token didn't claim support for
+     * X_509.
+     */
+    if (key->failedX509 != VCardEmulTrue
+                              && PK11_DoesMechanism(slot, CKM_RSA_X_509)) {
+        rv = PK11_PrivDecryptRaw(priv_key, bp, &signature_len, signature_len,
+                                 buffer, buffer_size);
+        if (rv == SECSuccess) {
+            assert(buffer_size == signature_len);
+            memcpy(buffer, bp, signature_len);
+            key->failedX509 = VCardEmulFalse;
+            goto cleanup;
+        }
+        /*
+         * we've had a successful X509 operation, this failure must be
+         * somethine else
+         */
+        if (key->failedX509 == VCardEmulFalse) {
+            ret = vcard_emul_map_error(PORT_GetError());
+            goto cleanup;
+        }
+        /*
+         * key->failedX509 must be Unknown at this point, try the
+         * non-x_509 case
+         */
+    }
+    /* token does not support CKM_RSA_X509, emulate that with CKM_RSA_PKCS */
+    /* is this a PKCS #1 formatted signature? */
+    if ((buffer[0] == 0) && (buffer[1] == 1)) {
+        int i;
+
+        for (i = 2; i < buffer_size; i++) {
+            /* rsa signature pad */
+            if (buffer[i] != 0xff) {
+                break;
+            }
+        }
+        if ((i < buffer_size) && (buffer[i] == 0)) {
+            /* yes, we have a properly formated PKCS #1 signature */
+            /*
+             * NOTE: even if we accidentally got an encrypt buffer, which
+             * through shear luck started with 00, 01, ff, 00, it won't matter
+             * because the resulting Sign operation will effectively decrypt
+             * the real buffer.
+             */
+            SECItem signature;
+            SECItem hash;
+
+            i++;
+            hash.data = &buffer[i];
+            hash.len = buffer_size - i;
+            signature.data = bp;
+            signature.len = signature_len;
+            rv = PK11_Sign(priv_key,  &signature, &hash);
+            if (rv != SECSuccess) {
+                ret = vcard_emul_map_error(PORT_GetError());
+                goto cleanup;
+            }
+            assert(buffer_size == signature.len);
+            memcpy(buffer, bp, signature.len);
+            /*
+             * we got here because either the X509 attempt failed, or the
+             * token couldn't do the X509 operation, in either case stay
+             * with the PKCS version for future operations on this key
+             */
+            key->failedX509 = VCardEmulTrue;
+            goto cleanup;
+        }
+    }
+    pad_len = buffer_size - signature_len;
+    assert(pad_len < 4);
+    /*
+     * OK now we've decrypted the payload, package it up in PKCS #1 for the
+     * upper layer.
+     */
+    buffer[0] = 0;
+    buffer[1] = 2; /* RSA_encrypt  */
+    pad_len -= 3; /* format is 0 || 2 || pad || 0 || data */
+    /*
+     * padding for PKCS #1 encrypted data is a string of random bytes. The
+     * random butes protect against potential decryption attacks against RSA.
+     * Since PrivDecrypt has already stripped those bytes, we can't reconstruct
+     * them. This shouldn't matter to the upper level code which should just
+     * strip this code out anyway, so We'll pad with a constant 3.
+     */
+    memset(&buffer[2], 0x03, pad_len);
+    pad_len += 2; /* index to the end of the pad */
+    buffer[pad_len] = 0;
+    pad_len++; /* index to the start of the data */
+    memcpy(&buffer[pad_len], bp, signature_len);
+    /*
+     * we got here because either the X509 attempt failed, or the
+     * token couldn't do the X509 operation, in either case stay
+     * with the PKCS version for future operations on this key
+     */
+    key->failedX509 = VCardEmulTrue;
+cleanup:
+    if (bp != buf) {
+        qemu_free(bp);
     }
-    assert(buffer_size == signature_len);
-    return VCARD7816_STATUS_SUCCESS;
+    return ret;
 }
 
 /*
@@ -476,6 +597,7 @@ vcard_emul_mirror_card(VReader *vreader)
     VCardKey **keys;
     PK11SlotInfo *slot;
     PRBool ret;
+    VCard *card;
 
     slot = vcard_emul_reader_get_slot(vreader);
     if (slot == NULL) {
@@ -535,7 +657,12 @@ vcard_emul_mirror_card(VReader *vreader)
     }
 
     /* now create the card */
-    return vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
+    card = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
+    qemu_free(certs);
+    qemu_free(cert_len);
+    qemu_free(keys);
+
+    return card;
 }
 
 static VCardEmulType default_card_type = VCARD_EMUL_NONE;
@@ -820,6 +947,9 @@ vcard_emul_init(const VCardEmulOptions *options)
             vreader_free(vreader);
             has_readers = PR_TRUE;
         }
+        qemu_free(certs);
+        qemu_free(cert_len);
+        qemu_free(keys);
     }
 
     /* if we aren't suppose to use hw, skip looking up hardware tokens */
@@ -925,17 +1055,6 @@ vcard_emul_replay_insertion_events(void)
 /*
  *  Silly little functions to help parsing our argument string
  */
-static char *
-copy_string(const char *str, int str_len)
-{
-    char *new_str;
-
-    new_str = qemu_malloc(str_len+1);
-    memcpy(new_str, str, str_len);
-    new_str[str_len] = 0;
-    return new_str;
-}
-
 static int
 count_tokens(const char *str, char token, char token_end)
 {
@@ -975,13 +1094,31 @@ find_blank(const char *str)
 static VCardEmulOptions options;
 #define READER_STEP 4
 
+/* Expects "args" to be at the beginning of a token (ie right after the ','
+ * ending the previous token), and puts the next token start in "token",
+ * and its length in "token_length". "token" will not be nul-terminated.
+ * After calling the macro, "args" will be advanced to the beginning of
+ * the next token.
+ * This macro may call continue or break.
+ */
+#define NEXT_TOKEN(token) \
+            (token) = args; \
+            args = strpbrk(args, ",)"); \
+            if (*args == 0) { \
+                break; \
+            } \
+            if (*args == ')') { \
+                args++; \
+                continue; \
+            } \
+            (token##_length) = args - (token); \
+            args = strip(args+1);
+
 VCardEmulOptions *
 vcard_emul_options(const char *args)
 {
     int reader_count = 0;
     VCardEmulOptions *opts;
-    char type_str[100];
-    int type_len;
 
     /* Allow the future use of allocating the options structure on the fly */
     memcpy(&options, &default_options, sizeof(options));
@@ -996,63 +1133,32 @@ vcard_emul_options(const char *args)
          *       cert_2,cert_3...) */
         if (strncmp(args, "soft=", 5) == 0) {
             const char *name;
+            size_t name_length;
             const char *vname;
+            size_t vname_length;
             const char *type_params;
+            size_t type_params_length;
+            char type_str[100];
             VCardEmulType type;
-            int name_length, vname_length, type_params_length, count, i;
+            int count, i;
             VirtualReaderOptions *vreaderOpt = NULL;
 
             args = strip(args + 5);
             if (*args != '(') {
                 continue;
             }
-            name = args;
-            args = strpbrk(args + 1, ",)");
-            if (*args == 0) {
-                break;
-            }
-            if (*args == ')') {
-                args++;
-                continue;
-            }
-            args = strip(args+1);
-            name_length = args - name - 2;
-            vname = args;
-            args = strpbrk(args + 1, ",)");
-            if (*args == 0) {
-                break;
-            }
-            if (*args == ')') {
-                args++;
-                continue;
-            }
-            vname_length = args - name - 2;
             args = strip(args+1);
-            type_len = strpbrk(args, ",)") - args;
-            assert(sizeof(type_str) > type_len);
-            strncpy(type_str, args, type_len);
-            type_str[type_len] = 0;
+
+            NEXT_TOKEN(name)
+            NEXT_TOKEN(vname)
+            NEXT_TOKEN(type_params)
+            type_params_length = MIN(type_params_length, sizeof(type_str)-1);
+            strncpy(type_str, type_params, type_params_length);
+            type_str[type_params_length] = 0;
             type = vcard_emul_type_from_string(type_str);
-            args = strpbrk(args, ",)");
-            if (*args == 0) {
-                break;
-            }
-            if (*args == ')') {
-                args++;
-                continue;
-            }
-            args = strip(args++);
-            type_params = args;
-            args = strpbrk(args + 1, ",)");
-            if (*args == 0) {
-                break;
-            }
-            if (*args == ')') {
-                args++;
-                continue;
-            }
-            type_params_length = args - name;
-            args = strip(args++);
+
+            NEXT_TOKEN(type_params)
+
             if (*args == 0) {
                 break;
             }
@@ -1067,18 +1173,19 @@ vcard_emul_options(const char *args)
             }
             opts->vreader = vreaderOpt;
             vreaderOpt = &vreaderOpt[opts->vreader_count];
-            vreaderOpt->name = copy_string(name, name_length);
-            vreaderOpt->vname = copy_string(vname, vname_length);
+            vreaderOpt->name = qemu_strndup(name, name_length);
+            vreaderOpt->vname = qemu_strndup(vname, vname_length);
             vreaderOpt->card_type = type;
             vreaderOpt->type_params =
-                copy_string(type_params, type_params_length);
-            count = count_tokens(args, ',', ')');
+                qemu_strndup(type_params, type_params_length);
+            count = count_tokens(args, ',', ')') + 1;
             vreaderOpt->cert_count = count;
             vreaderOpt->cert_name = (char **)qemu_malloc(count*sizeof(char *));
             for (i = 0; i < count; i++) {
-                const char *cert = args + 1;
-                args = strpbrk(args + 1, ",)");
-                vreaderOpt->cert_name[i] = copy_string(cert, args - cert);
+                const char *cert = args;
+                args = strpbrk(args, ",)");
+                vreaderOpt->cert_name[i] = qemu_strndup(cert, args - cert);
+                args = strip(args+1);
             }
             if (*args == ')') {
                 args++;
@@ -1104,7 +1211,7 @@ vcard_emul_options(const char *args)
             args = strip(args+10);
             params = args;
             args = find_blank(args);
-            opts->hw_type_params = copy_string(params, args-params);
+            opts->hw_type_params = qemu_strndup(params, args-params);
         /* db="/data/base/path" */
         } else if (strncmp(args, "db=", 3) == 0) {
             const char *db;
@@ -1115,7 +1222,7 @@ vcard_emul_options(const char *args)
             args++;
             db = args;
             args = strpbrk(args, "\"\n");
-            opts->nss_db = copy_string(db, args-db);
+            opts->nss_db = qemu_strndup(db, args-db);
             if (*args != 0) {
                 args++;
             }
index 68f4b3d7572f93057def5021160f39d0efc5f2cf..dc3faf24995a673c802ea754a28b73c26d69134c 100644 (file)
@@ -31,7 +31,6 @@ struct qemu_laiocb {
     struct iocb iocb;
     ssize_t ret;
     size_t nbytes;
-    int async_context_id;
     QLIST_ENTRY(qemu_laiocb) node;
 };
 
@@ -39,7 +38,6 @@ struct qemu_laio_state {
     io_context_t ctx;
     int efd;
     int count;
-    QLIST_HEAD(, qemu_laiocb) completed_reqs;
 };
 
 static inline ssize_t io_event_ret(struct io_event *ev)
@@ -49,7 +47,6 @@ static inline ssize_t io_event_ret(struct io_event *ev)
 
 /*
  * Completes an AIO request (calls the callback and frees the ACB).
- * Be sure to be in the right AsyncContext before calling this function.
  */
 static void qemu_laio_process_completion(struct qemu_laio_state *s,
     struct qemu_laiocb *laiocb)
@@ -72,42 +69,12 @@ static void qemu_laio_process_completion(struct qemu_laio_state *s,
 }
 
 /*
- * Processes all queued AIO requests, i.e. requests that have return from OS
- * but their callback was not called yet. Requests that cannot have their
- * callback called in the current AsyncContext, remain in the queue.
- *
- * Returns 1 if at least one request could be completed, 0 otherwise.
+ * All requests are directly processed when they complete, so there's nothing
+ * left to do during qemu_aio_wait().
  */
 static int qemu_laio_process_requests(void *opaque)
 {
-    struct qemu_laio_state *s = opaque;
-    struct qemu_laiocb *laiocb, *next;
-    int res = 0;
-
-    QLIST_FOREACH_SAFE (laiocb, &s->completed_reqs, node, next) {
-        if (laiocb->async_context_id == get_async_context_id()) {
-            qemu_laio_process_completion(s, laiocb);
-            QLIST_REMOVE(laiocb, node);
-            res = 1;
-        }
-    }
-
-    return res;
-}
-
-/*
- * Puts a request in the completion queue so that its callback is called the
- * next time when it's possible. If we already are in the right AsyncContext,
- * the request is completed immediately instead.
- */
-static void qemu_laio_enqueue_completed(struct qemu_laio_state *s,
-    struct qemu_laiocb* laiocb)
-{
-    if (laiocb->async_context_id == get_async_context_id()) {
-        qemu_laio_process_completion(s, laiocb);
-    } else {
-        QLIST_INSERT_HEAD(&s->completed_reqs, laiocb, node);
-    }
+    return 0;
 }
 
 static void qemu_laio_completion_cb(void *opaque)
@@ -141,7 +108,7 @@ static void qemu_laio_completion_cb(void *opaque)
                     container_of(iocb, struct qemu_laiocb, iocb);
 
             laiocb->ret = io_event_ret(&events[i]);
-            qemu_laio_enqueue_completed(s, laiocb);
+            qemu_laio_process_completion(s, laiocb);
         }
     }
 }
@@ -204,7 +171,6 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
     laiocb->nbytes = nb_sectors * 512;
     laiocb->ctx = s;
     laiocb->ret = -EINPROGRESS;
-    laiocb->async_context_id = get_async_context_id();
 
     iocbs = &laiocb->iocb;
 
@@ -239,7 +205,6 @@ void *laio_init(void)
     struct qemu_laio_state *s;
 
     s = qemu_mallocz(sizeof(*s));
-    QLIST_INIT(&s->completed_reqs);
     s->efd = eventfd(0, 0);
     if (s->efd == -1)
         goto out_free_state;
index 2135b9c714014bfe7d37efeace1896b92567607e..8e15474329c14e8a45f0867c806950885a9f838d 100644 (file)
@@ -3048,11 +3048,6 @@ int main(int argc, char **argv, char **envp)
             usage();
         }
     }
-    if (optind >= argc)
-        usage();
-    filename = argv[optind];
-    exec_path = argv[optind];
-
     /* init debug */
     cpu_set_log_filename(log_file);
     if (log_mask) {
@@ -3070,6 +3065,12 @@ int main(int argc, char **argv, char **envp)
         cpu_set_log(mask);
     }
 
+    if (optind >= argc) {
+        usage();
+    }
+    filename = argv[optind];
+    exec_path = argv[optind];
+
     /* Zero out regs */
     memset(regs, 0, sizeof(struct target_pt_regs));
 
@@ -3116,7 +3117,8 @@ int main(int argc, char **argv, char **envp)
         cpu_model = "any";
 #endif
     }
-    cpu_exec_init_all(0);
+    tcg_exec_init(0);
+    cpu_exec_init_all();
     /* NOTE: we need to init the CPU at this stage to get
        qemu_host_page_size */
     env = cpu_init(cpu_model);
diff --git a/memory.c b/memory.c
new file mode 100644 (file)
index 0000000..be891c6
--- /dev/null
+++ b/memory.c
@@ -0,0 +1,1150 @@
+/*
+ * Physical memory management
+ *
+ * Copyright 2011 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *  Avi Kivity <avi@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "memory.h"
+#include "exec-memory.h"
+#include "ioport.h"
+#include "bitops.h"
+#include "kvm.h"
+#include <assert.h>
+
+unsigned memory_region_transaction_depth = 0;
+
+typedef struct AddrRange AddrRange;
+
+/*
+ * Note using signed integers limits us to physical addresses at most
+ * 63 bits wide.  They are needed for negative offsetting in aliases
+ * (large MemoryRegion::alias_offset).
+ */
+struct AddrRange {
+    int64_t start;
+    int64_t size;
+};
+
+static AddrRange addrrange_make(int64_t start, int64_t size)
+{
+    return (AddrRange) { start, size };
+}
+
+static bool addrrange_equal(AddrRange r1, AddrRange r2)
+{
+    return r1.start == r2.start && r1.size == r2.size;
+}
+
+static int64_t addrrange_end(AddrRange r)
+{
+    return r.start + r.size;
+}
+
+static AddrRange addrrange_shift(AddrRange range, int64_t delta)
+{
+    range.start += delta;
+    return range;
+}
+
+static bool addrrange_intersects(AddrRange r1, AddrRange r2)
+{
+    return (r1.start >= r2.start && r1.start < r2.start + r2.size)
+        || (r2.start >= r1.start && r2.start < r1.start + r1.size);
+}
+
+static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2)
+{
+    int64_t start = MAX(r1.start, r2.start);
+    /* off-by-one arithmetic to prevent overflow */
+    int64_t end = MIN(addrrange_end(r1) - 1, addrrange_end(r2) - 1);
+    return addrrange_make(start, end - start + 1);
+}
+
+struct CoalescedMemoryRange {
+    AddrRange addr;
+    QTAILQ_ENTRY(CoalescedMemoryRange) link;
+};
+
+struct MemoryRegionIoeventfd {
+    AddrRange addr;
+    bool match_data;
+    uint64_t data;
+    int fd;
+};
+
+static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
+                                           MemoryRegionIoeventfd b)
+{
+    if (a.addr.start < b.addr.start) {
+        return true;
+    } else if (a.addr.start > b.addr.start) {
+        return false;
+    } else if (a.addr.size < b.addr.size) {
+        return true;
+    } else if (a.addr.size > b.addr.size) {
+        return false;
+    } else if (a.match_data < b.match_data) {
+        return true;
+    } else  if (a.match_data > b.match_data) {
+        return false;
+    } else if (a.match_data) {
+        if (a.data < b.data) {
+            return true;
+        } else if (a.data > b.data) {
+            return false;
+        }
+    }
+    if (a.fd < b.fd) {
+        return true;
+    } else if (a.fd > b.fd) {
+        return false;
+    }
+    return false;
+}
+
+static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd a,
+                                          MemoryRegionIoeventfd b)
+{
+    return !memory_region_ioeventfd_before(a, b)
+        && !memory_region_ioeventfd_before(b, a);
+}
+
+typedef struct FlatRange FlatRange;
+typedef struct FlatView FlatView;
+
+/* Range of memory in the global map.  Addresses are absolute. */
+struct FlatRange {
+    MemoryRegion *mr;
+    target_phys_addr_t offset_in_region;
+    AddrRange addr;
+    uint8_t dirty_log_mask;
+};
+
+/* Flattened global view of current active memory hierarchy.  Kept in sorted
+ * order.
+ */
+struct FlatView {
+    FlatRange *ranges;
+    unsigned nr;
+    unsigned nr_allocated;
+};
+
+typedef struct AddressSpace AddressSpace;
+typedef struct AddressSpaceOps AddressSpaceOps;
+
+/* A system address space - I/O, memory, etc. */
+struct AddressSpace {
+    const AddressSpaceOps *ops;
+    MemoryRegion *root;
+    FlatView current_map;
+    int ioeventfd_nb;
+    MemoryRegionIoeventfd *ioeventfds;
+};
+
+struct AddressSpaceOps {
+    void (*range_add)(AddressSpace *as, FlatRange *fr);
+    void (*range_del)(AddressSpace *as, FlatRange *fr);
+    void (*log_start)(AddressSpace *as, FlatRange *fr);
+    void (*log_stop)(AddressSpace *as, FlatRange *fr);
+    void (*ioeventfd_add)(AddressSpace *as, MemoryRegionIoeventfd *fd);
+    void (*ioeventfd_del)(AddressSpace *as, MemoryRegionIoeventfd *fd);
+};
+
+#define FOR_EACH_FLAT_RANGE(var, view)          \
+    for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var)
+
+static bool flatrange_equal(FlatRange *a, FlatRange *b)
+{
+    return a->mr == b->mr
+        && addrrange_equal(a->addr, b->addr)
+        && a->offset_in_region == b->offset_in_region;
+}
+
+static void flatview_init(FlatView *view)
+{
+    view->ranges = NULL;
+    view->nr = 0;
+    view->nr_allocated = 0;
+}
+
+/* Insert a range into a given position.  Caller is responsible for maintaining
+ * sorting order.
+ */
+static void flatview_insert(FlatView *view, unsigned pos, FlatRange *range)
+{
+    if (view->nr == view->nr_allocated) {
+        view->nr_allocated = MAX(2 * view->nr, 10);
+        view->ranges = qemu_realloc(view->ranges,
+                                    view->nr_allocated * sizeof(*view->ranges));
+    }
+    memmove(view->ranges + pos + 1, view->ranges + pos,
+            (view->nr - pos) * sizeof(FlatRange));
+    view->ranges[pos] = *range;
+    ++view->nr;
+}
+
+static void flatview_destroy(FlatView *view)
+{
+    qemu_free(view->ranges);
+}
+
+static bool can_merge(FlatRange *r1, FlatRange *r2)
+{
+    return addrrange_end(r1->addr) == r2->addr.start
+        && r1->mr == r2->mr
+        && r1->offset_in_region + r1->addr.size == r2->offset_in_region
+        && r1->dirty_log_mask == r2->dirty_log_mask;
+}
+
+/* Attempt to simplify a view by merging ajacent ranges */
+static void flatview_simplify(FlatView *view)
+{
+    unsigned i, j;
+
+    i = 0;
+    while (i < view->nr) {
+        j = i + 1;
+        while (j < view->nr
+               && can_merge(&view->ranges[j-1], &view->ranges[j])) {
+            view->ranges[i].addr.size += view->ranges[j].addr.size;
+            ++j;
+        }
+        ++i;
+        memmove(&view->ranges[i], &view->ranges[j],
+                (view->nr - j) * sizeof(view->ranges[j]));
+        view->nr -= j - i;
+    }
+}
+
+static void memory_region_prepare_ram_addr(MemoryRegion *mr);
+
+static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
+{
+    ram_addr_t phys_offset, region_offset;
+
+    memory_region_prepare_ram_addr(fr->mr);
+
+    phys_offset = fr->mr->ram_addr;
+    region_offset = fr->offset_in_region;
+    /* cpu_register_physical_memory_log() wants region_offset for
+     * mmio, but prefers offseting phys_offset for RAM.  Humour it.
+     */
+    if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
+        phys_offset += region_offset;
+        region_offset = 0;
+    }
+
+    cpu_register_physical_memory_log(fr->addr.start,
+                                     fr->addr.size,
+                                     phys_offset,
+                                     region_offset,
+                                     fr->dirty_log_mask);
+}
+
+static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
+{
+    if (fr->dirty_log_mask) {
+        cpu_physical_sync_dirty_bitmap(fr->addr.start,
+                                       fr->addr.start + fr->addr.size);
+    }
+    cpu_register_physical_memory(fr->addr.start, fr->addr.size,
+                                 IO_MEM_UNASSIGNED);
+}
+
+static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
+{
+    cpu_physical_log_start(fr->addr.start, fr->addr.size);
+}
+
+static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
+{
+    cpu_physical_log_stop(fr->addr.start, fr->addr.size);
+}
+
+static void as_memory_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    assert(fd->match_data && fd->addr.size == 4);
+
+    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, true);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void as_memory_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, false);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static const AddressSpaceOps address_space_ops_memory = {
+    .range_add = as_memory_range_add,
+    .range_del = as_memory_range_del,
+    .log_start = as_memory_log_start,
+    .log_stop = as_memory_log_stop,
+    .ioeventfd_add = as_memory_ioeventfd_add,
+    .ioeventfd_del = as_memory_ioeventfd_del,
+};
+
+static AddressSpace address_space_memory = {
+    .ops = &address_space_ops_memory,
+};
+
+static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset,
+                                             unsigned width, bool write)
+{
+    const MemoryRegionPortio *mrp;
+
+    for (mrp = mr->ops->old_portio; mrp->size; ++mrp) {
+        if (offset >= mrp->offset && offset < mrp->offset + mrp->len
+            && width == mrp->size
+            && (write ? (bool)mrp->write : (bool)mrp->read)) {
+            return mrp;
+        }
+    }
+    return NULL;
+}
+
+static void memory_region_iorange_read(IORange *iorange,
+                                       uint64_t offset,
+                                       unsigned width,
+                                       uint64_t *data)
+{
+    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+
+    if (mr->ops->old_portio) {
+        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, false);
+
+        *data = ((uint64_t)1 << (width * 8)) - 1;
+        if (mrp) {
+            *data = mrp->read(mr->opaque, offset - mrp->offset);
+        }
+        return;
+    }
+    *data = mr->ops->read(mr->opaque, offset, width);
+}
+
+static void memory_region_iorange_write(IORange *iorange,
+                                        uint64_t offset,
+                                        unsigned width,
+                                        uint64_t data)
+{
+    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+
+    if (mr->ops->old_portio) {
+        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, true);
+
+        if (mrp) {
+            mrp->write(mr->opaque, offset - mrp->offset, data);
+        }
+        return;
+    }
+    mr->ops->write(mr->opaque, offset, data, width);
+}
+
+static const IORangeOps memory_region_iorange_ops = {
+    .read = memory_region_iorange_read,
+    .write = memory_region_iorange_write,
+};
+
+static void as_io_range_add(AddressSpace *as, FlatRange *fr)
+{
+    iorange_init(&fr->mr->iorange, &memory_region_iorange_ops,
+                 fr->addr.start,fr->addr.size);
+    ioport_register(&fr->mr->iorange);
+}
+
+static void as_io_range_del(AddressSpace *as, FlatRange *fr)
+{
+    isa_unassign_ioport(fr->addr.start, fr->addr.size);
+}
+
+static void as_io_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    assert(fd->match_data && fd->addr.size == 2);
+
+    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, true);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void as_io_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, false);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static const AddressSpaceOps address_space_ops_io = {
+    .range_add = as_io_range_add,
+    .range_del = as_io_range_del,
+    .ioeventfd_add = as_io_ioeventfd_add,
+    .ioeventfd_del = as_io_ioeventfd_del,
+};
+
+static AddressSpace address_space_io = {
+    .ops = &address_space_ops_io,
+};
+
+/* Render a memory region into the global view.  Ranges in @view obscure
+ * ranges in @mr.
+ */
+static void render_memory_region(FlatView *view,
+                                 MemoryRegion *mr,
+                                 target_phys_addr_t base,
+                                 AddrRange clip)
+{
+    MemoryRegion *subregion;
+    unsigned i;
+    target_phys_addr_t offset_in_region;
+    int64_t remain;
+    int64_t now;
+    FlatRange fr;
+    AddrRange tmp;
+
+    base += mr->addr;
+
+    tmp = addrrange_make(base, mr->size);
+
+    if (!addrrange_intersects(tmp, clip)) {
+        return;
+    }
+
+    clip = addrrange_intersection(tmp, clip);
+
+    if (mr->alias) {
+        base -= mr->alias->addr;
+        base -= mr->alias_offset;
+        render_memory_region(view, mr->alias, base, clip);
+        return;
+    }
+
+    /* Render subregions in priority order. */
+    QTAILQ_FOREACH(subregion, &mr->subregions, subregions_link) {
+        render_memory_region(view, subregion, base, clip);
+    }
+
+    if (!mr->terminates) {
+        return;
+    }
+
+    offset_in_region = clip.start - base;
+    base = clip.start;
+    remain = clip.size;
+
+    /* Render the region itself into any gaps left by the current view. */
+    for (i = 0; i < view->nr && remain; ++i) {
+        if (base >= addrrange_end(view->ranges[i].addr)) {
+            continue;
+        }
+        if (base < view->ranges[i].addr.start) {
+            now = MIN(remain, view->ranges[i].addr.start - base);
+            fr.mr = mr;
+            fr.offset_in_region = offset_in_region;
+            fr.addr = addrrange_make(base, now);
+            fr.dirty_log_mask = mr->dirty_log_mask;
+            flatview_insert(view, i, &fr);
+            ++i;
+            base += now;
+            offset_in_region += now;
+            remain -= now;
+        }
+        if (base == view->ranges[i].addr.start) {
+            now = MIN(remain, view->ranges[i].addr.size);
+            base += now;
+            offset_in_region += now;
+            remain -= now;
+        }
+    }
+    if (remain) {
+        fr.mr = mr;
+        fr.offset_in_region = offset_in_region;
+        fr.addr = addrrange_make(base, remain);
+        fr.dirty_log_mask = mr->dirty_log_mask;
+        flatview_insert(view, i, &fr);
+    }
+}
+
+/* Render a memory topology into a list of disjoint absolute ranges. */
+static FlatView generate_memory_topology(MemoryRegion *mr)
+{
+    FlatView view;
+
+    flatview_init(&view);
+
+    render_memory_region(&view, mr, 0, addrrange_make(0, INT64_MAX));
+    flatview_simplify(&view);
+
+    return view;
+}
+
+static void address_space_add_del_ioeventfds(AddressSpace *as,
+                                             MemoryRegionIoeventfd *fds_new,
+                                             unsigned fds_new_nb,
+                                             MemoryRegionIoeventfd *fds_old,
+                                             unsigned fds_old_nb)
+{
+    unsigned iold, inew;
+
+    /* Generate a symmetric difference of the old and new fd sets, adding
+     * and deleting as necessary.
+     */
+
+    iold = inew = 0;
+    while (iold < fds_old_nb || inew < fds_new_nb) {
+        if (iold < fds_old_nb
+            && (inew == fds_new_nb
+                || memory_region_ioeventfd_before(fds_old[iold],
+                                                  fds_new[inew]))) {
+            as->ops->ioeventfd_del(as, &fds_old[iold]);
+            ++iold;
+        } else if (inew < fds_new_nb
+                   && (iold == fds_old_nb
+                       || memory_region_ioeventfd_before(fds_new[inew],
+                                                         fds_old[iold]))) {
+            as->ops->ioeventfd_add(as, &fds_new[inew]);
+            ++inew;
+        } else {
+            ++iold;
+            ++inew;
+        }
+    }
+}
+
+static void address_space_update_ioeventfds(AddressSpace *as)
+{
+    FlatRange *fr;
+    unsigned ioeventfd_nb = 0;
+    MemoryRegionIoeventfd *ioeventfds = NULL;
+    AddrRange tmp;
+    unsigned i;
+
+    FOR_EACH_FLAT_RANGE(fr, &as->current_map) {
+        for (i = 0; i < fr->mr->ioeventfd_nb; ++i) {
+            tmp = addrrange_shift(fr->mr->ioeventfds[i].addr,
+                                  fr->addr.start - fr->offset_in_region);
+            if (addrrange_intersects(fr->addr, tmp)) {
+                ++ioeventfd_nb;
+                ioeventfds = qemu_realloc(ioeventfds,
+                                          ioeventfd_nb * sizeof(*ioeventfds));
+                ioeventfds[ioeventfd_nb-1] = fr->mr->ioeventfds[i];
+                ioeventfds[ioeventfd_nb-1].addr = tmp;
+            }
+        }
+    }
+
+    address_space_add_del_ioeventfds(as, ioeventfds, ioeventfd_nb,
+                                     as->ioeventfds, as->ioeventfd_nb);
+
+    qemu_free(as->ioeventfds);
+    as->ioeventfds = ioeventfds;
+    as->ioeventfd_nb = ioeventfd_nb;
+}
+
+static void address_space_update_topology_pass(AddressSpace *as,
+                                               FlatView old_view,
+                                               FlatView new_view,
+                                               bool adding)
+{
+    unsigned iold, inew;
+    FlatRange *frold, *frnew;
+
+    /* Generate a symmetric difference of the old and new memory maps.
+     * Kill ranges in the old map, and instantiate ranges in the new map.
+     */
+    iold = inew = 0;
+    while (iold < old_view.nr || inew < new_view.nr) {
+        if (iold < old_view.nr) {
+            frold = &old_view.ranges[iold];
+        } else {
+            frold = NULL;
+        }
+        if (inew < new_view.nr) {
+            frnew = &new_view.ranges[inew];
+        } else {
+            frnew = NULL;
+        }
+
+        if (frold
+            && (!frnew
+                || frold->addr.start < frnew->addr.start
+                || (frold->addr.start == frnew->addr.start
+                    && !flatrange_equal(frold, frnew)))) {
+            /* In old, but (not in new, or in new but attributes changed). */
+
+            if (!adding) {
+                as->ops->range_del(as, frold);
+            }
+
+            ++iold;
+        } else if (frold && frnew && flatrange_equal(frold, frnew)) {
+            /* In both (logging may have changed) */
+
+            if (adding) {
+                if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
+                    as->ops->log_stop(as, frnew);
+                } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
+                    as->ops->log_start(as, frnew);
+                }
+            }
+
+            ++iold;
+            ++inew;
+        } else {
+            /* In new */
+
+            if (adding) {
+                as->ops->range_add(as, frnew);
+            }
+
+            ++inew;
+        }
+    }
+}
+
+
+static void address_space_update_topology(AddressSpace *as)
+{
+    FlatView old_view = as->current_map;
+    FlatView new_view = generate_memory_topology(as->root);
+
+    address_space_update_topology_pass(as, old_view, new_view, false);
+    address_space_update_topology_pass(as, old_view, new_view, true);
+
+    as->current_map = new_view;
+    flatview_destroy(&old_view);
+    address_space_update_ioeventfds(as);
+}
+
+static void memory_region_update_topology(void)
+{
+    if (memory_region_transaction_depth) {
+        return;
+    }
+
+    if (address_space_memory.root) {
+        address_space_update_topology(&address_space_memory);
+    }
+    if (address_space_io.root) {
+        address_space_update_topology(&address_space_io);
+    }
+}
+
+void memory_region_transaction_begin(void)
+{
+    ++memory_region_transaction_depth;
+}
+
+void memory_region_transaction_commit(void)
+{
+    assert(memory_region_transaction_depth);
+    --memory_region_transaction_depth;
+    memory_region_update_topology();
+}
+
+void memory_region_init(MemoryRegion *mr,
+                        const char *name,
+                        uint64_t size)
+{
+    mr->ops = NULL;
+    mr->parent = NULL;
+    mr->size = size;
+    mr->addr = 0;
+    mr->offset = 0;
+    mr->terminates = false;
+    mr->priority = 0;
+    mr->may_overlap = false;
+    mr->alias = NULL;
+    QTAILQ_INIT(&mr->subregions);
+    memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
+    QTAILQ_INIT(&mr->coalesced);
+    mr->name = qemu_strdup(name);
+    mr->dirty_log_mask = 0;
+    mr->ioeventfd_nb = 0;
+    mr->ioeventfds = NULL;
+}
+
+static bool memory_region_access_valid(MemoryRegion *mr,
+                                       target_phys_addr_t addr,
+                                       unsigned size)
+{
+    if (!mr->ops->valid.unaligned && (addr & (size - 1))) {
+        return false;
+    }
+
+    /* Treat zero as compatibility all valid */
+    if (!mr->ops->valid.max_access_size) {
+        return true;
+    }
+
+    if (size > mr->ops->valid.max_access_size
+        || size < mr->ops->valid.min_access_size) {
+        return false;
+    }
+    return true;
+}
+
+static uint32_t memory_region_read_thunk_n(void *_mr,
+                                           target_phys_addr_t addr,
+                                           unsigned size)
+{
+    MemoryRegion *mr = _mr;
+    unsigned access_size, access_size_min, access_size_max;
+    uint64_t access_mask;
+    uint32_t data = 0, tmp;
+    unsigned i;
+
+    if (!memory_region_access_valid(mr, addr, size)) {
+        return -1U; /* FIXME: better signalling */
+    }
+
+    if (!mr->ops->read) {
+        return mr->ops->old_mmio.read[bitops_ffsl(size)](mr->opaque, addr);
+    }
+
+    /* FIXME: support unaligned access */
+
+    access_size_min = mr->ops->impl.min_access_size;
+    if (!access_size_min) {
+        access_size_min = 1;
+    }
+    access_size_max = mr->ops->impl.max_access_size;
+    if (!access_size_max) {
+        access_size_max = 4;
+    }
+    access_size = MAX(MIN(size, access_size_max), access_size_min);
+    access_mask = -1ULL >> (64 - access_size * 8);
+    addr += mr->offset;
+    for (i = 0; i < size; i += access_size) {
+        /* FIXME: big-endian support */
+        tmp = mr->ops->read(mr->opaque, addr + i, access_size);
+        data |= (tmp & access_mask) << (i * 8);
+    }
+
+    return data;
+}
+
+static void memory_region_write_thunk_n(void *_mr,
+                                        target_phys_addr_t addr,
+                                        unsigned size,
+                                        uint64_t data)
+{
+    MemoryRegion *mr = _mr;
+    unsigned access_size, access_size_min, access_size_max;
+    uint64_t access_mask;
+    unsigned i;
+
+    if (!memory_region_access_valid(mr, addr, size)) {
+        return; /* FIXME: better signalling */
+    }
+
+    if (!mr->ops->write) {
+        mr->ops->old_mmio.write[bitops_ffsl(size)](mr->opaque, addr, data);
+        return;
+    }
+
+    /* FIXME: support unaligned access */
+
+    access_size_min = mr->ops->impl.min_access_size;
+    if (!access_size_min) {
+        access_size_min = 1;
+    }
+    access_size_max = mr->ops->impl.max_access_size;
+    if (!access_size_max) {
+        access_size_max = 4;
+    }
+    access_size = MAX(MIN(size, access_size_max), access_size_min);
+    access_mask = -1ULL >> (64 - access_size * 8);
+    addr += mr->offset;
+    for (i = 0; i < size; i += access_size) {
+        /* FIXME: big-endian support */
+        mr->ops->write(mr->opaque, addr + i, (data >> (i * 8)) & access_mask,
+                       access_size);
+    }
+}
+
+static uint32_t memory_region_read_thunk_b(void *mr, target_phys_addr_t addr)
+{
+    return memory_region_read_thunk_n(mr, addr, 1);
+}
+
+static uint32_t memory_region_read_thunk_w(void *mr, target_phys_addr_t addr)
+{
+    return memory_region_read_thunk_n(mr, addr, 2);
+}
+
+static uint32_t memory_region_read_thunk_l(void *mr, target_phys_addr_t addr)
+{
+    return memory_region_read_thunk_n(mr, addr, 4);
+}
+
+static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr,
+                                        uint32_t data)
+{
+    memory_region_write_thunk_n(mr, addr, 1, data);
+}
+
+static void memory_region_write_thunk_w(void *mr, target_phys_addr_t addr,
+                                        uint32_t data)
+{
+    memory_region_write_thunk_n(mr, addr, 2, data);
+}
+
+static void memory_region_write_thunk_l(void *mr, target_phys_addr_t addr,
+                                        uint32_t data)
+{
+    memory_region_write_thunk_n(mr, addr, 4, data);
+}
+
+static CPUReadMemoryFunc * const memory_region_read_thunk[] = {
+    memory_region_read_thunk_b,
+    memory_region_read_thunk_w,
+    memory_region_read_thunk_l,
+};
+
+static CPUWriteMemoryFunc * const memory_region_write_thunk[] = {
+    memory_region_write_thunk_b,
+    memory_region_write_thunk_w,
+    memory_region_write_thunk_l,
+};
+
+static void memory_region_prepare_ram_addr(MemoryRegion *mr)
+{
+    if (mr->backend_registered) {
+        return;
+    }
+
+    mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
+                                          memory_region_write_thunk,
+                                          mr,
+                                          mr->ops->endianness);
+    mr->backend_registered = true;
+}
+
+void memory_region_init_io(MemoryRegion *mr,
+                           const MemoryRegionOps *ops,
+                           void *opaque,
+                           const char *name,
+                           uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->ops = ops;
+    mr->opaque = opaque;
+    mr->terminates = true;
+    mr->backend_registered = false;
+}
+
+void memory_region_init_ram(MemoryRegion *mr,
+                            DeviceState *dev,
+                            const char *name,
+                            uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->terminates = true;
+    mr->ram_addr = qemu_ram_alloc(dev, name, size);
+    mr->backend_registered = true;
+}
+
+void memory_region_init_ram_ptr(MemoryRegion *mr,
+                                DeviceState *dev,
+                                const char *name,
+                                uint64_t size,
+                                void *ptr)
+{
+    memory_region_init(mr, name, size);
+    mr->terminates = true;
+    mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
+    mr->backend_registered = true;
+}
+
+void memory_region_init_alias(MemoryRegion *mr,
+                              const char *name,
+                              MemoryRegion *orig,
+                              target_phys_addr_t offset,
+                              uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->alias = orig;
+    mr->alias_offset = offset;
+}
+
+void memory_region_destroy(MemoryRegion *mr)
+{
+    assert(QTAILQ_EMPTY(&mr->subregions));
+    memory_region_clear_coalescing(mr);
+    qemu_free((char *)mr->name);
+    qemu_free(mr->ioeventfds);
+}
+
+uint64_t memory_region_size(MemoryRegion *mr)
+{
+    return mr->size;
+}
+
+void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
+{
+    mr->offset = offset;
+}
+
+void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
+{
+    uint8_t mask = 1 << client;
+
+    mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask);
+    memory_region_update_topology();
+}
+
+bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                             unsigned client)
+{
+    assert(mr->terminates);
+    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client);
+}
+
+void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
+{
+    assert(mr->terminates);
+    return cpu_physical_memory_set_dirty(mr->ram_addr + addr);
+}
+
+void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
+{
+    FlatRange *fr;
+
+    FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
+        if (fr->mr == mr) {
+            cpu_physical_sync_dirty_bitmap(fr->addr.start,
+                                           fr->addr.start + fr->addr.size);
+        }
+    }
+}
+
+void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
+{
+    /* FIXME */
+}
+
+void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                               target_phys_addr_t size, unsigned client)
+{
+    assert(mr->terminates);
+    cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
+                                    mr->ram_addr + addr + size,
+                                    1 << client);
+}
+
+void *memory_region_get_ram_ptr(MemoryRegion *mr)
+{
+    if (mr->alias) {
+        return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset;
+    }
+
+    assert(mr->terminates);
+
+    return qemu_get_ram_ptr(mr->ram_addr);
+}
+
+static void memory_region_update_coalesced_range(MemoryRegion *mr)
+{
+    FlatRange *fr;
+    CoalescedMemoryRange *cmr;
+    AddrRange tmp;
+
+    FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
+        if (fr->mr == mr) {
+            qemu_unregister_coalesced_mmio(fr->addr.start, fr->addr.size);
+            QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
+                tmp = addrrange_shift(cmr->addr,
+                                      fr->addr.start - fr->offset_in_region);
+                if (!addrrange_intersects(tmp, fr->addr)) {
+                    continue;
+                }
+                tmp = addrrange_intersection(tmp, fr->addr);
+                qemu_register_coalesced_mmio(tmp.start, tmp.size);
+            }
+        }
+    }
+}
+
+void memory_region_set_coalescing(MemoryRegion *mr)
+{
+    memory_region_clear_coalescing(mr);
+    memory_region_add_coalescing(mr, 0, mr->size);
+}
+
+void memory_region_add_coalescing(MemoryRegion *mr,
+                                  target_phys_addr_t offset,
+                                  uint64_t size)
+{
+    CoalescedMemoryRange *cmr = qemu_malloc(sizeof(*cmr));
+
+    cmr->addr = addrrange_make(offset, size);
+    QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link);
+    memory_region_update_coalesced_range(mr);
+}
+
+void memory_region_clear_coalescing(MemoryRegion *mr)
+{
+    CoalescedMemoryRange *cmr;
+
+    while (!QTAILQ_EMPTY(&mr->coalesced)) {
+        cmr = QTAILQ_FIRST(&mr->coalesced);
+        QTAILQ_REMOVE(&mr->coalesced, cmr, link);
+        qemu_free(cmr);
+    }
+    memory_region_update_coalesced_range(mr);
+}
+
+void memory_region_add_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd)
+{
+    MemoryRegionIoeventfd mrfd = {
+        .addr.start = addr,
+        .addr.size = size,
+        .match_data = match_data,
+        .data = data,
+        .fd = fd,
+    };
+    unsigned i;
+
+    for (i = 0; i < mr->ioeventfd_nb; ++i) {
+        if (memory_region_ioeventfd_before(mrfd, mr->ioeventfds[i])) {
+            break;
+        }
+    }
+    ++mr->ioeventfd_nb;
+    mr->ioeventfds = qemu_realloc(mr->ioeventfds,
+                                  sizeof(*mr->ioeventfds) * mr->ioeventfd_nb);
+    memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i],
+            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i));
+    mr->ioeventfds[i] = mrfd;
+    memory_region_update_topology();
+}
+
+void memory_region_del_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd)
+{
+    MemoryRegionIoeventfd mrfd = {
+        .addr.start = addr,
+        .addr.size = size,
+        .match_data = match_data,
+        .data = data,
+        .fd = fd,
+    };
+    unsigned i;
+
+    for (i = 0; i < mr->ioeventfd_nb; ++i) {
+        if (memory_region_ioeventfd_equal(mrfd, mr->ioeventfds[i])) {
+            break;
+        }
+    }
+    assert(i != mr->ioeventfd_nb);
+    memmove(&mr->ioeventfds[i], &mr->ioeventfds[i+1],
+            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb - (i+1)));
+    --mr->ioeventfd_nb;
+    mr->ioeventfds = qemu_realloc(mr->ioeventfds,
+                                  sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1);
+    memory_region_update_topology();
+}
+
+static void memory_region_add_subregion_common(MemoryRegion *mr,
+                                               target_phys_addr_t offset,
+                                               MemoryRegion *subregion)
+{
+    MemoryRegion *other;
+
+    assert(!subregion->parent);
+    subregion->parent = mr;
+    subregion->addr = offset;
+    QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
+        if (subregion->may_overlap || other->may_overlap) {
+            continue;
+        }
+        if (offset >= other->offset + other->size
+            || offset + subregion->size <= other->offset) {
+            continue;
+        }
+        printf("warning: subregion collision %llx/%llx vs %llx/%llx\n",
+               (unsigned long long)offset,
+               (unsigned long long)subregion->size,
+               (unsigned long long)other->offset,
+               (unsigned long long)other->size);
+    }
+    QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
+        if (subregion->priority >= other->priority) {
+            QTAILQ_INSERT_BEFORE(other, subregion, subregions_link);
+            goto done;
+        }
+    }
+    QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link);
+done:
+    memory_region_update_topology();
+}
+
+
+void memory_region_add_subregion(MemoryRegion *mr,
+                                 target_phys_addr_t offset,
+                                 MemoryRegion *subregion)
+{
+    subregion->may_overlap = false;
+    subregion->priority = 0;
+    memory_region_add_subregion_common(mr, offset, subregion);
+}
+
+void memory_region_add_subregion_overlap(MemoryRegion *mr,
+                                         target_phys_addr_t offset,
+                                         MemoryRegion *subregion,
+                                         unsigned priority)
+{
+    subregion->may_overlap = true;
+    subregion->priority = priority;
+    memory_region_add_subregion_common(mr, offset, subregion);
+}
+
+void memory_region_del_subregion(MemoryRegion *mr,
+                                 MemoryRegion *subregion)
+{
+    assert(subregion->parent == mr);
+    subregion->parent = NULL;
+    QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
+    memory_region_update_topology();
+}
+
+void set_system_memory_map(MemoryRegion *mr)
+{
+    address_space_memory.root = mr;
+    memory_region_update_topology();
+}
+
+void set_system_io_map(MemoryRegion *mr)
+{
+    address_space_io.root = mr;
+    memory_region_update_topology();
+}
diff --git a/memory.h b/memory.h
new file mode 100644 (file)
index 0000000..da00a3b
--- /dev/null
+++ b/memory.h
@@ -0,0 +1,469 @@
+/*
+ * Physical memory management API
+ *
+ * Copyright 2011 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *  Avi Kivity <avi@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef MEMORY_H
+#define MEMORY_H
+
+#ifndef CONFIG_USER_ONLY
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "qemu-common.h"
+#include "cpu-common.h"
+#include "targphys.h"
+#include "qemu-queue.h"
+#include "iorange.h"
+#include "ioport.h"
+
+typedef struct MemoryRegionOps MemoryRegionOps;
+typedef struct MemoryRegion MemoryRegion;
+typedef struct MemoryRegionPortio MemoryRegionPortio;
+typedef struct MemoryRegionMmio MemoryRegionMmio;
+
+/* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
+ * registration.
+ */
+#define DIRTY_MEMORY_VGA       0
+#define DIRTY_MEMORY_CODE      1
+#define DIRTY_MEMORY_MIGRATION 3
+
+struct MemoryRegionMmio {
+    CPUReadMemoryFunc *read[3];
+    CPUWriteMemoryFunc *write[3];
+};
+
+/*
+ * Memory region callbacks
+ */
+struct MemoryRegionOps {
+    /* Read from the memory region. @addr is relative to @mr; @size is
+     * in bytes. */
+    uint64_t (*read)(void *opaque,
+                     target_phys_addr_t addr,
+                     unsigned size);
+    /* Write to the memory region. @addr is relative to @mr; @size is
+     * in bytes. */
+    void (*write)(void *opaque,
+                  target_phys_addr_t addr,
+                  uint64_t data,
+                  unsigned size);
+
+    enum device_endian endianness;
+    /* Guest-visible constraints: */
+    struct {
+        /* If nonzero, specify bounds on access sizes beyond which a machine
+         * check is thrown.
+         */
+        unsigned min_access_size;
+        unsigned max_access_size;
+        /* If true, unaligned accesses are supported.  Otherwise unaligned
+         * accesses throw machine checks.
+         */
+         bool unaligned;
+    } valid;
+    /* Internal implementation constraints: */
+    struct {
+        /* If nonzero, specifies the minimum size implemented.  Smaller sizes
+         * will be rounded upwards and a partial result will be returned.
+         */
+        unsigned min_access_size;
+        /* If nonzero, specifies the maximum size implemented.  Larger sizes
+         * will be done as a series of accesses with smaller sizes.
+         */
+        unsigned max_access_size;
+        /* If true, unaligned accesses are supported.  Otherwise all accesses
+         * are converted to (possibly multiple) naturally aligned accesses.
+         */
+         bool unaligned;
+    } impl;
+
+    /* If .read and .write are not present, old_portio may be used for
+     * backwards compatibility with old portio registration
+     */
+    const MemoryRegionPortio *old_portio;
+    /* If .read and .write are not present, old_mmio may be used for
+     * backwards compatibility with old mmio registration
+     */
+    const MemoryRegionMmio old_mmio;
+};
+
+typedef struct CoalescedMemoryRange CoalescedMemoryRange;
+typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
+
+struct MemoryRegion {
+    /* All fields are private - violators will be prosecuted */
+    const MemoryRegionOps *ops;
+    void *opaque;
+    MemoryRegion *parent;
+    uint64_t size;
+    target_phys_addr_t addr;
+    target_phys_addr_t offset;
+    bool backend_registered;
+    ram_addr_t ram_addr;
+    IORange iorange;
+    bool terminates;
+    MemoryRegion *alias;
+    target_phys_addr_t alias_offset;
+    unsigned priority;
+    bool may_overlap;
+    QTAILQ_HEAD(subregions, MemoryRegion) subregions;
+    QTAILQ_ENTRY(MemoryRegion) subregions_link;
+    QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
+    const char *name;
+    uint8_t dirty_log_mask;
+    unsigned ioeventfd_nb;
+    MemoryRegionIoeventfd *ioeventfds;
+};
+
+struct MemoryRegionPortio {
+    uint32_t offset;
+    uint32_t len;
+    unsigned size;
+    IOPortReadFunc *read;
+    IOPortWriteFunc *write;
+};
+
+#define PORTIO_END_OF_LIST() { }
+
+/**
+ * memory_region_init: Initialize a memory region
+ *
+ * The region typically acts as a container for other memory regions.  Us
+ * memory_region_add_subregion() to add subregions.
+ *
+ * @mr: the #MemoryRegion to be initialized
+ * @name: used for debugging; not visible to the user or ABI
+ * @size: size of the region; any subregions beyond this size will be clipped
+ */
+void memory_region_init(MemoryRegion *mr,
+                        const char *name,
+                        uint64_t size);
+/**
+ * memory_region_init_io: Initialize an I/O memory region.
+ *
+ * Accesses into the region will be cause the callbacks in @ops to be called.
+ * if @size is nonzero, subregions will be clipped to @size.
+ *
+ * @mr: the #MemoryRegion to be initialized.
+ * @ops: a structure containing read and write callbacks to be used when
+ *       I/O is performed on the region.
+ * @opaque: passed to to the read and write callbacks of the @ops structure.
+ * @name: used for debugging; not visible to the user or ABI
+ * @size: size of the region.
+ */
+void memory_region_init_io(MemoryRegion *mr,
+                           const MemoryRegionOps *ops,
+                           void *opaque,
+                           const char *name,
+                           uint64_t size);
+
+/**
+ * memory_region_init_ram:  Initialize RAM memory region.  Accesses into the
+ *                          region will be modify memory directly.
+ *
+ * @mr: the #MemoryRegion to be initialized.
+ * @dev: a device associated with the region; may be %NULL.
+ * @name: the name of the region; the pair (@dev, @name) must be globally
+ *        unique.  The name is part of the save/restore ABI and so cannot be
+ *        changed.
+ * @size: size of the region.
+ */
+void memory_region_init_ram(MemoryRegion *mr,
+                            DeviceState *dev, /* FIXME: layering violation */
+                            const char *name,
+                            uint64_t size);
+
+/**
+ * memory_region_init_ram:  Initialize RAM memory region from a user-provided.
+ *                          pointer.  Accesses into the region will be modify
+ *                          memory directly.
+ *
+ * @mr: the #MemoryRegion to be initialized.
+ * @dev: a device associated with the region; may be %NULL.
+ * @name: the name of the region; the pair (@dev, @name) must be globally
+ *        unique.  The name is part of the save/restore ABI and so cannot be
+ *        changed.
+ * @size: size of the region.
+ * @ptr: memory to be mapped; must contain at least @size bytes.
+ */
+void memory_region_init_ram_ptr(MemoryRegion *mr,
+                                DeviceState *dev, /* FIXME: layering violation */
+                                const char *name,
+                                uint64_t size,
+                                void *ptr);
+
+/**
+ * memory_region_init_alias: Initialize a memory region that aliases all or a
+ *                           part of another memory region.
+ *
+ * @mr: the #MemoryRegion to be initialized.
+ * @name: used for debugging; not visible to the user or ABI
+ * @orig: the region to be referenced; @mr will be equivalent to
+ *        @orig between @offset and @offset + @size - 1.
+ * @offset: start of the section in @orig to be referenced.
+ * @size: size of the region.
+ */
+void memory_region_init_alias(MemoryRegion *mr,
+                              const char *name,
+                              MemoryRegion *orig,
+                              target_phys_addr_t offset,
+                              uint64_t size);
+/**
+ * memory_region_destroy: Destroy a memory region and relaim all resources.
+ *
+ * @mr: the region to be destroyed.  May not currently be a subregion
+ *      (see memory_region_add_subregion()) or referenced in an alias
+ *      (see memory_region_init_alias()).
+ */
+void memory_region_destroy(MemoryRegion *mr);
+
+/**
+ * memory_region_size: get a memory region's size.
+ *
+ * @mr: the memory region being queried.
+ */
+uint64_t memory_region_size(MemoryRegion *mr);
+
+/**
+ * memory_region_get_ram_ptr: Get a pointer into a RAM memory region.
+ *
+ * Returns a host pointer to a RAM memory region (created with
+ * memory_region_init_ram() or memory_region_init_ram_ptr()).  Use with
+ * care.
+ *
+ * @mr: the memory region being queried.
+ */
+void *memory_region_get_ram_ptr(MemoryRegion *mr);
+
+/**
+ * memory_region_set_offset: Sets an offset to be added to MemoryRegionOps
+ *                           callbacks.
+ *
+ * This function is deprecated and should not be used in new code.
+ */
+void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset);
+
+/**
+ * memory_region_set_log: Turn dirty logging on or off for a region.
+ *
+ * Turns dirty logging on or off for a specified client (display, migration).
+ * Only meaningful for RAM regions.
+ *
+ * @mr: the memory region being updated.
+ * @log: whether dirty logging is to be enabled or disabled.
+ * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or
+ *          %DIRTY_MEMORY_VGA.
+ */
+void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client);
+
+/**
+ * memory_region_get_dirty: Check whether a page is dirty for a specified
+ *                          client.
+ *
+ * Checks whether a page has been written to since the last
+ * call to memory_region_reset_dirty() with the same @client.  Dirty logging
+ * must be enabled.
+ *
+ * @mr: the memory region being queried.
+ * @addr: the address (relative to the start of the region) being queried.
+ * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or
+ *          %DIRTY_MEMORY_VGA.
+ */
+bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                             unsigned client);
+
+/**
+ * memory_region_set_dirty: Mark a page as dirty in a memory region.
+ *
+ * Marks a page as dirty, after it has been dirtied outside guest code.
+ *
+ * @mr: the memory region being queried.
+ * @addr: the address (relative to the start of the region) being dirtied.
+ */
+void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr);
+
+/**
+ * memory_region_sync_dirty_bitmap: Synchronize a region's dirty bitmap with
+ *                                  any external TLBs (e.g. kvm)
+ *
+ * Flushes dirty information from accelerators such as kvm and vhost-net
+ * and makes it available to users of the memory API.
+ *
+ * @mr: the region being flushed.
+ */
+void memory_region_sync_dirty_bitmap(MemoryRegion *mr);
+
+/**
+ * memory_region_reset_dirty: Mark a range of pages as clean, for a specified
+ *                            client.
+ *
+ * Marks a range of pages as no longer dirty.
+ *
+ * @mr: the region being updated.
+ * @addr: the start of the subrange being cleaned.
+ * @size: the size of the subrange being cleaned.
+ * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or
+ *          %DIRTY_MEMORY_VGA.
+ */
+void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                               target_phys_addr_t size, unsigned client);
+
+/**
+ * memory_region_set_readonly: Turn a memory region read-only (or read-write)
+ *
+ * Allows a memory region to be marked as read-only (turning it into a ROM).
+ * only useful on RAM regions.
+ *
+ * @mr: the region being updated.
+ * @readonly: whether rhe region is to be ROM or RAM.
+ */
+void memory_region_set_readonly(MemoryRegion *mr, bool readonly);
+
+/**
+ * memory_region_set_coalescing: Enable memory coalescing for the region.
+ *
+ * Enabled writes to a region to be queued for later processing. MMIO ->write
+ * callbacks may be delayed until a non-coalesced MMIO is issued.
+ * Only useful for IO regions.  Roughly similar to write-combining hardware.
+ *
+ * @mr: the memory region to be write coalesced
+ */
+void memory_region_set_coalescing(MemoryRegion *mr);
+
+/**
+ * memory_region_add_coalescing: Enable memory coalescing for a sub-range of
+ *                               a region.
+ *
+ * Like memory_region_set_coalescing(), but works on a sub-range of a region.
+ * Multiple calls can be issued coalesced disjoint ranges.
+ *
+ * @mr: the memory region to be updated.
+ * @offset: the start of the range within the region to be coalesced.
+ * @size: the size of the subrange to be coalesced.
+ */
+void memory_region_add_coalescing(MemoryRegion *mr,
+                                  target_phys_addr_t offset,
+                                  uint64_t size);
+
+/**
+ * memory_region_clear_coalescing: Disable MMIO coalescing for the region.
+ *
+ * Disables any coalescing caused by memory_region_set_coalescing() or
+ * memory_region_add_coalescing().  Roughly equivalent to uncacheble memory
+ * hardware.
+ *
+ * @mr: the memory region to be updated.
+ */
+void memory_region_clear_coalescing(MemoryRegion *mr);
+
+/**
+ * memory_region_add_eventfd: Request an eventfd to be triggered when a word
+ *                            is written to a location.
+ *
+ * Marks a word in an IO region (initialized with memory_region_init_io())
+ * as a trigger for an eventfd event.  The I/O callback will not be called.
+ * The caller must be prepared to handle failure (hat is, take the required
+ * action if the callback _is_ called).
+ *
+ * @mr: the memory region being updated.
+ * @addr: the address within @mr that is to be monitored
+ * @size: the size of the access to trigger the eventfd
+ * @match_data: whether to match against @data, instead of just @addr
+ * @data: the data to match against the guest write
+ * @fd: the eventfd to be triggered when @addr, @size, and @data all match.
+ **/
+void memory_region_add_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd);
+
+/**
+ * memory_region_del_eventfd: Cancel and eventfd.
+ *
+ * Cancels an eventfd trigger request by a previous memory_region_add_eventfd()
+ * call.
+ *
+ * @mr: the memory region being updated.
+ * @addr: the address within @mr that is to be monitored
+ * @size: the size of the access to trigger the eventfd
+ * @match_data: whether to match against @data, instead of just @addr
+ * @data: the data to match against the guest write
+ * @fd: the eventfd to be triggered when @addr, @size, and @data all match.
+ */
+void memory_region_del_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd);
+/**
+ * memory_region_add_subregion: Add a sub-region to a container.
+ *
+ * Adds a sub-region at @offset.  The sub-region may not overlap with other
+ * subregions (except for those explicitly marked as overlapping).  A region
+ * may only be added once as a subregion (unless removed with
+ * memory_region_del_subregion()); use memory_region_init_alias() if you
+ * want a region to be a subregion in multiple locations.
+ *
+ * @mr: the region to contain the new subregion; must be a container
+ *      initialized with memory_region_init().
+ * @offset: the offset relative to @mr where @subregion is added.
+ * @subregion: the subregion to be added.
+ */
+void memory_region_add_subregion(MemoryRegion *mr,
+                                 target_phys_addr_t offset,
+                                 MemoryRegion *subregion);
+/**
+ * memory_region_add_subregion: Add a sub-region to a container, with overlap.
+ *
+ * Adds a sub-region at @offset.  The sub-region may overlap with other
+ * subregions.  Conflicts are resolved by having a higher @priority hide a
+ * lower @priority. Subregions without priority are taken as @priority 0.
+ * A region may only be added once as a subregion (unless removed with
+ * memory_region_del_subregion()); use memory_region_init_alias() if you
+ * want a region to be a subregion in multiple locations.
+ *
+ * @mr: the region to contain the new subregion; must be a container
+ *      initialized with memory_region_init().
+ * @offset: the offset relative to @mr where @subregion is added.
+ * @subregion: the subregion to be added.
+ * @priority: used for resolving overlaps; highest priority wins.
+ */
+void memory_region_add_subregion_overlap(MemoryRegion *mr,
+                                         target_phys_addr_t offset,
+                                         MemoryRegion *subregion,
+                                         unsigned priority);
+/**
+ * memory_region_del_subregion: Remove a subregion.
+ *
+ * Removes a subregion from its container.
+ *
+ * @mr: the container to be updated.
+ * @subregion: the region being removed; must be a current subregion of @mr.
+ */
+void memory_region_del_subregion(MemoryRegion *mr,
+                                 MemoryRegion *subregion);
+
+/* Start a transaction; changes will be accumulated and made visible only
+ * when the transaction ends.
+ */
+void memory_region_transaction_begin(void);
+/* Commit a transaction and make changes visible to the guest.
+ */
+void memory_region_transaction_commit(void);
+
+#endif
+
+#endif
index 2a15b98db9f328022893972bb4b62b4b3a9aee7c..756fa6261f95746c606d18d855b406c0fa947316 100644 (file)
@@ -292,18 +292,17 @@ int migrate_fd_cleanup(FdMigrationState *s)
             ret = -1;
         }
         s->file = NULL;
+    } else {
+        if (s->mon) {
+            monitor_resume(s->mon);
+        }
     }
 
-    if (s->fd != -1)
+    if (s->fd != -1) {
         close(s->fd);
-
-    /* Don't resume monitor until we've flushed all of the buffers */
-    if (s->mon) {
-        monitor_resume(s->mon);
+        s->fd = -1;
     }
 
-    s->fd = -1;
-
     return ret;
 }
 
@@ -330,9 +329,6 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
     if (ret == -EAGAIN) {
         qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s);
     } else if (ret < 0) {
-        if (s->mon) {
-            monitor_resume(s->mon);
-        }
         s->state = MIG_STATE_ERROR;
         notifier_list_notify(&migration_state_notifiers, NULL);
     }
@@ -458,6 +454,9 @@ int migrate_fd_close(void *opaque)
 {
     FdMigrationState *s = opaque;
 
+    if (s->mon) {
+        monitor_resume(s->mon);
+    }
     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
     return s->close(s);
 }
index 718935b881349be6e398e3e9fc1c1df177851618..1b8ba2c1fa284175262d6017d3fec083624bdf18 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -1200,10 +1200,12 @@ static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d
         }
        qerror_report(QERR_ADD_CLIENT_FAILED);
        return -1;
+#ifdef CONFIG_VNC
     } else if (strcmp(protocol, "vnc") == 0) {
        int fd = monitor_get_fd(mon, fdname);
        vnc_display_add_client(NULL, fd, skipauth);
        return 0;
+#endif
     } else if ((s = qemu_chr_find(protocol)) != NULL) {
        int fd = monitor_get_fd(mon, fdname);
        if (qemu_chr_add_client(s, fd) < 0) {
diff --git a/net.c b/net.c
index 31c23389c835f8e7fe2c31190c0063a06e16cbe4..cb6a2b03d8a06cb3192d63978e7027c2b8f2fd8d 100644 (file)
--- a/net.c
+++ b/net.c
@@ -150,12 +150,11 @@ void qemu_macaddr_default_if_unset(MACAddr *macaddr)
 static char *assign_name(VLANClientState *vc1, const char *model)
 {
     VLANState *vlan;
+    VLANClientState *vc;
     char buf[256];
     int id = 0;
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
-        VLANClientState *vc;
-
         QTAILQ_FOREACH(vc, &vlan->clients, next) {
             if (vc != vc1 && strcmp(vc->model, model) == 0) {
                 id++;
@@ -163,6 +162,12 @@ static char *assign_name(VLANClientState *vc1, const char *model)
         }
     }
 
+    QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
+        if (vc != vc1 && strcmp(vc->model, model) == 0) {
+            id++;
+        }
+    }
+
     snprintf(buf, sizeof(buf), "%s.%d", model, id);
 
     return qemu_strdup(buf);
@@ -653,6 +658,8 @@ VLANClientState *qemu_find_netdev(const char *id)
     VLANClientState *vc;
 
     QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
+        if (vc->info->type == NET_CLIENT_TYPE_NIC)
+            continue;
         if (!strcmp(vc->name, id)) {
             return vc;
         }
@@ -1212,7 +1219,7 @@ int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
     VLANClientState *vc;
 
     vc = qemu_find_netdev(id);
-    if (!vc || vc->info->type == NET_CLIENT_TYPE_NIC) {
+    if (!vc) {
         qerror_report(QERR_DEVICE_NOT_FOUND, id);
         return -1;
     }
@@ -1270,7 +1277,11 @@ int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data)
             }
         }
     }
-    vc = qemu_find_netdev(name);
+    QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
+        if (!strcmp(vc->name, name)) {
+            goto done;
+        }
+    }
 done:
 
     if (!vc) {
index 11fe5f383fec546f26c8d97ea0a2a86f6beec345..5cd0b9abf7e8d7299c7454d9650827468b8b9e64 100644 (file)
@@ -154,6 +154,12 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
     struct ip_mreq imr;
     int fd;
     int val, ret;
+#ifdef __OpenBSD__
+    unsigned char loop;
+#else
+    int loop;
+#endif
+
     if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
        fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) does not contain a multicast address\n",
                inet_ntoa(mcastaddr->sin_addr),
@@ -197,9 +203,9 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
     }
 
     /* Force mcast msgs to loopback (eg. several QEMUs in same host */
-    val = 1;
+    loop = 1;
     ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
-                   (const char *)&val, sizeof(val));
+                   (const char *)&loop, sizeof(loop));
     if (ret < 0) {
        perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
        goto fail;
index 2f3efdee03b5b57c801ae2c7828c8ee1601f9ffe..4b6b3a41a095de3e035ef85a9c5a911d4af6df6b 100644 (file)
@@ -28,6 +28,8 @@
 #include "qemu-error.h"
 
 #ifdef __NetBSD__
+#include <sys/ioctl.h>
+#include <net/if.h>
 #include <net/if_tap.h>
 #endif
 
 int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required)
 {
     int fd;
+#ifdef TAPGIFNAME
+    struct ifreq ifr;
+#else
     char *dev;
     struct stat s;
+#endif
 
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
     /* if no ifname is given, always start the search from tap0/tun0. */
@@ -77,14 +83,30 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
 #else
     TFR(fd = open("/dev/tap", O_RDWR));
     if (fd < 0) {
-        fprintf(stderr, "warning: could not open /dev/tap: no virtual network emulation\n");
+        fprintf(stderr,
+            "warning: could not open /dev/tap: no virtual network emulation: %s\n",
+            strerror(errno));
         return -1;
     }
 #endif
 
-    fstat(fd, &s);
+#ifdef TAPGIFNAME
+    if (ioctl(fd, TAPGIFNAME, (void *)&ifr) < 0) {
+        fprintf(stderr, "warning: could not get tap name: %s\n",
+            strerror(errno));
+        return -1;
+    }
+    pstrcpy(ifname, ifname_size, ifr.ifr_name);
+#else
+    if (fstat(fd, &s) < 0) {
+        fprintf(stderr,
+            "warning: could not stat /dev/tap: no virtual network emulation: %s\n",
+            strerror(errno));
+        return -1;
+    }
     dev = devname(s.st_rdev, S_IFCHR);
     pstrcpy(ifname, ifname_size, dev);
+#endif
 
     if (*vnet_hdr) {
         /* BSD doesn't have IFF_VNET_HDR */
index 3a18e865f399e4e454a03527b471fd91a1f9b252..196099cc77fdcfd33f380df28bcf4cb2a66b2bd4 100644 (file)
@@ -79,7 +79,10 @@ void *qemu_memalign(size_t alignment, size_t size)
 /* alloc shared memory pages */
 void *qemu_vmalloc(size_t size)
 {
-    return qemu_memalign(getpagesize(), size);
+    void *ptr;
+    ptr = qemu_memalign(getpagesize(), size);
+    trace_qemu_vmalloc(size, ptr);
+    return ptr;
 }
 
 void qemu_vfree(void *ptr)
index c4116e30f2e2391762b5528cd46a179d53843ba0..8dc00cbb0f1d60710aab47f9efd6e03357016a0f 100644 (file)
@@ -49,8 +49,6 @@ struct qemu_paiocb {
     ssize_t ret;
     int active;
     struct qemu_paiocb *next;
-
-    int async_context_id;
 };
 
 typedef struct PosixAioState {
@@ -200,6 +198,12 @@ static ssize_t handle_aiocb_rw_vector(struct qemu_paiocb *aiocb)
     return len;
 }
 
+/*
+ * Read/writes the data to/from a given linear buffer.
+ *
+ * Returns the number of bytes handles or -errno in case of an error. Short
+ * reads are only returned if the end of the file is reached.
+ */
 static ssize_t handle_aiocb_rw_linear(struct qemu_paiocb *aiocb, char *buf)
 {
     ssize_t offset = 0;
@@ -336,6 +340,19 @@ static void *aio_thread(void *unused)
 
         switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
         case QEMU_AIO_READ:
+            ret = handle_aiocb_rw(aiocb);
+            if (ret >= 0 && ret < aiocb->aio_nbytes && aiocb->common.bs->growable) {
+                /* A short read means that we have reached EOF. Pad the buffer
+                 * with zeros for bytes after EOF. */
+                QEMUIOVector qiov;
+
+                qemu_iovec_init_external(&qiov, aiocb->aio_iov,
+                                         aiocb->aio_niov);
+                qemu_iovec_memset_skip(&qiov, 0, aiocb->aio_nbytes - ret, ret);
+
+                ret = aiocb->aio_nbytes;
+            }
+            break;
         case QEMU_AIO_WRITE:
             ret = handle_aiocb_rw(aiocb);
             break;
@@ -420,7 +437,6 @@ static int posix_aio_process_queue(void *opaque)
     struct qemu_paiocb *acb, **pacb;
     int ret;
     int result = 0;
-    int async_context_id = get_async_context_id();
 
     for(;;) {
         pacb = &s->first_aio;
@@ -429,12 +445,6 @@ static int posix_aio_process_queue(void *opaque)
             if (!acb)
                 return result;
 
-            /* we're only interested in requests in the right context */
-            if (acb->async_context_id != async_context_id) {
-                pacb = &acb->next;
-                continue;
-            }
-
             ret = qemu_paio_error(acb);
             if (ret == ECANCELED) {
                 /* remove the request */
@@ -575,7 +585,6 @@ BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
     acb->aio_type = type;
     acb->aio_fildes = fd;
     acb->ev_signo = SIGUSR2;
-    acb->async_context_id = get_async_context_id();
 
     if (qiov) {
         acb->aio_iov = qiov->iov;
@@ -604,7 +613,6 @@ BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
     acb->aio_type = QEMU_AIO_IOCTL;
     acb->aio_fildes = fd;
     acb->ev_signo = SIGUSR2;
-    acb->async_context_id = get_async_context_id();
     acb->aio_offset = 0;
     acb->aio_ioctl_buf = buf;
     acb->aio_ioctl_cmd = req;
index 391fadda56f3842c9a46e6bcc9931bf8b08aa7c9..74d5c4b9620852985010f1e5e0854575023e1092 100644 (file)
@@ -5,6 +5,10 @@
 #include "compiler.h"
 #include "config-host.h"
 
+#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__ia64__)
+#define WORDS_ALIGNED
+#endif
+
 #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
 
 typedef struct QEMUTimer QEMUTimer;
@@ -111,10 +115,6 @@ int qemu_main(int argc, char **argv, char **envp);
 /* bottom halves */
 typedef void QEMUBHFunc(void *opaque);
 
-void async_context_push(void);
-void async_context_pop(void);
-int get_async_context_id(void);
-
 QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
 void qemu_bh_schedule(QEMUBH *bh);
 /* Bottom halfs that are scheduled from a bottom half handler are instantly
@@ -157,6 +157,8 @@ int fcntl_setfl(int fd, int flag);
 #define STRTOSZ_DEFSUFFIX_B    'B'
 int64_t strtosz(const char *nptr, char **end);
 int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix);
+int64_t strtosz_suffix_unit(const char *nptr, char **end,
+                            const char default_suffix, int64_t unit);
 
 /* path.c */
 void init_paths(const char *prefix);
@@ -266,10 +268,14 @@ typedef struct I2SCodec I2SCodec;
 typedef struct SSIBus SSIBus;
 typedef struct EventNotifier EventNotifier;
 typedef struct VirtIODevice VirtIODevice;
+typedef struct QEMUSGList QEMUSGList;
 
 typedef uint64_t pcibus_t;
 
-void cpu_exec_init_all(unsigned long tb_size);
+void tcg_exec_init(unsigned long tb_size);
+bool tcg_enabled(void);
+
+void cpu_exec_init_all(void);
 
 /* CPU save/load.  */
 void cpu_save(QEMUFile *f, void *opaque);
index b2ec40bd66f8ec82cc1cd76f307caae65cf5ab36..1eb6b9a70972e083e9d5e6aaeae3b04490bbeb3e 100644 (file)
@@ -480,6 +480,32 @@ static QemuOptsList qemu_machine_opts = {
     },
 };
 
+QemuOptsList qemu_boot_opts = {
+    .name = "boot-opts",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_boot_opts.head),
+    .desc = {
+        /* the three names below are not used now */
+        {
+            .name = "order",
+            .type = QEMU_OPT_STRING,
+        }, {
+            .name = "once",
+            .type = QEMU_OPT_STRING,
+        }, {
+            .name = "menu",
+            .type = QEMU_OPT_STRING,
+        /* following are really used */
+        }, {
+            .name = "splash",
+            .type = QEMU_OPT_STRING,
+        }, {
+            .name = "splash-time",
+            .type = QEMU_OPT_STRING,
+        },
+        { /*End of list */ }
+    },
+};
+
 static QemuOptsList *vm_config_groups[32] = {
     &qemu_drive_opts,
     &qemu_chardev_opts,
@@ -495,6 +521,7 @@ static QemuOptsList *vm_config_groups[32] = {
 #endif
     &qemu_option_rom_opts,
     &qemu_machine_opts,
+    &qemu_boot_opts,
     NULL,
 };
 
diff --git a/qemu-coroutine-int.h b/qemu-coroutine-int.h
new file mode 100644 (file)
index 0000000..d495615
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Coroutine internals
+ *
+ * Copyright (c) 2011 Kevin Wolf <kwolf@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef QEMU_COROUTINE_INT_H
+#define QEMU_COROUTINE_INT_H
+
+#include "qemu-queue.h"
+#include "qemu-coroutine.h"
+
+typedef enum {
+    COROUTINE_YIELD = 1,
+    COROUTINE_TERMINATE = 2,
+} CoroutineAction;
+
+struct Coroutine {
+    CoroutineEntry *entry;
+    void *entry_arg;
+    Coroutine *caller;
+    QLIST_ENTRY(Coroutine) pool_next;
+    QTAILQ_ENTRY(Coroutine) co_queue_next;
+};
+
+Coroutine *qemu_coroutine_new(void);
+void qemu_coroutine_delete(Coroutine *co);
+CoroutineAction qemu_coroutine_switch(Coroutine *from, Coroutine *to,
+                                      CoroutineAction action);
+
+#endif
diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c
new file mode 100644 (file)
index 0000000..a80f437
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * coroutine queues and locks
+ *
+ * Copyright (c) 2011 Kevin Wolf <kwolf@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "qemu-coroutine.h"
+#include "qemu-coroutine-int.h"
+#include "qemu-queue.h"
+#include "trace.h"
+
+static QTAILQ_HEAD(, Coroutine) unlock_bh_queue =
+    QTAILQ_HEAD_INITIALIZER(unlock_bh_queue);
+static QEMUBH* unlock_bh;
+
+static void qemu_co_queue_next_bh(void *opaque)
+{
+    Coroutine *next;
+
+    trace_qemu_co_queue_next_bh();
+    while ((next = QTAILQ_FIRST(&unlock_bh_queue))) {
+        QTAILQ_REMOVE(&unlock_bh_queue, next, co_queue_next);
+        qemu_coroutine_enter(next, NULL);
+    }
+}
+
+void qemu_co_queue_init(CoQueue *queue)
+{
+    QTAILQ_INIT(&queue->entries);
+
+    if (!unlock_bh) {
+        unlock_bh = qemu_bh_new(qemu_co_queue_next_bh, NULL);
+    }
+}
+
+void coroutine_fn qemu_co_queue_wait(CoQueue *queue)
+{
+    Coroutine *self = qemu_coroutine_self();
+    QTAILQ_INSERT_TAIL(&queue->entries, self, co_queue_next);
+    qemu_coroutine_yield();
+    assert(qemu_in_coroutine());
+}
+
+bool qemu_co_queue_next(CoQueue *queue)
+{
+    Coroutine *next;
+
+    next = QTAILQ_FIRST(&queue->entries);
+    if (next) {
+        QTAILQ_REMOVE(&queue->entries, next, co_queue_next);
+        QTAILQ_INSERT_TAIL(&unlock_bh_queue, next, co_queue_next);
+        trace_qemu_co_queue_next(next);
+        qemu_bh_schedule(unlock_bh);
+    }
+
+    return (next != NULL);
+}
+
+bool qemu_co_queue_empty(CoQueue *queue)
+{
+    return (QTAILQ_FIRST(&queue->entries) == NULL);
+}
+
+void qemu_co_mutex_init(CoMutex *mutex)
+{
+    memset(mutex, 0, sizeof(*mutex));
+    qemu_co_queue_init(&mutex->queue);
+}
+
+void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex)
+{
+    Coroutine *self = qemu_coroutine_self();
+
+    trace_qemu_co_mutex_lock_entry(mutex, self);
+
+    while (mutex->locked) {
+        qemu_co_queue_wait(&mutex->queue);
+    }
+
+    mutex->locked = true;
+
+    trace_qemu_co_mutex_lock_return(mutex, self);
+}
+
+void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex)
+{
+    Coroutine *self = qemu_coroutine_self();
+
+    trace_qemu_co_mutex_unlock_entry(mutex, self);
+
+    assert(mutex->locked == true);
+    assert(qemu_in_coroutine());
+
+    mutex->locked = false;
+    qemu_co_queue_next(&mutex->queue);
+
+    trace_qemu_co_mutex_unlock_return(mutex, self);
+}
diff --git a/qemu-coroutine.c b/qemu-coroutine.c
new file mode 100644 (file)
index 0000000..600be26
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * QEMU coroutines
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
+ *  Kevin Wolf         <kwolf@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "trace.h"
+#include "qemu-common.h"
+#include "qemu-coroutine.h"
+#include "qemu-coroutine-int.h"
+
+Coroutine *qemu_coroutine_create(CoroutineEntry *entry)
+{
+    Coroutine *co = qemu_coroutine_new();
+    co->entry = entry;
+    return co;
+}
+
+static void coroutine_swap(Coroutine *from, Coroutine *to)
+{
+    CoroutineAction ret;
+
+    ret = qemu_coroutine_switch(from, to, COROUTINE_YIELD);
+
+    switch (ret) {
+    case COROUTINE_YIELD:
+        return;
+    case COROUTINE_TERMINATE:
+        trace_qemu_coroutine_terminate(to);
+        qemu_coroutine_delete(to);
+        return;
+    default:
+        abort();
+    }
+}
+
+void qemu_coroutine_enter(Coroutine *co, void *opaque)
+{
+    Coroutine *self = qemu_coroutine_self();
+
+    trace_qemu_coroutine_enter(self, co, opaque);
+
+    if (co->caller) {
+        fprintf(stderr, "Co-routine re-entered recursively\n");
+        abort();
+    }
+
+    co->caller = self;
+    co->entry_arg = opaque;
+    coroutine_swap(self, co);
+}
+
+void coroutine_fn qemu_coroutine_yield(void)
+{
+    Coroutine *self = qemu_coroutine_self();
+    Coroutine *to = self->caller;
+
+    trace_qemu_coroutine_yield(self, to);
+
+    if (!to) {
+        fprintf(stderr, "Co-routine is yielding to no one\n");
+        abort();
+    }
+
+    self->caller = NULL;
+    coroutine_swap(self, to);
+}
diff --git a/qemu-coroutine.h b/qemu-coroutine.h
new file mode 100644 (file)
index 0000000..2f2fd95
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * QEMU coroutine implementation
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
+ *  Kevin Wolf         <kwolf@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_COROUTINE_H
+#define QEMU_COROUTINE_H
+
+#include <stdbool.h>
+#include "qemu-queue.h"
+
+/**
+ * Coroutines are a mechanism for stack switching and can be used for
+ * cooperative userspace threading.  These functions provide a simple but
+ * useful flavor of coroutines that is suitable for writing sequential code,
+ * rather than callbacks, for operations that need to give up control while
+ * waiting for events to complete.
+ *
+ * These functions are re-entrant and may be used outside the global mutex.
+ */
+
+/**
+ * Mark a function that executes in coroutine context
+ *
+ * Functions that execute in coroutine context cannot be called directly from
+ * normal functions.  In the future it would be nice to enable compiler or
+ * static checker support for catching such errors.  This annotation might make
+ * it possible and in the meantime it serves as documentation.
+ *
+ * For example:
+ *
+ *   static void coroutine_fn foo(void) {
+ *       ....
+ *   }
+ */
+#define coroutine_fn
+
+typedef struct Coroutine Coroutine;
+
+/**
+ * Coroutine entry point
+ *
+ * When the coroutine is entered for the first time, opaque is passed in as an
+ * argument.
+ *
+ * When this function returns, the coroutine is destroyed automatically and
+ * execution continues in the caller who last entered the coroutine.
+ */
+typedef void coroutine_fn CoroutineEntry(void *opaque);
+
+/**
+ * Create a new coroutine
+ *
+ * Use qemu_coroutine_enter() to actually transfer control to the coroutine.
+ */
+Coroutine *qemu_coroutine_create(CoroutineEntry *entry);
+
+/**
+ * Transfer control to a coroutine
+ *
+ * The opaque argument is passed as the argument to the entry point when
+ * entering the coroutine for the first time.  It is subsequently ignored.
+ */
+void qemu_coroutine_enter(Coroutine *coroutine, void *opaque);
+
+/**
+ * Transfer control back to a coroutine's caller
+ *
+ * This function does not return until the coroutine is re-entered using
+ * qemu_coroutine_enter().
+ */
+void coroutine_fn qemu_coroutine_yield(void);
+
+/**
+ * Get the currently executing coroutine
+ */
+Coroutine *coroutine_fn qemu_coroutine_self(void);
+
+/**
+ * Return whether or not currently inside a coroutine
+ *
+ * This can be used to write functions that work both when in coroutine context
+ * and when not in coroutine context.  Note that such functions cannot use the
+ * coroutine_fn annotation since they work outside coroutine context.
+ */
+bool qemu_in_coroutine(void);
+
+
+
+/**
+ * CoQueues are a mechanism to queue coroutines in order to continue executing
+ * them later. They provide the fundamental primitives on which coroutine locks
+ * are built.
+ */
+typedef struct CoQueue {
+    QTAILQ_HEAD(, Coroutine) entries;
+} CoQueue;
+
+/**
+ * Initialise a CoQueue. This must be called before any other operation is used
+ * on the CoQueue.
+ */
+void qemu_co_queue_init(CoQueue *queue);
+
+/**
+ * Adds the current coroutine to the CoQueue and transfers control to the
+ * caller of the coroutine.
+ */
+void coroutine_fn qemu_co_queue_wait(CoQueue *queue);
+
+/**
+ * Restarts the next coroutine in the CoQueue and removes it from the queue.
+ *
+ * Returns true if a coroutine was restarted, false if the queue is empty.
+ */
+bool qemu_co_queue_next(CoQueue *queue);
+
+/**
+ * Checks if the CoQueue is empty.
+ */
+bool qemu_co_queue_empty(CoQueue *queue);
+
+
+/**
+ * Provides a mutex that can be used to synchronise coroutines
+ */
+typedef struct CoMutex {
+    bool locked;
+    CoQueue queue;
+} CoMutex;
+
+/**
+ * Initialises a CoMutex. This must be called before any other operation is used
+ * on the CoMutex.
+ */
+void qemu_co_mutex_init(CoMutex *mutex);
+
+/**
+ * Locks the mutex. If the lock cannot be taken immediately, control is
+ * transferred to the caller of the current coroutine.
+ */
+void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex);
+
+/**
+ * Unlocks the mutex and schedules the next coroutine that was waiting for this
+ * lock to be run.
+ */
+void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex);
+
+#endif /* QEMU_COROUTINE_H */
index 47e1991712de827d821671b2cddc0bb2469affa4..31199f6004f414cd380eee45715c72913f96ba04 100644 (file)
@@ -288,6 +288,14 @@ then the modifier is Ctrl-Alt-Shift (instead of Ctrl-Alt) and if you use
 @kindex Ctrl-Alt-f
 Toggle full screen
 
+@item Ctrl-Alt-+
+@kindex Ctrl-Alt-+
+Enlarge the screen
+
+@item Ctrl-Alt--
+@kindex Ctrl-Alt--
+Shrink the screen
+
 @item Ctrl-Alt-u
 @kindex Ctrl-Alt-u
 Restore the screen's un-scaled dimensions
index 1d57f64888abee19542063fa0588a89d4fea02ee..d86815dc04050cf0b0c9377c075e587d8a3265e2 100644 (file)
@@ -303,10 +303,13 @@ ETEXI
 
 DEF("boot", HAS_ARG, QEMU_OPTION_boot,
     "-boot [order=drives][,once=drives][,menu=on|off]\n"
-    "                'drives': floppy (a), hard disk (c), CD-ROM (d), network (n)\n",
+    "      [,splash=sp_name][,splash-time=sp_time]\n"
+    "                'drives': floppy (a), hard disk (c), CD-ROM (d), network (n)\n"
+    "                'sp_name': the file's name that would be passed to bios as logo picture, if menu=on\n"
+    "                'sp_time': the period that splash picture last if menu=on, unit is ms\n",
     QEMU_ARCH_ALL)
 STEXI
-@item -boot [order=@var{drives}][,once=@var{drives}][,menu=on|off]
+@item -boot [order=@var{drives}][,once=@var{drives}][,menu=on|off][,splash=@var{sp_name}][,splash-time=@var{sp_time}]
 @findex -boot
 Specify boot order @var{drives} as a string of drive letters. Valid
 drive letters depend on the target achitecture. The x86 PC uses: a, b
@@ -318,11 +321,20 @@ particular boot order only on the first startup, specify it via
 Interactive boot menus/prompts can be enabled via @option{menu=on} as far
 as firmware/BIOS supports them. The default is non-interactive boot.
 
+A splash picture could be passed to bios, enabling user to show it as logo,
+when option splash=@var{sp_name} is given and menu=on, If firmware/BIOS
+supports them. Currently Seabios for X86 system support it.
+limitation: The splash file could be a jpeg file or a BMP file in 24 BPP
+format(true color). The resolution should be supported by the SVGA mode, so
+the recommended is 320x240, 640x480, 800x640.
+
 @example
 # try to boot from network first, then from hard disk
 qemu -boot order=nc
 # boot from CD-ROM first, switch back to default order after reboot
 qemu -boot once=d
+# boot with a splash picture for 5 seconds.
+qemu -boot menu=on,splash=/root/boot.bmp,splash-time=5000
 @end example
 
 Note: The legacy format '-boot @var{drives}' is still supported but its
@@ -1062,12 +1074,17 @@ Enable virtio balloon device (default), optionally with PCI address
 ETEXI
 
 DEF("acpitable", HAS_ARG, QEMU_OPTION_acpitable,
-    "-acpitable [sig=str][,rev=n][,oem_id=str][,oem_table_id=str][,oem_rev=n][,asl_compiler_id=str][,asl_compiler_rev=n][,data=file1[:file2]...]\n"
+    "-acpitable [sig=str][,rev=n][,oem_id=str][,oem_table_id=str][,oem_rev=n][,asl_compiler_id=str][,asl_compiler_rev=n][,{data|file}=file1[:file2]...]\n"
     "                ACPI table description\n", QEMU_ARCH_I386)
 STEXI
 @item -acpitable [sig=@var{str}][,rev=@var{n}][,oem_id=@var{str}][,oem_table_id=@var{str}][,oem_rev=@var{n}] [,asl_compiler_id=@var{str}][,asl_compiler_rev=@var{n}][,data=@var{file1}[:@var{file2}]...]
 @findex -acpitable
 Add ACPI table with specified header fields and context from specified files.
+For file=, take whole ACPI table from the specified files, including all
+ACPI headers (possible overridden by other options).
+For data=, only data
+portion of the table is used, all header information is specified in the
+command line.
 ETEXI
 
 DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
index 54e313ce52e3501e902ad8e874129f8f87091dfb..03f67da19826d93835ced726dd89d4885847d287 100644 (file)
@@ -42,7 +42,7 @@ and we're going to establish a deprecation policy for badly defined commands.
 
 If you're planning to adopt QMP, please observe the following:
 
-    1. The deprecation policy will take efect and be documented soon, please
+    1. The deprecation policy will take effect and be documented soon, please
        check the documentation of each used command as soon as a new release of
        QEMU is available
 
index 79db4cbd18b25b103bb8b3db1125174eb31145bc..7801aa7056b888c706e57d4974be3ed78972ae45 100644 (file)
--- a/savevm.c
+++ b/savevm.c
@@ -1234,6 +1234,7 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     se->opaque = opaque;
     se->vmsd = vmsd;
     se->alias_id = alias_id;
+    se->no_migrate = vmsd->unmigratable;
 
     if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
         char *id = dev->parent_bus->info->get_dev_path(dev);
diff --git a/slirp/arp_table.c b/slirp/arp_table.c
new file mode 100644 (file)
index 0000000..5d7b8ac
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * ARP table
+ *
+ * Copyright (c) 2011 AdaCore
+ *
+ * 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 "slirp.h"
+
+void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN])
+{
+    const uint32_t broadcast_addr =
+        ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr;
+    ArpTable *arptbl = &slirp->arp_table;
+    int i;
+
+    DEBUG_CALL("arp_table_add");
+    DEBUG_ARG("ip = 0x%x", ip_addr);
+    DEBUG_ARGS((dfd, " hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
+                ethaddr[0], ethaddr[1], ethaddr[2],
+                ethaddr[3], ethaddr[4], ethaddr[5]));
+
+    /* Check 0.0.0.0/8 invalid source-only addresses */
+    assert((ip_addr & htonl(~(0xf << 28))) != 0);
+
+    if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
+        /* Do not register broadcast addresses */
+        return;
+    }
+
+    /* Search for an entry */
+    for (i = 0; i < ARP_TABLE_SIZE; i++) {
+        if (arptbl->table[i].ar_sip == ip_addr) {
+            /* Update the entry */
+            memcpy(arptbl->table[i].ar_sha, ethaddr, ETH_ALEN);
+            return;
+        }
+    }
+
+    /* No entry found, create a new one */
+    arptbl->table[arptbl->next_victim].ar_sip = ip_addr;
+    memcpy(arptbl->table[arptbl->next_victim].ar_sha,  ethaddr, ETH_ALEN);
+    arptbl->next_victim = (arptbl->next_victim + 1) % ARP_TABLE_SIZE;
+}
+
+bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
+                      uint8_t out_ethaddr[ETH_ALEN])
+{
+    const uint32_t broadcast_addr =
+        ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr;
+    ArpTable *arptbl = &slirp->arp_table;
+    int i;
+
+    DEBUG_CALL("arp_table_search");
+    DEBUG_ARG("ip = 0x%x", ip_addr);
+
+    /* Check 0.0.0.0/8 invalid source-only addresses */
+    assert((ip_addr & htonl(~(0xf << 28))) != 0);
+
+    /* If broadcast address */
+    if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
+        /* return Ethernet broadcast address */
+        memset(out_ethaddr, 0xff, ETH_ALEN);
+        return 1;
+    }
+
+    for (i = 0; i < ARP_TABLE_SIZE; i++) {
+        if (arptbl->table[i].ar_sip == ip_addr) {
+            memcpy(out_ethaddr, arptbl->table[i].ar_sha,  ETH_ALEN);
+            DEBUG_ARGS((dfd, " found hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
+                        out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
+                        out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]));
+            return 1;
+        }
+    }
+
+    return 0;
+}
index 1eb2ed11434df1d61d4a5f0ba447762a070194ab..efd1fe777a3a774be93bb4d54941fd23e74af70b 100644 (file)
@@ -149,6 +149,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
     struct in_addr preq_addr;
     int dhcp_msg_type, val;
     uint8_t *q;
+    uint8_t client_ethaddr[ETH_ALEN];
 
     /* extract exact DHCP msg type */
     dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
@@ -164,8 +165,9 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
     if (dhcp_msg_type != DHCPDISCOVER &&
         dhcp_msg_type != DHCPREQUEST)
         return;
-    /* XXX: this is a hack to get the client mac address */
-    memcpy(slirp->client_ethaddr, bp->bp_hwaddr, 6);
+
+    /* Get client's hardware address from bootp request */
+    memcpy(client_ethaddr, bp->bp_hwaddr, ETH_ALEN);
 
     m = m_get(slirp);
     if (!m) {
@@ -178,25 +180,25 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
 
     if (dhcp_msg_type == DHCPDISCOVER) {
         if (preq_addr.s_addr != htonl(0L)) {
-            bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);
+            bc = request_addr(slirp, &preq_addr, client_ethaddr);
             if (bc) {
                 daddr.sin_addr = preq_addr;
             }
         }
         if (!bc) {
          new_addr:
-            bc = get_new_addr(slirp, &daddr.sin_addr, slirp->client_ethaddr);
+            bc = get_new_addr(slirp, &daddr.sin_addr, client_ethaddr);
             if (!bc) {
                 DPRINTF("no address left\n");
                 return;
             }
         }
-        memcpy(bc->macaddr, slirp->client_ethaddr, 6);
+        memcpy(bc->macaddr, client_ethaddr, ETH_ALEN);
     } else if (preq_addr.s_addr != htonl(0L)) {
-        bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);
+        bc = request_addr(slirp, &preq_addr, client_ethaddr);
         if (bc) {
             daddr.sin_addr = preq_addr;
-            memcpy(bc->macaddr, slirp->client_ethaddr, 6);
+            memcpy(bc->macaddr, client_ethaddr, ETH_ALEN);
         } else {
             daddr.sin_addr.s_addr = 0;
         }
@@ -209,6 +211,9 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
         }
     }
 
+    /* Update ARP table for this IP address */
+    arp_table_add(slirp, daddr.sin_addr.s_addr, client_ethaddr);
+
     saddr.sin_addr = slirp->vhost_addr;
     saddr.sin_port = htons(BOOTP_SERVER);
 
@@ -218,7 +223,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
     rbp->bp_xid = bp->bp_xid;
     rbp->bp_htype = 1;
     rbp->bp_hlen = 6;
-    memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, 6);
+    memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, ETH_ALEN);
 
     rbp->bp_yiaddr = daddr.sin_addr; /* Client IP address */
     rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */
index 0f04e13989afbbb5925584e65ae088b1ecc178a4..2852396a4a50ff14e80290f852a7b1389c430f2f 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <slirp.h>
+#include "qemu-timer.h"
 
 #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
 
@@ -153,6 +154,8 @@ diddit:
 void
 if_start(Slirp *slirp)
 {
+    uint64_t now = qemu_get_clock_ns(rt_clock);
+    int requeued = 0;
        struct mbuf *ifm, *ifqt;
 
        DEBUG_CALL("if_start");
@@ -199,11 +202,22 @@ if_start(Slirp *slirp)
                   ifm->ifq_so->so_nqueued = 0;
        }
 
-       /* Encapsulate the packet for sending */
-        if_encap(slirp, (uint8_t *)ifm->m_data, ifm->m_len);
-
-        m_free(ifm);
+        if (ifm->expiration_date < now) {
+            /* Expired */
+            m_free(ifm);
+        } else {
+            /* Encapsulate the packet for sending */
+            if (if_encap(slirp, ifm)) {
+                m_free(ifm);
+            } else {
+                /* re-queue */
+                insque(ifm, ifqt);
+                requeued++;
+            }
+        }
 
        if (slirp->if_queued)
           goto again;
+
+        slirp->if_queued = requeued;
 }
index 5e67631ab47d349a8963bd6e80061112ac17a786..c7b3eb48069d70bf5b749242b1cc93b3ac798383 100644 (file)
@@ -511,7 +511,7 @@ typedef uint32_t n_time;
                                 */
                                break;
                        }
-                       off--;                  / * 0 origin *  /
+                        off--; /* 0 origin */
                        if (off > optlen - sizeof(struct in_addr)) {
                                /*
                                 * End of source route.  Should be for us.
@@ -554,7 +554,7 @@ typedef uint32_t n_time;
                        /*
                         * If no space remains, ignore.
                         */
-                       off--;                   * 0 origin *
+                        off--; /* 0 origin */
                        if (off > optlen - sizeof(struct in_addr))
                                break;
                        bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
index 0dd8d81ce4edc05f85b1d4426a13ed3dd6e20e74..028df4b36157c8f6c540098518d45cddd236d346 100644 (file)
@@ -42,5 +42,5 @@ extern int tcp_keepintvl;
 #define PROTO_PPP 0x2
 #endif
 
-void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len);
+int if_encap(Slirp *slirp, struct mbuf *ifm);
 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags);
index ce2eb843f565dd2c7c53cc024111d892e73ad67b..c699c750962b9533fd148a486d4228b6b1ba8c33 100644 (file)
@@ -70,6 +70,8 @@ m_get(Slirp *slirp)
        m->m_len = 0;
         m->m_nextpkt = NULL;
         m->m_prevpkt = NULL;
+        m->arp_requested = false;
+        m->expiration_date = (uint64_t)-1;
 end_error:
        DEBUG_ARG("m = %lx", (long )m);
        return m;
index b74544b42b8432c549dffd28ad58fde1f1df9f48..55170e517bd2e6c11b97e4133370df09169815af 100644 (file)
@@ -86,6 +86,8 @@ struct mbuf {
                char    m_dat_[1]; /* ANSI don't like 0 sized arrays */
                char    *m_ext_;
        } M_dat;
+    bool     arp_requested;
+    uint64_t expiration_date;
 };
 
 #define m_next         m_hdr.mh_next
index df787ea1d923525d225e8678ae462d3b5b0a0d88..2c242ef4ebcbc89320b9134830fe60fb6d672227 100644 (file)
 struct in_addr loopback_addr;
 
 /* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
-static const uint8_t special_ethaddr[6] = {
+static const uint8_t special_ethaddr[ETH_ALEN] = {
     0x52, 0x55, 0x00, 0x00, 0x00, 0x00
 };
 
-static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
+static const uint8_t zero_ethaddr[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
 
 /* XXX: suppress those select globals */
 fd_set *global_readfds, *global_writefds, *global_xfds;
@@ -599,42 +599,8 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
         global_xfds = NULL;
 }
 
-#define ETH_ALEN 6
-#define ETH_HLEN 14
-
-#define ETH_P_IP       0x0800          /* Internet Protocol packet     */
-#define ETH_P_ARP      0x0806          /* Address Resolution packet    */
-
-#define        ARPOP_REQUEST   1               /* ARP request                  */
-#define        ARPOP_REPLY     2               /* ARP reply                    */
-
-struct ethhdr
-{
-       unsigned char   h_dest[ETH_ALEN];       /* destination eth addr */
-       unsigned char   h_source[ETH_ALEN];     /* source ether addr    */
-       unsigned short  h_proto;                /* packet type ID field */
-};
-
-struct arphdr
-{
-       unsigned short  ar_hrd;         /* format of hardware address   */
-       unsigned short  ar_pro;         /* format of protocol address   */
-       unsigned char   ar_hln;         /* length of hardware address   */
-       unsigned char   ar_pln;         /* length of protocol address   */
-       unsigned short  ar_op;          /* ARP opcode (command)         */
-
-        /*
-         *      Ethernet looks like this : This bit is variable sized however...
-         */
-       unsigned char           ar_sha[ETH_ALEN];       /* sender hardware address      */
-       uint32_t                ar_sip;                 /* sender IP address            */
-       unsigned char           ar_tha[ETH_ALEN];       /* target hardware address      */
-       uint32_t                ar_tip  ;               /* target IP address            */
-} __attribute__((packed));
-
 static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
 {
-    struct ethhdr *eh = (struct ethhdr *)pkt;
     struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
     uint8_t arp_reply[max(ETH_HLEN + sizeof(struct arphdr), 64)];
     struct ethhdr *reh = (struct ethhdr *)arp_reply;
@@ -645,6 +611,12 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
     ar_op = ntohs(ah->ar_op);
     switch(ar_op) {
     case ARPOP_REQUEST:
+        if (ah->ar_tip == ah->ar_sip) {
+            /* Gratuitous ARP */
+            arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
+            return;
+        }
+
         if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
             slirp->vnetwork_addr.s_addr) {
             if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
@@ -657,8 +629,8 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
             return;
         arp_ok:
             memset(arp_reply, 0, sizeof(arp_reply));
-            /* XXX: make an ARP request to have the client address */
-            memcpy(slirp->client_ethaddr, eh->h_source, ETH_ALEN);
+
+            arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
 
             /* ARP request for alias/dns mac address */
             memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
@@ -679,11 +651,7 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
         }
         break;
     case ARPOP_REPLY:
-        /* reply to request of client mac address ? */
-        if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN) &&
-            ah->ar_sip == slirp->client_ipaddr.s_addr) {
-            memcpy(slirp->client_ethaddr, ah->ar_sha, ETH_ALEN);
-        }
+        arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
         break;
     default:
         break;
@@ -724,54 +692,66 @@ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
     }
 }
 
-/* output the IP packet to the ethernet device */
-void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len)
+/* Output the IP packet to the ethernet device. Returns 0 if the packet must be
+ * re-queued.
+ */
+int if_encap(Slirp *slirp, struct mbuf *ifm)
 {
     uint8_t buf[1600];
     struct ethhdr *eh = (struct ethhdr *)buf;
+    uint8_t ethaddr[ETH_ALEN];
+    const struct ip *iph = (const struct ip *)ifm->m_data;
 
-    if (ip_data_len + ETH_HLEN > sizeof(buf))
-        return;
-    
-    if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN)) {
+    if (ifm->m_len + ETH_HLEN > sizeof(buf)) {
+        return 1;
+    }
+
+    if (!arp_table_search(slirp, iph->ip_dst.s_addr, ethaddr)) {
         uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
         struct ethhdr *reh = (struct ethhdr *)arp_req;
         struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
-        const struct ip *iph = (const struct ip *)ip_data;
-
-        /* If the client addr is not known, there is no point in
-           sending the packet to it. Normally the sender should have
-           done an ARP request to get its MAC address. Here we do it
-           in place of sending the packet and we hope that the sender
-           will retry sending its packet. */
-        memset(reh->h_dest, 0xff, ETH_ALEN);
-        memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
-        memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
-        reh->h_proto = htons(ETH_P_ARP);
-        rah->ar_hrd = htons(1);
-        rah->ar_pro = htons(ETH_P_IP);
-        rah->ar_hln = ETH_ALEN;
-        rah->ar_pln = 4;
-        rah->ar_op = htons(ARPOP_REQUEST);
-        /* source hw addr */
-        memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
-        memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
-        /* source IP */
-        rah->ar_sip = slirp->vhost_addr.s_addr;
-        /* target hw addr (none) */
-        memset(rah->ar_tha, 0, ETH_ALEN);
-        /* target IP */
-        rah->ar_tip = iph->ip_dst.s_addr;
-        slirp->client_ipaddr = iph->ip_dst;
-        slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
+
+        if (!ifm->arp_requested) {
+            /* If the client addr is not known, send an ARP request */
+            memset(reh->h_dest, 0xff, ETH_ALEN);
+            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
+            memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
+            reh->h_proto = htons(ETH_P_ARP);
+            rah->ar_hrd = htons(1);
+            rah->ar_pro = htons(ETH_P_IP);
+            rah->ar_hln = ETH_ALEN;
+            rah->ar_pln = 4;
+            rah->ar_op = htons(ARPOP_REQUEST);
+
+            /* source hw addr */
+            memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
+            memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
+
+            /* source IP */
+            rah->ar_sip = slirp->vhost_addr.s_addr;
+
+            /* target hw addr (none) */
+            memset(rah->ar_tha, 0, ETH_ALEN);
+
+            /* target IP */
+            rah->ar_tip = iph->ip_dst.s_addr;
+            slirp->client_ipaddr = iph->ip_dst;
+            slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
+            ifm->arp_requested = true;
+
+            /* Expire request and drop outgoing packet after 1 second */
+            ifm->expiration_date = qemu_get_clock_ns(rt_clock) + 1000000000ULL;
+        }
+        return 0;
     } else {
-        memcpy(eh->h_dest, slirp->client_ethaddr, ETH_ALEN);
+        memcpy(eh->h_dest, ethaddr, ETH_ALEN);
         memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
         /* XXX: not correct */
         memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
         eh->h_proto = htons(ETH_P_IP);
-        memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
-        slirp_output(slirp->opaque, buf, ip_data_len + ETH_HLEN);
+        memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
+        slirp_output(slirp->opaque, buf, ifm->m_len + ETH_HLEN);
+        return 1;
     }
 }
 
index 16bb6bae455363322f11e18893ce702f7edf2267..dcf99d5ca4c720fde188b836cc9f97f2fada36b6 100644 (file)
@@ -170,6 +170,48 @@ int inet_aton(const char *cp, struct in_addr *ia);
 /* osdep.c */
 int qemu_socket(int domain, int type, int protocol);
 
+#define ETH_ALEN 6
+#define ETH_HLEN 14
+
+#define ETH_P_IP  0x0800        /* Internet Protocol packet  */
+#define ETH_P_ARP 0x0806        /* Address Resolution packet */
+
+#define ARPOP_REQUEST 1         /* ARP request */
+#define ARPOP_REPLY   2         /* ARP reply   */
+
+struct ethhdr {
+    unsigned char  h_dest[ETH_ALEN];   /* destination eth addr */
+    unsigned char  h_source[ETH_ALEN]; /* source ether addr    */
+    unsigned short h_proto;            /* packet type ID field */
+};
+
+struct arphdr {
+    unsigned short ar_hrd;      /* format of hardware address */
+    unsigned short ar_pro;      /* format of protocol address */
+    unsigned char  ar_hln;      /* length of hardware address */
+    unsigned char  ar_pln;      /* length of protocol address */
+    unsigned short ar_op;       /* ARP opcode (command)       */
+
+    /*
+     *  Ethernet looks like this : This bit is variable sized however...
+     */
+    unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
+    uint32_t      ar_sip;           /* sender IP address       */
+    unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
+    uint32_t      ar_tip;           /* target IP address       */
+} __attribute__((packed));
+
+#define ARP_TABLE_SIZE 16
+
+typedef struct ArpTable {
+    struct arphdr table[ARP_TABLE_SIZE];
+    int next_victim;
+} ArpTable;
+
+void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]);
+
+bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
+                      uint8_t out_ethaddr[ETH_ALEN]);
 
 struct Slirp {
     QTAILQ_ENTRY(Slirp) entry;
@@ -181,9 +223,6 @@ struct Slirp {
     struct in_addr vdhcp_startaddr;
     struct in_addr vnameserver_addr;
 
-    /* ARP cache for the guest IP addresses (XXX: allow many entries) */
-    uint8_t client_ethaddr[6];
-
     struct in_addr client_ipaddr;
     char client_hostname[33];
 
@@ -227,6 +266,8 @@ struct Slirp {
     char *tftp_prefix;
     struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
 
+    ArpTable arp_table;
+
     void *opaque;
 };
 
index d3013f5cc40f6ef0d6358d664f882a1b2be158df..bd830e51490e8171aabd69d76e68e81866d76463 100644 (file)
--- a/sysemu.h
+++ b/sysemu.h
@@ -123,6 +123,9 @@ extern int no_shutdown;
 extern int semihosting_enabled;
 extern int old_param;
 extern int boot_menu;
+extern uint8_t *boot_splash_filedata;
+extern int boot_splash_filedata_size;
+extern uint8_t qemu_extra_params_fw[2];
 extern QEMUClock *rtc_clock;
 
 #define MAX_NODES 64
index 919be12a38ba211fa01ea3ebccf6a19830d48c69..c2e7bb31eff0ac4791b19847f7f1255c9cd9cffd 100644 (file)
@@ -426,7 +426,7 @@ int cpu_alpha_exec(CPUAlphaState *s);
 int cpu_alpha_signal_handler(int host_signum, void *pinfo,
                              void *puc);
 int cpu_alpha_handle_mmu_fault (CPUState *env, uint64_t address, int rw,
-                                int mmu_idx, int is_softmmu);
+                                int mmu_idx);
 #define cpu_handle_mmu_fault cpu_alpha_handle_mmu_fault
 void do_interrupt (CPUState *env);
 
diff --git a/target-alpha/exec.h b/target-alpha/exec.h
deleted file mode 100644 (file)
index afb01d3..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  Alpha emulation cpu run-time definitions for qemu.
- *
- *  Copyright (c) 2007 Jocelyn Mayer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#if !defined (__ALPHA_EXEC_H__)
-#define __ALPHA_EXEC_H__
-
-#include "config.h"
-
-#include "dyngen-exec.h"
-
-#define TARGET_LONG_BITS 64
-
-register struct CPUAlphaState *env asm(AREG0);
-
-#define FP_STATUS (env->fp_status)
-
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-#endif /* !defined (__ALPHA_EXEC_H__) */
index 7049c80d5cfc04d944bb6642b13b04471adb2572..06d2565a5cbc7b3323631288822502ddbc24830b 100644 (file)
@@ -160,7 +160,7 @@ void cpu_alpha_store_fpcr (CPUState *env, uint64_t val)
 
 #if defined(CONFIG_USER_ONLY)
 int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                                int mmu_idx, int is_softmmu)
+                                int mmu_idx)
 {
     env->exception_index = EXCP_MMFAULT;
     env->trap_arg0 = address;
@@ -316,7 +316,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 }
 
 int cpu_alpha_handle_mmu_fault(CPUState *env, target_ulong addr, int rw,
-                               int mmu_idx, int is_softmmu)
+                               int mmu_idx)
 {
     target_ulong phys;
     int prot, fail;
index 8f39154391462b79447014e5da7e0eeb541ec74c..38be2346e09e3a33721f7ac8062040a494d2e1ad 100644 (file)
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "host-utils.h"
 #include "softfloat.h"
 #include "helper.h"
 #include "qemu-timer.h"
 
+#define FP_STATUS (env->fp_status)
+
 /*****************************************************************************/
 /* Exceptions processing helpers */
 
@@ -1311,6 +1314,8 @@ void QEMU_NORETURN cpu_unassigned_access(CPUState *env1,
     dynamic_excp(EXCP_MCHK, 0);
 }
 
+#include "softmmu_exec.h"
+
 #define MMUSUFFIX _mmu
 #define ALIGNED_ONLY
 
@@ -1339,7 +1344,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (unlikely(ret != 0)) {
         do_restore_state(retaddr);
         /* Exception index and error code are already set */
index c28f76705198a3dc8badf11d56dea39429245cf3..6ab780d7ef8914989b7cb95dcb127ef1bd6883f8 100644 (file)
@@ -244,7 +244,7 @@ uint32_t do_arm_semihosting(CPUARMState *env);
 int cpu_arm_signal_handler(int host_signum, void *pinfo,
                            void *puc);
 int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw,
-                              int mmu_idx, int is_softmuu);
+                              int mmu_idx);
 #define cpu_handle_mmu_fault cpu_arm_handle_mmu_fault
 
 static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
diff --git a/target-arm/exec.h b/target-arm/exec.h
deleted file mode 100644 (file)
index 6793288..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *  ARM execution defines
- *
- *  Copyright (c) 2003 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "config.h"
-#include "dyngen-exec.h"
-
-register struct CPUARMState *env asm(AREG0);
-
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif
-
-void raise_exception(int);
index b4f699470a848c2a6bf9411ffe92e9fafc796760..8cae972344b40bd3477bec32dd1f2db3f01a4f68 100644 (file)
@@ -582,7 +582,7 @@ void do_interrupt (CPUState *env)
 }
 
 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                              int mmu_idx, int is_softmmu)
+                              int mmu_idx)
 {
     if (rw == 2) {
         env->exception_index = EXCP_PREFETCH_ABORT;
@@ -1294,7 +1294,7 @@ static inline int get_phys_addr(CPUState *env, uint32_t address,
 }
 
 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
-                              int access_type, int mmu_idx, int is_softmmu)
+                              int access_type, int mmu_idx)
 {
     uint32_t phys_addr;
     target_ulong page_size;
index 46358844c59706438fcec8154b2f4a56c42b8454..37b77e14e5ab523db033b5e13c43497bfb518578 100644 (file)
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "helper.h"
 
 #define SIGNBIT (uint32_t)0x80000000
 #define SIGNBIT64 ((uint64_t)1 << 63)
 
-void raise_exception(int tt)
+#if !defined(CONFIG_USER_ONLY)
+static void raise_exception(int tt)
 {
     env->exception_index = tt;
     cpu_loop_exit(env);
 }
+#endif
 
 uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
                           uint32_t rn, uint32_t maxindex)
@@ -52,6 +55,8 @@ uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
 
 #if !defined(CONFIG_USER_ONLY)
 
+#include "softmmu_exec.h"
+
 #define MMUSUFFIX _mmu
 
 #define SHIFT 0
@@ -81,7 +86,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (unlikely(ret)) {
         if (retaddr) {
             /* now we have a real cpu fault */
index ecb0df1d337eadfec954a41b16b3a8c7497b3f96..8ae0ce3ef329fa5b90e26400419a3207d78c5795 100644 (file)
@@ -226,7 +226,7 @@ static inline int cpu_mmu_index (CPUState *env)
 }
 
 int cpu_cris_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
-                              int mmu_idx, int is_softmmu);
+                              int mmu_idx);
 #define cpu_handle_mmu_fault cpu_cris_handle_mmu_fault
 
 #if defined(CONFIG_USER_ONLY)
diff --git a/target-cris/exec.h b/target-cris/exec.h
deleted file mode 100644 (file)
index 3294abe..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  CRIS execution defines
- *
- *  Copyright (c) 2007 AXIS Communications AB
- *  Written by Edgar E. Iglesias
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "dyngen-exec.h"
-
-register struct CPUCRISState *env asm(AREG0);
-
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif
index 962d2141774317e7c0196828de525186ab879c5b..75f0035e6e0c1d5ec760b0f026a1d7954fca0a47 100644 (file)
@@ -47,7 +47,7 @@ void do_interrupt (CPUState *env)
 }
 
 int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
-                             int mmu_idx, int is_softmmu)
+                              int mmu_idx)
 {
        env->exception_index = 0xaa;
        env->pregs[PR_EDA] = address;
@@ -68,7 +68,7 @@ static void cris_shift_ccs(CPUState *env)
 }
 
 int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                               int mmu_idx, int is_softmmu)
+                               int mmu_idx)
 {
        struct cris_mmu_result res;
        int prot, miss;
@@ -104,10 +104,9 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                 r = 0;
        }
        if (r > 0)
-               D_LOG("%s returns %d irqreq=%x addr=%x"
-                         " phy=%x ismmu=%d vec=%x pc=%x\n", 
-                         __func__, r, env->interrupt_request, 
-                         address, res.phy, is_softmmu, res.bf_vec, env->pc);
+            D_LOG("%s returns %d irqreq=%x addr=%x phy=%x vec=%x pc=%x\n",
+                  __func__, r, env->interrupt_request, address, res.phy,
+                  res.bf_vec, env->pc);
        return r;
 }
 
index b3ddd33e02253daaca6a72046b174dd36ed1dad6..0cfe1b18702004bb1826c92e06e1b78d4ae60e44 100644 (file)
@@ -18,7 +18,8 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "mmu.h"
 #include "helper.h"
 #include "host-utils.h"
@@ -35,6 +36,7 @@
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
 
 #define MMUSUFFIX _mmu
 
@@ -68,7 +70,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 
     D_LOG("%s pc=%x tpc=%x ra=%x\n", __func__, 
             env->pc, env->debug1, retaddr);
-    ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (unlikely(ret)) {
         if (retaddr) {
             /* now we have a real cpu fault */
index 9819b5fdb9977734fb1340cc9915a0aa2bd91f28..4a6f675f983a90505d1e7a959a60742e497dbbde 100644 (file)
@@ -743,6 +743,7 @@ typedef struct CPUX86State {
     uint32_t cpuid_kvm_features;
     uint32_t cpuid_svm_features;
     bool tsc_valid;
+    int tsc_khz;
     
     /* in order to simplify APIC support, we leave this pointer to the
        user */
@@ -889,7 +890,7 @@ void host_cpuid(uint32_t function, uint32_t count,
 
 /* helper.c */
 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
-                             int is_write, int mmu_idx, int is_softmmu);
+                             int is_write, int mmu_idx);
 #define cpu_handle_mmu_fault cpu_x86_handle_mmu_fault
 void cpu_x86_set_a20(CPUX86State *env, int a20_state);
 
@@ -1050,6 +1051,9 @@ void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
 /* op_helper.c */
 void do_interrupt(CPUState *env);
 void do_interrupt_x86_hardirq(CPUState *env, int intno, int is_hw);
+void QEMU_NORETURN raise_exception_env(int exception_index, CPUState *nenv);
+void QEMU_NORETURN raise_exception_err_env(CPUState *nenv, int exception_index,
+                                           int error_code);
 
 void do_smm_enter(CPUState *env1);
 
index e1ae3af1e3c5b2fc7f64d544525546bec6f6a1fa..89e9623859e165342d006a7a27073dce296397b1 100644 (file)
@@ -224,6 +224,7 @@ typedef struct x86_def_t {
     int family;
     int model;
     int stepping;
+    int tsc_khz;
     uint32_t features, ext_features, ext2_features, ext3_features;
     uint32_t kvm_features, svm_features;
     uint32_t xlevel;
@@ -704,6 +705,17 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
             } else if (!strcmp(featurestr, "model_id")) {
                 pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id),
                         val);
+            } else if (!strcmp(featurestr, "tsc_freq")) {
+                int64_t tsc_freq;
+                char *err;
+
+                tsc_freq = strtosz_suffix_unit(val, &err,
+                                               STRTOSZ_DEFSUFFIX_B, 1000);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                x86_cpu_def->tsc_khz = tsc_freq / 1000;
             } else {
                 fprintf(stderr, "unrecognized feature %s\n", featurestr);
                 goto error;
@@ -872,6 +884,7 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
     env->cpuid_svm_features = def->svm_features;
     env->cpuid_ext4_features = def->ext4_features;
     env->cpuid_xlevel2 = def->xlevel2;
+    env->tsc_khz = def->tsc_khz;
     if (!kvm_enabled()) {
         env->cpuid_features &= TCG_FEATURES;
         env->cpuid_ext_features &= TCG_EXT_FEATURES;
diff --git a/target-i386/exec.h b/target-i386/exec.h
deleted file mode 100644 (file)
index dd9bce4..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- *  i386 execution defines
- *
- *  Copyright (c) 2003 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "config.h"
-#include "dyngen-exec.h"
-
-/* XXX: factorize this mess */
-#ifdef TARGET_X86_64
-#define TARGET_LONG_BITS 64
-#else
-#define TARGET_LONG_BITS 32
-#endif
-
-#include "cpu-defs.h"
-
-register struct CPUX86State *env asm(AREG0);
-
-#include "qemu-common.h"
-#include "qemu-log.h"
-
-#include "cpu.h"
-
-/* op_helper.c */
-void QEMU_NORETURN raise_exception_err(int exception_index, int error_code);
-void QEMU_NORETURN raise_exception(int exception_index);
-void QEMU_NORETURN raise_exception_env(int exception_index, CPUState *nenv);
-
-/* n must be a constant to be efficient */
-static inline target_long lshift(target_long x, int n)
-{
-    if (n >= 0)
-        return x << n;
-    else
-        return x >> (-n);
-}
-
-#include "helper.h"
-
-#if !defined(CONFIG_USER_ONLY)
-
-#include "softmmu_exec.h"
-
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-#define RC_MASK         0xc00
-#define RC_NEAR                0x000
-#define RC_DOWN                0x400
-#define RC_UP          0x800
-#define RC_CHOP                0xc00
-
-#define MAXTAN 9223372036854775808.0
-
-/* the following deal with x86 long double-precision numbers */
-#define MAXEXPD 0x7fff
-#define EXPBIAS 16383
-#define EXPD(fp)       (fp.l.upper & 0x7fff)
-#define SIGND(fp)      ((fp.l.upper) & 0x8000)
-#define MANTD(fp)       (fp.l.lower)
-#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
-
-static inline void fpush(void)
-{
-    env->fpstt = (env->fpstt - 1) & 7;
-    env->fptags[env->fpstt] = 0; /* validate stack entry */
-}
-
-static inline void fpop(void)
-{
-    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
-    env->fpstt = (env->fpstt + 1) & 7;
-}
-
-static inline floatx80 helper_fldt(target_ulong ptr)
-{
-    CPU_LDoubleU temp;
-
-    temp.l.lower = ldq(ptr);
-    temp.l.upper = lduw(ptr + 8);
-    return temp.d;
-}
-
-static inline void helper_fstt(floatx80 f, target_ulong ptr)
-{
-    CPU_LDoubleU temp;
-
-    temp.d = f;
-    stq(ptr, temp.l.lower);
-    stw(ptr + 8, temp.l.upper);
-}
-
-#define FPUS_IE (1 << 0)
-#define FPUS_DE (1 << 1)
-#define FPUS_ZE (1 << 2)
-#define FPUS_OE (1 << 3)
-#define FPUS_UE (1 << 4)
-#define FPUS_PE (1 << 5)
-#define FPUS_SF (1 << 6)
-#define FPUS_SE (1 << 7)
-#define FPUS_B  (1 << 15)
-
-#define FPUC_EM 0x3f
-
-static inline uint32_t compute_eflags(void)
-{
-    return env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
-}
-
-/* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */
-static inline void load_eflags(int eflags, int update_mask)
-{
-    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-    DF = 1 - (2 * ((eflags >> 10) & 1));
-    env->eflags = (env->eflags & ~update_mask) |
-        (eflags & update_mask) | 0x2;
-}
-
-/* load efer and update the corresponding hflags. XXX: do consistency
-   checks with cpuid bits ? */
-static inline void cpu_load_efer(CPUState *env, uint64_t val)
-{
-    env->efer = val;
-    env->hflags &= ~(HF_LMA_MASK | HF_SVME_MASK);
-    if (env->efer & MSR_EFER_LMA)
-        env->hflags |= HF_LMA_MASK;
-    if (env->efer & MSR_EFER_SVME)
-        env->hflags |= HF_SVME_MASK;
-}
index e9be10429340cbce275ca9f72067a73cb83e3cec..f8c8633d8bd37bc0fe97c4c762de8f8e2c60db91 100644 (file)
@@ -546,7 +546,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
 #if defined(CONFIG_USER_ONLY)
 
 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
-                             int is_write, int mmu_idx, int is_softmmu)
+                             int is_write, int mmu_idx)
 {
     /* user mode only emulation */
     is_write &= 1;
@@ -573,7 +573,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
    1  = generate PF fault
 */
 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
-                             int is_write1, int mmu_idx, int is_softmmu)
+                             int is_write1, int mmu_idx)
 {
     uint64_t ptep, pte;
     target_ulong pde_addr, pte_addr;
@@ -1027,8 +1027,6 @@ int check_hw_breakpoints(CPUState *env, int force_dr6_update)
 
 static CPUDebugExcpHandler *prev_debug_excp_handler;
 
-void raise_exception_env(int exception_index, CPUState *env);
-
 static void breakpoint_handler(CPUState *env)
 {
     CPUBreakpoint *bp;
@@ -1245,8 +1243,8 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
     cpu_exec_init(env);
     env->cpu_model_str = cpu_model;
 
-    /* init various static tables */
-    if (!inited) {
+    /* init various static tables used in TCG mode */
+    if (tcg_enabled() && !inited) {
         inited = 1;
         optimize_flags_init();
 #ifndef CONFIG_USER_ONLY
index 10fb2c4b07302c80c4328b6830f2dadcd39bf80b..31b88b74997677e38d0b91419102d0ab40068129 100644 (file)
@@ -354,6 +354,7 @@ int kvm_arch_init_vcpu(CPUState *env)
     uint32_t unused;
     struct kvm_cpuid_entry2 *c;
     uint32_t signature[3];
+    int r;
 
     env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX);
 
@@ -499,7 +500,20 @@ int kvm_arch_init_vcpu(CPUState *env)
 
     qemu_add_vm_change_state_handler(cpu_update_state, env);
 
-    return kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data);
+    r = kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data);
+    if (r)
+           return r;
+
+    r = kvm_check_extension(env->kvm_state, KVM_CAP_TSC_CONTROL);
+    if (r && env->tsc_khz) {
+        r = kvm_vcpu_ioctl(env, KVM_SET_TSC_KHZ, env->tsc_khz);
+        if (r < 0) {
+            fprintf(stderr, "KVM_SET_TSC_KHZ failed\n");
+            return r;
+        }
+    }
+
+    return 0;
 }
 
 void kvm_arch_reset_vcpu(CPUState *env)
index 315e18b9a4c3f1e2e6962f433e754810574b9867..1bbc3b56dc166857c6e7716a15597fdac58485e4 100644 (file)
  */
 
 #include <math.h>
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "host-utils.h"
 #include "ioport.h"
+#include "qemu-common.h"
+#include "qemu-log.h"
+#include "cpu-defs.h"
+#include "helper.h"
 
-//#define DEBUG_PCALL
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif /* !defined(CONFIG_USER_ONLY) */
 
+//#define DEBUG_PCALL
 
 #ifdef DEBUG_PCALL
 #  define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
 #  define LOG_PCALL_STATE(env) do { } while (0)
 #endif
 
+/* n must be a constant to be efficient */
+static inline target_long lshift(target_long x, int n)
+{
+    if (n >= 0) {
+        return x << n;
+    } else {
+        return x >> (-n);
+    }
+}
+
+#define RC_MASK         0xc00
+#define RC_NEAR         0x000
+#define RC_DOWN         0x400
+#define RC_UP           0x800
+#define RC_CHOP         0xc00
+
+#define MAXTAN 9223372036854775808.0
+
+/* the following deal with x86 long double-precision numbers */
+#define MAXEXPD 0x7fff
+#define EXPBIAS 16383
+#define EXPD(fp)        (fp.l.upper & 0x7fff)
+#define SIGND(fp)       ((fp.l.upper) & 0x8000)
+#define MANTD(fp)       (fp.l.lower)
+#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
+
+static inline void fpush(void)
+{
+    env->fpstt = (env->fpstt - 1) & 7;
+    env->fptags[env->fpstt] = 0; /* validate stack entry */
+}
+
+static inline void fpop(void)
+{
+    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
+    env->fpstt = (env->fpstt + 1) & 7;
+}
+
+static inline floatx80 helper_fldt(target_ulong ptr)
+{
+    CPU_LDoubleU temp;
+
+    temp.l.lower = ldq(ptr);
+    temp.l.upper = lduw(ptr + 8);
+    return temp.d;
+}
+
+static inline void helper_fstt(floatx80 f, target_ulong ptr)
+{
+    CPU_LDoubleU temp;
+
+    temp.d = f;
+    stq(ptr, temp.l.lower);
+    stw(ptr + 8, temp.l.upper);
+}
+
+#define FPUS_IE (1 << 0)
+#define FPUS_DE (1 << 1)
+#define FPUS_ZE (1 << 2)
+#define FPUS_OE (1 << 3)
+#define FPUS_UE (1 << 4)
+#define FPUS_PE (1 << 5)
+#define FPUS_SF (1 << 6)
+#define FPUS_SE (1 << 7)
+#define FPUS_B  (1 << 15)
+
+#define FPUC_EM 0x3f
+
+static inline uint32_t compute_eflags(void)
+{
+    return env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
+}
+
+/* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */
+static inline void load_eflags(int eflags, int update_mask)
+{
+    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+    DF = 1 - (2 * ((eflags >> 10) & 1));
+    env->eflags = (env->eflags & ~update_mask) |
+        (eflags & update_mask) | 0x2;
+}
+
+/* load efer and update the corresponding hflags. XXX: do consistency
+   checks with cpuid bits ? */
+static inline void cpu_load_efer(CPUState *env, uint64_t val)
+{
+    env->efer = val;
+    env->hflags &= ~(HF_LMA_MASK | HF_SVME_MASK);
+    if (env->efer & MSR_EFER_LMA) {
+        env->hflags |= HF_LMA_MASK;
+    }
+    if (env->efer & MSR_EFER_SVME) {
+        env->hflags |= HF_SVME_MASK;
+    }
+}
 
 #if 0
 #define raise_exception_err(a, b)\
@@ -43,6 +146,9 @@ do {\
 } while (0)
 #endif
 
+static void QEMU_NORETURN raise_exception_err(int exception_index,
+                                              int error_code);
+
 static const uint8_t parity_table[256] = {
     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
@@ -1381,12 +1487,20 @@ static void QEMU_NORETURN raise_interrupt(int intno, int is_int, int error_code,
 
 /* shortcuts to generate exceptions */
 
-void raise_exception_err(int exception_index, int error_code)
+static void QEMU_NORETURN raise_exception_err(int exception_index,
+                                              int error_code)
+{
+    raise_interrupt(exception_index, 0, error_code, 0);
+}
+
+void raise_exception_err_env(CPUState *nenv, int exception_index,
+                             int error_code)
 {
+    env = nenv;
     raise_interrupt(exception_index, 0, error_code, 0);
 }
 
-void raise_exception(int exception_index)
+static void QEMU_NORETURN raise_exception(int exception_index)
 {
     raise_interrupt(exception_index, 0, 0, 0);
 }
@@ -4426,6 +4540,49 @@ void helper_frstor(target_ulong ptr, int data32)
     }
 }
 
+
+#if defined(CONFIG_USER_ONLY)
+void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
+{
+    CPUX86State *saved_env;
+
+    saved_env = env;
+    env = s;
+    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
+        selector &= 0xffff;
+        cpu_x86_load_seg_cache(env, seg_reg, selector,
+                               (selector << 4), 0xffff, 0);
+    } else {
+        helper_load_seg(seg_reg, selector);
+    }
+    env = saved_env;
+}
+
+void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
+{
+    CPUX86State *saved_env;
+
+    saved_env = env;
+    env = s;
+
+    helper_fsave(ptr, data32);
+
+    env = saved_env;
+}
+
+void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
+{
+    CPUX86State *saved_env;
+
+    saved_env = env;
+    env = s;
+
+    helper_frstor(ptr, data32);
+
+    env = saved_env;
+}
+#endif
+
 void helper_fxsave(target_ulong ptr, int data64)
 {
     int fpus, fptag, i, nb_xmm_regs;
@@ -4852,7 +5009,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
     saved_env = env;
     env = cpu_single_env;
 
-    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (ret) {
         if (retaddr) {
             /* now we have a real cpu fault */
index 876b5be2bdbdf38334168317ea28db70796d5984..037ef528ed832b30850dde38da7865a6311d731b 100644 (file)
@@ -205,7 +205,7 @@ void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value);
 #define CPU_SAVE_VERSION 1
 
 int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
-                            int mmu_idx, int is_softmmu);
+                              int mmu_idx);
 #define cpu_handle_mmu_fault cpu_lm32_handle_mmu_fault
 
 #if defined(CONFIG_USER_ONLY)
diff --git a/target-lm32/exec.h b/target-lm32/exec.h
deleted file mode 100644 (file)
index 2a227b2..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *  LatticeMico32 execution defines.
- *
- *  Copyright (c) 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "dyngen-exec.h"
-
-register struct CPULM32State *env asm(AREG0);
-
-#include "cpu.h"
-
-static inline int cpu_halted(CPUState *env)
-{
-    if (!env->halted) {
-        return 0;
-    }
-
-    /* IRQ execeptions wakes us up.  */
-    if (cpu_has_work(env)) {
-        env->halted = 0;
-        return 0;
-    }
-    return EXCP_HALTED;
-}
index e79428d8e01894e03ff1bc7f530998276f614feb..48c402e31bb77c4636125f5065ec4dbfe799ddcc 100644 (file)
@@ -26,7 +26,7 @@
 #include "host-utils.h"
 
 int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
-                               int mmu_idx, int is_softmmu)
+                              int mmu_idx)
 {
     int prot;
 
index a34cecd2951c6bcb974e38799345307b162120f4..557da6ce3842a6bc774f57f66bf40e1891a66a57 100644 (file)
@@ -1,5 +1,6 @@
 #include <assert.h>
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "helper.h"
 #include "host-utils.h"
 
@@ -86,7 +87,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
     saved_env = env;
     env = cpu_single_env;
 
-    ret = cpu_lm32_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    ret = cpu_lm32_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (unlikely(ret)) {
         if (retaddr) {
             /* now we have a real cpu fault */
index e0f9b3201476476d01ecb54a84613e495f3c6a06..0667f8214ad85239acb95627e8e96dbb3d8a0f88 100644 (file)
@@ -231,7 +231,7 @@ static inline int cpu_mmu_index (CPUState *env)
 }
 
 int cpu_m68k_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
-                              int mmu_idx, int is_softmmu);
+                              int mmu_idx);
 #define cpu_handle_mmu_fault cpu_m68k_handle_mmu_fault
 
 #if defined(CONFIG_USER_ONLY)
diff --git a/target-m68k/exec.h b/target-m68k/exec.h
deleted file mode 100644 (file)
index 93e7912..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  m68k execution defines
- *
- *  Copyright (c) 2005-2006 CodeSourcery
- *  Written by Paul Brook
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "dyngen-exec.h"
-
-register struct CPUM68KState *env asm(AREG0);
-
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif
index a936fe7b769150422fc4fa5f4af937a4921cd523..7ca75fb06d5c50a4018c21b8ddd3030a92421bb0 100644 (file)
@@ -344,7 +344,7 @@ void m68k_switch_sp(CPUM68KState *env)
 #if defined(CONFIG_USER_ONLY)
 
 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                               int mmu_idx, int is_softmmu)
+                               int mmu_idx)
 {
     env->exception_index = EXCP_ACCESS;
     env->mmu.ar = address;
@@ -362,7 +362,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 }
 
 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                               int mmu_idx, int is_softmmu)
+                               int mmu_idx)
 {
     int prot;
 
index 237fc4cb54e1245b1d02d0e5d0c46c18ed3b46f5..c66fa0cf3de1a477faba5e09f236062523e66034 100644 (file)
@@ -16,7 +16,8 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "helpers.h"
 
 #if defined(CONFIG_USER_ONLY)
@@ -34,6 +35,8 @@ void do_interrupt_m68k_hardirq(CPUState *env1)
 
 extern int semihosting_enabled;
 
+#include "softmmu_exec.h"
+
 #define MMUSUFFIX _mmu
 
 #define SHIFT 0
@@ -63,7 +66,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (unlikely(ret)) {
         if (retaddr) {
             /* now we have a real cpu fault */
index 76f4fc4a7a40145318fc3375a6b271ef2aa5772b..a81da629de6ba1aa0680e4fc1dc5d3706041a5ef 100644 (file)
@@ -309,7 +309,7 @@ static inline int cpu_mmu_index (CPUState *env)
 }
 
 int cpu_mb_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
-                            int mmu_idx, int is_softmmu);
+                            int mmu_idx);
 #define cpu_handle_mmu_fault cpu_mb_handle_mmu_fault
 
 #if defined(CONFIG_USER_ONLY)
diff --git a/target-microblaze/exec.h b/target-microblaze/exec.h
deleted file mode 100644 (file)
index 71b4d39..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  Microblaze execution defines
- *
- *  Copyright (c) 2009 Edgar E. Iglesias
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "dyngen-exec.h"
-
-register struct CPUMBState *env asm(AREG0);
-
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif
index 299259c3f0cfe687c779d31f6a300d05d7699026..2cf28022bd22b55cd4f55dffe9becb9cb44f7f5a 100644 (file)
@@ -37,7 +37,7 @@ void do_interrupt (CPUState *env)
 }
 
 int cpu_mb_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
-                             int mmu_idx, int is_softmmu)
+                            int mmu_idx)
 {
     env->exception_index = 0xaa;
     cpu_dump_state(env, stderr, fprintf, 0);
@@ -47,7 +47,7 @@ int cpu_mb_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
 #else /* !CONFIG_USER_ONLY */
 
 int cpu_mb_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                               int mmu_idx, int is_softmmu)
+                             int mmu_idx)
 {
     unsigned int hit;
     unsigned int mmu_available;
index 664ffe5990ffbcd35f7a79cdc567d835d7dfbd3a..8a7deac487315555d52d3aa350d47bb179dd89e4 100644 (file)
  */
 
 #include <assert.h>
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "helper.h"
 #include "host-utils.h"
 
 #define D(x)
 
 #if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+
 #define MMUSUFFIX _mmu
 #define SHIFT 0
 #include "softmmu_template.h"
@@ -51,7 +54,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
     saved_env = env;
     env = cpu_single_env;
 
-    ret = cpu_mb_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    ret = cpu_mb_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (unlikely(ret)) {
         if (retaddr) {
             /* now we have a real cpu fault */
index 31e8306ef30cf7b972b0ea3fd8d414d2a6dcee4d..41beb0a8e8160f1c17e1c6e87a2962dea0c6d03d 100644 (file)
@@ -1850,6 +1850,7 @@ CPUState *cpu_mb_init (const char *cpu_model)
 
     cpu_exec_init(env);
     cpu_reset(env);
+    qemu_init_vcpu(env);
     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
 
     if (tcg_initialized)
index 33be2962a24b0f809f56754420b1d5ec4698bc75..c5f70fa759d6b11edfa34d59b1992af4c3436962 100644 (file)
@@ -1,6 +1,8 @@
 #if !defined (__MIPS_CPU_H__)
 #define __MIPS_CPU_H__
 
+//#define DEBUG_OP
+
 #define TARGET_HAS_ICE 1
 
 #define ELF_MACHINE    EM_MIPS
@@ -634,7 +636,7 @@ void cpu_mips_soft_irq(CPUState *env, int irq, int level);
 
 /* helper.c */
 int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                               int mmu_idx, int is_softmmu);
+                               int mmu_idx);
 #define cpu_handle_mmu_fault cpu_mips_handle_mmu_fault
 void do_interrupt (CPUState *env);
 #if !defined(CONFIG_USER_ONLY)
diff --git a/target-mips/exec.h b/target-mips/exec.h
deleted file mode 100644 (file)
index e787e9a..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-#if !defined(__QEMU_MIPS_EXEC_H__)
-#define __QEMU_MIPS_EXEC_H__
-
-//#define DEBUG_OP
-
-#include "config.h"
-#include "mips-defs.h"
-#include "dyngen-exec.h"
-#include "cpu-defs.h"
-
-register struct CPUMIPSState *env asm(AREG0);
-
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-static inline void compute_hflags(CPUState *env)
-{
-    env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
-                     MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
-                     MIPS_HFLAG_UX);
-    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
-        !(env->CP0_Status & (1 << CP0St_ERL)) &&
-        !(env->hflags & MIPS_HFLAG_DM)) {
-        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
-    }
-#if defined(TARGET_MIPS64)
-    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
-        (env->CP0_Status & (1 << CP0St_PX)) ||
-        (env->CP0_Status & (1 << CP0St_UX)))
-        env->hflags |= MIPS_HFLAG_64;
-    if (env->CP0_Status & (1 << CP0St_UX))
-        env->hflags |= MIPS_HFLAG_UX;
-#endif
-    if ((env->CP0_Status & (1 << CP0St_CU0)) ||
-        !(env->hflags & MIPS_HFLAG_KSU))
-        env->hflags |= MIPS_HFLAG_CP0;
-    if (env->CP0_Status & (1 << CP0St_CU1))
-        env->hflags |= MIPS_HFLAG_FPU;
-    if (env->CP0_Status & (1 << CP0St_FR))
-        env->hflags |= MIPS_HFLAG_F64;
-    if (env->insn_flags & ISA_MIPS32R2) {
-        if (env->active_fpu.fcr0 & (1 << FCR0_F64))
-            env->hflags |= MIPS_HFLAG_COP1X;
-    } else if (env->insn_flags & ISA_MIPS32) {
-        if (env->hflags & MIPS_HFLAG_64)
-            env->hflags |= MIPS_HFLAG_COP1X;
-    } else if (env->insn_flags & ISA_MIPS4) {
-        /* All supported MIPS IV CPUs use the XX (CU3) to enable
-           and disable the MIPS IV extensions to the MIPS III ISA.
-           Some other MIPS IV CPUs ignore the bit, so the check here
-           would be too restrictive for them.  */
-        if (env->CP0_Status & (1 << CP0St_CU3))
-            env->hflags |= MIPS_HFLAG_COP1X;
-    }
-}
-
-#endif /* !defined(__QEMU_MIPS_EXEC_H__) */
index ecf6182f568469b04e7f6affad5e5c61048a09df..024caa23c13b935f396c880744159653493a8d54 100644 (file)
@@ -266,7 +266,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 #endif
 
 int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                               int mmu_idx, int is_softmmu)
+                               int mmu_idx)
 {
 #if !defined(CONFIG_USER_ONLY)
     target_phys_addr_t physical;
@@ -278,8 +278,8 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 #if 0
     log_cpu_state(env, 0);
 #endif
-    qemu_log("%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d mmu_idx %d smmu %d\n",
-              __func__, env->active_tc.PC, address, rw, mmu_idx, is_softmmu);
+    qemu_log("%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d mmu_idx %d\n",
+              __func__, env->active_tc.PC, address, rw, mmu_idx);
 
     rw &= 1;
 
index 01315ef0dc306f7d92ce662fef24bed71ce649e4..056011f1cc31c7b53d21504b2d0e9f4c128809ae 100644 (file)
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include <stdlib.h>
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 
 #include "host-utils.h"
 
 #include "helper.h"
 
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif /* !defined(CONFIG_USER_ONLY) */
+
 #ifndef CONFIG_USER_ONLY
 static inline void cpu_mips_tlb_flush (CPUState *env, int flush_global);
 #endif
 
+static inline void compute_hflags(CPUState *env)
+{
+    env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
+                     MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
+                     MIPS_HFLAG_UX);
+    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
+        !(env->CP0_Status & (1 << CP0St_ERL)) &&
+        !(env->hflags & MIPS_HFLAG_DM)) {
+        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
+    }
+#if defined(TARGET_MIPS64)
+    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
+        (env->CP0_Status & (1 << CP0St_PX)) ||
+        (env->CP0_Status & (1 << CP0St_UX))) {
+        env->hflags |= MIPS_HFLAG_64;
+    }
+    if (env->CP0_Status & (1 << CP0St_UX)) {
+        env->hflags |= MIPS_HFLAG_UX;
+    }
+#endif
+    if ((env->CP0_Status & (1 << CP0St_CU0)) ||
+        !(env->hflags & MIPS_HFLAG_KSU)) {
+        env->hflags |= MIPS_HFLAG_CP0;
+    }
+    if (env->CP0_Status & (1 << CP0St_CU1)) {
+        env->hflags |= MIPS_HFLAG_FPU;
+    }
+    if (env->CP0_Status & (1 << CP0St_FR)) {
+        env->hflags |= MIPS_HFLAG_F64;
+    }
+    if (env->insn_flags & ISA_MIPS32R2) {
+        if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
+            env->hflags |= MIPS_HFLAG_COP1X;
+        }
+    } else if (env->insn_flags & ISA_MIPS32) {
+        if (env->hflags & MIPS_HFLAG_64) {
+            env->hflags |= MIPS_HFLAG_COP1X;
+        }
+    } else if (env->insn_flags & ISA_MIPS4) {
+        /* All supported MIPS IV CPUs use the XX (CU3) to enable
+           and disable the MIPS IV extensions to the MIPS III ISA.
+           Some other MIPS IV CPUs ignore the bit, so the check here
+           would be too restrictive for them.  */
+        if (env->CP0_Status & (1 << CP0St_CU3)) {
+            env->hflags |= MIPS_HFLAG_COP1X;
+        }
+    }
+}
+
 /*****************************************************************************/
 /* Exceptions processing helpers */
 
@@ -1963,7 +2017,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (ret) {
         if (retaddr) {
             /* now we have a real cpu fault */
index d90336634dfc8a6950c89a2bf7bcee8de3d96c1e..024eb6f8ab97a35137260ddfa22db7d644f5495c 100644 (file)
@@ -1022,7 +1022,7 @@ void cpu_ppc_close (CPUPPCState *s);
 int cpu_ppc_signal_handler (int host_signum, void *pinfo,
                             void *puc);
 int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw,
-                              int mmu_idx, int is_softmmu);
+                              int mmu_idx);
 #define cpu_handle_mmu_fault cpu_ppc_handle_mmu_fault
 #if !defined(CONFIG_USER_ONLY)
 int get_physical_address (CPUPPCState *env, mmu_ctx_t *ctx, target_ulong vaddr,
diff --git a/target-ppc/exec.h b/target-ppc/exec.h
deleted file mode 100644 (file)
index f4453e4..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  PowerPC emulation definitions for qemu.
- *
- *  Copyright (c) 2003-2007 Jocelyn Mayer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#if !defined (__PPC_H__)
-#define __PPC_H__
-
-#include "config.h"
-
-#include "dyngen-exec.h"
-
-#include "cpu.h"
-
-register struct CPUPPCState *env asm(AREG0);
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-#endif /* !defined (__PPC_H__) */
index 176128a3e247db42f8eb76c94b291d326711f567..789e6aa325b89b975edb2cd1c777ab3dbcebdadd 100644 (file)
@@ -78,7 +78,7 @@ void (*cpu_ppc_hypercall)(CPUState *);
 
 #if defined(CONFIG_USER_ONLY)
 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                              int mmu_idx, int is_softmmu)
+                              int mmu_idx)
 {
     int exception, error_code;
 
@@ -1658,7 +1658,7 @@ static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address,
 
 /* Perform address translation */
 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                              int mmu_idx, int is_softmmu)
+                              int mmu_idx)
 {
     mmu_ctx_t ctx;
     int access_type;
@@ -3091,7 +3091,9 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model)
 
     env = qemu_mallocz(sizeof(CPUPPCState));
     cpu_exec_init(env);
-    ppc_translate_init();
+    if (tcg_enabled()) {
+        ppc_translate_init();
+    }
     env->cpu_model_str = cpu_model;
     cpu_ppc_register_internal(env, def);
 
index dde7595fda2c644dc30bb5eb9d5c5d29c9784f39..c5e0601292367cb5626eced5034533f4287695e1 100644 (file)
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include <string.h>
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "host-utils.h"
 #include "helper.h"
 
 #include "helper_regs.h"
 
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif /* !defined(CONFIG_USER_ONLY) */
+
 //#define DEBUG_OP
 //#define DEBUG_EXCEPTIONS
 //#define DEBUG_SOFTWARE_TLB
@@ -3720,7 +3725,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (unlikely(ret != 0)) {
         if (likely(retaddr)) {
             /* now we have a real cpu fault */
index d48a9b7a0c0f84420843a6273e3976289eea53cc..f8f0c82c6f126c9f85c537920d70264db50bae78 100644 (file)
@@ -280,7 +280,7 @@ void do_interrupt (CPUState *env);
 int cpu_s390x_signal_handler(int host_signum, void *pinfo,
                            void *puc);
 int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw,
-                              int mmu_idx, int is_softmuu);
+                                int mmu_idx);
 #define cpu_handle_mmu_fault cpu_s390x_handle_mmu_fault
 
 
diff --git a/target-s390x/exec.h b/target-s390x/exec.h
deleted file mode 100644 (file)
index fb73f31..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  S/390 execution defines
- *
- *  Copyright (c) 2009 Ulrich Hecht
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "dyngen-exec.h"
-
-register struct CPUS390XState *env asm(AREG0);
-
-#include "config.h"
-#include "cpu.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-static inline void regs_to_env(void)
-{
-}
-
-static inline void env_to_regs(void)
-{
-}
index 1ce7079af73f2e0e9dbb14eb62022c02cbe58b30..db88603d7e9f512d1a6c6f8c1319cf329aa49a26 100644 (file)
@@ -81,7 +81,7 @@ CPUS390XState *cpu_s390x_init(const char *cpu_model)
 
     env = qemu_mallocz(sizeof(CPUS390XState));
     cpu_exec_init(env);
-    if (!inited) {
+    if (tcg_enabled() && !inited) {
         inited = 1;
         s390x_translate_init();
     }
@@ -110,10 +110,10 @@ void do_interrupt (CPUState *env)
 }
 
 int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                              int mmu_idx, int is_softmmu)
+                                int mmu_idx)
 {
-    /* fprintf(stderr,"%s: address 0x%lx rw %d mmu_idx %d is_softmmu %d\n",
-            __FUNCTION__, address, rw, mmu_idx, is_softmmu); */
+    /* fprintf(stderr,"%s: address 0x%lx rw %d mmu_idx %d\n",
+            __FUNCTION__, address, rw, mmu_idx); */
     env->exception_index = EXCP_ADDR;
     env->__excp_addr = address; /* FIXME: find out how this works on a real machine */
     return 1;
@@ -394,14 +394,14 @@ out:
 }
 
 int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong _vaddr, int rw,
-                                int mmu_idx, int is_softmmu)
+                                int mmu_idx)
 {
     uint64_t asc = env->psw.mask & PSW_MASK_ASC;
     target_ulong vaddr, raddr;
     int prot;
 
-    DPRINTF("%s: address 0x%" PRIx64 " rw %d mmu_idx %d is_softmmu %d\n",
-            __FUNCTION__, _vaddr, rw, mmu_idx, is_softmmu);
+    DPRINTF("%s: address 0x%" PRIx64 " rw %d mmu_idx %d\n",
+            __FUNCTION__, _vaddr, rw, mmu_idx);
 
     _vaddr &= TARGET_PAGE_MASK;
     vaddr = _vaddr;
index cd33f99d21359591b605dfcbb3739e18c1503624..b3ac630a6ae4788e6be8cb462db20bafca38fea6 100644 (file)
@@ -18,7 +18,8 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "host-utils.h"
 #include "helpers.h"
 #include <string.h>
@@ -31,6 +32,7 @@
 /*****************************************************************************/
 /* Softmmu support */
 #if !defined (CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
 
 #define MMUSUFFIX _mmu
 
@@ -61,7 +63,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (unlikely(ret != 0)) {
         if (likely(retaddr)) {
             /* now we have a real cpu fault */
index 00e32f2b10bfa0e9960a07c003b32eea6a3d54fe..7d7fdde019b352cecd6a6c5129e398e98b4cc497 100644 (file)
@@ -194,7 +194,7 @@ int cpu_sh4_exec(CPUSH4State * s);
 int cpu_sh4_signal_handler(int host_signum, void *pinfo,
                            void *puc);
 int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw,
-                            int mmu_idx, int is_softmmu);
+                             int mmu_idx);
 #define cpu_handle_mmu_fault cpu_sh4_handle_mmu_fault
 void do_interrupt(CPUSH4State * env);
 
diff --git a/target-sh4/exec.h b/target-sh4/exec.h
deleted file mode 100644 (file)
index 4a6ae58..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *  SH4 emulation
- *
- *  Copyright (c) 2005 Samuel Tardieu
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef _EXEC_SH4_H
-#define _EXEC_SH4_H
-
-#include "config.h"
-#include "dyngen-exec.h"
-
-register struct CPUSH4State *env asm(AREG0);
-
-#include "cpu.h"
-
-#ifndef CONFIG_USER_ONLY
-#include "softmmu_exec.h"
-#endif
-
-#endif                         /* _EXEC_SH4_H */
index 20e9b134d6e77f11bd211a5049aebbd436c10b02..5a1e15e63da0a64e2c883c2bd305e6cb2eaf1edd 100644 (file)
@@ -34,7 +34,7 @@ void do_interrupt (CPUState *env)
 }
 
 int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
-                            int mmu_idx, int is_softmmu)
+                             int mmu_idx)
 {
     env->tea = address;
     env->exception_index = -1;
@@ -440,7 +440,7 @@ static int get_physical_address(CPUState * env, target_ulong * physical,
 }
 
 int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
-                            int mmu_idx, int is_softmmu)
+                             int mmu_idx)
 {
     target_ulong physical;
     int prot, ret, access_type;
index a932225880e5bc56190501474c39ae18ff573d51..163858f5605fe04f0a8f36ff543195cab60aef3d 100644 (file)
@@ -18,7 +18,8 @@
  */
 #include <assert.h>
 #include <stdlib.h>
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "helper.h"
 
 static void cpu_restore_state_from_retaddr(void *retaddr)
@@ -38,6 +39,7 @@ static void cpu_restore_state_from_retaddr(void *retaddr)
 }
 
 #ifndef CONFIG_USER_ONLY
+#include "softmmu_exec.h"
 
 #define MMUSUFFIX _mmu
 
@@ -62,7 +64,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (ret) {
         /* now we have a real cpu fault */
         cpu_restore_state_from_retaddr(retaddr);
index a51863cf07e24a35ce7cdbd34cba9fbb465eaf24..8654f26a4ee358f4d912cd36e201c0c1c8999b7f 100644 (file)
@@ -490,7 +490,7 @@ CPUSPARCState *cpu_sparc_init(const char *cpu_model);
 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw,
-                               int mmu_idx, int is_softmmu);
+                               int mmu_idx);
 #define cpu_handle_mmu_fault cpu_sparc_handle_mmu_fault
 target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev);
 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env);
diff --git a/target-sparc/exec.h b/target-sparc/exec.h
deleted file mode 100644 (file)
index 2395b00..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef EXEC_SPARC_H
-#define EXEC_SPARC_H 1
-#include "config.h"
-#include "dyngen-exec.h"
-
-register struct CPUSPARCState *env asm(AREG0);
-
-#include "cpu.h"
-#include "exec-all.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-#endif
index efab885b8375e6534f244d67f375c7c07aa7ceed..47110a55ce4e4baad94aa3bbaac6529c0e919809 100644 (file)
@@ -42,7 +42,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
 #if defined(CONFIG_USER_ONLY)
 
 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
-                               int mmu_idx, int is_softmmu)
+                               int mmu_idx)
 {
     if (rw & 2)
         env1->exception_index = TT_TFAULT;
@@ -212,7 +212,7 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
 
 /* Perform address translation */
 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                              int mmu_idx, int is_softmmu)
+                              int mmu_idx)
 {
     target_phys_addr_t paddr;
     target_ulong vaddr;
@@ -638,7 +638,7 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
 
 /* Perform address translation */
 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                              int mmu_idx, int is_softmmu)
+                              int mmu_idx)
 {
     target_ulong virt_addr, vaddr;
     target_phys_addr_t paddr;
index 8962e38219d682266c186d341e4d3ccdf8b69359..d1a8dd9939aed73b29c7f9db2d71ccced107f431 100644 (file)
@@ -1,8 +1,13 @@
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "host-utils.h"
 #include "helper.h"
 #include "sysemu.h"
 
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif
+
 //#define DEBUG_MMU
 //#define DEBUG_MXCC
 //#define DEBUG_UNALIGNED
@@ -4232,7 +4237,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
     saved_env = env;
     env = cpu_single_env;
 
-    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (ret) {
         cpu_restore_state2(retaddr);
         cpu_loop_exit(env);
@@ -4247,13 +4252,8 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 static void do_unassigned_access(target_phys_addr_t addr, int is_write,
                                  int is_exec, int is_asi, int size)
 {
-    CPUState *saved_env;
     int fault_type;
 
-    /* XXX: hack to restore env in all cases, even if not called from
-       generated code */
-    saved_env = env;
-    env = cpu_single_env;
 #ifdef DEBUG_UNASSIGNED
     if (is_asi)
         printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
@@ -4301,8 +4301,6 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
     if (env->mmuregs[0] & MMU_NF) {
         tlb_flush(env, 1);
     }
-
-    env = saved_env;
 }
 #endif
 #else
@@ -4314,13 +4312,6 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
                                  int is_exec, int is_asi, int size)
 #endif
 {
-    CPUState *saved_env;
-
-    /* XXX: hack to restore env in all cases, even if not called from
-       generated code */
-    saved_env = env;
-    env = cpu_single_env;
-
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
            "\n", addr, env->pc);
@@ -4330,8 +4321,6 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
         raise_exception(TT_CODE_ACCESS);
     else
         raise_exception(TT_DATA_ACCESS);
-
-    env = saved_env;
 }
 #endif
 
@@ -4365,7 +4354,14 @@ void helper_tick_set_limit(void *opaque, uint64_t limit)
 void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
                            int is_write, int is_exec, int is_asi, int size)
 {
+    CPUState *saved_env;
+
+    saved_env = env;
     env = env1;
-    do_unassigned_access(addr, is_write, is_exec, is_asi, size);
+    /* Ignore unassigned accesses outside of CPU context */
+    if (env1) {
+        do_unassigned_access(addr, is_write, is_exec, is_asi, size);
+    }
+    env = saved_env;
 }
 #endif
index 15967c551a9e80758666e891208c570037970039..dee67b334f7209f99659cca82a62d1718edd778e 100644 (file)
@@ -1286,7 +1286,6 @@ static inline void gen_cond_reg(TCGv r_dst, int cond, TCGv r_src)
 }
 #endif
 
-/* XXX: potentially incorrect if dynamic npc */
 static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
                       TCGv r_cond)
 {
@@ -1321,13 +1320,17 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
         } else {
             dc->pc = dc->npc;
             dc->jump_pc[0] = target;
-            dc->jump_pc[1] = dc->npc + 4;
-            dc->npc = JUMP_PC;
+            if (unlikely(dc->npc == DYNAMIC_PC)) {
+                dc->jump_pc[1] = DYNAMIC_PC;
+                tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
+            } else {
+                dc->jump_pc[1] = dc->npc + 4;
+                dc->npc = JUMP_PC;
+            }
         }
     }
 }
 
-/* XXX: potentially incorrect if dynamic npc */
 static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
                       TCGv r_cond)
 {
@@ -1362,14 +1365,18 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
         } else {
             dc->pc = dc->npc;
             dc->jump_pc[0] = target;
-            dc->jump_pc[1] = dc->npc + 4;
-            dc->npc = JUMP_PC;
+            if (unlikely(dc->npc == DYNAMIC_PC)) {
+                dc->jump_pc[1] = DYNAMIC_PC;
+                tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
+            } else {
+                dc->jump_pc[1] = dc->npc + 4;
+                dc->npc = JUMP_PC;
+            }
         }
     }
 }
 
 #ifdef TARGET_SPARC64
-/* XXX: potentially incorrect if dynamic npc */
 static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
                           TCGv r_cond, TCGv r_reg)
 {
@@ -1384,8 +1391,13 @@ static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
     } else {
         dc->pc = dc->npc;
         dc->jump_pc[0] = target;
-        dc->jump_pc[1] = dc->npc + 4;
-        dc->npc = JUMP_PC;
+        if (unlikely(dc->npc == DYNAMIC_PC)) {
+            dc->jump_pc[1] = DYNAMIC_PC;
+            tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
+        } else {
+            dc->jump_pc[1] = dc->npc + 4;
+            dc->npc = JUMP_PC;
+        }
     }
 }
 
@@ -1558,6 +1570,13 @@ static int gen_trap_ifnofpu(DisasContext *dc, TCGv r_cond)
     return 0;
 }
 
+static inline void gen_update_fprs_dirty(int rd)
+{
+#if defined(TARGET_SPARC64)
+    tcg_gen_ori_i32(cpu_fprs, cpu_fprs, (rd < 32) ? 1 : 2);
+#endif
+}
+
 static inline void gen_op_clear_ieee_excp_and_FTT(void)
 {
     tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK);
@@ -2351,12 +2370,15 @@ static void disas_sparc_insn(DisasContext * dc)
                 switch (xop) {
                 case 0x1: /* fmovs */
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x5: /* fnegs */
                     gen_helper_fnegs(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x9: /* fabss */
                     gen_helper_fabss(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x29: /* fsqrts */
                     CHECK_FPU_FEATURE(dc, FSQRT);
@@ -2364,6 +2386,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsqrts(cpu_tmp32, cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x2a: /* fsqrtd */
                     CHECK_FPU_FEATURE(dc, FSQRT);
@@ -2372,6 +2395,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsqrtd();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x2b: /* fsqrtq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2380,12 +2404,14 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsqrtq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x41: /* fadds */
                     gen_clear_float_exceptions();
                     gen_helper_fadds(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x42: /* faddd */
                     gen_op_load_fpr_DT0(DFPREG(rs1));
@@ -2394,6 +2420,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_faddd();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x43: /* faddq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2403,12 +2430,14 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_faddq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x45: /* fsubs */
                     gen_clear_float_exceptions();
                     gen_helper_fsubs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x46: /* fsubd */
                     gen_op_load_fpr_DT0(DFPREG(rs1));
@@ -2417,6 +2446,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsubd();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x47: /* fsubq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2426,6 +2456,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsubq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x49: /* fmuls */
                     CHECK_FPU_FEATURE(dc, FMUL);
@@ -2433,6 +2464,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fmuls(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x4a: /* fmuld */
                     CHECK_FPU_FEATURE(dc, FMUL);
@@ -2442,6 +2474,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fmuld();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x4b: /* fmulq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2452,12 +2485,14 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fmulq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x4d: /* fdivs */
                     gen_clear_float_exceptions();
                     gen_helper_fdivs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x4e: /* fdivd */
                     gen_op_load_fpr_DT0(DFPREG(rs1));
@@ -2466,6 +2501,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdivd();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x4f: /* fdivq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2475,6 +2511,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdivq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x69: /* fsmuld */
                     CHECK_FPU_FEATURE(dc, FSMULD);
@@ -2482,6 +2519,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsmuld(cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x6e: /* fdmulq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2491,12 +2529,14 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdmulq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xc4: /* fitos */
                     gen_clear_float_exceptions();
                     gen_helper_fitos(cpu_tmp32, cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xc6: /* fdtos */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2504,6 +2544,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdtos(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xc7: /* fqtos */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2512,14 +2553,17 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fqtos(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xc8: /* fitod */
                     gen_helper_fitod(cpu_fpr[rs2]);
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xc9: /* fstod */
                     gen_helper_fstod(cpu_fpr[rs2]);
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xcb: /* fqtod */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2528,28 +2572,33 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fqtod();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xcc: /* fitoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_helper_fitoq(cpu_fpr[rs2]);
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xcd: /* fstoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_helper_fstoq(cpu_fpr[rs2]);
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xce: /* fdtoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fdtoq();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xd1: /* fstoi */
                     gen_clear_float_exceptions();
                     gen_helper_fstoi(cpu_tmp32, cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xd2: /* fdtoi */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2557,6 +2606,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdtoi(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xd3: /* fqtoi */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2565,12 +2615,14 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fqtoi(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
 #ifdef TARGET_SPARC64
                 case 0x2: /* V9 fmovd */
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x3: /* V9 fmovq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2581,34 +2633,40 @@ static void disas_sparc_insn(DisasContext * dc)
                                     cpu_fpr[QFPREG(rs2) + 2]);
                     tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3],
                                     cpu_fpr[QFPREG(rs2) + 3]);
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x6: /* V9 fnegd */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fnegd();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x7: /* V9 fnegq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_helper_fnegq();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xa: /* V9 fabsd */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fabsd();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xb: /* V9 fabsq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_helper_fabsq();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x81: /* V9 fstox */
                     gen_clear_float_exceptions();
                     gen_helper_fstox(cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x82: /* V9 fdtox */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2616,6 +2674,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdtox();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x83: /* V9 fqtox */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2624,6 +2683,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fqtox();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x84: /* V9 fxtos */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2631,6 +2691,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fxtos(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x88: /* V9 fxtod */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2638,6 +2699,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fxtod();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x8c: /* V9 fxtoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2646,6 +2708,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fxtoq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
 #endif
                 default:
@@ -2672,6 +2735,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
                                        0, l1);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     gen_set_label(l1);
                     break;
                 } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
@@ -2684,6 +2748,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                        0, l1);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     gen_set_label(l1);
                     break;
                 } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
@@ -2699,6 +2764,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 1], cpu_fpr[QFPREG(rs2) + 1]);
                     tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 2], cpu_fpr[QFPREG(rs2) + 2]);
                     tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3], cpu_fpr[QFPREG(rs2) + 3]);
+                    gen_update_fprs_dirty(QFPREG(rd));
                     gen_set_label(l1);
                     break;
                 }
@@ -2717,6 +2783,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                            0, l1);                      \
                         tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);     \
+                        gen_update_fprs_dirty(rd);                      \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2735,6 +2802,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                         cpu_fpr[DFPREG(rs2)]);          \
                         tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],        \
                                         cpu_fpr[DFPREG(rs2) + 1]);      \
+                        gen_update_fprs_dirty(DFPREG(rd));              \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2757,6 +2825,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                         cpu_fpr[QFPREG(rs2) + 2]);      \
                         tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3],        \
                                         cpu_fpr[QFPREG(rs2) + 3]);      \
+                        gen_update_fprs_dirty(QFPREG(rd));              \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2815,6 +2884,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                            0, l1);                      \
                         tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);     \
+                        gen_update_fprs_dirty(rd);                      \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2833,6 +2903,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                         cpu_fpr[DFPREG(rs2)]);          \
                         tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],        \
                                         cpu_fpr[DFPREG(rs2) + 1]);      \
+                        gen_update_fprs_dirty(DFPREG(rd));              \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2855,6 +2926,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                         cpu_fpr[QFPREG(rs2) + 2]);      \
                         tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3],        \
                                         cpu_fpr[QFPREG(rs2) + 3]);      \
+                        gen_update_fprs_dirty(QFPREG(rd));              \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -3848,6 +3920,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8x16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x033: /* VIS I fmul8x16au */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3855,6 +3928,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8x16au();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x035: /* VIS I fmul8x16al */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3862,6 +3936,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8x16al();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x036: /* VIS I fmul8sux16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3869,6 +3944,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8sux16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x037: /* VIS I fmul8ulx16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3876,6 +3952,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8ulx16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x038: /* VIS I fmuld8sux16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3883,6 +3960,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmuld8sux16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x039: /* VIS I fmuld8ulx16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3890,6 +3968,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmuld8ulx16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x03a: /* VIS I fpack32 */
                 case 0x03b: /* VIS I fpack16 */
@@ -3903,6 +3982,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_faligndata();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x04b: /* VIS I fpmerge */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3910,6 +3990,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpmerge();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x04c: /* VIS II bshuffle */
                     // XXX
@@ -3920,6 +4001,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fexpand();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x050: /* VIS I fpadd16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3927,11 +4009,13 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpadd16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x051: /* VIS I fpadd16s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_helper_fpadd16s(cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x052: /* VIS I fpadd32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3939,11 +4023,13 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpadd32();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x053: /* VIS I fpadd32s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_helper_fpadd32s(cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x054: /* VIS I fpsub16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3951,11 +4037,13 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpsub16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x055: /* VIS I fpsub16s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_helper_fpsub16s(cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x056: /* VIS I fpsub32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3963,31 +4051,38 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpsub32();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x057: /* VIS I fpsub32s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_helper_fpsub32s(cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x060: /* VIS I fzero */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_movi_i32(cpu_fpr[DFPREG(rd)], 0);
                     tcg_gen_movi_i32(cpu_fpr[DFPREG(rd) + 1], 0);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x061: /* VIS I fzeros */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_movi_i32(cpu_fpr[rd], 0);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x062: /* VIS I fnor */
                     CHECK_FPU_FEATURE(dc, VIS1);
-                    tcg_gen_nor_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1)],
+                    tcg_gen_nor_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)],
                                     cpu_fpr[DFPREG(rs2)]);
-                    tcg_gen_nor_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1) + 1],
+                    tcg_gen_nor_i32(cpu_fpr[DFPREG(rd) + 1],
+                                    cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x063: /* VIS I fnors */
                     CHECK_FPU_FEATURE(dc, VIS1);
-                    tcg_gen_nor_i32(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
+                    tcg_gen_nor_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x064: /* VIS I fandnot2 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3996,20 +4091,24 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_andc_i32(cpu_fpr[DFPREG(rd) + 1],
                                      cpu_fpr[DFPREG(rs1) + 1],
                                      cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x065: /* VIS I fandnot2s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_andc_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x066: /* VIS I fnot2 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_not_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]);
                     tcg_gen_not_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x067: /* VIS I fnot2s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_not_i32(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x068: /* VIS I fandnot1 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4018,20 +4117,24 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_andc_i32(cpu_fpr[DFPREG(rd) + 1],
                                      cpu_fpr[DFPREG(rs2) + 1],
                                      cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x069: /* VIS I fandnot1s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_andc_i32(cpu_fpr[rd], cpu_fpr[rs2], cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x06a: /* VIS I fnot1 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_not_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)]);
                     tcg_gen_not_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x06b: /* VIS I fnot1s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_not_i32(cpu_fpr[rd], cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x06c: /* VIS I fxor */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4040,21 +4143,26 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_xor_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x06d: /* VIS I fxors */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_xor_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x06e: /* VIS I fnand */
                     CHECK_FPU_FEATURE(dc, VIS1);
-                    tcg_gen_nand_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1)],
+                    tcg_gen_nand_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)],
                                      cpu_fpr[DFPREG(rs2)]);
-                    tcg_gen_nand_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1) + 1],
+                    tcg_gen_nand_i32(cpu_fpr[DFPREG(rd) + 1],
+                                     cpu_fpr[DFPREG(rs1) + 1],
                                      cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x06f: /* VIS I fnands */
                     CHECK_FPU_FEATURE(dc, VIS1);
-                    tcg_gen_nand_i32(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
+                    tcg_gen_nand_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x070: /* VIS I fand */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4063,10 +4171,12 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_and_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x071: /* VIS I fands */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_and_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x072: /* VIS I fxnor */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4076,21 +4186,25 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_xori_i32(cpu_tmp32, cpu_fpr[DFPREG(rs2) + 1], -1);
                     tcg_gen_xor_i32(cpu_fpr[DFPREG(rd) + 1], cpu_tmp32,
                                     cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x073: /* VIS I fxnors */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_xori_i32(cpu_tmp32, cpu_fpr[rs2], -1);
                     tcg_gen_xor_i32(cpu_fpr[rd], cpu_tmp32, cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x074: /* VIS I fsrc1 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)]);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x075: /* VIS I fsrc1s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x076: /* VIS I fornot2 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4099,19 +4213,23 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_orc_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x077: /* VIS I fornot2s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_orc_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x078: /* VIS I fsrc2 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs2));
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x079: /* VIS I fsrc2s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x07a: /* VIS I fornot1 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4120,10 +4238,12 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_orc_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x07b: /* VIS I fornot1s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_orc_i32(cpu_fpr[rd], cpu_fpr[rs2], cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x07c: /* VIS I for */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4132,19 +4252,23 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_or_i32(cpu_fpr[DFPREG(rd) + 1],
                                    cpu_fpr[DFPREG(rs1) + 1],
                                    cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x07d: /* VIS I fors */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_or_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x07e: /* VIS I fone */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_movi_i32(cpu_fpr[DFPREG(rd)], -1);
                     tcg_gen_movi_i32(cpu_fpr[DFPREG(rd) + 1], -1);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x07f: /* VIS I fones */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_movi_i32(cpu_fpr[rd], -1);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x080: /* VIS I shutdown */
                 case 0x081: /* VIS II siam */
@@ -4490,6 +4614,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     }
                     save_state(dc, cpu_cond);
                     gen_ldf_asi(cpu_addr, insn, 4, rd);
+                    gen_update_fprs_dirty(rd);
                     goto skip_move;
                 case 0x33: /* V9 lddfa */
                     if (gen_trap_ifnofpu(dc, cpu_cond)) {
@@ -4497,6 +4622,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     }
                     save_state(dc, cpu_cond);
                     gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     goto skip_move;
                 case 0x3d: /* V9 prefetcha, no effect */
                     goto skip_move;
@@ -4507,6 +4633,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     }
                     save_state(dc, cpu_cond);
                     gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     goto skip_move;
 #endif
                 default:
@@ -4525,6 +4652,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
                     tcg_gen_trunc_tl_i32(cpu_fpr[rd], cpu_tmp0);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x21:      /* ldfsr, V9 ldxfsr */
 #ifdef TARGET_SPARC64
@@ -4554,6 +4682,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         gen_helper_ldqf(cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                         gen_op_store_QT0_fpr(QFPREG(rd));
+                        gen_update_fprs_dirty(QFPREG(rd));
                     }
                     break;
                 case 0x23:      /* lddf, load double fpreg */
@@ -4565,6 +4694,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         gen_helper_lddf(cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                         gen_op_store_DT0_fpr(DFPREG(rd));
+                        gen_update_fprs_dirty(DFPREG(rd));
                     }
                     break;
                 default:
index 981760734f2f52e8e561e277df48df5e2f20b285..b4e72cfa6e390db820195623cfb80df551a4491a 100644 (file)
@@ -130,7 +130,7 @@ CPUState *uc32_cpu_init(const char *cpu_model);
 int uc32_cpu_exec(CPUState *s);
 int uc32_cpu_signal_handler(int host_signum, void *pinfo, void *puc);
 int uc32_cpu_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
-                              int mmu_idx, int is_softmuu);
+                              int mmu_idx);
 
 #define CPU_SAVE_VERSION 2
 
diff --git a/target-unicore32/exec.h b/target-unicore32/exec.h
deleted file mode 100644 (file)
index 7912105..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  UniCore32 execution defines
- *
- * Copyright (C) 2010-2011 GUAN Xue-tao
- *
- * 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.
- */
-#ifndef __UC32_EXEC_H__
-#define __UC32_EXEC_H__
-
-#include "config.h"
-#include "dyngen-exec.h"
-
-register struct CPUState_UniCore32 *env asm(AREG0);
-
-#include "cpu.h"
-
-static inline void env_to_regs(void)
-{
-}
-
-static inline void regs_to_env(void)
-{
-}
-
-static inline int cpu_halted(CPUState *env)
-{
-    if (!env->halted) {
-        return 0;
-    }
-    /* An interrupt wakes the CPU even if the I and R ASR bits are
-       set.  We use EXITTB to silently wake CPU without causing an
-       actual interrupt.  */
-    if (cpu_has_work(env)) {
-        env->halted = 0;
-        return 0;
-    }
-    return EXCP_HALTED;
-}
-
-#endif /* __UC32_EXEC_H__ */
index 02707d5857bfa586f1f096d0b9431db93aa78022..8edfcb75bef5cf94542563ba817d3ae24848128a 100644 (file)
@@ -104,7 +104,7 @@ void do_interrupt(CPUState *env)
 }
 
 int uc32_cpu_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
-                              int mmu_idx, int is_softmmu)
+                              int mmu_idx)
 {
     env->exception_index = UC32_EXCP_TRAP;
     env->cp0.c4_faultaddr = address;
index 541e6f099d71c489bd99e2023688dc84b915d19e..6cf5255b264735127dbee691f46462343be51200 100644 (file)
@@ -7,7 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "helper.h"
 
 #define SIGNBIT (uint32_t)0x80000000
diff --git a/tcg/optimize.c b/tcg/optimize.c
new file mode 100644 (file)
index 0000000..7eb5eb1
--- /dev/null
@@ -0,0 +1,678 @@
+/*
+ * Optimizations for Tiny Code Generator for QEMU
+ *
+ * Copyright (c) 2010 Samsung Electronics.
+ * Contributed by Kirill Batuzov <batuzovk@ispras.ru>
+ *
+ * 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 "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "qemu-common.h"
+#include "tcg-op.h"
+
+#if TCG_TARGET_REG_BITS == 64
+#define CASE_OP_32_64(x)                        \
+        glue(glue(case INDEX_op_, x), _i32):    \
+        glue(glue(case INDEX_op_, x), _i64)
+#else
+#define CASE_OP_32_64(x)                        \
+        glue(glue(case INDEX_op_, x), _i32)
+#endif
+
+typedef enum {
+    TCG_TEMP_UNDEF = 0,
+    TCG_TEMP_CONST,
+    TCG_TEMP_COPY,
+    TCG_TEMP_HAS_COPY,
+    TCG_TEMP_ANY
+} tcg_temp_state;
+
+struct tcg_temp_info {
+    tcg_temp_state state;
+    uint16_t prev_copy;
+    uint16_t next_copy;
+    tcg_target_ulong val;
+};
+
+static struct tcg_temp_info temps[TCG_MAX_TEMPS];
+
+/* Reset TEMP's state to TCG_TEMP_ANY.  If TEMP was a representative of some
+   class of equivalent temp's, a new representative should be chosen in this
+   class. */
+static void reset_temp(TCGArg temp, int nb_temps, int nb_globals)
+{
+    int i;
+    TCGArg new_base = (TCGArg)-1;
+    if (temps[temp].state == TCG_TEMP_HAS_COPY) {
+        for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) {
+            if (i >= nb_globals) {
+                temps[i].state = TCG_TEMP_HAS_COPY;
+                new_base = i;
+                break;
+            }
+        }
+        for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) {
+            if (new_base == (TCGArg)-1) {
+                temps[i].state = TCG_TEMP_ANY;
+            } else {
+                temps[i].val = new_base;
+            }
+        }
+        temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
+        temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
+    } else if (temps[temp].state == TCG_TEMP_COPY) {
+        temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
+        temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
+        new_base = temps[temp].val;
+    }
+    temps[temp].state = TCG_TEMP_ANY;
+    if (new_base != (TCGArg)-1 && temps[new_base].next_copy == new_base) {
+        temps[new_base].state = TCG_TEMP_ANY;
+    }
+}
+
+static int op_bits(int op)
+{
+    switch (op) {
+    case INDEX_op_mov_i32:
+    case INDEX_op_add_i32:
+    case INDEX_op_sub_i32:
+    case INDEX_op_mul_i32:
+    case INDEX_op_and_i32:
+    case INDEX_op_or_i32:
+    case INDEX_op_xor_i32:
+    case INDEX_op_shl_i32:
+    case INDEX_op_shr_i32:
+    case INDEX_op_sar_i32:
+#ifdef TCG_TARGET_HAS_rot_i32
+    case INDEX_op_rotl_i32:
+    case INDEX_op_rotr_i32:
+#endif
+#ifdef TCG_TARGET_HAS_not_i32
+    case INDEX_op_not_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext8s_i32
+    case INDEX_op_ext8s_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext16s_i32
+    case INDEX_op_ext16s_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext8u_i32
+    case INDEX_op_ext8u_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext16u_i32
+    case INDEX_op_ext16u_i32:
+#endif
+        return 32;
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_mov_i64:
+    case INDEX_op_add_i64:
+    case INDEX_op_sub_i64:
+    case INDEX_op_mul_i64:
+    case INDEX_op_and_i64:
+    case INDEX_op_or_i64:
+    case INDEX_op_xor_i64:
+    case INDEX_op_shl_i64:
+    case INDEX_op_shr_i64:
+    case INDEX_op_sar_i64:
+#ifdef TCG_TARGET_HAS_rot_i64
+    case INDEX_op_rotl_i64:
+    case INDEX_op_rotr_i64:
+#endif
+#ifdef TCG_TARGET_HAS_not_i64
+    case INDEX_op_not_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext8s_i64
+    case INDEX_op_ext8s_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext16s_i64
+    case INDEX_op_ext16s_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext32s_i64
+    case INDEX_op_ext32s_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext8u_i64
+    case INDEX_op_ext8u_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext16u_i64
+    case INDEX_op_ext16u_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext32u_i64
+    case INDEX_op_ext32u_i64:
+#endif
+        return 64;
+#endif
+    default:
+        fprintf(stderr, "Unrecognized operation %d in op_bits.\n", op);
+        tcg_abort();
+    }
+}
+
+static int op_to_movi(int op)
+{
+    switch (op_bits(op)) {
+    case 32:
+        return INDEX_op_movi_i32;
+#if TCG_TARGET_REG_BITS == 64
+    case 64:
+        return INDEX_op_movi_i64;
+#endif
+    default:
+        fprintf(stderr, "op_to_movi: unexpected return value of "
+                "function op_bits.\n");
+        tcg_abort();
+    }
+}
+
+static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args, TCGArg dst,
+                            TCGArg src, int nb_temps, int nb_globals)
+{
+        reset_temp(dst, nb_temps, nb_globals);
+        assert(temps[src].state != TCG_TEMP_COPY);
+        /* Don't try to copy if one of temps is a global or either one
+           is local and another is register */
+        if (src >= nb_globals && dst >= nb_globals &&
+            tcg_arg_is_local(s, src) == tcg_arg_is_local(s, dst)) {
+            assert(temps[src].state != TCG_TEMP_CONST);
+            if (temps[src].state != TCG_TEMP_HAS_COPY) {
+                temps[src].state = TCG_TEMP_HAS_COPY;
+                temps[src].next_copy = src;
+                temps[src].prev_copy = src;
+            }
+            temps[dst].state = TCG_TEMP_COPY;
+            temps[dst].val = src;
+            temps[dst].next_copy = temps[src].next_copy;
+            temps[dst].prev_copy = src;
+            temps[temps[dst].next_copy].prev_copy = dst;
+            temps[src].next_copy = dst;
+        }
+        gen_args[0] = dst;
+        gen_args[1] = src;
+}
+
+static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val,
+                             int nb_temps, int nb_globals)
+{
+        reset_temp(dst, nb_temps, nb_globals);
+        temps[dst].state = TCG_TEMP_CONST;
+        temps[dst].val = val;
+        gen_args[0] = dst;
+        gen_args[1] = val;
+}
+
+static int op_to_mov(int op)
+{
+    switch (op_bits(op)) {
+    case 32:
+        return INDEX_op_mov_i32;
+#if TCG_TARGET_REG_BITS == 64
+    case 64:
+        return INDEX_op_mov_i64;
+#endif
+    default:
+        fprintf(stderr, "op_to_mov: unexpected return value of "
+                "function op_bits.\n");
+        tcg_abort();
+    }
+}
+
+static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
+{
+    switch (op) {
+    CASE_OP_32_64(add):
+        return x + y;
+
+    CASE_OP_32_64(sub):
+        return x - y;
+
+    CASE_OP_32_64(mul):
+        return x * y;
+
+    CASE_OP_32_64(and):
+        return x & y;
+
+    CASE_OP_32_64(or):
+        return x | y;
+
+    CASE_OP_32_64(xor):
+        return x ^ y;
+
+    case INDEX_op_shl_i32:
+        return (uint32_t)x << (uint32_t)y;
+
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_shl_i64:
+        return (uint64_t)x << (uint64_t)y;
+#endif
+
+    case INDEX_op_shr_i32:
+        return (uint32_t)x >> (uint32_t)y;
+
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_shr_i64:
+        return (uint64_t)x >> (uint64_t)y;
+#endif
+
+    case INDEX_op_sar_i32:
+        return (int32_t)x >> (int32_t)y;
+
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_sar_i64:
+        return (int64_t)x >> (int64_t)y;
+#endif
+
+#ifdef TCG_TARGET_HAS_rot_i32
+    case INDEX_op_rotr_i32:
+#if TCG_TARGET_REG_BITS == 64
+        x &= 0xffffffff;
+        y &= 0xffffffff;
+#endif
+        x = (x << (32 - y)) | (x >> y);
+        return x;
+#endif
+
+#ifdef TCG_TARGET_HAS_rot_i64
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_rotr_i64:
+        x = (x << (64 - y)) | (x >> y);
+        return x;
+#endif
+#endif
+
+#ifdef TCG_TARGET_HAS_rot_i32
+    case INDEX_op_rotl_i32:
+#if TCG_TARGET_REG_BITS == 64
+        x &= 0xffffffff;
+        y &= 0xffffffff;
+#endif
+        x = (x << y) | (x >> (32 - y));
+        return x;
+#endif
+
+#ifdef TCG_TARGET_HAS_rot_i64
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_rotl_i64:
+        x = (x << y) | (x >> (64 - y));
+        return x;
+#endif
+#endif
+
+#if defined(TCG_TARGET_HAS_not_i32) || defined(TCG_TARGET_HAS_not_i64)
+#ifdef TCG_TARGET_HAS_not_i32
+    case INDEX_op_not_i32:
+#endif
+#ifdef TCG_TARGET_HAS_not_i64
+    case INDEX_op_not_i64:
+#endif
+        return ~x;
+#endif
+
+#if defined(TCG_TARGET_HAS_ext8s_i32) || defined(TCG_TARGET_HAS_ext8s_i64)
+#ifdef TCG_TARGET_HAS_ext8s_i32
+    case INDEX_op_ext8s_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext8s_i64
+    case INDEX_op_ext8s_i64:
+#endif
+        return (int8_t)x;
+#endif
+
+#if defined(TCG_TARGET_HAS_ext16s_i32) || defined(TCG_TARGET_HAS_ext16s_i64)
+#ifdef TCG_TARGET_HAS_ext16s_i32
+    case INDEX_op_ext16s_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext16s_i64
+    case INDEX_op_ext16s_i64:
+#endif
+        return (int16_t)x;
+#endif
+
+#if defined(TCG_TARGET_HAS_ext8u_i32) || defined(TCG_TARGET_HAS_ext8u_i64)
+#ifdef TCG_TARGET_HAS_ext8u_i32
+    case INDEX_op_ext8u_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext8u_i64
+    case INDEX_op_ext8u_i64:
+#endif
+        return (uint8_t)x;
+#endif
+
+#if defined(TCG_TARGET_HAS_ext16u_i32) || defined(TCG_TARGET_HAS_ext16u_i64)
+#ifdef TCG_TARGET_HAS_ext16u_i32
+    case INDEX_op_ext16u_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext16u_i64
+    case INDEX_op_ext16u_i64:
+#endif
+        return (uint16_t)x;
+#endif
+
+#if TCG_TARGET_REG_BITS == 64
+#ifdef TCG_TARGET_HAS_ext32s_i64
+    case INDEX_op_ext32s_i64:
+        return (int32_t)x;
+#endif
+
+#ifdef TCG_TARGET_HAS_ext32u_i64
+    case INDEX_op_ext32u_i64:
+        return (uint32_t)x;
+#endif
+#endif
+
+    default:
+        fprintf(stderr,
+                "Unrecognized operation %d in do_constant_folding.\n", op);
+        tcg_abort();
+    }
+}
+
+static TCGArg do_constant_folding(int op, TCGArg x, TCGArg y)
+{
+    TCGArg res = do_constant_folding_2(op, x, y);
+#if TCG_TARGET_REG_BITS == 64
+    if (op_bits(op) == 32) {
+        res &= 0xffffffff;
+    }
+#endif
+    return res;
+}
+
+/* Propagate constants and copies, fold constant expressions. */
+static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
+                                    TCGArg *args, TCGOpDef *tcg_op_defs)
+{
+    int i, nb_ops, op_index, op, nb_temps, nb_globals, nb_call_args;
+    const TCGOpDef *def;
+    TCGArg *gen_args;
+    TCGArg tmp;
+    /* Array VALS has an element for each temp.
+       If this temp holds a constant then its value is kept in VALS' element.
+       If this temp is a copy of other ones then this equivalence class'
+       representative is kept in VALS' element.
+       If this temp is neither copy nor constant then corresponding VALS'
+       element is unused. */
+
+    nb_temps = s->nb_temps;
+    nb_globals = s->nb_globals;
+    memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
+
+    nb_ops = tcg_opc_ptr - gen_opc_buf;
+    gen_args = args;
+    for (op_index = 0; op_index < nb_ops; op_index++) {
+        op = gen_opc_buf[op_index];
+        def = &tcg_op_defs[op];
+        /* Do copy propagation */
+        if (!(def->flags & (TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS))) {
+            assert(op != INDEX_op_call);
+            for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
+                if (temps[args[i]].state == TCG_TEMP_COPY) {
+                    args[i] = temps[args[i]].val;
+                }
+            }
+        }
+
+        /* For commutative operations make constant second argument */
+        switch (op) {
+        CASE_OP_32_64(add):
+        CASE_OP_32_64(mul):
+        CASE_OP_32_64(and):
+        CASE_OP_32_64(or):
+        CASE_OP_32_64(xor):
+            if (temps[args[1]].state == TCG_TEMP_CONST) {
+                tmp = args[1];
+                args[1] = args[2];
+                args[2] = tmp;
+            }
+            break;
+        default:
+            break;
+        }
+
+        /* Simplify expression if possible. */
+        switch (op) {
+        CASE_OP_32_64(add):
+        CASE_OP_32_64(sub):
+        CASE_OP_32_64(shl):
+        CASE_OP_32_64(shr):
+        CASE_OP_32_64(sar):
+#ifdef TCG_TARGET_HAS_rot_i32
+        case INDEX_op_rotl_i32:
+        case INDEX_op_rotr_i32:
+#endif
+#ifdef TCG_TARGET_HAS_rot_i64
+        case INDEX_op_rotl_i64:
+        case INDEX_op_rotr_i64:
+#endif
+            if (temps[args[1]].state == TCG_TEMP_CONST) {
+                /* Proceed with possible constant folding. */
+                break;
+            }
+            if (temps[args[2]].state == TCG_TEMP_CONST
+                && temps[args[2]].val == 0) {
+                if ((temps[args[0]].state == TCG_TEMP_COPY
+                    && temps[args[0]].val == args[1])
+                    || args[0] == args[1]) {
+                    args += 3;
+                    gen_opc_buf[op_index] = INDEX_op_nop;
+                } else {
+                    gen_opc_buf[op_index] = op_to_mov(op);
+                    tcg_opt_gen_mov(s, gen_args, args[0], args[1],
+                                    nb_temps, nb_globals);
+                    gen_args += 2;
+                    args += 3;
+                }
+                continue;
+            }
+            break;
+        CASE_OP_32_64(mul):
+            if ((temps[args[2]].state == TCG_TEMP_CONST
+                && temps[args[2]].val == 0)) {
+                gen_opc_buf[op_index] = op_to_movi(op);
+                tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals);
+                args += 3;
+                gen_args += 2;
+                continue;
+            }
+            break;
+        CASE_OP_32_64(or):
+        CASE_OP_32_64(and):
+            if (args[1] == args[2]) {
+                if (args[1] == args[0]) {
+                    args += 3;
+                    gen_opc_buf[op_index] = INDEX_op_nop;
+                } else {
+                    gen_opc_buf[op_index] = op_to_mov(op);
+                    tcg_opt_gen_mov(s, gen_args, args[0], args[1], nb_temps,
+                                    nb_globals);
+                    gen_args += 2;
+                    args += 3;
+                }
+                continue;
+            }
+            break;
+        }
+
+        /* Propagate constants through copy operations and do constant
+           folding.  Constants will be substituted to arguments by register
+           allocator where needed and possible.  Also detect copies. */
+        switch (op) {
+        CASE_OP_32_64(mov):
+            if ((temps[args[1]].state == TCG_TEMP_COPY
+                && temps[args[1]].val == args[0])
+                || args[0] == args[1]) {
+                args += 2;
+                gen_opc_buf[op_index] = INDEX_op_nop;
+                break;
+            }
+            if (temps[args[1]].state != TCG_TEMP_CONST) {
+                tcg_opt_gen_mov(s, gen_args, args[0], args[1],
+                                nb_temps, nb_globals);
+                gen_args += 2;
+                args += 2;
+                break;
+            }
+            /* Source argument is constant.  Rewrite the operation and
+               let movi case handle it. */
+            op = op_to_movi(op);
+            gen_opc_buf[op_index] = op;
+            args[1] = temps[args[1]].val;
+            /* fallthrough */
+        CASE_OP_32_64(movi):
+            tcg_opt_gen_movi(gen_args, args[0], args[1], nb_temps, nb_globals);
+            gen_args += 2;
+            args += 2;
+            break;
+        CASE_OP_32_64(not):
+#ifdef TCG_TARGET_HAS_ext8s_i32
+        case INDEX_op_ext8s_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext8s_i64
+        case INDEX_op_ext8s_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext16s_i32
+        case INDEX_op_ext16s_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext16s_i64
+        case INDEX_op_ext16s_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext8u_i32
+        case INDEX_op_ext8u_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext8u_i64
+        case INDEX_op_ext8u_i64:
+#endif
+#ifdef TCG_TARGET_HAS_ext16u_i32
+        case INDEX_op_ext16u_i32:
+#endif
+#ifdef TCG_TARGET_HAS_ext16u_i64
+        case INDEX_op_ext16u_i64:
+#endif
+#if TCG_TARGET_REG_BITS == 64
+        case INDEX_op_ext32s_i64:
+        case INDEX_op_ext32u_i64:
+#endif
+            if (temps[args[1]].state == TCG_TEMP_CONST) {
+                gen_opc_buf[op_index] = op_to_movi(op);
+                tmp = do_constant_folding(op, temps[args[1]].val, 0);
+                tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
+                gen_args += 2;
+                args += 2;
+                break;
+            } else {
+                reset_temp(args[0], nb_temps, nb_globals);
+                gen_args[0] = args[0];
+                gen_args[1] = args[1];
+                gen_args += 2;
+                args += 2;
+                break;
+            }
+        CASE_OP_32_64(add):
+        CASE_OP_32_64(sub):
+        CASE_OP_32_64(mul):
+        CASE_OP_32_64(or):
+        CASE_OP_32_64(and):
+        CASE_OP_32_64(xor):
+        CASE_OP_32_64(shl):
+        CASE_OP_32_64(shr):
+        CASE_OP_32_64(sar):
+#ifdef TCG_TARGET_HAS_rot_i32
+        case INDEX_op_rotl_i32:
+        case INDEX_op_rotr_i32:
+#endif
+#ifdef TCG_TARGET_HAS_rot_i64
+        case INDEX_op_rotl_i64:
+        case INDEX_op_rotr_i64:
+#endif
+            if (temps[args[1]].state == TCG_TEMP_CONST
+                && temps[args[2]].state == TCG_TEMP_CONST) {
+                gen_opc_buf[op_index] = op_to_movi(op);
+                tmp = do_constant_folding(op, temps[args[1]].val,
+                                          temps[args[2]].val);
+                tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
+                gen_args += 2;
+                args += 3;
+                break;
+            } else {
+                reset_temp(args[0], nb_temps, nb_globals);
+                gen_args[0] = args[0];
+                gen_args[1] = args[1];
+                gen_args[2] = args[2];
+                gen_args += 3;
+                args += 3;
+                break;
+            }
+        case INDEX_op_call:
+            nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
+            if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
+                for (i = 0; i < nb_globals; i++) {
+                    reset_temp(i, nb_temps, nb_globals);
+                }
+            }
+            for (i = 0; i < (args[0] >> 16); i++) {
+                reset_temp(args[i + 1], nb_temps, nb_globals);
+            }
+            i = nb_call_args + 3;
+            while (i) {
+                *gen_args = *args;
+                args++;
+                gen_args++;
+                i--;
+            }
+            break;
+        case INDEX_op_set_label:
+        case INDEX_op_jmp:
+        case INDEX_op_br:
+        CASE_OP_32_64(brcond):
+            memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
+            for (i = 0; i < def->nb_args; i++) {
+                *gen_args = *args;
+                args++;
+                gen_args++;
+            }
+            break;
+        default:
+            /* Default case: we do know nothing about operation so no
+               propagation is done.  We only trash output args.  */
+            for (i = 0; i < def->nb_oargs; i++) {
+                reset_temp(args[i], nb_temps, nb_globals);
+            }
+            for (i = 0; i < def->nb_args; i++) {
+                gen_args[i] = args[i];
+            }
+            args += def->nb_args;
+            gen_args += def->nb_args;
+            break;
+        }
+    }
+
+    return gen_args;
+}
+
+TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr,
+        TCGArg *args, TCGOpDef *tcg_op_defs)
+{
+    TCGArg *res;
+    res = tcg_constant_folding(s, tcg_opc_ptr, args, tcg_op_defs);
+    return res;
+}
index c05413baa4b4d0d86da24456b9b6a290f32dede5..92f1989019558219f756b7ea30fc9648ab7ea766 100644 (file)
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -24,6 +24,7 @@
 
 /* define it to use liveness analysis (better code) */
 #define USE_LIVENESS_ANALYSIS
+#define USE_TCG_OPTIMIZATIONS
 
 #include "config.h"
 
@@ -2035,6 +2036,11 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
     }
 #endif
 
+#ifdef USE_TCG_OPTIMIZATIONS
+    gen_opparam_ptr =
+        tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
+#endif
+
 #ifdef CONFIG_PROFILER
     s->la_time -= profile_getclock();
 #endif
index a2dd8b892a5335f95ff38bc3c033dfdb073ef694..e2a7095bb5395cb29de413b76c1cac5f58464985 100644 (file)
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -410,6 +410,11 @@ static inline TCGv_i64 tcg_temp_local_new_i64(void)
 void tcg_temp_free_i64(TCGv_i64 arg);
 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg);
 
+static inline bool tcg_arg_is_local(TCGContext *s, TCGArg arg)
+{
+    return s->temps[arg].temp_local;
+}
+
 #if defined(CONFIG_DEBUG_TCG)
 /* If you call tcg_clear_temp_count() at the start of a section of
  * code which is not supposed to leak any TCG temporaries, then
@@ -502,6 +507,9 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
 void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
                         int c, int right, int arith);
 
+TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args,
+                     TCGOpDef *tcg_op_def);
+
 /* only used for debugging purposes */
 void tcg_register_helper(void *func, const char *name);
 const char *tcg_helper_get_name(TCGContext *s, void *func);
diff --git a/test-coroutine.c b/test-coroutine.c
new file mode 100644 (file)
index 0000000..bf9f3e9
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Coroutine tests
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include <glib.h>
+#include "qemu-coroutine.h"
+
+/*
+ * Check that qemu_in_coroutine() works
+ */
+
+static void coroutine_fn verify_in_coroutine(void *opaque)
+{
+    g_assert(qemu_in_coroutine());
+}
+
+static void test_in_coroutine(void)
+{
+    Coroutine *coroutine;
+
+    g_assert(!qemu_in_coroutine());
+
+    coroutine = qemu_coroutine_create(verify_in_coroutine);
+    qemu_coroutine_enter(coroutine, NULL);
+}
+
+/*
+ * Check that qemu_coroutine_self() works
+ */
+
+static void coroutine_fn verify_self(void *opaque)
+{
+    g_assert(qemu_coroutine_self() == opaque);
+}
+
+static void test_self(void)
+{
+    Coroutine *coroutine;
+
+    coroutine = qemu_coroutine_create(verify_self);
+    qemu_coroutine_enter(coroutine, coroutine);
+}
+
+/*
+ * Check that coroutines may nest multiple levels
+ */
+
+typedef struct {
+    unsigned int n_enter;   /* num coroutines entered */
+    unsigned int n_return;  /* num coroutines returned */
+    unsigned int max;       /* maximum level of nesting */
+} NestData;
+
+static void coroutine_fn nest(void *opaque)
+{
+    NestData *nd = opaque;
+
+    nd->n_enter++;
+
+    if (nd->n_enter < nd->max) {
+        Coroutine *child;
+
+        child = qemu_coroutine_create(nest);
+        qemu_coroutine_enter(child, nd);
+    }
+
+    nd->n_return++;
+}
+
+static void test_nesting(void)
+{
+    Coroutine *root;
+    NestData nd = {
+        .n_enter  = 0,
+        .n_return = 0,
+        .max      = 128,
+    };
+
+    root = qemu_coroutine_create(nest);
+    qemu_coroutine_enter(root, &nd);
+
+    /* Must enter and return from max nesting level */
+    g_assert_cmpint(nd.n_enter, ==, nd.max);
+    g_assert_cmpint(nd.n_return, ==, nd.max);
+}
+
+/*
+ * Check that yield/enter transfer control correctly
+ */
+
+static void coroutine_fn yield_5_times(void *opaque)
+{
+    bool *done = opaque;
+    int i;
+
+    for (i = 0; i < 5; i++) {
+        qemu_coroutine_yield();
+    }
+    *done = true;
+}
+
+static void test_yield(void)
+{
+    Coroutine *coroutine;
+    bool done = false;
+    int i = -1; /* one extra time to return from coroutine */
+
+    coroutine = qemu_coroutine_create(yield_5_times);
+    while (!done) {
+        qemu_coroutine_enter(coroutine, &done);
+        i++;
+    }
+    g_assert_cmpint(i, ==, 5); /* coroutine must yield 5 times */
+}
+
+/*
+ * Check that creation, enter, and return work
+ */
+
+static void coroutine_fn set_and_exit(void *opaque)
+{
+    bool *done = opaque;
+
+    *done = true;
+}
+
+static void test_lifecycle(void)
+{
+    Coroutine *coroutine;
+    bool done = false;
+
+    /* Create, enter, and return from coroutine */
+    coroutine = qemu_coroutine_create(set_and_exit);
+    qemu_coroutine_enter(coroutine, &done);
+    g_assert(done); /* expect done to be true (first time) */
+
+    /* Repeat to check that no state affects this test */
+    done = false;
+    coroutine = qemu_coroutine_create(set_and_exit);
+    qemu_coroutine_enter(coroutine, &done);
+    g_assert(done); /* expect done to be true (second time) */
+}
+
+/*
+ * Lifecycle benchmark
+ */
+
+static void coroutine_fn empty_coroutine(void *opaque)
+{
+    /* Do nothing */
+}
+
+static void perf_lifecycle(void)
+{
+    Coroutine *coroutine;
+    unsigned int i, max;
+    double duration;
+
+    max = 1000000;
+
+    g_test_timer_start();
+    for (i = 0; i < max; i++) {
+        coroutine = qemu_coroutine_create(empty_coroutine);
+        qemu_coroutine_enter(coroutine, NULL);
+    }
+    duration = g_test_timer_elapsed();
+
+    g_test_message("Lifecycle %u iterations: %f s\n", max, duration);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_add_func("/basic/lifecycle", test_lifecycle);
+    g_test_add_func("/basic/yield", test_yield);
+    g_test_add_func("/basic/nesting", test_nesting);
+    g_test_add_func("/basic/self", test_self);
+    g_test_add_func("/basic/in_coroutine", test_in_coroutine);
+    if (g_test_perf()) {
+        g_test_add_func("/perf/lifecycle", perf_lifecycle);
+    }
+    return g_test_run();
+}
index 713f042081e39c5361f2b117a19fe0284ce9483c..19d31e3541e1b6f6fff06caa43c77cea90c872fb 100644 (file)
@@ -66,6 +66,9 @@ disable bdrv_aio_flush(void *bs, void *opaque) "bs %p opaque %p"
 disable bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
 disable bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
 disable bdrv_set_locked(void *bs, int locked) "bs %p locked %d"
+disable bdrv_co_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
+disable bdrv_co_writev(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
+disable bdrv_co_io(int is_write, void *acb) "is_write %d acb %p"
 
 # hw/virtio-blk.c
 disable virtio_blk_req_complete(void *req, int status) "req %p status %d"
@@ -425,3 +428,16 @@ disable qemu_put_ram_ptr(void* addr) "%p"
 
 # hw/xen_platform.c
 disable xen_platform_log(char *s) "xen platform: %s"
+
+# qemu-coroutine.c
+disable qemu_coroutine_enter(void *from, void *to, void *opaque) "from %p to %p opaque %p"
+disable qemu_coroutine_yield(void *from, void *to) "from %p to %p"
+disable qemu_coroutine_terminate(void *co) "self %p"
+
+# qemu-coroutine-lock.c
+disable qemu_co_queue_next_bh(void) ""
+disable qemu_co_queue_next(void *next) "next %p"
+disable qemu_co_mutex_lock_entry(void *mutex, void *self) "mutex %p self %p"
+disable qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p"
+disable qemu_co_mutex_unlock_entry(void *mutex, void *self) "mutex %p self %p"
+disable qemu_co_mutex_unlock_return(void *mutex, void *self) "mutex %p self %p"
index 6dbc5cb0ed341b8d34fb4423b49f526989b56b85..30cde8662e2d5d1b7ce9882ab5bb58daf1e44bab 100644 (file)
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -39,15 +39,16 @@ static SDL_Surface *real_screen;
 static SDL_Surface *guest_screen = NULL;
 static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
 static int last_vm_running;
+static bool gui_saved_scaling;
+static int gui_saved_width;
+static int gui_saved_height;
 static int gui_saved_grab;
 static int gui_fullscreen;
 static int gui_noframe;
 static int gui_key_modifier_pressed;
 static int gui_keysym;
-static int gui_fullscreen_initial_grab;
 static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
 static uint8_t modifiers_state[256];
-static int width, height;
 static SDL_Cursor *sdl_cursor_normal;
 static SDL_Cursor *sdl_cursor_hidden;
 static int absolute_enabled = 0;
@@ -91,20 +92,21 @@ static void sdl_setdata(DisplayState *ds)
                                             ds->surface->pf.bmask, ds->surface->pf.amask);
 }
 
-static void do_sdl_resize(int new_width, int new_height, int bpp)
+static void do_sdl_resize(int width, int height, int bpp)
 {
     int flags;
 
     //    printf("resizing to %d %d\n", w, h);
 
-    flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_RESIZABLE;
-    if (gui_fullscreen)
+    flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
+    if (gui_fullscreen) {
         flags |= SDL_FULLSCREEN;
+    } else {
+        flags |= SDL_RESIZABLE;
+    }
     if (gui_noframe)
         flags |= SDL_NOFRAME;
 
-    width = new_width;
-    height = new_height;
     real_screen = SDL_SetVideoMode(width, height, bpp, flags);
     if (!real_screen) {
        fprintf(stderr, "Could not open SDL display (%dx%dx%d): %s\n", width, 
@@ -447,7 +449,7 @@ static void sdl_show_cursor(void)
     if (!cursor_hide)
         return;
 
-    if (!kbd_mouse_is_absolute()) {
+    if (!kbd_mouse_is_absolute() || !is_graphic_console()) {
         SDL_ShowCursor(1);
         if (guest_cursor &&
                 (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
@@ -485,32 +487,32 @@ static void sdl_mouse_mode_change(Notifier *notify, void *data)
 {
     if (kbd_mouse_is_absolute()) {
         if (!absolute_enabled) {
-            sdl_hide_cursor();
-            if (gui_grab) {
-                sdl_grab_end();
-            }
+            sdl_grab_start();
             absolute_enabled = 1;
         }
     } else if (absolute_enabled) {
-       sdl_show_cursor();
-       absolute_enabled = 0;
+        sdl_grab_end();
+        absolute_enabled = 0;
     }
 }
 
 static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state)
 {
-    int buttons;
-    buttons = 0;
-    if (state & SDL_BUTTON(SDL_BUTTON_LEFT))
+    int buttons = 0;
+
+    if (state & SDL_BUTTON(SDL_BUTTON_LEFT)) {
         buttons |= MOUSE_EVENT_LBUTTON;
-    if (state & SDL_BUTTON(SDL_BUTTON_RIGHT))
+    }
+    if (state & SDL_BUTTON(SDL_BUTTON_RIGHT)) {
         buttons |= MOUSE_EVENT_RBUTTON;
-    if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))
+    }
+    if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) {
         buttons |= MOUSE_EVENT_MBUTTON;
+    }
 
     if (kbd_mouse_is_absolute()) {
-       dx = x * 0x7FFF / (width - 1);
-       dy = y * 0x7FFF / (height - 1);
+        dx = x * 0x7FFF / (real_screen->w - 1);
+        dy = y * 0x7FFF / (real_screen->h - 1);
     } else if (guest_cursor) {
         x -= guest_x;
         y -= guest_y;
@@ -523,27 +525,331 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state
     kbd_mouse_event(dx, dy, dz, buttons);
 }
 
+static void sdl_scale(DisplayState *ds, int width, int height)
+{
+    int bpp = real_screen->format->BitsPerPixel;
+
+    if (bpp != 16 && bpp != 32) {
+        bpp = 32;
+    }
+    do_sdl_resize(width, height, bpp);
+    scaling_active = 1;
+    if (!is_buffer_shared(ds->surface)) {
+        ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds),
+                                                 ds_get_height(ds));
+        dpy_resize(ds);
+    }
+}
+
 static void toggle_full_screen(DisplayState *ds)
 {
     gui_fullscreen = !gui_fullscreen;
-    do_sdl_resize(real_screen->w, real_screen->h, real_screen->format->BitsPerPixel);
     if (gui_fullscreen) {
+        gui_saved_width = real_screen->w;
+        gui_saved_height = real_screen->h;
+        gui_saved_scaling = scaling_active;
+
+        do_sdl_resize(ds_get_width(ds), ds_get_height(ds),
+                      ds_get_bits_per_pixel(ds));
         scaling_active = 0;
+
         gui_saved_grab = gui_grab;
         sdl_grab_start();
     } else {
-        if (!gui_saved_grab)
+        if (gui_saved_scaling) {
+            sdl_scale(ds, gui_saved_width, gui_saved_height);
+        } else {
+            do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
+        }
+        if (!gui_saved_grab || !is_graphic_console()) {
             sdl_grab_end();
+        }
     }
     vga_hw_invalidate();
     vga_hw_update();
 }
 
-static void sdl_refresh(DisplayState *ds)
+static void absolute_mouse_grab(void)
+{
+    int mouse_x, mouse_y;
+
+    if (SDL_GetAppState() & SDL_APPINPUTFOCUS) {
+        SDL_GetMouseState(&mouse_x, &mouse_y);
+        if (mouse_x > 0 && mouse_x < real_screen->w - 1 &&
+            mouse_y > 0 && mouse_y < real_screen->h - 1) {
+            sdl_grab_start();
+        }
+    }
+}
+
+static void handle_keydown(DisplayState *ds, SDL_Event *ev)
+{
+    int mod_state;
+    int keycode;
+
+    if (alt_grab) {
+        mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) ==
+                    (gui_grab_code | KMOD_LSHIFT);
+    } else if (ctrl_grab) {
+        mod_state = (SDL_GetModState() & KMOD_RCTRL) == KMOD_RCTRL;
+    } else {
+        mod_state = (SDL_GetModState() & gui_grab_code) == gui_grab_code;
+    }
+    gui_key_modifier_pressed = mod_state;
+
+    if (gui_key_modifier_pressed) {
+        keycode = sdl_keyevent_to_keycode(&ev->key);
+        switch (keycode) {
+        case 0x21: /* 'f' key on US keyboard */
+            toggle_full_screen(ds);
+            gui_keysym = 1;
+            break;
+        case 0x16: /* 'u' key on US keyboard */
+            if (scaling_active) {
+                scaling_active = 0;
+                sdl_resize(ds);
+                vga_hw_invalidate();
+                vga_hw_update();
+            }
+            gui_keysym = 1;
+            break;
+        case 0x02 ... 0x0a: /* '1' to '9' keys */
+            /* Reset the modifiers sent to the current console */
+            reset_keys();
+            console_select(keycode - 0x02);
+            gui_keysym = 1;
+            if (gui_fullscreen) {
+                break;
+            }
+            if (!is_graphic_console()) {
+                /* release grab if going to a text console */
+                if (gui_grab) {
+                    sdl_grab_end();
+                } else if (absolute_enabled) {
+                    sdl_show_cursor();
+                }
+            } else if (absolute_enabled) {
+                sdl_hide_cursor();
+                absolute_mouse_grab();
+            }
+            break;
+        case 0x1b: /* '+' */
+        case 0x35: /* '-' */
+            if (!gui_fullscreen) {
+                int width = MAX(real_screen->w + (keycode == 0x1b ? 50 : -50),
+                                160);
+                int height = (ds_get_height(ds) * width) / ds_get_width(ds);
+
+                sdl_scale(ds, width, height);
+                vga_hw_invalidate();
+                vga_hw_update();
+                gui_keysym = 1;
+            }
+        default:
+            break;
+        }
+    } else if (!is_graphic_console()) {
+        int keysym = 0;
+
+        if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
+            switch (ev->key.keysym.sym) {
+            case SDLK_UP:
+                keysym = QEMU_KEY_CTRL_UP;
+                break;
+            case SDLK_DOWN:
+                keysym = QEMU_KEY_CTRL_DOWN;
+                break;
+            case SDLK_LEFT:
+                keysym = QEMU_KEY_CTRL_LEFT;
+                break;
+            case SDLK_RIGHT:
+                keysym = QEMU_KEY_CTRL_RIGHT;
+                break;
+            case SDLK_HOME:
+                keysym = QEMU_KEY_CTRL_HOME;
+                break;
+            case SDLK_END:
+                keysym = QEMU_KEY_CTRL_END;
+                break;
+            case SDLK_PAGEUP:
+                keysym = QEMU_KEY_CTRL_PAGEUP;
+                break;
+            case SDLK_PAGEDOWN:
+                keysym = QEMU_KEY_CTRL_PAGEDOWN;
+                break;
+            default:
+                break;
+            }
+        } else {
+            switch (ev->key.keysym.sym) {
+            case SDLK_UP:
+                keysym = QEMU_KEY_UP;
+                break;
+            case SDLK_DOWN:
+                keysym = QEMU_KEY_DOWN;
+                break;
+            case SDLK_LEFT:
+                keysym = QEMU_KEY_LEFT;
+                break;
+            case SDLK_RIGHT:
+                keysym = QEMU_KEY_RIGHT;
+                break;
+            case SDLK_HOME:
+                keysym = QEMU_KEY_HOME;
+                break;
+            case SDLK_END:
+                keysym = QEMU_KEY_END;
+                break;
+            case SDLK_PAGEUP:
+                keysym = QEMU_KEY_PAGEUP;
+                break;
+            case SDLK_PAGEDOWN:
+                keysym = QEMU_KEY_PAGEDOWN;
+                break;
+            case SDLK_BACKSPACE:
+                keysym = QEMU_KEY_BACKSPACE;
+                break;
+            case SDLK_DELETE:
+                keysym = QEMU_KEY_DELETE;
+                break;
+            default:
+                break;
+            }
+        }
+        if (keysym) {
+            kbd_put_keysym(keysym);
+        } else if (ev->key.keysym.unicode != 0) {
+            kbd_put_keysym(ev->key.keysym.unicode);
+        }
+    }
+    if (is_graphic_console() && !gui_keysym) {
+        sdl_process_key(&ev->key);
+    }
+}
+
+static void handle_keyup(DisplayState *ds, SDL_Event *ev)
 {
-    SDL_Event ev1, *ev = &ev1;
     int mod_state;
+
+    if (!alt_grab) {
+        mod_state = (ev->key.keysym.mod & gui_grab_code);
+    } else {
+        mod_state = (ev->key.keysym.mod & (gui_grab_code | KMOD_LSHIFT));
+    }
+    if (!mod_state && gui_key_modifier_pressed) {
+        gui_key_modifier_pressed = 0;
+        if (gui_keysym == 0) {
+            /* exit/enter grab if pressing Ctrl-Alt */
+            if (!gui_grab) {
+                /* If the application is not active, do not try to enter grab
+                 * state. It prevents 'SDL_WM_GrabInput(SDL_GRAB_ON)' from
+                 * blocking all the application (SDL bug). */
+                if (is_graphic_console() &&
+                    SDL_GetAppState() & SDL_APPACTIVE) {
+                    sdl_grab_start();
+                }
+            } else if (!gui_fullscreen) {
+                sdl_grab_end();
+            }
+            /* SDL does not send back all the modifiers key, so we must
+             * correct it. */
+            reset_keys();
+            return;
+        }
+        gui_keysym = 0;
+    }
+    if (is_graphic_console() && !gui_keysym) {
+        sdl_process_key(&ev->key);
+    }
+}
+
+static void handle_mousemotion(DisplayState *ds, SDL_Event *ev)
+{
+    int max_x, max_y;
+
+    if (is_graphic_console() &&
+        (kbd_mouse_is_absolute() || absolute_enabled)) {
+        max_x = real_screen->w - 1;
+        max_y = real_screen->h - 1;
+        if (gui_grab && (ev->motion.x == 0 || ev->motion.y == 0 ||
+            ev->motion.x == max_x || ev->motion.y == max_y)) {
+            sdl_grab_end();
+        }
+        if (!gui_grab && SDL_GetAppState() & SDL_APPINPUTFOCUS &&
+            (ev->motion.x > 0 && ev->motion.x < max_x &&
+            ev->motion.y > 0 && ev->motion.y < max_y)) {
+            sdl_grab_start();
+        }
+    }
+    if (gui_grab || kbd_mouse_is_absolute() || absolute_enabled) {
+        sdl_send_mouse_event(ev->motion.xrel, ev->motion.yrel, 0,
+                             ev->motion.x, ev->motion.y, ev->motion.state);
+    }
+}
+
+static void handle_mousebutton(DisplayState *ds, SDL_Event *ev)
+{
     int buttonstate = SDL_GetMouseState(NULL, NULL);
+    SDL_MouseButtonEvent *bev;
+    int dz;
+
+    if (!is_graphic_console()) {
+        return;
+    }
+
+    bev = &ev->button;
+    if (!gui_grab && !kbd_mouse_is_absolute()) {
+        if (ev->type == SDL_MOUSEBUTTONDOWN &&
+            (bev->button == SDL_BUTTON_LEFT)) {
+            /* start grabbing all events */
+            sdl_grab_start();
+        }
+    } else {
+        dz = 0;
+        if (ev->type == SDL_MOUSEBUTTONDOWN) {
+            buttonstate |= SDL_BUTTON(bev->button);
+        } else {
+            buttonstate &= ~SDL_BUTTON(bev->button);
+        }
+#ifdef SDL_BUTTON_WHEELUP
+        if (bev->button == SDL_BUTTON_WHEELUP &&
+            ev->type == SDL_MOUSEBUTTONDOWN) {
+            dz = -1;
+        } else if (bev->button == SDL_BUTTON_WHEELDOWN &&
+                   ev->type == SDL_MOUSEBUTTONDOWN) {
+            dz = 1;
+        }
+#endif
+        sdl_send_mouse_event(0, 0, dz, bev->x, bev->y, buttonstate);
+    }
+}
+
+static void handle_activation(DisplayState *ds, SDL_Event *ev)
+{
+    if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS &&
+        !ev->active.gain && !gui_fullscreen) {
+        sdl_grab_end();
+    }
+    if (!gui_grab && ev->active.gain && is_graphic_console() &&
+        (kbd_mouse_is_absolute() || absolute_enabled)) {
+        absolute_mouse_grab();
+    }
+    if (ev->active.state & SDL_APPACTIVE) {
+        if (ev->active.gain) {
+            /* Back to default interval */
+            dcl->gui_timer_interval = 0;
+            dcl->idle = 0;
+        } else {
+            /* Sleeping interval */
+            dcl->gui_timer_interval = 500;
+            dcl->idle = 1;
+        }
+    }
+}
+
+static void sdl_refresh(DisplayState *ds)
+{
+    SDL_Event ev1, *ev = &ev1;
 
     if (last_vm_running != vm_running) {
         last_vm_running = vm_running;
@@ -559,191 +865,32 @@ static void sdl_refresh(DisplayState *ds)
             sdl_update(ds, 0, 0, real_screen->w, real_screen->h);
             break;
         case SDL_KEYDOWN:
+            handle_keydown(ds, ev);
+            break;
         case SDL_KEYUP:
-            if (ev->type == SDL_KEYDOWN) {
-                if (alt_grab) {
-                    mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) ==
-                                (gui_grab_code | KMOD_LSHIFT);
-                } else if (ctrl_grab) {
-                    mod_state = (SDL_GetModState() & KMOD_RCTRL) == KMOD_RCTRL;
-                } else {
-                    mod_state = (SDL_GetModState() & gui_grab_code) ==
-                                gui_grab_code;
-                }
-                gui_key_modifier_pressed = mod_state;
-                if (gui_key_modifier_pressed) {
-                    int keycode;
-                    keycode = sdl_keyevent_to_keycode(&ev->key);
-                    switch(keycode) {
-                    case 0x21: /* 'f' key on US keyboard */
-                        toggle_full_screen(ds);
-                        gui_keysym = 1;
-                        break;
-                    case 0x16: /* 'u' key on US keyboard */
-                        scaling_active = 0;
-                        sdl_resize(ds);
-                        vga_hw_invalidate();
-                        vga_hw_update();
-                        break;
-                    case 0x02 ... 0x0a: /* '1' to '9' keys */
-                        /* Reset the modifiers sent to the current console */
-                        reset_keys();
-                        console_select(keycode - 0x02);
-                        if (!is_graphic_console()) {
-                            /* display grab if going to a text console */
-                            if (gui_grab)
-                                sdl_grab_end();
-                        }
-                        gui_keysym = 1;
-                        break;
-                    default:
-                        break;
-                    }
-                } else if (!is_graphic_console()) {
-                    int keysym;
-                    keysym = 0;
-                    if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
-                        switch(ev->key.keysym.sym) {
-                        case SDLK_UP: keysym = QEMU_KEY_CTRL_UP; break;
-                        case SDLK_DOWN: keysym = QEMU_KEY_CTRL_DOWN; break;
-                        case SDLK_LEFT: keysym = QEMU_KEY_CTRL_LEFT; break;
-                        case SDLK_RIGHT: keysym = QEMU_KEY_CTRL_RIGHT; break;
-                        case SDLK_HOME: keysym = QEMU_KEY_CTRL_HOME; break;
-                        case SDLK_END: keysym = QEMU_KEY_CTRL_END; break;
-                        case SDLK_PAGEUP: keysym = QEMU_KEY_CTRL_PAGEUP; break;
-                        case SDLK_PAGEDOWN: keysym = QEMU_KEY_CTRL_PAGEDOWN; break;
-                        default: break;
-                        }
-                    } else {
-                        switch(ev->key.keysym.sym) {
-                        case SDLK_UP: keysym = QEMU_KEY_UP; break;
-                        case SDLK_DOWN: keysym = QEMU_KEY_DOWN; break;
-                        case SDLK_LEFT: keysym = QEMU_KEY_LEFT; break;
-                        case SDLK_RIGHT: keysym = QEMU_KEY_RIGHT; break;
-                        case SDLK_HOME: keysym = QEMU_KEY_HOME; break;
-                        case SDLK_END: keysym = QEMU_KEY_END; break;
-                        case SDLK_PAGEUP: keysym = QEMU_KEY_PAGEUP; break;
-                        case SDLK_PAGEDOWN: keysym = QEMU_KEY_PAGEDOWN; break;
-                        case SDLK_BACKSPACE: keysym = QEMU_KEY_BACKSPACE; break;
-                        case SDLK_DELETE: keysym = QEMU_KEY_DELETE; break;
-                        default: break;
-                        }
-                    }
-                    if (keysym) {
-                        kbd_put_keysym(keysym);
-                    } else if (ev->key.keysym.unicode != 0) {
-                        kbd_put_keysym(ev->key.keysym.unicode);
-                    }
-                }
-            } else if (ev->type == SDL_KEYUP) {
-                if (!alt_grab) {
-                    mod_state = (ev->key.keysym.mod & gui_grab_code);
-                } else {
-                    mod_state = (ev->key.keysym.mod &
-                                 (gui_grab_code | KMOD_LSHIFT));
-                }
-                if (!mod_state) {
-                    if (gui_key_modifier_pressed) {
-                        gui_key_modifier_pressed = 0;
-                        if (gui_keysym == 0) {
-                            /* exit/enter grab if pressing Ctrl-Alt */
-                            if (!gui_grab) {
-                                /* if the application is not active,
-                                   do not try to enter grab state. It
-                                   prevents
-                                   'SDL_WM_GrabInput(SDL_GRAB_ON)'
-                                   from blocking all the application
-                                   (SDL bug). */
-                                if (SDL_GetAppState() & SDL_APPACTIVE)
-                                    sdl_grab_start();
-                            } else {
-                                sdl_grab_end();
-                            }
-                            /* SDL does not send back all the
-                               modifiers key, so we must correct it */
-                            reset_keys();
-                            break;
-                        }
-                        gui_keysym = 0;
-                    }
-                }
-            }
-            if (is_graphic_console() && !gui_keysym)
-                sdl_process_key(&ev->key);
+            handle_keyup(ds, ev);
             break;
         case SDL_QUIT:
-            if (!no_quit)
+            if (!no_quit) {
+                no_shutdown = 0;
                 qemu_system_shutdown_request();
+            }
             break;
         case SDL_MOUSEMOTION:
-            if (gui_grab || kbd_mouse_is_absolute() ||
-                absolute_enabled) {
-                sdl_send_mouse_event(ev->motion.xrel, ev->motion.yrel, 0,
-                       ev->motion.x, ev->motion.y, ev->motion.state);
-            }
+            handle_mousemotion(ds, ev);
             break;
         case SDL_MOUSEBUTTONDOWN:
         case SDL_MOUSEBUTTONUP:
-            {
-                SDL_MouseButtonEvent *bev = &ev->button;
-                if (!gui_grab && !kbd_mouse_is_absolute()) {
-                    if (ev->type == SDL_MOUSEBUTTONDOWN &&
-                        (bev->button == SDL_BUTTON_LEFT)) {
-                        /* start grabbing all events */
-                        sdl_grab_start();
-                    }
-                } else {
-                    int dz;
-                    dz = 0;
-                    if (ev->type == SDL_MOUSEBUTTONDOWN) {
-                        buttonstate |= SDL_BUTTON(bev->button);
-                    } else {
-                        buttonstate &= ~SDL_BUTTON(bev->button);
-                    }
-#ifdef SDL_BUTTON_WHEELUP
-                    if (bev->button == SDL_BUTTON_WHEELUP && ev->type == SDL_MOUSEBUTTONDOWN) {
-                        dz = -1;
-                    } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) {
-                        dz = 1;
-                    }
-#endif
-                    sdl_send_mouse_event(0, 0, dz, bev->x, bev->y, buttonstate);
-                }
-            }
+            handle_mousebutton(ds, ev);
             break;
         case SDL_ACTIVEEVENT:
-            if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS &&
-                !ev->active.gain && !gui_fullscreen_initial_grab) {
-                sdl_grab_end();
-            }
-            if (ev->active.state & SDL_APPACTIVE) {
-                if (ev->active.gain) {
-                    /* Back to default interval */
-                    dcl->gui_timer_interval = 0;
-                    dcl->idle = 0;
-                } else {
-                    /* Sleeping interval */
-                    dcl->gui_timer_interval = 500;
-                    dcl->idle = 1;
-                }
-            }
+            handle_activation(ds, ev);
             break;
-       case SDL_VIDEORESIZE:
-        {
-           SDL_ResizeEvent *rev = &ev->resize;
-            int bpp = real_screen->format->BitsPerPixel;
-            if (bpp != 16 && bpp != 32)
-                bpp = 32;
-            do_sdl_resize(rev->w, rev->h, bpp);
-            scaling_active = 1;
-            if (!is_buffer_shared(ds->surface)) {
-                ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds), ds_get_height(ds));
-                dpy_resize(ds);
-            }
+        case SDL_VIDEORESIZE:
+            sdl_scale(ds, ev->resize.w, ev->resize.h);
             vga_hw_invalidate();
             vga_hw_update();
             break;
-        }
         default:
             break;
         }
@@ -865,6 +1012,11 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
         qemu_free(filename);
     }
 
+    if (full_screen) {
+        gui_fullscreen = 1;
+        sdl_grab_start();
+    }
+
     dcl = qemu_mallocz(sizeof(DisplayChangeListener));
     dcl->dpy_update = sdl_update;
     dcl->dpy_resize = sdl_resize;
@@ -894,9 +1046,4 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
     sdl_cursor_normal = SDL_GetCursor();
 
     atexit(sdl_cleanup);
-    if (full_screen) {
-        gui_fullscreen = 1;
-        gui_fullscreen_initial_grab = 1;
-        sdl_grab_start();
-    }
 }
index feeee73dccedd83e080013e8086070dcf322f161..683d45429f85e3b3157b8ff3cc59741cf76c517c 100644 (file)
@@ -62,6 +62,70 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
     dest->right = MAX(dest->right, r->right);
 }
 
+void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
+                            qxl_async_io async)
+{
+    if (async != QXL_SYNC) {
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+        spice_qxl_add_memslot_async(&ssd->qxl, memslot, 0);
+#else
+        abort();
+#endif
+    } else {
+        ssd->worker->add_memslot(ssd->worker, memslot);
+    }
+}
+
+void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid)
+{
+    ssd->worker->del_memslot(ssd->worker, gid, sid);
+}
+
+void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
+                                       QXLDevSurfaceCreate *surface,
+                                       qxl_async_io async)
+{
+    if (async != QXL_SYNC) {
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+        spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface, 0);
+#else
+        abort();
+#endif
+    } else {
+        ssd->worker->create_primary_surface(ssd->worker, id, surface);
+    }
+}
+
+
+void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
+                                        uint32_t id, qxl_async_io async)
+{
+    if (async != QXL_SYNC) {
+#if SPICE_INTERFACE_QXL_MINOR >= 1
+        spice_qxl_destroy_primary_surface_async(&ssd->qxl, id, 0);
+#else
+        abort();
+#endif
+    } else {
+        ssd->worker->destroy_primary_surface(ssd->worker, id);
+    }
+}
+
+void qemu_spice_wakeup(SimpleSpiceDisplay *ssd)
+{
+    ssd->worker->wakeup(ssd->worker);
+}
+
+void qemu_spice_start(SimpleSpiceDisplay *ssd)
+{
+    ssd->worker->start(ssd->worker);
+}
+
+void qemu_spice_stop(SimpleSpiceDisplay *ssd)
+{
+    ssd->worker->stop(ssd->worker);
+}
+
 static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
 {
     SimpleSpiceUpdate *update;
@@ -161,7 +225,7 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd)
     memset(&memslot, 0, sizeof(memslot));
     memslot.slot_group_id = MEMSLOT_GROUP_HOST;
     memslot.virt_end = ~0;
-    ssd->worker->add_memslot(ssd->worker, &memslot);
+    qemu_spice_add_memslot(ssd, &memslot, QXL_SYNC);
 }
 
 void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
@@ -181,14 +245,14 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
     surface.mem        = (intptr_t)ssd->buf;
     surface.group_id   = MEMSLOT_GROUP_HOST;
 
-    ssd->worker->create_primary_surface(ssd->worker, 0, &surface);
+    qemu_spice_create_primary_surface(ssd, 0, &surface, QXL_SYNC);
 }
 
 void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
 {
     dprint(1, "%s:\n", __FUNCTION__);
 
-    ssd->worker->destroy_primary_surface(ssd->worker, 0);
+    qemu_spice_destroy_primary_surface(ssd, 0, QXL_SYNC);
 }
 
 void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
@@ -196,13 +260,23 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
     SimpleSpiceDisplay *ssd = opaque;
 
     if (running) {
-        ssd->worker->start(ssd->worker);
+        qemu_spice_start(ssd);
     } else {
-        ssd->worker->stop(ssd->worker);
+        qemu_spice_stop(ssd);
     }
     ssd->running = running;
 }
 
+void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds)
+{
+    ssd->ds = ds;
+    qemu_mutex_init(&ssd->lock);
+    ssd->mouse_x = -1;
+    ssd->mouse_y = -1;
+    ssd->bufsize = (16 * 1024 * 1024);
+    ssd->buf = qemu_malloc(ssd->bufsize);
+}
+
 /* display listener callbacks */
 
 void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
@@ -267,7 +341,7 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
 
     if (ssd->notify) {
         ssd->notify = 0;
-        ssd->worker->wakeup(ssd->worker);
+        qemu_spice_wakeup(ssd);
         dprint(2, "%s: notify\n", __FUNCTION__);
     }
 }
@@ -416,12 +490,7 @@ static DisplayChangeListener display_listener = {
 void qemu_spice_display_init(DisplayState *ds)
 {
     assert(sdpy.ds == NULL);
-    sdpy.ds = ds;
-    qemu_mutex_init(&sdpy.lock);
-    sdpy.mouse_x = -1;
-    sdpy.mouse_y = -1;
-    sdpy.bufsize = (16 * 1024 * 1024);
-    sdpy.buf = qemu_malloc(sdpy.bufsize);
+    qemu_spice_display_init_common(&sdpy, ds);
     register_displaychangelistener(ds, &display_listener);
 
     sdpy.qxl.base.sif = &dpy_interface.base;
index 2f95f68aad77ecc22856cb8558d848556b61c13f..1388641370ee57a66c04b3e576e8a08f38472cc2 100644 (file)
 
 #define NUM_SURFACES 1024
 
+/*
+ * Internal enum to differenciate between options for
+ * io calls that have a sync (old) version and an _async (new)
+ * version:
+ *  QXL_SYNC: use the old version
+ *  QXL_ASYNC: use the new version and make sure there are no two
+ *   happening at the same time. This is used for guest initiated
+ *   calls
+ */
+typedef enum qxl_async_io {
+    QXL_SYNC,
+    QXL_ASYNC,
+} qxl_async_io;
+
 typedef struct SimpleSpiceDisplay SimpleSpiceDisplay;
 typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
 
@@ -75,8 +89,22 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd);
 void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd);
 void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd);
 void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason);
+void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds);
 
 void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
                                int x, int y, int w, int h);
 void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
 void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
+
+void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
+                            qxl_async_io async);
+void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid,
+                            uint32_t sid);
+void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
+                                       QXLDevSurfaceCreate *surface,
+                                       qxl_async_io async);
+void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
+                                        uint32_t id, qxl_async_io async);
+void qemu_spice_wakeup(SimpleSpiceDisplay *ssd);
+void qemu_spice_start(SimpleSpiceDisplay *ssd);
+void qemu_spice_stop(SimpleSpiceDisplay *ssd);
index 3b97eb491bfd5933423bf470635095b9ef586b3a..ab84d938578c69d0f52345dce8d9fedbf9dc18f4 100644 (file)
--- a/usb-bsd.c
+++ b/usb-bsd.c
@@ -62,7 +62,6 @@ typedef struct USBHostDevice {
 } USBHostDevice;
 
 
-#if 0
 static int ensure_ep_open(USBHostDevice *dev, int ep, int mode)
 {
     char buf[32];
@@ -110,7 +109,6 @@ static void ensure_eps_closed(USBHostDevice *dev)
         epnum++;
     }
 }
-#endif
 
 static void usb_host_handle_reset(USBDevice *dev)
 {
@@ -119,7 +117,6 @@ static void usb_host_handle_reset(USBDevice *dev)
 #endif
 }
 
-#if 0
 /* XXX:
  * -check device states against transfer requests
  *  and return appropriate response
@@ -256,9 +253,9 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
     }
 
     if (p->pid == USB_TOKEN_IN)
-        ret = read(fd, p->data, p->len);
+        ret = readv(fd, p->iov.iov, p->iov.niov);
     else
-        ret = write(fd, p->data, p->len);
+        ret = writev(fd, p->iov.iov, p->iov.niov);
 
     sigprocmask(SIG_SETMASK, &old_mask, NULL);
 
@@ -278,7 +275,6 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
         return ret;
     }
 }
-#endif
 
 static void usb_host_handle_destroy(USBDevice *opaque)
 {
@@ -305,8 +301,8 @@ static int usb_host_initfn(USBDevice *dev)
 USBDevice *usb_host_device_open(const char *devname)
 {
     struct usb_device_info bus_info, dev_info;
-    USBDevice *d = NULL;
-    USBHostDevice *dev, *ret = NULL;
+    USBDevice *d = NULL, *ret = NULL;
+    USBHostDevice *dev;
     char ctlpath[PATH_MAX + 1];
     char buspath[PATH_MAX + 1];
     int bfd, dfd, bus, address, i;
@@ -408,10 +404,8 @@ static struct USBDeviceInfo usb_host_dev_info = {
     .init           = usb_host_initfn,
     .handle_packet  = usb_generic_handle_packet,
     .handle_reset   = usb_host_handle_reset,
-#if 0
     .handle_control = usb_host_handle_control,
     .handle_data    = usb_host_handle_data,
-#endif
     .handle_destroy = usb_host_handle_destroy,
 };
 
index 53cc5fc00eba5b2a361939c7abf58ac960709eee..5562187bd50a6e65e34df1c8aa3a1711be75c315 100644 (file)
@@ -341,16 +341,16 @@ static void async_complete(void *opaque)
         if (p) {
             switch (aurb->urb.status) {
             case 0:
-                p->len += aurb->urb.actual_length;
+                p->result += aurb->urb.actual_length;
                 break;
 
             case -EPIPE:
                 set_halt(s, p->devep);
-                p->len = USB_RET_STALL;
+                p->result = USB_RET_STALL;
                 break;
 
             default:
-                p->len = USB_RET_NAK;
+                p->result = USB_RET_NAK;
                 break;
             }
 
@@ -604,6 +604,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
 {
     AsyncURB *aurb;
     int i, j, ret, max_packet_size, offset, len = 0;
+    uint8_t *buf;
 
     max_packet_size = get_max_packet_size(s, p->devep);
     if (max_packet_size == 0)
@@ -628,19 +629,19 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
                 len = urb_status_to_usb_ret(
                                         aurb[i].urb.iso_frame_desc[j].status);
             /* Check the frame fits */
-            } else if (aurb[i].urb.iso_frame_desc[j].actual_length > p->len) {
+            } else if (aurb[i].urb.iso_frame_desc[j].actual_length
+                       > p->iov.size) {
                 printf("husb: received iso data is larger then packet\n");
                 len = USB_RET_NAK;
             /* All good copy data over */
             } else {
                 len = aurb[i].urb.iso_frame_desc[j].actual_length;
-                memcpy(p->data,
-                       aurb[i].urb.buffer +
-                           j * aurb[i].urb.iso_frame_desc[0].length,
-                       len);
+                buf  = aurb[i].urb.buffer +
+                    j * aurb[i].urb.iso_frame_desc[0].length;
+                usb_packet_copy(p, buf, len);
             }
         } else {
-            len = p->len;
+            len = p->iov.size;
             offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->devep);
 
             /* Check the frame fits */
@@ -650,7 +651,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
             }
 
             /* All good copy data over */
-            memcpy(aurb[i].urb.buffer + offset, p->data, len);
+            usb_packet_copy(p, aurb[i].urb.buffer + offset, len);
             aurb[i].urb.iso_frame_desc[j].length = len;
             offset += len;
             set_iso_buffer_used(s, p->devep, offset);
@@ -706,7 +707,7 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
     USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
     struct usbdevfs_urb *urb;
     AsyncURB *aurb;
-    int ret, rem;
+    int ret, rem, prem, v;
     uint8_t *pbuf;
     uint8_t ep;
 
@@ -734,10 +735,18 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
         return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
     }
 
-    rem = p->len;
-    pbuf = p->data;
-    p->len = 0;
+    v = 0;
+    prem = p->iov.iov[v].iov_len;
+    pbuf = p->iov.iov[v].iov_base;
+    rem = p->iov.size;
     while (rem) {
+        if (prem == 0) {
+            v++;
+            assert(v < p->iov.niov);
+            prem = p->iov.iov[v].iov_len;
+            pbuf = p->iov.iov[v].iov_base;
+            assert(prem <= rem);
+        }
         aurb = async_alloc(s);
         aurb->packet = p;
 
@@ -746,16 +755,17 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
         urb->type          = USBDEVFS_URB_TYPE_BULK;
         urb->usercontext   = s;
         urb->buffer        = pbuf;
+        urb->buffer_length = prem;
 
-        if (rem > MAX_USBFS_BUFFER_SIZE) {
+        if (urb->buffer_length > MAX_USBFS_BUFFER_SIZE) {
             urb->buffer_length = MAX_USBFS_BUFFER_SIZE;
-            aurb->more         = 1;
-        } else {
-            urb->buffer_length = rem;
-            aurb->more         = 0;
         }
         pbuf += urb->buffer_length;
+        prem -= urb->buffer_length;
         rem  -= urb->buffer_length;
+        if (rem) {
+            aurb->more         = 1;
+        }
 
         ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
 
index e2129931a07582b8edd15aa2a17bb62a7f9ce4a4..9e5fce21eafbf6bb3bf1233727eeabc472eed1d5 100644 (file)
@@ -365,12 +365,12 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
         }
 
         len = isop->len;
-        if (len > p->len) {
+        if (len > p->iov.size) {
             ERROR("received iso data is larger then packet ep %02X\n", ep);
             bufp_free(dev, isop, ep);
             return USB_RET_NAK;
         }
-        memcpy(p->data, isop->data, len);
+        usb_packet_copy(p, isop->data, len);
         bufp_free(dev, isop, ep);
         return len;
     } else {
@@ -379,18 +379,20 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
         if (dev->endpoint[EP2I(ep)].iso_started) {
             struct usb_redir_iso_packet_header iso_packet = {
                 .endpoint = ep,
-                .length = p->len
+                .length = p->iov.size
             };
+            uint8_t buf[p->iov.size];
             /* No id, we look at the ep when receiving a status back */
+            usb_packet_copy(p, buf, p->iov.size);
             usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet,
-                                           p->data, p->len);
+                                           buf, p->iov.size);
             usbredirparser_do_write(dev->parser);
         }
         status = dev->endpoint[EP2I(ep)].iso_error;
         dev->endpoint[EP2I(ep)].iso_error = 0;
-        DPRINTF2("iso-token-out ep %02X status %d len %d\n", ep, status,
-                 p->len);
-        return usbredir_handle_status(dev, status, p->len);
+        DPRINTF2("iso-token-out ep %02X status %d len %zd\n", ep, status,
+                 p->iov.size);
+        return usbredir_handle_status(dev, status, p->iov.size);
     }
 }
 
@@ -413,10 +415,11 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
     AsyncURB *aurb = async_alloc(dev, p);
     struct usb_redir_bulk_packet_header bulk_packet;
 
-    DPRINTF("bulk-out ep %02X len %d id %u\n", ep, p->len, aurb->packet_id);
+    DPRINTF("bulk-out ep %02X len %zd id %u\n", ep,
+            p->iov.size, aurb->packet_id);
 
     bulk_packet.endpoint  = ep;
-    bulk_packet.length    = p->len;
+    bulk_packet.length    = p->iov.size;
     bulk_packet.stream_id = 0;
     aurb->bulk_packet = bulk_packet;
 
@@ -424,9 +427,11 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
         usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
                                         &bulk_packet, NULL, 0);
     } else {
-        usbredir_log_data(dev, "bulk data out:", p->data, p->len);
+        uint8_t buf[p->iov.size];
+        usb_packet_copy(p, buf, p->iov.size);
+        usbredir_log_data(dev, "bulk data out:", buf, p->iov.size);
         usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
-                                        &bulk_packet, p->data, p->len);
+                                        &bulk_packet, buf, p->iov.size);
     }
     usbredirparser_do_write(dev->parser);
     return USB_RET_ASYNC;
@@ -471,29 +476,31 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
         }
 
         len = intp->len;
-        if (len > p->len) {
+        if (len > p->iov.size) {
             ERROR("received int data is larger then packet ep %02X\n", ep);
             bufp_free(dev, intp, ep);
             return USB_RET_NAK;
         }
-        memcpy(p->data, intp->data, len);
+        usb_packet_copy(p, intp->data, len);
         bufp_free(dev, intp, ep);
         return len;
     } else {
         /* Output interrupt endpoint, normal async operation */
         AsyncURB *aurb = async_alloc(dev, p);
         struct usb_redir_interrupt_packet_header interrupt_packet;
+        uint8_t buf[p->iov.size];
 
-        DPRINTF("interrupt-out ep %02X len %d id %u\n", ep, p->len,
+        DPRINTF("interrupt-out ep %02X len %zd id %u\n", ep, p->iov.size,
                 aurb->packet_id);
 
         interrupt_packet.endpoint  = ep;
-        interrupt_packet.length    = p->len;
+        interrupt_packet.length    = p->iov.size;
         aurb->interrupt_packet     = interrupt_packet;
 
-        usbredir_log_data(dev, "interrupt data out:", p->data, p->len);
+        usb_packet_copy(p, buf, p->iov.size);
+        usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size);
         usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id,
-                                        &interrupt_packet, p->data, p->len);
+                                        &interrupt_packet, buf, p->iov.size);
         usbredirparser_do_write(dev->parser);
         return USB_RET_ASYNC;
     }
@@ -959,7 +966,7 @@ static void usbredir_configuration_status(void *priv, uint32_t id,
             dev->dev.data_buf[0] = config_status->configuration;
             len = 1;
         }
-        aurb->packet->len =
+        aurb->packet->result =
             usbredir_handle_status(dev, config_status->status, len);
         usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
     }
@@ -987,7 +994,7 @@ static void usbredir_alt_setting_status(void *priv, uint32_t id,
             dev->dev.data_buf[0] = alt_setting_status->alt;
             len = 1;
         }
-        aurb->packet->len =
+        aurb->packet->result =
             usbredir_handle_status(dev, alt_setting_status->status, len);
         usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
     }
@@ -1070,7 +1077,7 @@ static void usbredir_control_packet(void *priv, uint32_t id,
                 len = USB_RET_STALL;
             }
         }
-        aurb->packet->len = len;
+        aurb->packet->result = len;
         usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
     }
     async_free(dev, aurb);
@@ -1105,15 +1112,15 @@ static void usbredir_bulk_packet(void *priv, uint32_t id,
         len = usbredir_handle_status(dev, bulk_packet->status, len);
         if (len > 0) {
             usbredir_log_data(dev, "bulk data in:", data, data_len);
-            if (data_len <= aurb->packet->len) {
-                memcpy(aurb->packet->data, data, data_len);
+            if (data_len <= aurb->packet->iov.size) {
+                usb_packet_copy(aurb->packet, data, data_len);
             } else {
-                ERROR("bulk buffer too small (%d > %d)\n", data_len,
-                      aurb->packet->len);
+                ERROR("bulk buffer too small (%d > %zd)\n", data_len,
+                      aurb->packet->iov.size);
                 len = USB_RET_STALL;
             }
         }
-        aurb->packet->len = len;
+        aurb->packet->result = len;
         usb_packet_complete(&dev->dev, aurb->packet);
     }
     async_free(dev, aurb);
@@ -1185,7 +1192,7 @@ static void usbredir_interrupt_packet(void *priv, uint32_t id,
         }
 
         if (aurb->packet) {
-            aurb->packet->len = usbredir_handle_status(dev,
+            aurb->packet->result = usbredir_handle_status(dev,
                                                interrupt_packet->status, len);
             usb_packet_complete(&dev->dev, aurb->packet);
         }
index 02c2f8ba43e2abe1f51f1bef792e5a7297c0ecc8..abf688546ec187a905eb84cb97f9eaeeda071313 100644 (file)
@@ -17,7 +17,8 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "config.h"
-#include "exec.h"
+#include "cpu.h"
+#include "dyngen-exec.h"
 #include "disas.h"
 #include "tcg.h"
 
@@ -40,7 +41,7 @@
 static void exception_action(CPUState *env1)
 {
 #if defined(TARGET_I386)
-    raise_exception_err(env1->exception_index, env1->error_code);
+    raise_exception_err_env(env1, env1->exception_index, env1->error_code);
 #else
     cpu_loop_exit(env1);
 #endif
@@ -101,7 +102,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
     }
 
     /* see if it is an MMU fault */
-    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
+    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX);
     if (ret < 0) {
         return 0; /* not an MMU fault */
     }
@@ -628,47 +629,3 @@ int cpu_signal_handler(int host_signum, void *pinfo,
 #error host CPU specific signal handler needed
 
 #endif
-
-#if defined(TARGET_I386)
-
-void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
-{
-    CPUX86State *saved_env;
-
-    saved_env = env;
-    env = s;
-    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
-        selector &= 0xffff;
-        cpu_x86_load_seg_cache(env, seg_reg, selector,
-                               (selector << 4), 0xffff, 0);
-    } else {
-        helper_load_seg(seg_reg, selector);
-    }
-    env = saved_env;
-}
-
-void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
-{
-    CPUX86State *saved_env;
-
-    saved_env = env;
-    env = s;
-
-    helper_fsave(ptr, data32);
-
-    env = saved_env;
-}
-
-void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
-{
-    CPUX86State *saved_env;
-
-    saved_env = env;
-    env = s;
-
-    helper_frstor(ptr, data32);
-
-    env = saved_env;
-}
-
-#endif /* TARGET_I386 */
diff --git a/vl.c b/vl.c
index 4b6688b5536e1f24d05c8be5bd64fd1c2602cae0..c7141274f771362fb91da92839f57a34a6782a09 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -228,6 +228,9 @@ int ctrl_grab = 0;
 unsigned int nb_prom_envs = 0;
 const char *prom_envs[MAX_PROM_ENVS];
 int boot_menu;
+uint8_t *boot_splash_filedata;
+int boot_splash_filedata_size;
+uint8_t qemu_extra_params_fw[2];
 
 typedef struct FWBootEntry FWBootEntry;
 
@@ -262,6 +265,7 @@ int kvm_allowed = 0;
 int xen_allowed = 0;
 uint32_t xen_domid;
 enum xen_mode xen_mode = XEN_EMULATE;
+static int tcg_tb_size;
 
 static int default_serial = 1;
 static int default_parallel = 1;
@@ -293,6 +297,14 @@ static struct {
     { .driver = "qxl-vga",              .flag = &default_vga       },
 };
 
+static void res_free(void)
+{
+    if (boot_splash_filedata != NULL) {
+        qemu_free(boot_splash_filedata);
+        boot_splash_filedata = NULL;
+    }
+}
+
 static int default_driver_check(QemuOpts *opts, void *opaque)
 {
     const char *driver = qemu_opt_get(opts, "driver");
@@ -1921,6 +1933,7 @@ static QEMUMachine *machine_parse(const char *name)
 
 static int tcg_init(void)
 {
+    tcg_exec_init(tcg_tb_size * 1024 * 1024);
     return 0;
 }
 
@@ -2081,7 +2094,6 @@ int main(int argc, char **argv, char **envp)
     const char *loadvm = NULL;
     QEMUMachine *machine;
     const char *cpu_model;
-    int tb_size;
     const char *pid_file = NULL;
     const char *incoming = NULL;
 #ifdef CONFIG_VNC
@@ -2121,7 +2133,6 @@ int main(int argc, char **argv, char **envp)
     nb_numa_nodes = 0;
     nb_nics = 0;
 
-    tb_size = 0;
     autostart= 1;
 
     /* first pass of option parsing */
@@ -2330,7 +2341,8 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_boot:
                 {
                     static const char * const params[] = {
-                        "order", "once", "menu", NULL
+                        "order", "once", "menu",
+                        "splash", "splash-time", NULL
                     };
                     char buf[sizeof(boot_devices)];
                     char *standard_boot_devices;
@@ -2373,6 +2385,8 @@ int main(int argc, char **argv, char **envp)
                                 exit(1);
                             }
                         }
+                        qemu_opts_parse(qemu_find_opts("boot-opts"),
+                                        optarg, 0);
                     }
                 }
                 break;
@@ -2440,11 +2454,6 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
 
-                /* On 32-bit hosts, QEMU is limited by virtual address space */
-                if (value > (2047 << 20) && HOST_LONG_BITS == 32) {
-                    fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n");
-                    exit(1);
-                }
                 if (value != (uint64_t)(ram_addr_t)value) {
                     fprintf(stderr, "qemu: ram size too large\n");
                     exit(1);
@@ -2710,7 +2719,10 @@ int main(int argc, char **argv, char **envp)
                     fprintf(stderr, "parse error: %s\n", optarg);
                     exit(1);
                 }
-                machine = machine_parse(qemu_opt_get(opts, "type"));
+                optarg = qemu_opt_get(opts, "type");
+                if (optarg) {
+                    machine = machine_parse(optarg);
+                }
                 break;
             case QEMU_OPTION_usb:
                 usb_enabled = 1;
@@ -2835,9 +2847,10 @@ int main(int argc, char **argv, char **envp)
                 configure_rtc(opts);
                 break;
             case QEMU_OPTION_tb_size:
-                tb_size = strtol(optarg, NULL, 0);
-                if (tb_size < 0)
-                    tb_size = 0;
+                tcg_tb_size = strtol(optarg, NULL, 0);
+                if (tcg_tb_size < 0) {
+                    tcg_tb_size = 0;
+                }
                 break;
             case QEMU_OPTION_icount:
                 icount_option = optarg;
@@ -3099,11 +3112,19 @@ int main(int argc, char **argv, char **envp)
         exit(1);
 
     /* init the memory */
-    if (ram_size == 0)
+    if (ram_size == 0) {
         ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
+    }
+
+    if (!xen_enabled()) {
+        /* On 32-bit hosts, QEMU is limited by virtual address space */
+        if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) {
+            fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n");
+            exit(1);
+        }
+    }
 
-    /* init the dynamic translator */
-    cpu_exec_init_all(tb_size * 1024 * 1024);
+    cpu_exec_init_all();
 
     bdrv_init_with_whitelist();
 
@@ -3335,6 +3356,7 @@ int main(int argc, char **argv, char **envp)
     main_loop();
     quit_timers();
     net_cleanup();
+    res_free();
 
     return 0;
 }
index 167bed6dbdcd526b422afe80d380a1a407c23306..9eaeac1654581d4db0d23a7fcbd05d0bcc714811 100644 (file)
--- a/xen-all.c
+++ b/xen-all.c
@@ -19,6 +19,7 @@
 
 #include <xen/hvm/ioreq.h>
 #include <xen/hvm/params.h>
+#include <xen/hvm/e820.h>
 
 //#define DEBUG_XEN
 
@@ -144,6 +145,12 @@ static void xen_ram_init(ram_addr_t ram_size)
     new_block->host = NULL;
     new_block->offset = 0;
     new_block->length = ram_size;
+    if (ram_size >= HVM_BELOW_4G_RAM_END) {
+        /* Xen does not allocate the memory continuously, and keep a hole at
+         * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH
+         */
+        new_block->length += HVM_BELOW_4G_MMIO_LENGTH;
+    }
 
     QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
 
@@ -152,20 +159,26 @@ static void xen_ram_init(ram_addr_t ram_size)
     memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
            0xff, new_block->length >> TARGET_PAGE_BITS);
 
-    if (ram_size >= 0xe0000000 ) {
-        above_4g_mem_size = ram_size - 0xe0000000;
-        below_4g_mem_size = 0xe0000000;
+    if (ram_size >= HVM_BELOW_4G_RAM_END) {
+        above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END;
+        below_4g_mem_size = HVM_BELOW_4G_RAM_END;
     } else {
         below_4g_mem_size = ram_size;
     }
 
-    cpu_register_physical_memory(0, below_4g_mem_size, new_block->offset);
-#if TARGET_PHYS_ADDR_BITS > 32
+    cpu_register_physical_memory(0, 0xa0000, 0);
+    /* Skip of the VGA IO memory space, it will be registered later by the VGA
+     * emulated device.
+     *
+     * The area between 0xc0000 and 0x100000 will be used by SeaBIOS to load
+     * the Options ROM, so it is registered here as RAM.
+     */
+    cpu_register_physical_memory(0xc0000, below_4g_mem_size - 0xc0000,
+                                 0xc0000);
     if (above_4g_mem_size > 0) {
         cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
-                                     new_block->offset + below_4g_mem_size);
+                                     0x100000000ULL);
     }
-#endif
 }
 
 void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)
@@ -184,7 +197,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)
     }
 
     if (xc_domain_populate_physmap_exact(xen_xc, xen_domid, nr_pfn, 0, 0, pfn_list)) {
-        hw_error("xen: failed to populate ram at %lx", ram_addr);
+        hw_error("xen: failed to populate ram at " RAM_ADDR_FMT, ram_addr);
     }
 
     qemu_free(pfn_list);
@@ -797,12 +810,17 @@ void xenstore_store_pv_console_info(int i, CharDriverState *chr)
     }
 }
 
-static void xenstore_record_dm_state(XenIOState *s, const char *state)
+static void xenstore_record_dm_state(struct xs_handle *xs, const char *state)
 {
     char path[50];
 
+    if (xs == NULL) {
+        fprintf(stderr, "xenstore connection not initialized\n");
+        exit(1);
+    }
+
     snprintf(path, sizeof (path), "/local/domain/0/device-model/%u/state", xen_domid);
-    if (!xs_write(s->xenstore, XBT_NULL, path, state, strlen(state))) {
+    if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) {
         fprintf(stderr, "error recording dm state\n");
         exit(1);
     }
@@ -823,15 +841,20 @@ static void xen_main_loop_prepare(XenIOState *state)
     if (evtchn_fd != -1) {
         qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
     }
-
-    /* record state running */
-    xenstore_record_dm_state(state, "running");
 }
 
 
 /* Initialise Xen */
 
-static void xen_vm_change_state_handler(void *opaque, int running, int reason)
+static void xen_change_state_handler(void *opaque, int running, int reason)
+{
+    if (running) {
+        /* record state running */
+        xenstore_record_dm_state(xenstore, "running");
+    }
+}
+
+static void xen_hvm_change_state_handler(void *opaque, int running, int reason)
 {
     XenIOState *state = opaque;
     if (running) {
@@ -854,6 +877,7 @@ int xen_init(void)
         xen_be_printf(NULL, 0, "can't open xen interface\n");
         return -1;
     }
+    qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);
 
     return 0;
 }
@@ -915,7 +939,7 @@ int xen_hvm_init(void)
     xen_map_cache_init();
     xen_ram_init(ram_size);
 
-    qemu_add_vm_change_state_handler(xen_vm_change_state_handler, state);
+    qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
 
     state->client = xen_cpu_phys_memory_client;
     QLIST_INIT(&state->physmap);
index 007136af26eb2058ce484917c1e6301fe4ebf001..15d12413d435f8f6c8d1ce17da4fd7318a65166d 100644 (file)
@@ -237,7 +237,7 @@ uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
 
 ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
 {
-    MapCacheEntry *entry = NULL, *pentry = NULL;
+    MapCacheEntry *entry = NULL;
     MapCacheRev *reventry;
     target_phys_addr_t paddr_index;
     target_phys_addr_t size;
@@ -263,7 +263,6 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
 
     entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
     while (entry && (entry->paddr_index != paddr_index || entry->size != size)) {
-        pentry = entry;
         entry = entry->next;
     }
     if (!entry) {