diff options
242 files changed, 6614 insertions, 1795 deletions
@@ -1 +1 @@ -2.1.93 +2.2.50 diff --git a/aio-posix.c b/aio-posix.c index d3ac06e238..cbd4c3438c 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -73,7 +73,7 @@ void aio_set_fd_handler(AioContext *ctx, } else { if (node == NULL) { /* Alloc and insert if it's not already there */ - node = g_malloc0(sizeof(AioHandler)); + node = g_new0(AioHandler, 1); node->pfd.fd = fd; QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); diff --git a/aio-win32.c b/aio-win32.c index d81313b00b..e6f4cedf48 100644 --- a/aio-win32.c +++ b/aio-win32.c @@ -67,7 +67,7 @@ void aio_set_fd_handler(AioContext *ctx, if (node == NULL) { /* Alloc and insert if it's not already there */ - node = g_malloc0(sizeof(AioHandler)); + node = g_new0(AioHandler, 1); node->pfd.fd = fd; QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); } @@ -129,7 +129,7 @@ void aio_set_event_notifier(AioContext *ctx, } else { if (node == NULL) { /* Alloc and insert if it's not already there */ - node = g_malloc0(sizeof(AioHandler)); + node = g_new0(AioHandler, 1); node->e = e; node->pfd.fd = (uintptr_t)event_notifier_get_handle(e); node->pfd.events = G_IO_IN; @@ -44,7 +44,7 @@ struct QEMUBH { QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque) { QEMUBH *bh; - bh = g_malloc0(sizeof(QEMUBH)); + bh = g_new0(QEMUBH, 1); bh->ctx = ctx; bh->cb = cb; bh->opaque = opaque; diff --git a/backends/rng-random.c b/backends/rng-random.c index 601d9dc0c2..4f85a8ea49 100644 --- a/backends/rng-random.c +++ b/backends/rng-random.c @@ -88,11 +88,7 @@ static char *rng_random_get_filename(Object *obj, Error **errp) { RndRandom *s = RNG_RANDOM(obj); - if (s->filename) { - return g_strdup(s->filename); - } - - return NULL; + return g_strdup(s->filename); } static void rng_random_set_filename(Object *obj, const char *filename, diff --git a/block-migration.c b/block-migration.c index 08db01a364..74d9eb125c 100644 --- a/block-migration.c +++ b/block-migration.c @@ -653,6 +653,7 @@ static int block_save_iterate(QEMUFile *f, void *opaque) { int ret; int64_t last_ftell = qemu_ftell(f); + int64_t delta_ftell; DPRINTF("Enter save live iterate submitted %d transferred %d\n", block_mig_state.submitted, block_mig_state.transferred); @@ -702,7 +703,14 @@ static int block_save_iterate(QEMUFile *f, void *opaque) } qemu_put_be64(f, BLK_MIG_FLAG_EOS); - return qemu_ftell(f) - last_ftell; + delta_ftell = qemu_ftell(f) - last_ftell; + if (delta_ftell > 0) { + return 1; + } else if (delta_ftell < 0) { + return -1; + } else { + return 0; + } } /* Called with iothread lock taken. */ @@ -229,7 +229,7 @@ size_t bdrv_opt_mem_align(BlockDriverState *bs) } /* check if the path starts with "<protocol>:" */ -static int path_has_protocol(const char *path) +int path_has_protocol(const char *path) { const char *p; @@ -629,7 +629,7 @@ BlockDriver *bdrv_find_protocol(const char *filename, } if (!path_has_protocol(filename) || !allow_protocol_prefix) { - return bdrv_find_format("file"); + return &bdrv_file; } p = strchr(filename, ':'); @@ -648,22 +648,49 @@ BlockDriver *bdrv_find_protocol(const char *filename, return NULL; } +/* + * Guess image format by probing its contents. + * This is not a good idea when your image is raw (CVE-2008-2004), but + * we do it anyway for backward compatibility. + * + * @buf contains the image's first @buf_size bytes. + * @buf_size is the buffer size in bytes (generally BLOCK_PROBE_BUF_SIZE, + * but can be smaller if the image file is smaller) + * @filename is its filename. + * + * For all block drivers, call the bdrv_probe() method to get its + * probing score. + * Return the first block driver with the highest probing score. + */ +BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, + const char *filename) +{ + int score_max = 0, score; + BlockDriver *drv = NULL, *d; + + QLIST_FOREACH(d, &bdrv_drivers, list) { + if (d->bdrv_probe) { + score = d->bdrv_probe(buf, buf_size, filename); + if (score > score_max) { + score_max = score; + drv = d; + } + } + } + + return drv; +} + static int find_image_format(BlockDriverState *bs, const char *filename, BlockDriver **pdrv, Error **errp) { - int score, score_max; - BlockDriver *drv1, *drv; - uint8_t buf[2048]; + BlockDriver *drv; + uint8_t buf[BLOCK_PROBE_BUF_SIZE]; int ret = 0; /* Return the raw BlockDriver * to scsi-generic devices or empty drives */ if (bs->sg || !bdrv_is_inserted(bs) || bdrv_getlength(bs) == 0) { - drv = bdrv_find_format("raw"); - if (!drv) { - error_setg(errp, "Could not find raw image format"); - ret = -ENOENT; - } - *pdrv = drv; + *pdrv = &bdrv_raw; return ret; } @@ -675,17 +702,7 @@ static int find_image_format(BlockDriverState *bs, const char *filename, return ret; } - score_max = 0; - drv = NULL; - QLIST_FOREACH(drv1, &bdrv_drivers, list) { - if (drv1->bdrv_probe) { - score = drv1->bdrv_probe(buf, ret, filename); - if (score > score_max) { - score_max = score; - drv = drv1; - } - } - } + drv = bdrv_probe_all(buf, ret, filename); if (!drv) { error_setg(errp, "Could not determine image format: No compatible " "driver found"); @@ -1180,7 +1197,6 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) { char *backing_filename = g_malloc0(PATH_MAX); int ret = 0; - BlockDriver *back_drv = NULL; BlockDriverState *backing_hd; Error *local_err = NULL; @@ -1213,14 +1229,14 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) backing_hd = bdrv_new(); - if (bs->backing_format[0] != '\0') { - back_drv = bdrv_find_format(bs->backing_format); + if (bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) { + qdict_put(options, "driver", qstring_from_str(bs->backing_format)); } assert(bs->backing_hd == NULL); ret = bdrv_open(&backing_hd, *backing_filename ? backing_filename : NULL, NULL, options, - bdrv_backing_flags(bs->open_flags), back_drv, &local_err); + bdrv_backing_flags(bs->open_flags), NULL, &local_err); if (ret < 0) { bdrv_unref(backing_hd); backing_hd = NULL; @@ -1294,7 +1310,6 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp) /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */ char *tmp_filename = g_malloc0(PATH_MAX + 1); int64_t total_size; - BlockDriver *bdrv_qcow2; QemuOpts *opts = NULL; QDict *snapshot_options; BlockDriverState *bs_snapshot; @@ -1319,11 +1334,10 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp) goto out; } - bdrv_qcow2 = bdrv_find_format("qcow2"); - opts = qemu_opts_create(bdrv_qcow2->create_opts, NULL, 0, + opts = qemu_opts_create(bdrv_qcow2.create_opts, NULL, 0, &error_abort); qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_size); - ret = bdrv_create(bdrv_qcow2, tmp_filename, opts, &local_err); + ret = bdrv_create(&bdrv_qcow2, tmp_filename, opts, &local_err); qemu_opts_del(opts); if (ret < 0) { error_setg_errno(errp, -ret, "Could not create temporary overlay " @@ -1343,7 +1357,7 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp) bs_snapshot = bdrv_new(); ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options, - flags, bdrv_qcow2, &local_err); + flags, &bdrv_qcow2, &local_err); if (ret < 0) { error_propagate(errp, local_err); goto out; @@ -1467,6 +1481,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, } /* Image format probing */ + bs->probed = !drv; if (!drv && file) { ret = find_image_format(file, filename, &drv, &local_err); if (ret < 0) { @@ -3801,6 +3816,14 @@ bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base) return top != NULL; } +BlockDriverState *bdrv_next_node(BlockDriverState *bs) +{ + if (!bs) { + return QTAILQ_FIRST(&graph_bdrv_states); + } + return QTAILQ_NEXT(bs, node_list); +} + BlockDriverState *bdrv_next(BlockDriverState *bs) { if (!bs) { @@ -3809,6 +3832,11 @@ BlockDriverState *bdrv_next(BlockDriverState *bs) return QTAILQ_NEXT(bs, device_list); } +const char *bdrv_get_node_name(const BlockDriverState *bs) +{ + return bs->node_name; +} + /* TODO check what callers really want: bs->node_name or blk_name() */ const char *bdrv_get_device_name(const BlockDriverState *bs) { @@ -5541,6 +5569,18 @@ void bdrv_img_create(const char *filename, const char *fmt, return; } + if (!drv->create_opts) { + error_setg(errp, "Format driver '%s' does not support image creation", + drv->format_name); + return; + } + + if (!proto_drv->create_opts) { + error_setg(errp, "Protocol driver '%s' does not support image creation", + proto_drv->format_name); + return; + } + create_opts = qemu_opts_append(create_opts, drv->create_opts); create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); @@ -5628,8 +5668,8 @@ void bdrv_img_create(const char *filename, const char *fmt, } if (!quiet) { - printf("Formatting '%s', fmt=%s ", filename, fmt); - qemu_opts_print(opts); + printf("Formatting '%s', fmt=%s", filename, fmt); + qemu_opts_print(opts, " "); puts(""); } diff --git a/block/accounting.c b/block/accounting.c index edbb1cc89f..18102f015d 100644 --- a/block/accounting.c +++ b/block/accounting.c @@ -24,6 +24,7 @@ #include "block/accounting.h" #include "block/block_int.h" +#include "qemu/timer.h" void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie, int64_t bytes, enum BlockAcctType type) @@ -31,7 +32,7 @@ void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie, assert(type < BLOCK_MAX_IOTYPE); cookie->bytes = bytes; - cookie->start_time_ns = get_clock(); + cookie->start_time_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); cookie->type = type; } @@ -41,7 +42,8 @@ void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie) stats->nr_bytes[cookie->type] += cookie->bytes; stats->nr_ops[cookie->type]++; - stats->total_time_ns[cookie->type] += get_clock() - cookie->start_time_ns; + stats->total_time_ns[cookie->type] += + qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - cookie->start_time_ns; } diff --git a/block/blkdebug.c b/block/blkdebug.c index 862d93b59b..9ce35cd035 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -721,93 +721,50 @@ static int64_t blkdebug_getlength(BlockDriverState *bs) static void blkdebug_refresh_filename(BlockDriverState *bs) { - BDRVBlkdebugState *s = bs->opaque; - struct BlkdebugRule *rule; QDict *opts; - QList *inject_error_list = NULL, *set_state_list = NULL; - QList *suspend_list = NULL; - int event; + const QDictEntry *e; + bool force_json = false; + + for (e = qdict_first(bs->options); e; e = qdict_next(bs->options, e)) { + if (strcmp(qdict_entry_key(e), "config") && + strcmp(qdict_entry_key(e), "x-image") && + strcmp(qdict_entry_key(e), "image") && + strncmp(qdict_entry_key(e), "image.", strlen("image."))) + { + force_json = true; + break; + } + } - if (!bs->file->full_open_options) { + if (force_json && !bs->file->full_open_options) { /* The config file cannot be recreated, so creating a plain filename * is impossible */ return; } + if (!force_json && bs->file->exact_filename[0]) { + snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "blkdebug:%s:%s", + qdict_get_try_str(bs->options, "config") ?: "", + bs->file->exact_filename); + } + opts = qdict_new(); qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("blkdebug"))); QINCREF(bs->file->full_open_options); qdict_put_obj(opts, "image", QOBJECT(bs->file->full_open_options)); - for (event = 0; event < BLKDBG_EVENT_MAX; event++) { - QLIST_FOREACH(rule, &s->rules[event], next) { - if (rule->action == ACTION_INJECT_ERROR) { - QDict *inject_error = qdict_new(); - - qdict_put_obj(inject_error, "event", QOBJECT(qstring_from_str( - BlkdebugEvent_lookup[rule->event]))); - qdict_put_obj(inject_error, "state", - QOBJECT(qint_from_int(rule->state))); - qdict_put_obj(inject_error, "errno", QOBJECT(qint_from_int( - rule->options.inject.error))); - qdict_put_obj(inject_error, "sector", QOBJECT(qint_from_int( - rule->options.inject.sector))); - qdict_put_obj(inject_error, "once", QOBJECT(qbool_from_int( - rule->options.inject.once))); - qdict_put_obj(inject_error, "immediately", - QOBJECT(qbool_from_int( - rule->options.inject.immediately))); - - if (!inject_error_list) { - inject_error_list = qlist_new(); - } - - qlist_append_obj(inject_error_list, QOBJECT(inject_error)); - } else if (rule->action == ACTION_SET_STATE) { - QDict *set_state = qdict_new(); - - qdict_put_obj(set_state, "event", QOBJECT(qstring_from_str( - BlkdebugEvent_lookup[rule->event]))); - qdict_put_obj(set_state, "state", - QOBJECT(qint_from_int(rule->state))); - qdict_put_obj(set_state, "new_state", QOBJECT(qint_from_int( - rule->options.set_state.new_state))); - - if (!set_state_list) { - set_state_list = qlist_new(); - } - - qlist_append_obj(set_state_list, QOBJECT(set_state)); - } else if (rule->action == ACTION_SUSPEND) { - QDict *suspend = qdict_new(); - - qdict_put_obj(suspend, "event", QOBJECT(qstring_from_str( - BlkdebugEvent_lookup[rule->event]))); - qdict_put_obj(suspend, "state", - QOBJECT(qint_from_int(rule->state))); - qdict_put_obj(suspend, "tag", QOBJECT(qstring_from_str( - rule->options.suspend.tag))); - - if (!suspend_list) { - suspend_list = qlist_new(); - } - - qlist_append_obj(suspend_list, QOBJECT(suspend)); - } + for (e = qdict_first(bs->options); e; e = qdict_next(bs->options, e)) { + if (strcmp(qdict_entry_key(e), "x-image") && + strcmp(qdict_entry_key(e), "image") && + strncmp(qdict_entry_key(e), "image.", strlen("image."))) + { + qobject_incref(qdict_entry_value(e)); + qdict_put_obj(opts, qdict_entry_key(e), qdict_entry_value(e)); } } - if (inject_error_list) { - qdict_put_obj(opts, "inject-error", QOBJECT(inject_error_list)); - } - if (set_state_list) { - qdict_put_obj(opts, "set-state", QOBJECT(set_state_list)); - } - if (suspend_list) { - qdict_put_obj(opts, "suspend", QOBJECT(suspend_list)); - } - bs->full_open_options = opts; } diff --git a/block/block-backend.c b/block/block-backend.c index d0692b18e9..ef16d7356a 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -497,6 +497,16 @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf, return bdrv_aio_ioctl(blk->bs, req, buf, cb, opaque); } +int blk_co_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors) +{ + return bdrv_co_discard(blk->bs, sector_num, nb_sectors); +} + +int blk_co_flush(BlockBackend *blk) +{ + return bdrv_co_flush(blk->bs); +} + int blk_flush(BlockBackend *blk) { return bdrv_flush(blk->bs); @@ -549,6 +559,11 @@ void blk_set_enable_write_cache(BlockBackend *blk, bool wce) bdrv_set_enable_write_cache(blk->bs, wce); } +void blk_invalidate_cache(BlockBackend *blk, Error **errp) +{ + bdrv_invalidate_cache(blk->bs, errp); +} + int blk_is_inserted(BlockBackend *blk) { return bdrv_is_inserted(blk->bs); @@ -609,6 +624,29 @@ void blk_set_aio_context(BlockBackend *blk, AioContext *new_context) bdrv_set_aio_context(blk->bs, new_context); } +void blk_add_aio_context_notifier(BlockBackend *blk, + void (*attached_aio_context)(AioContext *new_context, void *opaque), + void (*detach_aio_context)(void *opaque), void *opaque) +{ + bdrv_add_aio_context_notifier(blk->bs, attached_aio_context, + detach_aio_context, opaque); +} + +void blk_remove_aio_context_notifier(BlockBackend *blk, + void (*attached_aio_context)(AioContext *, + void *), + void (*detach_aio_context)(void *), + void *opaque) +{ + bdrv_remove_aio_context_notifier(blk->bs, attached_aio_context, + detach_aio_context, opaque); +} + +void blk_add_close_notifier(BlockBackend *blk, Notifier *notify) +{ + bdrv_add_close_notifier(blk->bs, notify); +} + void blk_io_plug(BlockBackend *blk) { bdrv_io_plug(blk->bs); diff --git a/block/linux-aio.c b/block/linux-aio.c index d92513b0f9..c991443c5d 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -35,14 +35,14 @@ struct qemu_laiocb { size_t nbytes; QEMUIOVector *qiov; bool is_read; - QLIST_ENTRY(qemu_laiocb) node; + QSIMPLEQ_ENTRY(qemu_laiocb) next; }; typedef struct { - struct iocb *iocbs[MAX_QUEUED_IO]; int plugged; - unsigned int size; - unsigned int idx; + unsigned int n; + bool blocked; + QSIMPLEQ_HEAD(, qemu_laiocb) pending; } LaioQueue; struct qemu_laio_state { @@ -59,6 +59,8 @@ struct qemu_laio_state { int event_max; }; +static void ioq_submit(struct qemu_laio_state *s); + static inline ssize_t io_event_ret(struct io_event *ev) { return (ssize_t)(((uint64_t)ev->res2 << 32) | ev->res); @@ -135,6 +137,10 @@ static void qemu_laio_completion_bh(void *opaque) qemu_laio_process_completion(s, laiocb); } + + if (!s->io_q.plugged && !QSIMPLEQ_EMPTY(&s->io_q.pending)) { + ioq_submit(s); + } } static void qemu_laio_completion_cb(EventNotifier *e) @@ -172,50 +178,41 @@ static const AIOCBInfo laio_aiocb_info = { static void ioq_init(LaioQueue *io_q) { - io_q->size = MAX_QUEUED_IO; - io_q->idx = 0; + QSIMPLEQ_INIT(&io_q->pending); io_q->plugged = 0; + io_q->n = 0; + io_q->blocked = false; } -static int ioq_submit(struct qemu_laio_state *s) +static void ioq_submit(struct qemu_laio_state *s) { - int ret, i = 0; - int len = s->io_q.idx; + int ret, len; + struct qemu_laiocb *aiocb; + struct iocb *iocbs[MAX_QUEUED_IO]; + QSIMPLEQ_HEAD(, qemu_laiocb) completed; 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; + len = 0; + QSIMPLEQ_FOREACH(aiocb, &s->io_q.pending, next) { + iocbs[len++] = &aiocb->iocb; + if (len == MAX_QUEUED_IO) { + break; + } + } - s->io_q.iocbs[idx++] = iocb; - s->io_q.idx = idx; + ret = io_submit(s->ctx, len, iocbs); + if (ret == -EAGAIN) { + break; + } + if (ret < 0) { + abort(); + } - /* submit immediately if queue is full */ - if (idx == s->io_q.size) { - ioq_submit(s); - } + s->io_q.n -= ret; + aiocb = container_of(iocbs[ret - 1], struct qemu_laiocb, iocb); + QSIMPLEQ_SPLIT_AFTER(&s->io_q.pending, aiocb, next, &completed); + } while (ret == len && !QSIMPLEQ_EMPTY(&s->io_q.pending)); + s->io_q.blocked = (s->io_q.n > 0); } void laio_io_plug(BlockDriverState *bs, void *aio_ctx) @@ -225,22 +222,19 @@ void laio_io_plug(BlockDriverState *bs, void *aio_ctx) s->io_q.plugged++; } -int laio_io_unplug(BlockDriverState *bs, void *aio_ctx, bool unplug) +void 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; + return; } - if (s->io_q.idx > 0) { - ret = ioq_submit(s); + if (!s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) { + ioq_submit(s); } - - return ret; } BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, @@ -276,12 +270,11 @@ BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, } io_set_eventfd(&laiocb->iocb, event_notifier_get_fd(&s->e)); - if (!s->io_q.plugged) { - if (io_submit(s->ctx, 1, &iocbs) < 0) { - goto out_free_aiocb; - } - } else { - ioq_enqueue(s, iocbs); + QSIMPLEQ_INSERT_TAIL(&s->io_q.pending, laiocb, next); + s->io_q.n++; + if (!s->io_q.blocked && + (!s->io_q.plugged || s->io_q.n >= MAX_QUEUED_IO)) { + ioq_submit(s); } return &laiocb->common; diff --git a/block/nfs.c b/block/nfs.c index c76e368b95..ca9e24efe5 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -409,6 +409,19 @@ out: return ret; } +static QemuOptsList nfs_create_opts = { + .name = "nfs-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(nfs_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { /* end of list */ } + } +}; + static int nfs_file_create(const char *url, QemuOpts *opts, Error **errp) { int ret = 0; @@ -470,6 +483,8 @@ static BlockDriver bdrv_nfs = { .instance_size = sizeof(NFSClient), .bdrv_needs_filename = true, + .create_opts = &nfs_create_opts, + .bdrv_has_zero_init = nfs_has_zero_init, .bdrv_get_allocated_file_size = nfs_get_allocated_file_size, .bdrv_truncate = nfs_file_truncate, diff --git a/block/qapi.c b/block/qapi.c index a87a34a8b4..fa68ba731f 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -40,6 +40,13 @@ BlockDeviceInfo *bdrv_block_device_info(BlockDriverState *bs) info->encrypted = bs->encrypted; info->encryption_key_missing = bdrv_key_required(bs); + info->cache = g_new(BlockdevCacheInfo, 1); + *info->cache = (BlockdevCacheInfo) { + .writeback = bdrv_enable_write_cache(bs), + .direct = !!(bs->open_flags & BDRV_O_NOCACHE), + .no_flush = !!(bs->open_flags & BDRV_O_NO_FLUSH), + }; + if (bs->node_name[0]) { info->has_node_name = true; info->node_name = g_strdup(bs->node_name); @@ -300,7 +307,8 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, qapi_free_BlockInfo(info); } -static BlockStats *bdrv_query_stats(const BlockDriverState *bs) +static BlockStats *bdrv_query_stats(const BlockDriverState *bs, + bool query_backing) { BlockStats *s; @@ -311,6 +319,11 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs) s->device = g_strdup(bdrv_get_device_name(bs)); } + if (bdrv_get_node_name(bs)[0]) { + s->has_node_name = true; + s->node_name = g_strdup(bdrv_get_node_name(bs)); + } + s->stats = g_malloc0(sizeof(*s->stats)); s->stats->rd_bytes = bs->stats.nr_bytes[BLOCK_ACCT_READ]; s->stats->wr_bytes = bs->stats.nr_bytes[BLOCK_ACCT_WRITE]; @@ -325,12 +338,12 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs) if (bs->file) { s->has_parent = true; - s->parent = bdrv_query_stats(bs->file); + s->parent = bdrv_query_stats(bs->file, query_backing); } - if (bs->backing_hd) { + if (query_backing && bs->backing_hd) { s->has_backing = true; - s->backing = bdrv_query_stats(bs->backing_hd); + s->backing = bdrv_query_stats(bs->backing_hd, query_backing); } return s; @@ -361,17 +374,22 @@ BlockInfoList *qmp_query_block(Error **errp) return NULL; } -BlockStatsList *qmp_query_blockstats(Error **errp) +BlockStatsList *qmp_query_blockstats(bool has_query_nodes, + bool query_nodes, + Error **errp) { BlockStatsList *head = NULL, **p_next = &head; BlockDriverState *bs = NULL; - while ((bs = bdrv_next(bs))) { + /* Just to be safe if query_nodes is not always initialized */ + query_nodes = has_query_nodes && query_nodes; + + while ((bs = query_nodes ? bdrv_next_node(bs) : bdrv_next(bs))) { BlockStatsList *info = g_malloc0(sizeof(*info)); AioContext *ctx = bdrv_get_aio_context(bs); aio_context_acquire(ctx); - info->value = bdrv_query_stats(bs); + info->value = bdrv_query_stats(bs, !query_nodes); aio_context_release(ctx); *p_next = info; diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index df0b2c9cec..1fea5142d0 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1263,7 +1263,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, again: start = offset; - remaining = *num << BDRV_SECTOR_BITS; + remaining = (uint64_t)*num << BDRV_SECTOR_BITS; cluster_offset = 0; *host_offset = 0; cur_bytes = 0; diff --git a/block/qcow2.c b/block/qcow2.c index d12049451a..e4e690a42b 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -117,7 +117,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, #ifdef DEBUG_EXT printf("ext.magic = 0x%x\n", ext.magic); #endif - if (ext.len > end_offset - offset) { + if (offset > end_offset || ext.len > end_offset - offset) { error_setg(errp, "Header extension too large"); return -EINVAL; } @@ -1428,10 +1428,23 @@ static void qcow2_close(BlockDriverState *bs) s->l1_table = NULL; if (!(bs->open_flags & BDRV_O_INCOMING)) { - qcow2_cache_flush(bs, s->l2_table_cache); - qcow2_cache_flush(bs, s->refcount_block_cache); + int ret1, ret2; - qcow2_mark_clean(bs); + ret1 = qcow2_cache_flush(bs, s->l2_table_cache); + ret2 = qcow2_cache_flush(bs, s->refcount_block_cache); + + if (ret1) { + error_report("Failed to flush the L2 table cache: %s", + strerror(-ret1)); + } + if (ret2) { + error_report("Failed to flush the refcount block cache: %s", + strerror(-ret2)); + } + + if (!ret1 && !ret2) { + qcow2_mark_clean(bs); + } } qcow2_cache_destroy(bs, s->l2_table_cache); @@ -1915,10 +1928,9 @@ static int qcow2_create2(const char *filename, int64_t total_size, * refcount of the cluster that is occupied by the header and the refcount * table) */ - BlockDriver* drv = bdrv_find_format("qcow2"); - assert(drv != NULL); ret = bdrv_open(&bs, filename, NULL, NULL, - BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv, &local_err); + BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, + &bdrv_qcow2, &local_err); if (ret < 0) { error_propagate(errp, local_err); goto out; @@ -1970,7 +1982,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, /* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning */ ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_BACKING, - drv, &local_err); + &bdrv_qcow2, &local_err); if (local_err) { error_propagate(errp, local_err); goto out; @@ -2150,8 +2162,7 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num, /* align end of file to a sector boundary to ease reading with sector based I/Os */ cluster_offset = bdrv_getlength(bs->file); - bdrv_truncate(bs->file, cluster_offset); - return 0; + return bdrv_truncate(bs->file, cluster_offset); } if (nb_sectors != s->cluster_sectors) { @@ -2847,7 +2858,7 @@ static QemuOptsList qcow2_create_opts = { } }; -static BlockDriver bdrv_qcow2 = { +BlockDriver bdrv_qcow2 = { .format_name = "qcow2", .instance_size = sizeof(BDRVQcowState), .bdrv_probe = qcow2_probe, diff --git a/block/raw-aio.h b/block/raw-aio.h index 80681ce175..31d791fe67 100644 --- a/block/raw-aio.h +++ b/block/raw-aio.h @@ -41,7 +41,7 @@ BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, 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); +void 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 b1af77e47f..e51293a455 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -446,6 +446,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, } if (fstat(s->fd, &st) < 0) { + ret = -errno; error_setg_errno(errp, errno, "Could not stat file"); goto fail; } @@ -1684,7 +1685,7 @@ static QemuOptsList raw_create_opts = { } }; -static BlockDriver bdrv_file = { +BlockDriver bdrv_file = { .format_name = "file", .protocol_name = "file", .instance_size = sizeof(BDRVRawState), @@ -1922,7 +1923,7 @@ static int fd_open(BlockDriverState *bs) return 0; last_media_present = (s->fd >= 0); if (s->fd >= 0 && - (get_clock() - s->fd_open_time) >= FD_OPEN_TIMEOUT) { + (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - s->fd_open_time) >= FD_OPEN_TIMEOUT) { qemu_close(s->fd); s->fd = -1; #ifdef DEBUG_FLOPPY @@ -1931,7 +1932,7 @@ static int fd_open(BlockDriverState *bs) } if (s->fd < 0) { if (s->fd_got_error && - (get_clock() - s->fd_error_time) < FD_OPEN_TIMEOUT) { + (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - s->fd_error_time) < FD_OPEN_TIMEOUT) { #ifdef DEBUG_FLOPPY printf("No floppy (open delayed)\n"); #endif @@ -1939,7 +1940,7 @@ static int fd_open(BlockDriverState *bs) } s->fd = qemu_open(bs->filename, s->open_flags & ~O_NONBLOCK); if (s->fd < 0) { - s->fd_error_time = get_clock(); + s->fd_error_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); s->fd_got_error = 1; if (last_media_present) s->fd_media_changed = 1; @@ -1954,7 +1955,7 @@ static int fd_open(BlockDriverState *bs) } if (!last_media_present) s->fd_media_changed = 1; - s->fd_open_time = get_clock(); + s->fd_open_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); s->fd_got_error = 0; return 0; } diff --git a/block/raw-win32.c b/block/raw-win32.c index 7b588815b9..06243d76df 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -540,7 +540,7 @@ static QemuOptsList raw_create_opts = { } }; -static BlockDriver bdrv_file = { +BlockDriver bdrv_file = { .format_name = "file", .protocol_name = "file", .instance_size = sizeof(BDRVRawState), diff --git a/block/raw_bsd.c b/block/raw_bsd.c index 401b967e85..05b02c76d4 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -58,8 +58,58 @@ static int coroutine_fn raw_co_readv(BlockDriverState *bs, int64_t sector_num, static int coroutine_fn raw_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov) { + void *buf = NULL; + BlockDriver *drv; + QEMUIOVector local_qiov; + int ret; + + if (bs->probed && sector_num == 0) { + /* As long as these conditions are true, we can't get partial writes to + * the probe buffer and can just directly check the request. */ + QEMU_BUILD_BUG_ON(BLOCK_PROBE_BUF_SIZE != 512); + QEMU_BUILD_BUG_ON(BDRV_SECTOR_SIZE != 512); + + if (nb_sectors == 0) { + /* qemu_iovec_to_buf() would fail, but we want to return success + * instead of -EINVAL in this case. */ + return 0; + } + + buf = qemu_try_blockalign(bs->file, 512); + if (!buf) { + ret = -ENOMEM; + goto fail; + } + + ret = qemu_iovec_to_buf(qiov, 0, buf, 512); + if (ret != 512) { + ret = -EINVAL; + goto fail; + } + + drv = bdrv_probe_all(buf, 512, NULL); + if (drv != bs->drv) { + ret = -EPERM; + goto fail; + } + + /* Use the checked buffer, a malicious guest might be overwriting its + * original buffer in the background. */ + qemu_iovec_init(&local_qiov, qiov->niov + 1); + qemu_iovec_add(&local_qiov, buf, 512); + qemu_iovec_concat(&local_qiov, qiov, 512, qiov->size - 512); + qiov = &local_qiov; + } + BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); - return bdrv_co_writev(bs->file, sector_num, nb_sectors, qiov); + ret = bdrv_co_writev(bs->file, sector_num, nb_sectors, qiov); + +fail: + if (qiov == &local_qiov) { + qemu_iovec_destroy(&local_qiov); + } + qemu_vfree(buf); + return ret; } static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, @@ -158,6 +208,18 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { bs->sg = bs->file->sg; + + if (bs->probed && !bdrv_is_read_only(bs)) { + fprintf(stderr, + "WARNING: Image format was not specified for '%s' and probing " + "guessed raw.\n" + " Automatically detecting the format is dangerous for " + "raw images, write operations on block 0 will be restricted.\n" + " Specify the 'raw' format explicitly to remove the " + "restrictions.\n", + bs->file->filename); + } + return 0; } @@ -173,7 +235,7 @@ static int raw_probe(const uint8_t *buf, int buf_size, const char *filename) return 1; } -static BlockDriver bdrv_raw = { +BlockDriver bdrv_raw = { .format_name = "raw", .bdrv_probe = &raw_probe, .bdrv_reopen_prepare = &raw_reopen_prepare, diff --git a/block/rbd.c b/block/rbd.c index 5b5a64a27a..f3ab2ddd5a 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -459,7 +459,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, clientname = qemu_rbd_parse_clientname(conf, clientname_buf); r = rados_create(&s->cluster, clientname); if (r < 0) { - error_setg(&local_err, "error initializing"); + error_setg(errp, "error initializing"); goto failed_opts; } @@ -495,19 +495,19 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, r = rados_connect(s->cluster); if (r < 0) { - error_setg(&local_err, "error connecting"); + error_setg(errp, "error connecting"); goto failed_shutdown; } r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); if (r < 0) { - error_setg(&local_err, "error opening pool %s", pool); + error_setg(errp, "error opening pool %s", pool); goto failed_shutdown; } r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); if (r < 0) { - error_setg(&local_err, "error reading header from %s", s->name); + error_setg(errp, "error reading header from %s", s->name); goto failed_open; } diff --git a/block/vdi.c b/block/vdi.c index 39070b75e8..74030c6e30 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -852,11 +852,6 @@ static QemuOptsList vdi_create_opts = { .def_value_str = "off" }, #endif - { - .name = BLOCK_OPT_NOCOW, - .type = QEMU_OPT_BOOL, - .help = "Turn off copy-on-write (valid only on btrfs)" - }, /* TODO: An additional option to set UUID values might be useful. */ { /* end of list */ } } diff --git a/block/vhdx.c b/block/vhdx.c index 12bfe75e51..06f2b1a0cb 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -1109,8 +1109,9 @@ static coroutine_fn int vhdx_co_readv(BlockDriverState *bs, int64_t sector_num, /* check the payload block state */ switch (s->bat[sinfo.bat_idx] & VHDX_BAT_STATE_BIT_MASK) { case PAYLOAD_BLOCK_NOT_PRESENT: /* fall through */ - case PAYLOAD_BLOCK_UNDEFINED: /* fall through */ - case PAYLOAD_BLOCK_UNMAPPED: /* fall through */ + case PAYLOAD_BLOCK_UNDEFINED: + case PAYLOAD_BLOCK_UNMAPPED: + case PAYLOAD_BLOCK_UNMAPPED_v095: case PAYLOAD_BLOCK_ZERO: /* return zero */ qemu_iovec_memset(&hd_qiov, 0, 0, sinfo.bytes_avail); @@ -1277,11 +1278,11 @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num, sectors_to_write += iov2.iov_len >> BDRV_SECTOR_BITS; } } - /* fall through */ case PAYLOAD_BLOCK_NOT_PRESENT: /* fall through */ - case PAYLOAD_BLOCK_UNMAPPED: /* fall through */ - case PAYLOAD_BLOCK_UNDEFINED: /* fall through */ + case PAYLOAD_BLOCK_UNMAPPED: + case PAYLOAD_BLOCK_UNMAPPED_v095: + case PAYLOAD_BLOCK_UNDEFINED: bat_prior_offset = sinfo.file_offset; ret = vhdx_allocate_block(bs, s, &sinfo.file_offset); if (ret < 0) { @@ -1773,7 +1774,7 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp) log_size = qemu_opt_get_size_del(opts, VHDX_BLOCK_OPT_LOG_SIZE, 0); block_size = qemu_opt_get_size_del(opts, VHDX_BLOCK_OPT_BLOCK_SIZE, 0); type = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT); - use_zero_blocks = qemu_opt_get_bool_del(opts, VHDX_BLOCK_OPT_ZERO, false); + use_zero_blocks = qemu_opt_get_bool_del(opts, VHDX_BLOCK_OPT_ZERO, true); if (image_size > VHDX_MAX_IMAGE_SIZE) { error_setg_errno(errp, EINVAL, "Image size too large; max of 64TB"); @@ -1935,7 +1936,9 @@ static QemuOptsList vhdx_create_opts = { { .name = VHDX_BLOCK_OPT_ZERO, .type = QEMU_OPT_BOOL, - .help = "Force use of payload blocks of type 'ZERO'. Non-standard." + .help = "Force use of payload blocks of type 'ZERO'. "\ + "Non-standard, but default. Do not set to 'off' when "\ + "using 'qemu-img convert' with subformat=dynamic." }, { NULL } } @@ -1953,6 +1956,7 @@ static BlockDriver bdrv_vhdx = { .bdrv_create = vhdx_create, .bdrv_get_info = vhdx_get_info, .bdrv_check = vhdx_check, + .bdrv_has_zero_init = bdrv_has_zero_init_1, .create_opts = &vhdx_create_opts, }; diff --git a/block/vhdx.h b/block/vhdx.h index b4a12a081e..7003ab7a79 100644 --- a/block/vhdx.h +++ b/block/vhdx.h @@ -226,7 +226,8 @@ typedef struct QEMU_PACKED VHDXLogDataSector { #define PAYLOAD_BLOCK_NOT_PRESENT 0 #define PAYLOAD_BLOCK_UNDEFINED 1 #define PAYLOAD_BLOCK_ZERO 2 -#define PAYLOAD_BLOCK_UNMAPPED 5 +#define PAYLOAD_BLOCK_UNMAPPED 3 +#define PAYLOAD_BLOCK_UNMAPPED_v095 5 #define PAYLOAD_BLOCK_FULLY_PRESENT 6 #define PAYLOAD_BLOCK_PARTIALLY_PRESENT 7 diff --git a/block/vmdk.c b/block/vmdk.c index 2cbfd3e72e..bfff900ba6 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -28,6 +28,7 @@ #include "qemu/module.h" #include "migration/migration.h" #include <zlib.h> +#include <glib.h> #define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D') #define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V') @@ -556,8 +557,16 @@ static char *vmdk_read_desc(BlockDriverState *file, uint64_t desc_offset, return NULL; } - size = MIN(size, 1 << 20); /* avoid unbounded allocation */ - buf = g_malloc0(size + 1); + if (size < 4) { + /* Both descriptor file and sparse image must be much larger than 4 + * bytes, also callers of vmdk_read_desc want to compare the first 4 + * bytes with VMDK4_MAGIC, let's error out if less is read. */ + error_setg(errp, "File is too small, not a valid image"); + return NULL; + } + + size = MIN(size, (1 << 20) - 1); /* avoid unbounded allocation */ + buf = g_malloc(size + 1); ret = bdrv_pread(file, desc_offset, buf, size); if (ret < 0) { @@ -565,6 +574,7 @@ static char *vmdk_read_desc(BlockDriverState *file, uint64_t desc_offset, g_free(buf); return NULL; } + buf[ret] = 0; return buf; } @@ -635,6 +645,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, bs->file->total_sectors * 512 - 1536, &footer, sizeof(footer)); if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to read footer"); return ret; } @@ -646,6 +657,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, le32_to_cpu(footer.eos_marker.size) != 0 || le32_to_cpu(footer.eos_marker.type) != MARKER_END_OF_STREAM) { + error_setg(errp, "Invalid footer"); return -EINVAL; } @@ -676,6 +688,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gt) * le64_to_cpu(header.granularity); if (l1_entry_sectors == 0) { + error_setg(errp, "L1 entry size is invalid"); return -EINVAL; } l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1) @@ -784,10 +797,12 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, VmdkExtent *extent; while (*p) { - /* parse extent line: + /* parse extent line in one of below formats: + * * RW [size in sectors] FLAT "file-name.vmdk" OFFSET - * or * RW [size in sectors] SPARSE "file-name.vmdk" + * RW [size in sectors] VMFS "file-name.vmdk" + * RW [size in sectors] VMFSSPARSE "file-name.vmdk" */ flat_offset = -1; ret = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64, @@ -818,6 +833,14 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, goto next_line; } + if (!path_is_absolute(fname) && !path_has_protocol(fname) && + !desc_file_path[0]) + { + error_setg(errp, "Cannot use relative extent paths with VMDK " + "descriptor file '%s'", bs->file->filename); + return -EINVAL; + } + path_combine(extent_path, sizeof(extent_path), desc_file_path, fname); extent_file = NULL; @@ -894,7 +917,7 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf, } s->create_type = g_strdup(ct); s->desc_offset = 0; - ret = vmdk_parse_extents(buf, bs, bs->file->filename, errp); + ret = vmdk_parse_extents(buf, bs, bs->file->exact_filename, errp); exit: return ret; } @@ -902,7 +925,7 @@ exit: static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { - char *buf = NULL; + char *buf; int ret; BDRVVmdkState *s = bs->opaque; uint32_t magic; @@ -1538,7 +1561,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num, /* update CID on the first write every time the virtual disk is * opened */ if (!s->cid_updated) { - ret = vmdk_write_cid(bs, time(NULL)); + ret = vmdk_write_cid(bs, g_random_int()); if (ret < 0) { return ret; } @@ -1922,7 +1945,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) } /* generate descriptor file */ desc = g_strdup_printf(desc_template, - (uint32_t)time(NULL), + g_random_int(), parent_cid, fmt, parent_desc_line, diff --git a/block/vpc.c b/block/vpc.c index 38c4f02fff..46803b14be 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -893,11 +893,6 @@ static QemuOptsList vpc_create_opts = { "Type of virtual hard disk format. Supported formats are " "{dynamic (default) | fixed} " }, - { - .name = BLOCK_OPT_NOCOW, - .type = QEMU_OPT_BOOL, - .help = "Turn off copy-on-write (valid only on btrfs)" - }, { /* end of list */ } } }; diff --git a/block/vvfat.c b/block/vvfat.c index cefe3a4f79..e34a789699 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -2917,6 +2917,12 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp) } bdrv_qcow = bdrv_find_format("qcow"); + if (!bdrv_qcow) { + error_setg(errp, "Failed to locate qcow driver"); + ret = -ENOENT; + goto err; + } + opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort); qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512); qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:"); diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 06f901ef6f..22e95d17ee 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -10,6 +10,7 @@ */ #include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/block/block.h" #include "monitor/monitor.h" #include "qapi/qmp/qerror.h" @@ -73,7 +74,7 @@ static void nbd_close_notifier(Notifier *n, void *data) void qmp_nbd_server_add(const char *device, bool has_writable, bool writable, Error **errp) { - BlockDriverState *bs; + BlockBackend *blk; NBDExport *exp; NBDCloseNotifier *n; @@ -87,12 +88,12 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable, return; } - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } - if (!bdrv_is_inserted(bs)) { + if (!blk_is_inserted(blk)) { error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); return; } @@ -100,18 +101,18 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable, if (!has_writable) { writable = false; } - if (bdrv_is_read_only(bs)) { + if (blk_is_read_only(blk)) { writable = false; } - exp = nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, NULL); + exp = nbd_export_new(blk, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, NULL); nbd_export_set_name(exp, device); n = g_new0(NBDCloseNotifier, 1); n->n.notify = nbd_close_notifier; n->exp = exp; - bdrv_add_close_notifier(bs, &n->n); + blk_add_close_notifier(blk, &n->n); QTAILQ_INSERT_TAIL(&close_notifiers, n, next); } diff --git a/blockdev.c b/blockdev.c index 57910b82c7..5651a8e140 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1105,6 +1105,7 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device, Error **errp) { BlockDriverState *bs = bdrv_find(device); + AioContext *aio_context; QEMUSnapshotInfo sn; Error *local_err = NULL; SnapshotInfo *info = NULL; @@ -1128,25 +1129,34 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device, return NULL; } + aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(aio_context); + + if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE, errp)) { + goto out_aio_context; + } + ret = bdrv_snapshot_find_by_id_and_name(bs, id, name, &sn, &local_err); if (local_err) { error_propagate(errp, local_err); - return NULL; + goto out_aio_context; } if (!ret) { error_setg(errp, "Snapshot with id '%s' and name '%s' does not exist on " "device '%s'", STR_OR_NULL(id), STR_OR_NULL(name), device); - return NULL; + goto out_aio_context; } bdrv_snapshot_delete(bs, id, name, &local_err); if (local_err) { error_propagate(errp, local_err); - return NULL; + goto out_aio_context; } + aio_context_release(aio_context); + info = g_new0(SnapshotInfo, 1); info->id = g_strdup(sn.id_str); info->name = g_strdup(sn.name); @@ -1157,9 +1167,13 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device, info->vm_clock_sec = sn.vm_clock_nsec / 1000000000; return info; + +out_aio_context: + aio_context_release(aio_context); + return NULL; } -/* New and old BlockDriverState structs for group snapshots */ +/* New and old BlockDriverState structs for atomic group operations */ typedef struct BlkTransactionState BlkTransactionState; @@ -1193,6 +1207,7 @@ struct BlkTransactionState { typedef struct InternalSnapshotState { BlkTransactionState common; BlockDriverState *bs; + AioContext *aio_context; QEMUSnapshotInfo sn; } InternalSnapshotState; @@ -1226,11 +1241,19 @@ static void internal_snapshot_prepare(BlkTransactionState *common, return; } + /* AioContext is released in .clean() */ + state->aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(state->aio_context); + if (!bdrv_is_inserted(bs)) { error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); return; } + if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT, errp)) { + return; + } + if (bdrv_is_read_only(bs)) { error_set(errp, QERR_DEVICE_IS_READ_ONLY, device); return; @@ -1303,11 +1326,22 @@ static void internal_snapshot_abort(BlkTransactionState *common) } } +static void internal_snapshot_clean(BlkTransactionState *common) +{ + InternalSnapshotState *state = DO_UPCAST(InternalSnapshotState, + common, common); + + if (state->aio_context) { + aio_context_release(state->aio_context); + } +} + /* external snapshot private data */ typedef struct ExternalSnapshotState { BlkTransactionState common; BlockDriverState *old_bs; BlockDriverState *new_bs; + AioContext *aio_context; } ExternalSnapshotState; static void external_snapshot_prepare(BlkTransactionState *common, @@ -1374,6 +1408,10 @@ static void external_snapshot_prepare(BlkTransactionState *common, return; } + /* Acquire AioContext now so any threads operating on old_bs stop */ + state->aio_context = bdrv_get_aio_context(state->old_bs); + aio_context_acquire(state->aio_context); + if (!bdrv_is_inserted(state->old_bs)) { error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); return; @@ -1432,6 +1470,8 @@ static void external_snapshot_commit(BlkTransactionState *common) ExternalSnapshotState *state = DO_UPCAST(ExternalSnapshotState, common, common); + bdrv_set_aio_context(state->new_bs, state->aio_context); + /* This removes our old bs and adds the new bs */ bdrv_append(state->new_bs, state->old_bs); /* We don't need (or want) to use the transactional @@ -1439,6 +1479,8 @@ static void external_snapshot_commit(BlkTransactionState *common) * don't want to abort all of them if one of them fails the reopen */ bdrv_reopen(state->new_bs, state->new_bs->open_flags & ~BDRV_O_RDWR, NULL); + + aio_context_release(state->aio_context); } static void external_snapshot_abort(BlkTransactionState *common) @@ -1448,23 +1490,38 @@ static void external_snapshot_abort(BlkTransactionState *common) if (state->new_bs) { bdrv_unref(state->new_bs); } + if (state->aio_context) { + aio_context_release(state->aio_context); + } } typedef struct DriveBackupState { BlkTransactionState common; BlockDriverState *bs; + AioContext *aio_context; BlockJob *job; } DriveBackupState; static void drive_backup_prepare(BlkTransactionState *common, Error **errp) { DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common); + BlockDriverState *bs; DriveBackup *backup; Error *local_err = NULL; assert(common->action->kind == TRANSACTION_ACTION_KIND_DRIVE_BACKUP); backup = common->action->drive_backup; + bs = bdrv_find(backup->device); + if (!bs) { + error_set(errp, QERR_DEVICE_NOT_FOUND, backup->device); + return; + } + + /* AioContext is released in .clean() */ + state->aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(state->aio_context); + qmp_drive_backup(backup->device, backup->target, backup->has_format, backup->format, backup->sync, @@ -1475,12 +1532,10 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp) &local_err); if (local_err) { error_propagate(errp, local_err); - state->bs = NULL; - state->job = NULL; return; } - state->bs = bdrv_find(backup->device); + state->bs = bs; state->job = state->bs->job; } @@ -1495,6 +1550,15 @@ static void drive_backup_abort(BlkTransactionState *common) } } +static void drive_backup_clean(BlkTransactionState *common) +{ + DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common); + + if (state->aio_context) { + aio_context_release(state->aio_context); + } +} + static void abort_prepare(BlkTransactionState *common, Error **errp) { error_setg(errp, "Transaction aborted using Abort action"); @@ -1516,6 +1580,7 @@ static const BdrvActionOps actions[] = { .instance_size = sizeof(DriveBackupState), .prepare = drive_backup_prepare, .abort = drive_backup_abort, + .clean = drive_backup_clean, }, [TRANSACTION_ACTION_KIND_ABORT] = { .instance_size = sizeof(BlkTransactionState), @@ -1526,13 +1591,13 @@ static const BdrvActionOps actions[] = { .instance_size = sizeof(InternalSnapshotState), .prepare = internal_snapshot_prepare, .abort = internal_snapshot_abort, + .clean = internal_snapshot_clean, }, }; /* - * 'Atomic' group snapshots. The snapshots are taken as a set, and if any fail - * then we do not pivot any of the devices in the group, and abandon the - * snapshots + * 'Atomic' group operations. The operations are performed as a set, and if + * any fail then we roll back all operations in the group. */ void qmp_transaction(TransactionActionList *dev_list, Error **errp) { @@ -1543,10 +1608,10 @@ void qmp_transaction(TransactionActionList *dev_list, Error **errp) QSIMPLEQ_HEAD(snap_bdrv_states, BlkTransactionState) snap_bdrv_states; QSIMPLEQ_INIT(&snap_bdrv_states); - /* drain all i/o before any snapshots */ + /* drain all i/o before any operations */ bdrv_drain_all(); - /* We don't do anything in this loop that commits us to the snapshot */ + /* We don't do anything in this loop that commits us to the operations */ while (NULL != dev_entry) { TransactionAction *dev_info = NULL; const BdrvActionOps *ops; @@ -1581,10 +1646,7 @@ void qmp_transaction(TransactionActionList *dev_list, Error **errp) goto exit; delete_and_fail: - /* - * failure, and it is all-or-none; abandon each new bs, and keep using - * the original bs for all images - */ + /* failure, and it is all-or-none; roll back all operations */ QSIMPLEQ_FOREACH(state, &snap_bdrv_states, entry) { if (state->ops->abort) { state->ops->abort(state); @@ -1603,14 +1665,18 @@ exit: static void eject_device(BlockBackend *blk, int force, Error **errp) { BlockDriverState *bs = blk_bs(blk); + AioContext *aio_context; + + aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(aio_context); if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) { - return; + goto out; } if (!blk_dev_has_removable_media(blk)) { error_setg(errp, "Device '%s' is not removable", bdrv_get_device_name(bs)); - return; + goto out; } if (blk_dev_is_medium_locked(blk) && !blk_dev_is_tray_open(blk)) { @@ -1618,11 +1684,14 @@ static void eject_device(BlockBackend *blk, int force, Error **errp) if (!force) { error_setg(errp, "Device '%s' is locked", bdrv_get_device_name(bs)); - return; + goto out; } } bdrv_close(bs); + +out: + aio_context_release(aio_context); } void qmp_eject(const char *device, bool has_force, bool force, Error **errp) @@ -1644,6 +1713,7 @@ void qmp_block_passwd(bool has_device, const char *device, { Error *local_err = NULL; BlockDriverState *bs; + AioContext *aio_context; int err; bs = bdrv_lookup_bs(has_device ? device : NULL, @@ -1654,16 +1724,23 @@ void qmp_block_passwd(bool has_device, const char *device, return; } + aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(aio_context); + err = bdrv_set_key(bs, password); if (err == -EINVAL) { error_set(errp, QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs)); - return; + goto out; } else if (err < 0) { error_set(errp, QERR_INVALID_PASSWORD); - return; + goto out; } + +out: + aio_context_release(aio_context); } +/* Assumes AioContext is held */ static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename, int bdrv_flags, BlockDriver *drv, const char *password, Error **errp) @@ -1696,6 +1773,7 @@ void qmp_change_blockdev(const char *device, const char *filename, { BlockBackend *blk; BlockDriverState *bs; + AioContext *aio_context; BlockDriver *drv = NULL; int bdrv_flags; Error *err = NULL; @@ -1707,24 +1785,30 @@ void qmp_change_blockdev(const char *device, const char *filename, } bs = blk_bs(blk); + aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(aio_context); + if (format) { drv = bdrv_find_whitelisted_format(format, bs->read_only); if (!drv) { error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); - return; + goto out; } } eject_device(blk, 0, &err); if (err) { error_propagate(errp, err); - return; + goto out; } bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR; bdrv_flags |= bdrv_is_snapshot(bs) ? BDRV_O_SNAPSHOT : 0; qmp_bdrv_open_encrypted(bs, filename, bdrv_flags, drv, NULL, errp); + +out: + aio_context_release(aio_context); } /* throttling disk I/O limits */ @@ -2548,6 +2632,7 @@ void qmp_change_backing_file(const char *device, Error **errp) { BlockDriverState *bs = NULL; + AioContext *aio_context; BlockDriverState *image_bs = NULL; Error *local_err = NULL; bool ro; @@ -2561,34 +2646,37 @@ void qmp_change_backing_file(const char *device, return; } + aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(aio_context); + image_bs = bdrv_lookup_bs(NULL, image_node_name, &local_err); if (local_err) { error_propagate(errp, local_err); - return; + goto out; } if (!image_bs) { error_setg(errp, "image file not found"); - return; + goto out; } if (bdrv_find_base(image_bs) == image_bs) { error_setg(errp, "not allowing backing file change on an image " "without a backing file"); - return; + goto out; } /* even though we are not necessarily operating on bs, we need it to * determine if block ops are currently prohibited on the chain */ if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_CHANGE, errp)) { - return; + goto out; } /* final sanity check */ if (!bdrv_chain_contains(bs, image_bs)) { error_setg(errp, "'%s' and image file are not in the same chain", device); - return; + goto out; } /* if not r/w, reopen to make r/w */ @@ -2599,7 +2687,7 @@ void qmp_change_backing_file(const char *device, bdrv_reopen(image_bs, open_flags | BDRV_O_RDWR, &local_err); if (local_err) { error_propagate(errp, local_err); - return; + goto out; } } @@ -2619,6 +2707,9 @@ void qmp_change_backing_file(const char *device, error_propagate(errp, local_err); /* will preserve prior errp */ } } + +out: + aio_context_release(aio_context); } void qmp_blockdev_add(BlockdevOptions *options, Error **errp) @@ -2727,7 +2727,7 @@ fi if test "$modules" = yes; then shacmd_probe="sha1sum sha1 shasum" for c in $shacmd_probe; do - if which $c >/dev/null 2>&1; then + if has $c; then shacmd="$c" break fi @@ -317,6 +317,8 @@ static GDBState *gdbserver_state; bool gdb_has_xml; +int semihosting_target = SEMIHOSTING_TARGET_AUTO; + #ifdef CONFIG_USER_ONLY /* XXX: This is not thread safe. Do we care? */ static int gdbserver_fd = -1; @@ -351,10 +353,19 @@ static enum { GDB_SYS_DISABLED, } gdb_syscall_mode; -/* If gdb is connected when the first semihosting syscall occurs then use - remote gdb syscalls. Otherwise use native file IO. */ +/* Decide if either remote gdb syscalls or native file IO should be used. */ int use_gdb_syscalls(void) { + if (semihosting_target == SEMIHOSTING_TARGET_NATIVE) { + /* -semihosting-config target=native */ + return false; + } else if (semihosting_target == SEMIHOSTING_TARGET_GDB) { + /* -semihosting-config target=gdb */ + return true; + } + + /* -semihosting-config target=auto */ + /* On the first call check if gdb is connected and remember. */ if (gdb_syscall_mode == GDB_SYS_UNKNOWN) { gdb_syscall_mode = (gdbserver_state ? GDB_SYS_ENABLED : GDB_SYS_DISABLED); @@ -290,14 +290,131 @@ void hmp_info_cpus(Monitor *mon, const QDict *qdict) qapi_free_CpuInfoList(cpu_list); } +static void print_block_info(Monitor *mon, BlockInfo *info, + BlockDeviceInfo *inserted, bool verbose) +{ + ImageInfo *image_info; + + assert(!info || !info->has_inserted || info->inserted == inserted); + + if (info) { + monitor_printf(mon, "%s", info->device); + if (inserted && inserted->has_node_name) { + monitor_printf(mon, " (%s)", inserted->node_name); + } + } else { + assert(inserted); + monitor_printf(mon, "%s", + inserted->has_node_name + ? inserted->node_name + : "<anonymous>"); + } + + if (inserted) { + monitor_printf(mon, ": %s (%s%s%s)\n", + inserted->file, + inserted->drv, + inserted->ro ? ", read-only" : "", + inserted->encrypted ? ", encrypted" : ""); + } else { + monitor_printf(mon, ": [not inserted]\n"); + } + + if (info) { + if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) { + monitor_printf(mon, " I/O status: %s\n", + BlockDeviceIoStatus_lookup[info->io_status]); + } + + if (info->removable) { + monitor_printf(mon, " Removable device: %slocked, tray %s\n", + info->locked ? "" : "not ", + info->tray_open ? "open" : "closed"); + } + } + + + if (!inserted) { + return; + } + + monitor_printf(mon, " Cache mode: %s%s%s\n", + inserted->cache->writeback ? "writeback" : "writethrough", + inserted->cache->direct ? ", direct" : "", + inserted->cache->no_flush ? ", ignore flushes" : ""); + + if (inserted->has_backing_file) { + monitor_printf(mon, + " Backing file: %s " + "(chain depth: %" PRId64 ")\n", + inserted->backing_file, + inserted->backing_file_depth); + } + + if (inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) { + monitor_printf(mon, " Detect zeroes: %s\n", + BlockdevDetectZeroesOptions_lookup[inserted->detect_zeroes]); + } + + if (inserted->bps || inserted->bps_rd || inserted->bps_wr || + inserted->iops || inserted->iops_rd || inserted->iops_wr) + { + monitor_printf(mon, " I/O throttling: bps=%" PRId64 + " bps_rd=%" PRId64 " bps_wr=%" PRId64 + " bps_max=%" PRId64 + " bps_rd_max=%" PRId64 + " bps_wr_max=%" PRId64 + " iops=%" PRId64 " iops_rd=%" PRId64 + " iops_wr=%" PRId64 + " iops_max=%" PRId64 + " iops_rd_max=%" PRId64 + " iops_wr_max=%" PRId64 + " iops_size=%" PRId64 "\n", + inserted->bps, + inserted->bps_rd, + inserted->bps_wr, + inserted->bps_max, + inserted->bps_rd_max, + inserted->bps_wr_max, + inserted->iops, + inserted->iops_rd, + inserted->iops_wr, + inserted->iops_max, + inserted->iops_rd_max, + inserted->iops_wr_max, + inserted->iops_size); + } + + if (verbose) { + monitor_printf(mon, "\nImages:\n"); + image_info = inserted->image; + while (1) { + bdrv_image_info_dump((fprintf_function)monitor_printf, + mon, image_info); + if (image_info->has_backing_image) { + image_info = image_info->backing_image; + } else { + break; + } + } + } +} + void hmp_info_block(Monitor *mon, const QDict *qdict) { BlockInfoList *block_list, *info; - ImageInfo *image_info; + BlockDeviceInfoList *blockdev_list, *blockdev; const char *device = qdict_get_try_str(qdict, "device"); bool verbose = qdict_get_try_bool(qdict, "verbose", 0); + bool nodes = qdict_get_try_bool(qdict, "nodes", 0); + bool printed = false; - block_list = qmp_query_block(NULL); + /* Print BlockBackend information */ + if (!nodes) { + block_list = qmp_query_block(false); + } else { + block_list = NULL; + } for (info = block_list; info; info = info->next) { if (device && strcmp(device, info->value->device)) { @@ -308,102 +425,40 @@ void hmp_info_block(Monitor *mon, const QDict *qdict) monitor_printf(mon, "\n"); } - monitor_printf(mon, "%s", info->value->device); - if (info->value->has_inserted) { - monitor_printf(mon, ": %s (%s%s%s)\n", - info->value->inserted->file, - info->value->inserted->drv, - info->value->inserted->ro ? ", read-only" : "", - info->value->inserted->encrypted ? ", encrypted" : ""); - } else { - monitor_printf(mon, ": [not inserted]\n"); - } - - if (info->value->has_io_status && info->value->io_status != BLOCK_DEVICE_IO_STATUS_OK) { - monitor_printf(mon, " I/O status: %s\n", - BlockDeviceIoStatus_lookup[info->value->io_status]); - } + print_block_info(mon, info->value, info->value->has_inserted + ? info->value->inserted : NULL, + verbose); + printed = true; + } - if (info->value->removable) { - monitor_printf(mon, " Removable device: %slocked, tray %s\n", - info->value->locked ? "" : "not ", - info->value->tray_open ? "open" : "closed"); - } + qapi_free_BlockInfoList(block_list); + if ((!device && !nodes) || printed) { + return; + } - if (!info->value->has_inserted) { + /* Print node information */ + blockdev_list = qmp_query_named_block_nodes(NULL); + for (blockdev = blockdev_list; blockdev; blockdev = blockdev->next) { + assert(blockdev->value->has_node_name); + if (device && strcmp(device, blockdev->value->node_name)) { continue; } - if (info->value->inserted->has_backing_file) { - monitor_printf(mon, - " Backing file: %s " - "(chain depth: %" PRId64 ")\n", - info->value->inserted->backing_file, - info->value->inserted->backing_file_depth); - } - - if (info->value->inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) { - monitor_printf(mon, " Detect zeroes: %s\n", - BlockdevDetectZeroesOptions_lookup[info->value->inserted->detect_zeroes]); - } - - if (info->value->inserted->bps - || info->value->inserted->bps_rd - || info->value->inserted->bps_wr - || info->value->inserted->iops - || info->value->inserted->iops_rd - || info->value->inserted->iops_wr) - { - monitor_printf(mon, " I/O throttling: bps=%" PRId64 - " bps_rd=%" PRId64 " bps_wr=%" PRId64 - " bps_max=%" PRId64 - " bps_rd_max=%" PRId64 - " bps_wr_max=%" PRId64 - " iops=%" PRId64 " iops_rd=%" PRId64 - " iops_wr=%" PRId64 - " iops_max=%" PRId64 - " iops_rd_max=%" PRId64 - " iops_wr_max=%" PRId64 - " iops_size=%" PRId64 "\n", - info->value->inserted->bps, - info->value->inserted->bps_rd, - info->value->inserted->bps_wr, - info->value->inserted->bps_max, - info->value->inserted->bps_rd_max, - info->value->inserted->bps_wr_max, - info->value->inserted->iops, - info->value->inserted->iops_rd, - info->value->inserted->iops_wr, - info->value->inserted->iops_max, - info->value->inserted->iops_rd_max, - info->value->inserted->iops_wr_max, - info->value->inserted->iops_size); + if (blockdev != blockdev_list) { + monitor_printf(mon, "\n"); } - if (verbose) { - monitor_printf(mon, "\nImages:\n"); - image_info = info->value->inserted->image; - while (1) { - bdrv_image_info_dump((fprintf_function)monitor_printf, - mon, image_info); - if (image_info->has_backing_image) { - image_info = image_info->backing_image; - } else { - break; - } - } - } + print_block_info(mon, NULL, blockdev->value, verbose); } - - qapi_free_BlockInfoList(block_list); + qapi_free_BlockDeviceInfoList(blockdev_list); } void hmp_info_blockstats(Monitor *mon, const QDict *qdict) { BlockStatsList *stats_list, *stats; - stats_list = qmp_query_blockstats(NULL); + stats_list = qmp_query_blockstats(false, false, NULL); for (stats = stats_list; stats; stats = stats->next) { if (!stats->value->has_device) { diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 0014c34ddd..e6a3c5bcfb 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -329,6 +329,8 @@ static void set_kernel_args_old(const struct arm_boot_info *info) * Returns: the size of the device tree image on success, * 0 if the image size exceeds the limit, * -1 on errors. + * + * Note: Must not be called unless have_dtb(binfo) is true. */ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo, hwaddr addr_limit) @@ -352,7 +354,7 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo, goto fail; } g_free(filename); - } else if (binfo->get_dtb) { + } else { fdt = binfo->get_dtb(binfo, &size); if (!fdt) { fprintf(stderr, "Board was unable to create a dtb blob\n"); diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index 693dfec9f2..8967cc4e0b 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -273,10 +273,10 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri, case 3: s->cpu->env.uncached_cpsr = ARM_CPU_MODE_SVC; s->cpu->env.daif = PSTATE_A | PSTATE_F | PSTATE_I; - s->cpu->env.cp15.c1_sys = 0; + s->cpu->env.cp15.sctlr_ns = 0; s->cpu->env.cp15.c1_coproc = 0; - s->cpu->env.cp15.ttbr0_el1 = 0; - s->cpu->env.cp15.c3 = 0; + s->cpu->env.cp15.ttbr0_el[1] = 0; + s->cpu->env.cp15.dacr_ns = 0; s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */ s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */ diff --git a/hw/arm/realview.c b/hw/arm/realview.c index af65aa4082..d41ec97a23 100644 --- a/hw/arm/realview.c +++ b/hw/arm/realview.c @@ -52,7 +52,7 @@ static void realview_init(MachineState *machine, CPUARMState *env; ObjectClass *cpu_oc; MemoryRegion *sysmem = get_system_memory(); - MemoryRegion *ram_lo = g_new(MemoryRegion, 1); + MemoryRegion *ram_lo; MemoryRegion *ram_hi = g_new(MemoryRegion, 1); MemoryRegion *ram_alias = g_new(MemoryRegion, 1); MemoryRegion *ram_hack = g_new(MemoryRegion, 1); @@ -135,6 +135,7 @@ static void realview_init(MachineState *machine, if (is_pb && ram_size > 0x20000000) { /* Core tile RAM. */ + ram_lo = g_new(MemoryRegion, 1); low_ram_size = ram_size - 0x20000000; ram_size = 0x20000000; memory_region_init_ram(ram_lo, NULL, "realview.lowmem", low_ram_size, diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 1222a37f4f..2a28978cba 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -197,7 +197,13 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_RESIZE, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_BACKUP_SOURCE, s->blocker); + blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_CHANGE, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_COMMIT, s->blocker); + blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_EJECT, s->blocker); + blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, s->blocker); + blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT, s->blocker); + blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE, + s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_MIRROR, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_STREAM, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_REPLACE, s->blocker); diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 13276589e4..aa1ed986d2 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -811,6 +811,7 @@ static int nvme_init(PCIDevice *pci_dev) NVME_CAP_SET_AMS(n->bar.cap, 1); NVME_CAP_SET_TO(n->bar.cap, 0xf); NVME_CAP_SET_CSS(n->bar.cap, 1); + NVME_CAP_SET_MPSMAX(n->bar.cap, 4); n->bar.vs = 0x00010001; n->bar.intmc = n->bar.intms = 0; diff --git a/hw/block/nvme.h b/hw/block/nvme.h index 993c51131c..b6ccb655a6 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -688,7 +688,7 @@ typedef struct NvmeCtrl { NvmeBar bar; BlockConf conf; - uint16_t page_size; + uint32_t page_size; uint16_t page_bits; uint16_t max_prp_ents; uint16_t cqe_size; diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index 8513a17e9f..389b4aa1f4 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -744,6 +744,7 @@ static void pflash_cfi02_class_init(ObjectClass *klass, void *data) dc->realize = pflash_cfi02_realize; dc->props = pflash_cfi02_properties; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } static const TypeInfo pflash_cfi02_info = { diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 413b41376f..901f289860 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -935,7 +935,7 @@ void qdev_alias_all_properties(DeviceState *target, Object *source) } while (class != object_class_by_name(TYPE_DEVICE)); } -int qdev_build_hotpluggable_device_list(Object *obj, void *opaque) +static int qdev_add_hotpluggable_device(Object *obj, void *opaque) { GSList **list = opaque; DeviceState *dev = DEVICE(obj); @@ -944,10 +944,18 @@ int qdev_build_hotpluggable_device_list(Object *obj, void *opaque) *list = g_slist_append(*list, dev); } - object_child_foreach(obj, qdev_build_hotpluggable_device_list, opaque); return 0; } +GSList *qdev_build_hotpluggable_device_list(Object *peripheral) +{ + GSList *list = NULL; + + object_child_foreach(peripheral, qdev_add_hotpluggable_device, &list); + + return list; +} + static bool device_get_realized(Object *obj, Error **errp) { DeviceState *dev = DEVICE(obj); @@ -1133,9 +1141,7 @@ static void device_finalize(Object *obj) NamedGPIOList *ngl, *next; DeviceState *dev = DEVICE(obj); - if (dev->opts) { - qemu_opts_del(dev->opts); - } + qemu_opts_del(dev->opts); QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) { QLIST_REMOVE(ngl, node); diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index 8a5b76c403..27252646bc 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -173,20 +173,6 @@ #define CIRRUS_PNPMMIO_SIZE 0x1000 -#define BLTUNSAFE(s) \ - ( \ - ( /* check dst is within bounds */ \ - (s)->cirrus_blt_height * ABS((s)->cirrus_blt_dstpitch) \ - + ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > \ - (s)->vga.vram_size \ - ) || \ - ( /* check src is within bounds */ \ - (s)->cirrus_blt_height * ABS((s)->cirrus_blt_srcpitch) \ - + ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > \ - (s)->vga.vram_size \ - ) \ - ) - struct CirrusVGAState; typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s, uint8_t * dst, const uint8_t * src, @@ -279,6 +265,50 @@ static void cirrus_update_memory_access(CirrusVGAState *s); * ***************************************/ +static bool blit_region_is_unsafe(struct CirrusVGAState *s, + int32_t pitch, int32_t addr) +{ + if (pitch < 0) { + int64_t min = addr + + ((int64_t)s->cirrus_blt_height-1) * pitch; + int32_t max = addr + + s->cirrus_blt_width; + if (min < 0 || max >= s->vga.vram_size) { + return true; + } + } else { + int64_t max = addr + + ((int64_t)s->cirrus_blt_height-1) * pitch + + s->cirrus_blt_width; + if (max >= s->vga.vram_size) { + return true; + } + } + return false; +} + +static bool blit_is_unsafe(struct CirrusVGAState *s) +{ + /* should be the case, see cirrus_bitblt_start */ + assert(s->cirrus_blt_width > 0); + assert(s->cirrus_blt_height > 0); + + if (s->cirrus_blt_width > CIRRUS_BLTBUFSIZE) { + return true; + } + + if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch, + s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) { + return true; + } + if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch, + s->cirrus_blt_srcaddr & s->cirrus_addr_mask)) { + return true; + } + + return false; +} + static void cirrus_bitblt_rop_nop(CirrusVGAState *s, uint8_t *dst,const uint8_t *src, int dstpitch,int srcpitch, @@ -636,7 +666,7 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, dst = s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask); - if (BLTUNSAFE(s)) + if (blit_is_unsafe(s)) return 0; (*s->cirrus_rop) (s, dst, src, @@ -654,8 +684,9 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop) { cirrus_fill_t rop_func; - if (BLTUNSAFE(s)) + if (blit_is_unsafe(s)) { return 0; + } rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; rop_func(s, s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), s->cirrus_blt_dstpitch, @@ -752,7 +783,7 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) { - if (BLTUNSAFE(s)) + if (blit_is_unsafe(s)) return 0; cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr, diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index b37a397820..a4d0c0c8bf 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -68,6 +68,14 @@ #define ACPI_BUILD_TABLE_SIZE 0x20000 +/* #define DEBUG_ACPI_BUILD */ +#ifdef DEBUG_ACPI_BUILD +#define ACPI_BUILD_DPRINTF(fmt, ...) \ + do {printf("ACPI_BUILD: " fmt, ## __VA_ARGS__); } while (0) +#else +#define ACPI_BUILD_DPRINTF(fmt, ...) +#endif + typedef struct AcpiCpuInfo { DECLARE_BITMAP(found_cpus, ACPI_CPU_HOTPLUG_ID_LIMIT); } AcpiCpuInfo; @@ -246,8 +254,6 @@ static void acpi_get_pci_info(PcPciInfo *info) #define ACPI_BUILD_APPNAME6 "BOCHS " #define ACPI_BUILD_APPNAME4 "BXPC" -#define ACPI_BUILD_DPRINTF(level, fmt, ...) do {} while (0) - #define ACPI_BUILD_TABLE_FILE "etc/acpi/tables" #define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp" #define ACPI_BUILD_TPMLOG_FILE "etc/tpm/log" @@ -273,12 +279,12 @@ build_header(GArray *linker, GArray *table_data, static inline GArray *build_alloc_array(void) { - return g_array_new(false, true /* clear */, 1); + return g_array_new(false, true /* clear */, 1); } static inline void build_free_array(GArray *array) { - g_array_free(array, true); + g_array_free(array, true); } static inline void build_prepend_byte(GArray *array, uint8_t val) @@ -1569,7 +1575,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables) table_offsets = g_array_new(false, true /* clear */, sizeof(uint32_t)); - ACPI_BUILD_DPRINTF(3, "init ACPI tables\n"); + ACPI_BUILD_DPRINTF("init ACPI tables\n"); bios_linker_loader_alloc(tables->linker, ACPI_BUILD_TABLE_FILE, 64 /* Ensure FACS is aligned */, @@ -1750,17 +1756,17 @@ void acpi_setup(PcGuestInfo *guest_info) AcpiBuildState *build_state; if (!guest_info->fw_cfg) { - ACPI_BUILD_DPRINTF(3, "No fw cfg. Bailing out.\n"); + ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n"); return; } if (!guest_info->has_acpi_build) { - ACPI_BUILD_DPRINTF(3, "ACPI build disabled. Bailing out.\n"); + ACPI_BUILD_DPRINTF("ACPI build disabled. Bailing out.\n"); return; } if (!acpi_enabled) { - ACPI_BUILD_DPRINTF(3, "ACPI disabled. Bailing out.\n"); + ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n"); return; } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 60c1d54b6d..c0e55a6446 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -61,6 +61,7 @@ #include "hw/mem/pc-dimm.h" #include "trace.h" #include "qapi/visitor.h" +#include "qapi-visit.h" /* debug PC/ISA interrupts */ //#define DEBUG_IRQ @@ -1771,18 +1772,21 @@ static void pc_machine_set_max_ram_below_4g(Object *obj, Visitor *v, pcms->max_ram_below_4g = value; } -static bool pc_machine_get_vmport(Object *obj, Error **errp) +static void pc_machine_get_vmport(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) { PCMachineState *pcms = PC_MACHINE(obj); + OnOffAuto vmport = pcms->vmport; - return pcms->vmport; + visit_type_OnOffAuto(v, &vmport, name, errp); } -static void pc_machine_set_vmport(Object *obj, bool value, Error **errp) +static void pc_machine_set_vmport(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) { PCMachineState *pcms = PC_MACHINE(obj); - pcms->vmport = value; + visit_type_OnOffAuto(v, &pcms->vmport, name, errp); } static bool pc_machine_get_aligned_dimm(Object *obj, Error **errp) @@ -1805,11 +1809,11 @@ static void pc_machine_initfn(Object *obj) pc_machine_set_max_ram_below_4g, NULL, NULL, NULL); - pcms->vmport = !xen_enabled(); - object_property_add_bool(obj, PC_MACHINE_VMPORT, - pc_machine_get_vmport, - pc_machine_set_vmport, - NULL); + pcms->vmport = ON_OFF_AUTO_AUTO; + object_property_add(obj, PC_MACHINE_VMPORT, "OnOffAuto", + pc_machine_get_vmport, + pc_machine_set_vmport, + NULL, NULL, NULL); pcms->enforce_aligned_dimm = true; object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM, diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 7647e34528..220f7415fa 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -234,9 +234,14 @@ static void pc_init1(MachineState *machine, pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL); + assert(pc_machine->vmport != ON_OFF_AUTO_MAX); + if (pc_machine->vmport == ON_OFF_AUTO_AUTO) { + pc_machine->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON; + } + /* init basic PC hardware */ pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, - !pc_machine->vmport, 0x4); + (pc_machine->vmport != ON_OFF_AUTO_ON), 0x4); pc_nic_init(isa_bus, pci_bus); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 858e82889d..7ba05353aa 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -242,9 +242,14 @@ static void pc_q35_init(MachineState *machine) pc_register_ferr_irq(gsi[13]); + assert(pc_machine->vmport != ON_OFF_AUTO_MAX); + if (pc_machine->vmport == ON_OFF_AUTO_AUTO) { + pc_machine->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON; + } + /* init basic PC hardware */ pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, - !pc_machine->vmport, 0xff0104); + (pc_machine->vmport != ON_OFF_AUTO_ON), 0xff0104); /* connect pm stuff to lpc */ ich9_lpc_pm_init(lpc); diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 94f28e6bac..5651372be3 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -34,15 +34,15 @@ #include <hw/ide/pci.h> #include <hw/ide/ahci.h> -/* #define DEBUG_AHCI */ +#define DEBUG_AHCI 0 -#ifdef DEBUG_AHCI #define DPRINTF(port, fmt, ...) \ -do { fprintf(stderr, "ahci: %s: [%d] ", __FUNCTION__, port); \ - fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(port, fmt, ...) do {} while(0) -#endif +do { \ + if (DEBUG_AHCI) { \ + fprintf(stderr, "ahci: %s: [%d] ", __func__, port); \ + fprintf(stderr, fmt, ## __VA_ARGS__); \ + } \ +} while (0) static void check_cmd(AHCIState *s, int port); static int handle_cmd(AHCIState *s,int port,int slot); @@ -551,7 +551,7 @@ static void ahci_reset_port(AHCIState *s, int port) static void debug_print_fis(uint8_t *fis, int cmd_len) { -#ifdef DEBUG_AHCI +#if DEBUG_AHCI int i; fprintf(stderr, "fis:"); @@ -580,7 +580,7 @@ static void ahci_write_fis_sdb(AHCIState *s, int port, uint32_t finished) sdb_fis = (SDBFIS *)&ad->res_fis[RES_FIS_SDBFIS]; ide_state = &ad->port.ifs[0]; - sdb_fis->type = 0xA1; + sdb_fis->type = SATA_FIS_TYPE_SDB; /* Interrupt pending & Notification bit */ sdb_fis->flags = (ad->hba->control_regs.irqstatus ? (1 << 6) : 0); sdb_fis->status = ide_state->status & 0x77; @@ -631,7 +631,7 @@ static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len) pio_fis = &ad->res_fis[RES_FIS_PSFIS]; - pio_fis[0] = 0x5f; + pio_fis[0] = SATA_FIS_TYPE_PIO_SETUP; pio_fis[1] = (ad->hba->control_regs.irqstatus ? (1 << 6) : 0); pio_fis[2] = s->status; pio_fis[3] = s->error; @@ -690,7 +690,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) d2h_fis = &ad->res_fis[RES_FIS_RFIS]; - d2h_fis[0] = 0x34; + d2h_fis[0] = SATA_FIS_TYPE_REGISTER_D2H; d2h_fis[1] = (ad->hba->control_regs.irqstatus ? (1 << 6) : 0); d2h_fis[2] = s->status; d2h_fis[3] = s->error; @@ -1154,9 +1154,7 @@ out: static void ahci_start_dma(IDEDMA *dma, IDEState *s, BlockCompletionFunc *dma_cb) { -#ifdef DEBUG_AHCI AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); -#endif DPRINTF(ad->port_no, "\n"); s->io_buffer_offset = 0; dma_cb(s, 0); diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h index e0d2eb8f15..99aa0c967f 100644 --- a/hw/ide/ahci.h +++ b/hw/ide/ahci.h @@ -156,7 +156,10 @@ #define AHCI_SCR_SCTL_DET 0xf #define SATA_FIS_TYPE_REGISTER_H2D 0x27 -#define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80 +#define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80 +#define SATA_FIS_TYPE_REGISTER_D2H 0x34 +#define SATA_FIS_TYPE_PIO_SETUP 0x5f +#define SATA_FIS_TYPE_SDB 0xA1 #define AHCI_CMD_HDR_CMD_FIS_LEN 0x1f #define AHCI_CMD_HDR_PRDT_LEN 16 diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index b4f096e12e..1ebb58d36d 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -163,6 +163,11 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) return -1; } + if (dev->conf.logical_block_size != 512) { + error_report("logical_block_size must be 512 for IDE"); + return -1; + } + blkconf_serial(&dev->conf, &dev->serial); if (kind != IDE_CD) { blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255, &err); diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c index 5038885afd..1ad3eb0ff8 100644 --- a/hw/intc/arm_gic_kvm.c +++ b/hw/intc/arm_gic_kvm.c @@ -92,6 +92,21 @@ static bool kvm_arm_gic_can_save_restore(GICState *s) return s->dev_fd >= 0; } +static bool kvm_gic_supports_attr(GICState *s, int group, int attrnum) +{ + struct kvm_device_attr attr = { + .group = group, + .attr = attrnum, + .flags = 0, + }; + + if (s->dev_fd == -1) { + return false; + } + + return kvm_device_ioctl(s->dev_fd, KVM_HAS_DEVICE_ATTR, &attr) == 0; +} + static void kvm_gic_access(GICState *s, int group, int offset, int cpu, uint32_t *val, bool write) { @@ -553,6 +568,11 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) return; } + if (kvm_gic_supports_attr(s, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) { + uint32_t numirqs = s->num_irq; + kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, 0, &numirqs, 1); + } + /* Distributor */ memory_region_init_reservation(&s->iomem, OBJECT(s), "kvm-gic_dist", 0x1000); diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index e0c235c3c2..223b947939 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -50,13 +50,13 @@ typedef struct VT82C686BState { static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data, unsigned size) { - int can_write; SuperIOConfig *superio_conf = opaque; DPRINTF("superio_ioport_writeb address 0x%x val 0x%x\n", addr, data); if (addr == 0x3f0) { superio_conf->index = data & 0xff; } else { + bool can_write = true; /* 0x3f1 */ switch (superio_conf->index) { case 0x00 ... 0xdf: @@ -68,30 +68,27 @@ static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data, case 0xf7: case 0xf9 ... 0xfb: case 0xfd ... 0xff: - can_write = 0; + can_write = false; break; - default: - can_write = 1; - - if (can_write) { - switch (superio_conf->index) { - case 0xe7: - if ((data & 0xff) != 0xfe) { - DPRINTF("chage uart 1 base. unsupported yet\n"); - } - break; - case 0xe8: - if ((data & 0xff) != 0xbe) { - DPRINTF("chage uart 2 base. unsupported yet\n"); - } - break; - - default: - superio_conf->config[superio_conf->index] = data & 0xff; - } + case 0xe7: + if ((data & 0xff) != 0xfe) { + DPRINTF("change uart 1 base. unsupported yet\n"); + can_write = false; + } + break; + case 0xe8: + if ((data & 0xff) != 0xbe) { + DPRINTF("change uart 2 base. unsupported yet\n"); + can_write = false; } + break; + default: + break; + + } + if (can_write) { + superio_conf->config[superio_conf->index] = data & 0xff; } - superio_conf->config[superio_conf->index] = data & 0xff; } } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 9b88775fac..e574bd4322 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -798,7 +798,7 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) virtio_net_ctrl_ack status = VIRTIO_NET_ERR; VirtQueueElement elem; size_t s; - struct iovec *iov; + struct iovec *iov, *iov2; unsigned int iov_cnt; while (virtqueue_pop(vq, &elem)) { @@ -808,8 +808,8 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) exit(1); } - iov = elem.out_sg; iov_cnt = elem.out_num; + iov2 = iov = g_memdup(elem.out_sg, sizeof(struct iovec) * elem.out_num); s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl)); iov_discard_front(&iov, &iov_cnt, sizeof(ctrl)); if (s != sizeof(ctrl)) { @@ -833,6 +833,7 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) virtqueue_push(vq, &elem, sizeof(status)); virtio_notify(vdev, vq); + g_free(iov2); } } diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index e7ed27e242..c4b78ed36c 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -523,6 +523,7 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data, size_t len) { int i, index; + void *ptr = NULL; assert(s->files); @@ -531,8 +532,10 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename, for (i = 0; i < index; i++) { if (strcmp(filename, s->files->f[i].name) == 0) { - return fw_cfg_modify_bytes_read(s, FW_CFG_FILE_FIRST + i, - data, len); + ptr = fw_cfg_modify_bytes_read(s, FW_CFG_FILE_FIRST + i, + data, len); + s->files->f[i].size = cpu_to_be32(len); + return ptr; } } /* add new one */ @@ -618,7 +621,6 @@ static void fw_cfg_realize(DeviceState *dev, Error **errp) FWCfgState *s = FW_CFG(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - if (s->ctl_iobase + 1 == s->data_iobase) { sysbus_add_io(sbd, s->ctl_iobase, &s->comb_iomem); } else { diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index 308b393f96..dcb2bc5a6e 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -233,6 +233,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) vhost_dummy_handle_output); if (err != NULL) { error_propagate(errp, err); + close(vhostfd); return; } diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index e160e8facc..d8bc231e5b 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -1,5 +1,5 @@ /* - * High Precisition Event Timer emulation + * High Precision Event Timer emulation * * Copyright (c) 2007 Alexander Graf * Copyright (c) 2008 IBM Corporation diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c index 56e9e0f8a2..2bf3c6fd61 100644 --- a/hw/tpm/tpm_passthrough.c +++ b/hw/tpm/tpm_passthrough.c @@ -400,9 +400,7 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) const char *value; value = qemu_opt_get(opts, "cancel-path"); - if (value) { - tb->cancel_path = g_strdup(value); - } + tb->cancel_path = g_strdup(value); value = qemu_opt_get(opts, "path"); if (!value) { diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index a5f9dab0cd..cff4f7cd51 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -1237,7 +1237,7 @@ static void usb_host_handle_control(USBDevice *udev, USBPacket *p, /* Fix up USB-3 ep0 maxpacket size to allow superspeed connected devices * to work redirected to a not superspeed capable hcd */ if (udev->speed == USB_SPEED_SUPER && - !((udev->port->speedmask & USB_SPEED_MASK_SUPER)) && + !(udev->port->speedmask & USB_SPEED_MASK_SUPER) && request == 0x8006 && value == 0x100 && index == 0) { r->usb3ep0quirk = true; } diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 5d7c40ac04..5a128613bb 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -817,10 +817,12 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, int i, r; if (vhost_set_backend_type(hdev, backend_type) < 0) { + close((uintptr_t)opaque); return -1; } if (hdev->vhost_ops->vhost_backend_init(hdev, opaque) < 0) { + close((uintptr_t)opaque); return -errno; } diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c index eb77019267..dfd2d8c772 100644 --- a/hw/virtio/virtio-bus.c +++ b/hw/virtio/virtio-bus.c @@ -58,7 +58,7 @@ void virtio_bus_reset(VirtioBusState *bus) { VirtIODevice *vdev = virtio_bus_get_device(bus); - DPRINTF("%s: reset device.\n", qbus->name); + DPRINTF("%s: reset device.\n", BUS(bus)->name); if (vdev != NULL) { virtio_reset(vdev); } diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c index e85a979754..473c04410e 100644 --- a/hw/virtio/virtio-rng.c +++ b/hw/virtio/virtio-rng.c @@ -113,20 +113,22 @@ static void virtio_rng_save(QEMUFile *f, void *opaque) static int virtio_rng_load(QEMUFile *f, void *opaque, int version_id) { + VirtIORNG *vrng = opaque; + int ret; + if (version_id != 1) { return -EINVAL; } - return virtio_load(VIRTIO_DEVICE(opaque), f, version_id); -} + ret = virtio_load(VIRTIO_DEVICE(vrng), f, version_id); + if (ret != 0) { + return ret; + } -static int virtio_rng_load_device(VirtIODevice *vdev, QEMUFile *f, - int version_id) -{ /* We may have an element ready but couldn't process it due to a quota * limit. Make sure to try again after live migration when the quota may * have been reset. */ - virtio_rng_process(VIRTIO_RNG(vdev)); + virtio_rng_process(vrng); return 0; } @@ -231,7 +233,6 @@ static void virtio_rng_class_init(ObjectClass *klass, void *data) vdc->realize = virtio_rng_device_realize; vdc->unrealize = virtio_rng_device_unrealize; vdc->get_features = get_features; - vdc->load = virtio_rng_load_device; } static void virtio_rng_initfn(Object *obj) diff --git a/include/block/block.h b/include/block/block.h index 5450610bc1..6e7275d95b 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -329,8 +329,6 @@ BlockAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp); void bdrv_invalidate_cache_all(Error **errp); -void bdrv_clear_incoming_migration_all(void); - /* Ensure contents are flushed to disk. */ int bdrv_flush(BlockDriverState *bs); int coroutine_fn bdrv_co_flush(BlockDriverState *bs); @@ -374,6 +372,7 @@ BlockDriverState *bdrv_lookup_bs(const char *device, const char *node_name, Error **errp); bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base); +BlockDriverState *bdrv_next_node(BlockDriverState *bs); BlockDriverState *bdrv_next(BlockDriverState *bs); int bdrv_is_encrypted(BlockDriverState *bs); int bdrv_key_required(BlockDriverState *bs); @@ -381,6 +380,7 @@ int bdrv_set_key(BlockDriverState *bs, const char *key); int bdrv_query_missing_keys(void); void bdrv_iterate_format(void (*it)(void *opaque, const char *name), void *opaque); +const char *bdrv_get_node_name(const BlockDriverState *bs); const char *bdrv_get_device_name(const BlockDriverState *bs); int bdrv_get_flags(BlockDriverState *bs); int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, @@ -399,6 +399,7 @@ void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz); int bdrv_is_snapshot(BlockDriverState *bs); +int path_has_protocol(const char *path); int path_is_absolute(const char *path); void path_combine(char *dest, int dest_size, const char *base_path, diff --git a/include/block/block_int.h b/include/block/block_int.h index a1c17b9578..06a21dd13d 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -57,6 +57,8 @@ #define BLOCK_OPT_REDUNDANCY "redundancy" #define BLOCK_OPT_NOCOW "nocow" +#define BLOCK_PROBE_BUF_SIZE 512 + typedef struct BdrvTrackedRequest { BlockDriverState *bs; int64_t offset; @@ -324,6 +326,7 @@ struct BlockDriverState { int sg; /* if true, the device is a /dev/sg* */ int copy_on_read; /* if true, copy read backing sectors into image note this is a reference count */ + bool probed; BlockDriver *drv; /* NULL means no media */ void *opaque; @@ -411,7 +414,17 @@ struct BlockDriverState { Error *backing_blocker; }; + +/* Essential block drivers which must always be statically linked into qemu, and + * which therefore can be accessed without using bdrv_find_format() */ +extern BlockDriver bdrv_file; +extern BlockDriver bdrv_raw; +extern BlockDriver bdrv_qcow2; + + int get_tmp_filename(char *filename, int size); +BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, + const char *filename); void bdrv_set_io_limits(BlockDriverState *bs, ThrottleConfig *cfg); diff --git a/include/block/nbd.h b/include/block/nbd.h index 9e835d2cbb..348302c90b 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -85,14 +85,13 @@ int nbd_disconnect(int fd); typedef struct NBDExport NBDExport; typedef struct NBDClient NBDClient; -NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, - off_t size, uint32_t nbdflags, - void (*close)(NBDExport *)); +NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, + uint32_t nbdflags, void (*close)(NBDExport *)); void nbd_export_close(NBDExport *exp); void nbd_export_get(NBDExport *exp); void nbd_export_put(NBDExport *exp); -BlockDriverState *nbd_export_get_blockdev(NBDExport *exp); +BlockBackend *nbd_export_get_blockdev(NBDExport *exp); NBDExport *nbd_export_find(const char *name); void nbd_export_set_name(NBDExport *exp, const char *name); diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h index a608a26c30..c6332489a7 100644 --- a/include/exec/gdbstub.h +++ b/include/exec/gdbstub.h @@ -95,4 +95,10 @@ extern bool gdb_has_xml; /* in gdbstub-xml.c, generated by scripts/feature_to_c.sh */ extern const char *const xml_builtin[][2]; +/* Command line option defining whether semihosting should go via gdb or not */ +extern int semihosting_target; +#define SEMIHOSTING_TARGET_AUTO 0 +#define SEMIHOSTING_TARGET_NATIVE 1 +#define SEMIHOSTING_TARGET_GDB 2 + #endif diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 9d85b89e4f..69d9cf8e67 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -39,7 +39,7 @@ struct PCMachineState { ISADevice *rtc; uint64_t max_ram_below_4g; - bool vmport; + OnOffAuto vmport; bool enforce_aligned_dimm; }; diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index d3a29408d4..589bbe7360 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -365,7 +365,7 @@ extern int qdev_hotplug; char *qdev_get_dev_path(DeviceState *dev); -int qdev_build_hotpluggable_device_list(Object *obj, void *opaque); +GSList *qdev_build_hotpluggable_device_list(Object *peripheral); void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, Error **errp); diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 0726d76f49..f24997d218 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -230,9 +230,6 @@ int virtio_set_features(VirtIODevice *vdev, uint32_t val); /* Base devices. */ typedef struct VirtIOBlkConf VirtIOBlkConf; struct virtio_net_conf; -VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf, - struct virtio_net_conf *net, - uint32_t host_features); typedef struct virtio_serial_conf virtio_serial_conf; typedef struct VirtIOSCSIConf VirtIOSCSIConf; typedef struct VirtIORNGConf VirtIORNGConf; diff --git a/include/qemu/option.h b/include/qemu/option.h index 59bea759a2..58c0157ed5 100644 --- a/include/qemu/option.h +++ b/include/qemu/option.h @@ -124,7 +124,7 @@ QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict); void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp); typedef int (*qemu_opts_loopfunc)(QemuOpts *opts, void *opaque); -void qemu_opts_print(QemuOpts *opts); +void qemu_opts_print(QemuOpts *opts, const char *sep); int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque, int abort_on_failure); void qemu_opts_print_help(QemuOptsList *list); diff --git a/include/qemu/queue.h b/include/qemu/queue.h index d433b9017c..42bcadfbb1 100644 --- a/include/qemu/queue.h +++ b/include/qemu/queue.h @@ -268,6 +268,17 @@ struct { \ (head)->sqh_last = &(head)->sqh_first; \ } while (/*CONSTCOND*/0) +#define QSIMPLEQ_SPLIT_AFTER(head, elm, field, removed) do { \ + QSIMPLEQ_INIT(removed); \ + if (((removed)->sqh_first = (head)->sqh_first) != NULL) { \ + if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) { \ + (head)->sqh_last = &(head)->sqh_first; \ + } \ + (removed)->sqh_last = &(elm)->field.sqe_next; \ + (elm)->field.sqe_next = NULL; \ + } \ +} while (/*CONSTCOND*/0) + #define QSIMPLEQ_REMOVE(head, elm, type, field) do { \ if ((head)->sqh_first == (elm)) { \ QSIMPLEQ_REMOVE_HEAD((head), field); \ diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index 34751778a3..57ff47f284 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -3,80 +3,75 @@ /* A load of opaque types so that device init declarations don't have to pull in all the real definitions. */ -typedef struct QEMUTimer QEMUTimer; -typedef struct QEMUTimerListGroup QEMUTimerListGroup; -typedef struct QEMUFile QEMUFile; -typedef struct QEMUBH QEMUBH; - -typedef struct AioContext AioContext; - -typedef struct Visitor Visitor; - struct Monitor; -typedef struct Monitor Monitor; -typedef struct MigrationParams MigrationParams; - -typedef struct Property Property; -typedef struct PropertyInfo PropertyInfo; -typedef struct CompatProperty CompatProperty; -typedef struct DeviceState DeviceState; -typedef struct BusState BusState; -typedef struct BusClass BusClass; +/* Please keep this list in alphabetical order */ +typedef struct AdapterInfo AdapterInfo; typedef struct AddressSpace AddressSpace; -typedef struct MemoryRegion MemoryRegion; -typedef struct MemoryRegionSection MemoryRegionSection; -typedef struct MemoryListener MemoryListener; - -typedef struct MemoryMappingList MemoryMappingList; - -typedef struct QEMUMachine QEMUMachine; -typedef struct MachineClass MachineClass; -typedef struct MachineState MachineState; -typedef struct NICInfo NICInfo; -typedef struct HCIInfo HCIInfo; +typedef struct AioContext AioContext; typedef struct AudioState AudioState; typedef struct BlockBackend BlockBackend; typedef struct BlockDriverState BlockDriverState; -typedef struct DriveInfo DriveInfo; -typedef struct DisplayState DisplayState; +typedef struct BusClass BusClass; +typedef struct BusState BusState; +typedef struct CharDriverState CharDriverState; +typedef struct CompatProperty CompatProperty; +typedef struct DeviceState DeviceState; typedef struct DisplayChangeListener DisplayChangeListener; +typedef struct DisplayState DisplayState; typedef struct DisplaySurface DisplaySurface; -typedef struct PixelFormat PixelFormat; -typedef struct QemuConsole QemuConsole; -typedef struct CharDriverState CharDriverState; -typedef struct MACAddr MACAddr; -typedef struct NetClientState NetClientState; +typedef struct DriveInfo DriveInfo; +typedef struct EventNotifier EventNotifier; +typedef struct FWCfgState FWCfgState; +typedef struct HCIInfo HCIInfo; typedef struct I2CBus I2CBus; +typedef struct I2SCodec I2SCodec; typedef struct ISABus ISABus; typedef struct ISADevice ISADevice; -typedef struct SMBusDevice SMBusDevice; -typedef struct PCIHostState PCIHostState; -typedef struct PCIExpressHost PCIExpressHost; +typedef struct MACAddr MACAddr; +typedef struct MachineClass MachineClass; +typedef struct MachineState MachineState; +typedef struct MemoryListener MemoryListener; +typedef struct MemoryMappingList MemoryMappingList; +typedef struct MemoryRegion MemoryRegion; +typedef struct MemoryRegionSection MemoryRegionSection; +typedef struct MigrationParams MigrationParams; +typedef struct Monitor Monitor; +typedef struct MouseTransformInfo MouseTransformInfo; +typedef struct MSIMessage MSIMessage; +typedef struct NetClientState NetClientState; +typedef struct NICInfo NICInfo; +typedef struct PcGuestInfo PcGuestInfo; +typedef struct PCIBridge PCIBridge; typedef struct PCIBus PCIBus; typedef struct PCIDevice PCIDevice; -typedef struct PCIExpressDevice PCIExpressDevice; -typedef struct PCIBridge PCIBridge; -typedef struct PCIEAERMsg PCIEAERMsg; -typedef struct PCIEAERLog PCIEAERLog; typedef struct PCIEAERErr PCIEAERErr; +typedef struct PCIEAERLog PCIEAERLog; +typedef struct PCIEAERMsg PCIEAERMsg; typedef struct PCIEPort PCIEPort; typedef struct PCIESlot PCIESlot; -typedef struct MSIMessage MSIMessage; -typedef struct SerialState SerialState; +typedef struct PCIExpressDevice PCIExpressDevice; +typedef struct PCIExpressHost PCIExpressHost; +typedef struct PCIHostState PCIHostState; typedef struct PCMCIACardState PCMCIACardState; -typedef struct MouseTransformInfo MouseTransformInfo; -typedef struct uWireSlave uWireSlave; -typedef struct I2SCodec I2SCodec; -typedef struct SSIBus SSIBus; -typedef struct EventNotifier EventNotifier; -typedef struct VirtIODevice VirtIODevice; +typedef struct PixelFormat PixelFormat; +typedef struct PropertyInfo PropertyInfo; +typedef struct Property Property; +typedef struct QEMUBH QEMUBH; +typedef struct QemuConsole QemuConsole; +typedef struct QEMUFile QEMUFile; +typedef struct QEMUMachine QEMUMachine; typedef struct QEMUSGList QEMUSGList; typedef struct QEMUSizedBuffer QEMUSizedBuffer; -typedef struct SHPCDevice SHPCDevice; -typedef struct FWCfgState FWCfgState; -typedef struct PcGuestInfo PcGuestInfo; +typedef struct QEMUTimerListGroup QEMUTimerListGroup; +typedef struct QEMUTimer QEMUTimer; typedef struct Range Range; -typedef struct AdapterInfo AdapterInfo; +typedef struct SerialState SerialState; +typedef struct SHPCDevice SHPCDevice; +typedef struct SMBusDevice SMBusDevice; +typedef struct SSIBus SSIBus; +typedef struct uWireSlave uWireSlave; +typedef struct VirtIODevice VirtIODevice; +typedef struct Visitor Visitor; #endif /* QEMU_TYPEDEFS_H */ diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 52d13c1c0e..8871a021d0 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -108,6 +108,8 @@ int blk_aio_multiwrite(BlockBackend *blk, BlockRequest *reqs, int num_reqs); int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf); BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf, BlockCompletionFunc *cb, void *opaque); +int blk_co_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors); +int blk_co_flush(BlockBackend *blk); int blk_flush(BlockBackend *blk); int blk_flush_all(void); void blk_drain_all(void); @@ -120,6 +122,7 @@ int blk_is_read_only(BlockBackend *blk); int blk_is_sg(BlockBackend *blk); int blk_enable_write_cache(BlockBackend *blk); void blk_set_enable_write_cache(BlockBackend *blk, bool wce); +void blk_invalidate_cache(BlockBackend *blk, Error **errp); int blk_is_inserted(BlockBackend *blk); void blk_lock_medium(BlockBackend *blk, bool locked); void blk_eject(BlockBackend *blk, bool eject_flag); @@ -132,6 +135,15 @@ void blk_op_block_all(BlockBackend *blk, Error *reason); void blk_op_unblock_all(BlockBackend *blk, Error *reason); AioContext *blk_get_aio_context(BlockBackend *blk); void blk_set_aio_context(BlockBackend *blk, AioContext *new_context); +void blk_add_aio_context_notifier(BlockBackend *blk, + void (*attached_aio_context)(AioContext *new_context, void *opaque), + void (*detach_aio_context)(void *opaque), void *opaque); +void blk_remove_aio_context_notifier(BlockBackend *blk, + void (*attached_aio_context)(AioContext *, + void *), + void (*detach_aio_context)(void *), + void *opaque); +void blk_add_close_notifier(BlockBackend *blk, Notifier *notify); void blk_io_plug(BlockBackend *blk); void blk_io_unplug(BlockBackend *blk); BlockAcctStats *blk_get_stats(BlockBackend *blk); diff --git a/linux-user/aarch64/target_cpu.h b/linux-user/aarch64/target_cpu.h index 21560ef832..b5593dc5ad 100644 --- a/linux-user/aarch64/target_cpu.h +++ b/linux-user/aarch64/target_cpu.h @@ -32,7 +32,7 @@ static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls) /* Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is * different from AArch32 Linux, which uses TPIDRRO. */ - env->cp15.tpidr_el0 = newtls; + env->cp15.tpidr_el[0] = newtls; } #endif diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h index 39d65b692b..d8a534d7b1 100644 --- a/linux-user/arm/target_cpu.h +++ b/linux-user/arm/target_cpu.h @@ -29,7 +29,7 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls) { - env->cp15.tpidrro_el0 = newtls; + env->cp15.tpidrro_el[0] = newtls; } #endif diff --git a/linux-user/main.c b/linux-user/main.c index 5c14c1e874..186ee4d54f 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -564,7 +564,7 @@ do_kernel_trap(CPUARMState *env) end_exclusive(); break; case 0xffff0fe0: /* __kernel_get_tls */ - env->regs[0] = env->cp15.tpidrro_el0; + env->regs[0] = env->cp15.tpidrro_el[0]; break; case 0xffff0f60: /* __kernel_cmpxchg64 */ arm_kernel_cmpxchg64_helper(env); @@ -2628,10 +2628,10 @@ static mon_cmd_t info_cmds[] = { }, { .name = "block", - .args_type = "verbose:-v,device:B?", - .params = "[-v] [device]", + .args_type = "nodes:-n,verbose:-v,device:B?", + .params = "[-n] [-v] [device]", .help = "show info of one block device or all block devices " - "(and details of images with -v option)", + "(-n: show named nodes; -v: show details)", .mhandler.cmd = hmp_info_block, }, { @@ -4321,17 +4321,14 @@ void object_add_completion(ReadLineState *rs, int nb_args, const char *str) static void peripheral_device_del_completion(ReadLineState *rs, const char *str, size_t len) { - Object *peripheral; - GSList *list = NULL, *item; + Object *peripheral = container_get(qdev_get_machine(), "/peripheral"); + GSList *list, *item; - peripheral = object_resolve_path("/machine/peripheral/", NULL); - if (peripheral == NULL) { + list = qdev_build_hotpluggable_device_list(peripheral); + if (!list) { return; } - object_child_foreach(peripheral, qdev_build_hotpluggable_device_list, - &list); - for (item = list; item; item = g_slist_next(item)) { DeviceState *dev = item->data; @@ -4698,7 +4695,7 @@ static void monitor_find_completion_by_table(Monitor *mon, } } str = args[nb_args - 1]; - if (*ptype == '-' && ptype[1] != '\0') { + while (*ptype == '-' && ptype[1] != '\0') { ptype = next_arg_type(ptype); } switch(*ptype) { @@ -17,8 +17,7 @@ */ #include "block/nbd.h" -#include "block/block.h" -#include "block/block_int.h" +#include "sysemu/block-backend.h" #include "block/coroutine.h" @@ -101,7 +100,7 @@ struct NBDExport { int refcount; void (*close)(NBDExport *exp); - BlockDriverState *bs; + BlockBackend *blk; char *name; off_t dev_offset; off_t size; @@ -929,7 +928,7 @@ static void nbd_request_put(NBDRequest *req) nbd_client_put(client); } -static void bs_aio_attached(AioContext *ctx, void *opaque) +static void blk_aio_attached(AioContext *ctx, void *opaque) { NBDExport *exp = opaque; NBDClient *client; @@ -943,7 +942,7 @@ static void bs_aio_attached(AioContext *ctx, void *opaque) } } -static void bs_aio_detach(void *opaque) +static void blk_aio_detach(void *opaque) { NBDExport *exp = opaque; NBDClient *client; @@ -957,27 +956,26 @@ static void bs_aio_detach(void *opaque) exp->ctx = NULL; } -NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, - off_t size, uint32_t nbdflags, - void (*close)(NBDExport *)) +NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, + uint32_t nbdflags, void (*close)(NBDExport *)) { NBDExport *exp = g_malloc0(sizeof(NBDExport)); exp->refcount = 1; QTAILQ_INIT(&exp->clients); - exp->bs = bs; + exp->blk = blk; exp->dev_offset = dev_offset; exp->nbdflags = nbdflags; - exp->size = size == -1 ? bdrv_getlength(bs) : size; + exp->size = size == -1 ? blk_getlength(blk) : size; exp->close = close; - exp->ctx = bdrv_get_aio_context(bs); - bdrv_ref(bs); - bdrv_add_aio_context_notifier(bs, bs_aio_attached, bs_aio_detach, exp); + exp->ctx = blk_get_aio_context(blk); + blk_ref(blk); + blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp); /* * NBD exports are used for non-shared storage migration. Make sure * that BDRV_O_INCOMING is cleared and the image is ready for write * access since the export could be available before migration handover. */ - bdrv_invalidate_cache(bs, NULL); + blk_invalidate_cache(blk, NULL); return exp; } @@ -1024,11 +1022,11 @@ void nbd_export_close(NBDExport *exp) } nbd_export_set_name(exp, NULL); nbd_export_put(exp); - if (exp->bs) { - bdrv_remove_aio_context_notifier(exp->bs, bs_aio_attached, - bs_aio_detach, exp); - bdrv_unref(exp->bs); - exp->bs = NULL; + if (exp->blk) { + blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, + blk_aio_detach, exp); + blk_unref(exp->blk); + exp->blk = NULL; } } @@ -1056,9 +1054,9 @@ void nbd_export_put(NBDExport *exp) } } -BlockDriverState *nbd_export_get_blockdev(NBDExport *exp) +BlockBackend *nbd_export_get_blockdev(NBDExport *exp) { - return exp->bs; + return exp->blk; } void nbd_export_close_all(void) @@ -1137,7 +1135,7 @@ static ssize_t nbd_co_receive_request(NBDRequest *req, struct nbd_request *reque command = request->type & NBD_CMD_MASK_COMMAND; if (command == NBD_CMD_READ || command == NBD_CMD_WRITE) { - req->data = qemu_blockalign(client->exp->bs, request->len); + req->data = blk_blockalign(client->exp->blk, request->len); } if (command == NBD_CMD_WRITE) { TRACE("Reading %u byte(s)", request->len); @@ -1203,7 +1201,7 @@ static void nbd_trip(void *opaque) TRACE("Request type is READ"); if (request.type & NBD_CMD_FLAG_FUA) { - ret = bdrv_co_flush(exp->bs); + ret = blk_co_flush(exp->blk); if (ret < 0) { LOG("flush failed"); reply.error = -ret; @@ -1211,8 +1209,9 @@ static void nbd_trip(void *opaque) } } - ret = bdrv_read(exp->bs, (request.from + exp->dev_offset) / 512, - req->data, request.len / 512); + ret = blk_read(exp->blk, + (request.from + exp->dev_offset) / BDRV_SECTOR_SIZE, + req->data, request.len / BDRV_SECTOR_SIZE); if (ret < 0) { LOG("reading from file failed"); reply.error = -ret; @@ -1234,8 +1233,9 @@ static void nbd_trip(void *opaque) TRACE("Writing to device"); - ret = bdrv_write(exp->bs, (request.from + exp->dev_offset) / 512, - req->data, request.len / 512); + ret = blk_write(exp->blk, + (request.from + exp->dev_offset) / BDRV_SECTOR_SIZE, + req->data, request.len / BDRV_SECTOR_SIZE); if (ret < 0) { LOG("writing to file failed"); reply.error = -ret; @@ -1243,7 +1243,7 @@ static void nbd_trip(void *opaque) } if (request.type & NBD_CMD_FLAG_FUA) { - ret = bdrv_co_flush(exp->bs); + ret = blk_co_flush(exp->blk); if (ret < 0) { LOG("flush failed"); reply.error = -ret; @@ -1262,7 +1262,7 @@ static void nbd_trip(void *opaque) case NBD_CMD_FLUSH: TRACE("Request type is FLUSH"); - ret = bdrv_co_flush(exp->bs); + ret = blk_co_flush(exp->blk); if (ret < 0) { LOG("flush failed"); reply.error = -ret; @@ -1273,8 +1273,9 @@ static void nbd_trip(void *opaque) break; case NBD_CMD_TRIM: TRACE("Request type is TRIM"); - ret = bdrv_co_discard(exp->bs, (request.from + exp->dev_offset) / 512, - request.len / 512); + ret = blk_co_discard(exp->blk, (request.from + exp->dev_offset) + / BDRV_SECTOR_SIZE, + request.len / BDRV_SECTOR_SIZE); if (ret < 0) { LOG("discard failed"); reply.error = -ret; diff --git a/qapi-schema.json b/qapi-schema.json index 9ffdcf8e85..563b4ad98a 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1533,7 +1533,7 @@ # # Change the VNC server password. # -# @target: the new password to use with VNC authentication +# @password: the new password to use with VNC authentication # # Since: 1.1 # diff --git a/qapi/block-core.json b/qapi/block-core.json index a14e6ab1fd..6e8db15861 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -183,6 +183,22 @@ '*fragmented-clusters': 'int', '*compressed-clusters': 'int' } } ## +# @BlockdevCacheInfo +# +# Cache mode information for a block device +# +# @writeback: true if writeback mode is enabled +# @direct: true if the host page cache is bypassed (O_DIRECT) +# @no-flush: true if flush requests are ignored for the device +# +# Since: 2.3 +## +{ 'type': 'BlockdevCacheInfo', + 'data': { 'writeback': 'bool', + 'direct': 'bool', + 'no-flush': 'bool' } } + +## # @BlockDeviceInfo: # # Information about the backing device for a block device. @@ -239,6 +255,8 @@ # # @iops_size: #optional an I/O size in bytes (Since 1.7) # +# @cache: the cache mode used for the block device (since: 2.3) +# # Since: 0.14.0 # ## @@ -253,7 +271,7 @@ '*bps_max': 'int', '*bps_rd_max': 'int', '*bps_wr_max': 'int', '*iops_max': 'int', '*iops_rd_max': 'int', '*iops_wr_max': 'int', - '*iops_size': 'int' } } + '*iops_size': 'int', 'cache': 'BlockdevCacheInfo' } } ## # @BlockDeviceIoStatus: @@ -405,6 +423,8 @@ # @device: #optional If the stats are for a virtual block device, the name # corresponding to the virtual block device. # +# @device: #optional The node name of the device. (Since 2.3) +# # @stats: A @BlockDeviceStats for the device. # # @parent: #optional This describes the file block device if it has one. @@ -415,7 +435,8 @@ # Since: 0.14.0 ## { 'type': 'BlockStats', - 'data': {'*device': 'str', 'stats': 'BlockDeviceStats', + 'data': {'*device': 'str', '*node-name': 'str', + 'stats': 'BlockDeviceStats', '*parent': 'BlockStats', '*backing': 'BlockStats'} } @@ -424,11 +445,20 @@ # # Query the @BlockStats for all virtual block devices. # +# @query-nodes: #optional If true, the command will query all the block nodes +# that have a node name, in a list which will include "parent" +# information, but not "backing". +# If false or omitted, the behavior is as before - query all the +# device backends, recursively including their "parent" and +# "backing". (Since 2.3) +# # Returns: A list of @BlockStats for each virtual block devices. # # Since: 0.14.0 ## -{ 'command': 'query-blockstats', 'returns': ['BlockStats'] } +{ 'command': 'query-blockstats', + 'data': { '*query-nodes': 'bool' }, + 'returns': ['BlockStats'] } ## # @BlockdevOnError: diff --git a/qapi/common.json b/qapi/common.json index 4e9a21f2f6..63ef3b4724 100644 --- a/qapi/common.json +++ b/qapi/common.json @@ -87,3 +87,18 @@ ## { 'command': 'query-commands', 'returns': ['CommandInfo'] } +## +# @OnOffAuto +# +# An enumeration of three options: on, off, and auto +# +# @auto: QEMU selects the value between on and off +# +# @on: Enabled +# +# @off: Disabled +# +# Since: 2.2 +## +{ 'enum': 'OnOffAuto', + 'data': [ 'auto', 'on', 'off' ] } diff --git a/qemu-char.c b/qemu-char.c index a8b01da3ee..ef84b53681 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -3825,9 +3825,7 @@ void qemu_chr_delete(CharDriverState *chr) } g_free(chr->filename); g_free(chr->label); - if (chr->opts) { - qemu_opts_del(chr->opts); - } + qemu_opts_del(chr->opts); g_free(chr); } diff --git a/qemu-doc.texi b/qemu-doc.texi index ad418f851d..aabe8df2f3 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -698,7 +698,11 @@ Supported options: Specifies which VHDX subformat to use. Valid options are @code{dynamic} (default) and @code{fixed}. @item block_state_zero -Force use of payload blocks of type 'ZERO'. +Force use of payload blocks of type 'ZERO'. Can be set to @code{on} (default) +or @code{off}. When set to @code{off}, new blocks will be created as +@code{PAYLOAD_BLOCK_NOT_PRESENT}, which means parsers are free to return +arbitrary data for those blocks. Do not set to @code{off} when using +@code{qemu-img convert} with @code{subformat=dynamic}. @item block_size Block size; min 1 MB, max 256 MB. 0 means auto-calculate based on image size. @item log_size diff --git a/qemu-img.c b/qemu-img.c index a42335c632..7876258fa9 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1531,6 +1531,20 @@ static int img_convert(int argc, char **argv) goto out; } + if (!drv->create_opts) { + error_report("Format driver '%s' does not support image creation", + drv->format_name); + ret = -1; + goto out; + } + + if (!proto_drv->create_opts) { + error_report("Protocol driver '%s' does not support image creation", + proto_drv->format_name); + ret = -1; + goto out; + } + create_opts = qemu_opts_append(create_opts, drv->create_opts); create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); @@ -2972,6 +2986,13 @@ static int img_amend(int argc, char **argv) goto out; } + if (!bs->drv->create_opts) { + error_report("Format driver '%s' does not support any options to amend", + fmt); + ret = -1; + goto out; + } + create_opts = qemu_opts_append(create_opts, bs->drv->create_opts); opts = qemu_opts_create(create_opts, NULL, 0, &error_abort); if (options && qemu_opts_do_parse(opts, options, NULL)) { diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index d94fb1e2ea..e70855254a 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -2048,6 +2048,51 @@ static const cmdinfo_t abort_cmd = { .oneline = "simulate a program crash using abort(3)", }; +static void sigraise_help(void) +{ + printf( +"\n" +" raises the given signal\n" +"\n" +" Example:\n" +" 'sigraise %i' - raises SIGTERM\n" +"\n" +" Invokes raise(signal), where \"signal\" is the mandatory integer argument\n" +" given to sigraise.\n" +"\n", SIGTERM); +} + +static int sigraise_f(BlockDriverState *bs, int argc, char **argv); + +static const cmdinfo_t sigraise_cmd = { + .name = "sigraise", + .cfunc = sigraise_f, + .argmin = 1, + .argmax = 1, + .flags = CMD_NOFILE_OK, + .args = "signal", + .oneline = "raises a signal", + .help = sigraise_help, +}; + +static int sigraise_f(BlockDriverState *bs, int argc, char **argv) +{ + int sig = cvtnum(argv[1]); + if (sig < 0) { + printf("non-numeric signal number argument -- %s\n", argv[1]); + return 0; + } + + /* Using raise() to kill this process does not necessarily flush all open + * streams. At least stdout and stderr (although the latter should be + * non-buffered anyway) should be flushed, though. */ + fflush(stdout); + fflush(stderr); + + raise(sig); + return 0; +} + static void sleep_cb(void *opaque) { bool *expired = opaque; @@ -2202,4 +2247,5 @@ static void __attribute((constructor)) init_qemuio_commands(void) qemuio_add_command(&wait_break_cmd); qemuio_add_command(&abort_cmd); qemuio_add_command(&sleep_cmd); + qemuio_add_command(&sigraise_cmd); } @@ -51,7 +51,8 @@ static const cmdinfo_t close_cmd = { .oneline = "close the current open file", }; -static int openfile(char *name, int flags, int growable, QDict *opts) +static int openfile(char *name, BlockDriver *drv, int flags, int growable, + QDict *opts) { Error *local_err = NULL; @@ -68,7 +69,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts) flags |= BDRV_O_PROTOCOL; } - if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, NULL, &local_err) < 0) { + if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, drv, &local_err) < 0) { fprintf(stderr, "%s: can't open%s%s: %s\n", progname, name ? " device " : "", name ?: "", error_get_pretty(local_err)); @@ -169,9 +170,9 @@ static int open_f(BlockDriverState *bs, int argc, char **argv) qemu_opts_reset(&empty_opts); if (optind == argc - 1) { - return openfile(argv[optind], flags, growable, opts); + return openfile(argv[optind], NULL, flags, growable, opts); } else if (optind == argc) { - return openfile(NULL, flags, growable, opts); + return openfile(NULL, NULL, flags, growable, opts); } else { QDECREF(opts); return qemuio_command_usage(&open_cmd); @@ -196,11 +197,12 @@ static const cmdinfo_t quit_cmd = { static void usage(const char *name) { printf( -"Usage: %s [-h] [-V] [-rsnm] [-c STRING] ... [file]\n" +"Usage: %s [-h] [-V] [-rsnm] [-f FMT] [-c STRING] ... [file]\n" "QEMU Disk exerciser\n" "\n" " -c, --cmd STRING execute command with its arguments\n" " from the given string\n" +" -f, --format FMT specifies the block driver to use\n" " -r, --read-only export read-only\n" " -s, --snapshot use snapshot file\n" " -n, --nocache disable host cache\n" @@ -364,12 +366,13 @@ int main(int argc, char **argv) { int readonly = 0; int growable = 0; - const char *sopt = "hVc:d:rsnmgkt:T:"; + const char *sopt = "hVc:d:f:rsnmgkt:T:"; const struct option lopt[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { "offset", 1, NULL, 'o' }, { "cmd", 1, NULL, 'c' }, + { "format", 1, NULL, 'f' }, { "read-only", 0, NULL, 'r' }, { "snapshot", 0, NULL, 's' }, { "nocache", 0, NULL, 'n' }, @@ -384,6 +387,7 @@ int main(int argc, char **argv) int c; int opt_index = 0; int flags = BDRV_O_UNMAP; + BlockDriver *drv = NULL; Error *local_error = NULL; #ifdef CONFIG_POSIX @@ -393,6 +397,8 @@ int main(int argc, char **argv) progname = basename(argv[0]); qemu_init_exec_dir(argv[0]); + bdrv_init(); + while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { switch (c) { case 's': @@ -407,6 +413,13 @@ int main(int argc, char **argv) exit(1); } break; + case 'f': + drv = bdrv_find_format(optarg); + if (!drv) { + error_report("Invalid format '%s'", optarg); + exit(EXIT_FAILURE); + } + break; case 'c': add_user_command(optarg); break; @@ -455,7 +468,6 @@ int main(int argc, char **argv) error_free(local_error); exit(1); } - bdrv_init(); /* initialize commands */ qemuio_add_command(&quit_cmd); @@ -477,7 +489,7 @@ int main(int argc, char **argv) } if ((argc - optind) == 1) { - openfile(argv[optind], flags, growable, NULL); + openfile(argv[optind], drv, flags, growable, NULL); } command_loop(); diff --git a/qemu-nbd.c b/qemu-nbd.c index 5cd6c6d187..d222512412 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -146,7 +146,7 @@ static void read_partition(uint8_t *p, struct partition_record *r) r->nb_sectors_abs = p[12] | p[13] << 8 | p[14] << 16 | p[15] << 24; } -static int find_partition(BlockDriverState *bs, int partition, +static int find_partition(BlockBackend *blk, int partition, off_t *offset, off_t *size) { struct partition_record mbr[4]; @@ -155,7 +155,7 @@ static int find_partition(BlockDriverState *bs, int partition, int ext_partnum = 4; int ret; - if ((ret = bdrv_read(bs, 0, data, 1)) < 0) { + if ((ret = blk_read(blk, 0, data, 1)) < 0) { errno = -ret; err(EXIT_FAILURE, "error while reading"); } @@ -175,7 +175,7 @@ static int find_partition(BlockDriverState *bs, int partition, uint8_t data1[512]; int j; - if ((ret = bdrv_read(bs, mbr[i].start_sector_abs, data1, 1)) < 0) { + if ((ret = blk_read(blk, mbr[i].start_sector_abs, data1, 1)) < 0) { errno = -ret; err(EXIT_FAILURE, "error while reading"); } @@ -720,17 +720,17 @@ int main(int argc, char **argv) } bs->detect_zeroes = detect_zeroes; - fd_size = bdrv_getlength(bs); + fd_size = blk_getlength(blk); if (partition != -1) { - ret = find_partition(bs, partition, &dev_offset, &fd_size); + ret = find_partition(blk, partition, &dev_offset, &fd_size); if (ret < 0) { errno = -ret; err(EXIT_FAILURE, "Could not find partition %d", partition); } } - exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, nbd_export_closed); + exp = nbd_export_new(blk, dev_offset, fd_size, nbdflags, nbd_export_closed); if (sockpath) { fd = unix_socket_incoming(sockpath); diff --git a/qemu-options.hx b/qemu-options.hx index da9851d483..10b9568815 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -33,7 +33,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ " property accel=accel1[:accel2[:...]] selects accelerator\n" " supported accelerators are kvm, xen, tcg (default: tcg)\n" " kernel_irqchip=on|off controls accelerated irqchip support\n" - " vmport=on|off controls emulation of vmport (default: on)\n" + " vmport=on|off|auto controls emulation of vmport (default: auto)\n" " kvm_shadow_mem=size of KVM shadow MMU\n" " dump-guest-core=on|off include guest memory in a core dump (default=on)\n" " mem-merge=on|off controls memory merge support (default: on)\n" @@ -52,8 +52,10 @@ than one accelerator specified, the next one is used if the previous one fails to initialize. @item kernel_irqchip=on|off Enables in-kernel irqchip support for the chosen accelerator when available. -@item vmport=on|off -Enables emulation of VMWare IO port, for vmmouse etc. (enabled by default) +@item vmport=on|off|auto +Enables emulation of VMWare IO port, for vmmouse etc. auto says to select the +value based on accel. For accel=xen the default is off otherwise the default +is on. @item kvm_shadow_mem=size Defines the size of the KVM shadow MMU. @item dump-guest-core=on|off @@ -2788,6 +2790,14 @@ STEXI @findex -qmp Like -monitor but opens in 'control' mode. ETEXI +DEF("qmp-pretty", HAS_ARG, QEMU_OPTION_qmp_pretty, \ + "-qmp-pretty dev like -qmp but uses pretty JSON formatting\n", + QEMU_ARCH_ALL) +STEXI +@item -qmp-pretty @var{dev} +@findex -qmp-pretty +Like -qmp but uses pretty JSON formatting. +ETEXI DEF("mon", HAS_ARG, QEMU_OPTION_mon, \ "-mon [chardev=]name[,mode=readline|control][,default]\n", QEMU_ARCH_ALL) @@ -3216,7 +3226,17 @@ DEF("semihosting", 0, QEMU_OPTION_semihosting, STEXI @item -semihosting @findex -semihosting -Semihosting mode (ARM, M68K, Xtensa only). +Enable semihosting mode (ARM, M68K, Xtensa only). +ETEXI +DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config, + "-semihosting-config [enable=on|off,]target=native|gdb|auto semihosting configuration\n", +QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32) +STEXI +@item -semihosting-config [enable=on|off,]target=native|gdb|auto +@findex -semihosting-config +Enable semihosting and define where the semihosting calls will be addressed, +to QEMU (@code{native}) or to GDB (@code{gdb}). The default is @code{auto}, which means +@code{gdb} during debug sessions and @code{native} otherwise (ARM, M68K, Xtensa only). ETEXI DEF("old-param", 0, QEMU_OPTION_old_param, "-old-param old param mode\n", QEMU_ARCH_ARM) diff --git a/qemu-timer.c b/qemu-timer.c index f4b4b6aa45..cb7d988b56 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -314,7 +314,14 @@ int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout) return ppoll((struct pollfd *)fds, nfds, NULL, NULL); } else { struct timespec ts; - ts.tv_sec = timeout / 1000000000LL; + int64_t tvsec = timeout / 1000000000LL; + /* Avoid possibly overflowing and specifying a negative number of + * seconds, which would turn a very long timeout into a busy-wait. + */ + if (tvsec > (int64_t)INT32_MAX) { + tvsec = INT32_MAX; + } + ts.tv_sec = tvsec; ts.tv_nsec = timeout % 1000000000LL; return ppoll((struct pollfd *)fds, nfds, &ts, NULL); } diff --git a/qmp-commands.hx b/qmp-commands.hx index 718dd92f6a..33487820a4 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -2347,7 +2347,7 @@ EQMP { .name = "query-blockstats", - .args_type = "", + .args_type = "query-nodes:b?", .mhandler.cmd_new = qmp_marshal_input_query_blockstats, }, @@ -3820,13 +3820,13 @@ Press left mouse button. -> { "execute": "x-input-send-event", "arguments": { "console": 0, "events": [ { "type": "btn", - "data" : { "down": true, "button": "Left" } } } } + "data" : { "down": true, "button": "Left" } } ] } } <- { "return": {} } -> { "execute": "x-input-send-event", "arguments": { "console": 0, "events": [ { "type": "btn", - "data" : { "down": false, "button": "Left" } } } } + "data" : { "down": false, "button": "Left" } } ] } } <- { "return": {} } Example (2): diff --git a/qobject/qjson.c b/qobject/qjson.c index 6cf2511580..12c576d548 100644 --- a/qobject/qjson.c +++ b/qobject/qjson.c @@ -86,8 +86,9 @@ static void to_json_dict_iter(const char *key, QObject *obj, void *opaque) QString *qkey; int j; - if (s->count) - qstring_append(s->str, ", "); + if (s->count) { + qstring_append(s->str, s->pretty ? "," : ", "); + } if (s->pretty) { qstring_append(s->str, "\n"); @@ -109,8 +110,9 @@ static void to_json_list_iter(QObject *obj, void *opaque) ToJsonIterState *s = opaque; int j; - if (s->count) - qstring_append(s->str, ", "); + if (s->count) { + qstring_append(s->str, s->pretty ? "," : ", "); + } if (s->pretty) { qstring_append(s->str, "\n"); diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index af68c6c92d..f39630eb3d 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -23,7 +23,6 @@ my $email_usename = 1; my $email_maintainer = 1; my $email_list = 1; my $email_subscriber_list = 0; -my $email_git_penguin_chiefs = 0; my $email_git = 0; my $email_git_all_signature_types = 0; my $email_git_blame = 0; @@ -60,21 +59,6 @@ my $exit = 0; my %commit_author_hash; my %commit_signer_hash; -my @penguin_chief = (); -push(@penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org"); -#Andrew wants in on most everything - 2009/01/14 -#push(@penguin_chief, "Andrew Morton:akpm\@linux-foundation.org"); - -my @penguin_chief_names = (); -foreach my $chief (@penguin_chief) { - if ($chief =~ m/^(.*):(.*)/) { - my $chief_name = $1; - my $chief_addr = $2; - push(@penguin_chief_names, $chief_name); - } -} -my $penguin_chiefs = "\(" . join("|", @penguin_chief_names) . "\)"; - # Signature types of people who are either # a) responsible for the code in question, or # b) familiar enough with it to give relevant feedback @@ -187,7 +171,6 @@ if (!GetOptions( 'git-blame!' => \$email_git_blame, 'git-blame-signatures!' => \$email_git_blame_signatures, 'git-fallback!' => \$email_git_fallback, - 'git-chief-penguins!' => \$email_git_penguin_chiefs, 'git-min-signatures=i' => \$email_git_min_signatures, 'git-max-maintainers=i' => \$email_git_max_maintainers, 'git-min-percent=i' => \$email_git_min_percent, @@ -256,7 +239,7 @@ if ($sections) { if ($email && ($email_maintainer + $email_list + $email_subscriber_list + - $email_git + $email_git_penguin_chiefs + $email_git_blame) == 0) { + $email_git + $email_git_blame) == 0) { die "$P: Please select at least 1 email option\n"; } @@ -671,19 +654,6 @@ sub get_maintainers { } } - foreach my $chief (@penguin_chief) { - if ($chief =~ m/^(.*):(.*)/) { - my $email_address; - - $email_address = format_email($1, $2, $email_usename); - if ($email_git_penguin_chiefs) { - push(@email_to, [$email_address, 'chief penguin']); - } else { - @email_to = grep($_->[0] !~ /${email_address}/, @email_to); - } - } - } - foreach my $email (@file_emails) { my ($name, $address) = parse_email($email); @@ -740,7 +710,6 @@ MAINTAINER field selection options: --git-all-signature-types => include signers regardless of signature type or use only ${signature_pattern} signers (default: $email_git_all_signature_types) --git-fallback => use git when no exact MAINTAINERS pattern (default: $email_git_fallback) - --git-chief-penguins => include ${penguin_chiefs} --git-min-signatures => number of signatures required (default: $email_git_min_signatures) --git-max-maintainers => maximum maintainers to add (default: $email_git_max_maintainers) --git-min-percent => minimum percentage of commits required (default: $email_git_min_percent) @@ -1281,10 +1250,6 @@ sub vcs_find_signers { save_commits_by_author(@lines) if ($interactive); save_commits_by_signer(@lines) if ($interactive); - if (!$email_git_penguin_chiefs) { - @signatures = grep(!/${penguin_chiefs}/i, @signatures); - } - my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures); return ($commits, @$signers_ref); @@ -1296,10 +1261,6 @@ sub vcs_find_author { @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); - if (!$email_git_penguin_chiefs) { - @lines = grep(!/${penguin_chiefs}/i, @lines); - } - return @lines if !@lines; my @authors = (); @@ -1925,10 +1886,6 @@ sub vcs_file_blame { @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); - if (!$email_git_penguin_chiefs) { - @lines = grep(!/${penguin_chiefs}/i, @lines); - } - last if !@lines; my @authors = (); diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c index ebb5235521..a8b83e6912 100644 --- a/target-arm/arm-semi.c +++ b/target-arm/arm-semi.c @@ -58,6 +58,10 @@ #define TARGET_SYS_HEAPINFO 0x16 #define TARGET_SYS_EXIT 0x18 +/* ADP_Stopped_ApplicationExit is used for exit(0), + * anything else is implemented as exit(1) */ +#define ADP_Stopped_ApplicationExit (0x20026) + #ifndef O_BINARY #define O_BINARY 0 #endif @@ -551,8 +555,11 @@ uint32_t do_arm_semihosting(CPUARMState *env) return 0; } case TARGET_SYS_EXIT: - gdb_exit(env, 0); - exit(0); + /* ARM specifies only Stopped_ApplicationExit as normal + * exit, everything else is considered an error */ + ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1; + gdb_exit(env, ret); + exit(ret); default: fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr); cpu_dump_state(cs, stderr, fprintf, 0); diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 5ce7350ce6..d3db279e1b 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -109,7 +109,7 @@ static void arm_cpu_reset(CPUState *s) #if defined(CONFIG_USER_ONLY) env->pstate = PSTATE_MODE_EL0t; /* Userspace expects access to DC ZVA, CTL_EL0 and the cache ops */ - env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE; + env->cp15.sctlr_el[1] |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE; /* and to the FP/Neon instructions */ env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 2, 3); #else @@ -167,7 +167,11 @@ static void arm_cpu_reset(CPUState *s) env->thumb = initial_pc & 1; } - if (env->cp15.c1_sys & SCTLR_V) { + /* AArch32 has a hard highvec setting of 0xFFFF0000. If we are currently + * executing as AArch32 then check if highvecs are enabled and + * adjust the PC accordingly. + */ + if (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_V) { env->regs[15] = 0xFFFF0000; } @@ -548,7 +552,7 @@ static void arm1026_initfn(Object *obj) ARMCPRegInfo ifar = { .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1, .access = PL1_RW, - .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el[1]), + .fieldoffset = offsetof(CPUARMState, cp15.ifar_ns), .resetvalue = 0 }; define_one_arm_cp_reg(cpu, &ifar); diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 7f800908f4..7ba55f0c2e 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -120,6 +120,12 @@ typedef struct ARMGenericTimer { #define GTIMER_VIRT 1 #define NUM_GTIMERS 2 +typedef struct { + uint64_t raw_tcr; + uint32_t mask; + uint32_t base_mask; +} TCR; + typedef struct CPUARMState { /* Regs for current mode. */ uint32_t regs[16]; @@ -177,28 +183,111 @@ typedef struct CPUARMState { /* System control coprocessor (cp15) */ struct { uint32_t c0_cpuid; - uint64_t c0_cssel; /* Cache size selection. */ - uint64_t c1_sys; /* System control register. */ + union { /* Cache size selection */ + struct { + uint64_t _unused_csselr0; + uint64_t csselr_ns; + uint64_t _unused_csselr1; + uint64_t csselr_s; + }; + uint64_t csselr_el[4]; + }; + union { /* System control register. */ + struct { + uint64_t _unused_sctlr; + uint64_t sctlr_ns; + uint64_t hsctlr; + uint64_t sctlr_s; + }; + uint64_t sctlr_el[4]; + }; uint64_t c1_coproc; /* Coprocessor access register. */ uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */ - uint64_t ttbr0_el1; /* MMU translation table base 0. */ - uint64_t ttbr1_el1; /* MMU translation table base 1. */ - uint64_t c2_control; /* MMU translation table base control. */ - uint32_t c2_mask; /* MMU translation table base selection mask. */ - uint32_t c2_base_mask; /* MMU translation table base 0 mask. */ + uint64_t sder; /* Secure debug enable register. */ + uint32_t nsacr; /* Non-secure access control register. */ + union { /* MMU translation table base 0. */ + struct { + uint64_t _unused_ttbr0_0; + uint64_t ttbr0_ns; + uint64_t _unused_ttbr0_1; + uint64_t ttbr0_s; + }; + uint64_t ttbr0_el[4]; + }; + union { /* MMU translation table base 1. */ + struct { + uint64_t _unused_ttbr1_0; + uint64_t ttbr1_ns; + uint64_t _unused_ttbr1_1; + uint64_t ttbr1_s; + }; + uint64_t ttbr1_el[4]; + }; + /* MMU translation table base control. */ + TCR tcr_el[4]; uint32_t c2_data; /* MPU data cachable bits. */ uint32_t c2_insn; /* MPU instruction cachable bits. */ - uint32_t c3; /* MMU domain access control register - MPU write buffer control. */ + union { /* MMU domain access control register + * MPU write buffer control. + */ + struct { + uint64_t dacr_ns; + uint64_t dacr_s; + }; + struct { + uint64_t dacr32_el2; + }; + }; uint32_t pmsav5_data_ap; /* PMSAv5 MPU data access permissions */ uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */ uint64_t hcr_el2; /* Hypervisor configuration register */ uint64_t scr_el3; /* Secure configuration register. */ - uint32_t ifsr_el2; /* Fault status registers. */ - uint64_t esr_el[4]; + union { /* Fault status registers. */ + struct { + uint64_t ifsr_ns; + uint64_t ifsr_s; + }; + struct { + uint64_t ifsr32_el2; + }; + }; + union { + struct { + uint64_t _unused_dfsr; + uint64_t dfsr_ns; + uint64_t hsr; + uint64_t dfsr_s; + }; + uint64_t esr_el[4]; + }; uint32_t c6_region[8]; /* MPU base/size registers. */ - uint64_t far_el[4]; /* Fault address registers. */ - uint64_t par_el1; /* Translation result. */ + union { /* Fault address registers. */ + struct { + uint64_t _unused_far0; +#ifdef HOST_WORDS_BIGENDIAN + uint32_t ifar_ns; + uint32_t dfar_ns; + uint32_t ifar_s; + uint32_t dfar_s; +#else + uint32_t dfar_ns; + uint32_t ifar_ns; + uint32_t dfar_s; + uint32_t ifar_s; +#endif + uint64_t _unused_far3; + }; + uint64_t far_el[4]; + }; + union { /* Translation result. */ + struct { + uint64_t _unused_par_0; + uint64_t par_ns; + uint64_t _unused_par_1; + uint64_t par_s; + }; + uint64_t par_el[4]; + }; uint32_t c9_insn; /* Cache lockdown registers. */ uint32_t c9_data; uint64_t c9_pmcr; /* performance monitor control register */ @@ -207,13 +296,67 @@ typedef struct CPUARMState { uint32_t c9_pmxevtyper; /* perf monitor event type */ uint32_t c9_pmuserenr; /* perf monitor user enable */ uint32_t c9_pminten; /* perf monitor interrupt enables */ - uint64_t mair_el1; - uint64_t vbar_el[4]; /* vector base address register */ - uint32_t c13_fcse; /* FCSE PID. */ - uint64_t contextidr_el1; /* Context ID. */ - uint64_t tpidr_el0; /* User RW Thread register. */ - uint64_t tpidrro_el0; /* User RO Thread register. */ - uint64_t tpidr_el1; /* Privileged Thread register. */ + union { /* Memory attribute redirection */ + struct { +#ifdef HOST_WORDS_BIGENDIAN + uint64_t _unused_mair_0; + uint32_t mair1_ns; + uint32_t mair0_ns; + uint64_t _unused_mair_1; + uint32_t mair1_s; + uint32_t mair0_s; +#else + uint64_t _unused_mair_0; + uint32_t mair0_ns; + uint32_t mair1_ns; + uint64_t _unused_mair_1; + uint32_t mair0_s; + uint32_t mair1_s; +#endif + }; + uint64_t mair_el[4]; + }; + union { /* vector base address register */ + struct { + uint64_t _unused_vbar; + uint64_t vbar_ns; + uint64_t hvbar; + uint64_t vbar_s; + }; + uint64_t vbar_el[4]; + }; + uint32_t mvbar; /* (monitor) vector base address register */ + struct { /* FCSE PID. */ + uint32_t fcseidr_ns; + uint32_t fcseidr_s; + }; + union { /* Context ID. */ + struct { + uint64_t _unused_contextidr_0; + uint64_t contextidr_ns; + uint64_t _unused_contextidr_1; + uint64_t contextidr_s; + }; + uint64_t contextidr_el[4]; + }; + union { /* User RW Thread register. */ + struct { + uint64_t tpidrurw_ns; + uint64_t tpidrprw_ns; + uint64_t htpidr; + uint64_t _tpidr_el3; + }; + uint64_t tpidr_el[4]; + }; + /* The secure banks of these registers don't map anywhere */ + uint64_t tpidrurw_s; + uint64_t tpidrprw_s; + uint64_t tpidruro_s; + + union { /* User RO Thread register. */ + uint64_t tpidruro_ns; + uint64_t tpidrro_el[1]; + }; uint64_t c14_cntfrq; /* Counter Frequency register */ uint64_t c14_cntkctl; /* Timer Control register */ ARMGenericTimer c14_timer[NUM_GTIMERS]; @@ -817,6 +960,49 @@ static inline bool arm_el_is_aa64(CPUARMState *env, int el) return arm_feature(env, ARM_FEATURE_AARCH64); } +/* Function for determing whether guest cp register reads and writes should + * access the secure or non-secure bank of a cp register. When EL3 is + * operating in AArch32 state, the NS-bit determines whether the secure + * instance of a cp register should be used. When EL3 is AArch64 (or if + * it doesn't exist at all) then there is no register banking, and all + * accesses are to the non-secure version. + */ +static inline bool access_secure_reg(CPUARMState *env) +{ + bool ret = (arm_feature(env, ARM_FEATURE_EL3) && + !arm_el_is_aa64(env, 3) && + !(env->cp15.scr_el3 & SCR_NS)); + + return ret; +} + +/* Macros for accessing a specified CP register bank */ +#define A32_BANKED_REG_GET(_env, _regname, _secure) \ + ((_secure) ? (_env)->cp15._regname##_s : (_env)->cp15._regname##_ns) + +#define A32_BANKED_REG_SET(_env, _regname, _secure, _val) \ + do { \ + if (_secure) { \ + (_env)->cp15._regname##_s = (_val); \ + } else { \ + (_env)->cp15._regname##_ns = (_val); \ + } \ + } while (0) + +/* Macros for automatically accessing a specific CP register bank depending on + * the current secure state of the system. These macros are not intended for + * supporting instruction translation reads/writes as these are dependent + * solely on the SCR.NS bit and not the mode. + */ +#define A32_BANKED_CURRENT_REG_GET(_env, _regname) \ + A32_BANKED_REG_GET((_env), _regname, \ + ((!arm_el_is_aa64((_env), 3) && arm_is_secure(_env)))) + +#define A32_BANKED_CURRENT_REG_SET(_env, _regname, _val) \ + A32_BANKED_REG_SET((_env), _regname, \ + ((!arm_el_is_aa64((_env), 3) && arm_is_secure(_env))), \ + (_val)) + void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf); unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx); @@ -836,6 +1022,7 @@ void armv7m_nvic_complete_irq(void *opaque, int irq); * Crn, Crm, opc1, opc2 fields * 32 or 64 bit register (ie is it accessed via MRC/MCR * or via MRRC/MCRR?) + * non-secure/secure bank (AArch32 only) * We allow 4 bits for opc1 because MRRC/MCRR have a 4 bit field. * (In this case crn and opc2 should be zero.) * For AArch64, there is no 32/64 bit size distinction; @@ -853,9 +1040,16 @@ void armv7m_nvic_complete_irq(void *opaque, int irq); #define CP_REG_AA64_SHIFT 28 #define CP_REG_AA64_MASK (1 << CP_REG_AA64_SHIFT) -#define ENCODE_CP_REG(cp, is64, crn, crm, opc1, opc2) \ - (((cp) << 16) | ((is64) << 15) | ((crn) << 11) | \ - ((crm) << 7) | ((opc1) << 3) | (opc2)) +/* To enable banking of coprocessor registers depending on ns-bit we + * add a bit to distinguish between secure and non-secure cpregs in the + * hashtable. + */ +#define CP_REG_NS_SHIFT 29 +#define CP_REG_NS_MASK (1 << CP_REG_NS_SHIFT) + +#define ENCODE_CP_REG(cp, is64, ns, crn, crm, opc1, opc2) \ + ((ns) << CP_REG_NS_SHIFT | ((cp) << 16) | ((is64) << 15) | \ + ((crn) << 11) | ((crm) << 7) | ((opc1) << 3) | (opc2)) #define ENCODE_AA64_CP_REG(cp, crn, crm, op0, op1, op2) \ (CP_REG_AA64_MASK | \ @@ -874,8 +1068,15 @@ static inline uint32_t kvm_to_cpreg_id(uint64_t kvmid) uint32_t cpregid = kvmid; if ((kvmid & CP_REG_ARCH_MASK) == CP_REG_ARM64) { cpregid |= CP_REG_AA64_MASK; - } else if ((kvmid & CP_REG_SIZE_MASK) == CP_REG_SIZE_U64) { - cpregid |= (1 << 15); + } else { + if ((kvmid & CP_REG_SIZE_MASK) == CP_REG_SIZE_U64) { + cpregid |= (1 << 15); + } + + /* KVM is always non-secure so add the NS flag on AArch32 register + * entries. + */ + cpregid |= 1 << CP_REG_NS_SHIFT; } return cpregid; } @@ -950,6 +1151,21 @@ enum { ARM_CP_STATE_BOTH = 2, }; +/* ARM CP register secure state flags. These flags identify security state + * attributes for a given CP register entry. + * The existence of both or neither secure and non-secure flags indicates that + * the register has both a secure and non-secure hash entry. A single one of + * these flags causes the register to only be hashed for the specified + * security state. + * Although definitions may have any combination of the S/NS bits, each + * registered entry will only have one to identify whether the entry is secure + * or non-secure. + */ +enum { + ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */ + ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */ +}; + /* Return true if cptype is a valid type field. This is used to try to * catch errors where the sentinel has been accidentally left off the end * of a list of registers. @@ -1084,6 +1300,8 @@ struct ARMCPRegInfo { int type; /* Access rights: PL*_[RW] */ int access; + /* Security state: ARM_CP_SECSTATE_* bits/values */ + int secure; /* The opaque pointer passed to define_arm_cp_regs_with_opaque() when * this register was defined: can be used to hand data through to the * register read/write functions, since they are passed the ARMCPRegInfo*. @@ -1093,12 +1311,27 @@ struct ARMCPRegInfo { * fieldoffset is non-zero, the reset value of the register. */ uint64_t resetvalue; - /* Offset of the field in CPUARMState for this register. This is not - * needed if either: + /* Offset of the field in CPUARMState for this register. + * + * This is not needed if either: * 1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs * 2. both readfn and writefn are specified */ ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */ + + /* Offsets of the secure and non-secure fields in CPUARMState for the + * register if it is banked. These fields are only used during the static + * registration of a register. During hashing the bank associated + * with a given security state is copied to fieldoffset which is used from + * there on out. + * + * It is expected that register definitions use either fieldoffset or + * bank_fieldoffsets in the definition but not both. It is also expected + * that both bank offsets are set when defining a banked register. This + * use indicates that a register is banked. + */ + ptrdiff_t bank_fieldoffsets[2]; + /* Function for making any access checks for this register in addition to * those specified by the 'access' permissions bits. If NULL, no extra * checks required. The access check is performed at runtime, not at @@ -1247,27 +1480,50 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx) CPUARMState *env = cs->env_ptr; unsigned int cur_el = arm_current_el(env); unsigned int target_el = arm_excp_target_el(cs, excp_idx); - /* FIXME: Use actual secure state. */ - bool secure = false; - /* If in EL1/0, Physical IRQ routing to EL2 only happens from NS state. */ - bool irq_can_hyp = !secure && cur_el < 2 && target_el == 2; - - /* Don't take exceptions if they target a lower EL. */ + bool secure = arm_is_secure(env); + uint32_t scr; + uint32_t hcr; + bool pstate_unmasked; + int8_t unmasked = 0; + + /* Don't take exceptions if they target a lower EL. + * This check should catch any exceptions that would not be taken but left + * pending. + */ if (cur_el > target_el) { return false; } switch (excp_idx) { case EXCP_FIQ: - if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_FMO)) { - return true; - } - return !(env->daif & PSTATE_F); + /* If FIQs are routed to EL3 or EL2 then there are cases where we + * override the CPSR.F in determining if the exception is masked or + * not. If neither of these are set then we fall back to the CPSR.F + * setting otherwise we further assess the state below. + */ + hcr = (env->cp15.hcr_el2 & HCR_FMO); + scr = (env->cp15.scr_el3 & SCR_FIQ); + + /* When EL3 is 32-bit, the SCR.FW bit controls whether the CPSR.F bit + * masks FIQ interrupts when taken in non-secure state. If SCR.FW is + * set then FIQs can be masked by CPSR.F when non-secure but only + * when FIQs are only routed to EL3. + */ + scr &= !((env->cp15.scr_el3 & SCR_FW) && !hcr); + pstate_unmasked = !(env->daif & PSTATE_F); + break; + case EXCP_IRQ: - if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_IMO)) { - return true; - } - return !(env->daif & PSTATE_I); + /* When EL3 execution state is 32-bit, if HCR.IMO is set then we may + * override the CPSR.I masking when in non-secure state. The SCR.IRQ + * setting has already been taken into consideration when setting the + * target EL, so it does not have a further affect here. + */ + hcr = (env->cp15.hcr_el2 & HCR_IMO); + scr = false; + pstate_unmasked = !(env->daif & PSTATE_I); + break; + case EXCP_VFIQ: if (secure || !(env->cp15.hcr_el2 & HCR_FMO)) { /* VFIQs are only taken when hypervized and non-secure. */ @@ -1283,6 +1539,21 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx) default: g_assert_not_reached(); } + + /* Use the target EL, current execution state and SCR/HCR settings to + * determine whether the corresponding CPSR bit is used to mask the + * interrupt. + */ + if ((target_el > cur_el) && (target_el != 1)) { + if (arm_el_is_aa64(env, 3) || ((scr || hcr) && (!secure))) { + unmasked = 1; + } + } + + /* The PSTATE bits only mask the interrupt if we have not overriden the + * ability above. + */ + return unmasked || pstate_unmasked; } static inline CPUARMState *cpu_init(const char *cpu_model) @@ -1402,6 +1673,12 @@ static inline bool arm_singlestep_active(CPUARMState *env) */ #define ARM_TBFLAG_XSCALE_CPAR_SHIFT 20 #define ARM_TBFLAG_XSCALE_CPAR_MASK (3 << ARM_TBFLAG_XSCALE_CPAR_SHIFT) +/* Indicates whether cp register reads and writes by guest code should access + * the secure or nonsecure bank of banked registers; note that this is not + * the same thing as the current security state of the processor! + */ +#define ARM_TBFLAG_NS_SHIFT 22 +#define ARM_TBFLAG_NS_MASK (1 << ARM_TBFLAG_NS_SHIFT) /* Bit usage when in AArch64 state */ #define ARM_TBFLAG_AA64_EL_SHIFT 0 @@ -1446,6 +1723,8 @@ static inline bool arm_singlestep_active(CPUARMState *env) (((F) & ARM_TBFLAG_AA64_SS_ACTIVE_MASK) >> ARM_TBFLAG_AA64_SS_ACTIVE_SHIFT) #define ARM_TBFLAG_AA64_PSTATE_SS(F) \ (((F) & ARM_TBFLAG_AA64_PSTATE_SS_MASK) >> ARM_TBFLAG_AA64_PSTATE_SS_SHIFT) +#define ARM_TBFLAG_NS(F) \ + (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT) static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, target_ulong *cs_base, int *flags) @@ -1495,6 +1774,9 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, if (privmode) { *flags |= ARM_TBFLAG_PRIV_MASK; } + if (!(access_secure_reg(env))) { + *flags |= ARM_TBFLAG_NS_MASK; + } if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30) || arm_el_is_aa64(env, 1)) { *flags |= ARM_TBFLAG_VFPEN_MASK; diff --git a/target-arm/helper.c b/target-arm/helper.c index b74d348a3b..96abbed935 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -136,6 +136,11 @@ static void raw_write(CPUARMState *env, const ARMCPRegInfo *ri, } } +static void *raw_ptr(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return (char *)env + ri->fieldoffset; +} + static uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri) { /* Raw read of a coprocessor register (as needed for migration, etc). */ @@ -419,13 +424,36 @@ static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri, } static const ARMCPRegInfo cp_reginfo[] = { - { .name = "FCSEIDR", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c13_fcse), + /* Define the secure and non-secure FCSE identifier CP registers + * separately because there is no secure bank in V8 (no _EL3). This allows + * the secure register to be properly reset and migrated. There is also no + * v8 EL1 version of the register so the non-secure instance stands alone. + */ + { .name = "FCSEIDR(NS)", + .cp = 15, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 0, + .access = PL1_RW, .secure = ARM_CP_SECSTATE_NS, + .fieldoffset = offsetof(CPUARMState, cp15.fcseidr_ns), + .resetvalue = 0, .writefn = fcse_write, .raw_writefn = raw_write, }, + { .name = "FCSEIDR(S)", + .cp = 15, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 0, + .access = PL1_RW, .secure = ARM_CP_SECSTATE_S, + .fieldoffset = offsetof(CPUARMState, cp15.fcseidr_s), .resetvalue = 0, .writefn = fcse_write, .raw_writefn = raw_write, }, - { .name = "CONTEXTIDR", .state = ARM_CP_STATE_BOTH, + /* Define the secure and non-secure context identifier CP registers + * separately because there is no secure bank in V8 (no _EL3). This allows + * the secure register to be properly reset and migrated. In the + * non-secure case, the 32-bit register will have reset and migration + * disabled during registration as it is handled by the 64-bit instance. + */ + { .name = "CONTEXTIDR_EL1", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 1, - .access = PL1_RW, - .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el1), + .access = PL1_RW, .secure = ARM_CP_SECSTATE_NS, + .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el[1]), + .resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, }, + { .name = "CONTEXTIDR(S)", .state = ARM_CP_STATE_AA32, + .cp = 15, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 1, + .access = PL1_RW, .secure = ARM_CP_SECSTATE_S, + .fieldoffset = offsetof(CPUARMState, cp15.contextidr_s), .resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, }, REGINFO_SENTINEL }; @@ -435,10 +463,12 @@ static const ARMCPRegInfo not_v8_cp_reginfo[] = { * definitions that don't use CP_ANY wildcards (mostly in v8_cp_reginfo[]). */ /* MMU Domain access control / MPU write buffer control */ - { .name = "DACR", .cp = 15, - .crn = 3, .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c3), - .resetvalue = 0, .writefn = dacr_write, .raw_writefn = raw_write, }, + { .name = "DACR", + .cp = 15, .opc1 = CP_ANY, .crn = 3, .crm = CP_ANY, .opc2 = CP_ANY, + .access = PL1_RW, .resetvalue = 0, + .writefn = dacr_write, .raw_writefn = raw_write, + .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dacr_s), + offsetoflow32(CPUARMState, cp15.dacr_ns) } }, /* ??? This covers not just the impdef TLB lockdown registers but also * some v7VMSA registers relating to TEX remap, so it is overly broad. */ @@ -552,7 +582,8 @@ static const ARMCPRegInfo v6_cp_reginfo[] = { .access = PL0_W, .type = ARM_CP_NOP }, { .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 2, .access = PL1_RW, - .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el[1]), + .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ifar_s), + offsetof(CPUARMState, cp15.ifar_ns) }, .resetvalue = 0, }, /* Watchpoint Fault Address Register : should actually only be present * for 1136, 1176, 11MPCore. @@ -776,7 +807,14 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri) { ARMCPU *cpu = arm_env_get_cpu(env); - return cpu->ccsidr[env->cp15.c0_cssel]; + + /* Acquire the CSSELR index from the bank corresponding to the CCSIDR + * bank + */ + uint32_t index = A32_BANKED_REG_GET(env, csselr, + ri->secure & ARM_CP_SECSTATE_S); + + return cpu->ccsidr[index]; } static void csselr_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -896,18 +934,17 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { { .name = "VBAR", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0, .access = PL1_RW, .writefn = vbar_write, - .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[1]), + .bank_fieldoffsets = { offsetof(CPUARMState, cp15.vbar_s), + offsetof(CPUARMState, cp15.vbar_ns) }, .resetvalue = 0 }, - { .name = "SCR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3), - .resetvalue = 0, .writefn = scr_write }, { .name = "CCSIDR", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0, .access = PL1_R, .readfn = ccsidr_read, .type = ARM_CP_NO_MIGRATE }, { .name = "CSSELR", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 2, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c0_cssel), - .writefn = csselr_write, .resetvalue = 0 }, + .access = PL1_RW, .writefn = csselr_write, .resetvalue = 0, + .bank_fieldoffsets = { offsetof(CPUARMState, cp15.csselr_s), + offsetof(CPUARMState, cp15.csselr_ns) } }, /* Auxiliary ID register: this actually has an IMPDEF value but for now * just RAZ for all cores: */ @@ -928,20 +965,26 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { */ { .name = "MAIR_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el1), + .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[1]), .resetvalue = 0 }, /* For non-long-descriptor page tables these are PRRR and NMRR; * regardless they still act as reads-as-written for QEMU. * The override is necessary because of the overly-broad TLB_LOCKDOWN * definition. */ + /* MAIR0/1 are defined seperately from their 64-bit counterpart which + * allows them to assign the correct fieldoffset based on the endianness + * handled in the field definitions. + */ { .name = "MAIR0", .state = ARM_CP_STATE_AA32, .type = ARM_CP_OVERRIDE, .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0, .access = PL1_RW, - .fieldoffset = offsetoflow32(CPUARMState, cp15.mair_el1), + .bank_fieldoffsets = { offsetof(CPUARMState, cp15.mair0_s), + offsetof(CPUARMState, cp15.mair0_ns) }, .resetfn = arm_cp_reset_ignore }, { .name = "MAIR1", .state = ARM_CP_STATE_AA32, .type = ARM_CP_OVERRIDE, .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 1, .access = PL1_RW, - .fieldoffset = offsetofhigh32(CPUARMState, cp15.mair_el1), + .bank_fieldoffsets = { offsetof(CPUARMState, cp15.mair1_s), + offsetof(CPUARMState, cp15.mair1_ns) }, .resetfn = arm_cp_reset_ignore }, { .name = "ISR_EL1", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 1, .opc2 = 0, @@ -1017,23 +1060,31 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = { { .name = "TPIDR_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .opc2 = 2, .crn = 13, .crm = 0, .access = PL0_RW, - .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el0), .resetvalue = 0 }, + .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[0]), .resetvalue = 0 }, { .name = "TPIDRURW", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 2, .access = PL0_RW, - .fieldoffset = offsetoflow32(CPUARMState, cp15.tpidr_el0), + .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidrurw_s), + offsetoflow32(CPUARMState, cp15.tpidrurw_ns) }, .resetfn = arm_cp_reset_ignore }, { .name = "TPIDRRO_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .opc2 = 3, .crn = 13, .crm = 0, .access = PL0_R|PL1_W, - .fieldoffset = offsetof(CPUARMState, cp15.tpidrro_el0), .resetvalue = 0 }, + .fieldoffset = offsetof(CPUARMState, cp15.tpidrro_el[0]), + .resetvalue = 0}, { .name = "TPIDRURO", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 3, .access = PL0_R|PL1_W, - .fieldoffset = offsetoflow32(CPUARMState, cp15.tpidrro_el0), + .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidruro_s), + offsetoflow32(CPUARMState, cp15.tpidruro_ns) }, .resetfn = arm_cp_reset_ignore }, - { .name = "TPIDR_EL1", .state = ARM_CP_STATE_BOTH, + { .name = "TPIDR_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .opc2 = 4, .crn = 13, .crm = 0, .access = PL1_RW, - .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el1), .resetvalue = 0 }, + .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[1]), .resetvalue = 0 }, + { .name = "TPIDRPRW", .opc1 = 0, .cp = 15, .crn = 13, .crm = 0, .opc2 = 4, + .access = PL1_RW, + .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidrprw_s), + offsetoflow32(CPUARMState, cp15.tpidrprw_ns) }, + .resetvalue = 0 }, REGINFO_SENTINEL }; @@ -1391,6 +1442,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) int prot; int ret, is_user = ri->opc2 & 2; int access_type = ri->opc2 & 1; + uint64_t par64; ret = get_phys_addr(env, value, access_type, is_user, &phys_addr, &prot, &page_size); @@ -1399,7 +1451,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) * translation table format, but with WnR always clear. * Convert it to a 64-bit PAR. */ - uint64_t par64 = (1 << 11); /* LPAE bit always set */ + par64 = (1 << 11); /* LPAE bit always set */ if (ret == 0) { par64 |= phys_addr & ~0xfffULL; /* We don't set the ATTR or SH fields in the PAR. */ @@ -1411,7 +1463,6 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) * fault. */ } - env->cp15.par_el1 = par64; } else { /* ret is a DFSR/IFSR value for the short descriptor * translation table format (with WnR always clear). @@ -1421,23 +1472,25 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) /* We do not set any attribute bits in the PAR */ if (page_size == (1 << 24) && arm_feature(env, ARM_FEATURE_V7)) { - env->cp15.par_el1 = (phys_addr & 0xff000000) | 1 << 1; + par64 = (phys_addr & 0xff000000) | (1 << 1); } else { - env->cp15.par_el1 = phys_addr & 0xfffff000; + par64 = phys_addr & 0xfffff000; } } else { - env->cp15.par_el1 = ((ret & (1 << 10)) >> 5) | - ((ret & (1 << 12)) >> 6) | - ((ret & 0xf) << 1) | 1; + par64 = ((ret & (1 << 10)) >> 5) | ((ret & (1 << 12)) >> 6) | + ((ret & 0xf) << 1) | 1; } } + + A32_BANKED_CURRENT_REG_SET(env, par, par64); } #endif static const ARMCPRegInfo vapa_cp_reginfo[] = { { .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0, .access = PL1_RW, .resetvalue = 0, - .fieldoffset = offsetoflow32(CPUARMState, cp15.par_el1), + .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.par_s), + offsetoflow32(CPUARMState, cp15.par_ns) }, .writefn = par_write }, #ifndef CONFIG_USER_ONLY { .name = "ATS", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = CP_ANY, @@ -1555,6 +1608,7 @@ static const ARMCPRegInfo pmsav5_cp_reginfo[] = { static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { + TCR *tcr = raw_ptr(env, ri); int maskshift = extract32(value, 0, 3); if (!arm_feature(env, ARM_FEATURE_V8)) { @@ -1573,14 +1627,15 @@ static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri, } } - /* Note that we always calculate c2_mask and c2_base_mask, but + /* Update the masks corresponding to the the TCR bank being written + * Note that we always calculate mask and base_mask, but * they are only used for short-descriptor tables (ie if EAE is 0); - * for long-descriptor tables the TTBCR fields are used differently - * and the c2_mask and c2_base_mask values are meaningless. + * for long-descriptor tables the TCR fields are used differently + * and the mask and base_mask values are meaningless. */ - raw_write(env, ri, value); - env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> maskshift); - env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> maskshift); + tcr->raw_tcr = value; + tcr->mask = ~(((uint32_t)0xffffffffu) >> maskshift); + tcr->base_mask = ~((uint32_t)0x3fffu >> maskshift); } static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -1599,19 +1654,25 @@ static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri) { - env->cp15.c2_base_mask = 0xffffc000u; - raw_write(env, ri, 0); - env->cp15.c2_mask = 0; + TCR *tcr = raw_ptr(env, ri); + + /* Reset both the TCR as well as the masks corresponding to the bank of + * the TCR being reset. + */ + tcr->raw_tcr = 0; + tcr->mask = 0; + tcr->base_mask = 0xffffc000u; } static void vmsa_tcr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { ARMCPU *cpu = arm_env_get_cpu(env); + TCR *tcr = raw_ptr(env, ri); /* For AArch64 the A1 bit could result in a change of ASID, so TLB flush. */ tlb_flush(CPU(cpu), 1); - raw_write(env, ri, value); + tcr->raw_tcr = value; } static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -1631,37 +1692,45 @@ static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri, static const ARMCPRegInfo vmsa_cp_reginfo[] = { { .name = "DFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0, .access = PL1_RW, .type = ARM_CP_NO_MIGRATE, - .fieldoffset = offsetoflow32(CPUARMState, cp15.esr_el[1]), + .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dfsr_s), + offsetoflow32(CPUARMState, cp15.dfsr_ns) }, .resetfn = arm_cp_reset_ignore, }, { .name = "IFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1, - .access = PL1_RW, - .fieldoffset = offsetof(CPUARMState, cp15.ifsr_el2), .resetvalue = 0, }, + .access = PL1_RW, .resetvalue = 0, + .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.ifsr_s), + offsetoflow32(CPUARMState, cp15.ifsr_ns) } }, { .name = "ESR_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .crn = 5, .crm = 2, .opc1 = 0, .opc2 = 0, .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[1]), .resetvalue = 0, }, { .name = "TTBR0_EL1", .state = ARM_CP_STATE_BOTH, - .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el1), - .writefn = vmsa_ttbr_write, .resetvalue = 0 }, + .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 0, + .access = PL1_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0, + .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s), + offsetof(CPUARMState, cp15.ttbr0_ns) } }, { .name = "TTBR1_EL1", .state = ARM_CP_STATE_BOTH, - .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el1), - .writefn = vmsa_ttbr_write, .resetvalue = 0 }, + .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 1, + .access = PL1_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0, + .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s), + offsetof(CPUARMState, cp15.ttbr1_ns) } }, { .name = "TCR_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2, .access = PL1_RW, .writefn = vmsa_tcr_el1_write, .resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write, - .fieldoffset = offsetof(CPUARMState, cp15.c2_control) }, + .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[1]) }, { .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2, .access = PL1_RW, .type = ARM_CP_NO_MIGRATE, .writefn = vmsa_ttbcr_write, .resetfn = arm_cp_reset_ignore, .raw_writefn = vmsa_ttbcr_raw_write, - .fieldoffset = offsetoflow32(CPUARMState, cp15.c2_control) }, - /* 64-bit FAR; this entry also gives us the AArch32 DFAR */ - { .name = "FAR_EL1", .state = ARM_CP_STATE_BOTH, + .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tcr_el[3]), + offsetoflow32(CPUARMState, cp15.tcr_el[1])} }, + { .name = "FAR_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0, .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[1]), .resetvalue = 0, }, + { .name = "DFAR", .cp = 15, .opc1 = 0, .crn = 6, .crm = 0, .opc2 = 0, + .access = PL1_RW, .resetvalue = 0, + .bank_fieldoffsets = { offsetof(CPUARMState, cp15.dfar_s), + offsetof(CPUARMState, cp15.dfar_ns) } }, REGINFO_SENTINEL }; @@ -1874,15 +1943,18 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = { .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue = 0 }, { .name = "PAR", .cp = 15, .crm = 7, .opc1 = 0, - .access = PL1_RW, .type = ARM_CP_64BIT, - .fieldoffset = offsetof(CPUARMState, cp15.par_el1), .resetvalue = 0 }, + .access = PL1_RW, .type = ARM_CP_64BIT, .resetvalue = 0, + .bank_fieldoffsets = { offsetof(CPUARMState, cp15.par_s), + offsetof(CPUARMState, cp15.par_ns)} }, { .name = "TTBR0", .cp = 15, .crm = 2, .opc1 = 0, .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE, - .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el1), + .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s), + offsetof(CPUARMState, cp15.ttbr0_ns) }, .writefn = vmsa_ttbr_write, .resetfn = arm_cp_reset_ignore }, { .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1, .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE, - .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el1), + .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s), + offsetof(CPUARMState, cp15.ttbr1_ns) }, .writefn = vmsa_ttbr_write, .resetfn = arm_cp_reset_ignore }, REGINFO_SENTINEL }; @@ -1911,7 +1983,7 @@ static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri, static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInfo *ri) { - if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) { + if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) { return CP_ACCESS_TRAP; } return CP_ACCESS_OK; @@ -1929,7 +2001,7 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env, /* Cache invalidate/clean: NOP, but EL0 must UNDEF unless * SCTLR_EL1.UCI is set. */ - if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_UCI)) { + if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCI)) { return CP_ACCESS_TRAP; } return CP_ACCESS_OK; @@ -2006,7 +2078,7 @@ static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri) /* We don't implement EL2, so the only control on DC ZVA is the * bit in the SCTLR which can prohibit access for EL0. */ - if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_DZE)) { + if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_DZE)) { return CP_ACCESS_TRAP; } return CP_ACCESS_OK; @@ -2045,6 +2117,24 @@ static void spsel_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t val) update_spsel(env, val); } +static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu = arm_env_get_cpu(env); + + if (raw_read(env, ri) == value) { + /* Skip the TLB flush if nothing actually changed; Linux likes + * to do a lot of pointless SCTLR writes. + */ + return; + } + + raw_write(env, ri, value); + /* ??? Lots of these bits are not implemented. */ + /* This may enable/disable the MMU, so do a TLB flush. */ + tlb_flush(CPU(cpu), 1); +} + static const ARMCPRegInfo v8_cp_reginfo[] = { /* Minimal set of EL0-visible registers. This will need to be expanded * significantly for system emulation of AArch64 CPUs. @@ -2216,10 +2306,11 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { { .name = "DCCISW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2, .type = ARM_CP_NOP, .access = PL1_W }, /* MMU Domain access control / MPU write buffer control */ - { .name = "DACR", .cp = 15, - .opc1 = 0, .crn = 3, .crm = 0, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c3), - .resetvalue = 0, .writefn = dacr_write, .raw_writefn = raw_write, }, + { .name = "DACR", .cp = 15, .opc1 = 0, .crn = 3, .crm = 0, .opc2 = 0, + .access = PL1_RW, .resetvalue = 0, + .writefn = dacr_write, .raw_writefn = raw_write, + .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dacr_s), + offsetoflow32(CPUARMState, cp15.dacr_ns) } }, { .name = "ELR_EL1", .state = ARM_CP_STATE_AA64, .type = ARM_CP_NO_MIGRATE, .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 1, @@ -2289,6 +2380,11 @@ static const ARMCPRegInfo v8_el2_cp_reginfo[] = { .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0, .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2), .writefn = hcr_write }, + { .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0, + .access = PL2_RW, .resetvalue = 0, + .writefn = dacr_write, .raw_writefn = raw_write, + .fieldoffset = offsetof(CPUARMState, cp15.dacr32_el2) }, { .name = "ELR_EL2", .state = ARM_CP_STATE_AA64, .type = ARM_CP_NO_MIGRATE, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1, @@ -2298,6 +2394,10 @@ static const ARMCPRegInfo v8_el2_cp_reginfo[] = { .type = ARM_CP_NO_MIGRATE, .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0, .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[2]) }, + { .name = "IFSR32_EL2", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 0, .opc2 = 1, + .access = PL2_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.ifsr32_el2) }, { .name = "FAR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 0, .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[2]) }, @@ -2314,6 +2414,19 @@ static const ARMCPRegInfo v8_el2_cp_reginfo[] = { }; static const ARMCPRegInfo v8_el3_cp_reginfo[] = { + { .name = "SCTLR_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 0, .opc2 = 0, + .access = PL3_RW, .raw_writefn = raw_write, .writefn = sctlr_write, + .fieldoffset = offsetof(CPUARMState, cp15.sctlr_el[3]) }, + { .name = "TTBR0_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 0, .opc2 = 0, + .access = PL3_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[3]) }, + { .name = "TCR_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 0, .opc2 = 2, + .access = PL3_RW, .writefn = vmsa_tcr_el1_write, + .resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write, + .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[3]) }, { .name = "ELR_EL3", .state = ARM_CP_STATE_AA64, .type = ARM_CP_NO_MIGRATE, .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 1, @@ -2335,38 +2448,42 @@ static const ARMCPRegInfo v8_el3_cp_reginfo[] = { .access = PL3_RW, .writefn = vbar_write, .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[3]), .resetvalue = 0 }, + REGINFO_SENTINEL +}; + +static const ARMCPRegInfo el3_cp_reginfo[] = { { .name = "SCR_EL3", .state = ARM_CP_STATE_AA64, - .type = ARM_CP_NO_MIGRATE, .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 0, .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.scr_el3), - .writefn = scr_write }, + .resetvalue = 0, .writefn = scr_write }, + { .name = "SCR", .type = ARM_CP_NO_MIGRATE, + .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 0, + .access = PL3_RW, .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3), + .resetfn = arm_cp_reset_ignore, .writefn = scr_write }, + { .name = "SDER32_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 1, + .access = PL3_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.sder) }, + { .name = "SDER", + .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 1, + .access = PL3_RW, .resetvalue = 0, + .fieldoffset = offsetoflow32(CPUARMState, cp15.sder) }, + /* TODO: Implement NSACR trapping of secure EL1 accesses to EL3 */ + { .name = "NSACR", .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2, + .access = PL3_W | PL1_R, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.nsacr) }, + { .name = "MVBAR", .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1, + .access = PL3_RW, .writefn = vbar_write, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.mvbar) }, REGINFO_SENTINEL }; -static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu = arm_env_get_cpu(env); - - if (raw_read(env, ri) == value) { - /* Skip the TLB flush if nothing actually changed; Linux likes - * to do a lot of pointless SCTLR writes. - */ - return; - } - - raw_write(env, ri, value); - /* ??? Lots of these bits are not implemented. */ - /* This may enable/disable the MMU, so do a TLB flush. */ - tlb_flush(CPU(cpu), 1); -} - static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri) { /* Only accessible in EL0 if SCTLR.UCT is set (and only in AArch64, * but the AArch32 CTR has its own reginfo struct) */ - if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_UCT)) { + if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCT)) { return CP_ACCESS_TRAP; } return CP_ACCESS_OK; @@ -2960,7 +3077,10 @@ void register_cp_regs_for_features(ARMCPU *cpu) } } if (arm_feature(env, ARM_FEATURE_EL3)) { - define_arm_cp_regs(cpu, v8_el3_cp_reginfo); + if (arm_feature(env, ARM_FEATURE_V8)) { + define_arm_cp_regs(cpu, v8_el3_cp_reginfo); + } + define_arm_cp_regs(cpu, el3_cp_reginfo); } if (arm_feature(env, ARM_FEATURE_MPU)) { /* These are the MPU registers prior to PMSAv6. Any new @@ -3160,8 +3280,10 @@ void register_cp_regs_for_features(ARMCPU *cpu) { ARMCPRegInfo sctlr = { .name = "SCTLR", .state = ARM_CP_STATE_BOTH, - .opc0 = 3, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_sys), + .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 0, + .access = PL1_RW, + .bank_fieldoffsets = { offsetof(CPUARMState, cp15.sctlr_s), + offsetof(CPUARMState, cp15.sctlr_ns) }, .writefn = sctlr_write, .resetvalue = cpu->reset_sctlr, .raw_writefn = raw_write, }; @@ -3287,7 +3409,7 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) } static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r, - void *opaque, int state, + void *opaque, int state, int secstate, int crm, int opc1, int opc2) { /* Private utility function for define_one_arm_cp_reg_with_opaque(): @@ -3296,22 +3418,59 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r, uint32_t *key = g_new(uint32_t, 1); ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo)); int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0; - if (r->state == ARM_CP_STATE_BOTH && state == ARM_CP_STATE_AA32) { - /* The AArch32 view of a shared register sees the lower 32 bits - * of a 64 bit backing field. It is not migratable as the AArch64 - * view handles that. AArch64 also handles reset. - * We assume it is a cp15 register if the .cp field is left unset. + int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0; + + /* Reset the secure state to the specific incoming state. This is + * necessary as the register may have been defined with both states. + */ + r2->secure = secstate; + + if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) { + /* Register is banked (using both entries in array). + * Overwriting fieldoffset as the array is only used to define + * banked registers but later only fieldoffset is used. */ - if (r2->cp == 0) { - r2->cp = 15; + r2->fieldoffset = r->bank_fieldoffsets[ns]; + } + + if (state == ARM_CP_STATE_AA32) { + if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) { + /* If the register is banked then we don't need to migrate or + * reset the 32-bit instance in certain cases: + * + * 1) If the register has both 32-bit and 64-bit instances then we + * can count on the 64-bit instance taking care of the + * non-secure bank. + * 2) If ARMv8 is enabled then we can count on a 64-bit version + * taking care of the secure bank. This requires that separate + * 32 and 64-bit definitions are provided. + */ + if ((r->state == ARM_CP_STATE_BOTH && ns) || + (arm_feature(&cpu->env, ARM_FEATURE_V8) && !ns)) { + r2->type |= ARM_CP_NO_MIGRATE; + r2->resetfn = arm_cp_reset_ignore; + } + } else if ((secstate != r->secure) && !ns) { + /* The register is not banked so we only want to allow migration of + * the non-secure instance. + */ + r2->type |= ARM_CP_NO_MIGRATE; + r2->resetfn = arm_cp_reset_ignore; } - r2->type |= ARM_CP_NO_MIGRATE; - r2->resetfn = arm_cp_reset_ignore; + + if (r->state == ARM_CP_STATE_BOTH) { + /* We assume it is a cp15 register if the .cp field is left unset. + */ + if (r2->cp == 0) { + r2->cp = 15; + } + #ifdef HOST_WORDS_BIGENDIAN - if (r2->fieldoffset) { - r2->fieldoffset += sizeof(uint32_t); - } + if (r2->fieldoffset) { + r2->fieldoffset += sizeof(uint32_t); + } #endif + } } if (state == ARM_CP_STATE_AA64) { /* To allow abbreviation of ARMCPRegInfo @@ -3327,7 +3486,7 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r, *key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm, r2->opc0, opc1, opc2); } else { - *key = ENCODE_CP_REG(r2->cp, is64, r2->crn, crm, opc1, opc2); + *key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2); } if (opaque) { r2->opaque = opaque; @@ -3460,10 +3619,14 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, */ if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) { if (r->access & PL3_R) { - assert(r->fieldoffset || r->readfn); + assert((r->fieldoffset || + (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) || + r->readfn); } if (r->access & PL3_W) { - assert(r->fieldoffset || r->writefn); + assert((r->fieldoffset || + (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) || + r->writefn); } } /* Bad type field probably means missing sentinel at end of reg list */ @@ -3476,8 +3639,32 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, if (r->state != state && r->state != ARM_CP_STATE_BOTH) { continue; } - add_cpreg_to_hashtable(cpu, r, opaque, state, - crm, opc1, opc2); + if (state == ARM_CP_STATE_AA32) { + /* Under AArch32 CP registers can be common + * (same for secure and non-secure world) or banked. + */ + switch (r->secure) { + case ARM_CP_SECSTATE_S: + case ARM_CP_SECSTATE_NS: + add_cpreg_to_hashtable(cpu, r, opaque, state, + r->secure, crm, opc1, opc2); + break; + default: + add_cpreg_to_hashtable(cpu, r, opaque, state, + ARM_CP_SECSTATE_S, + crm, opc1, opc2); + add_cpreg_to_hashtable(cpu, r, opaque, state, + ARM_CP_SECSTATE_NS, + crm, opc1, opc2); + break; + } + } else { + /* AArch64 registers get mapped to non-secure instance + * of AArch32 */ + add_cpreg_to_hashtable(cpu, r, opaque, state, + ARM_CP_SECSTATE_NS, + crm, opc1, opc2); + } } } } @@ -3551,6 +3738,8 @@ uint32_t cpsr_read(CPUARMState *env) void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) { + uint32_t changed_daif; + if (mask & CPSR_NZCV) { env->ZF = (~val) & CPSR_Z; env->NF = val; @@ -3573,6 +3762,58 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) env->GE = (val >> 16) & 0xf; } + /* In a V7 implementation that includes the security extensions but does + * not include Virtualization Extensions the SCR.FW and SCR.AW bits control + * whether non-secure software is allowed to change the CPSR_F and CPSR_A + * bits respectively. + * + * In a V8 implementation, it is permitted for privileged software to + * change the CPSR A/F bits regardless of the SCR.AW/FW bits. + */ + if (!arm_feature(env, ARM_FEATURE_V8) && + arm_feature(env, ARM_FEATURE_EL3) && + !arm_feature(env, ARM_FEATURE_EL2) && + !arm_is_secure(env)) { + + changed_daif = (env->daif ^ val) & mask; + + if (changed_daif & CPSR_A) { + /* Check to see if we are allowed to change the masking of async + * abort exceptions from a non-secure state. + */ + if (!(env->cp15.scr_el3 & SCR_AW)) { + qemu_log_mask(LOG_GUEST_ERROR, + "Ignoring attempt to switch CPSR_A flag from " + "non-secure world with SCR.AW bit clear\n"); + mask &= ~CPSR_A; + } + } + + if (changed_daif & CPSR_F) { + /* Check to see if we are allowed to change the masking of FIQ + * exceptions from a non-secure state. + */ + if (!(env->cp15.scr_el3 & SCR_FW)) { + qemu_log_mask(LOG_GUEST_ERROR, + "Ignoring attempt to switch CPSR_F flag from " + "non-secure world with SCR.FW bit clear\n"); + mask &= ~CPSR_F; + } + + /* Check whether non-maskable FIQ (NMFI) support is enabled. + * If this bit is set software is not allowed to mask + * FIQs, but is allowed to set CPSR_F to 0. + */ + if ((A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_NMFI) && + (val & CPSR_F)) { + qemu_log_mask(LOG_GUEST_ERROR, + "Ignoring attempt to enable CPSR_F flag " + "(non-maskable FIQ [NMFI] support enabled)\n"); + mask &= ~CPSR_F; + } + } + } + env->daif &= ~(CPSR_AIF & mask); env->daif |= val & CPSR_AIF & mask; @@ -3761,6 +4002,101 @@ void switch_mode(CPUARMState *env, int mode) env->spsr = env->banked_spsr[i]; } +/* Physical Interrupt Target EL Lookup Table + * + * [ From ARM ARM section G1.13.4 (Table G1-15) ] + * + * The below multi-dimensional table is used for looking up the target + * exception level given numerous condition criteria. Specifically, the + * target EL is based on SCR and HCR routing controls as well as the + * currently executing EL and secure state. + * + * Dimensions: + * target_el_table[2][2][2][2][2][4] + * | | | | | +--- Current EL + * | | | | +------ Non-secure(0)/Secure(1) + * | | | +--------- HCR mask override + * | | +------------ SCR exec state control + * | +--------------- SCR mask override + * +------------------ 32-bit(0)/64-bit(1) EL3 + * + * The table values are as such: + * 0-3 = EL0-EL3 + * -1 = Cannot occur + * + * The ARM ARM target EL table includes entries indicating that an "exception + * is not taken". The two cases where this is applicable are: + * 1) An exception is taken from EL3 but the SCR does not have the exception + * routed to EL3. + * 2) An exception is taken from EL2 but the HCR does not have the exception + * routed to EL2. + * In these two cases, the below table contain a target of EL1. This value is + * returned as it is expected that the consumer of the table data will check + * for "target EL >= current EL" to ensure the exception is not taken. + * + * SCR HCR + * 64 EA AMO From + * BIT IRQ IMO Non-secure Secure + * EL3 FIQ RW FMO EL0 EL1 EL2 EL3 EL0 EL1 EL2 EL3 + */ +const int8_t target_el_table[2][2][2][2][2][4] = { + {{{{/* 0 0 0 0 */{ 1, 1, 2, -1 },{ 3, -1, -1, 3 },}, + {/* 0 0 0 1 */{ 2, 2, 2, -1 },{ 3, -1, -1, 3 },},}, + {{/* 0 0 1 0 */{ 1, 1, 2, -1 },{ 3, -1, -1, 3 },}, + {/* 0 0 1 1 */{ 2, 2, 2, -1 },{ 3, -1, -1, 3 },},},}, + {{{/* 0 1 0 0 */{ 3, 3, 3, -1 },{ 3, -1, -1, 3 },}, + {/* 0 1 0 1 */{ 3, 3, 3, -1 },{ 3, -1, -1, 3 },},}, + {{/* 0 1 1 0 */{ 3, 3, 3, -1 },{ 3, -1, -1, 3 },}, + {/* 0 1 1 1 */{ 3, 3, 3, -1 },{ 3, -1, -1, 3 },},},},}, + {{{{/* 1 0 0 0 */{ 1, 1, 2, -1 },{ 1, 1, -1, 1 },}, + {/* 1 0 0 1 */{ 2, 2, 2, -1 },{ 1, 1, -1, 1 },},}, + {{/* 1 0 1 0 */{ 1, 1, 1, -1 },{ 1, 1, -1, 1 },}, + {/* 1 0 1 1 */{ 2, 2, 2, -1 },{ 1, 1, -1, 1 },},},}, + {{{/* 1 1 0 0 */{ 3, 3, 3, -1 },{ 3, 3, -1, 3 },}, + {/* 1 1 0 1 */{ 3, 3, 3, -1 },{ 3, 3, -1, 3 },},}, + {{/* 1 1 1 0 */{ 3, 3, 3, -1 },{ 3, 3, -1, 3 },}, + {/* 1 1 1 1 */{ 3, 3, 3, -1 },{ 3, 3, -1, 3 },},},},}, +}; + +/* + * Determine the target EL for physical exceptions + */ +static inline uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx, + uint32_t cur_el, bool secure) +{ + CPUARMState *env = cs->env_ptr; + int rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW); + int scr; + int hcr; + int target_el; + int is64 = arm_el_is_aa64(env, 3); + + switch (excp_idx) { + case EXCP_IRQ: + scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ); + hcr = ((env->cp15.hcr_el2 & HCR_IMO) == HCR_IMO); + break; + case EXCP_FIQ: + scr = ((env->cp15.scr_el3 & SCR_FIQ) == SCR_FIQ); + hcr = ((env->cp15.hcr_el2 & HCR_FMO) == HCR_FMO); + break; + default: + scr = ((env->cp15.scr_el3 & SCR_EA) == SCR_EA); + hcr = ((env->cp15.hcr_el2 & HCR_AMO) == HCR_AMO); + break; + }; + + /* If HCR.TGE is set then HCR is treated as being 1 */ + hcr |= ((env->cp15.hcr_el2 & HCR_TGE) == HCR_TGE); + + /* Perform a table-lookup for the target EL given the current state */ + target_el = target_el_table[is64][scr][rw][hcr][secure][cur_el]; + + assert(target_el > 0); + + return target_el; +} + /* * Determine the target EL for a given exception type. */ @@ -3770,13 +4106,7 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx) CPUARMState *env = &cpu->env; unsigned int cur_el = arm_current_el(env); unsigned int target_el; - /* FIXME: Use actual secure state. */ - bool secure = false; - - if (!env->aarch64) { - /* TODO: Add EL2 and 3 exception handling for AArch32. */ - return 1; - } + bool secure = arm_is_secure(env); switch (excp_idx) { case EXCP_HVC: @@ -3788,19 +4118,8 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx) break; case EXCP_FIQ: case EXCP_IRQ: - { - const uint64_t hcr_mask = excp_idx == EXCP_FIQ ? HCR_FMO : HCR_IMO; - const uint32_t scr_mask = excp_idx == EXCP_FIQ ? SCR_FIQ : SCR_IRQ; - - target_el = 1; - if (!secure && (env->cp15.hcr_el2 & hcr_mask)) { - target_el = 2; - } - if (env->cp15.scr_el3 & scr_mask) { - target_el = 3; - } + target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure); break; - } case EXCP_VIRQ: case EXCP_VFIQ: target_el = 1; @@ -4055,22 +4374,20 @@ void arm_cpu_do_interrupt(CPUState *cs) env->exception.fsr = 2; /* Fall through to prefetch abort. */ case EXCP_PREFETCH_ABORT: - env->cp15.ifsr_el2 = env->exception.fsr; - env->cp15.far_el[1] = deposit64(env->cp15.far_el[1], 32, 32, - env->exception.vaddress); + A32_BANKED_CURRENT_REG_SET(env, ifsr, env->exception.fsr); + A32_BANKED_CURRENT_REG_SET(env, ifar, env->exception.vaddress); qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n", - env->cp15.ifsr_el2, (uint32_t)env->exception.vaddress); + env->exception.fsr, (uint32_t)env->exception.vaddress); new_mode = ARM_CPU_MODE_ABT; addr = 0x0c; mask = CPSR_A | CPSR_I; offset = 4; break; case EXCP_DATA_ABORT: - env->cp15.esr_el[1] = env->exception.fsr; - env->cp15.far_el[1] = deposit64(env->cp15.far_el[1], 0, 32, - env->exception.vaddress); + A32_BANKED_CURRENT_REG_SET(env, dfsr, env->exception.fsr); + A32_BANKED_CURRENT_REG_SET(env, dfar, env->exception.vaddress); qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n", - (uint32_t)env->cp15.esr_el[1], + env->exception.fsr, (uint32_t)env->exception.vaddress); new_mode = ARM_CPU_MODE_ABT; addr = 0x10; @@ -4083,12 +4400,21 @@ void arm_cpu_do_interrupt(CPUState *cs) /* Disable IRQ and imprecise data aborts. */ mask = CPSR_A | CPSR_I; offset = 4; + if (env->cp15.scr_el3 & SCR_IRQ) { + /* IRQ routed to monitor mode */ + new_mode = ARM_CPU_MODE_MON; + mask |= CPSR_F; + } break; case EXCP_FIQ: new_mode = ARM_CPU_MODE_FIQ; addr = 0x1c; /* Disable FIQ, IRQ and imprecise data aborts. */ mask = CPSR_A | CPSR_I | CPSR_F; + if (env->cp15.scr_el3 & SCR_FIQ) { + /* FIQ routed to monitor mode */ + new_mode = ARM_CPU_MODE_MON; + } offset = 4; break; case EXCP_SMC: @@ -4101,19 +4427,19 @@ void arm_cpu_do_interrupt(CPUState *cs) cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index); return; /* Never happens. Keep compiler happy. */ } - /* High vectors. */ - if (env->cp15.c1_sys & SCTLR_V) { - /* when enabled, base address cannot be remapped. */ + + if (new_mode == ARM_CPU_MODE_MON) { + addr += env->cp15.mvbar; + } else if (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_V) { + /* High vectors. When enabled, base address cannot be remapped. */ addr += 0xffff0000; } else { /* ARM v7 architectures provide a vector base address register to remap * the interrupt vector table. - * This register is only followed in non-monitor mode, and has a secure - * and un-secure copy. Since the cpu is always in a un-secure operation - * and is never in monitor mode this feature is always active. + * This register is only followed in non-monitor mode, and is banked. * Note: only bits 31:5 are valid. */ - addr += env->cp15.vbar_el[1]; + addr += A32_BANKED_CURRENT_REG_GET(env, vbar); } if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON) { @@ -4134,7 +4460,7 @@ void arm_cpu_do_interrupt(CPUState *cs) /* this is a lie, as the was no c1_sys on V4T/V5, but who cares * and we should just guard the thumb mode on V4 */ if (arm_feature(env, ARM_FEATURE_V4T)) { - env->thumb = (env->cp15.c1_sys & SCTLR_TE) != 0; + env->thumb = (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_TE) != 0; } env->regs[14] = env->regs[15] + offset; env->regs[15] = addr; @@ -4165,7 +4491,7 @@ static inline int check_ap(CPUARMState *env, int ap, int domain_prot, } if (access_type == 1) return 0; - switch (env->cp15.c1_sys & (SCTLR_S | SCTLR_R)) { + switch (A32_BANKED_CURRENT_REG_GET(env, sctlr) & (SCTLR_S | SCTLR_R)) { case SCTLR_S: return is_user ? 0 : PAGE_READ; case SCTLR_R: @@ -4200,18 +4526,25 @@ static inline int check_ap(CPUARMState *env, int ap, int domain_prot, static bool get_level1_table_address(CPUARMState *env, uint32_t *table, uint32_t address) { - if (address & env->cp15.c2_mask) { - if ((env->cp15.c2_control & TTBCR_PD1)) { + /* Get the TCR bank based on our security state */ + TCR *tcr = &env->cp15.tcr_el[arm_is_secure(env) ? 3 : 1]; + + /* We only get here if EL1 is running in AArch32. If EL3 is running in + * AArch32 there is a secure and non-secure instance of the translation + * table registers. + */ + if (address & tcr->mask) { + if (tcr->raw_tcr & TTBCR_PD1) { /* Translation table walk disabled for TTBR1 */ return false; } - *table = env->cp15.ttbr1_el1 & 0xffffc000; + *table = A32_BANKED_CURRENT_REG_GET(env, ttbr1) & 0xffffc000; } else { - if ((env->cp15.c2_control & TTBCR_PD0)) { + if (tcr->raw_tcr & TTBCR_PD0) { /* Translation table walk disabled for TTBR0 */ return false; } - *table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask; + *table = A32_BANKED_CURRENT_REG_GET(env, ttbr0) & tcr->base_mask; } *table |= (address >> 18) & 0x3ffc; return true; @@ -4241,7 +4574,7 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type, desc = ldl_phys(cs->as, table); type = (desc & 3); domain = (desc >> 5) & 0x0f; - domain_prot = (env->cp15.c3 >> (domain * 2)) & 3; + domain_prot = (A32_BANKED_CURRENT_REG_GET(env, dacr) >> (domain * 2)) & 3; if (type == 0) { /* Section translation fault. */ code = 5; @@ -4353,7 +4686,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type, /* Page or Section. */ domain = (desc >> 5) & 0x0f; } - domain_prot = (env->cp15.c3 >> (domain * 2)) & 3; + domain_prot = (A32_BANKED_CURRENT_REG_GET(env, dacr) >> (domain * 2)) & 3; if (domain_prot == 0 || domain_prot == 2) { if (type != 1) { code = 9; /* Section domain fault. */ @@ -4414,7 +4747,8 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type, goto do_fault; /* The simplified model uses AP[0] as an access control bit. */ - if ((env->cp15.c1_sys & SCTLR_AFE) && (ap & 1) == 0) { + if ((A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_AFE) + && (ap & 1) == 0) { /* Access flag fault. */ code = (code == 15) ? 6 : 3; goto do_fault; @@ -4464,13 +4798,14 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address, int32_t granule_sz = 9; int32_t va_size = 32; int32_t tbi = 0; + TCR *tcr = &env->cp15.tcr_el[arm_is_secure(env) ? 3 : 1]; if (arm_el_is_aa64(env, 1)) { va_size = 64; if (extract64(address, 55, 1)) - tbi = extract64(env->cp15.c2_control, 38, 1); + tbi = extract64(tcr->raw_tcr, 38, 1); else - tbi = extract64(env->cp15.c2_control, 37, 1); + tbi = extract64(tcr->raw_tcr, 37, 1); tbi *= 8; } @@ -4479,12 +4814,12 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address, * This is a Non-secure PL0/1 stage 1 translation, so controlled by * TTBCR/TTBR0/TTBR1 in accordance with ARM ARM DDI0406C table B-32: */ - uint32_t t0sz = extract32(env->cp15.c2_control, 0, 6); + uint32_t t0sz = extract32(tcr->raw_tcr, 0, 6); if (arm_el_is_aa64(env, 1)) { t0sz = MIN(t0sz, 39); t0sz = MAX(t0sz, 16); } - uint32_t t1sz = extract32(env->cp15.c2_control, 16, 6); + uint32_t t1sz = extract32(tcr->raw_tcr, 16, 6); if (arm_el_is_aa64(env, 1)) { t1sz = MIN(t1sz, 39); t1sz = MAX(t1sz, 16); @@ -4515,11 +4850,11 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address, * we will always flush the TLB any time the ASID is changed). */ if (ttbr_select == 0) { - ttbr = env->cp15.ttbr0_el1; - epd = extract32(env->cp15.c2_control, 7, 1); + ttbr = A32_BANKED_CURRENT_REG_GET(env, ttbr0); + epd = extract32(tcr->raw_tcr, 7, 1); tsz = t0sz; - tg = extract32(env->cp15.c2_control, 14, 2); + tg = extract32(tcr->raw_tcr, 14, 2); if (tg == 1) { /* 64KB pages */ granule_sz = 13; } @@ -4527,11 +4862,11 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address, granule_sz = 11; } } else { - ttbr = env->cp15.ttbr1_el1; - epd = extract32(env->cp15.c2_control, 23, 1); + ttbr = A32_BANKED_CURRENT_REG_GET(env, ttbr1); + epd = extract32(tcr->raw_tcr, 23, 1); tsz = t1sz; - tg = extract32(env->cp15.c2_control, 30, 2); + tg = extract32(tcr->raw_tcr, 30, 2); if (tg == 3) { /* 64KB pages */ granule_sz = 13; } @@ -4747,11 +5082,17 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address, hwaddr *phys_ptr, int *prot, target_ulong *page_size) { + /* This is not entirely correct as get_phys_addr() can also be called + * from ats_write() for an address translation of a specific regime. + */ + uint32_t sctlr = A32_BANKED_CURRENT_REG_GET(env, sctlr); + /* Fast Context Switch Extension. */ - if (address < 0x02000000) - address += env->cp15.c13_fcse; + if (address < 0x02000000) { + address += A32_BANKED_CURRENT_REG_GET(env, fcseidr); + } - if ((env->cp15.c1_sys & SCTLR_M) == 0) { + if ((sctlr & SCTLR_M) == 0) { /* MMU/MPU disabled. */ *phys_ptr = address; *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; @@ -4764,7 +5105,7 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address, } else if (extended_addresses_enabled(env)) { return get_phys_addr_lpae(env, address, access_type, is_user, phys_ptr, prot, page_size); - } else if (env->cp15.c1_sys & SCTLR_XP) { + } else if (sctlr & SCTLR_XP) { return get_phys_addr_v6(env, address, access_type, is_user, phys_ptr, prot, page_size); } else { diff --git a/target-arm/internals.h b/target-arm/internals.h index 2dff4ffb19..bb171a73bd 100644 --- a/target-arm/internals.h +++ b/target-arm/internals.h @@ -153,9 +153,9 @@ static inline void update_spsel(CPUARMState *env, uint32_t imm) */ static inline bool extended_addresses_enabled(CPUARMState *env) { - return arm_el_is_aa64(env, 1) - || ((arm_feature(env, ARM_FEATURE_LPAE) - && (env->cp15.c2_control & TTBCR_EAE))); + TCR *tcr = &env->cp15.tcr_el[arm_is_secure(env) ? 3 : 1]; + return arm_el_is_aa64(env, 1) || + (arm_feature(env, ARM_FEATURE_LPAE) && (tcr->raw_tcr & TTBCR_EAE)); } /* Valid Syndrome Register EC field values */ diff --git a/target-arm/kvm.c b/target-arm/kvm.c index 319784d689..4d81f3d765 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -21,6 +21,7 @@ #include "sysemu/kvm.h" #include "kvm_arm.h" #include "cpu.h" +#include "internals.h" #include "hw/arm/arm.h" const KVMCapabilityInfo kvm_arch_required_capabilities[] = { @@ -279,6 +280,94 @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group, memory_region_ref(kd->mr); } +static int compare_u64(const void *a, const void *b) +{ + if (*(uint64_t *)a > *(uint64_t *)b) { + return 1; + } + if (*(uint64_t *)a < *(uint64_t *)b) { + return -1; + } + return 0; +} + +/* Initialize the CPUState's cpreg list according to the kernel's + * definition of what CPU registers it knows about (and throw away + * the previous TCG-created cpreg list). + */ +int kvm_arm_init_cpreg_list(ARMCPU *cpu) +{ + struct kvm_reg_list rl; + struct kvm_reg_list *rlp; + int i, ret, arraylen; + CPUState *cs = CPU(cpu); + + rl.n = 0; + ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, &rl); + if (ret != -E2BIG) { + return ret; + } + rlp = g_malloc(sizeof(struct kvm_reg_list) + rl.n * sizeof(uint64_t)); + rlp->n = rl.n; + ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, rlp); + if (ret) { + goto out; + } + /* Sort the list we get back from the kernel, since cpreg_tuples + * must be in strictly ascending order. + */ + qsort(&rlp->reg, rlp->n, sizeof(rlp->reg[0]), compare_u64); + + for (i = 0, arraylen = 0; i < rlp->n; i++) { + if (!kvm_arm_reg_syncs_via_cpreg_list(rlp->reg[i])) { + continue; + } + switch (rlp->reg[i] & KVM_REG_SIZE_MASK) { + case KVM_REG_SIZE_U32: + case KVM_REG_SIZE_U64: + break; + default: + fprintf(stderr, "Can't handle size of register in kernel list\n"); + ret = -EINVAL; + goto out; + } + + arraylen++; + } + + cpu->cpreg_indexes = g_renew(uint64_t, cpu->cpreg_indexes, arraylen); + cpu->cpreg_values = g_renew(uint64_t, cpu->cpreg_values, arraylen); + cpu->cpreg_vmstate_indexes = g_renew(uint64_t, cpu->cpreg_vmstate_indexes, + arraylen); + cpu->cpreg_vmstate_values = g_renew(uint64_t, cpu->cpreg_vmstate_values, + arraylen); + cpu->cpreg_array_len = arraylen; + cpu->cpreg_vmstate_array_len = arraylen; + + for (i = 0, arraylen = 0; i < rlp->n; i++) { + uint64_t regidx = rlp->reg[i]; + if (!kvm_arm_reg_syncs_via_cpreg_list(regidx)) { + continue; + } + cpu->cpreg_indexes[arraylen] = regidx; + arraylen++; + } + assert(cpu->cpreg_array_len == arraylen); + + if (!write_kvmstate_to_list(cpu)) { + /* Shouldn't happen unless kernel is inconsistent about + * what registers exist. + */ + fprintf(stderr, "Initial read of kernel register state failed\n"); + ret = -EINVAL; + goto out; + } + +out: + g_free(rlp); + return ret; +} + bool write_kvmstate_to_list(ARMCPU *cpu) { CPUState *cs = CPU(cpu); @@ -351,6 +440,24 @@ bool write_list_to_kvmstate(ARMCPU *cpu) return ok; } +void kvm_arm_reset_vcpu(ARMCPU *cpu) +{ + int ret; + + /* Re-init VCPU so that all registers are set to + * their respective reset values. + */ + ret = kvm_arm_vcpu_init(CPU(cpu)); + if (ret < 0) { + fprintf(stderr, "kvm_arm_vcpu_init failed: %s\n", strerror(-ret)); + abort(); + } + if (!write_kvmstate_to_list(cpu)) { + fprintf(stderr, "write_kvmstate_to_list failed\n"); + abort(); + } +} + void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) { } diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c index 5ec4eb1f32..94030d1acb 100644 --- a/target-arm/kvm32.c +++ b/target-arm/kvm32.c @@ -51,17 +51,17 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc) struct kvm_one_reg idregs[] = { { .id = KVM_REG_ARM | KVM_REG_SIZE_U32 - | ENCODE_CP_REG(15, 0, 0, 0, 0, 0), + | ENCODE_CP_REG(15, 0, 0, 0, 0, 0, 0), .addr = (uintptr_t)&midr, }, { .id = KVM_REG_ARM | KVM_REG_SIZE_U32 - | ENCODE_CP_REG(15, 0, 0, 1, 0, 0), + | ENCODE_CP_REG(15, 0, 0, 0, 1, 0, 0), .addr = (uintptr_t)&id_pfr0, }, { .id = KVM_REG_ARM | KVM_REG_SIZE_U32 - | ENCODE_CP_REG(15, 0, 0, 2, 0, 0), + | ENCODE_CP_REG(15, 0, 0, 0, 2, 0, 0), .addr = (uintptr_t)&id_isar0, }, { @@ -138,7 +138,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc) return true; } -static bool reg_syncs_via_tuple_list(uint64_t regidx) +bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx) { /* Return true if the regidx is a register we should synchronize * via the cpreg_tuples array (ie is not a core reg we sync by @@ -153,24 +153,11 @@ static bool reg_syncs_via_tuple_list(uint64_t regidx) } } -static int compare_u64(const void *a, const void *b) -{ - if (*(uint64_t *)a > *(uint64_t *)b) { - return 1; - } - if (*(uint64_t *)a < *(uint64_t *)b) { - return -1; - } - return 0; -} - int kvm_arch_init_vcpu(CPUState *cs) { - int i, ret, arraylen; + int ret; uint64_t v; struct kvm_one_reg r; - struct kvm_reg_list rl; - struct kvm_reg_list *rlp; ARMCPU *cpu = ARM_CPU(cs); if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) { @@ -206,73 +193,7 @@ int kvm_arch_init_vcpu(CPUState *cs) return -EINVAL; } - /* Populate the cpreg list based on the kernel's idea - * of what registers exist (and throw away the TCG-created list). - */ - rl.n = 0; - ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, &rl); - if (ret != -E2BIG) { - return ret; - } - rlp = g_malloc(sizeof(struct kvm_reg_list) + rl.n * sizeof(uint64_t)); - rlp->n = rl.n; - ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, rlp); - if (ret) { - goto out; - } - /* Sort the list we get back from the kernel, since cpreg_tuples - * must be in strictly ascending order. - */ - qsort(&rlp->reg, rlp->n, sizeof(rlp->reg[0]), compare_u64); - - for (i = 0, arraylen = 0; i < rlp->n; i++) { - if (!reg_syncs_via_tuple_list(rlp->reg[i])) { - continue; - } - switch (rlp->reg[i] & KVM_REG_SIZE_MASK) { - case KVM_REG_SIZE_U32: - case KVM_REG_SIZE_U64: - break; - default: - fprintf(stderr, "Can't handle size of register in kernel list\n"); - ret = -EINVAL; - goto out; - } - - arraylen++; - } - - cpu->cpreg_indexes = g_renew(uint64_t, cpu->cpreg_indexes, arraylen); - cpu->cpreg_values = g_renew(uint64_t, cpu->cpreg_values, arraylen); - cpu->cpreg_vmstate_indexes = g_renew(uint64_t, cpu->cpreg_vmstate_indexes, - arraylen); - cpu->cpreg_vmstate_values = g_renew(uint64_t, cpu->cpreg_vmstate_values, - arraylen); - cpu->cpreg_array_len = arraylen; - cpu->cpreg_vmstate_array_len = arraylen; - - for (i = 0, arraylen = 0; i < rlp->n; i++) { - uint64_t regidx = rlp->reg[i]; - if (!reg_syncs_via_tuple_list(regidx)) { - continue; - } - cpu->cpreg_indexes[arraylen] = regidx; - arraylen++; - } - assert(cpu->cpreg_array_len == arraylen); - - if (!write_kvmstate_to_list(cpu)) { - /* Shouldn't happen unless kernel is inconsistent about - * what registers exist. - */ - fprintf(stderr, "Initial read of kernel register state failed\n"); - ret = -EINVAL; - goto out; - } - -out: - g_free(rlp); - return ret; + return kvm_arm_init_cpreg_list(cpu); } typedef struct Reg { @@ -508,12 +429,3 @@ int kvm_arch_get_registers(CPUState *cs) return 0; } - -void kvm_arm_reset_vcpu(ARMCPU *cpu) -{ - /* 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-arm/kvm64.c b/target-arm/kvm64.c index c615286158..ba16821737 100644 --- a/target-arm/kvm64.c +++ b/target-arm/kvm64.c @@ -103,9 +103,21 @@ int kvm_arch_init_vcpu(CPUState *cs) return ret; } - /* TODO : support for save/restore/reset of system regs via tuple list */ + return kvm_arm_init_cpreg_list(cpu); +} - return 0; +bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx) +{ + /* Return true if the regidx is a register we should synchronize + * via the cpreg_tuples array (ie is not a core reg we sync by + * hand in kvm_arch_get/put_registers()) + */ + switch (regidx & KVM_REG_ARM_COPROC_MASK) { + case KVM_REG_ARM_CORE: + return false; + default: + return true; + } } #define AARCH64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \ @@ -260,11 +272,3 @@ int kvm_arch_get_registers(CPUState *cs) /* TODO: other registers */ return ret; } - -void kvm_arm_reset_vcpu(ARMCPU *cpu) -{ - /* Re-init VCPU so that all registers are set to - * their respective reset values. - */ - kvm_arm_vcpu_init(CPU(cpu)); -} diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h index af93105517..455dea3f3f 100644 --- a/target-arm/kvm_arm.h +++ b/target-arm/kvm_arm.h @@ -47,6 +47,28 @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group, uint64_t attr, int dev_fd); /** + * kvm_arm_init_cpreg_list: + * @cs: CPUState + * + * Initialize the CPUState's cpreg list according to the kernel's + * definition of what CPU registers it knows about (and throw away + * the previous TCG-created cpreg list). + * + * Returns: 0 if success, else < 0 error code + */ +int kvm_arm_init_cpreg_list(ARMCPU *cpu); + +/** + * kvm_arm_reg_syncs_via_cpreg_list + * regidx: KVM register index + * + * Return true if this KVM register should be synchronized via the + * cpreg list of arbitrary system registers, false if it is synchronized + * by hand using code in kvm_arch_get/put_registers(). + */ +bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx); + +/** * write_list_to_kvmstate: * @cpu: ARMCPU * diff --git a/target-arm/machine.c b/target-arm/machine.c index 6437690af7..c29e7a2ac1 100644 --- a/target-arm/machine.c +++ b/target-arm/machine.c @@ -127,6 +127,13 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size) CPUARMState *env = &cpu->env; uint32_t val = qemu_get_be32(f); + env->aarch64 = ((val & PSTATE_nRW) == 0); + + if (is_a64(env)) { + pstate_write(env, val); + return 0; + } + /* Avoid mode switch when restoring CPSR */ env->uncached_cpsr = val & CPSR_M; cpsr_write(env, val, 0xffffffff); @@ -137,8 +144,15 @@ static void put_cpsr(QEMUFile *f, void *opaque, size_t size) { ARMCPU *cpu = opaque; CPUARMState *env = &cpu->env; + uint32_t val; + + if (is_a64(env)) { + val = pstate_read(env); + } else { + val = cpsr_read(env); + } - qemu_put_be32(f, cpsr_read(env)); + qemu_put_be32(f, val); } static const VMStateInfo vmstate_cpsr = { @@ -222,12 +236,14 @@ static int cpu_post_load(void *opaque, int version_id) const VMStateDescription vmstate_arm_cpu = { .name = "cpu", - .version_id = 21, - .minimum_version_id = 21, + .version_id = 22, + .minimum_version_id = 22, .pre_save = cpu_pre_save, .post_load = cpu_post_load, .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(env.regs, ARMCPU, 16), + VMSTATE_UINT64_ARRAY(env.xregs, ARMCPU, 32), + VMSTATE_UINT64(env.pc, ARMCPU), { .name = "cpsr", .version_id = 0, diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 62012c3a6e..2bed914770 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -361,7 +361,7 @@ void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm) * Note that SPSel is never OK from EL0; we rely on handle_msr_i() * to catch that case at translate time. */ - if (arm_current_el(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) { + if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) { raise_exception(env, EXCP_UDEF); } @@ -575,7 +575,7 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn) * short descriptor format (in which case it holds both PROCID and ASID), * since we don't implement the optional v7 context ID masking. */ - contextidr = extract64(env->cp15.contextidr_el1, 0, 32); + contextidr = extract64(env->cp15.contextidr_el[1], 0, 32); switch (bt) { case 3: /* linked context ID match */ diff --git a/target-arm/translate.c b/target-arm/translate.c index af5156857e..b52c758698 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -7091,7 +7091,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) rt = (insn >> 12) & 0xf; ri = get_arm_cp_reginfo(s->cp_regs, - ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2)); + ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2)); if (ri) { /* Check access permissions */ if (!cp_access_ok(s->current_el, ri, isread)) { @@ -7281,12 +7281,16 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) */ if (is64) { qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 " - "64 bit system register cp:%d opc1: %d crm:%d\n", - isread ? "read" : "write", cpnum, opc1, crm); + "64 bit system register cp:%d opc1: %d crm:%d " + "(%s)\n", + isread ? "read" : "write", cpnum, opc1, crm, + s->ns ? "non-secure" : "secure"); } else { qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 " - "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d\n", - isread ? "read" : "write", cpnum, opc1, crn, crm, opc2); + "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d " + "(%s)\n", + isread ? "read" : "write", cpnum, opc1, crn, crm, opc2, + s->ns ? "non-secure" : "secure"); } return 1; @@ -11031,6 +11035,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, #if !defined(CONFIG_USER_ONLY) dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0); #endif + dc->ns = ARM_TBFLAG_NS(tb->flags); dc->cpacr_fpen = ARM_TBFLAG_CPACR_FPEN(tb->flags); dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags); dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags); diff --git a/target-arm/translate.h b/target-arm/translate.h index 41a907157f..f6ee7892ba 100644 --- a/target-arm/translate.h +++ b/target-arm/translate.h @@ -20,6 +20,7 @@ typedef struct DisasContext { #if !defined(CONFIG_USER_ONLY) int user; #endif + bool ns; /* Use non-secure CPREG bank on access */ bool cpacr_fpen; /* FP enabled via CPACR.FPEN */ bool vfp_enabled; /* FP enabled via FPSCR.EN */ int vec_len; diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c index 1d4eee3974..30d34d5aee 100644 --- a/target-i386/fpu_helper.c +++ b/target-i386/fpu_helper.c @@ -251,16 +251,34 @@ int32_t helper_fist_ST0(CPUX86State *env) int32_t helper_fistl_ST0(CPUX86State *env) { int32_t val; + signed char old_exp_flags; + + old_exp_flags = get_float_exception_flags(&env->fp_status); + set_float_exception_flags(0, &env->fp_status); val = floatx80_to_int32(ST0, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) { + val = 0x80000000; + } + set_float_exception_flags(get_float_exception_flags(&env->fp_status) + | old_exp_flags, &env->fp_status); return val; } int64_t helper_fistll_ST0(CPUX86State *env) { int64_t val; + signed char old_exp_flags; - val = floatx80_to_int64(ST0, &env->fp_status); + old_exp_flags = get_float_exception_flags(&env->fp_status); + set_float_exception_flags(0, &env->fp_status); + + val = floatx80_to_int32(ST0, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) { + val = 0x8000000000000000ULL; + } + set_float_exception_flags(get_float_exception_flags(&env->fp_status) + | old_exp_flags, &env->fp_status); return val; } @@ -621,7 +639,7 @@ void helper_fbld_ST0(CPUX86State *env, target_ulong ptr) } tmp = int64_to_floatx80(val, &env->fp_status); if (cpu_ldub_data(env, ptr + 9) & 0x80) { - floatx80_chs(tmp); + tmp = floatx80_chs(tmp); } fpush(env); ST0 = tmp; diff --git a/target-i386/translate.c b/target-i386/translate.c index 31a9f74467..fc75da7fc0 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -115,6 +115,7 @@ typedef struct DisasContext { int tf; /* TF cpu flag */ int singlestep_enabled; /* "hardware" single step enabled */ int jmp_opt; /* use direct block chaining for direct jumps */ + int repz_opt; /* optimize jumps within repz instructions */ int mem_index; /* select memory access functions */ uint64_t flags; /* all execution flags */ struct TranslationBlock *tb; @@ -1215,7 +1216,7 @@ static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \ gen_op_add_reg_im(s->aflag, R_ECX, -1); \ /* a loop would cause two single step exceptions if ECX = 1 \ before rep string_insn */ \ - if (!s->jmp_opt) \ + if (s->repz_opt) \ gen_op_jz_ecx(s->aflag, l2); \ gen_jmp(s, cur_eip); \ } @@ -1233,7 +1234,7 @@ static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \ gen_op_add_reg_im(s->aflag, R_ECX, -1); \ gen_update_cc_op(s); \ gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \ - if (!s->jmp_opt) \ + if (s->repz_opt) \ gen_op_jz_ecx(s->aflag, l2); \ gen_jmp(s, cur_eip); \ } @@ -7951,6 +7952,17 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, || (flags & HF_SOFTMMU_MASK) #endif ); + /* Do not optimize repz jumps at all in icount mode, because + rep movsS instructions are execured with different paths + in !repz_opt and repz_opt modes. The first one was used + always except single step mode. And this setting + disables jumps optimization and control paths become + equivalent in run and single step modes. + Now there will be no jump optimization for repz in + record/replay modes and there will always be an + additional step for ecx=0 when icount is enabled. + */ + dc->repz_opt = !dc->jmp_opt && !use_icount; #if 0 /* check addseg logic */ if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32)) diff --git a/target-s390x/helper.c b/target-s390x/helper.c index 09aec7b42e..96a4f22734 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -648,7 +648,7 @@ static void do_ext_interrupt(CPUS390XState *env) cpu_abort(CPU(cpu), "Ext int w/o ext mask\n"); } - if (env->ext_index < 0 || env->ext_index > MAX_EXT_QUEUE) { + if (env->ext_index < 0 || env->ext_index >= MAX_EXT_QUEUE) { cpu_abort(CPU(cpu), "Ext queue overrun: %d\n", env->ext_index); } @@ -696,7 +696,7 @@ static void do_io_interrupt(CPUS390XState *env) if (env->io_index[isc] < 0) { continue; } - if (env->io_index[isc] > MAX_IO_QUEUE) { + if (env->io_index[isc] >= MAX_IO_QUEUE) { cpu_abort(CPU(cpu), "I/O queue overrun for isc %d: %d\n", isc, env->io_index[isc]); } @@ -754,7 +754,7 @@ static void do_mchk_interrupt(CPUS390XState *env) cpu_abort(CPU(cpu), "Machine check w/o mchk mask\n"); } - if (env->mchk_index < 0 || env->mchk_index > MAX_MCHK_QUEUE) { + if (env->mchk_index < 0 || env->mchk_index >= MAX_MCHK_QUEUE) { cpu_abort(CPU(cpu), "Mchk queue overrun: %d\n", env->mchk_index); } diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 1dcdaa6662..f3f8f2c2ca 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -106,7 +106,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { static int cap_sync_regs; static int cap_async_pf; -static void *legacy_s390_alloc(size_t size); +static void *legacy_s390_alloc(size_t size, uint64_t *align); static int kvm_s390_check_clear_cmma(KVMState *s) { @@ -404,7 +404,7 @@ int kvm_arch_get_registers(CPUState *cs) * to grow. We also have to use MAP parameters that avoid * read-only mapping of guest pages. */ -static void *legacy_s390_alloc(size_t size, , uint64_t *align) +static void *legacy_s390_alloc(size_t size, uint64_t *align) { void *mem; diff --git a/target-tricore/cpu.c b/target-tricore/cpu.c index 7bf041afb9..abe16fa7e6 100644 --- a/target-tricore/cpu.c +++ b/target-tricore/cpu.c @@ -63,8 +63,17 @@ static bool tricore_cpu_has_work(CPUState *cs) static void tricore_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); + TriCoreCPU *cpu = TRICORE_CPU(dev); TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(dev); + CPUTriCoreState *env = &cpu->env; + /* Some features automatically imply others */ + if (tricore_feature(env, TRICORE_FEATURE_16)) { + set_feature(env, TRICORE_FEATURE_131); + } + if (tricore_feature(env, TRICORE_FEATURE_131)) { + set_feature(env, TRICORE_FEATURE_13); + } cpu_reset(cs); qemu_init_vcpu(cs); diff --git a/target-tricore/csfr.def b/target-tricore/csfr.def new file mode 100644 index 0000000000..5b219b4bf1 --- /dev/null +++ b/target-tricore/csfr.def @@ -0,0 +1,124 @@ +/* A(ll) access permited + R(ead only) access + E(nd init protected) access + + A|R|E(offset, register, feature introducing reg) + + NOTE: PSW is handled as a special case in gen_mtcr/mfcr */ + +A(0xfe00, PCXI, TRICORE_FEATURE_13) +A(0xfe08, PC, TRICORE_FEATURE_13) +A(0xfe14, SYSCON, TRICORE_FEATURE_13) +R(0xfe18, CPU_ID, TRICORE_FEATURE_13) +E(0xfe20, BIV, TRICORE_FEATURE_13) +E(0xfe24, BTV, TRICORE_FEATURE_13) +E(0xfe28, ISP, TRICORE_FEATURE_13) +A(0xfe2c, ICR, TRICORE_FEATURE_13) +A(0xfe38, FCX, TRICORE_FEATURE_13) +A(0xfe3c, LCX, TRICORE_FEATURE_13) +E(0x9400, COMPAT, TRICORE_FEATURE_131) +/* memory protection register */ +A(0xC000, DPR0_0L, TRICORE_FEATURE_13) +A(0xC004, DPR0_0U, TRICORE_FEATURE_13) +A(0xC008, DPR0_1L, TRICORE_FEATURE_13) +A(0xC00C, DPR0_1U, TRICORE_FEATURE_13) +A(0xC010, DPR0_2L, TRICORE_FEATURE_13) +A(0xC014, DPR0_2U, TRICORE_FEATURE_13) +A(0xC018, DPR0_3L, TRICORE_FEATURE_13) +A(0xC01C, DPR0_3U, TRICORE_FEATURE_13) +A(0xC400, DPR1_0L, TRICORE_FEATURE_13) +A(0xC404, DPR1_0U, TRICORE_FEATURE_13) +A(0xC408, DPR1_1L, TRICORE_FEATURE_13) +A(0xC40C, DPR1_1U, TRICORE_FEATURE_13) +A(0xC410, DPR1_2L, TRICORE_FEATURE_13) +A(0xC414, DPR1_2U, TRICORE_FEATURE_13) +A(0xC418, DPR1_3L, TRICORE_FEATURE_13) +A(0xC41C, DPR1_3U, TRICORE_FEATURE_13) +A(0xC800, DPR2_0L, TRICORE_FEATURE_13) +A(0xC804, DPR2_0U, TRICORE_FEATURE_13) +A(0xC808, DPR2_1L, TRICORE_FEATURE_13) +A(0xC80C, DPR2_1U, TRICORE_FEATURE_13) +A(0xC810, DPR2_2L, TRICORE_FEATURE_13) +A(0xC814, DPR2_2U, TRICORE_FEATURE_13) +A(0xC818, DPR2_3L, TRICORE_FEATURE_13) +A(0xC81C, DPR2_3U, TRICORE_FEATURE_13) +A(0xCC00, DPR3_0L, TRICORE_FEATURE_13) +A(0xCC04, DPR3_0U, TRICORE_FEATURE_13) +A(0xCC08, DPR3_1L, TRICORE_FEATURE_13) +A(0xCC0C, DPR3_1U, TRICORE_FEATURE_13) +A(0xCC10, DPR3_2L, TRICORE_FEATURE_13) +A(0xCC14, DPR3_2U, TRICORE_FEATURE_13) +A(0xCC18, DPR3_3L, TRICORE_FEATURE_13) +A(0xCC1C, DPR3_3U, TRICORE_FEATURE_13) +A(0xD000, CPR0_0L, TRICORE_FEATURE_13) +A(0xD004, CPR0_0U, TRICORE_FEATURE_13) +A(0xD008, CPR0_1L, TRICORE_FEATURE_13) +A(0xD00C, CPR0_1U, TRICORE_FEATURE_13) +A(0xD010, CPR0_2L, TRICORE_FEATURE_13) +A(0xD014, CPR0_2U, TRICORE_FEATURE_13) +A(0xD018, CPR0_3L, TRICORE_FEATURE_13) +A(0xD01C, CPR0_3U, TRICORE_FEATURE_13) +A(0xD400, CPR1_0L, TRICORE_FEATURE_13) +A(0xD404, CPR1_0U, TRICORE_FEATURE_13) +A(0xD408, CPR1_1L, TRICORE_FEATURE_13) +A(0xD40C, CPR1_1U, TRICORE_FEATURE_13) +A(0xD410, CPR1_2L, TRICORE_FEATURE_13) +A(0xD414, CPR1_2U, TRICORE_FEATURE_13) +A(0xD418, CPR1_3L, TRICORE_FEATURE_13) +A(0xD41C, CPR1_3U, TRICORE_FEATURE_13) +A(0xD800, CPR2_0L, TRICORE_FEATURE_13) +A(0xD804, CPR2_0U, TRICORE_FEATURE_13) +A(0xD808, CPR2_1L, TRICORE_FEATURE_13) +A(0xD80C, CPR2_1U, TRICORE_FEATURE_13) +A(0xD810, CPR2_2L, TRICORE_FEATURE_13) +A(0xD814, CPR2_2U, TRICORE_FEATURE_13) +A(0xD818, CPR2_3L, TRICORE_FEATURE_13) +A(0xD81C, CPR2_3U, TRICORE_FEATURE_13) +A(0xDC00, CPR3_0L, TRICORE_FEATURE_13) +A(0xDC04, CPR3_0U, TRICORE_FEATURE_13) +A(0xDC08, CPR3_1L, TRICORE_FEATURE_13) +A(0xDC0C, CPR3_1U, TRICORE_FEATURE_13) +A(0xDC10, CPR3_2L, TRICORE_FEATURE_13) +A(0xDC14, CPR3_2U, TRICORE_FEATURE_13) +A(0xDC18, CPR3_3L, TRICORE_FEATURE_13) +A(0xDC1C, CPR3_3U, TRICORE_FEATURE_13) +A(0xE000, DPM0, TRICORE_FEATURE_13) +A(0xE080, DPM1, TRICORE_FEATURE_13) +A(0xE100, DPM2, TRICORE_FEATURE_13) +A(0xE180, DPM3, TRICORE_FEATURE_13) +A(0xE200, CPM0, TRICORE_FEATURE_13) +A(0xE280, CPM1, TRICORE_FEATURE_13) +A(0xE300, CPM2, TRICORE_FEATURE_13) +A(0xE380, CPM3, TRICORE_FEATURE_13) +/* memory Managment Registers */ +A(0x8000, MMU_CON, TRICORE_FEATURE_13) +A(0x8004, MMU_ASI, TRICORE_FEATURE_13) +A(0x800C, MMU_TVA, TRICORE_FEATURE_13) +A(0x8010, MMU_TPA, TRICORE_FEATURE_13) +A(0x8014, MMU_TPX, TRICORE_FEATURE_13) +A(0x8018, MMU_TFA, TRICORE_FEATURE_13) +E(0x9004, BMACON, TRICORE_FEATURE_131) +E(0x900C, SMACON, TRICORE_FEATURE_131) +A(0x9020, DIEAR, TRICORE_FEATURE_131) +A(0x9024, DIETR, TRICORE_FEATURE_131) +A(0x9028, CCDIER, TRICORE_FEATURE_131) +E(0x9044, MIECON, TRICORE_FEATURE_131) +A(0x9210, PIEAR, TRICORE_FEATURE_131) +A(0x9214, PIETR, TRICORE_FEATURE_131) +A(0x9218, CCPIER, TRICORE_FEATURE_131) +/* debug registers */ +A(0xFD00, DBGSR, TRICORE_FEATURE_13) +A(0xFD08, EXEVT, TRICORE_FEATURE_13) +A(0xFD0C, CREVT, TRICORE_FEATURE_13) +A(0xFD10, SWEVT, TRICORE_FEATURE_13) +A(0xFD20, TR0EVT, TRICORE_FEATURE_13) +A(0xFD24, TR1EVT, TRICORE_FEATURE_13) +A(0xFD40, DMS, TRICORE_FEATURE_13) +A(0xFD44, DCX, TRICORE_FEATURE_13) +A(0xFD48, DBGTCR, TRICORE_FEATURE_131) +A(0xFC00, CCTRL, TRICORE_FEATURE_131) +A(0xFC04, CCNT, TRICORE_FEATURE_131) +A(0xFC08, ICNT, TRICORE_FEATURE_131) +A(0xFC0C, M1CNT, TRICORE_FEATURE_131) +A(0xFC10, M2CNT, TRICORE_FEATURE_131) +A(0xFC14, M3CNT, TRICORE_FEATURE_131) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index b3fc33ceae..6c07bd7f28 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -17,7 +17,21 @@ /* Arithmetic */ DEF_HELPER_3(add_ssov, i32, env, i32, i32) +DEF_HELPER_3(add_suov, i32, env, i32, i32) DEF_HELPER_3(sub_ssov, i32, env, i32, i32) +DEF_HELPER_3(sub_suov, i32, env, i32, i32) +DEF_HELPER_3(mul_ssov, i32, env, i32, i32) +DEF_HELPER_3(mul_suov, i32, env, i32, i32) +DEF_HELPER_3(sha_ssov, i32, env, i32, i32) +DEF_HELPER_3(absdif_ssov, i32, env, i32, i32) +DEF_HELPER_4(madd32_ssov, i32, env, i32, i32, i32) +DEF_HELPER_4(madd32_suov, i32, env, i32, i32, i32) +DEF_HELPER_4(madd64_ssov, i64, env, i32, i64, i32) +DEF_HELPER_4(madd64_suov, i64, env, i32, i64, i32) +DEF_HELPER_4(msub32_ssov, i32, env, i32, i32, i32) +DEF_HELPER_4(msub32_suov, i32, env, i32, i32, i32) +DEF_HELPER_4(msub64_ssov, i64, env, i32, i64, i32) +DEF_HELPER_4(msub64_suov, i64, env, i32, i64, i32) /* CSA */ DEF_HELPER_2(call, void, env, i32) DEF_HELPER_1(ret, void, env) @@ -30,3 +44,6 @@ DEF_HELPER_2(stucx, void, env, i32) /* Address mode helper */ DEF_HELPER_1(br_update, i32, i32) DEF_HELPER_2(circ_update, i32, i32, i32) +/* PSW cache helper */ +DEF_HELPER_2(psw_write, void, env, i32) +DEF_HELPER_1(psw_read, i32, env) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index a36988aa1b..4da76ff232 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -77,6 +77,27 @@ uint32_t helper_circ_update(uint32_t reg, uint32_t off) env->PSW_USB_SAV |= env->PSW_USB_AV; \ } while (0) +#define SUOV(env, ret, arg, len) do { \ + int64_t max_pos = UINT##len ##_MAX; \ + if (arg > max_pos) { \ + env->PSW_USB_V = (1 << 31); \ + env->PSW_USB_SV = (1 << 31); \ + ret = (target_ulong)max_pos; \ + } else { \ + if (arg < 0) { \ + env->PSW_USB_V = (1 << 31); \ + env->PSW_USB_SV = (1 << 31); \ + ret = 0; \ + } else { \ + env->PSW_USB_V = 0; \ + ret = (target_ulong)arg; \ + } \ + } \ + env->PSW_USB_AV = arg ^ arg * 2u; \ + env->PSW_USB_SAV |= env->PSW_USB_AV; \ +} while (0) + + target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { @@ -88,6 +109,17 @@ target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1, return ret; } +target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2) +{ + target_ulong ret; + int64_t t1 = extract64(r1, 0, 32); + int64_t t2 = extract64(r2, 0, 32); + int64_t result = t1 + t2; + SUOV(env, ret, result, 32); + return ret; +} + target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { @@ -99,6 +131,241 @@ target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1, return ret; } +target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2) +{ + target_ulong ret; + int64_t t1 = extract64(r1, 0, 32); + int64_t t2 = extract64(r2, 0, 32); + int64_t result = t1 - t2; + SUOV(env, ret, result, 32); + return ret; +} + +target_ulong helper_mul_ssov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2) +{ + target_ulong ret; + int64_t t1 = sextract64(r1, 0, 32); + int64_t t2 = sextract64(r2, 0, 32); + int64_t result = t1 * t2; + SSOV(env, ret, result, 32); + return ret; +} + +target_ulong helper_mul_suov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2) +{ + target_ulong ret; + int64_t t1 = extract64(r1, 0, 32); + int64_t t2 = extract64(r2, 0, 32); + int64_t result = t1 * t2; + SUOV(env, ret, result, 32); + return ret; +} + +target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2) +{ + target_ulong ret; + int64_t t1 = sextract64(r1, 0, 32); + int32_t t2 = sextract64(r2, 0, 6); + int64_t result; + if (t2 == 0) { + result = t1; + } else if (t2 > 0) { + result = t1 << t2; + } else { + result = t1 >> -t2; + } + SSOV(env, ret, result, 32); + return ret; +} + +target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2) +{ + target_ulong ret; + int64_t t1 = sextract64(r1, 0, 32); + int64_t t2 = sextract64(r2, 0, 32); + int64_t result; + + if (t1 > t2) { + result = t1 - t2; + } else { + result = t2 - t1; + } + SSOV(env, ret, result, 32); + return ret; +} + +target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2, target_ulong r3) +{ + target_ulong ret; + int64_t t1 = sextract64(r1, 0, 32); + int64_t t2 = sextract64(r2, 0, 32); + int64_t t3 = sextract64(r3, 0, 32); + int64_t result; + + result = t2 + (t1 * t3); + SSOV(env, ret, result, 32); + return ret; +} + +target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2, target_ulong r3) +{ + target_ulong ret; + uint64_t t1 = extract64(r1, 0, 32); + uint64_t t2 = extract64(r2, 0, 32); + uint64_t t3 = extract64(r3, 0, 32); + int64_t result; + + result = t2 + (t1 * t3); + SUOV(env, ret, result, 32); + return ret; +} + +uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1, + uint64_t r2, target_ulong r3) +{ + uint64_t ret, ovf; + int64_t t1 = sextract64(r1, 0, 32); + int64_t t3 = sextract64(r3, 0, 32); + int64_t mul; + + mul = t1 * t3; + ret = mul + r2; + ovf = (ret ^ mul) & ~(mul ^ r2); + + if ((int64_t)ovf < 0) { + env->PSW_USB_V = (1 << 31); + env->PSW_USB_SV = (1 << 31); + /* ext_ret > MAX_INT */ + if (mul >= 0) { + ret = INT64_MAX; + /* ext_ret < MIN_INT */ + } else { + ret = INT64_MIN; + } + } else { + env->PSW_USB_V = 0; + } + t1 = ret >> 32; + env->PSW_USB_AV = t1 ^ t1 * 2u; + env->PSW_USB_SAV |= env->PSW_USB_AV; + + return ret; +} + +uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1, + uint64_t r2, target_ulong r3) +{ + uint64_t ret, mul; + uint64_t t1 = extract64(r1, 0, 32); + uint64_t t3 = extract64(r3, 0, 32); + + mul = t1 * t3; + ret = mul + r2; + + if (ret < r2) { + env->PSW_USB_V = (1 << 31); + env->PSW_USB_SV = (1 << 31); + /* saturate */ + ret = UINT64_MAX; + } else { + env->PSW_USB_V = 0; + } + t1 = ret >> 32; + env->PSW_USB_AV = t1 ^ t1 * 2u; + env->PSW_USB_SAV |= env->PSW_USB_AV; + return ret; +} + +target_ulong helper_msub32_ssov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2, target_ulong r3) +{ + target_ulong ret; + int64_t t1 = sextract64(r1, 0, 32); + int64_t t2 = sextract64(r2, 0, 32); + int64_t t3 = sextract64(r3, 0, 32); + int64_t result; + + result = t2 - (t1 * t3); + SSOV(env, ret, result, 32); + return ret; +} + +target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2, target_ulong r3) +{ + target_ulong ret; + int64_t t1 = extract64(r1, 0, 32); + int64_t t2 = extract64(r2, 0, 32); + int64_t t3 = extract64(r3, 0, 32); + int64_t result; + + result = t2 - (t1 * t3); + SUOV(env, ret, result, 32); + return ret; +} + +uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1, + uint64_t r2, target_ulong r3) +{ + uint64_t ret, ovf; + int64_t t1 = sextract64(r1, 0, 32); + int64_t t3 = sextract64(r3, 0, 32); + int64_t mul; + + mul = t1 * t3; + ret = r2 - mul; + ovf = (ret ^ r2) & (mul ^ r2); + + if ((int64_t)ovf < 0) { + env->PSW_USB_V = (1 << 31); + env->PSW_USB_SV = (1 << 31); + /* ext_ret > MAX_INT */ + if (mul < 0) { + ret = INT64_MAX; + /* ext_ret < MIN_INT */ + } else { + ret = INT64_MIN; + } + } else { + env->PSW_USB_V = 0; + } + t1 = ret >> 32; + env->PSW_USB_AV = t1 ^ t1 * 2u; + env->PSW_USB_SAV |= env->PSW_USB_AV; + return ret; +} + +uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1, + uint64_t r2, target_ulong r3) +{ + uint64_t ret, mul; + uint64_t t1 = extract64(r1, 0, 32); + uint64_t t3 = extract64(r3, 0, 32); + + mul = t1 * t3; + ret = r2 - mul; + + if (ret > r2) { + env->PSW_USB_V = (1 << 31); + env->PSW_USB_SV = (1 << 31); + /* saturate */ + ret = 0; + } else { + env->PSW_USB_V = 0; + } + t1 = ret >> 32; + env->PSW_USB_AV = t1 ^ t1 * 2u; + env->PSW_USB_SAV |= env->PSW_USB_AV; + return ret; +} + /* context save area (CSA) related helpers */ static int cdc_increment(target_ulong *psw) @@ -437,6 +704,17 @@ void helper_stucx(CPUTriCoreState *env, uint32_t ea) save_context_upper(env, ea); } +void helper_psw_write(CPUTriCoreState *env, uint32_t arg) +{ + psw_write(env, arg); +} + +uint32_t helper_psw_read(CPUTriCoreState *env) +{ + return psw_read(env); +} + + static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env, uint32_t exception, int error_code, diff --git a/target-tricore/translate.c b/target-tricore/translate.c index d5a95969bb..65abf453f0 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -233,6 +233,63 @@ static void gen_swap(DisasContext *ctx, int reg, TCGv ea) tcg_temp_free(temp); } +/* We generate loads and store to core special function register (csfr) through + the function gen_mfcr and gen_mtcr. To handle access permissions, we use 3 + makros R, A and E, which allow read-only, all and endinit protected access. + These makros also specify in which ISA version the csfr was introduced. */ +#define R(ADDRESS, REG, FEATURE) \ + case ADDRESS: \ + if (tricore_feature(env, FEATURE)) { \ + tcg_gen_ld_tl(ret, cpu_env, offsetof(CPUTriCoreState, REG)); \ + } \ + break; +#define A(ADDRESS, REG, FEATURE) R(ADDRESS, REG, FEATURE) +#define E(ADDRESS, REG, FEATURE) R(ADDRESS, REG, FEATURE) +static inline void gen_mfcr(CPUTriCoreState *env, TCGv ret, int32_t offset) +{ + /* since we're caching PSW make this a special case */ + if (offset == 0xfe04) { + gen_helper_psw_read(ret, cpu_env); + } else { + switch (offset) { +#include "csfr.def" + } + } +} +#undef R +#undef A +#undef E + +#define R(ADDRESS, REG, FEATURE) /* don't gen writes to read-only reg, + since no execption occurs */ +#define A(ADDRESS, REG, FEATURE) R(ADDRESS, REG, FEATURE) \ + case ADDRESS: \ + if (tricore_feature(env, FEATURE)) { \ + tcg_gen_st_tl(r1, cpu_env, offsetof(CPUTriCoreState, REG)); \ + } \ + break; +/* Endinit protected registers + TODO: Since the endinit bit is in a register of a not yet implemented + watchdog device, we handle endinit protected registers like + all-access registers for now. */ +#define E(ADDRESS, REG, FEATURE) A(ADDRESS, REG, FEATURE) +static inline void gen_mtcr(CPUTriCoreState *env, DisasContext *ctx, TCGv r1, + int32_t offset) +{ + if (ctx->hflags & TRICORE_HFLAG_SM) { + /* since we're caching PSW make this a special case */ + if (offset == 0xfe04) { + gen_helper_psw_write(cpu_env, r1); + } else { + switch (offset) { +#include "csfr.def" + } + } + } else { + /* generate privilege trap */ + } +} + /* Functions for arithmetic instructions */ static inline void gen_add_d(TCGv ret, TCGv r1, TCGv r2) @@ -259,12 +316,337 @@ static inline void gen_add_d(TCGv ret, TCGv r1, TCGv r2) tcg_temp_free(t0); } +/* ret = r2 + (r1 * r3); */ +static inline void gen_madd32_d(TCGv ret, TCGv r1, TCGv r2, TCGv r3) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + tcg_gen_ext_i32_i64(t1, r1); + tcg_gen_ext_i32_i64(t2, r2); + tcg_gen_ext_i32_i64(t3, r3); + + tcg_gen_mul_i64(t1, t1, t3); + tcg_gen_add_i64(t1, t2, t1); + + tcg_gen_trunc_i64_i32(ret, t1); + /* calc V + t1 > 0x7fffffff */ + tcg_gen_setcondi_i64(TCG_COND_GT, t3, t1, 0x7fffffffLL); + /* t1 < -0x80000000 */ + tcg_gen_setcondi_i64(TCG_COND_LT, t2, t1, -0x80000000LL); + tcg_gen_or_i64(t2, t2, t3); + tcg_gen_trunc_i64_i32(cpu_PSW_V, t2); + tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31); + /* Calc SV bit */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* Calc AV/SAV bits */ + tcg_gen_add_tl(cpu_PSW_AV, ret, ret); + tcg_gen_xor_tl(cpu_PSW_AV, ret, cpu_PSW_AV); + /* calc SAV */ + tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); + + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t3); +} + +static inline void gen_maddi32_d(TCGv ret, TCGv r1, TCGv r2, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_madd32_d(ret, r1, r2, temp); + tcg_temp_free(temp); +} + +static inline void +gen_madd64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high, + TCGv r3) +{ + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + TCGv t4 = tcg_temp_new(); + + tcg_gen_muls2_tl(t1, t2, r1, r3); + /* only the add can overflow */ + tcg_gen_add2_tl(t3, t4, r2_low, r2_high, t1, t2); + /* calc V bit */ + tcg_gen_xor_tl(cpu_PSW_V, t4, r2_high); + tcg_gen_xor_tl(t1, r2_high, t2); + tcg_gen_andc_tl(cpu_PSW_V, cpu_PSW_V, t1); + /* Calc SV bit */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* Calc AV/SAV bits */ + tcg_gen_add_tl(cpu_PSW_AV, t4, t4); + tcg_gen_xor_tl(cpu_PSW_AV, t4, cpu_PSW_AV); + /* calc SAV */ + tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); + /* write back the result */ + tcg_gen_mov_tl(ret_low, t3); + tcg_gen_mov_tl(ret_high, t4); + + tcg_temp_free(t1); + tcg_temp_free(t2); + tcg_temp_free(t3); + tcg_temp_free(t4); +} + +static inline void +gen_maddu64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high, + TCGv r3) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + tcg_gen_extu_i32_i64(t1, r1); + tcg_gen_concat_i32_i64(t2, r2_low, r2_high); + tcg_gen_extu_i32_i64(t3, r3); + + tcg_gen_mul_i64(t1, t1, t3); + tcg_gen_add_i64(t2, t2, t1); + /* write back result */ + tcg_gen_extr_i64_i32(ret_low, ret_high, t2); + /* only the add overflows, if t2 < t1 + calc V bit */ + tcg_gen_setcond_i64(TCG_COND_LTU, t2, t2, t1); + tcg_gen_trunc_i64_i32(cpu_PSW_V, t2); + tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31); + /* Calc SV bit */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* Calc AV/SAV bits */ + tcg_gen_add_tl(cpu_PSW_AV, ret_high, ret_high); + tcg_gen_xor_tl(cpu_PSW_AV, ret_high, cpu_PSW_AV); + /* calc SAV */ + tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); + + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t3); +} + +static inline void +gen_maddi64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high, + int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_madd64_d(ret_low, ret_high, r1, r2_low, r2_high, temp); + tcg_temp_free(temp); +} + +static inline void +gen_maddui64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high, + int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_maddu64_d(ret_low, ret_high, r1, r2_low, r2_high, temp); + tcg_temp_free(temp); +} + +/* ret = r2 - (r1 * r3); */ +static inline void gen_msub32_d(TCGv ret, TCGv r1, TCGv r2, TCGv r3) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + tcg_gen_ext_i32_i64(t1, r1); + tcg_gen_ext_i32_i64(t2, r2); + tcg_gen_ext_i32_i64(t3, r3); + + tcg_gen_mul_i64(t1, t1, t3); + tcg_gen_sub_i64(t1, t2, t1); + + tcg_gen_trunc_i64_i32(ret, t1); + /* calc V + t2 > 0x7fffffff */ + tcg_gen_setcondi_i64(TCG_COND_GT, t3, t1, 0x7fffffffLL); + /* result < -0x80000000 */ + tcg_gen_setcondi_i64(TCG_COND_LT, t2, t1, -0x80000000LL); + tcg_gen_or_i64(t2, t2, t3); + tcg_gen_trunc_i64_i32(cpu_PSW_V, t2); + tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31); + + /* Calc SV bit */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* Calc AV/SAV bits */ + tcg_gen_add_tl(cpu_PSW_AV, ret, ret); + tcg_gen_xor_tl(cpu_PSW_AV, ret, cpu_PSW_AV); + /* calc SAV */ + tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); + + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t3); +} + +static inline void gen_msubi32_d(TCGv ret, TCGv r1, TCGv r2, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_msub32_d(ret, r1, r2, temp); + tcg_temp_free(temp); +} + +static inline void +gen_msub64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high, + TCGv r3) +{ + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + TCGv t4 = tcg_temp_new(); + + tcg_gen_muls2_tl(t1, t2, r1, r3); + /* only the sub can overflow */ + tcg_gen_sub2_tl(t3, t4, r2_low, r2_high, t1, t2); + /* calc V bit */ + tcg_gen_xor_tl(cpu_PSW_V, t4, r2_high); + tcg_gen_xor_tl(t1, r2_high, t2); + tcg_gen_and_tl(cpu_PSW_V, cpu_PSW_V, t1); + /* Calc SV bit */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* Calc AV/SAV bits */ + tcg_gen_add_tl(cpu_PSW_AV, t4, t4); + tcg_gen_xor_tl(cpu_PSW_AV, t4, cpu_PSW_AV); + /* calc SAV */ + tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); + /* write back the result */ + tcg_gen_mov_tl(ret_low, t3); + tcg_gen_mov_tl(ret_high, t4); + + tcg_temp_free(t1); + tcg_temp_free(t2); + tcg_temp_free(t3); + tcg_temp_free(t4); +} + +static inline void +gen_msubi64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high, + int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_msub64_d(ret_low, ret_high, r1, r2_low, r2_high, temp); + tcg_temp_free(temp); +} + +static inline void +gen_msubu64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high, + TCGv r3) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + tcg_gen_extu_i32_i64(t1, r1); + tcg_gen_concat_i32_i64(t2, r2_low, r2_high); + tcg_gen_extu_i32_i64(t3, r3); + + tcg_gen_mul_i64(t1, t1, t3); + tcg_gen_sub_i64(t3, t2, t1); + tcg_gen_extr_i64_i32(ret_low, ret_high, t3); + /* calc V bit, only the sub can overflow, if t1 > t2 */ + tcg_gen_setcond_i64(TCG_COND_GTU, t1, t1, t2); + tcg_gen_trunc_i64_i32(cpu_PSW_V, t1); + tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31); + /* Calc SV bit */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* Calc AV/SAV bits */ + tcg_gen_add_tl(cpu_PSW_AV, ret_high, ret_high); + tcg_gen_xor_tl(cpu_PSW_AV, ret_high, cpu_PSW_AV); + /* calc SAV */ + tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); + + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t3); +} + +static inline void +gen_msubui64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high, + int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_msubu64_d(ret_low, ret_high, r1, r2_low, r2_high, temp); + tcg_temp_free(temp); +} + static inline void gen_addi_d(TCGv ret, TCGv r1, target_ulong r2) { TCGv temp = tcg_const_i32(r2); gen_add_d(ret, r1, temp); tcg_temp_free(temp); } +/* calculate the carry bit too */ +static inline void gen_add_CC(TCGv ret, TCGv r1, TCGv r2) +{ + TCGv t0 = tcg_temp_new_i32(); + TCGv result = tcg_temp_new_i32(); + + tcg_gen_movi_tl(t0, 0); + /* Addition and set C/V/SV bits */ + tcg_gen_add2_i32(result, cpu_PSW_C, r1, t0, r2, t0); + /* calc V bit */ + tcg_gen_xor_tl(cpu_PSW_V, result, r1); + tcg_gen_xor_tl(t0, r1, r2); + tcg_gen_andc_tl(cpu_PSW_V, cpu_PSW_V, t0); + /* Calc SV bit */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* Calc AV/SAV bits */ + tcg_gen_add_tl(cpu_PSW_AV, result, result); + tcg_gen_xor_tl(cpu_PSW_AV, result, cpu_PSW_AV); + /* calc SAV */ + tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); + /* write back result */ + tcg_gen_mov_tl(ret, result); + + tcg_temp_free(result); + tcg_temp_free(t0); +} + +static inline void gen_addi_CC(TCGv ret, TCGv r1, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_add_CC(ret, r1, temp); + tcg_temp_free(temp); +} + +static inline void gen_addc_CC(TCGv ret, TCGv r1, TCGv r2) +{ + TCGv carry = tcg_temp_new_i32(); + TCGv t0 = tcg_temp_new_i32(); + TCGv result = tcg_temp_new_i32(); + + tcg_gen_movi_tl(t0, 0); + tcg_gen_setcondi_tl(TCG_COND_NE, carry, cpu_PSW_C, 0); + /* Addition, carry and set C/V/SV bits */ + tcg_gen_add2_i32(result, cpu_PSW_C, r1, t0, carry, t0); + tcg_gen_add2_i32(result, cpu_PSW_C, result, cpu_PSW_C, r2, t0); + /* calc V bit */ + tcg_gen_xor_tl(cpu_PSW_V, result, r1); + tcg_gen_xor_tl(t0, r1, r2); + tcg_gen_andc_tl(cpu_PSW_V, cpu_PSW_V, t0); + /* Calc SV bit */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* Calc AV/SAV bits */ + tcg_gen_add_tl(cpu_PSW_AV, result, result); + tcg_gen_xor_tl(cpu_PSW_AV, result, cpu_PSW_AV); + /* calc SAV */ + tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); + /* write back result */ + tcg_gen_mov_tl(ret, result); + + tcg_temp_free(result); + tcg_temp_free(t0); + tcg_temp_free(carry); +} + +static inline void gen_addci_CC(TCGv ret, TCGv r1, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_addc_CC(ret, r1, temp); + tcg_temp_free(temp); +} static inline void gen_cond_add(TCGCond cond, TCGv r1, TCGv r2, TCGv r3, TCGv r4) @@ -337,6 +719,49 @@ static inline void gen_sub_d(TCGv ret, TCGv r1, TCGv r2) tcg_temp_free(result); } +static inline void gen_absdif(TCGv ret, TCGv r1, TCGv r2) +{ + TCGv temp = tcg_temp_new_i32(); + TCGv result = tcg_temp_new_i32(); + + tcg_gen_sub_tl(result, r1, r2); + tcg_gen_sub_tl(temp, r2, r1); + tcg_gen_movcond_tl(TCG_COND_GT, result, r1, r2, result, temp); + + /* calc V bit */ + tcg_gen_xor_tl(cpu_PSW_V, result, r1); + tcg_gen_xor_tl(temp, result, r2); + tcg_gen_movcond_tl(TCG_COND_GT, cpu_PSW_V, r1, r2, cpu_PSW_V, temp); + tcg_gen_xor_tl(temp, r1, r2); + tcg_gen_and_tl(cpu_PSW_V, cpu_PSW_V, temp); + /* calc SV bit */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* Calc AV bit */ + tcg_gen_add_tl(cpu_PSW_AV, result, result); + tcg_gen_xor_tl(cpu_PSW_AV, result, cpu_PSW_AV); + /* calc SAV bit */ + tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); + /* write back result */ + tcg_gen_mov_tl(ret, result); + + tcg_temp_free(temp); + tcg_temp_free(result); +} + +static inline void gen_absdifi(TCGv ret, TCGv r1, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_absdif(ret, r1, temp); + tcg_temp_free(temp); +} + +static inline void gen_absdifsi(TCGv ret, TCGv r1, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_helper_absdif_ssov(ret, cpu_env, r1, temp); + tcg_temp_free(temp); +} + static inline void gen_mul_i32s(TCGv ret, TCGv r1, TCGv r2) { TCGv high = tcg_temp_new(); @@ -360,6 +785,151 @@ static inline void gen_mul_i32s(TCGv ret, TCGv r1, TCGv r2) tcg_temp_free(low); } +static inline void gen_muli_i32s(TCGv ret, TCGv r1, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_mul_i32s(ret, r1, temp); + tcg_temp_free(temp); +} + +static inline void gen_mul_i64s(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2) +{ + tcg_gen_muls2_tl(ret_low, ret_high, r1, r2); + /* clear V bit */ + tcg_gen_movi_tl(cpu_PSW_V, 0); + /* calc SV bit */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* Calc AV bit */ + tcg_gen_add_tl(cpu_PSW_AV, ret_high, ret_high); + tcg_gen_xor_tl(cpu_PSW_AV, ret_high, cpu_PSW_AV); + /* calc SAV bit */ + tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); +} + +static inline void gen_muli_i64s(TCGv ret_low, TCGv ret_high, TCGv r1, + int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_mul_i64s(ret_low, ret_high, r1, temp); + tcg_temp_free(temp); +} + +static inline void gen_mul_i64u(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2) +{ + tcg_gen_mulu2_tl(ret_low, ret_high, r1, r2); + /* clear V bit */ + tcg_gen_movi_tl(cpu_PSW_V, 0); + /* calc SV bit */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* Calc AV bit */ + tcg_gen_add_tl(cpu_PSW_AV, ret_high, ret_high); + tcg_gen_xor_tl(cpu_PSW_AV, ret_high, cpu_PSW_AV); + /* calc SAV bit */ + tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); +} + +static inline void gen_muli_i64u(TCGv ret_low, TCGv ret_high, TCGv r1, + int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_mul_i64u(ret_low, ret_high, r1, temp); + tcg_temp_free(temp); +} + +static inline void gen_mulsi_i32(TCGv ret, TCGv r1, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_helper_mul_ssov(ret, cpu_env, r1, temp); + tcg_temp_free(temp); +} + +static inline void gen_mulsui_i32(TCGv ret, TCGv r1, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_helper_mul_suov(ret, cpu_env, r1, temp); + tcg_temp_free(temp); +} +/* gen_maddsi_32(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9); */ +static inline void gen_maddsi_32(TCGv ret, TCGv r1, TCGv r2, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_helper_madd32_ssov(ret, cpu_env, r1, r2, temp); + tcg_temp_free(temp); +} + +static inline void gen_maddsui_32(TCGv ret, TCGv r1, TCGv r2, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_helper_madd32_suov(ret, cpu_env, r1, r2, temp); + tcg_temp_free(temp); +} + +static inline void +gen_maddsi_64(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high, + int32_t con) +{ + TCGv temp = tcg_const_i32(con); + TCGv_i64 temp64 = tcg_temp_new_i64(); + tcg_gen_concat_i32_i64(temp64, r2_low, r2_high); + gen_helper_madd64_ssov(temp64, cpu_env, r1, temp64, temp); + tcg_gen_extr_i64_i32(ret_low, ret_high, temp64); + tcg_temp_free(temp); + tcg_temp_free_i64(temp64); +} + +static inline void +gen_maddsui_64(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high, + int32_t con) +{ + TCGv temp = tcg_const_i32(con); + TCGv_i64 temp64 = tcg_temp_new_i64(); + tcg_gen_concat_i32_i64(temp64, r2_low, r2_high); + gen_helper_madd64_suov(temp64, cpu_env, r1, temp64, temp); + tcg_gen_extr_i64_i32(ret_low, ret_high, temp64); + tcg_temp_free(temp); + tcg_temp_free_i64(temp64); +} + +static inline void gen_msubsi_32(TCGv ret, TCGv r1, TCGv r2, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_helper_msub32_ssov(ret, cpu_env, r1, r2, temp); + tcg_temp_free(temp); +} + +static inline void gen_msubsui_32(TCGv ret, TCGv r1, TCGv r2, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_helper_msub32_suov(ret, cpu_env, r1, r2, temp); + tcg_temp_free(temp); +} + +static inline void +gen_msubsi_64(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high, + int32_t con) +{ + TCGv temp = tcg_const_i32(con); + TCGv_i64 temp64 = tcg_temp_new_i64(); + tcg_gen_concat_i32_i64(temp64, r2_low, r2_high); + gen_helper_msub64_ssov(temp64, cpu_env, r1, temp64, temp); + tcg_gen_extr_i64_i32(ret_low, ret_high, temp64); + tcg_temp_free(temp); + tcg_temp_free_i64(temp64); +} + +static inline void +gen_msubsui_64(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high, + int32_t con) +{ + TCGv temp = tcg_const_i32(con); + TCGv_i64 temp64 = tcg_temp_new_i64(); + tcg_gen_concat_i32_i64(temp64, r2_low, r2_high); + gen_helper_msub64_suov(temp64, cpu_env, r1, temp64, temp); + tcg_gen_extr_i64_i32(ret_low, ret_high, temp64); + tcg_temp_free(temp); + tcg_temp_free_i64(temp64); +} + static void gen_saturate(TCGv ret, TCGv arg, int32_t up, int32_t low) { TCGv sat_neg = tcg_const_i32(low); @@ -394,6 +964,27 @@ static void gen_shi(TCGv ret, TCGv r1, int32_t shift_count) } } +static void gen_sh_hi(TCGv ret, TCGv r1, int32_t shiftcount) +{ + TCGv temp_low, temp_high; + + if (shiftcount == -16) { + tcg_gen_movi_tl(ret, 0); + } else { + temp_high = tcg_temp_new(); + temp_low = tcg_temp_new(); + + tcg_gen_andi_tl(temp_low, r1, 0xffff); + tcg_gen_andi_tl(temp_high, r1, 0xffff0000); + gen_shi(temp_low, temp_low, shiftcount); + gen_shi(ret, temp_high, shiftcount); + tcg_gen_deposit_tl(ret, ret, temp_low, 0, 16); + + tcg_temp_free(temp_low); + tcg_temp_free(temp_high); + } +} + static void gen_shaci(TCGv ret, TCGv r1, int32_t shift_count) { uint32_t msk, msk_start; @@ -453,16 +1044,100 @@ static void gen_shaci(TCGv ret, TCGv r1, int32_t shift_count) tcg_temp_free(t_0); } +static void gen_shas(TCGv ret, TCGv r1, TCGv r2) +{ + gen_helper_sha_ssov(ret, cpu_env, r1, r2); +} + +static void gen_shasi(TCGv ret, TCGv r1, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_shas(ret, r1, temp); + tcg_temp_free(temp); +} + +static void gen_sha_hi(TCGv ret, TCGv r1, int32_t shift_count) +{ + TCGv low, high; + + if (shift_count == 0) { + tcg_gen_mov_tl(ret, r1); + } else if (shift_count > 0) { + low = tcg_temp_new(); + high = tcg_temp_new(); + + tcg_gen_andi_tl(high, r1, 0xffff0000); + tcg_gen_shli_tl(low, r1, shift_count); + tcg_gen_shli_tl(ret, high, shift_count); + tcg_gen_deposit_tl(ret, ret, low, 0, 16); + + tcg_temp_free(low); + tcg_temp_free(high); + } else { + low = tcg_temp_new(); + high = tcg_temp_new(); + + tcg_gen_ext16s_tl(low, r1); + tcg_gen_sari_tl(low, low, -shift_count); + tcg_gen_sari_tl(ret, r1, -shift_count); + tcg_gen_deposit_tl(ret, ret, low, 0, 16); + + tcg_temp_free(low); + tcg_temp_free(high); + } + +} + +/* ret = {ret[30:0], (r1 cond r2)}; */ +static void gen_sh_cond(int cond, TCGv ret, TCGv r1, TCGv r2) +{ + TCGv temp = tcg_temp_new(); + TCGv temp2 = tcg_temp_new(); + + tcg_gen_shli_tl(temp, ret, 1); + tcg_gen_setcond_tl(cond, temp2, r1, r2); + tcg_gen_or_tl(ret, temp, temp2); + + tcg_temp_free(temp); + tcg_temp_free(temp2); +} + +static void gen_sh_condi(int cond, TCGv ret, TCGv r1, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_sh_cond(cond, ret, r1, temp); + tcg_temp_free(temp); +} + static inline void gen_adds(TCGv ret, TCGv r1, TCGv r2) { gen_helper_add_ssov(ret, cpu_env, r1, r2); } +static inline void gen_addsi(TCGv ret, TCGv r1, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_helper_add_ssov(ret, cpu_env, r1, temp); + tcg_temp_free(temp); +} + +static inline void gen_addsui(TCGv ret, TCGv r1, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + gen_helper_add_suov(ret, cpu_env, r1, temp); + tcg_temp_free(temp); +} + static inline void gen_subs(TCGv ret, TCGv r1, TCGv r2) { gen_helper_sub_ssov(ret, cpu_env, r1, r2); } +static inline void gen_subsu(TCGv ret, TCGv r1, TCGv r2) +{ + gen_helper_sub_suov(ret, cpu_env, r1, r2); +} + static inline void gen_bit_2op(TCGv ret, TCGv r1, TCGv r2, int pos1, int pos2, void(*op1)(TCGv, TCGv, TCGv), @@ -506,6 +1181,109 @@ static inline void gen_bit_1op(TCGv ret, TCGv r1, TCGv r2, tcg_temp_free(temp2); } +static inline void gen_accumulating_cond(int cond, TCGv ret, TCGv r1, TCGv r2, + void(*op)(TCGv, TCGv, TCGv)) +{ + TCGv temp = tcg_temp_new(); + TCGv temp2 = tcg_temp_new(); + /* temp = (arg1 cond arg2 )*/ + tcg_gen_setcond_tl(cond, temp, r1, r2); + /* temp2 = ret[0]*/ + tcg_gen_andi_tl(temp2, ret, 0x1); + /* temp = temp insn temp2 */ + (*op)(temp, temp, temp2); + /* ret = {ret[31:1], temp} */ + tcg_gen_deposit_tl(ret, ret, temp, 0, 1); + + tcg_temp_free(temp); + tcg_temp_free(temp2); +} + +static inline void +gen_accumulating_condi(int cond, TCGv ret, TCGv r1, int32_t con, + void(*op)(TCGv, TCGv, TCGv)) +{ + TCGv temp = tcg_const_i32(con); + gen_accumulating_cond(cond, ret, r1, temp, op); + tcg_temp_free(temp); +} + +static inline void gen_eqany_bi(TCGv ret, TCGv r1, int32_t con) +{ + TCGv b0 = tcg_temp_new(); + TCGv b1 = tcg_temp_new(); + TCGv b2 = tcg_temp_new(); + TCGv b3 = tcg_temp_new(); + + /* byte 0 */ + tcg_gen_andi_tl(b0, r1, 0xff); + tcg_gen_setcondi_tl(TCG_COND_EQ, b0, b0, con & 0xff); + + /* byte 1 */ + tcg_gen_andi_tl(b1, r1, 0xff00); + tcg_gen_setcondi_tl(TCG_COND_EQ, b1, b1, con & 0xff00); + + /* byte 2 */ + tcg_gen_andi_tl(b2, r1, 0xff0000); + tcg_gen_setcondi_tl(TCG_COND_EQ, b2, b2, con & 0xff0000); + + /* byte 3 */ + tcg_gen_andi_tl(b3, r1, 0xff000000); + tcg_gen_setcondi_tl(TCG_COND_EQ, b3, b3, con & 0xff000000); + + /* combine them */ + tcg_gen_or_tl(ret, b0, b1); + tcg_gen_or_tl(ret, ret, b2); + tcg_gen_or_tl(ret, ret, b3); + + tcg_temp_free(b0); + tcg_temp_free(b1); + tcg_temp_free(b2); + tcg_temp_free(b3); +} + +static inline void gen_eqany_hi(TCGv ret, TCGv r1, int32_t con) +{ + TCGv h0 = tcg_temp_new(); + TCGv h1 = tcg_temp_new(); + + /* halfword 0 */ + tcg_gen_andi_tl(h0, r1, 0xffff); + tcg_gen_setcondi_tl(TCG_COND_EQ, h0, h0, con & 0xffff); + + /* halfword 1 */ + tcg_gen_andi_tl(h1, r1, 0xffff0000); + tcg_gen_setcondi_tl(TCG_COND_EQ, h1, h1, con & 0xffff0000); + + /* combine them */ + tcg_gen_or_tl(ret, h0, h1); + + tcg_temp_free(h0); + tcg_temp_free(h1); +} +/* mask = ((1 << width) -1) << pos; + ret = (r1 & ~mask) | (r2 << pos) & mask); */ +static inline void gen_insert(TCGv ret, TCGv r1, TCGv r2, TCGv width, TCGv pos) +{ + TCGv mask = tcg_temp_new(); + TCGv temp = tcg_temp_new(); + TCGv temp2 = tcg_temp_new(); + + tcg_gen_movi_tl(mask, 1); + tcg_gen_shl_tl(mask, mask, width); + tcg_gen_subi_tl(mask, mask, 1); + tcg_gen_shl_tl(mask, mask, pos); + + tcg_gen_shl_tl(temp, r2, pos); + tcg_gen_and_tl(temp, temp, mask); + tcg_gen_andc_tl(temp2, r1, mask); + tcg_gen_or_tl(ret, temp, temp2); + + tcg_temp_free(mask); + tcg_temp_free(temp); + tcg_temp_free(temp2); +} + /* helpers for generating program flow micro-ops */ static inline void gen_save_pc(target_ulong pc) @@ -567,7 +1345,8 @@ static void gen_loop(DisasContext *ctx, int r1, int32_t offset) static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1, int r2 , int32_t constant , int32_t offset) { - TCGv temp; + TCGv temp, temp2; + int n; switch (opc) { /* SB-format jumps */ @@ -665,6 +1444,134 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1, tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc); gen_goto_tb(ctx, 0, ctx->pc + offset * 2); break; +/* BOL format */ + case OPCM_32_BRC_EQ_NEQ: + if (MASK_OP_BRC_OP2(ctx->opcode) == OPC2_32_BRC_JEQ) { + gen_branch_condi(ctx, TCG_COND_EQ, cpu_gpr_d[r1], constant, offset); + } else { + gen_branch_condi(ctx, TCG_COND_NE, cpu_gpr_d[r1], constant, offset); + } + break; + case OPCM_32_BRC_GE: + if (MASK_OP_BRC_OP2(ctx->opcode) == OP2_32_BRC_JGE) { + gen_branch_condi(ctx, TCG_COND_GE, cpu_gpr_d[r1], constant, offset); + } else { + constant = MASK_OP_BRC_CONST4(ctx->opcode); + gen_branch_condi(ctx, TCG_COND_GEU, cpu_gpr_d[r1], constant, + offset); + } + break; + case OPCM_32_BRC_JLT: + if (MASK_OP_BRC_OP2(ctx->opcode) == OPC2_32_BRC_JLT) { + gen_branch_condi(ctx, TCG_COND_LT, cpu_gpr_d[r1], constant, offset); + } else { + constant = MASK_OP_BRC_CONST4(ctx->opcode); + gen_branch_condi(ctx, TCG_COND_LTU, cpu_gpr_d[r1], constant, + offset); + } + break; + case OPCM_32_BRC_JNE: + temp = tcg_temp_new(); + if (MASK_OP_BRC_OP2(ctx->opcode) == OPC2_32_BRC_JNED) { + tcg_gen_mov_tl(temp, cpu_gpr_d[r1]); + /* subi is unconditional */ + tcg_gen_subi_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], 1); + gen_branch_condi(ctx, TCG_COND_NE, temp, constant, offset); + } else { + tcg_gen_mov_tl(temp, cpu_gpr_d[r1]); + /* addi is unconditional */ + tcg_gen_addi_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], 1); + gen_branch_condi(ctx, TCG_COND_NE, temp, constant, offset); + } + tcg_temp_free(temp); + break; +/* BRN format */ + case OPCM_32_BRN_JTT: + n = MASK_OP_BRN_N(ctx->opcode); + + temp = tcg_temp_new(); + tcg_gen_andi_tl(temp, cpu_gpr_d[r1], (1 << n)); + + if (MASK_OP_BRN_OP2(ctx->opcode) == OPC2_32_BRN_JNZ_T) { + gen_branch_condi(ctx, TCG_COND_NE, temp, 0, offset); + } else { + gen_branch_condi(ctx, TCG_COND_EQ, temp, 0, offset); + } + tcg_temp_free(temp); + break; +/* BRR Format */ + case OPCM_32_BRR_EQ_NEQ: + if (MASK_OP_BRR_OP2(ctx->opcode) == OPC2_32_BRR_JEQ) { + gen_branch_cond(ctx, TCG_COND_EQ, cpu_gpr_d[r1], cpu_gpr_d[r2], + offset); + } else { + gen_branch_cond(ctx, TCG_COND_NE, cpu_gpr_d[r1], cpu_gpr_d[r2], + offset); + } + break; + case OPCM_32_BRR_ADDR_EQ_NEQ: + if (MASK_OP_BRR_OP2(ctx->opcode) == OPC2_32_BRR_JEQ_A) { + gen_branch_cond(ctx, TCG_COND_EQ, cpu_gpr_a[r1], cpu_gpr_a[r2], + offset); + } else { + gen_branch_cond(ctx, TCG_COND_NE, cpu_gpr_a[r1], cpu_gpr_a[r2], + offset); + } + break; + case OPCM_32_BRR_GE: + if (MASK_OP_BRR_OP2(ctx->opcode) == OPC2_32_BRR_JGE) { + gen_branch_cond(ctx, TCG_COND_GE, cpu_gpr_d[r1], cpu_gpr_d[r2], + offset); + } else { + gen_branch_cond(ctx, TCG_COND_GEU, cpu_gpr_d[r1], cpu_gpr_d[r2], + offset); + } + break; + case OPCM_32_BRR_JLT: + if (MASK_OP_BRR_OP2(ctx->opcode) == OPC2_32_BRR_JLT) { + gen_branch_cond(ctx, TCG_COND_LT, cpu_gpr_d[r1], cpu_gpr_d[r2], + offset); + } else { + gen_branch_cond(ctx, TCG_COND_LTU, cpu_gpr_d[r1], cpu_gpr_d[r2], + offset); + } + break; + case OPCM_32_BRR_LOOP: + if (MASK_OP_BRR_OP2(ctx->opcode) == OPC2_32_BRR_LOOP) { + gen_loop(ctx, r1, offset * 2); + } else { + /* OPC2_32_BRR_LOOPU */ + gen_goto_tb(ctx, 0, ctx->pc + offset * 2); + } + break; + case OPCM_32_BRR_JNE: + temp = tcg_temp_new(); + temp2 = tcg_temp_new(); + if (MASK_OP_BRC_OP2(ctx->opcode) == OPC2_32_BRR_JNED) { + tcg_gen_mov_tl(temp, cpu_gpr_d[r1]); + /* also save r2, in case of r1 == r2, so r2 is not decremented */ + tcg_gen_mov_tl(temp2, cpu_gpr_d[r2]); + /* subi is unconditional */ + tcg_gen_subi_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], 1); + gen_branch_cond(ctx, TCG_COND_NE, temp, temp2, offset); + } else { + tcg_gen_mov_tl(temp, cpu_gpr_d[r1]); + /* also save r2, in case of r1 == r2, so r2 is not decremented */ + tcg_gen_mov_tl(temp2, cpu_gpr_d[r2]); + /* addi is unconditional */ + tcg_gen_addi_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], 1); + gen_branch_cond(ctx, TCG_COND_NE, temp, temp2, offset); + } + tcg_temp_free(temp); + tcg_temp_free(temp2); + break; + case OPCM_32_BRR_JNZ: + if (MASK_OP_BRR_OP2(ctx->opcode) == OPC2_32_BRR_JNZ_A) { + gen_branch_condi(ctx, TCG_COND_NE, cpu_gpr_a[r1], 0, offset); + } else { + gen_branch_condi(ctx, TCG_COND_EQ, cpu_gpr_a[r1], 0, offset); + } + break; default: printf("Branch Error at %x\n", ctx->pc); } @@ -1712,17 +2619,17 @@ static void decode_bo_addrmode_post_pre_base(CPUTriCoreState *env, case OPC2_32_BO_CACHEI_WI_SHORTOFF: case OPC2_32_BO_CACHEI_W_SHORTOFF: /* TODO: Raise illegal opcode trap, - if tricore_feature(TRICORE_FEATURE_13) */ + if !tricore_feature(TRICORE_FEATURE_131) */ break; case OPC2_32_BO_CACHEI_W_POSTINC: case OPC2_32_BO_CACHEI_WI_POSTINC: - if (!tricore_feature(env, TRICORE_FEATURE_13)) { + if (tricore_feature(env, TRICORE_FEATURE_131)) { tcg_gen_addi_tl(cpu_gpr_d[r2], cpu_gpr_d[r2], off10); } /* TODO: else raise illegal opcode trap */ break; case OPC2_32_BO_CACHEI_W_PREINC: case OPC2_32_BO_CACHEI_WI_PREINC: - if (!tricore_feature(env, TRICORE_FEATURE_13)) { + if (tricore_feature(env, TRICORE_FEATURE_131)) { tcg_gen_addi_tl(cpu_gpr_d[r2], cpu_gpr_d[r2], off10); } /* TODO: else raise illegal opcode trap */ break; @@ -2279,17 +3186,633 @@ static void decode_bo_addrmode_ldmst_bitreverse_circular(CPUTriCoreState *env, tcg_temp_free(temp3); } +static void decode_bol_opc(CPUTriCoreState *env, DisasContext *ctx, int32_t op1) +{ + int r1, r2; + int32_t address; + TCGv temp; + + r1 = MASK_OP_BOL_S1D(ctx->opcode); + r2 = MASK_OP_BOL_S2(ctx->opcode); + address = MASK_OP_BOL_OFF16_SEXT(ctx->opcode); + + switch (op1) { + case OPC1_32_BOL_LD_A_LONGOFF: + temp = tcg_temp_new(); + tcg_gen_addi_tl(temp, cpu_gpr_a[r2], address); + tcg_gen_qemu_ld_tl(cpu_gpr_a[r1], temp, ctx->mem_idx, MO_LEUL); + tcg_temp_free(temp); + break; + case OPC1_32_BOL_LD_W_LONFOFF: + temp = tcg_temp_new(); + tcg_gen_addi_tl(temp, cpu_gpr_a[r2], address); + tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LEUL); + tcg_temp_free(temp); + break; + case OPC1_32_BOL_LEA_LONGOFF: + tcg_gen_addi_tl(cpu_gpr_a[r1], cpu_gpr_a[r2], address); + break; + case OPC1_32_BOL_ST_A_LONGOFF: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + gen_offset_st(ctx, cpu_gpr_a[r1], cpu_gpr_a[r2], address, MO_LEUL); + } else { + /* raise illegal opcode trap */ + } + break; + case OPC1_32_BOL_ST_W_LONGOFF: + gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUL); + break; + } + +} + +/* RC format */ +static void decode_rc_logical_shift(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + int r1, r2; + int32_t const9; + TCGv temp; + + r2 = MASK_OP_RC_D(ctx->opcode); + r1 = MASK_OP_RC_S1(ctx->opcode); + const9 = MASK_OP_RC_CONST9(ctx->opcode); + op2 = MASK_OP_RC_OP2(ctx->opcode); + + temp = tcg_temp_new(); + + switch (op2) { + case OPC2_32_RC_AND: + tcg_gen_andi_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_ANDN: + tcg_gen_andi_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], ~const9); + break; + case OPC2_32_RC_NAND: + tcg_gen_movi_tl(temp, const9); + tcg_gen_nand_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], temp); + break; + case OPC2_32_RC_NOR: + tcg_gen_movi_tl(temp, const9); + tcg_gen_nor_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], temp); + break; + case OPC2_32_RC_OR: + tcg_gen_ori_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_ORN: + tcg_gen_ori_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], ~const9); + break; + case OPC2_32_RC_SH: + const9 = sextract32(const9, 0, 6); + gen_shi(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_SH_H: + const9 = sextract32(const9, 0, 5); + gen_sh_hi(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_SHA: + const9 = sextract32(const9, 0, 6); + gen_shaci(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_SHA_H: + const9 = sextract32(const9, 0, 5); + gen_sha_hi(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_SHAS: + gen_shasi(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_XNOR: + tcg_gen_xori_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + tcg_gen_not_tl(cpu_gpr_d[r2], cpu_gpr_d[r2]); + break; + case OPC2_32_RC_XOR: + tcg_gen_xori_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + } + tcg_temp_free(temp); +} + +static void decode_rc_accumulator(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + int r1, r2; + int16_t const9; + + TCGv temp; + + r2 = MASK_OP_RC_D(ctx->opcode); + r1 = MASK_OP_RC_S1(ctx->opcode); + const9 = MASK_OP_RC_CONST9_SEXT(ctx->opcode); + + op2 = MASK_OP_RC_OP2(ctx->opcode); + + temp = tcg_temp_new(); + + switch (op2) { + case OPC2_32_RC_ABSDIF: + gen_absdifi(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_ABSDIFS: + gen_absdifsi(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_ADD: + gen_addi_d(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_ADDC: + gen_addci_CC(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_ADDS: + gen_addsi(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_ADDS_U: + gen_addsui(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_ADDX: + gen_addi_CC(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_AND_EQ: + gen_accumulating_condi(TCG_COND_EQ, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_and_tl); + break; + case OPC2_32_RC_AND_GE: + gen_accumulating_condi(TCG_COND_GE, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_and_tl); + break; + case OPC2_32_RC_AND_GE_U: + const9 = MASK_OP_RC_CONST9(ctx->opcode); + gen_accumulating_condi(TCG_COND_GEU, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_and_tl); + break; + case OPC2_32_RC_AND_LT: + gen_accumulating_condi(TCG_COND_LT, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_and_tl); + break; + case OPC2_32_RC_AND_LT_U: + const9 = MASK_OP_RC_CONST9(ctx->opcode); + gen_accumulating_condi(TCG_COND_LTU, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_and_tl); + break; + case OPC2_32_RC_AND_NE: + gen_accumulating_condi(TCG_COND_NE, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_and_tl); + break; + case OPC2_32_RC_EQ: + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_EQANY_B: + gen_eqany_bi(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_EQANY_H: + gen_eqany_hi(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_GE: + tcg_gen_setcondi_tl(TCG_COND_GE, cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_GE_U: + const9 = MASK_OP_RC_CONST9(ctx->opcode); + tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_LT: + tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_LT_U: + const9 = MASK_OP_RC_CONST9(ctx->opcode); + tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_MAX: + tcg_gen_movi_tl(temp, const9); + tcg_gen_movcond_tl(TCG_COND_GT, cpu_gpr_d[r2], cpu_gpr_d[r1], temp, + cpu_gpr_d[r1], temp); + break; + case OPC2_32_RC_MAX_U: + tcg_gen_movi_tl(temp, MASK_OP_RC_CONST9(ctx->opcode)); + tcg_gen_movcond_tl(TCG_COND_GTU, cpu_gpr_d[r2], cpu_gpr_d[r1], temp, + cpu_gpr_d[r1], temp); + break; + case OPC2_32_RC_MIN: + tcg_gen_movi_tl(temp, const9); + tcg_gen_movcond_tl(TCG_COND_LT, cpu_gpr_d[r2], cpu_gpr_d[r1], temp, + cpu_gpr_d[r1], temp); + break; + case OPC2_32_RC_MIN_U: + tcg_gen_movi_tl(temp, MASK_OP_RC_CONST9(ctx->opcode)); + tcg_gen_movcond_tl(TCG_COND_LTU, cpu_gpr_d[r2], cpu_gpr_d[r1], temp, + cpu_gpr_d[r1], temp); + break; + case OPC2_32_RC_NE: + tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_OR_EQ: + gen_accumulating_condi(TCG_COND_EQ, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_or_tl); + break; + case OPC2_32_RC_OR_GE: + gen_accumulating_condi(TCG_COND_GE, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_or_tl); + break; + case OPC2_32_RC_OR_GE_U: + const9 = MASK_OP_RC_CONST9(ctx->opcode); + gen_accumulating_condi(TCG_COND_GEU, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_or_tl); + break; + case OPC2_32_RC_OR_LT: + gen_accumulating_condi(TCG_COND_LT, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_or_tl); + break; + case OPC2_32_RC_OR_LT_U: + const9 = MASK_OP_RC_CONST9(ctx->opcode); + gen_accumulating_condi(TCG_COND_LTU, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_or_tl); + break; + case OPC2_32_RC_OR_NE: + gen_accumulating_condi(TCG_COND_NE, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_or_tl); + break; + case OPC2_32_RC_RSUB: + tcg_gen_movi_tl(temp, const9); + gen_sub_d(cpu_gpr_d[r2], temp, cpu_gpr_d[r1]); + break; + case OPC2_32_RC_RSUBS: + tcg_gen_movi_tl(temp, const9); + gen_subs(cpu_gpr_d[r2], temp, cpu_gpr_d[r1]); + break; + case OPC2_32_RC_RSUBS_U: + tcg_gen_movi_tl(temp, const9); + gen_subsu(cpu_gpr_d[r2], temp, cpu_gpr_d[r1]); + break; + case OPC2_32_RC_SH_EQ: + gen_sh_condi(TCG_COND_EQ, cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_SH_GE: + gen_sh_condi(TCG_COND_GE, cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_SH_GE_U: + const9 = MASK_OP_RC_CONST9(ctx->opcode); + gen_sh_condi(TCG_COND_GEU, cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_SH_LT: + gen_sh_condi(TCG_COND_LT, cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_SH_LT_U: + const9 = MASK_OP_RC_CONST9(ctx->opcode); + gen_sh_condi(TCG_COND_LTU, cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_SH_NE: + gen_sh_condi(TCG_COND_NE, cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_XOR_EQ: + gen_accumulating_condi(TCG_COND_EQ, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_xor_tl); + break; + case OPC2_32_RC_XOR_GE: + gen_accumulating_condi(TCG_COND_GE, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_xor_tl); + break; + case OPC2_32_RC_XOR_GE_U: + const9 = MASK_OP_RC_CONST9(ctx->opcode); + gen_accumulating_condi(TCG_COND_GEU, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_xor_tl); + break; + case OPC2_32_RC_XOR_LT: + gen_accumulating_condi(TCG_COND_LT, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_xor_tl); + break; + case OPC2_32_RC_XOR_LT_U: + const9 = MASK_OP_RC_CONST9(ctx->opcode); + gen_accumulating_condi(TCG_COND_LTU, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_xor_tl); + break; + case OPC2_32_RC_XOR_NE: + gen_accumulating_condi(TCG_COND_NE, cpu_gpr_d[r2], cpu_gpr_d[r1], + const9, &tcg_gen_xor_tl); + break; + } + tcg_temp_free(temp); +} + +static void decode_rc_serviceroutine(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + uint32_t const9; + + op2 = MASK_OP_RC_OP2(ctx->opcode); + const9 = MASK_OP_RC_CONST9(ctx->opcode); + + switch (op2) { + case OPC2_32_RC_BISR: + gen_helper_1arg(bisr, const9); + break; + case OPC2_32_RC_SYSCALL: + /* TODO: Add exception generation */ + break; + } +} + +static void decode_rc_mul(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + int r1, r2; + int16_t const9; + + r2 = MASK_OP_RC_D(ctx->opcode); + r1 = MASK_OP_RC_S1(ctx->opcode); + const9 = MASK_OP_RC_CONST9_SEXT(ctx->opcode); + + op2 = MASK_OP_RC_OP2(ctx->opcode); + + switch (op2) { + case OPC2_32_RC_MUL_32: + gen_muli_i32s(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_MUL_64: + gen_muli_i64s(cpu_gpr_d[r2], cpu_gpr_d[r2+1], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_MULS_32: + gen_mulsi_i32(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_MUL_U_64: + const9 = MASK_OP_RC_CONST9(ctx->opcode); + gen_muli_i64u(cpu_gpr_d[r2], cpu_gpr_d[r2+1], cpu_gpr_d[r1], const9); + break; + case OPC2_32_RC_MULS_U_32: + const9 = MASK_OP_RC_CONST9(ctx->opcode); + gen_mulsui_i32(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); + break; + } +} + +/* RCPW format */ +static void decode_rcpw_insert(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + int r1, r2; + int32_t pos, width, const4; + + TCGv temp; + + op2 = MASK_OP_RCPW_OP2(ctx->opcode); + r1 = MASK_OP_RCPW_S1(ctx->opcode); + r2 = MASK_OP_RCPW_D(ctx->opcode); + const4 = MASK_OP_RCPW_CONST4(ctx->opcode); + width = MASK_OP_RCPW_WIDTH(ctx->opcode); + pos = MASK_OP_RCPW_POS(ctx->opcode); + + switch (op2) { + case OPC2_32_RCPW_IMASK: + /* if pos + width > 31 undefined result */ + if (pos + width <= 31) { + tcg_gen_movi_tl(cpu_gpr_d[r2+1], ((1u << width) - 1) << pos); + tcg_gen_movi_tl(cpu_gpr_d[r2], (const4 << pos)); + } + break; + case OPC2_32_RCPW_INSERT: + /* if pos + width > 32 undefined result */ + if (pos + width <= 32) { + temp = tcg_const_i32(const4); + tcg_gen_deposit_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], temp, pos, width); + tcg_temp_free(temp); + } + break; + } +} + +/* RCRW format */ + +static void decode_rcrw_insert(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + int r1, r3, r4; + int32_t width, const4; + + TCGv temp, temp2, temp3; + + op2 = MASK_OP_RCRW_OP2(ctx->opcode); + r1 = MASK_OP_RCRW_S1(ctx->opcode); + r3 = MASK_OP_RCRW_S3(ctx->opcode); + r4 = MASK_OP_RCRW_D(ctx->opcode); + width = MASK_OP_RCRW_WIDTH(ctx->opcode); + const4 = MASK_OP_RCRW_CONST4(ctx->opcode); + + temp = tcg_temp_new(); + temp2 = tcg_temp_new(); + + switch (op2) { + case OPC2_32_RCRW_IMASK: + tcg_gen_andi_tl(temp, cpu_gpr_d[r4], 0x1f); + tcg_gen_movi_tl(temp2, (1 << width) - 1); + tcg_gen_shl_tl(cpu_gpr_d[r3 + 1], temp2, temp); + tcg_gen_movi_tl(temp2, const4); + tcg_gen_shl_tl(cpu_gpr_d[r3], temp2, temp); + break; + case OPC2_32_RCRW_INSERT: + temp3 = tcg_temp_new(); + + tcg_gen_movi_tl(temp, width); + tcg_gen_movi_tl(temp2, const4); + tcg_gen_andi_tl(temp3, cpu_gpr_d[r4], 0x1f); + gen_insert(cpu_gpr_d[r3], cpu_gpr_d[r1], temp2, temp, temp3); + + tcg_temp_free(temp3); + break; + } + tcg_temp_free(temp); + tcg_temp_free(temp2); +} + +/* RCR format */ + +static void decode_rcr_cond_select(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + int r1, r3, r4; + int32_t const9; + + TCGv temp, temp2; + + op2 = MASK_OP_RCR_OP2(ctx->opcode); + r1 = MASK_OP_RCR_S1(ctx->opcode); + const9 = MASK_OP_RCR_CONST9_SEXT(ctx->opcode); + r3 = MASK_OP_RCR_S3(ctx->opcode); + r4 = MASK_OP_RCR_D(ctx->opcode); + + switch (op2) { + case OPC2_32_RCR_CADD: + gen_condi_add(TCG_COND_NE, cpu_gpr_d[r1], const9, cpu_gpr_d[r3], + cpu_gpr_d[r4]); + break; + case OPC2_32_RCR_CADDN: + gen_condi_add(TCG_COND_EQ, cpu_gpr_d[r1], const9, cpu_gpr_d[r3], + cpu_gpr_d[r4]); + break; + case OPC2_32_RCR_SEL: + temp = tcg_const_i32(0); + temp2 = tcg_const_i32(const9); + tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r4], temp, + cpu_gpr_d[r1], temp2); + tcg_temp_free(temp); + tcg_temp_free(temp2); + break; + case OPC2_32_RCR_SELN: + temp = tcg_const_i32(0); + temp2 = tcg_const_i32(const9); + tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r4], temp, + cpu_gpr_d[r1], temp2); + tcg_temp_free(temp); + tcg_temp_free(temp2); + break; + } +} + +static void decode_rcr_madd(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + int r1, r3, r4; + int32_t const9; + + + op2 = MASK_OP_RCR_OP2(ctx->opcode); + r1 = MASK_OP_RCR_S1(ctx->opcode); + const9 = MASK_OP_RCR_CONST9_SEXT(ctx->opcode); + r3 = MASK_OP_RCR_S3(ctx->opcode); + r4 = MASK_OP_RCR_D(ctx->opcode); + + switch (op2) { + case OPC2_32_RCR_MADD_32: + gen_maddi32_d(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9); + break; + case OPC2_32_RCR_MADD_64: + gen_maddi64_d(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1], + cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9); + break; + case OPC2_32_RCR_MADDS_32: + gen_maddsi_32(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9); + break; + case OPC2_32_RCR_MADDS_64: + gen_maddsi_64(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1], + cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9); + break; + case OPC2_32_RCR_MADD_U_64: + const9 = MASK_OP_RCR_CONST9(ctx->opcode); + gen_maddui64_d(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1], + cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9); + break; + case OPC2_32_RCR_MADDS_U_32: + const9 = MASK_OP_RCR_CONST9(ctx->opcode); + gen_maddsui_32(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9); + break; + case OPC2_32_RCR_MADDS_U_64: + const9 = MASK_OP_RCR_CONST9(ctx->opcode); + gen_maddsui_64(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1], + cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9); + break; + } +} + +static void decode_rcr_msub(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + int r1, r3, r4; + int32_t const9; + + + op2 = MASK_OP_RCR_OP2(ctx->opcode); + r1 = MASK_OP_RCR_S1(ctx->opcode); + const9 = MASK_OP_RCR_CONST9_SEXT(ctx->opcode); + r3 = MASK_OP_RCR_S3(ctx->opcode); + r4 = MASK_OP_RCR_D(ctx->opcode); + + switch (op2) { + case OPC2_32_RCR_MSUB_32: + gen_msubi32_d(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9); + break; + case OPC2_32_RCR_MSUB_64: + gen_msubi64_d(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1], + cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9); + break; + case OPC2_32_RCR_MSUBS_32: + gen_msubsi_32(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9); + break; + case OPC2_32_RCR_MSUBS_64: + gen_msubsi_64(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1], + cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9); + break; + case OPC2_32_RCR_MSUB_U_64: + const9 = MASK_OP_RCR_CONST9(ctx->opcode); + gen_msubui64_d(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1], + cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9); + break; + case OPC2_32_RCR_MSUBS_U_32: + const9 = MASK_OP_RCR_CONST9(ctx->opcode); + gen_msubsui_32(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9); + break; + case OPC2_32_RCR_MSUBS_U_64: + const9 = MASK_OP_RCR_CONST9(ctx->opcode); + gen_msubsui_64(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1], + cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9); + break; + } +} + +/* RLC format */ + +static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx, + uint32_t op1) +{ + int32_t const16; + int r1, r2; + + const16 = MASK_OP_RLC_CONST16_SEXT(ctx->opcode); + r1 = MASK_OP_RLC_S1(ctx->opcode); + r2 = MASK_OP_RLC_D(ctx->opcode); + + switch (op1) { + case OPC1_32_RLC_ADDI: + gen_addi_CC(cpu_gpr_d[r2], cpu_gpr_d[r1], const16); + break; + case OPC1_32_RLC_ADDIH: + gen_addi_CC(cpu_gpr_d[r2], cpu_gpr_d[r1], const16 << 16); + break; + case OPC1_32_RLC_ADDIH_A: + tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r1], const16 << 16); + break; + case OPC1_32_RLC_MFCR: + gen_mfcr(env, cpu_gpr_d[r2], const16); + break; + case OPC1_32_RLC_MOV: + tcg_gen_movi_tl(cpu_gpr_d[r2], const16); + break; + case OPC1_32_RLC_MOV_U: + const16 = MASK_OP_RLC_CONST16(ctx->opcode); + tcg_gen_movi_tl(cpu_gpr_d[r2], const16); + break; + case OPC1_32_RLC_MOV_H: + tcg_gen_movi_tl(cpu_gpr_d[r2], const16 << 16); + break; + case OPC1_32_RLC_MOVH_A: + tcg_gen_movi_tl(cpu_gpr_a[r2], const16 << 16); + break; + case OPC1_32_RLC_MTCR: + gen_mtcr(env, ctx, cpu_gpr_d[r2], const16); + break; + } +} + static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) { int op1; - int32_t r1; - int32_t address; - int8_t b; + int32_t r1, r2, r3; + int32_t address, const16; + int8_t b, const4; int32_t bpos; - TCGv temp, temp2; + TCGv temp, temp2, temp3; op1 = MASK_OP_MAJOR(ctx->opcode); + /* handle JNZ.T opcode only being 6 bit long */ + if (unlikely((op1 & 0x3f) == OPCM_32_BRN_JTT)) { + op1 = OPCM_32_BRN_JTT; + } + switch (op1) { /* ABS-format */ case OPCM_32_ABS_LDW: @@ -2405,6 +3928,105 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) case OPCM_32_BO_ADDRMODE_LDMST_BITREVERSE_CIRCULAR: decode_bo_addrmode_ldmst_bitreverse_circular(env, ctx); break; +/* BOL-format */ + case OPC1_32_BOL_LD_A_LONGOFF: + case OPC1_32_BOL_LD_W_LONFOFF: + case OPC1_32_BOL_LEA_LONGOFF: + case OPC1_32_BOL_ST_W_LONGOFF: + case OPC1_32_BOL_ST_A_LONGOFF: + decode_bol_opc(env, ctx, op1); + break; +/* BRC Format */ + case OPCM_32_BRC_EQ_NEQ: + case OPCM_32_BRC_GE: + case OPCM_32_BRC_JLT: + case OPCM_32_BRC_JNE: + const4 = MASK_OP_BRC_CONST4_SEXT(ctx->opcode); + address = MASK_OP_BRC_DISP15_SEXT(ctx->opcode); + r1 = MASK_OP_BRC_S1(ctx->opcode); + gen_compute_branch(ctx, op1, r1, 0, const4, address); + break; +/* BRN Format */ + case OPCM_32_BRN_JTT: + address = MASK_OP_BRN_DISP15_SEXT(ctx->opcode); + r1 = MASK_OP_BRN_S1(ctx->opcode); + gen_compute_branch(ctx, op1, r1, 0, 0, address); + break; +/* BRR Format */ + case OPCM_32_BRR_EQ_NEQ: + case OPCM_32_BRR_ADDR_EQ_NEQ: + case OPCM_32_BRR_GE: + case OPCM_32_BRR_JLT: + case OPCM_32_BRR_JNE: + case OPCM_32_BRR_JNZ: + case OPCM_32_BRR_LOOP: + address = MASK_OP_BRR_DISP15_SEXT(ctx->opcode); + r2 = MASK_OP_BRR_S2(ctx->opcode); + r1 = MASK_OP_BRR_S1(ctx->opcode); + gen_compute_branch(ctx, op1, r1, r2, 0, address); + break; +/* RC Format */ + case OPCM_32_RC_LOGICAL_SHIFT: + decode_rc_logical_shift(env, ctx); + break; + case OPCM_32_RC_ACCUMULATOR: + decode_rc_accumulator(env, ctx); + break; + case OPCM_32_RC_SERVICEROUTINE: + decode_rc_serviceroutine(env, ctx); + break; + case OPCM_32_RC_MUL: + decode_rc_mul(env, ctx); + break; +/* RCPW Format */ + case OPCM_32_RCPW_MASK_INSERT: + decode_rcpw_insert(env, ctx); + break; +/* RCRR Format */ + case OPC1_32_RCRR_INSERT: + r1 = MASK_OP_RCRR_S1(ctx->opcode); + r2 = MASK_OP_RCRR_S3(ctx->opcode); + r3 = MASK_OP_RCRR_D(ctx->opcode); + const16 = MASK_OP_RCRR_CONST4(ctx->opcode); + temp = tcg_const_i32(const16); + temp2 = tcg_temp_new(); /* width*/ + temp3 = tcg_temp_new(); /* pos */ + + tcg_gen_andi_tl(temp2, cpu_gpr_d[r3+1], 0x1f); + tcg_gen_andi_tl(temp3, cpu_gpr_d[r3], 0x1f); + + gen_insert(cpu_gpr_d[r2], cpu_gpr_d[r1], temp, temp2, temp3); + + tcg_temp_free(temp); + tcg_temp_free(temp2); + tcg_temp_free(temp3); + break; +/* RCRW Format */ + case OPCM_32_RCRW_MASK_INSERT: + decode_rcrw_insert(env, ctx); + break; +/* RCR Format */ + case OPCM_32_RCR_COND_SELECT: + decode_rcr_cond_select(env, ctx); + break; + case OPCM_32_RCR_MADD: + decode_rcr_madd(env, ctx); + break; + case OPCM_32_RCR_MSUB: + decode_rcr_msub(env, ctx); + break; +/* RLC Format */ + case OPC1_32_RLC_ADDI: + case OPC1_32_RLC_ADDIH: + case OPC1_32_RLC_ADDIH_A: + case OPC1_32_RLC_MFCR: + case OPC1_32_RLC_MOV: + case OPC1_32_RLC_MOV_U: + case OPC1_32_RLC_MOV_H: + case OPC1_32_RLC_MOVH_A: + case OPC1_32_RLC_MTCR: + decode_rlc_opc(env, ctx, op1); + break; } } diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index 7e6f33bd62..0a9122cfb9 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -115,25 +115,31 @@ #define MASK_OP_BOL_OFF16(op) ((MASK_BITS_SHIFT(op, 16, 21) + \ (MASK_BITS_SHIFT(op, 28, 31) << 6)) + \ (MASK_BITS_SHIFT(op, 22, 27) >> 10)) - +#define MASK_OP_BOL_OFF16_SEXT(op) ((MASK_BITS_SHIFT(op, 16, 21) + \ + (MASK_BITS_SHIFT(op, 28, 31) << 6)) + \ + (MASK_BITS_SHIFT_SEXT(op, 22, 27) << 10)) #define MASK_OP_BOL_S2(op) MASK_BITS_SHIFT(op, 12, 15) #define MASK_OP_BOL_S1D(op) MASK_BITS_SHIFT(op, 8, 11) /* BRC Format */ #define MASK_OP_BRC_OP2(op) MASK_BITS_SHIFT(op, 31, 31) #define MASK_OP_BRC_DISP15(op) MASK_BITS_SHIFT(op, 16, 30) +#define MASK_OP_BRC_DISP15_SEXT(op) MASK_BITS_SHIFT_SEXT(op, 16, 30) #define MASK_OP_BRC_CONST4(op) MASK_BITS_SHIFT(op, 12, 15) +#define MASK_OP_BRC_CONST4_SEXT(op) MASK_BITS_SHIFT_SEXT(op, 12, 15) #define MASK_OP_BRC_S1(op) MASK_BITS_SHIFT(op, 8, 11) /* BRN Format */ #define MASK_OP_BRN_OP2(op) MASK_BITS_SHIFT(op, 31, 31) #define MASK_OP_BRN_DISP15(op) MASK_BITS_SHIFT(op, 16, 30) +#define MASK_OP_BRN_DISP15_SEXT(op) MASK_BITS_SHIFT_SEXT(op, 16, 30) #define MASK_OP_BRN_N(op) (MASK_BITS_SHIFT(op, 12, 15) + \ (MASK_BITS_SHIFT(op, 7, 7) << 4)) #define MASK_OP_BRN_S1(op) MASK_BITS_SHIFT(op, 8, 11) /* BRR Format */ #define MASK_OP_BRR_OP2(op) MASK_BITS_SHIFT(op, 31, 31) #define MASK_OP_BRR_DISP15(op) MASK_BITS_SHIFT(op, 16, 30) +#define MASK_OP_BRR_DISP15_SEXT(op) MASK_BITS_SHIFT_SEXT(op, 16, 30) #define MASK_OP_BRR_S2(op) MASK_BITS_SHIFT(op, 12, 15) #define MASK_OP_BRR_S1(op) MASK_BITS_SHIFT(op, 8, 11) @@ -145,6 +151,7 @@ #define MASK_OP_RC_D(op) MASK_OP_META_D(op) #define MASK_OP_RC_OP2(op) MASK_BITS_SHIFT(op, 21, 27) #define MASK_OP_RC_CONST9(op) MASK_BITS_SHIFT(op, 12, 20) +#define MASK_OP_RC_CONST9_SEXT(op) MASK_BITS_SHIFT_SEXT(op, 12, 20) #define MASK_OP_RC_S1(op) MASK_OP_META_S1(op) /* RCPW Format */ @@ -162,6 +169,7 @@ #define MASK_OP_RCR_S3(op) MASK_BITS_SHIFT(op, 24, 27) #define MASK_OP_RCR_OP2(op) MASK_BITS_SHIFT(op, 21, 23) #define MASK_OP_RCR_CONST9(op) MASK_BITS_SHIFT(op, 12, 20) +#define MASK_OP_RCR_CONST9_SEXT(op) MASK_BITS_SHIFT_SEXT(op, 12, 20) #define MASK_OP_RCR_S1(op) MASK_OP_META_S1(op) /* RCRR Format */ @@ -185,6 +193,7 @@ #define MASK_OP_RLC_D(op) MASK_OP_META_D(op) #define MASK_OP_RLC_CONST16(op) MASK_BITS_SHIFT(op, 12, 27) +#define MASK_OP_RLC_CONST16_SEXT(op) MASK_BITS_SHIFT_SEXT(op, 12, 27) #define MASK_OP_RLC_S1(op) MASK_OP_META_S1(op) /* RR Format */ @@ -763,8 +772,8 @@ enum { }; /* OPCM_32_BRC_GE */ enum { - OP2_BRC_JGE = 0x00, - OPC_BRC_JGE_U = 0x01, + OP2_32_BRC_JGE = 0x00, + OPC_32_BRC_JGE_U = 0x01, }; /* OPCM_32_BRC_JLT */ enum { @@ -937,7 +946,7 @@ enum { OPC2_32_RCR_MSUB_64 = 0x03, OPC2_32_RCR_MSUBS_32 = 0x05, OPC2_32_RCR_MSUBS_64 = 0x07, - OPC2_32_RCR_MSUB_U_32 = 0x02, + OPC2_32_RCR_MSUB_U_64 = 0x02, OPC2_32_RCR_MSUBS_U_32 = 0x04, OPC2_32_RCR_MSUBS_U_64 = 0x06, }; diff --git a/tests/ahci-test.c b/tests/ahci-test.c index 4c77ebec7a..e77fa3a25c 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -487,7 +487,8 @@ static void qtest_shutdown(void) */ static QPCIDevice *ahci_boot(void) { - qtest_boot("-drive if=none,id=drive0,file=%s,cache=writeback,serial=%s" + qtest_boot("-drive if=none,id=drive0,file=%s,cache=writeback,serial=%s," + "format=raw" " -M q35 " "-device ide-hd,drive=drive0 " "-global ide-hd.ver=%s", diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index 9e4d20592b..2519f7d0e2 100644 --- a/tests/bios-tables-test.c +++ b/tests/bios-tables-test.c @@ -716,7 +716,7 @@ static void test_acpi_one(const char *params, test_data *data) int i; args = g_strdup_printf("-net none -display none %s " - "-drive id=hd0,if=none,file=%s " + "-drive id=hd0,if=none,file=%s,format=raw " "-device ide-hd,drive=hd0 ", params ? params : "", disk); diff --git a/tests/drive_del-test.c b/tests/drive_del-test.c index 53fa969260..8951f6f610 100644 --- a/tests/drive_del-test.c +++ b/tests/drive_del-test.c @@ -103,7 +103,7 @@ static void test_after_failed_device_add(void) static void test_drive_del_device_del(void) { /* Start with a drive used by a device that unplugs instantaneously */ - qtest_start("-drive if=none,id=drive0,file=/dev/null" + qtest_start("-drive if=none,id=drive0,file=/dev/null,format=raw" " -device virtio-scsi-pci" " -device scsi-hd,drive=drive0,id=dev0"); diff --git a/tests/fdc-test.c b/tests/fdc-test.c index 203074cdad..3c6c83cac4 100644 --- a/tests/fdc-test.c +++ b/tests/fdc-test.c @@ -291,7 +291,7 @@ static void test_media_insert(void) /* Insert media in drive. DSKCHK should not be reset until a step pulse * is sent. */ qmp_discard_response("{'execute':'change', 'arguments':{" - " 'device':'floppy0', 'target': %s }}", + " 'device':'floppy0', 'target': %s, 'arg': 'raw' }}", test_image); qmp_discard_response(""); /* ignore event (FIXME open -> open transition?!) */ diff --git a/tests/hd-geo-test.c b/tests/hd-geo-test.c index c84d1e75e0..7cc8dfff16 100644 --- a/tests/hd-geo-test.c +++ b/tests/hd-geo-test.c @@ -208,7 +208,7 @@ static int setup_ide(int argc, char *argv[], int argv_sz, { char *s1, *s2, *s3; - s1 = g_strdup_printf("-drive id=drive%d,if=%s", + s1 = g_strdup_printf("-drive id=drive%d,if=%s,format=raw", ide_idx, dev ? "none" : "ide"); s2 = dev ? g_strdup("") : g_strdup_printf(",index=%d", ide_idx); diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c index ad232b561c..a3f72790ea 100644 --- a/tests/i440fx-test.c +++ b/tests/i440fx-test.c @@ -342,8 +342,9 @@ static void test_i440fx_firmware(FirmwareTestFixture *fixture, g_assert(fw_pathname != NULL); /* Better hope the user didn't put metacharacters in TMPDIR and co. */ - cmdline = g_strdup_printf("-S %s %s", - fixture->is_bios ? "-bios" : "-pflash", + cmdline = g_strdup_printf("-S %s%s", fixture->is_bios + ? "-bios " + : "-drive if=pflash,format=raw,file=", fw_pathname); g_test_message("qemu cmdline: %s", cmdline); qtest_start(cmdline); diff --git a/tests/ide-test.c b/tests/ide-test.c index b7a97e9362..29f4039bd5 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -385,7 +385,7 @@ static void test_bmdma_no_busmaster(void) static void test_bmdma_setup(void) { ide_test_start( - "-drive file=%s,if=ide,serial=%s,cache=writeback " + "-drive file=%s,if=ide,serial=%s,cache=writeback,format=raw " "-global ide-hd.ver=%s", tmp_path, "testdisk", "version"); } @@ -414,7 +414,7 @@ static void test_identify(void) int ret; ide_test_start( - "-drive file=%s,if=ide,serial=%s,cache=writeback " + "-drive file=%s,if=ide,serial=%s,cache=writeback,format=raw " "-global ide-hd.ver=%s", tmp_path, "testdisk", "version"); @@ -458,7 +458,7 @@ static void test_flush(void) uint8_t data; ide_test_start( - "-drive file=blkdebug::%s,if=ide,cache=writeback", + "-drive file=blkdebug::%s,if=ide,cache=writeback,format=raw", tmp_path); /* Delay the completion of the flush request until we explicitly do it */ @@ -526,7 +526,8 @@ static void test_retry_flush(void) ide_test_start( "-vnc none " - "-drive file=blkdebug:%s:%s,if=ide,cache=writeback,rerror=stop,werror=stop", + "-drive file=blkdebug:%s:%s,if=ide,cache=writeback,format=raw," + "rerror=stop,werror=stop", debug_path, tmp_path); /* FLUSH CACHE command on device 0*/ diff --git a/tests/nvme-test.c b/tests/nvme-test.c index 85768e837b..ff38b5e48f 100644 --- a/tests/nvme-test.c +++ b/tests/nvme-test.c @@ -24,7 +24,7 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); qtest_add_func("/nvme/nop", nop); - qtest_start("-drive id=drv0,if=none,file=/dev/null " + qtest_start("-drive id=drv0,if=none,file=/dev/null,format=raw " "-device nvme,drive=drv0,serial=foo"); ret = g_test_run(); diff --git a/tests/qemu-iotests/001.out b/tests/qemu-iotests/001.out index 330f5c9afa..b80e098a68 100644 --- a/tests/qemu-iotests/001.out +++ b/tests/qemu-iotests/001.out @@ -1,5 +1,5 @@ QA output created by 001 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == reading whole image == read 134217728/134217728 bytes at offset 0 diff --git a/tests/qemu-iotests/002.out b/tests/qemu-iotests/002.out index cd6aa0f9fa..1b46b34ad3 100644 --- a/tests/qemu-iotests/002.out +++ b/tests/qemu-iotests/002.out @@ -1,5 +1,5 @@ QA output created by 002 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == reading whole image == read 134217728/134217728 bytes at offset 0 diff --git a/tests/qemu-iotests/003.out b/tests/qemu-iotests/003.out index 4942482bab..e7641230fa 100644 --- a/tests/qemu-iotests/003.out +++ b/tests/qemu-iotests/003.out @@ -1,5 +1,5 @@ QA output created by 003 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == reading whole image == read 134217728/134217728 bytes at offset 0 diff --git a/tests/qemu-iotests/004.out b/tests/qemu-iotests/004.out index f1ed4d896a..fb8593289f 100644 --- a/tests/qemu-iotests/004.out +++ b/tests/qemu-iotests/004.out @@ -1,5 +1,5 @@ QA output created by 004 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 write before image boundary wrote 1048576/1048576 bytes at offset 133169152 diff --git a/tests/qemu-iotests/005.out b/tests/qemu-iotests/005.out index 2d3e7df25a..10044c34ae 100644 --- a/tests/qemu-iotests/005.out +++ b/tests/qemu-iotests/005.out @@ -1,7 +1,7 @@ QA output created by 005 creating large image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=5368709120000 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=5368709120000 small read read 4096/4096 bytes at offset 1024 diff --git a/tests/qemu-iotests/006.out b/tests/qemu-iotests/006.out index f82fbfbe25..d135841b70 100644 --- a/tests/qemu-iotests/006.out +++ b/tests/qemu-iotests/006.out @@ -2,5 +2,5 @@ QA output created by 006 creating 128GB image qemu-img: The image size is too large for file format 'vpc' -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=137438953472 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=137438953472 *** done diff --git a/tests/qemu-iotests/007.out b/tests/qemu-iotests/007.out index cf3d17da27..571505368f 100644 --- a/tests/qemu-iotests/007.out +++ b/tests/qemu-iotests/007.out @@ -1,7 +1,7 @@ QA output created by 007 creating image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 savevm 1 savevm 2 savevm 3 diff --git a/tests/qemu-iotests/008.out b/tests/qemu-iotests/008.out index 0acbb86ea5..08475c8a0d 100644 --- a/tests/qemu-iotests/008.out +++ b/tests/qemu-iotests/008.out @@ -1,5 +1,5 @@ QA output created by 008 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == reading whole image == read 134217728/134217728 bytes at offset 0 diff --git a/tests/qemu-iotests/009.out b/tests/qemu-iotests/009.out index 180e451689..19e15d0c7b 100644 --- a/tests/qemu-iotests/009.out +++ b/tests/qemu-iotests/009.out @@ -1,7 +1,7 @@ QA output created by 009 creating image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 creating pattern wrote 4096/4096 bytes at offset 2097152 diff --git a/tests/qemu-iotests/010.out b/tests/qemu-iotests/010.out index cc5c9414f7..1bee037d7a 100644 --- a/tests/qemu-iotests/010.out +++ b/tests/qemu-iotests/010.out @@ -1,7 +1,7 @@ QA output created by 010 creating image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 creating pattern wrote 4096/4096 bytes at offset 2097152 diff --git a/tests/qemu-iotests/011.out b/tests/qemu-iotests/011.out index dfec17d184..65c998eaa1 100644 --- a/tests/qemu-iotests/011.out +++ b/tests/qemu-iotests/011.out @@ -1,7 +1,7 @@ QA output created by 011 creating image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 overlapping I/O wrote 1048576/1048576 bytes at offset XXX diff --git a/tests/qemu-iotests/012.out b/tests/qemu-iotests/012.out index 5f9b9900b3..c4ffa8f608 100644 --- a/tests/qemu-iotests/012.out +++ b/tests/qemu-iotests/012.out @@ -1,5 +1,5 @@ QA output created by 012 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == mark image read-only diff --git a/tests/qemu-iotests/013.out b/tests/qemu-iotests/013.out index 43a414cbf6..317cdf4b48 100644 --- a/tests/qemu-iotests/013.out +++ b/tests/qemu-iotests/013.out @@ -1,5 +1,5 @@ QA output created by 013 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 Testing empty image At offset 0: diff --git a/tests/qemu-iotests/014.out b/tests/qemu-iotests/014.out index 4744b4b214..f19341c87e 100644 --- a/tests/qemu-iotests/014.out +++ b/tests/qemu-iotests/014.out @@ -1,5 +1,5 @@ QA output created by 014 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 Testing empty image: test2: With offset 0 === Clusters to be compressed [1] diff --git a/tests/qemu-iotests/015.out b/tests/qemu-iotests/015.out index d4b961c82c..3414afd9ee 100644 --- a/tests/qemu-iotests/015.out +++ b/tests/qemu-iotests/015.out @@ -1,7 +1,7 @@ QA output created by 015 creating image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=37748736 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=37748736 creating first snapshot wrote 37748736/37748736 bytes at offset 0 36 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/016 b/tests/qemu-iotests/016 index 7ea9e94b5d..52397aa80e 100755 --- a/tests/qemu-iotests/016 +++ b/tests/qemu-iotests/016 @@ -43,25 +43,28 @@ _supported_proto file sheepdog nfs _supported_os Linux +# No -f, use probing for the protocol driver +QEMU_IO_PROTO="$QEMU_IO_PROG -g --cache $CACHEMODE" + size=128M _make_test_img $size echo echo "== reading at EOF ==" -$QEMU_IO -g -c "read -P 0 $size 512" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO_PROTO -c "read -P 0 $size 512" "$TEST_IMG" | _filter_qemu_io echo echo "== reading far past EOF ==" -$QEMU_IO -g -c "read -P 0 256M 512" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO_PROTO -c "read -P 0 256M 512" "$TEST_IMG" | _filter_qemu_io echo echo "== writing at EOF ==" -$QEMU_IO -g -c "write -P 66 $size 512" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO_PROTO -c "write -P 66 $size 512" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "read -P 66 $size 512" "$TEST_IMG" | _filter_qemu_io echo echo "== writing far past EOF ==" -$QEMU_IO -g -c "write -P 66 256M 512" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO_PROTO -c "write -P 66 256M 512" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "read -P 66 256M 512" "$TEST_IMG" | _filter_qemu_io # success, all done diff --git a/tests/qemu-iotests/016.out b/tests/qemu-iotests/016.out index 18679780d0..acbd60b4a3 100644 --- a/tests/qemu-iotests/016.out +++ b/tests/qemu-iotests/016.out @@ -1,5 +1,5 @@ QA output created by 016 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == reading at EOF == read 512/512 bytes at offset 134217728 diff --git a/tests/qemu-iotests/017.out b/tests/qemu-iotests/017.out index 75ea61481e..7c409fc5bc 100644 --- a/tests/qemu-iotests/017.out +++ b/tests/qemu-iotests/017.out @@ -269,7 +269,7 @@ wrote 65536/65536 bytes at offset 4295032832 No errors were found on the image. Creating test image with backing file -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' Filling test image === IO: pattern 1 diff --git a/tests/qemu-iotests/018.out b/tests/qemu-iotests/018.out index 25e7b95708..39a6011d29 100644 --- a/tests/qemu-iotests/018.out +++ b/tests/qemu-iotests/018.out @@ -269,7 +269,7 @@ wrote 65536/65536 bytes at offset 4295032832 No errors were found on the image. Creating test image with backing file -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' Filling test image === IO: pattern 1 diff --git a/tests/qemu-iotests/019.out b/tests/qemu-iotests/019.out index f0c6e6375f..4695b972d5 100644 --- a/tests/qemu-iotests/019.out +++ b/tests/qemu-iotests/019.out @@ -1,5 +1,5 @@ QA output created by 019 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 Filling base image === IO: pattern 42 @@ -269,7 +269,7 @@ wrote 65536/65536 bytes at offset 4296015872 No errors were found on the image. Creating test image with backing file -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' Filling test image === IO: pattern 43 diff --git a/tests/qemu-iotests/020.out b/tests/qemu-iotests/020.out index fc9a63cf19..71aab1c747 100644 --- a/tests/qemu-iotests/020.out +++ b/tests/qemu-iotests/020.out @@ -1,5 +1,5 @@ QA output created by 020 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 Filling base image === IO: pattern 0 @@ -269,7 +269,7 @@ wrote 65536/65536 bytes at offset 4295032832 No errors were found on the image. Creating test image with backing file -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' Filling test image === IO: pattern 1 diff --git a/tests/qemu-iotests/021.out b/tests/qemu-iotests/021.out index ed4448c56b..8533f8e58a 100644 --- a/tests/qemu-iotests/021.out +++ b/tests/qemu-iotests/021.out @@ -1,5 +1,5 @@ QA output created by 021 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == testing writev -P -1 == -1 is not a valid pattern byte diff --git a/tests/qemu-iotests/022.out b/tests/qemu-iotests/022.out index 5a729e07e7..dbe9cdb0e7 100644 --- a/tests/qemu-iotests/022.out +++ b/tests/qemu-iotests/022.out @@ -1,5 +1,5 @@ QA output created by 022 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 Testing empty image At offset 10485760: diff --git a/tests/qemu-iotests/023.out b/tests/qemu-iotests/023.out index ec32341e3a..d4e9be25e1 100644 --- a/tests/qemu-iotests/023.out +++ b/tests/qemu-iotests/023.out @@ -1,7 +1,7 @@ QA output created by 023 Creating new image; cluster size: 1024 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 Testing empty image At offset 0: @@ -5664,7 +5664,7 @@ read 3072/3072 bytes at offset 4295491072 No errors were found on the image. Creating another new image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 More complex patterns test2: With offset 0 @@ -5887,7 +5887,7 @@ read 2048/2048 bytes at offset 4295001088 No errors were found on the image. Creating new image; cluster size: 4096 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 Testing empty image At offset 0: @@ -12270,7 +12270,7 @@ read 12288/12288 bytes at offset 4301256704 No errors were found on the image. Creating another new image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 More complex patterns test2: With offset 0 @@ -12493,7 +12493,7 @@ read 8192/8192 bytes at offset 4295102464 No errors were found on the image. Creating new image; cluster size: 16384 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 Testing empty image At offset 0: @@ -18876,7 +18876,7 @@ read 49152/49152 bytes at offset 4395622400 No errors were found on the image. Creating another new image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 More complex patterns test2: With offset 0 @@ -19099,7 +19099,7 @@ read 32768/32768 bytes at offset 4295507968 No errors were found on the image. Creating new image; cluster size: 65536 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 Testing empty image At offset 0: @@ -25482,7 +25482,7 @@ read 196608/196608 bytes at offset 5905547264 No errors were found on the image. Creating another new image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8589934592 More complex patterns test2: With offset 0 diff --git a/tests/qemu-iotests/024.out b/tests/qemu-iotests/024.out index e84b9730f5..521d469425 100644 --- a/tests/qemu-iotests/024.out +++ b/tests/qemu-iotests/024.out @@ -1,7 +1,7 @@ QA output created by 024 Creating backing file -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 === IO: pattern 0x11 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -21,7 +21,7 @@ wrote 65536/65536 bytes at offset 917504 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Creating new backing file -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 === IO: pattern 0x22 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -33,7 +33,7 @@ wrote 131072/131072 bytes at offset 786432 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Creating COW image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file='TEST_DIR/t.IMGFMT.base_old' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file='TEST_DIR/t.IMGFMT.base_old' === IO: pattern 0x33 wrote 262144/262144 bytes at offset 0 256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/025.out b/tests/qemu-iotests/025.out index 8c695e6394..f13fc2863c 100644 --- a/tests/qemu-iotests/025.out +++ b/tests/qemu-iotests/025.out @@ -1,7 +1,7 @@ QA output created by 025 === Creating image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 === Writing whole image === IO: pattern 0xc5 diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out index f7c78e712a..524f7ee21c 100644 --- a/tests/qemu-iotests/026.out +++ b/tests/qemu-iotests/026.out @@ -1,63 +1,71 @@ QA output created by 026 Errors while writing 128 kB -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l1_update; errno: 5; imm: off; once: on; write +Event: l1_update; errno: 5; imm: off; once: on; write write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: on; write -b write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l1_update; errno: 5; imm: off; once: off; write +Event: l1_update; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error 1 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error 1 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l1_update; errno: 28; imm: off; once: on; write +Event: l1_update; errno: 28; imm: off; once: on; write write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: on; write -b write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l1_update; errno: 28; imm: off; once: off; write +Event: l1_update; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 1 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 1 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l2_load; errno: 5; imm: off; once: on; write +Event: l2_load; errno: 5; imm: off; once: on; write wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) write failed: Input/output error read failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 5; imm: off; once: on; write -b wrote 131072/131072 bytes at offset 0 @@ -65,31 +73,39 @@ wrote 131072/131072 bytes at offset 0 write failed: Input/output error read failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l2_load; errno: 5; imm: off; once: off; write +Event: l2_load; errno: 5; imm: off; once: off; write wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error read failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 5; imm: off; once: off; write -b wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error read failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l2_load; errno: 28; imm: off; once: on; write +Event: l2_load; errno: 28; imm: off; once: on; write wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) write failed: No space left on device read failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 28; imm: off; once: on; write -b wrote 131072/131072 bytes at offset 0 @@ -97,437 +113,529 @@ wrote 131072/131072 bytes at offset 0 write failed: No space left on device read failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l2_load; errno: 28; imm: off; once: off; write +Event: l2_load; errno: 28; imm: off; once: off; write wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device read failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 28; imm: off; once: off; write -b wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device read failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l2_update; errno: 5; imm: off; once: on; write +Event: l2_update; errno: 5; imm: off; once: on; write +Failed to flush the L2 table cache: Input/output error write failed: Input/output error 127 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 5; imm: off; once: on; write -b +Failed to flush the L2 table cache: Input/output error write failed: Input/output error 127 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l2_update; errno: 5; imm: off; once: off; write +Event: l2_update; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error 127 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error 127 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l2_update; errno: 28; imm: off; once: on; write +Event: l2_update; errno: 28; imm: off; once: on; write +Failed to flush the L2 table cache: No space left on device write failed: No space left on device 127 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 28; imm: off; once: on; write -b +Failed to flush the L2 table cache: No space left on device write failed: No space left on device 127 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l2_update; errno: 28; imm: off; once: off; write +Event: l2_update; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 127 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 127 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l2_alloc.write; errno: 5; imm: off; once: on; write +Event: l2_alloc.write; errno: 5; imm: off; once: on; write write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 5; imm: off; once: on; write -b write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l2_alloc.write; errno: 5; imm: off; once: off; write +Event: l2_alloc.write; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error 1 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l2_alloc.write; errno: 28; imm: off; once: on; write +Event: l2_alloc.write; errno: 28; imm: off; once: on; write write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 28; imm: off; once: on; write -b write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: l2_alloc.write; errno: 28; imm: off; once: off; write +Event: l2_alloc.write; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 1 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: write_aio; errno: 5; imm: off; once: on; write +Event: write_aio; errno: 5; imm: off; once: on; write write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 5; imm: off; once: on; write -b write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: write_aio; errno: 5; imm: off; once: off; write +Event: write_aio; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: write_aio; errno: 28; imm: off; once: on; write +Event: write_aio; errno: 28; imm: off; once: on; write write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 28; imm: off; once: on; write -b write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: write_aio; errno: 28; imm: off; once: off; write +Event: write_aio; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_load; errno: 5; imm: off; once: on; write +Event: refblock_load; errno: 5; imm: off; once: on; write write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 5; imm: off; once: on; write -b write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_load; errno: 5; imm: off; once: off; write +Event: refblock_load; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_load; errno: 28; imm: off; once: on; write +Event: refblock_load; errno: 28; imm: off; once: on; write write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 28; imm: off; once: on; write -b write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_load; errno: 28; imm: off; once: off; write +Event: refblock_load; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_update_part; errno: 5; imm: off; once: on; write +Event: refblock_update_part; errno: 5; imm: off; once: on; write +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: on; write -b +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_update_part; errno: 5; imm: off; once: off; write +Event: refblock_update_part; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_update_part; errno: 28; imm: off; once: on; write +Event: refblock_update_part; errno: 28; imm: off; once: on; write +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: on; write -b +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_update_part; errno: 28; imm: off; once: off; write +Event: refblock_update_part; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc; errno: 5; imm: off; once: on; write +Event: refblock_alloc; errno: 5; imm: off; once: on; write write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 5; imm: off; once: on; write -b write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc; errno: 5; imm: off; once: off; write +Event: refblock_alloc; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc; errno: 28; imm: off; once: on; write +Event: refblock_alloc; errno: 28; imm: off; once: on; write write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 28; imm: off; once: on; write -b write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc; errno: 28; imm: off; once: off; write +Event: refblock_alloc; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: cluster_alloc; errno: 5; imm: off; once: on; write +Event: cluster_alloc; errno: 5; imm: off; once: on; write write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 5; imm: off; once: on; write -b write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: cluster_alloc; errno: 5; imm: off; once: off; write +Event: cluster_alloc; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: cluster_alloc; errno: 28; imm: off; once: on; write +Event: cluster_alloc; errno: 28; imm: off; once: on; write write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 28; imm: off; once: on; write -b write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: cluster_alloc; errno: 28; imm: off; once: off; write +Event: cluster_alloc; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. === Refcout table growth tests === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc.hookup; errno: 28; imm: off; once: on; write +Event: refblock_alloc.hookup; errno: 28; imm: off; once: on; write write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.hookup; errno: 28; imm: off; once: on; write -b write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc.hookup; errno: 28; imm: off; once: off; write +Event: refblock_alloc.hookup; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 55 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.hookup; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 251 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc.write; errno: 28; imm: off; once: on; write +Event: refblock_alloc.write; errno: 28; imm: off; once: on; write write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write; errno: 28; imm: off; once: on; write -b write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc.write; errno: 28; imm: off; once: off; write +Event: refblock_alloc.write; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: on; write +Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: on; write write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: on; write -b write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write +Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 11 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 23 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc.write_table; errno: 28; imm: off; once: on; write +Event: refblock_alloc.write_table; errno: 28; imm: off; once: on; write write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write_table; errno: 28; imm: off; once: on; write -b write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write +Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 11 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 23 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc.switch_table; errno: 28; imm: off; once: on; write +Event: refblock_alloc.switch_table; errno: 28; imm: off; once: on; write write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.switch_table; errno: 28; imm: off; once: on; write -b write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 -Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write +Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 11 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 23 leaked clusters were found on the image. @@ -535,66 +643,78 @@ This means waste of disk space, but no harm to data. === L1 growth tests === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.alloc_table; errno: 5; imm: off; once: on write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.alloc_table; errno: 5; imm: off; once: off +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.alloc_table; errno: 28; imm: off; once: on write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.alloc_table; errno: 28; imm: off; once: off +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.write_table; errno: 5; imm: off; once: on write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.write_table; errno: 5; imm: off; once: off +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.write_table; errno: 28; imm: off; once: on write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.write_table; errno: 28; imm: off; once: off +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.activate_table; errno: 5; imm: off; once: on write failed: Input/output error No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.activate_table; errno: 5; imm: off; once: off +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error 96 leaked clusters were found on the image. This means waste of disk space, but no harm to data. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.activate_table; errno: 28; imm: off; once: on write failed: No space left on device No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.activate_table; errno: 28; imm: off; once: off +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 96 leaked clusters were found on the image. diff --git a/tests/qemu-iotests/027.out b/tests/qemu-iotests/027.out index 4fcb4161da..c7bca71083 100644 --- a/tests/qemu-iotests/027.out +++ b/tests/qemu-iotests/027.out @@ -1,5 +1,5 @@ QA output created by 027 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == writing first cluster to populate metadata == wrote 65536/65536 bytes at offset 65536 diff --git a/tests/qemu-iotests/028.out b/tests/qemu-iotests/028.out index e8d02459be..5db167ce78 100644 --- a/tests/qemu-iotests/028.out +++ b/tests/qemu-iotests/028.out @@ -1,5 +1,5 @@ QA output created by 028 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=3221227008 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=3221227008 Filling base image === IO: pattern 195 @@ -70,7 +70,7 @@ wrote 512/512 bytes at offset 3221225984 No errors were found on the image. Creating test image with backing file -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294968832 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294968832 backing_file='TEST_DIR/t.IMGFMT.base' Filling test image === IO: pattern 196 @@ -469,7 +469,7 @@ No errors were found on the image. block-backup Formatting 'TEST_DIR/t.IMGFMT.copy', fmt=IMGFMT size=4294968832 backing_file='TEST_DIR/t.IMGFMT.base' backing_fmt='IMGFMT' -(qemu) +(qemu) (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 diff --git a/tests/qemu-iotests/029.out b/tests/qemu-iotests/029.out index ce0e64d24a..5bc93e0451 100644 --- a/tests/qemu-iotests/029.out +++ b/tests/qemu-iotests/029.out @@ -3,18 +3,18 @@ QA output created by 029 Test loading internal snapshots where the L1 table of the snapshot is smaller than the current L1 table. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 wrote 4194304/4194304 bytes at offset 0 4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) No errors were found on the image. Try using a huge VM state -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 4096/4096 bytes at offset 1099511627776 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 4096/4096 bytes at offset 1099511627776 @@ -23,5 +23,5 @@ No errors were found on the image. qcow2_snapshot_load_tmp() should take the L1 size from the snapshot -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 *** done diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 index 8ce2373cf5..952a524ec7 100755 --- a/tests/qemu-iotests/030 +++ b/tests/qemu-iotests/030 @@ -34,7 +34,7 @@ class TestSingleDrive(iotests.QMPTestCase): iotests.create_image(backing_img, TestSingleDrive.image_len) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) - qemu_io('-c', 'write -P 0x1 0 512', backing_img) + qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 512', backing_img) self.vm = iotests.VM().add_drive("blkdebug::" + test_img) self.vm.launch() @@ -55,8 +55,8 @@ class TestSingleDrive(iotests.QMPTestCase): self.assert_no_active_block_jobs() self.vm.shutdown() - self.assertEqual(qemu_io('-c', 'map', backing_img), - qemu_io('-c', 'map', test_img), + self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img), + qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img), 'image file map does not match backing file after streaming') def test_stream_pause(self): @@ -86,8 +86,8 @@ class TestSingleDrive(iotests.QMPTestCase): self.assert_no_active_block_jobs() self.vm.shutdown() - self.assertEqual(qemu_io('-c', 'map', backing_img), - qemu_io('-c', 'map', test_img), + self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img), + qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img), 'image file map does not match backing file after streaming') def test_stream_partial(self): @@ -101,8 +101,8 @@ class TestSingleDrive(iotests.QMPTestCase): self.assert_no_active_block_jobs() self.vm.shutdown() - self.assertEqual(qemu_io('-c', 'map', mid_img), - qemu_io('-c', 'map', test_img), + self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img), + qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img), 'image file map does not match backing file after streaming') def test_device_not_found(self): @@ -359,9 +359,9 @@ class TestStreamStop(iotests.QMPTestCase): def setUp(self): qemu_img('create', backing_img, str(TestStreamStop.image_len)) - qemu_io('-c', 'write -P 0x1 0 32M', backing_img) + qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) - qemu_io('-c', 'write -P 0x1 32M 32M', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img) self.vm = iotests.VM().add_drive("blkdebug::" + test_img) self.vm.launch() @@ -388,9 +388,9 @@ class TestSetSpeed(iotests.QMPTestCase): def setUp(self): qemu_img('create', backing_img, str(TestSetSpeed.image_len)) - qemu_io('-c', 'write -P 0x1 0 32M', backing_img) + qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) - qemu_io('-c', 'write -P 0x1 32M 32M', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img) self.vm = iotests.VM().add_drive('blkdebug::' + test_img) self.vm.launch() diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out index a94334478e..fce3ce0984 100644 --- a/tests/qemu-iotests/031.out +++ b/tests/qemu-iotests/031.out @@ -4,7 +4,7 @@ QA output created by 031 === Create image with unknown header extension === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 magic 0x514649fb version 2 backing_file_offset 0x0 @@ -105,7 +105,7 @@ data 'This is a test header extension' === Create image with unknown header extension === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 magic 0x514649fb version 3 backing_file_offset 0x0 diff --git a/tests/qemu-iotests/032.out b/tests/qemu-iotests/032.out index ca20de676d..ce27d5dfdc 100644 --- a/tests/qemu-iotests/032.out +++ b/tests/qemu-iotests/032.out @@ -2,7 +2,7 @@ QA output created by 032 === Prepare image === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 131072 diff --git a/tests/qemu-iotests/033.out b/tests/qemu-iotests/033.out index 2fe74df763..41475eefea 100644 --- a/tests/qemu-iotests/033.out +++ b/tests/qemu-iotests/033.out @@ -1,5 +1,5 @@ QA output created by 033 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == preparing image == wrote 1024/1024 bytes at offset 512 diff --git a/tests/qemu-iotests/034.out b/tests/qemu-iotests/034.out index e82dae55f7..d12daf206f 100644 --- a/tests/qemu-iotests/034.out +++ b/tests/qemu-iotests/034.out @@ -1,10 +1,10 @@ QA output created by 034 == creating backing file for COW tests == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' == zero write with backing file == wrote 196608/196608 bytes at offset 65536 diff --git a/tests/qemu-iotests/035.out b/tests/qemu-iotests/035.out index cde21d8135..dd3bd201d9 100644 --- a/tests/qemu-iotests/035.out +++ b/tests/qemu-iotests/035.out @@ -1,7 +1,7 @@ QA output created by 035 creating image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 wrote 512/512 bytes at offset XXX 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset XXX diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out index 720bd89161..5616e37b3f 100644 --- a/tests/qemu-iotests/036.out +++ b/tests/qemu-iotests/036.out @@ -2,7 +2,7 @@ QA output created by 036 === Image with unknown incompatible feature bit === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 magic 0x514649fb version 3 backing_file_offset 0x0 @@ -27,7 +27,7 @@ qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature whic === Image with multiple incompatible feature bits === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Unknown incompatible feature: e000000000000000 qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature, Unknown incompatible feature: 6000000000000000 qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature, Unknown incompatible feature: c000000000000000 @@ -36,7 +36,7 @@ qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature whic qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test2, Unknown incompatible feature: a000000000000000 === Create image with unknown autoclear feature bit === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 magic 0x514649fb version 3 backing_file_offset 0x0 diff --git a/tests/qemu-iotests/037.out b/tests/qemu-iotests/037.out index 4eb84ed55a..dc40a021a4 100644 --- a/tests/qemu-iotests/037.out +++ b/tests/qemu-iotests/037.out @@ -1,7 +1,7 @@ QA output created by 037 == creating backing file for COW tests == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset 512 @@ -514,7 +514,7 @@ wrote 512/512 bytes at offset 130048 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset 130560 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' == COW in a single cluster == wrote 2048/2048 bytes at offset 0 diff --git a/tests/qemu-iotests/038.out b/tests/qemu-iotests/038.out index a71c3fa359..e1a7e94410 100644 --- a/tests/qemu-iotests/038.out +++ b/tests/qemu-iotests/038.out @@ -1,7 +1,7 @@ QA output created by 038 == creating backing file for COW tests == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 65536 @@ -514,7 +514,7 @@ wrote 65536/65536 bytes at offset 16646144 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 16711680 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' == Some concurrent requests touching the same cluster == wrote 65536/65536 bytes at offset XXX diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039 index 84c9167660..859705f848 100755 --- a/tests/qemu-iotests/039 +++ b/tests/qemu-iotests/039 @@ -47,9 +47,11 @@ _supported_os Linux _default_cache_mode "writethrough" _supported_cache_modes "writethrough" -_no_dump_exec() +_subshell_exec() { - (ulimit -c 0; exec "$@") + # Executing crashing commands in a subshell prevents information like the + # "Killed" line from being lost + (exec "$@") } size=128M @@ -72,7 +74,9 @@ echo "== Creating a dirty image file ==" IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img $size -_no_dump_exec $QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" 2>&1 | _filter_qemu_io +_subshell_exec $QEMU_IO -c "write -P 0x5a 0 512" \ + -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \ + | _filter_qemu_io # The dirty bit must be set $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features @@ -105,7 +109,9 @@ echo "== Opening a dirty image read/write should repair it ==" IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img $size -_no_dump_exec $QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" 2>&1 | _filter_qemu_io +_subshell_exec $QEMU_IO -c "write -P 0x5a 0 512" \ + -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \ + | _filter_qemu_io # The dirty bit must be set $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features @@ -121,7 +127,9 @@ echo "== Creating an image file with lazy_refcounts=off ==" IMGOPTS="compat=1.1,lazy_refcounts=off" _make_test_img $size -_no_dump_exec $QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" 2>&1 | _filter_qemu_io +_subshell_exec $QEMU_IO -c "write -P 0x5a 0 512" \ + -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \ + | _filter_qemu_io # The dirty bit must not be set since lazy_refcounts=off $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out index 0adf1535ef..d09751f9c8 100644 --- a/tests/qemu-iotests/039.out +++ b/tests/qemu-iotests/039.out @@ -1,17 +1,17 @@ QA output created by 039 == Checking that image is clean on shutdown == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) incompatible_features 0x0 No errors were found on the image. == Creating a dirty image file == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -./039: Aborted ( ulimit -c 0; exec "$@" ) +./039: Killed ( exec "$@" ) incompatible_features 0x1 ERROR cluster 5 refcount=0 reference=1 ERROR OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=0 @@ -43,10 +43,10 @@ read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == Opening a dirty image read/write should repair it == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -./039: Aborted ( ulimit -c 0; exec "$@" ) +./039: Killed ( exec "$@" ) incompatible_features 0x1 ERROR cluster 5 refcount=0 reference=1 Rebuilding refcount structure @@ -57,16 +57,16 @@ wrote 512/512 bytes at offset 0 incompatible_features 0x0 == Creating an image file with lazy_refcounts=off == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -./039: Aborted ( ulimit -c 0; exec "$@" ) +./039: Killed ( exec "$@" ) incompatible_features 0x0 No errors were found on the image. == Committing to a backing file with lazy_refcounts=on == -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base' wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Image committed. diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 index 2b432ad7a1..ea2f98e51d 100755 --- a/tests/qemu-iotests/040 +++ b/tests/qemu-iotests/040 @@ -76,8 +76,8 @@ class TestSingleDrive(ImageCommitTestCase): iotests.create_image(backing_img, self.image_len) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) - qemu_io('-c', 'write -P 0xab 0 524288', backing_img) - qemu_io('-c', 'write -P 0xef 524288 524288', mid_img) + qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', backing_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img) self.vm = iotests.VM().add_drive(test_img) self.vm.launch() @@ -89,8 +89,8 @@ class TestSingleDrive(ImageCommitTestCase): def test_commit(self): self.run_commit_test(mid_img, backing_img) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) def test_device_not_found(self): result = self.vm.qmp('block-commit', device='nonexistent', top='%s' % mid_img) @@ -116,13 +116,13 @@ class TestSingleDrive(ImageCommitTestCase): def test_top_is_active(self): self.run_commit_test(test_img, backing_img, need_ready=True) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) def test_top_is_default_active(self): self.run_default_commit_test() - self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) def test_top_and_base_reversed(self): self.assert_no_active_block_jobs() @@ -159,8 +159,8 @@ class TestRelativePaths(ImageCommitTestCase): qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.mid_img_abs, self.test_img) qemu_img('rebase', '-u', '-b', self.backing_img, self.mid_img_abs) qemu_img('rebase', '-u', '-b', self.mid_img, self.test_img) - qemu_io('-c', 'write -P 0xab 0 524288', self.backing_img_abs) - qemu_io('-c', 'write -P 0xef 524288 524288', self.mid_img_abs) + qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', self.backing_img_abs) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', self.mid_img_abs) self.vm = iotests.VM().add_drive(self.test_img) self.vm.launch() @@ -179,8 +179,8 @@ class TestRelativePaths(ImageCommitTestCase): def test_commit(self): self.run_commit_test(self.mid_img, self.backing_img) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', self.backing_img_abs).find("verification failed")) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', self.backing_img_abs).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', self.backing_img_abs).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', self.backing_img_abs).find("verification failed")) def test_device_not_found(self): result = self.vm.qmp('block-commit', device='nonexistent', top='%s' % self.mid_img) @@ -206,8 +206,8 @@ class TestRelativePaths(ImageCommitTestCase): def test_top_is_active(self): self.run_commit_test(self.test_img, self.backing_img) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', self.backing_img_abs).find("verification failed")) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', self.backing_img_abs).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', self.backing_img_abs).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', self.backing_img_abs).find("verification failed")) def test_top_and_base_reversed(self): self.assert_no_active_block_jobs() @@ -223,8 +223,8 @@ class TestSetSpeed(ImageCommitTestCase): qemu_img('create', backing_img, str(TestSetSpeed.image_len)) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) - qemu_io('-c', 'write -P 0x1 0 512', test_img) - qemu_io('-c', 'write -P 0xef 524288 524288', mid_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 0 512', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img) self.vm = iotests.VM().add_drive(test_img) self.vm.launch() diff --git a/tests/qemu-iotests/042.out b/tests/qemu-iotests/042.out index dc80f4b5b3..8ab1520020 100644 --- a/tests/qemu-iotests/042.out +++ b/tests/qemu-iotests/042.out @@ -1,7 +1,7 @@ QA output created by 042 == Creating zero size image == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 No errors were found on the image. == Converting the image == diff --git a/tests/qemu-iotests/043.out b/tests/qemu-iotests/043.out index ad23337db5..012cc008e3 100644 --- a/tests/qemu-iotests/043.out +++ b/tests/qemu-iotests/043.out @@ -1,23 +1,23 @@ QA output created by 043 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == backing file references self == qemu-img: Backing file 'TEST_DIR/t.IMGFMT' creates an infinite loop. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base' == parent references self == qemu-img: Backing file 'TEST_DIR/t.IMGFMT' creates an infinite loop. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.1.base' -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.2.base' -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.3.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.1.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.2.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.3.base' == ancestor references another ancestor == qemu-img: Backing file 'TEST_DIR/t.IMGFMT.2.base' creates an infinite loop. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.1.base' -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.2.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.1.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.2.base' == finite chain of length 3 (human) == image: TEST_DIR/t.IMGFMT @@ -40,26 +40,26 @@ cluster_size: 65536 == finite chain of length 3 (json) == [ { - "virtual-size": 134217728, - "filename": "TEST_DIR/t.IMGFMT", - "cluster-size": 65536, - "format": "IMGFMT", - "backing-filename": "TEST_DIR/t.IMGFMT.2.base", + "virtual-size": 134217728, + "filename": "TEST_DIR/t.IMGFMT", + "cluster-size": 65536, + "format": "IMGFMT", + "backing-filename": "TEST_DIR/t.IMGFMT.2.base", "dirty-flag": false - }, + }, { - "virtual-size": 134217728, - "filename": "TEST_DIR/t.IMGFMT.2.base", - "cluster-size": 65536, - "format": "IMGFMT", - "backing-filename": "TEST_DIR/t.IMGFMT.1.base", + "virtual-size": 134217728, + "filename": "TEST_DIR/t.IMGFMT.2.base", + "cluster-size": 65536, + "format": "IMGFMT", + "backing-filename": "TEST_DIR/t.IMGFMT.1.base", "dirty-flag": false - }, + }, { - "virtual-size": 134217728, - "filename": "TEST_DIR/t.IMGFMT.1.base", - "cluster-size": 65536, - "format": "IMGFMT", + "virtual-size": 134217728, + "filename": "TEST_DIR/t.IMGFMT.1.base", + "cluster-size": 65536, + "format": "IMGFMT", "dirty-flag": false } ] diff --git a/tests/qemu-iotests/046.out b/tests/qemu-iotests/046.out index 65d584bcfe..9d18af53a1 100644 --- a/tests/qemu-iotests/046.out +++ b/tests/qemu-iotests/046.out @@ -1,7 +1,7 @@ QA output created by 046 == creating backing file for COW tests == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 65536 @@ -66,7 +66,7 @@ wrote 65536/65536 bytes at offset 1966080 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 2031616 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' == Some concurrent requests touching the same cluster == blkdebug: Suspended request 'A' diff --git a/tests/qemu-iotests/047.out b/tests/qemu-iotests/047.out index 959f2afa6c..856a2bcf87 100644 --- a/tests/qemu-iotests/047.out +++ b/tests/qemu-iotests/047.out @@ -1,5 +1,5 @@ QA output created by 047 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 327680/327680 bytes at offset 0 320 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 327680 diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048 index 65da46d6f5..e1eeac2a31 100755 --- a/tests/qemu-iotests/048 +++ b/tests/qemu-iotests/048 @@ -64,7 +64,7 @@ _compare _compare -q # Compare images with different size -$QEMU_IMG resize "$TEST_IMG" +512M +$QEMU_IMG resize -f $IMGFMT "$TEST_IMG" +512M _compare _compare -s diff --git a/tests/qemu-iotests/048.out b/tests/qemu-iotests/048.out index c0f380d3a3..57100dc453 100644 --- a/tests/qemu-iotests/048.out +++ b/tests/qemu-iotests/048.out @@ -1,5 +1,5 @@ QA output created by 048 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 === IO: pattern 45 wrote 4096/4096 bytes at offset 524288 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -28,7 +28,7 @@ wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Content mismatch at offset 0! 1 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 === IO: pattern 100 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out index 09ca0aed49..b6311b01b9 100644 --- a/tests/qemu-iotests/049.out +++ b/tests/qemu-iotests/049.out @@ -4,90 +4,90 @@ QA output created by 049 == 1. Traditional size parameter == qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024b -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 1k -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 1K -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 1M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 1G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 1T -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0b -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5k -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5K -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5T -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 encryption=off cluster_size=65536 lazy_refcounts=off == 2. Specifying size via -o == qemu-img create -f qcow2 -o size=1024 TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o size=1024b TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o size=1k TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o size=1K TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o size=1M TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o size=1G TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o size=1T TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o size=1024.0 TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o size=1024.0b TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o size=1.5k TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o size=1.5K TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o size=1.5M TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o size=1.5G TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o size=1.5T TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 encryption=off cluster_size=65536 lazy_refcounts=off == 3. Invalid sizes == @@ -97,7 +97,7 @@ qemu-img: Image size must be less than 8 EiB! qemu-img create -f qcow2 -o size=-1024 TEST_DIR/t.qcow2 qemu-img: qcow2 doesn't support shrinking images yet qemu-img: TEST_DIR/t.qcow2: Could not resize image: Operation not supported -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1k qemu-img: Image size must be less than 8 EiB! @@ -105,17 +105,17 @@ qemu-img: Image size must be less than 8 EiB! qemu-img create -f qcow2 -o size=-1k TEST_DIR/t.qcow2 qemu-img: qcow2 doesn't support shrinking images yet qemu-img: TEST_DIR/t.qcow2: Could not resize image: Operation not supported -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- 1kilobyte -qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for +qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes. qemu-img create -f qcow2 -o size=1kilobyte TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- foobar -qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for +qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes. qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2 @@ -125,84 +125,84 @@ qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2' == Check correct interpretation of suffixes for cluster size == qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off qemu-img create -f qcow2 -o cluster_size=1024b TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off qemu-img create -f qcow2 -o cluster_size=1k TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off qemu-img create -f qcow2 -o cluster_size=1K TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off qemu-img create -f qcow2 -o cluster_size=1M TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1048576 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1048576 lazy_refcounts=off qemu-img create -f qcow2 -o cluster_size=1024.0 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off qemu-img create -f qcow2 -o cluster_size=1024.0b TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off qemu-img create -f qcow2 -o cluster_size=0.5k TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=512 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=512 lazy_refcounts=off qemu-img create -f qcow2 -o cluster_size=0.5K TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=512 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=512 lazy_refcounts=off qemu-img create -f qcow2 -o cluster_size=0.5M TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=524288 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=524288 lazy_refcounts=off == Check compat level option == qemu-img create -f qcow2 -o compat=0.10 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: '0.42' -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.42' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.42' encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: 'foobar' -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='foobar' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='foobar' encryption=off cluster_size=65536 lazy_refcounts=off == Check preallocation option == qemu-img create -f qcow2 -o preallocation=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='off' lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='off' lazy_refcounts=off qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='metadata' lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='metadata' lazy_refcounts=off qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M qemu-img: TEST_DIR/t.qcow2: invalid parameter value: 1234 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='1234' lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='1234' lazy_refcounts=off == Check encryption option == qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o encryption=on TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on cluster_size=65536 lazy_refcounts=off == Check lazy_refcounts option (only with v3) == qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=on TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=on +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=on qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=off qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater) -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=on +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=on *** done diff --git a/tests/qemu-iotests/050.out b/tests/qemu-iotests/050.out index 3f5f7e1e7b..a6cb2e686d 100644 --- a/tests/qemu-iotests/050.out +++ b/tests/qemu-iotests/050.out @@ -1,13 +1,13 @@ QA output created by 050 == Creating images == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760 wrote 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760 wrote 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760 backing_file='TEST_DIR/t.IMGFMT.old' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760 backing_file='TEST_DIR/t.IMGFMT.old' wrote 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index 2c7e808765..f497c5717b 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -1,6 +1,6 @@ QA output created by 051 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base' === Unknown option === @@ -50,6 +50,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DI QEMU X.Y.Z monitor - type 'help' for more information (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 ide0-hd0: TEST_DIR/t.qcow2 (qcow2) + Cache mode: writeback Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1) (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K @@ -85,7 +86,7 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo: could n === With version 2 images enabling lazy refcounts must fail === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: could not open disk image TEST_DIR/t.qcow2: Lazy refcounts require a qcow2 image with at least qemu 1.1 compatibility level diff --git a/tests/qemu-iotests/052.out b/tests/qemu-iotests/052.out index 8617aa2a9e..9dab51c0e8 100644 --- a/tests/qemu-iotests/052.out +++ b/tests/qemu-iotests/052.out @@ -1,5 +1,5 @@ QA output created by 052 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == reading whole image == read 134217728/134217728 bytes at offset 0 diff --git a/tests/qemu-iotests/053.out b/tests/qemu-iotests/053.out index 16464e6dde..8e793b6462 100644 --- a/tests/qemu-iotests/053.out +++ b/tests/qemu-iotests/053.out @@ -1,7 +1,7 @@ QA output created by 053 == Creating single sector image == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=512 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=512 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/054.out b/tests/qemu-iotests/054.out index 7161d6e50b..e6ec430edd 100644 --- a/tests/qemu-iotests/054.out +++ b/tests/qemu-iotests/054.out @@ -2,9 +2,9 @@ QA output created by 054 creating too large image (1 EB) qemu-img: TEST_DIR/t.IMGFMT: The image size is too large for file format 'IMGFMT' (try using a larger cluster size) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1152921504606846976 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1152921504606846976 creating too large image (1 EB) using qcow2.py -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 qemu-img: Could not open 'TEST_DIR/t.qcow2': Image is too big *** done diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 index 451b67ddfb..0872444811 100755 --- a/tests/qemu-iotests/055 +++ b/tests/qemu-iotests/055 @@ -34,10 +34,10 @@ class TestSingleDrive(iotests.QMPTestCase): def setUp(self): # Write data to the image so we can compare later qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleDrive.image_len)) - qemu_io('-c', 'write -P0x5d 0 64k', test_img) - qemu_io('-c', 'write -P0xd5 1M 32k', test_img) - qemu_io('-c', 'write -P0xdc 32M 124k', test_img) - qemu_io('-c', 'write -P0xdc 67043328 64k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 0 64k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 67043328 64k', test_img) self.vm = iotests.VM().add_drive(test_img) self.vm.launch() @@ -115,7 +115,7 @@ class TestSetSpeed(iotests.QMPTestCase): def setUp(self): qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSetSpeed.image_len)) - qemu_io('-c', 'write -P1 0 512', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P1 0 512', test_img) self.vm = iotests.VM().add_drive(test_img) self.vm.launch() @@ -186,10 +186,10 @@ class TestSingleTransaction(iotests.QMPTestCase): def setUp(self): qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleTransaction.image_len)) - qemu_io('-c', 'write -P0x5d 0 64k', test_img) - qemu_io('-c', 'write -P0xd5 1M 32k', test_img) - qemu_io('-c', 'write -P0xdc 32M 124k', test_img) - qemu_io('-c', 'write -P0xdc 67043328 64k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 0 64k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 67043328 64k', test_img) self.vm = iotests.VM().add_drive(test_img) self.vm.launch() diff --git a/tests/qemu-iotests/058 b/tests/qemu-iotests/058 index 14584cdea2..2d5ca85ddc 100755 --- a/tests/qemu-iotests/058 +++ b/tests/qemu-iotests/058 @@ -89,6 +89,9 @@ _supported_fmt qcow2 _supported_proto file _require_command QEMU_NBD +# Use -f raw instead of -f $IMGFMT for the NBD connection +QEMU_IO_NBD="$QEMU_IO -f raw --cache=$CACHEMODE" + echo echo "== preparing image ==" _make_test_img 64M @@ -108,15 +111,15 @@ _export_nbd_snapshot sn1 echo echo "== verifying the exported snapshot with patterns, method 1 ==" -$QEMU_IO -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io -$QEMU_IO -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io +$QEMU_IO_NBD -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io +$QEMU_IO_NBD -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io _export_nbd_snapshot1 sn1 echo echo "== verifying the exported snapshot with patterns, method 2 ==" -$QEMU_IO -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io -$QEMU_IO -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io +$QEMU_IO_NBD -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io +$QEMU_IO_NBD -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io $QEMU_IMG convert "$TEST_IMG" -l sn1 -O qcow2 "$converted_image" diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 index 3c053c29b4..50ca5ce681 100755 --- a/tests/qemu-iotests/059 +++ b/tests/qemu-iotests/059 @@ -106,11 +106,17 @@ _img_info echo echo "=== Converting to streamOptimized from image with small cluster size===" TEST_IMG="$TEST_IMG.qcow2" IMGFMT=qcow2 IMGOPTS="cluster_size=4096" _make_test_img 1G -$QEMU_IO -c "write -P 0xa 0 512" "$TEST_IMG.qcow2" | _filter_qemu_io -$QEMU_IO -c "write -P 0xb 10240 512" "$TEST_IMG.qcow2" | _filter_qemu_io +$QEMU_IO -f qcow2 -c "write -P 0xa 0 512" "$TEST_IMG.qcow2" | _filter_qemu_io +$QEMU_IO -f qcow2 -c "write -P 0xb 10240 512" "$TEST_IMG.qcow2" | _filter_qemu_io $QEMU_IMG convert -f qcow2 -O vmdk -o subformat=streamOptimized "$TEST_IMG.qcow2" "$TEST_IMG" 2>&1 echo +echo "=== Testing monolithicFlat with internally generated JSON file name ===" +IMGOPTS="subformat=monolithicFlat" _make_test_img 64M +$QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.image.filename=$TEST_IMG,file.inject-error.0.event=read_aio" 2>&1 \ + | _filter_testdir | _filter_imgfmt + +echo echo "=== Testing version 3 ===" _use_sample_img iotest-version3.vmdk.bz2 _img_info diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out index 0dadba658f..cbb0de4254 100644 --- a/tests/qemu-iotests/059.out +++ b/tests/qemu-iotests/059.out @@ -2053,6 +2053,10 @@ wrote 512/512 bytes at offset 0 wrote 512/512 bytes at offset 10240 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +=== Testing monolithicFlat with internally generated JSON file name === +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-io: can't open: Cannot use relative extent paths with VMDK descriptor file 'json:{"image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "inject-error.0.event": "read_aio"}' + === Testing version 3 === image: TEST_DIR/iotest-version3.IMGFMT file format: IMGFMT diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 index 9772d365ae..73863bf1f6 100755 --- a/tests/qemu-iotests/060 +++ b/tests/qemu-iotests/060 @@ -77,7 +77,7 @@ $QEMU_IO -c "$OPEN_RW" -c "write -P 0x2a 0 512" | _filter_qemu_io $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features # This information should be available through qemu-img info -$QEMU_IMG info "$TEST_IMG" | _filter_testdir +_img_info --format-specific # Try to open the image R/W (which should fail) $QEMU_IO -c "$OPEN_RW" -c "read 0 512" 2>&1 | _filter_qemu_io \ diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out index 9419da1b41..7d493bbe61 100644 --- a/tests/qemu-iotests/060.out +++ b/tests/qemu-iotests/060.out @@ -2,7 +2,7 @@ QA output created by 060 === Testing L2 reference into L1 === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ERROR cluster 3 refcount=1 reference=3 1 errors were found on the image. @@ -11,10 +11,9 @@ incompatible_features 0x0 qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with active L1 table); further corruption events will be suppressed write failed: Input/output error incompatible_features 0x2 -image: TEST_DIR/t.qcow2 -file format: qcow2 +image: TEST_DIR/t.IMGFMT +file format: IMGFMT virtual size: 64M (67108864 bytes) -disk size: 196K cluster_size: 65536 Format specific information: compat: 1.1 @@ -26,7 +25,7 @@ read 512/512 bytes at offset 0 === Testing cluster data reference into refcount block === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ERROR refcount block 0 refcount=2 ERROR cluster 2 refcount=1 reference=2 @@ -55,7 +54,7 @@ incompatible_features 0x0 === Testing cluster data reference into inactive L2 table === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset 0 @@ -96,7 +95,7 @@ read 512/512 bytes at offset 0 === Testing overlap while COW is in flight === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 536870912 @@ -111,7 +110,7 @@ aio_write failed: No medium found === Testing unallocated image header === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with qcow2_header); further corruption events will be suppressed @@ -119,7 +118,7 @@ write failed: Input/output error === Testing unaligned L1 entry === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qcow2: Marking image as corrupt: L2 table offset 0x42a00 unaligned (L1 index: 0); further corruption events will be suppressed @@ -127,7 +126,7 @@ read failed: Input/output error === Testing unaligned L2 entry === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qcow2: Marking image as corrupt: Data cluster offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed @@ -135,13 +134,13 @@ read failed: Input/output error === Testing unaligned reftable entry === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qcow2: Marking image as corrupt: Refblock offset 0x22a00 unaligned (reftable index: 0); further corruption events will be suppressed write failed: Input/output error === Testing non-fatal corruption on freeing === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qcow2: Image is corrupt: Cannot free unaligned cluster 0x52a00; further non-fatal corruption events will be suppressed @@ -150,7 +149,7 @@ discard 65536/65536 bytes at offset 0 === Testing read-only corruption report === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qcow2: Image is corrupt: Data cluster offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further non-fatal corruption events will be suppressed @@ -159,7 +158,7 @@ read failed: Input/output error === Testing non-fatal and then fatal corruption report === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qcow2: Image is corrupt: Cannot free unaligned cluster 0x52a00; further non-fatal corruption events will be suppressed diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out index 9045544df2..e70f9834d8 100644 --- a/tests/qemu-iotests/061.out +++ b/tests/qemu-iotests/061.out @@ -2,7 +2,7 @@ QA output created by 061 === Testing version downgrade with zero expansion === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) magic 0x514649fb @@ -54,7 +54,7 @@ No errors were found on the image. === Testing dirty version downgrade === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) magic 0x514649fb @@ -111,7 +111,7 @@ No errors were found on the image. === Testing version downgrade with unknown compat/autoclear flags === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 magic 0x514649fb version 3 backing_file_offset 0x0 @@ -159,7 +159,7 @@ No errors were found on the image. === Testing version upgrade and resize === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 65536/65536 bytes at offset 44040192 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) magic 0x514649fb @@ -211,7 +211,7 @@ No errors were found on the image. === Testing dirty lazy_refcounts=off === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) magic 0x514649fb @@ -268,8 +268,8 @@ No errors were found on the image. === Testing backing file === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 131072/131072 bytes at offset 0 @@ -280,7 +280,7 @@ No errors were found on the image. === Testing invalid configurations === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater) qemu-img: Error while amending options: Invalid argument Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater) @@ -298,7 +298,7 @@ qemu-img: Error while amending options: Operation not supported === Testing correct handling of unset value === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Should work: Should not work: Changing the cluster size is not supported. @@ -306,7 +306,7 @@ qemu-img: Error while amending options: Operation not supported === Testing zero expansion on inactive clusters === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 0 @@ -320,7 +320,7 @@ read 131072/131072 bytes at offset 0 === Testing zero expansion on shared L2 table === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) No errors were found on the image. @@ -332,10 +332,10 @@ read 131072/131072 bytes at offset 0 === Testing zero expansion on backed image === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' read 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 0 @@ -348,10 +348,10 @@ read 65536/65536 bytes at offset 65536 === Testing zero expansion on backed inactive clusters === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 0 @@ -367,10 +367,10 @@ read 65536/65536 bytes at offset 65536 === Testing zero expansion on backed image with shared L2 table === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) No errors were found on the image. @@ -382,7 +382,7 @@ read 131072/131072 bytes at offset 0 === Testing preallocated zero expansion on full image === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 67108864/67108864 bytes at offset 0 64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 67108864/67108864 bytes at offset 0 @@ -393,8 +393,8 @@ read 67108864/67108864 bytes at offset 0 === Testing progress report without snapshot === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=4294967296 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=4294967296 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 backing_file='TEST_DIR/t.IMGFMT.base' wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 1073741824 @@ -408,8 +408,8 @@ No errors were found on the image. === Testing progress report with snapshot === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=4294967296 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=4294967296 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 backing_file='TEST_DIR/t.IMGFMT.base' wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 1073741824 diff --git a/tests/qemu-iotests/062.out b/tests/qemu-iotests/062.out index 442d761959..9ddf22b43c 100644 --- a/tests/qemu-iotests/062.out +++ b/tests/qemu-iotests/062.out @@ -2,7 +2,7 @@ QA output created by 062 === Testing snapshotting an image with zero clusters === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 262144/262144 bytes at offset 0 256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) No errors were found on the image. diff --git a/tests/qemu-iotests/066.out b/tests/qemu-iotests/066.out index 9139780f49..7bc9a107d5 100644 --- a/tests/qemu-iotests/066.out +++ b/tests/qemu-iotests/066.out @@ -2,7 +2,7 @@ QA output created by 066 === Testing snapshotting an image with zero clusters === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 262144/262144 bytes at offset 0 256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 262144/262144 bytes at offset 0 diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067 index d025192c83..29cd6b5aff 100755 --- a/tests/qemu-iotests/067 +++ b/tests/qemu-iotests/067 @@ -39,7 +39,7 @@ _supported_os Linux function do_run_qemu() { echo Testing: "$@" - $QEMU -nographic -qmp stdio -serial none "$@" + $QEMU -nographic -qmp-pretty stdio -serial none "$@" echo } diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out index 0f72dcf63a..13ff3cd7aa 100644 --- a/tests/qemu-iotests/067.out +++ b/tests/qemu-iotests/067.out @@ -1,80 +1,770 @@ QA output created by 067 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 === -drive/-device and device_del === Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virtio-blk-pci,drive=disk,id=virtio0 -QMP_VERSION -{"return": {}} -{"return": [{"io-status": "ok", "device": "disk", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false, "corrupt": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "RESET"} -{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}} +{ + QMP_VERSION +} +{ + "return": { + } +} +{ + "return": [ + { + "io-status": "ok", + "device": "disk", + "locked": false, + "removable": false, + "inserted": { + "iops_rd": 0, + "detect_zeroes": "off", + "image": { + "virtual-size": 134217728, + "filename": "TEST_DIR/t.qcow2", + "cluster-size": 65536, + "format": "qcow2", + "actual-size": SIZE, + "format-specific": { + "type": "qcow2", + "data": { + "compat": "1.1", + "lazy-refcounts": false, + "corrupt": false + } + }, + "dirty-flag": false + }, + "iops_wr": 0, + "ro": false, + "backing_file_depth": 0, + "drv": "qcow2", + "iops": 0, + "bps_wr": 0, + "encrypted": false, + "bps": 0, + "bps_rd": 0, + "cache": { + "no-flush": false, + "direct": false, + "writeback": true + }, + "file": "TEST_DIR/t.qcow2", + "encryption_key_missing": false + }, + "type": "unknown" + }, + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "path": "/machine/peripheral/virtio0/virtio-backend" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "device": "virtio0", + "path": "/machine/peripheral/virtio0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "RESET" +} +{ + "return": [ + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "SHUTDOWN" +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "ide1-cd0", + "tray-open": true + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "floppy0", + "tray-open": true + } +} === -drive/device_add and device_del === Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -QMP_VERSION -{"return": {}} -{"return": [{"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false, "corrupt": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "RESET"} -{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}} +{ + QMP_VERSION +} +{ + "return": { + } +} +{ + "return": [ + { + "device": "disk", + "locked": false, + "removable": true, + "inserted": { + "iops_rd": 0, + "detect_zeroes": "off", + "image": { + "virtual-size": 134217728, + "filename": "TEST_DIR/t.qcow2", + "cluster-size": 65536, + "format": "qcow2", + "actual-size": SIZE, + "format-specific": { + "type": "qcow2", + "data": { + "compat": "1.1", + "lazy-refcounts": false, + "corrupt": false + } + }, + "dirty-flag": false + }, + "iops_wr": 0, + "ro": false, + "backing_file_depth": 0, + "drv": "qcow2", + "iops": 0, + "bps_wr": 0, + "encrypted": false, + "bps": 0, + "bps_rd": 0, + "cache": { + "no-flush": false, + "direct": false, + "writeback": true + }, + "file": "TEST_DIR/t.qcow2", + "encryption_key_missing": false + }, + "tray_open": false, + "type": "unknown" + }, + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "path": "/machine/peripheral/virtio0/virtio-backend" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "device": "virtio0", + "path": "/machine/peripheral/virtio0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "RESET" +} +{ + "return": [ + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "SHUTDOWN" +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "ide1-cd0", + "tray-open": true + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "floppy0", + "tray-open": true + } +} === drive_add/device_add and device_del === Testing: -QMP_VERSION -{"return": {}} -{"return": "OK\r\n"} -{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false, "corrupt": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "RESET"} -{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}} +{ + QMP_VERSION +} +{ + "return": { + } +} +{ + "return": "OK\r\n" +} +{ + "return": [ + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "disk", + "locked": false, + "removable": true, + "inserted": { + "iops_rd": 0, + "detect_zeroes": "off", + "image": { + "virtual-size": 134217728, + "filename": "TEST_DIR/t.qcow2", + "cluster-size": 65536, + "format": "qcow2", + "actual-size": SIZE, + "format-specific": { + "type": "qcow2", + "data": { + "compat": "1.1", + "lazy-refcounts": false, + "corrupt": false + } + }, + "dirty-flag": false + }, + "iops_wr": 0, + "ro": false, + "backing_file_depth": 0, + "drv": "qcow2", + "iops": 0, + "bps_wr": 0, + "encrypted": false, + "bps": 0, + "bps_rd": 0, + "cache": { + "no-flush": false, + "direct": false, + "writeback": true + }, + "file": "TEST_DIR/t.qcow2", + "encryption_key_missing": false + }, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "path": "/machine/peripheral/virtio0/virtio-backend" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "device": "virtio0", + "path": "/machine/peripheral/virtio0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "RESET" +} +{ + "return": [ + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "SHUTDOWN" +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "ide1-cd0", + "tray-open": true + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "floppy0", + "tray-open": true + } +} === blockdev_add/device_add and device_del === Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false, "corrupt": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "RESET"} -{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false, "corrupt": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}} +{ + QMP_VERSION +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "return": [ + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "disk", + "locked": false, + "removable": true, + "inserted": { + "iops_rd": 0, + "detect_zeroes": "off", + "image": { + "virtual-size": 134217728, + "filename": "TEST_DIR/t.qcow2", + "cluster-size": 65536, + "format": "qcow2", + "actual-size": SIZE, + "format-specific": { + "type": "qcow2", + "data": { + "compat": "1.1", + "lazy-refcounts": false, + "corrupt": false + } + }, + "dirty-flag": false + }, + "iops_wr": 0, + "ro": false, + "backing_file_depth": 0, + "drv": "qcow2", + "iops": 0, + "bps_wr": 0, + "encrypted": false, + "bps": 0, + "bps_rd": 0, + "cache": { + "no-flush": false, + "direct": false, + "writeback": true + }, + "file": "TEST_DIR/t.qcow2", + "encryption_key_missing": false + }, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "path": "/machine/peripheral/virtio0/virtio-backend" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "device": "virtio0", + "path": "/machine/peripheral/virtio0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "RESET" +} +{ + "return": [ + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "io-status": "ok", + "device": "disk", + "locked": false, + "removable": true, + "inserted": { + "iops_rd": 0, + "detect_zeroes": "off", + "image": { + "virtual-size": 134217728, + "filename": "TEST_DIR/t.qcow2", + "cluster-size": 65536, + "format": "qcow2", + "actual-size": SIZE, + "format-specific": { + "type": "qcow2", + "data": { + "compat": "1.1", + "lazy-refcounts": false, + "corrupt": false + } + }, + "dirty-flag": false + }, + "iops_wr": 0, + "ro": false, + "backing_file_depth": 0, + "drv": "qcow2", + "iops": 0, + "bps_wr": 0, + "encrypted": false, + "bps": 0, + "bps_rd": 0, + "cache": { + "no-flush": false, + "direct": false, + "writeback": true + }, + "file": "TEST_DIR/t.qcow2", + "encryption_key_missing": false + }, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "SHUTDOWN" +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "ide1-cd0", + "tray-open": true + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "floppy0", + "tray-open": true + } +} *** done diff --git a/tests/qemu-iotests/068.out b/tests/qemu-iotests/068.out index abe35a9f8c..84f19b4ffd 100644 --- a/tests/qemu-iotests/068.out +++ b/tests/qemu-iotests/068.out @@ -2,7 +2,7 @@ QA output created by 068 === Saving and reloading a VM state to/from a qcow2 image === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 QEMU X.Y.Z monitor - type 'help' for more information (qemu) s[K[Dsa[K[D[Dsav[K[D[D[Dsave[K[D[D[D[Dsavev[K[D[D[D[D[Dsavevm[K[D[D[D[D[D[Dsavevm [K[D[D[D[D[D[D[Dsavevm 0[K (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K diff --git a/tests/qemu-iotests/069.out b/tests/qemu-iotests/069.out index b48306d5ab..4d7e63cf88 100644 --- a/tests/qemu-iotests/069.out +++ b/tests/qemu-iotests/069.out @@ -2,7 +2,7 @@ QA output created by 069 === Creating an image with a backing file and deleting that file === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=131072 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=131072 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file='TEST_DIR/t.IMGFMT.base' qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open backing file: Could not open 'TEST_DIR/t.IMGFMT.base': No such file or directory *** done diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071 index 3924e51f51..5d61ef6d81 100755 --- a/tests/qemu-iotests/071 +++ b/tests/qemu-iotests/071 @@ -63,12 +63,12 @@ echo TEST_IMG="$TEST_IMG.base" IMGOPTS="" IMGFMT="raw" _make_test_img $IMG_SIZE |\ _filter_imgfmt _make_test_img $IMG_SIZE -$QEMU_IO -c "open -o file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \ +$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \ -c 'read 0 512' -c 'write -P 42 0x38000 512' -c 'read -P 42 0x38000 512' | _filter_qemu_io $QEMU_IO -c 'write -P 42 0 512' "$TEST_IMG" | _filter_qemu_io -$QEMU_IO -c "open -o file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \ +$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \ -c 'read -P 42 0 512' | _filter_qemu_io echo @@ -78,12 +78,12 @@ echo TEST_IMG="$TEST_IMG.base" IMGOPTS="" IMGFMT="raw" _make_test_img $IMG_SIZE |\ _filter_imgfmt _make_test_img $IMG_SIZE -$QEMU_IO -c "open -o file.driver=blkverify,file.raw.filename=$TEST_IMG.base,file.test.driver=$IMGFMT,file.test.file.filename=$TEST_IMG" \ +$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base,file.test.driver=$IMGFMT,file.test.file.filename=$TEST_IMG" \ -c 'read 0 512' -c 'write -P 42 0x38000 512' -c 'read -P 42 0x38000 512' | _filter_qemu_io $QEMU_IO -c 'write -P 42 0 512' "$TEST_IMG" | _filter_qemu_io -$QEMU_IO -c "open -o file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \ +$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \ -c 'read -P 42 0 512' | _filter_qemu_io echo @@ -163,7 +163,7 @@ echo echo "=== Testing blkverify on existing raw block device ===" echo -run_qemu -drive "file=$TEST_IMG.base,if=none,id=drive0" <<EOF +run_qemu -drive "file=$TEST_IMG.base,format=raw,if=none,id=drive0" <<EOF { "execute": "qmp_capabilities" } { "execute": "blockdev-add", "arguments": { diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out index 5f840a9980..46484ff69c 100644 --- a/tests/qemu-iotests/071.out +++ b/tests/qemu-iotests/071.out @@ -2,8 +2,8 @@ QA output created by 071 === Testing blkverify through filename === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset 229376 @@ -12,12 +12,12 @@ read 512/512 bytes at offset 229376 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkverify: read sector_num=0 nb_sectors=4 contents mismatch in sector 0 +blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0 === Testing blkverify through file blockref === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset 229376 @@ -26,14 +26,18 @@ read 512/512 bytes at offset 229376 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkverify: read sector_num=0 nb_sectors=4 contents mismatch in sector 0 +blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0 === Testing blkdebug through filename === +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error read failed: Input/output error === Testing blkdebug through file blockref === +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error read failed: Input/output error === Testing blkdebug on existing block device === @@ -48,6 +52,8 @@ read failed: Input/output error {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}} +qemu-system-x86_64: Failed to flush the L2 table cache: Input/output error +qemu-system-x86_64: Failed to flush the refcount block cache: Input/output error === Testing blkverify on existing block device === @@ -61,7 +67,7 @@ blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0 === Testing blkverify on existing raw block device === -Testing: -drive file=TEST_DIR/t.IMGFMT.base,if=none,id=drive0 +Testing: -drive file=TEST_DIR/t.IMGFMT.base,format=raw,if=none,id=drive0 QMP_VERSION {"return": {}} {"return": {}} @@ -86,5 +92,7 @@ read failed: Input/output error {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}} +qemu-system-x86_64: Failed to flush the L2 table cache: Input/output error +qemu-system-x86_64: Failed to flush the refcount block cache: Input/output error *** done diff --git a/tests/qemu-iotests/072.out b/tests/qemu-iotests/072.out index efe577c1c0..fe949d4781 100644 --- a/tests/qemu-iotests/072.out +++ b/tests/qemu-iotests/072.out @@ -2,7 +2,7 @@ QA output created by 072 === Testing nested image formats === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset 512 diff --git a/tests/qemu-iotests/073.out b/tests/qemu-iotests/073.out index c9b00763b2..733d79ca91 100644 --- a/tests/qemu-iotests/073.out +++ b/tests/qemu-iotests/073.out @@ -1,8 +1,8 @@ QA output created by 073 == creating backing file == -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base' wrote 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/077 b/tests/qemu-iotests/077 index 4dd1bdde20..42a90850c7 100755 --- a/tests/qemu-iotests/077 +++ b/tests/qemu-iotests/077 @@ -52,7 +52,7 @@ echo "== Some concurrent requests involving RMW ==" function test_io() { -echo "open -o file.align=4k blkdebug::$TEST_IMG" +echo "open -o driver=$IMGFMT,file.align=4k blkdebug::$TEST_IMG" # A simple RMW request cat <<EOF aio_write -P 10 0x200 0x200 diff --git a/tests/qemu-iotests/077.out b/tests/qemu-iotests/077.out index ab612344d6..eab14ae2e1 100644 --- a/tests/qemu-iotests/077.out +++ b/tests/qemu-iotests/077.out @@ -1,5 +1,5 @@ QA output created by 077 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == Some concurrent requests involving RMW == wrote XXX/XXX bytes at offset XXX diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 9de337c407..73795f198f 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -78,6 +78,8 @@ poke_file "$TEST_IMG" "$offset_backing_file_offset" "\xff\xff\xff\xff\xff\xff\xf poke_file "$TEST_IMG" "$offset_ext_magic" "\x12\x34\x56\x78" poke_file "$TEST_IMG" "$offset_ext_size" "\x7f\xff\xff\xff" { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x$(printf %x $offset_ext_size)" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x00" { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index f7a943c7a4..6061d84432 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -1,38 +1,40 @@ QA output created by 080 == Huge header size == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size no file open, try 'help open' == Huge unknown header extension == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow2: Invalid backing file offset no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large +no file open, try 'help open' == Huge refcount table size == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow2: Reference count table too large no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow2: Reference count table too large no file open, try 'help open' == Misaligned refcount table == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow2: Invalid reference count table offset no file open, try 'help open' == Huge refcount offset == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow2: Invalid reference count table offset no file open, try 'help open' == Invalid snapshot table == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow2: Too many snapshots no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow2: Too many snapshots @@ -43,13 +45,13 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset no file open, try 'help open' == Hitting snapshot table size limit == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-img: Could not create snapshot 'test': -27 (File too large) read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == Invalid L1 table == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow2: Active L1 table too large no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow2: Active L1 table too large @@ -60,23 +62,23 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset no file open, try 'help open' == Invalid L1 table (with internal snapshot in the image) == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-img: Could not open 'TEST_DIR/t.IMGFMT': L1 table is too small == Invalid backing file size == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow2: Backing file name too long no file open, try 'help open' == Invalid L2 entry (huge physical offset) == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Could not create snapshot 'test': -27 (File too large) qemu-img: Could not create snapshot 'test': -11 (Resource temporarily unavailable) == Invalid snapshot L1 table == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Failed to load snapshot: Snapshot L1 table too large diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081 index ed3c29e13c..9ab93ff89e 100755 --- a/tests/qemu-iotests/081 +++ b/tests/qemu-iotests/081 @@ -59,9 +59,13 @@ function run_qemu() test_quorum=$($QEMU_IMG --help|grep quorum) [ "$test_quorum" = "" ] && _supported_fmt quorum -quorum="file.driver=quorum,file.children.0.file.filename=$TEST_DIR/1.raw" +quorum="driver=raw,file.driver=quorum,file.vote-threshold=2" +quorum="$quorum,file.children.0.file.filename=$TEST_DIR/1.raw" quorum="$quorum,file.children.1.file.filename=$TEST_DIR/2.raw" -quorum="$quorum,file.children.2.file.filename=$TEST_DIR/3.raw,file.vote-threshold=2" +quorum="$quorum,file.children.2.file.filename=$TEST_DIR/3.raw" +quorum="$quorum,file.children.0.driver=raw" +quorum="$quorum,file.children.1.driver=raw" +quorum="$quorum,file.children.2.driver=raw" echo echo "== creating quorum files ==" diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out index 073515ea50..9f57d9d3b5 100644 --- a/tests/qemu-iotests/081.out +++ b/tests/qemu-iotests/081.out @@ -1,9 +1,9 @@ QA output created by 081 == creating quorum files == -Formatting 'TEST_DIR/1.IMGFMT', fmt=IMGFMT size=10485760 -Formatting 'TEST_DIR/2.IMGFMT', fmt=IMGFMT size=10485760 -Formatting 'TEST_DIR/3.IMGFMT', fmt=IMGFMT size=10485760 +Formatting 'TEST_DIR/1.IMGFMT', fmt=IMGFMT size=10485760 +Formatting 'TEST_DIR/2.IMGFMT', fmt=IMGFMT size=10485760 +Formatting 'TEST_DIR/3.IMGFMT', fmt=IMGFMT size=10485760 == writing images == wrote 10485760/10485760 bytes at offset 0 @@ -55,5 +55,5 @@ wrote 10485760/10485760 bytes at offset 0 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == checking that quorum is broken == -qemu-io: can't open: Could not read image for determining its format: Input/output error +read failed: Input/output error *** done diff --git a/tests/qemu-iotests/082 b/tests/qemu-iotests/082 index e64de27733..c83e01e7cd 100755 --- a/tests/qemu-iotests/082 +++ b/tests/qemu-iotests/082 @@ -60,11 +60,11 @@ _img_info # Multiple -o should be merged run_qemu_img create -f $IMGFMT -o cluster_size=4k -o lazy_refcounts=on "$TEST_IMG" $size -run_qemu_img info "$TEST_IMG" +_img_info --format-specific # If the same -o key is specified more than once, the last one wins run_qemu_img create -f $IMGFMT -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k "$TEST_IMG" $size -run_qemu_img info "$TEST_IMG" +_img_info --format-specific run_qemu_img create -f $IMGFMT -o cluster_size=4k,cluster_size=8k "$TEST_IMG" $size _img_info @@ -114,11 +114,11 @@ TEST_IMG="${TEST_IMG}.base" _img_info # Multiple -o should be merged run_qemu_img convert -O $IMGFMT -o cluster_size=4k -o lazy_refcounts=on "$TEST_IMG" "$TEST_IMG".base -run_qemu_img info "$TEST_IMG".base +TEST_IMG="${TEST_IMG}.base" _img_info --format-specific # If the same -o key is specified more than once, the last one wins run_qemu_img convert -O $IMGFMT -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k "$TEST_IMG" "$TEST_IMG".base -run_qemu_img info "$TEST_IMG".base +TEST_IMG="${TEST_IMG}.base" _img_info --format-specific run_qemu_img convert -O $IMGFMT -o cluster_size=4k,cluster_size=8k "$TEST_IMG" "$TEST_IMG".base TEST_IMG="${TEST_IMG}.base" _img_info @@ -157,15 +157,15 @@ echo === amend: Options specified more than once === # Last -f should win run_qemu_img amend -f foo -f $IMGFMT -o lazy_refcounts=on "$TEST_IMG" -run_qemu_img info "$TEST_IMG" +_img_info --format-specific # Multiple -o should be merged run_qemu_img amend -f $IMGFMT -o size=130M -o lazy_refcounts=off "$TEST_IMG" -run_qemu_img info "$TEST_IMG" +_img_info --format-specific # If the same -o key is specified more than once, the last one wins run_qemu_img amend -f $IMGFMT -o size=8M -o lazy_refcounts=on -o size=132M "$TEST_IMG" -run_qemu_img info "$TEST_IMG" +_img_info --format-specific run_qemu_img amend -f $IMGFMT -o size=4M,size=148M "$TEST_IMG" _img_info diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out index 0a3ab5ac90..d0234e6137 100644 --- a/tests/qemu-iotests/082.out +++ b/tests/qemu-iotests/082.out @@ -3,20 +3,17 @@ QA output created by 082 === create: Options specified more than once === Testing: create -f foo -f qcow2 TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=65536 lazy_refcounts=off image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 128M (134217728 bytes) cluster_size: 65536 Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=4096 lazy_refcounts=on - -Testing: info TEST_DIR/t.qcow2 -image: TEST_DIR/t.qcow2 -file format: qcow2 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=4096 lazy_refcounts=on +image: TEST_DIR/t.IMGFMT +file format: IMGFMT virtual size: 128M (134217728 bytes) -disk size: 16K cluster_size: 4096 Format specific information: compat: 1.1 @@ -24,13 +21,10 @@ Format specific information: corrupt: false Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=8192 lazy_refcounts=on - -Testing: info TEST_DIR/t.qcow2 -image: TEST_DIR/t.qcow2 -file format: qcow2 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=8192 lazy_refcounts=on +image: TEST_DIR/t.IMGFMT +file format: IMGFMT virtual size: 128M (134217728 bytes) -disk size: 28K cluster_size: 8192 Format specific information: compat: 1.1 @@ -38,7 +32,7 @@ Format specific information: corrupt: false Testing: create -f qcow2 -o cluster_size=4k,cluster_size=8k TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=8192 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=8192 lazy_refcounts=off image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 128M (134217728 bytes) @@ -143,10 +137,10 @@ lazy_refcounts Postpone refcount updates nocow Turn off copy-on-write (valid only on btrfs) Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2,help' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2,help' encryption=off cluster_size=65536 lazy_refcounts=off Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2,?' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2,?' encryption=off cluster_size=65536 lazy_refcounts=off Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 128M qemu-img: Invalid option list: backing_file=TEST_DIR/t.qcow2, @@ -175,7 +169,7 @@ size Virtual disk size === convert: Options specified more than once === Testing: create -f qcow2 TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=65536 lazy_refcounts=off Testing: convert -f foo -f qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base image: TEST_DIR/t.IMGFMT.base @@ -189,12 +183,9 @@ virtual size: 128M (134217728 bytes) cluster_size: 65536 Testing: convert -O qcow2 -o cluster_size=4k -o lazy_refcounts=on TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base - -Testing: info TEST_DIR/t.qcow2.base -image: TEST_DIR/t.qcow2.base -file format: qcow2 +image: TEST_DIR/t.IMGFMT.base +file format: IMGFMT virtual size: 128M (134217728 bytes) -disk size: 16K cluster_size: 4096 Format specific information: compat: 1.1 @@ -202,12 +193,9 @@ Format specific information: corrupt: false Testing: convert -O qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base - -Testing: info TEST_DIR/t.qcow2.base -image: TEST_DIR/t.qcow2.base -file format: qcow2 +image: TEST_DIR/t.IMGFMT.base +file format: IMGFMT virtual size: 128M (134217728 bytes) -disk size: 28K cluster_size: 8192 Format specific information: compat: 1.1 @@ -351,12 +339,9 @@ size Virtual disk size === amend: Options specified more than once === Testing: amend -f foo -f qcow2 -o lazy_refcounts=on TEST_DIR/t.qcow2 - -Testing: info TEST_DIR/t.qcow2 -image: TEST_DIR/t.qcow2 -file format: qcow2 +image: TEST_DIR/t.IMGFMT +file format: IMGFMT virtual size: 128M (134217728 bytes) -disk size: 196K cluster_size: 65536 Format specific information: compat: 1.1 @@ -364,12 +349,9 @@ Format specific information: corrupt: false Testing: amend -f qcow2 -o size=130M -o lazy_refcounts=off TEST_DIR/t.qcow2 - -Testing: info TEST_DIR/t.qcow2 -image: TEST_DIR/t.qcow2 -file format: qcow2 +image: TEST_DIR/t.IMGFMT +file format: IMGFMT virtual size: 130M (136314880 bytes) -disk size: 196K cluster_size: 65536 Format specific information: compat: 1.1 @@ -377,12 +359,9 @@ Format specific information: corrupt: false Testing: amend -f qcow2 -o size=8M -o lazy_refcounts=on -o size=132M TEST_DIR/t.qcow2 - -Testing: info TEST_DIR/t.qcow2 -image: TEST_DIR/t.qcow2 -file format: qcow2 +image: TEST_DIR/t.IMGFMT +file format: IMGFMT virtual size: 132M (138412032 bytes) -disk size: 196K cluster_size: 65536 Format specific information: compat: 1.1 diff --git a/tests/qemu-iotests/084.out b/tests/qemu-iotests/084.out index 5ece8299c8..5c5ab928c9 100644 --- a/tests/qemu-iotests/084.out +++ b/tests/qemu-iotests/084.out @@ -2,7 +2,7 @@ QA output created by 084 === Statically allocated image creation === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 64M (67108864 bytes) @@ -11,7 +11,7 @@ disk image file size in bytes: 67109888 === Testing image size bounds === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 64M (67108864 bytes) diff --git a/tests/qemu-iotests/086.out b/tests/qemu-iotests/086.out index 9c0bf23718..5ff996101b 100644 --- a/tests/qemu-iotests/086.out +++ b/tests/qemu-iotests/086.out @@ -1,5 +1,5 @@ QA output created by 086 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 1048576/1048576 bytes at offset 2097152 diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out index e8795b3a10..7d38cc26c5 100644 --- a/tests/qemu-iotests/087.out +++ b/tests/qemu-iotests/087.out @@ -1,5 +1,5 @@ QA output created by 087 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 === Missing ID === @@ -45,7 +45,7 @@ QMP_VERSION === Encrypted image === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on Testing: -S QMP_VERSION {"return": {}} @@ -67,7 +67,7 @@ QMP_VERSION === Missing driver === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on Testing: -S QMP_VERSION {"return": {}} diff --git a/tests/qemu-iotests/088.out b/tests/qemu-iotests/088.out index d961609e49..6e6bfcaf90 100644 --- a/tests/qemu-iotests/088.out +++ b/tests/qemu-iotests/088.out @@ -1,7 +1,7 @@ QA output created by 088 == Invalid block size == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 0 no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 0 diff --git a/tests/qemu-iotests/089 b/tests/qemu-iotests/089 index dffc977e1c..6f74cecde2 100755 --- a/tests/qemu-iotests/089 +++ b/tests/qemu-iotests/089 @@ -65,7 +65,8 @@ $QEMU_IO -c 'write -P 42 0 512' -c 'write -P 23 512 512' \ $QEMU_IMG convert -f raw -O $IMGFMT "$TEST_IMG.base" "$TEST_IMG" -$QEMU_IO -c 'read -P 42 0 512' -c 'read -P 23 512 512' \ +$QEMU_IO_PROG --cache $CACHEMODE \ + -c 'read -P 42 0 512' -c 'read -P 23 512 512' \ -c 'read -P 66 1024 512' "json:{ \"driver\": \"$IMGFMT\", \"file\": { @@ -91,7 +92,8 @@ $QEMU_IO -c 'write -P 42 0x38000 512' "$TEST_IMG" | _filter_qemu_io # The "image.filename" part tests whether "a": { "b": "c" } and "a.b": "c" do # the same (which they should). -$QEMU_IO -c 'read -P 42 0x38000 512' "json:{ +$QEMU_IO_PROG --cache $CACHEMODE \ + -c 'read -P 42 0x38000 512' "json:{ \"driver\": \"$IMGFMT\", \"file\": { \"driver\": \"blkdebug\", diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out index b2b0390818..a6d37118c7 100644 --- a/tests/qemu-iotests/089.out +++ b/tests/qemu-iotests/089.out @@ -2,7 +2,7 @@ QA output created by 089 === Testing nested image formats === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset 512 @@ -21,9 +21,11 @@ read 512/512 bytes at offset 0 === Testing blkdebug === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 512/512 bytes at offset 229376 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error read failed: Input/output error === Testing qemu-img info output === diff --git a/tests/qemu-iotests/090.out b/tests/qemu-iotests/090.out index 2df93e0d97..66ca5d58da 100644 --- a/tests/qemu-iotests/090.out +++ b/tests/qemu-iotests/090.out @@ -1,5 +1,5 @@ QA output created by 090 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 65536 diff --git a/tests/qemu-iotests/091.out b/tests/qemu-iotests/091.out index a2e0122966..5017f8c2d9 100644 --- a/tests/qemu-iotests/091.out +++ b/tests/qemu-iotests/091.out @@ -1,5 +1,5 @@ QA output created by 091 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 === Starting QEMU VM1 === diff --git a/tests/qemu-iotests/092.out b/tests/qemu-iotests/092.out index 496d8f0a63..c5c60f9178 100644 --- a/tests/qemu-iotests/092.out +++ b/tests/qemu-iotests/092.out @@ -1,7 +1,7 @@ QA output created by 092 == Invalid cluster size == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k @@ -12,7 +12,7 @@ qemu-io: can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and no file open, try 'help open' == Invalid L2 table size == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k @@ -23,14 +23,14 @@ qemu-io: can't open device TEST_DIR/t.qcow: L2 table size must be between 512 an no file open, try 'help open' == Invalid size == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow: Image too large no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow: Image too large no file open, try 'help open' == Invalid backing file length == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow: Backing file name too long no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow: Backing file name too long diff --git a/tests/qemu-iotests/095.out b/tests/qemu-iotests/095.out index cc86efacc6..267c4836e5 100644 --- a/tests/qemu-iotests/095.out +++ b/tests/qemu-iotests/095.out @@ -1,7 +1,7 @@ QA output created by 095 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=5242880 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=104857600 backing_file='TEST_DIR/t.IMGFMT.base' -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=104857600 backing_file='TEST_DIR/t.IMGFMT.snp1' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=5242880 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=104857600 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=104857600 backing_file='TEST_DIR/t.IMGFMT.snp1' === Base image info before commit and resize === image: TEST_DIR/t.IMGFMT.base diff --git a/tests/qemu-iotests/097.out b/tests/qemu-iotests/097.out index 1cb7764fe8..81651f496c 100644 --- a/tests/qemu-iotests/097.out +++ b/tests/qemu-iotests/097.out @@ -2,9 +2,9 @@ QA output created by 097 === Test pass 0 === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.itmd' +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.itmd' wrote 196608/196608 bytes at offset 0 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 65536 @@ -31,9 +31,9 @@ Offset Length File === Test pass 1 === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.itmd' +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.itmd' wrote 196608/196608 bytes at offset 0 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 65536 @@ -61,9 +61,9 @@ Offset Length File === Test pass 2 === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.itmd' +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.itmd' wrote 196608/196608 bytes at offset 0 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 65536 @@ -91,9 +91,9 @@ Offset Length File === Test pass 3 === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.itmd' +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.itmd' wrote 196608/196608 bytes at offset 0 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 65536 diff --git a/tests/qemu-iotests/098.out b/tests/qemu-iotests/098.out index 586dfc809f..e08a189b4f 100644 --- a/tests/qemu-iotests/098.out +++ b/tests/qemu-iotests/098.out @@ -2,8 +2,8 @@ QA output created by 098 === l1_update === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error @@ -11,8 +11,8 @@ No errors were found on the image. === empty_image_prepare === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error @@ -24,8 +24,8 @@ No errors were found on the image. === reftable_update === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error @@ -38,8 +38,8 @@ No errors were found on the image. === refblock_alloc === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error diff --git a/tests/qemu-iotests/099 b/tests/qemu-iotests/099 index ffc7ea795a..948afff28b 100755 --- a/tests/qemu-iotests/099 +++ b/tests/qemu-iotests/099 @@ -44,7 +44,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow qcow2 qed vdi vhdx vmdk vpc _supported_proto file _supported_os Linux - +_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \ + "subformat=twoGbMaxExtentSparse" function do_run_qemu() { @@ -107,8 +108,21 @@ echo # generate a JSON object here as well test_qemu "file.driver=blkverify,file.raw.filename=$TEST_IMG.compare,file.test.file.driver=blkdebug,file.test.file.image.filename=$TEST_IMG,file.test.file.inject-error.0.event=l1_update" +echo +echo '=== Testing plain filename for blkdebug ===' +echo + +touch "$TEST_DIR/blkdebug.conf" +test_qemu "file.driver=blkdebug,file.config=$TEST_DIR/blkdebug.conf,file.image.filename=$TEST_IMG" + +echo +echo '=== Testing plain filename for blkdebug without configuration file ===' +echo + +test_qemu "file.driver=blkdebug,file.image.filename=$TEST_IMG" + -rm -f "$TEST_IMG.compare" +rm -f "$TEST_IMG.compare" "$TEST_DIR/blkdebug.conf" # success, all done echo "*** done" diff --git a/tests/qemu-iotests/099.out b/tests/qemu-iotests/099.out index 55be4d4c56..8cce627529 100644 --- a/tests/qemu-iotests/099.out +++ b/tests/qemu-iotests/099.out @@ -1,6 +1,6 @@ QA output created by 099 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 -Formatting 'TEST_DIR/t.IMGFMT.compare', fmt=raw size=131072 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 +Formatting 'TEST_DIR/t.IMGFMT.compare', fmt=raw size=131072 === Testing simple filename for blkverify === @@ -12,9 +12,17 @@ blkverify:TEST_DIR/t.IMGFMT.compare:TEST_DIR/t.IMGFMT === Testing JSON filename for blkdebug === -json:{"driver": "IMGFMT", "file": {"inject-error": [{"immediately": false, "once": false, "state": 0, "sector": -1, "event": "l1_update", "errno": 5}], "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug"}} +json:{"driver": "IMGFMT", "file": {"image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "inject-error.0.event": "l1_update"}} === Testing indirectly enforced JSON filename === -json:{"driver": "raw", "file": {"test": {"driver": "IMGFMT", "file": {"inject-error": [{"immediately": false, "once": false, "state": 0, "sector": -1, "event": "l1_update", "errno": 5}], "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug"}}, "driver": "blkverify", "raw": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.compare"}}} +json:{"driver": "raw", "file": {"test": {"driver": "IMGFMT", "file": {"image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "inject-error.0.event": "l1_update"}}, "driver": "blkverify", "raw": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.compare"}}} + +=== Testing plain filename for blkdebug === + +blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT + +=== Testing plain filename for blkdebug without configuration file === + +blkdebug::TEST_DIR/t.IMGFMT *** done diff --git a/tests/qemu-iotests/100.out b/tests/qemu-iotests/100.out index 2d6e9f0a7d..05649038d9 100644 --- a/tests/qemu-iotests/100.out +++ b/tests/qemu-iotests/100.out @@ -1,7 +1,7 @@ QA output created by 100 == Single request == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -12,7 +12,7 @@ read 4096/4096 bytes at offset 4096 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == Sequential requests == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 8192/8192 bytes at offset 0 8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -25,7 +25,7 @@ read 4096/4096 bytes at offset 8192 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == Superset overlapping requests == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 6144/6144 bytes at offset 0 6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -38,7 +38,7 @@ read 4096/4096 bytes at offset 4096 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == Subset overlapping requests == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 6144/6144 bytes at offset 1024 6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -51,7 +51,7 @@ read 4096/4096 bytes at offset 4096 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == Head overlapping requests == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 6144/6144 bytes at offset 0 6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -62,7 +62,7 @@ read 4096/4096 bytes at offset 4096 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == Tail overlapping requests == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 6144/6144 bytes at offset 2048 6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -73,7 +73,7 @@ read 4096/4096 bytes at offset 4096 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == Disjoint requests == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 8192/8192 bytes at offset 0 8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/103.out b/tests/qemu-iotests/103.out index ddf6b5a075..ee705b05f0 100644 --- a/tests/qemu-iotests/103.out +++ b/tests/qemu-iotests/103.out @@ -1,5 +1,5 @@ QA output created by 103 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/104.out b/tests/qemu-iotests/104.out index de27852e35..ab8d892c2a 100644 --- a/tests/qemu-iotests/104.out +++ b/tests/qemu-iotests/104.out @@ -1,11 +1,11 @@ QA output created by 104 === Check qemu-img info output === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024 image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 1.0K (1024 bytes) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1234 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1234 image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 1.5K (1536 bytes) diff --git a/tests/qemu-iotests/107.out b/tests/qemu-iotests/107.out index 93445b731f..24f85d8c56 100644 --- a/tests/qemu-iotests/107.out +++ b/tests/qemu-iotests/107.out @@ -2,7 +2,7 @@ QA output created by 107 === Updates should not write random data === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 65528/65528 bytes at offset 196616 diff --git a/tests/qemu-iotests/108.out b/tests/qemu-iotests/108.out index 824d5cf139..75bab8dc84 100644 --- a/tests/qemu-iotests/108.out +++ b/tests/qemu-iotests/108.out @@ -2,7 +2,7 @@ QA output created by 108 === Repairing an image without any refcount table === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ERROR cluster 0 refcount=0 reference=1 @@ -22,7 +22,7 @@ read 65536/65536 bytes at offset 0 === Repairing unreferenced data cluster in new refblock area === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 111104/111104 bytes at offset 0 108.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 131072 @@ -49,7 +49,7 @@ read 512/512 bytes at offset 111104 --- Otherwise clean --- -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Repairing refcount block 1 is outside image The following inconsistencies were found and repaired: @@ -61,7 +61,7 @@ No errors were found on the image. --- Refblock is unallocated --- -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Repairing refcount block 1 is outside image ERROR cluster 16 refcount=0 reference=1 Rebuilding refcount structure @@ -78,7 +78,7 @@ No errors were found on the image. --- Signed overflow after the refblock --- -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Repairing refcount block 1 is outside image ERROR could not resize image: Invalid argument Rebuilding refcount structure @@ -94,7 +94,7 @@ No errors were found on the image. --- Unsigned overflow after the refblock --- -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Repairing refcount block 1 is outside image ERROR could not resize image: Invalid argument Rebuilding refcount structure diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109 new file mode 100755 index 0000000000..0b668da850 --- /dev/null +++ b/tests/qemu-iotests/109 @@ -0,0 +1,132 @@ +#!/bin/bash +# +# Test writing image headers of other formats into raw images +# +# Copyright (C) 2014 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=kwolf@redhat.com + +seq="$(basename $0)" +echo "QA output created by $seq" + +here="$PWD" +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + rm -f $TEST_IMG.src + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter +. ./common.qemu + +_supported_fmt raw +_supported_proto file +_supported_os Linux + +qemu_comm_method=qmp + +function run_qemu() +{ + local raw_img="$1" + local source_img="$2" + local qmp_format="$3" + local qmp_event="$4" + + _launch_qemu -drive file="${source_img}",format=raw,cache=${CACHEMODE},id=src + _send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'qmp_capabilities' }" "return" + + _send_qemu_cmd $QEMU_HANDLE \ + "{'execute':'drive-mirror', 'arguments':{ + 'device': 'src', 'target': '$raw_img', $qmp_format + 'mode': 'existing', 'sync': 'full'}}" \ + "return" + + _send_qemu_cmd $QEMU_HANDLE '' "$qmp_event" + _send_qemu_cmd $QEMU_HANDLE '{"execute":"query-block-jobs"}' "return" + _cleanup_qemu +} + +for fmt in qcow qcow2 qed vdi vmdk vpc; do + + echo + echo "=== Writing a $fmt header into raw ===" + echo + + _make_test_img 64M + TEST_IMG="$TEST_IMG.src" IMGFMT=$fmt _make_test_img 64M + + # This first test should fail: The image format was probed, we may not + # write an image header at the start of the image + run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" + $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io + + + # When raw was explicitly specified, the same must succeed + run_qemu "$TEST_IMG" "$TEST_IMG.src" "'format': 'raw'," "BLOCK_JOB_READY" + $QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src" + +done + + +for sample_img in empty.bochs iotest-dirtylog-10G-4M.vhdx parallels-v1 \ + simple-pattern.cloop; do + + echo + echo "=== Copying sample image $sample_img into raw ===" + echo + + # Can't use _use_sample_img because that isn't designed to be used multiple + # times and it overwrites $TEST_IMG (both breaks cleanup) + _make_test_img 64M + bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src" + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" + $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "'format': 'raw'," "BLOCK_JOB_READY" + # qemu-img compare can't handle unaligned file sizes + $QEMU_IMG resize -f raw "$TEST_IMG.src" +0 + $QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src" +done + +echo +echo "=== Write legitimate MBR into raw ===" +echo + +for sample_img in grub_mbr.raw; do + _make_test_img 64M + bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src" + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_READY" + $QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src" + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "'format': 'raw'," "BLOCK_JOB_READY" + $QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src" +done + + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out new file mode 100644 index 0000000000..7db92c9ce8 --- /dev/null +++ b/tests/qemu-iotests/109.out @@ -0,0 +1,231 @@ +QA output created by 109 + +=== Writing a qcow header into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 1024, "offset": 1024, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. + +=== Writing a qcow2 header into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 197120, "offset": 197120, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. + +=== Writing a qed header into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 327680, "offset": 327680, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. + +=== Writing a vdi header into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 1024, "offset": 1024, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. + +=== Writing a vmdk header into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 65536, "offset": 65536, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. + +=== Writing a vpc header into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2560, "offset": 2560, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. + +=== Copying sample image empty.bochs into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2560, "offset": 2560, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Image resized. +Warning: Image size mismatch! +Images are identical. + +=== Copying sample image iotest-dirtylog-10G-4M.vhdx into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 31457280, "offset": 31457280, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Image resized. +Warning: Image size mismatch! +Images are identical. + +=== Copying sample image parallels-v1 into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 327680, "offset": 327680, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Image resized. +Warning: Image size mismatch! +Images are identical. + +=== Copying sample image simple-pattern.cloop into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2048, "offset": 2048, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Image resized. +Warning: Image size mismatch! +Images are identical. + +=== Write legitimate MBR into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 512, "offset": 512, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 512, "offset": 512, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. +*** done diff --git a/tests/qemu-iotests/113 b/tests/qemu-iotests/113 new file mode 100755 index 0000000000..a2cd96b176 --- /dev/null +++ b/tests/qemu-iotests/113 @@ -0,0 +1,76 @@ +#!/bin/bash +# +# Test case for accessing creation options on image formats and +# protocols not supporting image creation +# +# Copyright (C) 2014 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=mreitz@redhat.com + +seq="$(basename $0)" +echo "QA output created by $seq" + +here="$PWD" +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +# We can only test one format here because we need its sample file +_supported_fmt bochs +_supported_proto nbd +_supported_os Linux + +echo +echo '=== Unsupported image creation in qemu-img create ===' +echo + +$QEMU_IMG create -f $IMGFMT nbd://example.com 2>&1 64M | _filter_imgfmt + +echo +echo '=== Unsupported image creation in qemu-img convert ===' +echo + +# We could use any input image format here, but this is a bochs test, so just +# use the bochs image +_use_sample_img empty.bochs.bz2 +$QEMU_IMG convert -f $IMGFMT -O $IMGFMT "$TEST_IMG" nbd://example.com 2>&1 \ + | _filter_imgfmt + +echo +echo '=== Unsupported format in qemu-img amend ===' +echo + +# The protocol does not matter here +_use_sample_img empty.bochs.bz2 +$QEMU_IMG amend -f $IMGFMT -o foo=bar "$TEST_IMG" 2>&1 | _filter_imgfmt + + +# success, all done +echo +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/113.out b/tests/qemu-iotests/113.out new file mode 100644 index 0000000000..00bdfd6887 --- /dev/null +++ b/tests/qemu-iotests/113.out @@ -0,0 +1,15 @@ +QA output created by 113 + +=== Unsupported image creation in qemu-img create === + +qemu-img: nbd://example.com: Format driver 'IMGFMT' does not support image creation + +=== Unsupported image creation in qemu-img convert === + +qemu-img: Format driver 'IMGFMT' does not support image creation + +=== Unsupported format in qemu-img amend === + +qemu-img: Format driver 'IMGFMT' does not support any options to amend + +*** done diff --git a/tests/qemu-iotests/114 b/tests/qemu-iotests/114 new file mode 100755 index 0000000000..d02e7ffbe3 --- /dev/null +++ b/tests/qemu-iotests/114 @@ -0,0 +1,61 @@ +#!/bin/bash +# +# Test invalid backing file format in qcow2 images +# +# Copyright (C) 2014 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=kwolf@redhat.com + +seq="$(basename $0)" +echo "QA output created by $seq" + +here="$PWD" +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto generic +_supported_os Linux + + +TEST_IMG="$TEST_IMG.base" _make_test_img 64M +_make_test_img -b "$TEST_IMG.base" 64M + +# Set an invalid backing file format +$PYTHON qcow2.py "$TEST_IMG" add-header-ext 0xE2792ACA "foo" +_img_info + +# Try opening the image. Should fail (and not probe) in the first case, but +# overriding the backing file format should be possible. +$QEMU_IO -c "open $TEST_IMG" -c "read 0 4k" 2>&1 | _filter_qemu_io | _filter_testdir +$QEMU_IO -c "open -o backing.driver=$IMGFMT $TEST_IMG" -c "read 0 4k" | _filter_qemu_io + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/114.out b/tests/qemu-iotests/114.out new file mode 100644 index 0000000000..6c6b21085a --- /dev/null +++ b/tests/qemu-iotests/114.out @@ -0,0 +1,13 @@ +QA output created by 114 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 64M (67108864 bytes) +cluster_size: 65536 +backing file: TEST_DIR/t.IMGFMT.base +backing file format: foo +qemu-io: can't open device TEST_DIR/t.qcow2: Could not open backing file: Unknown driver 'foo' +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +*** done diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common index 9e12bec2bf..1e556bbb7d 100644 --- a/tests/qemu-iotests/common +++ b/tests/qemu-iotests/common @@ -289,10 +289,10 @@ testlist options if [ ! -z "$DISPLAY" ] then - which xdiff >/dev/null 2>&1 && diff=xdiff - which gdiff >/dev/null 2>&1 && diff=gdiff - which tkdiff >/dev/null 2>&1 && diff=tkdiff - which xxdiff >/dev/null 2>&1 && diff=xxdiff + command -v xdiff >/dev/null 2>&1 && diff=xdiff + command -v gdiff >/dev/null 2>&1 && diff=gdiff + command -v tkdiff >/dev/null 2>&1 && diff=tkdiff + command -v xxdiff >/dev/null 2>&1 && diff=xxdiff fi ;; @@ -391,7 +391,7 @@ BEGIN { for (t='$start'; t<='$end'; t++) printf "%03d\n",t }' \ done # Set qemu-io cache mode with $CACHEMODE we have -QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --cache $CACHEMODE" +QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT --cache $CACHEMODE" # Set default options for qemu-img create -o if they were not specified _set_default_imgopts diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config index bd6790be63..91a5ef696b 100644 --- a/tests/qemu-iotests/common.config +++ b/tests/qemu-iotests/common.config @@ -47,7 +47,7 @@ export PWD=`pwd` # $1 = prog to look for, $2* = default pathnames if not found in $PATH set_prog_path() { - p=`which $1 2> /dev/null` + p=`command -v $1 2> /dev/null` if [ -n "$p" -a -x "$p" ]; then echo $p return 0 diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index 3acdb307f4..6c14590594 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -150,7 +150,7 @@ _filter_win32() _filter_qemu_io() { _filter_win32 | sed -e "s/[0-9]* ops\; [0-9/:. sec]* ([0-9/.inf]* [EPTGMKiBbytes]*\/sec and [0-9/.inf]* ops\/sec)/X ops\; XX:XX:XX.X (XXX YYY\/sec and XXX ops\/sec)/" \ - -e "s/: line [0-9][0-9]*: *[0-9][0-9]*\( Aborted\)/:\1/" \ + -e "s/: line [0-9][0-9]*: *[0-9][0-9]*\( Aborted\| Killed\)/:\1/" \ -e "s/qemu-io> //g" } @@ -167,7 +167,9 @@ _filter_qmp() { _filter_win32 | \ sed -e 's#\("\(micro\)\?seconds": \)[0-9]\+#\1 TIMESTAMP#g' \ - -e 's#^{"QMP":.*}$#QMP_VERSION#' + -e 's#^{"QMP":.*}$#QMP_VERSION#' \ + -e '/^ "QMP": {\s*$/, /^ }\s*$/ c\' \ + -e ' QMP_VERSION' } # replace driver-specific options in the "Formatting..." line diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu index ee7ebb4c1d..8e618b5149 100644 --- a/tests/qemu-iotests/common.qemu +++ b/tests/qemu-iotests/common.qemu @@ -153,8 +153,9 @@ function _launch_qemu() mkfifo "${fifo_out}" mkfifo "${fifo_in}" - "${QEMU}" -nographic -serial none ${comm} -machine accel=qtest "${@}" 2>&1 \ + "${QEMU}" -nographic -serial none ${comm} -machine accel=qtest "${@}" \ >"${fifo_out}" \ + 2>&1 \ <"${fifo_in}" & QEMU_PID[${_QEMU_HANDLE}]=$! diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 9c49deb3dd..3b14053790 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -175,7 +175,9 @@ _cleanup_test_img() case "$IMGPROTO" in nbd) - kill $QEMU_NBD_PID + if [ -n "$QEMU_NBD_PID" ]; then + kill $QEMU_NBD_PID + fi rm -f "$TEST_IMG_FILE" ;; file) @@ -213,6 +215,13 @@ _check_test_img() _img_info() { + if [[ "$1" == "--format-specific" ]]; then + local format_specific=1 + shift + else + local format_specific=0 + fi + discard=0 regex_json_spec_start='^ *"format-specific": \{' $QEMU_IMG info "$@" "$TEST_IMG" 2>&1 | \ @@ -222,7 +231,9 @@ _img_info() -e "/^disk size:/ D" \ -e "/actual-size/ D" | \ while IFS='' read line; do - if [[ $line == "Format specific information:" ]]; then + if [[ $format_specific == 1 ]]; then + discard=0 + elif [[ $line == "Format specific information:" ]]; then discard=1 elif [[ $line =~ $regex_json_spec_start ]]; then discard=2 diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 7dfe46940a..a4742c6d01 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -111,4 +111,7 @@ 105 rw auto quick 107 rw auto quick 108 rw auto quick +109 rw auto 111 rw auto quick +113 rw auto quick +114 rw auto quick diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py index 2058596964..9cc4cf7d08 100755 --- a/tests/qemu-iotests/qcow2.py +++ b/tests/qemu-iotests/qcow2.py @@ -7,6 +7,10 @@ import string class QcowHeaderExtension: def __init__(self, magic, length, data): + if length % 8 != 0: + padding = 8 - (length % 8) + data += "\0" * padding + self.magic = magic self.length = length self.data = data diff --git a/tests/qemu-iotests/sample_images/grub_mbr.raw.bz2 b/tests/qemu-iotests/sample_images/grub_mbr.raw.bz2 Binary files differnew file mode 100644 index 0000000000..8585878bcd --- /dev/null +++ b/tests/qemu-iotests/sample_images/grub_mbr.raw.bz2 diff --git a/tests/usb-hcd-uhci-test.c b/tests/usb-hcd-uhci-test.c index 8cf2c5bcaa..6d631cf366 100644 --- a/tests/usb-hcd-uhci-test.c +++ b/tests/usb-hcd-uhci-test.c @@ -87,7 +87,7 @@ int main(int argc, char **argv) qtest_add_func("/uhci/pci/hotplug/usb-storage", test_usb_storage_hotplug); qtest_start("-device piix3-usb-uhci,id=uhci,addr=1d.0" - " -drive id=drive0,if=none,file=/dev/null" + " -drive id=drive0,if=none,file=/dev/null,format=raw" " -device usb-tablet,bus=uhci.0,port=1"); ret = g_test_run(); qtest_end(); diff --git a/tests/usb-hcd-xhci-test.c b/tests/usb-hcd-xhci-test.c index b1a7dec5bb..adf261e963 100644 --- a/tests/usb-hcd-xhci-test.c +++ b/tests/usb-hcd-xhci-test.c @@ -91,7 +91,7 @@ int main(int argc, char **argv) qtest_add_func("/xhci/pci/hotplug/usb-uas", test_usb_uas_hotplug); qtest_start("-device nec-usb-xhci,id=xhci" - " -drive id=drive0,if=none,file=/dev/null"); + " -drive id=drive0,if=none,file=/dev/null,format=raw"); ret = g_test_run(); qtest_end(); diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c index ead3911e28..89d7cbf919 100644 --- a/tests/virtio-blk-test.c +++ b/tests/virtio-blk-test.c @@ -68,8 +68,8 @@ static QPCIBus *test_start(void) g_assert_cmpint(ret, ==, 0); close(fd); - cmdline = g_strdup_printf("-drive if=none,id=drive0,file=%s " - "-drive if=none,id=drive1,file=/dev/null " + cmdline = g_strdup_printf("-drive if=none,id=drive0,file=%s,format=raw " + "-drive if=none,id=drive1,file=/dev/null,format=raw " "-device virtio-blk-pci,id=drv0,drive=drive0," "addr=%x.%x", tmp_path, PCI_SLOT, PCI_FN); diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c index 41f9602e44..989f8251c4 100644 --- a/tests/virtio-scsi-test.c +++ b/tests/virtio-scsi-test.c @@ -52,8 +52,8 @@ int main(int argc, char **argv) qtest_add_func("/virtio/scsi/pci/nop", pci_nop); qtest_add_func("/virtio/scsi/pci/hotplug", hotplug); - qtest_start("-drive id=drv0,if=none,file=/dev/null " - "-drive id=drv1,if=none,file=/dev/null " + qtest_start("-drive id=drv0,if=none,file=/dev/null,format=raw " + "-drive id=drv1,if=none,file=/dev/null,format=raw " "-device virtio-scsi-pci,id=vscsi0 " "-device scsi-hd,bus=vscsi0.0,drive=drv0"); ret = g_test_run(); diff --git a/ui/keymaps.c b/ui/keymaps.c index 80d658d907..49410ae9d1 100644 --- a/ui/keymaps.c +++ b/ui/keymaps.c @@ -26,18 +26,20 @@ #include "sysemu/sysemu.h" static int get_keysym(const name2keysym_t *table, - const char *name) + const char *name) { const name2keysym_t *p; for(p = table; p->name != NULL; p++) { - if (!strcmp(p->name, name)) + if (!strcmp(p->name, name)) { return p->keysym; + } } if (name[0] == 'U' && strlen(name) == 5) { /* try unicode Uxxxx */ char *end; int ret = (int)strtoul(name + 1, &end, 16); - if (*end == '\0' && ret > 0) - return ret; + if (*end == '\0' && ret > 0) { + return ret; + } } return 0; } @@ -46,19 +48,20 @@ static int get_keysym(const name2keysym_t *table, static void add_to_key_range(struct key_range **krp, int code) { struct key_range *kr; for (kr = *krp; kr; kr = kr->next) { - if (code >= kr->start && code <= kr->end) - break; - if (code == kr->start - 1) { - kr->start--; - break; - } - if (code == kr->end + 1) { - kr->end++; - break; - } + if (code >= kr->start && code <= kr->end) { + break; + } + if (code == kr->start - 1) { + kr->start--; + break; + } + if (code == kr->end + 1) { + kr->end++; + break; + } } if (kr == NULL) { - kr = g_malloc0(sizeof(*kr)); + kr = g_malloc0(sizeof(*kr)); kr->start = kr->end = code; kr->next = *krp; *krp = kr; @@ -67,30 +70,30 @@ static void add_to_key_range(struct key_range **krp, int code) { static void add_keysym(char *line, int keysym, int keycode, kbd_layout_t *k) { if (keysym < MAX_NORMAL_KEYCODE) { - //fprintf(stderr,"Setting keysym %s (%d) to %d\n",line,keysym,keycode); - k->keysym2keycode[keysym] = keycode; + /* fprintf(stderr,"Setting keysym %s (%d) to %d\n", + line, keysym, keycode); */ + k->keysym2keycode[keysym] = keycode; } else { - if (k->extra_count >= MAX_EXTRA_COUNT) { - fprintf(stderr, - "Warning: Could not assign keysym %s (0x%x) because of memory constraints.\n", - line, keysym); - } else { + if (k->extra_count >= MAX_EXTRA_COUNT) { + fprintf(stderr, "Warning: Could not assign keysym %s (0x%x)" + " because of memory constraints.\n", line, keysym); + } else { #if 0 - fprintf(stderr, "Setting %d: %d,%d\n", - k->extra_count, keysym, keycode); + fprintf(stderr, "Setting %d: %d,%d\n", + k->extra_count, keysym, keycode); #endif - k->keysym2keycode_extra[k->extra_count]. - keysym = keysym; - k->keysym2keycode_extra[k->extra_count]. - keycode = keycode; - k->extra_count++; - } + k->keysym2keycode_extra[k->extra_count]. + keysym = keysym; + k->keysym2keycode_extra[k->extra_count]. + keycode = keycode; + k->extra_count++; + } } } static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table, - const char *language, - kbd_layout_t * k) + const char *language, + kbd_layout_t *k) { FILE *f; char * filename; @@ -101,69 +104,78 @@ static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table, f = filename ? fopen(filename, "r") : NULL; g_free(filename); if (!f) { - fprintf(stderr, - "Could not read keymap file: '%s'\n", language); - return NULL; + fprintf(stderr, "Could not read keymap file: '%s'\n", language); + return NULL; } - if (!k) - k = g_malloc0(sizeof(kbd_layout_t)); + if (!k) { + k = g_malloc0(sizeof(kbd_layout_t)); + } for(;;) { - if (fgets(line, 1024, f) == NULL) + if (fgets(line, 1024, f) == NULL) { break; + } len = strlen(line); - if (len > 0 && line[len - 1] == '\n') + if (len > 0 && line[len - 1] == '\n') { line[len - 1] = '\0'; - if (line[0] == '#') - continue; - if (!strncmp(line, "map ", 4)) - continue; - if (!strncmp(line, "include ", 8)) { - parse_keyboard_layout(table, line + 8, k); + } + if (line[0] == '#') { + continue; + } + if (!strncmp(line, "map ", 4)) { + continue; + } + if (!strncmp(line, "include ", 8)) { + parse_keyboard_layout(table, line + 8, k); } else { - char *end_of_keysym = line; - while (*end_of_keysym != 0 && *end_of_keysym != ' ') - end_of_keysym++; - if (*end_of_keysym) { - int keysym; - *end_of_keysym = 0; - keysym = get_keysym(table, line); - if (keysym == 0) { - // fprintf(stderr, "Warning: unknown keysym %s\n", line); - } else { - const char *rest = end_of_keysym + 1; + char *end_of_keysym = line; + while (*end_of_keysym != 0 && *end_of_keysym != ' ') { + end_of_keysym++; + } + if (*end_of_keysym) { + int keysym; + *end_of_keysym = 0; + keysym = get_keysym(table, line); + if (keysym == 0) { + /* fprintf(stderr, "Warning: unknown keysym %s\n", line);*/ + } else { + const char *rest = end_of_keysym + 1; int keycode = strtol(rest, NULL, 0); if (strstr(rest, "numlock")) { - add_to_key_range(&k->keypad_range, keycode); - add_to_key_range(&k->numlock_range, keysym); - //fprintf(stderr, "keypad keysym %04x keycode %d\n", keysym, keycode); - } + add_to_key_range(&k->keypad_range, keycode); + add_to_key_range(&k->numlock_range, keysym); + /* fprintf(stderr, "keypad keysym %04x keycode %d\n", + keysym, keycode); */ + } if (strstr(rest, "shift")) { - keycode |= SCANCODE_SHIFT; + keycode |= SCANCODE_SHIFT; } if (strstr(rest, "altgr")) { - keycode |= SCANCODE_ALTGR; + keycode |= SCANCODE_ALTGR; } if (strstr(rest, "ctrl")) { - keycode |= SCANCODE_CTRL; + keycode |= SCANCODE_CTRL; } - add_keysym(line, keysym, keycode, k); + add_keysym(line, keysym, keycode, k); if (strstr(rest, "addupper")) { - char *c; - for (c = line; *c; c++) - *c = qemu_toupper(*c); - keysym = get_keysym(table, line); - if (keysym) - add_keysym(line, keysym, keycode | SCANCODE_SHIFT, k); - } - } - } - } + char *c; + for (c = line; *c; c++) { + *c = qemu_toupper(*c); + } + keysym = get_keysym(table, line); + if (keysym) { + add_keysym(line, keysym, + keycode | SCANCODE_SHIFT, k); + } + } + } + } + } } fclose(f); return k; @@ -180,19 +192,23 @@ int keysym2scancode(void *kbd_layout, int keysym) { kbd_layout_t *k = kbd_layout; if (keysym < MAX_NORMAL_KEYCODE) { - if (k->keysym2keycode[keysym] == 0) - fprintf(stderr, "Warning: no scancode found for keysym %d\n", - keysym); - return k->keysym2keycode[keysym]; + if (k->keysym2keycode[keysym] == 0) { + fprintf(stderr, "Warning: no scancode found for keysym %d\n", + keysym); + } + return k->keysym2keycode[keysym]; } else { - int i; + int i; #ifdef XK_ISO_Left_Tab - if (keysym == XK_ISO_Left_Tab) - keysym = XK_Tab; + if (keysym == XK_ISO_Left_Tab) { + keysym = XK_Tab; + } #endif - for (i = 0; i < k->extra_count; i++) - if (k->keysym2keycode_extra[i].keysym == keysym) - return k->keysym2keycode_extra[i].keycode; + for (i = 0; i < k->extra_count; i++) { + if (k->keysym2keycode_extra[i].keysym == keysym) { + return k->keysym2keycode_extra[i].keycode; + } + } } return 0; } @@ -202,9 +218,11 @@ int keycode_is_keypad(void *kbd_layout, int keycode) kbd_layout_t *k = kbd_layout; struct key_range *kr; - for (kr = k->keypad_range; kr; kr = kr->next) - if (keycode >= kr->start && keycode <= kr->end) + for (kr = k->keypad_range; kr; kr = kr->next) { + if (keycode >= kr->start && keycode <= kr->end) { return 1; + } + } return 0; } @@ -213,8 +231,10 @@ int keysym_is_numlock(void *kbd_layout, int keysym) kbd_layout_t *k = kbd_layout; struct key_range *kr; - for (kr = k->numlock_range; kr; kr = kr->next) - if (keysym >= kr->start && keysym <= kr->end) + for (kr = k->numlock_range; kr; kr = kr->next) { + if (keysym >= kr->start && keysym <= kr->end) { return 1; + } + } return 0; } diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 3d1b5cd066..9a9ddf2e3c 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -1489,7 +1489,7 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h) } #endif - colors = tight_fill_palette(vs, x, y, w * h, &fg, &bg, &palette); + colors = tight_fill_palette(vs, x, y, w * h, &bg, &fg, &palette); #ifdef CONFIG_VNC_JPEG if (allow_jpeg && vs->tight.quality != (uint8_t)-1) { diff --git a/util/hbitmap.c b/util/hbitmap.c index b3060e6976..ab139717f5 100644 --- a/util/hbitmap.c +++ b/util/hbitmap.c @@ -373,7 +373,7 @@ void hbitmap_free(HBitmap *hb) HBitmap *hbitmap_alloc(uint64_t size, int granularity) { - HBitmap *hb = g_malloc0(sizeof (struct HBitmap)); + HBitmap *hb = g_new0(struct HBitmap, 1); unsigned i; assert(granularity >= 0 && granularity < 64); @@ -384,7 +384,7 @@ HBitmap *hbitmap_alloc(uint64_t size, int granularity) hb->granularity = granularity; for (i = HBITMAP_LEVELS; i-- > 0; ) { size = MAX((size + BITS_PER_LONG - 1) >> BITS_PER_LEVEL, 1); - hb->levels[i] = g_malloc0(size * sizeof(unsigned long)); + hb->levels[i] = g_new0(unsigned long, size); } /* We necessarily have free bits in level 0 due to the definition diff --git a/util/iov.c b/util/iov.c index 24566c8789..2fb18e6654 100644 --- a/util/iov.c +++ b/util/iov.c @@ -253,7 +253,7 @@ unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt, void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint) { - qiov->iov = g_malloc(alloc_hint * sizeof(struct iovec)); + qiov->iov = g_new(struct iovec, alloc_hint); qiov->niov = 0; qiov->nalloc = alloc_hint; qiov->size = 0; @@ -277,7 +277,7 @@ void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len) if (qiov->niov == qiov->nalloc) { qiov->nalloc = 2 * qiov->nalloc + 1; - qiov->iov = g_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec)); + qiov->iov = g_renew(struct iovec, qiov->iov, qiov->nalloc); } qiov->iov[qiov->niov].iov_base = base; qiov->iov[qiov->niov].iov_len = len; diff --git a/util/qemu-option.c b/util/qemu-option.c index 5d106959ca..a708241643 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -737,14 +737,14 @@ void qemu_opts_del(QemuOpts *opts) g_free(opts); } -void qemu_opts_print(QemuOpts *opts) +void qemu_opts_print(QemuOpts *opts, const char *sep) { QemuOpt *opt; QemuOptDesc *desc = opts->list->desc; if (desc[0].name == NULL) { QTAILQ_FOREACH(opt, &opts->head, next) { - printf("%s=\"%s\" ", opt->name, opt->str); + printf("%s%s=\"%s\"", sep, opt->name, opt->str); } return; } @@ -757,12 +757,12 @@ void qemu_opts_print(QemuOpts *opts) continue; } if (desc->type == QEMU_OPT_STRING) { - printf("%s='%s' ", desc->name, value); + printf("%s%s='%s'", sep, desc->name, value); } else if ((desc->type == QEMU_OPT_SIZE || desc->type == QEMU_OPT_NUMBER) && opt) { - printf("%s=%" PRId64 " ", desc->name, opt->value.uint); + printf("%s%s=%" PRId64, sep, desc->name, opt->value.uint); } else { - printf("%s=%s ", desc->name, value); + printf("%s%s=%s", sep, desc->name, value); } } } diff --git a/util/uri.c b/util/uri.c index e348c1768c..918d23516d 100644 --- a/util/uri.c +++ b/util/uri.c @@ -225,7 +225,7 @@ rfc3986_parse_scheme(URI *uri, const char **str) { while (ISA_ALPHA(cur) || ISA_DIGIT(cur) || (*cur == '+') || (*cur == '-') || (*cur == '.')) cur++; if (uri != NULL) { - if (uri->scheme != NULL) g_free(uri->scheme); + g_free(uri->scheme); uri->scheme = g_strndup(*str, cur - *str); } *str = cur; @@ -262,8 +262,7 @@ rfc3986_parse_fragment(URI *uri, const char **str) ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) NEXT(cur); if (uri != NULL) { - if (uri->fragment != NULL) - g_free(uri->fragment); + g_free(uri->fragment); if (uri->cleanup & 2) uri->fragment = g_strndup(*str, cur - *str); else @@ -298,8 +297,7 @@ rfc3986_parse_query(URI *uri, const char **str) ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) NEXT(cur); if (uri != NULL) { - if (uri->query != NULL) - g_free (uri->query); + g_free(uri->query); uri->query = g_strndup (*str, cur - *str); } *str = cur; @@ -360,7 +358,7 @@ rfc3986_parse_user_info(URI *uri, const char **str) NEXT(cur); if (*cur == '@') { if (uri != NULL) { - if (uri->user != NULL) g_free(uri->user); + g_free(uri->user); if (uri->cleanup & 2) uri->user = g_strndup(*str, cur - *str); else @@ -473,9 +471,9 @@ not_ipv4: NEXT(cur); found: if (uri != NULL) { - if (uri->authority != NULL) g_free(uri->authority); + g_free(uri->authority); uri->authority = NULL; - if (uri->server != NULL) g_free(uri->server); + g_free(uri->server); if (cur != host) { if (uri->cleanup & 2) uri->server = g_strndup(host, cur - host); @@ -585,7 +583,7 @@ rfc3986_parse_path_ab_empty(URI *uri, const char **str) if (ret != 0) return(ret); } if (uri != NULL) { - if (uri->path != NULL) g_free(uri->path); + g_free(uri->path); if (*str != cur) { if (uri->cleanup & 2) uri->path = g_strndup(*str, cur - *str); @@ -631,7 +629,7 @@ rfc3986_parse_path_absolute(URI *uri, const char **str) } } if (uri != NULL) { - if (uri->path != NULL) g_free(uri->path); + g_free(uri->path); if (cur != *str) { if (uri->cleanup & 2) uri->path = g_strndup(*str, cur - *str); @@ -673,7 +671,7 @@ rfc3986_parse_path_rootless(URI *uri, const char **str) if (ret != 0) return(ret); } if (uri != NULL) { - if (uri->path != NULL) g_free(uri->path); + g_free(uri->path); if (cur != *str) { if (uri->cleanup & 2) uri->path = g_strndup(*str, cur - *str); @@ -715,7 +713,7 @@ rfc3986_parse_path_no_scheme(URI *uri, const char **str) if (ret != 0) return(ret); } if (uri != NULL) { - if (uri->path != NULL) g_free(uri->path); + g_free(uri->path); if (cur != *str) { if (uri->cleanup & 2) uri->path = g_strndup(*str, cur - *str); @@ -769,7 +767,7 @@ rfc3986_parse_hier_part(URI *uri, const char **str) } else { /* path-empty is effectively empty */ if (uri != NULL) { - if (uri->path != NULL) g_free(uri->path); + g_free(uri->path); uri->path = NULL; } } @@ -812,7 +810,7 @@ rfc3986_parse_relative_ref(URI *uri, const char *str) { } else { /* path-empty is effectively empty */ if (uri != NULL) { - if (uri->path != NULL) g_free(uri->path); + g_free(uri->path); uri->path = NULL; } } @@ -1006,8 +1004,7 @@ URI * uri_new(void) { URI *ret; - ret = (URI *) g_malloc(sizeof(URI)); - memset(ret, 0, sizeof(URI)); + ret = g_new0(URI, 1); return(ret); } @@ -1285,21 +1282,21 @@ static void uri_clean(URI *uri) { if (uri == NULL) return; - if (uri->scheme != NULL) g_free(uri->scheme); + g_free(uri->scheme); uri->scheme = NULL; - if (uri->server != NULL) g_free(uri->server); + g_free(uri->server); uri->server = NULL; - if (uri->user != NULL) g_free(uri->user); + g_free(uri->user); uri->user = NULL; - if (uri->path != NULL) g_free(uri->path); + g_free(uri->path); uri->path = NULL; - if (uri->fragment != NULL) g_free(uri->fragment); + g_free(uri->fragment); uri->fragment = NULL; - if (uri->opaque != NULL) g_free(uri->opaque); + g_free(uri->opaque); uri->opaque = NULL; - if (uri->authority != NULL) g_free(uri->authority); + g_free(uri->authority); uri->authority = NULL; - if (uri->query != NULL) g_free(uri->query); + g_free(uri->query); uri->query = NULL; } @@ -1711,10 +1708,8 @@ uri_resolve(const char *uri, const char *base) { /* * the base fragment must be ignored */ - if (bas->fragment != NULL) { - g_free(bas->fragment); - bas->fragment = NULL; - } + g_free(bas->fragment); + bas->fragment = NULL; val = uri_to_string(bas); goto done; } @@ -1736,24 +1731,21 @@ uri_resolve(const char *uri, const char *base) { goto done; if ((ref->scheme == NULL) && (ref->path == NULL) && ((ref->authority == NULL) && (ref->server == NULL))) { - if (bas->scheme != NULL) - res->scheme = g_strdup(bas->scheme); + res->scheme = g_strdup(bas->scheme); if (bas->authority != NULL) res->authority = g_strdup(bas->authority); else if (bas->server != NULL) { - res->server = g_strdup(bas->server); - if (bas->user != NULL) - res->user = g_strdup(bas->user); - res->port = bas->port; + res->server = g_strdup(bas->server); + res->user = g_strdup(bas->user); + res->port = bas->port; } - if (bas->path != NULL) - res->path = g_strdup(bas->path); - if (ref->query != NULL) + res->path = g_strdup(bas->path); + if (ref->query != NULL) { res->query = g_strdup (ref->query); - else if (bas->query != NULL) - res->query = g_strdup(bas->query); - if (ref->fragment != NULL) - res->fragment = g_strdup(ref->fragment); + } else { + res->query = g_strdup(bas->query); + } + res->fragment = g_strdup(ref->fragment); goto step_7; } @@ -1767,13 +1759,10 @@ uri_resolve(const char *uri, const char *base) { val = uri_to_string(ref); goto done; } - if (bas->scheme != NULL) - res->scheme = g_strdup(bas->scheme); + res->scheme = g_strdup(bas->scheme); - if (ref->query != NULL) - res->query = g_strdup(ref->query); - if (ref->fragment != NULL) - res->fragment = g_strdup(ref->fragment); + res->query = g_strdup(ref->query); + res->fragment = g_strdup(ref->fragment); /* * 4) If the authority component is defined, then the reference is a @@ -1787,20 +1776,17 @@ uri_resolve(const char *uri, const char *base) { res->authority = g_strdup(ref->authority); else { res->server = g_strdup(ref->server); - if (ref->user != NULL) - res->user = g_strdup(ref->user); + res->user = g_strdup(ref->user); res->port = ref->port; } - if (ref->path != NULL) - res->path = g_strdup(ref->path); + res->path = g_strdup(ref->path); goto step_7; } if (bas->authority != NULL) res->authority = g_strdup(bas->authority); else if (bas->server != NULL) { - res->server = g_strdup(bas->server); - if (bas->user != NULL) - res->user = g_strdup(bas->user); + res->server = g_strdup(bas->server); + res->user = g_strdup(bas->user); res->port = bas->port; } @@ -381,7 +381,7 @@ static QemuOptsList qemu_machine_opts = { .help = "maximum ram below the 4G boundary (32bit boundary)", }, { .name = PC_MACHINE_VMPORT, - .type = QEMU_OPT_BOOL, + .type = QEMU_OPT_STRING, .help = "Enable vmport (pc & q35)", },{ .name = "iommu", @@ -554,6 +554,22 @@ static QemuOptsList qemu_icount_opts = { }, }; +static QemuOptsList qemu_semihosting_config_opts = { + .name = "semihosting-config", + .implied_opt_name = "enable", + .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head), + .desc = { + { + .name = "enable", + .type = QEMU_OPT_BOOL, + }, { + .name = "target", + .type = QEMU_OPT_STRING, + }, + { /* end of list */ } + }, +}; + /** * Get machine options * @@ -2284,7 +2300,7 @@ static int mon_init_func(QemuOpts *opts, void *opaque) return 0; } -static void monitor_parse(const char *optarg, const char *mode) +static void monitor_parse(const char *optarg, const char *mode, bool pretty) { static int monitor_device_index = 0; QemuOpts *opts; @@ -2314,6 +2330,7 @@ static void monitor_parse(const char *optarg, const char *mode) } qemu_opt_set(opts, "mode", mode); qemu_opt_set(opts, "chardev", label); + qemu_opt_set_bool(opts, "pretty", pretty); if (def) qemu_opt_set(opts, "default", "on"); monitor_device_index++; @@ -2811,6 +2828,7 @@ int main(int argc, char **argv, char **envp) qemu_add_opts(&qemu_name_opts); qemu_add_opts(&qemu_numa_opts); qemu_add_opts(&qemu_icount_opts); + qemu_add_opts(&qemu_semihosting_config_opts); runstate_init(); @@ -3292,11 +3310,15 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_monitor: default_monitor = 0; if (strncmp(optarg, "none", 4)) { - monitor_parse(optarg, "readline"); + monitor_parse(optarg, "readline", false); } break; case QEMU_OPTION_qmp: - monitor_parse(optarg, "control"); + monitor_parse(optarg, "control", false); + default_monitor = 0; + break; + case QEMU_OPTION_qmp_pretty: + monitor_parse(optarg, "control", true); default_monitor = 0; break; case QEMU_OPTION_mon: @@ -3618,6 +3640,37 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_semihosting: semihosting_enabled = 1; + semihosting_target = SEMIHOSTING_TARGET_AUTO; + break; + case QEMU_OPTION_semihosting_config: + semihosting_enabled = 1; + opts = qemu_opts_parse(qemu_find_opts("semihosting-config"), + optarg, 0); + if (opts != NULL) { + semihosting_enabled = qemu_opt_get_bool(opts, "enable", + true); + const char *target = qemu_opt_get(opts, "target"); + if (target != NULL) { + if (strcmp("native", target) == 0) { + semihosting_target = SEMIHOSTING_TARGET_NATIVE; + } else if (strcmp("gdb", target) == 0) { + semihosting_target = SEMIHOSTING_TARGET_GDB; + } else if (strcmp("auto", target) == 0) { + semihosting_target = SEMIHOSTING_TARGET_AUTO; + } else { + fprintf(stderr, "Unsupported semihosting-config" + " %s\n", + optarg); + exit(1); + } + } else { + semihosting_target = SEMIHOSTING_TARGET_AUTO; + } + } else { + fprintf(stderr, "Unsupported semihosting-config %s\n", + optarg); + exit(1); + } break; case QEMU_OPTION_tdf: fprintf(stderr, "Warning: user space PIT time drift fix " @@ -3994,7 +4047,7 @@ int main(int argc, char **argv, char **envp) add_device_config(DEV_SCLP, "stdio"); } if (default_monitor) - monitor_parse("stdio", "readline"); + monitor_parse("stdio", "readline", false); } } else { if (default_serial) @@ -4002,7 +4055,7 @@ int main(int argc, char **argv, char **envp) if (default_parallel) add_device_config(DEV_PARALLEL, "vc:80Cx24C"); if (default_monitor) - monitor_parse("vc:80Cx24C", "readline"); + monitor_parse("vc:80Cx24C", "readline", false); if (default_virtcon) add_device_config(DEV_VIRTCON, "vc:80Cx24C"); if (default_sclp) { |