Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc,vhost,test fixes
Minor bugfixes all over the place.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Fri 18 Jul 2014 00:43:04 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>"
* remotes/mst/tags/for_upstream:
vhost-user: minor cleanups
qtest: Adapt vhost-user-test to latest vhost-user changes
vhost-user: Fix VHOST_SET_MEM_TABLE processing
qtest: fix vhost-user-test compilation with old GLib
fix typo: apci -> acpi
pc_piix: Reuse pc_compat_1_2() for pc-0.1[0123]
pc: fix qemu exiting with error when -m X < 128 with old machines types
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/MAINTAINERS b/MAINTAINERS
index e7dc907..906f252 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -563,6 +563,7 @@
-------
IDE
M: Kevin Wolf <kwolf@redhat.com>
+M: Stefan Hajnoczi <stefanha@redhat.com>
S: Odd Fixes
F: include/hw/ide.h
F: hw/ide/
diff --git a/Makefile b/Makefile
index 1eea0c4..d6b9dc1 100644
--- a/Makefile
+++ b/Makefile
@@ -344,7 +344,8 @@
s390-zipl.rom \
s390-ccw.img \
spapr-rtas.bin slof.bin \
-palcode-clipper
+palcode-clipper \
+u-boot.e500
else
BLOBS=
endif
diff --git a/VERSION b/VERSION
index 36831c3..0a7e4e5 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.90
+2.0.92
diff --git a/aio-posix.c b/aio-posix.c
index f921d4f..2eada2e 100644
--- a/aio-posix.c
+++ b/aio-posix.c
@@ -125,7 +125,7 @@
bool progress = false;
/*
- * We have to walk very carefully in case qemu_aio_set_fd_handler is
+ * We have to walk very carefully in case aio_set_fd_handler is
* called while we're walking.
*/
node = QLIST_FIRST(&ctx->aio_handlers);
@@ -175,27 +175,56 @@
bool aio_poll(AioContext *ctx, bool blocking)
{
AioHandler *node;
+ bool was_dispatching;
int ret;
bool progress;
+ was_dispatching = ctx->dispatching;
progress = false;
+ /* aio_notify can avoid the expensive event_notifier_set if
+ * everything (file descriptors, bottom halves, timers) will
+ * be re-evaluated before the next blocking poll(). This happens
+ * in two cases:
+ *
+ * 1) when aio_poll is called with blocking == false
+ *
+ * 2) when we are called after poll(). If we are called before
+ * poll(), bottom halves will not be re-evaluated and we need
+ * aio_notify() if blocking == true.
+ *
+ * The first aio_dispatch() only does something when AioContext is
+ * running as a GSource, and in that case aio_poll is used only
+ * with blocking == false, so this optimization is already quite
+ * effective. However, the code is ugly and should be restructured
+ * to have a single aio_dispatch() call. To do this, we need to
+ * reorganize aio_poll into a prepare/poll/dispatch model like
+ * glib's.
+ *
+ * If we're in a nested event loop, ctx->dispatching might be true.
+ * In that case we can restore it just before returning, but we
+ * have to clear it now.
+ */
+ aio_set_dispatching(ctx, !blocking);
+
/*
* If there are callbacks left that have been queued, we need to call them.
* Do not call select in this case, because it is possible that the caller
- * does not need a complete flush (as is the case for qemu_aio_wait loops).
+ * does not need a complete flush (as is the case for aio_poll loops).
*/
if (aio_bh_poll(ctx)) {
blocking = false;
progress = true;
}
+ /* Re-evaluate condition (1) above. */
+ aio_set_dispatching(ctx, !blocking);
if (aio_dispatch(ctx)) {
progress = true;
}
if (progress && !blocking) {
- return true;
+ goto out;
}
ctx->walking_handlers++;
@@ -234,9 +263,12 @@
}
/* Run dispatch even if there were no readable fds to run timers */
+ aio_set_dispatching(ctx, true);
if (aio_dispatch(ctx)) {
progress = true;
}
+out:
+ aio_set_dispatching(ctx, was_dispatching);
return progress;
}
diff --git a/aio-win32.c b/aio-win32.c
index 23f4e5b..c12f61e 100644
--- a/aio-win32.c
+++ b/aio-win32.c
@@ -102,7 +102,7 @@
/*
* If there are callbacks left that have been queued, we need to call then.
* Do not call select in this case, because it is possible that the caller
- * does not need a complete flush (as is the case for qemu_aio_wait loops).
+ * does not need a complete flush (as is the case for aio_poll loops).
*/
if (aio_bh_poll(ctx)) {
blocking = false;
@@ -115,7 +115,7 @@
/*
* Then dispatch any pending callbacks from the GSource.
*
- * We have to walk very carefully in case qemu_aio_set_fd_handler is
+ * We have to walk very carefully in case aio_set_fd_handler is
* called while we're walking.
*/
node = QLIST_FIRST(&ctx->aio_handlers);
@@ -177,7 +177,7 @@
blocking = false;
/* we have to walk very carefully in case
- * qemu_aio_set_fd_handler is called while we're walking */
+ * aio_set_fd_handler is called while we're walking */
node = QLIST_FIRST(&ctx->aio_handlers);
while (node) {
AioHandler *tmp;
diff --git a/async.c b/async.c
index 5b6fe6b..34af0b2 100644
--- a/async.c
+++ b/async.c
@@ -26,6 +26,7 @@
#include "block/aio.h"
#include "block/thread-pool.h"
#include "qemu/main-loop.h"
+#include "qemu/atomic.h"
/***********************************************************/
/* bottom halves (can be seen as timers which expire ASAP) */
@@ -247,9 +248,25 @@
return ctx->thread_pool;
}
+void aio_set_dispatching(AioContext *ctx, bool dispatching)
+{
+ ctx->dispatching = dispatching;
+ if (!dispatching) {
+ /* Write ctx->dispatching before reading e.g. bh->scheduled.
+ * Optimization: this is only needed when we're entering the "unsafe"
+ * phase where other threads must call event_notifier_set.
+ */
+ smp_mb();
+ }
+}
+
void aio_notify(AioContext *ctx)
{
- event_notifier_set(&ctx->notifier);
+ /* Write e.g. bh->scheduled before reading ctx->dispatching. */
+ smp_mb();
+ if (!ctx->dispatching) {
+ event_notifier_set(&ctx->notifier);
+ }
}
static void aio_timerlist_notify(void *opaque)
diff --git a/block.c b/block.c
index f80e2b2..3e252a2 100644
--- a/block.c
+++ b/block.c
@@ -471,7 +471,7 @@
co = qemu_coroutine_create(bdrv_create_co_entry);
qemu_coroutine_enter(co, &cco);
while (cco.ret == NOT_DONE) {
- qemu_aio_wait();
+ aio_poll(qemu_get_aio_context(), true);
}
}
@@ -1905,6 +1905,7 @@
bool bs_busy;
aio_context_acquire(aio_context);
+ bdrv_flush_io_queue(bs);
bdrv_start_throttled_reqs(bs);
bs_busy = bdrv_requests_pending(bs);
bs_busy |= aio_poll(aio_context, bs_busy);
@@ -3009,6 +3010,7 @@
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
+ assert(!qiov || bytes == qiov->size);
/* Handle Copy on Read and associated serialisation */
if (flags & BDRV_REQ_COPY_ON_READ) {
@@ -3053,8 +3055,20 @@
max_nb_sectors = ROUND_UP(MAX(0, total_sectors - sector_num),
align >> BDRV_SECTOR_BITS);
if (max_nb_sectors > 0) {
- ret = drv->bdrv_co_readv(bs, sector_num,
- MIN(nb_sectors, max_nb_sectors), qiov);
+ QEMUIOVector local_qiov;
+ size_t local_sectors;
+
+ max_nb_sectors = MIN(max_nb_sectors, SIZE_MAX / BDRV_SECTOR_BITS);
+ local_sectors = MIN(max_nb_sectors, nb_sectors);
+
+ qemu_iovec_init(&local_qiov, qiov->niov);
+ qemu_iovec_concat(&local_qiov, qiov, 0,
+ local_sectors * BDRV_SECTOR_SIZE);
+
+ ret = drv->bdrv_co_readv(bs, sector_num, local_sectors,
+ &local_qiov);
+
+ qemu_iovec_destroy(&local_qiov);
} else {
ret = 0;
}
@@ -3266,6 +3280,7 @@
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
+ assert(!qiov || bytes == qiov->size);
waited = wait_serialising_requests(req);
assert(!waited || !req->serialising);
@@ -4039,7 +4054,7 @@
if (ret < 0) {
return ret;
}
- return (ret & BDRV_BLOCK_ALLOCATED);
+ return !!(ret & BDRV_BLOCK_ALLOCATED);
}
/*
@@ -5782,3 +5797,33 @@
return to_replace_bs;
}
+
+void bdrv_io_plug(BlockDriverState *bs)
+{
+ BlockDriver *drv = bs->drv;
+ if (drv && drv->bdrv_io_plug) {
+ drv->bdrv_io_plug(bs);
+ } else if (bs->file) {
+ bdrv_io_plug(bs->file);
+ }
+}
+
+void bdrv_io_unplug(BlockDriverState *bs)
+{
+ BlockDriver *drv = bs->drv;
+ if (drv && drv->bdrv_io_unplug) {
+ drv->bdrv_io_unplug(bs);
+ } else if (bs->file) {
+ bdrv_io_unplug(bs->file);
+ }
+}
+
+void bdrv_flush_io_queue(BlockDriverState *bs)
+{
+ BlockDriver *drv = bs->drv;
+ if (drv && drv->bdrv_flush_io_queue) {
+ drv->bdrv_flush_io_queue(bs);
+ } else if (bs->file) {
+ bdrv_flush_io_queue(bs->file);
+ }
+}
diff --git a/block/backup.c b/block/backup.c
index 7978ae2..d0b0225 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -307,7 +307,7 @@
BACKUP_SECTORS_PER_CLUSTER - i, &n);
i += n;
- if (alloced == 1) {
+ if (alloced == 1 || n == 0) {
break;
}
}
diff --git a/block/linux-aio.c b/block/linux-aio.c
index f0a2c08..7ac7e8c 100644
--- a/block/linux-aio.c
+++ b/block/linux-aio.c
@@ -25,6 +25,8 @@
*/
#define MAX_EVENTS 128
+#define MAX_QUEUED_IO 128
+
struct qemu_laiocb {
BlockDriverAIOCB common;
struct qemu_laio_state *ctx;
@@ -36,9 +38,19 @@
QLIST_ENTRY(qemu_laiocb) node;
};
+typedef struct {
+ struct iocb *iocbs[MAX_QUEUED_IO];
+ int plugged;
+ unsigned int size;
+ unsigned int idx;
+} LaioQueue;
+
struct qemu_laio_state {
io_context_t ctx;
EventNotifier e;
+
+ /* io queue for submit at batch */
+ LaioQueue io_q;
};
static inline ssize_t io_event_ret(struct io_event *ev)
@@ -135,6 +147,79 @@
.cancel = laio_cancel,
};
+static void ioq_init(LaioQueue *io_q)
+{
+ io_q->size = MAX_QUEUED_IO;
+ io_q->idx = 0;
+ io_q->plugged = 0;
+}
+
+static int ioq_submit(struct qemu_laio_state *s)
+{
+ int ret, i = 0;
+ int len = s->io_q.idx;
+
+ do {
+ ret = io_submit(s->ctx, len, s->io_q.iocbs);
+ } while (i++ < 3 && ret == -EAGAIN);
+
+ /* empty io queue */
+ s->io_q.idx = 0;
+
+ if (ret < 0) {
+ i = 0;
+ } else {
+ i = ret;
+ }
+
+ for (; i < len; i++) {
+ struct qemu_laiocb *laiocb =
+ container_of(s->io_q.iocbs[i], struct qemu_laiocb, iocb);
+
+ laiocb->ret = (ret < 0) ? ret : -EIO;
+ qemu_laio_process_completion(s, laiocb);
+ }
+ return ret;
+}
+
+static void ioq_enqueue(struct qemu_laio_state *s, struct iocb *iocb)
+{
+ unsigned int idx = s->io_q.idx;
+
+ s->io_q.iocbs[idx++] = iocb;
+ s->io_q.idx = idx;
+
+ /* submit immediately if queue is full */
+ if (idx == s->io_q.size) {
+ ioq_submit(s);
+ }
+}
+
+void laio_io_plug(BlockDriverState *bs, void *aio_ctx)
+{
+ struct qemu_laio_state *s = aio_ctx;
+
+ s->io_q.plugged++;
+}
+
+int laio_io_unplug(BlockDriverState *bs, void *aio_ctx, bool unplug)
+{
+ struct qemu_laio_state *s = aio_ctx;
+ int ret = 0;
+
+ assert(s->io_q.plugged > 0 || !unplug);
+
+ if (unplug && --s->io_q.plugged > 0) {
+ return 0;
+ }
+
+ if (s->io_q.idx > 0) {
+ ret = ioq_submit(s);
+ }
+
+ return ret;
+}
+
BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type)
@@ -168,8 +253,13 @@
}
io_set_eventfd(&laiocb->iocb, event_notifier_get_fd(&s->e));
- if (io_submit(s->ctx, 1, &iocbs) < 0)
- goto out_free_aiocb;
+ if (!s->io_q.plugged) {
+ if (io_submit(s->ctx, 1, &iocbs) < 0) {
+ goto out_free_aiocb;
+ }
+ } else {
+ ioq_enqueue(s, iocbs);
+ }
return &laiocb->common;
out_free_aiocb:
@@ -204,6 +294,8 @@
goto out_close_efd;
}
+ ioq_init(&s->io_q);
+
return s;
out_close_efd:
@@ -218,5 +310,10 @@
struct qemu_laio_state *s = s_;
event_notifier_cleanup(&s->e);
+
+ if (io_destroy(s->ctx) != 0) {
+ fprintf(stderr, "%s: destroy AIO context %p failed\n",
+ __func__, &s->ctx);
+ }
g_free(s);
}
diff --git a/block/mirror.c b/block/mirror.c
index 6c3ee70..c7a655f 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -265,9 +265,11 @@
next_sector = sector_num;
while (nb_chunks-- > 0) {
MirrorBuffer *buf = QSIMPLEQ_FIRST(&s->buf_free);
+ size_t remaining = (nb_sectors * BDRV_SECTOR_SIZE) - op->qiov.size;
+
QSIMPLEQ_REMOVE_HEAD(&s->buf_free, next);
s->buf_free_count--;
- qemu_iovec_add(&op->qiov, buf, s->granularity);
+ qemu_iovec_add(&op->qiov, buf, MIN(s->granularity, remaining));
/* Advance the HBitmapIter in parallel, so that we do not examine
* the same sector twice.
diff --git a/block/qcow2.c b/block/qcow2.c
index 67e55c9..b0faa69 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1020,11 +1020,20 @@
n1 = qcow2_backing_read1(bs->backing_hd, &hd_qiov,
sector_num, cur_nr_sectors);
if (n1 > 0) {
+ QEMUIOVector local_qiov;
+
+ qemu_iovec_init(&local_qiov, hd_qiov.niov);
+ qemu_iovec_concat(&local_qiov, &hd_qiov, 0,
+ n1 * BDRV_SECTOR_SIZE);
+
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
qemu_co_mutex_unlock(&s->lock);
ret = bdrv_co_readv(bs->backing_hd, sector_num,
- n1, &hd_qiov);
+ n1, &local_qiov);
qemu_co_mutex_lock(&s->lock);
+
+ qemu_iovec_destroy(&local_qiov);
+
if (ret < 0) {
goto fail;
}
diff --git a/block/qed.c b/block/qed.c
index b69374b..cd4872b 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -761,17 +761,19 @@
/**
* Read from the backing file or zero-fill if no backing file
*
- * @s: QED state
- * @pos: Byte position in device
- * @qiov: Destination I/O vector
- * @cb: Completion function
- * @opaque: User data for completion function
+ * @s: QED state
+ * @pos: Byte position in device
+ * @qiov: Destination I/O vector
+ * @backing_qiov: Possibly shortened copy of qiov, to be allocated here
+ * @cb: Completion function
+ * @opaque: User data for completion function
*
* This function reads qiov->size bytes starting at pos from the backing file.
* If there is no backing file then zeroes are read.
*/
static void qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
QEMUIOVector *qiov,
+ QEMUIOVector **backing_qiov,
BlockDriverCompletionFunc *cb, void *opaque)
{
uint64_t backing_length = 0;
@@ -804,15 +806,21 @@
/* If the read straddles the end of the backing file, shorten it */
size = MIN((uint64_t)backing_length - pos, qiov->size);
+ assert(*backing_qiov == NULL);
+ *backing_qiov = g_new(QEMUIOVector, 1);
+ qemu_iovec_init(*backing_qiov, qiov->niov);
+ qemu_iovec_concat(*backing_qiov, qiov, 0, size);
+
BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO);
bdrv_aio_readv(s->bs->backing_hd, pos / BDRV_SECTOR_SIZE,
- qiov, size / BDRV_SECTOR_SIZE, cb, opaque);
+ *backing_qiov, size / BDRV_SECTOR_SIZE, cb, opaque);
}
typedef struct {
GenericCB gencb;
BDRVQEDState *s;
QEMUIOVector qiov;
+ QEMUIOVector *backing_qiov;
struct iovec iov;
uint64_t offset;
} CopyFromBackingFileCB;
@@ -829,6 +837,12 @@
CopyFromBackingFileCB *copy_cb = opaque;
BDRVQEDState *s = copy_cb->s;
+ if (copy_cb->backing_qiov) {
+ qemu_iovec_destroy(copy_cb->backing_qiov);
+ g_free(copy_cb->backing_qiov);
+ copy_cb->backing_qiov = NULL;
+ }
+
if (ret) {
qed_copy_from_backing_file_cb(copy_cb, ret);
return;
@@ -866,11 +880,12 @@
copy_cb = gencb_alloc(sizeof(*copy_cb), cb, opaque);
copy_cb->s = s;
copy_cb->offset = offset;
+ copy_cb->backing_qiov = NULL;
copy_cb->iov.iov_base = qemu_blockalign(s->bs, len);
copy_cb->iov.iov_len = len;
qemu_iovec_init_external(©_cb->qiov, ©_cb->iov, 1);
- qed_read_backing_file(s, pos, ©_cb->qiov,
+ qed_read_backing_file(s, pos, ©_cb->qiov, ©_cb->backing_qiov,
qed_copy_from_backing_file_write, copy_cb);
}
@@ -1313,7 +1328,7 @@
return;
} else if (ret != QED_CLUSTER_FOUND) {
qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov,
- qed_aio_next_io, acb);
+ &acb->backing_qiov, qed_aio_next_io, acb);
return;
}
@@ -1339,6 +1354,12 @@
trace_qed_aio_next_io(s, acb, ret, acb->cur_pos + acb->cur_qiov.size);
+ if (acb->backing_qiov) {
+ qemu_iovec_destroy(acb->backing_qiov);
+ g_free(acb->backing_qiov);
+ acb->backing_qiov = NULL;
+ }
+
/* Handle I/O error */
if (ret) {
qed_aio_complete(acb, ret);
@@ -1378,6 +1399,7 @@
acb->qiov_offset = 0;
acb->cur_pos = (uint64_t)sector_num * BDRV_SECTOR_SIZE;
acb->end_pos = acb->cur_pos + nb_sectors * BDRV_SECTOR_SIZE;
+ acb->backing_qiov = NULL;
acb->request.l2_table = NULL;
qemu_iovec_init(&acb->cur_qiov, qiov->niov);
diff --git a/block/qed.h b/block/qed.h
index b024751..2b0e724 100644
--- a/block/qed.h
+++ b/block/qed.h
@@ -142,6 +142,7 @@
/* Current cluster scatter-gather list */
QEMUIOVector cur_qiov;
+ QEMUIOVector *backing_qiov;
uint64_t cur_pos; /* position on block device, in bytes */
uint64_t cur_cluster; /* cluster offset in image file */
unsigned int cur_nclusters; /* number of clusters being accessed */
diff --git a/block/raw-aio.h b/block/raw-aio.h
index 8cf084e..e18c975 100644
--- a/block/raw-aio.h
+++ b/block/raw-aio.h
@@ -40,6 +40,8 @@
BlockDriverCompletionFunc *cb, void *opaque, int type);
void laio_detach_aio_context(void *s, AioContext *old_context);
void laio_attach_aio_context(void *s, AioContext *new_context);
+void laio_io_plug(BlockDriverState *bs, void *aio_ctx);
+int laio_io_unplug(BlockDriverState *bs, void *aio_ctx, bool unplug);
#endif
#ifdef _WIN32
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 825a0c8..2bcc73d 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -790,6 +790,7 @@
memcpy(p, aiocb->aio_iov[i].iov_base, aiocb->aio_iov[i].iov_len);
p += aiocb->aio_iov[i].iov_len;
}
+ assert(p - buf == aiocb->aio_nbytes);
}
nbytes = handle_aiocb_rw_linear(aiocb, buf);
@@ -804,9 +805,11 @@
copy = aiocb->aio_iov[i].iov_len;
}
memcpy(aiocb->aio_iov[i].iov_base, p, copy);
+ assert(count >= copy);
p += copy;
count -= copy;
}
+ assert(count == 0);
}
qemu_vfree(buf);
@@ -993,12 +996,14 @@
acb->aio_type = type;
acb->aio_fildes = fd;
+ acb->aio_nbytes = nb_sectors * BDRV_SECTOR_SIZE;
+ acb->aio_offset = sector_num * BDRV_SECTOR_SIZE;
+
if (qiov) {
acb->aio_iov = qiov->iov;
acb->aio_niov = qiov->niov;
+ assert(qiov->size == acb->aio_nbytes);
}
- acb->aio_nbytes = nb_sectors * 512;
- acb->aio_offset = sector_num * 512;
trace_paio_submit_co(sector_num, nb_sectors, type);
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
@@ -1016,12 +1021,14 @@
acb->aio_type = type;
acb->aio_fildes = fd;
+ acb->aio_nbytes = nb_sectors * BDRV_SECTOR_SIZE;
+ acb->aio_offset = sector_num * BDRV_SECTOR_SIZE;
+
if (qiov) {
acb->aio_iov = qiov->iov;
acb->aio_niov = qiov->niov;
+ assert(qiov->size == acb->aio_nbytes);
}
- acb->aio_nbytes = nb_sectors * 512;
- acb->aio_offset = sector_num * 512;
trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
@@ -1057,6 +1064,36 @@
cb, opaque, type);
}
+static void raw_aio_plug(BlockDriverState *bs)
+{
+#ifdef CONFIG_LINUX_AIO
+ BDRVRawState *s = bs->opaque;
+ if (s->use_aio) {
+ laio_io_plug(bs, s->aio_ctx);
+ }
+#endif
+}
+
+static void raw_aio_unplug(BlockDriverState *bs)
+{
+#ifdef CONFIG_LINUX_AIO
+ BDRVRawState *s = bs->opaque;
+ if (s->use_aio) {
+ laio_io_unplug(bs, s->aio_ctx, true);
+ }
+#endif
+}
+
+static void raw_aio_flush_io_queue(BlockDriverState *bs)
+{
+#ifdef CONFIG_LINUX_AIO
+ BDRVRawState *s = bs->opaque;
+ if (s->use_aio) {
+ laio_io_unplug(bs, s->aio_ctx, false);
+ }
+#endif
+}
+
static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
@@ -1133,12 +1170,12 @@
struct stat st;
if (fstat(fd, &st))
- return -1;
+ return -errno;
if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
struct disklabel dl;
if (ioctl(fd, DIOCGDINFO, &dl))
- return -1;
+ return -errno;
return (uint64_t)dl.d_secsize *
dl.d_partitions[DISKPART(st.st_rdev)].p_size;
} else
@@ -1152,7 +1189,7 @@
struct stat st;
if (fstat(fd, &st))
- return -1;
+ return -errno;
if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
struct dkwedge_info dkw;
@@ -1162,7 +1199,7 @@
struct disklabel dl;
if (ioctl(fd, DIOCGDINFO, &dl))
- return -1;
+ return -errno;
return (uint64_t)dl.d_secsize *
dl.d_partitions[DISKPART(st.st_rdev)].p_size;
}
@@ -1175,6 +1212,7 @@
BDRVRawState *s = bs->opaque;
struct dk_minfo minfo;
int ret;
+ int64_t size;
ret = fd_open(bs);
if (ret < 0) {
@@ -1193,7 +1231,11 @@
* There are reports that lseek on some devices fails, but
* irc discussion said that contingency on contingency was overkill.
*/
- return lseek(s->fd, 0, SEEK_END);
+ size = lseek(s->fd, 0, SEEK_END);
+ if (size < 0) {
+ return -errno;
+ }
+ return size;
}
#elif defined(CONFIG_BSD)
static int64_t raw_getlength(BlockDriverState *bs)
@@ -1231,6 +1273,9 @@
size = LLONG_MAX;
#else
size = lseek(fd, 0LL, SEEK_END);
+ if (size < 0) {
+ return -errno;
+ }
#endif
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
switch(s->type) {
@@ -1247,6 +1292,9 @@
#endif
} else {
size = lseek(fd, 0, SEEK_END);
+ if (size < 0) {
+ return -errno;
+ }
}
return size;
}
@@ -1255,13 +1303,18 @@
{
BDRVRawState *s = bs->opaque;
int ret;
+ int64_t size;
ret = fd_open(bs);
if (ret < 0) {
return ret;
}
- return lseek(s->fd, 0, SEEK_END);
+ size = lseek(s->fd, 0, SEEK_END);
+ if (size < 0) {
+ return -errno;
+ }
+ return size;
}
#endif
@@ -1528,6 +1581,9 @@
.bdrv_aio_flush = raw_aio_flush,
.bdrv_aio_discard = raw_aio_discard,
.bdrv_refresh_limits = raw_refresh_limits,
+ .bdrv_io_plug = raw_aio_plug,
+ .bdrv_io_unplug = raw_aio_unplug,
+ .bdrv_flush_io_queue = raw_aio_flush_io_queue,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
@@ -1927,6 +1983,9 @@
.bdrv_aio_flush = raw_aio_flush,
.bdrv_aio_discard = hdev_aio_discard,
.bdrv_refresh_limits = raw_refresh_limits,
+ .bdrv_io_plug = raw_aio_plug,
+ .bdrv_io_unplug = raw_aio_unplug,
+ .bdrv_flush_io_queue = raw_aio_flush_io_queue,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
@@ -2072,6 +2131,9 @@
.bdrv_aio_writev = raw_aio_writev,
.bdrv_aio_flush = raw_aio_flush,
.bdrv_refresh_limits = raw_refresh_limits,
+ .bdrv_io_plug = raw_aio_plug,
+ .bdrv_io_unplug = raw_aio_unplug,
+ .bdrv_flush_io_queue = raw_aio_flush_io_queue,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
@@ -2200,6 +2262,9 @@
.bdrv_aio_writev = raw_aio_writev,
.bdrv_aio_flush = raw_aio_flush,
.bdrv_refresh_limits = raw_refresh_limits,
+ .bdrv_io_plug = raw_aio_plug,
+ .bdrv_io_unplug = raw_aio_unplug,
+ .bdrv_flush_io_queue = raw_aio_flush_io_queue,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
@@ -2334,6 +2399,9 @@
.bdrv_aio_writev = raw_aio_writev,
.bdrv_aio_flush = raw_aio_flush,
.bdrv_refresh_limits = raw_refresh_limits,
+ .bdrv_io_plug = raw_aio_plug,
+ .bdrv_io_unplug = raw_aio_unplug,
+ .bdrv_flush_io_queue = raw_aio_flush_io_queue,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
diff --git a/blockjob.c b/blockjob.c
index 67a64ea..ca0b4e2 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -187,7 +187,7 @@
job->opaque = &data;
block_job_cancel(job);
while (data.ret == -EINPROGRESS) {
- qemu_aio_wait();
+ aio_poll(bdrv_get_aio_context(bs), true);
}
return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret;
}
diff --git a/configure b/configure
index 7dd43fd..f7685b5 100755
--- a/configure
+++ b/configure
@@ -1489,8 +1489,9 @@
fi
done
-if test "$stack_protector" != "no" ; then
+if test "$stack_protector" != "no"; then
gcc_flags="-fstack-protector-strong -fstack-protector-all"
+ sp_on=0
for flag in $gcc_flags; do
# We need to check both a compile and a link, since some compiler
# setups fail only on a .c->.o compile and some only at link time
@@ -1498,9 +1499,15 @@
compile_prog "-Werror $flag" ""; then
QEMU_CFLAGS="$QEMU_CFLAGS $flag"
LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,$flag"
+ sp_on=1
break
fi
done
+ if test "$stack_protector" = yes; then
+ if test $sp_on = 0; then
+ error_exit "Stack protector not supported"
+ fi
+ fi
fi
# Workaround for http://gcc.gnu.org/PR55489. Happens with -fPIE/-fPIC and
diff --git a/disas/libvixl/Makefile.objs b/disas/libvixl/Makefile.objs
index 0adb3ce..17e6565 100644
--- a/disas/libvixl/Makefile.objs
+++ b/disas/libvixl/Makefile.objs
@@ -3,6 +3,6 @@
a64/decoder-a64.o \
a64/disasm-a64.o
-$(addprefix $(obj)/,$(libvixl_OBJS)): QEMU_CFLAGS += -I$(SRC_PATH)/disas/libvixl
+$(addprefix $(obj)/,$(libvixl_OBJS)): QEMU_CFLAGS := -I$(SRC_PATH)/disas/libvixl $(QEMU_CFLAGS)
common-obj-$(CONFIG_ARM_A64_DIS) += $(libvixl_OBJS)
diff --git a/dma-helpers.c b/dma-helpers.c
index 53cbe92..499b52b 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -170,6 +170,10 @@
return;
}
+ if (dbs->iov.size & ~BDRV_SECTOR_MASK) {
+ qemu_iovec_discard_back(&dbs->iov, dbs->iov.size & ~BDRV_SECTOR_MASK);
+ }
+
dbs->acb = dbs->io_func(dbs->bs, dbs->sector_num, &dbs->iov,
dbs->iov.size / 512, dma_bdrv_cb, dbs);
assert(dbs->acb);
diff --git a/docs/aio_notify.promela b/docs/aio_notify.promela
new file mode 100644
index 0000000..ad3f6f0
--- /dev/null
+++ b/docs/aio_notify.promela
@@ -0,0 +1,104 @@
+/*
+ * This model describes the interaction between aio_set_dispatching()
+ * and aio_notify().
+ *
+ * Author: Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This file is in the public domain. If you really want a license,
+ * the WTFPL will do.
+ *
+ * To simulate it:
+ * spin -p docs/aio_notify.promela
+ *
+ * To verify it:
+ * spin -a docs/aio_notify.promela
+ * gcc -O2 pan.c
+ * ./a.out -a
+ */
+
+#define MAX 4
+#define LAST (1 << (MAX - 1))
+#define FINAL ((LAST << 1) - 1)
+
+bool dispatching;
+bool event;
+
+int req, done;
+
+active proctype waiter()
+{
+ int fetch, blocking;
+
+ do
+ :: done != FINAL -> {
+ // Computing "blocking" is separate from execution of the
+ // "bottom half"
+ blocking = (req == 0);
+
+ // This is our "bottom half"
+ atomic { fetch = req; req = 0; }
+ done = done | fetch;
+
+ // Wait for a nudge from the other side
+ do
+ :: event == 1 -> { event = 0; break; }
+ :: !blocking -> break;
+ od;
+
+ dispatching = 1;
+
+ // If you are simulating this model, you may want to add
+ // something like this here:
+ //
+ // int foo; foo++; foo++; foo++;
+ //
+ // This only wastes some time and makes it more likely
+ // that the notifier process hits the "fast path".
+
+ dispatching = 0;
+ }
+ :: else -> break;
+ od
+}
+
+active proctype notifier()
+{
+ int next = 1;
+ int sets = 0;
+
+ do
+ :: next <= LAST -> {
+ // generate a request
+ req = req | next;
+ next = next << 1;
+
+ // aio_notify
+ if
+ :: dispatching == 0 -> sets++; event = 1;
+ :: else -> skip;
+ fi;
+
+ // Test both synchronous and asynchronous delivery
+ if
+ :: 1 -> do
+ :: req == 0 -> break;
+ od;
+ :: 1 -> skip;
+ fi;
+ }
+ :: else -> break;
+ od;
+ printf("Skipped %d event_notifier_set\n", MAX - sets);
+}
+
+#define p (done == FINAL)
+
+never {
+ do
+ :: 1 // after an arbitrarily long prefix
+ :: p -> break // p becomes true
+ od;
+ do
+ :: !p -> accept: break // it then must remains true forever after
+ od
+}
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 3d83e6c..a88732c 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -84,6 +84,7 @@
};
static hwaddr motherboard_legacy_map[] = {
+ [VE_NORFLASHALIAS] = 0,
/* CS7: 0x10000000 .. 0x10020000 */
[VE_SYSREGS] = 0x10000000,
[VE_SP810] = 0x10001000,
@@ -114,7 +115,6 @@
[VE_VIDEORAM] = 0x4c000000,
[VE_ETHERNET] = 0x4e000000,
[VE_USB] = 0x4f000000,
- [VE_NORFLASHALIAS] = -1, /* not present */
};
static hwaddr motherboard_aseries_map[] = {
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 4c5ba18..d6ba65c 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -34,6 +34,7 @@
VirtIODevice *vdev;
Vring vring; /* virtqueue vring */
EventNotifier *guest_notifier; /* irq */
+ QEMUBH *bh; /* bh for guest notification */
/* Note that these EventNotifiers are assigned by value. This is
* fine as long as you do not call event_notifier_cleanup on them
@@ -61,46 +62,60 @@
event_notifier_set(s->guest_notifier);
}
+static void notify_guest_bh(void *opaque)
+{
+ VirtIOBlockDataPlane *s = opaque;
+
+ notify_guest(s);
+}
+
static void complete_request_vring(VirtIOBlockReq *req, unsigned char status)
{
+ VirtIOBlockDataPlane *s = req->dev->dataplane;
stb_p(&req->in->status, status);
- vring_push(&req->dev->dataplane->vring, req->elem,
+ vring_push(&req->dev->dataplane->vring, &req->elem,
req->qiov.size + sizeof(*req->in));
- notify_guest(req->dev->dataplane);
- g_slice_free(VirtIOBlockReq, req);
+
+ /* Suppress notification to guest by BH and its scheduled
+ * flag because requests are completed as a batch after io
+ * plug & unplug is introduced, and the BH can still be
+ * executed in dataplane aio context even after it is
+ * stopped, so needn't worry about notification loss with BH.
+ */
+ qemu_bh_schedule(s->bh);
}
static void handle_notify(EventNotifier *e)
{
VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
host_notifier);
-
- VirtQueueElement *elem;
- VirtIOBlockReq *req;
- int ret;
- MultiReqBuffer mrb = {
- .num_writes = 0,
- };
+ VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
event_notifier_test_and_clear(&s->host_notifier);
+ bdrv_io_plug(s->blk->conf.bs);
for (;;) {
+ MultiReqBuffer mrb = {
+ .num_writes = 0,
+ };
+ int ret;
+
/* Disable guest->host notifies to avoid unnecessary vmexits */
vring_disable_notification(s->vdev, &s->vring);
for (;;) {
- ret = vring_pop(s->vdev, &s->vring, &elem);
+ VirtIOBlockReq *req = virtio_blk_alloc_request(vblk);
+
+ ret = vring_pop(s->vdev, &s->vring, &req->elem);
if (ret < 0) {
- assert(elem == NULL);
+ virtio_blk_free_request(req);
break; /* no more requests */
}
- trace_virtio_blk_data_plane_process_request(s, elem->out_num,
- elem->in_num, elem->index);
+ trace_virtio_blk_data_plane_process_request(s, req->elem.out_num,
+ req->elem.in_num,
+ req->elem.index);
- req = g_slice_new(VirtIOBlockReq);
- req->dev = VIRTIO_BLK(s->vdev);
- req->elem = elem;
virtio_blk_handle_request(req, &mrb);
}
@@ -117,6 +132,7 @@
break;
}
}
+ bdrv_io_unplug(s->blk->conf.bs);
}
/* Context: QEMU global mutex held */
@@ -125,7 +141,6 @@
Error **errp)
{
VirtIOBlockDataPlane *s;
- VirtIOBlock *vblk = VIRTIO_BLK(vdev);
Error *local_err = NULL;
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
@@ -173,13 +188,12 @@
s->iothread = &s->internal_iothread_obj;
}
s->ctx = iothread_get_aio_context(s->iothread);
+ s->bh = aio_bh_new(s->ctx, notify_guest_bh, s);
error_setg(&s->blocker, "block device is in use by data plane");
bdrv_op_block_all(blk->conf.bs, s->blocker);
*dataplane = s;
- s->saved_complete_request = vblk->complete_request;
- vblk->complete_request = complete_request_vring;
}
/* Context: QEMU global mutex held */
@@ -193,6 +207,7 @@
bdrv_op_unblock_all(s->blk->conf.bs, s->blocker);
error_free(s->blocker);
object_unref(OBJECT(s->iothread));
+ qemu_bh_delete(s->bh);
g_free(s);
}
@@ -201,6 +216,7 @@
{
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+ VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
VirtQueue *vq;
if (s->started) {
@@ -234,6 +250,9 @@
}
s->host_notifier = *virtio_queue_get_host_notifier(vq);
+ s->saved_complete_request = vblk->complete_request;
+ vblk->complete_request = complete_request_vring;
+
s->starting = false;
s->started = true;
trace_virtio_blk_data_plane_start(s);
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index aec3146..c241c50 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -29,18 +29,18 @@
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
-static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
+VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
{
- VirtIOBlockReq *req = g_slice_new0(VirtIOBlockReq);
+ VirtIOBlockReq *req = g_slice_new(VirtIOBlockReq);
req->dev = s;
- req->elem = g_slice_new0(VirtQueueElement);
+ req->qiov.size = 0;
+ req->next = NULL;
return req;
}
-static void virtio_blk_free_request(VirtIOBlockReq *req)
+void virtio_blk_free_request(VirtIOBlockReq *req)
{
if (req) {
- g_slice_free(VirtQueueElement, req->elem);
g_slice_free(VirtIOBlockReq, req);
}
}
@@ -54,7 +54,7 @@
trace_virtio_blk_req_complete(req, status);
stb_p(&req->in->status, status);
- virtqueue_push(s->vq, req->elem, req->qiov.size + sizeof(*req->in));
+ virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in));
virtio_notify(vdev, s->vq);
}
@@ -119,7 +119,7 @@
{
VirtIOBlockReq *req = virtio_blk_alloc_request(s);
- if (!virtqueue_pop(s->vq, req->elem)) {
+ if (!virtqueue_pop(s->vq, &req->elem)) {
virtio_blk_free_request(req);
return NULL;
}
@@ -252,7 +252,7 @@
{
int status;
- status = virtio_blk_handle_scsi_req(req->dev, req->elem);
+ status = virtio_blk_handle_scsi_req(req->dev, &req->elem);
virtio_blk_req_complete(req, status);
virtio_blk_free_request(req);
}
@@ -288,6 +288,25 @@
bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
}
+static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,
+ uint64_t sector, size_t size)
+{
+ uint64_t nb_sectors = size >> BDRV_SECTOR_BITS;
+ uint64_t total_sectors;
+
+ if (sector & dev->sector_mask) {
+ return false;
+ }
+ if (size % dev->conf->logical_block_size) {
+ return false;
+ }
+ bdrv_get_geometry(dev->bs, &total_sectors);
+ if (sector > total_sectors || nb_sectors > total_sectors - sector) {
+ return false;
+ }
+ return true;
+}
+
static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
{
BlockRequest *blkreq;
@@ -295,18 +314,15 @@
sector = virtio_ldq_p(VIRTIO_DEVICE(req->dev), &req->out.sector);
- bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_WRITE);
-
trace_virtio_blk_handle_write(req, sector, req->qiov.size / 512);
- if (sector & req->dev->sector_mask) {
- virtio_blk_rw_complete(req, -EIO);
+ if (!virtio_blk_sect_range_ok(req->dev, sector, req->qiov.size)) {
+ virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
+ virtio_blk_free_request(req);
return;
}
- if (req->qiov.size % req->dev->conf->logical_block_size) {
- virtio_blk_rw_complete(req, -EIO);
- return;
- }
+
+ bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_WRITE);
if (mrb->num_writes == 32) {
virtio_submit_multiwrite(req->dev->bs, mrb);
@@ -329,18 +345,15 @@
sector = virtio_ldq_p(VIRTIO_DEVICE(req->dev), &req->out.sector);
- bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ);
-
trace_virtio_blk_handle_read(req, sector, req->qiov.size / 512);
- if (sector & req->dev->sector_mask) {
- virtio_blk_rw_complete(req, -EIO);
+ if (!virtio_blk_sect_range_ok(req->dev, sector, req->qiov.size)) {
+ virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
+ virtio_blk_free_request(req);
return;
}
- if (req->qiov.size % req->dev->conf->logical_block_size) {
- virtio_blk_rw_complete(req, -EIO);
- return;
- }
+
+ bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ);
bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
req->qiov.size / BDRV_SECTOR_SIZE,
virtio_blk_rw_complete, req);
@@ -349,12 +362,12 @@
void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
{
uint32_t type;
- struct iovec *in_iov = req->elem->in_sg;
- struct iovec *iov = req->elem->out_sg;
- unsigned in_num = req->elem->in_num;
- unsigned out_num = req->elem->out_num;
+ struct iovec *in_iov = req->elem.in_sg;
+ struct iovec *iov = req->elem.out_sg;
+ unsigned in_num = req->elem.in_num;
+ unsigned out_num = req->elem.out_num;
- if (req->elem->out_num < 1 || req->elem->in_num < 1) {
+ if (req->elem.out_num < 1 || req->elem.in_num < 1) {
error_report("virtio-blk missing headers");
exit(1);
}
@@ -391,19 +404,19 @@
* NB: per existing s/n string convention the string is
* terminated by '\0' only when shorter than buffer.
*/
- strncpy(req->elem->in_sg[0].iov_base,
+ strncpy(req->elem.in_sg[0].iov_base,
s->blk.serial ? s->blk.serial : "",
- MIN(req->elem->in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
+ MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
virtio_blk_free_request(req);
} else if (type & VIRTIO_BLK_T_OUT) {
- qemu_iovec_init_external(&req->qiov, &req->elem->out_sg[1],
- req->elem->out_num - 1);
+ qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
+ req->elem.out_num - 1);
virtio_blk_handle_write(req, mrb);
} else if (type == VIRTIO_BLK_T_IN || type == VIRTIO_BLK_T_BARRIER) {
/* VIRTIO_BLK_T_IN is 0, so we can't just & it. */
- qemu_iovec_init_external(&req->qiov, &req->elem->in_sg[0],
- req->elem->in_num - 1);
+ qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
+ req->elem.in_num - 1);
virtio_blk_handle_read(req);
} else {
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
@@ -627,7 +640,7 @@
while (req) {
qemu_put_sbyte(f, 1);
- qemu_put_buffer(f, (unsigned char *)req->elem,
+ qemu_put_buffer(f, (unsigned char *)&req->elem,
sizeof(VirtQueueElement));
req = req->next;
}
@@ -652,15 +665,15 @@
while (qemu_get_sbyte(f)) {
VirtIOBlockReq *req = virtio_blk_alloc_request(s);
- qemu_get_buffer(f, (unsigned char *)req->elem,
+ qemu_get_buffer(f, (unsigned char *)&req->elem,
sizeof(VirtQueueElement));
req->next = s->rq;
s->rq = req;
- virtqueue_map_sg(req->elem->in_sg, req->elem->in_addr,
- req->elem->in_num, 1);
- virtqueue_map_sg(req->elem->out_sg, req->elem->out_addr,
- req->elem->out_num, 0);
+ virtqueue_map_sg(req->elem.in_sg, req->elem.in_addr,
+ req->elem.in_num, 1);
+ virtqueue_map_sg(req->elem.out_sg, req->elem.out_addr,
+ req->elem.out_num, 0);
}
return 0;
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index dbbc167..a5736cb 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -175,8 +175,10 @@
{
int break_enabled = 1;
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
- &break_enabled);
+ if (s->chr) {
+ qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
+ &break_enabled);
+ }
}
static void uart_parameters_setup(UartState *s)
@@ -227,7 +229,9 @@
packet_size += ssp.data_bits + ssp.stop_bits;
s->char_tx_time = (get_ticks_per_sec() / ssp.speed) * packet_size;
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+ if (s->chr) {
+ qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+ }
}
static int uart_can_receive(void *opaque)
@@ -295,6 +299,7 @@
/* instant drain the fifo when there's no back-end */
if (!s->chr) {
s->tx_count = 0;
+ return FALSE;
}
if (!s->tx_count) {
@@ -375,7 +380,9 @@
*c = s->rx_fifo[rx_rpos];
s->rx_count--;
- qemu_chr_accept_input(s->chr);
+ if (s->chr) {
+ qemu_chr_accept_input(s->chr);
+ }
} else {
*c = 0;
}
diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c
index f53bb9c..c133c33 100644
--- a/hw/char/serial-pci.c
+++ b/hw/char/serial-pci.c
@@ -148,6 +148,7 @@
for (i = 0; i < pci->ports; i++) {
s = pci->state + i;
serial_exit_core(s);
+ memory_region_del_subregion(&pci->iobar, &s->io);
memory_region_destroy(&s->io);
g_free(pci->name[i]);
}
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 54180a9..764e184 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -223,37 +223,42 @@
{
SerialState *s = opaque;
- if (s->tsr_retry <= 0) {
- if (s->fcr & UART_FCR_FE) {
- if (fifo8_is_empty(&s->xmit_fifo)) {
+ do {
+ if (s->tsr_retry <= 0) {
+ if (s->fcr & UART_FCR_FE) {
+ if (fifo8_is_empty(&s->xmit_fifo)) {
+ return FALSE;
+ }
+ s->tsr = 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 {
+ s->tsr = s->thr;
+ s->lsr |= UART_LSR_THRE;
+ s->lsr &= ~UART_LSR_TEMT;
+ }
+ }
+
+ if (s->mcr & UART_MCR_LOOP) {
+ /* in loopback mode, say that we just received a char */
+ serial_receive1(s, &s->tsr, 1);
+ } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
+ if (s->tsr_retry >= 0 && s->tsr_retry < MAX_XMIT_RETRY &&
+ qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
+ serial_xmit, s) > 0) {
+ s->tsr_retry++;
return FALSE;
}
- s->tsr = fifo8_pop(&s->xmit_fifo);
- if (!s->xmit_fifo.num) {
- s->lsr |= UART_LSR_THRE;
- }
- } else if ((s->lsr & UART_LSR_THRE)) {
- return FALSE;
+ s->tsr_retry = 0;
} else {
- s->tsr = s->thr;
- s->lsr |= UART_LSR_THRE;
- s->lsr &= ~UART_LSR_TEMT;
+ s->tsr_retry = 0;
}
- }
-
- if (s->mcr & UART_MCR_LOOP) {
- /* in loopback mode, say that we just received a char */
- serial_receive1(s, &s->tsr, 1);
- } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
- if (s->tsr_retry >= 0 && s->tsr_retry < MAX_XMIT_RETRY &&
- qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP, serial_xmit, s) > 0) {
- s->tsr_retry++;
- return FALSE;
- }
- s->tsr_retry = 0;
- } else {
- s->tsr_retry = 0;
- }
+ /* Transmit another byte if it is already available. It is only
+ possible when FIFO is enabled and not empty. */
+ } while ((s->fcr & UART_FCR_FE) && !fifo8_is_empty(&s->xmit_fifo));
s->last_xmit_ts = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
@@ -293,7 +298,9 @@
s->thr_ipending = 0;
s->lsr &= ~UART_LSR_THRE;
serial_update_irq(s);
- serial_xmit(NULL, G_IO_OUT, s);
+ if (s->tsr_retry <= 0) {
+ serial_xmit(NULL, G_IO_OUT, s);
+ }
}
break;
case 1:
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 07bebc0..23123b7 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -797,10 +797,18 @@
static void remove_port(VirtIOSerial *vser, uint32_t port_id)
{
VirtIOSerialPort *port;
- unsigned int i;
- i = port_id / 32;
- vser->ports_map[i] &= ~(1U << (port_id % 32));
+ /*
+ * Don't mark port 0 removed -- we explicitly reserve it for
+ * backward compat with older guests, ensure a virtconsole device
+ * unplug retains the reservation.
+ */
+ if (port_id) {
+ unsigned int i;
+
+ i = port_id / 32;
+ vser->ports_map[i] &= ~(1U << (port_id % 32));
+ }
port = find_port_by_id(vser, port_id);
/*
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 6fbe39d..db330e9 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -2059,7 +2059,7 @@
}
} else {
#ifdef DEBUG_CIRRUS
- printf("cirrus: mem_writeb " TARGET_FMT_plx " value %02x\n", addr,
+ printf("cirrus: mem_writeb " TARGET_FMT_plx " value 0x%02" PRIu64 "\n", addr,
mem_value);
#endif
}
@@ -2594,7 +2594,7 @@
break;
case 0x3c5:
#ifdef DEBUG_VGA_REG
- printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
+ printf("vga: write SR%x = 0x%02" PRIu64 "\n", s->sr_index, val);
#endif
cirrus_vga_write_sr(c, val);
break;
@@ -2619,7 +2619,7 @@
break;
case 0x3cf:
#ifdef DEBUG_VGA_REG
- printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
+ printf("vga: write GR%x = 0x%02" PRIu64 "\n", s->gr_index, val);
#endif
cirrus_vga_write_gr(c, s->gr_index, val);
break;
@@ -2630,7 +2630,7 @@
case 0x3b5:
case 0x3d5:
#ifdef DEBUG_VGA_REG
- printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
+ printf("vga: write CR%x = 0x%02"PRIu64"\n", s->cr_index, val);
#endif
cirrus_vga_write_cr(c, val);
break;
@@ -2911,6 +2911,14 @@
ISACirrusVGAState *d = ISA_CIRRUS_VGA(dev);
VGACommonState *s = &d->cirrus_vga.vga;
+ /* follow real hardware, cirrus card emulated has 4 MB video memory.
+ Also accept 8 MB/16 MB for backward compatibility. */
+ if (s->vram_size_mb != 4 && s->vram_size_mb != 8 &&
+ s->vram_size_mb != 16) {
+ error_setg(errp, "Invalid cirrus_vga ram size '%u'",
+ s->vram_size_mb);
+ return;
+ }
vga_common_init(s, OBJECT(dev), true);
cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0,
isa_address_space(isadev),
@@ -2957,6 +2965,14 @@
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
int16_t device_id = pc->device_id;
+ /* follow real hardware, cirrus card emulated has 4 MB video memory.
+ Also accept 8 MB/16 MB for backward compatibility. */
+ if (s->vga.vram_size_mb != 4 && s->vga.vram_size_mb != 8 &&
+ s->vga.vram_size_mb != 16) {
+ error_report("Invalid cirrus_vga ram size '%u'",
+ s->vga.vram_size_mb);
+ return -1;
+ }
/* setup VGA */
vga_common_init(&s->vga, OBJECT(dev), true);
cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev),
diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h
index 9c7bb09..0925a00 100644
--- a/hw/display/cirrus_vga_rop.h
+++ b/hw/display/cirrus_vga_rop.h
@@ -52,8 +52,7 @@
dstpitch -= bltwidth;
srcpitch -= bltwidth;
- if (dstpitch < 0 || srcpitch < 0) {
- /* is 0 valid? srcpitch == 0 could be useful */
+ if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) {
return;
}
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index 032eb7a..07ddc9d 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -93,10 +93,12 @@
static int common_bind(struct common *c)
{
- int mfn;
+ uint64_t mfn;
- if (xenstore_read_fe_int(&c->xendev, "page-ref", &mfn) == -1)
+ if (xenstore_read_fe_uint64(&c->xendev, "page-ref", &mfn) == -1)
return -1;
+ assert(mfn == (xen_pfn_t)mfn);
+
if (xenstore_read_fe_int(&c->xendev, "event-channel", &c->xendev.remote_port) == -1)
return -1;
@@ -107,7 +109,7 @@
return -1;
xen_be_bind_evtchn(&c->xendev);
- xen_be_printf(&c->xendev, 1, "ring mfn %d, remote-port %d, local-port %d\n",
+ xen_be_printf(&c->xendev, 1, "ring mfn %"PRIx64", remote-port %d, local-port %d\n",
mfn, c->xendev.remote_port, c->xendev.local_port);
return 0;
@@ -409,7 +411,7 @@
/* -------------------------------------------------------------------- */
-static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src)
+static void xenfb_copy_mfns(int mode, int count, xen_pfn_t *dst, void *src)
{
uint32_t *src32 = src;
uint64_t *src64 = src;
@@ -424,8 +426,8 @@
struct xenfb_page *page = xenfb->c.page;
char *protocol = xenfb->c.xendev.protocol;
int n_fbdirs;
- unsigned long *pgmfns = NULL;
- unsigned long *fbmfns = NULL;
+ xen_pfn_t *pgmfns = NULL;
+ xen_pfn_t *fbmfns = NULL;
void *map, *pd;
int mode, ret = -1;
@@ -483,8 +485,8 @@
n_fbdirs = xenfb->fbpages * mode / 8;
n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
- pgmfns = g_malloc0(sizeof(unsigned long) * n_fbdirs);
- fbmfns = g_malloc0(sizeof(unsigned long) * xenfb->fbpages);
+ pgmfns = g_malloc0(sizeof(xen_pfn_t) * n_fbdirs);
+ fbmfns = g_malloc0(sizeof(xen_pfn_t) * xenfb->fbpages);
xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
map = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 9bae22e..604152a 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -175,17 +175,18 @@
ahci_check_irq(s);
}
-static void map_page(uint8_t **ptr, uint64_t addr, uint32_t wanted)
+static void map_page(AddressSpace *as, uint8_t **ptr, uint64_t addr,
+ uint32_t wanted)
{
hwaddr len = wanted;
if (*ptr) {
- cpu_physical_memory_unmap(*ptr, len, 1, len);
+ dma_memory_unmap(as, *ptr, len, DMA_DIRECTION_FROM_DEVICE, len);
}
- *ptr = cpu_physical_memory_map(addr, &len, 1);
+ *ptr = dma_memory_map(as, addr, &len, DMA_DIRECTION_FROM_DEVICE);
if (len < wanted) {
- cpu_physical_memory_unmap(*ptr, len, 1, len);
+ dma_memory_unmap(as, *ptr, len, DMA_DIRECTION_FROM_DEVICE, len);
*ptr = NULL;
}
}
@@ -198,24 +199,24 @@
switch (offset) {
case PORT_LST_ADDR:
pr->lst_addr = val;
- map_page(&s->dev[port].lst,
+ map_page(s->as, &s->dev[port].lst,
((uint64_t)pr->lst_addr_hi << 32) | pr->lst_addr, 1024);
s->dev[port].cur_cmd = NULL;
break;
case PORT_LST_ADDR_HI:
pr->lst_addr_hi = val;
- map_page(&s->dev[port].lst,
+ map_page(s->as, &s->dev[port].lst,
((uint64_t)pr->lst_addr_hi << 32) | pr->lst_addr, 1024);
s->dev[port].cur_cmd = NULL;
break;
case PORT_FIS_ADDR:
pr->fis_addr = val;
- map_page(&s->dev[port].res_fis,
+ map_page(s->as, &s->dev[port].res_fis,
((uint64_t)pr->fis_addr_hi << 32) | pr->fis_addr, 256);
break;
case PORT_FIS_ADDR_HI:
pr->fis_addr_hi = val;
- map_page(&s->dev[port].res_fis,
+ map_page(s->as, &s->dev[port].res_fis,
((uint64_t)pr->fis_addr_hi << 32) | pr->fis_addr, 256);
break;
case PORT_IRQ_STAT:
@@ -639,6 +640,11 @@
}
}
+static int prdt_tbl_entry_size(const AHCI_SG *tbl)
+{
+ return (le32_to_cpu(tbl->flags_size) & AHCI_PRDT_SIZE_MASK) + 1;
+}
+
static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
{
AHCICmdHdr *cmd = ad->cur_cmd;
@@ -681,7 +687,7 @@
sum = 0;
for (i = 0; i < sglist_alloc_hint; i++) {
/* flags_size is zero-based */
- tbl_entry_size = (le32_to_cpu(tbl[i].flags_size) + 1);
+ tbl_entry_size = prdt_tbl_entry_size(&tbl[i]);
if (offset <= (sum + tbl_entry_size)) {
off_idx = i;
off_pos = offset - sum;
@@ -700,12 +706,12 @@
qemu_sglist_init(sglist, qbus->parent, (sglist_alloc_hint - off_idx),
ad->hba->as);
qemu_sglist_add(sglist, le64_to_cpu(tbl[off_idx].addr + off_pos),
- le32_to_cpu(tbl[off_idx].flags_size) + 1 - off_pos);
+ prdt_tbl_entry_size(&tbl[off_idx]) - off_pos);
for (i = off_idx + 1; i < sglist_alloc_hint; i++) {
/* flags_size is zero-based */
qemu_sglist_add(sglist, le64_to_cpu(tbl[i].addr),
- le32_to_cpu(tbl[i].flags_size) + 1);
+ prdt_tbl_entry_size(&tbl[i]));
}
}
@@ -1260,9 +1266,9 @@
ad = &s->dev[i];
AHCIPortRegs *pr = &ad->port_regs;
- map_page(&ad->lst,
+ map_page(s->as, &ad->lst,
((uint64_t)pr->lst_addr_hi << 32) | pr->lst_addr, 1024);
- map_page(&ad->res_fis,
+ map_page(s->as, &ad->res_fis,
((uint64_t)pr->fis_addr_hi << 32) | pr->fis_addr, 256);
/*
* All pending i/o should be flushed out on a migrate. However,
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index 9a4064f..f418b30 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -201,6 +201,8 @@
#define AHCI_COMMAND_TABLE_ACMD 0x40
+#define AHCI_PRDT_SIZE_MASK 0x3fffff
+
#define IDE_FEATURE_DMA 1
#define READ_FPDMA_QUEUED 0x60
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 3a38f1e..db191a6 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -499,6 +499,18 @@
ide_set_irq(s->bus);
}
+static bool ide_sect_range_ok(IDEState *s,
+ uint64_t sector, uint64_t nb_sectors)
+{
+ uint64_t total_sectors;
+
+ bdrv_get_geometry(s->bs, &total_sectors);
+ if (sector > total_sectors || nb_sectors > total_sectors - sector) {
+ return false;
+ }
+ return true;
+}
+
static void ide_sector_read_cb(void *opaque, int ret)
{
IDEState *s = opaque;
@@ -554,6 +566,11 @@
printf("sector=%" PRId64 "\n", sector_num);
#endif
+ if (!ide_sect_range_ok(s, sector_num, n)) {
+ ide_rw_error(s);
+ return;
+ }
+
s->iov.iov_base = s->io_buffer;
s->iov.iov_len = n * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&s->qiov, &s->iov, 1);
@@ -671,6 +688,12 @@
sector_num, n, s->dma_cmd);
#endif
+ if (!ide_sect_range_ok(s, sector_num, n)) {
+ dma_buf_commit(s);
+ ide_dma_error(s);
+ return;
+ }
+
switch (s->dma_cmd) {
case IDE_DMA_READ:
s->bus->dma->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
@@ -790,6 +813,11 @@
n = s->req_nb_sectors;
}
+ if (!ide_sect_range_ok(s, sector_num, n)) {
+ ide_rw_error(s);
+ return;
+ }
+
s->iov.iov_base = s->io_buffer;
s->iov.iov_len = n * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&s->qiov, &s->iov, 1);
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 2868ee5..cfb60af 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -792,9 +792,23 @@
loaderparams.kernel_filename);
exit(1);
}
+
+ /* Sanity check where the kernel has been linked */
if (kvm_enabled()) {
+ if (kernel_entry & 0x80000000ll) {
+ error_report("KVM guest kernels must be linked in useg. "
+ "Did you forget to enable CONFIG_KVM_GUEST?");
+ exit(1);
+ }
+
xlate_to_kseg0 = cpu_mips_kvm_um_phys_to_kseg0;
} else {
+ if (!(kernel_entry & 0x80000000ll)) {
+ error_report("KVM guest kernels aren't supported with TCG. "
+ "Did you unintentionally enable CONFIG_KVM_GUEST?");
+ exit(1);
+ }
+
xlate_to_kseg0 = cpu_mips_phys_to_kseg0;
}
@@ -1028,7 +1042,7 @@
fl_idx++;
if (kernel_filename) {
ram_low_size = MIN(ram_size, 256 << 20);
- /* For KVM T&E we reserve 1MB of RAM for running bootloader */
+ /* For KVM we reserve 1MB of RAM for running bootloader */
if (kvm_enabled()) {
ram_low_size -= 0x100000;
bootloader_run_addr = 0x40000000 + ram_low_size;
@@ -1052,10 +1066,10 @@
bootloader_run_addr, kernel_entry);
}
} else {
- /* The flash region isn't executable from a KVM T&E guest */
+ /* The flash region isn't executable from a KVM guest */
if (kvm_enabled()) {
error_report("KVM enabled but no -kernel argument was specified. "
- "Booting from flash is not supported with KVM T&E.");
+ "Booting from flash is not supported with KVM.");
exit(1);
}
/* Load firmware from flash. */
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index aef4c9c..0b9eba0 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -2489,7 +2489,7 @@
return;
}
- if (iotlb->perm != IOMMU_NONE) {
+ if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) {
vaddr = memory_region_get_ram_ptr(mr) + xlat;
ret = vfio_dma_map(container, iotlb->iova,
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
index 4014540..ec6f186 100644
--- a/hw/pci-host/prep.c
+++ b/hw/pci-host/prep.c
@@ -256,9 +256,7 @@
memory_region_init(&s->pci_io, obj, "pci-io", 0x3f800000);
memory_region_init_io(&s->pci_io_non_contiguous, obj, &raven_io_ops, s,
"pci-io-non-contiguous", 0x00800000);
- /* Open Hack'Ware hack: real size should be only 0x3f000000 bytes */
- memory_region_init(&s->pci_memory, obj, "pci-memory",
- 0x3f000000 + 0xc0000000ULL);
+ memory_region_init(&s->pci_memory, obj, "pci-memory", 0x3f000000);
address_space_init(&s->pci_io_as, &s->pci_io, "raven-io");
/* CPU address space */
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index bb2e75f..1a5b30d 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -701,8 +701,7 @@
machine->ram_size = ram_size;
/* Register Memory */
- memory_region_init_ram(ram, NULL, "mpc8544ds.ram", ram_size);
- vmstate_register_ram_global(ram);
+ memory_region_allocate_system_memory(ram, NULL, "mpc8544ds.ram", ram_size);
memory_region_add_subregion(address_space_mem, 0, ram);
dev = qdev_create(NULL, "e500-ccsr");
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 89d3cad..7e97af4 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -200,13 +200,12 @@
}
/* allocate RAM */
- memory_region_init_ram(ram, NULL, "ppc_core99.ram", ram_size);
- vmstate_register_ram_global(ram);
+ memory_region_allocate_system_memory(ram, NULL, "ppc_core99.ram", ram_size);
memory_region_add_subregion(get_system_memory(), 0, ram);
/* allocate and load BIOS */
- memory_region_init_ram(bios, NULL, "ppc_core99.bios", BIOS_SIZE);
- vmstate_register_ram_global(bios);
+ memory_region_allocate_system_memory(bios, NULL, "ppc_core99.bios",
+ BIOS_SIZE);
if (bios_name == NULL)
bios_name = PROM_FILENAME;
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 4b5e905..afae825 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -130,13 +130,13 @@
exit(1);
}
- memory_region_init_ram(ram, NULL, "ppc_heathrow.ram", ram_size);
- vmstate_register_ram_global(ram);
+ memory_region_allocate_system_memory(ram, NULL, "ppc_heathrow.ram",
+ ram_size);
memory_region_add_subregion(sysmem, 0, ram);
/* allocate and load BIOS */
- memory_region_init_ram(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE);
- vmstate_register_ram_global(bios);
+ memory_region_allocate_system_memory(bios, NULL, "ppc_heathrow.bios",
+ BIOS_SIZE);
if (bios_name == NULL)
bios_name = PROM_FILENAME;
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 98ad2d7..6b566cd 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -199,8 +199,8 @@
MemoryRegion *sysmem = get_system_memory();
/* XXX: fix this */
- memory_region_init_ram(&ram_memories[0], NULL, "ef405ep.ram", 0x08000000);
- vmstate_register_ram_global(&ram_memories[0]);
+ memory_region_allocate_system_memory(&ram_memories[0], NULL, "ef405ep.ram",
+ 0x08000000);
ram_bases[0] = 0;
ram_sizes[0] = 0x08000000;
memory_region_init(&ram_memories[1], NULL, "ef405ep.ram1", 0);
@@ -214,8 +214,7 @@
33333333, &pic, kernel_filename == NULL ? 0 : 1);
/* allocate SRAM */
sram_size = 512 * 1024;
- memory_region_init_ram(sram, NULL, "ef405ep.sram", sram_size);
- vmstate_register_ram_global(sram);
+ memory_region_allocate_system_memory(sram, NULL, "ef405ep.sram", sram_size);
memory_region_add_subregion(sysmem, 0xFFF00000, sram);
/* allocate and load BIOS */
#ifdef DEBUG_BOARD_INIT
@@ -246,8 +245,8 @@
printf("Load BIOS from file\n");
#endif
bios = g_new(MemoryRegion, 1);
- memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE);
- vmstate_register_ram_global(bios);
+ memory_region_allocate_system_memory(bios, NULL, "ef405ep.bios",
+ BIOS_SIZE);
if (bios_name == NULL)
bios_name = BIOS_FILENAME;
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -518,14 +517,12 @@
DriveInfo *dinfo;
/* RAM is soldered to the board so the size cannot be changed */
- memory_region_init_ram(&ram_memories[0], NULL,
+ memory_region_allocate_system_memory(&ram_memories[0], NULL,
"taihu_405ep.ram-0", 0x04000000);
- vmstate_register_ram_global(&ram_memories[0]);
ram_bases[0] = 0;
ram_sizes[0] = 0x04000000;
- memory_region_init_ram(&ram_memories[1], NULL,
+ memory_region_allocate_system_memory(&ram_memories[1], NULL,
"taihu_405ep.ram-1", 0x04000000);
- vmstate_register_ram_global(&ram_memories[1]);
ram_bases[1] = 0x04000000;
ram_sizes[1] = 0x04000000;
ram_size = 0x08000000;
@@ -567,8 +564,8 @@
if (bios_name == NULL)
bios_name = BIOS_FILENAME;
bios = g_new(MemoryRegion, 1);
- memory_region_init_ram(bios, NULL, "taihu_405ep.bios", BIOS_SIZE);
- vmstate_register_ram_global(bios);
+ memory_region_allocate_system_memory(bios, NULL, "taihu_405ep.bios",
+ BIOS_SIZE);
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 54ba59e..fcd5f2d 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -23,6 +23,7 @@
*/
#include "hw/hw.h"
#include "hw/ppc/ppc.h"
+#include "hw/boards.h"
#include "ppc405.h"
#include "hw/char/serial.h"
#include "qemu/timer.h"
@@ -973,8 +974,8 @@
ocm = g_malloc0(sizeof(ppc405_ocm_t));
/* XXX: Size is 4096 or 0x04000000 */
- memory_region_init_ram(&ocm->isarc_ram, NULL, "ppc405.ocm", 4096);
- vmstate_register_ram_global(&ocm->isarc_ram);
+ memory_region_allocate_system_memory(&ocm->isarc_ram, NULL, "ppc405.ocm",
+ 4096);
memory_region_init_alias(&ocm->dsarc_ram, NULL, "ppc405.dsarc", &ocm->isarc_ram,
0, 4096);
qemu_register_reset(&ocm_reset, ocm);
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 8a43111..07f9d00 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -24,6 +24,7 @@
#include "hw/hw.h"
#include "hw/ppc/ppc.h"
#include "hw/ppc/ppc4xx.h"
+#include "hw/boards.h"
#include "qemu/log.h"
#include "exec/address-spaces.h"
@@ -694,8 +695,8 @@
if (bank_size <= size_left) {
char name[32];
snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
- memory_region_init_ram(&ram_memories[i], NULL, name, bank_size);
- vmstate_register_ram_global(&ram_memories[i]);
+ memory_region_allocate_system_memory(&ram_memories[i], NULL,
+ name, bank_size);
ram_bases[i] = base;
ram_sizes[i] = bank_size;
base += bank_size;
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 2383254..f0ef1af 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -346,9 +346,6 @@
PowerPCCPU *cpu = opaque;
cpu_reset(CPU(cpu));
-
- /* Reset address */
- cpu->env.nip = 0xfffffffc;
}
static const MemoryRegionPortio prep_portio_list[] = {
@@ -382,7 +379,6 @@
#endif
int linux_boot, i, nb_nics1;
MemoryRegion *ram = g_new(MemoryRegion, 1);
- MemoryRegion *vga = g_new(MemoryRegion, 1);
uint32_t kernel_base, initrd_base;
long kernel_size, initrd_size;
DeviceState *dev;
@@ -421,8 +417,7 @@
}
/* allocate RAM */
- memory_region_init_ram(ram, NULL, "ppc_prep.ram", ram_size);
- vmstate_register_ram_global(ram);
+ memory_region_allocate_system_memory(ram, NULL, "ppc_prep.ram", ram_size);
memory_region_add_subregion(sysmem, 0, ram);
if (linux_boot) {
@@ -508,14 +503,6 @@
/* init basic PC hardware */
pci_vga_init(pci_bus);
- /* Open Hack'Ware hack: PCI BAR#0 is programmed to 0xf0000000.
- * While bios will access framebuffer at 0xf0000000, real physical
- * address is 0xf0000000 + 0xc0000000 (PCI memory base).
- * Alias the wrong memory accesses to the right place.
- */
- memory_region_init_alias(vga, NULL, "vga-alias", pci_address_space(pci),
- 0xf0000000, 0x1000000);
- memory_region_add_subregion_overlap(sysmem, 0xf0000000, vga, 10);
nb_nics1 = nb_nics;
if (nb_nics1 > NE2000_NB_MAX)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index a8ba916..d01978f 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -160,8 +160,7 @@
int index = ppc_get_vcpu_dt_id(cpu);
if (cpu->cpu_version) {
- ret = fdt_setprop(fdt, offset, "cpu-version",
- &cpu->cpu_version, sizeof(cpu->cpu_version));
+ ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->cpu_version);
if (ret < 0) {
return ret;
}
@@ -1224,6 +1223,8 @@
int i;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
+ MemoryRegion *rma_region;
+ void *rma = NULL;
hwaddr rma_alloc_size;
hwaddr node0_size = (nb_numa_nodes > 1) ? numa_info[0].node_mem : ram_size;
uint32_t initrd_base = 0;
@@ -1240,7 +1241,7 @@
cpu_ppc_hypercall = emulate_spapr_hypercall;
/* Allocate RMA if necessary */
- rma_alloc_size = kvmppc_alloc_rma("ppc_spapr.rma", sysmem);
+ rma_alloc_size = kvmppc_alloc_rma(&rma);
if (rma_alloc_size == -1) {
hw_error("qemu: Unable to create RMA\n");
@@ -1334,13 +1335,16 @@
/* allocate RAM */
spapr->ram_limit = ram_size;
- if (spapr->ram_limit > rma_alloc_size) {
- ram_addr_t nonrma_base = rma_alloc_size;
- ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size;
+ memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram",
+ spapr->ram_limit);
+ memory_region_add_subregion(sysmem, 0, ram);
- memory_region_init_ram(ram, NULL, "ppc_spapr.ram", nonrma_size);
- vmstate_register_ram_global(ram);
- memory_region_add_subregion(sysmem, nonrma_base, ram);
+ if (rma_alloc_size && rma) {
+ rma_region = g_new(MemoryRegion, 1);
+ memory_region_init_ram_ptr(rma_region, NULL, "ppc_spapr.rma",
+ rma_alloc_size, rma);
+ vmstate_register_ram_global(rma_region);
+ memory_region_add_subregion(sysmem, 0, rma_region);
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 7952077..467858c 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -770,7 +770,7 @@
prefix = 0x18000;
break;
case H_SET_MODE_ADDR_TRANS_C000_0000_0000_4000:
- prefix = 0xC000000000004000;
+ prefix = 0xC000000000004000ULL;
break;
default:
return H_UNSUPPORTED_FLAG;
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 698ae60..f6e32a4 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -81,7 +81,7 @@
ret.iova = addr & page_mask;
ret.translated_addr = tce & page_mask;
ret.addr_mask = ~page_mask;
- ret.perm = tce;
+ ret.perm = tce & IOMMU_RW;
}
trace_spapr_iommu_xlate(tcet->liobn, addr, ret.iova, ret.perm,
ret.addr_mask);
@@ -223,7 +223,7 @@
entry.iova = ioba & page_mask;
entry.translated_addr = tce & page_mask;
entry.addr_mask = ~page_mask;
- entry.perm = tce;
+ entry.perm = tce & IOMMU_RW;
memory_region_notify_iommu(&tcet->iommu, entry);
return H_SUCCESS;
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index 02b4f82..0de5148 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -222,8 +222,7 @@
env = &cpu->env;
qemu_register_reset(main_cpu_reset, cpu);
- memory_region_init_ram(phys_ram, NULL, "ram", ram_size);
- vmstate_register_ram_global(phys_ram);
+ memory_region_allocate_system_memory(phys_ram, NULL, "ram", ram_size);
memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
dinfo = drive_get(IF_PFLASH, 0, 0);
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index e758890..49c2aaf 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -200,6 +200,7 @@
PMCW *p = &sch->curr_status.pmcw;
SCSW *s = &sch->curr_status.scsw;
+ hwaddr curr_ccw = sch->channel_prog;
int path;
/* Path management: In our simple css, we always choose the only path. */
@@ -216,6 +217,10 @@
(s->ctrl & SCSW_ACTL_SUSP))) {
s->dstat = SCSW_DSTAT_DEVICE_END;
}
+ if ((s->ctrl & (SCSW_ACTL_SUBCH_ACTIVE | SCSW_ACTL_DEVICE_ACTIVE)) ||
+ (s->ctrl & SCSW_ACTL_SUSP)) {
+ s->cpa = curr_ccw + 8;
+ }
s->cstat = 0;
p->lpum = path;
@@ -398,6 +403,7 @@
s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
SCSW_STCTL_STATUS_PEND;
s->dstat = SCSW_DSTAT_CHANNEL_END | SCSW_DSTAT_DEVICE_END;
+ s->cpa = sch->channel_prog + 8;
break;
case -ENOSYS:
/* unsupported command, generate unit check (command reject) */
@@ -408,6 +414,7 @@
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
+ s->cpa = sch->channel_prog + 8;
break;
case -EFAULT:
/* memory problem, generate channel data check */
@@ -416,6 +423,7 @@
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
+ s->cpa = sch->channel_prog + 8;
break;
case -EBUSY:
/* subchannel busy, generate deferred cc 1 */
@@ -436,6 +444,7 @@
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
+ s->cpa = sch->channel_prog + 8;
break;
}
} while (ret == -EAGAIN);
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index ea1ac09..4341754 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -177,7 +177,8 @@
d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
assert(d);
if (d->lun == dev->lun && dev != d) {
- object_unparent(OBJECT(d));
+ error_report("lun already used by '%s'", d->qdev.id);
+ goto err;
}
}
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 9d817ca..233fc70 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -895,7 +895,7 @@
check_update_timer(s);
s->clock_reset_notifier.notify = rtc_notify_clock_reset;
- qemu_clock_register_reset_notifier(QEMU_CLOCK_REALTIME,
+ qemu_clock_register_reset_notifier(rtc_clock,
&s->clock_reset_notifier);
s->suspend_notifier.notify = rtc_notify_suspend;
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 380b465..1b51a90 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -145,6 +145,7 @@
STR_MANUFACTURER = 1,
STR_PRODUCT,
STR_SERIALNUMBER,
+ STR_MTP,
STR_CONFIG_FULL,
STR_CONFIG_HIGH,
STR_CONFIG_SUPER,
@@ -154,6 +155,7 @@
[STR_MANUFACTURER] = MTP_MANUFACTURER,
[STR_PRODUCT] = MTP_PRODUCT,
[STR_SERIALNUMBER] = "34617",
+ [STR_MTP] = "MTP",
[STR_CONFIG_FULL] = "Full speed config (usb 1.1)",
[STR_CONFIG_HIGH] = "High speed config (usb 2.0)",
[STR_CONFIG_SUPER] = "Super speed config (usb 3.0)",
@@ -165,6 +167,7 @@
.bInterfaceClass = USB_CLASS_STILL_IMAGE,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01,
+ .iInterface = STR_MTP,
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_IN | EP_DATA_IN,
@@ -206,6 +209,7 @@
.bInterfaceClass = USB_CLASS_STILL_IMAGE,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01,
+ .iInterface = STR_MTP,
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_IN | EP_DATA_IN,
diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
index 665a1ff..67cb2b8 100644
--- a/hw/virtio/dataplane/vring.c
+++ b/hw/virtio/dataplane/vring.c
@@ -272,7 +272,7 @@
return 0;
}
-void vring_free_element(VirtQueueElement *elem)
+static void vring_unmap_element(VirtQueueElement *elem)
{
int i;
@@ -287,8 +287,6 @@
for (i = 0; i < elem->in_num; i++) {
vring_unmap(elem->in_sg[i].iov_base, true);
}
-
- g_slice_free(VirtQueueElement, elem);
}
/* This looks in the virtqueue and for the first available buffer, and converts
@@ -303,14 +301,16 @@
* Stolen from linux/drivers/vhost/vhost.c.
*/
int vring_pop(VirtIODevice *vdev, Vring *vring,
- VirtQueueElement **p_elem)
+ VirtQueueElement *elem)
{
struct vring_desc desc;
unsigned int i, head, found = 0, num = vring->vr.num;
uint16_t avail_idx, last_avail_idx;
- VirtQueueElement *elem = NULL;
int ret;
+ /* Initialize elem so it can be safely unmapped */
+ elem->in_num = elem->out_num = 0;
+
/* If there was a fatal error then refuse operation */
if (vring->broken) {
ret = -EFAULT;
@@ -342,10 +342,8 @@
* the index we've seen. */
head = vring->vr.avail->ring[last_avail_idx % num];
- elem = g_slice_new(VirtQueueElement);
elem->index = head;
- elem->in_num = elem->out_num = 0;
-
+
/* If their number is silly, that's an error. */
if (unlikely(head >= num)) {
error_report("Guest says index %u > %u is available", head, num);
@@ -393,7 +391,6 @@
/* On success, increment avail index. */
vring->last_avail_idx++;
- *p_elem = elem;
return head;
out:
@@ -401,10 +398,7 @@
if (ret == -EFAULT) {
vring->broken = true;
}
- if (elem) {
- vring_free_element(elem);
- }
- *p_elem = NULL;
+ vring_unmap_element(elem);
return ret;
}
@@ -418,7 +412,7 @@
unsigned int head = elem->index;
uint16_t new;
- vring_free_element(elem);
+ vring_unmap_element(elem);
/* Don't touch vring if a fatal error occurred */
if (vring->broken) {
diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index 9f607d4..c307f9b 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -122,8 +122,12 @@
exit(0);
case WDT_PAUSE: /* same as 'stop' command in monitor */
+ /* In a timer callback, when vm_stop calls qemu_clock_enable
+ * you would get a deadlock. Bypass the problem.
+ */
+ qemu_system_vmstop_request_prepare();
qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_PAUSE, &error_abort);
- vm_stop(RUN_STATE_WATCHDOG);
+ qemu_system_vmstop_request(RUN_STATE_WATCHDOG);
break;
case WDT_DEBUG:
diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
index 3cd45b4..b2cb22b 100644
--- a/hw/xen/xen_backend.c
+++ b/hw/xen/xen_backend.c
@@ -111,6 +111,19 @@
return rc;
}
+int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
+{
+ char *val;
+ int rc = -1;
+
+ val = xenstore_read_str(base, node);
+ if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
+ rc = 0;
+ }
+ g_free(val);
+ return rc;
+}
+
int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val)
{
return xenstore_write_str(xendev->be, node, val);
@@ -146,6 +159,11 @@
return xenstore_read_int(xendev->fe, node, ival);
}
+int xenstore_read_fe_uint64(struct XenDevice *xendev, const char *node, uint64_t *uval)
+{
+ return xenstore_read_uint64(xendev->fe, node, uval);
+}
+
/* ------------------------------------------------------------- */
const char *xenbus_strstate(enum xenbus_state state)
diff --git a/include/block/aio.h b/include/block/aio.h
index a92511b..c23de3c 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -60,8 +60,14 @@
*/
int walking_handlers;
+ /* Used to avoid unnecessary event_notifier_set calls in aio_notify.
+ * Writes protected by lock or BQL, reads are lockless.
+ */
+ bool dispatching;
+
/* lock to protect between bh's adders and deleter */
QemuMutex bh_lock;
+
/* Anchor of the list of Bottom Halves belonging to the context */
struct QEMUBH *first_bh;
@@ -83,6 +89,9 @@
QEMUTimerListGroup tlg;
};
+/* Used internally to synchronize aio_poll against qemu_bh_schedule. */
+void aio_set_dispatching(AioContext *ctx, bool dispatching);
+
/**
* aio_context_new: Allocate a new AioContext.
*
@@ -205,9 +214,9 @@
/* Progress in completing AIO work to occur. This can issue new pending
* aio as a result of executing I/O completion or bh callbacks.
*
- * If there is no pending AIO operation or completion (bottom half),
- * return false. If there are pending AIO operations of bottom halves,
- * return true.
+ * Return whether any progress was made by executing AIO or bottom half
+ * handlers. If @blocking == true, this should always be true except
+ * if someone called aio_notify.
*
* If there are no pending bottom halves, but there are pending AIO
* operations, it may not be possible to make any progress without
@@ -220,7 +229,7 @@
#ifdef CONFIG_POSIX
/* Register a file descriptor and associated callbacks. Behaves very similarly
* to qemu_set_fd_handler2. Unlike qemu_set_fd_handler2, these callbacks will
- * be invoked when using qemu_aio_wait().
+ * be invoked when using aio_poll().
*
* Code that invokes AIO completion functions should rely on this function
* instead of qemu_set_fd_handler[2].
@@ -234,7 +243,7 @@
/* Register an event notifier and associated callbacks. Behaves very similarly
* to event_notifier_set_handler. Unlike event_notifier_set_handler, these callbacks
- * will be invoked when using qemu_aio_wait().
+ * will be invoked when using aio_poll().
*
* Code that invokes AIO completion functions should rely on this function
* instead of event_notifier_set_handler.
@@ -251,19 +260,6 @@
/* Return the ThreadPool bound to this AioContext */
struct ThreadPool *aio_get_thread_pool(AioContext *ctx);
-/* Functions to operate on the main QEMU AioContext. */
-
-bool qemu_aio_wait(void);
-void qemu_aio_set_event_notifier(EventNotifier *notifier,
- EventNotifierHandler *io_read);
-
-#ifdef CONFIG_POSIX
-void qemu_aio_set_fd_handler(int fd,
- IOHandler *io_read,
- IOHandler *io_write,
- void *opaque);
-#endif
-
/**
* aio_timer_new:
* @ctx: the aio context
diff --git a/include/block/block.h b/include/block/block.h
index baecc26..32d3676 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -584,4 +584,8 @@
*/
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context);
+void bdrv_io_plug(BlockDriverState *bs);
+void bdrv_io_unplug(BlockDriverState *bs);
+void bdrv_flush_io_queue(BlockDriverState *bs);
+
#endif
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 8f8e65e..f6c3bef 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -261,6 +261,11 @@
void (*bdrv_attach_aio_context)(BlockDriverState *bs,
AioContext *new_context);
+ /* io queue for linux-aio */
+ void (*bdrv_io_plug)(BlockDriverState *bs);
+ void (*bdrv_io_unplug)(BlockDriverState *bs);
+ void (*bdrv_flush_io_queue)(BlockDriverState *bs);
+
QLIST_ENTRY(BlockDriver) list;
};
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index f3cf63f..60aa835 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -74,7 +74,7 @@
* Set to true if the job should cancel itself. The flag must
* always be tested just before toggling the busy flag from false
* to true. After a job has been cancelled, it should only yield
- * if #qemu_aio_wait will ("sooner or later") reenter the coroutine.
+ * if #aio_poll will ("sooner or later") reenter the coroutine.
*/
bool cancelled;
@@ -87,7 +87,7 @@
/**
* Set to false by the job while it is in a quiescent state, where
* no I/O is pending and the job has yielded on any condition
- * that is not detected by #qemu_aio_wait, such as a timer.
+ * that is not detected by #aio_poll, such as a timer.
*/
bool busy;
diff --git a/include/block/coroutine.h b/include/block/coroutine.h
index a1797ae..b408f96 100644
--- a/include/block/coroutine.h
+++ b/include/block/coroutine.h
@@ -212,7 +212,7 @@
* Yield the coroutine for a given duration
*
* Behaves similarly to co_sleep_ns(), but the sleeping coroutine will be
- * resumed when using qemu_aio_wait().
+ * resumed when using aio_poll().
*/
void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
int64_t ns);
diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h
index 63e7bf4..af73ee2 100644
--- a/include/hw/virtio/dataplane/vring.h
+++ b/include/hw/virtio/dataplane/vring.h
@@ -53,8 +53,7 @@
void vring_disable_notification(VirtIODevice *vdev, Vring *vring);
bool vring_enable_notification(VirtIODevice *vdev, Vring *vring);
bool vring_should_notify(VirtIODevice *vdev, Vring *vring);
-int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement **elem);
+int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem);
void vring_push(Vring *vring, VirtQueueElement *elem, int len);
-void vring_free_element(VirtQueueElement *elem);
#endif /* VRING_H */
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index b3080a2..afb7b8d 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -144,7 +144,7 @@
typedef struct VirtIOBlockReq {
VirtIOBlock *dev;
- VirtQueueElement *elem;
+ VirtQueueElement elem;
struct virtio_blk_inhdr *in;
struct virtio_blk_outhdr out;
QEMUIOVector qiov;
@@ -152,6 +152,10 @@
BlockAcctCookie acct;
} VirtIOBlockReq;
+VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s);
+
+void virtio_blk_free_request(VirtIOBlockReq *req);
+
int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
VirtQueueElement *elem);
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 0419ee4..188a2d9 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -178,6 +178,8 @@
DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128)
#define DEFINE_VIRTIO_SCSI_FEATURES(_state, _feature_field) \
+ DEFINE_PROP_BIT("any_layout", _state, _feature_field, \
+ VIRTIO_F_ANY_LAYOUT, true), \
DEFINE_PROP_BIT("hotplug", _state, _feature_field, VIRTIO_SCSI_F_HOTPLUG, \
true), \
DEFINE_PROP_BIT("param_change", _state, _feature_field, \
diff --git a/include/hw/xen/xen_backend.h b/include/hw/xen/xen_backend.h
index 3b7d96d..3b4125e 100644
--- a/include/hw/xen/xen_backend.h
+++ b/include/hw/xen/xen_backend.h
@@ -74,6 +74,8 @@
int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival);
char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node);
int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival);
+int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval);
+int xenstore_read_fe_uint64(struct XenDevice *xendev, const char *node, uint64_t *uval);
const char *xenbus_strstate(enum xenbus_state state);
struct XenDevice *xen_be_find_xendev(const char *type, int dom, int dev);
diff --git a/include/qemu-common.h b/include/qemu-common.h
index ae76197..6ef8282 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -329,6 +329,7 @@
int fillc, size_t bytes);
ssize_t qemu_iovec_compare(QEMUIOVector *a, QEMUIOVector *b);
void qemu_iovec_clone(QEMUIOVector *dest, const QEMUIOVector *src, void *buf);
+void qemu_iovec_discard_back(QEMUIOVector *qiov, size_t bytes);
bool buffer_is_zero(const void *buf, size_t len);
diff --git a/iothread.c b/iothread.c
index 1fbf9f1..d9403cf 100644
--- a/iothread.c
+++ b/iothread.c
@@ -30,6 +30,7 @@
static void *iothread_run(void *opaque)
{
IOThread *iothread = opaque;
+ bool blocking;
qemu_mutex_lock(&iothread->init_done_lock);
iothread->thread_id = qemu_get_thread_id();
@@ -38,8 +39,10 @@
while (!iothread->stopping) {
aio_context_acquire(iothread->ctx);
- while (!iothread->stopping && aio_poll(iothread->ctx, true)) {
+ blocking = true;
+ while (!iothread->stopping && aio_poll(iothread->ctx, blocking)) {
/* Progress was made, keep going */
+ blocking = false;
}
aio_context_release(iothread->ctx);
}
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 07a00da..609b27c 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -118,7 +118,7 @@
IOCTL(SIOCSIFMEM, IOC_W, MK_PTR(MK_STRUCT(STRUCT_ptr_ifreq)))
IOCTL(SIOCADDMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCDELMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
- IOCTL(SIOCGIFINDEX, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
+ IOCTL(SIOCGIFINDEX, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
IOCTL(SIOCSIFLINK, 0, TYPE_NULL)
IOCTL_SPECIAL(SIOCGIFCONF, IOC_W | IOC_R, do_ioctl_ifconf,
MK_PTR(MK_STRUCT(STRUCT_ifconf)))
diff --git a/linux-user/main.c b/linux-user/main.c
index 900a17f..b453a39 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3901,11 +3901,11 @@
#elif defined TARGET_OPENRISC
cpu_model = "or1200";
#elif defined(TARGET_PPC)
-#ifdef TARGET_PPC64
- cpu_model = "970fx";
-#else
+# ifdef TARGET_PPC64
+ cpu_model = "POWER7";
+# else
cpu_model = "750";
-#endif
+# endif
#else
cpu_model = "any";
#endif
diff --git a/linux-user/signal.c b/linux-user/signal.c
index f3b4378..1141054 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1305,7 +1305,7 @@
/*
* This is the X/Open sanctioned signal stack switching.
*/
- if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
+ if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
}
@@ -3509,8 +3509,9 @@
{
abi_ulong sp = env->regs[1];
- if ((ka->sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
+ if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+ }
return ((sp - frame_size) & -8UL);
}
@@ -3891,7 +3892,7 @@
/* redzone */
/* This is the X/Open sanctioned signal stack switching. */
- if ((ka->sa_flags & SA_ONSTACK) != 0 && !onsigstack) {
+ if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5a272d3..a50229d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1140,6 +1140,13 @@
memcpy(addr, target_saddr, len);
addr->sa_family = sa_family;
+ if (sa_family == AF_PACKET) {
+ struct target_sockaddr_ll *lladdr;
+
+ lladdr = (struct target_sockaddr_ll *)addr;
+ lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
+ lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
+ }
unlock_user(target_saddr, target_addr, 0);
return 0;
@@ -1497,6 +1504,25 @@
unlock_user_struct(tfprog, optval_addr, 1);
return ret;
}
+ case TARGET_SO_BINDTODEVICE:
+ {
+ char *dev_ifname, *addr_ifname;
+
+ if (optlen > IFNAMSIZ - 1) {
+ optlen = IFNAMSIZ - 1;
+ }
+ dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1);
+ if (!dev_ifname) {
+ return -TARGET_EFAULT;
+ }
+ optname = SO_BINDTODEVICE;
+ addr_ifname = alloca(IFNAMSIZ);
+ memcpy(addr_ifname, dev_ifname, optlen);
+ addr_ifname[optlen] = 0;
+ ret = get_errno(setsockopt(sockfd, level, optname, addr_ifname, optlen));
+ unlock_user (dev_ifname, optval_addr, 0);
+ return ret;
+ }
/* Options with 'int' argument. */
case TARGET_SO_DEBUG:
optname = SO_DEBUG;
@@ -1958,7 +1984,7 @@
return -TARGET_EINVAL;
}
- addr = alloca(addrlen);
+ addr = alloca(addrlen+1);
ret = target_to_host_sockaddr(addr, target_addr, addrlen);
if (ret)
@@ -1979,7 +2005,7 @@
if (msgp->msg_name) {
msg.msg_namelen = tswap32(msgp->msg_namelen);
- msg.msg_name = alloca(msg.msg_namelen);
+ msg.msg_name = alloca(msg.msg_namelen+1);
ret = target_to_host_sockaddr(msg.msg_name, tswapal(msgp->msg_name),
msg.msg_namelen);
if (ret) {
@@ -2242,7 +2268,7 @@
if (!host_msg)
return -TARGET_EFAULT;
if (target_addr) {
- addr = alloca(addrlen);
+ addr = alloca(addrlen+1);
ret = target_to_host_sockaddr(addr, target_addr, addrlen);
if (ret) {
unlock_user(host_msg, msg, 0);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 8563027..c9e6323 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -121,6 +121,16 @@
uint8_t sa_data[14];
};
+struct target_sockaddr_ll {
+ uint16_t sll_family; /* Always AF_PACKET */
+ uint16_t sll_protocol; /* Physical layer protocol */
+ int sll_ifindex; /* Interface number */
+ uint16_t sll_hatype; /* ARP hardware type */
+ uint8_t sll_pkttype; /* Packet type */
+ uint8_t sll_halen; /* Length of address */
+ uint8_t sll_addr[8]; /* Physical layer address */
+};
+
struct target_sock_filter {
abi_ushort code;
uint8_t jt;
diff --git a/main-loop.c b/main-loop.c
index 8a85493..3cc79f8 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -498,24 +498,3 @@
{
return aio_bh_new(qemu_aio_context, cb, opaque);
}
-
-bool qemu_aio_wait(void)
-{
- return aio_poll(qemu_aio_context, true);
-}
-
-#ifdef CONFIG_POSIX
-void qemu_aio_set_fd_handler(int fd,
- IOHandler *io_read,
- IOHandler *io_write,
- void *opaque)
-{
- aio_set_fd_handler(qemu_aio_context, fd, io_read, io_write, opaque);
-}
-#endif
-
-void qemu_aio_set_event_notifier(EventNotifier *notifier,
- EventNotifierHandler *io_read)
-{
- aio_set_event_notifier(qemu_aio_context, notifier, io_read);
-}
diff --git a/pc-bios/README b/pc-bios/README
index 49cdacf..edfadd7 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -17,7 +17,7 @@
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
implementation for certain IBM POWER hardware. The sources are at
https://github.com/aik/SLOF, and the image currently in qemu is
- built from git tag qemu-slof-20140404.
+ built from git tag qemu-slof-20140630.
- sgabios (the Serial Graphics Adapter option ROM) provides a means for
legacy x86 software to communicate with an attached serial console as
diff --git a/pc-bios/ppc_rom.bin b/pc-bios/ppc_rom.bin
index e7f7693..174a247 100644
--- a/pc-bios/ppc_rom.bin
+++ b/pc-bios/ppc_rom.bin
Binary files differ
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
index 603e19e..e3ea0d5 100644
--- a/pc-bios/s390-ccw.img
+++ b/pc-bios/s390-ccw.img
Binary files differ
diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index fa54abb..f175679 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -51,6 +51,8 @@
static void jump_to_IPL_code(uint64_t address)
{
+ /* store the subsystem information _after_ the bootmap was loaded */
+ write_subsystem_identification();
/*
* The IPL PSW is at address 0. We also must not overwrite the
* content of non-BIOS memory after we loaded the guest, so we
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index dbfb40e..f9ec215 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -13,6 +13,22 @@
char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
uint64_t boot_value;
+struct subchannel_id blk_schid = { .one = 1 };
+
+/*
+ * Priniciples of Operations (SA22-7832-09) chapter 17 requires that
+ * a subsystem-identification is at 184-187 and bytes 188-191 are zero
+ * after list-directed-IPL and ccw-IPL.
+ */
+void write_subsystem_identification(void)
+{
+ struct subchannel_id *schid = (struct subchannel_id *) 184;
+ uint32_t *zeroes = (uint32_t *) 188;
+
+ *schid = blk_schid;
+ *zeroes = 0;
+}
+
void virtio_panic(const char *string)
{
@@ -23,7 +39,6 @@
static void virtio_setup(uint64_t dev_info)
{
- struct subchannel_id blk_schid = { .one = 1 };
struct schib schib;
int i;
int r;
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index 959aed0..2b773de 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -50,6 +50,7 @@
/* main.c */
void virtio_panic(const char *string);
+void write_subsystem_identification(void);
/* sclp-ascii.c */
void sclp_print(const char *string);
diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin
index 972e012..69b0a5d 100644
--- a/pc-bios/slof.bin
+++ b/pc-bios/slof.bin
Binary files differ
diff --git a/qemu-char.c b/qemu-char.c
index 55e372c..7acc03f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1089,6 +1089,7 @@
/* Protected by the CharDriverState chr_write_lock. */
int connected;
guint timer_tag;
+ guint open_tag;
} PtyCharDriver;
static void pty_chr_update_read_handler_locked(CharDriverState *chr);
@@ -1101,6 +1102,7 @@
qemu_mutex_lock(&chr->chr_write_lock);
s->timer_tag = 0;
+ s->open_tag = 0;
if (!s->connected) {
/* Next poll ... */
pty_chr_update_read_handler_locked(chr);
@@ -1203,12 +1205,26 @@
return TRUE;
}
+static gboolean qemu_chr_be_generic_open_func(gpointer opaque)
+{
+ CharDriverState *chr = opaque;
+ PtyCharDriver *s = chr->opaque;
+
+ s->open_tag = 0;
+ qemu_chr_be_generic_open(chr);
+ return FALSE;
+}
+
/* Called with chr_write_lock held. */
static void pty_chr_state(CharDriverState *chr, int connected)
{
PtyCharDriver *s = chr->opaque;
if (!connected) {
+ if (s->open_tag) {
+ g_source_remove(s->open_tag);
+ s->open_tag = 0;
+ }
remove_fd_in_watch(chr);
s->connected = 0;
/* (re-)connect poll interval for idle guests: once per second.
@@ -1221,8 +1237,9 @@
s->timer_tag = 0;
}
if (!s->connected) {
+ g_assert(s->open_tag == 0);
s->connected = 1;
- qemu_chr_be_generic_open(chr);
+ s->open_tag = g_idle_add(qemu_chr_be_generic_open_func, chr);
}
if (!chr->fd_in_tag) {
chr->fd_in_tag = io_add_watch_poll(s->fd, pty_chr_read_poll,
@@ -1236,7 +1253,8 @@
PtyCharDriver *s = chr->opaque;
int fd;
- remove_fd_in_watch(chr);
+ qemu_mutex_lock(&chr->chr_write_lock);
+ pty_chr_state(chr, 0);
fd = g_io_channel_unix_get_fd(s->fd);
g_io_channel_unref(s->fd);
close(fd);
@@ -1244,6 +1262,7 @@
g_source_remove(s->timer_tag);
s->timer_tag = 0;
}
+ qemu_mutex_unlock(&chr->chr_write_lock);
g_free(s);
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
diff --git a/qemu-doc.texi b/qemu-doc.texi
index ad92c85..551619a 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -590,7 +590,7 @@
This option can only be enabled if @code{compat=1.1} is specified.
@item nocow
-If this option is set to @code{on}, it will trun off COW of the file. It's only
+If this option is set to @code{on}, it will turn off COW of the file. It's only
valid on btrfs, no effect on other file systems.
Btrfs has low performance when hosting a VM image file, even more when the guest
@@ -603,7 +603,7 @@
Note: this option is only valid to new or empty files. If there is an existing
file which is COW and has data blocks already, it couldn't be changed to NOCOW
by setting @code{nocow=on}. One can issue @code{lsattr filename} to check if
-the NOCOW flag is set or not (Capitabl 'C' is NOCOW flag).
+the NOCOW flag is set or not (Capital 'C' is NOCOW flag).
@end table
diff --git a/qemu-img.texi b/qemu-img.texi
index 8496f3b..514be90 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -475,7 +475,7 @@
This option can only be enabled if @code{compat=1.1} is specified.
@item nocow
-If this option is set to @code{on}, it will trun off COW of the file. It's only
+If this option is set to @code{on}, it will turn off COW of the file. It's only
valid on btrfs, no effect on other file systems.
Btrfs has low performance when hosting a VM image file, even more when the guest
@@ -488,7 +488,7 @@
Note: this option is only valid to new or empty files. If there is an existing
file which is COW and has data blocks already, it couldn't be changed to NOCOW
by setting @code{nocow=on}. One can issue @code{lsattr filename} to check if
-the NOCOW flag is set or not (Capitabl 'C' is NOCOW flag).
+the NOCOW flag is set or not (Capital 'C' is NOCOW flag).
@end table
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 60c1ceb..c503fc6 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -483,7 +483,7 @@
co = qemu_coroutine_create(co_write_zeroes_entry);
qemu_coroutine_enter(co, &data);
while (!data.done) {
- qemu_aio_wait();
+ aio_poll(bdrv_get_aio_context(bs), true);
}
if (data.ret < 0) {
return data.ret;
@@ -2027,7 +2027,7 @@
static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
{
while (!bdrv_debug_is_suspended(bs, argv[1])) {
- qemu_aio_wait();
+ aio_poll(bdrv_get_aio_context(bs), true);
}
return 0;
diff --git a/qmp.c b/qmp.c
index dca6efb..0d2553a 100644
--- a/qmp.c
+++ b/qmp.c
@@ -433,11 +433,57 @@
return ret;
}
+/* Return a DevicePropertyInfo for a qdev property.
+ *
+ * If a qdev property with the given name does not exist, use the given default
+ * type. If the qdev property info should not be shown, return NULL.
+ *
+ * The caller must free the return value.
+ */
+static DevicePropertyInfo *make_device_property_info(ObjectClass *klass,
+ const char *name,
+ const char *default_type)
+{
+ DevicePropertyInfo *info;
+ Property *prop;
+
+ do {
+ for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
+ if (strcmp(name, prop->name) != 0) {
+ continue;
+ }
+
+ /*
+ * TODO Properties without a parser are just for dirty hacks.
+ * qdev_prop_ptr is the only such PropertyInfo. It's marked
+ * for removal. This conditional should be removed along with
+ * it.
+ */
+ if (!prop->info->set) {
+ return NULL; /* no way to set it, don't show */
+ }
+
+ info = g_malloc0(sizeof(*info));
+ info->name = g_strdup(prop->name);
+ info->type = g_strdup(prop->info->legacy_name ?: prop->info->name);
+ return info;
+ }
+ klass = object_class_get_parent(klass);
+ } while (klass != object_class_by_name(TYPE_DEVICE));
+
+ /* Not a qdev property, use the default type */
+ info = g_malloc0(sizeof(*info));
+ info->name = g_strdup(name);
+ info->type = g_strdup(default_type);
+ return info;
+}
+
DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
Error **errp)
{
ObjectClass *klass;
- Property *prop;
+ Object *obj;
+ ObjectProperty *prop;
DevicePropertyInfoList *prop_list = NULL;
klass = object_class_by_name(typename);
@@ -453,32 +499,39 @@
return NULL;
}
- do {
- for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
- DevicePropertyInfoList *entry;
- DevicePropertyInfo *info;
+ obj = object_new(typename);
- /*
- * TODO Properties without a parser are just for dirty hacks.
- * qdev_prop_ptr is the only such PropertyInfo. It's marked
- * for removal. This conditional should be removed along with
- * it.
- */
- if (!prop->info->set) {
- continue; /* no way to set it, don't show */
- }
+ QTAILQ_FOREACH(prop, &obj->properties, node) {
+ DevicePropertyInfo *info;
+ DevicePropertyInfoList *entry;
- info = g_malloc0(sizeof(*info));
- info->name = g_strdup(prop->name);
- info->type = g_strdup(prop->info->legacy_name ?: prop->info->name);
-
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = prop_list;
- prop_list = entry;
+ /* Skip Object and DeviceState properties */
+ if (strcmp(prop->name, "type") == 0 ||
+ strcmp(prop->name, "realized") == 0 ||
+ strcmp(prop->name, "hotpluggable") == 0 ||
+ strcmp(prop->name, "parent_bus") == 0) {
+ continue;
}
- klass = object_class_get_parent(klass);
- } while (klass != object_class_by_name(TYPE_DEVICE));
+
+ /* Skip legacy properties since they are just string versions of
+ * properties that we already list.
+ */
+ if (strstart(prop->name, "legacy-", NULL)) {
+ continue;
+ }
+
+ info = make_device_property_info(klass, prop->name, prop->type);
+ if (!info) {
+ continue;
+ }
+
+ entry = g_malloc0(sizeof(*entry));
+ entry->value = info;
+ entry->next = prop_list;
+ prop_list = entry;
+ }
+
+ object_unref(obj);
return prop_list;
}
diff --git a/roms/SLOF b/roms/SLOF
index c90b50b..f284ab3 160000
--- a/roms/SLOF
+++ b/roms/SLOF
@@ -1 +1 @@
-Subproject commit c90b50b5055f976a0da3c032f26fb80157292adc
+Subproject commit f284ab3f03ae69a20e1ae966f6ddf76da33cbf72
diff --git a/roms/openhackware b/roms/openhackware
index 1af7e55..c559da7 160000
--- a/roms/openhackware
+++ b/roms/openhackware
@@ -1 +1 @@
-Subproject commit 1af7e55425e58a6dcb5133b092fcf16f8c654fb9
+Subproject commit c559da7c8eec5e45ef1f67978827af6f0b9546f5
diff --git a/scripts/vmstate-static-checker.py b/scripts/vmstate-static-checker.py
index 1604e68..3bae769 100755
--- a/scripts/vmstate-static-checker.py
+++ b/scripts/vmstate-static-checker.py
@@ -79,6 +79,18 @@
return False
+def get_changed_sec_name(sec):
+ # Section names can change -- see commit 292b1634 for an example.
+ changes = {
+ "ICH9 LPC": "ICH9-LPC",
+ }
+
+ for item in changes:
+ if item == sec:
+ return changes[item]
+ if changes[item] == sec:
+ return item
+ return ""
def exists_in_substruct(fields, item):
# Some QEMU versions moved a few fields inside a substruct. This
@@ -314,13 +326,18 @@
dest_data = temp
for sec in src_data:
- if not sec in dest_data:
- print "Section \"" + sec + "\" does not exist in dest"
- bump_taint()
- continue
+ dest_sec = sec
+ if not dest_sec in dest_data:
+ # Either the section name got changed, or the section
+ # doesn't exist in dest.
+ dest_sec = get_changed_sec_name(sec)
+ if not dest_sec in dest_data:
+ print "Section \"" + sec + "\" does not exist in dest"
+ bump_taint()
+ continue
s = src_data[sec]
- d = dest_data[sec]
+ d = dest_data[dest_sec]
if sec == "vmschkmachine":
check_machine_type(s, d)
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index eaee944..ee4fbb1 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -72,10 +72,6 @@
uint64_t *cpreg_indexes;
/* Values of the registers (cpreg_indexes[i]'s value is cpreg_values[i]) */
uint64_t *cpreg_values;
- /* When using KVM, keeps a copy of the initial state of the VCPU,
- * so that on reset we can feed the reset values back into the kernel.
- */
- uint64_t *cpreg_reset_values;
/* Length of the indexes, values, reset_values arrays */
int32_t cpreg_array_len;
/* These are used only for migration: incoming data arrives in
diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c
index 068af7d..5ec4eb1 100644
--- a/target-arm/kvm32.c
+++ b/target-arm/kvm32.c
@@ -270,13 +270,6 @@
goto out;
}
- /* Save a copy of the initial register values so that we can
- * feed it back to the kernel on VCPU reset.
- */
- cpu->cpreg_reset_values = g_memdup(cpu->cpreg_values,
- cpu->cpreg_array_len *
- sizeof(cpu->cpreg_values[0]));
-
out:
g_free(rlp);
return ret;
@@ -518,11 +511,9 @@
void kvm_arm_reset_vcpu(ARMCPU *cpu)
{
- /* Feed the kernel back its initial register state */
- memmove(cpu->cpreg_values, cpu->cpreg_reset_values,
- cpu->cpreg_array_len * sizeof(cpu->cpreg_values[0]));
-
- if (!write_list_to_kvmstate(cpu)) {
- abort();
- }
+ /* Re-init VCPU so that all registers are set to
+ * their respective reset values.
+ */
+ kvm_arm_vcpu_init(CPU(cpu));
+ write_kvmstate_to_list(cpu);
}
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 45c662d..6d008ab 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -241,7 +241,7 @@
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
+ "kvmclock-stable-bit", NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
};
diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index 844e5bb..97fd51a 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -61,6 +61,13 @@
void kvm_mips_reset_vcpu(MIPSCPU *cpu)
{
+ CPUMIPSState *env = &cpu->env;
+
+ if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+ fprintf(stderr, "Warning: FPU not supported with KVM, disabling\n");
+ env->CP0_Config1 &= ~(1 << CP0C1_FP);
+ }
+
DPRINTF("%s\n", __func__);
}
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 2f91959..d7b8c4d 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -28,6 +28,7 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "sysemu/kvm.h"
#define MIPS_DEBUG_DISAS 0
//#define MIPS_DEBUG_SIGN_EXTENSIONS
@@ -16076,7 +16077,12 @@
env->CP0_Random = env->tlb->nb_tlb - 1;
env->tlb->tlb_in_use = env->tlb->nb_tlb;
env->CP0_Wired = 0;
- env->CP0_EBase = 0x80000000 | (cs->cpu_index & 0x3FF);
+ env->CP0_EBase = (cs->cpu_index & 0x3FF);
+ if (kvm_enabled()) {
+ env->CP0_EBase |= 0x40000000;
+ } else {
+ env->CP0_EBase |= 0x80000000;
+ }
env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
/* vectored interrupts not implemented, timer on int 7,
no performance counters. */
diff --git a/target-ppc/cpu-models.c b/target-ppc/cpu-models.c
index 9a91af9..52ac6ec 100644
--- a/target-ppc/cpu-models.c
+++ b/target-ppc/cpu-models.c
@@ -44,7 +44,6 @@
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); \
\
pcc->pvr = _pvr; \
- pcc->pvr_mask = CPU_POWERPC_DEFAULT_MASK; \
pcc->svr = _svr; \
dc->desc = _desc; \
} \
@@ -1136,9 +1135,9 @@
#endif
POWERPC_DEF("POWER7_v2.3", CPU_POWERPC_POWER7_v23, POWER7,
"POWER7 v2.3")
- POWERPC_DEF("POWER7+_v2.1", CPU_POWERPC_POWER7P_v21, POWER7P,
+ POWERPC_DEF("POWER7+_v2.1", CPU_POWERPC_POWER7P_v21, POWER7,
"POWER7+ v2.1")
- POWERPC_DEF("POWER8E_v1.0", CPU_POWERPC_POWER8E_v10, POWER8E,
+ POWERPC_DEF("POWER8E_v1.0", CPU_POWERPC_POWER8E_v10, POWER8,
"POWER8E v1.0")
POWERPC_DEF("POWER8_v1.0", CPU_POWERPC_POWER8_v10, POWER8,
"POWER8 v1.0")
diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h
index c39d03a..290a759 100644
--- a/target-ppc/cpu-models.h
+++ b/target-ppc/cpu-models.h
@@ -39,7 +39,6 @@
/*****************************************************************************/
/* PVR definitions for most known PowerPC */
enum {
- CPU_POWERPC_DEFAULT_MASK = 0xFFFFFFFF,
/* PowerPC 401 family */
/* Generic PowerPC 401 */
#define CPU_POWERPC_401 CPU_POWERPC_401G2
@@ -553,17 +552,14 @@
CPU_POWERPC_POWER6 = 0x003E0000,
CPU_POWERPC_POWER6_5 = 0x0F000001, /* POWER6 in POWER5 mode */
CPU_POWERPC_POWER6A = 0x0F000002,
+ CPU_POWERPC_POWER_SERVER_MASK = 0xFFFF0000,
CPU_POWERPC_POWER7_BASE = 0x003F0000,
- CPU_POWERPC_POWER7_MASK = 0xFFFF0000,
CPU_POWERPC_POWER7_v23 = 0x003F0203,
CPU_POWERPC_POWER7P_BASE = 0x004A0000,
- CPU_POWERPC_POWER7P_MASK = 0xFFFF0000,
CPU_POWERPC_POWER7P_v21 = 0x004A0201,
CPU_POWERPC_POWER8E_BASE = 0x004B0000,
- CPU_POWERPC_POWER8E_MASK = 0xFFFF0000,
CPU_POWERPC_POWER8E_v10 = 0x004B0100,
CPU_POWERPC_POWER8_BASE = 0x004D0000,
- CPU_POWERPC_POWER8_MASK = 0xFFFF0000,
CPU_POWERPC_POWER8_v10 = 0x004D0100,
CPU_POWERPC_970 = 0x00390202,
CPU_POWERPC_970FX_v10 = 0x00391100,
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index f1f0a52..0fee36f 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -56,7 +56,7 @@
void (*parent_reset)(CPUState *cpu);
uint32_t pvr;
- uint32_t pvr_mask;
+ bool (*pvr_match)(struct PowerPCCPUClass *pcc, uint32_t pvr);
uint64_t pcr_mask;
uint32_t svr;
uint64_t insns_flags;
diff --git a/target-ppc/gdbstub.c b/target-ppc/gdbstub.c
index 694d303..14675f4 100644
--- a/target-ppc/gdbstub.c
+++ b/target-ppc/gdbstub.c
@@ -83,16 +83,24 @@
}
}
-
-static void ppc_gdb_swap_register(uint8_t *mem_buf, int n, int len)
+/* We need to present the registers to gdb in the "current" memory ordering.
+ For user-only mode we get this for free; TARGET_WORDS_BIGENDIAN is set to
+ the proper ordering for the binary, and cannot be changed.
+ For system mode, TARGET_WORDS_BIGENDIAN is always set, and we must check
+ the current mode of the chip to see if we're running in little-endian. */
+static void maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len)
{
- if (len == 4) {
+#ifndef CONFIG_USER_ONLY
+ if (!msr_le) {
+ /* do nothing */
+ } else if (len == 4) {
bswap32s((uint32_t *)mem_buf);
} else if (len == 8) {
bswap64s((uint64_t *)mem_buf);
} else {
g_assert_not_reached();
}
+#endif
}
/* Old gdb always expects FP registers. Newer (xml-aware) gdb only
@@ -150,10 +158,7 @@
break;
}
}
- if (msr_le) {
- /* If cpu is in LE mode, convert memory contents to LE. */
- ppc_gdb_swap_register(mem_buf, n, r);
- }
+ maybe_bswap_register(env, mem_buf, r);
return r;
}
@@ -209,10 +214,7 @@
break;
}
}
- if (msr_le) {
- /* If cpu is in LE mode, convert memory contents to LE. */
- ppc_gdb_swap_register(mem_buf, n, r);
- }
+ maybe_bswap_register(env, mem_buf, r);
return r;
}
@@ -225,10 +227,7 @@
if (!r) {
return r;
}
- if (msr_le) {
- /* If cpu is in LE mode, convert memory contents to LE. */
- ppc_gdb_swap_register(mem_buf, n, r);
- }
+ maybe_bswap_register(env, mem_buf, r);
if (n < 32) {
/* gprs */
env->gpr[n] = ldtul_p(mem_buf);
@@ -278,10 +277,7 @@
if (!r) {
return r;
}
- if (msr_le) {
- /* If cpu is in LE mode, convert memory contents to LE. */
- ppc_gdb_swap_register(mem_buf, n, r);
- }
+ maybe_bswap_register(env, mem_buf, r);
if (n < 32) {
/* gprs */
env->gpr[n] = ldq_p(mem_buf);
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 2d87108..42718f7 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1580,13 +1580,11 @@
}
#ifdef TARGET_PPC64
-off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
+off_t kvmppc_alloc_rma(void **rma)
{
- void *rma;
off_t size;
int fd;
struct kvm_allocate_rma ret;
- MemoryRegion *rma_region;
/* If cap_ppc_rma == 0, contiguous RMA allocation is not supported
* if cap_ppc_rma == 1, contiguous RMA allocation is supported, but
@@ -1609,17 +1607,12 @@
size = MIN(ret.rma_size, 256ul << 20);
- rma = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- if (rma == MAP_FAILED) {
+ *rma = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (*rma == MAP_FAILED) {
fprintf(stderr, "KVM: Error mapping RMA: %s\n", strerror(errno));
return -1;
};
- rma_region = g_new(MemoryRegion, 1);
- memory_region_init_ram_ptr(rma_region, NULL, name, size, rma);
- vmstate_register_ram_global(rma_region);
- memory_region_add_subregion(sysmem, 0, rma_region);
-
return size;
}
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 1118122..d9516e7 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -31,7 +31,7 @@
int kvmppc_set_tcr(PowerPCCPU *cpu);
int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu);
#ifndef CONFIG_USER_ONLY
-off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
+off_t kvmppc_alloc_rma(void **rma);
bool kvmppc_spapr_use_multitce(void);
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd,
bool vfio_accel);
@@ -134,7 +134,7 @@
}
#ifndef CONFIG_USER_ONLY
-static inline off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
+static inline off_t kvmppc_alloc_rma(void **rma)
{
return 0;
}
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 4d6b1e2..4a34a73 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -897,10 +897,10 @@
/* TLB check function for MAS based SoftTLBs */
static int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
- hwaddr *raddrp,
- target_ulong address, uint32_t pid)
+ hwaddr *raddrp, target_ulong address,
+ uint32_t pid)
{
- target_ulong mask;
+ hwaddr mask;
uint32_t tlb_pid;
if (!msr_cm) {
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 2ab2810..48177ed 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8062,6 +8062,17 @@
init_proc_book3s_64(env, BOOK3S_CPU_POWER7);
}
+static bool ppc_pvr_match_power7(PowerPCCPUClass *pcc, uint32_t pvr)
+{
+ if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER7P_BASE) {
+ return true;
+ }
+ if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER7_BASE) {
+ return true;
+ }
+ return false;
+}
+
POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
@@ -8070,69 +8081,7 @@
dc->fw_name = "PowerPC,POWER7";
dc->desc = "POWER7";
dc->props = powerpc_servercpu_properties;
- pcc->pvr = CPU_POWERPC_POWER7_BASE;
- pcc->pvr_mask = CPU_POWERPC_POWER7_MASK;
- pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
- pcc->init_proc = init_proc_POWER7;
- pcc->check_pow = check_pow_nocheck;
- pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
- PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
- PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
- PPC_FLOAT_FRSQRTES |
- PPC_FLOAT_STFIWX |
- PPC_FLOAT_EXT |
- PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
- PPC_MEM_SYNC | PPC_MEM_EIEIO |
- PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
- PPC_64B | PPC_ALTIVEC |
- PPC_SEGMENT_64B | PPC_SLBI |
- PPC_POPCNTB | PPC_POPCNTWD;
- pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX | PPC2_ISA205 |
- PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 |
- PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 |
- PPC2_FP_TST_ISA206;
- pcc->msr_mask = (1ull << MSR_SF) |
- (1ull << MSR_VR) |
- (1ull << MSR_VSX) |
- (1ull << MSR_EE) |
- (1ull << MSR_PR) |
- (1ull << MSR_FP) |
- (1ull << MSR_ME) |
- (1ull << MSR_FE0) |
- (1ull << MSR_SE) |
- (1ull << MSR_DE) |
- (1ull << MSR_FE1) |
- (1ull << MSR_IR) |
- (1ull << MSR_DR) |
- (1ull << MSR_PMM) |
- (1ull << MSR_RI) |
- (1ull << MSR_LE);
- pcc->mmu_model = POWERPC_MMU_2_06;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
-#endif
- pcc->excp_model = POWERPC_EXCP_POWER7;
- pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
- pcc->bfd_mach = bfd_mach_ppc64;
- pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
- POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
- POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR |
- POWERPC_FLAG_VSX;
- pcc->l1_dcache_size = 0x8000;
- pcc->l1_icache_size = 0x8000;
- pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
-}
-
-POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
- PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-
- dc->fw_name = "PowerPC,POWER7+";
- dc->desc = "POWER7+";
- dc->props = powerpc_servercpu_properties;
- pcc->pvr = CPU_POWERPC_POWER7P_BASE;
- pcc->pvr_mask = CPU_POWERPC_POWER7P_MASK;
+ pcc->pvr_match = ppc_pvr_match_power7;
pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
pcc->init_proc = init_proc_POWER7;
pcc->check_pow = check_pow_nocheck;
@@ -8189,16 +8138,26 @@
init_proc_book3s_64(env, BOOK3S_CPU_POWER8);
}
-POWERPC_FAMILY(POWER8E)(ObjectClass *oc, void *data)
+static bool ppc_pvr_match_power8(PowerPCCPUClass *pcc, uint32_t pvr)
+{
+ if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER8E_BASE) {
+ return true;
+ }
+ if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER8_BASE) {
+ return true;
+ }
+ return false;
+}
+
+POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
dc->fw_name = "PowerPC,POWER8";
- dc->desc = "POWER8E";
+ dc->desc = "POWER8";
dc->props = powerpc_servercpu_properties;
- pcc->pvr = CPU_POWERPC_POWER8E_BASE;
- pcc->pvr_mask = CPU_POWERPC_POWER8E_MASK;
+ pcc->pvr_match = ppc_pvr_match_power8;
pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
pcc->init_proc = init_proc_POWER8;
pcc->check_pow = check_pow_nocheck;
@@ -8252,18 +8211,6 @@
pcc->l1_icache_size = 0x8000;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
}
-
-POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
- PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-
- ppc_POWER8E_cpu_family_class_init(oc, data);
-
- dc->desc = "POWER8";
- pcc->pvr = CPU_POWERPC_POWER8_BASE;
- pcc->pvr_mask = CPU_POWERPC_POWER8_MASK;
-}
#endif /* defined (TARGET_PPC64) */
@@ -9151,29 +9098,21 @@
int ppc_get_compat_smt_threads(PowerPCCPU *cpu)
{
- int ret = smp_threads;
- PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ int ret = MIN(smp_threads, kvmppc_smt_threads());
switch (cpu->cpu_version) {
case CPU_POWERPC_LOGICAL_2_05:
- ret = 2;
+ ret = MIN(ret, 2);
break;
case CPU_POWERPC_LOGICAL_2_06:
- ret = 4;
+ ret = MIN(ret, 4);
break;
case CPU_POWERPC_LOGICAL_2_07:
- ret = 8;
- break;
- default:
- if (pcc->pcr_mask & PCR_COMPAT_2_06) {
- ret = 4;
- } else if (pcc->pcr_mask & PCR_COMPAT_2_05) {
- ret = 2;
- }
+ ret = MIN(ret, 8);
break;
}
- return MIN(ret, smp_threads);
+ return ret;
}
int ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version)
@@ -9245,7 +9184,6 @@
ObjectClass *oc = (ObjectClass *)a;
uint32_t pvr = *(uint32_t *)b;
PowerPCCPUClass *pcc = (PowerPCCPUClass *)a;
- gint ret;
/* -cpu host does a PVR lookup during construction */
if (unlikely(strcmp(object_class_get_name(oc),
@@ -9257,9 +9195,11 @@
return -1;
}
- ret = (((pcc->pvr & pcc->pvr_mask) == (pvr & pcc->pvr_mask)) ? 0 : -1);
+ if (pcc->pvr_match(pcc, pvr)) {
+ return 0;
+ }
- return ret;
+ return -1;
}
PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr)
@@ -9551,6 +9491,10 @@
#endif
#if !defined(TARGET_WORDS_BIGENDIAN)
msr |= (target_ulong)1 << MSR_LE; /* Little-endian user mode */
+ if (!((env->msr_mask >> MSR_LE) & 1)) {
+ fprintf(stderr, "Selected CPU does not support little-endian.\n");
+ exit(1);
+ }
#endif
#endif
@@ -9656,6 +9600,11 @@
}
}
+static bool ppc_pvr_match_default(PowerPCCPUClass *pcc, uint32_t pvr)
+{
+ return pcc->pvr == pvr;
+}
+
static void ppc_cpu_class_init(ObjectClass *oc, void *data)
{
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
@@ -9663,8 +9612,7 @@
DeviceClass *dc = DEVICE_CLASS(oc);
pcc->parent_realize = dc->realize;
- pcc->pvr = CPU_POWERPC_DEFAULT_MASK;
- pcc->pvr_mask = CPU_POWERPC_DEFAULT_MASK;
+ pcc->pvr_match = ppc_pvr_match_default;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always;
dc->realize = ppc_cpu_realizefn;
dc->unrealize = ppc_cpu_unrealizefn;
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index a6e587b..a32d91a 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -207,6 +207,7 @@
CPUS390XState *env = &cpu->env;
struct kvm_sregs sregs;
struct kvm_regs regs;
+ struct kvm_fpu fpu;
int r;
int i;
@@ -229,6 +230,17 @@
}
}
+ /* Floating point */
+ for (i = 0; i < 16; i++) {
+ fpu.fprs[i] = env->fregs[i].ll;
+ }
+ fpu.fpc = env->fpc;
+
+ r = kvm_vcpu_ioctl(cs, KVM_SET_FPU, &fpu);
+ if (r < 0) {
+ return r;
+ }
+
/* Do we need to save more than that? */
if (level == KVM_PUT_RUNTIME_STATE) {
return 0;
@@ -296,6 +308,7 @@
CPUS390XState *env = &cpu->env;
struct kvm_sregs sregs;
struct kvm_regs regs;
+ struct kvm_fpu fpu;
int i, r;
/* get the PSW */
@@ -336,6 +349,16 @@
}
}
+ /* Floating point */
+ r = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu);
+ if (r < 0) {
+ return r;
+ }
+ for (i = 0; i < 16; i++) {
+ env->fregs[i].ll = fpu.fprs[i];
+ }
+ env->fpc = fpu.fpc;
+
/* The prefix */
if (cap_sync_regs && cs->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) {
env->psa = cs->kvm_run->s.regs.prefix;
diff --git a/tests/Makefile b/tests/Makefile
index 1fcd633..fa25c70 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -158,7 +158,7 @@
gcov-files-i386-y += hw/usb/hcd-uhci.c
gcov-files-i386-y += hw/usb/dev-hid.c
gcov-files-i386-y += hw/usb/dev-storage.c
-check-qtest-i386-$(CONFIG_POSIX) += tests/vhost-user-test$(EXESUF)
+check-qtest-i386-$(CONFIG_LINUX) += tests/vhost-user-test$(EXESUF)
check-qtest-x86_64-y = $(check-qtest-i386-y)
gcov-files-i386-y += i386-softmmu/hw/timer/mc146818rtc.c
gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
index bf741a4..4adf400 100644
--- a/tests/libqos/pci-pc.c
+++ b/tests/libqos/pci-pc.c
@@ -41,7 +41,7 @@
if (port < 0x10000) {
value = inb(port);
} else {
- memread(port, &value, sizeof(value));
+ value = readb(port);
}
return value;
@@ -55,7 +55,7 @@
if (port < 0x10000) {
value = inw(port);
} else {
- memread(port, &value, sizeof(value));
+ value = readw(port);
}
return value;
@@ -69,7 +69,7 @@
if (port < 0x10000) {
value = inl(port);
} else {
- memread(port, &value, sizeof(value));
+ value = readl(port);
}
return value;
@@ -82,7 +82,7 @@
if (port < 0x10000) {
outb(port, value);
} else {
- memwrite(port, &value, sizeof(value));
+ writeb(port, value);
}
}
@@ -93,7 +93,7 @@
if (port < 0x10000) {
outw(port, value);
} else {
- memwrite(port, &value, sizeof(value));
+ writew(port, value);
}
}
@@ -104,7 +104,7 @@
if (port < 0x10000) {
outl(port, value);
} else {
- memwrite(port, &value, sizeof(value));
+ writel(port, value);
}
}
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
index a99e4fa..d5718c5 100755
--- a/tests/qemu-iotests/028
+++ b/tests/qemu-iotests/028
@@ -33,7 +33,8 @@
_cleanup()
{
- _cleanup_test_img
+ rm -f "${TEST_IMG}.copy"
+ _cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -41,6 +42,7 @@
. ./common.rc
. ./common.filter
. ./common.pattern
+. ./common.qemu
# Any format supporting backing files except vmdk and qcow which do not support
# smaller backing files.
@@ -99,6 +101,29 @@
# Rebase it on top of its base image
$QEMU_IMG rebase -b "$TEST_IMG.base" "$TEST_IMG"
+echo
+echo block-backup
+echo
+
+qemu_comm_method="monitor"
+_launch_qemu -drive file="${TEST_IMG}",cache=${CACHEMODE},id=disk
+h=$QEMU_HANDLE
+QEMU_COMM_TIMEOUT=1
+
+_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)"
+qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs"
+_send_qemu_cmd $h 'quit' ""
+
+# Base image sectors
+TEST_IMG="${TEST_IMG}.copy" io readv $(( offset )) 512 1024 32
+
+# Image sectors
+TEST_IMG="${TEST_IMG}.copy" io readv $(( offset + 512 )) 512 1024 64
+
+# Zero sectors beyond end of base image
+TEST_IMG="${TEST_IMG}.copy" io_zero readv $(( offset + 32 * 1024 )) 512 1024 32
+
+
_check_test_img
# success, all done
diff --git a/tests/qemu-iotests/028.out b/tests/qemu-iotests/028.out
index 8affb7f..38099e4 100644
--- a/tests/qemu-iotests/028.out
+++ b/tests/qemu-iotests/028.out
@@ -465,5 +465,274 @@
read 512/512 bytes at offset 3221258752
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
+
+block-backup
+
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) d[K[Ddr[K[D[Ddri[K[D[D[Ddriv[K[D[D[D[Ddrive[K[D[D[D[D[Ddrive_[K[D[D[D[D[D[Ddrive_b[K[D[D[D[D[D[D[Ddrive_ba[K[D[D[D[D[D[D[D[Ddrive_bac[K[D[D[D[D[D[D[D[D[Ddrive_back[K[D[D[D[D[D[D[D[D[D[Ddrive_backu[K[D[D[D[D[D[D[D[D[D[D[Ddrive_backup[K[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup [K[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup d[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup di[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup dis[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /ho[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /hom[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kw[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwo[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwol[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/s[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/so[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/sou[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/sour[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/sourc[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/q[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qe[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qem[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/t[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/te[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tes[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/test[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/q[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qe[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qem[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-i[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-io[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iot[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iote[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotes[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotest[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/s[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/sc[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scra[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scrat[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scratc[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.q[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qc[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qco[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow2.[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow2.c[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow2.co[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow2.cop[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow2.copy[K
+Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=4294968832 backing_file='TEST_DIR/t.qcow2.base' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off
+(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block-[K[D[D[D[D[D[D[D[D[D[D[Dinfo block-j[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-jo[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-job[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-jobs[K
+Type backup, device disk: Completed 0 of 4294968832 bytes, speed limit 0 bytes/s
+i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block-[K[D[D[D[D[D[D[D[D[D[D[Dinfo block-j[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-jo[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-job[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-jobs[K
+No active jobs
+=== IO: pattern 195
+read 512/512 bytes at offset 3221194240
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221195264
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221196288
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221197312
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221198336
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221199360
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221200384
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221201408
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221202432
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221203456
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221204480
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221205504
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221206528
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221207552
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221208576
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221209600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221210624
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221211648
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221212672
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221213696
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221214720
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221215744
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221216768
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221217792
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221218816
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221219840
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221220864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221221888
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221222912
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221223936
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221224960
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221225984
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+=== IO: pattern 196
+read 512/512 bytes at offset 3221194752
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221195776
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221196800
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221197824
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221198848
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221199872
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221200896
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221201920
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221202944
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221203968
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221204992
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221206016
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221207040
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221208064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221209088
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221210112
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221211136
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221212160
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221213184
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221214208
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221215232
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221216256
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221217280
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221218304
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221219328
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221220352
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221221376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221222400
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221223424
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221224448
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221225472
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221226496
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221227520
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221228544
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221229568
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221230592
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221231616
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221232640
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221233664
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221234688
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221235712
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221236736
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221237760
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221238784
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221239808
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221240832
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221241856
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221242880
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221243904
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221244928
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221245952
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221246976
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221248000
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221249024
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221250048
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221251072
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221252096
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221253120
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221254144
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221255168
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221256192
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221257216
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221258240
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221259264
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+=== IO: pattern 0
+read 512/512 bytes at offset 3221227008
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221228032
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221229056
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221230080
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221231104
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221232128
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221233152
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221234176
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221235200
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221236224
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221237248
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221238272
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221239296
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221240320
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221241344
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221242368
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221243392
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221244416
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221245440
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221246464
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221247488
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221248512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221249536
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221250560
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221251584
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221252608
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221253632
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221254656
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221255680
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221256704
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221257728
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221258752
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
*** done
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index 0815e19..5dbd4ee 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -217,6 +217,11 @@
test_small_buffer2 = None
test_large_cluster = None
+class TestSingleDriveUnalignedLength(TestSingleDrive):
+ image_len = 1025 * 1024
+ test_small_buffer2 = None
+ test_large_cluster = None
+
class TestMirrorNoBacking(ImageMirroringTestCase):
image_len = 2 * 1024 * 1024 # MB
@@ -735,6 +740,9 @@
image_len = 1 * 1024 * 1024 # MB
IMAGES = [ quorum_img1, quorum_img2, quorum_img3 ]
+ def has_quorum(self):
+ return 'quorum' in iotests.qemu_img_pipe('--help')
+
def setUp(self):
self.vm = iotests.VM()
@@ -752,8 +760,9 @@
#assemble the quorum block device from the individual files
args = { "options" : { "driver": "quorum", "id": "quorum0",
"vote-threshold": 2, "children": [ "img0", "img1", "img2" ] } }
- result = self.vm.qmp("blockdev-add", **args)
- self.assert_qmp(result, 'return', {})
+ if self.has_quorum():
+ result = self.vm.qmp("blockdev-add", **args)
+ self.assert_qmp(result, 'return', {})
def tearDown(self):
@@ -766,6 +775,9 @@
pass
def test_complete(self):
+ if not self.has_quorum():
+ return
+
self.assert_no_active_block_jobs()
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
@@ -784,6 +796,9 @@
'target image does not match source after mirroring')
def test_cancel(self):
+ if not self.has_quorum():
+ return
+
self.assert_no_active_block_jobs()
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
@@ -800,6 +815,9 @@
self.vm.shutdown()
def test_cancel_after_ready(self):
+ if not self.has_quorum():
+ return
+
self.assert_no_active_block_jobs()
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
@@ -818,6 +836,9 @@
'target image does not match source after mirroring')
def test_pause(self):
+ if not self.has_quorum():
+ return
+
self.assert_no_active_block_jobs()
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
@@ -846,6 +867,9 @@
'target image does not match source after mirroring')
def test_medium_not_found(self):
+ if not self.has_quorum():
+ return
+
result = self.vm.qmp('drive-mirror', device='ide1-cd0', sync='full',
node_name='repair0',
replaces='img1',
@@ -853,6 +877,9 @@
self.assert_qmp(result, 'error/class', 'GenericError')
def test_image_not_found(self):
+ if not self.has_quorum():
+ return
+
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
node_name='repair0',
replaces='img1',
@@ -861,6 +888,9 @@
self.assert_qmp(result, 'error/class', 'GenericError')
def test_device_not_found(self):
+ if not self.has_quorum():
+ return
+
result = self.vm.qmp('drive-mirror', device='nonexistent', sync='full',
node_name='repair0',
replaces='img1',
@@ -868,6 +898,9 @@
self.assert_qmp(result, 'error/class', 'DeviceNotFound')
def test_wrong_sync_mode(self):
+ if not self.has_quorum():
+ return
+
result = self.vm.qmp('drive-mirror', device='quorum0',
node_name='repair0',
replaces='img1',
@@ -875,12 +908,18 @@
self.assert_qmp(result, 'error/class', 'GenericError')
def test_no_node_name(self):
+ if not self.has_quorum():
+ return
+
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
replaces='img1',
target=quorum_repair_img, format=iotests.imgfmt)
self.assert_qmp(result, 'error/class', 'GenericError')
def test_unexistant_replaces(self):
+ if not self.has_quorum():
+ return
+
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
node_name='repair0',
replaces='img77',
@@ -888,6 +927,9 @@
self.assert_qmp(result, 'error/class', 'GenericError')
def test_after_a_quorum_snapshot(self):
+ if not self.has_quorum():
+ return
+
result = self.vm.qmp('blockdev-snapshot-sync', node_name='img1',
snapshot_file=quorum_snapshot_file,
snapshot_node_name="snap1");
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
index 42147c0..24093bc 100644
--- a/tests/qemu-iotests/041.out
+++ b/tests/qemu-iotests/041.out
@@ -1,5 +1,5 @@
-..............................................
+......................................................
----------------------------------------------------------------------
-Ran 46 tests
+Ran 54 tests
OK
diff --git a/tests/test-aio.c b/tests/test-aio.c
index e5f8b55..4c40a49 100644
--- a/tests/test-aio.c
+++ b/tests/test-aio.c
@@ -24,14 +24,6 @@
bool auto_set;
} EventNotifierTestData;
-/* Wait until there are no more BHs or AIO requests */
-static void wait_for_aio(void)
-{
- while (aio_poll(ctx, true)) {
- /* Do nothing */
- }
-}
-
/* Wait until event notifier becomes inactive */
static void wait_until_inactive(EventNotifierTestData *data)
{
@@ -204,7 +196,9 @@
g_assert(aio_poll(ctx, true));
g_assert_cmpint(data.n, ==, 2);
- wait_for_aio();
+ while (data.n < 10) {
+ aio_poll(ctx, true);
+ }
g_assert_cmpint(data.n, ==, 10);
g_assert(!aio_poll(ctx, false));
@@ -252,7 +246,9 @@
qemu_bh_schedule(data1.bh);
g_assert_cmpint(data1.n, ==, 0);
- wait_for_aio();
+ while (data1.n < data1.max) {
+ aio_poll(ctx, true);
+ }
g_assert_cmpint(data1.n, ==, data1.max);
g_assert(data1.bh == NULL);
@@ -287,7 +283,12 @@
g_assert_cmpint(data4.n, ==, 1);
g_assert(data1.bh == NULL);
- wait_for_aio();
+ while (data1.n < data1.max ||
+ data2.n < data2.max ||
+ data3.n < data3.max ||
+ data4.n < data4.max) {
+ aio_poll(ctx, true);
+ }
g_assert_cmpint(data1.n, ==, data1.max);
g_assert_cmpint(data2.n, ==, data2.max);
g_assert_cmpint(data3.n, ==, data3.max);
@@ -306,7 +307,7 @@
qemu_bh_schedule(data.bh);
g_assert_cmpint(data.n, ==, 0);
- wait_for_aio();
+ g_assert(aio_poll(ctx, true));
g_assert_cmpint(data.n, ==, 1);
g_assert(!aio_poll(ctx, false));
@@ -806,17 +807,16 @@
g_usleep(1 * G_USEC_PER_SEC);
g_assert_cmpint(data.n, ==, 0);
- g_assert(g_main_context_iteration(NULL, false));
+ g_assert(g_main_context_iteration(NULL, true));
g_assert_cmpint(data.n, ==, 1);
+ expiry += data.ns;
- /* The comment above was not kidding when it said this wakes up itself */
- do {
- g_assert(g_main_context_iteration(NULL, true));
- } while (qemu_clock_get_ns(data.clock_type) <= expiry);
- g_usleep(1 * G_USEC_PER_SEC);
- g_main_context_iteration(NULL, false);
+ while (data.n < 2) {
+ g_main_context_iteration(NULL, true);
+ }
g_assert_cmpint(data.n, ==, 2);
+ g_assert(qemu_clock_get_ns(data.clock_type) > expiry);
aio_set_fd_handler(ctx, pipefd[0], NULL, NULL, NULL);
close(pipefd[0]);
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index e89e43c..101fb27 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -196,16 +196,11 @@
for (i = 0; i < ENUM_ONE_MAX; i++) {
char *str_human;
- int len;
visit_type_EnumOne(data->ov, &i, "unused", &err);
g_assert(!err);
- len = strlen(EnumOne_lookup[i]) + 2;
- str_human = g_malloc0(len);
- str_human[0] = '"';
- strncpy(str_human + 1, EnumOne_lookup[i], strlen(EnumOne_lookup[i]));
- str_human[len - 1] = '"';
+ str_human = g_strdup_printf("\"%s\"", EnumOne_lookup[i]);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
index aa156bc..f40b7fc 100644
--- a/tests/test-thread-pool.c
+++ b/tests/test-thread-pool.c
@@ -83,7 +83,7 @@
data->ret = 0;
active--;
- /* The test continues in test_submit_co, after qemu_aio_wait_all... */
+ /* The test continues in test_submit_co, after aio_poll... */
}
static void test_submit_co(void)
@@ -98,7 +98,7 @@
g_assert_cmpint(active, ==, 1);
g_assert_cmpint(data.ret, ==, -EINPROGRESS);
- /* qemu_aio_wait_all will execute the rest of the coroutine. */
+ /* aio_poll will execute the rest of the coroutine. */
while (data.ret == -EINPROGRESS) {
aio_poll(ctx, true);
diff --git a/ui/gtk.c b/ui/gtk.c
index b02fcd6..2345d7e 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -992,13 +992,16 @@
{
GtkDisplayState *s = opaque;
VirtualConsole *vc = gd_vc_find_by_menu(s);
+ GtkNotebook *nb = GTK_NOTEBOOK(s->notebook);
+ GtkWidget *child;
gint page;
gtk_release_modifiers(s);
if (vc) {
- page = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook),
- vc->tab_item);
- gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), page);
+ page = gtk_notebook_page_num(nb, vc->tab_item);
+ gtk_notebook_set_current_page(nb, page);
+ child = gtk_notebook_get_nth_page(nb, page);
+ gtk_widget_grab_focus(child);
}
}
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 70df446..7bb91e6 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -741,6 +741,7 @@
error_report("spice: failed to enable sasl");
exit(1);
}
+ auth = "sasl";
}
if (qemu_opt_get_bool(opts, "disable-ticketing", 0)) {
auth = "none";
@@ -894,6 +895,10 @@
int qemu_spice_set_passwd(const char *passwd,
bool fail_if_conn, bool disconnect_if_conn)
{
+ if (strcmp(auth, "spice") != 0) {
+ return -1;
+ }
+
g_free(auth_passwd);
auth_passwd = g_strdup(passwd);
return qemu_spice_set_ticket(fail_if_conn, disconnect_if_conn);
diff --git a/util/iov.c b/util/iov.c
index 2b4f46d..24566c8 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -550,3 +550,16 @@
return total;
}
+
+void qemu_iovec_discard_back(QEMUIOVector *qiov, size_t bytes)
+{
+ size_t total;
+ unsigned int niov = qiov->niov;
+
+ assert(qiov->size >= bytes);
+ total = iov_discard_back(qiov->iov, &niov, bytes);
+ assert(total == bytes);
+
+ qiov->niov = niov;
+ qiov->size -= bytes;
+}
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 1524ead..cdbfb2e 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -366,10 +366,9 @@
void os_mem_prealloc(int fd, char *area, size_t memory)
{
- int ret, i;
+ int ret;
struct sigaction act, oldact;
sigset_t set, oldset;
- size_t hpagesize = fd_getpagesize(fd);
memset(&act, 0, sizeof(act));
act.sa_handler = &sigbus_handler;
@@ -389,19 +388,22 @@
if (sigsetjmp(sigjump, 1)) {
fprintf(stderr, "os_mem_prealloc: failed to preallocate pages\n");
exit(1);
- }
+ } else {
+ int i;
+ size_t hpagesize = fd_getpagesize(fd);
- /* MAP_POPULATE silently ignores failures */
- memory = (memory + hpagesize - 1) & -hpagesize;
- for (i = 0; i < (memory/hpagesize); i++) {
- memset(area + (hpagesize*i), 0, 1);
- }
+ /* MAP_POPULATE silently ignores failures */
+ memory = (memory + hpagesize - 1) & -hpagesize;
+ for (i = 0; i < (memory / hpagesize); i++) {
+ memset(area + (hpagesize * i), 0, 1);
+ }
- ret = sigaction(SIGBUS, &oldact, NULL);
- if (ret) {
- perror("os_mem_prealloc: failed to reinstall signal handler");
- exit(1);
- }
+ ret = sigaction(SIGBUS, &oldact, NULL);
+ if (ret) {
+ perror("os_mem_prealloc: failed to reinstall signal handler");
+ exit(1);
+ }
- pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+ }
}
diff --git a/xen-hvm.c b/xen-hvm.c
index bafdf12..c928b36 100644
--- a/xen-hvm.c
+++ b/xen-hvm.c
@@ -390,7 +390,7 @@
start_addr >>= TARGET_PAGE_BITS;
phys_offset >>= TARGET_PAGE_BITS;
for (i = 0; i < size; i++) {
- unsigned long idx = start_addr + i;
+ xen_pfn_t idx = start_addr + i;
xen_pfn_t gpfn = phys_offset + i;
rc = xc_domain_add_to_physmap(xen_xc, xen_domid, XENMAPSPACE_gmfn, idx, gpfn);
diff --git a/xen-mapcache.c b/xen-mapcache.c
index eda914a..66da1a6 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -33,10 +33,10 @@
# define DPRINTF(fmt, ...) do { } while (0)
#endif
-#if defined(__i386__)
+#if HOST_LONG_BITS == 32
# define MCACHE_BUCKET_SHIFT 16
# define MCACHE_MAX_SIZE (1UL<<31) /* 2GB Cap */
-#elif defined(__x86_64__)
+#else
# define MCACHE_BUCKET_SHIFT 20
# define MCACHE_MAX_SIZE (1UL<<35) /* 32GB Cap */
#endif