diff options
189 files changed, 6033 insertions, 2854 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 206bf7e..8eed800 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -198,7 +198,9 @@ M: Cornelia Huck <cornelia.huck@de.ibm.com> M: Alexander Graf <agraf@suse.de> S: Maintained F: target-s390x/kvm.c -F: hw/intc/s390_flic.[hc] +F: hw/intc/s390_flic.c +F: hw/intc/s390_flic_kvm.c +F: include/hw/s390x/s390_flic.h X86 M: Marcelo Tosatti <mtosatti@redhat.com> @@ -521,6 +523,8 @@ F: hw/s390x/s390-virtio-ccw.c F: hw/s390x/css.[hc] F: hw/s390x/sclp*.[hc] F: hw/s390x/ipl*.[hc] +F: include/hw/s390x/ +F: pc-bios/s390-ccw/ T: git git://github.com/cohuck/qemu virtio-ccw-upstr UniCore32 Machines diff --git a/block-migration.c b/block-migration.c index 3ad31a2..08db01a 100644 --- a/block-migration.c +++ b/block-migration.c @@ -14,7 +14,9 @@ */ #include "qemu-common.h" -#include "block/block_int.h" +#include "block/block.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" #include "hw/hw.h" #include "qemu/queue.h" #include "qemu/timer.h" @@ -70,7 +72,7 @@ typedef struct BlkMigBlock { int nr_sectors; struct iovec iov; QEMUIOVector qiov; - BlockDriverAIOCB *aiocb; + BlockAIOCB *aiocb; /* Protected by block migration lock. */ int ret; @@ -130,9 +132,9 @@ static void blk_send(QEMUFile *f, BlkMigBlock * blk) | flags); /* device name */ - len = strlen(blk->bmds->bs->device_name); + len = strlen(bdrv_get_device_name(blk->bmds->bs)); qemu_put_byte(f, len); - qemu_put_buffer(f, (uint8_t *)blk->bmds->bs->device_name, len); + qemu_put_buffer(f, (uint8_t *)bdrv_get_device_name(blk->bmds->bs), len); /* if a block is zero we need to flush here since the network * bandwidth is now a lot higher than the storage device bandwidth. @@ -343,12 +345,25 @@ static void unset_dirty_tracking(void) } } -static void init_blk_migration_it(void *opaque, BlockDriverState *bs) +static void init_blk_migration(QEMUFile *f) { + BlockDriverState *bs; BlkMigDevState *bmds; int64_t sectors; - if (!bdrv_is_read_only(bs)) { + block_mig_state.submitted = 0; + block_mig_state.read_done = 0; + block_mig_state.transferred = 0; + block_mig_state.total_sector_sum = 0; + block_mig_state.prev_progress = -1; + block_mig_state.bulk_completed = 0; + block_mig_state.zero_blocks = migrate_zero_blocks(); + + for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) { + if (bdrv_is_read_only(bs)) { + continue; + } + sectors = bdrv_nb_sectors(bs); if (sectors <= 0) { return; @@ -369,28 +384,15 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs) if (bmds->shared_base) { DPRINTF("Start migration for %s with shared base image\n", - bs->device_name); + bdrv_get_device_name(bs)); } else { - DPRINTF("Start full migration for %s\n", bs->device_name); + DPRINTF("Start full migration for %s\n", bdrv_get_device_name(bs)); } QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry); } } -static void init_blk_migration(QEMUFile *f) -{ - block_mig_state.submitted = 0; - block_mig_state.read_done = 0; - block_mig_state.transferred = 0; - block_mig_state.total_sector_sum = 0; - block_mig_state.prev_progress = -1; - block_mig_state.bulk_completed = 0; - block_mig_state.zero_blocks = migrate_zero_blocks(); - - bdrv_iterate(init_blk_migration_it, NULL); -} - /* Called with no lock taken. */ static int blk_mig_save_bulked_block(QEMUFile *f) @@ -28,8 +28,8 @@ #include "block/blockjob.h" #include "qemu/module.h" #include "qapi/qmp/qjson.h" +#include "sysemu/block-backend.h" #include "sysemu/sysemu.h" -#include "sysemu/blockdev.h" /* FIXME layering violation */ #include "qemu/notify.h" #include "block/coroutine.h" #include "block/qapi.h" @@ -58,15 +58,12 @@ struct BdrvDirtyBitmap { #define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */ -#define COROUTINE_POOL_RESERVATION 64 /* number of coroutines to reserve */ - -static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load); -static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, +static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); -static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, + BlockCompletionFunc *cb, void *opaque); +static BlockAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); + BlockCompletionFunc *cb, void *opaque); static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *iov); @@ -79,14 +76,14 @@ static int coroutine_fn bdrv_co_do_preadv(BlockDriverState *bs, static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags); -static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BdrvRequestFlags flags, - BlockDriverCompletionFunc *cb, - void *opaque, - bool is_write); +static BlockAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, + int nb_sectors, + BdrvRequestFlags flags, + BlockCompletionFunc *cb, + void *opaque, + bool is_write); static void coroutine_fn bdrv_co_do_rw(void *opaque); static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs, int64_t sector_num, int nb_sectors, BdrvRequestFlags flags); @@ -335,35 +332,21 @@ void bdrv_register(BlockDriver *bdrv) QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list); } -/* create a new block device (by default it is empty) */ -BlockDriverState *bdrv_new(const char *device_name, Error **errp) +BlockDriverState *bdrv_new_root(void) { - BlockDriverState *bs; - int i; + BlockDriverState *bs = bdrv_new(); - if (*device_name && !id_wellformed(device_name)) { - error_setg(errp, "Invalid device name"); - return NULL; - } + QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list); + return bs; +} - if (bdrv_find(device_name)) { - error_setg(errp, "Device with id '%s' already exists", - device_name); - return NULL; - } - if (bdrv_find_node(device_name)) { - error_setg(errp, - "Device name '%s' conflicts with an existing node name", - device_name); - return NULL; - } +BlockDriverState *bdrv_new(void) +{ + BlockDriverState *bs; + int i; bs = g_new0(BlockDriverState, 1); QLIST_INIT(&bs->dirty_bitmaps); - pstrcpy(bs->device_name, sizeof(bs->device_name), device_name); - if (device_name[0] != '\0') { - QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list); - } for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) { QLIST_INIT(&bs->op_blockers[i]); } @@ -875,7 +858,7 @@ static void bdrv_assign_node_name(BlockDriverState *bs, } /* takes care of avoiding namespaces collisions */ - if (bdrv_find(node_name)) { + if (blk_by_name(node_name)) { error_setg(errp, "node-name=%s is conflicting with a device id", node_name); return; @@ -1159,7 +1142,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd) } else if (backing_hd) { error_setg(&bs->backing_blocker, "device is used as backing hd of '%s'", - bs->device_name); + bdrv_get_device_name(bs)); } bs->backing_hd = backing_hd; @@ -1224,7 +1207,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) goto free_exit; } - backing_hd = bdrv_new("", errp); + backing_hd = bdrv_new(); if (bs->backing_format[0] != '\0') { back_drv = bdrv_find_format(bs->backing_format); @@ -1353,7 +1336,7 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp) qdict_put(snapshot_options, "file.filename", qstring_from_str(tmp_filename)); - bs_snapshot = bdrv_new("", &error_abort); + bs_snapshot = bdrv_new(); ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options, flags, bdrv_qcow2, &local_err); @@ -1424,7 +1407,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, if (*pbs) { bs = *pbs; } else { - bs = bdrv_new("", &error_abort); + bs = bdrv_new(); } /* NULL means an empty set of options */ @@ -1533,7 +1516,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, } else { error_setg(errp, "Block format '%s' used by device '%s' doesn't " "support the option '%s'", drv->format_name, - bs->device_name, entry->key); + bdrv_get_device_name(bs), entry->key); } ret = -EINVAL; @@ -1541,7 +1524,9 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, } if (!bdrv_key_required(bs)) { - bdrv_dev_change_media_cb(bs, true); + if (bs->blk) { + blk_dev_change_media_cb(bs->blk, true); + } } else if (!runstate_check(RUN_STATE_PRELAUNCH) && !runstate_check(RUN_STATE_INMIGRATE) && !runstate_check(RUN_STATE_PAUSED)) { /* HACK */ @@ -1740,7 +1725,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue, if (!(reopen_state->bs->open_flags & BDRV_O_ALLOW_RDWR) && reopen_state->flags & BDRV_O_RDWR) { error_set(errp, QERR_DEVICE_IS_READ_ONLY, - reopen_state->bs->device_name); + bdrv_get_device_name(reopen_state->bs)); goto error; } @@ -1767,7 +1752,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue, /* It is currently mandatory to have a bdrv_reopen_prepare() * handler for each supported drv. */ error_set(errp, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, - drv->format_name, reopen_state->bs->device_name, + drv->format_name, bdrv_get_device_name(reopen_state->bs), "reopening of file"); ret = -1; goto error; @@ -1866,7 +1851,9 @@ void bdrv_close(BlockDriverState *bs) } } - bdrv_dev_change_media_cb(bs, false); + if (bs->blk) { + blk_dev_change_media_cb(bs->blk, false); + } /*throttling disk I/O limits*/ if (bs->io_limits_enabled) { @@ -1955,10 +1942,17 @@ void bdrv_drain_all(void) Also, NULL terminate the device_name to prevent double remove */ void bdrv_make_anon(BlockDriverState *bs) { - if (bs->device_name[0] != '\0') { + /* + * Take care to remove bs from bdrv_states only when it's actually + * in it. Note that bs->device_list.tqe_prev is initially null, + * and gets set to non-null by QTAILQ_INSERT_TAIL(). Establish + * the useful invariant "bs in bdrv_states iff bs->tqe_prev" by + * resetting it to null on remove. + */ + if (bs->device_list.tqe_prev) { QTAILQ_REMOVE(&bdrv_states, bs, device_list); + bs->device_list.tqe_prev = NULL; } - bs->device_name[0] = '\0'; if (bs->node_name[0] != '\0') { QTAILQ_REMOVE(&graph_bdrv_states, bs, node_list); } @@ -1978,9 +1972,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest, /* move some fields that need to stay attached to the device */ /* dev info */ - bs_dest->dev_ops = bs_src->dev_ops; - bs_dest->dev_opaque = bs_src->dev_opaque; - bs_dest->dev = bs_src->dev; bs_dest->guest_block_size = bs_src->guest_block_size; bs_dest->copy_on_read = bs_src->copy_on_read; @@ -2012,9 +2003,9 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest, bs_dest->job = bs_src->job; /* keep the same entry in bdrv_states */ - pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name), - bs_src->device_name); bs_dest->device_list = bs_src->device_list; + bs_dest->blk = bs_src->blk; + memcpy(bs_dest->op_blockers, bs_src->op_blockers, sizeof(bs_dest->op_blockers)); } @@ -2027,7 +2018,7 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest, * This will modify the BlockDriverState fields, and swap contents * between bs_new and bs_old. Both bs_new and bs_old are modified. * - * bs_new is required to be anonymous. + * bs_new must not be attached to a BlockBackend. * * This function does not create any image files. */ @@ -2046,11 +2037,10 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) QTAILQ_REMOVE(&graph_bdrv_states, bs_old, node_list); } - /* bs_new must be anonymous and shouldn't have anything fancy enabled */ - assert(bs_new->device_name[0] == '\0'); + /* bs_new must be unattached and shouldn't have anything fancy enabled */ + assert(!bs_new->blk); assert(QLIST_EMPTY(&bs_new->dirty_bitmaps)); assert(bs_new->job == NULL); - assert(bs_new->dev == NULL); assert(bs_new->io_limits_enabled == false); assert(!throttle_have_timer(&bs_new->throttle_state)); @@ -2063,11 +2053,10 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) bdrv_move_feature_fields(bs_old, bs_new); bdrv_move_feature_fields(bs_new, &tmp); - /* bs_new shouldn't be in bdrv_states even after the swap! */ - assert(bs_new->device_name[0] == '\0'); + /* bs_new must remain unattached */ + assert(!bs_new->blk); /* Check a few fields that should remain attached to the device */ - assert(bs_new->dev == NULL); assert(bs_new->job == NULL); assert(bs_new->io_limits_enabled == false); assert(!throttle_have_timer(&bs_new->throttle_state)); @@ -2091,7 +2080,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) * This will modify the BlockDriverState fields, and swap contents * between bs_new and bs_top. Both bs_new and bs_top are modified. * - * bs_new is required to be anonymous. + * bs_new must not be attached to a BlockBackend. * * This function does not create any image files. */ @@ -2106,7 +2095,6 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top) static void bdrv_delete(BlockDriverState *bs) { - assert(!bs->dev); assert(!bs->job); assert(bdrv_op_blocker_is_empty(bs)); assert(!bs->refcnt); @@ -2117,109 +2105,9 @@ static void bdrv_delete(BlockDriverState *bs) /* remove from list, if necessary */ bdrv_make_anon(bs); - drive_info_del(drive_get_by_blockdev(bs)); g_free(bs); } -int bdrv_attach_dev(BlockDriverState *bs, void *dev) -/* TODO change to DeviceState *dev when all users are qdevified */ -{ - if (bs->dev) { - return -EBUSY; - } - bs->dev = dev; - bdrv_iostatus_reset(bs); - - /* We're expecting I/O from the device so bump up coroutine pool size */ - qemu_coroutine_adjust_pool_size(COROUTINE_POOL_RESERVATION); - return 0; -} - -/* TODO qdevified devices don't use this, remove when devices are qdevified */ -void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev) -{ - if (bdrv_attach_dev(bs, dev) < 0) { - abort(); - } -} - -void bdrv_detach_dev(BlockDriverState *bs, void *dev) -/* TODO change to DeviceState *dev when all users are qdevified */ -{ - assert(bs->dev == dev); - bs->dev = NULL; - bs->dev_ops = NULL; - bs->dev_opaque = NULL; - bs->guest_block_size = 512; - qemu_coroutine_adjust_pool_size(-COROUTINE_POOL_RESERVATION); -} - -/* TODO change to return DeviceState * when all users are qdevified */ -void *bdrv_get_attached_dev(BlockDriverState *bs) -{ - return bs->dev; -} - -void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, - void *opaque) -{ - bs->dev_ops = ops; - bs->dev_opaque = opaque; -} - -static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load) -{ - if (bs->dev_ops && bs->dev_ops->change_media_cb) { - bool tray_was_closed = !bdrv_dev_is_tray_open(bs); - bs->dev_ops->change_media_cb(bs->dev_opaque, load); - if (tray_was_closed) { - /* tray open */ - qapi_event_send_device_tray_moved(bdrv_get_device_name(bs), - true, &error_abort); - } - if (load) { - /* tray close */ - qapi_event_send_device_tray_moved(bdrv_get_device_name(bs), - false, &error_abort); - } - } -} - -bool bdrv_dev_has_removable_media(BlockDriverState *bs) -{ - return !bs->dev || (bs->dev_ops && bs->dev_ops->change_media_cb); -} - -void bdrv_dev_eject_request(BlockDriverState *bs, bool force) -{ - if (bs->dev_ops && bs->dev_ops->eject_request_cb) { - bs->dev_ops->eject_request_cb(bs->dev_opaque, force); - } -} - -bool bdrv_dev_is_tray_open(BlockDriverState *bs) -{ - if (bs->dev_ops && bs->dev_ops->is_tray_open) { - return bs->dev_ops->is_tray_open(bs->dev_opaque); - } - return false; -} - -static void bdrv_dev_resize_cb(BlockDriverState *bs) -{ - if (bs->dev_ops && bs->dev_ops->resize_cb) { - bs->dev_ops->resize_cb(bs->dev_opaque); - } -} - -bool bdrv_dev_is_medium_locked(BlockDriverState *bs) -{ - if (bs->dev_ops && bs->dev_ops->is_medium_locked) { - return bs->dev_ops->is_medium_locked(bs->dev_opaque); - } - return false; -} - /* * Run consistency checks on an image * @@ -3553,7 +3441,9 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset) ret = drv->bdrv_truncate(bs, offset); if (ret == 0) { ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); - bdrv_dev_resize_cb(bs); + if (bs->blk) { + blk_dev_resize_cb(bs->blk); + } } return ret; } @@ -3754,8 +3644,10 @@ int bdrv_set_key(BlockDriverState *bs, const char *key) bs->valid_key = 0; } else if (!bs->valid_key) { bs->valid_key = 1; - /* call the change callback now, we skipped it on open */ - bdrv_dev_change_media_cb(bs, true); + if (bs->blk) { + /* call the change callback now, we skipped it on open */ + blk_dev_change_media_cb(bs->blk, true); + } } return ret; } @@ -3803,16 +3695,12 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name), } /* This function is to find block backend bs */ +/* TODO convert callers to blk_by_name(), then remove */ BlockDriverState *bdrv_find(const char *name) { - BlockDriverState *bs; + BlockBackend *blk = blk_by_name(name); - QTAILQ_FOREACH(bs, &bdrv_states, device_list) { - if (!strcmp(name, bs->device_name)) { - return bs; - } - } - return NULL; + return blk ? blk_bs(blk) : NULL; } /* This function is to find a node in the bs graph */ @@ -3851,13 +3739,14 @@ BlockDriverState *bdrv_lookup_bs(const char *device, const char *node_name, Error **errp) { - BlockDriverState *bs = NULL; + BlockBackend *blk; + BlockDriverState *bs; if (device) { - bs = bdrv_find(device); + blk = blk_by_name(device); - if (bs) { - return bs; + if (blk) { + return blk_bs(blk); } } @@ -3894,18 +3783,10 @@ BlockDriverState *bdrv_next(BlockDriverState *bs) return QTAILQ_NEXT(bs, device_list); } -void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque) +/* TODO check what callers really want: bs->node_name or blk_name() */ +const char *bdrv_get_device_name(const BlockDriverState *bs) { - BlockDriverState *bs; - - QTAILQ_FOREACH(bs, &bdrv_states, device_list) { - it(opaque, bs); - } -} - -const char *bdrv_get_device_name(BlockDriverState *bs) -{ - return bs->device_name; + return bs->blk ? blk_name(bs->blk) : ""; } int bdrv_get_flags(BlockDriverState *bs) @@ -4432,9 +4313,9 @@ int bdrv_get_backing_file_depth(BlockDriverState *bs) /**************************************************************/ /* async I/Os */ -BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) +BlockAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, + QEMUIOVector *qiov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque) { trace_bdrv_aio_readv(bs, sector_num, nb_sectors, opaque); @@ -4442,9 +4323,9 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, cb, opaque, false); } -BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) +BlockAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, + QEMUIOVector *qiov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque) { trace_bdrv_aio_writev(bs, sector_num, nb_sectors, opaque); @@ -4452,9 +4333,9 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, cb, opaque, true); } -BlockDriverAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs, +BlockAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs, int64_t sector_num, int nb_sectors, BdrvRequestFlags flags, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { trace_bdrv_aio_write_zeroes(bs, sector_num, nb_sectors, flags, opaque); @@ -4469,7 +4350,7 @@ typedef struct MultiwriteCB { int num_requests; int num_callbacks; struct { - BlockDriverCompletionFunc *cb; + BlockCompletionFunc *cb; void *opaque; QEMUIOVector *free_qiov; } callbacks[]; @@ -4646,7 +4527,7 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs) return 0; } -void bdrv_aio_cancel(BlockDriverAIOCB *acb) +void bdrv_aio_cancel(BlockAIOCB *acb) { qemu_aio_ref(acb); bdrv_aio_cancel_async(acb); @@ -4665,7 +4546,7 @@ void bdrv_aio_cancel(BlockDriverAIOCB *acb) /* Async version of aio cancel. The caller is not blocked if the acb implements * cancel_async, otherwise we do nothing and let the request normally complete. * In either case the completion callback must be called. */ -void bdrv_aio_cancel_async(BlockDriverAIOCB *acb) +void bdrv_aio_cancel_async(BlockAIOCB *acb) { if (acb->aiocb_info->cancel_async) { acb->aiocb_info->cancel_async(acb); @@ -4675,23 +4556,23 @@ void bdrv_aio_cancel_async(BlockDriverAIOCB *acb) /**************************************************************/ /* async block device emulation */ -typedef struct BlockDriverAIOCBSync { - BlockDriverAIOCB common; +typedef struct BlockAIOCBSync { + BlockAIOCB common; QEMUBH *bh; int ret; /* vector translation state */ QEMUIOVector *qiov; uint8_t *bounce; int is_write; -} BlockDriverAIOCBSync; +} BlockAIOCBSync; static const AIOCBInfo bdrv_em_aiocb_info = { - .aiocb_size = sizeof(BlockDriverAIOCBSync), + .aiocb_size = sizeof(BlockAIOCBSync), }; static void bdrv_aio_bh_cb(void *opaque) { - BlockDriverAIOCBSync *acb = opaque; + BlockAIOCBSync *acb = opaque; if (!acb->is_write && acb->ret >= 0) { qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size); @@ -4703,16 +4584,16 @@ static void bdrv_aio_bh_cb(void *opaque) qemu_aio_unref(acb); } -static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque, - int is_write) +static BlockAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, + int nb_sectors, + BlockCompletionFunc *cb, + void *opaque, + int is_write) { - BlockDriverAIOCBSync *acb; + BlockAIOCBSync *acb; acb = qemu_aio_get(&bdrv_em_aiocb_info, bs, cb, opaque); acb->is_write = is_write; @@ -4734,36 +4615,36 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs, return &acb->common; } -static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, +static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); } -static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, +static BlockAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1); } -typedef struct BlockDriverAIOCBCoroutine { - BlockDriverAIOCB common; +typedef struct BlockAIOCBCoroutine { + BlockAIOCB common; BlockRequest req; bool is_write; bool *done; QEMUBH* bh; -} BlockDriverAIOCBCoroutine; +} BlockAIOCBCoroutine; static const AIOCBInfo bdrv_em_co_aiocb_info = { - .aiocb_size = sizeof(BlockDriverAIOCBCoroutine), + .aiocb_size = sizeof(BlockAIOCBCoroutine), }; static void bdrv_co_em_bh(void *opaque) { - BlockDriverAIOCBCoroutine *acb = opaque; + BlockAIOCBCoroutine *acb = opaque; acb->common.cb(acb->common.opaque, acb->req.error); @@ -4774,7 +4655,7 @@ static void bdrv_co_em_bh(void *opaque) /* Invoke bdrv_co_do_readv/bdrv_co_do_writev */ static void coroutine_fn bdrv_co_do_rw(void *opaque) { - BlockDriverAIOCBCoroutine *acb = opaque; + BlockAIOCBCoroutine *acb = opaque; BlockDriverState *bs = acb->common.bs; if (!acb->is_write) { @@ -4789,17 +4670,17 @@ static void coroutine_fn bdrv_co_do_rw(void *opaque) qemu_bh_schedule(acb->bh); } -static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BdrvRequestFlags flags, - BlockDriverCompletionFunc *cb, - void *opaque, - bool is_write) +static BlockAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, + int nb_sectors, + BdrvRequestFlags flags, + BlockCompletionFunc *cb, + void *opaque, + bool is_write) { Coroutine *co; - BlockDriverAIOCBCoroutine *acb; + BlockAIOCBCoroutine *acb; acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque); acb->req.sector = sector_num; @@ -4816,7 +4697,7 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs, static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque) { - BlockDriverAIOCBCoroutine *acb = opaque; + BlockAIOCBCoroutine *acb = opaque; BlockDriverState *bs = acb->common.bs; acb->req.error = bdrv_co_flush(bs); @@ -4824,13 +4705,13 @@ static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque) qemu_bh_schedule(acb->bh); } -BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque) +BlockAIOCB *bdrv_aio_flush(BlockDriverState *bs, + BlockCompletionFunc *cb, void *opaque) { trace_bdrv_aio_flush(bs, opaque); Coroutine *co; - BlockDriverAIOCBCoroutine *acb; + BlockAIOCBCoroutine *acb; acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque); @@ -4842,7 +4723,7 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque) { - BlockDriverAIOCBCoroutine *acb = opaque; + BlockAIOCBCoroutine *acb = opaque; BlockDriverState *bs = acb->common.bs; acb->req.error = bdrv_co_discard(bs, acb->req.sector, acb->req.nb_sectors); @@ -4850,12 +4731,12 @@ static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque) qemu_bh_schedule(acb->bh); } -BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs, +BlockAIOCB *bdrv_aio_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { Coroutine *co; - BlockDriverAIOCBCoroutine *acb; + BlockAIOCBCoroutine *acb; trace_bdrv_aio_discard(bs, sector_num, nb_sectors, opaque); @@ -4880,9 +4761,9 @@ void bdrv_init_with_whitelist(void) } void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { - BlockDriverAIOCB *acb; + BlockAIOCB *acb; acb = g_slice_alloc(aiocb_info->aiocb_size); acb->aiocb_info = aiocb_info; @@ -4895,13 +4776,13 @@ void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs, void qemu_aio_ref(void *p) { - BlockDriverAIOCB *acb = p; + BlockAIOCB *acb = p; acb->refcnt++; } void qemu_aio_unref(void *p) { - BlockDriverAIOCB *acb = p; + BlockAIOCB *acb = p; assert(acb->refcnt > 0); if (--acb->refcnt == 0) { g_slice_free1(acb->aiocb_info->aiocb_size, acb); @@ -4931,7 +4812,7 @@ static int coroutine_fn bdrv_co_io_em(BlockDriverState *bs, int64_t sector_num, CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; - BlockDriverAIOCB *acb; + BlockAIOCB *acb; if (is_write) { acb = bs->drv->bdrv_aio_writev(bs, sector_num, iov, nb_sectors, @@ -4997,7 +4878,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) if (bs->drv->bdrv_co_flush_to_disk) { ret = bs->drv->bdrv_co_flush_to_disk(bs); } else if (bs->drv->bdrv_aio_flush) { - BlockDriverAIOCB *acb; + BlockAIOCB *acb; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; @@ -5172,7 +5053,7 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, if (bs->drv->bdrv_co_discard) { ret = bs->drv->bdrv_co_discard(bs, sector_num, num); } else { - BlockDriverAIOCB *acb; + BlockAIOCB *acb; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; @@ -5259,13 +5140,15 @@ int bdrv_media_changed(BlockDriverState *bs) void bdrv_eject(BlockDriverState *bs, bool eject_flag) { BlockDriver *drv = bs->drv; + const char *device_name; if (drv && drv->bdrv_eject) { drv->bdrv_eject(bs, eject_flag); } - if (bs->device_name[0] != '\0') { - qapi_event_send_device_tray_moved(bdrv_get_device_name(bs), + device_name = bdrv_get_device_name(bs); + if (device_name[0] != '\0') { + qapi_event_send_device_tray_moved(device_name, eject_flag, &error_abort); } } @@ -5296,9 +5179,9 @@ int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) return -ENOTSUP; } -BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, +BlockAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, unsigned long int req, void *buf, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { BlockDriver *drv = bs->drv; @@ -5475,7 +5358,8 @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp) blocker = QLIST_FIRST(&bs->op_blockers[op]); if (errp) { error_setg(errp, "Device '%s' is busy: %s", - bs->device_name, error_get_pretty(blocker->reason)); + bdrv_get_device_name(bs), + error_get_pretty(blocker->reason)); } return true; } diff --git a/block/Makefile.objs b/block/Makefile.objs index a833ed5..27911b6 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -5,7 +5,7 @@ block-obj-y += qed-check.o block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o block-obj-$(CONFIG_QUORUM) += quorum.o block-obj-y += parallels.o blkdebug.o blkverify.o -block-obj-y += snapshot.o qapi.o +block-obj-y += block-backend.o snapshot.o qapi.o block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o block-obj-$(CONFIG_POSIX) += raw-posix.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o diff --git a/block/archipelago.c b/block/archipelago.c index 73d91a4..a8114b5 100644 --- a/block/archipelago.c +++ b/block/archipelago.c @@ -86,7 +86,7 @@ typedef enum { } ARCHIPCmd; typedef struct ArchipelagoAIOCB { - BlockDriverAIOCB common; + BlockAIOCB common; QEMUBH *bh; struct BDRVArchipelagoState *s; QEMUIOVector *qiov; @@ -856,13 +856,13 @@ err_exit: return ret; } -static BlockDriverAIOCB *qemu_archipelago_aio_rw(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque, - int op) +static BlockAIOCB *qemu_archipelago_aio_rw(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, + int nb_sectors, + BlockCompletionFunc *cb, + void *opaque, + int op) { ArchipelagoAIOCB *aio_cb; BDRVArchipelagoState *s = bs->opaque; @@ -894,17 +894,17 @@ err_exit: return NULL; } -static BlockDriverAIOCB *qemu_archipelago_aio_readv(BlockDriverState *bs, +static BlockAIOCB *qemu_archipelago_aio_readv(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { return qemu_archipelago_aio_rw(bs, sector_num, qiov, nb_sectors, cb, opaque, ARCHIP_OP_READ); } -static BlockDriverAIOCB *qemu_archipelago_aio_writev(BlockDriverState *bs, +static BlockAIOCB *qemu_archipelago_aio_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { return qemu_archipelago_aio_rw(bs, sector_num, qiov, nb_sectors, cb, opaque, ARCHIP_OP_WRITE); @@ -1052,8 +1052,8 @@ static QemuOptsList qemu_archipelago_create_opts = { } }; -static BlockDriverAIOCB *qemu_archipelago_aio_flush(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque) +static BlockAIOCB *qemu_archipelago_aio_flush(BlockDriverState *bs, + BlockCompletionFunc *cb, void *opaque) { return qemu_archipelago_aio_rw(bs, 0, NULL, 0, cb, opaque, ARCHIP_OP_FLUSH); diff --git a/block/backup.c b/block/backup.c index d0b0225..e334740 100644 --- a/block/backup.c +++ b/block/backup.c @@ -353,7 +353,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target, int64_t speed, MirrorSyncMode sync_mode, BlockdevOnError on_source_error, BlockdevOnError on_target_error, - BlockDriverCompletionFunc *cb, void *opaque, + BlockCompletionFunc *cb, void *opaque, Error **errp) { int64_t len; diff --git a/block/blkdebug.c b/block/blkdebug.c index f8fbb0f..e046b92 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -41,7 +41,7 @@ typedef struct BDRVBlkdebugState { } BDRVBlkdebugState; typedef struct BlkdebugAIOCB { - BlockDriverAIOCB common; + BlockAIOCB common; QEMUBH *bh; int ret; } BlkdebugAIOCB; @@ -463,8 +463,8 @@ static void error_callback_bh(void *opaque) qemu_aio_unref(acb); } -static BlockDriverAIOCB *inject_error(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque, BlkdebugRule *rule) +static BlockAIOCB *inject_error(BlockDriverState *bs, + BlockCompletionFunc *cb, void *opaque, BlkdebugRule *rule) { BDRVBlkdebugState *s = bs->opaque; int error = rule->options.inject.error; @@ -489,9 +489,9 @@ static BlockDriverAIOCB *inject_error(BlockDriverState *bs, return &acb->common; } -static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs, +static BlockAIOCB *blkdebug_aio_readv(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { BDRVBlkdebugState *s = bs->opaque; BlkdebugRule *rule = NULL; @@ -511,9 +511,9 @@ static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs, return bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque); } -static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs, +static BlockAIOCB *blkdebug_aio_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { BDRVBlkdebugState *s = bs->opaque; BlkdebugRule *rule = NULL; @@ -533,8 +533,8 @@ static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs, return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque); } -static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque) +static BlockAIOCB *blkdebug_aio_flush(BlockDriverState *bs, + BlockCompletionFunc *cb, void *opaque) { BDRVBlkdebugState *s = bs->opaque; BlkdebugRule *rule = NULL; diff --git a/block/blkverify.c b/block/blkverify.c index 7d64a23..438dff8 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -19,7 +19,7 @@ typedef struct { typedef struct BlkverifyAIOCB BlkverifyAIOCB; struct BlkverifyAIOCB { - BlockDriverAIOCB common; + BlockAIOCB common; QEMUBH *bh; /* Request metadata */ @@ -165,7 +165,7 @@ static int64_t blkverify_getlength(BlockDriverState *bs) static BlkverifyAIOCB *blkverify_aio_get(BlockDriverState *bs, bool is_write, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, + BlockCompletionFunc *cb, void *opaque) { BlkverifyAIOCB *acb = qemu_aio_get(&blkverify_aiocb_info, bs, cb, opaque); @@ -229,9 +229,9 @@ static void blkverify_verify_readv(BlkverifyAIOCB *acb) } } -static BlockDriverAIOCB *blkverify_aio_readv(BlockDriverState *bs, +static BlockAIOCB *blkverify_aio_readv(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { BDRVBlkverifyState *s = bs->opaque; BlkverifyAIOCB *acb = blkverify_aio_get(bs, false, sector_num, qiov, @@ -249,9 +249,9 @@ static BlockDriverAIOCB *blkverify_aio_readv(BlockDriverState *bs, return &acb->common; } -static BlockDriverAIOCB *blkverify_aio_writev(BlockDriverState *bs, +static BlockAIOCB *blkverify_aio_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { BDRVBlkverifyState *s = bs->opaque; BlkverifyAIOCB *acb = blkverify_aio_get(bs, true, sector_num, qiov, @@ -264,9 +264,9 @@ static BlockDriverAIOCB *blkverify_aio_writev(BlockDriverState *bs, return &acb->common; } -static BlockDriverAIOCB *blkverify_aio_flush(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, - void *opaque) +static BlockAIOCB *blkverify_aio_flush(BlockDriverState *bs, + BlockCompletionFunc *cb, + void *opaque) { BDRVBlkverifyState *s = bs->opaque; diff --git a/block/block-backend.c b/block/block-backend.c new file mode 100644 index 0000000..d0692b1 --- /dev/null +++ b/block/block-backend.c @@ -0,0 +1,631 @@ +/* + * QEMU Block backends + * + * Copyright (C) 2014 Red Hat, Inc. + * + * Authors: + * Markus Armbruster <armbru@redhat.com>, + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 + * or later. See the COPYING.LIB file in the top-level directory. + */ + +#include "sysemu/block-backend.h" +#include "block/block_int.h" +#include "sysemu/blockdev.h" +#include "qapi-event.h" + +/* Number of coroutines to reserve per attached device model */ +#define COROUTINE_POOL_RESERVATION 64 + +struct BlockBackend { + char *name; + int refcnt; + BlockDriverState *bs; + DriveInfo *legacy_dinfo; /* null unless created by drive_new() */ + QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */ + + void *dev; /* attached device model, if any */ + /* TODO change to DeviceState when all users are qdevified */ + const BlockDevOps *dev_ops; + void *dev_opaque; +}; + +static void drive_info_del(DriveInfo *dinfo); + +/* All the BlockBackends (except for hidden ones) */ +static QTAILQ_HEAD(, BlockBackend) blk_backends = + QTAILQ_HEAD_INITIALIZER(blk_backends); + +/* + * Create a new BlockBackend with @name, with a reference count of one. + * @name must not be null or empty. + * Fail if a BlockBackend with this name already exists. + * Store an error through @errp on failure, unless it's null. + * Return the new BlockBackend on success, null on failure. + */ +BlockBackend *blk_new(const char *name, Error **errp) +{ + BlockBackend *blk; + + assert(name && name[0]); + if (!id_wellformed(name)) { + error_setg(errp, "Invalid device name"); + return NULL; + } + if (blk_by_name(name)) { + error_setg(errp, "Device with id '%s' already exists", name); + return NULL; + } + if (bdrv_find_node(name)) { + error_setg(errp, + "Device name '%s' conflicts with an existing node name", + name); + return NULL; + } + + blk = g_new0(BlockBackend, 1); + blk->name = g_strdup(name); + blk->refcnt = 1; + QTAILQ_INSERT_TAIL(&blk_backends, blk, link); + return blk; +} + +/* + * Create a new BlockBackend with a new BlockDriverState attached. + * Otherwise just like blk_new(), which see. + */ +BlockBackend *blk_new_with_bs(const char *name, Error **errp) +{ + BlockBackend *blk; + BlockDriverState *bs; + + blk = blk_new(name, errp); + if (!blk) { + return NULL; + } + + bs = bdrv_new_root(); + blk->bs = bs; + bs->blk = blk; + return blk; +} + +static void blk_delete(BlockBackend *blk) +{ + assert(!blk->refcnt); + assert(!blk->dev); + if (blk->bs) { + assert(blk->bs->blk == blk); + blk->bs->blk = NULL; + bdrv_unref(blk->bs); + blk->bs = NULL; + } + /* Avoid double-remove after blk_hide_on_behalf_of_do_drive_del() */ + if (blk->name[0]) { + QTAILQ_REMOVE(&blk_backends, blk, link); + } + g_free(blk->name); + drive_info_del(blk->legacy_dinfo); + g_free(blk); +} + +static void drive_info_del(DriveInfo *dinfo) +{ + if (!dinfo) { + return; + } + qemu_opts_del(dinfo->opts); + g_free(dinfo->serial); + g_free(dinfo); +} + +/* + * Increment @blk's reference count. + * @blk must not be null. + */ +void blk_ref(BlockBackend *blk) +{ + blk->refcnt++; +} + +/* + * Decrement @blk's reference count. + * If this drops it to zero, destroy @blk. + * For convenience, do nothing if @blk is null. + */ +void blk_unref(BlockBackend *blk) +{ + if (blk) { + assert(blk->refcnt > 0); + if (!--blk->refcnt) { + blk_delete(blk); + } + } +} + +/* + * Return the BlockBackend after @blk. + * If @blk is null, return the first one. + * Else, return @blk's next sibling, which may be null. + * + * To iterate over all BlockBackends, do + * for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { + * ... + * } + */ +BlockBackend *blk_next(BlockBackend *blk) +{ + return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends); +} + +/* + * Return @blk's name, a non-null string. + * Wart: the name is empty iff @blk has been hidden with + * blk_hide_on_behalf_of_do_drive_del(). + */ +const char *blk_name(BlockBackend *blk) +{ + return blk->name; +} + +/* + * Return the BlockBackend with name @name if it exists, else null. + * @name must not be null. + */ +BlockBackend *blk_by_name(const char *name) +{ + BlockBackend *blk; + + assert(name); + QTAILQ_FOREACH(blk, &blk_backends, link) { + if (!strcmp(name, blk->name)) { + return blk; + } + } + return NULL; +} + +/* + * Return the BlockDriverState attached to @blk if any, else null. + */ +BlockDriverState *blk_bs(BlockBackend *blk) +{ + return blk->bs; +} + +/* + * Return @blk's DriveInfo if any, else null. + */ +DriveInfo *blk_legacy_dinfo(BlockBackend *blk) +{ + return blk->legacy_dinfo; +} + +/* + * Set @blk's DriveInfo to @dinfo, and return it. + * @blk must not have a DriveInfo set already. + * No other BlockBackend may have the same DriveInfo set. + */ +DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo) +{ + assert(!blk->legacy_dinfo); + return blk->legacy_dinfo = dinfo; +} + +/* + * Return the BlockBackend with DriveInfo @dinfo. + * It must exist. + */ +BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo) +{ + BlockBackend *blk; + + QTAILQ_FOREACH(blk, &blk_backends, link) { + if (blk->legacy_dinfo == dinfo) { + return blk; + } + } + abort(); +} + +/* + * Hide @blk. + * @blk must not have been hidden already. + * Make attached BlockDriverState, if any, anonymous. + * Once hidden, @blk is invisible to all functions that don't receive + * it as argument. For example, blk_by_name() won't return it. + * Strictly for use by do_drive_del(). + * TODO get rid of it! + */ +void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk) +{ + QTAILQ_REMOVE(&blk_backends, blk, link); + blk->name[0] = 0; + if (blk->bs) { + bdrv_make_anon(blk->bs); + } +} + +/* + * Attach device model @dev to @blk. + * Return 0 on success, -EBUSY when a device model is attached already. + */ +int blk_attach_dev(BlockBackend *blk, void *dev) +/* TODO change to DeviceState *dev when all users are qdevified */ +{ + if (blk->dev) { + return -EBUSY; + } + blk_ref(blk); + blk->dev = dev; + bdrv_iostatus_reset(blk->bs); + + /* We're expecting I/O from the device so bump up coroutine pool size */ + qemu_coroutine_adjust_pool_size(COROUTINE_POOL_RESERVATION); + return 0; +} + +/* + * Attach device model @dev to @blk. + * @blk must not have a device model attached already. + * TODO qdevified devices don't use this, remove when devices are qdevified + */ +void blk_attach_dev_nofail(BlockBackend *blk, void *dev) +{ + if (blk_attach_dev(blk, dev) < 0) { + abort(); + } +} + +/* + * Detach device model @dev from @blk. + * @dev must be currently attached to @blk. + */ +void blk_detach_dev(BlockBackend *blk, void *dev) +/* TODO change to DeviceState *dev when all users are qdevified */ +{ + assert(blk->dev == dev); + blk->dev = NULL; + blk->dev_ops = NULL; + blk->dev_opaque = NULL; + bdrv_set_guest_block_size(blk->bs, 512); + qemu_coroutine_adjust_pool_size(-COROUTINE_POOL_RESERVATION); + blk_unref(blk); +} + +/* + * Return the device model attached to @blk if any, else null. + */ +void *blk_get_attached_dev(BlockBackend *blk) +/* TODO change to return DeviceState * when all users are qdevified */ +{ + return blk->dev; +} + +/* + * Set @blk's device model callbacks to @ops. + * @opaque is the opaque argument to pass to the callbacks. + * This is for use by device models. + */ +void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, + void *opaque) +{ + blk->dev_ops = ops; + blk->dev_opaque = opaque; +} + +/* + * Notify @blk's attached device model of media change. + * If @load is true, notify of media load. + * Else, notify of media eject. + * Also send DEVICE_TRAY_MOVED events as appropriate. + */ +void blk_dev_change_media_cb(BlockBackend *blk, bool load) +{ + if (blk->dev_ops && blk->dev_ops->change_media_cb) { + bool tray_was_closed = !blk_dev_is_tray_open(blk); + + blk->dev_ops->change_media_cb(blk->dev_opaque, load); + if (tray_was_closed) { + /* tray open */ + qapi_event_send_device_tray_moved(blk_name(blk), + true, &error_abort); + } + if (load) { + /* tray close */ + qapi_event_send_device_tray_moved(blk_name(blk), + false, &error_abort); + } + } +} + +/* + * Does @blk's attached device model have removable media? + * %true if no device model is attached. + */ +bool blk_dev_has_removable_media(BlockBackend *blk) +{ + return !blk->dev || (blk->dev_ops && blk->dev_ops->change_media_cb); +} + +/* + * Notify @blk's attached device model of a media eject request. + * If @force is true, the medium is about to be yanked out forcefully. + */ +void blk_dev_eject_request(BlockBackend *blk, bool force) +{ + if (blk->dev_ops && blk->dev_ops->eject_request_cb) { + blk->dev_ops->eject_request_cb(blk->dev_opaque, force); + } +} + +/* + * Does @blk's attached device model have a tray, and is it open? + */ +bool blk_dev_is_tray_open(BlockBackend *blk) +{ + if (blk->dev_ops && blk->dev_ops->is_tray_open) { + return blk->dev_ops->is_tray_open(blk->dev_opaque); + } + return false; +} + +/* + * Does @blk's attached device model have the medium locked? + * %false if the device model has no such lock. + */ +bool blk_dev_is_medium_locked(BlockBackend *blk) +{ + if (blk->dev_ops && blk->dev_ops->is_medium_locked) { + return blk->dev_ops->is_medium_locked(blk->dev_opaque); + } + return false; +} + +/* + * Notify @blk's attached device model of a backend size change. + */ +void blk_dev_resize_cb(BlockBackend *blk) +{ + if (blk->dev_ops && blk->dev_ops->resize_cb) { + blk->dev_ops->resize_cb(blk->dev_opaque); + } +} + +void blk_iostatus_enable(BlockBackend *blk) +{ + bdrv_iostatus_enable(blk->bs); +} + +int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf, + int nb_sectors) +{ + return bdrv_read(blk->bs, sector_num, buf, nb_sectors); +} + +int blk_read_unthrottled(BlockBackend *blk, int64_t sector_num, uint8_t *buf, + int nb_sectors) +{ + return bdrv_read_unthrottled(blk->bs, sector_num, buf, nb_sectors); +} + +int blk_write(BlockBackend *blk, int64_t sector_num, const uint8_t *buf, + int nb_sectors) +{ + return bdrv_write(blk->bs, sector_num, buf, nb_sectors); +} + +BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t sector_num, + int nb_sectors, BdrvRequestFlags flags, + BlockCompletionFunc *cb, void *opaque) +{ + return bdrv_aio_write_zeroes(blk->bs, sector_num, nb_sectors, flags, + cb, opaque); +} + +int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count) +{ + return bdrv_pread(blk->bs, offset, buf, count); +} + +int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count) +{ + return bdrv_pwrite(blk->bs, offset, buf, count); +} + +int64_t blk_getlength(BlockBackend *blk) +{ + return bdrv_getlength(blk->bs); +} + +void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr) +{ + bdrv_get_geometry(blk->bs, nb_sectors_ptr); +} + +BlockAIOCB *blk_aio_readv(BlockBackend *blk, int64_t sector_num, + QEMUIOVector *iov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque) +{ + return bdrv_aio_readv(blk->bs, sector_num, iov, nb_sectors, cb, opaque); +} + +BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num, + QEMUIOVector *iov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque) +{ + return bdrv_aio_writev(blk->bs, sector_num, iov, nb_sectors, cb, opaque); +} + +BlockAIOCB *blk_aio_flush(BlockBackend *blk, + BlockCompletionFunc *cb, void *opaque) +{ + return bdrv_aio_flush(blk->bs, cb, opaque); +} + +BlockAIOCB *blk_aio_discard(BlockBackend *blk, + int64_t sector_num, int nb_sectors, + BlockCompletionFunc *cb, void *opaque) +{ + return bdrv_aio_discard(blk->bs, sector_num, nb_sectors, cb, opaque); +} + +void blk_aio_cancel(BlockAIOCB *acb) +{ + bdrv_aio_cancel(acb); +} + +void blk_aio_cancel_async(BlockAIOCB *acb) +{ + bdrv_aio_cancel_async(acb); +} + +int blk_aio_multiwrite(BlockBackend *blk, BlockRequest *reqs, int num_reqs) +{ + return bdrv_aio_multiwrite(blk->bs, reqs, num_reqs); +} + +int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf) +{ + return bdrv_ioctl(blk->bs, req, buf); +} + +BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf, + BlockCompletionFunc *cb, void *opaque) +{ + return bdrv_aio_ioctl(blk->bs, req, buf, cb, opaque); +} + +int blk_flush(BlockBackend *blk) +{ + return bdrv_flush(blk->bs); +} + +int blk_flush_all(void) +{ + return bdrv_flush_all(); +} + +void blk_drain_all(void) +{ + bdrv_drain_all(); +} + +BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read) +{ + return bdrv_get_on_error(blk->bs, is_read); +} + +BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read, + int error) +{ + return bdrv_get_error_action(blk->bs, is_read, error); +} + +void blk_error_action(BlockBackend *blk, BlockErrorAction action, + bool is_read, int error) +{ + bdrv_error_action(blk->bs, action, is_read, error); +} + +int blk_is_read_only(BlockBackend *blk) +{ + return bdrv_is_read_only(blk->bs); +} + +int blk_is_sg(BlockBackend *blk) +{ + return bdrv_is_sg(blk->bs); +} + +int blk_enable_write_cache(BlockBackend *blk) +{ + return bdrv_enable_write_cache(blk->bs); +} + +void blk_set_enable_write_cache(BlockBackend *blk, bool wce) +{ + bdrv_set_enable_write_cache(blk->bs, wce); +} + +int blk_is_inserted(BlockBackend *blk) +{ + return bdrv_is_inserted(blk->bs); +} + +void blk_lock_medium(BlockBackend *blk, bool locked) +{ + bdrv_lock_medium(blk->bs, locked); +} + +void blk_eject(BlockBackend *blk, bool eject_flag) +{ + bdrv_eject(blk->bs, eject_flag); +} + +int blk_get_flags(BlockBackend *blk) +{ + return bdrv_get_flags(blk->bs); +} + +void blk_set_guest_block_size(BlockBackend *blk, int align) +{ + bdrv_set_guest_block_size(blk->bs, align); +} + +void *blk_blockalign(BlockBackend *blk, size_t size) +{ + return qemu_blockalign(blk ? blk->bs : NULL, size); +} + +bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp) +{ + return bdrv_op_is_blocked(blk->bs, op, errp); +} + +void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason) +{ + bdrv_op_unblock(blk->bs, op, reason); +} + +void blk_op_block_all(BlockBackend *blk, Error *reason) +{ + bdrv_op_block_all(blk->bs, reason); +} + +void blk_op_unblock_all(BlockBackend *blk, Error *reason) +{ + bdrv_op_unblock_all(blk->bs, reason); +} + +AioContext *blk_get_aio_context(BlockBackend *blk) +{ + return bdrv_get_aio_context(blk->bs); +} + +void blk_set_aio_context(BlockBackend *blk, AioContext *new_context) +{ + bdrv_set_aio_context(blk->bs, new_context); +} + +void blk_io_plug(BlockBackend *blk) +{ + bdrv_io_plug(blk->bs); +} + +void blk_io_unplug(BlockBackend *blk) +{ + bdrv_io_unplug(blk->bs); +} + +BlockAcctStats *blk_get_stats(BlockBackend *blk) +{ + return bdrv_get_stats(blk->bs); +} + +void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk, + BlockCompletionFunc *cb, void *opaque) +{ + return qemu_aio_get(aiocb_info, blk_bs(blk), cb, opaque); +} diff --git a/block/commit.c b/block/commit.c index 91517d3..60a2acc 100644 --- a/block/commit.c +++ b/block/commit.c @@ -182,7 +182,7 @@ static const BlockJobDriver commit_job_driver = { void commit_start(BlockDriverState *bs, BlockDriverState *base, BlockDriverState *top, int64_t speed, - BlockdevOnError on_error, BlockDriverCompletionFunc *cb, + BlockdevOnError on_error, BlockCompletionFunc *cb, void *opaque, const char *backing_file_str, Error **errp) { CommitBlockJob *s; diff --git a/block/curl.c b/block/curl.c index 225407c..b4157cc 100644 --- a/block/curl.c +++ b/block/curl.c @@ -78,7 +78,7 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, struct BDRVCURLState; typedef struct CURLAIOCB { - BlockDriverAIOCB common; + BlockAIOCB common; QEMUBH *bh; QEMUIOVector *qiov; @@ -680,9 +680,9 @@ static void curl_readv_bh_cb(void *p) curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); } -static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs, +static BlockAIOCB *curl_aio_readv(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { CURLAIOCB *acb; diff --git a/block/iscsi.c b/block/iscsi.c index 3a01de0..233f462 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -80,7 +80,7 @@ typedef struct IscsiTask { } IscsiTask; typedef struct IscsiAIOCB { - BlockDriverAIOCB common; + BlockAIOCB common; QEMUIOVector *qiov; QEMUBH *bh; IscsiLun *iscsilun; @@ -227,7 +227,7 @@ iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data, } static void -iscsi_aio_cancel(BlockDriverAIOCB *blockacb) +iscsi_aio_cancel(BlockAIOCB *blockacb) { IscsiAIOCB *acb = (IscsiAIOCB *)blockacb; IscsiLun *iscsilun = acb->iscsilun; @@ -663,9 +663,9 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status, iscsi_schedule_bh(acb); } -static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, +static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, unsigned long int req, void *buf, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { IscsiLun *iscsilun = bs->opaque; struct iscsi_context *iscsi = iscsilun->iscsi; @@ -1519,7 +1519,7 @@ static int iscsi_create(const char *filename, QemuOpts *opts, Error **errp) IscsiLun *iscsilun = NULL; QDict *bs_options; - bs = bdrv_new("", &error_abort); + bs = bdrv_new(); /* Read out options */ total_size = DIV_ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), diff --git a/block/linux-aio.c b/block/linux-aio.c index f4baba2..d92513b 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -28,7 +28,7 @@ #define MAX_QUEUED_IO 128 struct qemu_laiocb { - BlockDriverAIOCB common; + BlockAIOCB common; struct qemu_laio_state *ctx; struct iocb iocb; ssize_t ret; @@ -146,7 +146,7 @@ static void qemu_laio_completion_cb(EventNotifier *e) } } -static void laio_cancel(BlockDriverAIOCB *blockacb) +static void laio_cancel(BlockAIOCB *blockacb) { struct qemu_laiocb *laiocb = (struct qemu_laiocb *)blockacb; struct io_event event; @@ -243,9 +243,9 @@ int laio_io_unplug(BlockDriverState *bs, void *aio_ctx, bool unplug) return ret; } -BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, +BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque, int type) + BlockCompletionFunc *cb, void *opaque, int type) { struct qemu_laio_state *s = aio_ctx; struct qemu_laiocb *laiocb; diff --git a/block/mirror.c b/block/mirror.c index 18b18e0..e8a43eb 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -567,7 +567,8 @@ static void mirror_complete(BlockJob *job, Error **errp) return; } if (!s->synced) { - error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name); + error_set(errp, QERR_BLOCK_JOB_NOT_READY, + bdrv_get_device_name(job->bs)); return; } @@ -612,7 +613,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target, int64_t buf_size, BlockdevOnError on_source_error, BlockdevOnError on_target_error, - BlockDriverCompletionFunc *cb, + BlockCompletionFunc *cb, void *opaque, Error **errp, const BlockJobDriver *driver, bool is_none_mode, BlockDriverState *base) @@ -672,7 +673,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target, int64_t speed, int64_t granularity, int64_t buf_size, MirrorSyncMode mode, BlockdevOnError on_source_error, BlockdevOnError on_target_error, - BlockDriverCompletionFunc *cb, + BlockCompletionFunc *cb, void *opaque, Error **errp) { bool is_none_mode; @@ -689,7 +690,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target, void commit_active_start(BlockDriverState *bs, BlockDriverState *base, int64_t speed, BlockdevOnError on_error, - BlockDriverCompletionFunc *cb, + BlockCompletionFunc *cb, void *opaque, Error **errp) { int64_t length, base_length; diff --git a/block/nbd.c b/block/nbd.c index 89775e1..04cc845 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -342,30 +342,44 @@ static void nbd_attach_aio_context(BlockDriverState *bs, static void nbd_refresh_filename(BlockDriverState *bs) { - BDRVNBDState *s = bs->opaque; QDict *opts = qdict_new(); - const char *path = qemu_opt_get(s->socket_opts, "path"); - const char *host = qemu_opt_get(s->socket_opts, "host"); - const char *port = qemu_opt_get(s->socket_opts, "port"); - const char *export = qemu_opt_get(s->socket_opts, "export"); + const char *path = qdict_get_try_str(bs->options, "path"); + const char *host = qdict_get_try_str(bs->options, "host"); + const char *port = qdict_get_try_str(bs->options, "port"); + const char *export = qdict_get_try_str(bs->options, "export"); qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("nbd"))); - if (path) { + if (path && export) { snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd+unix:%s", path); - qdict_put_obj(opts, "path", QOBJECT(qstring_from_str(path))); - } else if (export) { + "nbd+unix:///%s?socket=%s", export, path); + } else if (path && !export) { snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd:%s:%s/%s", host, port, export); - qdict_put_obj(opts, "host", QOBJECT(qstring_from_str(host))); - qdict_put_obj(opts, "port", QOBJECT(qstring_from_str(port))); - qdict_put_obj(opts, "export", QOBJECT(qstring_from_str(export))); - } else { + "nbd+unix://?socket=%s", path); + } else if (!path && export && port) { + snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nbd://%s:%s/%s", host, port, export); + } else if (!path && export && !port) { + snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nbd://%s/%s", host, export); + } else if (!path && !export && port) { + snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nbd://%s:%s", host, port); + } else if (!path && !export && !port) { snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd:%s:%s", host, port); + "nbd://%s", host); + } + + if (path) { + qdict_put_obj(opts, "path", QOBJECT(qstring_from_str(path))); + } else if (port) { qdict_put_obj(opts, "host", QOBJECT(qstring_from_str(host))); qdict_put_obj(opts, "port", QOBJECT(qstring_from_str(port))); + } else { + qdict_put_obj(opts, "host", QOBJECT(qstring_from_str(host))); + } + if (export) { + qdict_put_obj(opts, "export", QOBJECT(qstring_from_str(export))); } bs->full_open_options = opts; diff --git a/block/null.c b/block/null.c index 8284419..ec2bd27 100644 --- a/block/null.c +++ b/block/null.c @@ -78,7 +78,7 @@ static coroutine_fn int null_co_flush(BlockDriverState *bs) } typedef struct { - BlockDriverAIOCB common; + BlockAIOCB common; QEMUBH *bh; } NullAIOCB; @@ -94,9 +94,9 @@ static void null_bh_cb(void *opaque) qemu_aio_unref(acb); } -static inline BlockDriverAIOCB *null_aio_common(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, - void *opaque) +static inline BlockAIOCB *null_aio_common(BlockDriverState *bs, + BlockCompletionFunc *cb, + void *opaque) { NullAIOCB *acb; @@ -106,27 +106,27 @@ static inline BlockDriverAIOCB *null_aio_common(BlockDriverState *bs, return &acb->common; } -static BlockDriverAIOCB *null_aio_readv(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque) +static BlockAIOCB *null_aio_readv(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, + int nb_sectors, + BlockCompletionFunc *cb, + void *opaque) { return null_aio_common(bs, cb, opaque); } -static BlockDriverAIOCB *null_aio_writev(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque) +static BlockAIOCB *null_aio_writev(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, + int nb_sectors, + BlockCompletionFunc *cb, + void *opaque) { return null_aio_common(bs, cb, opaque); } -static BlockDriverAIOCB *null_aio_flush(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, - void *opaque) +static BlockAIOCB *null_aio_flush(BlockDriverState *bs, + BlockCompletionFunc *cb, + void *opaque) { return null_aio_common(bs, cb, opaque); } diff --git a/block/qapi.c b/block/qapi.c index 9733ebd..1301144 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -28,6 +28,7 @@ #include "qapi-visit.h" #include "qapi/qmp-output-visitor.h" #include "qapi/qmp/types.h" +#include "sysemu/block-backend.h" #ifdef __linux__ #include <linux/fs.h> #include <sys/ioctl.h> @@ -264,22 +265,22 @@ void bdrv_query_image_info(BlockDriverState *bs, } /* @p_info will be set only on success. */ -void bdrv_query_info(BlockDriverState *bs, - BlockInfo **p_info, - Error **errp) +static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, + Error **errp) { BlockInfo *info = g_malloc0(sizeof(*info)); + BlockDriverState *bs = blk_bs(blk); BlockDriverState *bs0; ImageInfo **p_image_info; Error *local_err = NULL; - info->device = g_strdup(bs->device_name); + info->device = g_strdup(blk_name(blk)); info->type = g_strdup("unknown"); - info->locked = bdrv_dev_is_medium_locked(bs); - info->removable = bdrv_dev_has_removable_media(bs); + info->locked = blk_dev_is_medium_locked(blk); + info->removable = blk_dev_has_removable_media(blk); - if (bdrv_dev_has_removable_media(bs)) { + if (blk_dev_has_removable_media(blk)) { info->has_tray_open = true; - info->tray_open = bdrv_dev_is_tray_open(bs); + info->tray_open = blk_dev_is_tray_open(blk); } if (bdrv_iostatus_is_enabled(bs)) { @@ -327,9 +328,9 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs) s = g_malloc0(sizeof(*s)); - if (bs->device_name[0]) { + if (bdrv_get_device_name(bs)[0]) { s->has_device = true; - s->device = g_strdup(bs->device_name); + s->device = g_strdup(bdrv_get_device_name(bs)); } s->stats = g_malloc0(sizeof(*s->stats)); @@ -360,12 +361,12 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs) BlockInfoList *qmp_query_block(Error **errp) { BlockInfoList *head = NULL, **p_next = &head; - BlockDriverState *bs = NULL; + BlockBackend *blk; Error *local_err = NULL; - while ((bs = bdrv_next(bs))) { + for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { BlockInfoList *info = g_malloc0(sizeof(*info)); - bdrv_query_info(bs, &info->value, &local_err); + bdrv_query_info(blk, &info->value, &local_err); if (local_err) { error_propagate(errp, local_err); goto err; diff --git a/block/qcow.c b/block/qcow.c index a87bd69..ece2269 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -124,7 +124,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, snprintf(version, sizeof(version), "QCOW version %" PRIu32, header.version); error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, - bs->device_name, "qcow", version); + bdrv_get_device_name(bs), "qcow", version); ret = -ENOTSUP; goto fail; } @@ -231,7 +231,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, /* Disable migration when qcow images are used */ error_set(&s->migration_blocker, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, - "qcow", bs->device_name, "live migration"); + "qcow", bdrv_get_device_name(bs), "live migration"); migrate_add_blocker(s->migration_blocker); qemu_co_mutex_init(&s->lock); diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 2bcaaf9..c31d85a 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -524,6 +524,7 @@ found: QTAILQ_REMOVE(&s->discards, p, next); d->offset = MIN(d->offset, p->offset); d->bytes += p->bytes; + g_free(p); } } diff --git a/block/qcow2.c b/block/qcow2.c index fb28493..156a219 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -206,8 +206,8 @@ static void GCC_FMT_ATTR(3, 4) report_unsupported(BlockDriverState *bs, vsnprintf(msg, sizeof(msg), fmt, ap); va_end(ap); - error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, bs->device_name, "qcow2", - msg); + error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, + bdrv_get_device_name(bs), "qcow2", msg); } static void report_unsupported_feature(BlockDriverState *bs, diff --git a/block/qed-gencb.c b/block/qed-gencb.c index 7d7ac1f..b817a8b 100644 --- a/block/qed-gencb.c +++ b/block/qed-gencb.c @@ -13,7 +13,7 @@ #include "qed.h" -void *gencb_alloc(size_t len, BlockDriverCompletionFunc *cb, void *opaque) +void *gencb_alloc(size_t len, BlockCompletionFunc *cb, void *opaque) { GenericCB *gencb = g_malloc(len); gencb->cb = cb; @@ -24,7 +24,7 @@ void *gencb_alloc(size_t len, BlockDriverCompletionFunc *cb, void *opaque) void gencb_complete(void *opaque, int ret) { GenericCB *gencb = opaque; - BlockDriverCompletionFunc *cb = gencb->cb; + BlockCompletionFunc *cb = gencb->cb; void *user_opaque = gencb->opaque; g_free(gencb); diff --git a/block/qed-table.c b/block/qed-table.c index f61107a..513aa87 100644 --- a/block/qed-table.c +++ b/block/qed-table.c @@ -49,7 +49,7 @@ out: } static void qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { QEDReadTableCB *read_table_cb = gencb_alloc(sizeof(*read_table_cb), cb, opaque); @@ -119,7 +119,7 @@ out: */ static void qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table, unsigned int index, unsigned int n, bool flush, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { QEDWriteTableCB *write_table_cb; unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1; @@ -180,7 +180,7 @@ int qed_read_l1_table_sync(BDRVQEDState *s) } void qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { BLKDBG_EVENT(s->bs->file, BLKDBG_L1_UPDATE); qed_write_table(s, s->header.l1_table_offset, @@ -235,7 +235,7 @@ static void qed_read_l2_table_cb(void *opaque, int ret) } void qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { QEDReadL2TableCB *read_l2_table_cb; @@ -275,7 +275,7 @@ int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset void qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, unsigned int index, unsigned int n, bool flush, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { BLKDBG_EVENT(s->bs->file, BLKDBG_L2_UPDATE); qed_write_table(s, request->l2_table->offset, diff --git a/block/qed.c b/block/qed.c index e2316d7..80f18d8 100644 --- a/block/qed.c +++ b/block/qed.c @@ -130,7 +130,7 @@ static void qed_write_header_read_cb(void *opaque, int ret) * This function only updates known header fields in-place and does not affect * extra data after the QED header. */ -static void qed_write_header(BDRVQEDState *s, BlockDriverCompletionFunc cb, +static void qed_write_header(BDRVQEDState *s, BlockCompletionFunc cb, void *opaque) { /* We must write full sectors for O_DIRECT but cannot necessarily generate @@ -408,7 +408,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags, snprintf(buf, sizeof(buf), "%" PRIx64, s->header.features & ~QED_FEATURE_MASK); error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, - bs->device_name, "QED", buf); + bdrv_get_device_name(bs), "QED", buf); return -ENOTSUP; } if (!qed_is_cluster_size_valid(s->header.cluster_size)) { @@ -759,7 +759,7 @@ static BDRVQEDState *acb_to_s(QEDAIOCB *acb) static void qed_read_backing_file(BDRVQEDState *s, uint64_t pos, QEMUIOVector *qiov, QEMUIOVector **backing_qiov, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { uint64_t backing_length = 0; size_t size; @@ -851,7 +851,7 @@ static void qed_copy_from_backing_file_write(void *opaque, int ret) */ static void qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos, uint64_t len, uint64_t offset, - BlockDriverCompletionFunc *cb, + BlockCompletionFunc *cb, void *opaque) { CopyFromBackingFileCB *copy_cb; @@ -902,7 +902,7 @@ static void qed_update_l2_table(BDRVQEDState *s, QEDTable *table, int index, static void qed_aio_complete_bh(void *opaque) { QEDAIOCB *acb = opaque; - BlockDriverCompletionFunc *cb = acb->common.cb; + BlockCompletionFunc *cb = acb->common.cb; void *user_opaque = acb->common.opaque; int ret = acb->bh_ret; @@ -1064,7 +1064,7 @@ static void qed_aio_write_main(void *opaque, int ret) BDRVQEDState *s = acb_to_s(acb); uint64_t offset = acb->cur_cluster + qed_offset_into_cluster(s, acb->cur_pos); - BlockDriverCompletionFunc *next_fn; + BlockCompletionFunc *next_fn; trace_qed_aio_write_main(s, acb, ret, offset, acb->cur_qiov.size); @@ -1164,7 +1164,7 @@ static void qed_aio_write_zero_cluster(void *opaque, int ret) static void qed_aio_write_alloc(QEDAIOCB *acb, size_t len) { BDRVQEDState *s = acb_to_s(acb); - BlockDriverCompletionFunc *cb; + BlockCompletionFunc *cb; /* Cancel timer when the first allocating request comes in */ if (QSIMPLEQ_EMPTY(&s->allocating_write_reqs)) { @@ -1365,11 +1365,11 @@ static void qed_aio_next_io(void *opaque, int ret) io_fn, acb); } -static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque, int flags) +static BlockAIOCB *qed_aio_setup(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, int nb_sectors, + BlockCompletionFunc *cb, + void *opaque, int flags) { QEDAIOCB *acb = qemu_aio_get(&qed_aiocb_info, bs, cb, opaque); @@ -1390,20 +1390,20 @@ static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs, return &acb->common; } -static BlockDriverAIOCB *bdrv_qed_aio_readv(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque) +static BlockAIOCB *bdrv_qed_aio_readv(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, int nb_sectors, + BlockCompletionFunc *cb, + void *opaque) { return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); } -static BlockDriverAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque) +static BlockAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, int nb_sectors, + BlockCompletionFunc *cb, + void *opaque) { return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, QED_AIOCB_WRITE); @@ -1431,7 +1431,7 @@ static int coroutine_fn bdrv_qed_co_write_zeroes(BlockDriverState *bs, int nb_sectors, BdrvRequestFlags flags) { - BlockDriverAIOCB *blockacb; + BlockAIOCB *blockacb; BDRVQEDState *s = bs->opaque; QEDWriteZeroesCB cb = { .done = false }; QEMUIOVector qiov; diff --git a/block/qed.h b/block/qed.h index 2b0e724..d3934a0 100644 --- a/block/qed.h +++ b/block/qed.h @@ -128,7 +128,7 @@ enum { }; typedef struct QEDAIOCB { - BlockDriverAIOCB common; + BlockAIOCB common; QEMUBH *bh; int bh_ret; /* final return status for completion bh */ QSIMPLEQ_ENTRY(QEDAIOCB) next; /* next request */ @@ -203,11 +203,11 @@ typedef void QEDFindClusterFunc(void *opaque, int ret, uint64_t offset, size_t l * Generic callback for chaining async callbacks */ typedef struct { - BlockDriverCompletionFunc *cb; + BlockCompletionFunc *cb; void *opaque; } GenericCB; -void *gencb_alloc(size_t len, BlockDriverCompletionFunc *cb, void *opaque); +void *gencb_alloc(size_t len, BlockCompletionFunc *cb, void *opaque); void gencb_complete(void *opaque, int ret); /** @@ -230,16 +230,16 @@ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table); */ int qed_read_l1_table_sync(BDRVQEDState *s); void qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n, - BlockDriverCompletionFunc *cb, void *opaque); + BlockCompletionFunc *cb, void *opaque); int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, unsigned int n); int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset); void qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset, - BlockDriverCompletionFunc *cb, void *opaque); + BlockCompletionFunc *cb, void *opaque); void qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, unsigned int index, unsigned int n, bool flush, - BlockDriverCompletionFunc *cb, void *opaque); + BlockCompletionFunc *cb, void *opaque); int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request, unsigned int index, unsigned int n, bool flush); diff --git a/block/quorum.c b/block/quorum.c index 7687466..437b122 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -92,7 +92,7 @@ typedef struct QuorumAIOCB QuorumAIOCB; * $children_count QuorumChildRequest. */ typedef struct QuorumChildRequest { - BlockDriverAIOCB *aiocb; + BlockAIOCB *aiocb; QEMUIOVector qiov; uint8_t *buf; int ret; @@ -105,7 +105,7 @@ typedef struct QuorumChildRequest { * used to do operations on each children and track overall progress. */ struct QuorumAIOCB { - BlockDriverAIOCB common; + BlockAIOCB common; /* Request metadata */ uint64_t sector_num; @@ -130,7 +130,7 @@ struct QuorumAIOCB { static bool quorum_vote(QuorumAIOCB *acb); -static void quorum_aio_cancel(BlockDriverAIOCB *blockacb) +static void quorum_aio_cancel(BlockAIOCB *blockacb) { QuorumAIOCB *acb = container_of(blockacb, QuorumAIOCB, common); BDRVQuorumState *s = acb->common.bs->opaque; @@ -186,7 +186,7 @@ static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s, QEMUIOVector *qiov, uint64_t sector_num, int nb_sectors, - BlockDriverCompletionFunc *cb, + BlockCompletionFunc *cb, void *opaque) { QuorumAIOCB *acb = qemu_aio_get(&quorum_aiocb_info, bs, cb, opaque); @@ -226,8 +226,8 @@ static void quorum_report_bad(QuorumAIOCB *acb, char *node_name, int ret) static void quorum_report_failure(QuorumAIOCB *acb) { - const char *reference = acb->common.bs->device_name[0] ? - acb->common.bs->device_name : + const char *reference = bdrv_get_device_name(acb->common.bs)[0] ? + bdrv_get_device_name(acb->common.bs) : acb->common.bs->node_name; qapi_event_send_quorum_failure(reference, acb->sector_num, @@ -264,7 +264,7 @@ static void quorum_rewrite_aio_cb(void *opaque, int ret) quorum_aio_finalize(acb); } -static BlockDriverAIOCB *read_fifo_child(QuorumAIOCB *acb); +static BlockAIOCB *read_fifo_child(QuorumAIOCB *acb); static void quorum_copy_qiov(QEMUIOVector *dest, QEMUIOVector *source) { @@ -640,7 +640,7 @@ free_exit: return rewrite; } -static BlockDriverAIOCB *read_quorum_children(QuorumAIOCB *acb) +static BlockAIOCB *read_quorum_children(QuorumAIOCB *acb) { BDRVQuorumState *s = acb->common.bs->opaque; int i; @@ -659,7 +659,7 @@ static BlockDriverAIOCB *read_quorum_children(QuorumAIOCB *acb) return &acb->common; } -static BlockDriverAIOCB *read_fifo_child(QuorumAIOCB *acb) +static BlockAIOCB *read_fifo_child(QuorumAIOCB *acb) { BDRVQuorumState *s = acb->common.bs->opaque; @@ -675,12 +675,12 @@ static BlockDriverAIOCB *read_fifo_child(QuorumAIOCB *acb) return &acb->common; } -static BlockDriverAIOCB *quorum_aio_readv(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque) +static BlockAIOCB *quorum_aio_readv(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, + int nb_sectors, + BlockCompletionFunc *cb, + void *opaque) { BDRVQuorumState *s = bs->opaque; QuorumAIOCB *acb = quorum_aio_get(s, bs, qiov, sector_num, @@ -696,12 +696,12 @@ static BlockDriverAIOCB *quorum_aio_readv(BlockDriverState *bs, return read_fifo_child(acb); } -static BlockDriverAIOCB *quorum_aio_writev(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque) +static BlockAIOCB *quorum_aio_writev(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, + int nb_sectors, + BlockCompletionFunc *cb, + void *opaque) { BDRVQuorumState *s = bs->opaque; QuorumAIOCB *acb = quorum_aio_get(s, bs, qiov, sector_num, nb_sectors, diff --git a/block/raw-aio.h b/block/raw-aio.h index e18c975..80681ce 100644 --- a/block/raw-aio.h +++ b/block/raw-aio.h @@ -35,9 +35,9 @@ #ifdef CONFIG_LINUX_AIO void *laio_init(void); void laio_cleanup(void *s); -BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, +BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque, int type); + BlockCompletionFunc *cb, void *opaque, int type); void laio_detach_aio_context(void *s, AioContext *old_context); void laio_attach_aio_context(void *s, AioContext *new_context); void laio_io_plug(BlockDriverState *bs, void *aio_ctx); @@ -49,10 +49,10 @@ typedef struct QEMUWin32AIOState QEMUWin32AIOState; QEMUWin32AIOState *win32_aio_init(void); void win32_aio_cleanup(QEMUWin32AIOState *aio); int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile); -BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs, +BlockAIOCB *win32_aio_submit(BlockDriverState *bs, QEMUWin32AIOState *aio, HANDLE hfile, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque, int type); + BlockCompletionFunc *cb, void *opaque, int type); void win32_aio_detach_aio_context(QEMUWin32AIOState *aio, AioContext *old_context); void win32_aio_attach_aio_context(QEMUWin32AIOState *aio, diff --git a/block/raw-posix.c b/block/raw-posix.c index 86ce4f2..ee4ca3c 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -1041,9 +1041,9 @@ static int paio_submit_co(BlockDriverState *bs, int fd, return thread_pool_submit_co(pool, aio_worker, acb); } -static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd, +static BlockAIOCB *paio_submit(BlockDriverState *bs, int fd, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque, int type) + BlockCompletionFunc *cb, void *opaque, int type) { RawPosixAIOData *acb = g_slice_new(RawPosixAIOData); ThreadPool *pool; @@ -1066,9 +1066,9 @@ static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd, return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque); } -static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs, +static BlockAIOCB *raw_aio_submit(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque, int type) + BlockCompletionFunc *cb, void *opaque, int type) { BDRVRawState *s = bs->opaque; @@ -1125,24 +1125,24 @@ static void raw_aio_flush_io_queue(BlockDriverState *bs) #endif } -static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs, +static BlockAIOCB *raw_aio_readv(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { return raw_aio_submit(bs, sector_num, qiov, nb_sectors, cb, opaque, QEMU_AIO_READ); } -static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs, +static BlockAIOCB *raw_aio_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { return raw_aio_submit(bs, sector_num, qiov, nb_sectors, cb, opaque, QEMU_AIO_WRITE); } -static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque) +static BlockAIOCB *raw_aio_flush(BlockDriverState *bs, + BlockCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; @@ -1482,7 +1482,7 @@ static int64_t try_fiemap(BlockDriverState *bs, off_t start, off_t *data, f.fm.fm_start = start; f.fm.fm_length = (int64_t)nb_sectors * BDRV_SECTOR_SIZE; - f.fm.fm_flags = 0; + f.fm.fm_flags = FIEMAP_FLAG_SYNC; f.fm.fm_extent_count = 1; f.fm.fm_reserved = 0; if (ioctl(s->fd, FS_IOC_FIEMAP, &f) == -1) { @@ -1571,9 +1571,9 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, start = sector_num * BDRV_SECTOR_SIZE; - ret = try_fiemap(bs, start, &data, &hole, nb_sectors, pnum); + ret = try_seek_hole(bs, start, &data, &hole, pnum); if (ret < 0) { - ret = try_seek_hole(bs, start, &data, &hole, pnum); + ret = try_fiemap(bs, start, &data, &hole, nb_sectors, pnum); if (ret < 0) { /* Assume everything is allocated. */ data = 0; @@ -1595,9 +1595,9 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, return ret; } -static coroutine_fn BlockDriverAIOCB *raw_aio_discard(BlockDriverState *bs, +static coroutine_fn BlockAIOCB *raw_aio_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; @@ -1935,9 +1935,9 @@ static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) return ioctl(s->fd, req, buf); } -static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs, +static BlockAIOCB *hdev_aio_ioctl(BlockDriverState *bs, unsigned long int req, void *buf, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; RawPosixAIOData *acb; @@ -1976,9 +1976,9 @@ static int fd_open(BlockDriverState *bs) #endif /* !linux && !FreeBSD */ -static coroutine_fn BlockDriverAIOCB *hdev_aio_discard(BlockDriverState *bs, +static coroutine_fn BlockAIOCB *hdev_aio_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; diff --git a/block/raw-win32.c b/block/raw-win32.c index 9bf8225..7b58881 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -138,9 +138,9 @@ static int aio_worker(void *arg) return ret; } -static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile, +static BlockAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque, int type) + BlockCompletionFunc *cb, void *opaque, int type) { RawWin32AIOData *acb = g_slice_new(RawWin32AIOData); ThreadPool *pool; @@ -369,9 +369,9 @@ fail: return ret; } -static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs, +static BlockAIOCB *raw_aio_readv(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; if (s->aio) { @@ -383,9 +383,9 @@ static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs, } } -static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs, +static BlockAIOCB *raw_aio_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; if (s->aio) { @@ -397,8 +397,8 @@ static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs, } } -static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque) +static BlockAIOCB *raw_aio_flush(BlockDriverState *bs, + BlockCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; return paio_submit(bs, s->hfile, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH); diff --git a/block/raw_bsd.c b/block/raw_bsd.c index f82f4c2..401b967 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -129,10 +129,10 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) return bdrv_ioctl(bs->file, req, buf); } -static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, - unsigned long int req, void *buf, - BlockDriverCompletionFunc *cb, - void *opaque) +static BlockAIOCB *raw_aio_ioctl(BlockDriverState *bs, + unsigned long int req, void *buf, + BlockCompletionFunc *cb, + void *opaque) { return bdrv_aio_ioctl(bs->file, req, buf, cb, opaque); } diff --git a/block/rbd.c b/block/rbd.c index 96947e3..47cab8b 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -68,7 +68,7 @@ typedef enum { } RBDAIOCmd; typedef struct RBDAIOCB { - BlockDriverAIOCB common; + BlockAIOCB common; QEMUBH *bh; int64_t ret; QEMUIOVector *qiov; @@ -589,13 +589,13 @@ static int rbd_aio_flush_wrapper(rbd_image_t image, #endif } -static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque, - RBDAIOCmd cmd) +static BlockAIOCB *rbd_start_aio(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, + int nb_sectors, + BlockCompletionFunc *cb, + void *opaque, + RBDAIOCmd cmd) { RBDAIOCB *acb; RADOSCB *rcb = NULL; @@ -675,32 +675,32 @@ failed: return NULL; } -static BlockDriverAIOCB *qemu_rbd_aio_readv(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque) +static BlockAIOCB *qemu_rbd_aio_readv(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, + int nb_sectors, + BlockCompletionFunc *cb, + void *opaque) { return rbd_start_aio(bs, sector_num, qiov, nb_sectors, cb, opaque, RBD_AIO_READ); } -static BlockDriverAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque) +static BlockAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, + int nb_sectors, + BlockCompletionFunc *cb, + void *opaque) { return rbd_start_aio(bs, sector_num, qiov, nb_sectors, cb, opaque, RBD_AIO_WRITE); } #ifdef LIBRBD_SUPPORTS_AIO_FLUSH -static BlockDriverAIOCB *qemu_rbd_aio_flush(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, - void *opaque) +static BlockAIOCB *qemu_rbd_aio_flush(BlockDriverState *bs, + BlockCompletionFunc *cb, + void *opaque) { return rbd_start_aio(bs, 0, NULL, 0, cb, opaque, RBD_AIO_FLUSH); } @@ -876,11 +876,11 @@ static int qemu_rbd_snap_list(BlockDriverState *bs, } #ifdef LIBRBD_SUPPORTS_DISCARD -static BlockDriverAIOCB* qemu_rbd_aio_discard(BlockDriverState *bs, - int64_t sector_num, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque) +static BlockAIOCB* qemu_rbd_aio_discard(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, + BlockCompletionFunc *cb, + void *opaque) { return rbd_start_aio(bs, sector_num, NULL, nb_sectors, cb, opaque, RBD_AIO_DISCARD); diff --git a/block/sheepdog.c b/block/sheepdog.c index 2d78ef9..be3176f 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -301,7 +301,7 @@ enum AIOCBState { }; struct SheepdogAIOCB { - BlockDriverAIOCB common; + BlockAIOCB common; QEMUIOVector *qiov; @@ -473,7 +473,7 @@ static bool sd_acb_cancelable(const SheepdogAIOCB *acb) return true; } -static void sd_aio_cancel(BlockDriverAIOCB *blockacb) +static void sd_aio_cancel(BlockAIOCB *blockacb) { SheepdogAIOCB *acb = (SheepdogAIOCB *)blockacb; BDRVSheepdogState *s = acb->common.bs->opaque; diff --git a/block/stream.c b/block/stream.c index cdea3e8..a1dc8da 100644 --- a/block/stream.c +++ b/block/stream.c @@ -220,7 +220,7 @@ static const BlockJobDriver stream_job_driver = { void stream_start(BlockDriverState *bs, BlockDriverState *base, const char *backing_file_str, int64_t speed, BlockdevOnError on_error, - BlockDriverCompletionFunc *cb, + BlockCompletionFunc *cb, void *opaque, Error **errp) { StreamBlockJob *s; diff --git a/block/vdi.c b/block/vdi.c index cfa08b0..9604721 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -490,7 +490,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags, /* Disable migration when vdi images are used */ error_set(&s->migration_blocker, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, - "vdi", bs->device_name, "live migration"); + "vdi", bdrv_get_device_name(bs), "live migration"); migrate_add_blocker(s->migration_blocker); return 0; diff --git a/block/vhdx.c b/block/vhdx.c index b046448..12bfe75 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -1004,7 +1004,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags, /* Disable migration when VHDX images are used */ error_set(&s->migration_blocker, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, - "vhdx", bs->device_name, "live migration"); + "vhdx", bdrv_get_device_name(bs), "live migration"); migrate_add_blocker(s->migration_blocker); return 0; diff --git a/block/vmdk.c b/block/vmdk.c index 4ae6c75..673d3f5 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -657,7 +657,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, snprintf(buf, sizeof(buf), "VMDK version %" PRId32, le32_to_cpu(header.version)); error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, - bs->device_name, "vmdk", buf); + bdrv_get_device_name(bs), "vmdk", buf); return -ENOTSUP; } else if (le32_to_cpu(header.version) == 3 && (flags & BDRV_O_RDWR)) { /* VMware KB 2064959 explains that version 3 added support for @@ -939,7 +939,7 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, /* Disable migration when VMDK images are used */ error_set(&s->migration_blocker, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, - "vmdk", bs->device_name, "live migration"); + "vmdk", bdrv_get_device_name(bs), "live migration"); migrate_add_blocker(s->migration_blocker); g_free(buf); return 0; diff --git a/block/vpc.c b/block/vpc.c index e08144a..38c4f02 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -320,7 +320,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, /* Disable migration when VHD images are used */ error_set(&s->migration_blocker, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, - "vpc", bs->device_name, "live migration"); + "vpc", bdrv_get_device_name(bs), "live migration"); migrate_add_blocker(s->migration_blocker); return 0; diff --git a/block/vvfat.c b/block/vvfat.c index 731e591..cefe3a4 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -1182,7 +1182,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, if (s->qcow) { error_set(&s->migration_blocker, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, - "vvfat (rw)", bs->device_name, "live migration"); + "vvfat (rw)", bdrv_get_device_name(bs), "live migration"); migrate_add_blocker(s->migration_blocker); } @@ -2939,7 +2939,7 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp) unlink(s->qcow_filename); #endif - bdrv_set_backing_hd(s->bs, bdrv_new("", &error_abort)); + bdrv_set_backing_hd(s->bs, bdrv_new()); s->bs->backing_hd->drv = &vvfat_write_target; s->bs->backing_hd->opaque = g_new(void *, 1); *(void**)s->bs->backing_hd->opaque = s; diff --git a/block/win32-aio.c b/block/win32-aio.c index 9323c1a..64e8682 100644 --- a/block/win32-aio.c +++ b/block/win32-aio.c @@ -44,7 +44,7 @@ struct QEMUWin32AIOState { }; typedef struct QEMUWin32AIOCB { - BlockDriverAIOCB common; + BlockAIOCB common; struct QEMUWin32AIOState *ctx; int nbytes; OVERLAPPED ov; @@ -110,10 +110,10 @@ static const AIOCBInfo win32_aiocb_info = { .aiocb_size = sizeof(QEMUWin32AIOCB), }; -BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs, +BlockAIOCB *win32_aio_submit(BlockDriverState *bs, QEMUWin32AIOState *aio, HANDLE hfile, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque, int type) + BlockCompletionFunc *cb, void *opaque, int type) { struct QEMUWin32AIOCB *waiocb; uint64_t offset = sector_num * 512; @@ -30,6 +30,7 @@ * THE SOFTWARE. */ +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/block/block.h" #include "block/blockjob.h" @@ -46,8 +47,6 @@ #include "trace.h" #include "sysemu/arch_init.h" -static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives); - static const char *const if_name[IF_COUNT] = { [IF_NONE] = "none", [IF_IDE] = "ide", @@ -85,13 +84,15 @@ static int if_max_devs[IF_COUNT] = { */ void override_max_devs(BlockInterfaceType type, int max_devs) { + BlockBackend *blk; DriveInfo *dinfo; if (max_devs <= 0) { return; } - QTAILQ_FOREACH(dinfo, &drives, next) { + for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { + dinfo = blk_legacy_dinfo(blk); if (dinfo->type == type) { fprintf(stderr, "Cannot override units-per-bus property of" " the %s interface, because a drive of that type has" @@ -110,28 +111,27 @@ void override_max_devs(BlockInterfaceType type, int max_devs) * automatic deletion, and generic qdev code calls blockdev_auto_del() * when deletion is actually safe. */ -void blockdev_mark_auto_del(BlockDriverState *bs) +void blockdev_mark_auto_del(BlockBackend *blk) { - DriveInfo *dinfo = drive_get_by_blockdev(bs); + DriveInfo *dinfo = blk_legacy_dinfo(blk); + BlockDriverState *bs = blk_bs(blk); - if (dinfo && !dinfo->enable_auto_del) { + if (!dinfo) { return; } if (bs->job) { block_job_cancel(bs->job); } - if (dinfo) { - dinfo->auto_del = 1; - } + dinfo->auto_del = 1; } -void blockdev_auto_del(BlockDriverState *bs) +void blockdev_auto_del(BlockBackend *blk) { - DriveInfo *dinfo = drive_get_by_blockdev(bs); + DriveInfo *dinfo = blk_legacy_dinfo(blk); if (dinfo && dinfo->auto_del) { - drive_del(dinfo); + blk_unref(blk); } } @@ -193,15 +193,15 @@ QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file, DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) { + BlockBackend *blk; DriveInfo *dinfo; - /* seek interface, bus and unit */ - - QTAILQ_FOREACH(dinfo, &drives, next) { - if (dinfo->type == type && - dinfo->bus == bus && - dinfo->unit == unit) + for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { + dinfo = blk_legacy_dinfo(blk); + if (dinfo && dinfo->type == type + && dinfo->bus == bus && dinfo->unit == unit) { return dinfo; + } } return NULL; @@ -209,17 +209,19 @@ DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) bool drive_check_orphaned(void) { + BlockBackend *blk; DriveInfo *dinfo; bool rs = false; - QTAILQ_FOREACH(dinfo, &drives, next) { + for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { + dinfo = blk_legacy_dinfo(blk); /* If dinfo->bdrv->dev is NULL, it has no device attached. */ /* Unless this is a default drive, this may be an oversight. */ - if (!dinfo->bdrv->dev && !dinfo->is_default && + if (!blk_get_attached_dev(blk) && !dinfo->is_default && dinfo->type != IF_NONE) { fprintf(stderr, "Warning: Orphaned drive without device: " "id=%s,file=%s,if=%s,bus=%d,unit=%d\n", - dinfo->id, dinfo->bdrv->filename, if_name[dinfo->type], + blk_name(blk), blk_bs(blk)->filename, if_name[dinfo->type], dinfo->bus, dinfo->unit); rs = true; } @@ -238,13 +240,15 @@ DriveInfo *drive_get_by_index(BlockInterfaceType type, int index) int drive_get_max_bus(BlockInterfaceType type) { int max_bus; + BlockBackend *blk; DriveInfo *dinfo; max_bus = -1; - QTAILQ_FOREACH(dinfo, &drives, next) { - if(dinfo->type == type && - dinfo->bus > max_bus) + for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { + dinfo = blk_legacy_dinfo(blk); + if (dinfo && dinfo->type == type && dinfo->bus > max_bus) { max_bus = dinfo->bus; + } } return max_bus; } @@ -259,40 +263,11 @@ DriveInfo *drive_get_next(BlockInterfaceType type) return drive_get(type, 0, next_block_unit[type]++); } -DriveInfo *drive_get_by_blockdev(BlockDriverState *bs) -{ - DriveInfo *dinfo; - - QTAILQ_FOREACH(dinfo, &drives, next) { - if (dinfo->bdrv == bs) { - return dinfo; - } - } - return NULL; -} - static void bdrv_format_print(void *opaque, const char *name) { error_printf(" %s", name); } -void drive_del(DriveInfo *dinfo) -{ - bdrv_unref(dinfo->bdrv); -} - -void drive_info_del(DriveInfo *dinfo) -{ - if (!dinfo) { - return; - } - qemu_opts_del(dinfo->opts); - g_free(dinfo->id); - QTAILQ_REMOVE(&drives, dinfo, next); - g_free(dinfo->serial); - g_free(dinfo); -} - typedef struct { QEMUBH *bh; BlockDriverState *bs; @@ -360,15 +335,15 @@ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp) typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType; /* Takes the ownership of bs_opts */ -static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, - Error **errp) +static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, + Error **errp) { const char *buf; int ro = 0; int bdrv_flags = 0; int on_read_error, on_write_error; + BlockBackend *blk; BlockDriverState *bs; - DriveInfo *dinfo; ThrottleConfig cfg; int snapshot = 0; bool copy_on_read; @@ -523,10 +498,11 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, } /* init */ - bs = bdrv_new(qemu_opts_id(opts), errp); - if (!bs) { + blk = blk_new_with_bs(qemu_opts_id(opts), errp); + if (!blk) { goto early_err; } + bs = blk_bs(blk); bs->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0; bs->read_only = ro; bs->detect_zeroes = detect_zeroes; @@ -539,18 +515,13 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, bdrv_set_io_limits(bs, &cfg); } - dinfo = g_malloc0(sizeof(*dinfo)); - dinfo->id = g_strdup(qemu_opts_id(opts)); - dinfo->bdrv = bs; - QTAILQ_INSERT_TAIL(&drives, dinfo, next); - if (!file || !*file) { if (has_driver_specific_opts) { file = NULL; } else { QDECREF(bs_opts); qemu_opts_del(opts); - return dinfo; + return blk; } } if (snapshot) { @@ -571,11 +542,11 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, QINCREF(bs_opts); ret = bdrv_open(&bs, file, NULL, bs_opts, bdrv_flags, drv, &error); - assert(bs == dinfo->bdrv); + assert(bs == blk_bs(blk)); if (ret < 0) { error_setg(errp, "could not open disk image %s: %s", - file ?: dinfo->id, error_get_pretty(error)); + file ?: blk_name(blk), error_get_pretty(error)); error_free(error); goto err; } @@ -587,10 +558,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, QDECREF(bs_opts); qemu_opts_del(opts); - return dinfo; + return blk; err: - bdrv_unref(bs); + blk_unref(blk); early_err: qemu_opts_del(opts); err_no_opts: @@ -703,6 +674,7 @@ QemuOptsList qemu_legacy_drive_opts = { DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type) { const char *value; + BlockBackend *blk; DriveInfo *dinfo = NULL; QDict *bs_opts; QemuOpts *legacy_opts; @@ -1000,9 +972,9 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type) } /* Actual block device init: Functionality shared with blockdev-add */ - dinfo = blockdev_init(filename, bs_opts, &local_err); + blk = blockdev_init(filename, bs_opts, &local_err); bs_opts = NULL; - if (dinfo == NULL) { + if (!blk) { if (local_err) { error_report("%s", error_get_pretty(local_err)); error_free(local_err); @@ -1012,8 +984,8 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type) assert(!local_err); } - /* Set legacy DriveInfo fields */ - dinfo->enable_auto_del = true; + /* Create legacy DriveInfo */ + dinfo = g_malloc0(sizeof(*dinfo)); dinfo->opts = all_opts; dinfo->cyls = cyls; @@ -1025,9 +997,10 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type) dinfo->bus = bus_id; dinfo->unit = unit_id; dinfo->devaddr = devaddr; - dinfo->serial = g_strdup(serial); + blk_set_legacy_dinfo(blk, dinfo); + switch(type) { case IF_IDE: case IF_SCSI: @@ -1620,19 +1593,21 @@ exit: } -static void eject_device(BlockDriverState *bs, int force, Error **errp) +static void eject_device(BlockBackend *blk, int force, Error **errp) { + BlockDriverState *bs = blk_bs(blk); + if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) { return; } - if (!bdrv_dev_has_removable_media(bs)) { + if (!blk_dev_has_removable_media(blk)) { error_setg(errp, "Device '%s' is not removable", bdrv_get_device_name(bs)); return; } - if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) { - bdrv_dev_eject_request(bs, force); + if (blk_dev_is_medium_locked(blk) && !blk_dev_is_tray_open(blk)) { + blk_dev_eject_request(blk, force); if (!force) { error_setg(errp, "Device '%s' is locked", bdrv_get_device_name(bs)); @@ -1645,15 +1620,15 @@ static void eject_device(BlockDriverState *bs, int force, Error **errp) void qmp_eject(const char *device, bool has_force, bool force, Error **errp) { - BlockDriverState *bs; + BlockBackend *blk; - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } - eject_device(bs, force, errp); + eject_device(blk, force, errp); } void qmp_block_passwd(bool has_device, const char *device, @@ -1712,16 +1687,18 @@ static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename, void qmp_change_blockdev(const char *device, const char *filename, const char *format, Error **errp) { + BlockBackend *blk; BlockDriverState *bs; BlockDriver *drv = NULL; int bdrv_flags; Error *err = NULL; - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } + bs = blk_bs(blk); if (format) { drv = bdrv_find_whitelisted_format(format, bs->read_only); @@ -1731,7 +1708,7 @@ void qmp_change_blockdev(const char *device, const char *filename, } } - eject_device(bs, 0, &err); + eject_device(blk, 0, &err); if (err) { error_propagate(errp, err); return; @@ -1829,19 +1806,19 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) { const char *id = qdict_get_str(qdict, "id"); + BlockBackend *blk; BlockDriverState *bs; - DriveInfo *dinfo; AioContext *aio_context; Error *local_err = NULL; - bs = bdrv_find(id); - if (!bs) { + blk = blk_by_name(id); + if (!blk) { error_report("Device '%s' not found", id); return -1; } + bs = blk_bs(blk); - dinfo = drive_get_by_blockdev(bs); - if (dinfo && !dinfo->enable_auto_del) { + if (!blk_legacy_dinfo(blk)) { error_report("Deleting device added with blockdev-add" " is not supported"); return -1; @@ -1867,14 +1844,13 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) * can be removed. If this is a drive with no device backing * then we can just get rid of the block driver state right here. */ - if (bdrv_get_attached_dev(bs)) { - bdrv_make_anon(bs); - + if (blk_get_attached_dev(blk)) { + blk_hide_on_behalf_of_do_drive_del(blk); /* Further I/O must not pause the guest */ bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT); } else { - drive_del(dinfo); + blk_unref(blk); } aio_context_release(aio_context); @@ -2566,7 +2542,7 @@ void qmp_change_backing_file(const char *device, void qmp_blockdev_add(BlockdevOptions *options, Error **errp) { QmpOutputVisitor *ov = qmp_output_visitor_new(); - DriveInfo *dinfo; + BlockBackend *blk; QObject *obj; QDict *qdict; Error *local_err = NULL; @@ -2604,14 +2580,14 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) qdict_flatten(qdict); - dinfo = blockdev_init(NULL, qdict, &local_err); + blk = blockdev_init(NULL, qdict, &local_err); if (local_err) { error_propagate(errp, local_err); goto fail; } - if (bdrv_key_required(dinfo->bdrv)) { - drive_del(dinfo); + if (bdrv_key_required(blk_bs(blk))) { + blk_unref(blk); error_setg(errp, "blockdev-add doesn't support encrypted devices"); goto fail; } @@ -2620,26 +2596,21 @@ fail: qmp_output_visitor_cleanup(ov); } -static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs) +BlockJobInfoList *qmp_query_block_jobs(Error **errp) { - BlockJobInfoList **prev = opaque; - BlockJob *job = bs->job; + BlockJobInfoList *head = NULL, **p_next = &head; + BlockDriverState *bs; - if (job) { - BlockJobInfoList *elem = g_new0(BlockJobInfoList, 1); - elem->value = block_job_query(bs->job); - (*prev)->next = elem; - *prev = elem; + for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) { + if (bs->job) { + BlockJobInfoList *elem = g_new0(BlockJobInfoList, 1); + elem->value = block_job_query(bs->job); + *p_next = elem; + p_next = &elem->next; + } } -} -BlockJobInfoList *qmp_query_block_jobs(Error **errp) -{ - /* Dummy is a fake list element for holding the head pointer */ - BlockJobInfoList dummy = {}; - BlockJobInfoList *prev = &dummy; - bdrv_iterate(do_qmp_query_block_jobs_one, &prev); - return dummy.next; + return head; } QemuOptsList qemu_common_drive_opts = { @@ -36,7 +36,7 @@ #include "qapi-event.h" void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs, - int64_t speed, BlockDriverCompletionFunc *cb, + int64_t speed, BlockCompletionFunc *cb, void *opaque, Error **errp) { BlockJob *job; @@ -107,7 +107,8 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) void block_job_complete(BlockJob *job, Error **errp) { if (job->paused || job->cancelled || !job->driver->complete) { - error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name); + error_set(errp, QERR_BLOCK_JOB_NOT_READY, + bdrv_get_device_name(job->bs)); return; } @@ -154,7 +155,7 @@ void block_job_iostatus_reset(BlockJob *job) struct BlockCancelData { BlockJob *job; - BlockDriverCompletionFunc *cb; + BlockCompletionFunc *cb; void *opaque; bool cancelled; int ret; @@ -4211,9 +4211,9 @@ EOF fi fi -# add pixman flags after all config tests are done -QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags $fdt_cflags" -libs_softmmu="$libs_softmmu $pixman_libs" +# prepend pixman and ftd flags after all config tests are done +QEMU_CFLAGS="$pixman_cflags $fdt_cflags $QEMU_CFLAGS" +libs_softmmu="$pixman_libs $libs_softmmu" echo "Install prefix $prefix" echo "BIOS directory `eval echo $qemu_datadir`" diff --git a/device-hotplug.c b/device-hotplug.c index e6a1ffb..9e38cc4 100644 --- a/device-hotplug.c +++ b/device-hotplug.c @@ -24,6 +24,7 @@ #include "hw/hw.h" #include "hw/boards.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "qemu/config-file.h" #include "sysemu/sysemu.h" @@ -76,6 +77,6 @@ void drive_hot_add(Monitor *mon, const QDict *qdict) err: if (dinfo) { - drive_del(dinfo); + blk_unref(blk_by_legacy_dinfo(dinfo)); } } diff --git a/disas/mips.c b/disas/mips.c index 2106b57..7297825 100644 --- a/disas/mips.c +++ b/disas/mips.c @@ -119,6 +119,8 @@ see <http://www.gnu.org/licenses/>. */ #define OP_SH_IMMEDIATE 0 #define OP_MASK_DELTA 0xffff #define OP_SH_DELTA 0 +#define OP_MASK_DELTA_R6 0x1ff +#define OP_SH_DELTA_R6 7 #define OP_MASK_FUNCT 0x3f #define OP_SH_FUNCT 0 #define OP_MASK_SPEC 0x3f @@ -405,6 +407,12 @@ struct mips_opcode "+3" UDI immediate bits 6-20 "+4" UDI immediate bits 6-25 + R6 immediates/displacements : + (adding suffix to 'o' to avoid adding new characters) + "+o" 9 bits immediate/displacement (shift = 7) + "+o1" 18 bits immediate/displacement (shift = 0) + "+o2" 19 bits immediate/displacement (shift = 0) + Other: "()" parens surrounding optional value "," separates operands @@ -521,6 +529,8 @@ struct mips_opcode #define INSN_ISA64 0x00000040 #define INSN_ISA32R2 0x00000080 #define INSN_ISA64R2 0x00000100 +#define INSN_ISA32R6 0x00000200 +#define INSN_ISA64R6 0x00000400 /* Masks used for MIPS-defined ASEs. */ #define INSN_ASE_MASK 0x0000f000 @@ -585,6 +595,8 @@ struct mips_opcode #define ISA_MIPS32R2 (ISA_MIPS32 | INSN_ISA32R2) #define ISA_MIPS64R2 (ISA_MIPS64 | INSN_ISA32R2 | INSN_ISA64R2) +#define ISA_MIPS32R6 (ISA_MIPS32R2 | INSN_ISA32R6) +#define ISA_MIPS64R6 (ISA_MIPS64R2 | INSN_ISA32R6 | INSN_ISA64R6) /* CPU defines, use instead of hardcoding processor number. Keep this in sync with bfd/archures.c in order for machine selection to work. */ @@ -1121,6 +1133,8 @@ extern const int bfd_mips16_num_opcodes; #define I64 INSN_ISA64 #define I33 INSN_ISA32R2 #define I65 INSN_ISA64R2 +#define I32R6 INSN_ISA32R6 +#define I64R6 INSN_ISA64R6 /* MIPS64 MIPS-3D ASE support. */ #define I16 INSN_MIPS16 @@ -1209,6 +1223,146 @@ const struct mips_opcode mips_builtin_opcodes[] = them first. The assemblers uses a hash table based on the instruction name anyhow. */ /* name, args, match, mask, pinfo, membership */ +{"lwpc", "s,+o2", 0xec080000, 0xfc180000, WR_d, 0, I32R6}, +{"lwupc", "s,+o2", 0xec100000, 0xfc180000, WR_d, 0, I64R6}, +{"ldpc", "s,+o1", 0xec180000, 0xfc1c0000, WR_d, 0, I64R6}, +{"addiupc", "s,+o2", 0xec000000, 0xfc180000, WR_d, 0, I32R6}, +{"auipc", "s,u", 0xec1e0000, 0xfc1f0000, WR_d, 0, I32R6}, +{"aluipc", "s,u", 0xec1f0000, 0xfc1f0000, WR_d, 0, I32R6}, +{"daui", "s,t,u", 0x74000000, 0xfc000000, RD_s|WR_t, 0, I64R6}, +{"dahi", "s,u", 0x04060000, 0xfc1f0000, RD_s, 0, I64R6}, +{"dati", "s,u", 0x041e0000, 0xfc1f0000, RD_s, 0, I64R6}, +{"lsa", "d,s,t", 0x00000005, 0xfc00073f, WR_d|RD_s|RD_t, 0, I32R6}, +{"dlsa", "d,s,t", 0x00000015, 0xfc00073f, WR_d|RD_s|RD_t, 0, I64R6}, +{"clz", "U,s", 0x00000050, 0xfc1f07ff, WR_d|RD_s, 0, I32R6}, +{"clo", "U,s", 0x00000051, 0xfc1f07ff, WR_d|RD_s, 0, I32R6}, +{"dclz", "U,s", 0x00000052, 0xfc1f07ff, WR_d|RD_s, 0, I64R6}, +{"dclo", "U,s", 0x00000053, 0xfc1f07ff, WR_d|RD_s, 0, I64R6}, +{"sdbbp", "B", 0x0000000e, 0xfc00003f, TRAP, 0, I32R6}, +{"mul", "d,s,t", 0x00000098, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, +{"muh", "d,s,t", 0x000000d8, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, +{"mulu", "d,s,t", 0x00000099, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, +{"muhu", "d,s,t", 0x000000d9, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, +{"div", "d,s,t", 0x0000009a, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, +{"mod", "d,s,t", 0x000000da, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, +{"divu", "d,s,t", 0x0000009b, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, +{"modu", "d,s,t", 0x000000db, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, +{"dmul", "d,s,t", 0x0000009c, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6}, +{"dmuh", "d,s,t", 0x000000dc, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6}, +{"dmulu", "d,s,t", 0x0000009d, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6}, +{"dmuhu", "d,s,t", 0x000000dd, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6}, +{"ddiv", "d,s,t", 0x0000009e, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6}, +{"dmod", "d,s,t", 0x000000de, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6}, +{"ddivu", "d,s,t", 0x0000009f, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6}, +{"dmodu", "d,s,t", 0x000000df, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6}, +{"ll", "t,o(b)", 0x7c000036, 0xfc00007f, LDD|RD_b|WR_t, 0, I32R6}, +{"sc", "t,o(b)", 0x7c000026, 0xfc00007f, LDD|RD_b|WR_t, 0, I32R6}, +{"lld", "t,o(b)", 0x7c000037, 0xfc00007f, LDD|RD_b|WR_t, 0, I64R6}, +{"scd", "t,o(b)", 0x7c000027, 0xfc00007f, LDD|RD_b|WR_t, 0, I64R6}, +{"pref", "h,o(b)", 0x7c000035, 0xfc00007f, RD_b, 0, I32R6}, +{"cache", "k,o(b)", 0x7c000025, 0xfc00007f, RD_b, 0, I32R6}, +{"seleqz", "d,v,t", 0x00000035, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, +{"selnez", "d,v,t", 0x00000037, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, +{"maddf.s", "D,S,T", 0x46000018, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"maddf.d", "D,S,T", 0x46200018, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"msubf.s", "D,S,T", 0x46000019, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"msubf.d", "D,S,T", 0x46200019, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"max.s", "D,S,T", 0x4600001e, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"max.d", "D,S,T", 0x4620001e, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"maxa.s", "D,S,T", 0x4600001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"maxa.d", "D,S,T", 0x4620001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"rint.s", "D,S", 0x4600001a, 0xffff003f, WR_D|RD_S|FP_S, 0, I32R6}, +{"rint.d", "D,S", 0x4620001a, 0xffff003f, WR_D|RD_S|FP_D, 0, I32R6}, +{"class.s", "D,S", 0x4600001b, 0xffff003f, WR_D|RD_S|FP_S, 0, I32R6}, +{"class.d", "D,S", 0x4620001b, 0xffff003f, WR_D|RD_S|FP_D, 0, I32R6}, +{"min.s", "D,S,T", 0x4600001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"min.d", "D,S,T", 0x4620001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"mina.s", "D,S,T", 0x4600001d, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"mina.d", "D,S,T", 0x4620001d, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"sel.s", "D,S,T", 0x46000010, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"sel.d", "D,S,T", 0x46200010, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"seleqz.s", "D,S,T", 0x46000014, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"seleqz.d", "D,S,T", 0x46200014, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"selnez.s", "D,S,T", 0x46000017, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"selnez.d", "D,S,T", 0x46200017, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"align", "d,v,t", 0x7c000220, 0xfc00073f, WR_d|RD_s|RD_t, 0, I32R6}, +{"dalign", "d,v,t", 0x7c000224, 0xfc00063f, WR_d|RD_s|RD_t, 0, I64R6}, +{"bitswap", "d,w", 0x7c000020, 0xffe007ff, WR_d|RD_t, 0, I32R6}, +{"dbitswap","d,w", 0x7c000024, 0xffe007ff, WR_d|RD_t, 0, I64R6}, +{"balc", "+p", 0xe8000000, 0xfc000000, UBD|WR_31, 0, I32R6}, +{"bc", "+p", 0xc8000000, 0xfc000000, UBD|WR_31, 0, I32R6}, +{"jic", "t,o", 0xd8000000, 0xffe00000, UBD|RD_t, 0, I32R6}, +{"beqzc", "s,+p", 0xd8000000, 0xfc000000, CBD|RD_s, 0, I32R6}, +{"jialc", "t,o", 0xf8000000, 0xffe00000, UBD|RD_t, 0, I32R6}, +{"bnezc", "s,+p", 0xf8000000, 0xfc000000, CBD|RD_s, 0, I32R6}, +{"beqzalc", "s,t,p", 0x20000000, 0xffe00000, CBD|RD_s|RD_t, 0, I32R6}, +{"bovc", "s,t,p", 0x20000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6}, +{"beqc", "s,t,p", 0x20000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6}, +{"bnezalc", "s,t,p", 0x60000000, 0xffe00000, CBD|RD_s|RD_t, 0, I32R6}, +{"bnvc", "s,t,p", 0x60000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6}, +{"bnec", "s,t,p", 0x60000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6}, +{"blezc", "s,t,p", 0x58000000, 0xffe00000, CBD|RD_s|RD_t, 0, I32R6}, +{"bgezc", "s,t,p", 0x58000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6}, +{"bgec", "s,t,p", 0x58000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6}, +{"bgtzc", "s,t,p", 0x5c000000, 0xffe00000, CBD|RD_s|RD_t, 0, I32R6}, +{"bltzc", "s,t,p", 0x5c000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6}, +{"bltc", "s,t,p", 0x5c000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6}, +{"blezalc", "s,t,p", 0x18000000, 0xffe00000, CBD|RD_s|RD_t, 0, I32R6}, +{"bgezalc", "s,t,p", 0x18000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6}, +{"bgeuc", "s,t,p", 0x18000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6}, +{"bgtzalc", "s,t,p", 0x1c000000, 0xffe00000, CBD|RD_s|RD_t, 0, I32R6}, +{"bltzalc", "s,t,p", 0x1c000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6}, +{"bltuc", "s,t,p", 0x1c000000, 0xfc000000, CBD|RD_s|RD_t, 0, I32R6}, +{"nal", "p", 0x04100000, 0xffff0000, WR_31, 0, I32R6}, +{"bal", "p", 0x04110000, 0xffff0000, UBD|WR_31, 0, I32R6}, +{"bc1eqz", "T,p", 0x45200000, 0xffe00000, CBD|RD_T|FP_S|FP_D, 0, I32R6}, +{"bc1nez", "T,p", 0x45a00000, 0xffe00000, CBD|RD_T|FP_S|FP_D, 0, I32R6}, +{"bc2eqz", "E,p", 0x49200000, 0xffe00000, CBD|RD_C2, 0, I32R6}, +{"bc2nez", "E,p", 0x49a00000, 0xffe00000, CBD|RD_C2, 0, I32R6}, +{"cmp.af.s", "D,S,T", 0x46800000, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.un.s", "D,S,T", 0x46800001, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.eq.s", "D,S,T", 0x46800002, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.ueq.s", "D,S,T", 0x46800003, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.lt.s", "D,S,T", 0x46800004, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.ult.s", "D,S,T", 0x46800005, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.le.s", "D,S,T", 0x46800006, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.ule.s", "D,S,T", 0x46800007, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.saf.s", "D,S,T", 0x46800008, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.sun.s", "D,S,T", 0x46800009, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.seq.s", "D,S,T", 0x4680000a, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.sueq.s", "D,S,T", 0x4680000b, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.slt.s", "D,S,T", 0x4680000c, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.sult.s", "D,S,T", 0x4680000d, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.sle.s", "D,S,T", 0x4680000e, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.sule.s", "D,S,T", 0x4680000f, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.or.s", "D,S,T", 0x46800011, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.une.s", "D,S,T", 0x46800012, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.ne.s", "D,S,T", 0x46800013, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.sor.s", "D,S,T", 0x46800019, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.sune.s", "D,S,T", 0x4680001a, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.sne.s", "D,S,T", 0x4680001b, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, I32R6}, +{"cmp.af.d", "D,S,T", 0x46a00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.un.d", "D,S,T", 0x46a00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.eq.d", "D,S,T", 0x46a00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.ueq.d", "D,S,T", 0x46a00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.lt.d", "D,S,T", 0x46a00004, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.ult.d", "D,S,T", 0x46a00005, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.le.d", "D,S,T", 0x46a00006, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.ule.d", "D,S,T", 0x46a00007, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.saf.d", "D,S,T", 0x46a00008, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.sun.d", "D,S,T", 0x46a00009, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.seq.d", "D,S,T", 0x46a0000a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.sueq.d", "D,S,T", 0x46a0000b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.slt.d", "D,S,T", 0x46a0000c, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.sult.d", "D,S,T", 0x46a0000d, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.sle.d", "D,S,T", 0x46a0000e, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.sule.d", "D,S,T", 0x46a0000f, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.or.d", "D,S,T", 0x46a00011, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.une.d", "D,S,T", 0x46a00012, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.ne.d", "D,S,T", 0x46a00013, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.sor.d", "D,S,T", 0x46a00019, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.sune.d", "D,S,T", 0x46a0001a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, +{"cmp.sne.d", "D,S,T", 0x46a0001b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, {"pref", "k,o(b)", 0xcc000000, 0xfc000000, RD_b, 0, I4|I32|G3 }, {"prefx", "h,t(b)", 0x4c00000f, 0xfc0007ff, RD_b|RD_t, 0, I4|I33 }, {"nop", "", 0x00000000, 0xffffffff, 0, INSN2_ALIAS, I1 }, /* sll */ @@ -1753,6 +1907,7 @@ const struct mips_opcode mips_builtin_opcodes[] = {"lld", "t,o(b)", 0xd0000000, 0xfc000000, LDD|RD_b|WR_t, 0, I3 }, {"lld", "t,A(b)", 0, (int) M_LLD_AB, INSN_MACRO, 0, I3 }, {"lui", "t,u", 0x3c000000, 0xffe00000, WR_t, 0, I1 }, +{"aui", "s,t,u", 0x3c000000, 0xfc000000, RD_s|WR_t, 0, I32R6}, {"luxc1", "D,t(b)", 0x4c000005, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|FP_D, 0, I5|I33|N55}, {"lw", "t,o(b)", 0x8c000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, {"lw", "t,A(b)", 0, (int) M_LW_AB, INSN_MACRO, 0, I1 }, @@ -3575,6 +3730,42 @@ print_insn_args (const char *d, (*info->fprintf_func) (info->stream, "0x%x", msbd + 1); break; + case 'o': + switch (*(d+1)) { + case '1': + d++; + delta = l & ((1 << 18) - 1); + if (delta & 0x20000) { + delta |= ~0x1ffff; + } + break; + case '2': + d++; + delta = l & ((1 << 19) - 1); + if (delta & 0x40000) { + delta |= ~0x3ffff; + } + break; + default: + delta = (l >> OP_SH_DELTA_R6) & OP_MASK_DELTA_R6; + if (delta & 0x8000) { + delta |= ~0xffff; + } + } + + (*info->fprintf_func) (info->stream, "%d", delta); + break; + + case 'p': + /* Sign extend the displacement with 26 bits. */ + delta = (l >> OP_SH_DELTA) & OP_MASK_TARGET; + if (delta & 0x2000000) { + delta |= ~0x3FFFFFF; + } + info->target = (delta << 2) + pc + INSNLEN; + (*info->print_address_func) (info->target, info); + break; + case 't': /* Coprocessor 0 reg name */ (*info->fprintf_func) (info->stream, "%s", mips_cp0_names[(l >> OP_SH_RT) & @@ -3726,7 +3917,8 @@ print_insn_args (const char *d, case 'j': /* Same as i, but sign-extended. */ case 'o': - delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA; + delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA; + if (delta & 0x8000) delta |= ~0xffff; (*info->fprintf_func) (info->stream, "%d", @@ -4052,6 +4244,23 @@ print_insn_mips (bfd_vma memaddr, && strcmp (op->name, "jalx")) continue; + if (strcmp(op->name, "bovc") == 0 + || strcmp(op->name, "bnvc") == 0) { + if (((word >> OP_SH_RS) & OP_MASK_RS) < + ((word >> OP_SH_RT) & OP_MASK_RT)) { + continue; + } + } + if (strcmp(op->name, "bgezc") == 0 + || strcmp(op->name, "bltzc") == 0 + || strcmp(op->name, "bgezalc") == 0 + || strcmp(op->name, "bltzalc") == 0) { + if (((word >> OP_SH_RS) & OP_MASK_RS) != + ((word >> OP_SH_RT) & OP_MASK_RT)) { + continue; + } + } + /* Figure out instruction type and branch delay information. */ if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0) { diff --git a/dma-helpers.c b/dma-helpers.c index 7f86e18..6918572 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -7,6 +7,7 @@ * (GNU GPL), version 2 or later. */ +#include "sysemu/block-backend.h" #include "sysemu/dma.h" #include "trace.h" #include "qemu/range.h" @@ -67,9 +68,9 @@ void qemu_sglist_destroy(QEMUSGList *qsg) } typedef struct { - BlockDriverAIOCB common; - BlockDriverState *bs; - BlockDriverAIOCB *acb; + BlockAIOCB common; + BlockBackend *blk; + BlockAIOCB *acb; QEMUSGList *sg; uint64_t sector_num; DMADirection dir; @@ -80,7 +81,7 @@ typedef struct { DMAIOFunc *io_func; } DMAAIOCB; -static void dma_bdrv_cb(void *opaque, int ret); +static void dma_blk_cb(void *opaque, int ret); static void reschedule_dma(void *opaque) { @@ -88,7 +89,7 @@ static void reschedule_dma(void *opaque) qemu_bh_delete(dbs->bh); dbs->bh = NULL; - dma_bdrv_cb(dbs, 0); + dma_blk_cb(dbs, 0); } static void continue_after_map_failure(void *opaque) @@ -99,7 +100,7 @@ static void continue_after_map_failure(void *opaque) qemu_bh_schedule(dbs->bh); } -static void dma_bdrv_unmap(DMAAIOCB *dbs) +static void dma_blk_unmap(DMAAIOCB *dbs) { int i; @@ -115,7 +116,7 @@ static void dma_complete(DMAAIOCB *dbs, int ret) { trace_dma_complete(dbs, ret, dbs->common.cb); - dma_bdrv_unmap(dbs); + dma_blk_unmap(dbs); if (dbs->common.cb) { dbs->common.cb(dbs->common.opaque, ret); } @@ -127,13 +128,13 @@ static void dma_complete(DMAAIOCB *dbs, int ret) qemu_aio_unref(dbs); } -static void dma_bdrv_cb(void *opaque, int ret) +static void dma_blk_cb(void *opaque, int ret) { DMAAIOCB *dbs = (DMAAIOCB *)opaque; dma_addr_t cur_addr, cur_len; void *mem; - trace_dma_bdrv_cb(dbs, ret); + trace_dma_blk_cb(dbs, ret); dbs->acb = NULL; dbs->sector_num += dbs->iov.size / 512; @@ -142,7 +143,7 @@ static void dma_bdrv_cb(void *opaque, int ret) dma_complete(dbs, ret); return; } - dma_bdrv_unmap(dbs); + dma_blk_unmap(dbs); while (dbs->sg_cur_index < dbs->sg->nsg) { cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte; @@ -168,19 +169,19 @@ static void dma_bdrv_cb(void *opaque, int ret) qemu_iovec_discard_back(&dbs->iov, dbs->iov.size & ~BDRV_SECTOR_MASK); } - dbs->acb = dbs->io_func(dbs->bs, dbs->sector_num, &dbs->iov, - dbs->iov.size / 512, dma_bdrv_cb, dbs); + dbs->acb = dbs->io_func(dbs->blk, dbs->sector_num, &dbs->iov, + dbs->iov.size / 512, dma_blk_cb, dbs); assert(dbs->acb); } -static void dma_aio_cancel(BlockDriverAIOCB *acb) +static void dma_aio_cancel(BlockAIOCB *acb) { DMAAIOCB *dbs = container_of(acb, DMAAIOCB, common); trace_dma_aio_cancel(dbs); if (dbs->acb) { - bdrv_aio_cancel_async(dbs->acb); + blk_aio_cancel_async(dbs->acb); } } @@ -190,17 +191,17 @@ static const AIOCBInfo dma_aiocb_info = { .cancel_async = dma_aio_cancel, }; -BlockDriverAIOCB *dma_bdrv_io( - BlockDriverState *bs, QEMUSGList *sg, uint64_t sector_num, - DMAIOFunc *io_func, BlockDriverCompletionFunc *cb, +BlockAIOCB *dma_blk_io( + BlockBackend *blk, QEMUSGList *sg, uint64_t sector_num, + DMAIOFunc *io_func, BlockCompletionFunc *cb, void *opaque, DMADirection dir) { - DMAAIOCB *dbs = qemu_aio_get(&dma_aiocb_info, bs, cb, opaque); + DMAAIOCB *dbs = blk_aio_get(&dma_aiocb_info, blk, cb, opaque); - trace_dma_bdrv_io(dbs, bs, sector_num, (dir == DMA_DIRECTION_TO_DEVICE)); + trace_dma_blk_io(dbs, blk, sector_num, (dir == DMA_DIRECTION_TO_DEVICE)); dbs->acb = NULL; - dbs->bs = bs; + dbs->blk = blk; dbs->sg = sg; dbs->sector_num = sector_num; dbs->sg_cur_index = 0; @@ -209,25 +210,25 @@ BlockDriverAIOCB *dma_bdrv_io( dbs->io_func = io_func; dbs->bh = NULL; qemu_iovec_init(&dbs->iov, sg->nsg); - dma_bdrv_cb(dbs, 0); + dma_blk_cb(dbs, 0); return &dbs->common; } -BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs, - QEMUSGList *sg, uint64_t sector, - void (*cb)(void *opaque, int ret), void *opaque) +BlockAIOCB *dma_blk_read(BlockBackend *blk, + QEMUSGList *sg, uint64_t sector, + void (*cb)(void *opaque, int ret), void *opaque) { - return dma_bdrv_io(bs, sg, sector, bdrv_aio_readv, cb, opaque, - DMA_DIRECTION_FROM_DEVICE); + return dma_blk_io(blk, sg, sector, blk_aio_readv, cb, opaque, + DMA_DIRECTION_FROM_DEVICE); } -BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs, - QEMUSGList *sg, uint64_t sector, - void (*cb)(void *opaque, int ret), void *opaque) +BlockAIOCB *dma_blk_write(BlockBackend *blk, + QEMUSGList *sg, uint64_t sector, + void (*cb)(void *opaque, int ret), void *opaque) { - return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque, - DMA_DIRECTION_TO_DEVICE); + return dma_blk_io(blk, sg, sector, blk_aio_writev, cb, opaque, + DMA_DIRECTION_TO_DEVICE); } @@ -262,8 +263,8 @@ uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg) return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_TO_DEVICE); } -void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie, +void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, QEMUSGList *sg, enum BlockAcctType type) { - block_acct_start(bdrv_get_stats(bs), cookie, sg->size, type); + block_acct_start(blk_get_stats(blk), cookie, sg->size, type); } diff --git a/docs/blkdebug.txt b/docs/blkdebug.txt index 5dde072..b67a36d 100644 --- a/docs/blkdebug.txt +++ b/docs/blkdebug.txt @@ -70,10 +70,10 @@ Rules support the following attributes: once - (optional, default "off") only execute this action on the first matching request - immediately - (optional, default "off") return a NULL BlockDriverAIOCB - pointer and fail without an errno instead. This exercises the - code path where BlockDriverAIOCB fails and the caller's - BlockDriverCompletionFunc is not invoked. + immediately - (optional, default "off") return a NULL BlockAIOCB + pointer and fail without an errno instead. This + exercises the code path where BlockAIOCB fails and the + caller's BlockCompletionFunc is not invoked. Events ------ diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 9274ebf..16b21eb 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -7240,13 +7240,17 @@ int float128_compare_quiet( float128 a, float128 b STATUS_PARAM ) * minnum() and maxnum correspond to the IEEE 754-2008 minNum() * and maxNum() operations. min() and max() are the typical min/max * semantics provided by many CPUs which predate that specification. + * + * minnummag() and maxnummag() functions correspond to minNumMag() + * and minNumMag() from the IEEE-754 2008. */ #define MINMAX(s) \ static inline float ## s float ## s ## _minmax(float ## s a, float ## s b, \ - int ismin, int isieee STATUS_PARAM) \ + int ismin, int isieee, \ + int ismag STATUS_PARAM) \ { \ flag aSign, bSign; \ - uint ## s ## _t av, bv; \ + uint ## s ## _t av, bv, aav, abv; \ a = float ## s ## _squash_input_denormal(a STATUS_VAR); \ b = float ## s ## _squash_input_denormal(b STATUS_VAR); \ if (float ## s ## _is_any_nan(a) || \ @@ -7266,6 +7270,17 @@ static inline float ## s float ## s ## _minmax(float ## s a, float ## s b, \ bSign = extractFloat ## s ## Sign(b); \ av = float ## s ## _val(a); \ bv = float ## s ## _val(b); \ + if (ismag) { \ + aav = float ## s ## _abs(av); \ + abv = float ## s ## _abs(bv); \ + if (aav != abv) { \ + if (ismin) { \ + return (aav < abv) ? a : b; \ + } else { \ + return (aav < abv) ? b : a; \ + } \ + } \ + } \ if (aSign != bSign) { \ if (ismin) { \ return aSign ? a : b; \ @@ -7283,22 +7298,32 @@ static inline float ## s float ## s ## _minmax(float ## s a, float ## s b, \ \ float ## s float ## s ## _min(float ## s a, float ## s b STATUS_PARAM) \ { \ - return float ## s ## _minmax(a, b, 1, 0 STATUS_VAR); \ + return float ## s ## _minmax(a, b, 1, 0, 0 STATUS_VAR); \ } \ \ float ## s float ## s ## _max(float ## s a, float ## s b STATUS_PARAM) \ { \ - return float ## s ## _minmax(a, b, 0, 0 STATUS_VAR); \ + return float ## s ## _minmax(a, b, 0, 0, 0 STATUS_VAR); \ } \ \ float ## s float ## s ## _minnum(float ## s a, float ## s b STATUS_PARAM) \ { \ - return float ## s ## _minmax(a, b, 1, 1 STATUS_VAR); \ + return float ## s ## _minmax(a, b, 1, 1, 0 STATUS_VAR); \ } \ \ float ## s float ## s ## _maxnum(float ## s a, float ## s b STATUS_PARAM) \ { \ - return float ## s ## _minmax(a, b, 0, 1 STATUS_VAR); \ + return float ## s ## _minmax(a, b, 0, 1, 0 STATUS_VAR); \ +} \ + \ +float ## s float ## s ## _minnummag(float ## s a, float ## s b STATUS_PARAM) \ +{ \ + return float ## s ## _minmax(a, b, 1, 1, 1 STATUS_VAR); \ +} \ + \ +float ## s float ## s ## _maxnummag(float ## s a, float ## s b STATUS_PARAM) \ +{ \ + return float ## s ## _minmax(a, b, 0, 1, 1 STATUS_VAR); \ } MINMAX(32) diff --git a/hw/arm/collie.c b/hw/arm/collie.c index ed7851f..6c9b82f 100644 --- a/hw/arm/collie.c +++ b/hw/arm/collie.c @@ -15,7 +15,7 @@ #include "strongarm.h" #include "hw/arm/arm.h" #include "hw/block/flash.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" static struct arm_boot_info collie_binfo = { @@ -41,13 +41,13 @@ static void collie_init(MachineState *machine) dinfo = drive_get(IF_PFLASH, 0, 0); pflash_cfi01_register(SA_CS0, NULL, "collie.fl1", 0x02000000, - dinfo ? dinfo->bdrv : NULL, (64 * 1024), - 512, 4, 0x00, 0x00, 0x00, 0x00, 0); + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, + (64 * 1024), 512, 4, 0x00, 0x00, 0x00, 0x00, 0); dinfo = drive_get(IF_PFLASH, 0, 1); pflash_cfi01_register(SA_CS1, NULL, "collie.fl2", 0x02000000, - dinfo ? dinfo->bdrv : NULL, (64 * 1024), - 512, 4, 0x00, 0x00, 0x00, 0x00, 0); + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, + (64 * 1024), 512, 4, 0x00, 0x00, 0x00, 0x00, 0); sysbus_create_simple("scoop", 0x40800000, NULL); diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c index 3f8465e..8103278 100644 --- a/hw/arm/gumstix.c +++ b/hw/arm/gumstix.c @@ -40,7 +40,7 @@ #include "hw/block/flash.h" #include "hw/devices.h" #include "hw/boards.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #include "sysemu/qtest.h" @@ -71,7 +71,7 @@ static void connex_init(MachineState *machine) be = 0; #endif if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom, - dinfo ? dinfo->bdrv : NULL, + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, sector_len, connex_rom / sector_len, 2, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); @@ -109,7 +109,7 @@ static void verdex_init(MachineState *machine) be = 0; #endif if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom, - dinfo ? dinfo->bdrv : NULL, + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, sector_len, verdex_rom / sector_len, 2, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index fa61e5f..30f744a 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -24,7 +24,7 @@ #include "net/net.h" #include "sysemu/sysemu.h" #include "hw/boards.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #include "qemu/error-report.h" diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c index 2f1d618..0da02a6 100644 --- a/hw/arm/mainstone.c +++ b/hw/arm/mainstone.c @@ -18,7 +18,7 @@ #include "hw/devices.h" #include "hw/boards.h" #include "hw/block/flash.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" #include "sysemu/qtest.h" @@ -149,9 +149,9 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, if (!pflash_cfi01_register(mainstone_flash_base[i], NULL, i ? "mainstone.flash1" : "mainstone.flash0", MAINSTONE_FLASH, - dinfo->bdrv, sector_len, - MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0, - be)) { + blk_by_legacy_dinfo(dinfo), + sector_len, MAINSTONE_FLASH / sector_len, + 4, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); exit(1); } diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index c541455..3712de6 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -18,11 +18,10 @@ #include "hw/char/serial.h" #include "qemu/timer.h" #include "hw/ptimer.h" -#include "block/block.h" #include "hw/block/flash.h" #include "ui/console.h" #include "hw/i2c/i2c.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #include "ui/pixel_ops.h" @@ -1632,7 +1631,9 @@ static void musicpal_init(MachineState *machine) /* Register flash */ dinfo = drive_get(IF_PFLASH, 0, 0); if (dinfo) { - flash_size = bdrv_getlength(dinfo->bdrv); + BlockBackend *blk = blk_by_legacy_dinfo(dinfo); + + flash_size = blk_getlength(blk); if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 && flash_size != 32*1024*1024) { fprintf(stderr, "Invalid flash image size\n"); @@ -1647,16 +1648,14 @@ static void musicpal_init(MachineState *machine) #ifdef TARGET_WORDS_BIGENDIAN pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL, "musicpal.flash", flash_size, - dinfo->bdrv, 0x10000, - (flash_size + 0xffff) >> 16, + blk, 0x10000, (flash_size + 0xffff) >> 16, MP_FLASH_SIZE_MAX / flash_size, 2, 0x00BF, 0x236D, 0x0000, 0x0000, 0x5555, 0x2AAA, 1); #else pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL, "musicpal.flash", flash_size, - dinfo->bdrv, 0x10000, - (flash_size + 0xffff) >> 16, + blk, 0x10000, (flash_size + 0xffff) >> 16, MP_FLASH_SIZE_MAX / flash_size, 2, 0x00BF, 0x236D, 0x0000, 0x0000, 0x5555, 0x2AAA, 0); diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index 4f092d6..c7ebaa6 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -31,7 +31,7 @@ #include "hw/hw.h" #include "hw/bt.h" #include "hw/loader.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" @@ -172,8 +172,9 @@ static void n8x0_nand_setup(struct n800_s *s) qdev_prop_set_uint16(s->nand, "version_id", 0); qdev_prop_set_int32(s->nand, "shift", 1); dinfo = drive_get(IF_MTD, 0, 0); - if (dinfo && dinfo->bdrv) { - qdev_prop_set_drive_nofail(s->nand, "drive", dinfo->bdrv); + if (dinfo) { + qdev_prop_set_drive_nofail(s->nand, "drive", + blk_by_legacy_dinfo(dinfo)); } qdev_init_nofail(s->nand); sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0, diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c index 306cf17..abb183c 100644 --- a/hw/arm/omap1.c +++ b/hw/arm/omap1.c @@ -21,6 +21,7 @@ #include "hw/arm/omap.h" #include "sysemu/sysemu.h" #include "hw/arm/soc_dma.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "qemu/range.h" #include "hw/sysbus.h" @@ -3978,7 +3979,8 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory, fprintf(stderr, "qemu: missing SecureDigital device\n"); exit(1); } - s->mmc = omap_mmc_init(0xfffb7800, system_memory, dinfo->bdrv, + s->mmc = omap_mmc_init(0xfffb7800, system_memory, + blk_by_legacy_dinfo(dinfo), qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN), &s->drq[OMAP_DMA_MMC_TX], omap_findclk(s, "mmc_ck")); diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c index d6e19ae..b083ebe 100644 --- a/hw/arm/omap2.c +++ b/hw/arm/omap2.c @@ -18,6 +18,7 @@ * with this program; if not, see <http://www.gnu.org/licenses/>. */ +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/hw.h" #include "hw/arm/arm.h" @@ -2461,7 +2462,8 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem, fprintf(stderr, "qemu: missing SecureDigital device\n"); exit(1); } - s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), dinfo->bdrv, + s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), + blk_by_legacy_dinfo(dinfo), qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ), &s->drq[OMAP24XX_DMA_MMC1_TX], omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk")); diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c index 320b39c..671e02c 100644 --- a/hw/arm/omap_sx1.c +++ b/hw/arm/omap_sx1.c @@ -31,7 +31,7 @@ #include "hw/boards.h" #include "hw/arm/arm.h" #include "hw/block/flash.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "sysemu/qtest.h" #include "exec/address-spaces.h" @@ -154,8 +154,8 @@ static void sx1_init(MachineState *machine, const int version) if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) { if (!pflash_cfi01_register(OMAP_CS0_BASE, NULL, "omap_sx1.flash0-1", flash_size, - dinfo->bdrv, sector_size, - flash_size / sector_size, + blk_by_legacy_dinfo(dinfo), + sector_size, flash_size / sector_size, 4, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory %d.\n", fl_idx); @@ -178,8 +178,8 @@ static void sx1_init(MachineState *machine, const int version) if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL, "omap_sx1.flash1-1", flash1_size, - dinfo->bdrv, sector_size, - flash1_size / sector_size, + blk_by_legacy_dinfo(dinfo), + sector_size, flash1_size / sector_size, 4, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory %d.\n", fl_idx); diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index 7d306fb..693dfec 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -14,6 +14,7 @@ #include "hw/i2c/i2c.h" #include "hw/ssi.h" #include "sysemu/char.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" static struct { @@ -2085,7 +2086,8 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space, fprintf(stderr, "qemu: missing SecureDigital device\n"); exit(1); } - s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv, + s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, + blk_by_legacy_dinfo(dinfo), qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC), qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI), qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI)); @@ -2217,7 +2219,8 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size) fprintf(stderr, "qemu: missing SecureDigital device\n"); exit(1); } - s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv, + s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, + blk_by_legacy_dinfo(dinfo), qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC), qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI), qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI)); diff --git a/hw/arm/realview.c b/hw/arm/realview.c index 8bd3ff6..af65aa4 100644 --- a/hw/arm/realview.c +++ b/hw/arm/realview.c @@ -16,7 +16,7 @@ #include "sysemu/sysemu.h" #include "hw/boards.h" #include "hw/i2c/i2c.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #include "qemu/error-report.h" diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index 9260896..a16831c 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -22,10 +22,9 @@ #include "hw/devices.h" #include "hw/arm/sharpsl.h" #include "ui/console.h" -#include "block/block.h" #include "audio/audio.h" #include "hw/boards.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" @@ -170,7 +169,8 @@ static int sl_nand_init(SysBusDevice *dev) s->ctl = 0; nand = drive_get(IF_MTD, 0, 0); - s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id); + s->nand = nand_init(nand ? blk_by_legacy_dinfo(nand) : NULL, + s->manf_id, s->chip_id); memory_region_init_io(&s->iomem, OBJECT(s), &sl_ops, s, "sl", 0x40); sysbus_init_mmio(dev, &s->iomem); diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c index 6c574bc..73572eb 100644 --- a/hw/arm/tosa.c +++ b/hw/arm/tosa.c @@ -17,11 +17,10 @@ #include "hw/devices.h" #include "hw/arm/sharpsl.h" #include "hw/pcmcia.h" -#include "block/block.h" #include "hw/boards.h" #include "hw/i2c/i2c.h" #include "hw/ssi.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c index 7696be1..e6ef0a2 100644 --- a/hw/arm/versatilepb.c +++ b/hw/arm/versatilepb.c @@ -15,7 +15,7 @@ #include "hw/pci/pci.h" #include "hw/i2c/i2c.h" #include "hw/boards.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #include "hw/block/flash.h" @@ -338,7 +338,8 @@ static void versatile_init(MachineState *machine, int board_id) dinfo = drive_get(IF_PFLASH, 0, 0); if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, NULL, "versatile.flash", - VERSATILE_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL, + VERSATILE_FLASH_SIZE, + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, VERSATILE_FLASH_SECT_SIZE, VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE, 4, 0x0089, 0x0018, 0x0000, 0x0, 0)) { diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index aed218f..7cbd13f 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -30,7 +30,7 @@ #include "hw/boards.h" #include "hw/loader.h" #include "exec/address-spaces.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/block/flash.h" #include "sysemu/device_tree.h" #include "qemu/error-report.h" @@ -491,7 +491,8 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name, { DeviceState *dev = qdev_create(NULL, "cfi.pflash01"); - if (di && qdev_prop_set_drive(dev, "drive", di->bdrv)) { + if (di && qdev_prop_set_drive(dev, "drive", + blk_by_legacy_dinfo(di))) { abort(); } diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 8c6b171..8ea592e 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -33,6 +33,7 @@ #include "hw/arm/primecell.h" #include "hw/devices.h" #include "net/net.h" +#include "sysemu/block-backend.h" #include "sysemu/device_tree.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" @@ -450,7 +451,8 @@ static void create_one_flash(const char *name, hwaddr flashbase, DeviceState *dev = qdev_create(NULL, "cfi.pflash01"); const uint64_t sectorlength = 256 * 1024; - if (dinfo && qdev_prop_set_drive(dev, "drive", dinfo->bdrv)) { + if (dinfo && qdev_prop_set_drive(dev, "drive", + blk_by_legacy_dinfo(dinfo))) { abort(); } diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c index ad85c7a..b590392 100644 --- a/hw/arm/xilinx_zynq.c +++ b/hw/arm/xilinx_zynq.c @@ -22,7 +22,7 @@ #include "sysemu/sysemu.h" #include "hw/boards.h" #include "hw/block/flash.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/loader.h" #include "hw/ssi.h" #include "qemu/error-report.h" @@ -164,7 +164,8 @@ static void zynq_init(MachineState *machine) /* AMD */ pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE, - dinfo ? dinfo->bdrv : NULL, FLASH_SECTOR_SIZE, + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, + FLASH_SECTOR_SIZE, FLASH_SIZE/FLASH_SECTOR_SIZE, 1, 1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa, 0); diff --git a/hw/arm/z2.c b/hw/arm/z2.c index 36b3b50..1735547 100644 --- a/hw/arm/z2.c +++ b/hw/arm/z2.c @@ -20,7 +20,7 @@ #include "hw/boards.h" #include "sysemu/sysemu.h" #include "hw/block/flash.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "ui/console.h" #include "audio/audio.h" #include "exec/address-spaces.h" @@ -336,9 +336,9 @@ static void z2_init(MachineState *machine) if (!pflash_cfi01_register(Z2_FLASH_BASE, NULL, "z2.flash0", Z2_FLASH_SIZE, - dinfo ? dinfo->bdrv : NULL, sector_len, - Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0, - be)) { + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, + sector_len, Z2_FLASH_SIZE / sector_len, + 4, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); exit(1); } diff --git a/hw/block/block.c b/hw/block/block.c index b6a6dc6..a625773 100644 --- a/hw/block/block.c +++ b/hw/block/block.c @@ -8,6 +8,7 @@ */ #include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/block/block.h" #include "qemu/error-report.h" @@ -17,8 +18,10 @@ void blkconf_serial(BlockConf *conf, char **serial) if (!*serial) { /* try to fall back to value set with legacy -drive serial=... */ - dinfo = drive_get_by_blockdev(conf->bs); - *serial = g_strdup(dinfo->serial); + dinfo = blk_legacy_dinfo(conf->blk); + if (dinfo) { + *serial = g_strdup(dinfo->serial); + } } } @@ -30,16 +33,18 @@ void blkconf_geometry(BlockConf *conf, int *ptrans, if (!conf->cyls && !conf->heads && !conf->secs) { /* try to fall back to value set with legacy -drive cyls=... */ - dinfo = drive_get_by_blockdev(conf->bs); - conf->cyls = dinfo->cyls; - conf->heads = dinfo->heads; - conf->secs = dinfo->secs; - if (ptrans) { - *ptrans = dinfo->trans; + dinfo = blk_legacy_dinfo(conf->blk); + if (dinfo) { + conf->cyls = dinfo->cyls; + conf->heads = dinfo->heads; + conf->secs = dinfo->secs; + if (ptrans) { + *ptrans = dinfo->trans; + } } } if (!conf->cyls && !conf->heads && !conf->secs) { - hd_geometry_guess(conf->bs, + hd_geometry_guess(conf->blk, &conf->cyls, &conf->heads, &conf->secs, ptrans); } else if (ptrans && *ptrans == BIOS_ATA_TRANSLATION_AUTO) { diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 5458f9d..45b1164 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -17,7 +17,7 @@ #include "qemu/thread.h" #include "qemu/error-report.h" #include "hw/virtio/dataplane/vring.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "hw/virtio/virtio-blk.h" #include "virtio-blk.h" #include "block/aio.h" @@ -30,7 +30,7 @@ struct VirtIOBlockDataPlane { bool stopping; bool disabled; - VirtIOBlkConf *blk; + VirtIOBlkConf *conf; VirtIODevice *vdev; Vring vring; /* virtqueue vring */ @@ -94,7 +94,7 @@ static void handle_notify(EventNotifier *e) VirtIOBlock *vblk = VIRTIO_BLK(s->vdev); event_notifier_test_and_clear(&s->host_notifier); - bdrv_io_plug(s->blk->conf.bs); + blk_io_plug(s->conf->conf.blk); for (;;) { MultiReqBuffer mrb = { .num_writes = 0, @@ -120,7 +120,7 @@ static void handle_notify(EventNotifier *e) virtio_blk_handle_request(req, &mrb); } - virtio_submit_multiwrite(s->blk->conf.bs, &mrb); + virtio_submit_multiwrite(s->conf->conf.blk, &mrb); if (likely(ret == -EAGAIN)) { /* vring emptied */ /* Re-enable guest->host notifies and stop processing the vring. @@ -133,11 +133,11 @@ static void handle_notify(EventNotifier *e) break; } } - bdrv_io_unplug(s->blk->conf.bs); + blk_io_unplug(s->conf->conf.blk); } /* Context: QEMU global mutex held */ -void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, +void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, VirtIOBlockDataPlane **dataplane, Error **errp) { @@ -148,7 +148,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, *dataplane = NULL; - if (!blk->data_plane && !blk->iothread) { + if (!conf->data_plane && !conf->iothread) { return; } @@ -163,7 +163,8 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, /* If dataplane is (re-)enabled while the guest is running there could be * block jobs that can conflict. */ - if (bdrv_op_is_blocked(blk->conf.bs, BLOCK_OP_TYPE_DATAPLANE, &local_err)) { + if (blk_op_is_blocked(conf->conf.blk, BLOCK_OP_TYPE_DATAPLANE, + &local_err)) { error_setg(errp, "cannot start dataplane thread: %s", error_get_pretty(local_err)); error_free(local_err); @@ -172,10 +173,10 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, s = g_new0(VirtIOBlockDataPlane, 1); s->vdev = vdev; - s->blk = blk; + s->conf = conf; - if (blk->iothread) { - s->iothread = blk->iothread; + if (conf->iothread) { + s->iothread = conf->iothread; object_ref(OBJECT(s->iothread)); } else { /* Create per-device IOThread if none specified. This is for @@ -192,9 +193,9 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, s->bh = aio_bh_new(s->ctx, notify_guest_bh, s); error_setg(&s->blocker, "block device is in use by data plane"); - bdrv_op_block_all(blk->conf.bs, s->blocker); - bdrv_op_unblock(blk->conf.bs, BLOCK_OP_TYPE_RESIZE, s->blocker); - bdrv_op_unblock(blk->conf.bs, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker); + blk_op_block_all(conf->conf.blk, s->blocker); + 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); *dataplane = s; } @@ -207,7 +208,7 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s) } virtio_blk_data_plane_stop(s); - bdrv_op_unblock_all(s->blk->conf.bs, s->blocker); + blk_op_unblock_all(s->conf->conf.blk, s->blocker); error_free(s->blocker); object_unref(OBJECT(s->iothread)); qemu_bh_delete(s->bh); @@ -262,7 +263,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) s->started = true; trace_virtio_blk_data_plane_start(s); - bdrv_set_aio_context(s->blk->conf.bs, s->ctx); + blk_set_aio_context(s->conf->conf.blk, s->ctx); /* Kick right away to begin processing requests already in vring */ event_notifier_set(virtio_queue_get_host_notifier(vq)); @@ -308,7 +309,7 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s) aio_set_event_notifier(s->ctx, &s->host_notifier, NULL); /* Drain and switch bs back to the QEMU main loop */ - bdrv_set_aio_context(s->blk->conf.bs, qemu_get_aio_context()); + blk_set_aio_context(s->conf->conf.blk, qemu_get_aio_context()); aio_context_release(s->ctx); diff --git a/hw/block/dataplane/virtio-blk.h b/hw/block/dataplane/virtio-blk.h index 1750c99..c88d40e 100644 --- a/hw/block/dataplane/virtio-blk.h +++ b/hw/block/dataplane/virtio-blk.h @@ -19,7 +19,7 @@ typedef struct VirtIOBlockDataPlane VirtIOBlockDataPlane; -void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, +void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, VirtIOBlockDataPlane **dataplane, Error **errp); void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s); diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 34c1d8f..739a03e 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -33,6 +33,7 @@ #include "qemu/timer.h" #include "hw/isa/isa.h" #include "hw/sysbus.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "sysemu/sysemu.h" #include "qemu/log.h" @@ -113,7 +114,7 @@ static const FDFormat fd_formats[] = { { FDRIVE_DRV_NONE, -1, -1, 0, 0, }, }; -static void pick_geometry(BlockDriverState *bs, int *nb_heads, +static void pick_geometry(BlockBackend *blk, int *nb_heads, int *max_track, int *last_sect, FDriveType drive_in, FDriveType *drive, FDriveRate *rate) @@ -122,7 +123,7 @@ static void pick_geometry(BlockDriverState *bs, int *nb_heads, uint64_t nb_sectors, size; int i, first_match, match; - bdrv_get_geometry(bs, &nb_sectors); + blk_get_geometry(blk, &nb_sectors); match = -1; first_match = -1; for (i = 0; ; i++) { @@ -175,7 +176,7 @@ typedef enum FDiskFlags { typedef struct FDrive { FDCtrl *fdctrl; - BlockDriverState *bs; + BlockBackend *blk; /* Drive status */ FDriveType drive; uint8_t perpendicular; /* 2.88 MB access mode */ @@ -260,7 +261,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect, #endif drv->head = head; if (drv->track != track) { - if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) { + if (drv->blk != NULL && blk_is_inserted(drv->blk)) { drv->media_changed = 0; } ret = 1; @@ -269,7 +270,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect, drv->sect = sect; } - if (drv->bs == NULL || !bdrv_is_inserted(drv->bs)) { + if (drv->blk == NULL || !blk_is_inserted(drv->blk)) { ret = 2; } @@ -291,11 +292,11 @@ static void fd_revalidate(FDrive *drv) FDriveRate rate; FLOPPY_DPRINTF("revalidate\n"); - if (drv->bs != NULL) { - ro = bdrv_is_read_only(drv->bs); - pick_geometry(drv->bs, &nb_heads, &max_track, + if (drv->blk != NULL) { + ro = blk_is_read_only(drv->blk); + pick_geometry(drv->blk, &nb_heads, &max_track, &last_sect, drv->drive, &drive, &rate); - if (!bdrv_is_inserted(drv->bs)) { + if (!blk_is_inserted(drv->blk)) { FLOPPY_DPRINTF("No disk in drive\n"); } else { FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads, @@ -665,7 +666,7 @@ static bool fdrive_media_changed_needed(void *opaque) { FDrive *drive = opaque; - return (drive->bs != NULL && drive->media_changed != 1); + return (drive->blk != NULL && drive->media_changed != 1); } static const VMStateDescription vmstate_fdrive_media_changed = { @@ -910,8 +911,9 @@ static void fdctrl_reset(FDCtrl *fdctrl, int do_irq) /* Initialise controller */ fdctrl->sra = 0; fdctrl->srb = 0xc0; - if (!fdctrl->drives[1].bs) + if (!fdctrl->drives[1].blk) { fdctrl->sra |= FD_SRA_nDRV2; + } fdctrl->cur_drv = 0; fdctrl->dor = FD_DOR_nRESET; fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0; @@ -1403,7 +1405,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, status2 = FD_SR2_SNS; if (dma_len > fdctrl->data_len) dma_len = fdctrl->data_len; - if (cur_drv->bs == NULL) { + if (cur_drv->blk == NULL) { if (fdctrl->data_dir == FD_DIR_WRITE) fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); else @@ -1424,8 +1426,8 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, if (fdctrl->data_dir != FD_DIR_WRITE || len < FD_SECTOR_LEN || rel_pos != 0) { /* READ & SCAN commands and realign to a sector for WRITE */ - if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), - fdctrl->fifo, 1) < 0) { + if (blk_read(cur_drv->blk, fd_sector(cur_drv), + fdctrl->fifo, 1) < 0) { FLOPPY_DPRINTF("Floppy: error getting sector %d\n", fd_sector(cur_drv)); /* Sure, image size is too small... */ @@ -1452,8 +1454,8 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, DMA_read_memory (nchan, fdctrl->fifo + rel_pos, fdctrl->data_pos, len); - if (bdrv_write(cur_drv->bs, fd_sector(cur_drv), - fdctrl->fifo, 1) < 0) { + if (blk_write(cur_drv->blk, fd_sector(cur_drv), + fdctrl->fifo, 1) < 0) { FLOPPY_DPRINTF("error writing sector %d\n", fd_sector(cur_drv)); fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); @@ -1528,7 +1530,8 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl) fd_sector(cur_drv)); return 0; } - if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) { + if (blk_read(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1) + < 0) { FLOPPY_DPRINTF("error getting sector %d\n", fd_sector(cur_drv)); /* Sure, image size is too small... */ @@ -1597,8 +1600,8 @@ static void fdctrl_format_sector(FDCtrl *fdctrl) break; } memset(fdctrl->fifo, 0, FD_SECTOR_LEN); - if (cur_drv->bs == NULL || - bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) { + if (cur_drv->blk == NULL || + blk_write(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) { FLOPPY_DPRINTF("error formatting sector %d\n", fd_sector(cur_drv)); fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); } else { @@ -1988,7 +1991,8 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value) if (pos == FD_SECTOR_LEN - 1 || fdctrl->data_pos == fdctrl->data_len) { cur_drv = get_cur_drv(fdctrl); - if (bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) { + if (blk_write(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1) + < 0) { FLOPPY_DPRINTF("error writing sector %d\n", fd_sector(cur_drv)); return; @@ -2076,12 +2080,12 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, Error **errp) drive = &fdctrl->drives[i]; drive->fdctrl = fdctrl; - if (drive->bs) { - if (bdrv_get_on_error(drive->bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) { + if (drive->blk) { + if (blk_get_on_error(drive->blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) { error_setg(errp, "fdc doesn't support drive option werror"); return; } - if (bdrv_get_on_error(drive->bs, 1) != BLOCKDEV_ON_ERROR_REPORT) { + if (blk_get_on_error(drive->blk, 1) != BLOCKDEV_ON_ERROR_REPORT) { error_setg(errp, "fdc doesn't support drive option rerror"); return; } @@ -2089,8 +2093,8 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, Error **errp) fd_init(drive); fdctrl_change_cb(drive, 0); - if (drive->bs) { - bdrv_set_dev_ops(drive->bs, &fdctrl_block_ops, drive); + if (drive->blk) { + blk_set_dev_ops(drive->blk, &fdctrl_block_ops, drive); } } } @@ -2107,10 +2111,10 @@ ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds) dev = DEVICE(isadev); if (fds[0]) { - qdev_prop_set_drive_nofail(dev, "driveA", fds[0]->bdrv); + qdev_prop_set_drive_nofail(dev, "driveA", blk_by_legacy_dinfo(fds[0])); } if (fds[1]) { - qdev_prop_set_drive_nofail(dev, "driveB", fds[1]->bdrv); + qdev_prop_set_drive_nofail(dev, "driveB", blk_by_legacy_dinfo(fds[1])); } qdev_init_nofail(dev); @@ -2130,10 +2134,10 @@ void fdctrl_init_sysbus(qemu_irq irq, int dma_chann, fdctrl = &sys->state; fdctrl->dma_chann = dma_chann; /* FIXME */ if (fds[0]) { - qdev_prop_set_drive_nofail(dev, "driveA", fds[0]->bdrv); + qdev_prop_set_drive_nofail(dev, "driveA", blk_by_legacy_dinfo(fds[0])); } if (fds[1]) { - qdev_prop_set_drive_nofail(dev, "driveB", fds[1]->bdrv); + qdev_prop_set_drive_nofail(dev, "driveB", blk_by_legacy_dinfo(fds[1])); } qdev_init_nofail(dev); sbd = SYS_BUS_DEVICE(dev); @@ -2149,7 +2153,7 @@ void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base, dev = qdev_create(NULL, "SUNW,fdtwo"); if (fds[0]) { - qdev_prop_set_drive_nofail(dev, "drive", fds[0]->bdrv); + qdev_prop_set_drive_nofail(dev, "drive", blk_by_legacy_dinfo(fds[0])); } qdev_init_nofail(dev); sys = SYSBUS_FDC(dev); @@ -2286,8 +2290,8 @@ static Property isa_fdc_properties[] = { DEFINE_PROP_UINT32("iobase", FDCtrlISABus, iobase, 0x3f0), DEFINE_PROP_UINT32("irq", FDCtrlISABus, irq, 6), DEFINE_PROP_UINT32("dma", FDCtrlISABus, dma, 2), - DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].bs), - DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].bs), + DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].blk), + DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].blk), DEFINE_PROP_BIT("check_media_rate", FDCtrlISABus, state.check_media_rate, 0, true), DEFINE_PROP_END_OF_LIST(), @@ -2336,8 +2340,8 @@ static const VMStateDescription vmstate_sysbus_fdc ={ }; static Property sysbus_fdc_properties[] = { - DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].bs), - DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].bs), + DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].blk), + DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].blk), DEFINE_PROP_END_OF_LIST(), }; @@ -2357,7 +2361,7 @@ static const TypeInfo sysbus_fdc_info = { }; static Property sun4m_fdc_properties[] = { - DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].bs), + DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].blk), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/block/hd-geometry.c b/hw/block/hd-geometry.c index 6feb4f8..6fcf74d 100644 --- a/hw/block/hd-geometry.c +++ b/hw/block/hd-geometry.c @@ -30,7 +30,7 @@ * THE SOFTWARE. */ -#include "block/block.h" +#include "sysemu/block-backend.h" #include "hw/block/block.h" #include "trace.h" @@ -49,7 +49,7 @@ struct partition { /* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */ -static int guess_disk_lchs(BlockDriverState *bs, +static int guess_disk_lchs(BlockBackend *blk, int *pcylinders, int *pheads, int *psectors) { uint8_t buf[BDRV_SECTOR_SIZE]; @@ -58,14 +58,14 @@ static int guess_disk_lchs(BlockDriverState *bs, uint32_t nr_sects; uint64_t nb_sectors; - bdrv_get_geometry(bs, &nb_sectors); + blk_get_geometry(blk, &nb_sectors); /** * The function will be invoked during startup not only in sync I/O mode, * but also in async I/O mode. So the I/O throttling function has to * be disabled temporarily here, not permanently. */ - if (bdrv_read_unthrottled(bs, 0, buf, 1) < 0) { + if (blk_read_unthrottled(blk, 0, buf, 1) < 0) { return -1; } /* test msdos magic */ @@ -90,20 +90,20 @@ static int guess_disk_lchs(BlockDriverState *bs, *pheads = heads; *psectors = sectors; *pcylinders = cylinders; - trace_hd_geometry_lchs_guess(bs, cylinders, heads, sectors); + trace_hd_geometry_lchs_guess(blk, cylinders, heads, sectors); return 0; } } return -1; } -static void guess_chs_for_size(BlockDriverState *bs, +static void guess_chs_for_size(BlockBackend *blk, uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs) { uint64_t nb_sectors; int cylinders; - bdrv_get_geometry(bs, &nb_sectors); + blk_get_geometry(blk, &nb_sectors); cylinders = nb_sectors / (16 * 63); if (cylinders > 16383) { @@ -116,21 +116,21 @@ static void guess_chs_for_size(BlockDriverState *bs, *psecs = 63; } -void hd_geometry_guess(BlockDriverState *bs, +void hd_geometry_guess(BlockBackend *blk, uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs, int *ptrans) { int cylinders, heads, secs, translation; - if (guess_disk_lchs(bs, &cylinders, &heads, &secs) < 0) { + if (guess_disk_lchs(blk, &cylinders, &heads, &secs) < 0) { /* no LCHS guess: use a standard physical disk geometry */ - guess_chs_for_size(bs, pcyls, pheads, psecs); + guess_chs_for_size(blk, pcyls, pheads, psecs); translation = hd_bios_chs_auto_trans(*pcyls, *pheads, *psecs); } else if (heads > 16) { /* LCHS guess with heads > 16 means that a BIOS LBA translation was active, so a standard physical disk geometry is OK */ - guess_chs_for_size(bs, pcyls, pheads, psecs); + guess_chs_for_size(blk, pcyls, pheads, psecs); translation = *pcyls * *pheads <= 131072 ? BIOS_ATA_TRANSLATION_LARGE : BIOS_ATA_TRANSLATION_LBA; @@ -146,7 +146,7 @@ void hd_geometry_guess(BlockDriverState *bs, if (ptrans) { *ptrans = translation; } - trace_hd_geometry_guess(bs, *pcyls, *pheads, *psecs, translation); + trace_hd_geometry_guess(blk, *pcyls, *pheads, *psecs, translation); } int hd_bios_chs_auto_trans(uint32_t cyls, uint32_t heads, uint32_t secs) diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 5893773..ff1106b 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -22,6 +22,7 @@ */ #include "hw/hw.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/ssi.h" @@ -245,7 +246,7 @@ typedef struct Flash { uint32_t r; - BlockDriverState *bdrv; + BlockBackend *blk; uint8_t *storage; uint32_t size; @@ -279,7 +280,7 @@ typedef struct M25P80Class { #define M25P80_GET_CLASS(obj) \ OBJECT_GET_CLASS(M25P80Class, (obj), TYPE_M25P80) -static void bdrv_sync_complete(void *opaque, int ret) +static void blk_sync_complete(void *opaque, int ret) { /* do nothing. Masters do not directly interact with the backing store, * only the working copy so no mutexing required. @@ -288,20 +289,20 @@ static void bdrv_sync_complete(void *opaque, int ret) static void flash_sync_page(Flash *s, int page) { - int bdrv_sector, nb_sectors; + int blk_sector, nb_sectors; QEMUIOVector iov; - if (!s->bdrv || bdrv_is_read_only(s->bdrv)) { + if (!s->blk || blk_is_read_only(s->blk)) { return; } - bdrv_sector = (page * s->pi->page_size) / BDRV_SECTOR_SIZE; + blk_sector = (page * s->pi->page_size) / BDRV_SECTOR_SIZE; nb_sectors = DIV_ROUND_UP(s->pi->page_size, BDRV_SECTOR_SIZE); qemu_iovec_init(&iov, 1); - qemu_iovec_add(&iov, s->storage + bdrv_sector * BDRV_SECTOR_SIZE, + qemu_iovec_add(&iov, s->storage + blk_sector * BDRV_SECTOR_SIZE, nb_sectors * BDRV_SECTOR_SIZE); - bdrv_aio_writev(s->bdrv, bdrv_sector, &iov, nb_sectors, bdrv_sync_complete, - NULL); + blk_aio_writev(s->blk, blk_sector, &iov, nb_sectors, blk_sync_complete, + NULL); } static inline void flash_sync_area(Flash *s, int64_t off, int64_t len) @@ -309,7 +310,7 @@ static inline void flash_sync_area(Flash *s, int64_t off, int64_t len) int64_t start, end, nb_sectors; QEMUIOVector iov; - if (!s->bdrv || bdrv_is_read_only(s->bdrv)) { + if (!s->blk || blk_is_read_only(s->blk)) { return; } @@ -320,7 +321,7 @@ static inline void flash_sync_area(Flash *s, int64_t off, int64_t len) qemu_iovec_init(&iov, 1); qemu_iovec_add(&iov, s->storage + (start * BDRV_SECTOR_SIZE), nb_sectors * BDRV_SECTOR_SIZE); - bdrv_aio_writev(s->bdrv, start, &iov, nb_sectors, bdrv_sync_complete, NULL); + blk_aio_writev(s->blk, start, &iov, nb_sectors, blk_sync_complete, NULL); } static void flash_erase(Flash *s, int offset, FlashCMD cmd) @@ -620,17 +621,17 @@ static int m25p80_init(SSISlave *ss) s->size = s->pi->sector_size * s->pi->n_sectors; s->dirty_page = -1; - s->storage = qemu_blockalign(s->bdrv, s->size); + s->storage = blk_blockalign(s->blk, s->size); dinfo = drive_get_next(IF_MTD); - if (dinfo && dinfo->bdrv) { + if (dinfo) { DB_PRINT_L(0, "Binding to IF_MTD drive\n"); - s->bdrv = dinfo->bdrv; + s->blk = blk_by_legacy_dinfo(dinfo); /* FIXME: Move to late init */ - if (bdrv_read(s->bdrv, 0, s->storage, DIV_ROUND_UP(s->size, - BDRV_SECTOR_SIZE))) { + if (blk_read(s->blk, 0, s->storage, + DIV_ROUND_UP(s->size, BDRV_SECTOR_SIZE))) { fprintf(stderr, "Failed to initialize SPI flash!\n"); return 1; } diff --git a/hw/block/nand.c b/hw/block/nand.c index 38eefd4..1882a0c 100644 --- a/hw/block/nand.c +++ b/hw/block/nand.c @@ -20,7 +20,7 @@ # include "hw/hw.h" # include "hw/block/flash.h" -# include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/qdev.h" #include "qemu/error-report.h" @@ -61,7 +61,7 @@ struct NANDFlashState { int size, pages; int page_shift, oob_shift, erase_shift, addr_shift; uint8_t *storage; - BlockDriverState *bdrv; + BlockBackend *blk; int mem_oob; uint8_t cle, ale, ce, wp, gnd; @@ -400,12 +400,12 @@ static void nand_realize(DeviceState *dev, Error **errp) pagesize = 1 << s->oob_shift; s->mem_oob = 1; - if (s->bdrv) { - if (bdrv_is_read_only(s->bdrv)) { + if (s->blk) { + if (blk_is_read_only(s->blk)) { error_setg(errp, "Can't use a read-only drive"); return; } - if (bdrv_getlength(s->bdrv) >= + if (blk_getlength(s->blk) >= (s->pages << s->page_shift) + (s->pages << s->oob_shift)) { pagesize = 0; s->mem_oob = 0; @@ -424,7 +424,7 @@ static void nand_realize(DeviceState *dev, Error **errp) static Property nand_properties[] = { DEFINE_PROP_UINT8("manufacturer_id", NANDFlashState, manf_id, 0), DEFINE_PROP_UINT8("chip_id", NANDFlashState, chip_id, 0), - DEFINE_PROP_DRIVE("drive", NANDFlashState, bdrv), + DEFINE_PROP_DRIVE("drive", NANDFlashState, blk), DEFINE_PROP_END_OF_LIST(), }; @@ -624,7 +624,7 @@ uint32_t nand_getbuswidth(DeviceState *dev) return s->buswidth << 3; } -DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id) +DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id) { DeviceState *dev; @@ -634,8 +634,8 @@ DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id) dev = DEVICE(object_new(TYPE_NAND)); qdev_prop_set_uint8(dev, "manufacturer_id", manf_id); qdev_prop_set_uint8(dev, "chip_id", chip_id); - if (bdrv) { - qdev_prop_set_drive_nofail(dev, "drive", bdrv); + if (blk) { + qdev_prop_set_drive_nofail(dev, "drive", blk); } qdev_init_nofail(dev); @@ -654,14 +654,14 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) if (PAGE(s->addr) >= s->pages) return; - if (!s->bdrv) { + if (!s->blk) { mem_and(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset, s->io, s->iolen); } else if (s->mem_oob) { sector = SECTOR(s->addr); off = (s->addr & PAGE_MASK) + s->offset; soff = SECTOR_OFFSET(s->addr); - if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS) < 0) { + if (blk_read(s->blk, sector, iobuf, PAGE_SECTORS) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); return; } @@ -673,21 +673,21 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE)); } - if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS) < 0) { + if (blk_write(s->blk, sector, iobuf, PAGE_SECTORS) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, sector); } } else { off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset; sector = off >> 9; soff = off & 0x1ff; - if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) < 0) { + if (blk_read(s->blk, sector, iobuf, PAGE_SECTORS + 2) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); return; } mem_and(iobuf + soff, s->io, s->iolen); - if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) < 0) { + if (blk_write(s->blk, sector, iobuf, PAGE_SECTORS + 2) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, sector); } } @@ -705,7 +705,7 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s) return; } - if (!s->bdrv) { + if (!s->blk) { memset(s->storage + PAGE_START(addr), 0xff, (PAGE_SIZE + OOB_SIZE) << s->erase_shift); } else if (s->mem_oob) { @@ -714,17 +714,17 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s) i = SECTOR(addr); page = SECTOR(addr + (ADDR_SHIFT + s->erase_shift)); for (; i < page; i ++) - if (bdrv_write(s->bdrv, i, iobuf, 1) < 0) { + if (blk_write(s->blk, i, iobuf, 1) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, i); } } else { addr = PAGE_START(addr); page = addr >> 9; - if (bdrv_read(s->bdrv, page, iobuf, 1) < 0) { + if (blk_read(s->blk, page, iobuf, 1) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, page); } memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1); - if (bdrv_write(s->bdrv, page, iobuf, 1) < 0) { + if (blk_write(s->blk, page, iobuf, 1) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, page); } @@ -732,18 +732,18 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s) i = (addr & ~0x1ff) + 0x200; for (addr += ((PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200; i < addr; i += 0x200) { - if (bdrv_write(s->bdrv, i >> 9, iobuf, 1) < 0) { + if (blk_write(s->blk, i >> 9, iobuf, 1) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, i >> 9); } } page = i >> 9; - if (bdrv_read(s->bdrv, page, iobuf, 1) < 0) { + if (blk_read(s->blk, page, iobuf, 1) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, page); } memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1); - if (bdrv_write(s->bdrv, page, iobuf, 1) < 0) { + if (blk_write(s->blk, page, iobuf, 1) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, page); } } @@ -756,9 +756,9 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s, return; } - if (s->bdrv) { + if (s->blk) { if (s->mem_oob) { - if (bdrv_read(s->bdrv, SECTOR(addr), s->io, PAGE_SECTORS) < 0) { + if (blk_read(s->blk, SECTOR(addr), s->io, PAGE_SECTORS) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, SECTOR(addr)); } @@ -767,8 +767,8 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s, OOB_SIZE); s->ioaddr = s->io + SECTOR_OFFSET(s->addr) + offset; } else { - if (bdrv_read(s->bdrv, PAGE_START(addr) >> 9, - s->io, (PAGE_SECTORS + 2)) < 0) { + if (blk_read(s->blk, PAGE_START(addr) >> 9, + s->io, (PAGE_SECTORS + 2)) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, PAGE_START(addr) >> 9); } diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 9a95f75..b6263dc 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -26,6 +26,7 @@ #include <hw/pci/pci.h> #include "sysemu/sysemu.h" #include "qapi/visitor.h" +#include "sysemu/block-backend.h" #include "nvme.h" @@ -199,7 +200,7 @@ static void nvme_rw_cb(void *opaque, int ret) NvmeCtrl *n = sq->ctrl; NvmeCQueue *cq = n->cq[sq->cqid]; - block_acct_done(bdrv_get_stats(n->conf.bs), &req->acct); + block_acct_done(blk_get_stats(n->conf.blk), &req->acct); if (!ret) { req->status = NVME_SUCCESS; } else { @@ -233,11 +234,11 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd, } assert((nlb << data_shift) == req->qsg.size); - dma_acct_start(n->conf.bs, &req->acct, &req->qsg, is_write ? - BLOCK_ACCT_WRITE : BLOCK_ACCT_READ); + dma_acct_start(n->conf.blk, &req->acct, &req->qsg, + is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ); req->aiocb = is_write ? - dma_bdrv_write(n->conf.bs, &req->qsg, aio_slba, nvme_rw_cb, req) : - dma_bdrv_read(n->conf.bs, &req->qsg, aio_slba, nvme_rw_cb, req); + dma_blk_write(n->conf.blk, &req->qsg, aio_slba, nvme_rw_cb, req) : + dma_blk_read(n->conf.blk, &req->qsg, aio_slba, nvme_rw_cb, req); return NVME_NO_COMPLETE; } @@ -290,7 +291,7 @@ static uint16_t nvme_del_sq(NvmeCtrl *n, NvmeCmd *cmd) while (!QTAILQ_EMPTY(&sq->out_req_list)) { req = QTAILQ_FIRST(&sq->out_req_list); assert(req->aiocb); - bdrv_aio_cancel(req->aiocb); + blk_aio_cancel(req->aiocb); } if (!nvme_check_cqid(n, sq->cqid)) { cq = n->cq[sq->cqid]; @@ -565,7 +566,7 @@ static void nvme_clear_ctrl(NvmeCtrl *n) } } - bdrv_flush(n->conf.bs); + blk_flush(n->conf.blk); n->bar.cc = 0; } @@ -750,11 +751,11 @@ static int nvme_init(PCIDevice *pci_dev) int64_t bs_size; uint8_t *pci_conf; - if (!(n->conf.bs)) { + if (!n->conf.blk) { return -1; } - bs_size = bdrv_getlength(n->conf.bs); + bs_size = blk_getlength(n->conf.blk); if (bs_size < 0) { return -1; } diff --git a/hw/block/nvme.h b/hw/block/nvme.h index bd8fc3e..993c511 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -636,7 +636,7 @@ typedef struct NvmeAsyncEvent { typedef struct NvmeRequest { struct NvmeSQueue *sq; - BlockDriverAIOCB *aiocb; + BlockAIOCB *aiocb; uint16_t status; NvmeCqe cqe; BlockAcctCookie acct; diff --git a/hw/block/onenand.c b/hw/block/onenand.c index e48e585..348630d 100644 --- a/hw/block/onenand.c +++ b/hw/block/onenand.c @@ -22,6 +22,7 @@ #include "hw/hw.h" #include "hw/block/flash.h" #include "hw/irq.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "exec/memory.h" #include "exec/address-spaces.h" @@ -49,8 +50,8 @@ typedef struct OneNANDState { hwaddr base; qemu_irq intr; qemu_irq rdy; - BlockDriverState *bdrv; - BlockDriverState *bdrv_cur; + BlockBackend *blk; + BlockBackend *blk_cur; uint8_t *image; uint8_t *otp; uint8_t *current; @@ -213,7 +214,7 @@ static void onenand_reset(OneNANDState *s, int cold) s->wpstatus = 0x0002; s->cycle = 0; s->otpmode = 0; - s->bdrv_cur = s->bdrv; + s->blk_cur = s->blk; s->current = s->image; s->secs_cur = s->secs; @@ -221,7 +222,7 @@ static void onenand_reset(OneNANDState *s, int cold) /* Lock the whole flash */ memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks); - if (s->bdrv_cur && bdrv_read(s->bdrv_cur, 0, s->boot[0], 8) < 0) { + if (s->blk_cur && blk_read(s->blk_cur, 0, s->boot[0], 8) < 0) { hw_error("%s: Loading the BootRAM failed.\n", __func__); } } @@ -237,10 +238,11 @@ static void onenand_system_reset(DeviceState *dev) static inline int onenand_load_main(OneNANDState *s, int sec, int secn, void *dest) { - if (s->bdrv_cur) - return bdrv_read(s->bdrv_cur, sec, dest, secn) < 0; - else if (sec + secn > s->secs_cur) + if (s->blk_cur) { + return blk_read(s->blk_cur, sec, dest, secn) < 0; + } else if (sec + secn > s->secs_cur) { return 1; + } memcpy(dest, s->current + (sec << 9), secn << 9); @@ -256,9 +258,9 @@ static inline int onenand_prog_main(OneNANDState *s, int sec, int secn, uint32_t size = (uint32_t)secn * 512; const uint8_t *sp = (const uint8_t *)src; uint8_t *dp = 0; - if (s->bdrv_cur) { + if (s->blk_cur) { dp = g_malloc(size); - if (!dp || bdrv_read(s->bdrv_cur, sec, dp, secn) < 0) { + if (!dp || blk_read(s->blk_cur, sec, dp, secn) < 0) { result = 1; } } else { @@ -273,11 +275,11 @@ static inline int onenand_prog_main(OneNANDState *s, int sec, int secn, for (i = 0; i < size; i++) { dp[i] &= sp[i]; } - if (s->bdrv_cur) { - result = bdrv_write(s->bdrv_cur, sec, dp, secn) < 0; + if (s->blk_cur) { + result = blk_write(s->blk_cur, sec, dp, secn) < 0; } } - if (dp && s->bdrv_cur) { + if (dp && s->blk_cur) { g_free(dp); } } @@ -290,14 +292,16 @@ static inline int onenand_load_spare(OneNANDState *s, int sec, int secn, { uint8_t buf[512]; - if (s->bdrv_cur) { - if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0) + if (s->blk_cur) { + if (blk_read(s->blk_cur, s->secs_cur + (sec >> 5), buf, 1) < 0) { return 1; + } memcpy(dest, buf + ((sec & 31) << 4), secn << 4); - } else if (sec + secn > s->secs_cur) + } else if (sec + secn > s->secs_cur) { return 1; - else + } else { memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4); + } return 0; } @@ -309,11 +313,10 @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn, if (secn > 0) { const uint8_t *sp = (const uint8_t *)src; uint8_t *dp = 0, *dpp = 0; - if (s->bdrv_cur) { + if (s->blk_cur) { dp = g_malloc(512); - if (!dp || bdrv_read(s->bdrv_cur, - s->secs_cur + (sec >> 5), - dp, 1) < 0) { + if (!dp + || blk_read(s->blk_cur, s->secs_cur + (sec >> 5), dp, 1) < 0) { result = 1; } else { dpp = dp + ((sec & 31) << 4); @@ -330,9 +333,9 @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn, for (i = 0; i < (secn << 4); i++) { dpp[i] &= sp[i]; } - if (s->bdrv_cur) { - result = bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5), - dp, 1) < 0; + if (s->blk_cur) { + result = blk_write(s->blk_cur, s->secs_cur + (sec >> 5), + dp, 1) < 0; } } g_free(dp); @@ -354,16 +357,16 @@ static inline int onenand_erase(OneNANDState *s, int sec, int num) } memset(blankbuf, 0xff, 512); for (; num > 0; num--, sec++) { - if (s->bdrv_cur) { + if (s->blk_cur) { int erasesec = s->secs_cur + (sec >> 5); - if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1) < 0) { + if (blk_write(s->blk_cur, sec, blankbuf, 1) < 0) { goto fail; } - if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) { + if (blk_read(s->blk_cur, erasesec, tmpbuf, 1) < 0) { goto fail; } memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4); - if (bdrv_write(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) { + if (blk_write(s->blk_cur, erasesec, tmpbuf, 1) < 0) { goto fail; } } else { @@ -576,7 +579,7 @@ static void onenand_command(OneNANDState *s) case 0x65: /* OTP Access */ s->intstatus |= ONEN_INT; - s->bdrv_cur = NULL; + s->blk_cur = NULL; s->current = s->otp; s->secs_cur = 1 << (BLOCK_SHIFT - 9); s->addr[ONEN_BUF_BLOCK] = 0; @@ -776,15 +779,15 @@ static int onenand_initfn(SysBusDevice *sbd) ? (1 << (6 + ((s->id.dev >> 4) & 7))) : 0; memory_region_init_io(&s->iomem, OBJECT(s), &onenand_ops, s, "onenand", 0x10000 << s->shift); - if (!s->bdrv) { + if (!s->blk) { s->image = memset(g_malloc(size + (size >> 5)), 0xff, size + (size >> 5)); } else { - if (bdrv_is_read_only(s->bdrv)) { + if (blk_is_read_only(s->blk)) { error_report("Can't use a read-only drive"); return -1; } - s->bdrv_cur = s->bdrv; + s->blk_cur = s->blk; } s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT), 0xff, (64 + 2) << PAGE_SHIFT); @@ -815,7 +818,7 @@ static Property onenand_properties[] = { DEFINE_PROP_UINT16("device_id", OneNANDState, id.dev, 0), DEFINE_PROP_UINT16("version_id", OneNANDState, id.ver, 0), DEFINE_PROP_INT32("shift", OneNANDState, shift, 0), - DEFINE_PROP_DRIVE("drive", OneNANDState, bdrv), + DEFINE_PROP_DRIVE("drive", OneNANDState, blk), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 1346541..89d380e 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -38,7 +38,7 @@ #include "hw/hw.h" #include "hw/block/flash.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "qemu/timer.h" #include "qemu/bitops.h" #include "exec/address-spaces.h" @@ -69,7 +69,7 @@ struct pflash_t { SysBusDevice parent_obj; /*< public >*/ - BlockDriverState *bs; + BlockBackend *blk; uint32_t nb_blocs; uint64_t sector_len; uint8_t bank_width; @@ -395,13 +395,13 @@ static void pflash_update(pflash_t *pfl, int offset, int size) { int offset_end; - if (pfl->bs) { + if (pfl->blk) { offset_end = offset + size; /* round to sectors */ offset = offset >> 9; offset_end = (offset_end + 511) >> 9; - bdrv_write(pfl->bs, offset, pfl->storage + (offset << 9), - offset_end - offset); + blk_write(pfl->blk, offset, pfl->storage + (offset << 9), + offset_end - offset); } } @@ -784,9 +784,9 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) pfl->storage = memory_region_get_ram_ptr(&pfl->mem); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem); - if (pfl->bs) { + if (pfl->blk) { /* read the initial flash content */ - ret = bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9); + ret = blk_read(pfl->blk, 0, pfl->storage, total_len >> 9); if (ret < 0) { vmstate_unregister_ram(&pfl->mem, DEVICE(pfl)); @@ -795,8 +795,8 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) } } - if (pfl->bs) { - pfl->ro = bdrv_is_read_only(pfl->bs); + if (pfl->blk) { + pfl->ro = blk_is_read_only(pfl->blk); } else { pfl->ro = 0; } @@ -898,7 +898,7 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) } static Property pflash_cfi01_properties[] = { - DEFINE_PROP_DRIVE("drive", struct pflash_t, bs), + DEFINE_PROP_DRIVE("drive", struct pflash_t, blk), /* num-blocks is the number of blocks actually visible to the guest, * ie the total size of the device divided by the sector length. * If we're emulating flash devices wired in parallel the actual @@ -962,14 +962,14 @@ type_init(pflash_cfi01_register_types) pflash_t *pflash_cfi01_register(hwaddr base, DeviceState *qdev, const char *name, hwaddr size, - BlockDriverState *bs, + BlockBackend *blk, uint32_t sector_len, int nb_blocs, int bank_width, uint16_t id0, uint16_t id1, uint16_t id2, uint16_t id3, int be) { DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH01); - if (bs && qdev_prop_set_drive(dev, "drive", bs)) { + if (blk && qdev_prop_set_drive(dev, "drive", blk)) { abort(); } qdev_prop_set_uint32(dev, "num-blocks", nb_blocs); diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index 01011cf..8513a17 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -38,7 +38,7 @@ #include "hw/hw.h" #include "hw/block/flash.h" #include "qemu/timer.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #include "qemu/host-utils.h" #include "hw/sysbus.h" @@ -63,7 +63,7 @@ struct pflash_t { SysBusDevice parent_obj; /*< public >*/ - BlockDriverState *bs; + BlockBackend *blk; uint32_t sector_len; uint32_t nb_blocs; uint32_t chip_len; @@ -249,13 +249,13 @@ static void pflash_update(pflash_t *pfl, int offset, int size) { int offset_end; - if (pfl->bs) { + if (pfl->blk) { offset_end = offset + size; /* round to sectors */ offset = offset >> 9; offset_end = (offset_end + 511) >> 9; - bdrv_write(pfl->bs, offset, pfl->storage + (offset << 9), - offset_end - offset); + blk_write(pfl->blk, offset, pfl->storage + (offset << 9), + offset_end - offset); } } @@ -618,9 +618,9 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) vmstate_register_ram(&pfl->orig_mem, DEVICE(pfl)); pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem); pfl->chip_len = chip_len; - if (pfl->bs) { + if (pfl->blk) { /* read the initial flash content */ - ret = bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9); + ret = blk_read(pfl->blk, 0, pfl->storage, chip_len >> 9); if (ret < 0) { vmstate_unregister_ram(&pfl->orig_mem, DEVICE(pfl)); error_setg(errp, "failed to read the initial flash content"); @@ -632,8 +632,8 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) pfl->rom_mode = 1; sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem); - if (pfl->bs) { - pfl->ro = bdrv_is_read_only(pfl->bs); + if (pfl->blk) { + pfl->ro = blk_is_read_only(pfl->blk); } else { pfl->ro = 0; } @@ -722,7 +722,7 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) } static Property pflash_cfi02_properties[] = { - DEFINE_PROP_DRIVE("drive", struct pflash_t, bs), + DEFINE_PROP_DRIVE("drive", struct pflash_t, blk), DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0), DEFINE_PROP_UINT32("sector-length", struct pflash_t, sector_len, 0), DEFINE_PROP_UINT8("width", struct pflash_t, width, 0), @@ -763,7 +763,7 @@ type_init(pflash_cfi02_register_types) pflash_t *pflash_cfi02_register(hwaddr base, DeviceState *qdev, const char *name, hwaddr size, - BlockDriverState *bs, uint32_t sector_len, + BlockBackend *blk, uint32_t sector_len, int nb_blocs, int nb_mappings, int width, uint16_t id0, uint16_t id1, uint16_t id2, uint16_t id3, @@ -772,7 +772,7 @@ pflash_t *pflash_cfi02_register(hwaddr base, { DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH02); - if (bs && qdev_prop_set_drive(dev, "drive", bs)) { + if (blk && qdev_prop_set_drive(dev, "drive", blk)) { abort(); } qdev_prop_set_uint32(dev, "num-blocks", nb_blocs); diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 1fa9770..b19b102 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -16,6 +16,7 @@ #include "qemu/error-report.h" #include "trace.h" #include "hw/block/block.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/virtio/virtio-blk.h" #include "dataplane/virtio-blk.h" @@ -64,7 +65,8 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status) static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, bool is_read) { - BlockErrorAction action = bdrv_get_error_action(req->dev->bs, is_read, error); + BlockErrorAction action = blk_get_error_action(req->dev->blk, + is_read, error); VirtIOBlock *s = req->dev; if (action == BLOCK_ERROR_ACTION_STOP) { @@ -72,11 +74,11 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, s->rq = req; } else if (action == BLOCK_ERROR_ACTION_REPORT) { virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR); - block_acct_done(bdrv_get_stats(s->bs), &req->acct); + block_acct_done(blk_get_stats(s->blk), &req->acct); virtio_blk_free_request(req); } - bdrv_error_action(s->bs, action, is_read, error); + blk_error_action(s->blk, action, is_read, error); return action != BLOCK_ERROR_ACTION_IGNORE; } @@ -94,7 +96,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret) } virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); - block_acct_done(bdrv_get_stats(req->dev->bs), &req->acct); + block_acct_done(blk_get_stats(req->dev->blk), &req->acct); virtio_blk_free_request(req); } @@ -109,7 +111,7 @@ static void virtio_blk_flush_complete(void *opaque, int ret) } virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); - block_acct_done(bdrv_get_stats(req->dev->bs), &req->acct); + block_acct_done(blk_get_stats(req->dev->blk), &req->acct); virtio_blk_free_request(req); } @@ -155,7 +157,7 @@ int virtio_blk_handle_scsi_req(VirtIOBlock *blk, */ scsi = (void *)elem->in_sg[elem->in_num - 2].iov_base; - if (!blk->blk.scsi) { + if (!blk->conf.scsi) { status = VIRTIO_BLK_S_UNSUPP; goto fail; } @@ -209,7 +211,7 @@ int virtio_blk_handle_scsi_req(VirtIOBlock *blk, hdr.sbp = elem->in_sg[elem->in_num - 3].iov_base; hdr.mx_sb_len = elem->in_sg[elem->in_num - 3].iov_len; - status = bdrv_ioctl(blk->bs, SG_IO, &hdr); + status = blk_ioctl(blk->blk, SG_IO, &hdr); if (status) { status = VIRTIO_BLK_S_UNSUPP; goto fail; @@ -255,7 +257,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req) virtio_blk_free_request(req); } -void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb) +void virtio_submit_multiwrite(BlockBackend *blk, MultiReqBuffer *mrb) { int i, ret; @@ -263,7 +265,7 @@ void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb) return; } - ret = bdrv_aio_multiwrite(bs, mrb->blkreq, mrb->num_writes); + ret = blk_aio_multiwrite(blk, mrb->blkreq, mrb->num_writes); if (ret != 0) { for (i = 0; i < mrb->num_writes; i++) { if (mrb->blkreq[i].error) { @@ -277,14 +279,14 @@ void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb) static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb) { - block_acct_start(bdrv_get_stats(req->dev->bs), &req->acct, 0, + block_acct_start(blk_get_stats(req->dev->blk), &req->acct, 0, BLOCK_ACCT_FLUSH); /* * Make sure all outstanding writes are posted to the backing device. */ - virtio_submit_multiwrite(req->dev->bs, mrb); - bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req); + virtio_submit_multiwrite(req->dev->blk, mrb); + blk_aio_flush(req->dev->blk, virtio_blk_flush_complete, req); } static bool virtio_blk_sect_range_ok(VirtIOBlock *dev, @@ -296,10 +298,10 @@ static bool virtio_blk_sect_range_ok(VirtIOBlock *dev, if (sector & dev->sector_mask) { return false; } - if (size % dev->conf->logical_block_size) { + if (size % dev->conf.conf.logical_block_size) { return false; } - bdrv_get_geometry(dev->bs, &total_sectors); + blk_get_geometry(dev->blk, &total_sectors); if (sector > total_sectors || nb_sectors > total_sectors - sector) { return false; } @@ -321,11 +323,11 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb) return; } - block_acct_start(bdrv_get_stats(req->dev->bs), &req->acct, req->qiov.size, + block_acct_start(blk_get_stats(req->dev->blk), &req->acct, req->qiov.size, BLOCK_ACCT_WRITE); if (mrb->num_writes == 32) { - virtio_submit_multiwrite(req->dev->bs, mrb); + virtio_submit_multiwrite(req->dev->blk, mrb); } blkreq = &mrb->blkreq[mrb->num_writes]; @@ -353,11 +355,11 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req) return; } - block_acct_start(bdrv_get_stats(req->dev->bs), &req->acct, req->qiov.size, + block_acct_start(blk_get_stats(req->dev->blk), &req->acct, req->qiov.size, BLOCK_ACCT_READ); - bdrv_aio_readv(req->dev->bs, sector, &req->qiov, - req->qiov.size / BDRV_SECTOR_SIZE, - virtio_blk_rw_complete, req); + blk_aio_readv(req->dev->blk, sector, &req->qiov, + req->qiov.size / BDRV_SECTOR_SIZE, + virtio_blk_rw_complete, req); } void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb) @@ -405,7 +407,7 @@ void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb) * NB: per existing s/n string convention the string is * terminated by '\0' only when shorter than buffer. */ - const char *serial = s->blk.serial ? s->blk.serial : ""; + const char *serial = s->conf.serial ? s->conf.serial : ""; size_t size = MIN(strlen(serial) + 1, MIN(iov_size(in_iov, in_num), VIRTIO_BLK_ID_BYTES)); @@ -445,7 +447,7 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) virtio_blk_handle_request(req, &mrb); } - virtio_submit_multiwrite(s->bs, &mrb); + virtio_submit_multiwrite(s->blk, &mrb); /* * FIXME: Want to check for completions before returning to guest mode, @@ -473,7 +475,7 @@ static void virtio_blk_dma_restart_bh(void *opaque) req = next; } - virtio_submit_multiwrite(s->bs, &mrb); + virtio_submit_multiwrite(s->blk, &mrb); } static void virtio_blk_dma_restart_cb(void *opaque, int running, @@ -486,7 +488,7 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running, } if (!s->bh) { - s->bh = aio_bh_new(bdrv_get_aio_context(s->blk.conf.bs), + s->bh = aio_bh_new(blk_get_aio_context(s->conf.conf.blk), virtio_blk_dma_restart_bh, s); qemu_bh_schedule(s->bh); } @@ -504,8 +506,8 @@ static void virtio_blk_reset(VirtIODevice *vdev) * This should cancel pending requests, but can't do nicely until there * are per-device request lists. */ - bdrv_drain_all(); - bdrv_set_enable_write_cache(s->bs, s->original_wce); + blk_drain_all(); + blk_set_enable_write_cache(s->blk, s->original_wce); } /* coalesce internal state, copy to pci i/o region 0 @@ -513,19 +515,20 @@ static void virtio_blk_reset(VirtIODevice *vdev) static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) { VirtIOBlock *s = VIRTIO_BLK(vdev); + BlockConf *conf = &s->conf.conf; struct virtio_blk_config blkcfg; uint64_t capacity; - int blk_size = s->conf->logical_block_size; + int blk_size = conf->logical_block_size; - bdrv_get_geometry(s->bs, &capacity); + blk_get_geometry(s->blk, &capacity); memset(&blkcfg, 0, sizeof(blkcfg)); virtio_stq_p(vdev, &blkcfg.capacity, capacity); virtio_stl_p(vdev, &blkcfg.seg_max, 128 - 2); - virtio_stw_p(vdev, &blkcfg.cylinders, s->conf->cyls); + virtio_stw_p(vdev, &blkcfg.cylinders, conf->cyls); virtio_stl_p(vdev, &blkcfg.blk_size, blk_size); - virtio_stw_p(vdev, &blkcfg.min_io_size, s->conf->min_io_size / blk_size); - virtio_stw_p(vdev, &blkcfg.opt_io_size, s->conf->opt_io_size / blk_size); - blkcfg.heads = s->conf->heads; + virtio_stw_p(vdev, &blkcfg.min_io_size, conf->min_io_size / blk_size); + virtio_stw_p(vdev, &blkcfg.opt_io_size, conf->opt_io_size / blk_size); + blkcfg.heads = conf->heads; /* * We must ensure that the block device capacity is a multiple of * the logical block size. If that is not the case, let's use @@ -537,15 +540,15 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) * divided by 512 - instead it is the amount of blk_size blocks * per track (cylinder). */ - if (bdrv_getlength(s->bs) / s->conf->heads / s->conf->secs % blk_size) { - blkcfg.sectors = s->conf->secs & ~s->sector_mask; + if (blk_getlength(s->blk) / conf->heads / conf->secs % blk_size) { + blkcfg.sectors = conf->secs & ~s->sector_mask; } else { - blkcfg.sectors = s->conf->secs; + blkcfg.sectors = conf->secs; } blkcfg.size_max = 0; - blkcfg.physical_block_exp = get_physical_block_exp(s->conf); + blkcfg.physical_block_exp = get_physical_block_exp(conf); blkcfg.alignment_offset = 0; - blkcfg.wce = bdrv_enable_write_cache(s->bs); + blkcfg.wce = blk_enable_write_cache(s->blk); memcpy(config, &blkcfg, sizeof(struct virtio_blk_config)); } @@ -556,9 +559,9 @@ static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config) memcpy(&blkcfg, config, sizeof(blkcfg)); - aio_context_acquire(bdrv_get_aio_context(s->bs)); - bdrv_set_enable_write_cache(s->bs, blkcfg.wce != 0); - aio_context_release(bdrv_get_aio_context(s->bs)); + aio_context_acquire(blk_get_aio_context(s->blk)); + blk_set_enable_write_cache(s->blk, blkcfg.wce != 0); + aio_context_release(blk_get_aio_context(s->blk)); } static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features) @@ -571,14 +574,15 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features) features |= (1 << VIRTIO_BLK_F_BLK_SIZE); features |= (1 << VIRTIO_BLK_F_SCSI); - if (s->blk.config_wce) { + if (s->conf.config_wce) { features |= (1 << VIRTIO_BLK_F_CONFIG_WCE); } - if (bdrv_enable_write_cache(s->bs)) + if (blk_enable_write_cache(s->blk)) { features |= (1 << VIRTIO_BLK_F_WCE); - - if (bdrv_is_read_only(s->bs)) + } + if (blk_is_read_only(s->blk)) { features |= 1 << VIRTIO_BLK_F_RO; + } return features; } @@ -612,13 +616,13 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) * Guest writes 1 to the WCE configuration field (writeback mode) * Guest sets DRIVER_OK bit in status field * - * s->bs would erroneously be placed in writethrough mode. + * s->blk would erroneously be placed in writethrough mode. */ if (!(features & (1 << VIRTIO_BLK_F_CONFIG_WCE))) { - aio_context_acquire(bdrv_get_aio_context(s->bs)); - bdrv_set_enable_write_cache(s->bs, - !!(features & (1 << VIRTIO_BLK_F_WCE))); - aio_context_release(bdrv_get_aio_context(s->bs)); + aio_context_acquire(blk_get_aio_context(s->blk)); + blk_set_enable_write_cache(s->blk, + !!(features & (1 << VIRTIO_BLK_F_WCE))); + aio_context_release(blk_get_aio_context(s->blk)); } } @@ -707,8 +711,8 @@ static void virtio_blk_migration_state_changed(Notifier *notifier, void *data) if (s->dataplane) { return; } - bdrv_drain_all(); /* complete in-flight non-dataplane requests */ - virtio_blk_data_plane_create(VIRTIO_DEVICE(s), &s->blk, + blk_drain_all(); /* complete in-flight non-dataplane requests */ + virtio_blk_data_plane_create(VIRTIO_DEVICE(s), &s->conf, &s->dataplane, &err); if (err != NULL) { error_report("%s", error_get_pretty(err)); @@ -721,22 +725,22 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOBlock *s = VIRTIO_BLK(dev); - VirtIOBlkConf *blk = &(s->blk); + VirtIOBlkConf *conf = &s->conf; Error *err = NULL; static int virtio_blk_id; - if (!blk->conf.bs) { + if (!conf->conf.blk) { error_setg(errp, "drive property not set"); return; } - if (!bdrv_is_inserted(blk->conf.bs)) { + if (!blk_is_inserted(conf->conf.blk)) { error_setg(errp, "Device needs media, but drive is empty"); return; } - blkconf_serial(&blk->conf, &blk->serial); - s->original_wce = bdrv_enable_write_cache(blk->conf.bs); - blkconf_geometry(&blk->conf, NULL, 65535, 255, 255, &err); + blkconf_serial(&conf->conf, &conf->serial); + s->original_wce = blk_enable_write_cache(conf->conf.blk); + blkconf_geometry(&conf->conf, NULL, 65535, 255, 255, &err); if (err) { error_propagate(errp, err); return; @@ -745,14 +749,13 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK, sizeof(struct virtio_blk_config)); - s->bs = blk->conf.bs; - s->conf = &blk->conf; + s->blk = conf->conf.blk; s->rq = NULL; - s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1; + s->sector_mask = (s->conf.conf.logical_block_size / BDRV_SECTOR_SIZE) - 1; s->vq = virtio_add_queue(vdev, 128, virtio_blk_handle_output); s->complete_request = virtio_blk_complete_request; - virtio_blk_data_plane_create(vdev, blk, &s->dataplane, &err); + virtio_blk_data_plane_create(vdev, conf, &s->dataplane, &err); if (err != NULL) { error_propagate(errp, err); virtio_cleanup(vdev); @@ -764,10 +767,10 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s); register_savevm(dev, "virtio-blk", virtio_blk_id++, 2, virtio_blk_save, virtio_blk_load, s); - bdrv_set_dev_ops(s->bs, &virtio_block_ops, s); - bdrv_set_guest_block_size(s->bs, s->conf->logical_block_size); + blk_set_dev_ops(s->blk, &virtio_block_ops, s); + blk_set_guest_block_size(s->blk, s->conf.conf.logical_block_size); - bdrv_iostatus_enable(s->bs); + blk_iostatus_enable(s->blk); } static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp) @@ -780,7 +783,7 @@ static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp) s->dataplane = NULL; qemu_del_vm_change_state_handler(s->change); unregister_savevm(dev, "virtio-blk", s); - blockdev_mark_auto_del(s->bs); + blockdev_mark_auto_del(s->blk); virtio_cleanup(vdev); } @@ -789,23 +792,23 @@ static void virtio_blk_instance_init(Object *obj) VirtIOBlock *s = VIRTIO_BLK(obj); object_property_add_link(obj, "iothread", TYPE_IOTHREAD, - (Object **)&s->blk.iothread, + (Object **)&s->conf.iothread, qdev_prop_allow_set_link_before_realize, OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL); - device_add_bootindex_property(obj, &s->blk.conf.bootindex, + device_add_bootindex_property(obj, &s->conf.conf.bootindex, "bootindex", "/disk@0,0", DEVICE(obj), NULL); } static Property virtio_blk_properties[] = { - DEFINE_BLOCK_PROPERTIES(VirtIOBlock, blk.conf), - DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlock, blk.conf), - DEFINE_PROP_STRING("serial", VirtIOBlock, blk.serial), - DEFINE_PROP_BIT("config-wce", VirtIOBlock, blk.config_wce, 0, true), + DEFINE_BLOCK_PROPERTIES(VirtIOBlock, conf.conf), + DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlock, conf.conf), + DEFINE_PROP_STRING("serial", VirtIOBlock, conf.serial), + DEFINE_PROP_BIT("config-wce", VirtIOBlock, conf.config_wce, 0, true), #ifdef __linux__ - DEFINE_PROP_BIT("scsi", VirtIOBlock, blk.scsi, 0, true), + DEFINE_PROP_BIT("scsi", VirtIOBlock, conf.scsi, 0, true), #endif - DEFINE_PROP_BIT("x-data-plane", VirtIOBlock, blk.data_plane, 0, false), + DEFINE_PROP_BIT("x-data-plane", VirtIOBlock, conf.data_plane, 0, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c index 0d27ab1..231e9a7 100644 --- a/hw/block/xen_disk.c +++ b/hw/block/xen_disk.c @@ -39,6 +39,7 @@ #include "hw/xen/xen_backend.h" #include "xen_blkif.h" #include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" /* ------------------------------------------------------------- */ @@ -122,7 +123,7 @@ struct XenBlkDev { /* qemu block driver */ DriveInfo *dinfo; - BlockDriverState *bs; + BlockBackend *blk; QEMUBH *bh; }; @@ -479,7 +480,7 @@ static void qemu_aio_complete(void *opaque, int ret) if (ioreq->postsync) { ioreq->postsync = 0; ioreq->aio_inflight++; - bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq); + blk_aio_flush(ioreq->blkdev->blk, qemu_aio_complete, ioreq); return; } @@ -493,7 +494,7 @@ static void qemu_aio_complete(void *opaque, int ret) break; } case BLKIF_OP_READ: - block_acct_done(bdrv_get_stats(ioreq->blkdev->bs), &ioreq->acct); + block_acct_done(blk_get_stats(ioreq->blkdev->blk), &ioreq->acct); break; case BLKIF_OP_DISCARD: default: @@ -512,18 +513,18 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) ioreq->aio_inflight++; if (ioreq->presync) { - bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq); + blk_aio_flush(ioreq->blkdev->blk, qemu_aio_complete, ioreq); return 0; } switch (ioreq->req.operation) { case BLKIF_OP_READ: - block_acct_start(bdrv_get_stats(blkdev->bs), &ioreq->acct, + block_acct_start(blk_get_stats(blkdev->blk), &ioreq->acct, ioreq->v.size, BLOCK_ACCT_READ); ioreq->aio_inflight++; - bdrv_aio_readv(blkdev->bs, ioreq->start / BLOCK_SIZE, - &ioreq->v, ioreq->v.size / BLOCK_SIZE, - qemu_aio_complete, ioreq); + blk_aio_readv(blkdev->blk, ioreq->start / BLOCK_SIZE, + &ioreq->v, ioreq->v.size / BLOCK_SIZE, + qemu_aio_complete, ioreq); break; case BLKIF_OP_WRITE: case BLKIF_OP_FLUSH_DISKCACHE: @@ -531,18 +532,18 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) break; } - block_acct_start(bdrv_get_stats(blkdev->bs), &ioreq->acct, + block_acct_start(blk_get_stats(blkdev->blk), &ioreq->acct, ioreq->v.size, BLOCK_ACCT_WRITE); ioreq->aio_inflight++; - bdrv_aio_writev(blkdev->bs, ioreq->start / BLOCK_SIZE, - &ioreq->v, ioreq->v.size / BLOCK_SIZE, - qemu_aio_complete, ioreq); + blk_aio_writev(blkdev->blk, ioreq->start / BLOCK_SIZE, + &ioreq->v, ioreq->v.size / BLOCK_SIZE, + qemu_aio_complete, ioreq); break; case BLKIF_OP_DISCARD: { struct blkif_request_discard *discard_req = (void *)&ioreq->req; ioreq->aio_inflight++; - bdrv_aio_discard(blkdev->bs, + blk_aio_discard(blkdev->blk, discard_req->sector_number, discard_req->nr_sectors, qemu_aio_complete, ioreq); break; @@ -854,44 +855,49 @@ static int blk_connect(struct XenDevice *xendev) blkdev->dinfo = drive_get(IF_XEN, 0, index); if (!blkdev->dinfo) { Error *local_err = NULL; + BlockBackend *blk; BlockDriver *drv; + BlockDriverState *bs; /* setup via xenbus -> create new block driver instance */ xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n"); - blkdev->bs = bdrv_new(blkdev->dev, NULL); - if (!blkdev->bs) { + blk = blk_new_with_bs(blkdev->dev, NULL); + if (!blk) { return -1; } + blkdev->blk = blk; + bs = blk_bs(blk); drv = bdrv_find_whitelisted_format(blkdev->fileproto, readonly); - if (bdrv_open(&blkdev->bs, blkdev->filename, NULL, NULL, qflags, + if (bdrv_open(&bs, blkdev->filename, NULL, NULL, qflags, drv, &local_err) != 0) { xen_be_printf(&blkdev->xendev, 0, "error: %s\n", error_get_pretty(local_err)); error_free(local_err); - bdrv_unref(blkdev->bs); - blkdev->bs = NULL; + blk_unref(blk); + blkdev->blk = NULL; return -1; } + assert(bs == blk_bs(blk)); } else { /* setup via qemu cmdline -> already setup for us */ xen_be_printf(&blkdev->xendev, 2, "get configured bdrv (cmdline setup)\n"); - blkdev->bs = blkdev->dinfo->bdrv; - if (bdrv_is_read_only(blkdev->bs) && !readonly) { + blkdev->blk = blk_by_legacy_dinfo(blkdev->dinfo); + if (blk_is_read_only(blkdev->blk) && !readonly) { xen_be_printf(&blkdev->xendev, 0, "Unexpected read-only drive"); - blkdev->bs = NULL; + blkdev->blk = NULL; return -1; } - /* blkdev->bs is not create by us, we get a reference - * so we can bdrv_unref() unconditionally */ - bdrv_ref(blkdev->bs); + /* blkdev->blk is not create by us, we get a reference + * so we can blk_unref() unconditionally */ + blk_ref(blkdev->blk); } - bdrv_attach_dev_nofail(blkdev->bs, blkdev); - blkdev->file_size = bdrv_getlength(blkdev->bs); + blk_attach_dev_nofail(blkdev->blk, blkdev); + blkdev->file_size = blk_getlength(blkdev->blk); if (blkdev->file_size < 0) { - xen_be_printf(&blkdev->xendev, 1, "bdrv_getlength: %d (%s) | drv %s\n", + xen_be_printf(&blkdev->xendev, 1, "blk_getlength: %d (%s) | drv %s\n", (int)blkdev->file_size, strerror(-blkdev->file_size), - bdrv_get_format_name(blkdev->bs) ?: "-"); + bdrv_get_format_name(blk_bs(blkdev->blk)) ?: "-"); blkdev->file_size = 0; } @@ -982,10 +988,10 @@ static void blk_disconnect(struct XenDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); - if (blkdev->bs) { - bdrv_detach_dev(blkdev->bs, blkdev); - bdrv_unref(blkdev->bs); - blkdev->bs = NULL; + if (blkdev->blk) { + blk_detach_dev(blkdev->blk, blkdev); + blk_unref(blkdev->blk); + blkdev->blk = NULL; } xen_be_unbind_evtchn(&blkdev->xendev); @@ -1001,7 +1007,7 @@ static int blk_free(struct XenDevice *xendev) struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); struct ioreq *ioreq; - if (blkdev->bs || blkdev->sring) { + if (blkdev->blk || blkdev->sring) { blk_disconnect(xendev); } diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index f2bd954..65901ef 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -13,6 +13,7 @@ #include "net/net.h" #include "hw/qdev.h" #include "qapi/qmp/qerror.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/block/block.h" #include "net/hub.h" @@ -68,16 +69,16 @@ static void set_pointer(Object *obj, Visitor *v, Property *prop, static int parse_drive(DeviceState *dev, const char *str, void **ptr) { - BlockDriverState *bs; + BlockBackend *blk; - bs = bdrv_find(str); - if (bs == NULL) { + blk = blk_by_name(str); + if (!blk) { return -ENOENT; } - if (bdrv_attach_dev(bs, dev) < 0) { + if (blk_attach_dev(blk, dev) < 0) { return -EEXIST; } - *ptr = bs; + *ptr = blk; return 0; } @@ -85,17 +86,17 @@ static void release_drive(Object *obj, const char *name, void *opaque) { DeviceState *dev = DEVICE(obj); Property *prop = opaque; - BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop); + BlockBackend **ptr = qdev_get_prop_ptr(dev, prop); if (*ptr) { - bdrv_detach_dev(*ptr, dev); + blk_detach_dev(*ptr, dev); blockdev_auto_del(*ptr); } } static char *print_drive(void *ptr) { - return g_strdup(bdrv_get_device_name(ptr)); + return g_strdup(blk_name(ptr)); } static void get_drive(Object *obj, Visitor *v, void *opaque, @@ -335,12 +336,11 @@ PropertyInfo qdev_prop_vlan = { }; int qdev_prop_set_drive(DeviceState *dev, const char *name, - BlockDriverState *value) + BlockBackend *value) { Error *err = NULL; - const char *bdrv_name = value ? bdrv_get_device_name(value) : ""; - object_property_set_str(OBJECT(dev), bdrv_name, - name, &err); + object_property_set_str(OBJECT(dev), + value ? blk_name(value) : "", name, &err); if (err) { qerror_report_err(err); error_free(err); @@ -350,7 +350,7 @@ int qdev_prop_set_drive(DeviceState *dev, const char *name, } void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, - BlockDriverState *value) + BlockBackend *value) { if (qdev_prop_set_drive(dev, name, value) < 0) { exit(1); diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 2ed995f..2e47f70 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -1,7 +1,7 @@ #include "net/net.h" #include "hw/qdev.h" #include "qapi/qmp/qerror.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/block/block.h" #include "net/hub.h" #include "qapi/visitor.h" diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c index 2fb3aa8..0479196 100644 --- a/hw/cris/axis_dev88.c +++ b/hw/cris/axis_dev88.c @@ -30,7 +30,7 @@ #include "hw/loader.h" #include "elf.h" #include "boot.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #include "sysemu/qtest.h" @@ -284,7 +284,7 @@ void axisdev88_init(MachineState *machine) /* Attach a NAND flash to CS1. */ nand = drive_get(IF_MTD, 0, 0); - nand_state.nand = nand_init(nand ? nand->bdrv : NULL, + nand_state.nand = nand_init(nand ? blk_by_legacy_dinfo(nand) : NULL, NAND_MFR_STMICRO, 0x39); memory_region_init_io(&nand_state.iomem, NULL, &nand_ops, &nand_state, "nand", 0x05000000); diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 93b3518..b540dd6 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1591,6 +1591,11 @@ async_common: qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: invalid area (%ux%u)x(%ux%u)\n", update.left, update.top, update.right, update.bottom); + if (update.left == update.right || update.top == update.bottom) { + /* old drivers may provide empty area, keep going */ + qxl_clear_guest_bug(d); + goto cancel_async; + } break; } if (async == QXL_ASYNC) { diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c index c19c055..4306adc 100644 --- a/hw/display/tc6393xb.c +++ b/hw/display/tc6393xb.c @@ -15,6 +15,7 @@ #include "hw/block/flash.h" #include "ui/console.h" #include "ui/pixel_ops.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #define IRQ_TC6393_NAND 0 @@ -576,7 +577,8 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq) s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS); nand = drive_get(IF_MTD, 0, 0); - s->flash = nand_init(nand ? nand->bdrv : NULL, NAND_MFR_TOSHIBA, 0x76); + s->flash = nand_init(nand ? blk_by_legacy_dinfo(nand) : NULL, + NAND_MFR_TOSHIBA, 0x76); memory_region_init_io(&s->iomem, NULL, &tc6393xb_ops, s, "tc6393xb", 0x10000); memory_region_add_subregion(sysmem, base, &s->iomem); diff --git a/hw/i386/pc.c b/hw/i386/pc.c index d045e8b..61aba9f 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -44,7 +44,7 @@ #include "sysemu/kvm.h" #include "kvm_i386.h" #include "hw/xen/xen.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/block/block.h" #include "ui/qemu-spice.h" #include "exec/memory.h" diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 4384633..91a20cb 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -41,7 +41,7 @@ #include "hw/sysbus.h" #include "hw/cpu/icc_bus.h" #include "sysemu/arch_init.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/i2c/smbus.h" #include "hw/xen/xen.h" #include "exec/memory.h" diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index bb0dc8e..e225c6d 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -254,7 +254,7 @@ static void pc_q35_init(MachineState *machine) true, "ich9-ahci"); idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0"); idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1"); - g_assert_cmpint(MAX_SATA_PORTS, ==, ICH_AHCI(ahci)->ahci.ports); + g_assert(MAX_SATA_PORTS == ICH_AHCI(ahci)->ahci.ports); ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports); ahci_ide_create_devs(ahci, hd); diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index bbe367a..75913c5 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "qemu/error-report.h" #include "hw/sysbus.h" #include "hw/hw.h" @@ -103,7 +103,7 @@ static void pc_system_flash_init(MemoryRegion *rom_memory) { int unit; DriveInfo *pflash_drv; - BlockDriverState *bdrv; + BlockBackend *blk; int64_t size; char *fatal_errmsg = NULL; hwaddr phys_addr = 0x100000000ULL; @@ -119,8 +119,8 @@ static void pc_system_flash_init(MemoryRegion *rom_memory) (unit < FLASH_MAP_UNIT_MAX && (pflash_drv = drive_get(IF_PFLASH, 0, unit)) != NULL); ++unit) { - bdrv = pflash_drv->bdrv; - size = bdrv_getlength(bdrv); + blk = blk_by_legacy_dinfo(pflash_drv); + size = blk_getlength(blk); if (size < 0) { fatal_errmsg = g_strdup_printf("failed to get backing file size"); } else if (size == 0) { @@ -156,7 +156,7 @@ static void pc_system_flash_init(MemoryRegion *rom_memory) /* pflash_cfi01_register() creates a deep copy of the name */ snprintf(name, sizeof name, "system.flash%d", unit); system_flash = pflash_cfi01_register(phys_addr, NULL /* qdev */, name, - size, bdrv, sector_size, + size, blk, sector_size, size >> sector_bits, 1 /* width */, 0x0000 /* id0 */, diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c index 8bb18b4..28b324a 100644 --- a/hw/i386/xen/xen_platform.c +++ b/hw/i386/xen/xen_platform.c @@ -34,6 +34,7 @@ #include "hw/xen/xen_backend.h" #include "trace.h" #include "exec/address-spaces.h" +#include "sysemu/block-backend.h" #include <xenguest.h> @@ -132,8 +133,8 @@ static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t v devices, and bit 2 the non-primary-master IDE devices. */ if (val & UNPLUG_ALL_IDE_DISKS) { DPRINTF("unplug disks\n"); - bdrv_drain_all(); - bdrv_flush_all(); + blk_drain_all(); + blk_flush_all(); pci_unplug_disks(pci_dev->bus); } if (val & UNPLUG_ALL_NICS) { diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 063730e..70958e3 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -28,6 +28,7 @@ #include <hw/sysbus.h> #include "monitor/monitor.h" +#include "sysemu/block-backend.h" #include "sysemu/dma.h" #include "internal.h" #include <hw/ide/pci.h> @@ -84,7 +85,7 @@ static uint32_t ahci_port_read(AHCIState *s, int port, int offset) val = pr->sig; break; case PORT_SCR_STAT: - if (s->dev[port].port.ifs[0].bs) { + if (s->dev[port].port.ifs[0].blk) { val = SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP | SATA_SCR_SSTATUS_SPD_GEN1 | SATA_SCR_SSTATUS_IPM_ACTIVE; } else { @@ -501,7 +502,7 @@ static void ahci_reset_port(AHCIState *s, int port) d->init_d2h_sent = false; ide_state = &s->dev[port].port.ifs[0]; - if (!ide_state->bs) { + if (!ide_state->blk) { return; } @@ -513,11 +514,11 @@ static void ahci_reset_port(AHCIState *s, int port) } if (ncq_tfs->aiocb) { - bdrv_aio_cancel(ncq_tfs->aiocb); + blk_aio_cancel(ncq_tfs->aiocb); ncq_tfs->aiocb = NULL; } - /* Maybe we just finished the request thanks to bdrv_aio_cancel() */ + /* Maybe we just finished the request thanks to blk_aio_cancel() */ if (!ncq_tfs->used) { continue; } @@ -527,7 +528,7 @@ static void ahci_reset_port(AHCIState *s, int port) } s->dev[port].port_state = STATE_RUN; - if (!ide_state->bs) { + if (!ide_state->blk) { pr->sig = 0; ide_state->status = SEEK_STAT | WRERR_STAT; } else if (ide_state->drive_kind == IDE_CD) { @@ -826,7 +827,7 @@ static void ncq_cb(void *opaque, int ret) DPRINTF(ncq_tfs->drive->port_no, "NCQ transfer tag %d finished\n", ncq_tfs->tag); - block_acct_done(bdrv_get_stats(ncq_tfs->drive->port.ifs[0].bs), + block_acct_done(blk_get_stats(ncq_tfs->drive->port.ifs[0].blk), &ncq_tfs->acct); qemu_sglist_destroy(&ncq_tfs->sglist); ncq_tfs->used = 0; @@ -877,11 +878,11 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, DPRINTF(port, "tag %d aio read %"PRId64"\n", ncq_tfs->tag, ncq_tfs->lba); - dma_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct, + dma_acct_start(ncq_tfs->drive->port.ifs[0].blk, &ncq_tfs->acct, &ncq_tfs->sglist, BLOCK_ACCT_READ); - ncq_tfs->aiocb = dma_bdrv_read(ncq_tfs->drive->port.ifs[0].bs, - &ncq_tfs->sglist, ncq_tfs->lba, - ncq_cb, ncq_tfs); + ncq_tfs->aiocb = dma_blk_read(ncq_tfs->drive->port.ifs[0].blk, + &ncq_tfs->sglist, ncq_tfs->lba, + ncq_cb, ncq_tfs); break; case WRITE_FPDMA_QUEUED: DPRINTF(port, "NCQ writing %d sectors to LBA %"PRId64", tag %d\n", @@ -890,11 +891,11 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, DPRINTF(port, "tag %d aio write %"PRId64"\n", ncq_tfs->tag, ncq_tfs->lba); - dma_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct, + dma_acct_start(ncq_tfs->drive->port.ifs[0].blk, &ncq_tfs->acct, &ncq_tfs->sglist, BLOCK_ACCT_WRITE); - ncq_tfs->aiocb = dma_bdrv_write(ncq_tfs->drive->port.ifs[0].bs, - &ncq_tfs->sglist, ncq_tfs->lba, - ncq_cb, ncq_tfs); + ncq_tfs->aiocb = dma_blk_write(ncq_tfs->drive->port.ifs[0].blk, + &ncq_tfs->sglist, ncq_tfs->lba, + ncq_cb, ncq_tfs); break; default: DPRINTF(port, "error: tried to process non-NCQ command as NCQ\n"); @@ -943,7 +944,7 @@ static int handle_cmd(AHCIState *s, int port, int slot) /* The device we are working for */ ide_state = &s->dev[port].port.ifs[0]; - if (!ide_state->bs) { + if (!ide_state->blk) { DPRINTF(port, "error: guest accessed unused port"); goto out; } @@ -1122,7 +1123,7 @@ out: } static void ahci_start_dma(IDEDMA *dma, IDEState *s, - BlockDriverCompletionFunc *dma_cb) + BlockCompletionFunc *dma_cb) { #ifdef DEBUG_AHCI AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h index e223258..e8ea34a 100644 --- a/hw/ide/ahci.h +++ b/hw/ide/ahci.h @@ -241,7 +241,7 @@ typedef struct AHCIDevice AHCIDevice; typedef struct NCQTransferState { AHCIDevice *drive; - BlockDriverAIOCB *aiocb; + BlockAIOCB *aiocb; QEMUSGList sglist; BlockAcctCookie acct; uint16_t sector_count; diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index 10218df..c63b7e5 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -25,6 +25,7 @@ #include "hw/ide/internal.h" #include "hw/scsi/scsi.h" +#include "sysemu/block-backend.h" static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret); @@ -110,16 +111,16 @@ static int cd_read_sector(IDEState *s, int lba, uint8_t *buf, int sector_size) switch(sector_size) { case 2048: - block_acct_start(bdrv_get_stats(s->bs), &s->acct, + block_acct_start(blk_get_stats(s->blk), &s->acct, 4 * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ); - ret = bdrv_read(s->bs, (int64_t)lba << 2, buf, 4); - block_acct_done(bdrv_get_stats(s->bs), &s->acct); + ret = blk_read(s->blk, (int64_t)lba << 2, buf, 4); + block_acct_done(blk_get_stats(s->blk), &s->acct); break; case 2352: - block_acct_start(bdrv_get_stats(s->bs), &s->acct, + block_acct_start(blk_get_stats(s->blk), &s->acct, 4 * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ); - ret = bdrv_read(s->bs, (int64_t)lba << 2, buf + 16, 4); - block_acct_done(bdrv_get_stats(s->bs), &s->acct); + ret = blk_read(s->blk, (int64_t)lba << 2, buf + 16, 4); + block_acct_done(blk_get_stats(s->blk), &s->acct); if (ret < 0) return ret; cd_data_to_raw(buf, lba); @@ -254,7 +255,7 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) s->io_buffer_index = 0; if (s->atapi_dma) { - block_acct_start(bdrv_get_stats(s->bs), &s->acct, size, + block_acct_start(blk_get_stats(s->blk), &s->acct, size, BLOCK_ACCT_READ); s->status = READY_STAT | SEEK_STAT | DRQ_STAT; ide_start_dma(s, ide_atapi_cmd_read_dma_cb); @@ -350,13 +351,13 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) s->bus->dma->iov.iov_len = n * 4 * 512; qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1); - s->bus->dma->aiocb = bdrv_aio_readv(s->bs, (int64_t)s->lba << 2, + s->bus->dma->aiocb = blk_aio_readv(s->blk, (int64_t)s->lba << 2, &s->bus->dma->qiov, n * 4, ide_atapi_cmd_read_dma_cb, s); return; eot: - block_acct_done(bdrv_get_stats(s->bs), &s->acct); + block_acct_done(blk_get_stats(s->blk), &s->acct); ide_set_inactive(s, false); } @@ -371,7 +372,7 @@ static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors, s->io_buffer_size = 0; s->cd_sector_size = sector_size; - block_acct_start(bdrv_get_stats(s->bs), &s->acct, s->packet_transfer_size, + block_acct_start(blk_get_stats(s->blk), &s->acct, s->packet_transfer_size, BLOCK_ACCT_READ); /* XXX: check if BUSY_STAT should be set */ @@ -504,7 +505,7 @@ static unsigned int event_status_media(IDEState *s, media_status = 0; if (s->tray_open) { media_status = MS_TRAY_OPEN; - } else if (bdrv_is_inserted(s->bs)) { + } else if (blk_is_inserted(s->blk)) { media_status = MS_MEDIA_PRESENT; } @@ -800,7 +801,7 @@ static void cmd_test_unit_ready(IDEState *s, uint8_t *buf) static void cmd_prevent_allow_medium_removal(IDEState *s, uint8_t* buf) { s->tray_locked = buf[4] & 1; - bdrv_lock_medium(s->bs, buf[4] & 1); + blk_lock_medium(s->blk, buf[4] & 1); ide_atapi_cmd_ok(s); } @@ -884,14 +885,14 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf) if (loej) { if (!start && !s->tray_open && s->tray_locked) { - sense = bdrv_is_inserted(s->bs) + sense = blk_is_inserted(s->blk) ? NOT_READY : ILLEGAL_REQUEST; ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED); return; } if (s->tray_open != !start) { - bdrv_eject(s->bs, !start); + blk_eject(s->blk, !start); s->tray_open = !start; } } @@ -1125,7 +1126,7 @@ void ide_atapi_cmd(IDEState *s) * states rely on this behavior. */ if (!(atapi_cmd_table[s->io_buffer[0]].flags & ALLOW_UA) && - !s->tray_open && bdrv_is_inserted(s->bs) && s->cdrom_changed) { + !s->tray_open && blk_is_inserted(s->blk) && s->cdrom_changed) { if (s->cdrom_changed == 1) { ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT); @@ -1140,7 +1141,7 @@ void ide_atapi_cmd(IDEState *s) /* Report a Not Ready condition if appropriate for the command */ if ((atapi_cmd_table[s->io_buffer[0]].flags & CHECK_READY) && - (!media_present(s) || !bdrv_is_inserted(s->bs))) + (!media_present(s) || !blk_is_inserted(s->blk))) { ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT); return; diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 91048f2..c8b0322 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -26,7 +26,7 @@ #include <hw/i386/pc.h> #include <hw/pci/pci.h> #include <hw/isa/isa.h> -#include "block/block.h" +#include "sysemu/block-backend.h" #include "sysemu/sysemu.h" #include "sysemu/dma.h" diff --git a/hw/ide/core.c b/hw/ide/core.c index ae85428..44e3d50 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -31,7 +31,7 @@ #include "sysemu/sysemu.h" #include "sysemu/dma.h" #include "hw/block/block.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include <hw/ide/internal.h> @@ -158,10 +158,11 @@ static void ide_identify(IDEState *s) put_le16(p + 84, (1 << 14) | 0); } /* 14 = NOP supported, 5=WCACHE enabled, 0=SMART feature set enabled */ - if (bdrv_enable_write_cache(s->bs)) - put_le16(p + 85, (1 << 14) | (1 << 5) | 1); - else - put_le16(p + 85, (1 << 14) | 1); + if (blk_enable_write_cache(s->blk)) { + put_le16(p + 85, (1 << 14) | (1 << 5) | 1); + } else { + put_le16(p + 85, (1 << 14) | 1); + } /* 13=flush_cache_ext,12=flush_cache,10=lba48 */ put_le16(p + 86, (1 << 13) | (1 <<12) | (1 << 10)); /* 14=set to 1, 8=has WWN, 1=SMART self test, 0=SMART error logging */ @@ -350,7 +351,7 @@ static void ide_set_signature(IDEState *s) if (s->drive_kind == IDE_CD) { s->lcyl = 0x14; s->hcyl = 0xeb; - } else if (s->bs) { + } else if (s->blk) { s->lcyl = 0; s->hcyl = 0; } else { @@ -360,15 +361,16 @@ static void ide_set_signature(IDEState *s) } typedef struct TrimAIOCB { - BlockDriverAIOCB common; + BlockAIOCB common; + BlockBackend *blk; QEMUBH *bh; int ret; QEMUIOVector *qiov; - BlockDriverAIOCB *aiocb; + BlockAIOCB *aiocb; int i, j; } TrimAIOCB; -static void trim_aio_cancel(BlockDriverAIOCB *acb) +static void trim_aio_cancel(BlockAIOCB *acb) { TrimAIOCB *iocb = container_of(acb, TrimAIOCB, common); @@ -379,7 +381,7 @@ static void trim_aio_cancel(BlockDriverAIOCB *acb) iocb->ret = -ECANCELED; if (iocb->aiocb) { - bdrv_aio_cancel_async(iocb->aiocb); + blk_aio_cancel_async(iocb->aiocb); iocb->aiocb = NULL; } } @@ -420,8 +422,8 @@ static void ide_issue_trim_cb(void *opaque, int ret) } /* Got an entry! Submit and exit. */ - iocb->aiocb = bdrv_aio_discard(iocb->common.bs, sector, count, - ide_issue_trim_cb, opaque); + iocb->aiocb = blk_aio_discard(iocb->blk, sector, count, + ide_issue_trim_cb, opaque); return; } @@ -438,13 +440,14 @@ static void ide_issue_trim_cb(void *opaque, int ret) } } -BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs, +BlockAIOCB *ide_issue_trim(BlockBackend *blk, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { TrimAIOCB *iocb; - iocb = qemu_aio_get(&trim_aiocb_info, bs, cb, opaque); + iocb = blk_aio_get(&trim_aiocb_info, blk, cb, opaque); + iocb->blk = blk; iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb); iocb->ret = 0; iocb->qiov = qiov; @@ -551,7 +554,7 @@ static bool ide_sect_range_ok(IDEState *s, { uint64_t total_sectors; - bdrv_get_geometry(s->bs, &total_sectors); + blk_get_geometry(s->blk, &total_sectors); if (sector > total_sectors || nb_sectors > total_sectors - sector) { return false; } @@ -569,7 +572,7 @@ static void ide_sector_read_cb(void *opaque, int ret) if (ret == -ECANCELED) { return; } - block_acct_done(bdrv_get_stats(s->bs), &s->acct); + block_acct_done(blk_get_stats(s->blk), &s->acct); if (ret != 0) { if (ide_handle_rw_error(s, -ret, IDE_RETRY_PIO | IDE_RETRY_READ)) { @@ -625,10 +628,10 @@ void ide_sector_read(IDEState *s) s->iov.iov_len = n * BDRV_SECTOR_SIZE; qemu_iovec_init_external(&s->qiov, &s->iov, 1); - block_acct_start(bdrv_get_stats(s->bs), &s->acct, + block_acct_start(blk_get_stats(s->blk), &s->acct, n * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ); - s->pio_aiocb = bdrv_aio_readv(s->bs, sector_num, &s->qiov, n, - ide_sector_read_cb, s); + s->pio_aiocb = blk_aio_readv(s->blk, sector_num, &s->qiov, n, + ide_sector_read_cb, s); } static void dma_buf_commit(IDEState *s) @@ -655,7 +658,7 @@ void ide_dma_error(IDEState *s) static int ide_handle_rw_error(IDEState *s, int error, int op) { bool is_read = (op & IDE_RETRY_READ) != 0; - BlockErrorAction action = bdrv_get_error_action(s->bs, is_read, error); + BlockErrorAction action = blk_get_error_action(s->blk, is_read, error); if (action == BLOCK_ERROR_ACTION_STOP) { s->bus->dma->ops->set_unit(s->bus->dma, s->unit); @@ -668,7 +671,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op) ide_rw_error(s); } } - bdrv_error_action(s->bs, action, is_read, error); + blk_error_action(s->blk, action, is_read, error); return action != BLOCK_ERROR_ACTION_IGNORE; } @@ -744,24 +747,24 @@ void ide_dma_cb(void *opaque, int ret) switch (s->dma_cmd) { case IDE_DMA_READ: - s->bus->dma->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num, - ide_dma_cb, s); + s->bus->dma->aiocb = dma_blk_read(s->blk, &s->sg, sector_num, + ide_dma_cb, s); break; case IDE_DMA_WRITE: - s->bus->dma->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num, - ide_dma_cb, s); + s->bus->dma->aiocb = dma_blk_write(s->blk, &s->sg, sector_num, + ide_dma_cb, s); break; case IDE_DMA_TRIM: - s->bus->dma->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num, - ide_issue_trim, ide_dma_cb, s, - DMA_DIRECTION_TO_DEVICE); + s->bus->dma->aiocb = dma_blk_io(s->blk, &s->sg, sector_num, + ide_issue_trim, ide_dma_cb, s, + DMA_DIRECTION_TO_DEVICE); break; } return; eot: if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { - block_acct_done(bdrv_get_stats(s->bs), &s->acct); + block_acct_done(blk_get_stats(s->blk), &s->acct); } ide_set_inactive(s, stay_active); } @@ -775,11 +778,11 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd) switch (dma_cmd) { case IDE_DMA_READ: - block_acct_start(bdrv_get_stats(s->bs), &s->acct, + block_acct_start(blk_get_stats(s->blk), &s->acct, s->nsector * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ); break; case IDE_DMA_WRITE: - block_acct_start(bdrv_get_stats(s->bs), &s->acct, + block_acct_start(blk_get_stats(s->blk), &s->acct, s->nsector * BDRV_SECTOR_SIZE, BLOCK_ACCT_WRITE); break; default: @@ -789,7 +792,7 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd) ide_start_dma(s, ide_dma_cb); } -void ide_start_dma(IDEState *s, BlockDriverCompletionFunc *cb) +void ide_start_dma(IDEState *s, BlockCompletionFunc *cb) { if (s->bus->dma->ops->start_dma) { s->bus->dma->ops->start_dma(s->bus->dma, s, cb); @@ -810,7 +813,7 @@ static void ide_sector_write_cb(void *opaque, int ret) if (ret == -ECANCELED) { return; } - block_acct_done(bdrv_get_stats(s->bs), &s->acct); + block_acct_done(blk_get_stats(s->blk), &s->acct); s->pio_aiocb = NULL; s->status &= ~BUSY_STAT; @@ -877,10 +880,10 @@ void ide_sector_write(IDEState *s) s->iov.iov_len = n * BDRV_SECTOR_SIZE; qemu_iovec_init_external(&s->qiov, &s->iov, 1); - block_acct_start(bdrv_get_stats(s->bs), &s->acct, + block_acct_start(blk_get_stats(s->blk), &s->acct, n * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ); - s->pio_aiocb = bdrv_aio_writev(s->bs, sector_num, &s->qiov, n, - ide_sector_write_cb, s); + s->pio_aiocb = blk_aio_writev(s->blk, sector_num, &s->qiov, n, + ide_sector_write_cb, s); } static void ide_flush_cb(void *opaque, int ret) @@ -899,8 +902,8 @@ static void ide_flush_cb(void *opaque, int ret) } } - if (s->bs) { - block_acct_done(bdrv_get_stats(s->bs), &s->acct); + if (s->blk) { + block_acct_done(blk_get_stats(s->blk), &s->acct); } s->status = READY_STAT | SEEK_STAT; ide_cmd_done(s); @@ -909,14 +912,14 @@ static void ide_flush_cb(void *opaque, int ret) void ide_flush_cache(IDEState *s) { - if (s->bs == NULL) { + if (s->blk == NULL) { ide_flush_cb(s, 0); return; } s->status |= BUSY_STAT; - block_acct_start(bdrv_get_stats(s->bs), &s->acct, 0, BLOCK_ACCT_FLUSH); - s->pio_aiocb = bdrv_aio_flush(s->bs, ide_flush_cb, s); + block_acct_start(blk_get_stats(s->blk), &s->acct, 0, BLOCK_ACCT_FLUSH); + s->pio_aiocb = blk_aio_flush(s->blk, ide_flush_cb, s); } static void ide_cfata_metadata_inquiry(IDEState *s) @@ -979,7 +982,7 @@ static void ide_cd_change_cb(void *opaque, bool load) uint64_t nb_sectors; s->tray_open = !load; - bdrv_get_geometry(s->bs, &nb_sectors); + blk_get_geometry(s->blk, &nb_sectors); s->nb_sectors = nb_sectors; /* @@ -1113,7 +1116,7 @@ static bool cmd_data_set_management(IDEState *s, uint8_t cmd) { switch (s->feature) { case DSM_TRIM: - if (s->bs) { + if (s->blk) { ide_sector_start_dma(s, IDE_DMA_TRIM); return false; } @@ -1126,7 +1129,7 @@ static bool cmd_data_set_management(IDEState *s, uint8_t cmd) static bool cmd_identify(IDEState *s, uint8_t cmd) { - if (s->bs && s->drive_kind != IDE_CD) { + if (s->blk && s->drive_kind != IDE_CD) { if (s->drive_kind != IDE_CFATA) { ide_identify(s); } else { @@ -1176,7 +1179,7 @@ static bool cmd_read_multiple(IDEState *s, uint8_t cmd) { bool lba48 = (cmd == WIN_MULTREAD_EXT); - if (!s->bs || !s->mult_sectors) { + if (!s->blk || !s->mult_sectors) { ide_abort_command(s); return true; } @@ -1192,7 +1195,7 @@ static bool cmd_write_multiple(IDEState *s, uint8_t cmd) bool lba48 = (cmd == WIN_MULTWRITE_EXT); int n; - if (!s->bs || !s->mult_sectors) { + if (!s->blk || !s->mult_sectors) { ide_abort_command(s); return true; } @@ -1220,7 +1223,7 @@ static bool cmd_read_pio(IDEState *s, uint8_t cmd) return true; } - if (!s->bs) { + if (!s->blk) { ide_abort_command(s); return true; } @@ -1236,7 +1239,7 @@ static bool cmd_write_pio(IDEState *s, uint8_t cmd) { bool lba48 = (cmd == WIN_WRITE_EXT); - if (!s->bs) { + if (!s->blk) { ide_abort_command(s); return true; } @@ -1256,7 +1259,7 @@ static bool cmd_read_dma(IDEState *s, uint8_t cmd) { bool lba48 = (cmd == WIN_READDMA_EXT); - if (!s->bs) { + if (!s->blk) { ide_abort_command(s); return true; } @@ -1271,7 +1274,7 @@ static bool cmd_write_dma(IDEState *s, uint8_t cmd) { bool lba48 = (cmd == WIN_WRITEDMA_EXT); - if (!s->bs) { + if (!s->blk) { ide_abort_command(s); return true; } @@ -1322,7 +1325,7 @@ static bool cmd_set_features(IDEState *s, uint8_t cmd) { uint16_t *identify_data; - if (!s->bs) { + if (!s->blk) { ide_abort_command(s); return true; } @@ -1330,12 +1333,12 @@ static bool cmd_set_features(IDEState *s, uint8_t cmd) /* XXX: valid for CDROM ? */ switch (s->feature) { case 0x02: /* write cache enable */ - bdrv_set_enable_write_cache(s->bs, true); + blk_set_enable_write_cache(s->blk, true); identify_data = (uint16_t *)s->identify_data; put_le16(identify_data + 85, (1 << 14) | (1 << 5) | 1); return true; case 0x82: /* write cache disable */ - bdrv_set_enable_write_cache(s->bs, false); + blk_set_enable_write_cache(s->blk, false); identify_data = (uint16_t *)s->identify_data; put_le16(identify_data + 85, (1 << 14) | 1); ide_flush_cache(s); @@ -1802,8 +1805,9 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) #endif s = idebus_active_if(bus); /* ignore commands to non existent slave */ - if (s != bus->ifs && !s->bs) + if (s != bus->ifs && !s->blk) { return; + } /* Only DEVICE RESET is allowed while BSY or/and DRQ are set */ if ((s->status & (BUSY_STAT|DRQ_STAT)) && val != WIN_DEVICE_RESET) @@ -1848,59 +1852,66 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1) ret = 0xff; break; case 1: - if ((!bus->ifs[0].bs && !bus->ifs[1].bs) || - (s != bus->ifs && !s->bs)) + if ((!bus->ifs[0].blk && !bus->ifs[1].blk) || + (s != bus->ifs && !s->blk)) { ret = 0; - else if (!hob) + } else if (!hob) { ret = s->error; - else + } else { ret = s->hob_feature; + } break; case 2: - if (!bus->ifs[0].bs && !bus->ifs[1].bs) + if (!bus->ifs[0].blk && !bus->ifs[1].blk) { ret = 0; - else if (!hob) + } else if (!hob) { ret = s->nsector & 0xff; - else + } else { ret = s->hob_nsector; + } break; case 3: - if (!bus->ifs[0].bs && !bus->ifs[1].bs) + if (!bus->ifs[0].blk && !bus->ifs[1].blk) { ret = 0; - else if (!hob) + } else if (!hob) { ret = s->sector; - else + } else { ret = s->hob_sector; + } break; case 4: - if (!bus->ifs[0].bs && !bus->ifs[1].bs) + if (!bus->ifs[0].blk && !bus->ifs[1].blk) { ret = 0; - else if (!hob) + } else if (!hob) { ret = s->lcyl; - else + } else { ret = s->hob_lcyl; + } break; case 5: - if (!bus->ifs[0].bs && !bus->ifs[1].bs) + if (!bus->ifs[0].blk && !bus->ifs[1].blk) { ret = 0; - else if (!hob) + } else if (!hob) { ret = s->hcyl; - else + } else { ret = s->hob_hcyl; + } break; case 6: - if (!bus->ifs[0].bs && !bus->ifs[1].bs) + if (!bus->ifs[0].blk && !bus->ifs[1].blk) { ret = 0; - else + } else { ret = s->select; + } break; default: case 7: - if ((!bus->ifs[0].bs && !bus->ifs[1].bs) || - (s != bus->ifs && !s->bs)) + if ((!bus->ifs[0].blk && !bus->ifs[1].blk) || + (s != bus->ifs && !s->blk)) { ret = 0; - else + } else { ret = s->status; + } qemu_irq_lower(bus->irq); break; } @@ -1916,11 +1927,12 @@ uint32_t ide_status_read(void *opaque, uint32_t addr) IDEState *s = idebus_active_if(bus); int ret; - if ((!bus->ifs[0].bs && !bus->ifs[1].bs) || - (s != bus->ifs && !s->bs)) + if ((!bus->ifs[0].blk && !bus->ifs[1].blk) || + (s != bus->ifs && !s->blk)) { ret = 0; - else + } else { ret = s->status; + } #ifdef DEBUG_IDE printf("ide: read status addr=0x%x val=%02x\n", addr, ret); #endif @@ -2081,7 +2093,7 @@ static void ide_reset(IDEState *s) #endif if (s->pio_aiocb) { - bdrv_aio_cancel(s->pio_aiocb); + blk_aio_cancel(s->pio_aiocb); s->pio_aiocb = NULL; } @@ -2145,7 +2157,7 @@ void ide_bus_reset(IDEBus *bus) #ifdef DEBUG_AIO printf("aio_cancel\n"); #endif - bdrv_aio_cancel(bus->dma->aiocb); + blk_aio_cancel(bus->dma->aiocb); bus->dma->aiocb = NULL; } @@ -2174,7 +2186,7 @@ static void ide_resize_cb(void *opaque) return; } - bdrv_get_geometry(s->bs, &nb_sectors); + blk_get_geometry(s->blk, &nb_sectors); s->nb_sectors = nb_sectors; /* Update the identify data buffer. */ @@ -2198,7 +2210,7 @@ static const BlockDevOps ide_hd_block_ops = { .resize_cb = ide_resize_cb, }; -int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, +int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind, const char *version, const char *serial, const char *model, uint64_t wwn, uint32_t cylinders, uint32_t heads, uint32_t secs, @@ -2206,10 +2218,10 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, { uint64_t nb_sectors; - s->bs = bs; + s->blk = blk; s->drive_kind = kind; - bdrv_get_geometry(bs, &nb_sectors); + blk_get_geometry(blk, &nb_sectors); s->cylinders = cylinders; s->heads = heads; s->sectors = secs; @@ -2223,18 +2235,18 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, s->smart_errors = 0; s->smart_selftest_count = 0; if (kind == IDE_CD) { - bdrv_set_dev_ops(bs, &ide_cd_block_ops, s); - bdrv_set_guest_block_size(bs, 2048); + blk_set_dev_ops(blk, &ide_cd_block_ops, s); + blk_set_guest_block_size(blk, 2048); } else { - if (!bdrv_is_inserted(s->bs)) { + if (!blk_is_inserted(s->blk)) { error_report("Device needs media, but drive is empty"); return -1; } - if (bdrv_is_read_only(bs)) { + if (blk_is_read_only(blk)) { error_report("Can't use a read-only drive"); return -1; } - bdrv_set_dev_ops(bs, &ide_hd_block_ops, s); + blk_set_dev_ops(blk, &ide_hd_block_ops, s); } if (serial) { pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), serial); @@ -2265,7 +2277,7 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, } ide_reset(s); - bdrv_iostatus_enable(bs); + blk_iostatus_enable(blk); return 0; } @@ -2282,7 +2294,7 @@ static void ide_init1(IDEBus *bus, int unit) s->io_buffer = qemu_memalign(2048, s->io_buffer_total_len); memset(s->io_buffer, 0, s->io_buffer_total_len); - s->smart_selftest_data = qemu_blockalign(s->bs, 512); + s->smart_selftest_data = blk_blockalign(s->blk, 512); memset(s->smart_selftest_data, 0, 512); s->sector_write_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, @@ -2377,7 +2389,7 @@ static int ide_drive_post_load(void *opaque, int version_id) IDEState *s = opaque; if (s->identify_set) { - bdrv_set_enable_write_cache(s->bs, !!(s->identify_data[85] & (1 << 5))); + blk_set_enable_write_cache(s->blk, !!(s->identify_data[85] & (1 << 5))); } return 0; } diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 8eb77a1..fb1d095 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -65,7 +65,7 @@ #include <hw/i386/pc.h> #include <hw/pci/pci.h> #include <hw/isa/isa.h> -#include "block/block.h" +#include "sysemu/block-backend.h" #include "sysemu/dma.h" #include <hw/ide/pci.h> diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 5c19f79..68ac610 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -319,7 +319,7 @@ typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind; typedef void EndTransferFunc(IDEState *); -typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockDriverCompletionFunc *); +typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockCompletionFunc *); typedef void DMAVoidFunc(IDEDMA *); typedef int DMAIntFunc(IDEDMA *, int); typedef void DMAStopFunc(IDEDMA *, bool); @@ -373,7 +373,7 @@ struct IDEState { /* set for lba48 access */ uint8_t lba48; - BlockDriverState *bs; + BlockBackend *blk; char version[9]; /* ATAPI specific */ struct unreported_events events; @@ -389,7 +389,7 @@ struct IDEState { int cd_sector_size; int atapi_dma; /* true if dma is requested for the packet cmd */ BlockAcctCookie acct; - BlockDriverAIOCB *pio_aiocb; + BlockAIOCB *pio_aiocb; struct iovec iov; QEMUIOVector qiov; /* ATA DMA state */ @@ -442,7 +442,7 @@ struct IDEDMA { const struct IDEDMAOps *ops; struct iovec iov; QEMUIOVector qiov; - BlockDriverAIOCB *aiocb; + BlockAIOCB *aiocb; }; struct IDEBus { @@ -521,7 +521,7 @@ void ide_bus_reset(IDEBus *bus); int64_t ide_get_sector(IDEState *s); void ide_set_sector(IDEState *s, int64_t sector_num); -void ide_start_dma(IDEState *s, BlockDriverCompletionFunc *cb); +void ide_start_dma(IDEState *s, BlockCompletionFunc *cb); void ide_dma_error(IDEState *s); void ide_atapi_cmd_ok(IDEState *s); @@ -537,7 +537,7 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr); void ide_data_writel(void *opaque, uint32_t addr, uint32_t val); uint32_t ide_data_readl(void *opaque, uint32_t addr); -int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, +int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind, const char *version, const char *serial, const char *model, uint64_t wwn, uint32_t cylinders, uint32_t heads, uint32_t secs, @@ -555,9 +555,9 @@ void ide_transfer_start(IDEState *s, uint8_t *buf, int size, EndTransferFunc *end_transfer_func); void ide_transfer_stop(IDEState *s); void ide_set_inactive(IDEState *s, bool more); -BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs, +BlockAIOCB *ide_issue_trim(BlockBackend *blk, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); + BlockCompletionFunc *cb, void *opaque); /* hw/ide/atapi.c */ void ide_atapi_cmd(IDEState *s); diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 4cbcb1c..b084162 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -25,7 +25,7 @@ #include <hw/hw.h> #include <hw/i386/pc.h> #include <hw/isa/isa.h> -#include "block/block.h" +#include "sysemu/block-backend.h" #include "sysemu/dma.h" #include <hw/ide/internal.h> diff --git a/hw/ide/macio.c b/hw/ide/macio.c index cefc85c..9a55407 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -25,7 +25,7 @@ #include "hw/hw.h" #include "hw/ppc/mac.h" #include "hw/ppc/mac_dbdma.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "sysemu/dma.h" #include <hw/ide/internal.h> @@ -134,7 +134,7 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) MACIO_DPRINTF("precopying unaligned %d bytes to %#" HWADDR_PRIx "\n", unaligned, io->addr + io->len - unaligned); - bdrv_read(s->bs, sector_num + nsector, io->remainder, 1); + blk_read(s->blk, sector_num + nsector, io->remainder, 1); cpu_physical_memory_write(io->addr + io->len - unaligned, io->remainder, unaligned); @@ -164,14 +164,14 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) (s->lba << 2) + (s->io_buffer_index >> 9), s->packet_transfer_size, s->dma_cmd); - m->aiocb = dma_bdrv_read(s->bs, &s->sg, - (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9), - pmac_ide_atapi_transfer_cb, io); + m->aiocb = dma_blk_read(s->blk, &s->sg, + (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9), + pmac_ide_atapi_transfer_cb, io); return; done: MACIO_DPRINTF("done DMA\n"); - block_acct_done(bdrv_get_stats(s->bs), &s->acct); + block_acct_done(blk_get_stats(s->blk), &s->acct); io->dma_end(opaque); } @@ -254,8 +254,8 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) qemu_iovec_reset(&io->iov); qemu_iovec_add(&io->iov, io->remainder, 0x200); - m->aiocb = bdrv_aio_writev(s->bs, sector_num - 1, &io->iov, 1, - pmac_ide_transfer_cb, io); + m->aiocb = blk_aio_writev(s->blk, sector_num - 1, &io->iov, 1, + pmac_ide_transfer_cb, io); } } @@ -294,8 +294,8 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) qemu_iovec_reset(&io->iov); qemu_iovec_add(&io->iov, io->remainder, 0x200); - m->aiocb = bdrv_aio_readv(s->bs, sector_num + nsector, &io->iov, 1, - pmac_ide_transfer_cb, io); + m->aiocb = blk_aio_readv(s->blk, sector_num + nsector, &io->iov, 1, + pmac_ide_transfer_cb, io); break; case IDE_DMA_WRITE: /* cache the contents in our io struct */ @@ -333,17 +333,17 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) switch (s->dma_cmd) { case IDE_DMA_READ: - m->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num, - pmac_ide_transfer_cb, io); + m->aiocb = dma_blk_read(s->blk, &s->sg, sector_num, + pmac_ide_transfer_cb, io); break; case IDE_DMA_WRITE: - m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num, - pmac_ide_transfer_cb, io); + m->aiocb = dma_blk_write(s->blk, &s->sg, sector_num, + pmac_ide_transfer_cb, io); break; case IDE_DMA_TRIM: - m->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num, - ide_issue_trim, pmac_ide_transfer_cb, io, - DMA_DIRECTION_TO_DEVICE); + m->aiocb = dma_blk_io(s->blk, &s->sg, sector_num, + ide_issue_trim, pmac_ide_transfer_cb, io, + DMA_DIRECTION_TO_DEVICE); break; } @@ -352,7 +352,7 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) done: if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { - block_acct_done(bdrv_get_stats(s->bs), &s->acct); + block_acct_done(blk_get_stats(s->blk), &s->acct); } io->dma_end(io); } @@ -370,7 +370,7 @@ static void pmac_ide_transfer(DBDMA_io *io) /* Handle non-block ATAPI DMA transfers */ if (s->lba == -1) { s->io_buffer_size = MIN(io->len, s->packet_transfer_size); - block_acct_start(bdrv_get_stats(s->bs), &s->acct, s->io_buffer_size, + block_acct_start(blk_get_stats(s->blk), &s->acct, s->io_buffer_size, BLOCK_ACCT_READ); MACIO_DPRINTF("non-block ATAPI DMA transfer size: %d\n", s->io_buffer_size); @@ -382,12 +382,12 @@ static void pmac_ide_transfer(DBDMA_io *io) m->dma_active = false; MACIO_DPRINTF("end of non-block ATAPI DMA transfer\n"); - block_acct_done(bdrv_get_stats(s->bs), &s->acct); + block_acct_done(blk_get_stats(s->blk), &s->acct); io->dma_end(io); return; } - block_acct_start(bdrv_get_stats(s->bs), &s->acct, io->len, + block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, BLOCK_ACCT_READ); pmac_ide_atapi_transfer_cb(io, 0); return; @@ -395,11 +395,11 @@ static void pmac_ide_transfer(DBDMA_io *io) switch (s->dma_cmd) { case IDE_DMA_READ: - block_acct_start(bdrv_get_stats(s->bs), &s->acct, io->len, + block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, BLOCK_ACCT_READ); break; case IDE_DMA_WRITE: - block_acct_start(bdrv_get_stats(s->bs), &s->acct, io->len, + block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, BLOCK_ACCT_WRITE); break; default: @@ -415,7 +415,7 @@ static void pmac_ide_flush(DBDMA_io *io) MACIOIDEState *m = io->opaque; if (m->aiocb) { - bdrv_drain_all(); + blk_drain_all(); } } @@ -558,7 +558,7 @@ static void ide_nop_restart(void *opaque, int x, RunState y) } static void ide_dbdma_start(IDEDMA *dma, IDEState *s, - BlockDriverCompletionFunc *cb) + BlockCompletionFunc *cb) { MACIOIDEState *m = container_of(dma, MACIOIDEState, dma); diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 15671b8..ed85185 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -25,7 +25,7 @@ #include <hw/hw.h> #include <hw/i386/pc.h> #include <hw/pcmcia.h> -#include "block/block.h" +#include "sysemu/block-backend.h" #include "sysemu/dma.h" #include <hw/ide/internal.h> @@ -247,7 +247,7 @@ static uint16_t md_common_read(PCMCIACardState *card, uint32_t at) return ide_ioport_read(&s->bus, 0x1); case 0xe: /* Alternate Status */ ifs = idebus_active_if(&s->bus); - if (ifs->bs) { + if (ifs->blk) { return ifs->status; } else { return 0; diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c index 334c8cc..b6ce62a 100644 --- a/hw/ide/mmio.c +++ b/hw/ide/mmio.c @@ -24,7 +24,7 @@ */ #include "hw/hw.h" #include "hw/sysbus.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "sysemu/dma.h" #include <hw/ide/internal.h> diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 2397f35..2dad50e 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -26,7 +26,7 @@ #include <hw/i386/pc.h> #include <hw/pci/pci.h> #include <hw/isa/isa.h> -#include "block/block.h" +#include "sysemu/block-backend.h" #include "sysemu/dma.h" #include <hw/ide/pci.h> @@ -38,7 +38,7 @@ IDE_RETRY_READ | IDE_RETRY_FLUSH) static void bmdma_start_dma(IDEDMA *dma, IDEState *s, - BlockDriverCompletionFunc *dma_cb) + BlockCompletionFunc *dma_cb) { BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); @@ -302,7 +302,7 @@ void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val) * aio operation with preadv/pwritev. */ if (bm->bus->dma->aiocb) { - bdrv_drain_all(); + blk_drain_all(); assert(bm->bus->dma->aiocb == NULL); } bm->status &= ~BM_STATUS_DMAING; diff --git a/hw/ide/pci.h b/hw/ide/pci.h index 517711f..2e9314a 100644 --- a/hw/ide/pci.h +++ b/hw/ide/pci.h @@ -23,7 +23,7 @@ typedef struct BMDMAState { uint32_t cur_prd_addr; uint32_t cur_prd_len; uint8_t unit; - BlockDriverCompletionFunc *dma_cb; + BlockCompletionFunc *dma_cb; int64_t sector_num; uint32_t nsector; MemoryRegion addr_ioport; diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 49e78a7..574b9c1 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -27,7 +27,7 @@ #include <hw/i386/pc.h> #include <hw/pci/pci.h> #include <hw/isa/isa.h> -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "sysemu/sysemu.h" #include "sysemu/dma.h" @@ -178,12 +178,13 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev) for (; i < 3; i++) { di = drive_get_by_index(IF_IDE, i); if (di != NULL && !di->media_cd) { - DeviceState *ds = bdrv_get_attached_dev(di->bdrv); + BlockBackend *blk = blk_by_legacy_dinfo(di); + DeviceState *ds = blk_get_attached_dev(blk); if (ds) { - bdrv_detach_dev(di->bdrv, ds); + blk_detach_dev(blk, ds); } - pci_ide->bus[di->bus].ifs[di->unit].bs = NULL; - drive_del(di); + pci_ide->bus[di->bus].ifs[di->unit].blk = NULL; + blk_unref(blk); } } qdev_reset_all(DEVICE(dev)); diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 9814ef0..b4f096e 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -20,6 +20,7 @@ #include "sysemu/dma.h" #include "qemu/error-report.h" #include <hw/ide/internal.h> +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/block/block.h" #include "sysemu/sysemu.h" @@ -72,7 +73,7 @@ static int ide_qdev_init(DeviceState *qdev) IDEDeviceClass *dc = IDE_DEVICE_GET_CLASS(dev); IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus); - if (!dev->conf.bs) { + if (!dev->conf.blk) { error_report("No drive specified"); goto err; } @@ -117,7 +118,7 @@ IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive) dev = qdev_create(&bus->qbus, drive->media_cd ? "ide-cd" : "ide-hd"); qdev_prop_set_uint32(dev, "unit", unit); - qdev_prop_set_drive_nofail(dev, "drive", drive->bdrv); + qdev_prop_set_drive_nofail(dev, "drive", blk_by_legacy_dinfo(drive)); qdev_init_nofail(dev); return DO_UPCAST(IDEDevice, qdev, dev); } @@ -127,7 +128,7 @@ int ide_get_geometry(BusState *bus, int unit, { IDEState *s = &DO_UPCAST(IDEBus, qbus, bus)->ifs[unit]; - if (s->drive_kind != IDE_HD || !s->bs) { + if (s->drive_kind != IDE_HD || !s->blk) { return -1; } @@ -172,7 +173,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) } } - if (ide_init_drive(s, dev->conf.bs, kind, + if (ide_init_drive(s, dev->conf.blk, kind, dev->version, dev->serial, dev->model, dev->wwn, dev->conf.cyls, dev->conf.heads, dev->conf.secs, dev->chs_trans) < 0) { @@ -249,9 +250,9 @@ static int ide_cd_initfn(IDEDevice *dev) static int ide_drive_initfn(IDEDevice *dev) { - DriveInfo *dinfo = drive_get_by_blockdev(dev->conf.bs); + DriveInfo *dinfo = blk_legacy_dinfo(dev->conf.blk); - return ide_dev_initfn(dev, dinfo->media_cd ? IDE_CD : IDE_HD); + return ide_dev_initfn(dev, dinfo && dinfo->media_cd ? IDE_CD : IDE_HD); } #define DEFINE_IDE_DEV_PROPERTIES() \ diff --git a/hw/ide/via.c b/hw/ide/via.c index 89d27b4..4d8089d 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -27,7 +27,7 @@ #include <hw/i386/pc.h> #include <hw/pci/pci.h> #include <hw/isa/isa.h> -#include "block/block.h" +#include "sysemu/block-backend.h" #include "sysemu/sysemu.h" #include "sysemu/dma.h" diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c index 9327c53..40a1106 100644 --- a/hw/isa/pc87312.c +++ b/hw/isa/pc87312.c @@ -25,6 +25,7 @@ #include "hw/isa/pc87312.h" #include "qemu/error-report.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "sysemu/sysemu.h" #include "sysemu/char.h" @@ -320,11 +321,13 @@ static void pc87312_realize(DeviceState *dev, Error **errp) qdev_prop_set_uint32(d, "irq", 6); drive = drive_get(IF_FLOPPY, 0, 0); if (drive != NULL) { - qdev_prop_set_drive_nofail(d, "driveA", drive->bdrv); + qdev_prop_set_drive_nofail(d, "driveA", + blk_by_legacy_dinfo(drive)); } drive = drive_get(IF_FLOPPY, 0, 1); if (drive != NULL) { - qdev_prop_set_drive_nofail(d, "driveB", drive->bdrv); + qdev_prop_set_drive_nofail(d, "driveB", + blk_by_legacy_dinfo(drive)); } qdev_init_nofail(d); s->fdc.dev = isa; diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c index 5ae6cad..af0abdb 100644 --- a/hw/lm32/lm32_boards.c +++ b/hw/lm32/lm32_boards.c @@ -23,7 +23,7 @@ #include "hw/devices.h" #include "hw/boards.h" #include "hw/loader.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "elf.h" #include "lm32_hwsetup.h" #include "lm32.h" @@ -119,9 +119,9 @@ static void lm32_evr_init(MachineState *machine) dinfo = drive_get(IF_PFLASH, 0, 0); /* Spansion S29NS128P */ pflash_cfi02_register(flash_base, NULL, "lm32_evr.flash", flash_size, - dinfo ? dinfo->bdrv : NULL, flash_sector_size, - flash_size / flash_sector_size, 1, 2, - 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1); + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, + flash_sector_size, flash_size / flash_sector_size, + 1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1); /* create irq lines */ cpu_irq = qemu_allocate_irqs(cpu_irq_handler, cpu, 1); @@ -222,9 +222,9 @@ static void lm32_uclinux_init(MachineState *machine) dinfo = drive_get(IF_PFLASH, 0, 0); /* Spansion S29NS128P */ pflash_cfi02_register(flash_base, NULL, "lm32_uclinux.flash", flash_size, - dinfo ? dinfo->bdrv : NULL, flash_sector_size, - flash_size / flash_sector_size, 1, 2, - 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1); + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, + flash_sector_size, flash_size / flash_sector_size, + 1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1); /* create irq lines */ cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1); diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c index c8832f0..256c102 100644 --- a/hw/lm32/milkymist.c +++ b/hw/lm32/milkymist.c @@ -26,7 +26,7 @@ #include "hw/boards.h" #include "hw/loader.h" #include "elf.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "milkymist-hw.h" #include "lm32.h" #include "exec/address-spaces.h" @@ -126,9 +126,9 @@ milkymist_init(MachineState *machine) dinfo = drive_get(IF_PFLASH, 0, 0); /* Numonyx JS28F256J3F105 */ pflash_cfi01_register(flash_base, NULL, "milkymist.flash", flash_size, - dinfo ? dinfo->bdrv : NULL, flash_sector_size, - flash_size / flash_sector_size, 2, - 0x00, 0x89, 0x00, 0x1d, 1); + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, + flash_sector_size, flash_size / flash_sector_size, + 2, 0x00, 0x89, 0x00, 0x1d, 1); /* create irq lines */ cpu_irq = qemu_allocate_irqs(cpu_irq_handler, cpu, 1); diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c index fcb51bc..48c264b 100644 --- a/hw/microblaze/petalogix_ml605_mmu.c +++ b/hw/microblaze/petalogix_ml605_mmu.c @@ -32,7 +32,7 @@ #include "sysemu/sysemu.h" #include "hw/devices.h" #include "hw/boards.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/char/serial.h" #include "exec/address-spaces.h" #include "hw/ssi.h" @@ -113,8 +113,8 @@ petalogix_ml605_init(MachineState *machine) * 10th paremeter 0 means little-endian */ pflash_cfi01_register(FLASH_BASEADDR, NULL, "petalogix_ml605.flash", FLASH_SIZE, - dinfo ? dinfo->bdrv : NULL, (64 * 1024), - FLASH_SIZE >> 16, + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, + (64 * 1024), FLASH_SIZE >> 16, 2, 0x89, 0x18, 0x0000, 0x0, 0); diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c index 8e0fca9..84f6e74 100644 --- a/hw/microblaze/petalogix_s3adsp1800_mmu.c +++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c @@ -30,7 +30,7 @@ #include "sysemu/sysemu.h" #include "hw/devices.h" #include "hw/boards.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #include "boot.h" @@ -94,8 +94,8 @@ petalogix_s3adsp1800_init(MachineState *machine) dinfo = drive_get(IF_PFLASH, 0, 0); pflash_cfi01_register(FLASH_BASEADDR, NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE, - dinfo ? dinfo->bdrv : NULL, (64 * 1024), - FLASH_SIZE >> 16, + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, + (64 * 1024), FLASH_SIZE >> 16, 1, 0x89, 0x18, 0x0000, 0x0, 1); dev = qdev_create(NULL, "xlnx.xps-intc"); diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index 29cd708..6a9ebfa 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -25,7 +25,7 @@ #include "net/net.h" #include "hw/boards.h" #include "hw/i2c/smbus.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "hw/block/flash.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c index 6c31cb8..3f33093 100644 --- a/hw/mips/mips_jazz.c +++ b/hw/mips/mips_jazz.c @@ -39,7 +39,7 @@ #include "hw/timer/mc146818rtc.h" #include "hw/timer/i8254.h" #include "hw/audio/pcspk.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" #include "sysemu/qtest.h" diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index b20807c..5845158 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -29,7 +29,7 @@ #include "net/net.h" #include "hw/boards.h" #include "hw/i2c/smbus.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "hw/block/flash.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" @@ -44,6 +44,7 @@ #include "elf.h" #include "hw/timer/mc146818rtc.h" #include "hw/timer/i8254.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "exec/address-spaces.h" #include "hw/sysbus.h" /* SysBusDevice */ @@ -697,12 +698,12 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base, /* Jump to kernel code */ stl_p(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff)); /* lui ra, high(kernel_entry) */ stl_p(p++, 0x37ff0000 | (kernel_entry & 0xffff)); /* ori ra, ra, low(kernel_entry) */ - stl_p(p++, 0x03e00008); /* jr ra */ + stl_p(p++, 0x03e00009); /* jalr ra */ stl_p(p++, 0x00000000); /* nop */ /* YAMON subroutines */ p = (uint32_t *) (base + 0x800); - stl_p(p++, 0x03e00008); /* jr ra */ + stl_p(p++, 0x03e00009); /* jalr ra */ stl_p(p++, 0x24020000); /* li v0,0 */ /* 808 YAMON print */ stl_p(p++, 0x03e06821); /* move t5,ra */ @@ -716,7 +717,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base, stl_p(p++, 0x00000000); /* nop */ stl_p(p++, 0x08000205); /* j 814 */ stl_p(p++, 0x00000000); /* nop */ - stl_p(p++, 0x01a00008); /* jr t5 */ + stl_p(p++, 0x01a00009); /* jalr t5 */ stl_p(p++, 0x01602021); /* move a0,t3 */ /* 0x83c YAMON print_count */ stl_p(p++, 0x03e06821); /* move t5,ra */ @@ -730,7 +731,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base, stl_p(p++, 0x258cffff); /* addiu t4,t4,-1 */ stl_p(p++, 0x1580fffa); /* bnez t4,84c */ stl_p(p++, 0x00000000); /* nop */ - stl_p(p++, 0x01a00008); /* jr t5 */ + stl_p(p++, 0x01a00009); /* jalr t5 */ stl_p(p++, 0x01602021); /* move a0,t3 */ /* 0x870 */ stl_p(p++, 0x3c08b800); /* lui t0,0xb400 */ @@ -740,7 +741,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base, stl_p(p++, 0x31290040); /* andi t1,t1,0x40 */ stl_p(p++, 0x1120fffc); /* beqz t1,878 <outch+0x8> */ stl_p(p++, 0x00000000); /* nop */ - stl_p(p++, 0x03e00008); /* jr ra */ + stl_p(p++, 0x03e00009); /* jalr ra */ stl_p(p++, 0xa1040000); /* sb a0,0(t0) */ } @@ -1032,11 +1033,12 @@ void mips_malta_init(MachineState *machine) printf("Register parallel flash %d size " TARGET_FMT_lx " at " "addr %08llx '%s' %x\n", fl_idx, bios_size, FLASH_ADDRESS, - bdrv_get_device_name(dinfo->bdrv), fl_sectors); + blk_name(dinfo->bdrv), fl_sectors); } #endif fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios", - BIOS_SIZE, dinfo ? dinfo->bdrv : NULL, + BIOS_SIZE, + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, 65536, fl_sectors, 4, 0x0000, 0x0000, 0x0000, 0x0000, be); bios = pflash_cfi01_get_memory(fl); diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c index 93606a4..a7fe0ce 100644 --- a/hw/mips/mips_r4k.c +++ b/hw/mips/mips_r4k.c @@ -24,7 +24,7 @@ #include "elf.h" #include "hw/timer/mc146818rtc.h" #include "hw/timer/i8254.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #include "sysemu/qtest.h" @@ -241,8 +241,8 @@ void mips_r4k_init(MachineState *machine) } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) { uint32_t mips_rom = 0x00400000; if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom, - dinfo->bdrv, sector_len, - mips_rom / sector_len, + blk_by_legacy_dinfo(dinfo), + sector_len, mips_rom / sector_len, 4, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); } diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c index 6a72ef4..10b5b2e 100644 --- a/hw/nvram/spapr_nvram.c +++ b/hw/nvram/spapr_nvram.c @@ -24,6 +24,7 @@ #include <libfdt.h> +#include "sysemu/block-backend.h" #include "sysemu/device_tree.h" #include "hw/sysbus.h" #include "hw/ppc/spapr.h" @@ -33,7 +34,7 @@ typedef struct sPAPRNVRAM { VIOsPAPRDevice sdev; uint32_t size; uint8_t *buf; - BlockDriverState *drive; + BlockBackend *blk; } sPAPRNVRAM; #define TYPE_VIO_SPAPR_NVRAM "spapr-nvram" @@ -77,8 +78,8 @@ static void rtas_nvram_fetch(PowerPCCPU *cpu, sPAPREnvironment *spapr, } membuf = cpu_physical_memory_map(buffer, &len, 1); - if (nvram->drive) { - alen = bdrv_pread(nvram->drive, offset, membuf, len); + if (nvram->blk) { + alen = blk_pread(nvram->blk, offset, membuf, len); } else { assert(nvram->buf); @@ -122,8 +123,8 @@ static void rtas_nvram_store(PowerPCCPU *cpu, sPAPREnvironment *spapr, } membuf = cpu_physical_memory_map(buffer, &len, 0); - if (nvram->drive) { - alen = bdrv_pwrite(nvram->drive, offset, membuf, len); + if (nvram->blk) { + alen = blk_pwrite(nvram->blk, offset, membuf, len); } else { assert(nvram->buf); @@ -140,8 +141,8 @@ static int spapr_nvram_init(VIOsPAPRDevice *dev) { sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(dev); - if (nvram->drive) { - nvram->size = bdrv_getlength(nvram->drive); + if (nvram->blk) { + nvram->size = blk_getlength(nvram->blk); } else { nvram->size = DEFAULT_NVRAM_SIZE; nvram->buf = g_malloc0(nvram->size); @@ -168,7 +169,7 @@ static int spapr_nvram_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off) static Property spapr_nvram_properties[] = { DEFINE_SPAPR_PROPERTIES(sPAPRNVRAM, sdev), - DEFINE_PROP_DRIVE("drive", sPAPRNVRAM, drive), + DEFINE_PROP_DRIVE("drive", sPAPRNVRAM, blk), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c index 6ab28b7..0c09c72 100644 --- a/hw/pci/pci-hotplug-old.c +++ b/hw/pci/pci-hotplug-old.c @@ -33,7 +33,7 @@ #include "hw/scsi/scsi.h" #include "hw/virtio/virtio-blk.h" #include "qemu/config-file.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "qapi/error.h" static int pci_read_devaddr(Monitor *mon, const char *addr, @@ -127,8 +127,10 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter, */ dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1); dinfo->bus = scsibus->busnr; - scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, - false, -1, NULL, &local_err); + scsidev = scsi_bus_legacy_add_drive(scsibus, + blk_by_legacy_dinfo(dinfo), + dinfo->unit, false, -1, NULL, + &local_err); if (!scsidev) { error_report("%s", error_get_pretty(local_err)); error_free(local_err); @@ -250,7 +252,8 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, return NULL; } dev = pci_create(bus, devfn, "virtio-blk-pci"); - if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { + if (qdev_prop_set_drive(&dev->qdev, "drive", + blk_by_legacy_dinfo(dinfo)) < 0) { object_unparent(OBJECT(dev)); dev = NULL; break; diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index aff2b9a..8bdba30 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -131,7 +131,7 @@ typedef struct MACIOIDEState { MemoryRegion mem; IDEBus bus; - BlockDriverAIOCB *aiocb; + BlockAIOCB *aiocb; IDEDMA dma; void *dbdma; bool dma_active; diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 4094beb..89aee71 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -65,7 +65,7 @@ #include "sysemu/kvm.h" #include "kvm_ppc.h" #include "hw/usb.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #include "hw/sysbus.h" diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index ebd87fb..32c21a4 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -40,7 +40,7 @@ #include "elf.h" #include "sysemu/kvm.h" #include "kvm_ppc.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #define MAX_IDE_BUS 2 diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index 18a4ec5..1dcea77 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -28,11 +28,12 @@ #include "hw/block/flash.h" #include "sysemu/sysemu.h" #include "sysemu/qtest.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "hw/boards.h" #include "qemu/log.h" #include "qemu/error-report.h" #include "hw/loader.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "exec/address-spaces.h" @@ -225,17 +226,19 @@ static void ref405ep_init(MachineState *machine) #ifdef USE_FLASH_BIOS dinfo = drive_get(IF_PFLASH, 0, fl_idx); if (dinfo) { - bios_size = bdrv_getlength(dinfo->bdrv); + BlockBackend *blk = blk_by_legacy_dinfo(dinfo); + + bios_size = blk_getlength(blk); fl_sectors = (bios_size + 65535) >> 16; #ifdef DEBUG_BOARD_INIT printf("Register parallel flash %d size %lx" " at addr %lx '%s' %d\n", fl_idx, bios_size, -bios_size, - bdrv_get_device_name(dinfo->bdrv), fl_sectors); + blk_name(blk), fl_sectors); #endif pflash_cfi02_register((uint32_t)(-bios_size), NULL, "ef405ep.bios", bios_size, - dinfo->bdrv, 65536, fl_sectors, 1, + blk, 65536, fl_sectors, 1, 2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA, 1); fl_idx++; @@ -548,7 +551,9 @@ static void taihu_405ep_init(MachineState *machine) #if defined(USE_FLASH_BIOS) dinfo = drive_get(IF_PFLASH, 0, fl_idx); if (dinfo) { - bios_size = bdrv_getlength(dinfo->bdrv); + BlockBackend *blk = blk_by_legacy_dinfo(dinfo); + + bios_size = blk_getlength(blk); /* XXX: should check that size is 2MB */ // bios_size = 2 * 1024 * 1024; fl_sectors = (bios_size + 65535) >> 16; @@ -556,11 +561,11 @@ static void taihu_405ep_init(MachineState *machine) printf("Register parallel flash %d size %lx" " at addr %lx '%s' %d\n", fl_idx, bios_size, -bios_size, - bdrv_get_device_name(dinfo->bdrv), fl_sectors); + blk_name(blk), fl_sectors); #endif pflash_cfi02_register((uint32_t)(-bios_size), NULL, "taihu_405ep.bios", bios_size, - dinfo->bdrv, 65536, fl_sectors, 1, + blk, 65536, fl_sectors, 1, 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA, 1); fl_idx++; @@ -595,7 +600,9 @@ static void taihu_405ep_init(MachineState *machine) /* Register Linux flash */ dinfo = drive_get(IF_PFLASH, 0, fl_idx); if (dinfo) { - bios_size = bdrv_getlength(dinfo->bdrv); + BlockBackend *blk = blk_by_legacy_dinfo(dinfo); + + bios_size = blk_getlength(blk); /* XXX: should check that size is 32MB */ bios_size = 32 * 1024 * 1024; fl_sectors = (bios_size + 65535) >> 16; @@ -603,10 +610,10 @@ static void taihu_405ep_init(MachineState *machine) printf("Register parallel flash %d size %lx" " at addr " TARGET_FMT_lx " '%s'\n", fl_idx, bios_size, (target_ulong)0xfc000000, - bdrv_get_device_name(dinfo->bdrv)); + blk_name(blk)); #endif pflash_cfi02_register(0xfc000000, NULL, "taihu_405ep.flash", bios_size, - dinfo->bdrv, 65536, fl_sectors, 1, + blk, 65536, fl_sectors, 1, 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA, 1); fl_idx++; diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index 9f484cd..dd8433d 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -38,7 +38,7 @@ #include "hw/loader.h" #include "hw/timer/mc146818rtc.h" #include "hw/isa/pc87312.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "sysemu/arch_init.h" #include "sysemu/qtest.h" #include "exec/address-spaces.h" diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 2becc9f..45764a7 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -29,7 +29,7 @@ #include "hw/fw-path-provider.h" #include "elf.h" #include "net/net.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "sysemu/cpus.h" #include "sysemu/kvm.h" #include "kvm_ppc.h" @@ -925,7 +925,7 @@ static void spapr_create_nvram(sPAPREnvironment *spapr) DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); if (dinfo) { - qdev_prop_set_drive_nofail(dev, "drive", dinfo->bdrv); + qdev_prop_set_drive_nofail(dev, "drive", blk_by_legacy_dinfo(dinfo)); } qdev_init_nofail(dev); diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index 0de5148..6ebd5be 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -39,7 +39,7 @@ #include "hw/ppc/ppc4xx.h" #include "ppc405.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "qapi/qmp/qerror.h" #define EPAPR_MAGIC (0x45504150) @@ -227,8 +227,8 @@ static void virtex_init(MachineState *machine) dinfo = drive_get(IF_PFLASH, 0, 0); pflash_cfi01_register(PFLASH_BASEADDR, NULL, "virtex.flash", FLASH_SIZE, - dinfo ? dinfo->bdrv : NULL, (64 * 1024), - FLASH_SIZE >> 16, + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, + (64 * 1024), FLASH_SIZE >> 16, 1, 0x89, 0x18, 0x0000, 0x0, 1); cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT]; diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index 29ecdb4..2059874 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -18,7 +18,7 @@ */ #include "hw/hw.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "sysemu/sysemu.h" #include "hw/boards.h" #include "monitor/monitor.h" diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c index af0004a..c215cd8 100644 --- a/hw/s390x/s390-virtio.c +++ b/hw/s390x/s390-virtio.c @@ -22,7 +22,7 @@ */ #include "hw/hw.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "sysemu/sysemu.h" #include "net/net.h" diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index f5ec946..1c0d913 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -10,7 +10,7 @@ */ #include "hw/hw.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "sysemu/sysemu.h" #include "net/net.h" diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index eedc992..36a04f3 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -21,6 +21,7 @@ #include "hw/hw.h" #include "hw/pci/pci.h" #include "sysemu/dma.h" +#include "sysemu/block-backend.h" #include "hw/pci/msi.h" #include "hw/pci/msix.h" #include "qemu/iov.h" @@ -976,7 +977,6 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, { struct mfi_pd_info *info = cmd->iov_buf; size_t dcmd_size = sizeof(struct mfi_pd_info); - BlockConf *conf = &sdev->conf; uint64_t pd_size; uint16_t sdev_id = ((sdev->id & 0xFF) >> 8) | (lun & 0xFF); uint8_t cmdbuf[6]; @@ -1037,7 +1037,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, info->ref.v.device_id = cpu_to_le16(sdev_id); info->state.ddf.pd_type = cpu_to_le16(MFI_PD_DDF_TYPE_IN_VD| MFI_PD_DDF_TYPE_INTF_SAS); - bdrv_get_geometry(conf->bs, &pd_size); + blk_get_geometry(sdev->conf.blk, &pd_size); info->raw_size = cpu_to_le64(pd_size); info->non_coerced_size = cpu_to_le64(pd_size); info->coerced_size = cpu_to_le64(pd_size); @@ -1100,13 +1100,12 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) } QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) { SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child); - BlockConf *conf = &sdev->conf; if (num_ld_disks >= max_ld_disks) { break; } /* Logical device size is in blocks */ - bdrv_get_geometry(conf->bs, &ld_size); + blk_get_geometry(sdev->conf.blk, &ld_size); info.ld_list[num_ld_disks].ld.v.target_id = sdev->id; info.ld_list[num_ld_disks].ld.v.lun_id = sdev->lun; info.ld_list[num_ld_disks].state = MFI_LD_STATE_OPTIMAL; @@ -1144,7 +1143,6 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, uint8_t cdb[6]; SCSIRequest *req; ssize_t len, resid; - BlockConf *conf = &sdev->conf; uint16_t sdev_id = ((sdev->id & 0xFF) >> 8) | (lun & 0xFF); uint64_t ld_size; @@ -1177,7 +1175,7 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, info->ld_config.params.num_drives = 1; info->ld_config.params.is_consistent = 1; /* Logical device size is in blocks */ - bdrv_get_geometry(conf->bs, &ld_size); + blk_get_geometry(sdev->conf.blk, &ld_size); info->size = cpu_to_le64(ld_size); memset(info->ld_config.span, 0, sizeof(info->ld_config.span)); info->ld_config.span[0].start_block = 0; @@ -1261,7 +1259,6 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd) QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) { SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child); - BlockConf *conf = &sdev->conf; uint16_t sdev_id = ((sdev->id & 0xFF) >> 8) | (sdev->lun & 0xFF); struct mfi_array *array; struct mfi_ld_config *ld; @@ -1269,7 +1266,7 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd) int i; array = (struct mfi_array *)(data + array_offset); - bdrv_get_geometry(conf->bs, &pd_size); + blk_get_geometry(sdev->conf.blk, &pd_size); array->size = cpu_to_le64(pd_size); array->num_drives = 1; array->array_ref = cpu_to_le16(sdev_id); @@ -1340,7 +1337,7 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd) static int megasas_cache_flush(MegasasState *s, MegasasCmd *cmd) { - bdrv_drain_all(); + blk_drain_all(); return MFI_STAT_OK; } diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 022a524..af7707c 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -3,6 +3,7 @@ #include "hw/scsi/scsi.h" #include "block/scsi.h" #include "hw/qdev.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "trace.h" #include "sysemu/dma.h" @@ -221,7 +222,7 @@ static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp) } /* handle legacy '-drive if=scsi,...' cmd line args */ -SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, +SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk, int unit, bool removable, int bootindex, const char *serial, Error **errp) { @@ -229,7 +230,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, DeviceState *dev; Error *err = NULL; - driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk"; + driver = blk_is_sg(blk) ? "scsi-generic" : "scsi-disk"; dev = qdev_create(&bus->qbus, driver); qdev_prop_set_uint32(dev, "scsi-id", unit); if (bootindex >= 0) { @@ -242,7 +243,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, if (serial && object_property_find(OBJECT(dev), "serial", NULL)) { qdev_prop_set_string(dev, "serial", serial); } - if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) { + if (qdev_prop_set_drive(dev, "drive", blk) < 0) { error_setg(errp, "Setting drive property failed"); object_unparent(OBJECT(dev)); return NULL; @@ -270,8 +271,8 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp) continue; } qemu_opts_loc_restore(dinfo->opts); - scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1, NULL, - &err); + scsi_bus_legacy_add_drive(bus, blk_by_legacy_dinfo(dinfo), + unit, false, -1, NULL, &err); if (err != NULL) { error_report("%s", error_get_pretty(err)); error_propagate(errp, err); @@ -1753,7 +1754,7 @@ void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier) scsi_req_dequeue(req); req->io_canceled = true; if (req->aiocb) { - bdrv_aio_cancel_async(req->aiocb); + blk_aio_cancel_async(req->aiocb); } } @@ -1767,7 +1768,7 @@ void scsi_req_cancel(SCSIRequest *req) scsi_req_dequeue(req); req->io_canceled = true; if (req->aiocb) { - bdrv_aio_cancel(req->aiocb); + blk_aio_cancel(req->aiocb); } } diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index ae9e08d..010eefd 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -33,6 +33,7 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0) #include "hw/scsi/scsi.h" #include "block/scsi.h" #include "sysemu/sysemu.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/block/block.h" #include "sysemu/dma.h" @@ -111,7 +112,7 @@ static uint32_t scsi_init_iovec(SCSIDiskReq *r, size_t size) if (!r->iov.iov_base) { r->buflen = size; - r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen); + r->iov.iov_base = blk_blockalign(s->qdev.conf.blk, r->buflen); } r->iov.iov_len = MIN(r->sector_count * 512, r->buflen); qemu_iovec_init_external(&r->qiov, &r->iov, 1); @@ -166,7 +167,7 @@ static void scsi_aio_complete(void *opaque, int ret) assert(r->req.aiocb != NULL); r->req.aiocb = NULL; - block_acct_done(bdrv_get_stats(s->qdev.conf.bs), &r->acct); + block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct); if (r->req.io_canceled) { scsi_req_cancel_complete(&r->req); goto done; @@ -220,9 +221,9 @@ static void scsi_write_do_fua(SCSIDiskReq *r) } if (scsi_is_cmd_fua(&r->req.cmd)) { - block_acct_start(bdrv_get_stats(s->qdev.conf.bs), &r->acct, 0, + block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, 0, BLOCK_ACCT_FLUSH); - r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r); + r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_aio_complete, r); return; } @@ -239,7 +240,7 @@ static void scsi_dma_complete_noio(void *opaque, int ret) if (r->req.aiocb != NULL) { r->req.aiocb = NULL; - block_acct_done(bdrv_get_stats(s->qdev.conf.bs), &r->acct); + block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct); } if (r->req.io_canceled) { scsi_req_cancel_complete(&r->req); @@ -281,7 +282,7 @@ static void scsi_read_complete(void * opaque, int ret) assert(r->req.aiocb != NULL); r->req.aiocb = NULL; - block_acct_done(bdrv_get_stats(s->qdev.conf.bs), &r->acct); + block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct); if (r->req.io_canceled) { scsi_req_cancel_complete(&r->req); goto done; @@ -313,7 +314,7 @@ static void scsi_do_read(void *opaque, int ret) if (r->req.aiocb != NULL) { r->req.aiocb = NULL; - block_acct_done(bdrv_get_stats(s->qdev.conf.bs), &r->acct); + block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct); } if (r->req.io_canceled) { scsi_req_cancel_complete(&r->req); @@ -330,16 +331,16 @@ static void scsi_do_read(void *opaque, int ret) scsi_req_ref(&r->req); if (r->req.sg) { - dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BLOCK_ACCT_READ); + dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BLOCK_ACCT_READ); r->req.resid -= r->req.sg->size; - r->req.aiocb = dma_bdrv_read(s->qdev.conf.bs, r->req.sg, r->sector, - scsi_dma_complete, r); + r->req.aiocb = dma_blk_read(s->qdev.conf.blk, r->req.sg, r->sector, + scsi_dma_complete, r); } else { n = scsi_init_iovec(r, SCSI_DMA_BUF_SIZE); - block_acct_start(bdrv_get_stats(s->qdev.conf.bs), &r->acct, + block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, n * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ); - r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n, - scsi_read_complete, r); + r->req.aiocb = blk_aio_readv(s->qdev.conf.blk, r->sector, &r->qiov, n, + scsi_read_complete, r); } done: @@ -379,9 +380,9 @@ static void scsi_read_data(SCSIRequest *req) first = !r->started; r->started = true; if (first && scsi_is_cmd_fua(&r->req.cmd)) { - block_acct_start(bdrv_get_stats(s->qdev.conf.bs), &r->acct, 0, + block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, 0, BLOCK_ACCT_FLUSH); - r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_do_read, r); + r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_do_read, r); } else { scsi_do_read(r, 0); } @@ -398,7 +399,8 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error) { bool is_read = (r->req.cmd.xfer == SCSI_XFER_FROM_DEV); SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); - BlockErrorAction action = bdrv_get_error_action(s->qdev.conf.bs, is_read, error); + BlockErrorAction action = blk_get_error_action(s->qdev.conf.blk, + is_read, error); if (action == BLOCK_ERROR_ACTION_REPORT) { switch (error) { @@ -419,7 +421,7 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error) break; } } - bdrv_error_action(s->qdev.conf.bs, action, is_read, error); + blk_error_action(s->qdev.conf.blk, action, is_read, error); if (action == BLOCK_ERROR_ACTION_STOP) { scsi_req_retry(&r->req); } @@ -434,7 +436,7 @@ static void scsi_write_complete(void * opaque, int ret) if (r->req.aiocb != NULL) { r->req.aiocb = NULL; - block_acct_done(bdrv_get_stats(s->qdev.conf.bs), &r->acct); + block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct); } if (r->req.io_canceled) { scsi_req_cancel_complete(&r->req); @@ -502,16 +504,16 @@ static void scsi_write_data(SCSIRequest *req) } if (r->req.sg) { - dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BLOCK_ACCT_WRITE); + dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BLOCK_ACCT_WRITE); r->req.resid -= r->req.sg->size; - r->req.aiocb = dma_bdrv_write(s->qdev.conf.bs, r->req.sg, r->sector, - scsi_dma_complete, r); + r->req.aiocb = dma_blk_write(s->qdev.conf.blk, r->req.sg, r->sector, + scsi_dma_complete, r); } else { n = r->qiov.size / 512; - block_acct_start(bdrv_get_stats(s->qdev.conf.bs), &r->acct, + block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, n * BDRV_SECTOR_SIZE, BLOCK_ACCT_WRITE); - r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n, - scsi_write_complete, r); + r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, r->sector, &r->qiov, n, + scsi_write_complete, r); } } @@ -578,7 +580,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) case 0x83: /* Device identification page, mandatory */ { - const char *str = s->serial ?: bdrv_get_device_name(s->qdev.conf.bs); + const char *str = s->serial ?: blk_name(s->qdev.conf.blk); int max_len = s->serial ? 20 : 255 - 8; int id_len = strlen(str); @@ -739,10 +741,10 @@ static inline bool media_is_dvd(SCSIDiskState *s) if (s->qdev.type != TYPE_ROM) { return false; } - if (!bdrv_is_inserted(s->qdev.conf.bs)) { + if (!blk_is_inserted(s->qdev.conf.blk)) { return false; } - bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors); + blk_get_geometry(s->qdev.conf.blk, &nb_sectors); return nb_sectors > CD_MAX_SECTORS; } @@ -752,10 +754,10 @@ static inline bool media_is_cd(SCSIDiskState *s) if (s->qdev.type != TYPE_ROM) { return false; } - if (!bdrv_is_inserted(s->qdev.conf.bs)) { + if (!blk_is_inserted(s->qdev.conf.blk)) { return false; } - bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors); + blk_get_geometry(s->qdev.conf.blk, &nb_sectors); return nb_sectors <= CD_MAX_SECTORS; } @@ -816,7 +818,7 @@ static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r, } if (format != 0xff) { - if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) { + if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) { scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); return -1; } @@ -838,7 +840,7 @@ static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r, if (layer != 0) { goto fail; } - bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors); + blk_get_geometry(s->qdev.conf.blk, &nb_sectors); outbuf[4] = 1; /* DVD-ROM, part version 1 */ outbuf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ @@ -893,7 +895,7 @@ static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf) media_status = 0; if (s->tray_open) { media_status = MS_TRAY_OPEN; - } else if (bdrv_is_inserted(s->qdev.conf.bs)) { + } else if (blk_is_inserted(s->qdev.conf.blk)) { media_status = MS_MEDIA_PRESENT; } @@ -1091,7 +1093,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf, case MODE_PAGE_CACHING: length = 0x12; if (page_control == 1 || /* Changeable Values */ - bdrv_enable_write_cache(s->qdev.conf.bs)) { + blk_enable_write_cache(s->qdev.conf.blk)) { p[0] = 4; /* WCE */ } break; @@ -1172,7 +1174,7 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf) if (s->qdev.type == TYPE_DISK) { dev_specific_param = s->features & (1 << SCSI_DISK_F_DPOFUA) ? 0x10 : 0; - if (bdrv_is_read_only(s->qdev.conf.bs)) { + if (blk_is_read_only(s->qdev.conf.blk)) { dev_specific_param |= 0x80; /* Readonly. */ } } else { @@ -1194,7 +1196,7 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf) p += 8; } - bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors); + blk_get_geometry(s->qdev.conf.blk, &nb_sectors); if (!dbd && nb_sectors) { if (r->req.cmd.buf[0] == MODE_SENSE) { outbuf[3] = 8; /* Block descriptor length */ @@ -1257,7 +1259,7 @@ static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf) msf = req->cmd.buf[1] & 2; format = req->cmd.buf[2] & 0xf; start_track = req->cmd.buf[6]; - bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors); + blk_get_geometry(s->qdev.conf.blk, &nb_sectors); DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1); nb_sectors /= s->qdev.blocksize / 512; switch (format) { @@ -1297,14 +1299,14 @@ static int scsi_disk_emulate_start_stop(SCSIDiskReq *r) if ((s->features & (1 << SCSI_DISK_F_REMOVABLE)) && loej) { if (!start && !s->tray_open && s->tray_locked) { scsi_check_condition(r, - bdrv_is_inserted(s->qdev.conf.bs) + blk_is_inserted(s->qdev.conf.blk) ? SENSE_CODE(ILLEGAL_REQ_REMOVAL_PREVENTED) : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED)); return -1; } if (s->tray_open != !start) { - bdrv_eject(s->qdev.conf.bs, !start); + blk_eject(s->qdev.conf.blk, !start); s->tray_open = !start; } } @@ -1371,7 +1373,7 @@ static void scsi_disk_apply_mode_select(SCSIDiskState *s, int page, uint8_t *p) { switch (page) { case MODE_PAGE_CACHING: - bdrv_set_enable_write_cache(s->qdev.conf.bs, (p[0] & 4) != 0); + blk_set_enable_write_cache(s->qdev.conf.blk, (p[0] & 4) != 0); break; default: @@ -1474,12 +1476,12 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf) return; } } - if (!bdrv_enable_write_cache(s->qdev.conf.bs)) { + if (!blk_enable_write_cache(s->qdev.conf.blk)) { /* The request is used as the AIO opaque value, so add a ref. */ scsi_req_ref(&r->req); - block_acct_start(bdrv_get_stats(s->qdev.conf.bs), &r->acct, 0, + block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, 0, BLOCK_ACCT_FLUSH); - r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r); + r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_aio_complete, r); return; } @@ -1548,10 +1550,10 @@ static void scsi_unmap_complete(void *opaque, int ret) goto done; } - r->req.aiocb = bdrv_aio_discard(s->qdev.conf.bs, - sector_num * (s->qdev.blocksize / 512), - nb_sectors * (s->qdev.blocksize / 512), - scsi_unmap_complete, data); + r->req.aiocb = blk_aio_discard(s->qdev.conf.blk, + sector_num * (s->qdev.blocksize / 512), + nb_sectors * (s->qdev.blocksize / 512), + scsi_unmap_complete, data); data->count--; data->inbuf += 16; return; @@ -1589,7 +1591,7 @@ static void scsi_disk_emulate_unmap(SCSIDiskReq *r, uint8_t *inbuf) goto invalid_param_len; } - if (bdrv_is_read_only(s->qdev.conf.bs)) { + if (blk_is_read_only(s->qdev.conf.blk)) { scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED)); return; } @@ -1628,7 +1630,7 @@ static void scsi_write_same_complete(void *opaque, int ret) assert(r->req.aiocb != NULL); r->req.aiocb = NULL; - block_acct_done(bdrv_get_stats(s->qdev.conf.bs), &r->acct); + block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct); if (r->req.io_canceled) { scsi_req_cancel_complete(&r->req); goto done; @@ -1644,11 +1646,11 @@ static void scsi_write_same_complete(void *opaque, int ret) data->sector += data->iov.iov_len / 512; data->iov.iov_len = MIN(data->nb_sectors * 512, data->iov.iov_len); if (data->iov.iov_len) { - block_acct_start(bdrv_get_stats(s->qdev.conf.bs), &r->acct, + block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, data->iov.iov_len, BLOCK_ACCT_WRITE); - r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, data->sector, - &data->qiov, data->iov.iov_len / 512, - scsi_write_same_complete, data); + r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, data->sector, + &data->qiov, data->iov.iov_len / 512, + scsi_write_same_complete, data); return; } @@ -1675,7 +1677,7 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf) return; } - if (bdrv_is_read_only(s->qdev.conf.bs)) { + if (blk_is_read_only(s->qdev.conf.blk)) { scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED)); return; } @@ -1689,13 +1691,13 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf) /* The request is used as the AIO opaque value, so add a ref. */ scsi_req_ref(&r->req); - block_acct_start(bdrv_get_stats(s->qdev.conf.bs), &r->acct, + block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, nb_sectors * s->qdev.blocksize, BLOCK_ACCT_WRITE); - r->req.aiocb = bdrv_aio_write_zeroes(s->qdev.conf.bs, - r->req.cmd.lba * (s->qdev.blocksize / 512), - nb_sectors * (s->qdev.blocksize / 512), - flags, scsi_aio_complete, r); + r->req.aiocb = blk_aio_write_zeroes(s->qdev.conf.blk, + r->req.cmd.lba * (s->qdev.blocksize / 512), + nb_sectors * (s->qdev.blocksize / 512), + flags, scsi_aio_complete, r); return; } @@ -1704,7 +1706,8 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf) data->sector = r->req.cmd.lba * (s->qdev.blocksize / 512); data->nb_sectors = nb_sectors * (s->qdev.blocksize / 512); data->iov.iov_len = MIN(data->nb_sectors * 512, SCSI_WRITE_SAME_MAX); - data->iov.iov_base = buf = qemu_blockalign(s->qdev.conf.bs, data->iov.iov_len); + data->iov.iov_base = buf = blk_blockalign(s->qdev.conf.blk, + data->iov.iov_len); qemu_iovec_init_external(&data->qiov, &data->iov, 1); for (i = 0; i < data->iov.iov_len; i += s->qdev.blocksize) { @@ -1712,11 +1715,11 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf) } scsi_req_ref(&r->req); - block_acct_start(bdrv_get_stats(s->qdev.conf.bs), &r->acct, + block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, data->iov.iov_len, BLOCK_ACCT_WRITE); - r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, data->sector, - &data->qiov, data->iov.iov_len / 512, - scsi_write_same_complete, data); + r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, data->sector, + &data->qiov, data->iov.iov_len / 512, + scsi_write_same_complete, data); } static void scsi_disk_emulate_write_data(SCSIRequest *req) @@ -1785,7 +1788,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) break; default: - if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) { + if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) { scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); return 0; } @@ -1806,7 +1809,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) r->buflen = MAX(4096, req->cmd.xfer); if (!r->iov.iov_base) { - r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen); + r->iov.iov_base = blk_blockalign(s->qdev.conf.blk, r->buflen); } buflen = req->cmd.xfer; @@ -1814,7 +1817,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) memset(outbuf, 0, r->buflen); switch (req->cmd.buf[0]) { case TEST_UNIT_READY: - assert(!s->tray_open && bdrv_is_inserted(s->qdev.conf.bs)); + assert(!s->tray_open && blk_is_inserted(s->qdev.conf.blk)); break; case INQUIRY: buflen = scsi_disk_emulate_inquiry(req, outbuf); @@ -1862,12 +1865,12 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) break; case ALLOW_MEDIUM_REMOVAL: s->tray_locked = req->cmd.buf[4] & 1; - bdrv_lock_medium(s->qdev.conf.bs, req->cmd.buf[4] & 1); + blk_lock_medium(s->qdev.conf.blk, req->cmd.buf[4] & 1); break; case READ_CAPACITY_10: /* The normal LEN field for this command is zero. */ memset(outbuf, 0, 8); - bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors); + blk_get_geometry(s->qdev.conf.blk, &nb_sectors); if (!nb_sectors) { scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY)); return 0; @@ -1936,7 +1939,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) if ((req->cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) { DPRINTF("SAI READ CAPACITY(16)\n"); memset(outbuf, 0, req->cmd.xfer); - bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors); + blk_get_geometry(s->qdev.conf.blk, &nb_sectors); if (!nb_sectors) { scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY)); return 0; @@ -1977,9 +1980,9 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) case SYNCHRONIZE_CACHE: /* The request is used as the AIO opaque value, so add a ref. */ scsi_req_ref(&r->req); - block_acct_start(bdrv_get_stats(s->qdev.conf.bs), &r->acct, 0, + block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, 0, BLOCK_ACCT_FLUSH); - r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r); + r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_aio_complete, r); return 0; case SEEK_10: DPRINTF("Seek(10) (sector %" PRId64 ")\n", r->req.cmd.lba); @@ -2053,7 +2056,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) command = buf[0]; - if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) { + if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) { scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); return 0; } @@ -2081,7 +2084,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) case WRITE_VERIFY_10: case WRITE_VERIFY_12: case WRITE_VERIFY_16: - if (bdrv_is_read_only(s->qdev.conf.bs)) { + if (blk_is_read_only(s->qdev.conf.blk)) { scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED)); return 0; } @@ -2124,7 +2127,7 @@ static void scsi_disk_reset(DeviceState *dev) scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET)); - bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors); + blk_get_geometry(s->qdev.conf.blk, &nb_sectors); nb_sectors /= s->qdev.blocksize / 512; if (nb_sectors) { nb_sectors--; @@ -2140,7 +2143,7 @@ static void scsi_unrealize(SCSIDevice *dev, Error **errp) SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE)); - blockdev_mark_auto_del(s->qdev.conf.bs); + blockdev_mark_auto_del(s->qdev.conf.blk); } static void scsi_disk_resize_cb(void *opaque) @@ -2223,13 +2226,13 @@ static void scsi_realize(SCSIDevice *dev, Error **errp) SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); Error *err = NULL; - if (!s->qdev.conf.bs) { + if (!s->qdev.conf.blk) { error_setg(errp, "drive property not set"); return; } if (!(s->features & (1 << SCSI_DISK_F_REMOVABLE)) && - !bdrv_is_inserted(s->qdev.conf.bs)) { + !blk_is_inserted(s->qdev.conf.blk)) { error_setg(errp, "Device needs media, but drive is empty"); return; } @@ -2255,20 +2258,20 @@ static void scsi_realize(SCSIDevice *dev, Error **errp) s->vendor = g_strdup("QEMU"); } - if (bdrv_is_sg(s->qdev.conf.bs)) { + if (blk_is_sg(s->qdev.conf.blk)) { error_setg(errp, "unwanted /dev/sg*"); return; } if ((s->features & (1 << SCSI_DISK_F_REMOVABLE)) && !(s->features & (1 << SCSI_DISK_F_NO_REMOVABLE_DEVOPS))) { - bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_disk_removable_block_ops, s); + blk_set_dev_ops(s->qdev.conf.blk, &scsi_disk_removable_block_ops, s); } else { - bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_disk_block_ops, s); + blk_set_dev_ops(s->qdev.conf.blk, &scsi_disk_block_ops, s); } - bdrv_set_guest_block_size(s->qdev.conf.bs, s->qdev.blocksize); + blk_set_guest_block_size(s->qdev.conf.blk, s->qdev.blocksize); - bdrv_iostatus_enable(s->qdev.conf.bs); + blk_iostatus_enable(s->qdev.conf.blk); } static void scsi_hd_realize(SCSIDevice *dev, Error **errp) @@ -2299,15 +2302,15 @@ static void scsi_disk_realize(SCSIDevice *dev, Error **errp) DriveInfo *dinfo; Error *local_err = NULL; - if (!dev->conf.bs) { + if (!dev->conf.blk) { scsi_realize(dev, &local_err); assert(local_err); error_propagate(errp, local_err); return; } - dinfo = drive_get_by_blockdev(dev->conf.bs); - if (dinfo->media_cd) { + dinfo = blk_legacy_dinfo(dev->conf.blk); + if (dinfo && dinfo->media_cd) { scsi_cd_realize(dev, errp); } else { scsi_hd_realize(dev, errp); @@ -2406,7 +2409,6 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun, #ifdef __linux__ static int get_device_type(SCSIDiskState *s) { - BlockDriverState *bdrv = s->qdev.conf.bs; uint8_t cmd[16]; uint8_t buf[36]; uint8_t sensebuf[8]; @@ -2429,7 +2431,7 @@ static int get_device_type(SCSIDiskState *s) io_header.sbp = sensebuf; io_header.timeout = 6000; /* XXX */ - ret = bdrv_ioctl(bdrv, SG_IO, &io_header); + ret = blk_ioctl(s->qdev.conf.blk, SG_IO, &io_header); if (ret < 0 || io_header.driver_status || io_header.host_status) { return -1; } @@ -2446,13 +2448,13 @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp) int sg_version; int rc; - if (!s->qdev.conf.bs) { + if (!s->qdev.conf.blk) { error_setg(errp, "drive property not set"); return; } /* check we are using a driver managing SG_IO (version 3 and after) */ - rc = bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version); + rc = blk_ioctl(s->qdev.conf.blk, SG_GET_VERSION_NUM, &sg_version); if (rc < 0) { error_setg(errp, "cannot get SG_IO version number: %s. " "Is this a SCSI device?", @@ -2511,7 +2513,7 @@ static bool scsi_block_is_passthrough(SCSIDiskState *s, uint8_t *buf) * ones (such as WRITE SAME or EXTENDED COPY, etc.). So, without * O_DIRECT everything must go through SG_IO. */ - if (!(bdrv_get_flags(s->qdev.conf.bs) & BDRV_O_NOCACHE)) { + if (!(blk_get_flags(s->qdev.conf.blk) & BDRV_O_NOCACHE)) { break; } @@ -2660,7 +2662,7 @@ static const TypeInfo scsi_cd_info = { #ifdef __linux__ static Property scsi_block_properties[] = { - DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.bs), + DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 84a1d5b..f2e53af 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -14,6 +14,7 @@ #include "qemu-common.h" #include "qemu/error-report.h" #include "hw/scsi/scsi.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #ifdef __linux__ @@ -141,9 +142,9 @@ done: scsi_req_unref(&r->req); } -static int execute_command(BlockDriverState *bdrv, +static int execute_command(BlockBackend *blk, SCSIGenericReq *r, int direction, - BlockDriverCompletionFunc *complete) + BlockCompletionFunc *complete) { r->io_header.interface_id = 'S'; r->io_header.dxfer_direction = direction; @@ -157,7 +158,7 @@ static int execute_command(BlockDriverState *bdrv, r->io_header.usr_ptr = r; r->io_header.flags |= SG_FLAG_DIRECT_IO; - r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r); + r->req.aiocb = blk_aio_ioctl(blk, SG_IO, &r->io_header, complete, r); if (r->req.aiocb == NULL) { return -EIO; } @@ -193,7 +194,7 @@ static void scsi_read_complete(void * opaque, int ret) s->blocksize = ldl_be_p(&r->buf[8]); s->max_lba = ldq_be_p(&r->buf[0]); } - bdrv_set_guest_block_size(s->conf.bs, s->blocksize); + blk_set_guest_block_size(s->conf.blk, s->blocksize); scsi_req_data(&r->req, len); scsi_req_unref(&r->req); @@ -216,7 +217,8 @@ static void scsi_read_data(SCSIRequest *req) return; } - ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete); + ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV, + scsi_read_complete); if (ret < 0) { scsi_command_complete(r, ret); } @@ -260,7 +262,7 @@ static void scsi_write_data(SCSIRequest *req) /* The request is used as the AIO opaque value, so add a ref. */ scsi_req_ref(&r->req); - ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete); + ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete); if (ret < 0) { scsi_command_complete(r, ret); } @@ -302,7 +304,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) r->buf = NULL; /* The request is used as the AIO opaque value, so add a ref. */ scsi_req_ref(&r->req); - ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete); + ret = execute_command(s->conf.blk, r, SG_DXFER_NONE, + scsi_command_complete); if (ret < 0) { scsi_command_complete(r, ret); return 0; @@ -327,7 +330,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) } } -static int get_stream_blocksize(BlockDriverState *bdrv) +static int get_stream_blocksize(BlockBackend *blk) { uint8_t cmd[6]; uint8_t buf[12]; @@ -351,7 +354,7 @@ static int get_stream_blocksize(BlockDriverState *bdrv) io_header.sbp = sensebuf; io_header.timeout = 6000; /* XXX */ - ret = bdrv_ioctl(bdrv, SG_IO, &io_header); + ret = blk_ioctl(blk, SG_IO, &io_header); if (ret < 0 || io_header.driver_status || io_header.host_status) { return -1; } @@ -368,7 +371,7 @@ static void scsi_generic_reset(DeviceState *dev) static void scsi_unrealize(SCSIDevice *s, Error **errp) { scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE)); - blockdev_mark_auto_del(s->conf.bs); + blockdev_mark_auto_del(s->conf.blk); } static void scsi_generic_realize(SCSIDevice *s, Error **errp) @@ -377,22 +380,22 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp) int sg_version; struct sg_scsi_id scsiid; - if (!s->conf.bs) { + if (!s->conf.blk) { error_setg(errp, "drive property not set"); return; } - if (bdrv_get_on_error(s->conf.bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) { + if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) { error_setg(errp, "Device doesn't support drive option werror"); return; } - if (bdrv_get_on_error(s->conf.bs, 1) != BLOCKDEV_ON_ERROR_REPORT) { + if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) { error_setg(errp, "Device doesn't support drive option rerror"); return; } /* check we are using a driver managing SG_IO (version 3 and after */ - rc = bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version); + rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version); if (rc < 0) { error_setg(errp, "cannot get SG_IO version number: %s. " "Is this a SCSI device?", @@ -405,7 +408,7 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp) } /* get LUN of the /dev/sg? */ - if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) { + if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) { error_setg(errp, "SG_GET_SCSI_ID ioctl failed"); return; } @@ -416,7 +419,7 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp) switch (s->type) { case TYPE_TAPE: - s->blocksize = get_stream_blocksize(s->conf.bs); + s->blocksize = get_stream_blocksize(s->conf.blk); if (s->blocksize == -1) { s->blocksize = 0; } @@ -459,7 +462,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun, } static Property scsi_generic_properties[] = { - DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.bs), + DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index b778e05..48dcfd2 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -13,6 +13,7 @@ #include "hw/virtio/virtio-scsi.h" #include "qemu/error-report.h" +#include "sysemu/block-backend.h" #include <hw/scsi/scsi.h> #include <block/scsi.h> #include <hw/virtio/virtio-bus.h> @@ -205,7 +206,7 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s) aio_set_event_notifier(s->ctx, &s->cmd_vrings[i]->host_notifier, NULL); } - bdrv_drain_all(); /* ensure there are no in-flight requests */ + blk_drain_all(); /* ensure there are no in-flight requests */ aio_context_release(s->ctx); diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 8547ea0..a1725b8 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -16,6 +16,7 @@ #include "hw/virtio/virtio-scsi.h" #include "qemu/error-report.h" #include "qemu/iov.h" +#include "sysemu/block-backend.h" #include <hw/scsi/scsi.h> #include <block/scsi.h> #include <hw/virtio/virtio-bus.h> @@ -236,9 +237,9 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) int target; int ret = 0; - if (s->dataplane_started && bdrv_get_aio_context(d->conf.bs) != s->ctx) { + if (s->dataplane_started && blk_get_aio_context(d->conf.blk) != s->ctx) { aio_context_acquire(s->ctx); - bdrv_set_aio_context(d->conf.bs, s->ctx); + blk_set_aio_context(d->conf.blk, s->ctx); aio_context_release(s->ctx); } /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */ @@ -522,9 +523,9 @@ bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req) virtio_scsi_complete_cmd_req(req); return false; } - if (s->dataplane_started && bdrv_get_aio_context(d->conf.bs) != s->ctx) { + if (s->dataplane_started && blk_get_aio_context(d->conf.blk) != s->ctx) { aio_context_acquire(s->ctx); - bdrv_set_aio_context(d->conf.bs, s->ctx); + blk_set_aio_context(d->conf.blk, s->ctx); aio_context_release(s->ctx); } req->sreq = scsi_req_new(d, req->req.cmd.tag, @@ -539,7 +540,7 @@ bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req) return false; } scsi_req_ref(req->sreq); - bdrv_io_plug(d->conf.bs); + blk_io_plug(d->conf.blk); return true; } @@ -549,7 +550,7 @@ void virtio_scsi_handle_cmd_req_submit(VirtIOSCSI *s, VirtIOSCSIReq *req) if (scsi_req_enqueue(sreq)) { scsi_req_continue(sreq); } - bdrv_io_unplug(sreq->dev->conf.bs); + blk_io_unplug(sreq->dev->conf.blk); scsi_req_unref(sreq); } @@ -832,7 +833,7 @@ static void virtio_scsi_migration_state_changed(Notifier *notifier, void *data) if (s->dataplane_started) { return; } - bdrv_drain_all(); /* complete in-flight non-dataplane requests */ + blk_drain_all(); /* complete in-flight non-dataplane requests */ s->dataplane_disabled = false; } } diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index 2a40f92..9661eaf 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -26,6 +26,7 @@ #include "sysemu/sysemu.h" #include "trace.h" #include "qemu/error-report.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/sd.h" @@ -252,14 +253,16 @@ static int milkymist_memcard_init(SysBusDevice *dev) { MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev); DriveInfo *dinfo; + BlockBackend *blk; dinfo = drive_get_next(IF_SD); - s->card = sd_init(dinfo ? dinfo->bdrv : NULL, false); + blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; + s->card = sd_init(blk, false); if (s->card == NULL) { return -1; } - s->enabled = dinfo ? bdrv_is_inserted(dinfo->bdrv) : 0; + s->enabled = blk && blk_is_inserted(blk); memory_region_init_io(&s->regs_region, OBJECT(s), &memcard_mmio_ops, s, "milkymist-memcard", R_MAX * 4); diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c index 6c92149..86c477d 100644 --- a/hw/sd/omap_mmc.c +++ b/hw/sd/omap_mmc.c @@ -574,7 +574,7 @@ static void omap_mmc_cover_cb(void *opaque, int line, int level) struct omap_mmc_s *omap_mmc_init(hwaddr base, MemoryRegion *sysmem, - BlockDriverState *bd, + BlockBackend *blk, qemu_irq irq, qemu_irq dma[], omap_clk clk) { struct omap_mmc_s *s = (struct omap_mmc_s *) @@ -592,7 +592,7 @@ struct omap_mmc_s *omap_mmc_init(hwaddr base, memory_region_add_subregion(sysmem, base, &s->iomem); /* Instantiate the storage */ - s->card = sd_init(bd, false); + s->card = sd_init(blk, false); if (s->card == NULL) { exit(1); } @@ -601,7 +601,7 @@ struct omap_mmc_s *omap_mmc_init(hwaddr base, } struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta, - BlockDriverState *bd, qemu_irq irq, qemu_irq dma[], + BlockBackend *blk, qemu_irq irq, qemu_irq dma[], omap_clk fclk, omap_clk iclk) { struct omap_mmc_s *s = (struct omap_mmc_s *) @@ -620,7 +620,7 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta, omap_l4_attach(ta, 0, &s->iomem); /* Instantiate the storage */ - s->card = sd_init(bd, false); + s->card = sd_init(blk, false); if (s->card == NULL) { exit(1); } diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c index 462558b..e704b6e 100644 --- a/hw/sd/pl181.c +++ b/hw/sd/pl181.c @@ -7,6 +7,7 @@ * This code is licensed under the GPL. */ +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/sysbus.h" #include "hw/sd.h" @@ -490,7 +491,7 @@ static int pl181_init(SysBusDevice *sbd) sysbus_init_irq(sbd, &s->irq[1]); qdev_init_gpio_out(dev, s->cardstatus, 2); dinfo = drive_get_next(IF_SD); - s->card = sd_init(dinfo ? dinfo->bdrv : NULL, false); + s->card = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, false); if (s->card == NULL) { return -1; } diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c index b9d8b1a..ac3ab39 100644 --- a/hw/sd/pxa2xx_mmci.c +++ b/hw/sd/pxa2xx_mmci.c @@ -523,7 +523,7 @@ static int pxa2xx_mmci_load(QEMUFile *f, void *opaque, int version_id) PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, hwaddr base, - BlockDriverState *bd, qemu_irq irq, + BlockBackend *blk, qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma) { PXA2xxMMCIState *s; @@ -538,7 +538,7 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, memory_region_add_subregion(sysmem, base, &s->iomem); /* Instantiate the actual storage */ - s->card = sd_init(bd, false); + s->card = sd_init(blk, false); if (s->card == NULL) { exit(1); } @@ -30,7 +30,7 @@ */ #include "hw/hw.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "hw/sd.h" #include "qemu/bitmap.h" @@ -110,7 +110,7 @@ struct SDState { uint8_t data[512]; qemu_irq readonly_cb; qemu_irq inserted_cb; - BlockDriverState *bdrv; + BlockBackend *blk; uint8_t *buf; bool enable; @@ -389,13 +389,13 @@ static inline uint64_t sd_addr_to_wpnum(uint64_t addr) return addr >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT); } -static void sd_reset(SDState *sd, BlockDriverState *bdrv) +static void sd_reset(SDState *sd, BlockBackend *blk) { uint64_t size; uint64_t sect; - if (bdrv) { - bdrv_get_geometry(bdrv, §); + if (blk) { + blk_get_geometry(blk, §); } else { sect = 0; } @@ -412,11 +412,11 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv) sd_set_cardstatus(sd); sd_set_sdstatus(sd); - sd->bdrv = bdrv; + sd->blk = blk; if (sd->wp_groups) g_free(sd->wp_groups); - sd->wp_switch = bdrv ? bdrv_is_read_only(bdrv) : false; + sd->wp_switch = blk ? blk_is_read_only(blk) : false; sd->wpgrps_size = sect; sd->wp_groups = bitmap_new(sd->wpgrps_size); memset(sd->function_group, 0, sizeof(sd->function_group)); @@ -432,9 +432,9 @@ static void sd_cardchange(void *opaque, bool load) { SDState *sd = opaque; - qemu_set_irq(sd->inserted_cb, bdrv_is_inserted(sd->bdrv)); - if (bdrv_is_inserted(sd->bdrv)) { - sd_reset(sd, sd->bdrv); + qemu_set_irq(sd->inserted_cb, blk_is_inserted(sd->blk)); + if (blk_is_inserted(sd->blk)) { + sd_reset(sd, sd->blk); qemu_set_irq(sd->readonly_cb, sd->wp_switch); } } @@ -479,23 +479,23 @@ static const VMStateDescription sd_vmstate = { whether card should be in SSI or MMC/SD mode. It is also up to the board to ensure that ssi transfers only occur when the chip select is asserted. */ -SDState *sd_init(BlockDriverState *bs, bool is_spi) +SDState *sd_init(BlockBackend *blk, bool is_spi) { SDState *sd; - if (bs && bdrv_is_read_only(bs)) { + if (blk && blk_is_read_only(blk)) { fprintf(stderr, "sd_init: Cannot use read-only drive\n"); return NULL; } sd = (SDState *) g_malloc0(sizeof(SDState)); - sd->buf = qemu_blockalign(bs, 512); + sd->buf = blk_blockalign(blk, 512); sd->spi = is_spi; sd->enable = true; - sd_reset(sd, bs); - if (sd->bdrv) { - bdrv_attach_dev_nofail(sd->bdrv, sd); - bdrv_set_dev_ops(sd->bdrv, &sd_block_ops, sd); + sd_reset(sd, blk); + if (sd->blk) { + blk_attach_dev_nofail(sd->blk, sd); + blk_set_dev_ops(sd->blk, &sd_block_ops, sd); } vmstate_register(NULL, -1, &sd_vmstate, sd); return sd; @@ -505,8 +505,8 @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert) { sd->readonly_cb = readonly; sd->inserted_cb = insert; - qemu_set_irq(readonly, sd->bdrv ? bdrv_is_read_only(sd->bdrv) : 0); - qemu_set_irq(insert, sd->bdrv ? bdrv_is_inserted(sd->bdrv) : 0); + qemu_set_irq(readonly, sd->blk ? blk_is_read_only(sd->blk) : 0); + qemu_set_irq(insert, sd->blk ? blk_is_inserted(sd->blk) : 0); } static void sd_erase(SDState *sd) @@ -680,7 +680,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, default: sd->state = sd_idle_state; - sd_reset(sd, sd->bdrv); + sd_reset(sd, sd->blk); return sd->spi ? sd_r1 : sd_r0; } break; @@ -1347,7 +1347,7 @@ int sd_do_command(SDState *sd, SDRequest *req, sd_rsp_type_t rtype; int rsplen; - if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable) { + if (!sd->blk || !blk_is_inserted(sd->blk) || !sd->enable) { return 0; } @@ -1456,7 +1456,7 @@ static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len) DPRINTF("sd_blk_read: addr = 0x%08llx, len = %d\n", (unsigned long long) addr, len); - if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) < 0) { + if (!sd->blk || blk_read(sd->blk, addr >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_read: read error on host side\n"); return; } @@ -1464,7 +1464,7 @@ static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len) if (end > (addr & ~511) + 512) { memcpy(sd->data, sd->buf + (addr & 511), 512 - (addr & 511)); - if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) < 0) { + if (blk_read(sd->blk, end >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_read: read error on host side\n"); return; } @@ -1478,29 +1478,29 @@ static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len) uint64_t end = addr + len; if ((addr & 511) || len < 512) - if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) < 0) { + if (!sd->blk || blk_read(sd->blk, addr >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_write: read error on host side\n"); return; } if (end > (addr & ~511) + 512) { memcpy(sd->buf + (addr & 511), sd->data, 512 - (addr & 511)); - if (bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) < 0) { + if (blk_write(sd->blk, addr >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_write: write error on host side\n"); return; } - if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) < 0) { + if (blk_read(sd->blk, end >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_write: read error on host side\n"); return; } memcpy(sd->buf, sd->data + 512 - (addr & 511), end & 511); - if (bdrv_write(sd->bdrv, end >> 9, sd->buf, 1) < 0) { + if (blk_write(sd->blk, end >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_write: write error on host side\n"); } } else { memcpy(sd->buf + (addr & 511), sd->data, len); - if (!sd->bdrv || bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) < 0) { + if (!sd->blk || blk_write(sd->blk, addr >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_write: write error on host side\n"); } } @@ -1515,7 +1515,7 @@ void sd_write_data(SDState *sd, uint8_t value) { int i; - if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable) + if (!sd->blk || !blk_is_inserted(sd->blk) || !sd->enable) return; if (sd->state != sd_receivingdata_state) { @@ -1641,7 +1641,7 @@ uint8_t sd_read_data(SDState *sd) uint8_t ret; int io_len; - if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable) + if (!sd->blk || !blk_is_inserted(sd->blk) || !sd->enable) return 0x00; if (sd->state != sd_sendingdata_state) { diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index f9fe700..b380050 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -23,6 +23,7 @@ */ #include "hw/hw.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "sysemu/dma.h" #include "qemu/timer.h" @@ -1165,7 +1166,7 @@ static void sdhci_initfn(Object *obj) DriveInfo *di; di = drive_get_next(IF_SD); - s->card = sd_init(di ? di->bdrv : NULL, false); + s->card = sd_init(di ? blk_by_legacy_dinfo(di) : NULL, false); if (s->card == NULL) { exit(1); } diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index b012e57..a71fbca 100644 --- a/hw/sd/ssi-sd.c +++ b/hw/sd/ssi-sd.c @@ -10,6 +10,7 @@ * GNU GPL, version 2 or (at your option) any later version. */ +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/ssi.h" #include "hw/sd.h" @@ -255,7 +256,7 @@ static int ssi_sd_init(SSISlave *d) s->mode = SSI_SD_CMD; dinfo = drive_get_next(IF_SD); - s->sd = sd_init(dinfo ? dinfo->bdrv : NULL, true); + s->sd = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, true); if (s->sd == NULL) { return -1; } diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c index 321379e..12f44d2 100644 --- a/hw/sh4/r2d.c +++ b/hw/sh4/r2d.c @@ -36,7 +36,7 @@ #include "hw/loader.h" #include "hw/usb.h" #include "hw/block/flash.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #define FLASH_BASE 0x00000000 @@ -290,8 +290,8 @@ static void r2d_init(MachineState *machine) /* onboard flash memory */ dinfo = drive_get(IF_PFLASH, 0, 0); pflash_cfi02_register(0x0, NULL, "r2d.flash", FLASH_SIZE, - dinfo ? dinfo->bdrv : NULL, (16 * 1024), - FLASH_SIZE >> 16, + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, + (16 * 1024), FLASH_SIZE >> 16, 1, 4, 0x0000, 0x0000, 0x0000, 0x0000, 0x555, 0x2aa, 0); diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 2feab35..8273199 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -40,7 +40,7 @@ #include "hw/empty_slot.h" #include "hw/loader.h" #include "elf.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "trace.h" /* diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 871a0ea..f42112c 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -38,7 +38,7 @@ #include "hw/ide.h" #include "hw/loader.h" #include "elf.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" //#define DEBUG_IRQ diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 82747ee..c0e7cd7 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -21,7 +21,7 @@ #include "sysemu/tpm_backend.h" #include "tpm_int.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #include "hw/hw.h" #include "hw/i386/pc.h" diff --git a/hw/tricore/tricore_testboard.c b/hw/tricore/tricore_testboard.c index 605de86..eeb4922 100644 --- a/hw/tricore/tricore_testboard.c +++ b/hw/tricore/tricore_testboard.c @@ -24,7 +24,7 @@ #include "sysemu/sysemu.h" #include "hw/boards.h" #include "hw/loader.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "exec/address-spaces.h" #include "hw/block/flash.h" #include "elf.h" diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index 467ec86..507c966 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -104,6 +104,37 @@ static const USBDescIface desc_iface_mouse = { }, }; +static const USBDescIface desc_iface_mouse2 = { + .bInterfaceNumber = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_HID, + .bInterfaceSubClass = 0x01, /* boot */ + .bInterfaceProtocol = 0x02, + .ndesc = 1, + .descs = (USBDescOther[]) { + { + /* HID descriptor */ + .data = (uint8_t[]) { + 0x09, /* u8 bLength */ + USB_DT_HID, /* u8 bDescriptorType */ + 0x01, 0x00, /* u16 HID_class */ + 0x00, /* u8 country_code */ + 0x01, /* u8 num_descriptors */ + USB_DT_REPORT, /* u8 type: Report */ + 52, 0, /* u16 len */ + }, + }, + }, + .eps = (USBDescEndpoint[]) { + { + .bEndpointAddress = USB_DIR_IN | 0x01, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = 4, + .bInterval = 7, /* 2 ^ (8-1) * 125 usecs = 8 ms */ + }, + }, +}; + static const USBDescIface desc_iface_tablet = { .bInterfaceNumber = 0, .bNumEndpoints = 1, @@ -195,6 +226,37 @@ static const USBDescIface desc_iface_keyboard = { }, }; +static const USBDescIface desc_iface_keyboard2 = { + .bInterfaceNumber = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_HID, + .bInterfaceSubClass = 0x01, /* boot */ + .bInterfaceProtocol = 0x01, /* keyboard */ + .ndesc = 1, + .descs = (USBDescOther[]) { + { + /* HID descriptor */ + .data = (uint8_t[]) { + 0x09, /* u8 bLength */ + USB_DT_HID, /* u8 bDescriptorType */ + 0x11, 0x01, /* u16 HID_class */ + 0x00, /* u8 country_code */ + 0x01, /* u8 num_descriptors */ + USB_DT_REPORT, /* u8 type: Report */ + 0x3f, 0, /* u16 len */ + }, + }, + }, + .eps = (USBDescEndpoint[]) { + { + .bEndpointAddress = USB_DIR_IN | 0x01, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = 8, + .bInterval = 7, /* 2 ^ (8-1) * 125 usecs = 8 ms */ + }, + }, +}; + static const USBDescDevice desc_device_mouse = { .bcdUSB = 0x0100, .bMaxPacketSize0 = 8, @@ -212,6 +274,23 @@ static const USBDescDevice desc_device_mouse = { }, }; +static const USBDescDevice desc_device_mouse2 = { + .bcdUSB = 0x0200, + .bMaxPacketSize0 = 64, + .bNumConfigurations = 1, + .confs = (USBDescConfig[]) { + { + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = STR_CONFIG_MOUSE, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP, + .bMaxPower = 50, + .nif = 1, + .ifs = &desc_iface_mouse2, + }, + }, +}; + static const USBDescDevice desc_device_tablet = { .bcdUSB = 0x0100, .bMaxPacketSize0 = 8, @@ -263,6 +342,23 @@ static const USBDescDevice desc_device_keyboard = { }, }; +static const USBDescDevice desc_device_keyboard2 = { + .bcdUSB = 0x0200, + .bMaxPacketSize0 = 64, + .bNumConfigurations = 1, + .confs = (USBDescConfig[]) { + { + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = STR_CONFIG_KEYBOARD, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP, + .bMaxPower = 50, + .nif = 1, + .ifs = &desc_iface_keyboard2, + }, + }, +}; + static const USBDescMSOS desc_msos_suspend = { .SelectiveSuspendEnabled = true, }; @@ -281,6 +377,21 @@ static const USBDesc desc_mouse = { .msos = &desc_msos_suspend, }; +static const USBDesc desc_mouse2 = { + .id = { + .idVendor = 0x0627, + .idProduct = 0x0001, + .bcdDevice = 0, + .iManufacturer = STR_MANUFACTURER, + .iProduct = STR_PRODUCT_MOUSE, + .iSerialNumber = STR_SERIALNUMBER, + }, + .full = &desc_device_mouse, + .high = &desc_device_mouse2, + .str = desc_strings, + .msos = &desc_msos_suspend, +}; + static const USBDesc desc_tablet = { .id = { .idVendor = 0x0627, @@ -324,6 +435,21 @@ static const USBDesc desc_keyboard = { .msos = &desc_msos_suspend, }; +static const USBDesc desc_keyboard2 = { + .id = { + .idVendor = 0x0627, + .idProduct = 0x0001, + .bcdDevice = 0, + .iManufacturer = STR_MANUFACTURER, + .iProduct = STR_PRODUCT_KEYBOARD, + .iSerialNumber = STR_SERIALNUMBER, + }, + .full = &desc_device_keyboard, + .high = &desc_device_keyboard2, + .str = desc_strings, + .msos = &desc_msos_suspend, +}; + static const uint8_t qemu_mouse_hid_report_descriptor[] = { 0x05, 0x01, /* Usage Page (Generic Desktop) */ 0x09, 0x02, /* Usage (Mouse) */ @@ -566,9 +692,26 @@ static void usb_hid_handle_destroy(USBDevice *dev) hid_free(&us->hid); } -static void usb_hid_initfn(USBDevice *dev, int kind) +static void usb_hid_initfn(USBDevice *dev, int kind, + const USBDesc *usb1, const USBDesc *usb2, + Error **errp) { USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); + switch (us->usb_version) { + case 1: + dev->usb_desc = usb1; + break; + case 2: + dev->usb_desc = usb2; + break; + default: + dev->usb_desc = NULL; + } + if (!dev->usb_desc) { + error_setg(errp, "Invalid usb version %d for usb hid device", + us->usb_version); + return; + } if (dev->serial) { usb_desc_set_string(dev, STR_SERIALNUMBER, dev->serial); @@ -583,32 +726,18 @@ static void usb_hid_initfn(USBDevice *dev, int kind) static void usb_tablet_realize(USBDevice *dev, Error **errp) { - USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); - switch (us->usb_version) { - case 1: - dev->usb_desc = &desc_tablet; - break; - case 2: - dev->usb_desc = &desc_tablet2; - break; - default: - error_setg(errp, "Invalid usb version %d for usb-tablet " - "(must be 1 or 2)", us->usb_version); - return; - } - - usb_hid_initfn(dev, HID_TABLET); + usb_hid_initfn(dev, HID_TABLET, &desc_tablet, &desc_tablet2, errp); } static void usb_mouse_realize(USBDevice *dev, Error **errp) { - usb_hid_initfn(dev, HID_MOUSE); + usb_hid_initfn(dev, HID_MOUSE, &desc_mouse, &desc_mouse2, errp); } static void usb_keyboard_realize(USBDevice *dev, Error **errp) { - usb_hid_initfn(dev, HID_KEYBOARD); + usb_hid_initfn(dev, HID_KEYBOARD, &desc_keyboard, &desc_keyboard2, errp); } static int usb_ptr_post_load(void *opaque, int version_id) @@ -682,6 +811,11 @@ static const TypeInfo usb_tablet_info = { .class_init = usb_tablet_class_initfn, }; +static Property usb_mouse_properties[] = { + DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2), + DEFINE_PROP_END_OF_LIST(), +}; + static void usb_mouse_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -690,8 +824,8 @@ static void usb_mouse_class_initfn(ObjectClass *klass, void *data) usb_hid_class_initfn(klass, data); uc->realize = usb_mouse_realize; uc->product_desc = "QEMU USB Mouse"; - uc->usb_desc = &desc_mouse; dc->vmsd = &vmstate_usb_ptr; + dc->props = usb_mouse_properties; set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } @@ -703,6 +837,7 @@ static const TypeInfo usb_mouse_info = { }; static Property usb_keyboard_properties[] = { + DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2), DEFINE_PROP_STRING("display", USBHIDState, display), DEFINE_PROP_END_OF_LIST(), }; @@ -715,7 +850,6 @@ static void usb_keyboard_class_initfn(ObjectClass *klass, void *data) usb_hid_class_initfn(klass, data); uc->realize = usb_keyboard_realize; uc->product_desc = "QEMU USB Keyboard"; - uc->usb_desc = &desc_keyboard; dc->vmsd = &vmstate_usb_kbd; dc->props = usb_keyboard_properties; set_bit(DEVICE_CATEGORY_INPUT, dc->categories); diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 5bfc72c..4539733 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -16,6 +16,7 @@ #include "ui/console.h" #include "monitor/monitor.h" #include "sysemu/sysemu.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "qapi/visitor.h" @@ -600,11 +601,11 @@ static const struct SCSIBusInfo usb_msd_scsi_info_bot = { static void usb_msd_realize_storage(USBDevice *dev, Error **errp) { MSDState *s = DO_UPCAST(MSDState, dev, dev); - BlockDriverState *bs = s->conf.bs; + BlockBackend *blk = s->conf.blk; SCSIDevice *scsi_dev; Error *err = NULL; - if (!bs) { + if (!blk) { error_setg(errp, "drive property not set"); return; } @@ -620,14 +621,14 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp) * * The hack is probably a bad idea. */ - bdrv_detach_dev(bs, &s->dev.qdev); - s->conf.bs = NULL; + blk_detach_dev(blk, &s->dev.qdev); + s->conf.blk = NULL; usb_desc_create_serial(dev); usb_desc_init(dev); scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), &usb_msd_scsi_info_storage, NULL); - scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable, + scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable, s->conf.bootindex, dev->serial, &err); if (!scsi_dev) { @@ -637,9 +638,10 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp) usb_msd_handle_reset(dev); s->scsi_dev = scsi_dev; - if (bdrv_key_required(bs)) { + if (bdrv_key_required(blk_bs(blk))) { if (cur_mon) { - monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb, s); + monitor_read_bdrv_key_start(cur_mon, blk_bs(blk), + usb_msd_password_cb, s); s->dev.auto_attach = 0; } else { autostart = 0; @@ -707,7 +709,8 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename) if (!dev) { return NULL; } - if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { + if (qdev_prop_set_drive(&dev->qdev, "drive", + blk_by_legacy_dinfo(dinfo)) < 0) { object_unparent(OBJECT(dev)); return NULL; } diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index c556367..a27c9d3 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1608,12 +1608,6 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid, "data might be lost\n"); } - uint8_t ep = epid>>1; - - if (epid & 1) { - ep |= 0x80; - } - if (!xhci->slots[slotid-1].uport || !xhci->slots[slotid-1].uport->dev || !xhci->slots[slotid-1].uport->dev->attached) { diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index ae7fef9..542fb9e 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -29,7 +29,7 @@ #include "hw/pci/msix.h" #include "hw/loader.h" #include "sysemu/kvm.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "virtio-pci.h" #include "qemu/range.h" #include "hw/virtio/virtio-bus.h" diff --git a/hw/xen/xen_devconfig.c b/hw/xen/xen_devconfig.c index fa998ef..e138dbb 100644 --- a/hw/xen/xen_devconfig.c +++ b/hw/xen/xen_devconfig.c @@ -1,4 +1,5 @@ #include "hw/xen/xen_backend.h" +#include "sysemu/block-backend.h" #include "sysemu/blockdev.h" /* ------------------------------------------------------------- */ diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c index 3150064..2e545d2 100644 --- a/hw/xenpv/xen_machine_pv.c +++ b/hw/xenpv/xen_machine_pv.c @@ -26,7 +26,7 @@ #include "hw/boards.h" #include "hw/xen/xen_backend.h" #include "xen_domainbuild.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" static void xen_init_pv(MachineState *machine) { diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index ed06ff7..0100c31 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -35,7 +35,7 @@ #include "net/net.h" #include "hw/sysbus.h" #include "hw/block/flash.h" -#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "sysemu/char.h" #include "sysemu/device_tree.h" #include "qemu/error-report.h" @@ -230,7 +230,8 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) if (dinfo) { flash = pflash_cfi01_register(board->flash_base, NULL, "lx60.io.flash", board->flash_size, - dinfo->bdrv, board->flash_sector_size, + blk_by_legacy_dinfo(dinfo), + board->flash_sector_size, board->flash_size / board->flash_sector_size, 4, 0x0000, 0x0000, 0x0000, 0x0000, be); if (flash == NULL) { diff --git a/include/block/aio.h b/include/block/aio.h index 1562721..6bf0e04 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -22,25 +22,25 @@ #include "qemu/rfifolock.h" #include "qemu/timer.h" -typedef struct BlockDriverAIOCB BlockDriverAIOCB; -typedef void BlockDriverCompletionFunc(void *opaque, int ret); +typedef struct BlockAIOCB BlockAIOCB; +typedef void BlockCompletionFunc(void *opaque, int ret); typedef struct AIOCBInfo { - void (*cancel_async)(BlockDriverAIOCB *acb); - AioContext *(*get_aio_context)(BlockDriverAIOCB *acb); + void (*cancel_async)(BlockAIOCB *acb); + AioContext *(*get_aio_context)(BlockAIOCB *acb); size_t aiocb_size; } AIOCBInfo; -struct BlockDriverAIOCB { +struct BlockAIOCB { const AIOCBInfo *aiocb_info; BlockDriverState *bs; - BlockDriverCompletionFunc *cb; + BlockCompletionFunc *cb; void *opaque; int refcnt; }; void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque); + BlockCompletionFunc *cb, void *opaque); void qemu_aio_unref(void *p); void qemu_aio_ref(void *p); diff --git a/include/block/block.h b/include/block/block.h index 3318f0d..c9ec0ab 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -48,41 +48,6 @@ typedef struct BlockFragInfo { uint64_t compressed_clusters; } BlockFragInfo; -/* Callbacks for block device models */ -typedef struct BlockDevOps { - /* - * Runs when virtual media changed (monitor commands eject, change) - * Argument load is true on load and false on eject. - * Beware: doesn't run when a host device's physical media - * changes. Sure would be useful if it did. - * Device models with removable media must implement this callback. - */ - void (*change_media_cb)(void *opaque, bool load); - /* - * Runs when an eject request is issued from the monitor, the tray - * is closed, and the medium is locked. - * Device models that do not implement is_medium_locked will not need - * this callback. Device models that can lock the medium or tray might - * want to implement the callback and unlock the tray when "force" is - * true, even if they do not support eject requests. - */ - void (*eject_request_cb)(void *opaque, bool force); - /* - * Is the virtual tray open? - * Device models implement this only when the device has a tray. - */ - bool (*is_tray_open)(void *opaque); - /* - * Is the virtual medium locked into the device? - * Device models implement this only when device has such a lock. - */ - bool (*is_medium_locked)(void *opaque); - /* - * Runs when the size changed (e.g. monitor command block_resize) - */ - void (*resize_cb)(void *opaque); -} BlockDevOps; - typedef enum { BDRV_REQ_COPY_ON_READ = 0x1, BDRV_REQ_ZERO_WRITE = 0x2, @@ -204,7 +169,8 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name, int bdrv_create(BlockDriver *drv, const char* filename, QemuOpts *opts, Error **errp); int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp); -BlockDriverState *bdrv_new(const char *device_name, Error **errp); +BlockDriverState *bdrv_new_root(void); +BlockDriverState *bdrv_new(void); void bdrv_make_anon(BlockDriverState *bs); void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old); void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top); @@ -229,16 +195,6 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state); void bdrv_reopen_abort(BDRVReopenState *reopen_state); void bdrv_close(BlockDriverState *bs); void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify); -int bdrv_attach_dev(BlockDriverState *bs, void *dev); -void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev); -void bdrv_detach_dev(BlockDriverState *bs, void *dev); -void *bdrv_get_attached_dev(BlockDriverState *bs); -void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, - void *opaque); -void bdrv_dev_eject_request(BlockDriverState *bs, bool force); -bool bdrv_dev_has_removable_media(BlockDriverState *bs); -bool bdrv_dev_is_tray_open(BlockDriverState *bs); -bool bdrv_dev_is_medium_locked(BlockDriverState *bs); int bdrv_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors); int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num, @@ -247,9 +203,9 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors); int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num, int nb_sectors, BdrvRequestFlags flags); -BlockDriverAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, BdrvRequestFlags flags, - BlockDriverCompletionFunc *cb, void *opaque); +BlockAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, BdrvRequestFlags flags, + BlockCompletionFunc *cb, void *opaque); int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags); int bdrv_pread(BlockDriverState *bs, int64_t offset, void *buf, int count); @@ -325,19 +281,19 @@ BlockDriverState *check_to_replace_node(const char *node_name, Error **errp); /* async block I/O */ typedef void BlockDriverDirtyHandler(BlockDriverState *bs, int64_t sector, int sector_num); -BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *iov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); -BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *iov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); -BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque); -BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); -void bdrv_aio_cancel(BlockDriverAIOCB *acb); -void bdrv_aio_cancel_async(BlockDriverAIOCB *acb); +BlockAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, + QEMUIOVector *iov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, + QEMUIOVector *iov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *bdrv_aio_flush(BlockDriverState *bs, + BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *bdrv_aio_discard(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, + BlockCompletionFunc *cb, void *opaque); +void bdrv_aio_cancel(BlockAIOCB *acb); +void bdrv_aio_cancel_async(BlockAIOCB *acb); typedef struct BlockRequest { /* Fields to be filled by multiwrite caller */ @@ -345,7 +301,7 @@ typedef struct BlockRequest { int nb_sectors; int flags; QEMUIOVector *qiov; - BlockDriverCompletionFunc *cb; + BlockCompletionFunc *cb; void *opaque; /* Filled by multiwrite implementation */ @@ -357,9 +313,9 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, /* sg packet commands */ int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf); -BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, +BlockAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, unsigned long int req, void *buf, - BlockDriverCompletionFunc *cb, void *opaque); + BlockCompletionFunc *cb, void *opaque); /* Invalidate any cached metadata used by image formats */ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp); @@ -410,15 +366,13 @@ BlockDriverState *bdrv_lookup_bs(const char *device, Error **errp); bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base); BlockDriverState *bdrv_next(BlockDriverState *bs); -void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), - void *opaque); int bdrv_is_encrypted(BlockDriverState *bs); int bdrv_key_required(BlockDriverState *bs); 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_device_name(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, const uint8_t *buf, int nb_sectors); diff --git a/include/block/block_int.h b/include/block/block_int.h index 8d86a6c..8898c6c 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -128,17 +128,17 @@ struct BlockDriver { void (*bdrv_refresh_filename)(BlockDriverState *bs); /* aio */ - BlockDriverAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs, + BlockAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); - BlockDriverAIOCB *(*bdrv_aio_writev)(BlockDriverState *bs, + BlockCompletionFunc *cb, void *opaque); + BlockAIOCB *(*bdrv_aio_writev)(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); - BlockDriverAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs, - BlockDriverCompletionFunc *cb, void *opaque); - BlockDriverAIOCB *(*bdrv_aio_discard)(BlockDriverState *bs, + BlockCompletionFunc *cb, void *opaque); + BlockAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs, + BlockCompletionFunc *cb, void *opaque); + BlockAIOCB *(*bdrv_aio_discard)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); + BlockCompletionFunc *cb, void *opaque); int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); @@ -218,9 +218,9 @@ struct BlockDriver { /* to control generic scsi devices */ int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf); - BlockDriverAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs, + BlockAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf, - BlockDriverCompletionFunc *cb, void *opaque); + BlockCompletionFunc *cb, void *opaque); /* List of options for creating images, terminated by name == NULL */ QemuOptsList *create_opts; @@ -324,10 +324,7 @@ struct BlockDriverState { BlockDriver *drv; /* NULL means no media */ void *opaque; - void *dev; /* attached device model, if any */ - /* TODO change to DeviceState when all users are qdevified */ - const BlockDevOps *dev_ops; - void *dev_opaque; + BlockBackend *blk; /* owning backend, if any */ AioContext *aio_context; /* event loop used for fd handlers, timers, etc */ /* long-running tasks intended to always use the same AioContext as this @@ -390,8 +387,6 @@ struct BlockDriverState { char node_name[32]; /* element of the list of named nodes building the graph */ QTAILQ_ENTRY(BlockDriverState) node_list; - /* Device name is the name associated with the "drive" the guest sees */ - char device_name[32]; /* element of the list of "drives" the guest sees */ QTAILQ_ENTRY(BlockDriverState) device_list; QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps; @@ -501,7 +496,7 @@ int is_windows_drive(const char *filename); */ void stream_start(BlockDriverState *bs, BlockDriverState *base, const char *base_id, int64_t speed, BlockdevOnError on_error, - BlockDriverCompletionFunc *cb, + BlockCompletionFunc *cb, void *opaque, Error **errp); /** @@ -519,7 +514,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base, */ void commit_start(BlockDriverState *bs, BlockDriverState *base, BlockDriverState *top, int64_t speed, - BlockdevOnError on_error, BlockDriverCompletionFunc *cb, + BlockdevOnError on_error, BlockCompletionFunc *cb, void *opaque, const char *backing_file_str, Error **errp); /** * commit_active_start: @@ -535,7 +530,7 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base, void commit_active_start(BlockDriverState *bs, BlockDriverState *base, int64_t speed, BlockdevOnError on_error, - BlockDriverCompletionFunc *cb, + BlockCompletionFunc *cb, void *opaque, Error **errp); /* * mirror_start: @@ -563,7 +558,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target, int64_t speed, int64_t granularity, int64_t buf_size, MirrorSyncMode mode, BlockdevOnError on_source_error, BlockdevOnError on_target_error, - BlockDriverCompletionFunc *cb, + BlockCompletionFunc *cb, void *opaque, Error **errp); /* @@ -584,7 +579,14 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target, int64_t speed, MirrorSyncMode sync_mode, BlockdevOnError on_source_error, BlockdevOnError on_target_error, - BlockDriverCompletionFunc *cb, void *opaque, + BlockCompletionFunc *cb, void *opaque, Error **errp); +void blk_dev_change_media_cb(BlockBackend *blk, bool load); +bool blk_dev_has_removable_media(BlockBackend *blk); +void blk_dev_eject_request(BlockBackend *blk, bool force); +bool blk_dev_is_tray_open(BlockBackend *blk); +bool blk_dev_is_medium_locked(BlockBackend *blk); +void blk_dev_resize_cb(BlockBackend *blk); + #endif /* BLOCK_INT_H */ diff --git a/include/block/blockjob.h b/include/block/blockjob.h index 60aa835..acb399f 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -104,7 +104,7 @@ struct BlockJob { int64_t speed; /** The completion function that will be called when the job completes. */ - BlockDriverCompletionFunc *cb; + BlockCompletionFunc *cb; /** Block other operations when block job is running */ Error *blocker; @@ -132,7 +132,7 @@ struct BlockJob { * called from a wrapper that is specific to the job type. */ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs, - int64_t speed, BlockDriverCompletionFunc *cb, + int64_t speed, BlockCompletionFunc *cb, void *opaque, Error **errp); /** diff --git a/include/block/qapi.h b/include/block/qapi.h index 0374546..168d788 100644 --- a/include/block/qapi.h +++ b/include/block/qapi.h @@ -36,9 +36,6 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs, void bdrv_query_image_info(BlockDriverState *bs, ImageInfo **p_info, Error **errp); -void bdrv_query_info(BlockDriverState *bs, - BlockInfo **p_info, - Error **errp); void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f, QEMUSnapshotInfo *sn); diff --git a/include/block/thread-pool.h b/include/block/thread-pool.h index 4723752..42eb5e8 100644 --- a/include/block/thread-pool.h +++ b/include/block/thread-pool.h @@ -27,9 +27,9 @@ typedef struct ThreadPool ThreadPool; ThreadPool *thread_pool_new(struct AioContext *ctx); void thread_pool_free(ThreadPool *pool); -BlockDriverAIOCB *thread_pool_submit_aio(ThreadPool *pool, +BlockAIOCB *thread_pool_submit_aio(ThreadPool *pool, ThreadPoolFunc *func, void *arg, - BlockDriverCompletionFunc *cb, void *opaque); + BlockCompletionFunc *cb, void *opaque); int coroutine_fn thread_pool_submit_co(ThreadPool *pool, ThreadPoolFunc *func, void *arg); void thread_pool_submit(ThreadPool *pool, ThreadPoolFunc *func, void *arg); diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 77177c5..e32e25d 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -374,6 +374,8 @@ float32 float32_min(float32, float32 STATUS_PARAM); float32 float32_max(float32, float32 STATUS_PARAM); float32 float32_minnum(float32, float32 STATUS_PARAM); float32 float32_maxnum(float32, float32 STATUS_PARAM); +float32 float32_minnummag(float32, float32 STATUS_PARAM); +float32 float32_maxnummag(float32, float32 STATUS_PARAM); int float32_is_quiet_nan( float32 ); int float32_is_signaling_nan( float32 ); float32 float32_maybe_silence_nan( float32 ); @@ -484,6 +486,8 @@ float64 float64_min(float64, float64 STATUS_PARAM); float64 float64_max(float64, float64 STATUS_PARAM); float64 float64_minnum(float64, float64 STATUS_PARAM); float64 float64_maxnum(float64, float64 STATUS_PARAM); +float64 float64_minnummag(float64, float64 STATUS_PARAM); +float64 float64_maxnummag(float64, float64 STATUS_PARAM); int float64_is_quiet_nan( float64 a ); int float64_is_signaling_nan( float64 ); float64 float64_maybe_silence_nan( float64 ); diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h index b9655ee..0ad5fb8 100644 --- a/include/hw/arm/omap.h +++ b/include/hw/arm/omap.h @@ -755,10 +755,10 @@ void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip); struct omap_mmc_s; struct omap_mmc_s *omap_mmc_init(hwaddr base, MemoryRegion *sysmem, - BlockDriverState *bd, + BlockBackend *blk, qemu_irq irq, qemu_irq dma[], omap_clk clk); struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta, - BlockDriverState *bd, qemu_irq irq, qemu_irq dma[], + BlockBackend *blk, qemu_irq irq, qemu_irq dma[], omap_clk fclk, omap_clk iclk); void omap_mmc_reset(struct omap_mmc_s *s); void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover); diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h index c507906..259b852 100644 --- a/include/hw/arm/pxa.h +++ b/include/hw/arm/pxa.h @@ -87,7 +87,7 @@ void pxa2xx_lcdc_oritentation(void *opaque, int angle); typedef struct PXA2xxMMCIState PXA2xxMMCIState; PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, hwaddr base, - BlockDriverState *bd, qemu_irq irq, + BlockBackend *blk, qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma); void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly, qemu_irq coverswitch); diff --git a/include/hw/block/block.h b/include/hw/block/block.h index 867a226..0d0ce9a 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h @@ -17,7 +17,7 @@ /* Configuration */ typedef struct BlockConf { - BlockDriverState *bs; + BlockBackend *blk; uint16_t physical_block_size; uint16_t logical_block_size; uint16_t min_io_size; @@ -42,7 +42,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) } #define DEFINE_BLOCK_PROPERTIES(_state, _conf) \ - DEFINE_PROP_DRIVE("drive", _state, _conf.bs), \ + DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \ DEFINE_PROP_BLOCKSIZE("logical_block_size", _state, \ _conf.logical_block_size, 512), \ DEFINE_PROP_BLOCKSIZE("physical_block_size", _state, \ @@ -66,7 +66,7 @@ void blkconf_geometry(BlockConf *conf, int *trans, /* Hard disk geometry */ -void hd_geometry_guess(BlockDriverState *bs, +void hd_geometry_guess(BlockBackend *blk, uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs, int *ptrans); int hd_bios_chs_auto_trans(uint32_t cyls, uint32_t heads, uint32_t secs); diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h index 920d759..50ccbbc 100644 --- a/include/hw/block/flash.h +++ b/include/hw/block/flash.h @@ -11,7 +11,7 @@ typedef struct pflash_t pflash_t; pflash_t *pflash_cfi01_register(hwaddr base, DeviceState *qdev, const char *name, hwaddr size, - BlockDriverState *bs, + BlockBackend *blk, uint32_t sector_len, int nb_blocs, int width, uint16_t id0, uint16_t id1, uint16_t id2, uint16_t id3, int be); @@ -20,7 +20,7 @@ pflash_t *pflash_cfi01_register(hwaddr base, pflash_t *pflash_cfi02_register(hwaddr base, DeviceState *qdev, const char *name, hwaddr size, - BlockDriverState *bs, uint32_t sector_len, + BlockBackend *blk, uint32_t sector_len, int nb_blocs, int nb_mappings, int width, uint16_t id0, uint16_t id1, uint16_t id2, uint16_t id3, @@ -30,7 +30,7 @@ pflash_t *pflash_cfi02_register(hwaddr base, MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl); /* nand.c */ -DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id); +DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id); void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale, uint8_t ce, uint8_t wp, uint8_t gnd); void nand_getpins(DeviceState *dev, int *rb); diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 1c2602e..c4ee520 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -314,6 +314,14 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); .driver = "secondary-vga",\ .property = "qemu-extended-regs",\ .value = "off",\ + },{\ + .driver = "usb-mouse",\ + .property = "usb_version",\ + .value = stringify(1),\ + },{\ + .driver = "usb-kbd",\ + .property = "usb_version",\ + .value = stringify(1),\ } #define PC_COMPAT_2_0 \ diff --git a/include/hw/isa/pc87312.h b/include/hw/isa/pc87312.h index befc8bd..bf74470 100644 --- a/include/hw/isa/pc87312.h +++ b/include/hw/isa/pc87312.h @@ -47,13 +47,10 @@ typedef struct PC87312State { struct { ISADevice *dev; - BlockDriverState *drive[2]; - uint32_t base; } fdc; struct { ISADevice *dev; - uint32_t base; } ide; MemoryRegion io; diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index ae56ee5..070006c 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -141,7 +141,7 @@ extern PropertyInfo qdev_prop_arraylen; #define DEFINE_PROP_VLAN(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NICPeers) #define DEFINE_PROP_DRIVE(_n, _s, _f) \ - DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *) + DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockBackend *) #define DEFINE_PROP_MACADDR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr) #define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \ @@ -168,8 +168,10 @@ void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value); void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value); void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value); void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value); -int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) QEMU_WARN_UNUSED_RESULT; -void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value); +int qdev_prop_set_drive(DeviceState *dev, const char *name, + BlockBackend *value) QEMU_WARN_UNUSED_RESULT; +void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, + BlockBackend *value); void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value); void qdev_prop_set_enum(DeviceState *dev, const char *name, int value); /* FIXME: Remove opaque pointer properties. */ diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index caaa320..6bc841a 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -2,7 +2,7 @@ #define QEMU_HW_SCSI_H #include "hw/qdev.h" -#include "block/block.h" +#include "qemu/typedefs.h" #include "hw/block/block.h" #include "sysemu/sysemu.h" #include "qemu/notify.h" @@ -68,7 +68,7 @@ struct SCSIRequest { bool io_canceled; bool retry; bool dma_started; - BlockDriverAIOCB *aiocb; + BlockAIOCB *aiocb; QEMUSGList *sg; QTAILQ_ENTRY(SCSIRequest) next; }; @@ -173,7 +173,7 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d) return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus); } -SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, +SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk, int unit, bool removable, int bootindex, const char *serial, Error **errp); void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp); diff --git a/include/hw/sd.h b/include/hw/sd.h index d9b97e4..79adb5b 100644 --- a/include/hw/sd.h +++ b/include/hw/sd.h @@ -68,7 +68,7 @@ typedef struct { typedef struct SDState SDState; -SDState *sd_init(BlockDriverState *bs, bool is_spi); +SDState *sd_init(BlockBackend *bs, bool is_spi); int sd_do_command(SDState *sd, SDRequest *req, uint8_t *response); void sd_write_data(SDState *sd, uint8_t value); diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h index f3853f2..3979dc4 100644 --- a/include/hw/virtio/virtio-blk.h +++ b/include/hw/virtio/virtio-blk.h @@ -17,8 +17,7 @@ #include "hw/virtio/virtio.h" #include "hw/block/block.h" #include "sysemu/iothread.h" -#include "block/block.h" -#include "block/accounting.h" +#include "sysemu/block-backend.h" #define TYPE_VIRTIO_BLK "virtio-blk-device" #define VIRTIO_BLK(obj) \ @@ -121,12 +120,11 @@ struct VirtIOBlockDataPlane; struct VirtIOBlockReq; typedef struct VirtIOBlock { VirtIODevice parent_obj; - BlockDriverState *bs; + BlockBackend *blk; VirtQueue *vq; void *rq; QEMUBH *bh; - BlockConf *conf; - VirtIOBlkConf blk; + VirtIOBlkConf conf; unsigned short sector_mask; bool original_wce; VMChangeStateEntry *change; @@ -160,6 +158,6 @@ int virtio_blk_handle_scsi_req(VirtIOBlock *blk, void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb); -void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb); +void virtio_submit_multiwrite(BlockBackend *blk, MultiReqBuffer *mrb); #endif diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index 78a5fc8..47606d0 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -27,10 +27,10 @@ int monitor_suspend(Monitor *mon); void monitor_resume(Monitor *mon); int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs, - BlockDriverCompletionFunc *completion_cb, + BlockCompletionFunc *completion_cb, void *opaque); int monitor_read_block_device_key(Monitor *mon, const char *device, - BlockDriverCompletionFunc *completion_cb, + BlockCompletionFunc *completion_cb, void *opaque); int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp); diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index 168a408..3475177 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -36,6 +36,7 @@ typedef struct MachineState MachineState; typedef struct NICInfo NICInfo; typedef struct HCIInfo HCIInfo; typedef struct AudioState AudioState; +typedef struct BlockBackend BlockBackend; typedef struct BlockDriverState BlockDriverState; typedef struct DriveInfo DriveInfo; typedef struct DisplayState DisplayState; diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h new file mode 100644 index 0000000..52d13c1 --- /dev/null +++ b/include/sysemu/block-backend.h @@ -0,0 +1,142 @@ +/* + * QEMU Block backends + * + * Copyright (C) 2014 Red Hat, Inc. + * + * Authors: + * Markus Armbruster <armbru@redhat.com>, + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 + * or later. See the COPYING.LIB file in the top-level directory. + */ + +#ifndef BLOCK_BACKEND_H +#define BLOCK_BACKEND_H + +#include "qemu/typedefs.h" +#include "qapi/error.h" + +/* + * TODO Have to include block/block.h for a bunch of block layer + * types. Unfortunately, this pulls in the whole BlockDriverState + * API, which we don't want used by many BlockBackend users. Some of + * the types belong here, and the rest should be split into a common + * header and one for the BlockDriverState API. + */ +#include "block/block.h" + +/* Callbacks for block device models */ +typedef struct BlockDevOps { + /* + * Runs when virtual media changed (monitor commands eject, change) + * Argument load is true on load and false on eject. + * Beware: doesn't run when a host device's physical media + * changes. Sure would be useful if it did. + * Device models with removable media must implement this callback. + */ + void (*change_media_cb)(void *opaque, bool load); + /* + * Runs when an eject request is issued from the monitor, the tray + * is closed, and the medium is locked. + * Device models that do not implement is_medium_locked will not need + * this callback. Device models that can lock the medium or tray might + * want to implement the callback and unlock the tray when "force" is + * true, even if they do not support eject requests. + */ + void (*eject_request_cb)(void *opaque, bool force); + /* + * Is the virtual tray open? + * Device models implement this only when the device has a tray. + */ + bool (*is_tray_open)(void *opaque); + /* + * Is the virtual medium locked into the device? + * Device models implement this only when device has such a lock. + */ + bool (*is_medium_locked)(void *opaque); + /* + * Runs when the size changed (e.g. monitor command block_resize) + */ + void (*resize_cb)(void *opaque); +} BlockDevOps; + +BlockBackend *blk_new(const char *name, Error **errp); +BlockBackend *blk_new_with_bs(const char *name, Error **errp); +void blk_ref(BlockBackend *blk); +void blk_unref(BlockBackend *blk); +const char *blk_name(BlockBackend *blk); +BlockBackend *blk_by_name(const char *name); +BlockBackend *blk_next(BlockBackend *blk); + +BlockDriverState *blk_bs(BlockBackend *blk); + +void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk); + +void blk_iostatus_enable(BlockBackend *blk); +int blk_attach_dev(BlockBackend *blk, void *dev); +void blk_attach_dev_nofail(BlockBackend *blk, void *dev); +void blk_detach_dev(BlockBackend *blk, void *dev); +void *blk_get_attached_dev(BlockBackend *blk); +void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque); +int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf, + int nb_sectors); +int blk_read_unthrottled(BlockBackend *blk, int64_t sector_num, uint8_t *buf, + int nb_sectors); +int blk_write(BlockBackend *blk, int64_t sector_num, const uint8_t *buf, + int nb_sectors); +BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t sector_num, + int nb_sectors, BdrvRequestFlags flags, + BlockCompletionFunc *cb, void *opaque); +int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count); +int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count); +int64_t blk_getlength(BlockBackend *blk); +void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr); +BlockAIOCB *blk_aio_readv(BlockBackend *blk, int64_t sector_num, + QEMUIOVector *iov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num, + QEMUIOVector *iov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *blk_aio_flush(BlockBackend *blk, + BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *blk_aio_discard(BlockBackend *blk, + int64_t sector_num, int nb_sectors, + BlockCompletionFunc *cb, void *opaque); +void blk_aio_cancel(BlockAIOCB *acb); +void blk_aio_cancel_async(BlockAIOCB *acb); +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_flush(BlockBackend *blk); +int blk_flush_all(void); +void blk_drain_all(void); +BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read); +BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read, + int error); +void blk_error_action(BlockBackend *blk, BlockErrorAction action, + bool is_read, int error); +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); +int blk_is_inserted(BlockBackend *blk); +void blk_lock_medium(BlockBackend *blk, bool locked); +void blk_eject(BlockBackend *blk, bool eject_flag); +int blk_get_flags(BlockBackend *blk); +void blk_set_guest_block_size(BlockBackend *blk, int align); +void *blk_blockalign(BlockBackend *blk, size_t size); +bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp); +void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason); +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_io_plug(BlockBackend *blk); +void blk_io_unplug(BlockBackend *blk); +BlockAcctStats *blk_get_stats(BlockBackend *blk); + +void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk, + BlockCompletionFunc *cb, void *opaque); + +#endif diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index 09716de..09d1e30 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -14,8 +14,8 @@ #include "qapi/error.h" #include "qemu/queue.h" -void blockdev_mark_auto_del(BlockDriverState *bs); -void blockdev_auto_del(BlockDriverState *bs); +void blockdev_mark_auto_del(BlockBackend *blk); +void blockdev_auto_del(BlockBackend *blk); typedef enum { IF_DEFAULT = -1, /* for use with drive_add() only */ @@ -30,14 +30,11 @@ typedef enum { } BlockInterfaceType; struct DriveInfo { - BlockDriverState *bdrv; - char *id; const char *devaddr; BlockInterfaceType type; int bus; int unit; int auto_del; /* see blockdev_mark_auto_del() */ - bool enable_auto_del; /* Only for legacy drive_new() */ bool is_default; /* Added by default_drive() ? */ int media_cd; int cyls, heads, secs, trans; @@ -46,6 +43,10 @@ struct DriveInfo { QTAILQ_ENTRY(DriveInfo) next; }; +DriveInfo *blk_legacy_dinfo(BlockBackend *blk); +DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo); +BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo); + void override_max_devs(BlockInterfaceType type, int max_devs); DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); @@ -54,14 +55,11 @@ DriveInfo *drive_get_by_index(BlockInterfaceType type, int index); int drive_get_max_bus(BlockInterfaceType type); int drive_get_max_devs(BlockInterfaceType type); DriveInfo *drive_get_next(BlockInterfaceType type); -DriveInfo *drive_get_by_blockdev(BlockDriverState *bs); QemuOpts *drive_def(const char *optstr); QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file, const char *optstr); DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type); -void drive_del(DriveInfo *dinfo); -void drive_info_del(DriveInfo *dinfo); /* device-hotplug */ diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 73ff86d..3f2f4c8 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -197,24 +197,24 @@ void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len); void qemu_sglist_destroy(QEMUSGList *qsg); #endif -typedef BlockDriverAIOCB *DMAIOFunc(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *iov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); - -BlockDriverAIOCB *dma_bdrv_io(BlockDriverState *bs, - QEMUSGList *sg, uint64_t sector_num, - DMAIOFunc *io_func, BlockDriverCompletionFunc *cb, - void *opaque, DMADirection dir); -BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs, - QEMUSGList *sg, uint64_t sector, - BlockDriverCompletionFunc *cb, void *opaque); -BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs, - QEMUSGList *sg, uint64_t sector, - BlockDriverCompletionFunc *cb, void *opaque); +typedef BlockAIOCB *DMAIOFunc(BlockBackend *blk, int64_t sector_num, + QEMUIOVector *iov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque); + +BlockAIOCB *dma_blk_io(BlockBackend *blk, + QEMUSGList *sg, uint64_t sector_num, + DMAIOFunc *io_func, BlockCompletionFunc *cb, + void *opaque, DMADirection dir); +BlockAIOCB *dma_blk_read(BlockBackend *blk, + QEMUSGList *sg, uint64_t sector, + BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *dma_blk_write(BlockBackend *blk, + QEMUSGList *sg, uint64_t sector, + BlockCompletionFunc *cb, void *opaque); uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg); uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg); -void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie, +void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, QEMUSGList *sg, enum BlockAcctType type); #endif @@ -206,7 +206,7 @@ struct Monitor { ReadLineState *rs; MonitorControl *mc; CPUState *mon_cpu; - BlockDriverCompletionFunc *password_completion_cb; + BlockCompletionFunc *password_completion_cb; void *password_opaque; mon_cmd_t *cmd_table; QError *error; @@ -4216,24 +4216,6 @@ static void file_completion(Monitor *mon, const char *input) closedir(ffs); } -typedef struct MonitorBlockComplete { - Monitor *mon; - const char *input; -} MonitorBlockComplete; - -static void block_completion_it(void *opaque, BlockDriverState *bs) -{ - const char *name = bdrv_get_device_name(bs); - MonitorBlockComplete *mbc = opaque; - Monitor *mon = mbc->mon; - const char *input = mbc->input; - - if (input[0] == '\0' || - !strncmp(name, (char *)input, strlen(input))) { - readline_add_completion(mon->rs, name); - } -} - static const char *next_arg_type(const char *typestr) { const char *p = strchr(typestr, ':'); @@ -4671,9 +4653,9 @@ static void monitor_find_completion_by_table(Monitor *mon, { const char *cmdname; int i; - const char *ptype, *str; + const char *ptype, *str, *name; const mon_cmd_t *cmd; - MonitorBlockComplete mbs; + BlockDriverState *bs; if (nb_args <= 1) { /* command completion */ @@ -4725,10 +4707,14 @@ static void monitor_find_completion_by_table(Monitor *mon, break; case 'B': /* block device name completion */ - mbs.mon = mon; - mbs.input = str; readline_set_completion_index(mon->rs, strlen(str)); - bdrv_iterate(block_completion_it, &mbs); + for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) { + name = bdrv_get_device_name(bs); + if (str[0] == '\0' || + !strncmp(name, str, strlen(str))) { + readline_add_completion(mon->rs, name); + } + } break; case 's': case 'S': @@ -5388,7 +5374,7 @@ ReadLineState *monitor_get_rs(Monitor *mon) } int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs, - BlockDriverCompletionFunc *completion_cb, + BlockCompletionFunc *completion_cb, void *opaque) { int err; @@ -5420,7 +5406,7 @@ int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs, } int monitor_read_block_device_key(Monitor *mon, const char *device, - BlockDriverCompletionFunc *completion_cb, + BlockCompletionFunc *completion_cb, void *opaque) { BlockDriverState *bs; @@ -29,6 +29,7 @@ #include "qemu/error-report.h" #include "qemu/osdep.h" #include "sysemu/sysemu.h" +#include "sysemu/block-backend.h" #include "block/block_int.h" #include "block/qapi.h" #include <getopt.h> @@ -283,20 +284,19 @@ static int print_block_option_help(const char *filename, const char *fmt) return 0; } -static BlockDriverState *bdrv_new_open(const char *id, - const char *filename, - const char *fmt, - int flags, - bool require_io, - bool quiet) +static BlockBackend *img_open(const char *id, const char *filename, + const char *fmt, int flags, + bool require_io, bool quiet) { + BlockBackend *blk; BlockDriverState *bs; BlockDriver *drv; char password[256]; Error *local_err = NULL; int ret; - bs = bdrv_new(id, &error_abort); + blk = blk_new_with_bs(id, &error_abort); + bs = blk_bs(blk); if (fmt) { drv = bdrv_find_format(fmt); @@ -327,9 +327,9 @@ static BlockDriverState *bdrv_new_open(const char *id, goto fail; } } - return bs; + return blk; fail: - bdrv_unref(bs); + blk_unref(blk); return NULL; } @@ -575,6 +575,7 @@ static int img_check(int argc, char **argv) int c, ret; OutputFormat output_format = OFORMAT_HUMAN; const char *filename, *fmt, *output, *cache; + BlockBackend *blk; BlockDriverState *bs; int fix = 0; int flags = BDRV_O_FLAGS | BDRV_O_CHECK; @@ -649,10 +650,11 @@ static int img_check(int argc, char **argv) return 1; } - bs = bdrv_new_open("image", filename, fmt, flags, true, quiet); - if (!bs) { + blk = img_open("image", filename, fmt, flags, true, quiet); + if (!blk) { return 1; } + bs = blk_bs(blk); check = g_new0(ImageCheck, 1); ret = collect_image_check(bs, check, filename, fmt, fix); @@ -709,8 +711,7 @@ static int img_check(int argc, char **argv) fail: qapi_free_ImageCheck(check); - bdrv_unref(bs); - + blk_unref(blk); return ret; } @@ -718,6 +719,7 @@ static int img_commit(int argc, char **argv) { int c, ret, flags; const char *filename, *fmt, *cache; + BlockBackend *blk; BlockDriverState *bs; bool quiet = false; @@ -756,10 +758,12 @@ static int img_commit(int argc, char **argv) return 1; } - bs = bdrv_new_open("image", filename, fmt, flags, true, quiet); - if (!bs) { + blk = img_open("image", filename, fmt, flags, true, quiet); + if (!blk) { return 1; } + bs = blk_bs(blk); + ret = bdrv_commit(bs); switch(ret) { case 0: @@ -779,7 +783,7 @@ static int img_commit(int argc, char **argv) break; } - bdrv_unref(bs); + blk_unref(blk); if (ret) { return 1; } @@ -942,6 +946,7 @@ static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num, static int img_compare(int argc, char **argv) { const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2; + BlockBackend *blk1, *blk2; BlockDriverState *bs1, *bs2; int64_t total_sectors1, total_sectors2; uint8_t *buf1 = NULL, *buf2 = NULL; @@ -1011,19 +1016,21 @@ static int img_compare(int argc, char **argv) goto out3; } - bs1 = bdrv_new_open("image_1", filename1, fmt1, flags, true, quiet); - if (!bs1) { + blk1 = img_open("image_1", filename1, fmt1, flags, true, quiet); + if (!blk1) { error_report("Can't open file %s", filename1); ret = 2; goto out3; } + bs1 = blk_bs(blk1); - bs2 = bdrv_new_open("image_2", filename2, fmt2, flags, true, quiet); - if (!bs2) { + blk2 = img_open("image_2", filename2, fmt2, flags, true, quiet); + if (!blk2) { error_report("Can't open file %s", filename2); ret = 2; goto out2; } + bs2 = blk_bs(blk2); buf1 = qemu_blockalign(bs1, IO_BUF_SIZE); buf2 = qemu_blockalign(bs2, IO_BUF_SIZE); @@ -1183,11 +1190,11 @@ static int img_compare(int argc, char **argv) ret = 0; out: - bdrv_unref(bs2); qemu_vfree(buf1); qemu_vfree(buf2); + blk_unref(blk2); out2: - bdrv_unref(bs1); + blk_unref(blk1); out3: qemu_progress_end(); return ret; @@ -1200,6 +1207,7 @@ static int img_convert(int argc, char **argv) int progress = 0, flags, src_flags; const char *fmt, *out_fmt, *cache, *src_cache, *out_baseimg, *out_filename; BlockDriver *drv, *proto_drv; + BlockBackend **blk = NULL, *out_blk = NULL; BlockDriverState **bs = NULL, *out_bs = NULL; int64_t total_sectors, nb_sectors, sector_num, bs_offset; int64_t *bs_sectors = NULL; @@ -1354,6 +1362,7 @@ static int img_convert(int argc, char **argv) qemu_progress_print(0, 100); + blk = g_new0(BlockBackend *, bs_n); bs = g_new0(BlockDriverState *, bs_n); bs_sectors = g_new(int64_t, bs_n); @@ -1361,14 +1370,15 @@ static int img_convert(int argc, char **argv) for (bs_i = 0; bs_i < bs_n; bs_i++) { char *id = bs_n > 1 ? g_strdup_printf("source_%d", bs_i) : g_strdup("source"); - bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, src_flags, - true, quiet); + blk[bs_i] = img_open(id, argv[optind + bs_i], fmt, src_flags, + true, quiet); g_free(id); - if (!bs[bs_i]) { + if (!blk[bs_i]) { error_report("Could not open '%s'", argv[optind + bs_i]); ret = -1; goto out; } + bs[bs_i] = blk_bs(blk[bs_i]); bs_sectors[bs_i] = bdrv_nb_sectors(bs[bs_i]); if (bs_sectors[bs_i] < 0) { error_report("Could not get size of %s: %s", @@ -1486,11 +1496,12 @@ static int img_convert(int argc, char **argv) goto out; } - out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet); - if (!out_bs) { + out_blk = img_open("target", out_filename, out_fmt, flags, true, quiet); + if (!out_blk) { ret = -1; goto out; } + out_bs = blk_bs(out_blk); bs_i = 0; bs_offset = 0; @@ -1737,16 +1748,13 @@ out: qemu_opts_free(create_opts); qemu_vfree(buf); qemu_opts_del(sn_opts); - if (out_bs) { - bdrv_unref(out_bs); - } - if (bs) { + blk_unref(out_blk); + g_free(bs); + if (blk) { for (bs_i = 0; bs_i < bs_n; bs_i++) { - if (bs[bs_i]) { - bdrv_unref(bs[bs_i]); - } + blk_unref(blk[bs_i]); } - g_free(bs); + g_free(blk); } g_free(bs_sectors); fail_getopt: @@ -1856,6 +1864,7 @@ static ImageInfoList *collect_image_info_list(const char *filename, filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL); while (filename) { + BlockBackend *blk; BlockDriverState *bs; ImageInfo *info; ImageInfoList *elem; @@ -1867,17 +1876,18 @@ static ImageInfoList *collect_image_info_list(const char *filename, } g_hash_table_insert(filenames, (gpointer)filename, NULL); - bs = bdrv_new_open("image", filename, fmt, - BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false); - if (!bs) { + blk = img_open("image", filename, fmt, + BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false); + if (!blk) { goto err; } + bs = blk_bs(blk); bdrv_query_image_info(bs, &info, &err); if (err) { error_report("%s", error_get_pretty(err)); error_free(err); - bdrv_unref(bs); + blk_unref(blk); goto err; } @@ -1886,7 +1896,7 @@ static ImageInfoList *collect_image_info_list(const char *filename, *last = elem; last = &elem->next; - bdrv_unref(bs); + blk_unref(blk); filename = fmt = NULL; if (chain) { @@ -2080,6 +2090,7 @@ static int img_map(int argc, char **argv) { int c; OutputFormat output_format = OFORMAT_HUMAN; + BlockBackend *blk; BlockDriverState *bs; const char *filename, *fmt, *output; int64_t length; @@ -2128,10 +2139,11 @@ static int img_map(int argc, char **argv) return 1; } - bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS, true, false); - if (!bs) { + blk = img_open("image", filename, fmt, BDRV_O_FLAGS, true, false); + if (!blk) { return 1; } + bs = blk_bs(blk); if (output_format == OFORMAT_HUMAN) { printf("%-16s%-16s%-16s%s\n", "Offset", "Length", "Mapped to", "File"); @@ -2172,7 +2184,7 @@ static int img_map(int argc, char **argv) dump_map_entry(output_format, &curr, NULL); out: - bdrv_unref(bs); + blk_unref(blk); return ret < 0; } @@ -2183,6 +2195,7 @@ out: static int img_snapshot(int argc, char **argv) { + BlockBackend *blk; BlockDriverState *bs; QEMUSnapshotInfo sn; char *filename, *snapshot_name = NULL; @@ -2248,10 +2261,11 @@ static int img_snapshot(int argc, char **argv) filename = argv[optind++]; /* Open the image */ - bs = bdrv_new_open("image", filename, NULL, bdrv_oflags, true, quiet); - if (!bs) { + blk = img_open("image", filename, NULL, bdrv_oflags, true, quiet); + if (!blk) { return 1; } + bs = blk_bs(blk); /* Perform the requested action */ switch(action) { @@ -2294,7 +2308,7 @@ static int img_snapshot(int argc, char **argv) } /* Cleanup */ - bdrv_unref(bs); + blk_unref(blk); if (ret) { return 1; } @@ -2303,6 +2317,7 @@ static int img_snapshot(int argc, char **argv) static int img_rebase(int argc, char **argv) { + BlockBackend *blk = NULL, *blk_old_backing = NULL, *blk_new_backing = NULL; BlockDriverState *bs = NULL, *bs_old_backing = NULL, *bs_new_backing = NULL; BlockDriver *old_backing_drv, *new_backing_drv; char *filename; @@ -2391,11 +2406,12 @@ static int img_rebase(int argc, char **argv) * Ignore the old backing file for unsafe rebase in case we want to correct * the reference to a renamed or moved backing file. */ - bs = bdrv_new_open("image", filename, fmt, flags, true, quiet); - if (!bs) { + blk = img_open("image", filename, fmt, flags, true, quiet); + if (!blk) { ret = -1; goto out; } + bs = blk_bs(blk); /* Find the right drivers for the backing files */ old_backing_drv = NULL; @@ -2423,7 +2439,8 @@ static int img_rebase(int argc, char **argv) if (!unsafe) { char backing_name[1024]; - bs_old_backing = bdrv_new("old_backing", &error_abort); + blk_old_backing = blk_new_with_bs("old_backing", &error_abort); + bs_old_backing = blk_bs(blk_old_backing); bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name)); ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags, old_backing_drv, &local_err); @@ -2434,7 +2451,8 @@ static int img_rebase(int argc, char **argv) goto out; } if (out_baseimg[0]) { - bs_new_backing = bdrv_new("new_backing", &error_abort); + blk_new_backing = blk_new_with_bs("new_backing", &error_abort); + bs_new_backing = blk_bs(blk_new_backing); ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags, new_backing_drv, &local_err); if (ret) { @@ -2609,15 +2627,11 @@ out: qemu_progress_end(); /* Cleanup */ if (!unsafe) { - if (bs_old_backing != NULL) { - bdrv_unref(bs_old_backing); - } - if (bs_new_backing != NULL) { - bdrv_unref(bs_new_backing); - } + blk_unref(blk_old_backing); + blk_unref(blk_new_backing); } - bdrv_unref(bs); + blk_unref(blk); if (ret) { return 1; } @@ -2630,6 +2644,7 @@ static int img_resize(int argc, char **argv) const char *filename, *fmt, *size; int64_t n, total_size; bool quiet = false; + BlockBackend *blk = NULL; BlockDriverState *bs = NULL; QemuOpts *param; static QemuOptsList resize_options = { @@ -2706,12 +2721,13 @@ static int img_resize(int argc, char **argv) n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0); qemu_opts_del(param); - bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, - true, quiet); - if (!bs) { + blk = img_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, + true, quiet); + if (!blk) { ret = -1; goto out; } + bs = blk_bs(blk); if (relative) { total_size = bdrv_getlength(bs) + n * relative; @@ -2740,9 +2756,7 @@ static int img_resize(int argc, char **argv) break; } out: - if (bs) { - bdrv_unref(bs); - } + blk_unref(blk); if (ret) { return 1; } @@ -2758,6 +2772,7 @@ static int img_amend(int argc, char **argv) const char *fmt = NULL, *filename, *cache; int flags; bool quiet = false; + BlockBackend *blk = NULL; BlockDriverState *bs = NULL; cache = BDRV_DEFAULT_CACHE; @@ -2821,12 +2836,13 @@ static int img_amend(int argc, char **argv) goto out; } - bs = bdrv_new_open("image", filename, fmt, flags, true, quiet); - if (!bs) { + blk = img_open("image", filename, fmt, flags, true, quiet); + if (!blk) { error_report("Could not open image '%s'", filename); ret = -1; goto out; } + bs = blk_bs(blk); fmt = bs->drv->format_name; @@ -2851,9 +2867,7 @@ static int img_amend(int argc, char **argv) } out: - if (bs) { - bdrv_unref(bs); - } + blk_unref(blk); qemu_opts_del(opts); qemu_opts_free(create_opts); g_free(options); @@ -19,6 +19,7 @@ #include "qemu/option.h" #include "qemu/config-file.h" #include "qemu/readline.h" +#include "sysemu/block-backend.h" #include "block/block_int.h" #include "trace/control.h" @@ -26,6 +27,7 @@ static char *progname; +static BlockBackend *qemuio_blk; static BlockDriverState *qemuio_bs; /* qemu-io commands passed using -c */ @@ -36,8 +38,9 @@ static ReadLineState *readline_state; static int close_f(BlockDriverState *bs, int argc, char **argv) { - bdrv_unref(bs); + blk_unref(qemuio_blk); qemuio_bs = NULL; + qemuio_blk = NULL; return 0; } @@ -58,7 +61,8 @@ static int openfile(char *name, int flags, int growable, QDict *opts) return 1; } - qemuio_bs = bdrv_new("hda", &error_abort); + qemuio_blk = blk_new_with_bs("hda", &error_abort); + qemuio_bs = blk_bs(qemuio_blk); if (growable) { flags |= BDRV_O_PROTOCOL; @@ -69,8 +73,9 @@ static int openfile(char *name, int flags, int growable, QDict *opts) name ? " device " : "", name ?: "", error_get_pretty(local_err)); error_free(local_err); - bdrv_unref(qemuio_bs); + blk_unref(qemuio_blk); qemuio_bs = NULL; + qemuio_blk = NULL; return 1; } @@ -481,9 +486,7 @@ int main(int argc, char **argv) */ bdrv_drain_all(); - if (qemuio_bs) { - bdrv_unref(qemuio_bs); - } + blk_unref(qemuio_blk); g_free(readline_state); return 0; } @@ -17,7 +17,7 @@ */ #include "qemu-common.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #include "block/block_int.h" #include "block/nbd.h" #include "qemu/main-loop.h" @@ -384,6 +384,7 @@ static void nbd_accept(void *opaque) int main(int argc, char **argv) { + BlockBackend *blk; BlockDriverState *bs; BlockDriver *drv; off_t dev_offset = 0; @@ -691,7 +692,8 @@ int main(int argc, char **argv) drv = NULL; } - bs = bdrv_new("hda", &error_abort); + blk = blk_new_with_bs("hda", &error_abort); + bs = blk_bs(blk); srcpath = argv[optind]; ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err); @@ -773,7 +775,7 @@ int main(int argc, char **argv) } } while (state != TERMINATED); - bdrv_unref(bs); + blk_unref(blk); if (sockpath) { unlink(sockpath); } diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index c0b1f6a..5e347d0 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -1,6 +1,5 @@ stub-obj-y += arch-query-cpu-def.o stub-obj-y += bdrv-commit-all.o -stub-obj-y += blockdev.o stub-obj-y += chr-baum-init.o stub-obj-y += chr-msmouse.o stub-obj-y += chr-testdev.o diff --git a/stubs/blockdev.c b/stubs/blockdev.c deleted file mode 100644 index 5d0a79c..0000000 --- a/stubs/blockdev.c +++ /dev/null @@ -1,12 +0,0 @@ -#include <assert.h> -#include "sysemu/blockdev.h" - -DriveInfo *drive_get_by_blockdev(BlockDriverState *bs) -{ - return NULL; -} - -void drive_info_del(DriveInfo *dinfo) -{ - assert(!dinfo); -} diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 8b9a92e..26e7894 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -431,7 +431,7 @@ struct CPUMIPSState { int error_code; uint32_t hflags; /* CPU State */ /* TMASK defines different execution modes */ -#define MIPS_HFLAG_TMASK 0xC07FF +#define MIPS_HFLAG_TMASK 0x1807FF #define MIPS_HFLAG_MODE 0x00007 /* execution modes */ /* The KSU flags must be the lowest bits in hflags. The flag order must be the same as defined for CP0 Status. This allows to use @@ -450,7 +450,7 @@ struct CPUMIPSState { and RSQRT.D. */ #define MIPS_HFLAG_COP1X 0x00080 /* COP1X instructions enabled */ #define MIPS_HFLAG_RE 0x00100 /* Reversed endianness */ -#define MIPS_HFLAG_UX 0x00200 /* 64-bit user mode */ +#define MIPS_HFLAG_AWRAP 0x00200 /* 32-bit compatibility address wrapping */ #define MIPS_HFLAG_M16 0x00400 /* MIPS16 mode flag */ #define MIPS_HFLAG_M16_SHIFT 10 /* If translation is interrupted between the branch instruction and @@ -463,17 +463,18 @@ struct CPUMIPSState { #define MIPS_HFLAG_BL 0x01800 /* Likely branch */ #define MIPS_HFLAG_BR 0x02000 /* branch to register (can't link TB) */ /* Extra flags about the current pending branch. */ -#define MIPS_HFLAG_BMASK_EXT 0x3C000 +#define MIPS_HFLAG_BMASK_EXT 0x7C000 #define MIPS_HFLAG_B16 0x04000 /* branch instruction was 16 bits */ #define MIPS_HFLAG_BDS16 0x08000 /* branch requires 16-bit delay slot */ #define MIPS_HFLAG_BDS32 0x10000 /* branch requires 32-bit delay slot */ -#define MIPS_HFLAG_BX 0x20000 /* branch exchanges execution mode */ +#define MIPS_HFLAG_BDS_STRICT 0x20000 /* Strict delay slot size */ +#define MIPS_HFLAG_BX 0x40000 /* branch exchanges execution mode */ #define MIPS_HFLAG_BMASK (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT) /* MIPS DSP resources access. */ -#define MIPS_HFLAG_DSP 0x40000 /* Enable access to MIPS DSP resources. */ -#define MIPS_HFLAG_DSPR2 0x80000 /* Enable access to MIPS DSPR2 resources. */ +#define MIPS_HFLAG_DSP 0x080000 /* Enable access to MIPS DSP resources. */ +#define MIPS_HFLAG_DSPR2 0x100000 /* Enable access to MIPS DSPR2 resources. */ /* Extra flag about HWREna register. */ -#define MIPS_HFLAG_HWRENA_ULR 0x100000 /* ULR bit from HWREna is set. */ +#define MIPS_HFLAG_HWRENA_ULR 0x200000 /* ULR bit from HWREna is set. */ target_ulong btarget; /* Jump / branch target */ target_ulong bcond; /* Branch condition (if needed) */ @@ -725,7 +726,7 @@ static inline void compute_hflags(CPUMIPSState *env) { env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU | - MIPS_HFLAG_UX | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2); + MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2); if (!(env->CP0_Status & (1 << CP0St_EXL)) && !(env->CP0_Status & (1 << CP0St_ERL)) && !(env->hflags & MIPS_HFLAG_DM)) { @@ -737,8 +738,18 @@ static inline void compute_hflags(CPUMIPSState *env) (env->CP0_Status & (1 << CP0St_UX))) { env->hflags |= MIPS_HFLAG_64; } - if (env->CP0_Status & (1 << CP0St_UX)) { - env->hflags |= MIPS_HFLAG_UX; + + if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) && + !(env->CP0_Status & (1 << CP0St_UX))) { + env->hflags |= MIPS_HFLAG_AWRAP; + } else if (env->insn_flags & ISA_MIPS32R6) { + /* Address wrapping for Supervisor and Kernel is specified in R6 */ + if ((((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_SM) && + !(env->CP0_Status & (1 << CP0St_SX))) || + (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_KM) && + !(env->CP0_Status & (1 << CP0St_KX)))) { + env->hflags |= MIPS_HFLAG_AWRAP; + } } #endif if ((env->CP0_Status & (1 << CP0St_CU0)) || diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index 94083fb..349f2a0 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -76,15 +76,6 @@ static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env) env->active_tc.DSPControl |= (target_ulong)flag << 24; } -static inline uint32_t get_DSPControl_24(int len, CPUMIPSState *env) -{ - uint32_t filter; - - filter = (0x01 << len) - 1; - - return (env->active_tc.DSPControl >> 24) & filter; -} - static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env) { target_ulong dspc; @@ -283,6 +274,7 @@ static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a, return result; } +#ifdef TARGET_MIPS64 /* a[0] is LO, a[1] is HI. */ static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret, int32_t ac, @@ -336,6 +328,7 @@ static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret, set_DSPControl_overflow_flag(1, 16 + ac, env); } } +#endif static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b, CPUMIPSState *env) @@ -357,10 +350,12 @@ static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b) return a * b; } +#ifdef TARGET_MIPS64 static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b) { return a * b; } +#endif static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b, CPUMIPSState *env) @@ -417,10 +412,12 @@ static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov) return a >> mov; } +#ifdef TARGET_MIPS64 static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov) { return a >> mov; } +#endif static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b) { @@ -479,6 +476,7 @@ static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b) return (temp >> 1) & 0x00FF; } +#ifdef TARGET_MIPS64 static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b) { uint16_t temp; @@ -496,6 +494,7 @@ static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b) return (temp >> 1) & 0x00FF; } +#endif /* 128 bits long. p[0] is LO, p[1] is HI. */ static inline void mipsdsp_rndrashift_short_acc(int64_t *p, @@ -511,6 +510,7 @@ static inline void mipsdsp_rndrashift_short_acc(int64_t *p, p[1] = (acc >> 63) & 0x01; } +#ifdef TARGET_MIPS64 /* 128 bits long. p[0] is LO, p[1] is HI */ static inline void mipsdsp_rashift_acc(uint64_t *p, uint32_t ac, @@ -558,6 +558,7 @@ static inline void mipsdsp_rndrashift_acc(uint64_t *p, } } } +#endif static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b, CPUMIPSState *env) @@ -608,10 +609,12 @@ static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b, return tempI & 0x0000FFFF; } +#ifdef TARGET_MIPS64 static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b) { return (uint64_t)a * (uint64_t)b; } +#endif static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b, CPUMIPSState *env) @@ -717,7 +720,7 @@ static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s, return a << s; } - +#ifdef TARGET_MIPS64 static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s, CPUMIPSState *env) { @@ -734,6 +737,7 @@ static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s, return a << s; } } +#endif static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s, CPUMIPSState *env) @@ -973,6 +977,7 @@ static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env) return temp & 0x00FF; } +#ifdef TARGET_MIPS64 static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env) { int32_t temp; @@ -997,6 +1002,7 @@ static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env) return temp; } +#endif static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b) { diff --git a/target-mips/helper.h b/target-mips/helper.h index 74ef094..a127db5 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -39,6 +39,11 @@ DEF_HELPER_3(macchiu, tl, env, tl, tl) DEF_HELPER_3(msachi, tl, env, tl, tl) DEF_HELPER_3(msachiu, tl, env, tl, tl) +DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl) +#ifdef TARGET_MIPS64 +DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl) +#endif + #ifndef CONFIG_USER_ONLY /* CP0 helpers */ DEF_HELPER_1(mfc0_mvpcontrol, tl, env) @@ -197,6 +202,25 @@ DEF_HELPER_2(float_cvtw_d, i32, env, i64) DEF_HELPER_3(float_addr_ps, i64, env, i64, i64) DEF_HELPER_3(float_mulr_ps, i64, env, i64, i64) +DEF_HELPER_FLAGS_1(float_class_s, TCG_CALL_NO_RWG_SE, i32, i32) +DEF_HELPER_FLAGS_1(float_class_d, TCG_CALL_NO_RWG_SE, i64, i64) + +#define FOP_PROTO(op) \ +DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \ +DEF_HELPER_4(float_ ## op ## _d, i64, env, i64, i64, i64) +FOP_PROTO(maddf) +FOP_PROTO(msubf) +#undef FOP_PROTO + +#define FOP_PROTO(op) \ +DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \ +DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64) +FOP_PROTO(max) +FOP_PROTO(maxa) +FOP_PROTO(min) +FOP_PROTO(mina) +#undef FOP_PROTO + #define FOP_PROTO(op) \ DEF_HELPER_2(float_ ## op ## l_s, i64, env, i32) \ DEF_HELPER_2(float_ ## op ## l_d, i64, env, i64) \ @@ -214,6 +238,7 @@ DEF_HELPER_2(float_ ## op ## _d, i64, env, i64) FOP_PROTO(sqrt) FOP_PROTO(rsqrt) FOP_PROTO(recip) +FOP_PROTO(rint) #undef FOP_PROTO #define FOP_PROTO(op) \ @@ -279,6 +304,33 @@ FOP_PROTO(le) FOP_PROTO(ngt) #undef FOP_PROTO +#define FOP_PROTO(op) \ +DEF_HELPER_3(r6_cmp_d_ ## op, i64, env, i64, i64) \ +DEF_HELPER_3(r6_cmp_s_ ## op, i32, env, i32, i32) +FOP_PROTO(af) +FOP_PROTO(un) +FOP_PROTO(eq) +FOP_PROTO(ueq) +FOP_PROTO(lt) +FOP_PROTO(ult) +FOP_PROTO(le) +FOP_PROTO(ule) +FOP_PROTO(saf) +FOP_PROTO(sun) +FOP_PROTO(seq) +FOP_PROTO(sueq) +FOP_PROTO(slt) +FOP_PROTO(sult) +FOP_PROTO(sle) +FOP_PROTO(sule) +FOP_PROTO(or) +FOP_PROTO(une) +FOP_PROTO(ne) +FOP_PROTO(sor) +FOP_PROTO(sune) +FOP_PROTO(sne) +#undef FOP_PROTO + /* Special functions */ #ifndef CONFIG_USER_ONLY DEF_HELPER_1(tlbwi, void, env) diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h index 9dfa516..6cb62b2 100644 --- a/target-mips/mips-defs.h +++ b/target-mips/mips-defs.h @@ -30,17 +30,21 @@ #define ISA_MIPS64 0x00000080 #define ISA_MIPS64R2 0x00000100 #define ISA_MIPS32R3 0x00000200 -#define ISA_MIPS32R5 0x00000400 +#define ISA_MIPS64R3 0x00000400 +#define ISA_MIPS32R5 0x00000800 +#define ISA_MIPS64R5 0x00001000 +#define ISA_MIPS32R6 0x00002000 +#define ISA_MIPS64R6 0x00004000 /* MIPS ASEs. */ -#define ASE_MIPS16 0x00001000 -#define ASE_MIPS3D 0x00002000 -#define ASE_MDMX 0x00004000 -#define ASE_DSP 0x00008000 -#define ASE_DSPR2 0x00010000 -#define ASE_MT 0x00020000 -#define ASE_SMARTMIPS 0x00040000 -#define ASE_MICROMIPS 0x00080000 +#define ASE_MIPS16 0x00010000 +#define ASE_MIPS3D 0x00020000 +#define ASE_MDMX 0x00040000 +#define ASE_DSP 0x00080000 +#define ASE_DSPR2 0x00100000 +#define ASE_MT 0x00200000 +#define ASE_SMARTMIPS 0x00400000 +#define ASE_MICROMIPS 0x00800000 /* Chip specific instructions. */ #define INSN_LOONGSON2E 0x20000000 @@ -68,9 +72,15 @@ /* MIPS Technologies "Release 3" */ #define CPU_MIPS32R3 (CPU_MIPS32R2 | ISA_MIPS32R3) +#define CPU_MIPS64R3 (CPU_MIPS64R2 | CPU_MIPS32R3 | ISA_MIPS64R3) /* MIPS Technologies "Release 5" */ #define CPU_MIPS32R5 (CPU_MIPS32R3 | ISA_MIPS32R5) +#define CPU_MIPS64R5 (CPU_MIPS64R3 | CPU_MIPS32R5 | ISA_MIPS64R5) + +/* MIPS Technologies "Release 6" */ +#define CPU_MIPS32R6 (CPU_MIPS32R5 | ISA_MIPS32R6) +#define CPU_MIPS64R6 (CPU_MIPS64R5 | CPU_MIPS32R6 | ISA_MIPS64R6) /* Strictly follow the architecture standard: - Disallow "special" instruction handling for PMON/SPIM. diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index df97b35..5204ed8 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -90,7 +90,6 @@ static inline type do_##name(CPUMIPSState *env, target_ulong addr, \ } \ } #endif -HELPER_LD(lbu, ldub, uint8_t) HELPER_LD(lw, ldl, int32_t) #ifdef TARGET_MIPS64 HELPER_LD(ld, ldq, int64_t) @@ -266,6 +265,29 @@ target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1, (uint64_t)(uint32_t)arg2); } +static inline target_ulong bitswap(target_ulong v) +{ + v = ((v >> 1) & (target_ulong)0x5555555555555555) | + ((v & (target_ulong)0x5555555555555555) << 1); + v = ((v >> 2) & (target_ulong)0x3333333333333333) | + ((v & (target_ulong)0x3333333333333333) << 2); + v = ((v >> 4) & (target_ulong)0x0F0F0F0F0F0F0F0F) | + ((v & (target_ulong)0x0F0F0F0F0F0F0F0F) << 4); + return v; +} + +#ifdef TARGET_MIPS64 +target_ulong helper_dbitswap(target_ulong rt) +{ + return bitswap(rt); +} +#endif + +target_ulong helper_bitswap(target_ulong rt) +{ + return (int32_t)bitswap(rt); +} + #ifndef CONFIG_USER_ONLY static inline hwaddr do_translate_address(CPUMIPSState *env, @@ -2786,6 +2808,110 @@ FLOAT_UNOP(abs) FLOAT_UNOP(chs) #undef FLOAT_UNOP +#define FLOAT_FMADDSUB(name, bits, muladd_arg) \ +uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \ + uint ## bits ## _t fs, \ + uint ## bits ## _t ft, \ + uint ## bits ## _t fd) \ +{ \ + uint ## bits ## _t fdret; \ + \ + fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg, \ + &env->active_fpu.fp_status); \ + update_fcr31(env, GETPC()); \ + return fdret; \ +} + +FLOAT_FMADDSUB(maddf_s, 32, 0) +FLOAT_FMADDSUB(maddf_d, 64, 0) +FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_product) +FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_product) +#undef FLOAT_FMADDSUB + +#define FLOAT_MINMAX(name, bits, minmaxfunc) \ +uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \ + uint ## bits ## _t fs, \ + uint ## bits ## _t ft) \ +{ \ + uint ## bits ## _t fdret; \ + \ + fdret = float ## bits ## _ ## minmaxfunc(fs, ft, \ + &env->active_fpu.fp_status); \ + update_fcr31(env, GETPC()); \ + return fdret; \ +} + +FLOAT_MINMAX(max_s, 32, maxnum) +FLOAT_MINMAX(max_d, 64, maxnum) +FLOAT_MINMAX(maxa_s, 32, maxnummag) +FLOAT_MINMAX(maxa_d, 64, maxnummag) + +FLOAT_MINMAX(min_s, 32, minnum) +FLOAT_MINMAX(min_d, 64, minnum) +FLOAT_MINMAX(mina_s, 32, minnummag) +FLOAT_MINMAX(mina_d, 64, minnummag) +#undef FLOAT_MINMAX + +#define FLOAT_RINT(name, bits) \ +uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \ + uint ## bits ## _t fs) \ +{ \ + uint ## bits ## _t fdret; \ + \ + fdret = float ## bits ## _round_to_int(fs, &env->active_fpu.fp_status); \ + update_fcr31(env, GETPC()); \ + return fdret; \ +} + +FLOAT_RINT(rint_s, 32) +FLOAT_RINT(rint_d, 64) +#undef FLOAT_RINT + +#define FLOAT_CLASS_SIGNALING_NAN 0x001 +#define FLOAT_CLASS_QUIET_NAN 0x002 +#define FLOAT_CLASS_NEGATIVE_INFINITY 0x004 +#define FLOAT_CLASS_NEGATIVE_NORMAL 0x008 +#define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010 +#define FLOAT_CLASS_NEGATIVE_ZERO 0x020 +#define FLOAT_CLASS_POSITIVE_INFINITY 0x040 +#define FLOAT_CLASS_POSITIVE_NORMAL 0x080 +#define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100 +#define FLOAT_CLASS_POSITIVE_ZERO 0x200 + +#define FLOAT_CLASS(name, bits) \ +uint ## bits ## _t helper_float_ ## name (uint ## bits ## _t arg) \ +{ \ + if (float ## bits ## _is_signaling_nan(arg)) { \ + return FLOAT_CLASS_SIGNALING_NAN; \ + } else if (float ## bits ## _is_quiet_nan(arg)) { \ + return FLOAT_CLASS_QUIET_NAN; \ + } else if (float ## bits ## _is_neg(arg)) { \ + if (float ## bits ## _is_infinity(arg)) { \ + return FLOAT_CLASS_NEGATIVE_INFINITY; \ + } else if (float ## bits ## _is_zero(arg)) { \ + return FLOAT_CLASS_NEGATIVE_ZERO; \ + } else if (float ## bits ## _is_zero_or_denormal(arg)) { \ + return FLOAT_CLASS_NEGATIVE_SUBNORMAL; \ + } else { \ + return FLOAT_CLASS_NEGATIVE_NORMAL; \ + } \ + } else { \ + if (float ## bits ## _is_infinity(arg)) { \ + return FLOAT_CLASS_POSITIVE_INFINITY; \ + } else if (float ## bits ## _is_zero(arg)) { \ + return FLOAT_CLASS_POSITIVE_ZERO; \ + } else if (float ## bits ## _is_zero_or_denormal(arg)) { \ + return FLOAT_CLASS_POSITIVE_SUBNORMAL; \ + } else { \ + return FLOAT_CLASS_POSITIVE_NORMAL; \ + } \ + } \ +} + +FLOAT_CLASS(class_s, 32) +FLOAT_CLASS(class_d, 64) +#undef FLOAT_CLASS + /* MIPS specific unary operations */ uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0) { @@ -3261,3 +3387,114 @@ FOP_COND_PS(le, float32_le(fst0, fst1, &env->active_fpu.fp_status), float32_le(fsth0, fsth1, &env->active_fpu.fp_status)) FOP_COND_PS(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status), float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) || float32_le(fsth0, fsth1, &env->active_fpu.fp_status)) + +/* R6 compare operations */ +#define FOP_CONDN_D(op, cond) \ +uint64_t helper_r6_cmp_d_ ## op(CPUMIPSState * env, uint64_t fdt0, \ + uint64_t fdt1) \ +{ \ + uint64_t c; \ + c = cond; \ + update_fcr31(env, GETPC()); \ + if (c) { \ + return -1; \ + } else { \ + return 0; \ + } \ +} + +/* NOTE: the comma operator will make "cond" to eval to false, + * but float64_unordered_quiet() is still called. */ +FOP_CONDN_D(af, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0)) +FOP_CONDN_D(un, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status))) +FOP_CONDN_D(eq, (float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(ueq, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(lt, (float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(ult, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(le, (float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(ule, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))) +/* NOTE: the comma operator will make "cond" to eval to false, + * but float64_unordered() is still called. */ +FOP_CONDN_D(saf, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0)) +FOP_CONDN_D(sun, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status))) +FOP_CONDN_D(seq, (float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(sueq, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(slt, (float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(sult, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(sle, (float64_le(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(sule, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(or, (float64_le_quiet(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(une, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_lt_quiet(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(ne, (float64_lt_quiet(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(sor, (float64_le(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(sune, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_lt(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))) +FOP_CONDN_D(sne, (float64_lt(fdt1, fdt0, &env->active_fpu.fp_status) + || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))) + +#define FOP_CONDN_S(op, cond) \ +uint32_t helper_r6_cmp_s_ ## op(CPUMIPSState * env, uint32_t fst0, \ + uint32_t fst1) \ +{ \ + uint64_t c; \ + c = cond; \ + update_fcr31(env, GETPC()); \ + if (c) { \ + return -1; \ + } else { \ + return 0; \ + } \ +} + +/* NOTE: the comma operator will make "cond" to eval to false, + * but float32_unordered_quiet() is still called. */ +FOP_CONDN_S(af, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0)) +FOP_CONDN_S(un, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status))) +FOP_CONDN_S(eq, (float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(ueq, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) + || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(lt, (float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(ult, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) + || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(le, (float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(ule, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) + || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))) +/* NOTE: the comma operator will make "cond" to eval to false, + * but float32_unordered() is still called. */ +FOP_CONDN_S(saf, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0)) +FOP_CONDN_S(sun, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status))) +FOP_CONDN_S(seq, (float32_eq(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(sueq, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status) + || float32_eq(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(slt, (float32_lt(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(sult, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status) + || float32_lt(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(sle, (float32_le(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(sule, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status) + || float32_le(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(or, (float32_le_quiet(fst1, fst0, &env->active_fpu.fp_status) + || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(une, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) + || float32_lt_quiet(fst1, fst0, &env->active_fpu.fp_status) + || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(ne, (float32_lt_quiet(fst1, fst0, &env->active_fpu.fp_status) + || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(sor, (float32_le(fst1, fst0, &env->active_fpu.fp_status) + || float32_le(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(sune, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status) + || float32_lt(fst1, fst0, &env->active_fpu.fp_status) + || float32_lt(fst0, fst1, &env->active_fpu.fp_status))) +FOP_CONDN_S(sne, (float32_lt(fst1, fst0, &env->active_fpu.fp_status) + || float32_lt(fst0, fst1, &env->active_fpu.fp_status))) diff --git a/target-mips/translate.c b/target-mips/translate.c index 06db150..446eb8a 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -65,7 +65,6 @@ enum { /* Jump and branches */ OPC_J = (0x02 << 26), OPC_JAL = (0x03 << 26), - OPC_JALS = OPC_JAL | 0x5, OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */ OPC_BEQL = (0x14 << 26), OPC_BNE = (0x05 << 26), @@ -74,8 +73,8 @@ enum { OPC_BLEZL = (0x16 << 26), OPC_BGTZ = (0x07 << 26), OPC_BGTZL = (0x17 << 26), - OPC_JALX = (0x1D << 26), /* MIPS 16 only */ - OPC_JALXS = OPC_JALX | 0x5, + OPC_JALX = (0x1D << 26), + OPC_DAUI = (0x1D << 26), /* Load and stores */ OPC_LDL = (0x1A << 26), OPC_LDR = (0x1B << 26), @@ -111,13 +110,55 @@ enum { OPC_SWC2 = (0x3A << 26), OPC_SDC1 = (0x3D << 26), OPC_SDC2 = (0x3E << 26), + /* Compact Branches */ + OPC_BLEZALC = (0x06 << 26), + OPC_BGEZALC = (0x06 << 26), + OPC_BGEUC = (0x06 << 26), + OPC_BGTZALC = (0x07 << 26), + OPC_BLTZALC = (0x07 << 26), + OPC_BLTUC = (0x07 << 26), + OPC_BOVC = (0x08 << 26), + OPC_BEQZALC = (0x08 << 26), + OPC_BEQC = (0x08 << 26), + OPC_BLEZC = (0x16 << 26), + OPC_BGEZC = (0x16 << 26), + OPC_BGEC = (0x16 << 26), + OPC_BGTZC = (0x17 << 26), + OPC_BLTZC = (0x17 << 26), + OPC_BLTC = (0x17 << 26), + OPC_BNVC = (0x18 << 26), + OPC_BNEZALC = (0x18 << 26), + OPC_BNEC = (0x18 << 26), + OPC_BC = (0x32 << 26), + OPC_BEQZC = (0x36 << 26), + OPC_JIC = (0x36 << 26), + OPC_BALC = (0x3A << 26), + OPC_BNEZC = (0x3E << 26), + OPC_JIALC = (0x3E << 26), /* MDMX ASE specific */ OPC_MDMX = (0x1E << 26), /* Cache and prefetch */ OPC_CACHE = (0x2F << 26), OPC_PREF = (0x33 << 26), - /* Reserved major opcode */ - OPC_MAJOR3B_RESERVED = (0x3B << 26), + /* PC-relative address computation / loads */ + OPC_PCREL = (0x3B << 26), +}; + +/* PC-relative address computation / loads */ +#define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19))) +#define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16))) +enum { + /* Instructions determined by bits 19 and 20 */ + OPC_ADDIUPC = OPC_PCREL | (0 << 19), + R6_OPC_LWPC = OPC_PCREL | (1 << 19), + OPC_LWUPC = OPC_PCREL | (2 << 19), + + /* Instructions determined by bits 16 ... 20 */ + OPC_AUIPC = OPC_PCREL | (0x1e << 16), + OPC_ALUIPC = OPC_PCREL | (0x1f << 16), + + /* Other */ + R6_OPC_LDPC = OPC_PCREL | (6 << 18), }; /* MIPS special opcodes */ @@ -157,6 +198,7 @@ enum { OPC_DMULTU = 0x1D | OPC_SPECIAL, OPC_DDIV = 0x1E | OPC_SPECIAL, OPC_DDIVU = 0x1F | OPC_SPECIAL, + /* 2 registers arithmetic / logic */ OPC_ADD = 0x20 | OPC_SPECIAL, OPC_ADDU = 0x21 | OPC_SPECIAL, @@ -175,8 +217,6 @@ enum { /* Jumps */ OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */ OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */ - OPC_JALRC = OPC_JALR | (0x5 << 6), - OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6), /* Traps */ OPC_TGE = 0x30 | OPC_SPECIAL, OPC_TGEU = 0x31 | OPC_SPECIAL, @@ -193,6 +233,9 @@ enum { OPC_MOVZ = 0x0A | OPC_SPECIAL, OPC_MOVN = 0x0B | OPC_SPECIAL, + OPC_SELEQZ = 0x35 | OPC_SPECIAL, + OPC_SELNEZ = 0x37 | OPC_SPECIAL, + OPC_MOVCI = 0x01 | OPC_SPECIAL, /* Special */ @@ -202,15 +245,45 @@ enum { OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */ OPC_SYNC = 0x0F | OPC_SPECIAL, - OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL, OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL, OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL, - OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL, - OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL, OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL, OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL, }; +/* R6 Multiply and Divide instructions have the same Opcode + and function field as legacy OPC_MULT[U]/OPC_DIV[U] */ +#define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff))) + +enum { + R6_OPC_MUL = OPC_MULT | (2 << 6), + R6_OPC_MUH = OPC_MULT | (3 << 6), + R6_OPC_MULU = OPC_MULTU | (2 << 6), + R6_OPC_MUHU = OPC_MULTU | (3 << 6), + R6_OPC_DIV = OPC_DIV | (2 << 6), + R6_OPC_MOD = OPC_DIV | (3 << 6), + R6_OPC_DIVU = OPC_DIVU | (2 << 6), + R6_OPC_MODU = OPC_DIVU | (3 << 6), + + R6_OPC_DMUL = OPC_DMULT | (2 << 6), + R6_OPC_DMUH = OPC_DMULT | (3 << 6), + R6_OPC_DMULU = OPC_DMULTU | (2 << 6), + R6_OPC_DMUHU = OPC_DMULTU | (3 << 6), + R6_OPC_DDIV = OPC_DDIV | (2 << 6), + R6_OPC_DMOD = OPC_DDIV | (3 << 6), + R6_OPC_DDIVU = OPC_DDIVU | (2 << 6), + R6_OPC_DMODU = OPC_DDIVU | (3 << 6), + + R6_OPC_CLZ = 0x10 | OPC_SPECIAL, + R6_OPC_CLO = 0x11 | OPC_SPECIAL, + R6_OPC_DCLZ = 0x12 | OPC_SPECIAL, + R6_OPC_DCLO = 0x13 | OPC_SPECIAL, + R6_OPC_SDBBP = 0x0e | OPC_SPECIAL, + + OPC_LSA = 0x05 | OPC_SPECIAL, + OPC_DLSA = 0x15 | OPC_SPECIAL, +}; + /* Multiplication variants of the vr54xx. */ #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6)) @@ -240,10 +313,8 @@ enum { OPC_BGEZ = (0x01 << 16) | OPC_REGIMM, OPC_BGEZL = (0x03 << 16) | OPC_REGIMM, OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM, - OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */ OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM, OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM, - OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */ OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM, OPC_TGEI = (0x08 << 16) | OPC_REGIMM, OPC_TGEIU = (0x09 << 16) | OPC_REGIMM, @@ -252,6 +323,9 @@ enum { OPC_TEQI = (0x0C << 16) | OPC_REGIMM, OPC_TNEI = (0x0E << 16) | OPC_REGIMM, OPC_SYNCI = (0x1F << 16) | OPC_REGIMM, + + OPC_DAHI = (0x06 << 16) | OPC_REGIMM, + OPC_DATI = (0x1e << 16) | OPC_REGIMM, }; /* Special2 opcodes */ @@ -346,23 +420,37 @@ enum { /* MIPS DSP Accumulator and DSPControl Access Sub-class */ OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3, OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3, + + /* R6 */ + R6_OPC_PREF = 0x35 | OPC_SPECIAL3, + R6_OPC_CACHE = 0x25 | OPC_SPECIAL3, + R6_OPC_LL = 0x36 | OPC_SPECIAL3, + R6_OPC_SC = 0x26 | OPC_SPECIAL3, + R6_OPC_LLD = 0x37 | OPC_SPECIAL3, + R6_OPC_SCD = 0x27 | OPC_SPECIAL3, }; /* BSHFL opcodes */ #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6)) enum { - OPC_WSBH = (0x02 << 6) | OPC_BSHFL, - OPC_SEB = (0x10 << 6) | OPC_BSHFL, - OPC_SEH = (0x18 << 6) | OPC_BSHFL, + OPC_WSBH = (0x02 << 6) | OPC_BSHFL, + OPC_SEB = (0x10 << 6) | OPC_BSHFL, + OPC_SEH = (0x18 << 6) | OPC_BSHFL, + OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */ + OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */ + OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */ }; /* DBSHFL opcodes */ #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6)) enum { - OPC_DSBH = (0x02 << 6) | OPC_DBSHFL, - OPC_DSHD = (0x05 << 6) | OPC_DBSHFL, + OPC_DSBH = (0x02 << 6) | OPC_DBSHFL, + OPC_DSHD = (0x05 << 6) | OPC_DBSHFL, + OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */ + OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */ + OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */ }; /* MIPS DSP REGIMM opcodes */ @@ -851,6 +939,8 @@ enum { OPC_W_FMT = (FMT_W << 21) | OPC_CP1, OPC_L_FMT = (FMT_L << 21) | OPC_CP1, OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1, + OPC_BC1EQZ = (0x09 << 21) | OPC_CP1, + OPC_BC1NEZ = (0x0D << 21) | OPC_CP1, }; #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F) @@ -885,6 +975,8 @@ enum { OPC_CTC2 = (0x06 << 21) | OPC_CP2, OPC_MTHC2 = (0x07 << 21) | OPC_CP2, OPC_BC2 = (0x08 << 21) | OPC_CP2, + OPC_BC2EQZ = (0x09 << 21) | OPC_CP2, + OPC_BC2NEZ = (0x0D << 21) | OPC_CP2, }; #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F)) @@ -1012,7 +1104,7 @@ enum { /* global register indices */ static TCGv_ptr cpu_env; static TCGv cpu_gpr[32], cpu_PC; -static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC]; +static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC]; static TCGv cpu_dspctrl, btarget, bcond; static TCGv_i32 hflags; static TCGv_i32 fpu_fcr0, fpu_fcr31; @@ -1103,10 +1195,6 @@ static const char * const regnames_LO[] = { "LO0", "LO1", "LO2", "LO3", }; -static const char * const regnames_ACX[] = { - "ACX0", "ACX1", "ACX2", "ACX3", -}; - static const char * const fregnames[] = { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", @@ -1149,17 +1237,6 @@ static inline void gen_store_gpr (TCGv t, int reg) tcg_gen_mov_tl(cpu_gpr[reg], t); } -/* Moves to/from ACX register. */ -static inline void gen_load_ACX (TCGv t, int reg) -{ - tcg_gen_mov_tl(t, cpu_ACX[reg]); -} - -static inline void gen_store_ACX (TCGv t, int reg) -{ - tcg_gen_mov_tl(cpu_ACX[reg], t); -} - /* Moves to/from shadow registers. */ static inline void gen_load_srsgpr (int from, int to) { @@ -1343,16 +1420,26 @@ static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv tcg_gen_add_tl(ret, arg0, arg1); #if defined(TARGET_MIPS64) - /* For compatibility with 32-bit code, data reference in user mode - with Status_UX = 0 should be casted to 32-bit and sign extended. - See the MIPS64 PRA manual, section 4.10. */ - if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) && - !(ctx->hflags & MIPS_HFLAG_UX)) { + if (ctx->hflags & MIPS_HFLAG_AWRAP) { tcg_gen_ext32s_i64(ret, ret); } #endif } +/* Addresses computation (translation time) */ +static target_long addr_add(DisasContext *ctx, target_long base, + target_long offset) +{ + target_long sum = base + offset; + +#if defined(TARGET_MIPS64) + if (ctx->hflags & MIPS_HFLAG_AWRAP) { + sum = (int32_t)sum; + } +#endif + return sum; +} + static inline void check_cp0_enabled(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) @@ -1436,6 +1523,17 @@ static inline void check_insn(DisasContext *ctx, int flags) } } +/* This code generates a "reserved instruction" exception if the + CPU has corresponding flag set which indicates that the instruction + has been removed. */ +static inline void check_insn_opc_removed(DisasContext *ctx, int flags) +{ + if (unlikely(ctx->insn_flags & flags)) { + generate_exception(ctx, EXCP_RI); + } +} + +#ifdef TARGET_MIPS64 /* This code generates a "reserved instruction" exception if 64-bit instructions are not enabled. */ static inline void check_mips_64(DisasContext *ctx) @@ -1443,6 +1541,7 @@ static inline void check_mips_64(DisasContext *ctx) if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) generate_exception(ctx, EXCP_RI); } +#endif /* Define small wrappers for gen_load_fpr* so that we have a uniform calling interface for 32 and 64-bit FPRs. No sense in changing @@ -1504,6 +1603,98 @@ FOP_CONDS(abs, 1, s, FMT_S, 32) FOP_CONDS(, 0, ps, FMT_PS, 64) FOP_CONDS(abs, 1, ps, FMT_PS, 64) #undef FOP_CONDS + +#define FOP_CONDNS(fmt, ifmt, bits, STORE) \ +static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \ + int ft, int fs, int fd) \ +{ \ + TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \ + TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \ + switch (ifmt) { \ + case FMT_D: \ + check_cp1_registers(ctx, fs | ft | fd); \ + break; \ + } \ + gen_ldcmp_fpr ## bits(ctx, fp0, fs); \ + gen_ldcmp_fpr ## bits(ctx, fp1, ft); \ + switch (n) { \ + case 0: \ + gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \ + break; \ + case 1: \ + gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \ + break; \ + case 2: \ + gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \ + break; \ + case 3: \ + gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \ + break; \ + case 4: \ + gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \ + break; \ + case 5: \ + gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \ + break; \ + case 6: \ + gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \ + break; \ + case 7: \ + gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \ + break; \ + case 8: \ + gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \ + break; \ + case 9: \ + gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \ + break; \ + case 10: \ + gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \ + break; \ + case 11: \ + gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \ + break; \ + case 12: \ + gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \ + break; \ + case 13: \ + gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \ + break; \ + case 14: \ + gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \ + break; \ + case 15: \ + gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \ + break; \ + case 17: \ + gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \ + break; \ + case 18: \ + gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \ + break; \ + case 19: \ + gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \ + break; \ + case 25: \ + gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \ + break; \ + case 26: \ + gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \ + break; \ + case 27: \ + gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \ + break; \ + default: \ + abort(); \ + } \ + STORE; \ + tcg_temp_free_i ## bits (fp0); \ + tcg_temp_free_i ## bits (fp1); \ +} + +FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd)) +FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(fp0, fd)) +#undef FOP_CONDNS #undef gen_ldcmp_fpr32 #undef gen_ldcmp_fpr64 @@ -1630,6 +1821,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, opn = "ld"; break; case OPC_LLD: + case R6_OPC_LLD: save_cpu_state(ctx, 1); op_ld_lld(t0, t0, ctx); gen_store_gpr(t0, rt); @@ -1764,6 +1956,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, opn = "lwr"; break; case OPC_LL: + case R6_OPC_LL: save_cpu_state(ctx, 1); op_ld_ll(t0, t0, ctx); gen_store_gpr(t0, rt); @@ -1851,12 +2044,14 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt, switch (opc) { #if defined(TARGET_MIPS64) case OPC_SCD: + case R6_OPC_SCD: save_cpu_state(ctx, 1); op_st_scd(t1, t0, rt, ctx); opn = "scd"; break; #endif case OPC_SC: + case R6_OPC_SC: save_cpu_state(ctx, 1); op_st_sc(t1, t0, rt, ctx); opn = "sc"; @@ -2063,8 +2258,15 @@ static void gen_logic_imm(DisasContext *ctx, uint32_t opc, regnames[rs], uimm); break; case OPC_LUI: - tcg_gen_movi_tl(cpu_gpr[rt], imm << 16); - MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm); + if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) { + /* OPC_AUI */ + tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16); + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); + MIPS_DEBUG("aui %s, %s, %04x", regnames[rt], regnames[rs], imm); + } else { + tcg_gen_movi_tl(cpu_gpr[rt], imm << 16); + MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm); + } break; default: @@ -2402,6 +2604,14 @@ static void gen_cond_move(DisasContext *ctx, uint32_t opc, tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]); opn = "movz"; break; + case OPC_SELNEZ: + tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1); + opn = "selnez"; + break; + case OPC_SELEQZ: + tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1); + opn = "seleqz"; + break; } tcg_temp_free(t2); tcg_temp_free(t1); @@ -2660,6 +2870,309 @@ static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg) MIPS_DEBUG("%s %s", opn, regnames[reg]); } +static inline void gen_r6_ld(target_long addr, int reg, int memidx, + TCGMemOp memop) +{ + TCGv t0 = tcg_const_tl(addr); + tcg_gen_qemu_ld_tl(t0, t0, memidx, memop); + gen_store_gpr(t0, reg); + tcg_temp_free(t0); +} + +static inline void gen_pcrel(DisasContext *ctx, int rs, int16_t imm) +{ + target_long offset; + target_long addr; + + switch (MASK_OPC_PCREL_TOP2BITS(ctx->opcode)) { + case OPC_ADDIUPC: + if (rs != 0) { + offset = sextract32(ctx->opcode << 2, 0, 21); + addr = addr_add(ctx, ctx->pc, offset); + tcg_gen_movi_tl(cpu_gpr[rs], addr); + } + break; + case R6_OPC_LWPC: + offset = sextract32(ctx->opcode << 2, 0, 21); + addr = addr_add(ctx, ctx->pc, offset); + gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL); + break; +#if defined(TARGET_MIPS64) + case OPC_LWUPC: + check_mips_64(ctx); + offset = sextract32(ctx->opcode << 2, 0, 21); + addr = addr_add(ctx, ctx->pc, offset); + gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL); + break; +#endif + default: + switch (MASK_OPC_PCREL_TOP5BITS(ctx->opcode)) { + case OPC_AUIPC: + if (rs != 0) { + offset = imm << 16; + addr = addr_add(ctx, ctx->pc, offset); + tcg_gen_movi_tl(cpu_gpr[rs], addr); + } + break; + case OPC_ALUIPC: + if (rs != 0) { + offset = imm << 16; + addr = ~0xFFFF & addr_add(ctx, ctx->pc, offset); + tcg_gen_movi_tl(cpu_gpr[rs], addr); + } + break; +#if defined(TARGET_MIPS64) + case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */ + case R6_OPC_LDPC + (1 << 16): + case R6_OPC_LDPC + (2 << 16): + case R6_OPC_LDPC + (3 << 16): + check_mips_64(ctx); + offset = sextract32(ctx->opcode << 3, 0, 21); + addr = addr_add(ctx, (ctx->pc & ~0x7), offset); + gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ); + break; +#endif + default: + MIPS_INVAL("OPC_PCREL"); + generate_exception(ctx, EXCP_RI); + break; + } + break; + } +} + +static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) +{ + const char *opn = "r6 mul/div"; + TCGv t0, t1; + + if (rd == 0) { + /* Treat as NOP. */ + MIPS_DEBUG("NOP"); + return; + } + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + + switch (opc) { + case R6_OPC_DIV: + { + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + tcg_gen_ext32s_tl(t0, t0); + tcg_gen_ext32s_tl(t1, t1); + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1); + tcg_gen_and_tl(t2, t2, t3); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); + tcg_gen_or_tl(t2, t2, t3); + tcg_gen_movi_tl(t3, 0); + tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); + tcg_gen_div_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + opn = "div"; + break; + case R6_OPC_MOD: + { + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + tcg_gen_ext32s_tl(t0, t0); + tcg_gen_ext32s_tl(t1, t1); + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1); + tcg_gen_and_tl(t2, t2, t3); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); + tcg_gen_or_tl(t2, t2, t3); + tcg_gen_movi_tl(t3, 0); + tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); + tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + opn = "mod"; + break; + case R6_OPC_DIVU: + { + TCGv t2 = tcg_const_tl(0); + TCGv t3 = tcg_const_tl(1); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); + tcg_gen_divu_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + opn = "divu"; + break; + case R6_OPC_MODU: + { + TCGv t2 = tcg_const_tl(0); + TCGv t3 = tcg_const_tl(1); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); + tcg_gen_remu_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + opn = "modu"; + break; + case R6_OPC_MUL: + { + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_mul_i32(t2, t2, t3); + tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + opn = "mul"; + break; + case R6_OPC_MUH: + { + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_muls2_i32(t2, t3, t2, t3); + tcg_gen_ext_i32_tl(cpu_gpr[rd], t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + opn = "muh"; + break; + case R6_OPC_MULU: + { + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_mul_i32(t2, t2, t3); + tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + opn = "mulu"; + break; + case R6_OPC_MUHU: + { + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_mulu2_i32(t2, t3, t2, t3); + tcg_gen_ext_i32_tl(cpu_gpr[rd], t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + opn = "muhu"; + break; +#if defined(TARGET_MIPS64) + case R6_OPC_DDIV: + { + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL); + tcg_gen_and_tl(t2, t2, t3); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); + tcg_gen_or_tl(t2, t2, t3); + tcg_gen_movi_tl(t3, 0); + tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); + tcg_gen_div_tl(cpu_gpr[rd], t0, t1); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + opn = "ddiv"; + break; + case R6_OPC_DMOD: + { + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL); + tcg_gen_and_tl(t2, t2, t3); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); + tcg_gen_or_tl(t2, t2, t3); + tcg_gen_movi_tl(t3, 0); + tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); + tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + opn = "dmod"; + break; + case R6_OPC_DDIVU: + { + TCGv t2 = tcg_const_tl(0); + TCGv t3 = tcg_const_tl(1); + tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); + tcg_gen_divu_i64(cpu_gpr[rd], t0, t1); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + opn = "ddivu"; + break; + case R6_OPC_DMODU: + { + TCGv t2 = tcg_const_tl(0); + TCGv t3 = tcg_const_tl(1); + tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); + tcg_gen_remu_i64(cpu_gpr[rd], t0, t1); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + opn = "dmodu"; + break; + case R6_OPC_DMUL: + tcg_gen_mul_i64(cpu_gpr[rd], t0, t1); + opn = "dmul"; + break; + case R6_OPC_DMUH: + { + TCGv t2 = tcg_temp_new(); + tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1); + tcg_temp_free(t2); + } + opn = "dmuh"; + break; + case R6_OPC_DMULU: + tcg_gen_mul_i64(cpu_gpr[rd], t0, t1); + opn = "dmulu"; + break; + case R6_OPC_DMUHU: + { + TCGv t2 = tcg_temp_new(); + tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1); + tcg_temp_free(t2); + } + opn = "dmuhu"; + break; +#endif + default: + MIPS_INVAL(opn); + generate_exception(ctx, EXCP_RI); + goto out; + } + (void)opn; /* avoid a compiler warning */ + MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]); + out: + tcg_temp_free(t0); + tcg_temp_free(t1); +} + static void gen_muldiv(DisasContext *ctx, uint32_t opc, int acc, int rs, int rt) { @@ -2975,19 +3488,23 @@ static void gen_cl (DisasContext *ctx, uint32_t opc, gen_load_gpr(t0, rs); switch (opc) { case OPC_CLO: + case R6_OPC_CLO: gen_helper_clo(cpu_gpr[rd], t0); opn = "clo"; break; case OPC_CLZ: + case R6_OPC_CLZ: gen_helper_clz(cpu_gpr[rd], t0); opn = "clz"; break; #if defined(TARGET_MIPS64) case OPC_DCLO: + case R6_OPC_DCLO: gen_helper_dclo(cpu_gpr[rd], t0); opn = "dclo"; break; case OPC_DCLZ: + case R6_OPC_DCLZ: gen_helper_dclz(cpu_gpr[rd], t0); opn = "dclz"; break; @@ -3601,7 +4118,8 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) /* Branches (before delay slot) */ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, int insn_bytes, - int rs, int rt, int32_t offset) + int rs, int rt, int32_t offset, + int delayslot_size) { target_ulong btgt = -1; int blink = 0; @@ -3633,7 +4151,6 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, break; case OPC_BGEZ: case OPC_BGEZAL: - case OPC_BGEZALS: case OPC_BGEZALL: case OPC_BGEZL: case OPC_BGTZ: @@ -3642,7 +4159,6 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, case OPC_BLEZL: case OPC_BLTZ: case OPC_BLTZAL: - case OPC_BLTZALS: case OPC_BLTZALL: case OPC_BLTZL: /* Compare to zero */ @@ -3665,15 +4181,11 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, case OPC_J: case OPC_JAL: case OPC_JALX: - case OPC_JALS: - case OPC_JALXS: /* Jump to immediate */ btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset; break; case OPC_JR: case OPC_JALR: - case OPC_JALRC: - case OPC_JALRS: /* Jump to register */ if (offset != 0 && offset != 16) { /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the @@ -3702,12 +4214,8 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, ctx->hflags |= MIPS_HFLAG_B; MIPS_DEBUG("balways"); break; - case OPC_BGEZALS: case OPC_BGEZAL: /* 0 >= 0 */ case OPC_BGEZALL: /* 0 >= 0 likely */ - ctx->hflags |= (opc == OPC_BGEZALS - ? MIPS_HFLAG_BDS16 - : MIPS_HFLAG_BDS32); /* Always take and link */ blink = 31; ctx->hflags |= MIPS_HFLAG_B; @@ -3719,15 +4227,11 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, /* Treat as NOP. */ MIPS_DEBUG("bnever (NOP)"); goto out; - case OPC_BLTZALS: case OPC_BLTZAL: /* 0 < 0 */ - ctx->hflags |= (opc == OPC_BLTZALS - ? MIPS_HFLAG_BDS16 - : MIPS_HFLAG_BDS32); /* Handle as an unconditional branch to get correct delay slot checking. */ blink = 31; - btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8); + btgt = ctx->pc + insn_bytes + delayslot_size; ctx->hflags |= MIPS_HFLAG_B; MIPS_DEBUG("bnever and link"); break; @@ -3748,33 +4252,21 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, ctx->hflags |= MIPS_HFLAG_B; MIPS_DEBUG("j " TARGET_FMT_lx, btgt); break; - case OPC_JALXS: case OPC_JALX: ctx->hflags |= MIPS_HFLAG_BX; /* Fallthrough */ - case OPC_JALS: case OPC_JAL: blink = 31; ctx->hflags |= MIPS_HFLAG_B; - ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS) - ? MIPS_HFLAG_BDS16 - : MIPS_HFLAG_BDS32); MIPS_DEBUG("jal " TARGET_FMT_lx, btgt); break; case OPC_JR: ctx->hflags |= MIPS_HFLAG_BR; - if (insn_bytes == 4) - ctx->hflags |= MIPS_HFLAG_BDS32; MIPS_DEBUG("jr %s", regnames[rs]); break; - case OPC_JALRS: case OPC_JALR: - case OPC_JALRC: blink = rt; ctx->hflags |= MIPS_HFLAG_BR; - ctx->hflags |= (opc == OPC_JALRS - ? MIPS_HFLAG_BDS16 - : MIPS_HFLAG_BDS32); MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]); break; default: @@ -3812,11 +4304,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0); MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt); goto likely; - case OPC_BGEZALS: case OPC_BGEZAL: - ctx->hflags |= (opc == OPC_BGEZALS - ? MIPS_HFLAG_BDS16 - : MIPS_HFLAG_BDS32); tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0); MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt); blink = 31; @@ -3860,11 +4348,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt); goto not_likely; #endif - case OPC_BLTZALS: case OPC_BLTZAL: - ctx->hflags |= (opc == OPC_BLTZALS - ? MIPS_HFLAG_BDS16 - : MIPS_HFLAG_BDS32); tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0); blink = 31; MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt); @@ -3888,13 +4372,20 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, blink, ctx->hflags, btgt); ctx->btarget = btgt; + + switch (delayslot_size) { + case 2: + ctx->hflags |= MIPS_HFLAG_BDS16; + break; + case 4: + ctx->hflags |= MIPS_HFLAG_BDS32; + break; + } + if (blink > 0) { - int post_delay = insn_bytes; + int post_delay = insn_bytes + delayslot_size; int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16); - if (opc != OPC_JALRC) - post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4); - tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit); } @@ -7128,11 +7619,60 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op, MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn, ctx->hflags, btarget); ctx->btarget = btarget; - + ctx->hflags |= MIPS_HFLAG_BDS32; out: tcg_temp_free_i32(t0); } +/* R6 CP1 Branches */ +static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op, + int32_t ft, int32_t offset) +{ + target_ulong btarget; + const char *opn = "cp1 cond branch"; + TCGv_i64 t0 = tcg_temp_new_i64(); + + if (ctx->hflags & MIPS_HFLAG_BMASK) { +#ifdef MIPS_DEBUG_DISAS + LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc); +#endif + generate_exception(ctx, EXCP_RI); + goto out; + } + + gen_load_fpr64(ctx, t0, ft); + tcg_gen_andi_i64(t0, t0, 1); + + btarget = addr_add(ctx, ctx->pc + 4, offset); + + switch (op) { + case OPC_BC1EQZ: + tcg_gen_xori_i64(t0, t0, 1); + opn = "bc1eqz"; + ctx->hflags |= MIPS_HFLAG_BC; + break; + case OPC_BC1NEZ: + /* t0 already set */ + opn = "bc1nez"; + ctx->hflags |= MIPS_HFLAG_BC; + break; + default: + MIPS_INVAL(opn); + generate_exception(ctx, EXCP_RI); + goto out; + } + + tcg_gen_trunc_i64_tl(bcond, t0); + + (void)opn; /* avoid a compiler warning */ + MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn, + ctx->hflags, btarget); + ctx->btarget = btarget; + +out: + tcg_temp_free_i64(t0); +} + /* Coprocessor 1 (FPU) */ #define FOP(func, fmt) (((fmt) << 21) | (func)) @@ -7154,14 +7694,25 @@ enum fopcode { OPC_TRUNC_W_S = FOP(13, FMT_S), OPC_CEIL_W_S = FOP(14, FMT_S), OPC_FLOOR_W_S = FOP(15, FMT_S), + OPC_SEL_S = FOP(16, FMT_S), OPC_MOVCF_S = FOP(17, FMT_S), OPC_MOVZ_S = FOP(18, FMT_S), OPC_MOVN_S = FOP(19, FMT_S), + OPC_SELEQZ_S = FOP(20, FMT_S), OPC_RECIP_S = FOP(21, FMT_S), OPC_RSQRT_S = FOP(22, FMT_S), + OPC_SELNEZ_S = FOP(23, FMT_S), + OPC_MADDF_S = FOP(24, FMT_S), + OPC_MSUBF_S = FOP(25, FMT_S), + OPC_RINT_S = FOP(26, FMT_S), + OPC_CLASS_S = FOP(27, FMT_S), + OPC_MIN_S = FOP(28, FMT_S), OPC_RECIP2_S = FOP(28, FMT_S), + OPC_MINA_S = FOP(29, FMT_S), OPC_RECIP1_S = FOP(29, FMT_S), + OPC_MAX_S = FOP(30, FMT_S), OPC_RSQRT1_S = FOP(30, FMT_S), + OPC_MAXA_S = FOP(31, FMT_S), OPC_RSQRT2_S = FOP(31, FMT_S), OPC_CVT_D_S = FOP(33, FMT_S), OPC_CVT_W_S = FOP(36, FMT_S), @@ -7200,14 +7751,25 @@ enum fopcode { OPC_TRUNC_W_D = FOP(13, FMT_D), OPC_CEIL_W_D = FOP(14, FMT_D), OPC_FLOOR_W_D = FOP(15, FMT_D), + OPC_SEL_D = FOP(16, FMT_D), OPC_MOVCF_D = FOP(17, FMT_D), OPC_MOVZ_D = FOP(18, FMT_D), OPC_MOVN_D = FOP(19, FMT_D), + OPC_SELEQZ_D = FOP(20, FMT_D), OPC_RECIP_D = FOP(21, FMT_D), OPC_RSQRT_D = FOP(22, FMT_D), + OPC_SELNEZ_D = FOP(23, FMT_D), + OPC_MADDF_D = FOP(24, FMT_D), + OPC_MSUBF_D = FOP(25, FMT_D), + OPC_RINT_D = FOP(26, FMT_D), + OPC_CLASS_D = FOP(27, FMT_D), + OPC_MIN_D = FOP(28, FMT_D), OPC_RECIP2_D = FOP(28, FMT_D), + OPC_MINA_D = FOP(29, FMT_D), OPC_RECIP1_D = FOP(29, FMT_D), + OPC_MAX_D = FOP(30, FMT_D), OPC_RSQRT1_D = FOP(30, FMT_D), + OPC_MAXA_D = FOP(31, FMT_D), OPC_RSQRT2_D = FOP(31, FMT_D), OPC_CVT_S_D = FOP(32, FMT_D), OPC_CVT_W_D = FOP(36, FMT_D), @@ -7277,6 +7839,53 @@ enum fopcode { OPC_CMP_NGT_PS = FOP (63, FMT_PS), }; +enum r6_f_cmp_op { + R6_OPC_CMP_AF_S = FOP(0, FMT_W), + R6_OPC_CMP_UN_S = FOP(1, FMT_W), + R6_OPC_CMP_EQ_S = FOP(2, FMT_W), + R6_OPC_CMP_UEQ_S = FOP(3, FMT_W), + R6_OPC_CMP_LT_S = FOP(4, FMT_W), + R6_OPC_CMP_ULT_S = FOP(5, FMT_W), + R6_OPC_CMP_LE_S = FOP(6, FMT_W), + R6_OPC_CMP_ULE_S = FOP(7, FMT_W), + R6_OPC_CMP_SAF_S = FOP(8, FMT_W), + R6_OPC_CMP_SUN_S = FOP(9, FMT_W), + R6_OPC_CMP_SEQ_S = FOP(10, FMT_W), + R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W), + R6_OPC_CMP_SLT_S = FOP(12, FMT_W), + R6_OPC_CMP_SULT_S = FOP(13, FMT_W), + R6_OPC_CMP_SLE_S = FOP(14, FMT_W), + R6_OPC_CMP_SULE_S = FOP(15, FMT_W), + R6_OPC_CMP_OR_S = FOP(17, FMT_W), + R6_OPC_CMP_UNE_S = FOP(18, FMT_W), + R6_OPC_CMP_NE_S = FOP(19, FMT_W), + R6_OPC_CMP_SOR_S = FOP(25, FMT_W), + R6_OPC_CMP_SUNE_S = FOP(26, FMT_W), + R6_OPC_CMP_SNE_S = FOP(27, FMT_W), + + R6_OPC_CMP_AF_D = FOP(0, FMT_L), + R6_OPC_CMP_UN_D = FOP(1, FMT_L), + R6_OPC_CMP_EQ_D = FOP(2, FMT_L), + R6_OPC_CMP_UEQ_D = FOP(3, FMT_L), + R6_OPC_CMP_LT_D = FOP(4, FMT_L), + R6_OPC_CMP_ULT_D = FOP(5, FMT_L), + R6_OPC_CMP_LE_D = FOP(6, FMT_L), + R6_OPC_CMP_ULE_D = FOP(7, FMT_L), + R6_OPC_CMP_SAF_D = FOP(8, FMT_L), + R6_OPC_CMP_SUN_D = FOP(9, FMT_L), + R6_OPC_CMP_SEQ_D = FOP(10, FMT_L), + R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L), + R6_OPC_CMP_SLT_D = FOP(12, FMT_L), + R6_OPC_CMP_SULT_D = FOP(13, FMT_L), + R6_OPC_CMP_SLE_D = FOP(14, FMT_L), + R6_OPC_CMP_SULE_D = FOP(15, FMT_L), + R6_OPC_CMP_OR_D = FOP(17, FMT_L), + R6_OPC_CMP_UNE_D = FOP(18, FMT_L), + R6_OPC_CMP_NE_D = FOP(19, FMT_L), + R6_OPC_CMP_SOR_D = FOP(25, FMT_L), + R6_OPC_CMP_SUNE_D = FOP(26, FMT_L), + R6_OPC_CMP_SNE_D = FOP(27, FMT_L), +}; static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) { const char *opn = "cp1 move"; @@ -7463,6 +8072,79 @@ static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd, gen_set_label(l2); } +static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft, + int fs) +{ + TCGv_i32 t1 = tcg_const_i32(0); + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + TCGv_i32 fp2 = tcg_temp_new_i32(); + gen_load_fpr32(fp0, fd); + gen_load_fpr32(fp1, ft); + gen_load_fpr32(fp2, fs); + + switch (op1) { + case OPC_SEL_S: + tcg_gen_andi_i32(fp0, fp0, 1); + tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2); + break; + case OPC_SELEQZ_S: + tcg_gen_andi_i32(fp1, fp1, 1); + tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1); + break; + case OPC_SELNEZ_S: + tcg_gen_andi_i32(fp1, fp1, 1); + tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1); + break; + default: + MIPS_INVAL("gen_sel_s"); + generate_exception (ctx, EXCP_RI); + break; + } + + gen_store_fpr32(fp0, fd); + tcg_temp_free_i32(fp2); + tcg_temp_free_i32(fp1); + tcg_temp_free_i32(fp0); + tcg_temp_free_i32(t1); +} + +static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft, + int fs) +{ + TCGv_i64 t1 = tcg_const_i64(0); + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + TCGv_i64 fp2 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, fd); + gen_load_fpr64(ctx, fp1, ft); + gen_load_fpr64(ctx, fp2, fs); + + switch (op1) { + case OPC_SEL_D: + tcg_gen_andi_i64(fp0, fp0, 1); + tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2); + break; + case OPC_SELEQZ_D: + tcg_gen_andi_i64(fp1, fp1, 1); + tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1); + break; + case OPC_SELNEZ_D: + tcg_gen_andi_i64(fp1, fp1, 1); + tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1); + break; + default: + MIPS_INVAL("gen_sel_d"); + generate_exception (ctx, EXCP_RI); + break; + } + + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp2); + tcg_temp_free_i64(fp1); + tcg_temp_free_i64(fp0); + tcg_temp_free_i64(t1); +} static void gen_farith (DisasContext *ctx, enum fopcode op1, int ft, int fs, int fd, int cc) @@ -7711,11 +8393,28 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, } opn = "floor.w.s"; break; + case OPC_SEL_S: + check_insn(ctx, ISA_MIPS32R6); + gen_sel_s(ctx, op1, fd, ft, fs); + opn = "sel.s"; + break; + case OPC_SELEQZ_S: + check_insn(ctx, ISA_MIPS32R6); + gen_sel_s(ctx, op1, fd, ft, fs); + opn = "seleqz.s"; + break; + case OPC_SELNEZ_S: + check_insn(ctx, ISA_MIPS32R6); + gen_sel_s(ctx, op1, fd, ft, fs); + opn = "selnez.s"; + break; case OPC_MOVCF_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1); opn = "movcf.s"; break; case OPC_MOVZ_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); { int l1 = gen_new_label(); TCGv_i32 fp0; @@ -7732,6 +8431,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, opn = "movz.s"; break; case OPC_MOVN_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); { int l1 = gen_new_label(); TCGv_i32 fp0; @@ -7771,59 +8471,175 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, } opn = "rsqrt.s"; break; - case OPC_RECIP2_S: - check_cp1_64bitmode(ctx); + case OPC_MADDF_S: + check_insn(ctx, ISA_MIPS32R6); { TCGv_i32 fp0 = tcg_temp_new_i32(); TCGv_i32 fp1 = tcg_temp_new_i32(); - + TCGv_i32 fp2 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); - gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1); + gen_load_fpr32(fp2, fd); + gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2); + gen_store_fpr32(fp2, fd); + tcg_temp_free_i32(fp2); tcg_temp_free_i32(fp1); - gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); + opn = "maddf.s"; } - opn = "recip2.s"; break; - case OPC_RECIP1_S: - check_cp1_64bitmode(ctx); + case OPC_MSUBF_S: + check_insn(ctx, ISA_MIPS32R6); { TCGv_i32 fp0 = tcg_temp_new_i32(); - + TCGv_i32 fp1 = tcg_temp_new_i32(); + TCGv_i32 fp2 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_helper_float_recip1_s(fp0, cpu_env, fp0); - gen_store_fpr32(fp0, fd); + gen_load_fpr32(fp1, ft); + gen_load_fpr32(fp2, fd); + gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2); + gen_store_fpr32(fp2, fd); + tcg_temp_free_i32(fp2); + tcg_temp_free_i32(fp1); tcg_temp_free_i32(fp0); + opn = "msubf.s"; } - opn = "recip1.s"; break; - case OPC_RSQRT1_S: - check_cp1_64bitmode(ctx); + case OPC_RINT_S: + check_insn(ctx, ISA_MIPS32R6); { TCGv_i32 fp0 = tcg_temp_new_i32(); - gen_load_fpr32(fp0, fs); - gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0); + gen_helper_float_rint_s(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); + opn = "rint.s"; } - opn = "rsqrt1.s"; break; - case OPC_RSQRT2_S: - check_cp1_64bitmode(ctx); + case OPC_CLASS_S: + check_insn(ctx, ISA_MIPS32R6); { TCGv_i32 fp0 = tcg_temp_new_i32(); + gen_load_fpr32(fp0, fs); + gen_helper_float_class_s(fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free_i32(fp0); + opn = "class.s"; + } + break; + case OPC_MIN_S: /* OPC_RECIP2_S */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* OPC_MIN_S */ + TCGv_i32 fp0 = tcg_temp_new_i32(); TCGv_i32 fp1 = tcg_temp_new_i32(); + TCGv_i32 fp2 = tcg_temp_new_i32(); + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + gen_helper_float_min_s(fp2, cpu_env, fp0, fp1); + gen_store_fpr32(fp2, fd); + tcg_temp_free_i32(fp2); + tcg_temp_free_i32(fp1); + tcg_temp_free_i32(fp0); + opn = "min.s"; + } else { + /* OPC_RECIP2_S */ + check_cp1_64bitmode(ctx); + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i32(fp1); + gen_store_fpr32(fp0, fd); + tcg_temp_free_i32(fp0); + } + opn = "recip2.s"; + } + break; + case OPC_MINA_S: /* OPC_RECIP1_S */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* OPC_MINA_S */ + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + TCGv_i32 fp2 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); - gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1); + gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1); + gen_store_fpr32(fp2, fd); + tcg_temp_free_i32(fp2); tcg_temp_free_i32(fp1); - gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); + opn = "mina.s"; + } else { + /* OPC_RECIP1_S */ + check_cp1_64bitmode(ctx); + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(fp0, fs); + gen_helper_float_recip1_s(fp0, cpu_env, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free_i32(fp0); + } + opn = "recip1.s"; + } + break; + case OPC_MAX_S: /* OPC_RSQRT1_S */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* OPC_MAX_S */ + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + gen_helper_float_max_s(fp1, cpu_env, fp0, fp1); + gen_store_fpr32(fp1, fd); + tcg_temp_free_i32(fp1); + tcg_temp_free_i32(fp0); + opn = "max.s"; + } else { + /* OPC_RSQRT1_S */ + check_cp1_64bitmode(ctx); + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(fp0, fs); + gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free_i32(fp0); + } + opn = "rsqrt1.s"; + } + break; + case OPC_MAXA_S: /* OPC_RSQRT2_S */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* OPC_MAXA_S */ + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1); + gen_store_fpr32(fp1, fd); + tcg_temp_free_i32(fp1); + tcg_temp_free_i32(fp0); + opn = "maxa.s"; + } else { + /* OPC_RSQRT2_S */ + check_cp1_64bitmode(ctx); + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i32(fp1); + gen_store_fpr32(fp0, fd); + tcg_temp_free_i32(fp0); + } + opn = "rsqrt2.s"; } - opn = "rsqrt2.s"; break; case OPC_CVT_D_S: check_cp1_registers(ctx, fd); @@ -7865,6 +8681,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, opn = "cvt.l.s"; break; case OPC_CVT_PS_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); check_cp1_64bitmode(ctx); { TCGv_i64 fp64 = tcg_temp_new_i64(); @@ -7897,6 +8714,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, case OPC_CMP_NGE_S: case OPC_CMP_LE_S: case OPC_CMP_NGT_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); if (ctx->opcode & (1 << 6)) { gen_cmpabs_s(ctx, func-48, ft, fs, cc); opn = condnames_abs[func-48]; @@ -8120,11 +8938,28 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, } opn = "floor.w.d"; break; + case OPC_SEL_D: + check_insn(ctx, ISA_MIPS32R6); + gen_sel_d(ctx, op1, fd, ft, fs); + opn = "sel.d"; + break; + case OPC_SELEQZ_D: + check_insn(ctx, ISA_MIPS32R6); + gen_sel_d(ctx, op1, fd, ft, fs); + opn = "seleqz.d"; + break; + case OPC_SELNEZ_D: + check_insn(ctx, ISA_MIPS32R6); + gen_sel_d(ctx, op1, fd, ft, fs); + opn = "selnez.d"; + break; case OPC_MOVCF_D: + check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1); opn = "movcf.d"; break; case OPC_MOVZ_D: + check_insn_opc_removed(ctx, ISA_MIPS32R6); { int l1 = gen_new_label(); TCGv_i64 fp0; @@ -8141,6 +8976,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, opn = "movz.d"; break; case OPC_MOVN_D: + check_insn_opc_removed(ctx, ISA_MIPS32R6); { int l1 = gen_new_label(); TCGv_i64 fp0; @@ -8180,59 +9016,171 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, } opn = "rsqrt.d"; break; - case OPC_RECIP2_D: - check_cp1_64bitmode(ctx); + case OPC_MADDF_D: + check_insn(ctx, ISA_MIPS32R6); { TCGv_i64 fp0 = tcg_temp_new_i64(); TCGv_i64 fp1 = tcg_temp_new_i64(); - + TCGv_i64 fp2 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); - gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1); + gen_load_fpr64(ctx, fp2, fd); + gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2); + gen_store_fpr64(ctx, fp2, fd); + tcg_temp_free_i64(fp2); tcg_temp_free_i64(fp1); - gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); + opn = "maddf.d"; } - opn = "recip2.d"; break; - case OPC_RECIP1_D: - check_cp1_64bitmode(ctx); + case OPC_MSUBF_D: + check_insn(ctx, ISA_MIPS32R6); { TCGv_i64 fp0 = tcg_temp_new_i64(); - + TCGv_i64 fp1 = tcg_temp_new_i64(); + TCGv_i64 fp2 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_recip1_d(fp0, cpu_env, fp0); - gen_store_fpr64(ctx, fp0, fd); + gen_load_fpr64(ctx, fp1, ft); + gen_load_fpr64(ctx, fp2, fd); + gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2); + gen_store_fpr64(ctx, fp2, fd); + tcg_temp_free_i64(fp2); + tcg_temp_free_i64(fp1); tcg_temp_free_i64(fp0); + opn = "msubf.d"; } - opn = "recip1.d"; break; - case OPC_RSQRT1_D: - check_cp1_64bitmode(ctx); + case OPC_RINT_D: + check_insn(ctx, ISA_MIPS32R6); { TCGv_i64 fp0 = tcg_temp_new_i64(); - gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0); + gen_helper_float_rint_d(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); + opn = "rint.d"; } - opn = "rsqrt1.d"; break; - case OPC_RSQRT2_D: - check_cp1_64bitmode(ctx); + case OPC_CLASS_D: + check_insn(ctx, ISA_MIPS32R6); { TCGv_i64 fp0 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_class_d(fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + opn = "class.d"; + } + break; + case OPC_MIN_D: /* OPC_RECIP2_D */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* OPC_MIN_D */ + TCGv_i64 fp0 = tcg_temp_new_i64(); TCGv_i64 fp1 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_helper_float_min_d(fp1, cpu_env, fp0, fp1); + gen_store_fpr64(ctx, fp1, fd); + tcg_temp_free_i64(fp1); + tcg_temp_free_i64(fp0); + opn = "min.d"; + } else { + /* OPC_RECIP2_D */ + check_cp1_64bitmode(ctx); + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i64(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + opn = "recip2.d"; + } + break; + case OPC_MINA_D: /* OPC_RECIP1_D */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* OPC_MINA_D */ + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); - gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1); + gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1); + gen_store_fpr64(ctx, fp1, fd); + tcg_temp_free_i64(fp1); + tcg_temp_free_i64(fp0); + opn = "mina.d"; + } else { + /* OPC_RECIP1_D */ + check_cp1_64bitmode(ctx); + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_recip1_d(fp0, cpu_env, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + opn = "recip1.d"; + } + break; + case OPC_MAX_D: /* OPC_RSQRT1_D */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* OPC_MAX_D */ + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_helper_float_max_d(fp1, cpu_env, fp0, fp1); + gen_store_fpr64(ctx, fp1, fd); + tcg_temp_free_i64(fp1); + tcg_temp_free_i64(fp0); + opn = "max.d"; + } else { + /* OPC_RSQRT1_D */ + check_cp1_64bitmode(ctx); + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + opn = "rsqrt1.d"; + } + break; + case OPC_MAXA_D: /* OPC_RSQRT2_D */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* OPC_MAXA_D */ + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1); + gen_store_fpr64(ctx, fp1, fd); tcg_temp_free_i64(fp1); - gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); + opn = "maxa.d"; + } else { + /* OPC_RSQRT2_D */ + check_cp1_64bitmode(ctx); + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i64(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + opn = "rsqrt2.d"; } - opn = "rsqrt2.d"; break; case OPC_CMP_F_D: case OPC_CMP_UN_D: @@ -8250,6 +9198,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, case OPC_CMP_NGE_D: case OPC_CMP_LE_D: case OPC_CMP_NGT_D: + check_insn_opc_removed(ctx, ISA_MIPS32R6); if (ctx->opcode & (1 << 6)) { gen_cmpabs_d(ctx, func-48, ft, fs, cc); opn = condnames_abs[func-48]; @@ -8350,6 +9299,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, opn = "cvt.d.l"; break; case OPC_CVT_PS_PW: + check_insn_opc_removed(ctx, ISA_MIPS32R6); check_cp1_64bitmode(ctx); { TCGv_i64 fp0 = tcg_temp_new_i64(); @@ -9128,7 +10078,7 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd) tcg_temp_free(t0); } -static void handle_delay_slot(DisasContext *ctx, int insn_bytes) +static void gen_branch(DisasContext *ctx, int insn_bytes) { if (ctx->hflags & MIPS_HFLAG_BMASK) { int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK; @@ -9671,15 +10621,15 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx) gen_addiupc(ctx, rx, imm, 0, 1); break; case M16_OPC_B: - gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1); + gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0); /* No delay slot, so just process as a normal instruction */ break; case M16_OPC_BEQZ: - gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1); + gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0); /* No delay slot, so just process as a normal instruction */ break; case M16_OPC_BNEQZ: - gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1); + gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0); /* No delay slot, so just process as a normal instruction */ break; case M16_OPC_SHIFT: @@ -9737,10 +10687,10 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx) case M16_OPC_I8: switch (funct) { case I8_BTEQZ: - gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1); + gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0); break; case I8_BTNEZ: - gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1); + gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0); break; case I8_SWRASP: gen_st(ctx, OPC_SW, 31, 29, imm); @@ -9868,7 +10818,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) case M16_OPC_B: offset = (ctx->opcode & 0x7ff) << 1; offset = (int16_t)(offset << 4) >> 4; - gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset); + gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0); /* No delay slot, so just process as a normal instruction */ break; case M16_OPC_JAL: @@ -9876,16 +10826,18 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) offset = (((ctx->opcode & 0x1f) << 21) | ((ctx->opcode >> 5) & 0x1f) << 16 | offset) << 2; - op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS; - gen_compute_branch(ctx, op, 4, rx, ry, offset); + op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL; + gen_compute_branch(ctx, op, 4, rx, ry, offset, 2); n_bytes = 4; break; case M16_OPC_BEQZ: - gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1); + gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, + ((int8_t)ctx->opcode) << 1, 0); /* No delay slot, so just process as a normal instruction */ break; case M16_OPC_BNEQZ: - gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1); + gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, + ((int8_t)ctx->opcode) << 1, 0); /* No delay slot, so just process as a normal instruction */ break; case M16_OPC_SHIFT: @@ -9958,11 +10910,11 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) switch (funct) { case I8_BTEQZ: gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0, - ((int8_t)ctx->opcode) << 1); + ((int8_t)ctx->opcode) << 1, 0); break; case I8_BTNEZ: gen_compute_branch(ctx, OPC_BNE, 2, 24, 0, - ((int8_t)ctx->opcode) << 1); + ((int8_t)ctx->opcode) << 1, 0); break; case I8_SWRASP: gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2); @@ -10111,12 +11063,13 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) int ra = (ctx->opcode >> 5) & 0x1; if (link) { - op = nd ? OPC_JALRC : OPC_JALRS; + op = OPC_JALR; } else { op = OPC_JR; } - gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0); + gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0, + (nd ? 0 : 2)); } break; case RR_SDBBP: @@ -10874,7 +11827,6 @@ static void gen_pool16c_insn(DisasContext *ctx) { int rd = mmreg((ctx->opcode >> 3) & 0x7); int rs = mmreg(ctx->opcode & 0x7); - int opc; switch (((ctx->opcode) >> 4) & 0x3f) { case NOT16 + 0: @@ -10930,32 +11882,27 @@ static void gen_pool16c_insn(DisasContext *ctx) { int reg = ctx->opcode & 0x1f; - gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0); + gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4); } break; case JRC16 + 0: case JRC16 + 1: { int reg = ctx->opcode & 0x1f; - - gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0); + gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0); /* Let normal delay slot handling in our caller take us to the branch target. */ } break; case JALR16 + 0: case JALR16 + 1: - opc = OPC_JALR; - goto do_jalr; + gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + break; case JALR16S + 0: case JALR16S + 1: - opc = OPC_JALRS; - do_jalr: - { - int reg = ctx->opcode & 0x1f; - - gen_compute_branch(ctx, opc, 2, reg, 31, 0); - } + gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; break; case MFHI16 + 0: case MFHI16 + 1: @@ -10983,8 +11930,7 @@ static void gen_pool16c_insn(DisasContext *ctx) case JRADDIUSP + 1: { int imm = ZIMM(ctx->opcode, 0, 5); - - gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0); + gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0); gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2); /* Let normal delay slot handling in our caller take us to the branch target. */ @@ -11241,11 +12187,13 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs) switch (minor) { case JALR: case JALR_HB: - gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0); + gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; break; case JALRS: case JALRS_HB: - gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0); + gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; break; default: goto pool32axf_invalid; @@ -12135,30 +13083,32 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, minor = (ctx->opcode >> 21) & 0x1f; switch (minor) { case BLTZ: - mips32_op = OPC_BLTZ; - goto do_branch; + gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4); + break; case BLTZAL: - mips32_op = OPC_BLTZAL; - goto do_branch; + gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + break; case BLTZALS: - mips32_op = OPC_BLTZALS; - goto do_branch; + gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + break; case BGEZ: - mips32_op = OPC_BGEZ; - goto do_branch; + gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4); + break; case BGEZAL: - mips32_op = OPC_BGEZAL; - goto do_branch; + gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + break; case BGEZALS: - mips32_op = OPC_BGEZALS; - goto do_branch; + gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + break; case BLEZ: - mips32_op = OPC_BLEZ; - goto do_branch; + gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4); + break; case BGTZ: - mips32_op = OPC_BGTZ; - do_branch: - gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1); + gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4); break; /* Traps */ @@ -12186,7 +13136,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, case BNEZC: case BEQZC: gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ, - 4, rs, 0, imm << 1); + 4, rs, 0, imm << 1, 0); /* Compact branches don't have a delay slot, so just let the normal delay slot handling take us to the branch target. */ @@ -12195,6 +13145,9 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, gen_logic_imm(ctx, OPC_LUI, rs, -1, imm); break; case SYNCI: + /* Break the TB to be able to sync copied instructions + immediately */ + ctx->bstate = BS_STOP; break; case BC2F: case BC2T: @@ -12324,25 +13277,28 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, break; case JALX32: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; - gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset); + gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; break; case JALS32: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1; - gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset); + gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; break; case BEQ32: - gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1); + gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4); break; case BNE32: - gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1); + gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4); break; case J32: gen_compute_branch(ctx, OPC_J, 4, rt, rs, - (int32_t)(ctx->opcode & 0x3FFFFFF) << 1); + (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); break; case JAL32: gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, - (int32_t)(ctx->opcode & 0x3FFFFFF) << 1); + (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; break; /* Floating point (COP1) */ case LWC132: @@ -12426,84 +13382,41 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx) op = (ctx->opcode >> 10) & 0x3f; /* Enforce properly-sized instructions in a delay slot */ - if (ctx->hflags & MIPS_HFLAG_BMASK) { - int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT; - - switch (op) { - case POOL32A: - case POOL32B: - case POOL32I: - case POOL32C: - case ADDI32: - case ADDIU32: - case ORI32: - case XORI32: - case SLTI32: - case SLTIU32: - case ANDI32: - case JALX32: - case LBU32: - case LHU32: - case POOL32F: - case JALS32: - case BEQ32: - case BNE32: - case J32: - case JAL32: - case SB32: - case SH32: - case POOL32S: - case ADDIUPC: - case SWC132: - case SDC132: - case SD32: - case SW32: - case LB32: - case LH32: - case DADDIU32: - case LWC132: - case LDC132: - case LD32: - case LW32: - if (bits & MIPS_HFLAG_BDS16) { + if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) { + switch (op & 0x7) { /* MSB-3..MSB-5 */ + case 0: + /* POOL32A, POOL32B, POOL32I, POOL32C */ + case 4: + /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */ + case 5: + /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */ + case 6: + /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */ + case 7: + /* LB32, LH32, LWC132, LDC132, LW32 */ + if (ctx->hflags & MIPS_HFLAG_BDS16) { generate_exception(ctx, EXCP_RI); /* Just stop translation; the user is confused. */ ctx->bstate = BS_STOP; return 2; } break; - case POOL16A: - case POOL16B: - case POOL16C: - case LWGP16: - case POOL16F: - case LBU16: - case LHU16: - case LWSP16: - case LW16: - case SB16: - case SH16: - case SWSP16: - case SW16: - case MOVE16: - case ANDI16: - case POOL16D: - case POOL16E: - case BEQZ16: - case BNEZ16: - case B16: - case LI16: - if (bits & MIPS_HFLAG_BDS32) { + case 1: + /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */ + case 2: + /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */ + case 3: + /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */ + if (ctx->hflags & MIPS_HFLAG_BDS32) { generate_exception(ctx, EXCP_RI); /* Just stop translation; the user is confused. */ ctx->bstate = BS_STOP; return 2; } break; - default: - break; } } + switch (op) { case POOL16A: { @@ -12684,13 +13597,13 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx) break; case B16: gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, - SIMM(ctx->opcode, 0, 10) << 1); + SIMM(ctx->opcode, 0, 10) << 1, 4); break; case BNEZ16: case BEQZ16: gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2, mmreg(uMIPS_RD(ctx->opcode)), - 0, SIMM(ctx->opcode, 0, 7) << 1); + 0, SIMM(ctx->opcode, 0, 7) << 1, 4); break; case LI16: { @@ -14447,905 +15360,1521 @@ static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, /* End MIPSDSP functions. */ -static void decode_opc (CPUMIPSState *env, DisasContext *ctx) +/* Compact Branches */ +static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, + int rs, int rt, int32_t offset) { - int32_t offset; - int rs, rt, rd, sa; - uint32_t op, op1, op2; - int16_t imm; + int bcond_compute = 0; + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); - /* make sure instructions are on a word boundary */ - if (ctx->pc & 0x3) { - env->CP0_BadVAddr = ctx->pc; - generate_exception(ctx, EXCP_AdEL); - return; + if (ctx->hflags & MIPS_HFLAG_BMASK) { +#ifdef MIPS_DEBUG_DISAS + LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc); +#endif + generate_exception(ctx, EXCP_RI); + goto out; } - /* Handle blikely not taken case */ - if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) { - int l1 = gen_new_label(); - - MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4); - tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1); - tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK); - gen_goto_tb(ctx, 1, ctx->pc + 4); - gen_set_label(l1); - } + /* Load needed operands and calculate btarget */ + switch (opc) { + /* compact branch */ + case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */ + case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */ + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + bcond_compute = 1; + ctx->btarget = addr_add(ctx, ctx->pc + 4, offset); + if (rs <= rt && rs == 0) { + /* OPC_BEQZALC, OPC_BNEZALC */ + tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4); + } + break; + case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */ + case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */ + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + bcond_compute = 1; + ctx->btarget = addr_add(ctx, ctx->pc + 4, offset); + break; + case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */ + case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */ + if (rs == 0 || rs == rt) { + /* OPC_BLEZALC, OPC_BGEZALC */ + /* OPC_BGTZALC, OPC_BLTZALC */ + tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4); + } + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + bcond_compute = 1; + ctx->btarget = addr_add(ctx, ctx->pc + 4, offset); + break; + case OPC_BC: + case OPC_BALC: + ctx->btarget = addr_add(ctx, ctx->pc + 4, offset); + break; + case OPC_BEQZC: + case OPC_BNEZC: + if (rs != 0) { + /* OPC_BEQZC, OPC_BNEZC */ + gen_load_gpr(t0, rs); + bcond_compute = 1; + ctx->btarget = addr_add(ctx, ctx->pc + 4, offset); + } else { + /* OPC_JIC, OPC_JIALC */ + TCGv tbase = tcg_temp_new(); + TCGv toffset = tcg_temp_new(); - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(ctx->pc); + gen_load_gpr(tbase, rt); + tcg_gen_movi_tl(toffset, offset); + gen_op_addr_add(ctx, btarget, tbase, toffset); + tcg_temp_free(tbase); + tcg_temp_free(toffset); + } + break; + default: + MIPS_INVAL("Compact branch/jump"); + generate_exception(ctx, EXCP_RI); + goto out; } - op = MASK_OP_MAJOR(ctx->opcode); - rs = (ctx->opcode >> 21) & 0x1f; - rt = (ctx->opcode >> 16) & 0x1f; - rd = (ctx->opcode >> 11) & 0x1f; - sa = (ctx->opcode >> 6) & 0x1f; - imm = (int16_t)ctx->opcode; - switch (op) { - case OPC_SPECIAL: - op1 = MASK_SPECIAL(ctx->opcode); - switch (op1) { - case OPC_SLL: /* Shift with immediate */ - case OPC_SRA: - gen_shift_imm(ctx, op1, rd, rt, sa); + if (bcond_compute == 0) { + /* Uncoditional compact branch */ + switch (opc) { + case OPC_JIALC: + tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4); + /* Fallthrough */ + case OPC_JIC: + ctx->hflags |= MIPS_HFLAG_BR; break; - case OPC_SRL: - switch ((ctx->opcode >> 21) & 0x1f) { - case 1: - /* rotr is decoded as srl on non-R2 CPUs */ - if (ctx->insn_flags & ISA_MIPS32R2) { - op1 = OPC_ROTR; - } - /* Fallthrough */ - case 0: - gen_shift_imm(ctx, op1, rd, rt, sa); - break; - default: - generate_exception(ctx, EXCP_RI); - break; - } + case OPC_BALC: + tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4); + /* Fallthrough */ + case OPC_BC: + ctx->hflags |= MIPS_HFLAG_B; break; - case OPC_MOVN: /* Conditional move */ - case OPC_MOVZ: - check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 | - INSN_LOONGSON2E | INSN_LOONGSON2F); - gen_cond_move(ctx, op1, rd, rs, rt); + default: + MIPS_INVAL("Compact branch/jump"); + generate_exception(ctx, EXCP_RI); + goto out; + } + + /* Generating branch here as compact branches don't have delay slot */ + gen_branch(ctx, 4); + } else { + /* Conditional compact branch */ + int l1 = gen_new_label(); + save_cpu_state(ctx, 0); + + switch (opc) { + case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */ + if (rs == 0 && rt != 0) { + /* OPC_BLEZALC */ + tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1); + } else if (rs != 0 && rt != 0 && rs == rt) { + /* OPC_BGEZALC */ + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1); + } else { + /* OPC_BGEUC */ + tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1); + } break; - case OPC_ADD ... OPC_SUBU: - gen_arith(ctx, op1, rd, rs, rt); + case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */ + if (rs == 0 && rt != 0) { + /* OPC_BGTZALC */ + tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1); + } else if (rs != 0 && rt != 0 && rs == rt) { + /* OPC_BLTZALC */ + tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1); + } else { + /* OPC_BLTUC */ + tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1); + } break; - case OPC_SLLV: /* Shifts */ - case OPC_SRAV: - gen_shift(ctx, op1, rd, rs, rt); + case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */ + if (rs == 0 && rt != 0) { + /* OPC_BLEZC */ + tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1); + } else if (rs != 0 && rt != 0 && rs == rt) { + /* OPC_BGEZC */ + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1); + } else { + /* OPC_BGEC */ + tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1); + } break; - case OPC_SRLV: - switch ((ctx->opcode >> 6) & 0x1f) { - case 1: - /* rotrv is decoded as srlv on non-R2 CPUs */ - if (ctx->insn_flags & ISA_MIPS32R2) { - op1 = OPC_ROTRV; - } - /* Fallthrough */ - case 0: - gen_shift(ctx, op1, rd, rs, rt); - break; - default: - generate_exception(ctx, EXCP_RI); - break; + case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */ + if (rs == 0 && rt != 0) { + /* OPC_BGTZC */ + tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1); + } else if (rs != 0 && rt != 0 && rs == rt) { + /* OPC_BLTZC */ + tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1); + } else { + /* OPC_BLTC */ + tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1); } break; - case OPC_SLT: /* Set on less than */ - case OPC_SLTU: - gen_slt(ctx, op1, rd, rs, rt); - break; - case OPC_AND: /* Logic*/ - case OPC_OR: - case OPC_NOR: - case OPC_XOR: - gen_logic(ctx, op1, rd, rs, rt); - break; - case OPC_MULT: - case OPC_MULTU: - if (sa) { - check_insn(ctx, INSN_VR54XX); - op1 = MASK_MUL_VR54XX(ctx->opcode); - gen_mul_vr54xx(ctx, op1, rd, rs, rt); + case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */ + case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */ + if (rs >= rt) { + /* OPC_BOVC, OPC_BNVC */ + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + TCGv t4 = tcg_temp_new(); + TCGv input_overflow = tcg_temp_new(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_ext32s_tl(t2, t0); + tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0); + tcg_gen_ext32s_tl(t3, t1); + tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1); + tcg_gen_or_tl(input_overflow, input_overflow, t4); + + tcg_gen_add_tl(t4, t2, t3); + tcg_gen_ext32s_tl(t4, t4); + tcg_gen_xor_tl(t2, t2, t3); + tcg_gen_xor_tl(t3, t4, t3); + tcg_gen_andc_tl(t2, t3, t2); + tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0); + tcg_gen_or_tl(t4, t4, input_overflow); + if (opc == OPC_BOVC) { + /* OPC_BOVC */ + tcg_gen_brcondi_tl(TCG_COND_NE, t4, 0, l1); + } else { + /* OPC_BNVC */ + tcg_gen_brcondi_tl(TCG_COND_EQ, t4, 0, l1); + } + tcg_temp_free(input_overflow); + tcg_temp_free(t4); + tcg_temp_free(t3); + tcg_temp_free(t2); + } else if (rs < rt && rs == 0) { + /* OPC_BEQZALC, OPC_BNEZALC */ + if (opc == OPC_BEQZALC) { + /* OPC_BEQZALC */ + tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); + } else { + /* OPC_BNEZALC */ + tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); + } } else { - gen_muldiv(ctx, op1, rd & 3, rs, rt); + /* OPC_BEQC, OPC_BNEC */ + if (opc == OPC_BEQC) { + /* OPC_BEQC */ + tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1); + } else { + /* OPC_BNEC */ + tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1); + } } break; - case OPC_DIV: - case OPC_DIVU: - gen_muldiv(ctx, op1, 0, rs, rt); + case OPC_BEQZC: + tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); break; - case OPC_JR ... OPC_JALR: - gen_compute_branch(ctx, op1, 4, rs, rd, sa); + case OPC_BNEZC: + tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1); break; - case OPC_TGE ... OPC_TEQ: /* Traps */ - case OPC_TNE: - gen_trap(ctx, op1, rs, rt, -1); + default: + MIPS_INVAL("Compact conditional branch/jump"); + generate_exception(ctx, EXCP_RI); + goto out; + } + + /* Generating branch here as compact branches don't have delay slot */ + /* TODO: implement forbidden slot */ + gen_goto_tb(ctx, 1, ctx->pc + 4); + gen_set_label(l1); + gen_goto_tb(ctx, 0, ctx->btarget); + MIPS_DEBUG("Compact conditional branch"); + ctx->bstate = BS_BRANCH; + } + +out: + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) +{ + int rs, rt, rd, sa; + uint32_t op1, op2; + + rs = (ctx->opcode >> 21) & 0x1f; + rt = (ctx->opcode >> 16) & 0x1f; + rd = (ctx->opcode >> 11) & 0x1f; + sa = (ctx->opcode >> 6) & 0x1f; + + op1 = MASK_SPECIAL(ctx->opcode); + switch (op1) { + case OPC_LSA: + if (rd != 0) { + int imm2 = extract32(ctx->opcode, 6, 3); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_shli_tl(t0, t0, imm2 + 1); + tcg_gen_add_tl(t0, t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], t0); + tcg_temp_free(t1); + tcg_temp_free(t0); + } + break; + case OPC_MULT ... OPC_DIVU: + op2 = MASK_R6_MULDIV(ctx->opcode); + switch (op2) { + case R6_OPC_MUL: + case R6_OPC_MUH: + case R6_OPC_MULU: + case R6_OPC_MUHU: + case R6_OPC_DIV: + case R6_OPC_MOD: + case R6_OPC_DIVU: + case R6_OPC_MODU: + gen_r6_muldiv(ctx, op2, rd, rs, rt); break; - case OPC_MFHI: /* Move from HI/LO */ - case OPC_MFLO: - gen_HILO(ctx, op1, rs & 3, rd); + default: + MIPS_INVAL("special_r6 muldiv"); + generate_exception(ctx, EXCP_RI); break; - case OPC_MTHI: - case OPC_MTLO: /* Move to HI/LO */ - gen_HILO(ctx, op1, rd & 3, rs); + } + break; + case OPC_SELEQZ: + case OPC_SELNEZ: + gen_cond_move(ctx, op1, rd, rs, rt); + break; + case R6_OPC_CLO: + case R6_OPC_CLZ: + if (rt == 0 && sa == 1) { + /* Major opcode and function field is shared with preR6 MFHI/MTHI. + We need additionally to check other fields */ + gen_cl(ctx, op1, rd, rs); + } else { + generate_exception(ctx, EXCP_RI); + } + break; + case R6_OPC_SDBBP: + generate_exception(ctx, EXCP_DBp); + break; +#if defined(TARGET_MIPS64) + case OPC_DLSA: + check_mips_64(ctx); + if (rd != 0) { + int imm2 = extract32(ctx->opcode, 6, 3); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_shli_tl(t0, t0, imm2 + 1); + tcg_gen_add_tl(cpu_gpr[rd], t0, t1); + tcg_temp_free(t1); + tcg_temp_free(t0); + } + break; + case R6_OPC_DCLO: + case R6_OPC_DCLZ: + if (rt == 0 && sa == 1) { + /* Major opcode and function field is shared with preR6 MFHI/MTHI. + We need additionally to check other fields */ + check_mips_64(ctx); + gen_cl(ctx, op1, rd, rs); + } else { + generate_exception(ctx, EXCP_RI); + } + break; + case OPC_DMULT ... OPC_DDIVU: + op2 = MASK_R6_MULDIV(ctx->opcode); + switch (op2) { + case R6_OPC_DMUL: + case R6_OPC_DMUH: + case R6_OPC_DMULU: + case R6_OPC_DMUHU: + case R6_OPC_DDIV: + case R6_OPC_DMOD: + case R6_OPC_DDIVU: + case R6_OPC_DMODU: + check_mips_64(ctx); + gen_r6_muldiv(ctx, op2, rd, rs, rt); break; - case OPC_PMON: /* Pmon entry point, also R4010 selsl */ -#ifdef MIPS_STRICT_STANDARD - MIPS_INVAL("PMON / selsl"); + default: + MIPS_INVAL("special_r6 muldiv"); generate_exception(ctx, EXCP_RI); + break; + } + break; +#endif + default: /* Invalid */ + MIPS_INVAL("special_r6"); + generate_exception(ctx, EXCP_RI); + break; + } +} + +static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx) +{ + int rs, rt, rd, sa; + uint32_t op1; + + rs = (ctx->opcode >> 21) & 0x1f; + rt = (ctx->opcode >> 16) & 0x1f; + rd = (ctx->opcode >> 11) & 0x1f; + sa = (ctx->opcode >> 6) & 0x1f; + + op1 = MASK_SPECIAL(ctx->opcode); + switch (op1) { + case OPC_MOVN: /* Conditional move */ + case OPC_MOVZ: + check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 | + INSN_LOONGSON2E | INSN_LOONGSON2F); + gen_cond_move(ctx, op1, rd, rs, rt); + break; + case OPC_MFHI: /* Move from HI/LO */ + case OPC_MFLO: + gen_HILO(ctx, op1, rs & 3, rd); + break; + case OPC_MTHI: + case OPC_MTLO: /* Move to HI/LO */ + gen_HILO(ctx, op1, rd & 3, rs); + break; + case OPC_MOVCI: + check_insn(ctx, ISA_MIPS4 | ISA_MIPS32); + if (env->CP0_Config1 & (1 << CP0C1_FP)) { + check_cp1_enabled(ctx); + gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7, + (ctx->opcode >> 16) & 1); + } else { + generate_exception_err(ctx, EXCP_CpU, 1); + } + break; + case OPC_MULT: + case OPC_MULTU: + if (sa) { + check_insn(ctx, INSN_VR54XX); + op1 = MASK_MUL_VR54XX(ctx->opcode); + gen_mul_vr54xx(ctx, op1, rd, rs, rt); + } else { + gen_muldiv(ctx, op1, rd & 3, rs, rt); + } + break; + case OPC_DIV: + case OPC_DIVU: + gen_muldiv(ctx, op1, 0, rs, rt); + break; +#if defined(TARGET_MIPS64) + case OPC_DMULT ... OPC_DDIVU: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_muldiv(ctx, op1, 0, rs, rt); + break; +#endif + case OPC_JR: + gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4); + break; + case OPC_SPIM: +#ifdef MIPS_STRICT_STANDARD + MIPS_INVAL("SPIM"); + generate_exception(ctx, EXCP_RI); #else - gen_helper_0e0i(pmon, sa); + /* Implemented as RI exception for now. */ + MIPS_INVAL("spim (unofficial)"); + generate_exception(ctx, EXCP_RI); #endif + break; + default: /* Invalid */ + MIPS_INVAL("special_legacy"); + generate_exception(ctx, EXCP_RI); + break; + } +} + +static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) +{ + int rs, rt, rd, sa; + uint32_t op1; + + rs = (ctx->opcode >> 21) & 0x1f; + rt = (ctx->opcode >> 16) & 0x1f; + rd = (ctx->opcode >> 11) & 0x1f; + sa = (ctx->opcode >> 6) & 0x1f; + + op1 = MASK_SPECIAL(ctx->opcode); + switch (op1) { + case OPC_SLL: /* Shift with immediate */ + case OPC_SRA: + gen_shift_imm(ctx, op1, rd, rt, sa); + break; + case OPC_SRL: + switch ((ctx->opcode >> 21) & 0x1f) { + case 1: + /* rotr is decoded as srl on non-R2 CPUs */ + if (ctx->insn_flags & ISA_MIPS32R2) { + op1 = OPC_ROTR; + } + /* Fallthrough */ + case 0: + gen_shift_imm(ctx, op1, rd, rt, sa); break; - case OPC_SYSCALL: - generate_exception(ctx, EXCP_SYSCALL); - ctx->bstate = BS_STOP; + default: + generate_exception(ctx, EXCP_RI); break; - case OPC_BREAK: - generate_exception(ctx, EXCP_BREAK); + } + break; + case OPC_ADD ... OPC_SUBU: + gen_arith(ctx, op1, rd, rs, rt); + break; + case OPC_SLLV: /* Shifts */ + case OPC_SRAV: + gen_shift(ctx, op1, rd, rs, rt); + break; + case OPC_SRLV: + switch ((ctx->opcode >> 6) & 0x1f) { + case 1: + /* rotrv is decoded as srlv on non-R2 CPUs */ + if (ctx->insn_flags & ISA_MIPS32R2) { + op1 = OPC_ROTRV; + } + /* Fallthrough */ + case 0: + gen_shift(ctx, op1, rd, rs, rt); + break; + default: + generate_exception(ctx, EXCP_RI); break; - case OPC_SPIM: + } + break; + case OPC_SLT: /* Set on less than */ + case OPC_SLTU: + gen_slt(ctx, op1, rd, rs, rt); + break; + case OPC_AND: /* Logic*/ + case OPC_OR: + case OPC_NOR: + case OPC_XOR: + gen_logic(ctx, op1, rd, rs, rt); + break; + case OPC_JALR: + gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4); + break; + case OPC_TGE ... OPC_TEQ: /* Traps */ + case OPC_TNE: + gen_trap(ctx, op1, rs, rt, -1); + break; + case OPC_LSA: /* OPC_PMON */ + if (ctx->insn_flags & ISA_MIPS32R6) { + decode_opc_special_r6(env, ctx); + } else { + /* Pmon entry point, also R4010 selsl */ #ifdef MIPS_STRICT_STANDARD - MIPS_INVAL("SPIM"); + MIPS_INVAL("PMON / selsl"); generate_exception(ctx, EXCP_RI); #else - /* Implemented as RI exception for now. */ - MIPS_INVAL("spim (unofficial)"); - generate_exception(ctx, EXCP_RI); + gen_helper_0e0i(pmon, sa); #endif - break; - case OPC_SYNC: - /* Treat as NOP. */ - break; - - case OPC_MOVCI: - check_insn(ctx, ISA_MIPS4 | ISA_MIPS32); - if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { - check_cp1_enabled(ctx); - gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7, - (ctx->opcode >> 16) & 1); - } else { - generate_exception_err(ctx, EXCP_CpU, 1); - } - break; + } + break; + case OPC_SYSCALL: + generate_exception(ctx, EXCP_SYSCALL); + ctx->bstate = BS_STOP; + break; + case OPC_BREAK: + generate_exception(ctx, EXCP_BREAK); + break; + case OPC_SYNC: + /* Treat as NOP. */ + break; #if defined(TARGET_MIPS64) - /* MIPS64 specific opcodes */ - case OPC_DSLL: - case OPC_DSRA: - case OPC_DSLL32: - case OPC_DSRA32: + /* MIPS64 specific opcodes */ + case OPC_DSLL: + case OPC_DSRA: + case OPC_DSLL32: + case OPC_DSRA32: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift_imm(ctx, op1, rd, rt, sa); + break; + case OPC_DSRL: + switch ((ctx->opcode >> 21) & 0x1f) { + case 1: + /* drotr is decoded as dsrl on non-R2 CPUs */ + if (ctx->insn_flags & ISA_MIPS32R2) { + op1 = OPC_DROTR; + } + /* Fallthrough */ + case 0: check_insn(ctx, ISA_MIPS3); check_mips_64(ctx); gen_shift_imm(ctx, op1, rd, rt, sa); break; - case OPC_DSRL: - switch ((ctx->opcode >> 21) & 0x1f) { - case 1: - /* drotr is decoded as dsrl on non-R2 CPUs */ - if (ctx->insn_flags & ISA_MIPS32R2) { - op1 = OPC_DROTR; - } - /* Fallthrough */ - case 0: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift_imm(ctx, op1, rd, rt, sa); - break; - default: - generate_exception(ctx, EXCP_RI); - break; - } + default: + generate_exception(ctx, EXCP_RI); break; - case OPC_DSRL32: - switch ((ctx->opcode >> 21) & 0x1f) { - case 1: - /* drotr32 is decoded as dsrl32 on non-R2 CPUs */ - if (ctx->insn_flags & ISA_MIPS32R2) { - op1 = OPC_DROTR32; - } - /* Fallthrough */ - case 0: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift_imm(ctx, op1, rd, rt, sa); - break; - default: - generate_exception(ctx, EXCP_RI); - break; + } + break; + case OPC_DSRL32: + switch ((ctx->opcode >> 21) & 0x1f) { + case 1: + /* drotr32 is decoded as dsrl32 on non-R2 CPUs */ + if (ctx->insn_flags & ISA_MIPS32R2) { + op1 = OPC_DROTR32; } - break; - case OPC_DADD ... OPC_DSUBU: + /* Fallthrough */ + case 0: check_insn(ctx, ISA_MIPS3); check_mips_64(ctx); - gen_arith(ctx, op1, rd, rs, rt); + gen_shift_imm(ctx, op1, rd, rt, sa); break; - case OPC_DSLLV: - case OPC_DSRAV: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift(ctx, op1, rd, rs, rt); + default: + generate_exception(ctx, EXCP_RI); break; - case OPC_DSRLV: - switch ((ctx->opcode >> 6) & 0x1f) { - case 1: - /* drotrv is decoded as dsrlv on non-R2 CPUs */ - if (ctx->insn_flags & ISA_MIPS32R2) { - op1 = OPC_DROTRV; - } - /* Fallthrough */ - case 0: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift(ctx, op1, rd, rs, rt); - break; - default: - generate_exception(ctx, EXCP_RI); - break; + } + break; + case OPC_DADD ... OPC_DSUBU: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_arith(ctx, op1, rd, rs, rt); + break; + case OPC_DSLLV: + case OPC_DSRAV: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift(ctx, op1, rd, rs, rt); + break; + case OPC_DSRLV: + switch ((ctx->opcode >> 6) & 0x1f) { + case 1: + /* drotrv is decoded as dsrlv on non-R2 CPUs */ + if (ctx->insn_flags & ISA_MIPS32R2) { + op1 = OPC_DROTRV; } - break; - case OPC_DMULT ... OPC_DDIVU: + /* Fallthrough */ + case 0: check_insn(ctx, ISA_MIPS3); check_mips_64(ctx); - gen_muldiv(ctx, op1, 0, rs, rt); + gen_shift(ctx, op1, rd, rs, rt); break; -#endif - default: /* Invalid */ - MIPS_INVAL("special"); + default: generate_exception(ctx, EXCP_RI); break; } break; - case OPC_SPECIAL2: - op1 = MASK_SPECIAL2(ctx->opcode); - switch (op1) { - case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */ - case OPC_MSUB ... OPC_MSUBU: - check_insn(ctx, ISA_MIPS32); - gen_muldiv(ctx, op1, rd & 3, rs, rt); - break; - case OPC_MUL: - gen_arith(ctx, op1, rd, rs, rt); - break; - case OPC_CLO: - case OPC_CLZ: - check_insn(ctx, ISA_MIPS32); - gen_cl(ctx, op1, rd, rs); - break; - case OPC_SDBBP: - /* XXX: not clear which exception should be raised - * when in debug mode... - */ - check_insn(ctx, ISA_MIPS32); - if (!(ctx->hflags & MIPS_HFLAG_DM)) { - generate_exception(ctx, EXCP_DBp); - } else { - generate_exception(ctx, EXCP_DBp); - } - /* Treat as NOP. */ - break; - case OPC_DIV_G_2F: - case OPC_DIVU_G_2F: - case OPC_MULT_G_2F: - case OPC_MULTU_G_2F: - case OPC_MOD_G_2F: - case OPC_MODU_G_2F: - check_insn(ctx, INSN_LOONGSON2F); - gen_loongson_integer(ctx, op1, rd, rs, rt); - break; +#endif + default: + if (ctx->insn_flags & ISA_MIPS32R6) { + decode_opc_special_r6(env, ctx); + } else { + decode_opc_special_legacy(env, ctx); + } + } +} + +static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) +{ + int rs, rt, rd; + uint32_t op1; + + check_insn_opc_removed(ctx, ISA_MIPS32R6); + + rs = (ctx->opcode >> 21) & 0x1f; + rt = (ctx->opcode >> 16) & 0x1f; + rd = (ctx->opcode >> 11) & 0x1f; + + op1 = MASK_SPECIAL2(ctx->opcode); + switch (op1) { + case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */ + case OPC_MSUB ... OPC_MSUBU: + check_insn(ctx, ISA_MIPS32); + gen_muldiv(ctx, op1, rd & 3, rs, rt); + break; + case OPC_MUL: + gen_arith(ctx, op1, rd, rs, rt); + break; + case OPC_DIV_G_2F: + case OPC_DIVU_G_2F: + case OPC_MULT_G_2F: + case OPC_MULTU_G_2F: + case OPC_MOD_G_2F: + case OPC_MODU_G_2F: + check_insn(ctx, INSN_LOONGSON2F); + gen_loongson_integer(ctx, op1, rd, rs, rt); + break; + case OPC_CLO: + case OPC_CLZ: + check_insn(ctx, ISA_MIPS32); + gen_cl(ctx, op1, rd, rs); + break; + case OPC_SDBBP: + /* XXX: not clear which exception should be raised + * when in debug mode... + */ + check_insn(ctx, ISA_MIPS32); + if (!(ctx->hflags & MIPS_HFLAG_DM)) { + generate_exception(ctx, EXCP_DBp); + } else { + generate_exception(ctx, EXCP_DBp); + } + /* Treat as NOP. */ + break; #if defined(TARGET_MIPS64) - case OPC_DCLO: - case OPC_DCLZ: - check_insn(ctx, ISA_MIPS64); - check_mips_64(ctx); - gen_cl(ctx, op1, rd, rs); - break; - case OPC_DMULT_G_2F: - case OPC_DMULTU_G_2F: - case OPC_DDIV_G_2F: - case OPC_DDIVU_G_2F: - case OPC_DMOD_G_2F: - case OPC_DMODU_G_2F: - check_insn(ctx, INSN_LOONGSON2F); - gen_loongson_integer(ctx, op1, rd, rs, rt); - break; + case OPC_DCLO: + case OPC_DCLZ: + check_insn(ctx, ISA_MIPS64); + check_mips_64(ctx); + gen_cl(ctx, op1, rd, rs); + break; + case OPC_DMULT_G_2F: + case OPC_DMULTU_G_2F: + case OPC_DDIV_G_2F: + case OPC_DDIVU_G_2F: + case OPC_DMOD_G_2F: + case OPC_DMODU_G_2F: + check_insn(ctx, INSN_LOONGSON2F); + gen_loongson_integer(ctx, op1, rd, rs, rt); + break; #endif - default: /* Invalid */ - MIPS_INVAL("special2"); + default: /* Invalid */ + MIPS_INVAL("special2_legacy"); + generate_exception(ctx, EXCP_RI); + break; + } +} + +static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx) +{ + int rs, rt, rd, sa; + uint32_t op1, op2; + int16_t imm; + + rs = (ctx->opcode >> 21) & 0x1f; + rt = (ctx->opcode >> 16) & 0x1f; + rd = (ctx->opcode >> 11) & 0x1f; + sa = (ctx->opcode >> 6) & 0x1f; + imm = (int16_t)ctx->opcode >> 7; + + op1 = MASK_SPECIAL3(ctx->opcode); + switch (op1) { + case R6_OPC_PREF: + if (rt >= 24) { + /* hint codes 24-31 are reserved and signal RI */ generate_exception(ctx, EXCP_RI); - break; } + /* Treat as NOP. */ break; - case OPC_SPECIAL3: - op1 = MASK_SPECIAL3(ctx->opcode); - switch (op1) { - case OPC_EXT: - case OPC_INS: - check_insn(ctx, ISA_MIPS32R2); - gen_bitops(ctx, op1, rt, rs, sa, rd); - break; - case OPC_BSHFL: - check_insn(ctx, ISA_MIPS32R2); - op2 = MASK_BSHFL(ctx->opcode); - gen_bshfl(ctx, op2, rt, rd); - break; - case OPC_RDHWR: - gen_rdhwr(ctx, rt, rd); - break; - case OPC_FORK: - check_insn(ctx, ASE_MT); - { - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - - gen_load_gpr(t0, rt); - gen_load_gpr(t1, rs); - gen_helper_fork(t0, t1); - tcg_temp_free(t0); - tcg_temp_free(t1); + case R6_OPC_CACHE: + /* Treat as NOP. */ + break; + case R6_OPC_SC: + gen_st_cond(ctx, op1, rt, rs, imm); + break; + case R6_OPC_LL: + gen_ld(ctx, op1, rt, rs, imm); + break; + case OPC_BSHFL: + { + if (rd == 0) { + /* Treat as NOP. */ + break; } - break; - case OPC_YIELD: - check_insn(ctx, ASE_MT); - { - TCGv t0 = tcg_temp_new(); + TCGv t0 = tcg_temp_new(); + gen_load_gpr(t0, rt); - save_cpu_state(ctx, 1); - gen_load_gpr(t0, rs); - gen_helper_yield(t0, cpu_env, t0); - gen_store_gpr(t0, rd); - tcg_temp_free(t0); - } - break; - case OPC_DIV_G_2E ... OPC_DIVU_G_2E: - case OPC_MOD_G_2E ... OPC_MODU_G_2E: - case OPC_MULT_G_2E ... OPC_MULTU_G_2E: - /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have - * the same mask and op1. */ - if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) { - op2 = MASK_ADDUH_QB(ctx->opcode); - switch (op2) { - case OPC_ADDUH_QB: - case OPC_ADDUH_R_QB: - case OPC_ADDQH_PH: - case OPC_ADDQH_R_PH: - case OPC_ADDQH_W: - case OPC_ADDQH_R_W: - case OPC_SUBUH_QB: - case OPC_SUBUH_R_QB: - case OPC_SUBQH_PH: - case OPC_SUBQH_R_PH: - case OPC_SUBQH_W: - case OPC_SUBQH_R_W: - gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); - break; - case OPC_MUL_PH: - case OPC_MUL_S_PH: - case OPC_MULQ_S_W: - case OPC_MULQ_RS_W: - gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1); - break; - default: - MIPS_INVAL("MASK ADDUH.QB"); - generate_exception(ctx, EXCP_RI); - break; - } - } else if (ctx->insn_flags & INSN_LOONGSON2E) { - gen_loongson_integer(ctx, op1, rd, rs, rt); - } else { - generate_exception(ctx, EXCP_RI); - } - break; - case OPC_LX_DSP: - op2 = MASK_LX(ctx->opcode); + op2 = MASK_BSHFL(ctx->opcode); switch (op2) { + case OPC_ALIGN ... OPC_ALIGN_END: + sa &= 3; + if (sa == 0) { + tcg_gen_mov_tl(cpu_gpr[rd], t0); + } else { + TCGv t1 = tcg_temp_new(); + TCGv_i64 t2 = tcg_temp_new_i64(); + gen_load_gpr(t1, rs); + tcg_gen_concat_tl_i64(t2, t1, t0); + tcg_gen_shri_i64(t2, t2, 8 * (4 - sa)); #if defined(TARGET_MIPS64) - case OPC_LDX: + tcg_gen_ext32s_i64(cpu_gpr[rd], t2); +#else + tcg_gen_trunc_i64_i32(cpu_gpr[rd], t2); #endif - case OPC_LBUX: - case OPC_LHX: - case OPC_LWX: - gen_mipsdsp_ld(ctx, op2, rd, rs, rt); + tcg_temp_free_i64(t2); + tcg_temp_free(t1); + } break; - default: /* Invalid */ - MIPS_INVAL("MASK LX"); - generate_exception(ctx, EXCP_RI); + case OPC_BITSWAP: + gen_helper_bitswap(cpu_gpr[rd], t0); break; } - break; - case OPC_ABSQ_S_PH_DSP: - op2 = MASK_ABSQ_S_PH(ctx->opcode); - switch (op2) { - case OPC_ABSQ_S_QB: - case OPC_ABSQ_S_PH: - case OPC_ABSQ_S_W: - case OPC_PRECEQ_W_PHL: - case OPC_PRECEQ_W_PHR: - case OPC_PRECEQU_PH_QBL: - case OPC_PRECEQU_PH_QBR: - case OPC_PRECEQU_PH_QBLA: - case OPC_PRECEQU_PH_QBRA: - case OPC_PRECEU_PH_QBL: - case OPC_PRECEU_PH_QBR: - case OPC_PRECEU_PH_QBLA: - case OPC_PRECEU_PH_QBRA: - gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); - break; - case OPC_BITREV: - case OPC_REPL_QB: - case OPC_REPLV_QB: - case OPC_REPL_PH: - case OPC_REPLV_PH: - gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt); - break; - default: - MIPS_INVAL("MASK ABSQ_S.PH"); - generate_exception(ctx, EXCP_RI); + tcg_temp_free(t0); + } + break; +#if defined(TARGET_MIPS64) + case R6_OPC_SCD: + gen_st_cond(ctx, op1, rt, rs, imm); + break; + case R6_OPC_LLD: + gen_ld(ctx, op1, rt, rs, imm); + break; + case OPC_DBSHFL: + check_mips_64(ctx); + { + if (rd == 0) { + /* Treat as NOP. */ break; } - break; - case OPC_ADDU_QB_DSP: - op2 = MASK_ADDU_QB(ctx->opcode); + TCGv t0 = tcg_temp_new(); + gen_load_gpr(t0, rt); + + op2 = MASK_DBSHFL(ctx->opcode); switch (op2) { - case OPC_ADDQ_PH: - case OPC_ADDQ_S_PH: - case OPC_ADDQ_S_W: - case OPC_ADDU_QB: - case OPC_ADDU_S_QB: - case OPC_ADDU_PH: - case OPC_ADDU_S_PH: - case OPC_SUBQ_PH: - case OPC_SUBQ_S_PH: - case OPC_SUBQ_S_W: - case OPC_SUBU_QB: - case OPC_SUBU_S_QB: - case OPC_SUBU_PH: - case OPC_SUBU_S_PH: - case OPC_ADDSC: - case OPC_ADDWC: - case OPC_MODSUB: - case OPC_RADDU_W_QB: - gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); - break; - case OPC_MULEU_S_PH_QBL: - case OPC_MULEU_S_PH_QBR: - case OPC_MULQ_RS_PH: - case OPC_MULEQ_S_W_PHL: - case OPC_MULEQ_S_W_PHR: - case OPC_MULQ_S_PH: - gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1); + case OPC_DALIGN ... OPC_DALIGN_END: + sa &= 7; + if (sa == 0) { + tcg_gen_mov_tl(cpu_gpr[rd], t0); + } else { + TCGv t1 = tcg_temp_new(); + gen_load_gpr(t1, rs); + tcg_gen_shli_tl(t0, t0, 8 * sa); + tcg_gen_shri_tl(t1, t1, 8 * (8 - sa)); + tcg_gen_or_tl(cpu_gpr[rd], t1, t0); + tcg_temp_free(t1); + } break; - default: /* Invalid */ - MIPS_INVAL("MASK ADDU.QB"); - generate_exception(ctx, EXCP_RI); + case OPC_DBITSWAP: + gen_helper_dbitswap(cpu_gpr[rd], t0); break; - } - break; - case OPC_CMPU_EQ_QB_DSP: - op2 = MASK_CMPU_EQ_QB(ctx->opcode); + tcg_temp_free(t0); + } + break; +#endif + default: /* Invalid */ + MIPS_INVAL("special3_r6"); + generate_exception(ctx, EXCP_RI); + break; + } +} + +static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) +{ + int rs, rt, rd; + uint32_t op1, op2; + + rs = (ctx->opcode >> 21) & 0x1f; + rt = (ctx->opcode >> 16) & 0x1f; + rd = (ctx->opcode >> 11) & 0x1f; + + op1 = MASK_SPECIAL3(ctx->opcode); + switch (op1) { + case OPC_DIV_G_2E ... OPC_DIVU_G_2E: + case OPC_MOD_G_2E ... OPC_MODU_G_2E: + case OPC_MULT_G_2E ... OPC_MULTU_G_2E: + /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have + * the same mask and op1. */ + if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) { + op2 = MASK_ADDUH_QB(ctx->opcode); switch (op2) { - case OPC_PRECR_SRA_PH_W: - case OPC_PRECR_SRA_R_PH_W: - gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd); - break; - case OPC_PRECR_QB_PH: - case OPC_PRECRQ_QB_PH: - case OPC_PRECRQ_PH_W: - case OPC_PRECRQ_RS_PH_W: - case OPC_PRECRQU_S_QB_PH: + case OPC_ADDUH_QB: + case OPC_ADDUH_R_QB: + case OPC_ADDQH_PH: + case OPC_ADDQH_R_PH: + case OPC_ADDQH_W: + case OPC_ADDQH_R_W: + case OPC_SUBUH_QB: + case OPC_SUBUH_R_QB: + case OPC_SUBQH_PH: + case OPC_SUBQH_R_PH: + case OPC_SUBQH_W: + case OPC_SUBQH_R_W: gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); break; - case OPC_CMPU_EQ_QB: - case OPC_CMPU_LT_QB: - case OPC_CMPU_LE_QB: - case OPC_CMP_EQ_PH: - case OPC_CMP_LT_PH: - case OPC_CMP_LE_PH: - gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0); - break; - case OPC_CMPGU_EQ_QB: - case OPC_CMPGU_LT_QB: - case OPC_CMPGU_LE_QB: - case OPC_CMPGDU_EQ_QB: - case OPC_CMPGDU_LT_QB: - case OPC_CMPGDU_LE_QB: - case OPC_PICK_QB: - case OPC_PICK_PH: - case OPC_PACKRL_PH: - gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1); + case OPC_MUL_PH: + case OPC_MUL_S_PH: + case OPC_MULQ_S_W: + case OPC_MULQ_RS_W: + gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1); break; - default: /* Invalid */ - MIPS_INVAL("MASK CMPU.EQ.QB"); + default: + MIPS_INVAL("MASK ADDUH.QB"); generate_exception(ctx, EXCP_RI); break; } + } else if (ctx->insn_flags & INSN_LOONGSON2E) { + gen_loongson_integer(ctx, op1, rd, rs, rt); + } else { + generate_exception(ctx, EXCP_RI); + } + break; + case OPC_LX_DSP: + op2 = MASK_LX(ctx->opcode); + switch (op2) { +#if defined(TARGET_MIPS64) + case OPC_LDX: +#endif + case OPC_LBUX: + case OPC_LHX: + case OPC_LWX: + gen_mipsdsp_ld(ctx, op2, rd, rs, rt); break; - case OPC_SHLL_QB_DSP: - gen_mipsdsp_shift(ctx, op1, rd, rs, rt); + default: /* Invalid */ + MIPS_INVAL("MASK LX"); + generate_exception(ctx, EXCP_RI); break; - case OPC_DPA_W_PH_DSP: - op2 = MASK_DPA_W_PH(ctx->opcode); - switch (op2) { - case OPC_DPAU_H_QBL: - case OPC_DPAU_H_QBR: - case OPC_DPSU_H_QBL: - case OPC_DPSU_H_QBR: - case OPC_DPA_W_PH: - case OPC_DPAX_W_PH: - case OPC_DPAQ_S_W_PH: - case OPC_DPAQX_S_W_PH: - case OPC_DPAQX_SA_W_PH: - case OPC_DPS_W_PH: - case OPC_DPSX_W_PH: - case OPC_DPSQ_S_W_PH: - case OPC_DPSQX_S_W_PH: - case OPC_DPSQX_SA_W_PH: - case OPC_MULSAQ_S_W_PH: - case OPC_DPAQ_SA_L_W: - case OPC_DPSQ_SA_L_W: - case OPC_MAQ_S_W_PHL: - case OPC_MAQ_S_W_PHR: - case OPC_MAQ_SA_W_PHL: - case OPC_MAQ_SA_W_PHR: - case OPC_MULSA_W_PH: - gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0); - break; - default: /* Invalid */ - MIPS_INVAL("MASK DPAW.PH"); - generate_exception(ctx, EXCP_RI); - break; - } + } + break; + case OPC_ABSQ_S_PH_DSP: + op2 = MASK_ABSQ_S_PH(ctx->opcode); + switch (op2) { + case OPC_ABSQ_S_QB: + case OPC_ABSQ_S_PH: + case OPC_ABSQ_S_W: + case OPC_PRECEQ_W_PHL: + case OPC_PRECEQ_W_PHR: + case OPC_PRECEQU_PH_QBL: + case OPC_PRECEQU_PH_QBR: + case OPC_PRECEQU_PH_QBLA: + case OPC_PRECEQU_PH_QBRA: + case OPC_PRECEU_PH_QBL: + case OPC_PRECEU_PH_QBR: + case OPC_PRECEU_PH_QBLA: + case OPC_PRECEU_PH_QBRA: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); + break; + case OPC_BITREV: + case OPC_REPL_QB: + case OPC_REPLV_QB: + case OPC_REPL_PH: + case OPC_REPLV_PH: + gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt); + break; + default: + MIPS_INVAL("MASK ABSQ_S.PH"); + generate_exception(ctx, EXCP_RI); + break; + } + break; + case OPC_ADDU_QB_DSP: + op2 = MASK_ADDU_QB(ctx->opcode); + switch (op2) { + case OPC_ADDQ_PH: + case OPC_ADDQ_S_PH: + case OPC_ADDQ_S_W: + case OPC_ADDU_QB: + case OPC_ADDU_S_QB: + case OPC_ADDU_PH: + case OPC_ADDU_S_PH: + case OPC_SUBQ_PH: + case OPC_SUBQ_S_PH: + case OPC_SUBQ_S_W: + case OPC_SUBU_QB: + case OPC_SUBU_S_QB: + case OPC_SUBU_PH: + case OPC_SUBU_S_PH: + case OPC_ADDSC: + case OPC_ADDWC: + case OPC_MODSUB: + case OPC_RADDU_W_QB: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); + break; + case OPC_MULEU_S_PH_QBL: + case OPC_MULEU_S_PH_QBR: + case OPC_MULQ_RS_PH: + case OPC_MULEQ_S_W_PHL: + case OPC_MULEQ_S_W_PHR: + case OPC_MULQ_S_PH: + gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1); + break; + default: /* Invalid */ + MIPS_INVAL("MASK ADDU.QB"); + generate_exception(ctx, EXCP_RI); break; - case OPC_INSV_DSP: - op2 = MASK_INSV(ctx->opcode); - switch (op2) { - case OPC_INSV: - check_dsp(ctx); - { - TCGv t0, t1; - if (rt == 0) { - MIPS_DEBUG("NOP"); - break; - } + } + break; + case OPC_CMPU_EQ_QB_DSP: + op2 = MASK_CMPU_EQ_QB(ctx->opcode); + switch (op2) { + case OPC_PRECR_SRA_PH_W: + case OPC_PRECR_SRA_R_PH_W: + gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd); + break; + case OPC_PRECR_QB_PH: + case OPC_PRECRQ_QB_PH: + case OPC_PRECRQ_PH_W: + case OPC_PRECRQ_RS_PH_W: + case OPC_PRECRQU_S_QB_PH: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); + break; + case OPC_CMPU_EQ_QB: + case OPC_CMPU_LT_QB: + case OPC_CMPU_LE_QB: + case OPC_CMP_EQ_PH: + case OPC_CMP_LT_PH: + case OPC_CMP_LE_PH: + gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0); + break; + case OPC_CMPGU_EQ_QB: + case OPC_CMPGU_LT_QB: + case OPC_CMPGU_LE_QB: + case OPC_CMPGDU_EQ_QB: + case OPC_CMPGDU_LT_QB: + case OPC_CMPGDU_LE_QB: + case OPC_PICK_QB: + case OPC_PICK_PH: + case OPC_PACKRL_PH: + gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1); + break; + default: /* Invalid */ + MIPS_INVAL("MASK CMPU.EQ.QB"); + generate_exception(ctx, EXCP_RI); + break; + } + break; + case OPC_SHLL_QB_DSP: + gen_mipsdsp_shift(ctx, op1, rd, rs, rt); + break; + case OPC_DPA_W_PH_DSP: + op2 = MASK_DPA_W_PH(ctx->opcode); + switch (op2) { + case OPC_DPAU_H_QBL: + case OPC_DPAU_H_QBR: + case OPC_DPSU_H_QBL: + case OPC_DPSU_H_QBR: + case OPC_DPA_W_PH: + case OPC_DPAX_W_PH: + case OPC_DPAQ_S_W_PH: + case OPC_DPAQX_S_W_PH: + case OPC_DPAQX_SA_W_PH: + case OPC_DPS_W_PH: + case OPC_DPSX_W_PH: + case OPC_DPSQ_S_W_PH: + case OPC_DPSQX_S_W_PH: + case OPC_DPSQX_SA_W_PH: + case OPC_MULSAQ_S_W_PH: + case OPC_DPAQ_SA_L_W: + case OPC_DPSQ_SA_L_W: + case OPC_MAQ_S_W_PHL: + case OPC_MAQ_S_W_PHR: + case OPC_MAQ_SA_W_PHL: + case OPC_MAQ_SA_W_PHR: + case OPC_MULSA_W_PH: + gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0); + break; + default: /* Invalid */ + MIPS_INVAL("MASK DPAW.PH"); + generate_exception(ctx, EXCP_RI); + break; + } + break; + case OPC_INSV_DSP: + op2 = MASK_INSV(ctx->opcode); + switch (op2) { + case OPC_INSV: + check_dsp(ctx); + { + TCGv t0, t1; - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); + if (rt == 0) { + MIPS_DEBUG("NOP"); + break; + } - gen_load_gpr(t0, rt); - gen_load_gpr(t1, rs); + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); - gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0); + gen_load_gpr(t0, rt); + gen_load_gpr(t1, rs); - tcg_temp_free(t0); - tcg_temp_free(t1); - break; - } - default: /* Invalid */ - MIPS_INVAL("MASK INSV"); - generate_exception(ctx, EXCP_RI); + gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0); + + tcg_temp_free(t0); + tcg_temp_free(t1); break; } + default: /* Invalid */ + MIPS_INVAL("MASK INSV"); + generate_exception(ctx, EXCP_RI); break; - case OPC_APPEND_DSP: - gen_mipsdsp_append(env, ctx, op1, rt, rs, rd); + } + break; + case OPC_APPEND_DSP: + gen_mipsdsp_append(env, ctx, op1, rt, rs, rd); + break; + case OPC_EXTR_W_DSP: + op2 = MASK_EXTR_W(ctx->opcode); + switch (op2) { + case OPC_EXTR_W: + case OPC_EXTR_R_W: + case OPC_EXTR_RS_W: + case OPC_EXTR_S_H: + case OPC_EXTRV_S_H: + case OPC_EXTRV_W: + case OPC_EXTRV_R_W: + case OPC_EXTRV_RS_W: + case OPC_EXTP: + case OPC_EXTPV: + case OPC_EXTPDP: + case OPC_EXTPDPV: + gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1); break; - case OPC_EXTR_W_DSP: - op2 = MASK_EXTR_W(ctx->opcode); - switch (op2) { - case OPC_EXTR_W: - case OPC_EXTR_R_W: - case OPC_EXTR_RS_W: - case OPC_EXTR_S_H: - case OPC_EXTRV_S_H: - case OPC_EXTRV_W: - case OPC_EXTRV_R_W: - case OPC_EXTRV_RS_W: - case OPC_EXTP: - case OPC_EXTPV: - case OPC_EXTPDP: - case OPC_EXTPDPV: - gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1); - break; - case OPC_RDDSP: - gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1); - break; - case OPC_SHILO: - case OPC_SHILOV: - case OPC_MTHLIP: - case OPC_WRDSP: - gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0); - break; - default: /* Invalid */ - MIPS_INVAL("MASK EXTR.W"); - generate_exception(ctx, EXCP_RI); - break; - } + case OPC_RDDSP: + gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1); break; + case OPC_SHILO: + case OPC_SHILOV: + case OPC_MTHLIP: + case OPC_WRDSP: + gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0); + break; + default: /* Invalid */ + MIPS_INVAL("MASK EXTR.W"); + generate_exception(ctx, EXCP_RI); + break; + } + break; #if defined(TARGET_MIPS64) - case OPC_DEXTM ... OPC_DEXT: - case OPC_DINSM ... OPC_DINS: - check_insn(ctx, ISA_MIPS64R2); - check_mips_64(ctx); - gen_bitops(ctx, op1, rt, rs, sa, rd); + case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E: + case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E: + case OPC_DMOD_G_2E ... OPC_DMODU_G_2E: + check_insn(ctx, INSN_LOONGSON2E); + gen_loongson_integer(ctx, op1, rd, rs, rt); + break; + case OPC_ABSQ_S_QH_DSP: + op2 = MASK_ABSQ_S_QH(ctx->opcode); + switch (op2) { + case OPC_PRECEQ_L_PWL: + case OPC_PRECEQ_L_PWR: + case OPC_PRECEQ_PW_QHL: + case OPC_PRECEQ_PW_QHR: + case OPC_PRECEQ_PW_QHLA: + case OPC_PRECEQ_PW_QHRA: + case OPC_PRECEQU_QH_OBL: + case OPC_PRECEQU_QH_OBR: + case OPC_PRECEQU_QH_OBLA: + case OPC_PRECEQU_QH_OBRA: + case OPC_PRECEU_QH_OBL: + case OPC_PRECEU_QH_OBR: + case OPC_PRECEU_QH_OBLA: + case OPC_PRECEU_QH_OBRA: + case OPC_ABSQ_S_OB: + case OPC_ABSQ_S_PW: + case OPC_ABSQ_S_QH: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); break; - case OPC_DBSHFL: - check_insn(ctx, ISA_MIPS64R2); - check_mips_64(ctx); - op2 = MASK_DBSHFL(ctx->opcode); - gen_bshfl(ctx, op2, rt, rd); + case OPC_REPL_OB: + case OPC_REPL_PW: + case OPC_REPL_QH: + case OPC_REPLV_OB: + case OPC_REPLV_PW: + case OPC_REPLV_QH: + gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt); break; - case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E: - case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E: - case OPC_DMOD_G_2E ... OPC_DMODU_G_2E: - check_insn(ctx, INSN_LOONGSON2E); - gen_loongson_integer(ctx, op1, rd, rs, rt); + default: /* Invalid */ + MIPS_INVAL("MASK ABSQ_S.QH"); + generate_exception(ctx, EXCP_RI); break; - case OPC_ABSQ_S_QH_DSP: - op2 = MASK_ABSQ_S_QH(ctx->opcode); - switch (op2) { - case OPC_PRECEQ_L_PWL: - case OPC_PRECEQ_L_PWR: - case OPC_PRECEQ_PW_QHL: - case OPC_PRECEQ_PW_QHR: - case OPC_PRECEQ_PW_QHLA: - case OPC_PRECEQ_PW_QHRA: - case OPC_PRECEQU_QH_OBL: - case OPC_PRECEQU_QH_OBR: - case OPC_PRECEQU_QH_OBLA: - case OPC_PRECEQU_QH_OBRA: - case OPC_PRECEU_QH_OBL: - case OPC_PRECEU_QH_OBR: - case OPC_PRECEU_QH_OBLA: - case OPC_PRECEU_QH_OBRA: - case OPC_ABSQ_S_OB: - case OPC_ABSQ_S_PW: - case OPC_ABSQ_S_QH: - gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); - break; - case OPC_REPL_OB: - case OPC_REPL_PW: - case OPC_REPL_QH: - case OPC_REPLV_OB: - case OPC_REPLV_PW: - case OPC_REPLV_QH: - gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt); - break; - default: /* Invalid */ - MIPS_INVAL("MASK ABSQ_S.QH"); - generate_exception(ctx, EXCP_RI); - break; - } + } + break; + case OPC_ADDU_OB_DSP: + op2 = MASK_ADDU_OB(ctx->opcode); + switch (op2) { + case OPC_RADDU_L_OB: + case OPC_SUBQ_PW: + case OPC_SUBQ_S_PW: + case OPC_SUBQ_QH: + case OPC_SUBQ_S_QH: + case OPC_SUBU_OB: + case OPC_SUBU_S_OB: + case OPC_SUBU_QH: + case OPC_SUBU_S_QH: + case OPC_SUBUH_OB: + case OPC_SUBUH_R_OB: + case OPC_ADDQ_PW: + case OPC_ADDQ_S_PW: + case OPC_ADDQ_QH: + case OPC_ADDQ_S_QH: + case OPC_ADDU_OB: + case OPC_ADDU_S_OB: + case OPC_ADDU_QH: + case OPC_ADDU_S_QH: + case OPC_ADDUH_OB: + case OPC_ADDUH_R_OB: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); break; - case OPC_ADDU_OB_DSP: - op2 = MASK_ADDU_OB(ctx->opcode); - switch (op2) { - case OPC_RADDU_L_OB: - case OPC_SUBQ_PW: - case OPC_SUBQ_S_PW: - case OPC_SUBQ_QH: - case OPC_SUBQ_S_QH: - case OPC_SUBU_OB: - case OPC_SUBU_S_OB: - case OPC_SUBU_QH: - case OPC_SUBU_S_QH: - case OPC_SUBUH_OB: - case OPC_SUBUH_R_OB: - case OPC_ADDQ_PW: - case OPC_ADDQ_S_PW: - case OPC_ADDQ_QH: - case OPC_ADDQ_S_QH: - case OPC_ADDU_OB: - case OPC_ADDU_S_OB: - case OPC_ADDU_QH: - case OPC_ADDU_S_QH: - case OPC_ADDUH_OB: - case OPC_ADDUH_R_OB: - gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); - break; - case OPC_MULEQ_S_PW_QHL: - case OPC_MULEQ_S_PW_QHR: - case OPC_MULEU_S_QH_OBL: - case OPC_MULEU_S_QH_OBR: - case OPC_MULQ_RS_QH: - gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1); - break; - default: /* Invalid */ - MIPS_INVAL("MASK ADDU.OB"); - generate_exception(ctx, EXCP_RI); - break; - } + case OPC_MULEQ_S_PW_QHL: + case OPC_MULEQ_S_PW_QHR: + case OPC_MULEU_S_QH_OBL: + case OPC_MULEU_S_QH_OBR: + case OPC_MULQ_RS_QH: + gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1); break; - case OPC_CMPU_EQ_OB_DSP: - op2 = MASK_CMPU_EQ_OB(ctx->opcode); - switch (op2) { - case OPC_PRECR_SRA_QH_PW: - case OPC_PRECR_SRA_R_QH_PW: - /* Return value is rt. */ - gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd); - break; - case OPC_PRECR_OB_QH: - case OPC_PRECRQ_OB_QH: - case OPC_PRECRQ_PW_L: - case OPC_PRECRQ_QH_PW: - case OPC_PRECRQ_RS_QH_PW: - case OPC_PRECRQU_S_OB_QH: - gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); - break; - case OPC_CMPU_EQ_OB: - case OPC_CMPU_LT_OB: - case OPC_CMPU_LE_OB: - case OPC_CMP_EQ_QH: - case OPC_CMP_LT_QH: - case OPC_CMP_LE_QH: - case OPC_CMP_EQ_PW: - case OPC_CMP_LT_PW: - case OPC_CMP_LE_PW: - gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0); - break; - case OPC_CMPGDU_EQ_OB: - case OPC_CMPGDU_LT_OB: - case OPC_CMPGDU_LE_OB: - case OPC_CMPGU_EQ_OB: - case OPC_CMPGU_LT_OB: - case OPC_CMPGU_LE_OB: - case OPC_PACKRL_PW: - case OPC_PICK_OB: - case OPC_PICK_PW: - case OPC_PICK_QH: - gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1); - break; - default: /* Invalid */ - MIPS_INVAL("MASK CMPU_EQ.OB"); - generate_exception(ctx, EXCP_RI); - break; - } + default: /* Invalid */ + MIPS_INVAL("MASK ADDU.OB"); + generate_exception(ctx, EXCP_RI); break; - case OPC_DAPPEND_DSP: - gen_mipsdsp_append(env, ctx, op1, rt, rs, rd); + } + break; + case OPC_CMPU_EQ_OB_DSP: + op2 = MASK_CMPU_EQ_OB(ctx->opcode); + switch (op2) { + case OPC_PRECR_SRA_QH_PW: + case OPC_PRECR_SRA_R_QH_PW: + /* Return value is rt. */ + gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd); break; - case OPC_DEXTR_W_DSP: - op2 = MASK_DEXTR_W(ctx->opcode); - switch (op2) { - case OPC_DEXTP: - case OPC_DEXTPDP: - case OPC_DEXTPDPV: - case OPC_DEXTPV: - case OPC_DEXTR_L: - case OPC_DEXTR_R_L: - case OPC_DEXTR_RS_L: - case OPC_DEXTR_W: - case OPC_DEXTR_R_W: - case OPC_DEXTR_RS_W: - case OPC_DEXTR_S_H: - case OPC_DEXTRV_L: - case OPC_DEXTRV_R_L: - case OPC_DEXTRV_RS_L: - case OPC_DEXTRV_S_H: - case OPC_DEXTRV_W: - case OPC_DEXTRV_R_W: - case OPC_DEXTRV_RS_W: - gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1); - break; - case OPC_DMTHLIP: - case OPC_DSHILO: - case OPC_DSHILOV: - gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0); - break; - default: /* Invalid */ - MIPS_INVAL("MASK EXTR.W"); - generate_exception(ctx, EXCP_RI); - break; - } + case OPC_PRECR_OB_QH: + case OPC_PRECRQ_OB_QH: + case OPC_PRECRQ_PW_L: + case OPC_PRECRQ_QH_PW: + case OPC_PRECRQ_RS_QH_PW: + case OPC_PRECRQU_S_OB_QH: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); break; - case OPC_DPAQ_W_QH_DSP: - op2 = MASK_DPAQ_W_QH(ctx->opcode); - switch (op2) { - case OPC_DPAU_H_OBL: - case OPC_DPAU_H_OBR: - case OPC_DPSU_H_OBL: - case OPC_DPSU_H_OBR: - case OPC_DPA_W_QH: - case OPC_DPAQ_S_W_QH: - case OPC_DPS_W_QH: - case OPC_DPSQ_S_W_QH: - case OPC_MULSAQ_S_W_QH: - case OPC_DPAQ_SA_L_PW: - case OPC_DPSQ_SA_L_PW: - case OPC_MULSAQ_S_L_PW: - gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0); - break; - case OPC_MAQ_S_W_QHLL: - case OPC_MAQ_S_W_QHLR: - case OPC_MAQ_S_W_QHRL: - case OPC_MAQ_S_W_QHRR: - case OPC_MAQ_SA_W_QHLL: - case OPC_MAQ_SA_W_QHLR: - case OPC_MAQ_SA_W_QHRL: - case OPC_MAQ_SA_W_QHRR: - case OPC_MAQ_S_L_PWL: - case OPC_MAQ_S_L_PWR: - case OPC_DMADD: - case OPC_DMADDU: - case OPC_DMSUB: - case OPC_DMSUBU: - gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0); - break; - default: /* Invalid */ - MIPS_INVAL("MASK DPAQ.W.QH"); - generate_exception(ctx, EXCP_RI); - break; - } + case OPC_CMPU_EQ_OB: + case OPC_CMPU_LT_OB: + case OPC_CMPU_LE_OB: + case OPC_CMP_EQ_QH: + case OPC_CMP_LT_QH: + case OPC_CMP_LE_QH: + case OPC_CMP_EQ_PW: + case OPC_CMP_LT_PW: + case OPC_CMP_LE_PW: + gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0); break; - case OPC_DINSV_DSP: - op2 = MASK_INSV(ctx->opcode); - switch (op2) { - case OPC_DINSV: - { - TCGv t0, t1; + case OPC_CMPGDU_EQ_OB: + case OPC_CMPGDU_LT_OB: + case OPC_CMPGDU_LE_OB: + case OPC_CMPGU_EQ_OB: + case OPC_CMPGU_LT_OB: + case OPC_CMPGU_LE_OB: + case OPC_PACKRL_PW: + case OPC_PICK_OB: + case OPC_PICK_PW: + case OPC_PICK_QH: + gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1); + break; + default: /* Invalid */ + MIPS_INVAL("MASK CMPU_EQ.OB"); + generate_exception(ctx, EXCP_RI); + break; + } + break; + case OPC_DAPPEND_DSP: + gen_mipsdsp_append(env, ctx, op1, rt, rs, rd); + break; + case OPC_DEXTR_W_DSP: + op2 = MASK_DEXTR_W(ctx->opcode); + switch (op2) { + case OPC_DEXTP: + case OPC_DEXTPDP: + case OPC_DEXTPDPV: + case OPC_DEXTPV: + case OPC_DEXTR_L: + case OPC_DEXTR_R_L: + case OPC_DEXTR_RS_L: + case OPC_DEXTR_W: + case OPC_DEXTR_R_W: + case OPC_DEXTR_RS_W: + case OPC_DEXTR_S_H: + case OPC_DEXTRV_L: + case OPC_DEXTRV_R_L: + case OPC_DEXTRV_RS_L: + case OPC_DEXTRV_S_H: + case OPC_DEXTRV_W: + case OPC_DEXTRV_R_W: + case OPC_DEXTRV_RS_W: + gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1); + break; + case OPC_DMTHLIP: + case OPC_DSHILO: + case OPC_DSHILOV: + gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0); + break; + default: /* Invalid */ + MIPS_INVAL("MASK EXTR.W"); + generate_exception(ctx, EXCP_RI); + break; + } + break; + case OPC_DPAQ_W_QH_DSP: + op2 = MASK_DPAQ_W_QH(ctx->opcode); + switch (op2) { + case OPC_DPAU_H_OBL: + case OPC_DPAU_H_OBR: + case OPC_DPSU_H_OBL: + case OPC_DPSU_H_OBR: + case OPC_DPA_W_QH: + case OPC_DPAQ_S_W_QH: + case OPC_DPS_W_QH: + case OPC_DPSQ_S_W_QH: + case OPC_MULSAQ_S_W_QH: + case OPC_DPAQ_SA_L_PW: + case OPC_DPSQ_SA_L_PW: + case OPC_MULSAQ_S_L_PW: + gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0); + break; + case OPC_MAQ_S_W_QHLL: + case OPC_MAQ_S_W_QHLR: + case OPC_MAQ_S_W_QHRL: + case OPC_MAQ_S_W_QHRR: + case OPC_MAQ_SA_W_QHLL: + case OPC_MAQ_SA_W_QHLR: + case OPC_MAQ_SA_W_QHRL: + case OPC_MAQ_SA_W_QHRR: + case OPC_MAQ_S_L_PWL: + case OPC_MAQ_S_L_PWR: + case OPC_DMADD: + case OPC_DMADDU: + case OPC_DMSUB: + case OPC_DMSUBU: + gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0); + break; + default: /* Invalid */ + MIPS_INVAL("MASK DPAQ.W.QH"); + generate_exception(ctx, EXCP_RI); + break; + } + break; + case OPC_DINSV_DSP: + op2 = MASK_INSV(ctx->opcode); + switch (op2) { + case OPC_DINSV: + { + TCGv t0, t1; - if (rt == 0) { - MIPS_DEBUG("NOP"); - break; - } - check_dsp(ctx); + if (rt == 0) { + MIPS_DEBUG("NOP"); + break; + } + check_dsp(ctx); - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); - gen_load_gpr(t0, rt); - gen_load_gpr(t1, rs); + gen_load_gpr(t0, rt); + gen_load_gpr(t1, rs); - gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0); + gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0); - tcg_temp_free(t0); - tcg_temp_free(t1); - break; - } - default: /* Invalid */ - MIPS_INVAL("MASK DINSV"); - generate_exception(ctx, EXCP_RI); - break; - } - break; - case OPC_SHLL_OB_DSP: - gen_mipsdsp_shift(ctx, op1, rd, rs, rt); + tcg_temp_free(t0); + tcg_temp_free(t1); break; -#endif + } default: /* Invalid */ - MIPS_INVAL("special3"); + MIPS_INVAL("MASK DINSV"); generate_exception(ctx, EXCP_RI); break; } break; + case OPC_SHLL_OB_DSP: + gen_mipsdsp_shift(ctx, op1, rd, rs, rt); + break; +#endif + default: /* Invalid */ + MIPS_INVAL("special3_legacy"); + generate_exception(ctx, EXCP_RI); + break; + } +} + +static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx) +{ + int rs, rt, rd, sa; + uint32_t op1, op2; + + rs = (ctx->opcode >> 21) & 0x1f; + rt = (ctx->opcode >> 16) & 0x1f; + rd = (ctx->opcode >> 11) & 0x1f; + sa = (ctx->opcode >> 6) & 0x1f; + + op1 = MASK_SPECIAL3(ctx->opcode); + switch (op1) { + case OPC_EXT: + case OPC_INS: + check_insn(ctx, ISA_MIPS32R2); + gen_bitops(ctx, op1, rt, rs, sa, rd); + break; + case OPC_BSHFL: + op2 = MASK_BSHFL(ctx->opcode); + switch (op2) { + case OPC_ALIGN ... OPC_ALIGN_END: + case OPC_BITSWAP: + check_insn(ctx, ISA_MIPS32R6); + decode_opc_special3_r6(env, ctx); + break; + default: + check_insn(ctx, ISA_MIPS32R2); + gen_bshfl(ctx, op2, rt, rd); + break; + } + break; +#if defined(TARGET_MIPS64) + case OPC_DEXTM ... OPC_DEXT: + case OPC_DINSM ... OPC_DINS: + check_insn(ctx, ISA_MIPS64R2); + check_mips_64(ctx); + gen_bitops(ctx, op1, rt, rs, sa, rd); + break; + case OPC_DBSHFL: + op2 = MASK_DBSHFL(ctx->opcode); + switch (op2) { + case OPC_DALIGN ... OPC_DALIGN_END: + case OPC_DBITSWAP: + check_insn(ctx, ISA_MIPS32R6); + decode_opc_special3_r6(env, ctx); + break; + default: + check_insn(ctx, ISA_MIPS64R2); + check_mips_64(ctx); + op2 = MASK_DBSHFL(ctx->opcode); + gen_bshfl(ctx, op2, rt, rd); + break; + } + break; +#endif + case OPC_RDHWR: + gen_rdhwr(ctx, rt, rd); + break; + case OPC_FORK: + check_insn(ctx, ASE_MT); + { + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + gen_load_gpr(t0, rt); + gen_load_gpr(t1, rs); + gen_helper_fork(t0, t1); + tcg_temp_free(t0); + tcg_temp_free(t1); + } + break; + case OPC_YIELD: + check_insn(ctx, ASE_MT); + { + TCGv t0 = tcg_temp_new(); + + save_cpu_state(ctx, 1); + gen_load_gpr(t0, rs); + gen_helper_yield(t0, cpu_env, t0); + gen_store_gpr(t0, rd); + tcg_temp_free(t0); + } + break; + default: + if (ctx->insn_flags & ISA_MIPS32R6) { + decode_opc_special3_r6(env, ctx); + } else { + decode_opc_special3_legacy(env, ctx); + } + } +} + +static void decode_opc (CPUMIPSState *env, DisasContext *ctx) +{ + int32_t offset; + int rs, rt, rd, sa; + uint32_t op, op1; + int16_t imm; + + /* make sure instructions are on a word boundary */ + if (ctx->pc & 0x3) { + env->CP0_BadVAddr = ctx->pc; + generate_exception(ctx, EXCP_AdEL); + return; + } + + /* Handle blikely not taken case */ + if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) { + int l1 = gen_new_label(); + + MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4); + tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1); + tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK); + gen_goto_tb(ctx, 1, ctx->pc + 4); + gen_set_label(l1); + } + + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { + tcg_gen_debug_insn_start(ctx->pc); + } + + op = MASK_OP_MAJOR(ctx->opcode); + rs = (ctx->opcode >> 21) & 0x1f; + rt = (ctx->opcode >> 16) & 0x1f; + rd = (ctx->opcode >> 11) & 0x1f; + sa = (ctx->opcode >> 6) & 0x1f; + imm = (int16_t)ctx->opcode; + switch (op) { + case OPC_SPECIAL: + decode_opc_special(env, ctx); + break; + case OPC_SPECIAL2: + decode_opc_special2_legacy(env, ctx); + break; + case OPC_SPECIAL3: + decode_opc_special3(env, ctx); + break; case OPC_REGIMM: op1 = MASK_REGIMM(ctx->opcode); switch (op1) { - case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */ - case OPC_BLTZAL ... OPC_BGEZALL: - gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2); + case OPC_BLTZL: /* REGIMM branches */ + case OPC_BGEZL: + case OPC_BLTZALL: + case OPC_BGEZALL: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + case OPC_BLTZ: + case OPC_BGEZ: + gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4); + break; + case OPC_BLTZAL: + case OPC_BGEZAL: + if (ctx->insn_flags & ISA_MIPS32R6) { + if (rs == 0) { + /* OPC_NAL, OPC_BAL */ + gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4); + } else { + generate_exception(ctx, EXCP_RI); + } + } else { + gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4); + } break; case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */ case OPC_TNEI: + check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_trap(ctx, op1, rs, -1, imm); break; case OPC_SYNCI: check_insn(ctx, ISA_MIPS32R2); - /* Treat as NOP. */ + /* Break the TB to be able to sync copied instructions + immediately */ + ctx->bstate = BS_STOP; break; case OPC_BPOSGE32: /* MIPS DSP branch */ #if defined(TARGET_MIPS64) case OPC_BPOSGE64: #endif check_dsp(ctx); - gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2); + gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4); + break; +#if defined(TARGET_MIPS64) + case OPC_DAHI: + check_insn(ctx, ISA_MIPS32R6); + check_mips_64(ctx); + if (rs != 0) { + tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32); + } + MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm); break; + case OPC_DATI: + check_insn(ctx, ISA_MIPS32R6); + check_mips_64(ctx); + if (rs != 0) { + tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48); + } + MIPS_DEBUG("dati %s, %04x", regnames[rs], imm); + break; +#endif default: /* Invalid */ MIPS_INVAL("regimm"); generate_exception(ctx, EXCP_RI); @@ -15376,6 +16905,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) case OPC_MFMC0: #ifndef CONFIG_USER_ONLY { + uint32_t op2; TCGv t0 = tcg_temp_new(); op2 = MASK_MFMC0(ctx->opcode); @@ -15439,7 +16969,16 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) break; } break; - case OPC_ADDI: /* Arithmetic with immediate opcode */ + case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */ + gen_compute_compact_branch(ctx, op, rs, rt, imm << 2); + } else { + /* OPC_ADDI */ + /* Arithmetic with immediate opcode */ + gen_arith_imm(ctx, op, rt, rs, imm); + } + break; case OPC_ADDIU: gen_arith_imm(ctx, op, rt, rs, imm); break; @@ -15448,36 +16987,96 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) gen_slt_imm(ctx, op, rt, rs, imm); break; case OPC_ANDI: /* Arithmetic with immediate opcode */ - case OPC_LUI: + case OPC_LUI: /* OPC_AUI */ case OPC_ORI: case OPC_XORI: gen_logic_imm(ctx, op, rt, rs, imm); break; case OPC_J ... OPC_JAL: /* Jump */ offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; - gen_compute_branch(ctx, op, 4, rs, rt, offset); + gen_compute_branch(ctx, op, 4, rs, rt, offset, 4); break; - case OPC_BEQ ... OPC_BGTZ: /* Branch */ - case OPC_BEQL ... OPC_BGTZL: - gen_compute_branch(ctx, op, 4, rs, rt, imm << 2); + /* Branch */ + case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */ + if (ctx->insn_flags & ISA_MIPS32R6) { + if (rt == 0) { + generate_exception(ctx, EXCP_RI); + break; + } + /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */ + gen_compute_compact_branch(ctx, op, rs, rt, imm << 2); + } else { + /* OPC_BLEZL */ + gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4); + } + break; + case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */ + if (ctx->insn_flags & ISA_MIPS32R6) { + if (rt == 0) { + generate_exception(ctx, EXCP_RI); + break; + } + /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */ + gen_compute_compact_branch(ctx, op, rs, rt, imm << 2); + } else { + /* OPC_BGTZL */ + gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4); + } + break; + case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */ + if (rt == 0) { + /* OPC_BLEZ */ + gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4); + } else { + check_insn(ctx, ISA_MIPS32R6); + /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */ + gen_compute_compact_branch(ctx, op, rs, rt, imm << 2); + } + break; + case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */ + if (rt == 0) { + /* OPC_BGTZ */ + gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4); + } else { + check_insn(ctx, ISA_MIPS32R6); + /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */ + gen_compute_compact_branch(ctx, op, rs, rt, imm << 2); + } + break; + case OPC_BEQL: + case OPC_BNEL: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + case OPC_BEQ: + case OPC_BNE: + gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4); break; - case OPC_LB ... OPC_LWR: /* Load and stores */ + case OPC_LWL: /* Load and stores */ + case OPC_LWR: case OPC_LL: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + case OPC_LB ... OPC_LH: + case OPC_LW ... OPC_LHU: gen_ld(ctx, op, rt, rs, imm); break; - case OPC_SB ... OPC_SW: + case OPC_SWL: case OPC_SWR: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + case OPC_SB ... OPC_SH: + case OPC_SW: gen_st(ctx, op, rt, rs, imm); break; case OPC_SC: + check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_st_cond(ctx, op, rt, rs, imm); break; case OPC_CACHE: + check_insn_opc_removed(ctx, ISA_MIPS32R6); check_cp0_enabled(ctx); check_insn(ctx, ISA_MIPS3 | ISA_MIPS32); /* Treat as NOP. */ break; case OPC_PREF: + check_insn_opc_removed(ctx, ISA_MIPS32R6); check_insn(ctx, ISA_MIPS4 | ISA_MIPS32); /* Treat as NOP. */ break; @@ -15511,23 +17110,106 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) gen_cp1(ctx, op1, rt, rd); break; #endif - case OPC_BC1ANY2: + case OPC_BC1EQZ: /* OPC_BC1ANY2 */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* OPC_BC1EQZ */ + gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode), + rt, imm << 2); + } else { + /* OPC_BC1ANY2 */ + check_cop1x(ctx); + check_insn(ctx, ASE_MIPS3D); + gen_compute_branch1(ctx, MASK_BC1(ctx->opcode), + (rt >> 2) & 0x7, imm << 2); + } + break; + case OPC_BC1NEZ: + check_insn(ctx, ISA_MIPS32R6); + gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode), + rt, imm << 2); + break; case OPC_BC1ANY4: + check_insn_opc_removed(ctx, ISA_MIPS32R6); check_cop1x(ctx); check_insn(ctx, ASE_MIPS3D); /* fall through */ case OPC_BC1: + check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_compute_branch1(ctx, MASK_BC1(ctx->opcode), (rt >> 2) & 0x7, imm << 2); break; + case OPC_PS_FMT: + check_insn_opc_removed(ctx, ISA_MIPS32R6); case OPC_S_FMT: case OPC_D_FMT: - case OPC_W_FMT: - case OPC_L_FMT: - case OPC_PS_FMT: gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa, (imm >> 8) & 0x7); break; + case OPC_W_FMT: + case OPC_L_FMT: + { + int r6_op = ctx->opcode & FOP(0x3f, 0x1f); + if (ctx->insn_flags & ISA_MIPS32R6) { + switch (r6_op) { + case R6_OPC_CMP_AF_S: + case R6_OPC_CMP_UN_S: + case R6_OPC_CMP_EQ_S: + case R6_OPC_CMP_UEQ_S: + case R6_OPC_CMP_LT_S: + case R6_OPC_CMP_ULT_S: + case R6_OPC_CMP_LE_S: + case R6_OPC_CMP_ULE_S: + case R6_OPC_CMP_SAF_S: + case R6_OPC_CMP_SUN_S: + case R6_OPC_CMP_SEQ_S: + case R6_OPC_CMP_SEUQ_S: + case R6_OPC_CMP_SLT_S: + case R6_OPC_CMP_SULT_S: + case R6_OPC_CMP_SLE_S: + case R6_OPC_CMP_SULE_S: + case R6_OPC_CMP_OR_S: + case R6_OPC_CMP_UNE_S: + case R6_OPC_CMP_NE_S: + case R6_OPC_CMP_SOR_S: + case R6_OPC_CMP_SUNE_S: + case R6_OPC_CMP_SNE_S: + gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa); + break; + case R6_OPC_CMP_AF_D: + case R6_OPC_CMP_UN_D: + case R6_OPC_CMP_EQ_D: + case R6_OPC_CMP_UEQ_D: + case R6_OPC_CMP_LT_D: + case R6_OPC_CMP_ULT_D: + case R6_OPC_CMP_LE_D: + case R6_OPC_CMP_ULE_D: + case R6_OPC_CMP_SAF_D: + case R6_OPC_CMP_SUN_D: + case R6_OPC_CMP_SEQ_D: + case R6_OPC_CMP_SEUQ_D: + case R6_OPC_CMP_SLT_D: + case R6_OPC_CMP_SULT_D: + case R6_OPC_CMP_SLE_D: + case R6_OPC_CMP_SULE_D: + case R6_OPC_CMP_OR_D: + case R6_OPC_CMP_UNE_D: + case R6_OPC_CMP_NE_D: + case R6_OPC_CMP_SOR_D: + case R6_OPC_CMP_SUNE_D: + case R6_OPC_CMP_SNE_D: + gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa); + break; + default: + gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa, + (imm >> 8) & 0x7); + break; + } + } else { + gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa, + (imm >> 8) & 0x7); + } + break; + } default: MIPS_INVAL("cp1"); generate_exception (ctx, EXCP_RI); @@ -15538,13 +17220,35 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) } break; - /* COP2. */ - case OPC_LWC2: - case OPC_LDC2: - case OPC_SWC2: - case OPC_SDC2: - /* COP2: Not implemented. */ - generate_exception_err(ctx, EXCP_CpU, 2); + /* Compact branches [R6] and COP2 [non-R6] */ + case OPC_BC: /* OPC_LWC2 */ + case OPC_BALC: /* OPC_SWC2 */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* OPC_BC, OPC_BALC */ + gen_compute_compact_branch(ctx, op, 0, 0, + sextract32(ctx->opcode << 2, 0, 28)); + } else { + /* OPC_LWC2, OPC_SWC2 */ + /* COP2: Not implemented. */ + generate_exception_err(ctx, EXCP_CpU, 2); + } + break; + case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */ + case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */ + if (ctx->insn_flags & ISA_MIPS32R6) { + if (rs != 0) { + /* OPC_BEQZC, OPC_BNEZC */ + gen_compute_compact_branch(ctx, op, rs, 0, + sextract32(ctx->opcode << 2, 0, 23)); + } else { + /* OPC_JIC, OPC_JIALC */ + gen_compute_compact_branch(ctx, op, 0, rt, imm); + } + } else { + /* OPC_LWC2, OPC_SWC2 */ + /* COP2: Not implemented. */ + generate_exception_err(ctx, EXCP_CpU, 2); + } break; case OPC_CP2: check_insn(ctx, INSN_LOONGSON2F); @@ -15553,6 +17257,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) break; case OPC_CP3: + check_insn_opc_removed(ctx, ISA_MIPS32R6); if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { check_cp1_enabled(ctx); op1 = MASK_CP3(ctx->opcode); @@ -15595,40 +17300,85 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) #if defined(TARGET_MIPS64) /* MIPS64 opcodes */ - case OPC_LWU: case OPC_LDL ... OPC_LDR: case OPC_LLD: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + case OPC_LWU: case OPC_LD: check_insn(ctx, ISA_MIPS3); check_mips_64(ctx); gen_ld(ctx, op, rt, rs, imm); break; case OPC_SDL ... OPC_SDR: + check_insn_opc_removed(ctx, ISA_MIPS32R6); case OPC_SD: check_insn(ctx, ISA_MIPS3); check_mips_64(ctx); gen_st(ctx, op, rt, rs, imm); break; case OPC_SCD: + check_insn_opc_removed(ctx, ISA_MIPS32R6); check_insn(ctx, ISA_MIPS3); check_mips_64(ctx); gen_st_cond(ctx, op, rt, rs, imm); break; - case OPC_DADDI: + case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */ + if (ctx->insn_flags & ISA_MIPS32R6) { + /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */ + gen_compute_compact_branch(ctx, op, rs, rt, imm << 2); + } else { + /* OPC_DADDI */ + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_arith_imm(ctx, op, rt, rs, imm); + } + break; case OPC_DADDIU: check_insn(ctx, ISA_MIPS3); check_mips_64(ctx); gen_arith_imm(ctx, op, rt, rs, imm); break; +#else + case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + gen_compute_compact_branch(ctx, op, rs, rt, imm << 2); + } else { + MIPS_INVAL("major opcode"); + generate_exception(ctx, EXCP_RI); + } + break; #endif - case OPC_JALX: - check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS); - offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; - gen_compute_branch(ctx, op, 4, rs, rt, offset); + case OPC_DAUI: /* OPC_JALX */ + if (ctx->insn_flags & ISA_MIPS32R6) { +#if defined(TARGET_MIPS64) + /* OPC_DAUI */ + check_mips_64(ctx); + if (rt != 0) { + TCGv t0 = tcg_temp_new(); + gen_load_gpr(t0, rs); + tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16); + tcg_temp_free(t0); + } + MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm); +#else + generate_exception(ctx, EXCP_RI); + MIPS_INVAL("major opcode"); +#endif + } else { + /* OPC_JALX */ + check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS); + offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; + gen_compute_branch(ctx, op, 4, rs, rt, offset, 4); + } break; case OPC_MDMX: check_insn(ctx, ASE_MDMX); /* MDMX: Not implemented. */ + break; + case OPC_PCREL: + check_insn(ctx, ISA_MIPS32R6); + gen_pcrel(ctx, rs, imm); + break; default: /* Invalid */ MIPS_INVAL("major opcode"); generate_exception(ctx, EXCP_RI); @@ -15726,8 +17476,15 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, ctx.bstate = BS_STOP; break; } + + if (ctx.hflags & MIPS_HFLAG_BMASK) { + if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32))) { + is_delay = 1; + /* force to generate branch as no delay slot is required */ + } + } if (is_delay) { - handle_delay_slot(&ctx, insn_bytes); + gen_branch(&ctx, insn_bytes); } ctx.pc += insn_bytes; @@ -15944,9 +17701,6 @@ void mips_tcg_init(void) cpu_LO[i] = tcg_global_mem_new(TCG_AREG0, offsetof(CPUMIPSState, active_tc.LO[i]), regnames_LO[i]); - cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0, - offsetof(CPUMIPSState, active_tc.ACX[i]), - regnames_ACX[i]); } cpu_dspctrl = tcg_global_mem_new(TCG_AREG0, offsetof(CPUMIPSState, active_tc.DSPControl), @@ -16134,6 +17888,12 @@ void cpu_state_reset(CPUMIPSState *env) } } #endif + if ((env->insn_flags & ISA_MIPS32R6) && + (env->active_fpu.fcr0 & (1 << FCR0_F64))) { + /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */ + env->CP0_Status |= (1 << CP0St_FR); + } + compute_hflags(env); cs->exception_index = EXCP_NONE; } diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 29dc2ef..67b7837 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -516,6 +516,36 @@ static const mips_def_t mips_defs[] = .mmu_type = MMU_TYPE_R4000, }, { + /* A generic CPU supporting MIPS64 Release 6 ISA. + FIXME: It does not support all the MIPS64R6 features yet. + Eventually this should be replaced by a real CPU model. */ + .name = "MIPS64R6-generic", + .CP0_PRid = 0x00010000, + .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AR) | (0x2 << CP0C0_AT) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) | + (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) | + (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) | + (0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP), + .CP0_Config2 = MIPS_CONFIG2, + .CP0_Config3 = MIPS_CONFIG3, + .CP0_LLAddr_rw_bitmask = 0, + .CP0_LLAddr_shift = 0, + .SYNCI_Step = 32, + .CCRes = 2, + .CP0_Status_rw_bitmask = 0x30D8FFFF, + .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | + (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) | + (0x0 << FCR0_REV), + .SEGBITS = 42, + /* The architectural limit is 59, but we have hardcoded 36 bit + in some places... + .PABITS = 59, */ /* the architectural limit */ + .PABITS = 36, + .insn_flags = CPU_MIPS64R6, + .mmu_type = MMU_TYPE_R4000, + }, + { .name = "Loongson-2E", .CP0_PRid = 0x6302, /*64KB I-cache and d-cache. 4 way with 32 bit cache line size*/ diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c index 8c4d68b..6a0b981 100644 --- a/tests/test-thread-pool.c +++ b/tests/test-thread-pool.c @@ -11,7 +11,7 @@ static ThreadPool *pool; static int active; typedef struct { - BlockDriverAIOCB *aiocb; + BlockAIOCB *aiocb; int n; int ret; } WorkerTestData; diff --git a/thread-pool.c b/thread-pool.c index 86fa4a8..e2cac8e 100644 --- a/thread-pool.c +++ b/thread-pool.c @@ -34,7 +34,7 @@ enum ThreadState { }; struct ThreadPoolElement { - BlockDriverAIOCB common; + BlockAIOCB common; ThreadPool *pool; ThreadPoolFunc *func; void *arg; @@ -195,7 +195,7 @@ restart: } } -static void thread_pool_cancel(BlockDriverAIOCB *acb) +static void thread_pool_cancel(BlockAIOCB *acb) { ThreadPoolElement *elem = (ThreadPoolElement *)acb; ThreadPool *pool = elem->pool; @@ -220,7 +220,7 @@ static void thread_pool_cancel(BlockDriverAIOCB *acb) qemu_mutex_unlock(&pool->lock); } -static AioContext *thread_pool_get_aio_context(BlockDriverAIOCB *acb) +static AioContext *thread_pool_get_aio_context(BlockAIOCB *acb) { ThreadPoolElement *elem = (ThreadPoolElement *)acb; ThreadPool *pool = elem->pool; @@ -233,9 +233,9 @@ static const AIOCBInfo thread_pool_aiocb_info = { .get_aio_context = thread_pool_get_aio_context, }; -BlockDriverAIOCB *thread_pool_submit_aio(ThreadPool *pool, +BlockAIOCB *thread_pool_submit_aio(ThreadPool *pool, ThreadPoolFunc *func, void *arg, - BlockDriverCompletionFunc *cb, void *opaque) + BlockCompletionFunc *cb, void *opaque) { ThreadPoolElement *req; diff --git a/trace-events b/trace-events index 5290806..6c3a400 100644 --- a/trace-events +++ b/trace-events @@ -195,8 +195,8 @@ fw_cfg_add_file_dupe(void *s, char *name) "%p %s" fw_cfg_add_file(void *s, int index, char *name, size_t len) "%p #%d: %s (%zd bytes)" # hw/block/hd-geometry.c -hd_geometry_lchs_guess(void *bs, int cyls, int heads, int secs) "bs %p LCHS %d %d %d" -hd_geometry_guess(void *bs, uint32_t cyls, uint32_t heads, uint32_t secs, int trans) "bs %p CHS %u %u %u trans %d" +hd_geometry_lchs_guess(void *blk, int cyls, int heads, int secs) "blk %p LCHS %d %d %d" +hd_geometry_guess(void *blk, uint32_t cyls, uint32_t heads, uint32_t secs, int trans) "blk %p CHS %u %u %u trans %d" # hw/display/jazz_led.c jazz_led_read(uint64_t addr, uint8_t val) "read addr=0x%"PRIx64": 0x%x" @@ -1078,10 +1078,10 @@ win_helper_done(uint32_t tl) "tl=%d" win_helper_retry(uint32_t tl) "tl=%d" # dma-helpers.c -dma_bdrv_io(void *dbs, void *bs, int64_t sector_num, bool to_dev) "dbs=%p bs=%p sector_num=%" PRId64 " to_dev=%d" +dma_blk_io(void *dbs, void *bs, int64_t sector_num, bool to_dev) "dbs=%p bs=%p sector_num=%" PRId64 " to_dev=%d" dma_aio_cancel(void *dbs) "dbs=%p" dma_complete(void *dbs, int ret, void *cb) "dbs=%p ret=%d cb=%p" -dma_bdrv_cb(void *dbs, int ret) "dbs=%p ret=%d" +dma_blk_cb(void *dbs, int ret) "dbs=%p ret=%d" dma_map_wait(void *dbs) "dbs=%p" # ui/console.c @@ -931,6 +931,12 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque) int qemu_keycode; int i; + if (key->keyval == GDK_KEY_Pause) { + qemu_input_event_send_key_qcode(vc->gfx.dcl.con, Q_KEY_CODE_PAUSE, + key->type == GDK_KEY_PRESS); + return TRUE; + } + qemu_keycode = gd_map_keycode(s, gtk_widget_get_display(widget), gdk_keycode); @@ -1810,6 +1816,13 @@ static void gd_set_keycode_type(GtkDisplayState *s) fprintf(stderr, "unknown keycodes `%s', please report to " "qemu-devel@nongnu.org\n", keycodes); } + + if (desc) { + XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True); + } + if (keycodes) { + XFree(keycodes); + } } #endif } |