summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--MAINTAINERS32
-rw-r--r--Makefile9
-rw-r--r--Makefile.objs1
-rw-r--r--Makefile.target8
-rw-r--r--QMP/qmp-events.txt3
-rw-r--r--arch_init.c3
-rw-r--r--backends/baum.c2
-rw-r--r--backends/msmouse.c1
-rw-r--r--block.c8
-rw-r--r--block/blkdebug.c3
-rw-r--r--block/curl.c4
-rw-r--r--block/qapi.c148
-rw-r--r--blockdev.c4
-rw-r--r--cmd.c612
-rw-r--r--cmd.h79
-rwxr-xr-xconfigure51
-rw-r--r--cputlb.c4
-rw-r--r--device_tree.c2
-rw-r--r--dump.c12
-rw-r--r--fpu/softfloat-macros.h2
-rw-r--r--gdbstub.c5
-rw-r--r--hmp-commands.hx20
-rw-r--r--hmp.c39
-rw-r--r--hmp.h1
-rw-r--r--hw/acpi/piix4.c12
-rw-r--r--hw/audio/intel-hda.c40
-rw-r--r--hw/char/serial.c128
-rw-r--r--hw/dma/xilinx_axidma.c3
-rw-r--r--hw/i386/pc.c5
-rw-r--r--hw/i386/pc_piix.c18
-rw-r--r--hw/i386/pc_q35.c16
-rw-r--r--hw/i386/smbios.c57
-rw-r--r--hw/ide/core.c1
-rw-r--r--hw/intc/xilinx_intc.c6
-rw-r--r--hw/misc/ivshmem.c1
-rw-r--r--hw/net/vmxnet3.c2
-rw-r--r--hw/net/xilinx_axienet.c2
-rw-r--r--hw/ppc/spapr_rtas.c28
-rw-r--r--hw/s390x/css.c2
-rw-r--r--hw/s390x/virtio-ccw.c8
-rw-r--r--hw/scsi/vmw_pvscsi.c2
-rw-r--r--hw/xen/xen_pt_config_init.c4
-rw-r--r--include/block/block.h3
-rw-r--r--include/block/qapi.h14
-rw-r--r--include/elf.h129
-rw-r--r--include/exec/cpu-defs.h2
-rw-r--r--include/exec/exec-all.h5
-rw-r--r--include/hw/char/serial.h15
-rw-r--r--include/hw/i386/pc.h28
-rw-r--r--include/hw/i386/smbios.h2
-rw-r--r--include/qemu-common.h18
-rw-r--r--include/qemu-io.h46
-rw-r--r--include/qemu/error-report.h1
-rw-r--r--include/qemu/log.h3
-rw-r--r--include/qemu/typedefs.h2
-rw-r--r--include/qom/cpu.h23
-rw-r--r--include/sysemu/char.h2
-rw-r--r--include/sysemu/memory_mapping.h16
-rw-r--r--include/ui/console.h2
-rw-r--r--libcacard/vscclient.c9
-rw-r--r--linux-headers/asm-arm/kvm.h12
-rw-r--r--linux-headers/asm-mips/kvm.h138
-rw-r--r--linux-headers/asm-mips/kvm_para.h1
-rw-r--r--linux-headers/asm-powerpc/kvm.h89
-rw-r--r--linux-headers/asm-x86/kvm.h1
-rw-r--r--linux-headers/linux/kvm.h42
-rw-r--r--linux-headers/linux/vfio.h1
-rw-r--r--linux-headers/linux/vhost.h28
-rw-r--r--linux-user/syscall.c279
-rw-r--r--main-loop.c3
-rw-r--r--memory_mapping-stub.c33
-rw-r--r--memory_mapping.c17
-rw-r--r--monitor.c29
-rw-r--r--net/tap.c18
-rw-r--r--pc-bios/qemu_logo_no_text.svg976
-rw-r--r--qapi-schema.json10
-rw-r--r--qemu-char.c117
-rw-r--r--qemu-img.c20
-rw-r--r--qemu-io-cmds.c2118
-rw-r--r--qemu-io.c1986
-rw-r--r--qmp-commands.hx69
-rw-r--r--qom/cpu.c29
-rw-r--r--spice-qemu-char.c1
-rw-r--r--stubs/Makefile.objs1
-rw-r--r--stubs/dump.c (renamed from dump-stub.c)8
-rw-r--r--target-arm/kvm.c4
-rw-r--r--target-arm/translate.c2
-rw-r--r--target-i386/arch_memory_mapping.c16
-rw-r--r--target-i386/cpu-qom.h3
-rw-r--r--target-i386/cpu.c26
-rw-r--r--target-ppc/kvm.c4
-rw-r--r--target-s390x/kvm.c4
-rw-r--r--target-sparc/cpu.c2
-rw-r--r--tcg/aarch64/tcg-target.c1404
-rw-r--r--tcg/aarch64/tcg-target.h99
-rw-r--r--tcg/arm/tcg-target.c6
-rw-r--r--tcg/i386/tcg-target.c6
-rw-r--r--tcg/s390/tcg-target.c7
-rw-r--r--tests/ide-test.c46
-rw-r--r--tests/qemu-iotests/049.out8
-rw-r--r--translate-all.c2
-rw-r--r--ui/console.c4
-rw-r--r--ui/gtk.c22
-rw-r--r--user-exec.c15
-rw-r--r--util/Makefile.objs2
-rw-r--r--util/cutils.c25
-rw-r--r--util/qemu-openpty.c135
-rw-r--r--vl.c18
-rw-r--r--xen-all.c8
110 files changed, 6344 insertions, 3259 deletions
diff --git a/.gitignore b/.gitignore
index 64e946696c..0fe114d251 100644
--- a/.gitignore
+++ b/.gitignore
@@ -82,7 +82,6 @@ fsdev/virtfs-proxy-helper.pod
*.swp
*.orig
.pc
-*.patch
*.gcda
*.gcno
patches
diff --git a/MAINTAINERS b/MAINTAINERS
index be02724e6e..3412b07c59 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -685,11 +685,12 @@ M: Anthony Liguori <aliguori@us.ibm.com>
S: Supported
F: vl.c
-Monitor (QMP/HMP)
+Human Monitor (HMP)
M: Luiz Capitulino <lcapitulino@redhat.com>
-M: Markus Armbruster <armbru@redhat.com>
S: Supported
F: monitor.c
+F: hmp.c
+F: hmp-commands.hx
Network device layer
M: Anthony Liguori <aliguori@us.ibm.com>
@@ -706,6 +707,27 @@ F: nbd.*
F: qemu-nbd.c
T: git git://github.com/bonzini/qemu.git nbd-next
+QAPI
+M: Luiz Capitulino <lcapitulino@redhat.com>
+M: Michael Roth <mdroth@linux.vnet.ibm.com>
+S: Supported
+F: qapi/
+
+QAPI Schema
+M: Eric Blake <eblake@redhat.com>
+M: Luiz Capitulino <lcapitulino@redhat.com>
+M: Markus Armbruster <armbru@redhat.com>
+S: Supported
+F: qapi-schema.json
+
+QMP
+M: Luiz Capitulino <lcapitulino@redhat.com>
+S: Supported
+F: qmp.c
+F: monitor.c
+F: qmp-commands.hx
+F: QMP/
+
SLIRP
M: Jan Kiszka <jan.kiszka@siemens.com>
S: Maintained
@@ -745,6 +767,12 @@ M: qemu-devel@nongnu.org
S: Maintained
F: tcg/
+AArch64 target
+M: Claudio Fontana <claudio.fontana@huawei.com>
+M: Claudio Fontana <claudio.fontana@gmail.com>
+S: Maintained
+F: tcg/aarch64/
+
ARM target
M: Andrzej Zaborowski <balrogg@gmail.com>
S: Maintained
diff --git a/Makefile b/Makefile
index a96736b06b..3cfa7d0f75 100644
--- a/Makefile
+++ b/Makefile
@@ -186,7 +186,7 @@ qemu-img.o: qemu-img-cmds.h
qemu-img$(EXESUF): qemu-img.o $(block-obj-y) libqemuutil.a libqemustub.a
qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) libqemuutil.a libqemustub.a
-qemu-io$(EXESUF): qemu-io.o cmd.o $(block-obj-y) libqemuutil.a libqemustub.a
+qemu-io$(EXESUF): qemu-io.o $(block-obj-y) libqemuutil.a libqemustub.a
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
@@ -289,7 +289,7 @@ pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \
efi-pcnet.rom efi-rtl8139.rom efi-virtio.rom \
-qemu-icon.bmp \
+qemu-icon.bmp qemu_logo_no_text.svg \
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
multiboot.bin linuxboot.bin kvmvapic.bin \
s390-zipl.rom \
@@ -306,10 +306,13 @@ install-doc: $(DOCS)
$(INSTALL_DATA) QMP/qmp-commands.txt "$(DESTDIR)$(qemu_docdir)"
ifdef CONFIG_POSIX
$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
- $(INSTALL_DATA) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1"
+ $(INSTALL_DATA) qemu.1 "$(DESTDIR)$(mandir)/man1"
+ifneq ($(TOOLS),)
+ $(INSTALL_DATA) qemu-img.1 "$(DESTDIR)$(mandir)/man1"
$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man8"
$(INSTALL_DATA) qemu-nbd.8 "$(DESTDIR)$(mandir)/man8"
endif
+endif
ifdef CONFIG_VIRTFS
$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
$(INSTALL_DATA) fsdev/virtfs-proxy-helper.1 "$(DESTDIR)$(mandir)/man1"
diff --git a/Makefile.objs b/Makefile.objs
index 286ce069b2..5b288ba42f 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -13,6 +13,7 @@ block-obj-$(CONFIG_POSIX) += aio-posix.o
block-obj-$(CONFIG_WIN32) += aio-win32.o
block-obj-y += block/
block-obj-y += qapi-types.o qapi-visit.o
+block-obj-y += qemu-io-cmds.o
block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
block-obj-y += qemu-coroutine-sleep.o
diff --git a/Makefile.target b/Makefile.target
index ce4391fca7..b0be124d29 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -63,8 +63,6 @@ all: $(PROGS) stap
CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
-CONFIG_NO_GET_MEMORY_MAPPING = $(if $(subst n,,$(CONFIG_HAVE_GET_MEMORY_MAPPING)),n,y)
-CONFIG_NO_CORE_DUMP = $(if $(subst n,,$(CONFIG_HAVE_CORE_DUMP)),n,y)
#########################################################
# cpu emulator library
@@ -111,10 +109,8 @@ obj-y += hw/
obj-$(CONFIG_FDT) += device_tree.o
obj-$(CONFIG_KVM) += kvm-all.o
obj-y += memory.o savevm.o cputlb.o
-obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += memory_mapping.o
-obj-$(CONFIG_HAVE_CORE_DUMP) += dump.o
-obj-$(CONFIG_NO_GET_MEMORY_MAPPING) += memory_mapping-stub.o
-obj-$(CONFIG_NO_CORE_DUMP) += dump-stub.o
+obj-y += memory_mapping.o
+obj-y += dump.o
LIBS+=$(libs_softmmu)
# xen support
diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
index 92fe5fb406..24e804e948 100644
--- a/QMP/qmp-events.txt
+++ b/QMP/qmp-events.txt
@@ -203,7 +203,8 @@ Emitted when the guest changes the RTC time.
Data:
-- "offset": delta against the host UTC in seconds (json-number)
+- "offset": Offset between base RTC clock (as specified by -rtc base), and
+new RTC clock value (json-number)
Example:
diff --git a/arch_init.c b/arch_init.c
index 5d32ecf23a..872020e062 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -1029,7 +1029,7 @@ int qemu_uuid_parse(const char *str, uint8_t *uuid)
return -1;
}
#ifdef TARGET_I386
- smbios_add_field(1, offsetof(struct smbios_type_1, uuid), 16, uuid);
+ smbios_add_field(1, offsetof(struct smbios_type_1, uuid), uuid, 16);
#endif
return 0;
}
@@ -1053,7 +1053,6 @@ void do_smbios_option(const char *optarg)
{
#ifdef TARGET_I386
if (smbios_entry_add(optarg) < 0) {
- fprintf(stderr, "Wrong smbios provided\n");
exit(1);
}
#endif
diff --git a/backends/baum.c b/backends/baum.c
index 4cba79fc7d..62aa784436 100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@ -611,8 +611,6 @@ CharDriverState *chr_baum_init(void)
qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
- qemu_chr_be_generic_open(chr);
-
return chr;
fail:
diff --git a/backends/msmouse.c b/backends/msmouse.c
index 0ac05a0d10..c0dbfcdd6b 100644
--- a/backends/msmouse.c
+++ b/backends/msmouse.c
@@ -70,6 +70,7 @@ CharDriverState *qemu_chr_open_msmouse(void)
chr = g_malloc0(sizeof(CharDriverState));
chr->chr_write = msmouse_chr_write;
chr->chr_close = msmouse_chr_close;
+ chr->explicit_be_open = true;
qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse");
diff --git a/block.c b/block.c
index 3f616de974..79ad33d0f9 100644
--- a/block.c
+++ b/block.c
@@ -3186,13 +3186,11 @@ int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event)
{
- BlockDriver *drv = bs->drv;
-
- if (!drv || !drv->bdrv_debug_event) {
+ if (!bs || !bs->drv || !bs->drv->bdrv_debug_event) {
return;
}
- drv->bdrv_debug_event(bs, event);
+ bs->drv->bdrv_debug_event(bs, event);
}
int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
@@ -4024,6 +4022,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
}
/* Write back cached data to the OS even with cache=unsafe */
+ BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_OS);
if (bs->drv->bdrv_co_flush_to_os) {
ret = bs->drv->bdrv_co_flush_to_os(bs);
if (ret < 0) {
@@ -4036,6 +4035,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
goto flush_parent;
}
+ BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_DISK);
if (bs->drv->bdrv_co_flush_to_disk) {
ret = bs->drv->bdrv_co_flush_to_disk(bs);
} else if (bs->drv->bdrv_aio_flush) {
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 71f99e4067..ccb627ad93 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -182,6 +182,9 @@ static const char *event_names[BLKDBG_EVENT_MAX] = {
[BLKDBG_CLUSTER_ALLOC] = "cluster_alloc",
[BLKDBG_CLUSTER_ALLOC_BYTES] = "cluster_alloc_bytes",
[BLKDBG_CLUSTER_FREE] = "cluster_free",
+
+ [BLKDBG_FLUSH_TO_OS] = "flush_to_os",
+ [BLKDBG_FLUSH_TO_DISK] = "flush_to_disk",
};
static int get_event_by_name(const char *name, BlkDebugEvent *event)
diff --git a/block/curl.c b/block/curl.c
index b8935fd991..4dc3b4b71b 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -462,8 +462,8 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags)
// initialize the multi interface!
s->multi = curl_multi_init();
- curl_multi_setopt( s->multi, CURLMOPT_SOCKETDATA, s);
- curl_multi_setopt( s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb );
+ curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s);
+ curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
curl_multi_do(s);
qemu_opts_del(opts);
diff --git a/block/qapi.c b/block/qapi.c
index 794dbf8fe8..a4bc4113b7 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -26,29 +26,56 @@
#include "block/block_int.h"
#include "qmp-commands.h"
-void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info)
+/*
+ * Returns 0 on success, with *p_list either set to describe snapshot
+ * information, or NULL because there are no snapshots. Returns -errno on
+ * error, with *p_list untouched.
+ */
+int bdrv_query_snapshot_info_list(BlockDriverState *bs,
+ SnapshotInfoList **p_list,
+ Error **errp)
{
int i, sn_count;
QEMUSnapshotInfo *sn_tab = NULL;
- SnapshotInfoList *info_list, *cur_item = NULL;
+ SnapshotInfoList *info_list, *cur_item = NULL, *head = NULL;
+ SnapshotInfo *info;
+
sn_count = bdrv_snapshot_list(bs, &sn_tab);
+ if (sn_count < 0) {
+ const char *dev = bdrv_get_device_name(bs);
+ switch (sn_count) {
+ case -ENOMEDIUM:
+ error_setg(errp, "Device '%s' is not inserted", dev);
+ break;
+ case -ENOTSUP:
+ error_setg(errp,
+ "Device '%s' does not support internal snapshots",
+ dev);
+ break;
+ default:
+ error_setg_errno(errp, -sn_count,
+ "Can't list snapshots of device '%s'", dev);
+ break;
+ }
+ return sn_count;
+ }
for (i = 0; i < sn_count; i++) {
- info->has_snapshots = true;
- info_list = g_new0(SnapshotInfoList, 1);
+ info = g_new0(SnapshotInfo, 1);
+ info->id = g_strdup(sn_tab[i].id_str);
+ info->name = g_strdup(sn_tab[i].name);
+ info->vm_state_size = sn_tab[i].vm_state_size;
+ info->date_sec = sn_tab[i].date_sec;
+ info->date_nsec = sn_tab[i].date_nsec;
+ info->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000;
+ info->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000;
- info_list->value = g_new0(SnapshotInfo, 1);
- info_list->value->id = g_strdup(sn_tab[i].id_str);
- info_list->value->name = g_strdup(sn_tab[i].name);
- info_list->value->vm_state_size = sn_tab[i].vm_state_size;
- info_list->value->date_sec = sn_tab[i].date_sec;
- info_list->value->date_nsec = sn_tab[i].date_nsec;
- info_list->value->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000;
- info_list->value->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000;
+ info_list = g_new0(SnapshotInfoList, 1);
+ info_list->value = info;
/* XXX: waiting for the qapi to support qemu-queue.h types */
if (!cur_item) {
- info->snapshots = cur_item = info_list;
+ head = cur_item = info_list;
} else {
cur_item->next = info_list;
cur_item = info_list;
@@ -57,20 +84,40 @@ void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info)
}
g_free(sn_tab);
+ *p_list = head;
+ return 0;
}
-void bdrv_collect_image_info(BlockDriverState *bs,
- ImageInfo *info,
- const char *filename)
+/**
+ * bdrv_query_image_info:
+ * @bs: block device to examine
+ * @p_info: location to store image information
+ * @errp: location to store error information
+ *
+ * Store "flat" image information in @p_info.
+ *
+ * "Flat" means it does *not* query backing image information,
+ * i.e. (*pinfo)->has_backing_image will be set to false and
+ * (*pinfo)->backing_image to NULL even when the image does in fact have
+ * a backing image.
+ *
+ * @p_info will be set only on success. On error, store error in @errp.
+ */
+void bdrv_query_image_info(BlockDriverState *bs,
+ ImageInfo **p_info,
+ Error **errp)
{
uint64_t total_sectors;
- char backing_filename[1024];
+ const char *backing_filename;
char backing_filename2[1024];
BlockDriverInfo bdi;
+ int ret;
+ Error *err = NULL;
+ ImageInfo *info = g_new0(ImageInfo, 1);
bdrv_get_geometry(bs, &total_sectors);
- info->filename = g_strdup(filename);
+ info->filename = g_strdup(bs->filename);
info->format = g_strdup(bdrv_get_format_name(bs));
info->virtual_size = total_sectors * 512;
info->actual_size = bdrv_get_allocated_file_size(bs);
@@ -87,7 +134,7 @@ void bdrv_collect_image_info(BlockDriverState *bs,
info->dirty_flag = bdi.is_dirty;
info->has_dirty_flag = true;
}
- bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
+ backing_filename = bs->backing_file;
if (backing_filename[0] != '\0') {
info->backing_filename = g_strdup(backing_filename);
info->has_backing_filename = true;
@@ -105,11 +152,37 @@ void bdrv_collect_image_info(BlockDriverState *bs,
info->has_backing_filename_format = true;
}
}
+
+ ret = bdrv_query_snapshot_info_list(bs, &info->snapshots, &err);
+ switch (ret) {
+ case 0:
+ if (info->snapshots) {
+ info->has_snapshots = true;
+ }
+ break;
+ /* recoverable error */
+ case -ENOMEDIUM:
+ case -ENOTSUP:
+ error_free(err);
+ break;
+ default:
+ error_propagate(errp, err);
+ qapi_free_ImageInfo(info);
+ return;
+ }
+
+ *p_info = info;
}
-BlockInfo *bdrv_query_info(BlockDriverState *bs)
+/* @p_info will be set only on success. */
+void bdrv_query_info(BlockDriverState *bs,
+ BlockInfo **p_info,
+ Error **errp)
{
BlockInfo *info = g_malloc0(sizeof(*info));
+ BlockDriverState *bs0;
+ ImageInfo **p_image_info;
+ Error *local_err = NULL;
info->device = g_strdup(bs->device_name);
info->type = g_strdup("unknown");
info->locked = bdrv_dev_is_medium_locked(bs);
@@ -163,8 +236,30 @@ BlockInfo *bdrv_query_info(BlockDriverState *bs)
info->inserted->iops_wr =
bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE];
}
+
+ bs0 = bs;
+ p_image_info = &info->inserted->image;
+ while (1) {
+ bdrv_query_image_info(bs0, p_image_info, &local_err);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
+ goto err;
+ }
+ if (bs0->drv && bs0->backing_hd) {
+ bs0 = bs0->backing_hd;
+ (*p_image_info)->has_backing_image = true;
+ p_image_info = &((*p_image_info)->backing_image);
+ } else {
+ break;
+ }
+ }
}
- return info;
+
+ *p_info = info;
+ return;
+
+ err:
+ qapi_free_BlockInfo(info);
}
BlockStats *bdrv_query_stats(const BlockDriverState *bs)
@@ -201,16 +296,25 @@ BlockInfoList *qmp_query_block(Error **errp)
{
BlockInfoList *head = NULL, **p_next = &head;
BlockDriverState *bs = NULL;
+ Error *local_err = NULL;
while ((bs = bdrv_next(bs))) {
BlockInfoList *info = g_malloc0(sizeof(*info));
- info->value = bdrv_query_info(bs);
+ bdrv_query_info(bs, &info->value, &local_err);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
+ goto err;
+ }
*p_next = info;
p_next = &info->next;
}
return head;
+
+ err:
+ qapi_free_BlockInfoList(head);
+ return NULL;
}
BlockStatsList *qmp_query_blockstats(Error **errp)
diff --git a/blockdev.c b/blockdev.c
index b9b2d10e6b..9937311aac 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1180,6 +1180,10 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
*/
if (bdrv_get_attached_dev(bs)) {
bdrv_make_anon(bs);
+
+ /* Further I/O must not pause the guest */
+ bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
+ BLOCKDEV_ON_ERROR_REPORT);
} else {
drive_uninit(drive_get_by_blockdev(bs));
}
diff --git a/cmd.c b/cmd.c
deleted file mode 100644
index 10a8688b2d..0000000000
--- a/cmd.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * Copyright (c) 2003-2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <getopt.h>
-
-#include "cmd.h"
-#include "block/aio.h"
-#include "qemu/main-loop.h"
-
-#define _(x) x /* not gettext support yet */
-
-/* from libxcmd/command.c */
-
-cmdinfo_t *cmdtab;
-int ncmds;
-
-static argsfunc_t args_func;
-static checkfunc_t check_func;
-static int ncmdline;
-static char **cmdline;
-
-static int
-compare(const void *a, const void *b)
-{
- return strcmp(((const cmdinfo_t *)a)->name,
- ((const cmdinfo_t *)b)->name);
-}
-
-void add_command(const cmdinfo_t *ci)
-{
- cmdtab = g_realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
- cmdtab[ncmds - 1] = *ci;
- qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
-}
-
-static int
-check_command(
- const cmdinfo_t *ci)
-{
- if (check_func)
- return check_func(ci);
- return 1;
-}
-
-void
-add_check_command(
- checkfunc_t cf)
-{
- check_func = cf;
-}
-
-int
-command_usage(
- const cmdinfo_t *ci)
-{
- printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
- return 0;
-}
-
-int
-command(
- const cmdinfo_t *ct,
- int argc,
- char **argv)
-{
- char *cmd = argv[0];
-
- if (!check_command(ct))
- return 0;
-
- if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) {
- if (ct->argmax == -1)
- fprintf(stderr,
- _("bad argument count %d to %s, expected at least %d arguments\n"),
- argc-1, cmd, ct->argmin);
- else if (ct->argmin == ct->argmax)
- fprintf(stderr,
- _("bad argument count %d to %s, expected %d arguments\n"),
- argc-1, cmd, ct->argmin);
- else
- fprintf(stderr,
- _("bad argument count %d to %s, expected between %d and %d arguments\n"),
- argc-1, cmd, ct->argmin, ct->argmax);
- return 0;
- }
- optind = 0;
- return ct->cfunc(argc, argv);
-}
-
-const cmdinfo_t *
-find_command(
- const char *cmd)
-{
- cmdinfo_t *ct;
-
- for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
- if (strcmp(ct->name, cmd) == 0 ||
- (ct->altname && strcmp(ct->altname, cmd) == 0))
- return (const cmdinfo_t *)ct;
- }
- return NULL;
-}
-
-void add_user_command(char *optarg)
-{
- cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *));
- cmdline[ncmdline-1] = optarg;
-}
-
-static int
-args_command(
- int index)
-{
- if (args_func)
- return args_func(index);
- return 0;
-}
-
-void
-add_args_command(
- argsfunc_t af)
-{
- args_func = af;
-}
-
-static void prep_fetchline(void *opaque)
-{
- int *fetchable = opaque;
-
- qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
- *fetchable= 1;
-}
-
-static char *get_prompt(void);
-
-void command_loop(void)
-{
- int c, i, j = 0, done = 0, fetchable = 0, prompted = 0;
- char *input;
- char **v;
- const cmdinfo_t *ct;
-
- for (i = 0; !done && i < ncmdline; i++) {
- input = strdup(cmdline[i]);
- if (!input) {
- fprintf(stderr, _("cannot strdup command '%s': %s\n"),
- cmdline[i], strerror(errno));
- exit(1);
- }
- v = breakline(input, &c);
- if (c) {
- ct = find_command(v[0]);
- if (ct) {
- if (ct->flags & CMD_FLAG_GLOBAL) {
- done = command(ct, c, v);
- } else {
- j = 0;
- while (!done && (j = args_command(j))) {
- done = command(ct, c, v);
- }
- }
- } else {
- fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
- }
- }
- doneline(input, v);
- }
- if (cmdline) {
- g_free(cmdline);
- return;
- }
-
- while (!done) {
- if (!prompted) {
- printf("%s", get_prompt());
- fflush(stdout);
- qemu_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, &fetchable);
- prompted = 1;
- }
-
- main_loop_wait(false);
-
- if (!fetchable) {
- continue;
- }
- input = fetchline();
- if (input == NULL) {
- break;
- }
- v = breakline(input, &c);
- if (c) {
- ct = find_command(v[0]);
- if (ct) {
- done = command(ct, c, v);
- } else {
- fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
- }
- }
- doneline(input, v);
-
- prompted = 0;
- fetchable = 0;
- }
- qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
-}
-
-/* from libxcmd/input.c */
-
-#if defined(ENABLE_READLINE)
-# include <readline/history.h>
-# include <readline/readline.h>
-#elif defined(ENABLE_EDITLINE)
-# include <histedit.h>
-#endif
-
-static char *
-get_prompt(void)
-{
- static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ];
-
- if (!prompt[0])
- snprintf(prompt, sizeof(prompt), "%s> ", progname);
- return prompt;
-}
-
-#if defined(ENABLE_READLINE)
-char *
-fetchline(void)
-{
- char *line;
-
- line = readline(get_prompt());
- if (line && *line)
- add_history(line);
- return line;
-}
-#elif defined(ENABLE_EDITLINE)
-static char *el_get_prompt(EditLine *e) { return get_prompt(); }
-char *
-fetchline(void)
-{
- static EditLine *el;
- static History *hist;
- HistEvent hevent;
- char *line;
- int count;
-
- if (!el) {
- hist = history_init();
- history(hist, &hevent, H_SETSIZE, 100);
- el = el_init(progname, stdin, stdout, stderr);
- el_source(el, NULL);
- el_set(el, EL_SIGNAL, 1);
- el_set(el, EL_PROMPT, el_get_prompt);
- el_set(el, EL_HIST, history, (const char *)hist);
- }
- line = strdup(el_gets(el, &count));
- if (line) {
- if (count > 0)
- line[count-1] = '\0';
- if (*line)
- history(hist, &hevent, H_ENTER, line);
- }
- return line;
-}
-#else
-# define MAXREADLINESZ 1024
-char *
-fetchline(void)
-{
- char *p, *line = malloc(MAXREADLINESZ);
-
- if (!line)
- return NULL;
- if (!fgets(line, MAXREADLINESZ, stdin)) {
- free(line);
- return NULL;
- }
- p = line + strlen(line);
- if (p != line && p[-1] == '\n')
- p[-1] = '\0';
- return line;
-}
-#endif
-
-static char *qemu_strsep(char **input, const char *delim)
-{
- char *result = *input;
- if (result != NULL) {
- char *p;
-
- for (p = result; *p != '\0'; p++) {
- if (strchr(delim, *p)) {
- break;
- }
- }
- if (*p == '\0') {
- *input = NULL;
- } else {
- *p = '\0';
- *input = p + 1;
- }
- }
- return result;
-}
-
-char **breakline(char *input, int *count)
-{
- int c = 0;
- char *p;
- char **rval = calloc(sizeof(char *), 1);
- char **tmp;
-
- while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
- if (!*p) {
- continue;
- }
- c++;
- tmp = realloc(rval, sizeof(*rval) * (c + 1));
- if (!tmp) {
- free(rval);
- rval = NULL;
- c = 0;
- break;
- } else {
- rval = tmp;
- }
- rval[c - 1] = p;
- rval[c] = NULL;
- }
- *count = c;
- return rval;
-}
-
-void
-doneline(
- char *input,
- char **vec)
-{
- free(input);
- free(vec);
-}
-
-#define EXABYTES(x) ((long long)(x) << 60)
-#define PETABYTES(x) ((long long)(x) << 50)
-#define TERABYTES(x) ((long long)(x) << 40)
-#define GIGABYTES(x) ((long long)(x) << 30)
-#define MEGABYTES(x) ((long long)(x) << 20)
-#define KILOBYTES(x) ((long long)(x) << 10)
-
-long long
-cvtnum(
- char *s)
-{
- long long i;
- char *sp;
- int c;
-
- i = strtoll(s, &sp, 0);
- if (i == 0 && sp == s)
- return -1LL;
- if (*sp == '\0')
- return i;
-
- if (sp[1] != '\0')
- return -1LL;
-
- c = qemu_tolower(*sp);
- switch (c) {
- default:
- return i;
- case 'k':
- return KILOBYTES(i);
- case 'm':
- return MEGABYTES(i);
- case 'g':
- return GIGABYTES(i);
- case 't':
- return TERABYTES(i);
- case 'p':
- return PETABYTES(i);
- case 'e':
- return EXABYTES(i);
- }
- return -1LL;
-}
-
-#define TO_EXABYTES(x) ((x) / EXABYTES(1))
-#define TO_PETABYTES(x) ((x) / PETABYTES(1))
-#define TO_TERABYTES(x) ((x) / TERABYTES(1))
-#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
-#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
-#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
-
-void
-cvtstr(
- double value,
- char *str,
- size_t size)
-{
- char *trim;
- const char *suffix;
-
- if (value >= EXABYTES(1)) {
- suffix = " EiB";
- snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
- } else if (value >= PETABYTES(1)) {
- suffix = " PiB";
- snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
- } else if (value >= TERABYTES(1)) {
- suffix = " TiB";
- snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
- } else if (value >= GIGABYTES(1)) {
- suffix = " GiB";
- snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
- } else if (value >= MEGABYTES(1)) {
- suffix = " MiB";
- snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
- } else if (value >= KILOBYTES(1)) {
- suffix = " KiB";
- snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
- } else {
- suffix = " bytes";
- snprintf(str, size - 6, "%f", value);
- }
-
- trim = strstr(str, ".000");
- if (trim) {
- strcpy(trim, suffix);
- } else {
- strcat(str, suffix);
- }
-}
-
-struct timeval
-tsub(struct timeval t1, struct timeval t2)
-{
- t1.tv_usec -= t2.tv_usec;
- if (t1.tv_usec < 0) {
- t1.tv_usec += 1000000;
- t1.tv_sec--;
- }
- t1.tv_sec -= t2.tv_sec;
- return t1;
-}
-
-double
-tdiv(double value, struct timeval tv)
-{
- return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
-}
-
-#define HOURS(sec) ((sec) / (60 * 60))
-#define MINUTES(sec) (((sec) % (60 * 60)) / 60)
-#define SECONDS(sec) ((sec) % 60)
-
-void
-timestr(
- struct timeval *tv,
- char *ts,
- size_t size,
- int format)
-{
- double usec = (double)tv->tv_usec / 1000000.0;
-
- if (format & TERSE_FIXED_TIME) {
- if (!HOURS(tv->tv_sec)) {
- snprintf(ts, size, "%u:%02u.%02u",
- (unsigned int) MINUTES(tv->tv_sec),
- (unsigned int) SECONDS(tv->tv_sec),
- (unsigned int) (usec * 100));
- return;
- }
- format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
- }
-
- if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
- snprintf(ts, size, "%u:%02u:%02u.%02u",
- (unsigned int) HOURS(tv->tv_sec),
- (unsigned int) MINUTES(tv->tv_sec),
- (unsigned int) SECONDS(tv->tv_sec),
- (unsigned int) (usec * 100));
- } else {
- snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
- }
-}
-
-
-/* from libxcmd/quit.c */
-
-static cmdinfo_t quit_cmd;
-
-/* ARGSUSED */
-static int
-quit_f(
- int argc,
- char **argv)
-{
- return 1;
-}
-
-void
-quit_init(void)
-{
- quit_cmd.name = _("quit");
- quit_cmd.altname = _("q");
- quit_cmd.cfunc = quit_f;
- quit_cmd.argmin = -1;
- quit_cmd.argmax = -1;
- quit_cmd.flags = CMD_FLAG_GLOBAL;
- quit_cmd.oneline = _("exit the program");
-
- add_command(&quit_cmd);
-}
-
-/* from libxcmd/help.c */
-
-static cmdinfo_t help_cmd;
-static void help_onecmd(const char *cmd, const cmdinfo_t *ct);
-static void help_oneline(const char *cmd, const cmdinfo_t *ct);
-
-static void
-help_all(void)
-{
- const cmdinfo_t *ct;
-
- for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++)
- help_oneline(ct->name, ct);
- printf(_("\nUse 'help commandname' for extended help.\n"));
-}
-
-static int
-help_f(
- int argc,
- char **argv)
-{
- const cmdinfo_t *ct;
-
- if (argc == 1) {
- help_all();
- return 0;
- }
- ct = find_command(argv[1]);
- if (ct == NULL) {
- printf(_("command %s not found\n"), argv[1]);
- return 0;
- }
- help_onecmd(argv[1], ct);
- return 0;
-}
-
-static void
-help_onecmd(
- const char *cmd,
- const cmdinfo_t *ct)
-{
- help_oneline(cmd, ct);
- if (ct->help)
- ct->help();
-}
-
-static void
-help_oneline(
- const char *cmd,
- const cmdinfo_t *ct)
-{
- if (cmd)
- printf("%s ", cmd);
- else {
- printf("%s ", ct->name);
- if (ct->altname)
- printf("(or %s) ", ct->altname);
- }
- if (ct->args)
- printf("%s ", ct->args);
- printf("-- %s\n", ct->oneline);
-}
-
-void
-help_init(void)
-{
- help_cmd.name = _("help");
- help_cmd.altname = _("?");
- help_cmd.cfunc = help_f;
- help_cmd.argmin = 0;
- help_cmd.argmax = 1;
- help_cmd.flags = CMD_FLAG_GLOBAL;
- help_cmd.args = _("[command]");
- help_cmd.oneline = _("help for one or all commands");
-
- add_command(&help_cmd);
-}
diff --git a/cmd.h b/cmd.h
deleted file mode 100644
index b763b198c4..0000000000
--- a/cmd.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __COMMAND_H__
-#define __COMMAND_H__
-
-#define CMD_FLAG_GLOBAL ((int)0x80000000) /* don't iterate "args" */
-
-typedef int (*cfunc_t)(int argc, char **argv);
-typedef void (*helpfunc_t)(void);
-
-typedef struct cmdinfo {
- const char *name;
- const char *altname;
- cfunc_t cfunc;
- int argmin;
- int argmax;
- int canpush;
- int flags;
- const char *args;
- const char *oneline;
- helpfunc_t help;
-} cmdinfo_t;
-
-extern cmdinfo_t *cmdtab;
-extern int ncmds;
-
-void help_init(void);
-void quit_init(void);
-
-typedef int (*argsfunc_t)(int index);
-typedef int (*checkfunc_t)(const cmdinfo_t *ci);
-
-void add_command(const cmdinfo_t *ci);
-void add_user_command(char *optarg);
-void add_args_command(argsfunc_t af);
-void add_check_command(checkfunc_t cf);
-
-const cmdinfo_t *find_command(const char *cmd);
-
-void command_loop(void);
-int command_usage(const cmdinfo_t *ci);
-int command(const cmdinfo_t *ci, int argc, char **argv);
-
-/* from input.h */
-char **breakline(char *input, int *count);
-void doneline(char *input, char **vec);
-char *fetchline(void);
-
-long long cvtnum(char *s);
-void cvtstr(double value, char *str, size_t sz);
-
-struct timeval tsub(struct timeval t1, struct timeval t2);
-double tdiv(double value, struct timeval tv);
-
-enum {
- DEFAULT_TIME = 0x0,
- TERSE_FIXED_TIME = 0x1,
- VERBOSE_FIXED_TIME = 0x2
-};
-
-void timestr(struct timeval *tv, char *str, size_t sz, int flags);
-
-extern char *progname;
-
-#endif /* __COMMAND_H__ */
diff --git a/configure b/configure
index 1654413762..60b0811706 100755
--- a/configure
+++ b/configure
@@ -386,6 +386,8 @@ elif check_define __s390__ ; then
fi
elif check_define __arm__ ; then
cpu="arm"
+elif check_define __aarch64__ ; then
+ cpu="aarch64"
elif check_define __hppa__ ; then
cpu="hppa"
else
@@ -408,6 +410,9 @@ case "$cpu" in
armv*b|armv*l|arm)
cpu="arm"
;;
+ aarch64)
+ cpu="aarch64"
+ ;;
hppa|parisc|parisc64)
cpu="hppa"
;;
@@ -553,7 +558,9 @@ esac
if [ "$bsd" = "yes" ] ; then
if [ "$darwin" != "yes" ] ; then
- usb="bsd"
+ if [ "$targetos" != "FreeBSD" ]; then
+ usb="bsd"
+ fi
bsd_user="yes"
fi
fi
@@ -2557,29 +2564,6 @@ EOF
fi
fi
-#
-# Check for xxxat() functions when we are building linux-user
-# emulator. This is done because older glibc versions don't
-# have syscall stubs for these implemented.
-#
-atfile=no
-cat > $TMPC << EOF
-#define _ATFILE_SOURCE
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-int
-main(void)
-{
- /* try to unlink nonexisting file */
- return (unlinkat(AT_FDCWD, "nonexistent_file", 0));
-}
-EOF
-if compile_prog "" "" ; then
- atfile=yes
-fi
-
# Check for inotify functions when we are building linux-user
# emulator. This is done because older glibc versions don't
# have syscall stubs for these implemented. In that case we
@@ -3556,7 +3540,6 @@ echo "-> Your SDL version is too old - please upgrade to have SDL support"
fi
config_host_mak="config-host.mak"
-config_host_ld="config-host.ld"
echo "# Automatically generated by configure - do not modify" >config-all-disas.mak
@@ -3722,9 +3705,6 @@ fi
if test "$curses" = "yes" ; then
echo "CONFIG_CURSES=y" >> $config_host_mak
fi
-if test "$atfile" = "yes" ; then
- echo "CONFIG_ATFILE=y" >> $config_host_mak
-fi
if test "$utimens" = "yes" ; then
echo "CONFIG_UTIMENSAT=y" >> $config_host_mak
fi
@@ -4071,7 +4051,7 @@ if test "$gcov" = "yes" ; then
fi
# generate list of library paths for linker script
-$ld --verbose -v 2> /dev/null | grep SEARCH_DIR > ${config_host_ld}
+$ld --verbose -v 2> /dev/null | grep SEARCH_DIR > config-host.ld
# use included Linux headers
if test "$linux" = "yes" ; then
@@ -4086,6 +4066,9 @@ if test "$linux" = "yes" ; then
s390x)
linux_arch=s390
;;
+ aarch64)
+ linux_arch=arm64
+ ;;
*)
# For most CPUs the kernel architecture name and QEMU CPU name match.
linux_arch="$cpu"
@@ -4298,19 +4281,11 @@ case "$target_arch2" in
fi
fi
esac
-case "$target_arch2" in
- i386|x86_64)
- echo "CONFIG_HAVE_GET_MEMORY_MAPPING=y" >> $config_target_mak
-esac
if test "$target_bigendian" = "yes" ; then
echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
fi
if test "$target_softmmu" = "yes" ; then
echo "CONFIG_SOFTMMU=y" >> $config_target_mak
- case "$target_arch2" in
- i386|x86_64)
- echo "CONFIG_HAVE_CORE_DUMP=y" >> $config_target_mak
- esac
fi
if test "$target_user_only" = "yes" ; then
echo "CONFIG_USER_ONLY=y" >> $config_target_mak
@@ -4450,7 +4425,7 @@ fi
if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
case "$ARCH" in
- alpha | s390x)
+ alpha | s390x | aarch64)
# The default placement of the application is fine.
;;
*)
diff --git a/cputlb.c b/cputlb.c
index 86666c8d57..1230e9e8ff 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -262,8 +262,8 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
#if defined(DEBUG_TLB)
printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
- " prot=%x idx=%d pd=0x%08lx\n",
- vaddr, paddr, prot, mmu_idx, pd);
+ " prot=%x idx=%d\n",
+ vaddr, paddr, prot, mmu_idx);
#endif
address = vaddr;
diff --git a/device_tree.c b/device_tree.c
index 56af24b397..69be9da8e4 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -213,7 +213,7 @@ uint32_t qemu_devtree_get_phandle(void *fdt, const char *path)
uint32_t r;
r = fdt_get_phandle(fdt, findnode_nofail(fdt, path));
- if (r <= 0) {
+ if (r == 0) {
fprintf(stderr, "%s: Couldn't get phandle for %s: %s\n", __func__,
path, fdt_strerror(r));
exit(1);
diff --git a/dump.c b/dump.c
index c0d3da515b..44a1339c8a 100644
--- a/dump.c
+++ b/dump.c
@@ -21,6 +21,7 @@
#include "sysemu/dump.h"
#include "sysemu/sysemu.h"
#include "sysemu/memory_mapping.h"
+#include "sysemu/cpus.h"
#include "qapi/error.h"
#include "qmp-commands.h"
@@ -706,6 +707,7 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
{
CPUArchState *env;
int nr_cpus;
+ Error *err = NULL;
int ret;
if (runstate_is_running()) {
@@ -731,12 +733,12 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
* If the target architecture is not supported, cpu_get_dump_info() will
* return -1.
*
- * if we use kvm, we should synchronize the register before we get dump
+ * If we use KVM, we should synchronize the registers before we get dump
* info.
*/
+ cpu_synchronize_all_states();
nr_cpus = 0;
for (env = first_cpu; env != NULL; env = env->next_cpu) {
- cpu_synchronize_state(env);
nr_cpus++;
}
@@ -756,7 +758,11 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
/* get memory mapping */
memory_mapping_list_init(&s->list);
if (paging) {
- qemu_get_guest_memory_mapping(&s->list);
+ qemu_get_guest_memory_mapping(&s->list, &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ goto cleanup;
+ }
} else {
qemu_get_guest_simple_memory_mapping(&s->list);
}
diff --git a/fpu/softfloat-macros.h b/fpu/softfloat-macros.h
index b5164af7fa..9b095456c5 100644
--- a/fpu/softfloat-macros.h
+++ b/fpu/softfloat-macros.h
@@ -168,7 +168,7 @@ INLINE void
z0 = a0>>count;
}
else {
- z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0;
+ z1 = (count < 128) ? (a0 >> (count & 63)) : 0;
z0 = 0;
}
*z1Ptr = z1;
diff --git a/gdbstub.c b/gdbstub.c
index 90e54cb4e3..94c78ced56 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -371,7 +371,10 @@ static inline void gdb_continue(GDBState *s)
#ifdef CONFIG_USER_ONLY
s->running_state = 1;
#else
- if (runstate_check(RUN_STATE_DEBUG)) {
+ if (runstate_check(RUN_STATE_GUEST_PANICKED)) {
+ runstate_set(RUN_STATE_DEBUG);
+ }
+ if (!runstate_needs_reset()) {
vm_start();
}
#endif
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 9cea4151b9..915b0d16fa 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -185,6 +185,8 @@ Remove host block device. The result is that guest generated IO is no longer
submitted against the host device underlying the disk. Once a drive has
been deleted, the QEMU Block layer returns -EIO which results in IO
errors in the guest for applications that are reading/writing to the device.
+These errors are always reported to the guest, regardless of the drive's error
+actions (drive options rerror, werror).
ETEXI
{
@@ -989,7 +991,6 @@ server will ask the spice/vnc client to automatically reconnect using the
new parameters (if specified) once the vm migration finished successfully.
ETEXI
-#if defined(CONFIG_HAVE_CORE_DUMP)
{
.name = "dump-guest-memory",
.args_type = "paging:-p,filename:F,begin:i?,length:i?",
@@ -1013,7 +1014,6 @@ gdb.
length: the memory size, in bytes. It's optional, and should be specified
with begin together.
ETEXI
-#endif
{
.name = "snapshot_blkdev",
@@ -1551,6 +1551,22 @@ Removes the chardev @var{id}.
ETEXI
{
+ .name = "qemu-io",
+ .args_type = "device:B,command:s",
+ .params = "[device] \"[command]\"",
+ .help = "run a qemu-io command on a block device",
+ .mhandler.cmd = hmp_qemu_io,
+ },
+
+STEXI
+@item qemu-io @var{device} @var{command}
+@findex qemu-io
+
+Executes a qemu-io command on the given block device.
+
+ETEXI
+
+ {
.name = "info",
.args_type = "item:s?",
.params = "[subcommand]",
diff --git a/hmp.c b/hmp.c
index 4fb76ec7a7..494a9aa459 100644
--- a/hmp.c
+++ b/hmp.c
@@ -22,6 +22,8 @@
#include "qemu/sockets.h"
#include "monitor/monitor.h"
#include "ui/console.h"
+#include "block/qapi.h"
+#include "qemu-io.h"
static void hmp_handle_error(Monitor *mon, Error **errp)
{
@@ -277,10 +279,16 @@ void hmp_info_cpus(Monitor *mon, const QDict *qdict)
void hmp_info_block(Monitor *mon, const QDict *qdict)
{
BlockInfoList *block_list, *info;
+ ImageInfo *image_info;
+ const char *device = qdict_get_try_str(qdict, "device");
+ bool verbose = qdict_get_try_bool(qdict, "verbose", 0);
block_list = qmp_query_block(NULL);
for (info = block_list; info; info = info->next) {
+ if (device && strcmp(device, info->value->device)) {
+ continue;
+ }
monitor_printf(mon, "%s: removable=%d",
info->value->device, info->value->removable);
@@ -318,6 +326,20 @@ void hmp_info_block(Monitor *mon, const QDict *qdict)
info->value->inserted->iops,
info->value->inserted->iops_rd,
info->value->inserted->iops_wr);
+
+ if (verbose) {
+ monitor_printf(mon, " images:\n");
+ image_info = info->value->inserted->image;
+ while (1) {
+ bdrv_image_info_dump((fprintf_function)monitor_printf,
+ mon, image_info);
+ if (image_info->has_backing_image) {
+ image_info = image_info->backing_image;
+ } else {
+ break;
+ }
+ }
+ }
} else {
monitor_printf(mon, " [not inserted]");
}
@@ -1425,3 +1447,20 @@ void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
qmp_chardev_remove(qdict_get_str(qdict, "id"), &local_err);
hmp_handle_error(mon, &local_err);
}
+
+void hmp_qemu_io(Monitor *mon, const QDict *qdict)
+{
+ BlockDriverState *bs;
+ const char* device = qdict_get_str(qdict, "device");
+ const char* command = qdict_get_str(qdict, "command");
+ Error *err = NULL;
+
+ bs = bdrv_find(device);
+ if (bs) {
+ qemuio_command(bs, command);
+ } else {
+ error_set(&err, QERR_DEVICE_NOT_FOUND, device);
+ }
+
+ hmp_handle_error(mon, &err);
+}
diff --git a/hmp.h b/hmp.h
index 95fe76e218..56d2e92aa6 100644
--- a/hmp.h
+++ b/hmp.h
@@ -85,5 +85,6 @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict);
void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict);
void hmp_chardev_add(Monitor *mon, const QDict *qdict);
void hmp_chardev_remove(Monitor *mon, const QDict *qdict);
+void hmp_qemu_io(Monitor *mon, const QDict *qdict);
#endif
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index e6525ac3ba..756df3bee2 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -518,7 +518,7 @@ static uint64_t gpe_readb(void *opaque, hwaddr addr, unsigned width)
PIIX4PMState *s = opaque;
uint32_t val = acpi_gpe_ioport_readb(&s->ar, addr);
- PIIX4_DPRINTF("gpe read %x == %x\n", addr, val);
+ PIIX4_DPRINTF("gpe read %" HWADDR_PRIx " == %" PRIu32 "\n", addr, val);
return val;
}
@@ -530,7 +530,7 @@ static void gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
acpi_gpe_ioport_writeb(&s->ar, addr, val);
pm_update_sci(s);
- PIIX4_DPRINTF("gpe write %x <== %d\n", addr, val);
+ PIIX4_DPRINTF("gpe write %" HWADDR_PRIx " <== %" PRIu64 "\n", addr, val);
}
static const MemoryRegionOps piix4_gpe_ops = {
@@ -553,15 +553,15 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
/* Manufacture an "up" value to cause a device check on any hotplug
* slot with a device. Extra device checks are harmless. */
val = s->pci0_slot_device_present & s->pci0_hotplug_enable;
- PIIX4_DPRINTF("pci_up_read %x\n", val);
+ PIIX4_DPRINTF("pci_up_read %" PRIu32 "\n", val);
break;
case PCI_DOWN_BASE - PCI_HOTPLUG_ADDR:
val = s->pci0_status.down;
- PIIX4_DPRINTF("pci_down_read %x\n", val);
+ PIIX4_DPRINTF("pci_down_read %" PRIu32 "\n", val);
break;
case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
/* No feature defined yet */
- PIIX4_DPRINTF("pci_features_read %x\n", val);
+ PIIX4_DPRINTF("pci_features_read %" PRIu32 "\n", val);
break;
case PCI_RMV_BASE - PCI_HOTPLUG_ADDR:
val = s->pci0_hotplug_enable;
@@ -579,7 +579,7 @@ static void pci_write(void *opaque, hwaddr addr, uint64_t data,
switch (addr) {
case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
acpi_piix_eject_slot(opaque, (uint32_t)data);
- PIIX4_DPRINTF("pciej write %" HWADDR_PRIx " <== % " PRIu64 "\n",
+ PIIX4_DPRINTF("pciej write %" HWADDR_PRIx " <== %" PRIu64 "\n",
addr, data);
break;
default:
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index 1016af0204..3ac90d510d 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -189,6 +189,11 @@ struct IntelHDAState {
uint32_t msi;
};
+#define TYPE_INTEL_HDA_GENERIC "intel-hda-generic"
+
+#define INTEL_HDA(obj) \
+ OBJECT_CHECK(IntelHDAState, (obj), TYPE_INTEL_HDA_GENERIC)
+
struct IntelHDAReg {
const char *name; /* register name */
uint32_t size; /* size in bytes */
@@ -498,7 +503,7 @@ static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool runn
static void intel_hda_set_g_ctl(IntelHDAState *d, const IntelHDAReg *reg, uint32_t old)
{
if ((d->g_ctl & ICH6_GCTL_RESET) == 0) {
- intel_hda_reset(&d->pci.qdev);
+ intel_hda_reset(DEVICE(d));
}
}
@@ -1102,7 +1107,7 @@ static const MemoryRegionOps intel_hda_mmio_ops = {
static void intel_hda_reset(DeviceState *dev)
{
BusChild *kid;
- IntelHDAState *d = DO_UPCAST(IntelHDAState, pci.qdev, dev);
+ IntelHDAState *d = INTEL_HDA(dev);
HDACodecDevice *cdev;
intel_hda_regs_reset(d);
@@ -1120,7 +1125,7 @@ static void intel_hda_reset(DeviceState *dev)
static int intel_hda_init(PCIDevice *pci)
{
- IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
+ IntelHDAState *d = INTEL_HDA(pci);
uint8_t *conf = d->pci.config;
d->name = object_get_typename(OBJECT(d));
@@ -1137,7 +1142,7 @@ static int intel_hda_init(PCIDevice *pci)
msi_init(&d->pci, 0x50, 1, true, false);
}
- hda_codec_bus_init(&d->pci.qdev, &d->codecs,
+ hda_codec_bus_init(DEVICE(pci), &d->codecs,
intel_hda_response, intel_hda_xfer);
return 0;
@@ -1145,7 +1150,7 @@ static int intel_hda_init(PCIDevice *pci)
static void intel_hda_exit(PCIDevice *pci)
{
- IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
+ IntelHDAState *d = INTEL_HDA(pci);
msi_uninit(&d->pci);
memory_region_destroy(&d->mmio);
@@ -1232,7 +1237,7 @@ static Property intel_hda_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
-static void intel_hda_class_init_common(ObjectClass *klass)
+static void intel_hda_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
@@ -1251,7 +1256,6 @@ static void intel_hda_class_init_ich6(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- intel_hda_class_init_common(klass);
k->device_id = 0x2668;
k->revision = 1;
dc->desc = "Intel HD Audio Controller (ich6)";
@@ -1262,23 +1266,28 @@ static void intel_hda_class_init_ich9(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- intel_hda_class_init_common(klass);
k->device_id = 0x293e;
k->revision = 3;
dc->desc = "Intel HD Audio Controller (ich9)";
}
-static const TypeInfo intel_hda_info_ich6 = {
- .name = "intel-hda",
+static const TypeInfo intel_hda_info = {
+ .name = TYPE_INTEL_HDA_GENERIC,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(IntelHDAState),
+ .class_init = intel_hda_class_init,
+ .abstract = true,
+};
+
+static const TypeInfo intel_hda_info_ich6 = {
+ .name = "intel-hda",
+ .parent = TYPE_INTEL_HDA_GENERIC,
.class_init = intel_hda_class_init_ich6,
};
static const TypeInfo intel_hda_info_ich9 = {
.name = "ich9-intel-hda",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(IntelHDAState),
+ .parent = TYPE_INTEL_HDA_GENERIC,
.class_init = intel_hda_class_init_ich9,
};
@@ -1306,12 +1315,12 @@ static const TypeInfo hda_codec_device_type_info = {
*/
static int intel_hda_and_codec_init(PCIBus *bus)
{
- PCIDevice *controller;
+ DeviceState *controller;
BusState *hdabus;
DeviceState *codec;
- controller = pci_create_simple(bus, -1, "intel-hda");
- hdabus = QLIST_FIRST(&controller->qdev.child_bus);
+ controller = DEVICE(pci_create_simple(bus, -1, "intel-hda"));
+ hdabus = QLIST_FIRST(&controller->child_bus);
codec = qdev_create(hdabus, "hda-duplex");
qdev_init_nofail(codec);
return 0;
@@ -1320,6 +1329,7 @@ static int intel_hda_and_codec_init(PCIBus *bus)
static void intel_hda_register_types(void)
{
type_register_static(&hda_codec_bus_info);
+ type_register_static(&intel_hda_info);
type_register_static(&intel_hda_info_ich6);
type_register_static(&intel_hda_info_ich9);
type_register_static(&hda_codec_device_type_info);
diff --git a/hw/char/serial.c b/hw/char/serial.c
index f2701e8c54..b537e426b0 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -92,8 +92,6 @@
#define UART_FCR_RFR 0x02 /* RCVR Fifo Reset */
#define UART_FCR_FE 0x01 /* FIFO Enable */
-#define XMIT_FIFO 0
-#define RECV_FIFO 1
#define MAX_XMIT_RETRY 4
#ifdef DEBUG_SERIAL
@@ -106,50 +104,14 @@ do {} while (0)
static void serial_receive1(void *opaque, const uint8_t *buf, int size);
-static void fifo_clear(SerialState *s, int fifo)
+static inline void recv_fifo_put(SerialState *s, uint8_t chr)
{
- SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
- memset(f->data, 0, UART_FIFO_LENGTH);
- f->count = 0;
- f->head = 0;
- f->tail = 0;
-}
-
-static int fifo_put(SerialState *s, int fifo, uint8_t chr)
-{
- SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
-
/* Receive overruns do not overwrite FIFO contents. */
- if (fifo == XMIT_FIFO || f->count < UART_FIFO_LENGTH) {
-
- f->data[f->head++] = chr;
-
- if (f->head == UART_FIFO_LENGTH)
- f->head = 0;
- }
-
- if (f->count < UART_FIFO_LENGTH)
- f->count++;
- else if (fifo == RECV_FIFO)
+ if (!fifo8_is_full(&s->recv_fifo)) {
+ fifo8_push(&s->recv_fifo, chr);
+ } else {
s->lsr |= UART_LSR_OE;
-
- return 1;
-}
-
-static uint8_t fifo_get(SerialState *s, int fifo)
-{
- SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
- uint8_t c;
-
- if(f->count == 0)
- return 0;
-
- c = f->data[f->tail++];
- if (f->tail == UART_FIFO_LENGTH)
- f->tail = 0;
- f->count--;
-
- return c;
+ }
}
static void serial_update_irq(SerialState *s)
@@ -165,7 +127,7 @@ static void serial_update_irq(SerialState *s)
tmp_iir = UART_IIR_CTI;
} else if ((s->ier & UART_IER_RDI) && (s->lsr & UART_LSR_DR) &&
(!(s->fcr & UART_FCR_FE) ||
- s->recv_fifo.count >= s->recv_fifo.itl)) {
+ s->recv_fifo.num >= s->recv_fifo_itl)) {
tmp_iir = UART_IIR_RDI;
} else if ((s->ier & UART_IER_THRI) && s->thr_ipending) {
tmp_iir = UART_IIR_THRI;
@@ -262,9 +224,11 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
if (s->tsr_retry <= 0) {
if (s->fcr & UART_FCR_FE) {
- s->tsr = fifo_get(s,XMIT_FIFO);
- if (!s->xmit_fifo.count)
+ s->tsr = fifo8_is_full(&s->xmit_fifo) ?
+ 0 : fifo8_pop(&s->xmit_fifo);
+ if (!s->xmit_fifo.num) {
s->lsr |= UART_LSR_THRE;
+ }
} else if ((s->lsr & UART_LSR_THRE)) {
return FALSE;
} else {
@@ -316,16 +280,16 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
} else {
s->thr = (uint8_t) val;
if(s->fcr & UART_FCR_FE) {
- fifo_put(s, XMIT_FIFO, s->thr);
- s->thr_ipending = 0;
+ /* xmit overruns overwrite data, so make space if needed */
+ if (fifo8_is_full(&s->xmit_fifo)) {
+ fifo8_pop(&s->xmit_fifo);
+ }
+ fifo8_push(&s->xmit_fifo, s->thr);
s->lsr &= ~UART_LSR_TEMT;
- s->lsr &= ~UART_LSR_THRE;
- serial_update_irq(s);
- } else {
- s->thr_ipending = 0;
- s->lsr &= ~UART_LSR_THRE;
- serial_update_irq(s);
}
+ s->thr_ipending = 0;
+ s->lsr &= ~UART_LSR_THRE;
+ serial_update_irq(s);
serial_xmit(NULL, G_IO_OUT, s);
}
break;
@@ -367,28 +331,28 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
if (val & UART_FCR_RFR) {
qemu_del_timer(s->fifo_timeout_timer);
s->timeout_ipending=0;
- fifo_clear(s,RECV_FIFO);
+ fifo8_reset(&s->recv_fifo);
}
if (val & UART_FCR_XFR) {
- fifo_clear(s,XMIT_FIFO);
+ fifo8_reset(&s->xmit_fifo);
}
if (val & UART_FCR_FE) {
s->iir |= UART_IIR_FE;
- /* Set RECV_FIFO trigger Level */
+ /* Set recv_fifo trigger Level */
switch (val & 0xC0) {
case UART_FCR_ITL_1:
- s->recv_fifo.itl = 1;
+ s->recv_fifo_itl = 1;
break;
case UART_FCR_ITL_2:
- s->recv_fifo.itl = 4;
+ s->recv_fifo_itl = 4;
break;
case UART_FCR_ITL_3:
- s->recv_fifo.itl = 8;
+ s->recv_fifo_itl = 8;
break;
case UART_FCR_ITL_4:
- s->recv_fifo.itl = 14;
+ s->recv_fifo_itl = 14;
break;
}
} else
@@ -460,11 +424,13 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size)
ret = s->divider & 0xff;
} else {
if(s->fcr & UART_FCR_FE) {
- ret = fifo_get(s,RECV_FIFO);
- if (s->recv_fifo.count == 0)
+ ret = fifo8_is_full(&s->recv_fifo) ?
+ 0 : fifo8_pop(&s->recv_fifo);
+ if (s->recv_fifo.num == 0) {
s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
- else
+ } else {
qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
+ }
s->timeout_ipending = 0;
} else {
ret = s->rbr;
@@ -534,15 +500,21 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size)
static int serial_can_receive(SerialState *s)
{
if(s->fcr & UART_FCR_FE) {
- if(s->recv_fifo.count < UART_FIFO_LENGTH)
- /* Advertise (fifo.itl - fifo.count) bytes when count < ITL, and 1 if above. If UART_FIFO_LENGTH - fifo.count is
- advertised the effect will be to almost always fill the fifo completely before the guest has a chance to respond,
- effectively overriding the ITL that the guest has set. */
- return (s->recv_fifo.count <= s->recv_fifo.itl) ? s->recv_fifo.itl - s->recv_fifo.count : 1;
- else
- return 0;
+ if (s->recv_fifo.num < UART_FIFO_LENGTH) {
+ /*
+ * Advertise (fifo.itl - fifo.count) bytes when count < ITL, and 1
+ * if above. If UART_FIFO_LENGTH - fifo.count is advertised the
+ * effect will be to almost always fill the fifo completely before
+ * the guest has a chance to respond, effectively overriding the ITL
+ * that the guest has set.
+ */
+ return (s->recv_fifo.num <= s->recv_fifo_itl) ?
+ s->recv_fifo_itl - s->recv_fifo.num : 1;
+ } else {
+ return 0;
+ }
} else {
- return !(s->lsr & UART_LSR_DR);
+ return !(s->lsr & UART_LSR_DR);
}
}
@@ -550,7 +522,7 @@ static void serial_receive_break(SerialState *s)
{
s->rbr = 0;
/* When the LSR_DR is set a null byte is pushed into the fifo */
- fifo_put(s, RECV_FIFO, '\0');
+ recv_fifo_put(s, '\0');
s->lsr |= UART_LSR_BI | UART_LSR_DR;
serial_update_irq(s);
}
@@ -558,7 +530,7 @@ static void serial_receive_break(SerialState *s)
/* There's data in recv_fifo and s->rbr has not been read for 4 char transmit times */
static void fifo_timeout_int (void *opaque) {
SerialState *s = opaque;
- if (s->recv_fifo.count) {
+ if (s->recv_fifo.num) {
s->timeout_ipending = 1;
serial_update_irq(s);
}
@@ -580,7 +552,7 @@ static void serial_receive1(void *opaque, const uint8_t *buf, int size)
if(s->fcr & UART_FCR_FE) {
int i;
for (i = 0; i < size; i++) {
- fifo_put(s, RECV_FIFO, buf[i]);
+ recv_fifo_put(s, buf[i]);
}
s->lsr |= UART_LSR_DR;
/* call the timeout receive callback in 4 char transmit time */
@@ -660,8 +632,8 @@ static void serial_reset(void *opaque)
s->char_transmit_time = (get_ticks_per_sec() / 9600) * 10;
s->poll_msl = 0;
- fifo_clear(s,RECV_FIFO);
- fifo_clear(s,XMIT_FIFO);
+ fifo8_reset(&s->recv_fifo);
+ fifo8_reset(&s->xmit_fifo);
s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
@@ -684,6 +656,8 @@ void serial_realize_core(SerialState *s, Error **errp)
qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
serial_event, s);
+ fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
+ fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
}
void serial_exit_core(SerialState *s)
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index 3a3ef8aff3..50054cf851 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -514,8 +514,9 @@ static void axidma_write(void *opaque, hwaddr addr,
break;
}
if (sid == 1 && d->notify) {
- d->notify(d->notify_opaque);
+ StreamCanPushNotifyFn notifytmp = d->notify;
d->notify = NULL;
+ notifytmp(d->notify_opaque);
}
stream_update_irq(s);
}
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 0ad062c093..e0fbb860ed 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -934,6 +934,11 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
DeviceState *icc_bridge;
int64_t apic_id = x86_cpu_apic_id_from_index(id);
+ if (id < 0) {
+ error_setg(errp, "Invalid CPU id: %" PRIi64, id);
+ return;
+ }
+
if (cpu_exists(apic_id)) {
error_setg(errp, "Unable to add CPU: %" PRIi64
", it already exists", id);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index af1e9afb04..97362f2c26 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -327,8 +327,8 @@ static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
}
#endif
-static QEMUMachine pc_i440fx_machine_v1_5 = {
- .name = "pc-i440fx-1.5",
+static QEMUMachine pc_i440fx_machine_v1_6 = {
+ .name = "pc-i440fx-1.6",
.alias = "pc",
.desc = "Standard PC (i440FX + PIIX, 1996)",
.init = pc_init_pci,
@@ -338,6 +338,19 @@ static QEMUMachine pc_i440fx_machine_v1_5 = {
DEFAULT_MACHINE_OPTIONS,
};
+static QEMUMachine pc_i440fx_machine_v1_5 = {
+ .name = "pc-i440fx-1.5",
+ .desc = "Standard PC (i440FX + PIIX, 1996)",
+ .init = pc_init_pci,
+ .hot_add_cpu = pc_hot_add_cpu,
+ .max_cpus = 255,
+ .compat_props = (GlobalProperty[]) {
+ PC_COMPAT_1_5,
+ { /* end of list */ }
+ },
+ DEFAULT_MACHINE_OPTIONS,
+};
+
static QEMUMachine pc_i440fx_machine_v1_4 = {
.name = "pc-i440fx-1.4",
.desc = "Standard PC (i440FX + PIIX, 1996)",
@@ -735,6 +748,7 @@ static QEMUMachine xenfv_machine = {
static void pc_machine_init(void)
{
+ qemu_register_machine(&pc_i440fx_machine_v1_6);
qemu_register_machine(&pc_i440fx_machine_v1_5);
qemu_register_machine(&pc_i440fx_machine_v1_4);
qemu_register_machine(&pc_machine_v1_3);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 7888dfe03f..bb0ce6ae6b 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -215,13 +215,26 @@ static void pc_q35_init_1_4(QEMUMachineInitArgs *args)
pc_q35_init(args);
}
+static QEMUMachine pc_q35_machine_v1_6 = {
+ .name = "pc-q35-1.6",
+ .alias = "q35",
+ .desc = "Standard PC (Q35 + ICH9, 2009)",
+ .init = pc_q35_init,
+ .hot_add_cpu = pc_hot_add_cpu,
+ .max_cpus = 255,
+ DEFAULT_MACHINE_OPTIONS,
+};
+
static QEMUMachine pc_q35_machine_v1_5 = {
.name = "pc-q35-1.5",
- .alias = "q35",
.desc = "Standard PC (Q35 + ICH9, 2009)",
.init = pc_q35_init,
.hot_add_cpu = pc_hot_add_cpu,
.max_cpus = 255,
+ .compat_props = (GlobalProperty[]) {
+ PC_COMPAT_1_5,
+ { /* end of list */ }
+ },
DEFAULT_MACHINE_OPTIONS,
};
@@ -239,6 +252,7 @@ static QEMUMachine pc_q35_machine_v1_4 = {
static void pc_q35_machine_init(void)
{
+ qemu_register_machine(&pc_q35_machine_v1_6);
qemu_register_machine(&pc_q35_machine_v1_5);
qemu_register_machine(&pc_q35_machine_v1_4);
}
diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
index c00bb2fad8..e708cb8919 100644
--- a/hw/i386/smbios.c
+++ b/hw/i386/smbios.c
@@ -13,6 +13,7 @@
* GNU GPL, version 2 or (at your option) any later version.
*/
+#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
#include "hw/i386/smbios.h"
#include "hw/loader.h"
@@ -48,8 +49,7 @@ static int smbios_type4_count = 0;
static void smbios_validate_table(void)
{
if (smbios_type4_count && smbios_type4_count != smp_cpus) {
- fprintf(stderr,
- "Number of SMBIOS Type 4 tables must match cpu count.\n");
+ error_report("Number of SMBIOS Type 4 tables must match cpu count");
exit(1);
}
}
@@ -82,16 +82,16 @@ static void smbios_check_collision(int type, int entry)
if (entry == SMBIOS_TABLE_ENTRY && header->type == SMBIOS_FIELD_ENTRY) {
struct smbios_field *field = (void *)header;
if (type == field->type) {
- fprintf(stderr, "SMBIOS type %d field already defined, "
- "cannot add table\n", type);
+ error_report("SMBIOS type %d field already defined, "
+ "cannot add table", type);
exit(1);
}
} else if (entry == SMBIOS_FIELD_ENTRY &&
header->type == SMBIOS_TABLE_ENTRY) {
struct smbios_structure_header *table = (void *)(header + 1);
if (type == table->type) {
- fprintf(stderr, "SMBIOS type %d table already defined, "
- "cannot add field\n", type);
+ error_report("SMBIOS type %d table already defined, "
+ "cannot add field", type);
exit(1);
}
}
@@ -99,7 +99,7 @@ static void smbios_check_collision(int type, int entry)
}
}
-void smbios_add_field(int type, int offset, int len, void *data)
+void smbios_add_field(int type, int offset, const void *data, size_t len)
{
struct smbios_field *field;
@@ -127,24 +127,29 @@ void smbios_add_field(int type, int offset, int len, void *data)
static void smbios_build_type_0_fields(const char *t)
{
char buf[1024];
+ unsigned char major, minor;
if (get_param_value(buf, sizeof(buf), "vendor", t))
smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str),
- strlen(buf) + 1, buf);
+ buf, strlen(buf) + 1);
if (get_param_value(buf, sizeof(buf), "version", t))
smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str),
- strlen(buf) + 1, buf);
+ buf, strlen(buf) + 1);
if (get_param_value(buf, sizeof(buf), "date", t))
smbios_add_field(0, offsetof(struct smbios_type_0,
bios_release_date_str),
- strlen(buf) + 1, buf);
+ buf, strlen(buf) + 1);
if (get_param_value(buf, sizeof(buf), "release", t)) {
- int major, minor;
- sscanf(buf, "%d.%d", &major, &minor);
+ if (sscanf(buf, "%hhu.%hhu", &major, &minor) != 2) {
+ error_report("Invalid release");
+ exit(1);
+ }
smbios_add_field(0, offsetof(struct smbios_type_0,
- system_bios_major_release), 1, &major);
+ system_bios_major_release),
+ &major, 1);
smbios_add_field(0, offsetof(struct smbios_type_0,
- system_bios_minor_release), 1, &minor);
+ system_bios_minor_release),
+ &minor, 1);
}
}
@@ -154,28 +159,28 @@ static void smbios_build_type_1_fields(const char *t)
if (get_param_value(buf, sizeof(buf), "manufacturer", t))
smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str),
- strlen(buf) + 1, buf);
+ buf, strlen(buf) + 1);
if (get_param_value(buf, sizeof(buf), "product", t))
smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str),
- strlen(buf) + 1, buf);
+ buf, strlen(buf) + 1);
if (get_param_value(buf, sizeof(buf), "version", t))
smbios_add_field(1, offsetof(struct smbios_type_1, version_str),
- strlen(buf) + 1, buf);
+ buf, strlen(buf) + 1);
if (get_param_value(buf, sizeof(buf), "serial", t))
smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str),
- strlen(buf) + 1, buf);
+ buf, strlen(buf) + 1);
if (get_param_value(buf, sizeof(buf), "uuid", t)) {
if (qemu_uuid_parse(buf, qemu_uuid) != 0) {
- fprintf(stderr, "Invalid SMBIOS UUID string\n");
+ error_report("Invalid UUID");
exit(1);
}
}
if (get_param_value(buf, sizeof(buf), "sku", t))
smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str),
- strlen(buf) + 1, buf);
+ buf, strlen(buf) + 1);
if (get_param_value(buf, sizeof(buf), "family", t))
smbios_add_field(1, offsetof(struct smbios_type_1, family_str),
- strlen(buf) + 1, buf);
+ buf, strlen(buf) + 1);
}
int smbios_entry_add(const char *t)
@@ -188,7 +193,7 @@ int smbios_entry_add(const char *t)
int size = get_image_size(buf);
if (size == -1 || size < sizeof(struct smbios_structure_header)) {
- fprintf(stderr, "Cannot read smbios file %s\n", buf);
+ error_report("Cannot read SMBIOS file %s", buf);
exit(1);
}
@@ -204,7 +209,7 @@ int smbios_entry_add(const char *t)
table->header.length = cpu_to_le16(sizeof(*table) + size);
if (load_image(buf, table->data) != size) {
- fprintf(stderr, "Failed to load smbios file %s", buf);
+ error_report("Failed to load SMBIOS file %s", buf);
exit(1);
}
@@ -230,12 +235,12 @@ int smbios_entry_add(const char *t)
smbios_build_type_1_fields(t);
return 0;
default:
- fprintf(stderr, "Don't know how to build fields for SMBIOS type "
- "%ld\n", type);
+ error_report("Don't know how to build fields for SMBIOS type %ld",
+ type);
exit(1);
}
}
- fprintf(stderr, "smbios: must specify type= or file=\n");
+ error_report("Must specify type= or file=");
return -1;
}
diff --git a/hw/ide/core.c b/hw/ide/core.c
index c7a80413be..9926d9202b 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -814,6 +814,7 @@ void ide_flush_cache(IDEState *s)
return;
}
+ s->status |= BUSY_STAT;
bdrv_acct_start(s->bs, &s->acct, 0, BDRV_ACCT_FLUSH);
bdrv_aio_flush(s->bs, ide_flush_cb, s);
}
diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c
index b106e724ab..5df7008e2f 100644
--- a/hw/intc/xilinx_intc.c
+++ b/hw/intc/xilinx_intc.c
@@ -66,11 +66,7 @@ static void update_irq(struct xlx_pic *p)
i = ~0;
p->regs[R_IVR] = i;
- if ((p->regs[R_MER] & 1) && p->regs[R_IPR]) {
- qemu_irq_raise(p->parent_irq);
- } else {
- qemu_irq_lower(p->parent_irq);
- }
+ qemu_set_irq(p->parent_irq, (p->regs[R_MER] & 1) && p->regs[R_IPR]);
}
static uint64_t
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index a19a6d6d8c..5658f733f4 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -735,6 +735,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
if (s->shmobj == NULL) {
fprintf(stderr, "Must specify 'chardev' or 'shm' to ivshmem\n");
+ exit(1);
}
IVSHMEM_DPRINTF("using shm_open (shm object = %s)\n", s->shmobj);
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 5f483e7f1e..4c575e55a7 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -1892,7 +1892,7 @@ static void vmxnet3_net_uninit(VMXNET3State *s)
vmxnet_tx_pkt_reset(s->tx_pkt);
vmxnet_tx_pkt_uninit(s->tx_pkt);
vmxnet_rx_pkt_uninit(s->rx_pkt);
- qemu_del_net_client(qemu_get_queue(s->nic));
+ qemu_del_nic(s->nic);
}
static void vmxnet3_net_init(VMXNET3State *s)
diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
index 8989e95297..2ca1511c06 100644
--- a/hw/net/xilinx_axienet.c
+++ b/hw/net/xilinx_axienet.c
@@ -575,7 +575,7 @@ static void enet_write(void *opaque, hwaddr addr,
break;
case R_MC:
- value &= ((1 < 7) - 1);
+ value &= ((1 << 7) - 1);
/* Enable the MII. */
if (value & MC_EN) {
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 8ecaa5f8ec..f4bd3c9d86 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -130,7 +130,6 @@ static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
uint32_t nret, target_ulong rets)
{
target_ulong id;
- CPUPPCState *env;
CPUState *cpu;
if (nargs != 1 || nret != 2) {
@@ -139,12 +138,8 @@ static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
}
id = rtas_ld(args, 0);
- for (env = first_cpu; env; env = env->next_cpu) {
- cpu = CPU(ppc_env_get_cpu(env));
- if (cpu->cpu_index != id) {
- continue;
- }
-
+ cpu = qemu_get_cpu(id);
+ if (cpu != NULL) {
if (cpu->halted) {
rtas_st(rets, 1, 0);
} else {
@@ -165,8 +160,7 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
uint32_t nret, target_ulong rets)
{
target_ulong id, start, r3;
- CPUState *cpu;
- CPUPPCState *env;
+ CPUState *cs;
if (nargs != 3 || nret != 1) {
rtas_st(rets, 0, -3);
@@ -177,14 +171,12 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
start = rtas_ld(args, 1);
r3 = rtas_ld(args, 2);
- for (env = first_cpu; env; env = env->next_cpu) {
- cpu = CPU(ppc_env_get_cpu(env));
-
- if (cpu->cpu_index != id) {
- continue;
- }
+ cs = qemu_get_cpu(id);
+ if (cs != NULL) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
- if (!cpu->halted) {
+ if (!cs->halted) {
rtas_st(rets, 0, -1);
return;
}
@@ -197,9 +189,9 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
env->nip = start;
env->gpr[3] = r3;
- cpu->halted = 0;
+ cs->halted = 0;
- qemu_cpu_kick(cpu);
+ qemu_cpu_kick(cs);
rtas_st(rets, 0, 0);
return;
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index e526a1c86c..f82abfe029 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -777,7 +777,7 @@ int css_do_tsch(SubchDev *sch, IRB *target_irb)
(p->chars & PMCW_CHARS_MASK_CSENSE)) {
irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF | SCSW_FLAGS_MASK_ECTL;
memcpy(irb.ecw, sch->sense_data, sizeof(sch->sense_data));
- irb.esw[1] = 0x02000000 | (sizeof(sch->sense_data) << 8);
+ irb.esw[1] = 0x01000000 | (sizeof(sch->sense_data) << 8);
}
}
/* Store the irb to the guest. */
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 5f5e267558..44f5772bb2 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -328,10 +328,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EINVAL;
break;
}
- indicators = ldq_phys(ccw.cda);
- if (!indicators) {
+ if (!ccw.cda) {
ret = -EFAULT;
} else {
+ indicators = ldq_phys(ccw.cda);
dev->indicators = indicators;
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
ret = 0;
@@ -348,10 +348,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EINVAL;
break;
}
- indicators = ldq_phys(ccw.cda);
- if (!indicators) {
+ if (!ccw.cda) {
ret = -EFAULT;
} else {
+ indicators = ldq_phys(ccw.cda);
dev->indicators2 = indicators;
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
ret = 0;
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 48d12f42dd..446f72374b 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -389,7 +389,7 @@ pvscsi_process_completion_queue(void *opaque)
QTAILQ_REMOVE(&s->completion_queue, pvscsi_req, next);
pvscsi_cmp_ring_put(s, &pvscsi_req->cmp);
g_free(pvscsi_req);
- has_completed++;
+ has_completed = true;
}
if (has_completed) {
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
index 01872db5b7..8ccc2e4b9c 100644
--- a/hw/xen/xen_pt_config_init.c
+++ b/hw/xen/xen_pt_config_init.c
@@ -1777,12 +1777,12 @@ static int xen_pt_config_reg_init(XenPCIPassthroughState *s,
rc = reg->init(s, reg_entry->reg,
reg_grp->base_offset + reg->offset, &data);
if (rc < 0) {
- free(reg_entry);
+ g_free(reg_entry);
return rc;
}
if (data == XEN_PT_INVALID_REG) {
/* free unused BAR register entry */
- free(reg_entry);
+ g_free(reg_entry);
return 0;
}
/* set register value */
diff --git a/include/block/block.h b/include/block/block.h
index dc5b388d87..2307f67b0e 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -424,6 +424,9 @@ typedef enum {
BLKDBG_CLUSTER_ALLOC_BYTES,
BLKDBG_CLUSTER_FREE,
+ BLKDBG_FLUSH_TO_OS,
+ BLKDBG_FLUSH_TO_DISK,
+
BLKDBG_EVENT_MAX,
} BlkDebugEvent;
diff --git a/include/block/qapi.h b/include/block/qapi.h
index e6e568da94..0496cc9282 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -29,11 +29,15 @@
#include "block/block.h"
#include "block/snapshot.h"
-void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info);
-void bdrv_collect_image_info(BlockDriverState *bs,
- ImageInfo *info,
- const char *filename);
-BlockInfo *bdrv_query_info(BlockDriverState *s);
+int bdrv_query_snapshot_info_list(BlockDriverState *bs,
+ SnapshotInfoList **p_list,
+ Error **errp);
+void bdrv_query_image_info(BlockDriverState *bs,
+ ImageInfo **p_info,
+ Error **errp);
+void bdrv_query_info(BlockDriverState *bs,
+ BlockInfo **p_info,
+ Error **errp);
BlockStats *bdrv_query_stats(const BlockDriverState *bs);
void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
diff --git a/include/elf.h b/include/elf.h
index a21ea535bd..cf0d3e2bd6 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -129,6 +129,8 @@ typedef int64_t Elf64_Sxword;
#define EM_XTENSA 94 /* Tensilica Xtensa */
+#define EM_AARCH64 183
+
/* This is the info that is needed to parse the dynamic section of the file */
#define DT_NULL 0
#define DT_NEEDED 1
@@ -616,6 +618,133 @@ typedef struct {
/* Keep this the last entry. */
#define R_ARM_NUM 256
+/* ARM Aarch64 relocation types */
+#define R_AARCH64_NONE 256 /* also accepts R_ARM_NONE (0) */
+/* static data relocations */
+#define R_AARCH64_ABS64 257
+#define R_AARCH64_ABS32 258
+#define R_AARCH64_ABS16 259
+#define R_AARCH64_PREL64 260
+#define R_AARCH64_PREL32 261
+#define R_AARCH64_PREL16 262
+/* static aarch64 group relocations */
+/* group relocs to create unsigned data value or address inline */
+#define R_AARCH64_MOVW_UABS_G0 263
+#define R_AARCH64_MOVW_UABS_G0_NC 264
+#define R_AARCH64_MOVW_UABS_G1 265
+#define R_AARCH64_MOVW_UABS_G1_NC 266
+#define R_AARCH64_MOVW_UABS_G2 267
+#define R_AARCH64_MOVW_UABS_G2_NC 268
+#define R_AARCH64_MOVW_UABS_G3 269
+/* group relocs to create signed data or offset value inline */
+#define R_AARCH64_MOVW_SABS_G0 270
+#define R_AARCH64_MOVW_SABS_G1 271
+#define R_AARCH64_MOVW_SABS_G2 272
+/* relocs to generate 19, 21, and 33 bit PC-relative addresses */
+#define R_AARCH64_LD_PREL_LO19 273
+#define R_AARCH64_ADR_PREL_LO21 274
+#define R_AARCH64_ADR_PREL_PG_HI21 275
+#define R_AARCH64_ADR_PREL_PG_HI21_NC 276
+#define R_AARCH64_ADD_ABS_LO12_NC 277
+#define R_AARCH64_LDST8_ABS_LO12_NC 278
+#define R_AARCH64_LDST16_ABS_LO12_NC 284
+#define R_AARCH64_LDST32_ABS_LO12_NC 285
+#define R_AARCH64_LDST64_ABS_LO12_NC 286
+#define R_AARCH64_LDST128_ABS_LO12_NC 299
+/* relocs for control-flow - all offsets as multiple of 4 */
+#define R_AARCH64_TSTBR14 279
+#define R_AARCH64_CONDBR19 280
+#define R_AARCH64_JUMP26 282
+#define R_AARCH64_CALL26 283
+/* group relocs to create pc-relative offset inline */
+#define R_AARCH64_MOVW_PREL_G0 287
+#define R_AARCH64_MOVW_PREL_G0_NC 288
+#define R_AARCH64_MOVW_PREL_G1 289
+#define R_AARCH64_MOVW_PREL_G1_NC 290
+#define R_AARCH64_MOVW_PREL_G2 291
+#define R_AARCH64_MOVW_PREL_G2_NC 292
+#define R_AARCH64_MOVW_PREL_G3 293
+/* group relocs to create a GOT-relative offset inline */
+#define R_AARCH64_MOVW_GOTOFF_G0 300
+#define R_AARCH64_MOVW_GOTOFF_G0_NC 301
+#define R_AARCH64_MOVW_GOTOFF_G1 302
+#define R_AARCH64_MOVW_GOTOFF_G1_NC 303
+#define R_AARCH64_MOVW_GOTOFF_G2 304
+#define R_AARCH64_MOVW_GOTOFF_G2_NC 305
+#define R_AARCH64_MOVW_GOTOFF_G3 306
+/* GOT-relative data relocs */
+#define R_AARCH64_GOTREL64 307
+#define R_AARCH64_GOTREL32 308
+/* GOT-relative instr relocs */
+#define R_AARCH64_GOT_LD_PREL19 309
+#define R_AARCH64_LD64_GOTOFF_LO15 310
+#define R_AARCH64_ADR_GOT_PAGE 311
+#define R_AARCH64_LD64_GOT_LO12_NC 312
+#define R_AARCH64_LD64_GOTPAGE_LO15 313
+/* General Dynamic TLS relocations */
+#define R_AARCH64_TLSGD_ADR_PREL21 512
+#define R_AARCH64_TLSGD_ADR_PAGE21 513
+#define R_AARCH64_TLSGD_ADD_LO12_NC 514
+#define R_AARCH64_TLSGD_MOVW_G1 515
+#define R_AARCH64_TLSGD_MOVW_G0_NC 516
+/* Local Dynamic TLS relocations */
+#define R_AARCH64_TLSLD_ADR_PREL21 517
+#define R_AARCH64_TLSLD_ADR_PAGE21 518
+#define R_AARCH64_TLSLD_ADD_LO12_NC 519
+#define R_AARCH64_TLSLD_MOVW_G1 520
+#define R_AARCH64_TLSLD_MOVW_G0_NC 521
+#define R_AARCH64_TLSLD_LD_PREL19 522
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527
+#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538
+/* initial exec TLS relocations */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540
+#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541
+#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542
+#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543
+/* local exec TLS relocations */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548
+#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559
+/* Dynamic Relocations */
+#define R_AARCH64_COPY 1024
+#define R_AARCH64_GLOB_DAT 1025
+#define R_AARCH64_JUMP_SLOT 1026
+#define R_AARCH64_RELATIVE 1027
+#define R_AARCH64_TLS_DTPREL64 1028
+#define R_AARCH64_TLS_DTPMOD64 1029
+#define R_AARCH64_TLS_TPREL64 1030
+#define R_AARCH64_TLS_DTPREL32 1031
+#define R_AARCH64_TLS_DTPMOD32 1032
+#define R_AARCH64_TLS_TPREL32 1033
+
/* s390 relocations defined by the ABIs */
#define R_390_NONE 0 /* No reloc. */
#define R_390_8 1 /* Direct 8 bit. */
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index d8c64e9278..2e5a9bab3c 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -99,7 +99,7 @@ typedef struct CPUTLBEntry {
sizeof(uintptr_t))];
} CPUTLBEntry;
-extern int CPUTLBEntry_wrong_size[sizeof(CPUTLBEntry) == (1 << CPU_TLB_ENTRY_BITS) ? 1 : -1];
+QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
#define CPU_COMMON_TLB \
/* The meaning of the MMU modes is defined in the target code. */ \
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 17fde25c74..b2162a4ec4 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -128,7 +128,7 @@ static inline void tlb_flush(CPUArchState *env, int flush_global)
#if defined(__arm__) || defined(_ARCH_PPC) \
|| defined(__x86_64__) || defined(__i386__) \
- || defined(__sparc__) \
+ || defined(__sparc__) || defined(__aarch64__) \
|| defined(CONFIG_TCG_INTERPRETER)
#define USE_DIRECT_JUMP
#endif
@@ -230,6 +230,9 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
*(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
/* no need to flush icache explicitly */
}
+#elif defined(__aarch64__)
+void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr);
+#define tb_set_jmp_target1 aarch64_tb_set_jmp_target
#elif defined(__arm__)
static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
{
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
index c15354ae05..85f58acd51 100644
--- a/include/hw/char/serial.h
+++ b/include/hw/char/serial.h
@@ -28,17 +28,10 @@
#include "hw/hw.h"
#include "sysemu/sysemu.h"
#include "exec/memory.h"
+#include "qemu/fifo8.h"
#define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */
-typedef struct SerialFIFO {
- uint8_t data[UART_FIFO_LENGTH];
- uint8_t count;
- uint8_t itl; /* Interrupt Trigger Level */
- uint8_t tail;
- uint8_t head;
-} SerialFIFO;
-
struct SerialState {
uint16_t divider;
uint8_t rbr; /* receive register */
@@ -67,8 +60,10 @@ struct SerialState {
/* Time when the last byte was successfully sent out of the tsr */
uint64_t last_xmit_ts;
- SerialFIFO recv_fifo;
- SerialFIFO xmit_fifo;
+ Fifo8 recv_fifo;
+ Fifo8 xmit_fifo;
+ /* Interrupt trigger level for recv_fifo */
+ uint8_t recv_fifo_itl;
struct QEMUTimer *fifo_timeout_timer;
int timeout_ipending; /* timeout interrupt pending state */
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 5d883eb647..7f0496764c 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -189,7 +189,35 @@ int pvpanic_init(ISABus *bus);
int e820_add_entry(uint64_t, uint64_t, uint32_t);
+#define PC_COMPAT_1_5 \
+ {\
+ .driver = "Conroe-" TYPE_X86_CPU,\
+ .property = "model",\
+ .value = stringify(2),\
+ },{\
+ .driver = "Conroe-" TYPE_X86_CPU,\
+ .property = "level",\
+ .value = stringify(2),\
+ },{\
+ .driver = "Penryn-" TYPE_X86_CPU,\
+ .property = "model",\
+ .value = stringify(2),\
+ },{\
+ .driver = "Penryn-" TYPE_X86_CPU,\
+ .property = "level",\
+ .value = stringify(2),\
+ },{\
+ .driver = "Nehalem-" TYPE_X86_CPU,\
+ .property = "model",\
+ .value = stringify(2),\
+ },{\
+ .driver = "Nehalem-" TYPE_X86_CPU,\
+ .property = "level",\
+ .value = stringify(2),\
+ }
+
#define PC_COMPAT_1_4 \
+ PC_COMPAT_1_5, \
{\
.driver = "scsi-hd",\
.property = "discard_granularity",\
diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h
index 94e3641f9a..9babeaf270 100644
--- a/include/hw/i386/smbios.h
+++ b/include/hw/i386/smbios.h
@@ -14,7 +14,7 @@
*/
int smbios_entry_add(const char *t);
-void smbios_add_field(int type, int offset, int len, void *data);
+void smbios_add_field(int type, int offset, const void *data, size_t len);
uint8_t *smbios_get_table(size_t *length);
/*
diff --git a/include/qemu-common.h b/include/qemu-common.h
index cb82ef3d42..3c913758c9 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -42,19 +42,6 @@
#include <signal.h>
#include "glib-compat.h"
-#if defined(__GLIBC__)
-# include <pty.h>
-#elif defined CONFIG_BSD
-# include <termios.h>
-# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-# include <libutil.h>
-# else
-# include <util.h>
-# endif
-#elif defined CONFIG_SOLARIS
-# include <stropts.h>
-#endif
-
#ifdef _WIN32
#include "sysemu/os-win32.h"
#endif
@@ -174,6 +161,7 @@ char *pstrcat(char *buf, int buf_size, const char *s);
int strstart(const char *str, const char *val, const char **ptr);
int stristart(const char *str, const char *val, const char **ptr);
int qemu_strnlen(const char *s, int max_len);
+char *qemu_strsep(char **input, const char *delim);
time_t mktimegm(struct tm *tm);
int qemu_fls(int i);
int qemu_fdatasync(int fd);
@@ -191,6 +179,8 @@ int parse_uint_full(const char *s, unsigned long long *value, int base);
* A-Z, as strtosz() will use qemu_toupper() on the given argument
* prior to comparison.
*/
+#define STRTOSZ_DEFSUFFIX_EB 'E'
+#define STRTOSZ_DEFSUFFIX_PB 'P'
#define STRTOSZ_DEFSUFFIX_TB 'T'
#define STRTOSZ_DEFSUFFIX_GB 'G'
#define STRTOSZ_DEFSUFFIX_MB 'M'
@@ -232,6 +222,8 @@ ssize_t qemu_recv_full(int fd, void *buf, size_t count, int flags)
#ifndef _WIN32
int qemu_pipe(int pipefd[2]);
+/* like openpty() but also makes it raw; return master fd */
+int qemu_openpty_raw(int *aslave, char *pty_name);
#endif
#ifdef _WIN32
diff --git a/include/qemu-io.h b/include/qemu-io.h
new file mode 100644
index 0000000000..a418b46a40
--- /dev/null
+++ b/include/qemu-io.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_IO_H
+#define QEMU_IO_H
+
+#include "qemu-common.h"
+
+#define CMD_FLAG_GLOBAL ((int)0x80000000) /* don't iterate "args" */
+
+typedef int (*cfunc_t)(BlockDriverState *bs, int argc, char **argv);
+typedef void (*helpfunc_t)(void);
+
+typedef struct cmdinfo {
+ const char* name;
+ const char* altname;
+ cfunc_t cfunc;
+ int argmin;
+ int argmax;
+ int canpush;
+ int flags;
+ const char *args;
+ const char *oneline;
+ helpfunc_t help;
+} cmdinfo_t;
+
+bool qemuio_command(BlockDriverState *bs, const char *cmd);
+
+void qemuio_add_command(const cmdinfo_t *ci);
+int qemuio_command_usage(const cmdinfo_t *ci);
+
+#endif /* QEMU_IO_H */
diff --git a/include/qemu/error-report.h b/include/qemu/error-report.h
index c902cc10de..14c1719ad2 100644
--- a/include/qemu/error-report.h
+++ b/include/qemu/error-report.h
@@ -14,6 +14,7 @@
#define QEMU_ERROR_H
#include <stdarg.h>
+#include "qemu/compiler.h"
typedef struct Location {
/* all members are private to qemu-error.c */
diff --git a/include/qemu/log.h b/include/qemu/log.h
index 6b0db02efc..fd76f913eb 100644
--- a/include/qemu/log.h
+++ b/include/qemu/log.h
@@ -2,6 +2,9 @@
#define QEMU_LOG_H
#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include "qemu/compiler.h"
#ifdef NEED_CPU_H
#include "disas/disas.h"
#endif
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index afe4ec76e1..698fc03d78 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -22,6 +22,8 @@ typedef struct AddressSpace AddressSpace;
typedef struct MemoryRegion MemoryRegion;
typedef struct MemoryRegionSection MemoryRegionSection;
+typedef struct MemoryMappingList MemoryMappingList;
+
typedef struct NICInfo NICInfo;
typedef struct HCIInfo HCIInfo;
typedef struct AudioState AudioState;
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 7cd9442503..a5bb515978 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -23,6 +23,7 @@
#include <signal.h>
#include "hw/qdev-core.h"
#include "qemu/thread.h"
+#include "qemu/typedefs.h"
typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque);
@@ -48,6 +49,8 @@ typedef struct CPUState CPUState;
* @reset: Callback to reset the #CPUState to its initial state.
* @do_interrupt: Callback for interrupt handling.
* @get_arch_id: Callback for getting architecture-dependent CPU ID.
+ * @get_paging_enabled: Callback for inquiring whether paging is enabled.
+ * @get_memory_mapping: Callback for obtaining the memory mappings.
* @vmsd: State description for migration.
*
* Represents a CPU family or model.
@@ -62,6 +65,9 @@ typedef struct CPUClass {
void (*reset)(CPUState *cpu);
void (*do_interrupt)(CPUState *cpu);
int64_t (*get_arch_id)(CPUState *cpu);
+ bool (*get_paging_enabled)(const CPUState *cpu);
+ void (*get_memory_mapping)(CPUState *cpu, MemoryMappingList *list,
+ Error **errp);
const struct VMStateDescription *vmsd;
int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
@@ -138,6 +144,23 @@ struct CPUState {
};
/**
+ * cpu_paging_enabled:
+ * @cpu: The CPU whose state is to be inspected.
+ *
+ * Returns: %true if paging is enabled, %false otherwise.
+ */
+bool cpu_paging_enabled(const CPUState *cpu);
+
+/**
+ * cpu_get_memory_mapping:
+ * @cpu: The CPU whose memory mappings are to be obtained.
+ * @list: Where to write the memory mappings to.
+ * @errp: Pointer for reporting an #Error.
+ */
+void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
+ Error **errp);
+
+/**
* cpu_write_elf64_note:
* @f: pointer to a function that writes memory to a file
* @cpu: The CPU whose memory is to be dumped
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 5e42c90df7..066c2161d5 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -70,12 +70,12 @@ struct CharDriverState {
void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
void (*chr_set_fe_open)(struct CharDriverState *chr, int fe_open);
void *opaque;
- int idle_tag;
char *label;
char *filename;
int be_open;
int fe_open;
int explicit_fe_open;
+ int explicit_be_open;
int avail_connections;
QemuOpts *opts;
QTAILQ_ENTRY(CharDriverState) next;
diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h
index 1256125963..6dfb68ddcd 100644
--- a/include/sysemu/memory_mapping.h
+++ b/include/sysemu/memory_mapping.h
@@ -15,6 +15,7 @@
#define MEMORY_MAPPING_H
#include "qemu/queue.h"
+#include "qemu/typedefs.h"
/* The physical and virtual address in the memory mapping are contiguous. */
typedef struct MemoryMapping {
@@ -24,14 +25,11 @@ typedef struct MemoryMapping {
QTAILQ_ENTRY(MemoryMapping) next;
} MemoryMapping;
-typedef struct MemoryMappingList {
+struct MemoryMappingList {
unsigned int num;
MemoryMapping *last_mapping;
QTAILQ_HEAD(, MemoryMapping) head;
-} MemoryMappingList;
-
-int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env);
-bool cpu_paging_enabled(CPUArchState *env);
+};
/*
* add or merge the memory region [phys_addr, phys_addr + length) into the
@@ -47,13 +45,7 @@ void memory_mapping_list_free(MemoryMappingList *list);
void memory_mapping_list_init(MemoryMappingList *list);
-/*
- * Return value:
- * 0: success
- * -1: failed
- * -2: unsupported
- */
-int qemu_get_guest_memory_mapping(MemoryMappingList *list);
+void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp);
/* get guest's memory mapping without do paging(virtual address is 0). */
void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list);
diff --git a/include/ui/console.h b/include/ui/console.h
index 4307b5fe88..f1d79f92a4 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -339,6 +339,6 @@ int index_from_keycode(int code);
/* gtk.c */
void early_gtk_display_init(void);
-void gtk_display_init(DisplayState *ds);
+void gtk_display_init(DisplayState *ds, bool full_screen);
#endif
diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index ac23647236..5180d2945a 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -618,18 +618,22 @@ connect_to_qemu(
if (ret != 0) {
/* Error */
fprintf(stderr, "getaddrinfo failed\n");
- return -1;
+ goto cleanup_socket;
}
if (connect(sock, server->ai_addr, server->ai_addrlen) < 0) {
/* Error */
fprintf(stderr, "Could not connect\n");
- return -1;
+ goto cleanup_socket;
}
if (verbose) {
printf("Connected (sizeof Header=%zd)!\n", sizeof(VSCMsgHeader));
}
return sock;
+
+cleanup_socket:
+ closesocket(sock);
+ return -1;
}
int
@@ -759,5 +763,6 @@ main(
g_io_channel_unref(channel_socket);
g_byte_array_unref(socket_to_send);
+ closesocket(sock);
return 0;
}
diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h
index 023bfeb367..c1ee007523 100644
--- a/linux-headers/asm-arm/kvm.h
+++ b/linux-headers/asm-arm/kvm.h
@@ -53,12 +53,12 @@
#define KVM_ARM_FIQ_spsr fiq_regs[7]
struct kvm_regs {
- struct pt_regs usr_regs;/* R0_usr - R14_usr, PC, CPSR */
- __u32 svc_regs[3]; /* SP_svc, LR_svc, SPSR_svc */
- __u32 abt_regs[3]; /* SP_abt, LR_abt, SPSR_abt */
- __u32 und_regs[3]; /* SP_und, LR_und, SPSR_und */
- __u32 irq_regs[3]; /* SP_irq, LR_irq, SPSR_irq */
- __u32 fiq_regs[8]; /* R8_fiq - R14_fiq, SPSR_fiq */
+ struct pt_regs usr_regs; /* R0_usr - R14_usr, PC, CPSR */
+ unsigned long svc_regs[3]; /* SP_svc, LR_svc, SPSR_svc */
+ unsigned long abt_regs[3]; /* SP_abt, LR_abt, SPSR_abt */
+ unsigned long und_regs[3]; /* SP_und, LR_und, SPSR_und */
+ unsigned long irq_regs[3]; /* SP_irq, LR_irq, SPSR_irq */
+ unsigned long fiq_regs[8]; /* R8_fiq - R14_fiq, SPSR_fiq */
};
/* Supported Processor Types */
diff --git a/linux-headers/asm-mips/kvm.h b/linux-headers/asm-mips/kvm.h
new file mode 100644
index 0000000000..3f424f5217
--- /dev/null
+++ b/linux-headers/asm-mips/kvm.h
@@ -0,0 +1,138 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Cavium, Inc.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#ifndef __LINUX_KVM_MIPS_H
+#define __LINUX_KVM_MIPS_H
+
+#include <linux/types.h>
+
+/*
+ * KVM MIPS specific structures and definitions.
+ *
+ * Some parts derived from the x86 version of this file.
+ */
+
+/*
+ * for KVM_GET_REGS and KVM_SET_REGS
+ *
+ * If Config[AT] is zero (32-bit CPU), the register contents are
+ * stored in the lower 32-bits of the struct kvm_regs fields and sign
+ * extended to 64-bits.
+ */
+struct kvm_regs {
+ /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+ __u64 gpr[32];
+ __u64 hi;
+ __u64 lo;
+ __u64 pc;
+};
+
+/*
+ * for KVM_GET_FPU and KVM_SET_FPU
+ *
+ * If Status[FR] is zero (32-bit FPU), the upper 32-bits of the FPRs
+ * are zero filled.
+ */
+struct kvm_fpu {
+ __u64 fpr[32];
+ __u32 fir;
+ __u32 fccr;
+ __u32 fexr;
+ __u32 fenr;
+ __u32 fcsr;
+ __u32 pad;
+};
+
+
+/*
+ * For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access CP0
+ * registers. The id field is broken down as follows:
+ *
+ * bits[2..0] - Register 'sel' index.
+ * bits[7..3] - Register 'rd' index.
+ * bits[15..8] - Must be zero.
+ * bits[63..16] - 1 -> CP0 registers.
+ *
+ * Other sets registers may be added in the future. Each set would
+ * have its own identifier in bits[63..16].
+ *
+ * The addr field of struct kvm_one_reg must point to an aligned
+ * 64-bit wide location. For registers that are narrower than
+ * 64-bits, the value is stored in the low order bits of the location,
+ * and sign extended to 64-bits.
+ *
+ * The registers defined in struct kvm_regs are also accessible, the
+ * id values for these are below.
+ */
+
+#define KVM_REG_MIPS_R0 0
+#define KVM_REG_MIPS_R1 1
+#define KVM_REG_MIPS_R2 2
+#define KVM_REG_MIPS_R3 3
+#define KVM_REG_MIPS_R4 4
+#define KVM_REG_MIPS_R5 5
+#define KVM_REG_MIPS_R6 6
+#define KVM_REG_MIPS_R7 7
+#define KVM_REG_MIPS_R8 8
+#define KVM_REG_MIPS_R9 9
+#define KVM_REG_MIPS_R10 10
+#define KVM_REG_MIPS_R11 11
+#define KVM_REG_MIPS_R12 12
+#define KVM_REG_MIPS_R13 13
+#define KVM_REG_MIPS_R14 14
+#define KVM_REG_MIPS_R15 15
+#define KVM_REG_MIPS_R16 16
+#define KVM_REG_MIPS_R17 17
+#define KVM_REG_MIPS_R18 18
+#define KVM_REG_MIPS_R19 19
+#define KVM_REG_MIPS_R20 20
+#define KVM_REG_MIPS_R21 21
+#define KVM_REG_MIPS_R22 22
+#define KVM_REG_MIPS_R23 23
+#define KVM_REG_MIPS_R24 24
+#define KVM_REG_MIPS_R25 25
+#define KVM_REG_MIPS_R26 26
+#define KVM_REG_MIPS_R27 27
+#define KVM_REG_MIPS_R28 28
+#define KVM_REG_MIPS_R29 29
+#define KVM_REG_MIPS_R30 30
+#define KVM_REG_MIPS_R31 31
+
+#define KVM_REG_MIPS_HI 32
+#define KVM_REG_MIPS_LO 33
+#define KVM_REG_MIPS_PC 34
+
+/*
+ * KVM MIPS specific structures and definitions
+ *
+ */
+struct kvm_debug_exit_arch {
+ __u64 epc;
+};
+
+/* for KVM_SET_GUEST_DEBUG */
+struct kvm_guest_debug_arch {
+};
+
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
+/* dummy definition */
+struct kvm_sregs {
+};
+
+struct kvm_mips_interrupt {
+ /* in */
+ __u32 cpu;
+ __u32 irq;
+};
+
+#endif /* __LINUX_KVM_MIPS_H */
diff --git a/linux-headers/asm-mips/kvm_para.h b/linux-headers/asm-mips/kvm_para.h
new file mode 100644
index 0000000000..14fab8f0b9
--- /dev/null
+++ b/linux-headers/asm-mips/kvm_para.h
@@ -0,0 +1 @@
+#include <asm-generic/kvm_para.h>
diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index ef072b1a6e..0fb1a6e9ff 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -25,6 +25,8 @@
/* Select powerpc specific features in <linux/kvm.h> */
#define __KVM_HAVE_SPAPR_TCE
#define __KVM_HAVE_PPC_SMT
+#define __KVM_HAVE_IRQCHIP
+#define __KVM_HAVE_IRQ_LINE
struct kvm_regs {
__u64 pc;
@@ -272,8 +274,31 @@ struct kvm_debug_exit_arch {
/* for KVM_SET_GUEST_DEBUG */
struct kvm_guest_debug_arch {
+ struct {
+ /* H/W breakpoint/watchpoint address */
+ __u64 addr;
+ /*
+ * Type denotes h/w breakpoint, read watchpoint, write
+ * watchpoint or watchpoint (both read and write).
+ */
+#define KVMPPC_DEBUG_NONE 0x0
+#define KVMPPC_DEBUG_BREAKPOINT (1UL << 1)
+#define KVMPPC_DEBUG_WATCH_WRITE (1UL << 2)
+#define KVMPPC_DEBUG_WATCH_READ (1UL << 3)
+ __u32 type;
+ __u32 reserved;
+ } bp[16];
};
+/* Debug related defines */
+/*
+ * kvm_guest_debug->control is a 32 bit field. The lower 16 bits are generic
+ * and upper 16 bits are architecture specific. Architecture specific defines
+ * that ioctl is for setting hardware breakpoint or software breakpoint.
+ */
+#define KVM_GUESTDBG_USE_SW_BP 0x00010000
+#define KVM_GUESTDBG_USE_HW_BP 0x00020000
+
/* definition of registers in kvm_run */
struct kvm_sync_regs {
};
@@ -299,6 +324,12 @@ struct kvm_allocate_rma {
__u64 rma_size;
};
+/* for KVM_CAP_PPC_RTAS */
+struct kvm_rtas_token_args {
+ char name[120];
+ __u64 token; /* Use a token of 0 to undefine a mapping */
+};
+
struct kvm_book3e_206_tlb_entry {
__u32 mas8;
__u32 mas1;
@@ -359,6 +390,26 @@ struct kvm_get_htab_header {
__u16 n_invalid;
};
+/* Per-vcpu XICS interrupt controller state */
+#define KVM_REG_PPC_ICP_STATE (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8c)
+
+#define KVM_REG_PPC_ICP_CPPR_SHIFT 56 /* current proc priority */
+#define KVM_REG_PPC_ICP_CPPR_MASK 0xff
+#define KVM_REG_PPC_ICP_XISR_SHIFT 32 /* interrupt status field */
+#define KVM_REG_PPC_ICP_XISR_MASK 0xffffff
+#define KVM_REG_PPC_ICP_MFRR_SHIFT 24 /* pending IPI priority */
+#define KVM_REG_PPC_ICP_MFRR_MASK 0xff
+#define KVM_REG_PPC_ICP_PPRI_SHIFT 16 /* pending irq priority */
+#define KVM_REG_PPC_ICP_PPRI_MASK 0xff
+
+/* Device control API: PPC-specific devices */
+#define KVM_DEV_MPIC_GRP_MISC 1
+#define KVM_DEV_MPIC_BASE_ADDR 0 /* 64-bit */
+
+#define KVM_DEV_MPIC_GRP_REGISTER 2 /* 32-bit */
+#define KVM_DEV_MPIC_GRP_IRQ_ACTIVE 3 /* 32-bit */
+
+/* One-Reg API: PPC-specific registers */
#define KVM_REG_PPC_HIOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
#define KVM_REG_PPC_IAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x2)
#define KVM_REG_PPC_IAC2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3)
@@ -422,4 +473,42 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_CLEAR_TSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x88)
#define KVM_REG_PPC_TCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x89)
#define KVM_REG_PPC_TSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8a)
+
+/* Debugging: Special instruction for software breakpoint */
+#define KVM_REG_PPC_DEBUG_INST (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8b)
+
+/* MMU registers */
+#define KVM_REG_PPC_MAS0 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8c)
+#define KVM_REG_PPC_MAS1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8d)
+#define KVM_REG_PPC_MAS2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8e)
+#define KVM_REG_PPC_MAS7_3 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8f)
+#define KVM_REG_PPC_MAS4 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x90)
+#define KVM_REG_PPC_MAS6 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x91)
+#define KVM_REG_PPC_MMUCFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x92)
+/*
+ * TLBnCFG fields TLBnCFG_N_ENTRY and TLBnCFG_ASSOC can be changed only using
+ * KVM_CAP_SW_TLB ioctl
+ */
+#define KVM_REG_PPC_TLB0CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x93)
+#define KVM_REG_PPC_TLB1CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x94)
+#define KVM_REG_PPC_TLB2CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x95)
+#define KVM_REG_PPC_TLB3CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x96)
+#define KVM_REG_PPC_TLB0PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x97)
+#define KVM_REG_PPC_TLB1PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x98)
+#define KVM_REG_PPC_TLB2PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x99)
+#define KVM_REG_PPC_TLB3PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9a)
+#define KVM_REG_PPC_EPTCFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9b)
+
+/* PPC64 eXternal Interrupt Controller Specification */
+#define KVM_DEV_XICS_GRP_SOURCES 1 /* 64-bit source attributes */
+
+/* Layout of 64-bit source attribute values */
+#define KVM_XICS_DESTINATION_SHIFT 0
+#define KVM_XICS_DESTINATION_MASK 0xffffffffULL
+#define KVM_XICS_PRIORITY_SHIFT 32
+#define KVM_XICS_PRIORITY_MASK 0xff
+#define KVM_XICS_LEVEL_SENSITIVE (1ULL << 40)
+#define KVM_XICS_MASKED (1ULL << 41)
+#define KVM_XICS_PENDING (1ULL << 42)
+
#endif /* __LINUX_KVM_POWERPC_H */
diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h
index a65ec29e6f..5d9a3033b3 100644
--- a/linux-headers/asm-x86/kvm.h
+++ b/linux-headers/asm-x86/kvm.h
@@ -29,7 +29,6 @@
#define __KVM_HAVE_PIT
#define __KVM_HAVE_IOAPIC
#define __KVM_HAVE_IRQ_LINE
-#define __KVM_HAVE_DEVICE_ASSIGNMENT
#define __KVM_HAVE_MSI
#define __KVM_HAVE_USER_NMI
#define __KVM_HAVE_GUEST_DEBUG
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index eb02d8a837..c614070662 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -561,9 +561,7 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_MP_STATE 14
#define KVM_CAP_COALESCED_MMIO 15
#define KVM_CAP_SYNC_MMU 16 /* Changes to host mmap are reflected in guest */
-#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
#define KVM_CAP_DEVICE_ASSIGNMENT 17
-#endif
#define KVM_CAP_IOMMU 18
#ifdef __KVM_HAVE_MSI
#define KVM_CAP_DEVICE_MSI 20
@@ -579,13 +577,9 @@ struct kvm_ppc_smmu_info {
#ifdef __KVM_HAVE_PIT
#define KVM_CAP_REINJECT_CONTROL 24
#endif
-#ifdef __KVM_HAVE_IOAPIC
#define KVM_CAP_IRQ_ROUTING 25
-#endif
#define KVM_CAP_IRQ_INJECT_STATUS 26
-#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
#define KVM_CAP_DEVICE_DEASSIGNMENT 27
-#endif
#ifdef __KVM_HAVE_MSIX
#define KVM_CAP_DEVICE_MSIX 28
#endif
@@ -668,6 +662,10 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_PPC_EPR 86
#define KVM_CAP_ARM_PSCI 87
#define KVM_CAP_ARM_SET_DEVICE_ADDR 88
+#define KVM_CAP_DEVICE_CTRL 89
+#define KVM_CAP_IRQ_MPIC 90
+#define KVM_CAP_PPC_RTAS 91
+#define KVM_CAP_IRQ_XICS 92
#ifdef KVM_CAP_IRQ_ROUTING
@@ -821,6 +819,28 @@ struct kvm_arm_device_addr {
};
/*
+ * Device control API, available with KVM_CAP_DEVICE_CTRL
+ */
+#define KVM_CREATE_DEVICE_TEST 1
+
+struct kvm_create_device {
+ __u32 type; /* in: KVM_DEV_TYPE_xxx */
+ __u32 fd; /* out: device handle */
+ __u32 flags; /* in: KVM_CREATE_DEVICE_xxx */
+};
+
+struct kvm_device_attr {
+ __u32 flags; /* no flags currently defined */
+ __u32 group; /* device-defined */
+ __u64 attr; /* group-defined */
+ __u64 addr; /* userspace address of attr data */
+};
+
+#define KVM_DEV_TYPE_FSL_MPIC_20 1
+#define KVM_DEV_TYPE_FSL_MPIC_42 2
+#define KVM_DEV_TYPE_XICS 3
+
+/*
* ioctls for VM fds
*/
#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 0x40, struct kvm_memory_region)
@@ -907,6 +927,16 @@ struct kvm_s390_ucas_mapping {
#define KVM_PPC_GET_HTAB_FD _IOW(KVMIO, 0xaa, struct kvm_get_htab_fd)
/* Available with KVM_CAP_ARM_SET_DEVICE_ADDR */
#define KVM_ARM_SET_DEVICE_ADDR _IOW(KVMIO, 0xab, struct kvm_arm_device_addr)
+/* Available with KVM_CAP_PPC_RTAS */
+#define KVM_PPC_RTAS_DEFINE_TOKEN _IOW(KVMIO, 0xac, struct kvm_rtas_token_args)
+
+/* ioctl for vm fd */
+#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)
+
+/* ioctls for fds returned by KVM_CREATE_DEVICE */
+#define KVM_SET_DEVICE_ATTR _IOW(KVMIO, 0xe1, struct kvm_device_attr)
+#define KVM_GET_DEVICE_ATTR _IOW(KVMIO, 0xe2, struct kvm_device_attr)
+#define KVM_HAS_DEVICE_ATTR _IOW(KVMIO, 0xe3, struct kvm_device_attr)
/*
* ioctls for vcpu fds
diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index e094121ee7..7ec1864765 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -319,6 +319,7 @@ enum {
VFIO_PCI_INTX_IRQ_INDEX,
VFIO_PCI_MSI_IRQ_INDEX,
VFIO_PCI_MSIX_IRQ_INDEX,
+ VFIO_PCI_ERR_IRQ_INDEX,
VFIO_PCI_NUM_IRQS
};
diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h
index 165a4848c6..c656f61cfc 100644
--- a/linux-headers/linux/vhost.h
+++ b/linux-headers/linux/vhost.h
@@ -127,4 +127,32 @@ struct vhost_memory {
/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
#define VHOST_NET_F_VIRTIO_NET_HDR 27
+/* VHOST_SCSI specific definitions */
+
+/*
+ * Used by QEMU userspace to ensure a consistent vhost-scsi ABI.
+ *
+ * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate +
+ * RFC-v2 vhost-scsi userspace. Add GET_ABI_VERSION ioctl usage
+ * ABI Rev 1: January 2013. Ignore vhost_tpgt filed in struct vhost_scsi_target.
+ * All the targets under vhost_wwpn can be seen and used by guset.
+ */
+
+#define VHOST_SCSI_ABI_VERSION 1
+
+struct vhost_scsi_target {
+ int abi_version;
+ char vhost_wwpn[224]; /* TRANSPORT_IQN_LEN */
+ unsigned short vhost_tpgt;
+ unsigned short reserved;
+};
+
+#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
+#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
+/* Changing this breaks userspace. */
+#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int)
+/* Set and get the events missed flag */
+#define VHOST_SCSI_SET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x43, __u32)
+#define VHOST_SCSI_GET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x44, __u32)
+
#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 0099d64a9c..cdd0c28fff 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -181,29 +181,14 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
#define __NR_sys_uname __NR_uname
-#define __NR_sys_faccessat __NR_faccessat
-#define __NR_sys_fchmodat __NR_fchmodat
-#define __NR_sys_fchownat __NR_fchownat
-#define __NR_sys_fstatat64 __NR_fstatat64
-#define __NR_sys_futimesat __NR_futimesat
#define __NR_sys_getcwd1 __NR_getcwd
#define __NR_sys_getdents __NR_getdents
#define __NR_sys_getdents64 __NR_getdents64
#define __NR_sys_getpriority __NR_getpriority
-#define __NR_sys_linkat __NR_linkat
-#define __NR_sys_mkdirat __NR_mkdirat
-#define __NR_sys_mknodat __NR_mknodat
-#define __NR_sys_newfstatat __NR_newfstatat
-#define __NR_sys_openat __NR_openat
-#define __NR_sys_readlinkat __NR_readlinkat
-#define __NR_sys_renameat __NR_renameat
#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
-#define __NR_sys_symlinkat __NR_symlinkat
#define __NR_sys_syslog __NR_syslog
#define __NR_sys_tgkill __NR_tgkill
#define __NR_sys_tkill __NR_tkill
-#define __NR_sys_unlinkat __NR_unlinkat
-#define __NR_sys_utimensat __NR_utimensat
#define __NR_sys_futex __NR_futex
#define __NR_sys_inotify_init __NR_inotify_init
#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
@@ -223,8 +208,11 @@ static int gettid(void) {
return -ENOSYS;
}
#endif
+#ifdef __NR_getdents
_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
-#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
+#endif
+#if !defined(__NR_getdents) || \
+ (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
#endif
#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
@@ -336,72 +324,6 @@ static int sys_getcwd1(char *buf, size_t size)
return strlen(buf)+1;
}
-#ifdef CONFIG_ATFILE
-/*
- * Host system seems to have atfile syscall stubs available. We
- * now enable them one by one as specified by target syscall_nr.h.
- */
-
-#ifdef TARGET_NR_faccessat
-static int sys_faccessat(int dirfd, const char *pathname, int mode)
-{
- return (faccessat(dirfd, pathname, mode, 0));
-}
-#endif
-#ifdef TARGET_NR_fchmodat
-static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode)
-{
- return (fchmodat(dirfd, pathname, mode, 0));
-}
-#endif
-#if defined(TARGET_NR_fchownat)
-static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
- gid_t group, int flags)
-{
- return (fchownat(dirfd, pathname, owner, group, flags));
-}
-#endif
-#ifdef __NR_fstatat64
-static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
- int flags)
-{
- return (fstatat(dirfd, pathname, buf, flags));
-}
-#endif
-#ifdef __NR_newfstatat
-static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf,
- int flags)
-{
- return (fstatat(dirfd, pathname, buf, flags));
-}
-#endif
-#ifdef TARGET_NR_futimesat
-static int sys_futimesat(int dirfd, const char *pathname,
- const struct timeval times[2])
-{
- return (futimesat(dirfd, pathname, times));
-}
-#endif
-#ifdef TARGET_NR_linkat
-static int sys_linkat(int olddirfd, const char *oldpath,
- int newdirfd, const char *newpath, int flags)
-{
- return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
-}
-#endif
-#ifdef TARGET_NR_mkdirat
-static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
-{
- return (mkdirat(dirfd, pathname, mode));
-}
-#endif
-#ifdef TARGET_NR_mknodat
-static int sys_mknodat(int dirfd, const char *pathname, mode_t mode,
- dev_t dev)
-{
- return (mknodat(dirfd, pathname, mode, dev));
-}
-#endif
#ifdef TARGET_NR_openat
static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode)
{
@@ -415,91 +337,6 @@ static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode)
return (openat(dirfd, pathname, flags));
}
#endif
-#ifdef TARGET_NR_readlinkat
-static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
-{
- return (readlinkat(dirfd, pathname, buf, bufsiz));
-}
-#endif
-#ifdef TARGET_NR_renameat
-static int sys_renameat(int olddirfd, const char *oldpath,
- int newdirfd, const char *newpath)
-{
- return (renameat(olddirfd, oldpath, newdirfd, newpath));
-}
-#endif
-#ifdef TARGET_NR_symlinkat
-static int sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath)
-{
- return (symlinkat(oldpath, newdirfd, newpath));
-}
-#endif
-#ifdef TARGET_NR_unlinkat
-static int sys_unlinkat(int dirfd, const char *pathname, int flags)
-{
- return (unlinkat(dirfd, pathname, flags));
-}
-#endif
-#else /* !CONFIG_ATFILE */
-
-/*
- * Try direct syscalls instead
- */
-#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
-_syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)
-#endif
-#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
-_syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)
-#endif
-#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
-_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
- uid_t,owner,gid_t,group,int,flags)
-#endif
-#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
- defined(__NR_fstatat64)
-_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
- struct stat *,buf,int,flags)
-#endif
-#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
-_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
- const struct timeval *,times)
-#endif
-#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
- defined(__NR_newfstatat)
-_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
- struct stat *,buf,int,flags)
-#endif
-#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
-_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
- int,newdirfd,const char *,newpath,int,flags)
-#endif
-#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
-_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
-#endif
-#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
-_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
- mode_t,mode,dev_t,dev)
-#endif
-#if defined(TARGET_NR_openat) && defined(__NR_openat)
-_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
-#endif
-#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
-_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
- char *,buf,size_t,bufsize)
-#endif
-#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
-_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
- int,newdirfd,const char *,newpath)
-#endif
-#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
-_syscall3(int,sys_symlinkat,const char *,oldpath,
- int,newdirfd,const char *,newpath)
-#endif
-#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
-_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
-#endif
-
-#endif /* CONFIG_ATFILE */
#ifdef CONFIG_UTIMENSAT
static int sys_utimensat(int dirfd, const char *pathname,
@@ -5342,7 +5179,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, 0);
}
break;
-#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
+#if defined(TARGET_NR_linkat)
case TARGET_NR_linkat:
{
void * p2 = NULL;
@@ -5353,7 +5190,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!p || !p2)
ret = -TARGET_EFAULT;
else
- ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
+ ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
unlock_user(p, arg2, 0);
unlock_user(p2, arg4, 0);
}
@@ -5365,11 +5202,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(unlink(p));
unlock_user(p, arg1, 0);
break;
-#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
+#if defined(TARGET_NR_unlinkat)
case TARGET_NR_unlinkat:
if (!(p = lock_user_string(arg2)))
goto efault;
- ret = get_errno(sys_unlinkat(arg1, p, arg3));
+ ret = get_errno(unlinkat(arg1, p, arg3));
unlock_user(p, arg2, 0);
break;
#endif
@@ -5487,11 +5324,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(mknod(p, arg2, arg3));
unlock_user(p, arg1, 0);
break;
-#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
+#if defined(TARGET_NR_mknodat)
case TARGET_NR_mknodat:
if (!(p = lock_user_string(arg2)))
goto efault;
- ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
+ ret = get_errno(mknodat(arg1, p, arg3, arg4));
unlock_user(p, arg2, 0);
break;
#endif
@@ -5622,7 +5459,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, 0);
}
break;
-#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
+#if defined(TARGET_NR_futimesat)
case TARGET_NR_futimesat:
{
struct timeval *tvp, tv[2];
@@ -5637,7 +5474,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
if (!(p = lock_user_string(arg2)))
goto efault;
- ret = get_errno(sys_futimesat(arg1, path(p), tvp));
+ ret = get_errno(futimesat(arg1, path(p), tvp));
unlock_user(p, arg2, 0);
}
break;
@@ -5660,7 +5497,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_faccessat:
if (!(p = lock_user_string(arg2)))
goto efault;
- ret = get_errno(sys_faccessat(arg1, p, arg3));
+ ret = get_errno(faccessat(arg1, p, arg3, 0));
unlock_user(p, arg2, 0);
break;
#endif
@@ -5693,7 +5530,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, 0);
}
break;
-#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
+#if defined(TARGET_NR_renameat)
case TARGET_NR_renameat:
{
void *p2;
@@ -5702,7 +5539,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!p || !p2)
ret = -TARGET_EFAULT;
else
- ret = get_errno(sys_renameat(arg1, p, arg3, p2));
+ ret = get_errno(renameat(arg1, p, arg3, p2));
unlock_user(p2, arg4, 0);
unlock_user(p, arg2, 0);
}
@@ -5714,11 +5551,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(mkdir(p, arg2));
unlock_user(p, arg1, 0);
break;
-#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
+#if defined(TARGET_NR_mkdirat)
case TARGET_NR_mkdirat:
if (!(p = lock_user_string(arg2)))
goto efault;
- ret = get_errno(sys_mkdirat(arg1, p, arg3));
+ ret = get_errno(mkdirat(arg1, p, arg3));
unlock_user(p, arg2, 0);
break;
#endif
@@ -6404,7 +6241,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, 0);
}
break;
-#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
+#if defined(TARGET_NR_symlinkat)
case TARGET_NR_symlinkat:
{
void *p2;
@@ -6413,7 +6250,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!p || !p2)
ret = -TARGET_EFAULT;
else
- ret = get_errno(sys_symlinkat(p, arg2, p2));
+ ret = get_errno(symlinkat(p, arg2, p2));
unlock_user(p2, arg3, 0);
unlock_user(p, arg1, 0);
}
@@ -6444,7 +6281,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, 0);
}
break;
-#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
+#if defined(TARGET_NR_readlinkat)
case TARGET_NR_readlinkat:
{
void *p2;
@@ -6453,7 +6290,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!p || !p2)
ret = -TARGET_EFAULT;
else
- ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
+ ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
unlock_user(p2, arg3, ret);
unlock_user(p, arg2, 0);
}
@@ -6588,11 +6425,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_fchmod:
ret = get_errno(fchmod(arg1, arg2));
break;
-#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
+#if defined(TARGET_NR_fchmodat)
case TARGET_NR_fchmodat:
if (!(p = lock_user_string(arg2)))
goto efault;
- ret = get_errno(sys_fchmodat(arg1, p, arg3));
+ ret = get_errno(fchmodat(arg1, p, arg3, 0));
unlock_user(p, arg2, 0);
break;
#endif
@@ -7123,6 +6960,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break;
#endif
case TARGET_NR_getdents:
+#ifdef __NR_getdents
#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
{
struct target_dirent *target_dirp;
@@ -7195,6 +7033,61 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(dirp, arg2, ret);
}
#endif
+#else
+ /* Implement getdents in terms of getdents64 */
+ {
+ struct linux_dirent64 *dirp;
+ abi_long count = arg3;
+
+ dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
+ if (!dirp) {
+ goto efault;
+ }
+ ret = get_errno(sys_getdents64(arg1, dirp, count));
+ if (!is_error(ret)) {
+ /* Convert the dirent64 structs to target dirent. We do this
+ * in-place, since we can guarantee that a target_dirent is no
+ * larger than a dirent64; however this means we have to be
+ * careful to read everything before writing in the new format.
+ */
+ struct linux_dirent64 *de;
+ struct target_dirent *tde;
+ int len = ret;
+ int tlen = 0;
+
+ de = dirp;
+ tde = (struct target_dirent *)dirp;
+ while (len > 0) {
+ int namelen, treclen;
+ int reclen = de->d_reclen;
+ uint64_t ino = de->d_ino;
+ int64_t off = de->d_off;
+ uint8_t type = de->d_type;
+
+ namelen = strlen(de->d_name);
+ treclen = offsetof(struct target_dirent, d_name)
+ + namelen + 2;
+ treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long));
+
+ memmove(tde->d_name, de->d_name, namelen + 1);
+ tde->d_ino = tswapal(ino);
+ tde->d_off = tswapal(off);
+ tde->d_reclen = tswap16(treclen);
+ /* The target_dirent type is in what was formerly a padding
+ * byte at the end of the structure:
+ */
+ *(((char *)tde) + treclen - 1) = type;
+
+ de = (struct linux_dirent64 *)((char *)de + reclen);
+ tde = (struct target_dirent *)((char *)tde + treclen);
+ len -= reclen;
+ tlen += treclen;
+ }
+ ret = tlen;
+ }
+ unlock_user(dirp, arg2, ret);
+ }
+#endif
break;
#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
case TARGET_NR_getdents64:
@@ -7680,8 +7573,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = host_to_target_stat64(cpu_env, arg2, &st);
break;
#endif
-#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
- (defined(__NR_fstatat64) || defined(__NR_newfstatat))
+#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
#ifdef TARGET_NR_fstatat64
case TARGET_NR_fstatat64:
#endif
@@ -7690,11 +7582,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
if (!(p = lock_user_string(arg2)))
goto efault;
-#ifdef __NR_fstatat64
- ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
-#else
- ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4));
-#endif
+ ret = get_errno(fstatat(arg1, path(p), &st, arg4));
if (!is_error(ret))
ret = host_to_target_stat64(cpu_env, arg3, &st);
break;
@@ -7776,11 +7664,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_fchown:
ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
break;
-#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
+#if defined(TARGET_NR_fchownat)
case TARGET_NR_fchownat:
if (!(p = lock_user_string(arg2)))
goto efault;
- ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
+ ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
+ low2highgid(arg4), arg5));
unlock_user(p, arg2, 0);
break;
#endif
diff --git a/main-loop.c b/main-loop.c
index cf36645af4..a44fff6e9a 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -24,7 +24,8 @@
#include "qemu-common.h"
#include "qemu/timer.h"
-#include "slirp/slirp.h"
+#include "qemu/sockets.h" // struct in_addr needed for libslirp.h
+#include "slirp/libslirp.h"
#include "qemu/main-loop.h"
#include "block/aio.h"
diff --git a/memory_mapping-stub.c b/memory_mapping-stub.c
deleted file mode 100644
index 24d5d67371..0000000000
--- a/memory_mapping-stub.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * QEMU memory mapping
- *
- * Copyright Fujitsu, Corp. 2011, 2012
- *
- * Authors:
- * Wen Congyang <wency@cn.fujitsu.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "cpu.h"
-#include "exec/cpu-all.h"
-#include "sysemu/memory_mapping.h"
-
-int qemu_get_guest_memory_mapping(MemoryMappingList *list)
-{
- return -2;
-}
-
-int cpu_get_memory_mapping(MemoryMappingList *list,
- CPUArchState *env)
-{
- return -1;
-}
-
-bool cpu_paging_enabled(CPUArchState *env)
-{
- return true;
-}
-
diff --git a/memory_mapping.c b/memory_mapping.c
index ff45b3a239..5634f813cd 100644
--- a/memory_mapping.c
+++ b/memory_mapping.c
@@ -170,7 +170,7 @@ static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu)
CPUArchState *env;
for (env = start_cpu; env != NULL; env = env->next_cpu) {
- if (cpu_paging_enabled(env)) {
+ if (cpu_paging_enabled(ENV_GET_CPU(env))) {
return env;
}
}
@@ -178,22 +178,23 @@ static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu)
return NULL;
}
-int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp)
{
CPUArchState *env, *first_paging_enabled_cpu;
RAMBlock *block;
ram_addr_t offset, length;
- int ret;
first_paging_enabled_cpu = find_paging_enabled_cpu(first_cpu);
if (first_paging_enabled_cpu) {
for (env = first_paging_enabled_cpu; env != NULL; env = env->next_cpu) {
- ret = cpu_get_memory_mapping(list, env);
- if (ret < 0) {
- return -1;
+ Error *err = NULL;
+ cpu_get_memory_mapping(ENV_GET_CPU(env), list, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
}
}
- return 0;
+ return;
}
/*
@@ -205,8 +206,6 @@ int qemu_get_guest_memory_mapping(MemoryMappingList *list)
length = block->length;
create_new_memory_mapping(list, offset, offset, length);
}
-
- return 0;
}
void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list)
diff --git a/monitor.c b/monitor.c
index eefc7f083f..70ae8f5b18 100644
--- a/monitor.c
+++ b/monitor.c
@@ -93,10 +93,10 @@
* 'M' Non-negative target long (32 or 64 bit), in user mode the
* value is multiplied by 2^20 (think Mebibyte)
* 'o' octets (aka bytes)
- * user mode accepts an optional T, t, G, g, M, m, K, k
- * suffix, which multiplies the value by 2^40 for
- * suffixes T and t, 2^30 for suffixes G and g, 2^20 for
- * M and m, 2^10 for K and k
+ * user mode accepts an optional E, e, P, p, T, t, G, g, M, m,
+ * K, k suffix, which multiplies the value by 2^60 for suffixes E
+ * and e, 2^50 for suffixes P and p, 2^40 for suffixes T and t,
+ * 2^30 for suffixes G and g, 2^20 for M and m, 2^10 for K and k
* 'T' double
* user mode accepts an optional ms, us, ns suffix,
* which divides the value by 1e3, 1e6, 1e9, respectively
@@ -2013,7 +2013,6 @@ static void do_acl_remove(Monitor *mon, const QDict *qdict)
static void do_inject_mce(Monitor *mon, const QDict *qdict)
{
X86CPU *cpu;
- CPUX86State *cenv;
CPUState *cs;
int cpu_index = qdict_get_int(qdict, "cpu_index");
int bank = qdict_get_int(qdict, "bank");
@@ -2026,14 +2025,11 @@ static void do_inject_mce(Monitor *mon, const QDict *qdict)
if (qdict_get_try_bool(qdict, "broadcast", 0)) {
flags |= MCE_INJECT_BROADCAST;
}
- for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
- cpu = x86_env_get_cpu(cenv);
- cs = CPU(cpu);
- if (cs->cpu_index == cpu_index) {
- cpu_x86_inject_mce(mon, cpu, bank, status, mcg_status, addr, misc,
- flags);
- break;
- }
+ cs = qemu_get_cpu(cpu_index);
+ if (cs != NULL) {
+ cpu = X86_CPU(cs);
+ cpu_x86_inject_mce(mon, cpu, bank, status, mcg_status, addr, misc,
+ flags);
}
}
#endif
@@ -2472,9 +2468,10 @@ static mon_cmd_t info_cmds[] = {
},
{
.name = "block",
- .args_type = "",
- .params = "",
- .help = "show the block devices",
+ .args_type = "verbose:-v,device:B?",
+ .params = "[-v] [device]",
+ .help = "show info of one block device or all block devices "
+ "(and details of images with -v option)",
.mhandler.cmd = hmp_info_block,
},
{
diff --git a/net/tap.c b/net/tap.c
index e0b7a2a5a0..39c1cda3e4 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -698,9 +698,10 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
if (tap->has_fd) {
if (tap->has_ifname || tap->has_script || tap->has_downscript ||
tap->has_vnet_hdr || tap->has_helper || tap->has_queues ||
- tap->has_fds) {
+ tap->has_fds || tap->has_vhostfds) {
error_report("ifname=, script=, downscript=, vnet_hdr=, "
- "helper=, queues=, and fds= are invalid with fd=");
+ "helper=, queues=, fds=, and vhostfds= "
+ "are invalid with fd=");
return -1;
}
@@ -725,9 +726,10 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
if (tap->has_ifname || tap->has_script || tap->has_downscript ||
tap->has_vnet_hdr || tap->has_helper || tap->has_queues ||
- tap->has_fd) {
+ tap->has_vhostfd) {
error_report("ifname=, script=, downscript=, vnet_hdr=, "
- "helper=, queues=, and fd= are invalid with fds=");
+ "helper=, queues=, and vhostfd= "
+ "are invalid with fds=");
return -1;
}
@@ -765,9 +767,9 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
}
} else if (tap->has_helper) {
if (tap->has_ifname || tap->has_script || tap->has_downscript ||
- tap->has_vnet_hdr || tap->has_queues || tap->has_fds) {
+ tap->has_vnet_hdr || tap->has_queues || tap->has_vhostfds) {
error_report("ifname=, script=, downscript=, and vnet_hdr= "
- "queues=, and fds= are invalid with helper=");
+ "queues=, and vhostfds= are invalid with helper=");
return -1;
}
@@ -785,6 +787,10 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
return -1;
}
} else {
+ if (tap->has_vhostfds) {
+ error_report("vhostfds= is invalid if fds= wasn't specified");
+ return -1;
+ }
script = tap->has_script ? tap->script : DEFAULT_NETWORK_SCRIPT;
downscript = tap->has_downscript ? tap->downscript :
DEFAULT_NETWORK_DOWN_SCRIPT;
diff --git a/pc-bios/qemu_logo_no_text.svg b/pc-bios/qemu_logo_no_text.svg
new file mode 100644
index 0000000000..24ca23a1e9
--- /dev/null
+++ b/pc-bios/qemu_logo_no_text.svg
@@ -0,0 +1,976 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="111.71874"
+ height="111.12498"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.2 r9819"
+ sodipodi:docname="qemu_logo_no_text.svg">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient4686">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop4688" />
+ <stop
+ id="stop3956"
+ offset="0.75"
+ style="stop-color:#000000;stop-opacity:0.87843138;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.43921569;"
+ offset="0.75"
+ id="stop3958" />
+ <stop
+ id="stop3960"
+ offset="0.88"
+ style="stop-color:#181818;stop-opacity:1;" />
+ <stop
+ style="stop-color:#242424;stop-opacity:1;"
+ offset="0.88"
+ id="stop3962" />
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="1"
+ id="stop4690" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4467">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop4469" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0.8974359;"
+ offset="1"
+ id="stop4471" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4431">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4433" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4435" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4466">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4468" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4470" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4321">
+ <stop
+ style="stop-color:#ff6702;stop-opacity:1;"
+ offset="0"
+ id="stop4323" />
+ <stop
+ style="stop-color:#ff9a55;stop-opacity:1;"
+ offset="1"
+ id="stop4325" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4283">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop4285" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop4287" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4251">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop4253" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop4255" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4007">
+ <stop
+ style="stop-color:#ff6600;stop-opacity:1;"
+ offset="0"
+ id="stop4009" />
+ <stop
+ style="stop-color:#ff9148;stop-opacity:1;"
+ offset="1"
+ id="stop4011" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3999">
+ <stop
+ style="stop-color:#fff7f2;stop-opacity:1;"
+ offset="0"
+ id="stop4001" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4003" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3890">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3892" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3894" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3880">
+ <stop
+ style="stop-color:#eb7400;stop-opacity:1;"
+ offset="0"
+ id="stop3882" />
+ <stop
+ style="stop-color:#f7b06a;stop-opacity:1;"
+ offset="1"
+ id="stop3884" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4011">
+ <stop
+ style="stop-color:#042dc8;stop-opacity:1;"
+ offset="0"
+ id="stop4013" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3879">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.90598291;"
+ offset="0"
+ id="stop3881" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3869">
+ <stop
+ style="stop-color:#c95000;stop-opacity:1;"
+ offset="0"
+ id="stop3871" />
+ <stop
+ style="stop-color:#ff9e5e;stop-opacity:1;"
+ offset="1"
+ id="stop3873" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3861">
+ <stop
+ style="stop-color:#f06000;stop-opacity:1;"
+ offset="0"
+ id="stop3863" />
+ <stop
+ style="stop-color:#ffccaa;stop-opacity:1;"
+ offset="1"
+ id="stop3865" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3826">
+ <stop
+ style="stop-color:#ff6600;stop-opacity:1;"
+ offset="0"
+ id="stop3828" />
+ <stop
+ style="stop-color:#ff893b;stop-opacity:1;"
+ offset="1"
+ id="stop3830" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3879-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.90598291;"
+ offset="0"
+ id="stop3881-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-7" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3869-5">
+ <stop
+ style="stop-color:#c95000;stop-opacity:1;"
+ offset="0"
+ id="stop3871-9" />
+ <stop
+ style="stop-color:#ff9e5e;stop-opacity:1;"
+ offset="1"
+ id="stop3873-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3879-4"
+ id="linearGradient3885-6"
+ x1="76.025352"
+ y1="124.8497"
+ x2="75.874107"
+ y2="143.03978"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3879-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3869-2">
+ <stop
+ style="stop-color:#c95000;stop-opacity:1;"
+ offset="0"
+ id="stop3871-99" />
+ <stop
+ style="stop-color:#ff9e5e;stop-opacity:1;"
+ offset="1"
+ id="stop3873-6" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011"
+ id="radialGradient4017"
+ cx="66.639"
+ cy="93.096375"
+ fx="66.639"
+ fy="93.096375"
+ r="11.515625"
+ gradientTransform="matrix(0.23244854,1.600893,-1.0124495,0.14700695,145.40424,-26.300303)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3879-4-7"
+ id="linearGradient3885-6-2"
+ x1="76.025352"
+ y1="124.8497"
+ x2="75.874107"
+ y2="143.03978"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3879-4-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-6" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011-5"
+ id="radialGradient4017-7"
+ cx="66.639"
+ cy="93.096375"
+ fx="66.639"
+ fy="93.096375"
+ r="11.515625"
+ gradientTransform="matrix(0.99779178,6.8718773,-4.3459674,0.6310314,452.75975,-225.98471)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4011-5">
+ <stop
+ style="stop-color:#042dc8;stop-opacity:1;"
+ offset="0"
+ id="stop4013-1" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3879-4-75"
+ id="linearGradient3885-6-8"
+ x1="76.025352"
+ y1="124.8497"
+ x2="75.874107"
+ y2="143.03978"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3879-4-75">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-4" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011-0"
+ id="radialGradient4017-5"
+ cx="66.639"
+ cy="93.096375"
+ fx="66.639"
+ fy="93.096375"
+ r="11.515625"
+ gradientTransform="matrix(0.23244854,1.600893,-1.0124495,0.14700695,146.34996,53.681728)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4011-0">
+ <stop
+ style="stop-color:#042dc8;stop-opacity:1;"
+ offset="0"
+ id="stop4013-4" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011-0"
+ id="linearGradient4117"
+ x1="107.03001"
+ y1="189.72537"
+ x2="107.18476"
+ y2="173.47537"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3879-4-7-2"
+ id="linearGradient3885-6-2-8"
+ x1="76.025352"
+ y1="124.8497"
+ x2="75.874107"
+ y2="143.03978"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3879-4-7-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-7-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-6-9" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011-5-1"
+ id="radialGradient4017-7-9"
+ cx="66.639"
+ cy="93.096375"
+ fx="66.639"
+ fy="93.096375"
+ r="11.515625"
+ gradientTransform="matrix(0.99779178,6.8718773,-4.3459674,0.6310314,448.94742,-406.99277)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4011-5-1">
+ <stop
+ style="stop-color:#042dc8;stop-opacity:1;"
+ offset="0"
+ id="stop4013-1-9" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015-3-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3879-4-7-2-7"
+ id="linearGradient3885-6-2-8-0"
+ x1="76.025352"
+ y1="124.8497"
+ x2="75.874107"
+ y2="143.03978"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3879-4-7-2-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-7-9-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-6-9-6" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011-5-1-5"
+ id="radialGradient4017-7-9-5"
+ cx="66.639"
+ cy="93.096375"
+ fx="66.639"
+ fy="93.096375"
+ r="11.515625"
+ gradientTransform="matrix(0.55965334,3.8543806,-2.4376181,0.3539404,454.75182,-145.44353)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4011-5-1-5">
+ <stop
+ style="stop-color:#042dc8;stop-opacity:1;"
+ offset="0"
+ id="stop4013-1-9-6" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015-3-8-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3879-4-7-2-4"
+ id="linearGradient3885-6-2-8-4"
+ x1="76.025352"
+ y1="124.8497"
+ x2="75.874107"
+ y2="143.03978"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3879-4-7-2-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-7-9-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-6-9-3" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011-5-1-7"
+ id="radialGradient4017-7-9-7"
+ cx="66.639"
+ cy="93.096375"
+ fx="66.639"
+ fy="93.096375"
+ r="11.515625"
+ gradientTransform="matrix(0.26837158,1.8482981,-1.1689154,0.16972569,466.57614,26.180822)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4011-5-1-7">
+ <stop
+ style="stop-color:#042dc8;stop-opacity:1;"
+ offset="0"
+ id="stop4013-1-9-1" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015-3-8-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3879-4-7-2-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-7-9-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-6-9-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4011-5-1-55">
+ <stop
+ style="stop-color:#000a30;stop-opacity:1;"
+ offset="0"
+ id="stop4013-1-9-8" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015-3-8-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3890-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3892-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3894-9" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3880-4">
+ <stop
+ style="stop-color:#eb7400;stop-opacity:1;"
+ offset="0"
+ id="stop3882-5" />
+ <stop
+ style="stop-color:#f7b06a;stop-opacity:1;"
+ offset="1"
+ id="stop3884-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3999-7">
+ <stop
+ style="stop-color:#fff7f2;stop-opacity:1;"
+ offset="0"
+ id="stop4001-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4003-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4007-9">
+ <stop
+ style="stop-color:#ff6600;stop-opacity:1;"
+ offset="0"
+ id="stop4009-1" />
+ <stop
+ style="stop-color:#ff9148;stop-opacity:1;"
+ offset="1"
+ id="stop4011-9" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4007-9-5">
+ <stop
+ style="stop-color:#ff6600;stop-opacity:1;"
+ offset="0"
+ id="stop4009-1-9" />
+ <stop
+ style="stop-color:#ff9148;stop-opacity:1;"
+ offset="1"
+ id="stop4011-9-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3999-7-1">
+ <stop
+ style="stop-color:#fff7f2;stop-opacity:1;"
+ offset="0"
+ id="stop4001-9-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4003-4-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4007-9-5-3">
+ <stop
+ style="stop-color:#ff6600;stop-opacity:1;"
+ offset="0"
+ id="stop4009-1-9-3" />
+ <stop
+ style="stop-color:#ff9148;stop-opacity:1;"
+ offset="1"
+ id="stop4011-9-5-9" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3999-7-1-4">
+ <stop
+ style="stop-color:#fff7f2;stop-opacity:1;"
+ offset="0"
+ id="stop4001-9-1-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4003-4-4-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3879-4-7-2-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-7-9-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-6-9-87" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4011-5-1-1">
+ <stop
+ style="stop-color:#fde8a1;stop-opacity:1;"
+ offset="0"
+ id="stop4013-1-9-63" />
+ <stop
+ style="stop-color:#2947b9;stop-opacity:1;"
+ offset="1"
+ id="stop4015-3-8-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4466"
+ id="linearGradient4472"
+ x1="161.7561"
+ y1="540.72662"
+ x2="161.7561"
+ y2="579.80206"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4321"
+ id="radialGradient4474"
+ cx="130.8242"
+ cy="575.27838"
+ fx="130.8242"
+ fy="575.27838"
+ r="49.498173"
+ gradientTransform="matrix(0.95670828,0.96684666,-0.72623533,0.71862001,423.45109,35.05138)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4466-5"
+ id="linearGradient4472-9"
+ x1="161.7561"
+ y1="540.72662"
+ x2="161.7561"
+ y2="579.80206"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4466-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4468-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4470-3" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4321-0"
+ id="radialGradient4474-6"
+ cx="130.8242"
+ cy="575.27838"
+ fx="130.8242"
+ fy="575.27838"
+ r="49.498173"
+ gradientTransform="matrix(0.95670828,0.96684666,-0.72623533,0.71862001,442.64399,170.9169)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4321-0">
+ <stop
+ style="stop-color:#ff6702;stop-opacity:1;"
+ offset="0"
+ id="stop4323-3" />
+ <stop
+ style="stop-color:#ff9a55;stop-opacity:1;"
+ offset="1"
+ id="stop4325-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4466-5-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4468-2-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4470-3-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4321-0-0">
+ <stop
+ style="stop-color:#ff6702;stop-opacity:1;"
+ offset="0"
+ id="stop4323-3-9" />
+ <stop
+ style="stop-color:#ff9a55;stop-opacity:1;"
+ offset="1"
+ id="stop4325-1-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4466-5-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4468-2-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4470-3-7" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4321-0-7">
+ <stop
+ style="stop-color:#ff6702;stop-opacity:1;"
+ offset="0"
+ id="stop4323-3-3" />
+ <stop
+ style="stop-color:#ff9a55;stop-opacity:1;"
+ offset="1"
+ id="stop4325-1-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4431"
+ id="linearGradient4437"
+ x1="142.81854"
+ y1="831.52283"
+ x2="142.81854"
+ y2="878.90735"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4467"
+ id="radialGradient4475"
+ cx="116.51958"
+ cy="98.282051"
+ fx="116.51958"
+ fy="98.282051"
+ r="55.859375"
+ gradientTransform="matrix(0.97442557,1.5088911,-0.83559154,0.53961599,79.641615,-130.28522)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4431-3"
+ id="linearGradient4437-6"
+ x1="142.81854"
+ y1="831.52283"
+ x2="142.81854"
+ y2="878.90735"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4431-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4433-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4435-2" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4467-7"
+ id="radialGradient4475-0"
+ cx="116.51958"
+ cy="98.282051"
+ fx="116.51958"
+ fy="98.282051"
+ r="55.859375"
+ gradientTransform="matrix(0.97442557,1.5088911,-0.83559154,0.53961599,225.10358,63.664066)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4467-7">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop4469-4" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0.8974359;"
+ offset="1"
+ id="stop4471-7" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4467"
+ id="radialGradient3262"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.97442557,1.5088911,-0.83559154,0.53961599,59.641615,-150.28522)"
+ cx="116.51958"
+ cy="98.282051"
+ fx="116.51958"
+ fy="98.282051"
+ r="55.859375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4431"
+ id="linearGradient3264"
+ gradientUnits="userSpaceOnUse"
+ x1="142.81854"
+ y1="831.52283"
+ x2="142.81854"
+ y2="878.90735" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="5.6"
+ inkscape:cx="31.144191"
+ inkscape:cy="38.335716"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ showguides="false"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1920"
+ inkscape:window-height="1056"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ fit-margin-top="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ fit-margin-left="0">
+ <sodipodi:guide
+ orientation="0,1"
+ position="72.563745,37.346999"
+ id="guide2989" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="74.584055,7.2949693"
+ id="guide2991" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="71.048515,20.426949"
+ id="guide2993" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="97.817565,20.174409"
+ id="guide2995" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="71.048515,20.426949"
+ id="guide3017" />
+ <inkscape:grid
+ type="xygrid"
+ id="grid3019"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="105.6589,-12.377861"
+ id="guide3021" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="126.6589,-16.377861"
+ id="guide3023" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="110.6589,-3.3778607"
+ id="guide3025" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="110.6589,-27.377861"
+ id="guide3027" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="19.658895,-35.37786"
+ id="guide3810" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="21.658895,-70.377861"
+ id="guide3814" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="2.301752,-9.4850007"
+ id="guide3856" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="26.601806,-9.4850007"
+ id="guide3887" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="44.658283,37.346999"
+ id="guide4019" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="126.6589,-27.377861"
+ id="guide4481" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="159.08747,-213.94929"
+ id="guide4483" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-42.341105,-35.859333)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient3262);fill-opacity:1;stroke:none"
+ d="m 98.2161,35.859333 c -30.850815,0 -55.874995,24.87043 -55.874995,55.562497 0,30.69207 25.02418,55.56249 55.874995,55.56249 10.09496,0 19.54625,-2.6525 27.71875,-7.3125 l 2.90625,7.3125 2.40625,0 20,0 0.125,0 -8.8125,-21.78124 c 7.21537,-9.3622 11.5,-21.07236 11.5,-33.78125 0,-30.692067 -24.99293,-55.562497 -55.84375,-55.562497 z"
+ id="path3834-7-7-2-5-5-0-5-4" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient3264);fill-opacity:1;stroke:none"
+ id="path3661"
+ sodipodi:cx="142.5"
+ sodipodi:cy="856.29077"
+ sodipodi:rx="35.357143"
+ sodipodi:ry="24.642857"
+ d="m 177.85714,856.29077 c 0,13.60988 -15.82993,24.64286 -35.35714,24.64286 -19.52721,0 -35.35714,-11.03298 -35.35714,-24.64286 0,-13.60987 15.82993,-24.64286 35.35714,-24.64286 19.52721,0 35.35714,11.03299 35.35714,24.64286 z"
+ transform="matrix(1.0465082,0,0,1.2920463,-51.641235,-1036.8612)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1;stroke:none"
+ id="path4442"
+ sodipodi:cx="115.66247"
+ sodipodi:cy="856.39258"
+ sodipodi:rx="6.5659914"
+ sodipodi:ry="6.5659914"
+ d="m 122.22846,856.39258 c 0,3.6263 -2.9397,6.56599 -6.56599,6.56599 -3.6263,0 -6.56599,-2.93969 -6.56599,-6.56599 0,-3.6263 2.93969,-6.56599 6.56599,-6.56599 3.62629,0 6.56599,2.93969 6.56599,6.56599 z"
+ transform="translate(-12.329975,-797.60351)" />
+ <rect
+ style="fill:#000000;fill-opacity:1;stroke:none"
+ id="rect4444"
+ width="37.643608"
+ height="5.5005069"
+ x="101.55376"
+ y="48.297417"
+ transform="matrix(0.98974903,0.14281759,-0.18972639,0.981837,0,0)" />
+ <rect
+ style="fill:#000000;fill-opacity:1;stroke:none"
+ id="rect4446"
+ width="6.5659914"
+ height="2.9041886"
+ x="124.92451"
+ y="69.016899" />
+ <path
+ style="fill:#ff6600;fill-opacity:1"
+ d="m 83.38797,45.010543 c -0.057,2.18531 -3.865755,0.28296 -4.031245,2.78125 -4.22387,-1.88052 0.32884,2.87188 -0.0937,3.3125 l -0.0312,0 -0.3125,-0.0312 c -0.20386,-0.0728 -0.49977,-0.19904 -0.9375,-0.46875 -2.9499,2.35025 -3.02157,7.23369 -6.0625,9.9375 -1.99467,4.30504 -2.47977,8.98337 -3.9375,13.46875 -0.71796,4.30292 -1.34881,8.597857 -0.28125,12.906247 0.32053,3.50159 -0.68919,8.25865 2.5,10.71875 4.72728,3.88304 8.65575,8.79543 12.624995,13.46875 6.21914,7.65333 11.72948,15.86251 16.59375,24.4375 0.32431,-2.11756 1.10954,4.26459 2.53125,4.6875 -0.49161,-3.19231 -1.13213,-8.26328 -1.4375,-12.1875 -1.5814,-10.2909 -6.65305,-19.64903 -8.5625,-29.84375 -0.0587,-0.43037 -0.12809,-0.87203 -0.1875,-1.3125 l 0,-1.28125 -0.15625,0 c -0.62551,-5.04297 -0.8504,-10.46546 2.8125,-14.40625 3.73968,-3.772097 9.30633,-4.722447 13.8125,-7.343747 1.00194,-0.59119 2.04921,-1.07174 3.125,-1.40625 0.009,-0.003 0.0228,0.003 0.0312,0 3.11701,-0.96341 6.44862,-0.93323 9.6875,-0.40625 0.0479,0.008 0.10841,0.0233 0.15625,0.0312 0.29455,0.0493 0.61389,0.099 0.90625,0.15625 2.37136,0.21133 7.14463,1.13687 8,-0.5 -3.27225,-2.78631 -7.98526,-2.59211 -11.96875,-3.6875 -0.63059,-0.11469 -1.41182,-0.24041 -2.1875,-0.3125 l -3.90625,-0.875 -0.96875,-0.25 0,0.0312 -13.96875,-2.71875 c -0.22212,-0.20226 -0.46434,-0.40933 -0.6875,-0.5625 l 13.625,1.6875 0,-0.0625 c 0.48011,0.10699 0.95576,0.19361 1.4375,0.25 l 0,0.0312 9.625,1.78125 c 1.66103,0.61952 3.4322,1.08374 5.09375,1.1875 2.74263,0.39907 6.22526,4.49092 7.125,4.6875 -0.44096,-4.307 -4.7422,-6.23586 -8.3125,-7.5 -4.1712,-2.02803 -10.4023,-1.95417 -11.0625,-7.5625 -0.1756,-0.39076 -0.34902,-0.78118 -0.5625,-1.15625 l -1.625,-2.15625 0.0625,-0.0312 c -2.21724,-2.61691 -5.34011,-4.52196 -8.65625,-5.25 -3.2914,-1.13611 -6.98773,-2.2671 -10.46875,-2.71875 -1.18132,3.47826 -2.5031,-2.75561 -5.34375,-0.90625 -2.48996,0.29488 -2.14614,0.95256 -4,-0.625 z m 17.90625,10.15625 c 0.90187,-0.0238 1.93277,0.14208 2.96875,0.5 2.76259,0.95447 4.56151,2.96523 4.03125,4.5 -0.53026,1.53477 -3.20616,1.98572 -5.96875,1.03125 -2.76259,-0.95447 -4.5615,-2.93398 -4.03125,-4.46875 0.33141,-0.95923 1.49689,-1.52281 3,-1.5625 z"
+ id="path3499-9-7"
+ inkscape:connector-curvature="0" />
+ </g>
+</svg>
diff --git a/qapi-schema.json b/qapi-schema.json
index ef1f657efb..5ad6894738 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -236,6 +236,8 @@
#
# @snapshots: #optional list of VM snapshots
#
+# @backing-image: #optional info of the backing image (since 1.6)
+#
# Since: 1.3
#
##
@@ -245,7 +247,8 @@
'*actual-size': 'int', 'virtual-size': 'int',
'*cluster-size': 'int', '*encrypted': 'bool',
'*backing-filename': 'str', '*full-backing-filename': 'str',
- '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'] } }
+ '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
+ '*backing-image': 'ImageInfo' } }
##
# @ImageCheck:
@@ -756,6 +759,8 @@
#
# @iops_wr: write I/O operations per second is specified
#
+# @image: the info of image used (since: 1.6)
+#
# Since: 0.14.0
#
# Notes: This interface is only found in @BlockInfo.
@@ -765,7 +770,8 @@
'*backing_file': 'str', 'backing_file_depth': 'int',
'encrypted': 'bool', 'encryption_key_missing': 'bool',
'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
- 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int'} }
+ 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int',
+ 'image': 'ImageInfo' } }
##
# @BlockDeviceIoStatus:
diff --git a/qemu-char.c b/qemu-char.c
index d04b429a03..2c3cfe6b69 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -76,8 +76,6 @@
#include <netinet/ip_icmp.h> // must come after ip.h
#include <netinet/udp.h>
#include <netinet/tcp.h>
-#include <net/if.h>
-#include <syslog.h>
#endif
#endif
#endif
@@ -110,19 +108,9 @@ void qemu_chr_be_event(CharDriverState *s, int event)
s->chr_event(s->handler_opaque, event);
}
-static gboolean qemu_chr_be_generic_open_bh(gpointer opaque)
-{
- CharDriverState *s = opaque;
- qemu_chr_be_event(s, CHR_EVENT_OPENED);
- s->idle_tag = 0;
- return FALSE;
-}
-
void qemu_chr_be_generic_open(CharDriverState *s)
{
- if (s->idle_tag == 0) {
- s->idle_tag = g_idle_add(qemu_chr_be_generic_open_bh, s);
- }
+ qemu_chr_be_event(s, CHR_EVENT_OPENED);
}
int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len)
@@ -247,6 +235,7 @@ static CharDriverState *qemu_chr_open_null(void)
chr = g_malloc0(sizeof(CharDriverState));
chr->chr_write = null_chr_write;
+ chr->explicit_be_open = true;
return chr;
}
@@ -504,9 +493,6 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
/* Frontend guest-open / -close notification is not support with muxes */
chr->chr_set_fe_open = NULL;
- /* Muxes are always open on creation */
- qemu_chr_be_generic_open(chr);
-
return chr;
}
@@ -883,8 +869,6 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
chr->chr_update_read_handler = fd_chr_update_read_handler;
chr->chr_close = fd_chr_close;
- qemu_chr_be_generic_open(chr);
-
return chr;
}
@@ -980,63 +964,6 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
return chr;
}
-#ifdef __sun__
-/* Once Solaris has openpty(), this is going to be removed. */
-static int openpty(int *amaster, int *aslave, char *name,
- struct termios *termp, struct winsize *winp)
-{
- const char *slave;
- int mfd = -1, sfd = -1;
-
- *amaster = *aslave = -1;
-
- mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
- if (mfd < 0)
- goto err;
-
- if (grantpt(mfd) == -1 || unlockpt(mfd) == -1)
- goto err;
-
- if ((slave = ptsname(mfd)) == NULL)
- goto err;
-
- if ((sfd = open(slave, O_RDONLY | O_NOCTTY)) == -1)
- goto err;
-
- if (ioctl(sfd, I_PUSH, "ptem") == -1 ||
- (termp != NULL && tcgetattr(sfd, termp) < 0))
- goto err;
-
- if (amaster)
- *amaster = mfd;
- if (aslave)
- *aslave = sfd;
- if (winp)
- ioctl(sfd, TIOCSWINSZ, winp);
-
- return 0;
-
-err:
- if (sfd != -1)
- close(sfd);
- close(mfd);
- return -1;
-}
-
-static void cfmakeraw (struct termios *termios_p)
-{
- termios_p->c_iflag &=
- ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
- termios_p->c_oflag &= ~OPOST;
- termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
- termios_p->c_cflag &= ~(CSIZE|PARENB);
- termios_p->c_cflag |= CS8;
-
- termios_p->c_cc[VMIN] = 0;
- termios_p->c_cc[VTIME] = 0;
-}
-#endif
-
#if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
|| defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
|| defined(__GLIBC__)
@@ -1208,34 +1135,24 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
{
CharDriverState *chr;
PtyCharDriver *s;
- struct termios tty;
int master_fd, slave_fd;
-#if defined(__OpenBSD__) || defined(__DragonFly__)
char pty_name[PATH_MAX];
-#define q_ptsname(x) pty_name
-#else
- char *pty_name = NULL;
-#define q_ptsname(x) ptsname(x)
-#endif
- if (openpty(&master_fd, &slave_fd, pty_name, NULL, NULL) < 0) {
+ master_fd = qemu_openpty_raw(&slave_fd, pty_name);
+ if (master_fd < 0) {
return NULL;
}
- /* Set raw attributes on the pty. */
- tcgetattr(slave_fd, &tty);
- cfmakeraw(&tty);
- tcsetattr(slave_fd, TCSAFLUSH, &tty);
close(slave_fd);
chr = g_malloc0(sizeof(CharDriverState));
- chr->filename = g_strdup_printf("pty:%s", q_ptsname(master_fd));
- ret->pty = g_strdup(q_ptsname(master_fd));
+ chr->filename = g_strdup_printf("pty:%s", pty_name);
+ ret->pty = g_strdup(pty_name);
ret->has_pty = true;
fprintf(stderr, "char device redirected to %s (label %s)\n",
- q_ptsname(master_fd), id);
+ pty_name, id);
s = g_malloc0(sizeof(PtyCharDriver));
chr->opaque = s;
@@ -1243,6 +1160,7 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
chr->chr_update_read_handler = pty_chr_update_read_handler;
chr->chr_close = pty_chr_close;
chr->chr_add_watch = pty_chr_add_watch;
+ chr->explicit_be_open = true;
s->fd = io_channel_from_fd(master_fd);
s->timer_tag = 0;
@@ -1595,8 +1513,6 @@ static CharDriverState *qemu_chr_open_pp_fd(int fd)
chr->chr_close = pp_close;
chr->opaque = drv;
- qemu_chr_be_generic_open(chr);
-
return chr;
}
#endif /* __linux__ */
@@ -1650,6 +1566,7 @@ static CharDriverState *qemu_chr_open_pp_fd(int fd)
chr->opaque = (void *)(intptr_t)fd;
chr->chr_write = null_chr_write;
chr->chr_ioctl = pp_ioctl;
+ chr->explicit_be_open = true;
return chr;
}
#endif
@@ -1880,7 +1797,6 @@ static CharDriverState *qemu_chr_open_win_path(const char *filename)
g_free(chr);
return NULL;
}
- qemu_chr_be_generic_open(chr);
return chr;
}
@@ -1980,7 +1896,6 @@ static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
g_free(chr);
return NULL;
}
- qemu_chr_be_generic_open(chr);
return chr;
}
@@ -1994,7 +1909,6 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
s->hcom = fd_out;
chr->opaque = s;
chr->chr_write = win_chr_write;
- qemu_chr_be_generic_open(chr);
return chr;
}
@@ -2329,6 +2243,8 @@ static CharDriverState *qemu_chr_open_udp_fd(int fd)
chr->chr_write = udp_chr_write;
chr->chr_update_read_handler = udp_chr_update_read_handler;
chr->chr_close = udp_chr_close;
+ /* be isn't opened until we get a connection */
+ chr->explicit_be_open = true;
return chr;
}
@@ -2731,6 +2647,8 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
chr->get_msgfd = tcp_get_msgfd;
chr->chr_add_client = tcp_chr_add_client;
chr->chr_add_watch = tcp_chr_add_watch;
+ /* be isn't opened until we get a connection */
+ chr->explicit_be_open = true;
if (is_listen) {
s->listen_fd = fd;
@@ -3325,6 +3243,12 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
if (!chr->filename)
chr->filename = g_strdup(qemu_opt_get(opts, "backend"));
chr->init = init;
+ /* if we didn't create the chardev via qmp_chardev_add, we
+ * need to send the OPENED event here
+ */
+ if (!chr->explicit_be_open) {
+ qemu_chr_be_event(chr, CHR_EVENT_OPENED);
+ }
QTAILQ_INSERT_TAIL(&chardevs, chr, next);
if (qemu_opt_get_bool(opts, "mux", 0)) {
@@ -3804,6 +3728,9 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
if (!chr->filename) {
chr->filename = g_strdup(ChardevBackendKind_lookup[backend->kind]);
}
+ if (!chr->explicit_be_open) {
+ qemu_chr_be_event(chr, CHR_EVENT_OPENED);
+ }
QTAILQ_INSERT_TAIL(&chardevs, chr, next);
return ret;
} else {
diff --git a/qemu-img.c b/qemu-img.c
index 82c7977353..809b4f1c00 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -85,8 +85,9 @@ static void help(void)
" options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
" 'directsync' and 'unsafe' (default for convert)\n"
" 'size' is the disk image size in bytes. Optional suffixes\n"
- " 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
- " and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
+ " 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M),\n"
+ " 'T' (terabyte, 1024G), 'P' (petabyte, 1024T) and 'E' (exabyte, 1024P) are\n"
+ " supported. 'b' is ignored.\n"
" 'output_filename' is the destination disk image filename\n"
" 'output_fmt' is the destination format\n"
" 'options' is a comma separated list of format specific options in a\n"
@@ -387,8 +388,9 @@ static int img_create(int argc, char **argv)
error_report("Image size must be less than 8 EiB!");
} else {
error_report("Invalid image size specified! You may use k, M, "
- "G or T suffixes for ");
- error_report("kilobytes, megabytes, gigabytes and terabytes.");
+ "G, T, P or E suffixes for ");
+ error_report("kilobytes, megabytes, gigabytes, terabytes, "
+ "petabytes and exabytes.");
}
return 1;
}
@@ -1642,6 +1644,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
ImageInfoList *head = NULL;
ImageInfoList **last = &head;
GHashTable *filenames;
+ Error *err = NULL;
filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
@@ -1663,9 +1666,12 @@ static ImageInfoList *collect_image_info_list(const char *filename,
goto err;
}
- info = g_new0(ImageInfo, 1);
- bdrv_collect_image_info(bs, info, filename);
- bdrv_collect_snapshots(bs, info);
+ bdrv_query_image_info(bs, &info, &err);
+ if (error_is_set(&err)) {
+ error_report("%s", error_get_pretty(err));
+ error_free(err);
+ goto err;
+ }
elem = g_new0(ImageInfoList, 1);
elem->value = info;
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
new file mode 100644
index 0000000000..ffbcf31cfc
--- /dev/null
+++ b/qemu-io-cmds.c
@@ -0,0 +1,2118 @@
+/*
+ * Command line utility to exercise the QEMU I/O path.
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (c) 2003-2005 Silicon Graphics, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu-io.h"
+#include "block/block_int.h"
+
+#define CMD_NOFILE_OK 0x01
+
+int qemuio_misalign;
+
+static cmdinfo_t *cmdtab;
+static int ncmds;
+
+static int compare_cmdname(const void *a, const void *b)
+{
+ return strcmp(((const cmdinfo_t *)a)->name,
+ ((const cmdinfo_t *)b)->name);
+}
+
+void qemuio_add_command(const cmdinfo_t *ci)
+{
+ cmdtab = g_realloc(cmdtab, ++ncmds * sizeof(*cmdtab));
+ cmdtab[ncmds - 1] = *ci;
+ qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
+}
+
+int qemuio_command_usage(const cmdinfo_t *ci)
+{
+ printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
+ return 0;
+}
+
+static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
+{
+ if (ct->flags & CMD_FLAG_GLOBAL) {
+ return 1;
+ }
+ if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
+ fprintf(stderr, "no file open, try 'help open'\n");
+ return 0;
+ }
+ return 1;
+}
+
+static int command(BlockDriverState *bs, const cmdinfo_t *ct, int argc,
+ char **argv)
+{
+ char *cmd = argv[0];
+
+ if (!init_check_command(bs, ct)) {
+ return 0;
+ }
+
+ if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
+ if (ct->argmax == -1) {
+ fprintf(stderr,
+ "bad argument count %d to %s, expected at least %d arguments\n",
+ argc-1, cmd, ct->argmin);
+ } else if (ct->argmin == ct->argmax) {
+ fprintf(stderr,
+ "bad argument count %d to %s, expected %d arguments\n",
+ argc-1, cmd, ct->argmin);
+ } else {
+ fprintf(stderr,
+ "bad argument count %d to %s, expected between %d and %d arguments\n",
+ argc-1, cmd, ct->argmin, ct->argmax);
+ }
+ return 0;
+ }
+ optind = 0;
+ return ct->cfunc(bs, argc, argv);
+}
+
+static const cmdinfo_t *find_command(const char *cmd)
+{
+ cmdinfo_t *ct;
+
+ for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
+ if (strcmp(ct->name, cmd) == 0 ||
+ (ct->altname && strcmp(ct->altname, cmd) == 0))
+ {
+ return (const cmdinfo_t *)ct;
+ }
+ }
+ return NULL;
+}
+
+static char **breakline(char *input, int *count)
+{
+ int c = 0;
+ char *p;
+ char **rval = g_malloc0(sizeof(char *));
+ char **tmp;
+
+ while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
+ if (!*p) {
+ continue;
+ }
+ c++;
+ tmp = g_realloc(rval, sizeof(*rval) * (c + 1));
+ if (!tmp) {
+ g_free(rval);
+ rval = NULL;
+ c = 0;
+ break;
+ } else {
+ rval = tmp;
+ }
+ rval[c - 1] = p;
+ rval[c] = NULL;
+ }
+ *count = c;
+ return rval;
+}
+
+static int64_t cvtnum(const char *s)
+{
+ char *end;
+ return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
+}
+
+#define EXABYTES(x) ((long long)(x) << 60)
+#define PETABYTES(x) ((long long)(x) << 50)
+#define TERABYTES(x) ((long long)(x) << 40)
+#define GIGABYTES(x) ((long long)(x) << 30)
+#define MEGABYTES(x) ((long long)(x) << 20)
+#define KILOBYTES(x) ((long long)(x) << 10)
+
+#define TO_EXABYTES(x) ((x) / EXABYTES(1))
+#define TO_PETABYTES(x) ((x) / PETABYTES(1))
+#define TO_TERABYTES(x) ((x) / TERABYTES(1))
+#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
+#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
+#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
+
+static void cvtstr(double value, char *str, size_t size)
+{
+ char *trim;
+ const char *suffix;
+
+ if (value >= EXABYTES(1)) {
+ suffix = " EiB";
+ snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
+ } else if (value >= PETABYTES(1)) {
+ suffix = " PiB";
+ snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
+ } else if (value >= TERABYTES(1)) {
+ suffix = " TiB";
+ snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
+ } else if (value >= GIGABYTES(1)) {
+ suffix = " GiB";
+ snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
+ } else if (value >= MEGABYTES(1)) {
+ suffix = " MiB";
+ snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
+ } else if (value >= KILOBYTES(1)) {
+ suffix = " KiB";
+ snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
+ } else {
+ suffix = " bytes";
+ snprintf(str, size - 6, "%f", value);
+ }
+
+ trim = strstr(str, ".000");
+ if (trim) {
+ strcpy(trim, suffix);
+ } else {
+ strcat(str, suffix);
+ }
+}
+
+
+
+static struct timeval tsub(struct timeval t1, struct timeval t2)
+{
+ t1.tv_usec -= t2.tv_usec;
+ if (t1.tv_usec < 0) {
+ t1.tv_usec += 1000000;
+ t1.tv_sec--;
+ }
+ t1.tv_sec -= t2.tv_sec;
+ return t1;
+}
+
+static double tdiv(double value, struct timeval tv)
+{
+ return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
+}
+
+#define HOURS(sec) ((sec) / (60 * 60))
+#define MINUTES(sec) (((sec) % (60 * 60)) / 60)
+#define SECONDS(sec) ((sec) % 60)
+
+enum {
+ DEFAULT_TIME = 0x0,
+ TERSE_FIXED_TIME = 0x1,
+ VERBOSE_FIXED_TIME = 0x2,
+};
+
+static void timestr(struct timeval *tv, char *ts, size_t size, int format)
+{
+ double usec = (double)tv->tv_usec / 1000000.0;
+
+ if (format & TERSE_FIXED_TIME) {
+ if (!HOURS(tv->tv_sec)) {
+ snprintf(ts, size, "%u:%02u.%02u",
+ (unsigned int) MINUTES(tv->tv_sec),
+ (unsigned int) SECONDS(tv->tv_sec),
+ (unsigned int) (usec * 100));
+ return;
+ }
+ format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
+ }
+
+ if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
+ snprintf(ts, size, "%u:%02u:%02u.%02u",
+ (unsigned int) HOURS(tv->tv_sec),
+ (unsigned int) MINUTES(tv->tv_sec),
+ (unsigned int) SECONDS(tv->tv_sec),
+ (unsigned int) (usec * 100));
+ } else {
+ snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
+ }
+}
+
+/*
+ * Parse the pattern argument to various sub-commands.
+ *
+ * Because the pattern is used as an argument to memset it must evaluate
+ * to an unsigned integer that fits into a single byte.
+ */
+static int parse_pattern(const char *arg)
+{
+ char *endptr = NULL;
+ long pattern;
+
+ pattern = strtol(arg, &endptr, 0);
+ if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
+ printf("%s is not a valid pattern byte\n", arg);
+ return -1;
+ }
+
+ return pattern;
+}
+
+/*
+ * Memory allocation helpers.
+ *
+ * Make sure memory is aligned by default, or purposefully misaligned if
+ * that is specified on the command line.
+ */
+
+#define MISALIGN_OFFSET 16
+static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
+{
+ void *buf;
+
+ if (qemuio_misalign) {
+ len += MISALIGN_OFFSET;
+ }
+ buf = qemu_blockalign(bs, len);
+ memset(buf, pattern, len);
+ if (qemuio_misalign) {
+ buf += MISALIGN_OFFSET;
+ }
+ return buf;
+}
+
+static void qemu_io_free(void *p)
+{
+ if (qemuio_misalign) {
+ p -= MISALIGN_OFFSET;
+ }
+ qemu_vfree(p);
+}
+
+static void dump_buffer(const void *buffer, int64_t offset, int len)
+{
+ int i, j;
+ const uint8_t *p;
+
+ for (i = 0, p = buffer; i < len; i += 16) {
+ const uint8_t *s = p;
+
+ printf("%08" PRIx64 ": ", offset + i);
+ for (j = 0; j < 16 && i + j < len; j++, p++) {
+ printf("%02x ", *p);
+ }
+ printf(" ");
+ for (j = 0; j < 16 && i + j < len; j++, s++) {
+ if (isalnum(*s)) {
+ printf("%c", *s);
+ } else {
+ printf(".");
+ }
+ }
+ printf("\n");
+ }
+}
+
+static void print_report(const char *op, struct timeval *t, int64_t offset,
+ int count, int total, int cnt, int Cflag)
+{
+ char s1[64], s2[64], ts[64];
+
+ timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
+ if (!Cflag) {
+ cvtstr((double)total, s1, sizeof(s1));
+ cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
+ printf("%s %d/%d bytes at offset %" PRId64 "\n",
+ op, total, count, offset);
+ printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
+ s1, cnt, ts, s2, tdiv((double)cnt, *t));
+ } else {/* bytes,ops,time,bytes/sec,ops/sec */
+ printf("%d,%d,%s,%.3f,%.3f\n",
+ total, cnt, ts,
+ tdiv((double)total, *t),
+ tdiv((double)cnt, *t));
+ }
+}
+
+/*
+ * Parse multiple length statements for vectored I/O, and construct an I/O
+ * vector matching it.
+ */
+static void *
+create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
+ int pattern)
+{
+ size_t *sizes = g_new0(size_t, nr_iov);
+ size_t count = 0;
+ void *buf = NULL;
+ void *p;
+ int i;
+
+ for (i = 0; i < nr_iov; i++) {
+ char *arg = argv[i];
+ int64_t len;
+
+ len = cvtnum(arg);
+ if (len < 0) {
+ printf("non-numeric length argument -- %s\n", arg);
+ goto fail;
+ }
+
+ /* should be SIZE_T_MAX, but that doesn't exist */
+ if (len > INT_MAX) {
+ printf("too large length argument -- %s\n", arg);
+ goto fail;
+ }
+
+ if (len & 0x1ff) {
+ printf("length argument %" PRId64
+ " is not sector aligned\n", len);
+ goto fail;
+ }
+
+ sizes[i] = len;
+ count += len;
+ }
+
+ qemu_iovec_init(qiov, nr_iov);
+
+ buf = p = qemu_io_alloc(bs, count, pattern);
+
+ for (i = 0; i < nr_iov; i++) {
+ qemu_iovec_add(qiov, p, sizes[i]);
+ p += sizes[i];
+ }
+
+fail:
+ g_free(sizes);
+ return buf;
+}
+
+static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
+ int *total)
+{
+ int ret;
+
+ ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+ if (ret < 0) {
+ return ret;
+ }
+ *total = count;
+ return 1;
+}
+
+static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
+ int *total)
+{
+ int ret;
+
+ ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+ if (ret < 0) {
+ return ret;
+ }
+ *total = count;
+ return 1;
+}
+
+static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
+ int *total)
+{
+ *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
+ if (*total < 0) {
+ return *total;
+ }
+ return 1;
+}
+
+static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
+ int *total)
+{
+ *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
+ if (*total < 0) {
+ return *total;
+ }
+ return 1;
+}
+
+typedef struct {
+ BlockDriverState *bs;
+ int64_t offset;
+ int count;
+ int *total;
+ int ret;
+ bool done;
+} CoWriteZeroes;
+
+static void coroutine_fn co_write_zeroes_entry(void *opaque)
+{
+ CoWriteZeroes *data = opaque;
+
+ data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
+ data->count / BDRV_SECTOR_SIZE);
+ data->done = true;
+ if (data->ret < 0) {
+ *data->total = data->ret;
+ return;
+ }
+
+ *data->total = data->count;
+}
+
+static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
+ int *total)
+{
+ Coroutine *co;
+ CoWriteZeroes data = {
+ .bs = bs,
+ .offset = offset,
+ .count = count,
+ .total = total,
+ .done = false,
+ };
+
+ co = qemu_coroutine_create(co_write_zeroes_entry);
+ qemu_coroutine_enter(co, &data);
+ while (!data.done) {
+ qemu_aio_wait();
+ }
+ if (data.ret < 0) {
+ return data.ret;
+ } else {
+ return 1;
+ }
+}
+
+static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
+ int count, int *total)
+{
+ int ret;
+
+ ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+ if (ret < 0) {
+ return ret;
+ }
+ *total = count;
+ return 1;
+}
+
+static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
+ int count, int *total)
+{
+ *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
+ if (*total < 0) {
+ return *total;
+ }
+ return 1;
+}
+
+static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
+ int count, int *total)
+{
+ *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
+ if (*total < 0) {
+ return *total;
+ }
+ return 1;
+}
+
+#define NOT_DONE 0x7fffffff
+static void aio_rw_done(void *opaque, int ret)
+{
+ *(int *)opaque = ret;
+}
+
+static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
+ int64_t offset, int *total)
+{
+ int async_ret = NOT_DONE;
+
+ bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
+ aio_rw_done, &async_ret);
+ while (async_ret == NOT_DONE) {
+ main_loop_wait(false);
+ }
+
+ *total = qiov->size;
+ return async_ret < 0 ? async_ret : 1;
+}
+
+static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
+ int64_t offset, int *total)
+{
+ int async_ret = NOT_DONE;
+
+ bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
+ aio_rw_done, &async_ret);
+ while (async_ret == NOT_DONE) {
+ main_loop_wait(false);
+ }
+
+ *total = qiov->size;
+ return async_ret < 0 ? async_ret : 1;
+}
+
+struct multiwrite_async_ret {
+ int num_done;
+ int error;
+};
+
+static void multiwrite_cb(void *opaque, int ret)
+{
+ struct multiwrite_async_ret *async_ret = opaque;
+
+ async_ret->num_done++;
+ if (ret < 0) {
+ async_ret->error = ret;
+ }
+}
+
+static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
+ int num_reqs, int *total)
+{
+ int i, ret;
+ struct multiwrite_async_ret async_ret = {
+ .num_done = 0,
+ .error = 0,
+ };
+
+ *total = 0;
+ for (i = 0; i < num_reqs; i++) {
+ reqs[i].cb = multiwrite_cb;
+ reqs[i].opaque = &async_ret;
+ *total += reqs[i].qiov->size;
+ }
+
+ ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
+ if (ret < 0) {
+ return ret;
+ }
+
+ while (async_ret.num_done < num_reqs) {
+ main_loop_wait(false);
+ }
+
+ return async_ret.error < 0 ? async_ret.error : 1;
+}
+
+static void read_help(void)
+{
+ printf(
+"\n"
+" reads a range of bytes from the given offset\n"
+"\n"
+" Example:\n"
+" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
+"\n"
+" Reads a segment of the currently open file, optionally dumping it to the\n"
+" standard output stream (with -v option) for subsequent inspection.\n"
+" -b, -- read from the VM state rather than the virtual disk\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -l, -- length for pattern verification (only with -P)\n"
+" -p, -- use bdrv_pread to read the file\n"
+" -P, -- use a pattern to verify read data\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+" -s, -- start offset for pattern verification (only with -P)\n"
+" -v, -- dump buffer to standard output\n"
+"\n");
+}
+
+static int read_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t read_cmd = {
+ .name = "read",
+ .altname = "r",
+ .cfunc = read_f,
+ .argmin = 2,
+ .argmax = -1,
+ .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
+ .oneline = "reads a number of bytes at a specified offset",
+ .help = read_help,
+};
+
+static int read_f(BlockDriverState *bs, int argc, char **argv)
+{
+ struct timeval t1, t2;
+ int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
+ int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
+ int c, cnt;
+ char *buf;
+ int64_t offset;
+ int count;
+ /* Some compilers get confused and warn if this is not initialized. */
+ int total = 0;
+ int pattern = 0, pattern_offset = 0, pattern_count = 0;
+
+ while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
+ switch (c) {
+ case 'b':
+ bflag = 1;
+ break;
+ case 'C':
+ Cflag = 1;
+ break;
+ case 'l':
+ lflag = 1;
+ pattern_count = cvtnum(optarg);
+ if (pattern_count < 0) {
+ printf("non-numeric length argument -- %s\n", optarg);
+ return 0;
+ }
+ break;
+ case 'p':
+ pflag = 1;
+ break;
+ case 'P':
+ Pflag = 1;
+ pattern = parse_pattern(optarg);
+ if (pattern < 0) {
+ return 0;
+ }
+ break;
+ case 'q':
+ qflag = 1;
+ break;
+ case 's':
+ sflag = 1;
+ pattern_offset = cvtnum(optarg);
+ if (pattern_offset < 0) {
+ printf("non-numeric length argument -- %s\n", optarg);
+ return 0;
+ }
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ default:
+ return qemuio_command_usage(&read_cmd);
+ }
+ }
+
+ if (optind != argc - 2) {
+ return qemuio_command_usage(&read_cmd);
+ }
+
+ if (bflag && pflag) {
+ printf("-b and -p cannot be specified at the same time\n");
+ return 0;
+ }
+
+ offset = cvtnum(argv[optind]);
+ if (offset < 0) {
+ printf("non-numeric length argument -- %s\n", argv[optind]);
+ return 0;
+ }
+
+ optind++;
+ count = cvtnum(argv[optind]);
+ if (count < 0) {
+ printf("non-numeric length argument -- %s\n", argv[optind]);
+ return 0;
+ }
+
+ if (!Pflag && (lflag || sflag)) {
+ return qemuio_command_usage(&read_cmd);
+ }
+
+ if (!lflag) {
+ pattern_count = count - pattern_offset;
+ }
+
+ if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
+ printf("pattern verification range exceeds end of read data\n");
+ return 0;
+ }
+
+ if (!pflag) {
+ if (offset & 0x1ff) {
+ printf("offset %" PRId64 " is not sector aligned\n",
+ offset);
+ return 0;
+ }
+ if (count & 0x1ff) {
+ printf("count %d is not sector aligned\n",
+ count);
+ return 0;
+ }
+ }
+
+ buf = qemu_io_alloc(bs, count, 0xab);
+
+ gettimeofday(&t1, NULL);
+ if (pflag) {
+ cnt = do_pread(bs, buf, offset, count, &total);
+ } else if (bflag) {
+ cnt = do_load_vmstate(bs, buf, offset, count, &total);
+ } else {
+ cnt = do_read(bs, buf, offset, count, &total);
+ }
+ gettimeofday(&t2, NULL);
+
+ if (cnt < 0) {
+ printf("read failed: %s\n", strerror(-cnt));
+ goto out;
+ }
+
+ if (Pflag) {
+ void *cmp_buf = g_malloc(pattern_count);
+ memset(cmp_buf, pattern, pattern_count);
+ if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
+ printf("Pattern verification failed at offset %"
+ PRId64 ", %d bytes\n",
+ offset + pattern_offset, pattern_count);
+ }
+ g_free(cmp_buf);
+ }
+
+ if (qflag) {
+ goto out;
+ }
+
+ if (vflag) {
+ dump_buffer(buf, offset, count);
+ }
+
+ /* Finally, report back -- -C gives a parsable format */
+ t2 = tsub(t2, t1);
+ print_report("read", &t2, offset, count, total, cnt, Cflag);
+
+out:
+ qemu_io_free(buf);
+
+ return 0;
+}
+
+static void readv_help(void)
+{
+ printf(
+"\n"
+" reads a range of bytes from the given offset into multiple buffers\n"
+"\n"
+" Example:\n"
+" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
+"\n"
+" Reads a segment of the currently open file, optionally dumping it to the\n"
+" standard output stream (with -v option) for subsequent inspection.\n"
+" Uses multiple iovec buffers if more than one byte range is specified.\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -P, -- use a pattern to verify read data\n"
+" -v, -- dump buffer to standard output\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+"\n");
+}
+
+static int readv_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t readv_cmd = {
+ .name = "readv",
+ .cfunc = readv_f,
+ .argmin = 2,
+ .argmax = -1,
+ .args = "[-Cqv] [-P pattern ] off len [len..]",
+ .oneline = "reads a number of bytes at a specified offset",
+ .help = readv_help,
+};
+
+static int readv_f(BlockDriverState *bs, int argc, char **argv)
+{
+ struct timeval t1, t2;
+ int Cflag = 0, qflag = 0, vflag = 0;
+ int c, cnt;
+ char *buf;
+ int64_t offset;
+ /* Some compilers get confused and warn if this is not initialized. */
+ int total = 0;
+ int nr_iov;
+ QEMUIOVector qiov;
+ int pattern = 0;
+ int Pflag = 0;
+
+ while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
+ switch (c) {
+ case 'C':
+ Cflag = 1;
+ break;
+ case 'P':
+ Pflag = 1;
+ pattern = parse_pattern(optarg);
+ if (pattern < 0) {
+ return 0;
+ }
+ break;
+ case 'q':
+ qflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ default:
+ return qemuio_command_usage(&readv_cmd);
+ }
+ }
+
+ if (optind > argc - 2) {
+ return qemuio_command_usage(&readv_cmd);
+ }
+
+
+ offset = cvtnum(argv[optind]);
+ if (offset < 0) {
+ printf("non-numeric length argument -- %s\n", argv[optind]);
+ return 0;
+ }
+ optind++;
+
+ if (offset & 0x1ff) {
+ printf("offset %" PRId64 " is not sector aligned\n",
+ offset);
+ return 0;
+ }
+
+ nr_iov = argc - optind;
+ buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
+ if (buf == NULL) {
+ return 0;
+ }
+
+ gettimeofday(&t1, NULL);
+ cnt = do_aio_readv(bs, &qiov, offset, &total);
+ gettimeofday(&t2, NULL);
+
+ if (cnt < 0) {
+ printf("readv failed: %s\n", strerror(-cnt));
+ goto out;
+ }
+
+ if (Pflag) {
+ void *cmp_buf = g_malloc(qiov.size);
+ memset(cmp_buf, pattern, qiov.size);
+ if (memcmp(buf, cmp_buf, qiov.size)) {
+ printf("Pattern verification failed at offset %"
+ PRId64 ", %zd bytes\n", offset, qiov.size);
+ }
+ g_free(cmp_buf);
+ }
+
+ if (qflag) {
+ goto out;
+ }
+
+ if (vflag) {
+ dump_buffer(buf, offset, qiov.size);
+ }
+
+ /* Finally, report back -- -C gives a parsable format */
+ t2 = tsub(t2, t1);
+ print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
+
+out:
+ qemu_iovec_destroy(&qiov);
+ qemu_io_free(buf);
+ return 0;
+}
+
+static void write_help(void)
+{
+ printf(
+"\n"
+" writes a range of bytes from the given offset\n"
+"\n"
+" Example:\n"
+" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
+"\n"
+" Writes into a segment of the currently open file, using a buffer\n"
+" filled with a set pattern (0xcdcdcdcd).\n"
+" -b, -- write to the VM state rather than the virtual disk\n"
+" -c, -- write compressed data with bdrv_write_compressed\n"
+" -p, -- use bdrv_pwrite to write the file\n"
+" -P, -- use different pattern to fill file\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+" -z, -- write zeroes using bdrv_co_write_zeroes\n"
+"\n");
+}
+
+static int write_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t write_cmd = {
+ .name = "write",
+ .altname = "w",
+ .cfunc = write_f,
+ .argmin = 2,
+ .argmax = -1,
+ .args = "[-bcCpqz] [-P pattern ] off len",
+ .oneline = "writes a number of bytes at a specified offset",
+ .help = write_help,
+};
+
+static int write_f(BlockDriverState *bs, int argc, char **argv)
+{
+ struct timeval t1, t2;
+ int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
+ int cflag = 0;
+ int c, cnt;
+ char *buf = NULL;
+ int64_t offset;
+ int count;
+ /* Some compilers get confused and warn if this is not initialized. */
+ int total = 0;
+ int pattern = 0xcd;
+
+ while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
+ switch (c) {
+ case 'b':
+ bflag = 1;
+ break;
+ case 'c':
+ cflag = 1;
+ break;
+ case 'C':
+ Cflag = 1;
+ break;
+ case 'p':
+ pflag = 1;
+ break;
+ case 'P':
+ Pflag = 1;
+ pattern = parse_pattern(optarg);
+ if (pattern < 0) {
+ return 0;
+ }
+ break;
+ case 'q':
+ qflag = 1;
+ break;
+ case 'z':
+ zflag = 1;
+ break;
+ default:
+ return qemuio_command_usage(&write_cmd);
+ }
+ }
+
+ if (optind != argc - 2) {
+ return qemuio_command_usage(&write_cmd);
+ }
+
+ if (bflag + pflag + zflag > 1) {
+ printf("-b, -p, or -z cannot be specified at the same time\n");
+ return 0;
+ }
+
+ if (zflag && Pflag) {
+ printf("-z and -P cannot be specified at the same time\n");
+ return 0;
+ }
+
+ offset = cvtnum(argv[optind]);
+ if (offset < 0) {
+ printf("non-numeric length argument -- %s\n", argv[optind]);
+ return 0;
+ }
+
+ optind++;
+ count = cvtnum(argv[optind]);
+ if (count < 0) {
+ printf("non-numeric length argument -- %s\n", argv[optind]);
+ return 0;
+ }
+
+ if (!pflag) {
+ if (offset & 0x1ff) {
+ printf("offset %" PRId64 " is not sector aligned\n",
+ offset);
+ return 0;
+ }
+
+ if (count & 0x1ff) {
+ printf("count %d is not sector aligned\n",
+ count);
+ return 0;
+ }
+ }
+
+ if (!zflag) {
+ buf = qemu_io_alloc(bs, count, pattern);
+ }
+
+ gettimeofday(&t1, NULL);
+ if (pflag) {
+ cnt = do_pwrite(bs, buf, offset, count, &total);
+ } else if (bflag) {
+ cnt = do_save_vmstate(bs, buf, offset, count, &total);
+ } else if (zflag) {
+ cnt = do_co_write_zeroes(bs, offset, count, &total);
+ } else if (cflag) {
+ cnt = do_write_compressed(bs, buf, offset, count, &total);
+ } else {
+ cnt = do_write(bs, buf, offset, count, &total);
+ }
+ gettimeofday(&t2, NULL);
+
+ if (cnt < 0) {
+ printf("write failed: %s\n", strerror(-cnt));
+ goto out;
+ }
+
+ if (qflag) {
+ goto out;
+ }
+
+ /* Finally, report back -- -C gives a parsable format */
+ t2 = tsub(t2, t1);
+ print_report("wrote", &t2, offset, count, total, cnt, Cflag);
+
+out:
+ if (!zflag) {
+ qemu_io_free(buf);
+ }
+
+ return 0;
+}
+
+static void
+writev_help(void)
+{
+ printf(
+"\n"
+" writes a range of bytes from the given offset source from multiple buffers\n"
+"\n"
+" Example:\n"
+" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
+"\n"
+" Writes into a segment of the currently open file, using a buffer\n"
+" filled with a set pattern (0xcdcdcdcd).\n"
+" -P, -- use different pattern to fill file\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+"\n");
+}
+
+static int writev_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t writev_cmd = {
+ .name = "writev",
+ .cfunc = writev_f,
+ .argmin = 2,
+ .argmax = -1,
+ .args = "[-Cq] [-P pattern ] off len [len..]",
+ .oneline = "writes a number of bytes at a specified offset",
+ .help = writev_help,
+};
+
+static int writev_f(BlockDriverState *bs, int argc, char **argv)
+{
+ struct timeval t1, t2;
+ int Cflag = 0, qflag = 0;
+ int c, cnt;
+ char *buf;
+ int64_t offset;
+ /* Some compilers get confused and warn if this is not initialized. */
+ int total = 0;
+ int nr_iov;
+ int pattern = 0xcd;
+ QEMUIOVector qiov;
+
+ while ((c = getopt(argc, argv, "CqP:")) != EOF) {
+ switch (c) {
+ case 'C':
+ Cflag = 1;
+ break;
+ case 'q':
+ qflag = 1;
+ break;
+ case 'P':
+ pattern = parse_pattern(optarg);
+ if (pattern < 0) {
+ return 0;
+ }
+ break;
+ default:
+ return qemuio_command_usage(&writev_cmd);
+ }
+ }
+
+ if (optind > argc - 2) {
+ return qemuio_command_usage(&writev_cmd);
+ }
+
+ offset = cvtnum(argv[optind]);
+ if (offset < 0) {
+ printf("non-numeric length argument -- %s\n", argv[optind]);
+ return 0;
+ }
+ optind++;
+
+ if (offset & 0x1ff) {
+ printf("offset %" PRId64 " is not sector aligned\n",
+ offset);
+ return 0;
+ }
+
+ nr_iov = argc - optind;
+ buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
+ if (buf == NULL) {
+ return 0;
+ }
+
+ gettimeofday(&t1, NULL);
+ cnt = do_aio_writev(bs, &qiov, offset, &total);
+ gettimeofday(&t2, NULL);
+
+ if (cnt < 0) {
+ printf("writev failed: %s\n", strerror(-cnt));
+ goto out;
+ }
+
+ if (qflag) {
+ goto out;
+ }
+
+ /* Finally, report back -- -C gives a parsable format */
+ t2 = tsub(t2, t1);
+ print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
+out:
+ qemu_iovec_destroy(&qiov);
+ qemu_io_free(buf);
+ return 0;
+}
+
+static void multiwrite_help(void)
+{
+ printf(
+"\n"
+" writes a range of bytes from the given offset source from multiple buffers,\n"
+" in a batch of requests that may be merged by qemu\n"
+"\n"
+" Example:\n"
+" 'multiwrite 512 1k 1k ; 4k 1k'\n"
+" writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
+"\n"
+" Writes into a segment of the currently open file, using a buffer\n"
+" filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
+" by one for each request contained in the multiwrite command.\n"
+" -P, -- use different pattern to fill file\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+"\n");
+}
+
+static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t multiwrite_cmd = {
+ .name = "multiwrite",
+ .cfunc = multiwrite_f,
+ .argmin = 2,
+ .argmax = -1,
+ .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
+ .oneline = "issues multiple write requests at once",
+ .help = multiwrite_help,
+};
+
+static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
+{
+ struct timeval t1, t2;
+ int Cflag = 0, qflag = 0;
+ int c, cnt;
+ char **buf;
+ int64_t offset, first_offset = 0;
+ /* Some compilers get confused and warn if this is not initialized. */
+ int total = 0;
+ int nr_iov;
+ int nr_reqs;
+ int pattern = 0xcd;
+ QEMUIOVector *qiovs;
+ int i;
+ BlockRequest *reqs;
+
+ while ((c = getopt(argc, argv, "CqP:")) != EOF) {
+ switch (c) {
+ case 'C':
+ Cflag = 1;
+ break;
+ case 'q':
+ qflag = 1;
+ break;
+ case 'P':
+ pattern = parse_pattern(optarg);
+ if (pattern < 0) {
+ return 0;
+ }
+ break;
+ default:
+ return qemuio_command_usage(&writev_cmd);
+ }
+ }
+
+ if (optind > argc - 2) {
+ return qemuio_command_usage(&writev_cmd);
+ }
+
+ nr_reqs = 1;
+ for (i = optind; i < argc; i++) {
+ if (!strcmp(argv[i], ";")) {
+ nr_reqs++;
+ }
+ }
+
+ reqs = g_malloc0(nr_reqs * sizeof(*reqs));
+ buf = g_malloc0(nr_reqs * sizeof(*buf));
+ qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
+
+ for (i = 0; i < nr_reqs && optind < argc; i++) {
+ int j;
+
+ /* Read the offset of the request */
+ offset = cvtnum(argv[optind]);
+ if (offset < 0) {
+ printf("non-numeric offset argument -- %s\n", argv[optind]);
+ goto out;
+ }
+ optind++;
+
+ if (offset & 0x1ff) {
+ printf("offset %lld is not sector aligned\n",
+ (long long)offset);
+ goto out;
+ }
+
+ if (i == 0) {
+ first_offset = offset;
+ }
+
+ /* Read lengths for qiov entries */
+ for (j = optind; j < argc; j++) {
+ if (!strcmp(argv[j], ";")) {
+ break;
+ }
+ }
+
+ nr_iov = j - optind;
+
+ /* Build request */
+ buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
+ if (buf[i] == NULL) {
+ goto out;
+ }
+
+ reqs[i].qiov = &qiovs[i];
+ reqs[i].sector = offset >> 9;
+ reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
+
+ optind = j + 1;
+
+ pattern++;
+ }
+
+ /* If there were empty requests at the end, ignore them */
+ nr_reqs = i;
+
+ gettimeofday(&t1, NULL);
+ cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
+ gettimeofday(&t2, NULL);
+
+ if (cnt < 0) {
+ printf("aio_multiwrite failed: %s\n", strerror(-cnt));
+ goto out;
+ }
+
+ if (qflag) {
+ goto out;
+ }
+
+ /* Finally, report back -- -C gives a parsable format */
+ t2 = tsub(t2, t1);
+ print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
+out:
+ for (i = 0; i < nr_reqs; i++) {
+ qemu_io_free(buf[i]);
+ if (reqs[i].qiov != NULL) {
+ qemu_iovec_destroy(&qiovs[i]);
+ }
+ }
+ g_free(buf);
+ g_free(reqs);
+ g_free(qiovs);
+ return 0;
+}
+
+struct aio_ctx {
+ QEMUIOVector qiov;
+ int64_t offset;
+ char *buf;
+ int qflag;
+ int vflag;
+ int Cflag;
+ int Pflag;
+ int pattern;
+ struct timeval t1;
+};
+
+static void aio_write_done(void *opaque, int ret)
+{
+ struct aio_ctx *ctx = opaque;
+ struct timeval t2;
+
+ gettimeofday(&t2, NULL);
+
+
+ if (ret < 0) {
+ printf("aio_write failed: %s\n", strerror(-ret));
+ goto out;
+ }
+
+ if (ctx->qflag) {
+ goto out;
+ }
+
+ /* Finally, report back -- -C gives a parsable format */
+ t2 = tsub(t2, ctx->t1);
+ print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
+ ctx->qiov.size, 1, ctx->Cflag);
+out:
+ qemu_io_free(ctx->buf);
+ qemu_iovec_destroy(&ctx->qiov);
+ g_free(ctx);
+}
+
+static void aio_read_done(void *opaque, int ret)
+{
+ struct aio_ctx *ctx = opaque;
+ struct timeval t2;
+
+ gettimeofday(&t2, NULL);
+
+ if (ret < 0) {
+ printf("readv failed: %s\n", strerror(-ret));
+ goto out;
+ }
+
+ if (ctx->Pflag) {
+ void *cmp_buf = g_malloc(ctx->qiov.size);
+
+ memset(cmp_buf, ctx->pattern, ctx->qiov.size);
+ if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
+ printf("Pattern verification failed at offset %"
+ PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
+ }
+ g_free(cmp_buf);
+ }
+
+ if (ctx->qflag) {
+ goto out;
+ }
+
+ if (ctx->vflag) {
+ dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
+ }
+
+ /* Finally, report back -- -C gives a parsable format */
+ t2 = tsub(t2, ctx->t1);
+ print_report("read", &t2, ctx->offset, ctx->qiov.size,
+ ctx->qiov.size, 1, ctx->Cflag);
+out:
+ qemu_io_free(ctx->buf);
+ qemu_iovec_destroy(&ctx->qiov);
+ g_free(ctx);
+}
+
+static void aio_read_help(void)
+{
+ printf(
+"\n"
+" asynchronously reads a range of bytes from the given offset\n"
+"\n"
+" Example:\n"
+" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
+"\n"
+" Reads a segment of the currently open file, optionally dumping it to the\n"
+" standard output stream (with -v option) for subsequent inspection.\n"
+" The read is performed asynchronously and the aio_flush command must be\n"
+" used to ensure all outstanding aio requests have been completed.\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -P, -- use a pattern to verify read data\n"
+" -v, -- dump buffer to standard output\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+"\n");
+}
+
+static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t aio_read_cmd = {
+ .name = "aio_read",
+ .cfunc = aio_read_f,
+ .argmin = 2,
+ .argmax = -1,
+ .args = "[-Cqv] [-P pattern ] off len [len..]",
+ .oneline = "asynchronously reads a number of bytes",
+ .help = aio_read_help,
+};
+
+static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
+{
+ int nr_iov, c;
+ struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
+
+ while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
+ switch (c) {
+ case 'C':
+ ctx->Cflag = 1;
+ break;
+ case 'P':
+ ctx->Pflag = 1;
+ ctx->pattern = parse_pattern(optarg);
+ if (ctx->pattern < 0) {
+ g_free(ctx);
+ return 0;
+ }
+ break;
+ case 'q':
+ ctx->qflag = 1;
+ break;
+ case 'v':
+ ctx->vflag = 1;
+ break;
+ default:
+ g_free(ctx);
+ return qemuio_command_usage(&aio_read_cmd);
+ }
+ }
+
+ if (optind > argc - 2) {
+ g_free(ctx);
+ return qemuio_command_usage(&aio_read_cmd);
+ }
+
+ ctx->offset = cvtnum(argv[optind]);
+ if (ctx->offset < 0) {
+ printf("non-numeric length argument -- %s\n", argv[optind]);
+ g_free(ctx);
+ return 0;
+ }
+ optind++;
+
+ if (ctx->offset & 0x1ff) {
+ printf("offset %" PRId64 " is not sector aligned\n",
+ ctx->offset);
+ g_free(ctx);
+ return 0;
+ }
+
+ nr_iov = argc - optind;
+ ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
+ if (ctx->buf == NULL) {
+ g_free(ctx);
+ return 0;
+ }
+
+ gettimeofday(&ctx->t1, NULL);
+ bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
+ ctx->qiov.size >> 9, aio_read_done, ctx);
+ return 0;
+}
+
+static void aio_write_help(void)
+{
+ printf(
+"\n"
+" asynchronously writes a range of bytes from the given offset source\n"
+" from multiple buffers\n"
+"\n"
+" Example:\n"
+" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
+"\n"
+" Writes into a segment of the currently open file, using a buffer\n"
+" filled with a set pattern (0xcdcdcdcd).\n"
+" The write is performed asynchronously and the aio_flush command must be\n"
+" used to ensure all outstanding aio requests have been completed.\n"
+" -P, -- use different pattern to fill file\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+"\n");
+}
+
+static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t aio_write_cmd = {
+ .name = "aio_write",
+ .cfunc = aio_write_f,
+ .argmin = 2,
+ .argmax = -1,
+ .args = "[-Cq] [-P pattern ] off len [len..]",
+ .oneline = "asynchronously writes a number of bytes",
+ .help = aio_write_help,
+};
+
+static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
+{
+ int nr_iov, c;
+ int pattern = 0xcd;
+ struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
+
+ while ((c = getopt(argc, argv, "CqP:")) != EOF) {
+ switch (c) {
+ case 'C':
+ ctx->Cflag = 1;
+ break;
+ case 'q':
+ ctx->qflag = 1;
+ break;
+ case 'P':
+ pattern = parse_pattern(optarg);
+ if (pattern < 0) {
+ g_free(ctx);
+ return 0;
+ }
+ break;
+ default:
+ g_free(ctx);
+ return qemuio_command_usage(&aio_write_cmd);
+ }
+ }
+
+ if (optind > argc - 2) {
+ g_free(ctx);
+ return qemuio_command_usage(&aio_write_cmd);
+ }
+
+ ctx->offset = cvtnum(argv[optind]);
+ if (ctx->offset < 0) {
+ printf("non-numeric length argument -- %s\n", argv[optind]);
+ g_free(ctx);
+ return 0;
+ }
+ optind++;
+
+ if (ctx->offset & 0x1ff) {
+ printf("offset %" PRId64 " is not sector aligned\n",
+ ctx->offset);
+ g_free(ctx);
+ return 0;
+ }
+
+ nr_iov = argc - optind;
+ ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
+ if (ctx->buf == NULL) {
+ g_free(ctx);
+ return 0;
+ }
+
+ gettimeofday(&ctx->t1, NULL);
+ bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
+ ctx->qiov.size >> 9, aio_write_done, ctx);
+ return 0;
+}
+
+static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
+{
+ bdrv_drain_all();
+ return 0;
+}
+
+static const cmdinfo_t aio_flush_cmd = {
+ .name = "aio_flush",
+ .cfunc = aio_flush_f,
+ .oneline = "completes all outstanding aio requests"
+};
+
+static int flush_f(BlockDriverState *bs, int argc, char **argv)
+{
+ bdrv_flush(bs);
+ return 0;
+}
+
+static const cmdinfo_t flush_cmd = {
+ .name = "flush",
+ .altname = "f",
+ .cfunc = flush_f,
+ .oneline = "flush all in-core file state to disk",
+};
+
+static int truncate_f(BlockDriverState *bs, int argc, char **argv)
+{
+ int64_t offset;
+ int ret;
+
+ offset = cvtnum(argv[1]);
+ if (offset < 0) {
+ printf("non-numeric truncate argument -- %s\n", argv[1]);
+ return 0;
+ }
+
+ ret = bdrv_truncate(bs, offset);
+ if (ret < 0) {
+ printf("truncate: %s\n", strerror(-ret));
+ return 0;
+ }
+
+ return 0;
+}
+
+static const cmdinfo_t truncate_cmd = {
+ .name = "truncate",
+ .altname = "t",
+ .cfunc = truncate_f,
+ .argmin = 1,
+ .argmax = 1,
+ .args = "off",
+ .oneline = "truncates the current file at the given offset",
+};
+
+static int length_f(BlockDriverState *bs, int argc, char **argv)
+{
+ int64_t size;
+ char s1[64];
+
+ size = bdrv_getlength(bs);
+ if (size < 0) {
+ printf("getlength: %s\n", strerror(-size));
+ return 0;
+ }
+
+ cvtstr(size, s1, sizeof(s1));
+ printf("%s\n", s1);
+ return 0;
+}
+
+
+static const cmdinfo_t length_cmd = {
+ .name = "length",
+ .altname = "l",
+ .cfunc = length_f,
+ .oneline = "gets the length of the current file",
+};
+
+
+static int info_f(BlockDriverState *bs, int argc, char **argv)
+{
+ BlockDriverInfo bdi;
+ char s1[64], s2[64];
+ int ret;
+
+ if (bs->drv && bs->drv->format_name) {
+ printf("format name: %s\n", bs->drv->format_name);
+ }
+ if (bs->drv && bs->drv->protocol_name) {
+ printf("format name: %s\n", bs->drv->protocol_name);
+ }
+
+ ret = bdrv_get_info(bs, &bdi);
+ if (ret) {
+ return 0;
+ }
+
+ cvtstr(bdi.cluster_size, s1, sizeof(s1));
+ cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
+
+ printf("cluster size: %s\n", s1);
+ printf("vm state offset: %s\n", s2);
+
+ return 0;
+}
+
+
+
+static const cmdinfo_t info_cmd = {
+ .name = "info",
+ .altname = "i",
+ .cfunc = info_f,
+ .oneline = "prints information about the current file",
+};
+
+static void discard_help(void)
+{
+ printf(
+"\n"
+" discards a range of bytes from the given offset\n"
+"\n"
+" Example:\n"
+" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
+"\n"
+" Discards a segment of the currently open file.\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+"\n");
+}
+
+static int discard_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t discard_cmd = {
+ .name = "discard",
+ .altname = "d",
+ .cfunc = discard_f,
+ .argmin = 2,
+ .argmax = -1,
+ .args = "[-Cq] off len",
+ .oneline = "discards a number of bytes at a specified offset",
+ .help = discard_help,
+};
+
+static int discard_f(BlockDriverState *bs, int argc, char **argv)
+{
+ struct timeval t1, t2;
+ int Cflag = 0, qflag = 0;
+ int c, ret;
+ int64_t offset;
+ int count;
+
+ while ((c = getopt(argc, argv, "Cq")) != EOF) {
+ switch (c) {
+ case 'C':
+ Cflag = 1;
+ break;
+ case 'q':
+ qflag = 1;
+ break;
+ default:
+ return qemuio_command_usage(&discard_cmd);
+ }
+ }
+
+ if (optind != argc - 2) {
+ return qemuio_command_usage(&discard_cmd);
+ }
+
+ offset = cvtnum(argv[optind]);
+ if (offset < 0) {
+ printf("non-numeric length argument -- %s\n", argv[optind]);
+ return 0;
+ }
+
+ optind++;
+ count = cvtnum(argv[optind]);
+ if (count < 0) {
+ printf("non-numeric length argument -- %s\n", argv[optind]);
+ return 0;
+ }
+
+ gettimeofday(&t1, NULL);
+ ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
+ count >> BDRV_SECTOR_BITS);
+ gettimeofday(&t2, NULL);
+
+ if (ret < 0) {
+ printf("discard failed: %s\n", strerror(-ret));
+ goto out;
+ }
+
+ /* Finally, report back -- -C gives a parsable format */
+ if (!qflag) {
+ t2 = tsub(t2, t1);
+ print_report("discard", &t2, offset, count, count, 1, Cflag);
+ }
+
+out:
+ return 0;
+}
+
+static int alloc_f(BlockDriverState *bs, int argc, char **argv)
+{
+ int64_t offset, sector_num;
+ int nb_sectors, remaining;
+ char s1[64];
+ int num, sum_alloc;
+ int ret;
+
+ offset = cvtnum(argv[1]);
+ if (offset < 0) {
+ printf("non-numeric offset argument -- %s\n", argv[1]);
+ return 0;
+ } else if (offset & 0x1ff) {
+ printf("offset %" PRId64 " is not sector aligned\n",
+ offset);
+ return 0;
+ }
+
+ if (argc == 3) {
+ nb_sectors = cvtnum(argv[2]);
+ if (nb_sectors < 0) {
+ printf("non-numeric length argument -- %s\n", argv[2]);
+ return 0;
+ }
+ } else {
+ nb_sectors = 1;
+ }
+
+ remaining = nb_sectors;
+ sum_alloc = 0;
+ sector_num = offset >> 9;
+ while (remaining) {
+ ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
+ sector_num += num;
+ remaining -= num;
+ if (ret) {
+ sum_alloc += num;
+ }
+ if (num == 0) {
+ nb_sectors -= remaining;
+ remaining = 0;
+ }
+ }
+
+ cvtstr(offset, s1, sizeof(s1));
+
+ printf("%d/%d sectors allocated at offset %s\n",
+ sum_alloc, nb_sectors, s1);
+ return 0;
+}
+
+static const cmdinfo_t alloc_cmd = {
+ .name = "alloc",
+ .altname = "a",
+ .argmin = 1,
+ .argmax = 2,
+ .cfunc = alloc_f,
+ .args = "off [sectors]",
+ .oneline = "checks if a sector is present in the file",
+};
+
+
+static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
+ int64_t nb_sectors, int64_t *pnum)
+{
+ int num, num_checked;
+ int ret, firstret;
+
+ num_checked = MIN(nb_sectors, INT_MAX);
+ ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
+ if (ret < 0) {
+ return ret;
+ }
+
+ firstret = ret;
+ *pnum = num;
+
+ while (nb_sectors > 0 && ret == firstret) {
+ sector_num += num;
+ nb_sectors -= num;
+
+ num_checked = MIN(nb_sectors, INT_MAX);
+ ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
+ if (ret == firstret) {
+ *pnum += num;
+ } else {
+ break;
+ }
+ }
+
+ return firstret;
+}
+
+static int map_f(BlockDriverState *bs, int argc, char **argv)
+{
+ int64_t offset;
+ int64_t nb_sectors;
+ char s1[64];
+ int64_t num;
+ int ret;
+ const char *retstr;
+
+ offset = 0;
+ nb_sectors = bs->total_sectors;
+
+ do {
+ ret = map_is_allocated(bs, offset, nb_sectors, &num);
+ if (ret < 0) {
+ error_report("Failed to get allocation status: %s", strerror(-ret));
+ return 0;
+ }
+
+ retstr = ret ? " allocated" : "not allocated";
+ cvtstr(offset << 9ULL, s1, sizeof(s1));
+ printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
+ "at offset %s (%d)\n",
+ offset << 9ULL, num, nb_sectors, retstr, s1, ret);
+
+ offset += num;
+ nb_sectors -= num;
+ } while (offset < bs->total_sectors);
+
+ return 0;
+}
+
+static const cmdinfo_t map_cmd = {
+ .name = "map",
+ .argmin = 0,
+ .argmax = 0,
+ .cfunc = map_f,
+ .args = "",
+ .oneline = "prints the allocated areas of a file",
+};
+
+static int break_f(BlockDriverState *bs, int argc, char **argv)
+{
+ int ret;
+
+ ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
+ if (ret < 0) {
+ printf("Could not set breakpoint: %s\n", strerror(-ret));
+ }
+
+ return 0;
+}
+
+static const cmdinfo_t break_cmd = {
+ .name = "break",
+ .argmin = 2,
+ .argmax = 2,
+ .cfunc = break_f,
+ .args = "event tag",
+ .oneline = "sets a breakpoint on event and tags the stopped "
+ "request as tag",
+};
+
+static int resume_f(BlockDriverState *bs, int argc, char **argv)
+{
+ int ret;
+
+ ret = bdrv_debug_resume(bs, argv[1]);
+ if (ret < 0) {
+ printf("Could not resume request: %s\n", strerror(-ret));
+ }
+
+ return 0;
+}
+
+static const cmdinfo_t resume_cmd = {
+ .name = "resume",
+ .argmin = 1,
+ .argmax = 1,
+ .cfunc = resume_f,
+ .args = "tag",
+ .oneline = "resumes the request tagged as tag",
+};
+
+static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
+{
+ while (!bdrv_debug_is_suspended(bs, argv[1])) {
+ qemu_aio_wait();
+ }
+
+ return 0;
+}
+
+static const cmdinfo_t wait_break_cmd = {
+ .name = "wait_break",
+ .argmin = 1,
+ .argmax = 1,
+ .cfunc = wait_break_f,
+ .args = "tag",
+ .oneline = "waits for the suspension of a request",
+};
+
+static int abort_f(BlockDriverState *bs, int argc, char **argv)
+{
+ abort();
+}
+
+static const cmdinfo_t abort_cmd = {
+ .name = "abort",
+ .cfunc = abort_f,
+ .flags = CMD_NOFILE_OK,
+ .oneline = "simulate a program crash using abort(3)",
+};
+
+static void help_oneline(const char *cmd, const cmdinfo_t *ct)
+{
+ if (cmd) {
+ printf("%s ", cmd);
+ } else {
+ printf("%s ", ct->name);
+ if (ct->altname) {
+ printf("(or %s) ", ct->altname);
+ }
+ }
+
+ if (ct->args) {
+ printf("%s ", ct->args);
+ }
+ printf("-- %s\n", ct->oneline);
+}
+
+static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
+{
+ help_oneline(cmd, ct);
+ if (ct->help) {
+ ct->help();
+ }
+}
+
+static void help_all(void)
+{
+ const cmdinfo_t *ct;
+
+ for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
+ help_oneline(ct->name, ct);
+ }
+ printf("\nUse 'help commandname' for extended help.\n");
+}
+
+static int help_f(BlockDriverState *bs, int argc, char **argv)
+{
+ const cmdinfo_t *ct;
+
+ if (argc == 1) {
+ help_all();
+ return 0;
+ }
+
+ ct = find_command(argv[1]);
+ if (ct == NULL) {
+ printf("command %s not found\n", argv[1]);
+ return 0;
+ }
+
+ help_onecmd(argv[1], ct);
+ return 0;
+}
+
+static const cmdinfo_t help_cmd = {
+ .name = "help",
+ .altname = "?",
+ .cfunc = help_f,
+ .argmin = 0,
+ .argmax = 1,
+ .flags = CMD_FLAG_GLOBAL,
+ .args = "[command]",
+ .oneline = "help for one or all commands",
+};
+
+bool qemuio_command(BlockDriverState *bs, const char *cmd)
+{
+ char *input;
+ const cmdinfo_t *ct;
+ char **v;
+ int c;
+ bool done = false;
+
+ input = g_strdup(cmd);
+ v = breakline(input, &c);
+ if (c) {
+ ct = find_command(v[0]);
+ if (ct) {
+ done = command(bs, ct, c, v);
+ } else {
+ fprintf(stderr, "command \"%s\" not found\n", v[0]);
+ }
+ }
+ g_free(input);
+ g_free(v);
+
+ return done;
+}
+
+static void __attribute((constructor)) init_qemuio_commands(void)
+{
+ /* initialize commands */
+ qemuio_add_command(&help_cmd);
+ qemuio_add_command(&read_cmd);
+ qemuio_add_command(&readv_cmd);
+ qemuio_add_command(&write_cmd);
+ qemuio_add_command(&writev_cmd);
+ qemuio_add_command(&multiwrite_cmd);
+ qemuio_add_command(&aio_read_cmd);
+ qemuio_add_command(&aio_write_cmd);
+ qemuio_add_command(&aio_flush_cmd);
+ qemuio_add_command(&flush_cmd);
+ qemuio_add_command(&truncate_cmd);
+ qemuio_add_command(&length_cmd);
+ qemuio_add_command(&info_cmd);
+ qemuio_add_command(&discard_cmd);
+ qemuio_add_command(&alloc_cmd);
+ qemuio_add_command(&map_cmd);
+ qemuio_add_command(&break_cmd);
+ qemuio_add_command(&resume_cmd);
+ qemuio_add_command(&wait_break_cmd);
+ qemuio_add_command(&abort_cmd);
+}
diff --git a/qemu-io.c b/qemu-io.c
index 5e6680b247..cb9def50e6 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -14,1776 +14,26 @@
#include <getopt.h>
#include <libgen.h>
-#include "qemu-common.h"
+#include "qemu-io.h"
#include "qemu/main-loop.h"
#include "block/block_int.h"
-#include "cmd.h"
#include "trace/control.h"
-#define VERSION "0.0.1"
-
#define CMD_NOFILE_OK 0x01
char *progname;
-static BlockDriverState *bs;
-
-static int misalign;
-
-/*
- * Parse the pattern argument to various sub-commands.
- *
- * Because the pattern is used as an argument to memset it must evaluate
- * to an unsigned integer that fits into a single byte.
- */
-static int parse_pattern(const char *arg)
-{
- char *endptr = NULL;
- long pattern;
-
- pattern = strtol(arg, &endptr, 0);
- if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
- printf("%s is not a valid pattern byte\n", arg);
- return -1;
- }
-
- return pattern;
-}
-
-/*
- * Memory allocation helpers.
- *
- * Make sure memory is aligned by default, or purposefully misaligned if
- * that is specified on the command line.
- */
-
-#define MISALIGN_OFFSET 16
-static void *qemu_io_alloc(size_t len, int pattern)
-{
- void *buf;
-
- if (misalign) {
- len += MISALIGN_OFFSET;
- }
- buf = qemu_blockalign(bs, len);
- memset(buf, pattern, len);
- if (misalign) {
- buf += MISALIGN_OFFSET;
- }
- return buf;
-}
-
-static void qemu_io_free(void *p)
-{
- if (misalign) {
- p -= MISALIGN_OFFSET;
- }
- qemu_vfree(p);
-}
-
-static void dump_buffer(const void *buffer, int64_t offset, int len)
-{
- int i, j;
- const uint8_t *p;
-
- for (i = 0, p = buffer; i < len; i += 16) {
- const uint8_t *s = p;
-
- printf("%08" PRIx64 ": ", offset + i);
- for (j = 0; j < 16 && i + j < len; j++, p++) {
- printf("%02x ", *p);
- }
- printf(" ");
- for (j = 0; j < 16 && i + j < len; j++, s++) {
- if (isalnum(*s)) {
- printf("%c", *s);
- } else {
- printf(".");
- }
- }
- printf("\n");
- }
-}
-
-static void print_report(const char *op, struct timeval *t, int64_t offset,
- int count, int total, int cnt, int Cflag)
-{
- char s1[64], s2[64], ts[64];
-
- timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
- if (!Cflag) {
- cvtstr((double)total, s1, sizeof(s1));
- cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
- printf("%s %d/%d bytes at offset %" PRId64 "\n",
- op, total, count, offset);
- printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
- s1, cnt, ts, s2, tdiv((double)cnt, *t));
- } else {/* bytes,ops,time,bytes/sec,ops/sec */
- printf("%d,%d,%s,%.3f,%.3f\n",
- total, cnt, ts,
- tdiv((double)total, *t),
- tdiv((double)cnt, *t));
- }
-}
-
-/*
- * Parse multiple length statements for vectored I/O, and construct an I/O
- * vector matching it.
- */
-static void *
-create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
-{
- size_t *sizes = g_new0(size_t, nr_iov);
- size_t count = 0;
- void *buf = NULL;
- void *p;
- int i;
-
- for (i = 0; i < nr_iov; i++) {
- char *arg = argv[i];
- int64_t len;
-
- len = cvtnum(arg);
- if (len < 0) {
- printf("non-numeric length argument -- %s\n", arg);
- goto fail;
- }
-
- /* should be SIZE_T_MAX, but that doesn't exist */
- if (len > INT_MAX) {
- printf("too large length argument -- %s\n", arg);
- goto fail;
- }
-
- if (len & 0x1ff) {
- printf("length argument %" PRId64
- " is not sector aligned\n", len);
- goto fail;
- }
-
- sizes[i] = len;
- count += len;
- }
-
- qemu_iovec_init(qiov, nr_iov);
-
- buf = p = qemu_io_alloc(count, pattern);
-
- for (i = 0; i < nr_iov; i++) {
- qemu_iovec_add(qiov, p, sizes[i]);
- p += sizes[i];
- }
-
-fail:
- g_free(sizes);
- return buf;
-}
-
-static int do_read(char *buf, int64_t offset, int count, int *total)
-{
- int ret;
-
- ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
- if (ret < 0) {
- return ret;
- }
- *total = count;
- return 1;
-}
-
-static int do_write(char *buf, int64_t offset, int count, int *total)
-{
- int ret;
-
- ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
- if (ret < 0) {
- return ret;
- }
- *total = count;
- return 1;
-}
-
-static int do_pread(char *buf, int64_t offset, int count, int *total)
-{
- *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
- if (*total < 0) {
- return *total;
- }
- return 1;
-}
-
-static int do_pwrite(char *buf, int64_t offset, int count, int *total)
-{
- *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
- if (*total < 0) {
- return *total;
- }
- return 1;
-}
-
-typedef struct {
- int64_t offset;
- int count;
- int *total;
- int ret;
- bool done;
-} CoWriteZeroes;
-
-static void coroutine_fn co_write_zeroes_entry(void *opaque)
-{
- CoWriteZeroes *data = opaque;
-
- data->ret = bdrv_co_write_zeroes(bs, data->offset / BDRV_SECTOR_SIZE,
- data->count / BDRV_SECTOR_SIZE);
- data->done = true;
- if (data->ret < 0) {
- *data->total = data->ret;
- return;
- }
-
- *data->total = data->count;
-}
-
-static int do_co_write_zeroes(int64_t offset, int count, int *total)
-{
- Coroutine *co;
- CoWriteZeroes data = {
- .offset = offset,
- .count = count,
- .total = total,
- .done = false,
- };
-
- co = qemu_coroutine_create(co_write_zeroes_entry);
- qemu_coroutine_enter(co, &data);
- while (!data.done) {
- qemu_aio_wait();
- }
- if (data.ret < 0) {
- return data.ret;
- } else {
- return 1;
- }
-}
-
-static int do_write_compressed(char *buf, int64_t offset, int count, int *total)
-{
- int ret;
-
- ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
- if (ret < 0) {
- return ret;
- }
- *total = count;
- return 1;
-}
-
-static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
-{
- *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
- if (*total < 0) {
- return *total;
- }
- return 1;
-}
-
-static int do_save_vmstate(char *buf, int64_t offset, int count, int *total)
-{
- *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
- if (*total < 0) {
- return *total;
- }
- return 1;
-}
-
-#define NOT_DONE 0x7fffffff
-static void aio_rw_done(void *opaque, int ret)
-{
- *(int *)opaque = ret;
-}
-
-static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
-{
- int async_ret = NOT_DONE;
-
- bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
- aio_rw_done, &async_ret);
- while (async_ret == NOT_DONE) {
- main_loop_wait(false);
- }
-
- *total = qiov->size;
- return async_ret < 0 ? async_ret : 1;
-}
-
-static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
-{
- int async_ret = NOT_DONE;
-
- bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
- aio_rw_done, &async_ret);
- while (async_ret == NOT_DONE) {
- main_loop_wait(false);
- }
-
- *total = qiov->size;
- return async_ret < 0 ? async_ret : 1;
-}
-
-struct multiwrite_async_ret {
- int num_done;
- int error;
-};
-
-static void multiwrite_cb(void *opaque, int ret)
-{
- struct multiwrite_async_ret *async_ret = opaque;
-
- async_ret->num_done++;
- if (ret < 0) {
- async_ret->error = ret;
- }
-}
-
-static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total)
-{
- int i, ret;
- struct multiwrite_async_ret async_ret = {
- .num_done = 0,
- .error = 0,
- };
- *total = 0;
- for (i = 0; i < num_reqs; i++) {
- reqs[i].cb = multiwrite_cb;
- reqs[i].opaque = &async_ret;
- *total += reqs[i].qiov->size;
- }
-
- ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
- if (ret < 0) {
- return ret;
- }
-
- while (async_ret.num_done < num_reqs) {
- main_loop_wait(false);
- }
-
- return async_ret.error < 0 ? async_ret.error : 1;
-}
-
-static void read_help(void)
-{
- printf(
-"\n"
-" reads a range of bytes from the given offset\n"
-"\n"
-" Example:\n"
-" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
-"\n"
-" Reads a segment of the currently open file, optionally dumping it to the\n"
-" standard output stream (with -v option) for subsequent inspection.\n"
-" -b, -- read from the VM state rather than the virtual disk\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -l, -- length for pattern verification (only with -P)\n"
-" -p, -- use bdrv_pread to read the file\n"
-" -P, -- use a pattern to verify read data\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-" -s, -- start offset for pattern verification (only with -P)\n"
-" -v, -- dump buffer to standard output\n"
-"\n");
-}
-
-static int read_f(int argc, char **argv);
+BlockDriverState *qemuio_bs;
+extern int qemuio_misalign;
-static const cmdinfo_t read_cmd = {
- .name = "read",
- .altname = "r",
- .cfunc = read_f,
- .argmin = 2,
- .argmax = -1,
- .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
- .oneline = "reads a number of bytes at a specified offset",
- .help = read_help,
-};
+/* qemu-io commands passed using -c */
+static int ncmdline;
+static char **cmdline;
-static int read_f(int argc, char **argv)
-{
- struct timeval t1, t2;
- int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
- int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
- int c, cnt;
- char *buf;
- int64_t offset;
- int count;
- /* Some compilers get confused and warn if this is not initialized. */
- int total = 0;
- int pattern = 0, pattern_offset = 0, pattern_count = 0;
-
- while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
- switch (c) {
- case 'b':
- bflag = 1;
- break;
- case 'C':
- Cflag = 1;
- break;
- case 'l':
- lflag = 1;
- pattern_count = cvtnum(optarg);
- if (pattern_count < 0) {
- printf("non-numeric length argument -- %s\n", optarg);
- return 0;
- }
- break;
- case 'p':
- pflag = 1;
- break;
- case 'P':
- Pflag = 1;
- pattern = parse_pattern(optarg);
- if (pattern < 0) {
- return 0;
- }
- break;
- case 'q':
- qflag = 1;
- break;
- case 's':
- sflag = 1;
- pattern_offset = cvtnum(optarg);
- if (pattern_offset < 0) {
- printf("non-numeric length argument -- %s\n", optarg);
- return 0;
- }
- break;
- case 'v':
- vflag = 1;
- break;
- default:
- return command_usage(&read_cmd);
- }
- }
-
- if (optind != argc - 2) {
- return command_usage(&read_cmd);
- }
-
- if (bflag && pflag) {
- printf("-b and -p cannot be specified at the same time\n");
- return 0;
- }
-
- offset = cvtnum(argv[optind]);
- if (offset < 0) {
- printf("non-numeric length argument -- %s\n", argv[optind]);
- return 0;
- }
-
- optind++;
- count = cvtnum(argv[optind]);
- if (count < 0) {
- printf("non-numeric length argument -- %s\n", argv[optind]);
- return 0;
- }
-
- if (!Pflag && (lflag || sflag)) {
- return command_usage(&read_cmd);
- }
-
- if (!lflag) {
- pattern_count = count - pattern_offset;
- }
-
- if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
- printf("pattern verification range exceeds end of read data\n");
- return 0;
- }
-
- if (!pflag) {
- if (offset & 0x1ff) {
- printf("offset %" PRId64 " is not sector aligned\n",
- offset);
- return 0;
- }
- if (count & 0x1ff) {
- printf("count %d is not sector aligned\n",
- count);
- return 0;
- }
- }
-
- buf = qemu_io_alloc(count, 0xab);
-
- gettimeofday(&t1, NULL);
- if (pflag) {
- cnt = do_pread(buf, offset, count, &total);
- } else if (bflag) {
- cnt = do_load_vmstate(buf, offset, count, &total);
- } else {
- cnt = do_read(buf, offset, count, &total);
- }
- gettimeofday(&t2, NULL);
-
- if (cnt < 0) {
- printf("read failed: %s\n", strerror(-cnt));
- goto out;
- }
-
- if (Pflag) {
- void *cmp_buf = g_malloc(pattern_count);
- memset(cmp_buf, pattern, pattern_count);
- if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
- printf("Pattern verification failed at offset %"
- PRId64 ", %d bytes\n",
- offset + pattern_offset, pattern_count);
- }
- g_free(cmp_buf);
- }
-
- if (qflag) {
- goto out;
- }
-
- if (vflag) {
- dump_buffer(buf, offset, count);
- }
-
- /* Finally, report back -- -C gives a parsable format */
- t2 = tsub(t2, t1);
- print_report("read", &t2, offset, count, total, cnt, Cflag);
-
-out:
- qemu_io_free(buf);
-
- return 0;
-}
-
-static void readv_help(void)
-{
- printf(
-"\n"
-" reads a range of bytes from the given offset into multiple buffers\n"
-"\n"
-" Example:\n"
-" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
-"\n"
-" Reads a segment of the currently open file, optionally dumping it to the\n"
-" standard output stream (with -v option) for subsequent inspection.\n"
-" Uses multiple iovec buffers if more than one byte range is specified.\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -P, -- use a pattern to verify read data\n"
-" -v, -- dump buffer to standard output\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-"\n");
-}
-
-static int readv_f(int argc, char **argv);
-
-static const cmdinfo_t readv_cmd = {
- .name = "readv",
- .cfunc = readv_f,
- .argmin = 2,
- .argmax = -1,
- .args = "[-Cqv] [-P pattern ] off len [len..]",
- .oneline = "reads a number of bytes at a specified offset",
- .help = readv_help,
-};
-
-static int readv_f(int argc, char **argv)
-{
- struct timeval t1, t2;
- int Cflag = 0, qflag = 0, vflag = 0;
- int c, cnt;
- char *buf;
- int64_t offset;
- /* Some compilers get confused and warn if this is not initialized. */
- int total = 0;
- int nr_iov;
- QEMUIOVector qiov;
- int pattern = 0;
- int Pflag = 0;
-
- while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
- switch (c) {
- case 'C':
- Cflag = 1;
- break;
- case 'P':
- Pflag = 1;
- pattern = parse_pattern(optarg);
- if (pattern < 0) {
- return 0;
- }
- break;
- case 'q':
- qflag = 1;
- break;
- case 'v':
- vflag = 1;
- break;
- default:
- return command_usage(&readv_cmd);
- }
- }
-
- if (optind > argc - 2) {
- return command_usage(&readv_cmd);
- }
-
-
- offset = cvtnum(argv[optind]);
- if (offset < 0) {
- printf("non-numeric length argument -- %s\n", argv[optind]);
- return 0;
- }
- optind++;
-
- if (offset & 0x1ff) {
- printf("offset %" PRId64 " is not sector aligned\n",
- offset);
- return 0;
- }
-
- nr_iov = argc - optind;
- buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
- if (buf == NULL) {
- return 0;
- }
-
- gettimeofday(&t1, NULL);
- cnt = do_aio_readv(&qiov, offset, &total);
- gettimeofday(&t2, NULL);
-
- if (cnt < 0) {
- printf("readv failed: %s\n", strerror(-cnt));
- goto out;
- }
-
- if (Pflag) {
- void *cmp_buf = g_malloc(qiov.size);
- memset(cmp_buf, pattern, qiov.size);
- if (memcmp(buf, cmp_buf, qiov.size)) {
- printf("Pattern verification failed at offset %"
- PRId64 ", %zd bytes\n", offset, qiov.size);
- }
- g_free(cmp_buf);
- }
-
- if (qflag) {
- goto out;
- }
-
- if (vflag) {
- dump_buffer(buf, offset, qiov.size);
- }
-
- /* Finally, report back -- -C gives a parsable format */
- t2 = tsub(t2, t1);
- print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
-
-out:
- qemu_iovec_destroy(&qiov);
- qemu_io_free(buf);
- return 0;
-}
-
-static void write_help(void)
-{
- printf(
-"\n"
-" writes a range of bytes from the given offset\n"
-"\n"
-" Example:\n"
-" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
-"\n"
-" Writes into a segment of the currently open file, using a buffer\n"
-" filled with a set pattern (0xcdcdcdcd).\n"
-" -b, -- write to the VM state rather than the virtual disk\n"
-" -c, -- write compressed data with bdrv_write_compressed\n"
-" -p, -- use bdrv_pwrite to write the file\n"
-" -P, -- use different pattern to fill file\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-" -z, -- write zeroes using bdrv_co_write_zeroes\n"
-"\n");
-}
-
-static int write_f(int argc, char **argv);
-
-static const cmdinfo_t write_cmd = {
- .name = "write",
- .altname = "w",
- .cfunc = write_f,
- .argmin = 2,
- .argmax = -1,
- .args = "[-bcCpqz] [-P pattern ] off len",
- .oneline = "writes a number of bytes at a specified offset",
- .help = write_help,
-};
-
-static int write_f(int argc, char **argv)
-{
- struct timeval t1, t2;
- int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
- int cflag = 0;
- int c, cnt;
- char *buf = NULL;
- int64_t offset;
- int count;
- /* Some compilers get confused and warn if this is not initialized. */
- int total = 0;
- int pattern = 0xcd;
-
- while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
- switch (c) {
- case 'b':
- bflag = 1;
- break;
- case 'c':
- cflag = 1;
- break;
- case 'C':
- Cflag = 1;
- break;
- case 'p':
- pflag = 1;
- break;
- case 'P':
- Pflag = 1;
- pattern = parse_pattern(optarg);
- if (pattern < 0) {
- return 0;
- }
- break;
- case 'q':
- qflag = 1;
- break;
- case 'z':
- zflag = 1;
- break;
- default:
- return command_usage(&write_cmd);
- }
- }
-
- if (optind != argc - 2) {
- return command_usage(&write_cmd);
- }
-
- if (bflag + pflag + zflag > 1) {
- printf("-b, -p, or -z cannot be specified at the same time\n");
- return 0;
- }
-
- if (zflag && Pflag) {
- printf("-z and -P cannot be specified at the same time\n");
- return 0;
- }
-
- offset = cvtnum(argv[optind]);
- if (offset < 0) {
- printf("non-numeric length argument -- %s\n", argv[optind]);
- return 0;
- }
-
- optind++;
- count = cvtnum(argv[optind]);
- if (count < 0) {
- printf("non-numeric length argument -- %s\n", argv[optind]);
- return 0;
- }
-
- if (!pflag) {
- if (offset & 0x1ff) {
- printf("offset %" PRId64 " is not sector aligned\n",
- offset);
- return 0;
- }
-
- if (count & 0x1ff) {
- printf("count %d is not sector aligned\n",
- count);
- return 0;
- }
- }
-
- if (!zflag) {
- buf = qemu_io_alloc(count, pattern);
- }
-
- gettimeofday(&t1, NULL);
- if (pflag) {
- cnt = do_pwrite(buf, offset, count, &total);
- } else if (bflag) {
- cnt = do_save_vmstate(buf, offset, count, &total);
- } else if (zflag) {
- cnt = do_co_write_zeroes(offset, count, &total);
- } else if (cflag) {
- cnt = do_write_compressed(buf, offset, count, &total);
- } else {
- cnt = do_write(buf, offset, count, &total);
- }
- gettimeofday(&t2, NULL);
-
- if (cnt < 0) {
- printf("write failed: %s\n", strerror(-cnt));
- goto out;
- }
-
- if (qflag) {
- goto out;
- }
-
- /* Finally, report back -- -C gives a parsable format */
- t2 = tsub(t2, t1);
- print_report("wrote", &t2, offset, count, total, cnt, Cflag);
-
-out:
- if (!zflag) {
- qemu_io_free(buf);
- }
-
- return 0;
-}
-
-static void
-writev_help(void)
-{
- printf(
-"\n"
-" writes a range of bytes from the given offset source from multiple buffers\n"
-"\n"
-" Example:\n"
-" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
-"\n"
-" Writes into a segment of the currently open file, using a buffer\n"
-" filled with a set pattern (0xcdcdcdcd).\n"
-" -P, -- use different pattern to fill file\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-"\n");
-}
-
-static int writev_f(int argc, char **argv);
-
-static const cmdinfo_t writev_cmd = {
- .name = "writev",
- .cfunc = writev_f,
- .argmin = 2,
- .argmax = -1,
- .args = "[-Cq] [-P pattern ] off len [len..]",
- .oneline = "writes a number of bytes at a specified offset",
- .help = writev_help,
-};
-
-static int writev_f(int argc, char **argv)
-{
- struct timeval t1, t2;
- int Cflag = 0, qflag = 0;
- int c, cnt;
- char *buf;
- int64_t offset;
- /* Some compilers get confused and warn if this is not initialized. */
- int total = 0;
- int nr_iov;
- int pattern = 0xcd;
- QEMUIOVector qiov;
-
- while ((c = getopt(argc, argv, "CqP:")) != EOF) {
- switch (c) {
- case 'C':
- Cflag = 1;
- break;
- case 'q':
- qflag = 1;
- break;
- case 'P':
- pattern = parse_pattern(optarg);
- if (pattern < 0) {
- return 0;
- }
- break;
- default:
- return command_usage(&writev_cmd);
- }
- }
-
- if (optind > argc - 2) {
- return command_usage(&writev_cmd);
- }
-
- offset = cvtnum(argv[optind]);
- if (offset < 0) {
- printf("non-numeric length argument -- %s\n", argv[optind]);
- return 0;
- }
- optind++;
-
- if (offset & 0x1ff) {
- printf("offset %" PRId64 " is not sector aligned\n",
- offset);
- return 0;
- }
-
- nr_iov = argc - optind;
- buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
- if (buf == NULL) {
- return 0;
- }
-
- gettimeofday(&t1, NULL);
- cnt = do_aio_writev(&qiov, offset, &total);
- gettimeofday(&t2, NULL);
-
- if (cnt < 0) {
- printf("writev failed: %s\n", strerror(-cnt));
- goto out;
- }
-
- if (qflag) {
- goto out;
- }
-
- /* Finally, report back -- -C gives a parsable format */
- t2 = tsub(t2, t1);
- print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
-out:
- qemu_iovec_destroy(&qiov);
- qemu_io_free(buf);
- return 0;
-}
-
-static void multiwrite_help(void)
-{
- printf(
-"\n"
-" writes a range of bytes from the given offset source from multiple buffers,\n"
-" in a batch of requests that may be merged by qemu\n"
-"\n"
-" Example:\n"
-" 'multiwrite 512 1k 1k ; 4k 1k'\n"
-" writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
-"\n"
-" Writes into a segment of the currently open file, using a buffer\n"
-" filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
-" by one for each request contained in the multiwrite command.\n"
-" -P, -- use different pattern to fill file\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-"\n");
-}
-
-static int multiwrite_f(int argc, char **argv);
-
-static const cmdinfo_t multiwrite_cmd = {
- .name = "multiwrite",
- .cfunc = multiwrite_f,
- .argmin = 2,
- .argmax = -1,
- .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
- .oneline = "issues multiple write requests at once",
- .help = multiwrite_help,
-};
-
-static int multiwrite_f(int argc, char **argv)
-{
- struct timeval t1, t2;
- int Cflag = 0, qflag = 0;
- int c, cnt;
- char **buf;
- int64_t offset, first_offset = 0;
- /* Some compilers get confused and warn if this is not initialized. */
- int total = 0;
- int nr_iov;
- int nr_reqs;
- int pattern = 0xcd;
- QEMUIOVector *qiovs;
- int i;
- BlockRequest *reqs;
-
- while ((c = getopt(argc, argv, "CqP:")) != EOF) {
- switch (c) {
- case 'C':
- Cflag = 1;
- break;
- case 'q':
- qflag = 1;
- break;
- case 'P':
- pattern = parse_pattern(optarg);
- if (pattern < 0) {
- return 0;
- }
- break;
- default:
- return command_usage(&writev_cmd);
- }
- }
-
- if (optind > argc - 2) {
- return command_usage(&writev_cmd);
- }
-
- nr_reqs = 1;
- for (i = optind; i < argc; i++) {
- if (!strcmp(argv[i], ";")) {
- nr_reqs++;
- }
- }
-
- reqs = g_malloc0(nr_reqs * sizeof(*reqs));
- buf = g_malloc0(nr_reqs * sizeof(*buf));
- qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
-
- for (i = 0; i < nr_reqs && optind < argc; i++) {
- int j;
-
- /* Read the offset of the request */
- offset = cvtnum(argv[optind]);
- if (offset < 0) {
- printf("non-numeric offset argument -- %s\n", argv[optind]);
- goto out;
- }
- optind++;
-
- if (offset & 0x1ff) {
- printf("offset %lld is not sector aligned\n",
- (long long)offset);
- goto out;
- }
-
- if (i == 0) {
- first_offset = offset;
- }
-
- /* Read lengths for qiov entries */
- for (j = optind; j < argc; j++) {
- if (!strcmp(argv[j], ";")) {
- break;
- }
- }
-
- nr_iov = j - optind;
-
- /* Build request */
- buf[i] = create_iovec(&qiovs[i], &argv[optind], nr_iov, pattern);
- if (buf[i] == NULL) {
- goto out;
- }
-
- reqs[i].qiov = &qiovs[i];
- reqs[i].sector = offset >> 9;
- reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
-
- optind = j + 1;
-
- pattern++;
- }
-
- /* If there were empty requests at the end, ignore them */
- nr_reqs = i;
-
- gettimeofday(&t1, NULL);
- cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
- gettimeofday(&t2, NULL);
-
- if (cnt < 0) {
- printf("aio_multiwrite failed: %s\n", strerror(-cnt));
- goto out;
- }
-
- if (qflag) {
- goto out;
- }
-
- /* Finally, report back -- -C gives a parsable format */
- t2 = tsub(t2, t1);
- print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
-out:
- for (i = 0; i < nr_reqs; i++) {
- qemu_io_free(buf[i]);
- if (reqs[i].qiov != NULL) {
- qemu_iovec_destroy(&qiovs[i]);
- }
- }
- g_free(buf);
- g_free(reqs);
- g_free(qiovs);
- return 0;
-}
-
-struct aio_ctx {
- QEMUIOVector qiov;
- int64_t offset;
- char *buf;
- int qflag;
- int vflag;
- int Cflag;
- int Pflag;
- int pattern;
- struct timeval t1;
-};
-
-static void aio_write_done(void *opaque, int ret)
-{
- struct aio_ctx *ctx = opaque;
- struct timeval t2;
-
- gettimeofday(&t2, NULL);
-
-
- if (ret < 0) {
- printf("aio_write failed: %s\n", strerror(-ret));
- goto out;
- }
-
- if (ctx->qflag) {
- goto out;
- }
-
- /* Finally, report back -- -C gives a parsable format */
- t2 = tsub(t2, ctx->t1);
- print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
- ctx->qiov.size, 1, ctx->Cflag);
-out:
- qemu_io_free(ctx->buf);
- qemu_iovec_destroy(&ctx->qiov);
- g_free(ctx);
-}
-
-static void aio_read_done(void *opaque, int ret)
-{
- struct aio_ctx *ctx = opaque;
- struct timeval t2;
-
- gettimeofday(&t2, NULL);
-
- if (ret < 0) {
- printf("readv failed: %s\n", strerror(-ret));
- goto out;
- }
-
- if (ctx->Pflag) {
- void *cmp_buf = g_malloc(ctx->qiov.size);
-
- memset(cmp_buf, ctx->pattern, ctx->qiov.size);
- if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
- printf("Pattern verification failed at offset %"
- PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
- }
- g_free(cmp_buf);
- }
-
- if (ctx->qflag) {
- goto out;
- }
-
- if (ctx->vflag) {
- dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
- }
-
- /* Finally, report back -- -C gives a parsable format */
- t2 = tsub(t2, ctx->t1);
- print_report("read", &t2, ctx->offset, ctx->qiov.size,
- ctx->qiov.size, 1, ctx->Cflag);
-out:
- qemu_io_free(ctx->buf);
- qemu_iovec_destroy(&ctx->qiov);
- g_free(ctx);
-}
-
-static void aio_read_help(void)
-{
- printf(
-"\n"
-" asynchronously reads a range of bytes from the given offset\n"
-"\n"
-" Example:\n"
-" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
-"\n"
-" Reads a segment of the currently open file, optionally dumping it to the\n"
-" standard output stream (with -v option) for subsequent inspection.\n"
-" The read is performed asynchronously and the aio_flush command must be\n"
-" used to ensure all outstanding aio requests have been completed.\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -P, -- use a pattern to verify read data\n"
-" -v, -- dump buffer to standard output\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-"\n");
-}
-
-static int aio_read_f(int argc, char **argv);
-
-static const cmdinfo_t aio_read_cmd = {
- .name = "aio_read",
- .cfunc = aio_read_f,
- .argmin = 2,
- .argmax = -1,
- .args = "[-Cqv] [-P pattern ] off len [len..]",
- .oneline = "asynchronously reads a number of bytes",
- .help = aio_read_help,
-};
-
-static int aio_read_f(int argc, char **argv)
-{
- int nr_iov, c;
- struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
-
- while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
- switch (c) {
- case 'C':
- ctx->Cflag = 1;
- break;
- case 'P':
- ctx->Pflag = 1;
- ctx->pattern = parse_pattern(optarg);
- if (ctx->pattern < 0) {
- g_free(ctx);
- return 0;
- }
- break;
- case 'q':
- ctx->qflag = 1;
- break;
- case 'v':
- ctx->vflag = 1;
- break;
- default:
- g_free(ctx);
- return command_usage(&aio_read_cmd);
- }
- }
-
- if (optind > argc - 2) {
- g_free(ctx);
- return command_usage(&aio_read_cmd);
- }
-
- ctx->offset = cvtnum(argv[optind]);
- if (ctx->offset < 0) {
- printf("non-numeric length argument -- %s\n", argv[optind]);
- g_free(ctx);
- return 0;
- }
- optind++;
-
- if (ctx->offset & 0x1ff) {
- printf("offset %" PRId64 " is not sector aligned\n",
- ctx->offset);
- g_free(ctx);
- return 0;
- }
-
- nr_iov = argc - optind;
- ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
- if (ctx->buf == NULL) {
- g_free(ctx);
- return 0;
- }
-
- gettimeofday(&ctx->t1, NULL);
- bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
- ctx->qiov.size >> 9, aio_read_done, ctx);
- return 0;
-}
-
-static void aio_write_help(void)
-{
- printf(
-"\n"
-" asynchronously writes a range of bytes from the given offset source\n"
-" from multiple buffers\n"
-"\n"
-" Example:\n"
-" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
-"\n"
-" Writes into a segment of the currently open file, using a buffer\n"
-" filled with a set pattern (0xcdcdcdcd).\n"
-" The write is performed asynchronously and the aio_flush command must be\n"
-" used to ensure all outstanding aio requests have been completed.\n"
-" -P, -- use different pattern to fill file\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-"\n");
-}
-
-static int aio_write_f(int argc, char **argv);
-
-static const cmdinfo_t aio_write_cmd = {
- .name = "aio_write",
- .cfunc = aio_write_f,
- .argmin = 2,
- .argmax = -1,
- .args = "[-Cq] [-P pattern ] off len [len..]",
- .oneline = "asynchronously writes a number of bytes",
- .help = aio_write_help,
-};
-
-static int aio_write_f(int argc, char **argv)
-{
- int nr_iov, c;
- int pattern = 0xcd;
- struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
-
- while ((c = getopt(argc, argv, "CqP:")) != EOF) {
- switch (c) {
- case 'C':
- ctx->Cflag = 1;
- break;
- case 'q':
- ctx->qflag = 1;
- break;
- case 'P':
- pattern = parse_pattern(optarg);
- if (pattern < 0) {
- g_free(ctx);
- return 0;
- }
- break;
- default:
- g_free(ctx);
- return command_usage(&aio_write_cmd);
- }
- }
-
- if (optind > argc - 2) {
- g_free(ctx);
- return command_usage(&aio_write_cmd);
- }
-
- ctx->offset = cvtnum(argv[optind]);
- if (ctx->offset < 0) {
- printf("non-numeric length argument -- %s\n", argv[optind]);
- g_free(ctx);
- return 0;
- }
- optind++;
-
- if (ctx->offset & 0x1ff) {
- printf("offset %" PRId64 " is not sector aligned\n",
- ctx->offset);
- g_free(ctx);
- return 0;
- }
-
- nr_iov = argc - optind;
- ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
- if (ctx->buf == NULL) {
- g_free(ctx);
- return 0;
- }
-
- gettimeofday(&ctx->t1, NULL);
- bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
- ctx->qiov.size >> 9, aio_write_done, ctx);
- return 0;
-}
-
-static int aio_flush_f(int argc, char **argv)
-{
- bdrv_drain_all();
- return 0;
-}
-
-static const cmdinfo_t aio_flush_cmd = {
- .name = "aio_flush",
- .cfunc = aio_flush_f,
- .oneline = "completes all outstanding aio requests"
-};
-
-static int flush_f(int argc, char **argv)
-{
- bdrv_flush(bs);
- return 0;
-}
-
-static const cmdinfo_t flush_cmd = {
- .name = "flush",
- .altname = "f",
- .cfunc = flush_f,
- .oneline = "flush all in-core file state to disk",
-};
-
-static int truncate_f(int argc, char **argv)
-{
- int64_t offset;
- int ret;
-
- offset = cvtnum(argv[1]);
- if (offset < 0) {
- printf("non-numeric truncate argument -- %s\n", argv[1]);
- return 0;
- }
-
- ret = bdrv_truncate(bs, offset);
- if (ret < 0) {
- printf("truncate: %s\n", strerror(-ret));
- return 0;
- }
-
- return 0;
-}
-
-static const cmdinfo_t truncate_cmd = {
- .name = "truncate",
- .altname = "t",
- .cfunc = truncate_f,
- .argmin = 1,
- .argmax = 1,
- .args = "off",
- .oneline = "truncates the current file at the given offset",
-};
-
-static int length_f(int argc, char **argv)
-{
- int64_t size;
- char s1[64];
-
- size = bdrv_getlength(bs);
- if (size < 0) {
- printf("getlength: %s\n", strerror(-size));
- return 0;
- }
-
- cvtstr(size, s1, sizeof(s1));
- printf("%s\n", s1);
- return 0;
-}
-
-
-static const cmdinfo_t length_cmd = {
- .name = "length",
- .altname = "l",
- .cfunc = length_f,
- .oneline = "gets the length of the current file",
-};
-
-
-static int info_f(int argc, char **argv)
-{
- BlockDriverInfo bdi;
- char s1[64], s2[64];
- int ret;
-
- if (bs->drv && bs->drv->format_name) {
- printf("format name: %s\n", bs->drv->format_name);
- }
- if (bs->drv && bs->drv->protocol_name) {
- printf("format name: %s\n", bs->drv->protocol_name);
- }
-
- ret = bdrv_get_info(bs, &bdi);
- if (ret) {
- return 0;
- }
-
- cvtstr(bdi.cluster_size, s1, sizeof(s1));
- cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
-
- printf("cluster size: %s\n", s1);
- printf("vm state offset: %s\n", s2);
-
- return 0;
-}
-
-
-
-static const cmdinfo_t info_cmd = {
- .name = "info",
- .altname = "i",
- .cfunc = info_f,
- .oneline = "prints information about the current file",
-};
-
-static void discard_help(void)
-{
- printf(
-"\n"
-" discards a range of bytes from the given offset\n"
-"\n"
-" Example:\n"
-" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
-"\n"
-" Discards a segment of the currently open file.\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-"\n");
-}
-
-static int discard_f(int argc, char **argv);
-
-static const cmdinfo_t discard_cmd = {
- .name = "discard",
- .altname = "d",
- .cfunc = discard_f,
- .argmin = 2,
- .argmax = -1,
- .args = "[-Cq] off len",
- .oneline = "discards a number of bytes at a specified offset",
- .help = discard_help,
-};
-
-static int discard_f(int argc, char **argv)
-{
- struct timeval t1, t2;
- int Cflag = 0, qflag = 0;
- int c, ret;
- int64_t offset;
- int count;
-
- while ((c = getopt(argc, argv, "Cq")) != EOF) {
- switch (c) {
- case 'C':
- Cflag = 1;
- break;
- case 'q':
- qflag = 1;
- break;
- default:
- return command_usage(&discard_cmd);
- }
- }
-
- if (optind != argc - 2) {
- return command_usage(&discard_cmd);
- }
-
- offset = cvtnum(argv[optind]);
- if (offset < 0) {
- printf("non-numeric length argument -- %s\n", argv[optind]);
- return 0;
- }
-
- optind++;
- count = cvtnum(argv[optind]);
- if (count < 0) {
- printf("non-numeric length argument -- %s\n", argv[optind]);
- return 0;
- }
-
- gettimeofday(&t1, NULL);
- ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
- count >> BDRV_SECTOR_BITS);
- gettimeofday(&t2, NULL);
-
- if (ret < 0) {
- printf("discard failed: %s\n", strerror(-ret));
- goto out;
- }
-
- /* Finally, report back -- -C gives a parsable format */
- if (!qflag) {
- t2 = tsub(t2, t1);
- print_report("discard", &t2, offset, count, count, 1, Cflag);
- }
-
-out:
- return 0;
-}
-
-static int alloc_f(int argc, char **argv)
-{
- int64_t offset, sector_num;
- int nb_sectors, remaining;
- char s1[64];
- int num, sum_alloc;
- int ret;
-
- offset = cvtnum(argv[1]);
- if (offset & 0x1ff) {
- printf("offset %" PRId64 " is not sector aligned\n",
- offset);
- return 0;
- }
-
- if (argc == 3) {
- nb_sectors = cvtnum(argv[2]);
- } else {
- nb_sectors = 1;
- }
-
- remaining = nb_sectors;
- sum_alloc = 0;
- sector_num = offset >> 9;
- while (remaining) {
- ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
- sector_num += num;
- remaining -= num;
- if (ret) {
- sum_alloc += num;
- }
- if (num == 0) {
- nb_sectors -= remaining;
- remaining = 0;
- }
- }
-
- cvtstr(offset, s1, sizeof(s1));
-
- printf("%d/%d sectors allocated at offset %s\n",
- sum_alloc, nb_sectors, s1);
- return 0;
-}
-
-static const cmdinfo_t alloc_cmd = {
- .name = "alloc",
- .altname = "a",
- .argmin = 1,
- .argmax = 2,
- .cfunc = alloc_f,
- .args = "off [sectors]",
- .oneline = "checks if a sector is present in the file",
-};
-
-
-static int map_is_allocated(int64_t sector_num, int64_t nb_sectors, int64_t *pnum)
-{
- int num, num_checked;
- int ret, firstret;
-
- num_checked = MIN(nb_sectors, INT_MAX);
- ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
- if (ret < 0) {
- return ret;
- }
-
- firstret = ret;
- *pnum = num;
-
- while (nb_sectors > 0 && ret == firstret) {
- sector_num += num;
- nb_sectors -= num;
-
- num_checked = MIN(nb_sectors, INT_MAX);
- ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
- if (ret == firstret) {
- *pnum += num;
- } else {
- break;
- }
- }
-
- return firstret;
-}
-
-static int map_f(int argc, char **argv)
-{
- int64_t offset;
- int64_t nb_sectors;
- char s1[64];
- int64_t num;
- int ret;
- const char *retstr;
-
- offset = 0;
- nb_sectors = bs->total_sectors;
-
- do {
- ret = map_is_allocated(offset, nb_sectors, &num);
- if (ret < 0) {
- error_report("Failed to get allocation status: %s", strerror(-ret));
- return 0;
- }
-
- retstr = ret ? " allocated" : "not allocated";
- cvtstr(offset << 9ULL, s1, sizeof(s1));
- printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
- "at offset %s (%d)\n",
- offset << 9ULL, num, nb_sectors, retstr, s1, ret);
-
- offset += num;
- nb_sectors -= num;
- } while (offset < bs->total_sectors);
-
- return 0;
-}
-
-static const cmdinfo_t map_cmd = {
- .name = "map",
- .argmin = 0,
- .argmax = 0,
- .cfunc = map_f,
- .args = "",
- .oneline = "prints the allocated areas of a file",
-};
-
-static int break_f(int argc, char **argv)
-{
- int ret;
-
- ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
- if (ret < 0) {
- printf("Could not set breakpoint: %s\n", strerror(-ret));
- }
-
- return 0;
-}
-
-static const cmdinfo_t break_cmd = {
- .name = "break",
- .argmin = 2,
- .argmax = 2,
- .cfunc = break_f,
- .args = "event tag",
- .oneline = "sets a breakpoint on event and tags the stopped "
- "request as tag",
-};
-
-static int resume_f(int argc, char **argv)
-{
- int ret;
-
- ret = bdrv_debug_resume(bs, argv[1]);
- if (ret < 0) {
- printf("Could not resume request: %s\n", strerror(-ret));
- }
-
- return 0;
-}
-
-static const cmdinfo_t resume_cmd = {
- .name = "resume",
- .argmin = 1,
- .argmax = 1,
- .cfunc = resume_f,
- .args = "tag",
- .oneline = "resumes the request tagged as tag",
-};
-
-static int wait_break_f(int argc, char **argv)
-{
- while (!bdrv_debug_is_suspended(bs, argv[1])) {
- qemu_aio_wait();
- }
-
- return 0;
-}
-
-static const cmdinfo_t wait_break_cmd = {
- .name = "wait_break",
- .argmin = 1,
- .argmax = 1,
- .cfunc = wait_break_f,
- .args = "tag",
- .oneline = "waits for the suspension of a request",
-};
-
-static int abort_f(int argc, char **argv)
-{
- abort();
-}
-
-static const cmdinfo_t abort_cmd = {
- .name = "abort",
- .cfunc = abort_f,
- .flags = CMD_NOFILE_OK,
- .oneline = "simulate a program crash using abort(3)",
-};
-
-static int close_f(int argc, char **argv)
+static int close_f(BlockDriverState *bs, int argc, char **argv)
{
bdrv_delete(bs);
- bs = NULL;
+ qemuio_bs = NULL;
return 0;
}
@@ -1796,23 +46,23 @@ static const cmdinfo_t close_cmd = {
static int openfile(char *name, int flags, int growable)
{
- if (bs) {
+ if (qemuio_bs) {
fprintf(stderr, "file open already, try 'help close'\n");
return 1;
}
if (growable) {
- if (bdrv_file_open(&bs, name, NULL, flags)) {
+ if (bdrv_file_open(&qemuio_bs, name, NULL, flags)) {
fprintf(stderr, "%s: can't open device %s\n", progname, name);
return 1;
}
} else {
- bs = bdrv_new("hda");
+ qemuio_bs = bdrv_new("hda");
- if (bdrv_open(bs, name, NULL, flags, NULL) < 0) {
+ if (bdrv_open(qemuio_bs, name, NULL, flags, NULL) < 0) {
fprintf(stderr, "%s: can't open device %s\n", progname, name);
- bdrv_delete(bs);
- bs = NULL;
+ bdrv_delete(qemuio_bs);
+ qemuio_bs = NULL;
return 1;
}
}
@@ -1837,7 +87,7 @@ static void open_help(void)
"\n");
}
-static int open_f(int argc, char **argv);
+static int open_f(BlockDriverState *bs, int argc, char **argv);
static const cmdinfo_t open_cmd = {
.name = "open",
@@ -1851,7 +101,7 @@ static const cmdinfo_t open_cmd = {
.help = open_help,
};
-static int open_f(int argc, char **argv)
+static int open_f(BlockDriverState *bs, int argc, char **argv)
{
int flags = 0;
int readonly = 0;
@@ -1873,7 +123,7 @@ static int open_f(int argc, char **argv)
growable = 1;
break;
default:
- return command_usage(&open_cmd);
+ return qemuio_command_usage(&open_cmd);
}
}
@@ -1882,33 +132,27 @@ static int open_f(int argc, char **argv)
}
if (optind != argc - 1) {
- return command_usage(&open_cmd);
+ return qemuio_command_usage(&open_cmd);
}
return openfile(argv[optind], flags, growable);
}
-static int init_args_command(int index)
-{
- /* only one device allowed so far */
- if (index >= 1) {
- return 0;
- }
- return ++index;
-}
-
-static int init_check_command(const cmdinfo_t *ct)
+static int quit_f(BlockDriverState *bs, int argc, char **argv)
{
- if (ct->flags & CMD_FLAG_GLOBAL) {
- return 1;
- }
- if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
- fprintf(stderr, "no file open, try 'help open'\n");
- return 0;
- }
return 1;
}
+static const cmdinfo_t quit_cmd = {
+ .name = "quit",
+ .altname = "q",
+ .cfunc = quit_f,
+ .argmin = -1,
+ .argmax = -1,
+ .flags = CMD_FLAG_GLOBAL,
+ .oneline = "exit the program",
+};
+
static void usage(const char *name)
{
printf(
@@ -1931,6 +175,141 @@ static void usage(const char *name)
}
+#if defined(ENABLE_READLINE)
+# include <readline/history.h>
+# include <readline/readline.h>
+#elif defined(ENABLE_EDITLINE)
+# include <histedit.h>
+#endif
+
+static char *get_prompt(void)
+{
+ static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ];
+
+ if (!prompt[0]) {
+ snprintf(prompt, sizeof(prompt), "%s> ", progname);
+ }
+
+ return prompt;
+}
+
+#if defined(ENABLE_READLINE)
+static char *fetchline(void)
+{
+ char *line = readline(get_prompt());
+ if (line && *line) {
+ add_history(line);
+ }
+ return line;
+}
+#elif defined(ENABLE_EDITLINE)
+static char *el_get_prompt(EditLine *e)
+{
+ return get_prompt();
+}
+
+static char *fetchline(void)
+{
+ static EditLine *el;
+ static History *hist;
+ HistEvent hevent;
+ char *line;
+ int count;
+
+ if (!el) {
+ hist = history_init();
+ history(hist, &hevent, H_SETSIZE, 100);
+ el = el_init(progname, stdin, stdout, stderr);
+ el_source(el, NULL);
+ el_set(el, EL_SIGNAL, 1);
+ el_set(el, EL_PROMPT, el_get_prompt);
+ el_set(el, EL_HIST, history, (const char *)hist);
+ }
+ line = strdup(el_gets(el, &count));
+ if (line) {
+ if (count > 0) {
+ line[count-1] = '\0';
+ }
+ if (*line) {
+ history(hist, &hevent, H_ENTER, line);
+ }
+ }
+ return line;
+}
+#else
+# define MAXREADLINESZ 1024
+static char *fetchline(void)
+{
+ char *p, *line = g_malloc(MAXREADLINESZ);
+
+ if (!fgets(line, MAXREADLINESZ, stdin)) {
+ g_free(line);
+ return NULL;
+ }
+
+ p = line + strlen(line);
+ if (p != line && p[-1] == '\n') {
+ p[-1] = '\0';
+ }
+
+ return line;
+}
+#endif
+
+static void prep_fetchline(void *opaque)
+{
+ int *fetchable = opaque;
+
+ qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
+ *fetchable= 1;
+}
+
+static void command_loop(void)
+{
+ int i, done = 0, fetchable = 0, prompted = 0;
+ char *input;
+
+ for (i = 0; !done && i < ncmdline; i++) {
+ done = qemuio_command(qemuio_bs, cmdline[i]);
+ }
+ if (cmdline) {
+ g_free(cmdline);
+ return;
+ }
+
+ while (!done) {
+ if (!prompted) {
+ printf("%s", get_prompt());
+ fflush(stdout);
+ qemu_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, &fetchable);
+ prompted = 1;
+ }
+
+ main_loop_wait(false);
+
+ if (!fetchable) {
+ continue;
+ }
+
+ input = fetchline();
+ if (input == NULL) {
+ break;
+ }
+ done = qemuio_command(qemuio_bs, input);
+ g_free(input);
+
+ prompted = 0;
+ fetchable = 0;
+ }
+ qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
+}
+
+static void add_user_command(char *optarg)
+{
+ cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *));
+ cmdline[ncmdline-1] = optarg;
+}
+
int main(int argc, char **argv)
{
int readonly = 0;
@@ -1979,7 +358,7 @@ int main(int argc, char **argv)
readonly = 1;
break;
case 'm':
- misalign = 1;
+ qemuio_misalign = 1;
break;
case 'g':
growable = 1;
@@ -1999,7 +378,7 @@ int main(int argc, char **argv)
}
break;
case 'V':
- printf("%s version %s\n", progname, VERSION);
+ printf("%s version %s\n", progname, QEMU_VERSION);
exit(0);
case 'h':
usage(progname);
@@ -2019,32 +398,9 @@ int main(int argc, char **argv)
bdrv_init();
/* initialize commands */
- quit_init();
- help_init();
- add_command(&open_cmd);
- add_command(&close_cmd);
- add_command(&read_cmd);
- add_command(&readv_cmd);
- add_command(&write_cmd);
- add_command(&writev_cmd);
- add_command(&multiwrite_cmd);
- add_command(&aio_read_cmd);
- add_command(&aio_write_cmd);
- add_command(&aio_flush_cmd);
- add_command(&flush_cmd);
- add_command(&truncate_cmd);
- add_command(&length_cmd);
- add_command(&info_cmd);
- add_command(&discard_cmd);
- add_command(&alloc_cmd);
- add_command(&map_cmd);
- add_command(&break_cmd);
- add_command(&resume_cmd);
- add_command(&wait_break_cmd);
- add_command(&abort_cmd);
-
- add_args_command(init_args_command);
- add_check_command(init_check_command);
+ qemuio_add_command(&quit_cmd);
+ qemuio_add_command(&open_cmd);
+ qemuio_add_command(&close_cmd);
/* open the device */
if (!readonly) {
@@ -2061,8 +417,8 @@ int main(int argc, char **argv)
*/
bdrv_drain_all();
- if (bs) {
- bdrv_delete(bs);
+ if (qemuio_bs) {
+ bdrv_delete(qemuio_bs);
}
return 0;
}
diff --git a/qmp-commands.hx b/qmp-commands.hx
index ffd130edf6..8cea5e554c 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1704,6 +1704,47 @@ Each json-object contain the following:
- "iops": limit total I/O operations per second (json-int)
- "iops_rd": limit read operations per second (json-int)
- "iops_wr": limit write operations per second (json-int)
+ - "image": the detail of the image, it is a json-object containing
+ the following:
+ - "filename": image file name (json-string)
+ - "format": image format (json-string)
+ - "virtual-size": image capacity in bytes (json-int)
+ - "dirty-flag": true if image is not cleanly closed, not present
+ means clean (json-bool, optional)
+ - "actual-size": actual size on disk in bytes of the image, not
+ present when image does not support thin
+ provision (json-int, optional)
+ - "cluster-size": size of a cluster in bytes, not present if image
+ format does not support it (json-int, optional)
+ - "encrypted": true if the image is encrypted, not present means
+ false or the image format does not support
+ encryption (json-bool, optional)
+ - "backing_file": backing file name, not present means no backing
+ file is used or the image format does not
+ support backing file chain
+ (json-string, optional)
+ - "full-backing-filename": full path of the backing file, not
+ present if it equals backing_file or no
+ backing file is used
+ (json-string, optional)
+ - "backing-filename-format": the format of the backing file, not
+ present means unknown or no backing
+ file (json-string, optional)
+ - "snapshots": the internal snapshot info, it is an optional list
+ of json-object containing the following:
+ - "id": unique snapshot id (json-string)
+ - "name": snapshot name (json-string)
+ - "vm-state-size": size of the VM state in bytes (json-int)
+ - "date-sec": UTC date of the snapshot in seconds (json-int)
+ - "date-nsec": fractional part in nanoseconds to be used with
+ date-sec(json-int)
+ - "vm-clock-sec": VM clock relative to boot in seconds
+ (json-int)
+ - "vm-clock-nsec": fractional part in nanoseconds to be used
+ with vm-clock-sec (json-int)
+ - "backing-image": the detail of the backing image, it is an
+ optional json-object only present when a
+ backing image present for this image
- "io-status": I/O operation status, only present if the device supports it
and the VM is configured to stop on errors. It's always reset
@@ -1724,14 +1765,38 @@ Example:
"ro":false,
"drv":"qcow2",
"encrypted":false,
- "file":"disks/test.img",
- "backing_file_depth":0,
+ "file":"disks/test.qcow2",
+ "backing_file_depth":1,
"bps":1000000,
"bps_rd":0,
"bps_wr":0,
"iops":1000000,
"iops_rd":0,
"iops_wr":0,
+ "image":{
+ "filename":"disks/test.qcow2",
+ "format":"qcow2",
+ "virtual-size":2048000,
+ "backing_file":"base.qcow2",
+ "full-backing-filename":"disks/base.qcow2",
+ "backing-filename-format:"qcow2",
+ "snapshots":[
+ {
+ "id": "1",
+ "name": "snapshot1",
+ "vm-state-size": 0,
+ "date-sec": 10000200,
+ "date-nsec": 12,
+ "vm-clock-sec": 206,
+ "vm-clock-nsec": 30
+ }
+ ],
+ "backing-image":{
+ "filename":"disks/base.qcow2",
+ "format":"qcow2",
+ "virtual-size":2048000
+ }
+ }
},
"type":"unknown"
},
diff --git a/qom/cpu.c b/qom/cpu.c
index 04aefbb956..dba4a11edc 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -50,6 +50,33 @@ bool cpu_exists(int64_t id)
return data.found;
}
+bool cpu_paging_enabled(const CPUState *cpu)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ return cc->get_paging_enabled(cpu);
+}
+
+static bool cpu_common_get_paging_enabled(const CPUState *cpu)
+{
+ return false;
+}
+
+void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
+ Error **errp)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ return cc->get_memory_mapping(cpu, list, errp);
+}
+
+static void cpu_common_get_memory_mapping(CPUState *cpu,
+ MemoryMappingList *list,
+ Error **errp)
+{
+ error_setg(errp, "Obtaining memory mappings is unsupported on this CPU.");
+}
+
/* CPU hot-plug notifiers */
static NotifierList cpu_added_notifiers =
NOTIFIER_LIST_INITIALIZER(cpu_add_notifiers);
@@ -176,6 +203,8 @@ static void cpu_class_init(ObjectClass *klass, void *data)
k->class_by_name = cpu_common_class_by_name;
k->reset = cpu_common_reset;
k->get_arch_id = cpu_common_get_arch_id;
+ k->get_paging_enabled = cpu_common_get_paging_enabled;
+ k->get_memory_mapping = cpu_common_get_memory_mapping;
k->write_elf32_qemunote = cpu_common_write_elf32_qemunote;
k->write_elf32_note = cpu_common_write_elf32_note;
k->write_elf64_qemunote = cpu_common_write_elf64_qemunote;
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index f10970c9db..6d147a7ece 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -255,6 +255,7 @@ static CharDriverState *chr_open(const char *subtype)
chr->chr_add_watch = spice_chr_add_watch;
chr->chr_close = spice_chr_close;
chr->chr_set_fe_open = spice_chr_set_fe_open;
+ chr->explicit_be_open = true;
QLIST_INSERT_HEAD(&spice_chars, s, next);
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 03dff202e4..9b701b4714 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -2,6 +2,7 @@ stub-obj-y += arch-query-cpu-def.o
stub-obj-y += clock-warp.o
stub-obj-y += cpu-get-clock.o
stub-obj-y += cpu-get-icount.o
+stub-obj-y += dump.o
stub-obj-y += fdset-add-fd.o
stub-obj-y += fdset-find-fd.o
stub-obj-y += fdset-get-fd.o
diff --git a/dump-stub.c b/stubs/dump.c
index b3f42cb2f1..43c9a3fa02 100644
--- a/dump-stub.c
+++ b/stubs/dump.c
@@ -16,14 +16,6 @@
#include "qapi/qmp/qerror.h"
#include "qmp-commands.h"
-/* we need this function in hmp.c */
-void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
- int64_t begin, bool has_length, int64_t length,
- Error **errp)
-{
- error_set(errp, QERR_UNSUPPORTED);
-}
-
int cpu_get_dump_info(ArchDumpInfo *info)
{
return -1;
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index b7bdc034fd..27dcab93f6 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -491,3 +491,7 @@ void kvm_arch_remove_all_hw_breakpoints(void)
{
qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
}
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index b3f26d6205..2a18ffe5cf 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6752,7 +6752,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
tcg_gen_qemu_ld32u(tmp, addr, 0);
tcg_gen_addi_i32(addr, addr, 4);
tmp2 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32u(tmp, addr, 0);
+ tcg_gen_qemu_ld32u(tmp2, addr, 0);
if (insn & (1 << 21)) {
/* Base writeback. */
switch (i) {
diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c
index 5096fbdf44..2566a040a6 100644
--- a/target-i386/arch_memory_mapping.c
+++ b/target-i386/arch_memory_mapping.c
@@ -239,11 +239,15 @@ static void walk_pml4e(MemoryMappingList *list,
}
#endif
-int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
+void x86_cpu_get_memory_mapping(CPUState *cs, MemoryMappingList *list,
+ Error **errp)
{
- if (!cpu_paging_enabled(env)) {
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+
+ if (!cpu_paging_enabled(cs)) {
/* paging is disabled */
- return 0;
+ return;
}
if (env->cr[4] & CR4_PAE_MASK) {
@@ -269,11 +273,5 @@ int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
pse = !!(env->cr[4] & CR4_PSE_MASK);
walk_pde2(list, pde_addr, env->a20_mask, pse);
}
-
- return 0;
}
-bool cpu_paging_enabled(CPUArchState *env)
-{
- return env->cr[0] & CR0_PG_MASK;
-}
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 849cedf94c..e0ac072c5f 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -98,4 +98,7 @@ int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
void *opaque);
+void x86_cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
+ Error **errp);
+
#endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 1a501d9d33..a7154af11d 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -221,7 +221,7 @@ X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = {
const char *get_register_name_32(unsigned int reg)
{
- if (reg > CPU_NB_REGS32) {
+ if (reg >= CPU_NB_REGS32) {
return NULL;
}
return x86_reg_info_32[reg].name;
@@ -669,10 +669,10 @@ static x86_def_t builtin_x86_defs[] = {
},
{
.name = "Conroe",
- .level = 2,
+ .level = 4,
.vendor = CPUID_VENDOR_INTEL,
.family = 6,
- .model = 2,
+ .model = 15,
.stepping = 3,
.features[FEAT_1_EDX] =
CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
@@ -691,10 +691,10 @@ static x86_def_t builtin_x86_defs[] = {
},
{
.name = "Penryn",
- .level = 2,
+ .level = 4,
.vendor = CPUID_VENDOR_INTEL,
.family = 6,
- .model = 2,
+ .model = 23,
.stepping = 3,
.features[FEAT_1_EDX] =
CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
@@ -714,10 +714,10 @@ static x86_def_t builtin_x86_defs[] = {
},
{
.name = "Nehalem",
- .level = 2,
+ .level = 4,
.vendor = CPUID_VENDOR_INTEL,
.family = 6,
- .model = 2,
+ .model = 26,
.stepping = 3,
.features[FEAT_1_EDX] =
CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
@@ -2505,6 +2505,13 @@ static int64_t x86_cpu_get_arch_id(CPUState *cs)
return env->cpuid_apic_id;
}
+static bool x86_cpu_get_paging_enabled(const CPUState *cs)
+{
+ X86CPU *cpu = X86_CPU(cs);
+
+ return cpu->env.cr[0] & CR0_PG_MASK;
+}
+
static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
{
X86CPUClass *xcc = X86_CPU_CLASS(oc);
@@ -2519,15 +2526,16 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
cc->reset = x86_cpu_reset;
cc->do_interrupt = x86_cpu_do_interrupt;
+ cc->get_arch_id = x86_cpu_get_arch_id;
+ cc->get_paging_enabled = x86_cpu_get_paging_enabled;
#ifndef CONFIG_USER_ONLY
+ cc->get_memory_mapping = x86_cpu_get_memory_mapping;
cc->write_elf64_note = x86_cpu_write_elf64_note;
cc->write_elf64_qemunote = x86_cpu_write_elf64_qemunote;
cc->write_elf32_note = x86_cpu_write_elf32_note;
cc->write_elf32_qemunote = x86_cpu_write_elf32_qemunote;
#endif
cpu_class_set_vmsd(cc, &vmstate_x86_cpu);
-
- cc->get_arch_id = x86_cpu_get_arch_id;
}
static const TypeInfo x86_cpu_type_info = {
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 3ab2946cfb..2bbc3b81dd 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1797,3 +1797,7 @@ int kvm_arch_on_sigbus(int code, void *addr)
{
return 1;
}
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+}
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 862fb12c84..4d9ac4ad0c 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -928,3 +928,7 @@ void kvm_s390_enable_css_support(S390CPU *cpu)
r = kvm_vcpu_ioctl(CPU(cpu), KVM_ENABLE_CAP, &cap);
assert(r == 0);
}
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+}
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 290b5809aa..13bb7bb94a 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -614,7 +614,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
return 0;
error:
- free(s);
+ g_free(s);
return -1;
}
diff --git a/tcg/aarch64/tcg-target.c b/tcg/aarch64/tcg-target.c
new file mode 100644
index 0000000000..562a549dab
--- /dev/null
+++ b/tcg/aarch64/tcg-target.c
@@ -0,0 +1,1404 @@
+/*
+ * Initial TCG Implementation for aarch64
+ *
+ * Copyright (c) 2013 Huawei Technologies Duesseldorf GmbH
+ * Written by Claudio Fontana
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.
+ *
+ * See the COPYING file in the top-level directory for details.
+ */
+
+#include "qemu/bitops.h"
+
+#ifndef NDEBUG
+static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
+ "%x0", "%x1", "%x2", "%x3", "%x4", "%x5", "%x6", "%x7",
+ "%x8", "%x9", "%x10", "%x11", "%x12", "%x13", "%x14", "%x15",
+ "%x16", "%x17", "%x18", "%x19", "%x20", "%x21", "%x22", "%x23",
+ "%x24", "%x25", "%x26", "%x27", "%x28",
+ "%fp", /* frame pointer */
+ "%lr", /* link register */
+ "%sp", /* stack pointer */
+};
+#endif /* NDEBUG */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+ #define TCG_LDST_BSWAP 1
+#else
+ #define TCG_LDST_BSWAP 0
+#endif
+
+static const int tcg_target_reg_alloc_order[] = {
+ TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23,
+ TCG_REG_X24, TCG_REG_X25, TCG_REG_X26, TCG_REG_X27,
+ TCG_REG_X28, /* we will reserve this for GUEST_BASE if configured */
+
+ TCG_REG_X9, TCG_REG_X10, TCG_REG_X11, TCG_REG_X12,
+ TCG_REG_X13, TCG_REG_X14, TCG_REG_X15,
+ TCG_REG_X16, TCG_REG_X17,
+
+ TCG_REG_X18, TCG_REG_X19, /* will not use these, see tcg_target_init */
+
+ TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
+ TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7,
+
+ TCG_REG_X8, /* will not use, see tcg_target_init */
+};
+
+static const int tcg_target_call_iarg_regs[8] = {
+ TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
+ TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7
+};
+static const int tcg_target_call_oarg_regs[1] = {
+ TCG_REG_X0
+};
+
+#define TCG_REG_TMP TCG_REG_X8
+
+#ifndef CONFIG_SOFTMMU
+# if defined(CONFIG_USE_GUEST_BASE)
+# define TCG_REG_GUEST_BASE TCG_REG_X28
+# else
+# define TCG_REG_GUEST_BASE TCG_REG_XZR
+# endif
+#endif
+
+static inline void reloc_pc26(void *code_ptr, tcg_target_long target)
+{
+ tcg_target_long offset; uint32_t insn;
+ offset = (target - (tcg_target_long)code_ptr) / 4;
+ /* read instruction, mask away previous PC_REL26 parameter contents,
+ set the proper offset, then write back the instruction. */
+ insn = *(uint32_t *)code_ptr;
+ insn = deposit32(insn, 0, 26, offset);
+ *(uint32_t *)code_ptr = insn;
+}
+
+static inline void reloc_pc19(void *code_ptr, tcg_target_long target)
+{
+ tcg_target_long offset; uint32_t insn;
+ offset = (target - (tcg_target_long)code_ptr) / 4;
+ /* read instruction, mask away previous PC_REL19 parameter contents,
+ set the proper offset, then write back the instruction. */
+ insn = *(uint32_t *)code_ptr;
+ insn = deposit32(insn, 5, 19, offset);
+ *(uint32_t *)code_ptr = insn;
+}
+
+static inline void patch_reloc(uint8_t *code_ptr, int type,
+ tcg_target_long value, tcg_target_long addend)
+{
+ value += addend;
+
+ switch (type) {
+ case R_AARCH64_JUMP26:
+ case R_AARCH64_CALL26:
+ reloc_pc26(code_ptr, value);
+ break;
+ case R_AARCH64_CONDBR19:
+ reloc_pc19(code_ptr, value);
+ break;
+
+ default:
+ tcg_abort();
+ }
+}
+
+/* parse target specific constraints */
+static int target_parse_constraint(TCGArgConstraint *ct,
+ const char **pct_str)
+{
+ const char *ct_str = *pct_str;
+
+ switch (ct_str[0]) {
+ case 'r':
+ ct->ct |= TCG_CT_REG;
+ tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
+ break;
+ case 'l': /* qemu_ld / qemu_st address, data_reg */
+ ct->ct |= TCG_CT_REG;
+ tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
+#ifdef CONFIG_SOFTMMU
+ /* x0 and x1 will be overwritten when reading the tlb entry,
+ and x2, and x3 for helper args, better to avoid using them. */
+ tcg_regset_reset_reg(ct->u.regs, TCG_REG_X0);
+ tcg_regset_reset_reg(ct->u.regs, TCG_REG_X1);
+ tcg_regset_reset_reg(ct->u.regs, TCG_REG_X2);
+ tcg_regset_reset_reg(ct->u.regs, TCG_REG_X3);
+#endif
+ break;
+ default:
+ return -1;
+ }
+
+ ct_str++;
+ *pct_str = ct_str;
+ return 0;
+}
+
+static inline int tcg_target_const_match(tcg_target_long val,
+ const TCGArgConstraint *arg_ct)
+{
+ int ct = arg_ct->ct;
+
+ if (ct & TCG_CT_CONST) {
+ return 1;
+ }
+
+ return 0;
+}
+
+enum aarch64_cond_code {
+ COND_EQ = 0x0,
+ COND_NE = 0x1,
+ COND_CS = 0x2, /* Unsigned greater or equal */
+ COND_HS = COND_CS, /* ALIAS greater or equal */
+ COND_CC = 0x3, /* Unsigned less than */
+ COND_LO = COND_CC, /* ALIAS Lower */
+ COND_MI = 0x4, /* Negative */
+ COND_PL = 0x5, /* Zero or greater */
+ COND_VS = 0x6, /* Overflow */
+ COND_VC = 0x7, /* No overflow */
+ COND_HI = 0x8, /* Unsigned greater than */
+ COND_LS = 0x9, /* Unsigned less or equal */
+ COND_GE = 0xa,
+ COND_LT = 0xb,
+ COND_GT = 0xc,
+ COND_LE = 0xd,
+ COND_AL = 0xe,
+ COND_NV = 0xf, /* behaves like COND_AL here */
+};
+
+static const enum aarch64_cond_code tcg_cond_to_aarch64[] = {
+ [TCG_COND_EQ] = COND_EQ,
+ [TCG_COND_NE] = COND_NE,
+ [TCG_COND_LT] = COND_LT,
+ [TCG_COND_GE] = COND_GE,
+ [TCG_COND_LE] = COND_LE,
+ [TCG_COND_GT] = COND_GT,
+ /* unsigned */
+ [TCG_COND_LTU] = COND_LO,
+ [TCG_COND_GTU] = COND_HI,
+ [TCG_COND_GEU] = COND_HS,
+ [TCG_COND_LEU] = COND_LS,
+};
+
+/* opcodes for LDR / STR instructions with base + simm9 addressing */
+enum aarch64_ldst_op_data { /* size of the data moved */
+ LDST_8 = 0x38,
+ LDST_16 = 0x78,
+ LDST_32 = 0xb8,
+ LDST_64 = 0xf8,
+};
+enum aarch64_ldst_op_type { /* type of operation */
+ LDST_ST = 0x0, /* store */
+ LDST_LD = 0x4, /* load */
+ LDST_LD_S_X = 0x8, /* load and sign-extend into Xt */
+ LDST_LD_S_W = 0xc, /* load and sign-extend into Wt */
+};
+
+enum aarch64_arith_opc {
+ ARITH_AND = 0x0a,
+ ARITH_ADD = 0x0b,
+ ARITH_OR = 0x2a,
+ ARITH_ADDS = 0x2b,
+ ARITH_XOR = 0x4a,
+ ARITH_SUB = 0x4b,
+ ARITH_ANDS = 0x6a,
+ ARITH_SUBS = 0x6b,
+};
+
+enum aarch64_srr_opc {
+ SRR_SHL = 0x0,
+ SRR_SHR = 0x4,
+ SRR_SAR = 0x8,
+ SRR_ROR = 0xc
+};
+
+static inline enum aarch64_ldst_op_data
+aarch64_ldst_get_data(TCGOpcode tcg_op)
+{
+ switch (tcg_op) {
+ case INDEX_op_ld8u_i32:
+ case INDEX_op_ld8s_i32:
+ case INDEX_op_ld8u_i64:
+ case INDEX_op_ld8s_i64:
+ case INDEX_op_st8_i32:
+ case INDEX_op_st8_i64:
+ return LDST_8;
+
+ case INDEX_op_ld16u_i32:
+ case INDEX_op_ld16s_i32:
+ case INDEX_op_ld16u_i64:
+ case INDEX_op_ld16s_i64:
+ case INDEX_op_st16_i32:
+ case INDEX_op_st16_i64:
+ return LDST_16;
+
+ case INDEX_op_ld_i32:
+ case INDEX_op_st_i32:
+ case INDEX_op_ld32u_i64:
+ case INDEX_op_ld32s_i64:
+ case INDEX_op_st32_i64:
+ return LDST_32;
+
+ case INDEX_op_ld_i64:
+ case INDEX_op_st_i64:
+ return LDST_64;
+
+ default:
+ tcg_abort();
+ }
+}
+
+static inline enum aarch64_ldst_op_type
+aarch64_ldst_get_type(TCGOpcode tcg_op)
+{
+ switch (tcg_op) {
+ case INDEX_op_st8_i32:
+ case INDEX_op_st16_i32:
+ case INDEX_op_st8_i64:
+ case INDEX_op_st16_i64:
+ case INDEX_op_st_i32:
+ case INDEX_op_st32_i64:
+ case INDEX_op_st_i64:
+ return LDST_ST;
+
+ case INDEX_op_ld8u_i32:
+ case INDEX_op_ld16u_i32:
+ case INDEX_op_ld8u_i64:
+ case INDEX_op_ld16u_i64:
+ case INDEX_op_ld_i32:
+ case INDEX_op_ld32u_i64:
+ case INDEX_op_ld_i64:
+ return LDST_LD;
+
+ case INDEX_op_ld8s_i32:
+ case INDEX_op_ld16s_i32:
+ return LDST_LD_S_W;
+
+ case INDEX_op_ld8s_i64:
+ case INDEX_op_ld16s_i64:
+ case INDEX_op_ld32s_i64:
+ return LDST_LD_S_X;
+
+ default:
+ tcg_abort();
+ }
+}
+
+static inline uint32_t tcg_in32(TCGContext *s)
+{
+ uint32_t v = *(uint32_t *)s->code_ptr;
+ return v;
+}
+
+static inline void tcg_out_ldst_9(TCGContext *s,
+ enum aarch64_ldst_op_data op_data,
+ enum aarch64_ldst_op_type op_type,
+ TCGReg rd, TCGReg rn, tcg_target_long offset)
+{
+ /* use LDUR with BASE register with 9bit signed unscaled offset */
+ unsigned int mod, off;
+
+ if (offset < 0) {
+ off = (256 + offset);
+ mod = 0x1;
+ } else {
+ off = offset;
+ mod = 0x0;
+ }
+
+ mod |= op_type;
+ tcg_out32(s, op_data << 24 | mod << 20 | off << 12 | rn << 5 | rd);
+}
+
+static inline void tcg_out_movr(TCGContext *s, int ext, TCGReg rd, TCGReg src)
+{
+ /* register to register move using MOV (shifted register with no shift) */
+ /* using MOV 0x2a0003e0 | (shift).. */
+ unsigned int base = ext ? 0xaa0003e0 : 0x2a0003e0;
+ tcg_out32(s, base | src << 16 | rd);
+}
+
+static inline void tcg_out_movi_aux(TCGContext *s,
+ TCGReg rd, uint64_t value)
+{
+ uint32_t half, base, shift, movk = 0;
+ /* construct halfwords of the immediate with MOVZ/MOVK with LSL */
+ /* using MOVZ 0x52800000 | extended reg.. */
+ base = (value > 0xffffffff) ? 0xd2800000 : 0x52800000;
+ /* count trailing zeros in 16 bit steps, mapping 64 to 0. Emit the
+ first MOVZ with the half-word immediate skipping the zeros, with a shift
+ (LSL) equal to this number. Then morph all next instructions into MOVKs.
+ Zero the processed half-word in the value, continue until empty.
+ We build the final result 16bits at a time with up to 4 instructions,
+ but do not emit instructions for 16bit zero holes. */
+ do {
+ shift = ctz64(value) & (63 & -16);
+ half = (value >> shift) & 0xffff;
+ tcg_out32(s, base | movk | shift << 17 | half << 5 | rd);
+ movk = 0x20000000; /* morph next MOVZs into MOVKs */
+ value &= ~(0xffffUL << shift);
+ } while (value);
+}
+
+static inline void tcg_out_movi(TCGContext *s, TCGType type,
+ TCGReg rd, tcg_target_long value)
+{
+ if (type == TCG_TYPE_I64) {
+ tcg_out_movi_aux(s, rd, value);
+ } else {
+ tcg_out_movi_aux(s, rd, value & 0xffffffff);
+ }
+}
+
+static inline void tcg_out_ldst_r(TCGContext *s,
+ enum aarch64_ldst_op_data op_data,
+ enum aarch64_ldst_op_type op_type,
+ TCGReg rd, TCGReg base, TCGReg regoff)
+{
+ /* load from memory to register using base + 64bit register offset */
+ /* using f.e. STR Wt, [Xn, Xm] 0xb8600800|(regoff << 16)|(base << 5)|rd */
+ /* the 0x6000 is for the "no extend field" */
+ tcg_out32(s, 0x00206800
+ | op_data << 24 | op_type << 20 | regoff << 16 | base << 5 | rd);
+}
+
+/* solve the whole ldst problem */
+static inline void tcg_out_ldst(TCGContext *s, enum aarch64_ldst_op_data data,
+ enum aarch64_ldst_op_type type,
+ TCGReg rd, TCGReg rn, tcg_target_long offset)
+{
+ if (offset >= -256 && offset < 256) {
+ tcg_out_ldst_9(s, data, type, rd, rn, offset);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, offset);
+ tcg_out_ldst_r(s, data, type, rd, rn, TCG_REG_TMP);
+ }
+}
+
+/* mov alias implemented with add immediate, useful to move to/from SP */
+static inline void tcg_out_movr_sp(TCGContext *s, int ext, TCGReg rd, TCGReg rn)
+{
+ /* using ADD 0x11000000 | (ext) | rn << 5 | rd */
+ unsigned int base = ext ? 0x91000000 : 0x11000000;
+ tcg_out32(s, base | rn << 5 | rd);
+}
+
+static inline void tcg_out_mov(TCGContext *s,
+ TCGType type, TCGReg ret, TCGReg arg)
+{
+ if (ret != arg) {
+ tcg_out_movr(s, type == TCG_TYPE_I64, ret, arg);
+ }
+}
+
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
+ TCGReg arg1, tcg_target_long arg2)
+{
+ tcg_out_ldst(s, (type == TCG_TYPE_I64) ? LDST_64 : LDST_32, LDST_LD,
+ arg, arg1, arg2);
+}
+
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+ TCGReg arg1, tcg_target_long arg2)
+{
+ tcg_out_ldst(s, (type == TCG_TYPE_I64) ? LDST_64 : LDST_32, LDST_ST,
+ arg, arg1, arg2);
+}
+
+static inline void tcg_out_arith(TCGContext *s, enum aarch64_arith_opc opc,
+ int ext, TCGReg rd, TCGReg rn, TCGReg rm,
+ int shift_imm)
+{
+ /* Using shifted register arithmetic operations */
+ /* if extended register operation (64bit) just OR with 0x80 << 24 */
+ unsigned int shift, base = ext ? (0x80 | opc) << 24 : opc << 24;
+ if (shift_imm == 0) {
+ shift = 0;
+ } else if (shift_imm > 0) {
+ shift = shift_imm << 10 | 1 << 22;
+ } else /* (shift_imm < 0) */ {
+ shift = (-shift_imm) << 10;
+ }
+ tcg_out32(s, base | rm << 16 | shift | rn << 5 | rd);
+}
+
+static inline void tcg_out_mul(TCGContext *s, int ext,
+ TCGReg rd, TCGReg rn, TCGReg rm)
+{
+ /* Using MADD 0x1b000000 with Ra = wzr alias MUL 0x1b007c00 */
+ unsigned int base = ext ? 0x9b007c00 : 0x1b007c00;
+ tcg_out32(s, base | rm << 16 | rn << 5 | rd);
+}
+
+static inline void tcg_out_shiftrot_reg(TCGContext *s,
+ enum aarch64_srr_opc opc, int ext,
+ TCGReg rd, TCGReg rn, TCGReg rm)
+{
+ /* using 2-source data processing instructions 0x1ac02000 */
+ unsigned int base = ext ? 0x9ac02000 : 0x1ac02000;
+ tcg_out32(s, base | rm << 16 | opc << 8 | rn << 5 | rd);
+}
+
+static inline void tcg_out_ubfm(TCGContext *s, int ext, TCGReg rd, TCGReg rn,
+ unsigned int a, unsigned int b)
+{
+ /* Using UBFM 0x53000000 Wd, Wn, a, b */
+ unsigned int base = ext ? 0xd3400000 : 0x53000000;
+ tcg_out32(s, base | a << 16 | b << 10 | rn << 5 | rd);
+}
+
+static inline void tcg_out_sbfm(TCGContext *s, int ext, TCGReg rd, TCGReg rn,
+ unsigned int a, unsigned int b)
+{
+ /* Using SBFM 0x13000000 Wd, Wn, a, b */
+ unsigned int base = ext ? 0x93400000 : 0x13000000;
+ tcg_out32(s, base | a << 16 | b << 10 | rn << 5 | rd);
+}
+
+static inline void tcg_out_extr(TCGContext *s, int ext, TCGReg rd,
+ TCGReg rn, TCGReg rm, unsigned int a)
+{
+ /* Using EXTR 0x13800000 Wd, Wn, Wm, a */
+ unsigned int base = ext ? 0x93c00000 : 0x13800000;
+ tcg_out32(s, base | rm << 16 | a << 10 | rn << 5 | rd);
+}
+
+static inline void tcg_out_shl(TCGContext *s, int ext,
+ TCGReg rd, TCGReg rn, unsigned int m)
+{
+ int bits, max;
+ bits = ext ? 64 : 32;
+ max = bits - 1;
+ tcg_out_ubfm(s, ext, rd, rn, bits - (m & max), max - (m & max));
+}
+
+static inline void tcg_out_shr(TCGContext *s, int ext,
+ TCGReg rd, TCGReg rn, unsigned int m)
+{
+ int max = ext ? 63 : 31;
+ tcg_out_ubfm(s, ext, rd, rn, m & max, max);
+}
+
+static inline void tcg_out_sar(TCGContext *s, int ext,
+ TCGReg rd, TCGReg rn, unsigned int m)
+{
+ int max = ext ? 63 : 31;
+ tcg_out_sbfm(s, ext, rd, rn, m & max, max);
+}
+
+static inline void tcg_out_rotr(TCGContext *s, int ext,
+ TCGReg rd, TCGReg rn, unsigned int m)
+{
+ int max = ext ? 63 : 31;
+ tcg_out_extr(s, ext, rd, rn, rn, m & max);
+}
+
+static inline void tcg_out_rotl(TCGContext *s, int ext,
+ TCGReg rd, TCGReg rn, unsigned int m)
+{
+ int bits, max;
+ bits = ext ? 64 : 32;
+ max = bits - 1;
+ tcg_out_extr(s, ext, rd, rn, rn, bits - (m & max));
+}
+
+static inline void tcg_out_cmp(TCGContext *s, int ext, TCGReg rn, TCGReg rm,
+ int shift_imm)
+{
+ /* Using CMP alias SUBS wzr, Wn, Wm */
+ tcg_out_arith(s, ARITH_SUBS, ext, TCG_REG_XZR, rn, rm, shift_imm);
+}
+
+static inline void tcg_out_cset(TCGContext *s, int ext, TCGReg rd, TCGCond c)
+{
+ /* Using CSET alias of CSINC 0x1a800400 Xd, XZR, XZR, invert(cond) */
+ unsigned int base = ext ? 0x9a9f07e0 : 0x1a9f07e0;
+ tcg_out32(s, base | tcg_cond_to_aarch64[tcg_invert_cond(c)] << 12 | rd);
+}
+
+static inline void tcg_out_goto(TCGContext *s, tcg_target_long target)
+{
+ tcg_target_long offset;
+ offset = (target - (tcg_target_long)s->code_ptr) / 4;
+
+ if (offset < -0x02000000 || offset >= 0x02000000) {
+ /* out of 26bit range */
+ tcg_abort();
+ }
+
+ tcg_out32(s, 0x14000000 | (offset & 0x03ffffff));
+}
+
+static inline void tcg_out_goto_noaddr(TCGContext *s)
+{
+ /* We pay attention here to not modify the branch target by
+ reading from the buffer. This ensure that caches and memory are
+ kept coherent during retranslation.
+ Mask away possible garbage in the high bits for the first translation,
+ while keeping the offset bits for retranslation. */
+ uint32_t insn;
+ insn = (tcg_in32(s) & 0x03ffffff) | 0x14000000;
+ tcg_out32(s, insn);
+}
+
+static inline void tcg_out_goto_cond_noaddr(TCGContext *s, TCGCond c)
+{
+ /* see comments in tcg_out_goto_noaddr */
+ uint32_t insn;
+ insn = tcg_in32(s) & (0x07ffff << 5);
+ insn |= 0x54000000 | tcg_cond_to_aarch64[c];
+ tcg_out32(s, insn);
+}
+
+static inline void tcg_out_goto_cond(TCGContext *s, TCGCond c,
+ tcg_target_long target)
+{
+ tcg_target_long offset;
+ offset = (target - (tcg_target_long)s->code_ptr) / 4;
+
+ if (offset < -0x40000 || offset >= 0x40000) {
+ /* out of 19bit range */
+ tcg_abort();
+ }
+
+ offset &= 0x7ffff;
+ tcg_out32(s, 0x54000000 | tcg_cond_to_aarch64[c] | offset << 5);
+}
+
+static inline void tcg_out_callr(TCGContext *s, TCGReg reg)
+{
+ tcg_out32(s, 0xd63f0000 | reg << 5);
+}
+
+static inline void tcg_out_gotor(TCGContext *s, TCGReg reg)
+{
+ tcg_out32(s, 0xd61f0000 | reg << 5);
+}
+
+static inline void tcg_out_call(TCGContext *s, tcg_target_long target)
+{
+ tcg_target_long offset;
+
+ offset = (target - (tcg_target_long)s->code_ptr) / 4;
+
+ if (offset < -0x02000000 || offset >= 0x02000000) { /* out of 26bit rng */
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, target);
+ tcg_out_callr(s, TCG_REG_TMP);
+ } else {
+ tcg_out32(s, 0x94000000 | (offset & 0x03ffffff));
+ }
+}
+
+/* encode a logical immediate, mapping user parameter
+ M=set bits pattern length to S=M-1 */
+static inline unsigned int
+aarch64_limm(unsigned int m, unsigned int r)
+{
+ assert(m > 0);
+ return r << 16 | (m - 1) << 10;
+}
+
+/* test a register against an immediate bit pattern made of
+ M set bits rotated right by R.
+ Examples:
+ to test a 32/64 reg against 0x00000007, pass M = 3, R = 0.
+ to test a 32/64 reg against 0x000000ff, pass M = 8, R = 0.
+ to test a 32bit reg against 0xff000000, pass M = 8, R = 8.
+ to test a 32bit reg against 0xff0000ff, pass M = 16, R = 8.
+ */
+static inline void tcg_out_tst(TCGContext *s, int ext, TCGReg rn,
+ unsigned int m, unsigned int r)
+{
+ /* using TST alias of ANDS XZR, Xn,#bimm64 0x7200001f */
+ unsigned int base = ext ? 0xf240001f : 0x7200001f;
+ tcg_out32(s, base | aarch64_limm(m, r) | rn << 5);
+}
+
+/* and a register with a bit pattern, similarly to TST, no flags change */
+static inline void tcg_out_andi(TCGContext *s, int ext, TCGReg rd, TCGReg rn,
+ unsigned int m, unsigned int r)
+{
+ /* using AND 0x12000000 */
+ unsigned int base = ext ? 0x92400000 : 0x12000000;
+ tcg_out32(s, base | aarch64_limm(m, r) | rn << 5 | rd);
+}
+
+static inline void tcg_out_ret(TCGContext *s)
+{
+ /* emit RET { LR } */
+ tcg_out32(s, 0xd65f03c0);
+}
+
+void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
+{
+ tcg_target_long target, offset;
+ target = (tcg_target_long)addr;
+ offset = (target - (tcg_target_long)jmp_addr) / 4;
+
+ if (offset < -0x02000000 || offset >= 0x02000000) {
+ /* out of 26bit range */
+ tcg_abort();
+ }
+
+ patch_reloc((uint8_t *)jmp_addr, R_AARCH64_JUMP26, target, 0);
+ flush_icache_range(jmp_addr, jmp_addr + 4);
+}
+
+static inline void tcg_out_goto_label(TCGContext *s, int label_index)
+{
+ TCGLabel *l = &s->labels[label_index];
+
+ if (!l->has_value) {
+ tcg_out_reloc(s, s->code_ptr, R_AARCH64_JUMP26, label_index, 0);
+ tcg_out_goto_noaddr(s);
+ } else {
+ tcg_out_goto(s, l->u.value);
+ }
+}
+
+static inline void tcg_out_goto_label_cond(TCGContext *s,
+ TCGCond c, int label_index)
+{
+ TCGLabel *l = &s->labels[label_index];
+
+ if (!l->has_value) {
+ tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, label_index, 0);
+ tcg_out_goto_cond_noaddr(s, c);
+ } else {
+ tcg_out_goto_cond(s, c, l->u.value);
+ }
+}
+
+static inline void tcg_out_rev(TCGContext *s, int ext, TCGReg rd, TCGReg rm)
+{
+ /* using REV 0x5ac00800 */
+ unsigned int base = ext ? 0xdac00c00 : 0x5ac00800;
+ tcg_out32(s, base | rm << 5 | rd);
+}
+
+static inline void tcg_out_rev16(TCGContext *s, int ext, TCGReg rd, TCGReg rm)
+{
+ /* using REV16 0x5ac00400 */
+ unsigned int base = ext ? 0xdac00400 : 0x5ac00400;
+ tcg_out32(s, base | rm << 5 | rd);
+}
+
+static inline void tcg_out_sxt(TCGContext *s, int ext, int s_bits,
+ TCGReg rd, TCGReg rn)
+{
+ /* using ALIASes SXTB 0x13001c00, SXTH 0x13003c00, SXTW 0x93407c00
+ of SBFM Xd, Xn, #0, #7|15|31 */
+ int bits = 8 * (1 << s_bits) - 1;
+ tcg_out_sbfm(s, ext, rd, rn, 0, bits);
+}
+
+static inline void tcg_out_uxt(TCGContext *s, int s_bits,
+ TCGReg rd, TCGReg rn)
+{
+ /* using ALIASes UXTB 0x53001c00, UXTH 0x53003c00
+ of UBFM Wd, Wn, #0, #7|15 */
+ int bits = 8 * (1 << s_bits) - 1;
+ tcg_out_ubfm(s, 0, rd, rn, 0, bits);
+}
+
+#ifdef CONFIG_SOFTMMU
+#include "exec/softmmu_defs.h"
+
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+ int mmu_idx) */
+static const void * const qemu_ld_helpers[4] = {
+ helper_ldb_mmu,
+ helper_ldw_mmu,
+ helper_ldl_mmu,
+ helper_ldq_mmu,
+};
+
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+ uintxx_t val, int mmu_idx) */
+static const void * const qemu_st_helpers[4] = {
+ helper_stb_mmu,
+ helper_stw_mmu,
+ helper_stl_mmu,
+ helper_stq_mmu,
+};
+
+#else /* !CONFIG_SOFTMMU */
+
+static void tcg_out_qemu_ld_direct(TCGContext *s, int opc, TCGReg data_r,
+ TCGReg addr_r, TCGReg off_r)
+{
+ switch (opc) {
+ case 0:
+ tcg_out_ldst_r(s, LDST_8, LDST_LD, data_r, addr_r, off_r);
+ break;
+ case 0 | 4:
+ tcg_out_ldst_r(s, LDST_8, LDST_LD_S_X, data_r, addr_r, off_r);
+ break;
+ case 1:
+ tcg_out_ldst_r(s, LDST_16, LDST_LD, data_r, addr_r, off_r);
+ if (TCG_LDST_BSWAP) {
+ tcg_out_rev16(s, 0, data_r, data_r);
+ }
+ break;
+ case 1 | 4:
+ if (TCG_LDST_BSWAP) {
+ tcg_out_ldst_r(s, LDST_16, LDST_LD, data_r, addr_r, off_r);
+ tcg_out_rev16(s, 0, data_r, data_r);
+ tcg_out_sxt(s, 1, 1, data_r, data_r);
+ } else {
+ tcg_out_ldst_r(s, LDST_16, LDST_LD_S_X, data_r, addr_r, off_r);
+ }
+ break;
+ case 2:
+ tcg_out_ldst_r(s, LDST_32, LDST_LD, data_r, addr_r, off_r);
+ if (TCG_LDST_BSWAP) {
+ tcg_out_rev(s, 0, data_r, data_r);
+ }
+ break;
+ case 2 | 4:
+ if (TCG_LDST_BSWAP) {
+ tcg_out_ldst_r(s, LDST_32, LDST_LD, data_r, addr_r, off_r);
+ tcg_out_rev(s, 0, data_r, data_r);
+ tcg_out_sxt(s, 1, 2, data_r, data_r);
+ } else {
+ tcg_out_ldst_r(s, LDST_32, LDST_LD_S_X, data_r, addr_r, off_r);
+ }
+ break;
+ case 3:
+ tcg_out_ldst_r(s, LDST_64, LDST_LD, data_r, addr_r, off_r);
+ if (TCG_LDST_BSWAP) {
+ tcg_out_rev(s, 1, data_r, data_r);
+ }
+ break;
+ default:
+ tcg_abort();
+ }
+}
+
+static void tcg_out_qemu_st_direct(TCGContext *s, int opc, TCGReg data_r,
+ TCGReg addr_r, TCGReg off_r)
+{
+ switch (opc) {
+ case 0:
+ tcg_out_ldst_r(s, LDST_8, LDST_ST, data_r, addr_r, off_r);
+ break;
+ case 1:
+ if (TCG_LDST_BSWAP) {
+ tcg_out_rev16(s, 0, TCG_REG_TMP, data_r);
+ tcg_out_ldst_r(s, LDST_16, LDST_ST, TCG_REG_TMP, addr_r, off_r);
+ } else {
+ tcg_out_ldst_r(s, LDST_16, LDST_ST, data_r, addr_r, off_r);
+ }
+ break;
+ case 2:
+ if (TCG_LDST_BSWAP) {
+ tcg_out_rev(s, 0, TCG_REG_TMP, data_r);
+ tcg_out_ldst_r(s, LDST_32, LDST_ST, TCG_REG_TMP, addr_r, off_r);
+ } else {
+ tcg_out_ldst_r(s, LDST_32, LDST_ST, data_r, addr_r, off_r);
+ }
+ break;
+ case 3:
+ if (TCG_LDST_BSWAP) {
+ tcg_out_rev(s, 1, TCG_REG_TMP, data_r);
+ tcg_out_ldst_r(s, LDST_64, LDST_ST, TCG_REG_TMP, addr_r, off_r);
+ } else {
+ tcg_out_ldst_r(s, LDST_64, LDST_ST, data_r, addr_r, off_r);
+ }
+ break;
+ default:
+ tcg_abort();
+ }
+}
+#endif /* CONFIG_SOFTMMU */
+
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
+{
+ TCGReg addr_reg, data_reg;
+#ifdef CONFIG_SOFTMMU
+ int mem_index, s_bits;
+#endif
+ data_reg = args[0];
+ addr_reg = args[1];
+
+#ifdef CONFIG_SOFTMMU
+ mem_index = args[2];
+ s_bits = opc & 3;
+
+ /* TODO: insert TLB lookup here */
+
+ /* all arguments passed via registers */
+ tcg_out_movr(s, 1, TCG_REG_X0, TCG_AREG0);
+ tcg_out_movr(s, (TARGET_LONG_BITS == 64), TCG_REG_X1, addr_reg);
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, mem_index);
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP,
+ (tcg_target_long)qemu_ld_helpers[s_bits]);
+ tcg_out_callr(s, TCG_REG_TMP);
+
+ if (opc & 0x04) { /* sign extend */
+ tcg_out_sxt(s, 1, s_bits, data_reg, TCG_REG_X0);
+ } else {
+ tcg_out_movr(s, 1, data_reg, TCG_REG_X0);
+ }
+
+#else /* !CONFIG_SOFTMMU */
+ tcg_out_qemu_ld_direct(s, opc, data_reg, addr_reg,
+ GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR);
+#endif /* CONFIG_SOFTMMU */
+}
+
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
+{
+ TCGReg addr_reg, data_reg;
+#ifdef CONFIG_SOFTMMU
+ int mem_index, s_bits;
+#endif
+ data_reg = args[0];
+ addr_reg = args[1];
+
+#ifdef CONFIG_SOFTMMU
+ mem_index = args[2];
+ s_bits = opc & 3;
+
+ /* TODO: insert TLB lookup here */
+
+ /* all arguments passed via registers */
+ tcg_out_movr(s, 1, TCG_REG_X0, TCG_AREG0);
+ tcg_out_movr(s, (TARGET_LONG_BITS == 64), TCG_REG_X1, addr_reg);
+ tcg_out_movr(s, 1, TCG_REG_X2, data_reg);
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, mem_index);
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP,
+ (tcg_target_long)qemu_st_helpers[s_bits]);
+ tcg_out_callr(s, TCG_REG_TMP);
+
+#else /* !CONFIG_SOFTMMU */
+ tcg_out_qemu_st_direct(s, opc, data_reg, addr_reg,
+ GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR);
+#endif /* CONFIG_SOFTMMU */
+}
+
+static uint8_t *tb_ret_addr;
+
+/* callee stack use example:
+ stp x29, x30, [sp,#-32]!
+ mov x29, sp
+ stp x1, x2, [sp,#16]
+ ...
+ ldp x1, x2, [sp,#16]
+ ldp x29, x30, [sp],#32
+ ret
+*/
+
+/* push r1 and r2, and alloc stack space for a total of
+ alloc_n elements (1 element=16 bytes, must be between 1 and 31. */
+static inline void tcg_out_push_pair(TCGContext *s, TCGReg addr,
+ TCGReg r1, TCGReg r2, int alloc_n)
+{
+ /* using indexed scaled simm7 STP 0x28800000 | (ext) | 0x01000000 (pre-idx)
+ | alloc_n * (-1) << 16 | r2 << 10 | addr << 5 | r1 */
+ assert(alloc_n > 0 && alloc_n < 0x20);
+ alloc_n = (-alloc_n) & 0x3f;
+ tcg_out32(s, 0xa9800000 | alloc_n << 16 | r2 << 10 | addr << 5 | r1);
+}
+
+/* dealloc stack space for a total of alloc_n elements and pop r1, r2. */
+static inline void tcg_out_pop_pair(TCGContext *s, TCGReg addr,
+ TCGReg r1, TCGReg r2, int alloc_n)
+{
+ /* using indexed scaled simm7 LDP 0x28c00000 | (ext) | nothing (post-idx)
+ | alloc_n << 16 | r2 << 10 | addr << 5 | r1 */
+ assert(alloc_n > 0 && alloc_n < 0x20);
+ tcg_out32(s, 0xa8c00000 | alloc_n << 16 | r2 << 10 | addr << 5 | r1);
+}
+
+static inline void tcg_out_store_pair(TCGContext *s, TCGReg addr,
+ TCGReg r1, TCGReg r2, int idx)
+{
+ /* using register pair offset simm7 STP 0x29000000 | (ext)
+ | idx << 16 | r2 << 10 | addr << 5 | r1 */
+ assert(idx > 0 && idx < 0x20);
+ tcg_out32(s, 0xa9000000 | idx << 16 | r2 << 10 | addr << 5 | r1);
+}
+
+static inline void tcg_out_load_pair(TCGContext *s, TCGReg addr,
+ TCGReg r1, TCGReg r2, int idx)
+{
+ /* using register pair offset simm7 LDP 0x29400000 | (ext)
+ | idx << 16 | r2 << 10 | addr << 5 | r1 */
+ assert(idx > 0 && idx < 0x20);
+ tcg_out32(s, 0xa9400000 | idx << 16 | r2 << 10 | addr << 5 | r1);
+}
+
+static void tcg_out_op(TCGContext *s, TCGOpcode opc,
+ const TCGArg *args, const int *const_args)
+{
+ /* ext will be set in the switch below, which will fall through to the
+ common code. It triggers the use of extended regs where appropriate. */
+ int ext = 0;
+
+ switch (opc) {
+ case INDEX_op_exit_tb:
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, args[0]);
+ tcg_out_goto(s, (tcg_target_long)tb_ret_addr);
+ break;
+
+ case INDEX_op_goto_tb:
+#ifndef USE_DIRECT_JUMP
+#error "USE_DIRECT_JUMP required for aarch64"
+#endif
+ assert(s->tb_jmp_offset != NULL); /* consistency for USE_DIRECT_JUMP */
+ s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
+ /* actual branch destination will be patched by
+ aarch64_tb_set_jmp_target later, beware retranslation. */
+ tcg_out_goto_noaddr(s);
+ s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
+ break;
+
+ case INDEX_op_call:
+ if (const_args[0]) {
+ tcg_out_call(s, args[0]);
+ } else {
+ tcg_out_callr(s, args[0]);
+ }
+ break;
+
+ case INDEX_op_br:
+ tcg_out_goto_label(s, args[0]);
+ break;
+
+ case INDEX_op_ld_i32:
+ case INDEX_op_ld_i64:
+ case INDEX_op_st_i32:
+ case INDEX_op_st_i64:
+ case INDEX_op_ld8u_i32:
+ case INDEX_op_ld8s_i32:
+ case INDEX_op_ld16u_i32:
+ case INDEX_op_ld16s_i32:
+ case INDEX_op_ld8u_i64:
+ case INDEX_op_ld8s_i64:
+ case INDEX_op_ld16u_i64:
+ case INDEX_op_ld16s_i64:
+ case INDEX_op_ld32u_i64:
+ case INDEX_op_ld32s_i64:
+ case INDEX_op_st8_i32:
+ case INDEX_op_st8_i64:
+ case INDEX_op_st16_i32:
+ case INDEX_op_st16_i64:
+ case INDEX_op_st32_i64:
+ tcg_out_ldst(s, aarch64_ldst_get_data(opc), aarch64_ldst_get_type(opc),
+ args[0], args[1], args[2]);
+ break;
+
+ case INDEX_op_mov_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_mov_i32:
+ tcg_out_movr(s, ext, args[0], args[1]);
+ break;
+
+ case INDEX_op_movi_i64:
+ tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
+ break;
+ case INDEX_op_movi_i32:
+ tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
+ break;
+
+ case INDEX_op_add_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_add_i32:
+ tcg_out_arith(s, ARITH_ADD, ext, args[0], args[1], args[2], 0);
+ break;
+
+ case INDEX_op_sub_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_sub_i32:
+ tcg_out_arith(s, ARITH_SUB, ext, args[0], args[1], args[2], 0);
+ break;
+
+ case INDEX_op_and_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_and_i32:
+ tcg_out_arith(s, ARITH_AND, ext, args[0], args[1], args[2], 0);
+ break;
+
+ case INDEX_op_or_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_or_i32:
+ tcg_out_arith(s, ARITH_OR, ext, args[0], args[1], args[2], 0);
+ break;
+
+ case INDEX_op_xor_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_xor_i32:
+ tcg_out_arith(s, ARITH_XOR, ext, args[0], args[1], args[2], 0);
+ break;
+
+ case INDEX_op_mul_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_mul_i32:
+ tcg_out_mul(s, ext, args[0], args[1], args[2]);
+ break;
+
+ case INDEX_op_shl_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_shl_i32:
+ if (const_args[2]) { /* LSL / UBFM Wd, Wn, (32 - m) */
+ tcg_out_shl(s, ext, args[0], args[1], args[2]);
+ } else { /* LSL / LSLV */
+ tcg_out_shiftrot_reg(s, SRR_SHL, ext, args[0], args[1], args[2]);
+ }
+ break;
+
+ case INDEX_op_shr_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_shr_i32:
+ if (const_args[2]) { /* LSR / UBFM Wd, Wn, m, 31 */
+ tcg_out_shr(s, ext, args[0], args[1], args[2]);
+ } else { /* LSR / LSRV */
+ tcg_out_shiftrot_reg(s, SRR_SHR, ext, args[0], args[1], args[2]);
+ }
+ break;
+
+ case INDEX_op_sar_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_sar_i32:
+ if (const_args[2]) { /* ASR / SBFM Wd, Wn, m, 31 */
+ tcg_out_sar(s, ext, args[0], args[1], args[2]);
+ } else { /* ASR / ASRV */
+ tcg_out_shiftrot_reg(s, SRR_SAR, ext, args[0], args[1], args[2]);
+ }
+ break;
+
+ case INDEX_op_rotr_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_rotr_i32:
+ if (const_args[2]) { /* ROR / EXTR Wd, Wm, Wm, m */
+ tcg_out_rotr(s, ext, args[0], args[1], args[2]);
+ } else { /* ROR / RORV */
+ tcg_out_shiftrot_reg(s, SRR_ROR, ext, args[0], args[1], args[2]);
+ }
+ break;
+
+ case INDEX_op_rotl_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_rotl_i32: /* same as rotate right by (32 - m) */
+ if (const_args[2]) { /* ROR / EXTR Wd, Wm, Wm, 32 - m */
+ tcg_out_rotl(s, ext, args[0], args[1], args[2]);
+ } else {
+ tcg_out_arith(s, ARITH_SUB, 0,
+ TCG_REG_TMP, TCG_REG_XZR, args[2], 0);
+ tcg_out_shiftrot_reg(s, SRR_ROR, ext,
+ args[0], args[1], TCG_REG_TMP);
+ }
+ break;
+
+ case INDEX_op_brcond_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_brcond_i32: /* CMP 0, 1, cond(2), label 3 */
+ tcg_out_cmp(s, ext, args[0], args[1], 0);
+ tcg_out_goto_label_cond(s, args[2], args[3]);
+ break;
+
+ case INDEX_op_setcond_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_setcond_i32:
+ tcg_out_cmp(s, ext, args[1], args[2], 0);
+ tcg_out_cset(s, 0, args[0], args[3]);
+ break;
+
+ case INDEX_op_qemu_ld8u:
+ tcg_out_qemu_ld(s, args, 0 | 0);
+ break;
+ case INDEX_op_qemu_ld8s:
+ tcg_out_qemu_ld(s, args, 4 | 0);
+ break;
+ case INDEX_op_qemu_ld16u:
+ tcg_out_qemu_ld(s, args, 0 | 1);
+ break;
+ case INDEX_op_qemu_ld16s:
+ tcg_out_qemu_ld(s, args, 4 | 1);
+ break;
+ case INDEX_op_qemu_ld32u:
+ tcg_out_qemu_ld(s, args, 0 | 2);
+ break;
+ case INDEX_op_qemu_ld32s:
+ tcg_out_qemu_ld(s, args, 4 | 2);
+ break;
+ case INDEX_op_qemu_ld32:
+ tcg_out_qemu_ld(s, args, 0 | 2);
+ break;
+ case INDEX_op_qemu_ld64:
+ tcg_out_qemu_ld(s, args, 0 | 3);
+ break;
+ case INDEX_op_qemu_st8:
+ tcg_out_qemu_st(s, args, 0);
+ break;
+ case INDEX_op_qemu_st16:
+ tcg_out_qemu_st(s, args, 1);
+ break;
+ case INDEX_op_qemu_st32:
+ tcg_out_qemu_st(s, args, 2);
+ break;
+ case INDEX_op_qemu_st64:
+ tcg_out_qemu_st(s, args, 3);
+ break;
+
+ case INDEX_op_bswap64_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_bswap32_i64:
+ case INDEX_op_bswap32_i32:
+ tcg_out_rev(s, ext, args[0], args[1]);
+ break;
+ case INDEX_op_bswap16_i64:
+ case INDEX_op_bswap16_i32:
+ tcg_out_rev16(s, 0, args[0], args[1]);
+ break;
+
+ case INDEX_op_ext8s_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_ext8s_i32:
+ tcg_out_sxt(s, ext, 0, args[0], args[1]);
+ break;
+ case INDEX_op_ext16s_i64:
+ ext = 1; /* fall through */
+ case INDEX_op_ext16s_i32:
+ tcg_out_sxt(s, ext, 1, args[0], args[1]);
+ break;
+ case INDEX_op_ext32s_i64:
+ tcg_out_sxt(s, 1, 2, args[0], args[1]);
+ break;
+ case INDEX_op_ext8u_i64:
+ case INDEX_op_ext8u_i32:
+ tcg_out_uxt(s, 0, args[0], args[1]);
+ break;
+ case INDEX_op_ext16u_i64:
+ case INDEX_op_ext16u_i32:
+ tcg_out_uxt(s, 1, args[0], args[1]);
+ break;
+ case INDEX_op_ext32u_i64:
+ tcg_out_movr(s, 0, args[0], args[1]);
+ break;
+
+ default:
+ tcg_abort(); /* opcode not implemented */
+ }
+}
+
+static const TCGTargetOpDef aarch64_op_defs[] = {
+ { INDEX_op_exit_tb, { } },
+ { INDEX_op_goto_tb, { } },
+ { INDEX_op_call, { "ri" } },
+ { INDEX_op_br, { } },
+
+ { INDEX_op_mov_i32, { "r", "r" } },
+ { INDEX_op_mov_i64, { "r", "r" } },
+
+ { INDEX_op_movi_i32, { "r" } },
+ { INDEX_op_movi_i64, { "r" } },
+
+ { INDEX_op_ld8u_i32, { "r", "r" } },
+ { INDEX_op_ld8s_i32, { "r", "r" } },
+ { INDEX_op_ld16u_i32, { "r", "r" } },
+ { INDEX_op_ld16s_i32, { "r", "r" } },
+ { INDEX_op_ld_i32, { "r", "r" } },
+ { INDEX_op_ld8u_i64, { "r", "r" } },
+ { INDEX_op_ld8s_i64, { "r", "r" } },
+ { INDEX_op_ld16u_i64, { "r", "r" } },
+ { INDEX_op_ld16s_i64, { "r", "r" } },
+ { INDEX_op_ld32u_i64, { "r", "r" } },
+ { INDEX_op_ld32s_i64, { "r", "r" } },
+ { INDEX_op_ld_i64, { "r", "r" } },
+
+ { INDEX_op_st8_i32, { "r", "r" } },
+ { INDEX_op_st16_i32, { "r", "r" } },
+ { INDEX_op_st_i32, { "r", "r" } },
+ { INDEX_op_st8_i64, { "r", "r" } },
+ { INDEX_op_st16_i64, { "r", "r" } },
+ { INDEX_op_st32_i64, { "r", "r" } },
+ { INDEX_op_st_i64, { "r", "r" } },
+
+ { INDEX_op_add_i32, { "r", "r", "r" } },
+ { INDEX_op_add_i64, { "r", "r", "r" } },
+ { INDEX_op_sub_i32, { "r", "r", "r" } },
+ { INDEX_op_sub_i64, { "r", "r", "r" } },
+ { INDEX_op_mul_i32, { "r", "r", "r" } },
+ { INDEX_op_mul_i64, { "r", "r", "r" } },
+ { INDEX_op_and_i32, { "r", "r", "r" } },
+ { INDEX_op_and_i64, { "r", "r", "r" } },
+ { INDEX_op_or_i32, { "r", "r", "r" } },
+ { INDEX_op_or_i64, { "r", "r", "r" } },
+ { INDEX_op_xor_i32, { "r", "r", "r" } },
+ { INDEX_op_xor_i64, { "r", "r", "r" } },
+
+ { INDEX_op_shl_i32, { "r", "r", "ri" } },
+ { INDEX_op_shr_i32, { "r", "r", "ri" } },
+ { INDEX_op_sar_i32, { "r", "r", "ri" } },
+ { INDEX_op_rotl_i32, { "r", "r", "ri" } },
+ { INDEX_op_rotr_i32, { "r", "r", "ri" } },
+ { INDEX_op_shl_i64, { "r", "r", "ri" } },
+ { INDEX_op_shr_i64, { "r", "r", "ri" } },
+ { INDEX_op_sar_i64, { "r", "r", "ri" } },
+ { INDEX_op_rotl_i64, { "r", "r", "ri" } },
+ { INDEX_op_rotr_i64, { "r", "r", "ri" } },
+
+ { INDEX_op_brcond_i32, { "r", "r" } },
+ { INDEX_op_setcond_i32, { "r", "r", "r" } },
+ { INDEX_op_brcond_i64, { "r", "r" } },
+ { INDEX_op_setcond_i64, { "r", "r", "r" } },
+
+ { INDEX_op_qemu_ld8u, { "r", "l" } },
+ { INDEX_op_qemu_ld8s, { "r", "l" } },
+ { INDEX_op_qemu_ld16u, { "r", "l" } },
+ { INDEX_op_qemu_ld16s, { "r", "l" } },
+ { INDEX_op_qemu_ld32u, { "r", "l" } },
+ { INDEX_op_qemu_ld32s, { "r", "l" } },
+
+ { INDEX_op_qemu_ld32, { "r", "l" } },
+ { INDEX_op_qemu_ld64, { "r", "l" } },
+
+ { INDEX_op_qemu_st8, { "l", "l" } },
+ { INDEX_op_qemu_st16, { "l", "l" } },
+ { INDEX_op_qemu_st32, { "l", "l" } },
+ { INDEX_op_qemu_st64, { "l", "l" } },
+
+ { INDEX_op_bswap16_i32, { "r", "r" } },
+ { INDEX_op_bswap32_i32, { "r", "r" } },
+ { INDEX_op_bswap16_i64, { "r", "r" } },
+ { INDEX_op_bswap32_i64, { "r", "r" } },
+ { INDEX_op_bswap64_i64, { "r", "r" } },
+
+ { INDEX_op_ext8s_i32, { "r", "r" } },
+ { INDEX_op_ext16s_i32, { "r", "r" } },
+ { INDEX_op_ext8u_i32, { "r", "r" } },
+ { INDEX_op_ext16u_i32, { "r", "r" } },
+
+ { INDEX_op_ext8s_i64, { "r", "r" } },
+ { INDEX_op_ext16s_i64, { "r", "r" } },
+ { INDEX_op_ext32s_i64, { "r", "r" } },
+ { INDEX_op_ext8u_i64, { "r", "r" } },
+ { INDEX_op_ext16u_i64, { "r", "r" } },
+ { INDEX_op_ext32u_i64, { "r", "r" } },
+
+ { -1 },
+};
+
+static void tcg_target_init(TCGContext *s)
+{
+#if !defined(CONFIG_USER_ONLY)
+ /* fail safe */
+ if ((1ULL << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry)) {
+ tcg_abort();
+ }
+#endif
+ tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
+ tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
+
+ tcg_regset_set32(tcg_target_call_clobber_regs, 0,
+ (1 << TCG_REG_X0) | (1 << TCG_REG_X1) |
+ (1 << TCG_REG_X2) | (1 << TCG_REG_X3) |
+ (1 << TCG_REG_X4) | (1 << TCG_REG_X5) |
+ (1 << TCG_REG_X6) | (1 << TCG_REG_X7) |
+ (1 << TCG_REG_X8) | (1 << TCG_REG_X9) |
+ (1 << TCG_REG_X10) | (1 << TCG_REG_X11) |
+ (1 << TCG_REG_X12) | (1 << TCG_REG_X13) |
+ (1 << TCG_REG_X14) | (1 << TCG_REG_X15) |
+ (1 << TCG_REG_X16) | (1 << TCG_REG_X17) |
+ (1 << TCG_REG_X18));
+
+ tcg_regset_clear(s->reserved_regs);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_X18); /* platform register */
+
+ tcg_add_target_add_op_defs(aarch64_op_defs);
+}
+
+static inline void tcg_out_addi(TCGContext *s, int ext,
+ TCGReg rd, TCGReg rn, unsigned int aimm)
+{
+ /* add immediate aimm unsigned 12bit value (we use LSL 0 - no shift) */
+ /* using ADD 0x11000000 | (ext) | (aimm << 10) | (rn << 5) | rd */
+ unsigned int base = ext ? 0x91000000 : 0x11000000;
+ assert(aimm <= 0xfff);
+ tcg_out32(s, base | (aimm << 10) | (rn << 5) | rd);
+}
+
+static inline void tcg_out_subi(TCGContext *s, int ext,
+ TCGReg rd, TCGReg rn, unsigned int aimm)
+{
+ /* sub immediate aimm unsigned 12bit value (we use LSL 0 - no shift) */
+ /* using SUB 0x51000000 | (ext) | (aimm << 10) | (rn << 5) | rd */
+ unsigned int base = ext ? 0xd1000000 : 0x51000000;
+ assert(aimm <= 0xfff);
+ tcg_out32(s, base | (aimm << 10) | (rn << 5) | rd);
+}
+
+static void tcg_target_qemu_prologue(TCGContext *s)
+{
+ /* NB: frame sizes are in 16 byte stack units! */
+ int frame_size_callee_saved, frame_size_tcg_locals;
+ TCGReg r;
+
+ /* save pairs (FP, LR) and (X19, X20) .. (X27, X28) */
+ frame_size_callee_saved = (1) + (TCG_REG_X28 - TCG_REG_X19) / 2 + 1;
+
+ /* frame size requirement for TCG local variables */
+ frame_size_tcg_locals = TCG_STATIC_CALL_ARGS_SIZE
+ + CPU_TEMP_BUF_NLONGS * sizeof(long)
+ + (TCG_TARGET_STACK_ALIGN - 1);
+ frame_size_tcg_locals &= ~(TCG_TARGET_STACK_ALIGN - 1);
+ frame_size_tcg_locals /= TCG_TARGET_STACK_ALIGN;
+
+ /* push (FP, LR) and update sp */
+ tcg_out_push_pair(s, TCG_REG_SP,
+ TCG_REG_FP, TCG_REG_LR, frame_size_callee_saved);
+
+ /* FP -> callee_saved */
+ tcg_out_movr_sp(s, 1, TCG_REG_FP, TCG_REG_SP);
+
+ /* store callee-preserved regs x19..x28 using FP -> callee_saved */
+ for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
+ int idx = (r - TCG_REG_X19) / 2 + 1;
+ tcg_out_store_pair(s, TCG_REG_FP, r, r + 1, idx);
+ }
+
+ /* make stack space for TCG locals */
+ tcg_out_subi(s, 1, TCG_REG_SP, TCG_REG_SP,
+ frame_size_tcg_locals * TCG_TARGET_STACK_ALIGN);
+ /* inform TCG about how to find TCG locals with register, offset, size */
+ tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE,
+ CPU_TEMP_BUF_NLONGS * sizeof(long));
+
+#if defined(CONFIG_USE_GUEST_BASE)
+ if (GUEST_BASE) {
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, GUEST_BASE);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
+ }
+#endif
+
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+ tcg_out_gotor(s, tcg_target_call_iarg_regs[1]);
+
+ tb_ret_addr = s->code_ptr;
+
+ /* remove TCG locals stack space */
+ tcg_out_addi(s, 1, TCG_REG_SP, TCG_REG_SP,
+ frame_size_tcg_locals * TCG_TARGET_STACK_ALIGN);
+
+ /* restore registers x19..x28.
+ FP must be preserved, so it still points to callee_saved area */
+ for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
+ int idx = (r - TCG_REG_X19) / 2 + 1;
+ tcg_out_load_pair(s, TCG_REG_FP, r, r + 1, idx);
+ }
+
+ /* pop (FP, LR), restore SP to previous frame, return */
+ tcg_out_pop_pair(s, TCG_REG_SP,
+ TCG_REG_FP, TCG_REG_LR, frame_size_callee_saved);
+ tcg_out_ret(s);
+}
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
new file mode 100644
index 0000000000..97e4a5baa7
--- /dev/null
+++ b/tcg/aarch64/tcg-target.h
@@ -0,0 +1,99 @@
+/*
+ * Initial TCG Implementation for aarch64
+ *
+ * Copyright (c) 2013 Huawei Technologies Duesseldorf GmbH
+ * Written by Claudio Fontana
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.
+ *
+ * See the COPYING file in the top-level directory for details.
+ */
+
+#ifndef TCG_TARGET_AARCH64
+#define TCG_TARGET_AARCH64 1
+
+#undef TCG_TARGET_WORDS_BIGENDIAN
+#undef TCG_TARGET_STACK_GROWSUP
+
+typedef enum {
+ TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3, TCG_REG_X4,
+ TCG_REG_X5, TCG_REG_X6, TCG_REG_X7, TCG_REG_X8, TCG_REG_X9,
+ TCG_REG_X10, TCG_REG_X11, TCG_REG_X12, TCG_REG_X13, TCG_REG_X14,
+ TCG_REG_X15, TCG_REG_X16, TCG_REG_X17, TCG_REG_X18, TCG_REG_X19,
+ TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23, TCG_REG_X24,
+ TCG_REG_X25, TCG_REG_X26, TCG_REG_X27, TCG_REG_X28,
+ TCG_REG_FP, /* frame pointer */
+ TCG_REG_LR, /* link register */
+ TCG_REG_SP, /* stack pointer or zero register */
+ TCG_REG_XZR = TCG_REG_SP /* same register number */
+ /* program counter is not directly accessible! */
+} TCGReg;
+
+#define TCG_TARGET_NB_REGS 32
+
+/* used for function call generation */
+#define TCG_REG_CALL_STACK TCG_REG_SP
+#define TCG_TARGET_STACK_ALIGN 16
+#define TCG_TARGET_CALL_ALIGN_ARGS 1
+#define TCG_TARGET_CALL_STACK_OFFSET 0
+
+/* optional instructions */
+#define TCG_TARGET_HAS_div_i32 0
+#define TCG_TARGET_HAS_ext8s_i32 1
+#define TCG_TARGET_HAS_ext16s_i32 1
+#define TCG_TARGET_HAS_ext8u_i32 1
+#define TCG_TARGET_HAS_ext16u_i32 1
+#define TCG_TARGET_HAS_bswap16_i32 1
+#define TCG_TARGET_HAS_bswap32_i32 1
+#define TCG_TARGET_HAS_not_i32 0
+#define TCG_TARGET_HAS_neg_i32 0
+#define TCG_TARGET_HAS_rot_i32 1
+#define TCG_TARGET_HAS_andc_i32 0
+#define TCG_TARGET_HAS_orc_i32 0
+#define TCG_TARGET_HAS_eqv_i32 0
+#define TCG_TARGET_HAS_nand_i32 0
+#define TCG_TARGET_HAS_nor_i32 0
+#define TCG_TARGET_HAS_deposit_i32 0
+#define TCG_TARGET_HAS_movcond_i32 0
+#define TCG_TARGET_HAS_add2_i32 0
+#define TCG_TARGET_HAS_sub2_i32 0
+#define TCG_TARGET_HAS_mulu2_i32 0
+#define TCG_TARGET_HAS_muls2_i32 0
+
+#define TCG_TARGET_HAS_div_i64 0
+#define TCG_TARGET_HAS_ext8s_i64 1
+#define TCG_TARGET_HAS_ext16s_i64 1
+#define TCG_TARGET_HAS_ext32s_i64 1
+#define TCG_TARGET_HAS_ext8u_i64 1
+#define TCG_TARGET_HAS_ext16u_i64 1
+#define TCG_TARGET_HAS_ext32u_i64 1
+#define TCG_TARGET_HAS_bswap16_i64 1
+#define TCG_TARGET_HAS_bswap32_i64 1
+#define TCG_TARGET_HAS_bswap64_i64 1
+#define TCG_TARGET_HAS_not_i64 0
+#define TCG_TARGET_HAS_neg_i64 0
+#define TCG_TARGET_HAS_rot_i64 1
+#define TCG_TARGET_HAS_andc_i64 0
+#define TCG_TARGET_HAS_orc_i64 0
+#define TCG_TARGET_HAS_eqv_i64 0
+#define TCG_TARGET_HAS_nand_i64 0
+#define TCG_TARGET_HAS_nor_i64 0
+#define TCG_TARGET_HAS_deposit_i64 0
+#define TCG_TARGET_HAS_movcond_i64 0
+#define TCG_TARGET_HAS_add2_i64 0
+#define TCG_TARGET_HAS_sub2_i64 0
+#define TCG_TARGET_HAS_mulu2_i64 0
+#define TCG_TARGET_HAS_muls2_i64 0
+
+enum {
+ TCG_AREG0 = TCG_REG_X19,
+};
+
+static inline void flush_icache_range(tcg_target_ulong start,
+ tcg_target_ulong stop)
+{
+ __builtin___clear_cache((char *)start, (char *)stop);
+}
+
+#endif /* TCG_TARGET_AARCH64 */
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 3d434124a0..6be736b75e 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -2053,12 +2053,6 @@ static const TCGTargetOpDef arm_op_defs[] = {
static void tcg_target_init(TCGContext *s)
{
-#if !defined(CONFIG_USER_ONLY)
- /* fail safe */
- if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
- tcg_abort();
-#endif
-
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
tcg_regset_set32(tcg_target_call_clobber_regs, 0,
(1 << TCG_REG_R0) |
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 9eec06c8a4..9e95477ef4 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -2283,12 +2283,6 @@ static void tcg_target_init(TCGContext *s)
}
#endif
-#if !defined(CONFIG_USER_ONLY)
- /* fail safe */
- if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
- tcg_abort();
-#endif
-
if (TCG_TARGET_REG_BITS == 64) {
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 7d6f777081..f229f1c346 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -2324,13 +2324,6 @@ static void query_facilities(void)
static void tcg_target_init(TCGContext *s)
{
-#if !defined(CONFIG_USER_ONLY)
- /* fail safe */
- if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry)) {
- tcg_abort();
- }
-#endif
-
query_facilities();
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
diff --git a/tests/ide-test.c b/tests/ide-test.c
index 365e9959ff..7e2eb9455a 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -64,6 +64,7 @@ enum {
};
enum {
+ DEV = 0x10,
LBA = 0x40,
};
@@ -76,6 +77,7 @@ enum {
enum {
CMD_READ_DMA = 0xc8,
CMD_WRITE_DMA = 0xca,
+ CMD_FLUSH_CACHE = 0xe7,
CMD_IDENTIFY = 0xec,
CMDF_ABORT = 0x100,
@@ -394,7 +396,7 @@ static void test_identify(void)
/* Read in the IDENTIFY buffer and check registers */
data = inb(IDE_BASE + reg_device);
- g_assert_cmpint(data & 0x10, ==, 0);
+ g_assert_cmpint(data & DEV, ==, 0);
for (i = 0; i < 256; i++) {
data = inb(IDE_BASE + reg_status);
@@ -423,6 +425,46 @@ static void test_identify(void)
ide_test_quit();
}
+static void test_flush(void)
+{
+ uint8_t data;
+
+ ide_test_start(
+ "-vnc none "
+ "-drive file=blkdebug::%s,if=ide,cache=writeback",
+ tmp_path);
+
+ /* Delay the completion of the flush request until we explicitly do it */
+ qmp("{'execute':'human-monitor-command', 'arguments': { "
+ "'command-line': 'qemu-io ide0-hd0 \"break flush_to_os A\"'} }");
+
+ /* FLUSH CACHE command on device 0*/
+ outb(IDE_BASE + reg_device, 0);
+ outb(IDE_BASE + reg_command, CMD_FLUSH_CACHE);
+
+ /* Check status while request is in flight*/
+ data = inb(IDE_BASE + reg_status);
+ assert_bit_set(data, BSY | DRDY);
+ assert_bit_clear(data, DF | ERR | DRQ);
+
+ /* Complete the command */
+ qmp("{'execute':'human-monitor-command', 'arguments': { "
+ "'command-line': 'qemu-io ide0-hd0 \"resume A\"'} }");
+
+ /* Check registers */
+ data = inb(IDE_BASE + reg_device);
+ g_assert_cmpint(data & DEV, ==, 0);
+
+ do {
+ data = inb(IDE_BASE + reg_status);
+ } while (data & BSY);
+
+ assert_bit_set(data, DRDY);
+ assert_bit_clear(data, BSY | DF | ERR | DRQ);
+
+ ide_test_quit();
+}
+
int main(int argc, char **argv)
{
const char *arch = qtest_get_arch();
@@ -453,6 +495,8 @@ int main(int argc, char **argv)
qtest_add_func("/ide/bmdma/long_prdt", test_bmdma_long_prdt);
qtest_add_func("/ide/bmdma/teardown", test_bmdma_teardown);
+ qtest_add_func("/ide/flush", test_flush);
+
ret = g_test_run();
/* Cleanup */
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
index 72db13f8d2..d2f0efe16d 100644
--- a/tests/qemu-iotests/049.out
+++ b/tests/qemu-iotests/049.out
@@ -108,15 +108,15 @@ qemu-img: Formatting or formatting option not supported for file format 'qcow2'
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off
qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- 1kilobyte
-qemu-img: Invalid image size specified! You may use k, M, G or T suffixes for
-qemu-img: kilobytes, megabytes, gigabytes and terabytes.
+qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for
+qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
qemu-img create -f qcow2 -o size=1kilobyte TEST_DIR/t.qcow2
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off
qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- foobar
-qemu-img: Invalid image size specified! You may use k, M, G or T suffixes for
-qemu-img: kilobytes, megabytes, gigabytes and terabytes.
+qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for
+qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2
qemu-img: Parameter 'size' expects a size
diff --git a/translate-all.c b/translate-all.c
index 40b8f3d2b5..df7c697692 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -460,6 +460,8 @@ static inline PageDesc *page_find(tb_page_addr_t index)
# define MAX_CODE_GEN_BUFFER_SIZE (2ul * 1024 * 1024 * 1024)
#elif defined(__sparc__)
# define MAX_CODE_GEN_BUFFER_SIZE (2ul * 1024 * 1024 * 1024)
+#elif defined(__aarch64__)
+# define MAX_CODE_GEN_BUFFER_SIZE (128ul * 1024 * 1024)
#elif defined(__arm__)
# define MAX_CODE_GEN_BUFFER_SIZE (16u * 1024 * 1024)
#elif defined(__s390x__)
diff --git a/ui/console.c b/ui/console.c
index b30853f6ef..28bba6de99 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1788,6 +1788,10 @@ static CharDriverState *text_console_init(ChardevVC *vc)
s->chr = chr;
chr->opaque = s;
chr->chr_set_echo = text_console_set_echo;
+ /* console/chardev init sometimes completes elsewhere in a 2nd
+ * stage, so defer OPENED events until they are fully initialized
+ */
+ chr->explicit_be_open = true;
if (display_state) {
text_console_do_init(chr, display_state);
diff --git a/ui/gtk.c b/ui/gtk.c
index 3bc284227e..50a6993627 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1119,6 +1119,8 @@ static CharDriverState *gd_vc_handler(ChardevVC *unused)
chr = g_malloc0(sizeof(*chr));
chr->chr_write = gd_vc_chr_write;
+ /* defer OPENED events until our vc is fully initialized */
+ chr->explicit_be_open = true;
vcs[nb_vcs++] = chr;
@@ -1158,8 +1160,7 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
GIOChannel *chan;
GtkWidget *scrolled_window;
GtkAdjustment *vadjustment;
- int master_fd, slave_fd, ret;
- struct termios tty;
+ int master_fd, slave_fd;
snprintf(buffer, sizeof(buffer), "vc%d", index);
snprintf(path, sizeof(path), "<QEMU>/View/VC%d", index);
@@ -1179,13 +1180,8 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
vc->terminal = vte_terminal_new();
- ret = openpty(&master_fd, &slave_fd, NULL, NULL, NULL);
- g_assert(ret != -1);
-
- /* Set raw attributes on the pty. */
- tcgetattr(slave_fd, &tty);
- cfmakeraw(&tty);
- tcsetattr(slave_fd, TCSAFLUSH, &tty);
+ master_fd = qemu_openpty_raw(&slave_fd, NULL);
+ g_assert(master_fd != -1);
#if VTE_CHECK_VERSION(0, 26, 0)
pty = vte_pty_new_foreign(master_fd, NULL);
@@ -1433,7 +1429,7 @@ static const DisplayChangeListenerOps dcl_ops = {
.dpy_cursor_define = gd_cursor_define,
};
-void gtk_display_init(DisplayState *ds)
+void gtk_display_init(DisplayState *ds, bool full_screen)
{
GtkDisplayState *s = g_malloc0(sizeof(*s));
char *filename;
@@ -1469,7 +1465,7 @@ void gtk_display_init(DisplayState *ds)
gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), s->drawing_area, gtk_label_new("VGA"));
- filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "qemu-icon.bmp");
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "qemu_logo_no_text.svg");
if (filename) {
GError *error = NULL;
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(filename, &error);
@@ -1509,6 +1505,10 @@ void gtk_display_init(DisplayState *ds)
gtk_widget_show_all(s->window);
+ if (full_screen) {
+ gtk_menu_item_activate(GTK_MENU_ITEM(s->full_screen_item));
+ }
+
register_displaychangelistener(&s->dcl);
global_state = s;
diff --git a/user-exec.c b/user-exec.c
index 71bd6c531c..fa7f1f1de9 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -448,6 +448,21 @@ int cpu_signal_handler(int host_signum, void *pinfo,
&uc->uc_sigmask, puc);
}
+#elif defined(__aarch64__)
+
+int cpu_signal_handler(int host_signum, void *pinfo,
+ void *puc)
+{
+ siginfo_t *info = pinfo;
+ struct ucontext *uc = puc;
+ uint64_t pc;
+ int is_write = 0; /* XXX how to determine? */
+
+ pc = uc->uc_mcontext.pc;
+ return handle_cpu_signal(pc, (uint64_t)info->si_addr,
+ is_write, &uc->uc_sigmask, puc);
+}
+
#elif defined(__mc68000)
int cpu_signal_handler(int host_signum, void *pinfo,
diff --git a/util/Makefile.objs b/util/Makefile.objs
index 4a1bd4ee3a..dc72ab0721 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -1,6 +1,6 @@
util-obj-y = osdep.o cutils.o unicode.o qemu-timer-common.o
util-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o event_notifier-win32.o
-util-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o event_notifier-posix.o
+util-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o event_notifier-posix.o qemu-openpty.o
util-obj-y += envlist.o path.o host-utils.o cache-utils.o module.o
util-obj-y += bitmap.o bitops.o hbitmap.o
util-obj-y += fifo8.o
diff --git a/util/cutils.c b/util/cutils.c
index a1658197cf..0116fcde74 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -107,6 +107,27 @@ int qemu_strnlen(const char *s, int max_len)
return i;
}
+char *qemu_strsep(char **input, const char *delim)
+{
+ char *result = *input;
+ if (result != NULL) {
+ char *p;
+
+ for (p = result; *p != '\0'; p++) {
+ if (strchr(delim, *p)) {
+ break;
+ }
+ }
+ if (*p == '\0') {
+ *input = NULL;
+ } else {
+ *p = '\0';
+ *input = p + 1;
+ }
+ }
+ return result;
+}
+
time_t mktimegm(struct tm *tm)
{
time_t t;
@@ -267,6 +288,10 @@ static int64_t suffix_mul(char suffix, int64_t unit)
return unit * unit * unit;
case STRTOSZ_DEFSUFFIX_TB:
return unit * unit * unit * unit;
+ case STRTOSZ_DEFSUFFIX_PB:
+ return unit * unit * unit * unit * unit;
+ case STRTOSZ_DEFSUFFIX_EB:
+ return unit * unit * unit * unit * unit * unit;
}
return -1;
}
diff --git a/util/qemu-openpty.c b/util/qemu-openpty.c
new file mode 100644
index 0000000000..4febfe9d72
--- /dev/null
+++ b/util/qemu-openpty.c
@@ -0,0 +1,135 @@
+/*
+ * qemu-openpty.c
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010 Red Hat, Inc.
+ *
+ * Wrapper function qemu_openpty() implementation.
+ *
+ * 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.
+ */
+
+/*
+ * This is not part of oslib-posix.c because this function
+ * uses openpty() which often in -lutil, and if we add this
+ * dependency to oslib-posix.o, every app will have to be
+ * linked with -lutil.
+ */
+
+#include "config-host.h"
+#include "qemu-common.h"
+
+#if defined(__GLIBC__)
+# include <pty.h>
+#elif defined CONFIG_BSD
+# include <termios.h>
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+# include <libutil.h>
+# else
+# include <util.h>
+# endif
+#elif defined CONFIG_SOLARIS
+# include <termios.h>
+# include <stropts.h>
+#endif
+
+#ifdef __sun__
+/* Once Solaris has openpty(), this is going to be removed. */
+static int openpty(int *amaster, int *aslave, char *name,
+ struct termios *termp, struct winsize *winp)
+{
+ const char *slave;
+ int mfd = -1, sfd = -1;
+
+ *amaster = *aslave = -1;
+
+ mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
+ if (mfd < 0)
+ goto err;
+
+ if (grantpt(mfd) == -1 || unlockpt(mfd) == -1)
+ goto err;
+
+ if ((slave = ptsname(mfd)) == NULL)
+ goto err;
+
+ if ((sfd = open(slave, O_RDONLY | O_NOCTTY)) == -1)
+ goto err;
+
+ if (ioctl(sfd, I_PUSH, "ptem") == -1 ||
+ (termp != NULL && tcgetattr(sfd, termp) < 0))
+ goto err;
+
+ if (amaster)
+ *amaster = mfd;
+ if (aslave)
+ *aslave = sfd;
+ if (winp)
+ ioctl(sfd, TIOCSWINSZ, winp);
+
+ return 0;
+
+err:
+ if (sfd != -1)
+ close(sfd);
+ close(mfd);
+ return -1;
+}
+
+static void cfmakeraw (struct termios *termios_p)
+{
+ termios_p->c_iflag &=
+ ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ termios_p->c_oflag &= ~OPOST;
+ termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ termios_p->c_cflag &= ~(CSIZE|PARENB);
+ termios_p->c_cflag |= CS8;
+
+ termios_p->c_cc[VMIN] = 0;
+ termios_p->c_cc[VTIME] = 0;
+}
+#endif
+
+int qemu_openpty_raw(int *aslave, char *pty_name)
+{
+ int amaster;
+ struct termios tty;
+#if defined(__OpenBSD__) || defined(__DragonFly__)
+ char pty_buf[PATH_MAX];
+#define q_ptsname(x) pty_buf
+#else
+ char *pty_buf = NULL;
+#define q_ptsname(x) ptsname(x)
+#endif
+
+ if (openpty(&amaster, aslave, pty_buf, NULL, NULL) < 0) {
+ return -1;
+ }
+
+ /* Set raw attributes on the pty. */
+ tcgetattr(*aslave, &tty);
+ cfmakeraw(&tty);
+ tcsetattr(*aslave, TCSAFLUSH, &tty);
+
+ if (pty_name) {
+ strcpy(pty_name, q_ptsname(amaster));
+ }
+
+ return amaster;
+}
diff --git a/vl.c b/vl.c
index 47ab45d37a..9f8fd6e377 100644
--- a/vl.c
+++ b/vl.c
@@ -610,6 +610,7 @@ static const RunStateTransition runstate_transitions_def[] = {
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_PAUSED },
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
+ { RUN_STATE_GUEST_PANICKED, RUN_STATE_DEBUG },
{ RUN_STATE_MAX, RUN_STATE_MAX },
};
@@ -3523,7 +3524,6 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_full_screen:
full_screen = 1;
break;
-#ifdef CONFIG_SDL
case QEMU_OPTION_no_frame:
no_frame = 1;
break;
@@ -3536,14 +3536,11 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_no_quit:
no_quit = 1;
break;
+#ifdef CONFIG_SDL
case QEMU_OPTION_sdl:
display_type = DT_SDL;
break;
#else
- case QEMU_OPTION_no_frame:
- case QEMU_OPTION_alt_grab:
- case QEMU_OPTION_ctrl_grab:
- case QEMU_OPTION_no_quit:
case QEMU_OPTION_sdl:
fprintf(stderr, "SDL support is disabled\n");
exit(1);
@@ -4084,6 +4081,15 @@ int main(int argc, char **argv, char **envp)
#endif
}
+ if ((no_frame || alt_grab || ctrl_grab) && display_type != DT_SDL) {
+ fprintf(stderr, "-no-frame, -alt-grab and -ctrl-grab are only valid "
+ "for SDL, ignoring option\n");
+ }
+ if (no_quit && (display_type != DT_GTK && display_type != DT_SDL)) {
+ fprintf(stderr, "-no-quit is only valid for GTK and SDL, "
+ "ignoring option\n");
+ }
+
#if defined(CONFIG_GTK)
if (display_type == DT_GTK) {
early_gtk_display_init();
@@ -4347,7 +4353,7 @@ int main(int argc, char **argv, char **envp)
#endif
#if defined(CONFIG_GTK)
case DT_GTK:
- gtk_display_init(ds);
+ gtk_display_init(ds, full_screen);
break;
#endif
default:
diff --git a/xen-all.c b/xen-all.c
index bc105f1627..1a1d7bbdcc 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -389,7 +389,7 @@ static int xen_remove_from_physmap(XenIOState *state,
if (state->log_for_dirtybit == physmap) {
state->log_for_dirtybit = NULL;
}
- free(physmap);
+ g_free(physmap);
return 0;
}
@@ -1030,7 +1030,7 @@ static void xen_read_physmap(XenIOState *state)
xen_domid, entries[i]);
value = xs_read(state->xenstore, 0, path, &len);
if (value == NULL) {
- free(physmap);
+ g_free(physmap);
continue;
}
physmap->start_addr = strtoull(value, NULL, 16);
@@ -1041,7 +1041,7 @@ static void xen_read_physmap(XenIOState *state)
xen_domid, entries[i]);
value = xs_read(state->xenstore, 0, path, &len);
if (value == NULL) {
- free(physmap);
+ g_free(physmap);
continue;
}
physmap->size = strtoull(value, NULL, 16);
@@ -1069,12 +1069,14 @@ int xen_hvm_init(void)
state->xce_handle = xen_xc_evtchn_open(NULL, 0);
if (state->xce_handle == XC_HANDLER_INITIAL_VALUE) {
perror("xen: event channel open");
+ g_free(state);
return -errno;
}
state->xenstore = xs_daemon_open();
if (state->xenstore == NULL) {
perror("xen: xenstore open");
+ g_free(state);
return -errno;
}