diff options
68 files changed, 1636 insertions, 679 deletions
diff --git a/.gitmodules b/.gitmodules index b426ea605a..d7e3f3c7cd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -15,7 +15,7 @@ url = git://git.qemu.org/openbios.git [submodule "roms/qemu-palcode"] path = roms/qemu-palcode - url = git://repo.or.cz/qemu-palcode.git + url = git://github.com/rth7680/qemu-palcode.git [submodule "roms/sgabios"] path = roms/sgabios url = git://git.qemu.org/sgabios.git diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt index 24e804e948..39b6016460 100644 --- a/QMP/qmp-events.txt +++ b/QMP/qmp-events.txt @@ -172,6 +172,23 @@ Data: }, "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +NIC_RX_FILTER_CHANGED +----------------- + +The event is emitted once until the query command is executed, +the first event will always be emitted. + +Data: + +- "name": net client name (json-string) +- "path": device path (json-string) + +{ "event": "NIC_RX_FILTER_CHANGED", + "data": { "name": "vnet0", + "path": "/machine/peripheral/vnet0/virtio-backend" }, + "timestamp": { "seconds": 1368697518, "microseconds": 326866 } } +} + RESET ----- diff --git a/async.c b/async.c index 90fe906539..5ce3633010 100644 --- a/async.c +++ b/async.c @@ -47,11 +47,16 @@ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque) bh->ctx = ctx; bh->cb = cb; bh->opaque = opaque; + qemu_mutex_lock(&ctx->bh_lock); bh->next = ctx->first_bh; + /* Make sure that the members are ready before putting bh into list */ + smp_wmb(); ctx->first_bh = bh; + qemu_mutex_unlock(&ctx->bh_lock); return bh; } +/* Multiple occurrences of aio_bh_poll cannot be called concurrently */ int aio_bh_poll(AioContext *ctx) { QEMUBH *bh, **bhp, *next; @@ -61,9 +66,15 @@ int aio_bh_poll(AioContext *ctx) ret = 0; for (bh = ctx->first_bh; bh; bh = next) { + /* Make sure that fetching bh happens before accessing its members */ + smp_read_barrier_depends(); next = bh->next; if (!bh->deleted && bh->scheduled) { bh->scheduled = 0; + /* Paired with write barrier in bh schedule to ensure reading for + * idle & callbacks coming after bh's scheduling. + */ + smp_rmb(); if (!bh->idle) ret = 1; bh->idle = 0; @@ -75,6 +86,7 @@ int aio_bh_poll(AioContext *ctx) /* remove deleted bhs */ if (!ctx->walking_bh) { + qemu_mutex_lock(&ctx->bh_lock); bhp = &ctx->first_bh; while (*bhp) { bh = *bhp; @@ -85,6 +97,7 @@ int aio_bh_poll(AioContext *ctx) bhp = &bh->next; } } + qemu_mutex_unlock(&ctx->bh_lock); } return ret; @@ -94,24 +107,38 @@ void qemu_bh_schedule_idle(QEMUBH *bh) { if (bh->scheduled) return; - bh->scheduled = 1; bh->idle = 1; + /* Make sure that idle & any writes needed by the callback are done + * before the locations are read in the aio_bh_poll. + */ + smp_wmb(); + bh->scheduled = 1; } void qemu_bh_schedule(QEMUBH *bh) { if (bh->scheduled) return; - bh->scheduled = 1; bh->idle = 0; + /* Make sure that idle & any writes needed by the callback are done + * before the locations are read in the aio_bh_poll. + */ + smp_wmb(); + bh->scheduled = 1; aio_notify(bh->ctx); } + +/* This func is async. + */ void qemu_bh_cancel(QEMUBH *bh) { bh->scheduled = 0; } +/* This func is async.The bottom half will do the delete action at the finial + * end. + */ void qemu_bh_delete(QEMUBH *bh) { bh->scheduled = 0; @@ -176,6 +203,7 @@ aio_ctx_finalize(GSource *source) thread_pool_free(ctx->thread_pool); aio_set_event_notifier(ctx, &ctx->notifier, NULL, NULL); event_notifier_cleanup(&ctx->notifier); + qemu_mutex_destroy(&ctx->bh_lock); g_array_free(ctx->pollfds, TRUE); } @@ -211,6 +239,7 @@ AioContext *aio_context_new(void) ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext)); ctx->pollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD)); ctx->thread_pool = NULL; + qemu_mutex_init(&ctx->bh_lock); event_notifier_init(&ctx->notifier, false); aio_set_event_notifier(ctx, &ctx->notifier, (EventNotifierHandler *) diff --git a/block-migration.c b/block-migration.c index 2fd7699794..f803f2006f 100644 --- a/block-migration.c +++ b/block-migration.c @@ -29,6 +29,7 @@ #define BLK_MIG_FLAG_DEVICE_BLOCK 0x01 #define BLK_MIG_FLAG_EOS 0x02 #define BLK_MIG_FLAG_PROGRESS 0x04 +#define BLK_MIG_FLAG_ZERO_BLOCK 0x08 #define MAX_IS_ALLOCATED_SEARCH 65536 @@ -80,6 +81,7 @@ typedef struct BlkMigState { int shared_base; QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list; int64_t total_sector_sum; + bool zero_blocks; /* Protected by lock. */ QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list; @@ -114,16 +116,30 @@ static void blk_mig_unlock(void) static void blk_send(QEMUFile *f, BlkMigBlock * blk) { int len; + uint64_t flags = BLK_MIG_FLAG_DEVICE_BLOCK; + + if (block_mig_state.zero_blocks && + buffer_is_zero(blk->buf, BLOCK_SIZE)) { + flags |= BLK_MIG_FLAG_ZERO_BLOCK; + } /* sector number and flags */ qemu_put_be64(f, (blk->sector << BDRV_SECTOR_BITS) - | BLK_MIG_FLAG_DEVICE_BLOCK); + | flags); /* device name */ len = strlen(blk->bmds->bs->device_name); qemu_put_byte(f, len); qemu_put_buffer(f, (uint8_t *)blk->bmds->bs->device_name, 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. + * thus if we queue zero blocks we slow down the migration */ + if (flags & BLK_MIG_FLAG_ZERO_BLOCK) { + qemu_fflush(f); + return; + } + qemu_put_buffer(f, blk->buf, BLOCK_SIZE); } @@ -344,6 +360,7 @@ static void init_blk_migration(QEMUFile *f) 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); } @@ -762,12 +779,15 @@ static int block_load(QEMUFile *f, void *opaque, int version_id) nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK; } - buf = g_malloc(BLOCK_SIZE); - - qemu_get_buffer(f, buf, BLOCK_SIZE); - ret = bdrv_write(bs, addr, buf, nr_sectors); + if (flags & BLK_MIG_FLAG_ZERO_BLOCK) { + ret = bdrv_write_zeroes(bs, addr, nr_sectors); + } else { + buf = g_malloc(BLOCK_SIZE); + qemu_get_buffer(f, buf, BLOCK_SIZE); + ret = bdrv_write(bs, addr, buf, nr_sectors); + g_free(buf); + } - g_free(buf); if (ret < 0) { return ret; } diff --git a/block.c b/block.c index b56024113b..6cd39fa146 100644 --- a/block.c +++ b/block.c @@ -2162,6 +2162,7 @@ typedef struct RwCo { QEMUIOVector *qiov; bool is_write; int ret; + BdrvRequestFlags flags; } RwCo; static void coroutine_fn bdrv_rw_co_entry(void *opaque) @@ -2170,10 +2171,12 @@ static void coroutine_fn bdrv_rw_co_entry(void *opaque) if (!rwco->is_write) { rwco->ret = bdrv_co_do_readv(rwco->bs, rwco->sector_num, - rwco->nb_sectors, rwco->qiov, 0); + rwco->nb_sectors, rwco->qiov, + rwco->flags); } else { rwco->ret = bdrv_co_do_writev(rwco->bs, rwco->sector_num, - rwco->nb_sectors, rwco->qiov, 0); + rwco->nb_sectors, rwco->qiov, + rwco->flags); } } @@ -2181,7 +2184,8 @@ static void coroutine_fn bdrv_rw_co_entry(void *opaque) * Process a vectored synchronous request using coroutines */ static int bdrv_rwv_co(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *qiov, bool is_write) + QEMUIOVector *qiov, bool is_write, + BdrvRequestFlags flags) { Coroutine *co; RwCo rwco = { @@ -2191,6 +2195,7 @@ static int bdrv_rwv_co(BlockDriverState *bs, int64_t sector_num, .qiov = qiov, .is_write = is_write, .ret = NOT_DONE, + .flags = flags, }; assert((qiov->size & (BDRV_SECTOR_SIZE - 1)) == 0); @@ -2222,7 +2227,7 @@ static int bdrv_rwv_co(BlockDriverState *bs, int64_t sector_num, * Process a synchronous request using coroutines */ static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, - int nb_sectors, bool is_write) + int nb_sectors, bool is_write, BdrvRequestFlags flags) { QEMUIOVector qiov; struct iovec iov = { @@ -2231,14 +2236,14 @@ static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, }; qemu_iovec_init_external(&qiov, &iov, 1); - return bdrv_rwv_co(bs, sector_num, &qiov, is_write); + return bdrv_rwv_co(bs, sector_num, &qiov, is_write, flags); } /* return < 0 if error. See bdrv_write() for the return codes */ int bdrv_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors) { - return bdrv_rw_co(bs, sector_num, buf, nb_sectors, false); + return bdrv_rw_co(bs, sector_num, buf, nb_sectors, false, 0); } /* Just like bdrv_read(), but with I/O throttling temporarily disabled */ @@ -2250,7 +2255,7 @@ int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num, enabled = bs->io_limits_enabled; bs->io_limits_enabled = false; - ret = bdrv_read(bs, 0, buf, 1); + ret = bdrv_read(bs, sector_num, buf, nb_sectors); bs->io_limits_enabled = enabled; return ret; } @@ -2264,12 +2269,18 @@ int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num, int bdrv_write(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors) { - return bdrv_rw_co(bs, sector_num, (uint8_t *)buf, nb_sectors, true); + return bdrv_rw_co(bs, sector_num, (uint8_t *)buf, nb_sectors, true, 0); } int bdrv_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov) { - return bdrv_rwv_co(bs, sector_num, qiov, true); + return bdrv_rwv_co(bs, sector_num, qiov, true, 0); +} + +int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num, int nb_sectors) +{ + return bdrv_rw_co(bs, sector_num, NULL, nb_sectors, true, + BDRV_REQ_ZERO_WRITE); } int bdrv_pread(BlockDriverState *bs, int64_t offset, diff --git a/block/gluster.c b/block/gluster.c index 61424bcb01..6de418c0bd 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -532,6 +532,39 @@ out: return NULL; } +#ifdef CONFIG_GLUSTERFS_DISCARD +static BlockDriverAIOCB *qemu_gluster_aio_discard(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, BlockDriverCompletionFunc *cb, + void *opaque) +{ + int ret; + GlusterAIOCB *acb; + BDRVGlusterState *s = bs->opaque; + size_t size; + off_t offset; + + offset = sector_num * BDRV_SECTOR_SIZE; + size = nb_sectors * BDRV_SECTOR_SIZE; + + acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque); + acb->size = 0; + acb->ret = 0; + acb->finished = NULL; + s->qemu_aio_count++; + + ret = glfs_discard_async(s->fd, offset, size, &gluster_finish_aiocb, acb); + if (ret < 0) { + goto out; + } + return &acb->common; + +out: + s->qemu_aio_count--; + qemu_aio_release(acb); + return NULL; +} +#endif + static int64_t qemu_gluster_getlength(BlockDriverState *bs) { BDRVGlusterState *s = bs->opaque; @@ -602,6 +635,9 @@ static BlockDriver bdrv_gluster = { .bdrv_aio_writev = qemu_gluster_aio_writev, .bdrv_aio_flush = qemu_gluster_aio_flush, .bdrv_has_zero_init = qemu_gluster_has_zero_init, +#ifdef CONFIG_GLUSTERFS_DISCARD + .bdrv_aio_discard = qemu_gluster_aio_discard, +#endif .create_options = qemu_gluster_create_options, }; @@ -618,6 +654,9 @@ static BlockDriver bdrv_gluster_tcp = { .bdrv_aio_writev = qemu_gluster_aio_writev, .bdrv_aio_flush = qemu_gluster_aio_flush, .bdrv_has_zero_init = qemu_gluster_has_zero_init, +#ifdef CONFIG_GLUSTERFS_DISCARD + .bdrv_aio_discard = qemu_gluster_aio_discard, +#endif .create_options = qemu_gluster_create_options, }; @@ -634,6 +673,9 @@ static BlockDriver bdrv_gluster_unix = { .bdrv_aio_writev = qemu_gluster_aio_writev, .bdrv_aio_flush = qemu_gluster_aio_flush, .bdrv_has_zero_init = qemu_gluster_has_zero_init, +#ifdef CONFIG_GLUSTERFS_DISCARD + .bdrv_aio_discard = qemu_gluster_aio_discard, +#endif .create_options = qemu_gluster_create_options, }; @@ -650,6 +692,9 @@ static BlockDriver bdrv_gluster_rdma = { .bdrv_aio_writev = qemu_gluster_aio_writev, .bdrv_aio_flush = qemu_gluster_aio_flush, .bdrv_has_zero_init = qemu_gluster_has_zero_init, +#ifdef CONFIG_GLUSTERFS_DISCARD + .bdrv_aio_discard = qemu_gluster_aio_discard, +#endif .create_options = qemu_gluster_create_options, }; diff --git a/block/iscsi.c b/block/iscsi.c index 0bbf0b18b4..5f28c6a2ea 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -32,6 +32,7 @@ #include "block/block_int.h" #include "trace.h" #include "block/scsi.h" +#include "qemu/iov.h" #include <iscsi/iscsi.h> #include <iscsi/scsi-lowlevel.h> @@ -61,8 +62,6 @@ typedef struct IscsiAIOCB { int status; int canceled; int retries; - size_t read_size; - size_t read_offset; int64_t sector_num; int nb_sectors; #ifdef __linux__ @@ -233,11 +232,28 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, iscsi_schedule_bh(acb); } +static int64_t sector_lun2qemu(int64_t sector, IscsiLun *iscsilun) +{ + return sector * iscsilun->block_size / BDRV_SECTOR_SIZE; +} + static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun) { return sector * BDRV_SECTOR_SIZE / iscsilun->block_size; } +static bool is_request_lun_aligned(int64_t sector_num, int nb_sectors, + IscsiLun *iscsilun) +{ + if ((sector_num * BDRV_SECTOR_SIZE) % iscsilun->block_size || + (nb_sectors * BDRV_SECTOR_SIZE) % iscsilun->block_size) { + error_report("iSCSI misaligned request: iscsilun->block_size %u, sector_num %ld, nb_sectors %d", + iscsilun->block_size, sector_num, nb_sectors); + return 0; + } + return 1; +} + static int iscsi_aio_writev_acb(IscsiAIOCB *acb) { @@ -285,7 +301,7 @@ iscsi_aio_writev_acb(IscsiAIOCB *acb) lba = sector_qemu2lun(acb->sector_num, acb->iscsilun); *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32); *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff); - num_sectors = size / acb->iscsilun->block_size; + num_sectors = sector_qemu2lun(acb->nb_sectors, acb->iscsilun); *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors); acb->task->expxferlen = size; @@ -322,6 +338,10 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, IscsiLun *iscsilun = bs->opaque; IscsiAIOCB *acb; + if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) { + return NULL; + } + acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque); trace_iscsi_aio_writev(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb); @@ -379,6 +399,7 @@ static int iscsi_aio_readv_acb(IscsiAIOCB *acb) { struct iscsi_context *iscsi = acb->iscsilun->iscsi; + size_t size; uint64_t lba; uint32_t num_sectors; int ret; @@ -391,20 +412,7 @@ iscsi_aio_readv_acb(IscsiAIOCB *acb) acb->status = -EINPROGRESS; acb->buf = NULL; - /* If LUN blocksize is bigger than BDRV_BLOCK_SIZE a read from QEMU - * may be misaligned to the LUN, so we may need to read some extra - * data. - */ - acb->read_offset = 0; - if (acb->iscsilun->block_size > BDRV_SECTOR_SIZE) { - uint64_t bdrv_offset = BDRV_SECTOR_SIZE * acb->sector_num; - - acb->read_offset = bdrv_offset % acb->iscsilun->block_size; - } - - num_sectors = (acb->read_size + acb->iscsilun->block_size - + acb->read_offset - 1) - / acb->iscsilun->block_size; + size = acb->nb_sectors * BDRV_SECTOR_SIZE; acb->task = malloc(sizeof(struct scsi_task)); if (acb->task == NULL) { @@ -415,8 +423,9 @@ iscsi_aio_readv_acb(IscsiAIOCB *acb) memset(acb->task, 0, sizeof(struct scsi_task)); acb->task->xfer_dir = SCSI_XFER_READ; + acb->task->expxferlen = size; lba = sector_qemu2lun(acb->sector_num, acb->iscsilun); - acb->task->expxferlen = acb->read_size; + num_sectors = sector_qemu2lun(acb->nb_sectors, acb->iscsilun); switch (acb->iscsilun->type) { case TYPE_DISK: @@ -464,6 +473,10 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num, IscsiLun *iscsilun = bs->opaque; IscsiAIOCB *acb; + if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) { + return NULL; + } + acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque); trace_iscsi_aio_readv(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb); @@ -471,7 +484,6 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num, acb->sector_num = sector_num; acb->iscsilun = iscsilun; acb->qiov = qiov; - acb->read_size = BDRV_SECTOR_SIZE * (size_t)acb->nb_sectors; acb->retries = ISCSI_CMD_RETRIES; if (iscsi_aio_readv_acb(acb) != 0) { @@ -651,6 +663,9 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status, { IscsiAIOCB *acb = opaque; + g_free(acb->buf); + acb->buf = NULL; + if (acb->canceled != 0) { return; } @@ -727,14 +742,30 @@ static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, memcpy(&acb->task->cdb[0], acb->ioh->cmdp, acb->ioh->cmd_len); acb->task->expxferlen = acb->ioh->dxfer_len; + data.size = 0; if (acb->task->xfer_dir == SCSI_XFER_WRITE) { - data.data = acb->ioh->dxferp; - data.size = acb->ioh->dxfer_len; + if (acb->ioh->iovec_count == 0) { + data.data = acb->ioh->dxferp; + data.size = acb->ioh->dxfer_len; + } else { +#if defined(LIBISCSI_FEATURE_IOVECTOR) + scsi_task_set_iov_out(acb->task, + (struct scsi_iovec *) acb->ioh->dxferp, + acb->ioh->iovec_count); +#else + struct iovec *iov = (struct iovec *)acb->ioh->dxferp; + + acb->buf = g_malloc(acb->ioh->dxfer_len); + data.data = acb->buf; + data.size = iov_to_buf(iov, acb->ioh->iovec_count, 0, + acb->buf, acb->ioh->dxfer_len); +#endif + } } + if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task, iscsi_aio_ioctl_cb, - (acb->task->xfer_dir == SCSI_XFER_WRITE) ? - &data : NULL, + (data.size > 0) ? &data : NULL, acb) != 0) { scsi_free_scsi_task(acb->task); qemu_aio_release(acb); @@ -743,9 +774,26 @@ static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, /* tell libiscsi to read straight into the buffer we got from ioctl */ if (acb->task->xfer_dir == SCSI_XFER_READ) { - scsi_task_add_data_in_buffer(acb->task, - acb->ioh->dxfer_len, - acb->ioh->dxferp); + if (acb->ioh->iovec_count == 0) { + scsi_task_add_data_in_buffer(acb->task, + acb->ioh->dxfer_len, + acb->ioh->dxferp); + } else { +#if defined(LIBISCSI_FEATURE_IOVECTOR) + scsi_task_set_iov_in(acb->task, + (struct scsi_iovec *) acb->ioh->dxferp, + acb->ioh->iovec_count); +#else + int i; + for (i = 0; i < acb->ioh->iovec_count; i++) { + struct iovec *iov = (struct iovec *)acb->ioh->dxferp; + + scsi_task_add_data_in_buffer(acb->task, + iov[i].iov_len, + iov[i].iov_base); + } +#endif + } } iscsi_set_events(iscsilun); @@ -1118,8 +1166,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags) if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) { goto out; } - bs->total_sectors = iscsilun->num_blocks * - iscsilun->block_size / BDRV_SECTOR_SIZE ; + bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun); /* Medium changer or tape. We dont have any emulation for this so this must * be sg ioctl compatible. We force it to be sg, otherwise qemu will try @@ -1235,6 +1282,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options) } if (bs.total_sectors < total_size) { ret = -ENOSPC; + goto out; } ret = 0; diff --git a/block/raw.c b/block/raw.c index ce10422006..f1682d4f32 100644 --- a/block/raw.c +++ b/block/raw.c @@ -42,6 +42,13 @@ static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs, return bdrv_co_is_allocated(bs->file, sector_num, nb_sectors, pnum); } +static int coroutine_fn raw_co_write_zeroes(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors) +{ + return bdrv_co_write_zeroes(bs->file, sector_num, nb_sectors); +} + static int64_t raw_getlength(BlockDriverState *bs) { return bdrv_getlength(bs->file); @@ -114,6 +121,11 @@ static int raw_has_zero_init(BlockDriverState *bs) return bdrv_has_zero_init(bs->file); } +static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +{ + return bdrv_get_info(bs->file, bdi); +} + static BlockDriver bdrv_raw = { .format_name = "raw", @@ -128,10 +140,12 @@ static BlockDriver bdrv_raw = { .bdrv_co_readv = raw_co_readv, .bdrv_co_writev = raw_co_writev, .bdrv_co_is_allocated = raw_co_is_allocated, + .bdrv_co_write_zeroes = raw_co_write_zeroes, .bdrv_co_discard = raw_co_discard, .bdrv_probe = raw_probe, .bdrv_getlength = raw_getlength, + .bdrv_get_info = raw_get_info, .bdrv_truncate = raw_truncate, .bdrv_is_inserted = raw_is_inserted, diff --git a/block/vvfat.c b/block/vvfat.c index 87b02799d0..cd3b8edd9f 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -1164,8 +1164,8 @@ DLOG(if (stderr == NULL) { s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1); if (qemu_opt_get_bool(opts, "rw", false)) { - if (enable_write_target(s)) { - ret = -EIO; + ret = enable_write_target(s); + if (ret < 0) { goto fail; } bs->read_only = 0; @@ -2917,9 +2917,7 @@ static int enable_write_target(BDRVVVFATState *s) s->qcow_filename = g_malloc(1024); ret = get_tmp_filename(s->qcow_filename, 1024); if (ret < 0) { - g_free(s->qcow_filename); - s->qcow_filename = NULL; - return ret; + goto err; } bdrv_qcow = bdrv_find_format("qcow"); @@ -2927,18 +2925,18 @@ static int enable_write_target(BDRVVVFATState *s) set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512); set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:"); - if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0) - return -1; + ret = bdrv_create(bdrv_qcow, s->qcow_filename, options); + if (ret < 0) { + goto err; + } s->qcow = bdrv_new(""); - if (s->qcow == NULL) { - return -1; - } ret = bdrv_open(s->qcow, s->qcow_filename, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow); if (ret < 0) { - return ret; + bdrv_delete(s->qcow); + goto err; } #ifndef _WIN32 @@ -2951,6 +2949,11 @@ static int enable_write_target(BDRVVVFATState *s) *(void**)s->bs->backing_hd->opaque = s; return 0; + +err: + g_free(s->qcow_filename); + s->qcow_filename = NULL; + return ret; } static void vvfat_close(BlockDriverState *bs) diff --git a/configure b/configure index cb0f870b95..7c45db2fdd 100755 --- a/configure +++ b/configure @@ -237,6 +237,7 @@ libiscsi="" coroutine="" seccomp="" glusterfs="" +glusterfs_discard="no" virtio_blk_data_plane="" gtk="" gtkabi="2.0" @@ -1697,19 +1698,23 @@ if test "$gtk" != "no"; then vtepackage="vte" vteversion="0.24.0" fi - if $pkg_config --exists "$gtkpackage >= $gtkversion" && \ - $pkg_config --exists "$vtepackage >= $vteversion"; then + if ! $pkg_config --exists "$gtkpackage >= $gtkversion"; then + if test "$gtk" = "yes" ; then + feature_not_found "gtk" + fi + gtk="no" + elif ! $pkg_config --exists "$vtepackage >= $vteversion"; then + if test "$gtk" = "yes" ; then + error_exit "libvte not found (required for gtk support)" + fi + gtk="no" + else gtk_cflags=`$pkg_config --cflags $gtkpackage 2>/dev/null` gtk_libs=`$pkg_config --libs $gtkpackage 2>/dev/null` vte_cflags=`$pkg_config --cflags $vtepackage 2>/dev/null` vte_libs=`$pkg_config --libs $vtepackage 2>/dev/null` libs_softmmu="$gtk_libs $vte_libs $libs_softmmu" gtk="yes" - else - if test "$gtk" = "yes" ; then - feature_not_found "gtk" - fi - gtk="no" fi fi @@ -2566,23 +2571,21 @@ fi ########################################## # glusterfs probe if test "$glusterfs" != "no" ; then - cat > $TMPC <<EOF -#include <glusterfs/api/glfs.h> -int main(void) { - (void) glfs_new("volume"); - return 0; -} -EOF - glusterfs_libs="-lgfapi -lgfrpc -lgfxdr" - if compile_prog "" "$glusterfs_libs" ; then - glusterfs=yes + if $pkg_config --atleast-version=3 glusterfs-api >/dev/null 2>&1; then + glusterfs="yes" + glusterfs_cflags=`$pkg_config --cflags glusterfs-api 2>/dev/null` + glusterfs_libs=`$pkg_config --libs glusterfs-api 2>/dev/null` + CFLAGS="$CFLAGS $glusterfs_cflags" libs_tools="$glusterfs_libs $libs_tools" libs_softmmu="$glusterfs_libs $libs_softmmu" + if $pkg_config --atleast-version=5 glusterfs-api >/dev/null 2>&1; then + glusterfs_discard="yes" + fi else if test "$glusterfs" = "yes" ; then feature_not_found "GlusterFS backend support" fi - glusterfs=no + glusterfs="no" fi fi @@ -3965,6 +3968,10 @@ if test "$glusterfs" = "yes" ; then echo "CONFIG_GLUSTERFS=y" >> $config_host_mak fi +if test "$glusterfs_discard" = "yes" ; then + echo "CONFIG_GLUSTERFS_DISCARD=y" >> $config_host_mak +fi + if test "$libssh2" = "yes" ; then echo "CONFIG_LIBSSH2=y" >> $config_host_mak fi diff --git a/cpus.c b/cpus.c index 8062cdd57e..2509eb5af3 100644 --- a/cpus.c +++ b/cpus.c @@ -443,11 +443,12 @@ static int do_vm_stop(RunState state) pause_all_vcpus(); runstate_set(state); vm_state_notify(0, state); - bdrv_drain_all(); - ret = bdrv_flush_all(); monitor_protocol_event(QEVENT_STOP, NULL); } + bdrv_drain_all(); + ret = bdrv_flush_all(); + return ret; } @@ -1126,7 +1127,9 @@ int vm_stop_force_state(RunState state) return vm_stop(state); } else { runstate_set(state); - return 0; + /* Make sure to return an error if the flush in a previous vm_stop() + * failed. */ + return bdrv_flush_all(); } } diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c index 3d7a1cd8e8..b7fb04406c 100644 --- a/hw/alpha/typhoon.c +++ b/hw/alpha/typhoon.c @@ -693,7 +693,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, AlphaCPU *cpu = cpus[i]; s->cchip.cpu[i] = cpu; if (cpu != NULL) { - cpu->alarm_timer = qemu_new_timer_ns(rtc_clock, + cpu->alarm_timer = qemu_new_timer_ns(vm_clock, typhoon_alarm_timer, (void *)((uintptr_t)s + i)); } diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 03566650c6..2faed43127 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -537,7 +537,7 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s) /* Clean up guest notifier (irq) */ k->set_guest_notifiers(qbus->parent, 1, false); - vring_teardown(&s->vring); + vring_teardown(&s->vring, s->vdev, 0); s->started = false; s->stopping = false; } diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index a927a6bc21..8c3b7f0d3b 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -123,10 +123,14 @@ static const FlashPartInfo known_devices[] = { { INFO("mx25l25655e", 0xc22619, 0, 64 << 10, 512, 0) }, /* Micron */ - { INFO("n25q032a", 0x20bb16, 0, 64 << 10, 64, ER_4K) }, - { INFO("n25q128a11", 0x20bb18, 0, 64 << 10, 256, 0) }, - { INFO("n25q128a13", 0x20ba18, 0, 64 << 10, 256, 0) }, - { INFO("n25q256a", 0x20ba19, 0, 64 << 10, 512, ER_4K) }, + { INFO("n25q032a11", 0x20bb16, 0, 64 << 10, 64, ER_4K) }, + { INFO("n25q032a13", 0x20ba16, 0, 64 << 10, 64, ER_4K) }, + { INFO("n25q064a11", 0x20bb17, 0, 64 << 10, 128, ER_4K) }, + { INFO("n25q064a13", 0x20ba17, 0, 64 << 10, 128, ER_4K) }, + { INFO("n25q128a11", 0x20bb18, 0, 64 << 10, 256, ER_4K) }, + { INFO("n25q128a13", 0x20ba18, 0, 64 << 10, 256, ER_4K) }, + { INFO("n25q256a11", 0x20bb19, 0, 64 << 10, 512, ER_4K) }, + { INFO("n25q256a13", 0x20ba19, 0, 64 << 10, 512, ER_4K) }, /* Spansion -- single (large) sector size only, at least * for the chips listed here (without boot sectors). diff --git a/hw/i386/pc.c b/hw/i386/pc.c index c5d8570af1..2a8756321b 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1005,7 +1005,7 @@ typedef struct PcRomPciInfo { static void pc_fw_cfg_guest_info(PcGuestInfo *guest_info) { PcRomPciInfo *info; - if (!guest_info->has_pci_info) { + if (!guest_info->has_pci_info || !guest_info->fw_cfg) { return; } diff --git a/hw/misc/slavio_misc.c b/hw/misc/slavio_misc.c index d274fb4a87..00d9542c0b 100644 --- a/hw/misc/slavio_misc.c +++ b/hw/misc/slavio_misc.c @@ -368,7 +368,7 @@ static void slavio_led_mem_writew(void *opaque, hwaddr addr, { MiscState *s = opaque; - trace_slavio_led_mem_readw(val & 0xffff); + trace_slavio_led_mem_writew(val & 0xffff); switch (addr) { case 0: s->leds = val; diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index 540c377f61..ad8ce770dc 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -59,8 +59,23 @@ typedef struct VFIOQuirk { MemoryRegion mem; struct VFIODevice *vdev; QLIST_ENTRY(VFIOQuirk) next; - uint32_t data; - uint32_t data2; + struct { + uint32_t base_offset:TARGET_PAGE_BITS; + uint32_t address_offset:TARGET_PAGE_BITS; + uint32_t address_size:3; + uint32_t bar:3; + + uint32_t address_match; + uint32_t address_mask; + + uint32_t address_val:TARGET_PAGE_BITS; + uint32_t data_offset:TARGET_PAGE_BITS; + uint32_t data_size:3; + + uint8_t flags; + uint8_t read_flags; + uint8_t write_flags; + } data; } VFIOQuirk; typedef struct VFIOBAR { @@ -72,6 +87,8 @@ typedef struct VFIOBAR { size_t size; uint32_t flags; /* VFIO region flags (rd/wr/mmap) */ uint8_t nr; /* cache the BAR number for debug */ + bool ioport; + bool mem64; QLIST_HEAD(, VFIOQuirk) quirks; } VFIOBAR; @@ -158,6 +175,7 @@ typedef struct VFIODevice { PCIHostDeviceAddress host; QLIST_ENTRY(VFIODevice) next; struct VFIOGroup *group; + EventNotifier err_notifier; uint32_t features; #define VFIO_FEATURE_ENABLE_VGA_BIT 0 #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT) @@ -165,6 +183,7 @@ typedef struct VFIODevice { uint8_t pm_cap; bool reset_works; bool has_vga; + bool pci_aer; } VFIODevice; typedef struct VFIOGroup { @@ -1097,251 +1116,315 @@ static const MemoryRegionOps vfio_vga_ops = { * Device specific quirks */ -#define PCI_VENDOR_ID_ATI 0x1002 +/* Is range1 fully contained within range2? */ +static bool vfio_range_contained(uint64_t first1, uint64_t len1, + uint64_t first2, uint64_t len2) { + return (first1 >= first2 && first1 + len1 <= first2 + len2); +} -/* - * Device 1002:68f9 (Advanced Micro Devices [AMD] nee ATI Cedar PRO [Radeon - * HD 5450/6350]) reports the upper byte of the physical address of the - * I/O port BAR4 through VGA register 0x3c3. The BAR is 256 bytes, so the - * lower byte is known to be zero. Probing for this quirk reads 0xff from - * port 0x3c3 on some devices so we store the physical address and replace - * reads with the virtual address any time it matches. XXX Research when - * to enable quirk. - */ -static uint64_t vfio_ati_3c3_quirk_read(void *opaque, - hwaddr addr, unsigned size) +static bool vfio_flags_enabled(uint8_t flags, uint8_t mask) +{ + return (mask && (flags & mask) == mask); +} + +static uint64_t vfio_generic_window_quirk_read(void *opaque, + hwaddr addr, unsigned size) { VFIOQuirk *quirk = opaque; VFIODevice *vdev = quirk->vdev; - PCIDevice *pdev = &vdev->pdev; - uint64_t data = vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], - addr + 0x3, size); + uint64_t data; + + if (vfio_flags_enabled(quirk->data.flags, quirk->data.read_flags) && + ranges_overlap(addr, size, + quirk->data.data_offset, quirk->data.data_size)) { + hwaddr offset = addr - quirk->data.data_offset; - if (data == quirk->data) { - data = pci_get_byte(pdev->config + PCI_BASE_ADDRESS_4 + 1); - DPRINTF("%s(0x3c3, 1) = 0x%"PRIx64"\n", __func__, data); + if (!vfio_range_contained(addr, size, quirk->data.data_offset, + quirk->data.data_size)) { + hw_error("%s: window data read not fully contained: %s\n", + __func__, memory_region_name(&quirk->mem)); + } + + data = vfio_pci_read_config(&vdev->pdev, + quirk->data.address_val + offset, size); + + DPRINTF("%s read(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx", %d) = 0x%" + PRIx64"\n", memory_region_name(&quirk->mem), vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function, + quirk->data.bar, addr, size, data); + } else { + data = vfio_bar_read(&vdev->bars[quirk->data.bar], + addr + quirk->data.base_offset, size); } return data; } -static const MemoryRegionOps vfio_ati_3c3_quirk = { - .read = vfio_ati_3c3_quirk_read, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static void vfio_vga_probe_ati_3c3_quirk(VFIODevice *vdev) +static void vfio_generic_window_quirk_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) { - PCIDevice *pdev = &vdev->pdev; - off_t physoffset = vdev->config_offset + PCI_BASE_ADDRESS_4; - uint32_t physbar; - VFIOQuirk *quirk; + VFIOQuirk *quirk = opaque; + VFIODevice *vdev = quirk->vdev; - if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI || - vdev->bars[4].size < 256) { - return; - } + if (ranges_overlap(addr, size, + quirk->data.address_offset, quirk->data.address_size)) { - /* Get I/O port BAR physical address */ - if (pread(vdev->fd, &physbar, 4, physoffset) != 4) { - error_report("vfio: probe failed for ATI/AMD 0x3c3 quirk on device " - "%04x:%02x:%02x.%x", vdev->host.domain, - vdev->host.bus, vdev->host.slot, vdev->host.function); - return; + if (addr != quirk->data.address_offset) { + hw_error("%s: offset write into address window: %s\n", + __func__, memory_region_name(&quirk->mem)); + } + + if ((data & ~quirk->data.address_mask) == quirk->data.address_match) { + quirk->data.flags |= quirk->data.write_flags | + quirk->data.read_flags; + quirk->data.address_val = data & quirk->data.address_mask; + } else { + quirk->data.flags &= ~(quirk->data.write_flags | + quirk->data.read_flags); + } } - quirk = g_malloc0(sizeof(*quirk)); - quirk->vdev = vdev; - quirk->data = (physbar >> 8) & 0xff; + if (vfio_flags_enabled(quirk->data.flags, quirk->data.write_flags) && + ranges_overlap(addr, size, + quirk->data.data_offset, quirk->data.data_size)) { + hwaddr offset = addr - quirk->data.data_offset; - memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_ati_3c3_quirk, quirk, - "vfio-ati-3c3-quirk", 1); - memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, 3, - &quirk->mem); + if (!vfio_range_contained(addr, size, quirk->data.data_offset, + quirk->data.data_size)) { + hw_error("%s: window data write not fully contained: %s\n", + __func__, memory_region_name(&quirk->mem)); + } - QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks, - quirk, next); + vfio_pci_write_config(&vdev->pdev, + quirk->data.address_val + offset, data, size); + DPRINTF("%s write(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx", 0x%" + PRIx64", %d)\n", memory_region_name(&quirk->mem), + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, quirk->data.bar, addr, data, size); + return; + } - DPRINTF("Enabled ATI/AMD quirk 0x3c3 for device %04x:%02x:%02x.%x\n", - vdev->host.domain, vdev->host.bus, vdev->host.slot, - vdev->host.function); + vfio_bar_write(&vdev->bars[quirk->data.bar], + addr + quirk->data.base_offset, data, size); } -/* - * Device 1002:68f9 (Advanced Micro Devices [AMD] nee ATI Cedar PRO [Radeon - * HD 5450/6350]) reports the physical address of MMIO BAR0 through a - * write/read operation on I/O port BAR4. When uint32_t 0x4010 is written - * to offset 0x0, the subsequent read from offset 0x4 returns the contents - * of BAR0. Test for this quirk on all ATI/AMD devices. XXX - Note that - * 0x10 is the offset of BAR0 in config sapce, is this a window to all of - * config space? - */ -static uint64_t vfio_ati_4010_quirk_read(void *opaque, - hwaddr addr, unsigned size) +static const MemoryRegionOps vfio_generic_window_quirk = { + .read = vfio_generic_window_quirk_read, + .write = vfio_generic_window_quirk_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static uint64_t vfio_generic_quirk_read(void *opaque, + hwaddr addr, unsigned size) { VFIOQuirk *quirk = opaque; VFIODevice *vdev = quirk->vdev; - PCIDevice *pdev = &vdev->pdev; - uint64_t data = vfio_bar_read(&vdev->bars[4], addr, size); + hwaddr base = quirk->data.address_match & TARGET_PAGE_MASK; + hwaddr offset = quirk->data.address_match & ~TARGET_PAGE_MASK; + uint64_t data; - if (addr == 4 && size == 4 && quirk->data) { - data = pci_get_long(pdev->config + PCI_BASE_ADDRESS_0); - DPRINTF("%s(BAR4+0x4) = 0x%"PRIx64"\n", __func__, data); - } + if (vfio_flags_enabled(quirk->data.flags, quirk->data.read_flags) && + ranges_overlap(addr, size, offset, quirk->data.address_mask + 1)) { + if (!vfio_range_contained(addr, size, offset, + quirk->data.address_mask + 1)) { + hw_error("%s: read not fully contained: %s\n", + __func__, memory_region_name(&quirk->mem)); + } - quirk->data = 0; + data = vfio_pci_read_config(&vdev->pdev, addr - offset, size); + + DPRINTF("%s read(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx", %d) = 0x%" + PRIx64"\n", memory_region_name(&quirk->mem), vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function, + quirk->data.bar, addr + base, size, data); + } else { + data = vfio_bar_read(&vdev->bars[quirk->data.bar], addr + base, size); + } return data; } -static void vfio_ati_4010_quirk_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) +static void vfio_generic_quirk_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) { VFIOQuirk *quirk = opaque; VFIODevice *vdev = quirk->vdev; + hwaddr base = quirk->data.address_match & TARGET_PAGE_MASK; + hwaddr offset = quirk->data.address_match & ~TARGET_PAGE_MASK; + + if (vfio_flags_enabled(quirk->data.flags, quirk->data.write_flags) && + ranges_overlap(addr, size, offset, quirk->data.address_mask + 1)) { + if (!vfio_range_contained(addr, size, offset, + quirk->data.address_mask + 1)) { + hw_error("%s: write not fully contained: %s\n", + __func__, memory_region_name(&quirk->mem)); + } + + vfio_pci_write_config(&vdev->pdev, addr - offset, data, size); + + DPRINTF("%s write(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx", 0x%" + PRIx64", %d)\n", memory_region_name(&quirk->mem), + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, quirk->data.bar, addr + base, data, size); + } else { + vfio_bar_write(&vdev->bars[quirk->data.bar], addr + base, data, size); + } +} - vfio_bar_write(&vdev->bars[4], addr, data, size); +static const MemoryRegionOps vfio_generic_quirk = { + .read = vfio_generic_quirk_read, + .write = vfio_generic_quirk_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +#define PCI_VENDOR_ID_ATI 0x1002 + +/* + * Radeon HD cards (HD5450 & HD7850) report the upper byte of the I/O port BAR + * through VGA register 0x3c3. On newer cards, the I/O port BAR is always + * BAR4 (older cards like the X550 used BAR1, but we don't care to support + * those). Note that on bare metal, a read of 0x3c3 doesn't always return the + * I/O port BAR address. Originally this was coded to return the virtual BAR + * address only if the physical register read returns the actual BAR address, + * but users have reported greater success if we return the virtual address + * unconditionally. + */ +static uint64_t vfio_ati_3c3_quirk_read(void *opaque, + hwaddr addr, unsigned size) +{ + VFIOQuirk *quirk = opaque; + VFIODevice *vdev = quirk->vdev; + uint64_t data = vfio_pci_read_config(&vdev->pdev, + PCI_BASE_ADDRESS_0 + (4 * 4) + 1, + size); + DPRINTF("%s(0x3c3, 1) = 0x%"PRIx64"\n", __func__, data); - quirk->data = (addr == 0 && size == 4 && data == 0x4010) ? 1 : 0; + return data; } -static const MemoryRegionOps vfio_ati_4010_quirk = { - .read = vfio_ati_4010_quirk_read, - .write = vfio_ati_4010_quirk_write, +static const MemoryRegionOps vfio_ati_3c3_quirk = { + .read = vfio_ati_3c3_quirk_read, .endianness = DEVICE_LITTLE_ENDIAN, }; -static void vfio_probe_ati_4010_quirk(VFIODevice *vdev, int nr) +static void vfio_vga_probe_ati_3c3_quirk(VFIODevice *vdev) { PCIDevice *pdev = &vdev->pdev; - off_t physoffset = vdev->config_offset + PCI_BASE_ADDRESS_0; - uint32_t physbar0; - uint64_t data; VFIOQuirk *quirk; - if (!vdev->has_vga || nr != 4 || !vdev->bars[0].size || - pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) { + if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) { return; } - /* Get I/O port BAR physical address */ - if (pread(vdev->fd, &physbar0, 4, physoffset) != 4) { - error_report("vfio: probe failed for ATI/AMD 0x4010 quirk on device " - "%04x:%02x:%02x.%x", vdev->host.domain, - vdev->host.bus, vdev->host.slot, vdev->host.function); - return; - } - - /* Write 0x4010 to I/O port BAR offset 0 */ - vfio_bar_write(&vdev->bars[4], 0, 0x4010, 4); - /* Read back result */ - data = vfio_bar_read(&vdev->bars[4], 4, 4); - - /* If the register matches the physical address of BAR0, we need a quirk */ - if (data != physbar0) { + /* + * As long as the BAR is >= 256 bytes it will be aligned such that the + * lower byte is always zero. Filter out anything else, if it exists. + */ + if (!vdev->bars[4].ioport || vdev->bars[4].size < 256) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->vdev = vdev; - memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_ati_4010_quirk, quirk, - "vfio-ati-4010-quirk", 8); - memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1); + memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_ati_3c3_quirk, quirk, + "vfio-ati-3c3-quirk", 1); + memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, + 3 /* offset 3 bytes from 0x3c0 */, &quirk->mem); - QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); + QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks, + quirk, next); - DPRINTF("Enabled ATI/AMD quirk 0x4010 for device %04x:%02x:%02x.%x\n", + DPRINTF("Enabled ATI/AMD quirk 0x3c3 BAR4for device %04x:%02x:%02x.%x\n", vdev->host.domain, vdev->host.bus, vdev->host.slot, vdev->host.function); } /* - * Device 1002:5b63 (Advanced Micro Devices [AMD] nee ATI RV370 [Radeon X550]) - * retrieves the upper half of the MMIO BAR0 physical address by writing - * 0xf10 to I/O port BAR1 offset 0 and reading the result from offset 6. - * XXX - 0x10 is the offset of BAR0 in PCI config space, this could provide - * full access to config space. Config space is little endian, so the data - * register probably starts at 0x4. + * Newer ATI/AMD devices, including HD5450 and HD7850, have a window to PCI + * config space through MMIO BAR2 at offset 0x4000. Nothing seems to access + * the MMIO space directly, but a window to this space is provided through + * I/O port BAR4. Offset 0x0 is the address register and offset 0x4 is the + * data register. When the address is programmed to a range of 0x4000-0x4fff + * PCI configuration space is available. Experimentation seems to indicate + * that only read-only access is provided, but we drop writes when the window + * is enabled to config space nonetheless. */ -static uint64_t vfio_ati_f10_quirk_read(void *opaque, - hwaddr addr, unsigned size) +static void vfio_probe_ati_bar4_window_quirk(VFIODevice *vdev, int nr) { - VFIOQuirk *quirk = opaque; - VFIODevice *vdev = quirk->vdev; PCIDevice *pdev = &vdev->pdev; - uint64_t data = vfio_bar_read(&vdev->bars[1], addr, size); + VFIOQuirk *quirk; - if (addr == 6 && size == 2 && quirk->data) { - data = pci_get_word(pdev->config + PCI_BASE_ADDRESS_0 + 2); - DPRINTF("%s(BAR1+0x6) = 0x%"PRIx64"\n", __func__, data); + if (!vdev->has_vga || nr != 4 || + pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) { + return; } - quirk->data = 0; - - return data; -} - -static void vfio_ati_f10_quirk_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - VFIOQuirk *quirk = opaque; - VFIODevice *vdev = quirk->vdev; + quirk = g_malloc0(sizeof(*quirk)); + quirk->vdev = vdev; + quirk->data.address_size = 4; + quirk->data.data_offset = 4; + quirk->data.data_size = 4; + quirk->data.address_match = 0x4000; + quirk->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1; + quirk->data.bar = nr; + quirk->data.read_flags = quirk->data.write_flags = 1; + + memory_region_init_io(&quirk->mem, OBJECT(vdev), + &vfio_generic_window_quirk, quirk, + "vfio-ati-bar4-window-quirk", 8); + memory_region_add_subregion_overlap(&vdev->bars[nr].mem, + quirk->data.base_offset, &quirk->mem, 1); - vfio_bar_write(&vdev->bars[1], addr, data, size); + QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); - quirk->data = (addr == 0 && size == 4 && data == 0xf10) ? 1 : 0; + DPRINTF("Enabled ATI/AMD BAR4 window quirk for device %04x:%02x:%02x.%x\n", + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function); } -static const MemoryRegionOps vfio_ati_f10_quirk = { - .read = vfio_ati_f10_quirk_read, - .write = vfio_ati_f10_quirk_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static void vfio_probe_ati_f10_quirk(VFIODevice *vdev, int nr) +/* + * Trap the BAR2 MMIO window to config space as well. + */ +static void vfio_probe_ati_bar2_4000_quirk(VFIODevice *vdev, int nr) { PCIDevice *pdev = &vdev->pdev; - off_t physoffset = vdev->config_offset + PCI_BASE_ADDRESS_0; - uint32_t physbar0; - uint64_t data; VFIOQuirk *quirk; - if (!vdev->has_vga || nr != 1 || !vdev->bars[0].size || + /* Only enable on newer devices where BAR2 is 64bit */ + if (!vdev->has_vga || nr != 2 || !vdev->bars[2].mem64 || pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) { return; } - /* Get I/O port BAR physical address */ - if (pread(vdev->fd, &physbar0, 4, physoffset) != 4) { - error_report("vfio: probe failed for ATI/AMD 0xf10 quirk on device " - "%04x:%02x:%02x.%x", vdev->host.domain, - vdev->host.bus, vdev->host.slot, vdev->host.function); - return; - } - - vfio_bar_write(&vdev->bars[1], 0, 0xf10, 4); - data = vfio_bar_read(&vdev->bars[1], 0x6, 2); - - /* If the register matches the physical address of BAR0, we need a quirk */ - if (data != (le32_to_cpu(physbar0) >> 16)) { - return; - } - quirk = g_malloc0(sizeof(*quirk)); quirk->vdev = vdev; - - memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_ati_f10_quirk, quirk, - "vfio-ati-f10-quirk", 8); - memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1); + quirk->data.flags = quirk->data.read_flags = quirk->data.write_flags = 1; + quirk->data.address_match = 0x4000; + quirk->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1; + quirk->data.bar = nr; + + memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_generic_quirk, quirk, + "vfio-ati-bar2-4000-quirk", + TARGET_PAGE_ALIGN(quirk->data.address_mask + 1)); + memory_region_add_subregion_overlap(&vdev->bars[nr].mem, + quirk->data.address_match & TARGET_PAGE_MASK, + &quirk->mem, 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); - DPRINTF("Enabled ATI/AMD quirk 0xf10 for device %04x:%02x:%02x.%x\n", + DPRINTF("Enabled ATI/AMD BAR2 0x4000 quirk for device %04x:%02x:%02x.%x\n", vdev->host.domain, vdev->host.bus, vdev->host.slot, vdev->host.function); } +/* + * Older ATI/AMD cards like the X550 have a similar window to that above. + * I/O port BAR1 provides a window to a mirror of PCI config space located + * in BAR2 at offset 0xf00. We don't care to support such older cards, but + * note it for future reference. + */ + #define PCI_VENDOR_ID_NVIDIA 0x10de /* @@ -1360,7 +1443,7 @@ static void vfio_probe_ati_f10_quirk(VFIODevice *vdev, int nr) * that use the I/O port BAR5 window but it doesn't hurt to leave it. */ enum { - NV_3D0_NONE, + NV_3D0_NONE = 0, NV_3D0_SELECT, NV_3D0_WINDOW, NV_3D0_READ, @@ -1374,14 +1457,14 @@ static uint64_t vfio_nvidia_3d0_quirk_read(void *opaque, VFIODevice *vdev = quirk->vdev; PCIDevice *pdev = &vdev->pdev; uint64_t data = vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], - addr + 0x10, size); + addr + quirk->data.base_offset, size); - if (quirk->data == NV_3D0_READ && addr == 0) { - data = vfio_pci_read_config(pdev, quirk->data2, size); + if (quirk->data.flags == NV_3D0_READ && addr == quirk->data.data_offset) { + data = vfio_pci_read_config(pdev, quirk->data.address_val, size); DPRINTF("%s(0x3d0, %d) = 0x%"PRIx64"\n", __func__, size, data); } - quirk->data = NV_3D0_NONE; + quirk->data.flags = NV_3D0_NONE; return data; } @@ -1393,43 +1476,42 @@ static void vfio_nvidia_3d0_quirk_write(void *opaque, hwaddr addr, VFIODevice *vdev = quirk->vdev; PCIDevice *pdev = &vdev->pdev; - switch (quirk->data) { + switch (quirk->data.flags) { case NV_3D0_NONE: - if (addr == 4 && data == 0x338) { - quirk->data = NV_3D0_SELECT; + if (addr == quirk->data.address_offset && data == 0x338) { + quirk->data.flags = NV_3D0_SELECT; } break; case NV_3D0_SELECT: - quirk->data = NV_3D0_NONE; - if (addr == 0 && (data & ~0xff) == 0x1800) { - quirk->data = NV_3D0_WINDOW; - quirk->data2 = data & 0xff; + quirk->data.flags = NV_3D0_NONE; + if (addr == quirk->data.data_offset && + (data & ~quirk->data.address_mask) == quirk->data.address_match) { + quirk->data.flags = NV_3D0_WINDOW; + quirk->data.address_val = data & quirk->data.address_mask; } break; case NV_3D0_WINDOW: - quirk->data = NV_3D0_NONE; - if (addr == 4) { + quirk->data.flags = NV_3D0_NONE; + if (addr == quirk->data.address_offset) { if (data == 0x538) { - quirk->data = NV_3D0_READ; + quirk->data.flags = NV_3D0_READ; } else if (data == 0x738) { - quirk->data = NV_3D0_WRITE; + quirk->data.flags = NV_3D0_WRITE; } } break; case NV_3D0_WRITE: - quirk->data = NV_3D0_NONE; - if (addr == 0) { - vfio_pci_write_config(pdev, quirk->data2, data, size); + quirk->data.flags = NV_3D0_NONE; + if (addr == quirk->data.data_offset) { + vfio_pci_write_config(pdev, quirk->data.address_val, data, size); DPRINTF("%s(0x3d0, 0x%"PRIx64", %d)\n", __func__, data, size); return; } break; - default: - quirk->data = NV_3D0_NONE; } vfio_vga_write(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], - addr + 0x10, data, size); + addr + quirk->data.base_offset, data, size); } static const MemoryRegionOps vfio_nvidia_3d0_quirk = { @@ -1450,11 +1532,18 @@ static void vfio_vga_probe_nvidia_3d0_quirk(VFIODevice *vdev) quirk = g_malloc0(sizeof(*quirk)); quirk->vdev = vdev; - - memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_3d0_quirk, quirk, - "vfio-nvidia-3d0-quirk", 6); + quirk->data.base_offset = 0x10; + quirk->data.address_offset = 4; + quirk->data.address_size = 2; + quirk->data.address_match = 0x1800; + quirk->data.address_mask = PCI_CONFIG_SPACE_SIZE - 1; + quirk->data.data_offset = 0; + quirk->data.data_size = 4; + + memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_3d0_quirk, + quirk, "vfio-nvidia-3d0-quirk", 6); memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, - 0x10, &quirk->mem); + quirk->data.base_offset, &quirk->mem); QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks, quirk, next); @@ -1478,76 +1567,46 @@ enum { NV_BAR5_VALID = 0x7, }; -static uint64_t vfio_nvidia_bar5_window_quirk_read(void *opaque, - hwaddr addr, unsigned size) -{ - VFIOQuirk *quirk = opaque; - VFIODevice *vdev = quirk->vdev; - uint64_t data = vfio_bar_read(&vdev->bars[5], addr, size); - - if (addr == 0xc && quirk->data == NV_BAR5_VALID) { - data = vfio_pci_read_config(&vdev->pdev, quirk->data2, size); - DPRINTF("%s(%04x:%02x:%02x.%x:BAR5+0x%"HWADDR_PRIx", %d) = 0x%" - PRIx64"\n", __func__, vdev->host.domain, vdev->host.bus, - vdev->host.slot, vdev->host.function, addr, size, data); - } - - return data; -} - static void vfio_nvidia_bar5_window_quirk_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { VFIOQuirk *quirk = opaque; - VFIODevice *vdev = quirk->vdev; - /* - * Use quirk->data to track enables and quirk->data2 for the offset - */ switch (addr) { case 0x0: if (data & 0x1) { - quirk->data |= NV_BAR5_MASTER; + quirk->data.flags |= NV_BAR5_MASTER; } else { - quirk->data &= ~NV_BAR5_MASTER; + quirk->data.flags &= ~NV_BAR5_MASTER; } break; case 0x4: if (data & 0x1) { - quirk->data |= NV_BAR5_ENABLE; + quirk->data.flags |= NV_BAR5_ENABLE; } else { - quirk->data &= ~NV_BAR5_ENABLE; + quirk->data.flags &= ~NV_BAR5_ENABLE; } break; case 0x8: - if (quirk->data & NV_BAR5_MASTER) { + if (quirk->data.flags & NV_BAR5_MASTER) { if ((data & ~0xfff) == 0x88000) { - quirk->data |= NV_BAR5_ADDRESS; - quirk->data2 = data & 0xfff; + quirk->data.flags |= NV_BAR5_ADDRESS; + quirk->data.address_val = data & 0xfff; } else if ((data & ~0xff) == 0x1800) { - quirk->data |= NV_BAR5_ADDRESS; - quirk->data2 = data & 0xff; + quirk->data.flags |= NV_BAR5_ADDRESS; + quirk->data.address_val = data & 0xff; } else { - quirk->data &= ~NV_BAR5_ADDRESS; + quirk->data.flags &= ~NV_BAR5_ADDRESS; } } break; - case 0xc: - if (quirk->data == NV_BAR5_VALID) { - vfio_pci_write_config(&vdev->pdev, quirk->data2, data, size); - DPRINTF("%s(%04x:%02x:%02x.%x:BAR5+0x%"HWADDR_PRIx", 0x%" - PRIx64", %d)\n", __func__, vdev->host.domain, - vdev->host.bus, vdev->host.slot, vdev->host.function, - addr, data, size); - return; - } } - vfio_bar_write(&vdev->bars[5], addr, data, size); + vfio_generic_window_quirk_write(opaque, addr, data, size); } static const MemoryRegionOps vfio_nvidia_bar5_window_quirk = { - .read = vfio_nvidia_bar5_window_quirk_read, + .read = vfio_generic_window_quirk_read, .write = vfio_nvidia_bar5_window_quirk_write, .valid.min_access_size = 4, .endianness = DEVICE_LITTLE_ENDIAN, @@ -1565,8 +1624,15 @@ static void vfio_probe_nvidia_bar5_window_quirk(VFIODevice *vdev, int nr) quirk = g_malloc0(sizeof(*quirk)); quirk->vdev = vdev; - - memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_bar5_window_quirk, quirk, + quirk->data.read_flags = quirk->data.write_flags = NV_BAR5_VALID; + quirk->data.address_offset = 0x8; + quirk->data.address_size = 0; /* actually 4, but avoids generic code */ + quirk->data.data_offset = 0xc; + quirk->data.data_size = 4; + quirk->data.bar = nr; + + memory_region_init_io(&quirk->mem, OBJECT(vdev), + &vfio_nvidia_bar5_window_quirk, quirk, "vfio-nvidia-bar5-window-quirk", 16); memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1); @@ -1586,51 +1652,6 @@ static void vfio_probe_nvidia_bar5_window_quirk(VFIODevice *vdev, int nr) * * Here's offset 0x88000... */ -static uint64_t vfio_nvidia_bar0_88000_quirk_read(void *opaque, - hwaddr addr, unsigned size) -{ - VFIOQuirk *quirk = opaque; - VFIODevice *vdev = quirk->vdev; - hwaddr base = 0x88000 & TARGET_PAGE_MASK; - hwaddr offset = 0x88000 & ~TARGET_PAGE_MASK; - uint64_t data = vfio_bar_read(&vdev->bars[0], addr + base, size); - - if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) { - data = vfio_pci_read_config(&vdev->pdev, addr - offset, size); - - DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", %d) = 0x%" - PRIx64"\n", __func__, vdev->host.domain, vdev->host.bus, - vdev->host.slot, vdev->host.function, addr + base, size, data); - } - - return data; -} - -static void vfio_nvidia_bar0_88000_quirk_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - VFIOQuirk *quirk = opaque; - VFIODevice *vdev = quirk->vdev; - hwaddr base = 0x88000 & TARGET_PAGE_MASK; - hwaddr offset = 0x88000 & ~TARGET_PAGE_MASK; - - if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) { - vfio_pci_write_config(&vdev->pdev, addr - offset, data, size); - - DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", 0x%" - PRIx64", %d)\n", __func__, vdev->host.domain, vdev->host.bus, - vdev->host.slot, vdev->host.function, addr + base, data, size); - } else { - vfio_bar_write(&vdev->bars[0], addr + base, data, size); - } -} - -static const MemoryRegionOps vfio_nvidia_bar0_88000_quirk = { - .read = vfio_nvidia_bar0_88000_quirk_read, - .write = vfio_nvidia_bar0_88000_quirk_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - static void vfio_probe_nvidia_bar0_88000_quirk(VFIODevice *vdev, int nr) { PCIDevice *pdev = &vdev->pdev; @@ -1643,13 +1664,17 @@ static void vfio_probe_nvidia_bar0_88000_quirk(VFIODevice *vdev, int nr) quirk = g_malloc0(sizeof(*quirk)); quirk->vdev = vdev; - - memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_bar0_88000_quirk, quirk, - "vfio-nvidia-bar0-88000-quirk", - TARGET_PAGE_ALIGN(PCIE_CONFIG_SPACE_SIZE)); + quirk->data.flags = quirk->data.read_flags = quirk->data.write_flags = 1; + quirk->data.address_match = 0x88000; + quirk->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1; + quirk->data.bar = nr; + + memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_generic_quirk, + quirk, "vfio-nvidia-bar0-88000-quirk", + TARGET_PAGE_ALIGN(quirk->data.address_mask + 1)); memory_region_add_subregion_overlap(&vdev->bars[nr].mem, - 0x88000 & TARGET_PAGE_MASK, - &quirk->mem, 1); + quirk->data.address_match & TARGET_PAGE_MASK, + &quirk->mem, 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); @@ -1661,51 +1686,6 @@ static void vfio_probe_nvidia_bar0_88000_quirk(VFIODevice *vdev, int nr) /* * And here's the same for BAR0 offset 0x1800... */ -static uint64_t vfio_nvidia_bar0_1800_quirk_read(void *opaque, - hwaddr addr, unsigned size) -{ - VFIOQuirk *quirk = opaque; - VFIODevice *vdev = quirk->vdev; - hwaddr base = 0x1800 & TARGET_PAGE_MASK; - hwaddr offset = 0x1800 & ~TARGET_PAGE_MASK; - uint64_t data = vfio_bar_read(&vdev->bars[0], addr + base, size); - - if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) { - data = vfio_pci_read_config(&vdev->pdev, addr - offset, size); - - DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", %d) = 0x%" - PRIx64"\n", __func__, vdev->host.domain, vdev->host.bus, - vdev->host.slot, vdev->host.function, addr + base, size, data); - } - - return data; -} - -static void vfio_nvidia_bar0_1800_quirk_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - VFIOQuirk *quirk = opaque; - VFIODevice *vdev = quirk->vdev; - hwaddr base = 0x1800 & TARGET_PAGE_MASK; - hwaddr offset = 0x1800 & ~TARGET_PAGE_MASK; - - if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) { - vfio_pci_write_config(&vdev->pdev, addr - offset, data, size); - - DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", 0x%" - PRIx64", %d)\n", __func__, vdev->host.domain, vdev->host.bus, - vdev->host.slot, vdev->host.function, addr + base, data, size); - } else { - vfio_bar_write(&vdev->bars[0], addr + base, data, size); - } -} - -static const MemoryRegionOps vfio_nvidia_bar0_1800_quirk = { - .read = vfio_nvidia_bar0_1800_quirk_read, - .write = vfio_nvidia_bar0_1800_quirk_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - static void vfio_probe_nvidia_bar0_1800_quirk(VFIODevice *vdev, int nr) { PCIDevice *pdev = &vdev->pdev; @@ -1722,13 +1702,17 @@ static void vfio_probe_nvidia_bar0_1800_quirk(VFIODevice *vdev, int nr) quirk = g_malloc0(sizeof(*quirk)); quirk->vdev = vdev; + quirk->data.flags = quirk->data.read_flags = quirk->data.write_flags = 1; + quirk->data.address_match = 0x1800; + quirk->data.address_mask = PCI_CONFIG_SPACE_SIZE - 1; + quirk->data.bar = nr; - memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_bar0_1800_quirk, quirk, + memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_generic_quirk, quirk, "vfio-nvidia-bar0-1800-quirk", - TARGET_PAGE_ALIGN(PCI_CONFIG_SPACE_SIZE)); + TARGET_PAGE_ALIGN(quirk->data.address_mask + 1)); memory_region_add_subregion_overlap(&vdev->bars[nr].mem, - 0x1800 & TARGET_PAGE_MASK, - &quirk->mem, 1); + quirk->data.address_match & TARGET_PAGE_MASK, + &quirk->mem, 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); @@ -1768,8 +1752,8 @@ static void vfio_vga_quirk_teardown(VFIODevice *vdev) static void vfio_bar_quirk_setup(VFIODevice *vdev, int nr) { - vfio_probe_ati_4010_quirk(vdev, nr); - vfio_probe_ati_f10_quirk(vdev, nr); + vfio_probe_ati_bar4_window_quirk(vdev, nr); + vfio_probe_ati_bar2_4000_quirk(vdev, nr); vfio_probe_nvidia_bar5_window_quirk(vdev, nr); vfio_probe_nvidia_bar0_88000_quirk(vdev, nr); vfio_probe_nvidia_bar0_1800_quirk(vdev, nr); @@ -2270,11 +2254,14 @@ static void vfio_map_bar(VFIODevice *vdev, int nr) } pci_bar = le32_to_cpu(pci_bar); - type = pci_bar & (pci_bar & PCI_BASE_ADDRESS_SPACE_IO ? - ~PCI_BASE_ADDRESS_IO_MASK : ~PCI_BASE_ADDRESS_MEM_MASK); + bar->ioport = (pci_bar & PCI_BASE_ADDRESS_SPACE_IO); + bar->mem64 = bar->ioport ? 0 : (pci_bar & PCI_BASE_ADDRESS_MEM_TYPE_64); + type = pci_bar & (bar->ioport ? ~PCI_BASE_ADDRESS_IO_MASK : + ~PCI_BASE_ADDRESS_MEM_MASK); /* A "slow" read/write mapping underlies all BARs */ - memory_region_init_io(&bar->mem, OBJECT(vdev), &vfio_bar_ops, bar, name, size); + memory_region_init_io(&bar->mem, OBJECT(vdev), &vfio_bar_ops, + bar, name, size); pci_register_bar(&vdev->pdev, nr, type, &bar->mem); /* @@ -2781,6 +2768,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev) { struct vfio_device_info dev_info = { .argsz = sizeof(dev_info) }; struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) }; + struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) }; int ret, i; ret = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, name); @@ -2924,6 +2912,19 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev) vdev->has_vga = true; } + irq_info.index = VFIO_PCI_ERR_IRQ_INDEX; + + ret = ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info); + if (ret) { + /* This can fail for an old kernel or legacy PCI dev */ + DPRINTF("VFIO_DEVICE_GET_IRQ_INFO failure ret=%d\n", ret); + ret = 0; + } else if (irq_info.count == 1) { + vdev->pci_aer = true; + } else { + error_report("vfio: Warning: " + "Could not enable error recovery for the device\n"); + } error: if (ret) { @@ -2946,6 +2947,113 @@ static void vfio_put_device(VFIODevice *vdev) } } +static void vfio_err_notifier_handler(void *opaque) +{ + VFIODevice *vdev = opaque; + + if (!event_notifier_test_and_clear(&vdev->err_notifier)) { + return; + } + + /* + * TBD. Retrieve the error details and decide what action + * needs to be taken. One of the actions could be to pass + * the error to the guest and have the guest driver recover + * from the error. This requires that PCIe capabilities be + * exposed to the guest. For now, we just terminate the + * guest to contain the error. + */ + + error_report("%s (%04x:%02x:%02x.%x)" + "Unrecoverable error detected...\n" + "Please collect any data possible and then kill the guest", + __func__, vdev->host.domain, vdev->host.bus, + vdev->host.slot, vdev->host.function); + + vm_stop(RUN_STATE_IO_ERROR); +} + +/* + * Registers error notifier for devices supporting error recovery. + * If we encounter a failure in this function, we report an error + * and continue after disabling error recovery support for the + * device. + */ +static void vfio_register_err_notifier(VFIODevice *vdev) +{ + int ret; + int argsz; + struct vfio_irq_set *irq_set; + int32_t *pfd; + + if (!vdev->pci_aer) { + return; + } + + if (event_notifier_init(&vdev->err_notifier, 0)) { + error_report("vfio: Warning: " + "Unable to init event notifier for error detection\n"); + vdev->pci_aer = false; + return; + } + + argsz = sizeof(*irq_set) + sizeof(*pfd); + + irq_set = g_malloc0(argsz); + irq_set->argsz = argsz; + irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | + VFIO_IRQ_SET_ACTION_TRIGGER; + irq_set->index = VFIO_PCI_ERR_IRQ_INDEX; + irq_set->start = 0; + irq_set->count = 1; + pfd = (int32_t *)&irq_set->data; + + *pfd = event_notifier_get_fd(&vdev->err_notifier); + qemu_set_fd_handler(*pfd, vfio_err_notifier_handler, NULL, vdev); + + ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); + if (ret) { + error_report("vfio: Failed to set up error notification\n"); + qemu_set_fd_handler(*pfd, NULL, NULL, vdev); + event_notifier_cleanup(&vdev->err_notifier); + vdev->pci_aer = false; + } + g_free(irq_set); +} + +static void vfio_unregister_err_notifier(VFIODevice *vdev) +{ + int argsz; + struct vfio_irq_set *irq_set; + int32_t *pfd; + int ret; + + if (!vdev->pci_aer) { + return; + } + + argsz = sizeof(*irq_set) + sizeof(*pfd); + + irq_set = g_malloc0(argsz); + irq_set->argsz = argsz; + irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | + VFIO_IRQ_SET_ACTION_TRIGGER; + irq_set->index = VFIO_PCI_ERR_IRQ_INDEX; + irq_set->start = 0; + irq_set->count = 1; + pfd = (int32_t *)&irq_set->data; + *pfd = -1; + + ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); + if (ret) { + error_report("vfio: Failed to de-assign error fd: %d\n", ret); + } + g_free(irq_set); + qemu_set_fd_handler(event_notifier_get_fd(&vdev->err_notifier), + NULL, NULL, vdev); + event_notifier_cleanup(&vdev->err_notifier); +} + static int vfio_initfn(PCIDevice *pdev) { VFIODevice *pvdev, *vdev = DO_UPCAST(VFIODevice, pdev, pdev); @@ -3078,6 +3186,7 @@ static int vfio_initfn(PCIDevice *pdev) } add_boot_device_path(vdev->bootindex, &pdev->qdev, NULL); + vfio_register_err_notifier(vdev); return 0; @@ -3097,6 +3206,7 @@ static void vfio_exitfn(PCIDevice *pdev) VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); VFIOGroup *group = vdev->group; + vfio_unregister_err_notifier(vdev); pci_device_set_intx_routing_notifier(&vdev->pdev, NULL); vfio_disable_interrupts(vdev); if (vdev->intx.mmap_timer) { diff --git a/hw/net/milkymist-minimac2.c b/hw/net/milkymist-minimac2.c index 2ef4ac3299..becd26c5d5 100644 --- a/hw/net/milkymist-minimac2.c +++ b/hw/net/milkymist-minimac2.c @@ -355,7 +355,7 @@ minimac2_write(void *opaque, hwaddr addr, uint64_t value, { MilkymistMinimac2State *s = opaque; - trace_milkymist_minimac2_memory_read(addr, value); + trace_milkymist_minimac2_memory_write(addr, value); addr >>= 2; switch (addr) { diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 1ea95564a5..679f50c33a 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -21,6 +21,8 @@ #include "hw/virtio/virtio-net.h" #include "net/vhost_net.h" #include "hw/virtio/virtio-bus.h" +#include "qapi/qmp/qjson.h" +#include "monitor/monitor.h" #define VIRTIO_NET_VM_VERSION 11 @@ -192,6 +194,105 @@ static void virtio_net_set_link_status(NetClientState *nc) virtio_net_set_status(vdev, vdev->status); } +static void rxfilter_notify(NetClientState *nc) +{ + QObject *event_data; + VirtIONet *n = qemu_get_nic_opaque(nc); + + if (nc->rxfilter_notify_enabled) { + if (n->netclient_name) { + event_data = qobject_from_jsonf("{ 'name': %s, 'path': %s }", + n->netclient_name, + object_get_canonical_path(OBJECT(n->qdev))); + } else { + event_data = qobject_from_jsonf("{ 'path': %s }", + object_get_canonical_path(OBJECT(n->qdev))); + } + monitor_protocol_event(QEVENT_NIC_RX_FILTER_CHANGED, event_data); + qobject_decref(event_data); + + /* disable event notification to avoid events flooding */ + nc->rxfilter_notify_enabled = 0; + } +} + +static char *mac_strdup_printf(const uint8_t *mac) +{ + return g_strdup_printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", mac[0], + mac[1], mac[2], mac[3], mac[4], mac[5]); +} + +static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc) +{ + VirtIONet *n = qemu_get_nic_opaque(nc); + RxFilterInfo *info; + strList *str_list, *entry; + intList *int_list, *int_entry; + int i, j; + + info = g_malloc0(sizeof(*info)); + info->name = g_strdup(nc->name); + info->promiscuous = n->promisc; + + if (n->nouni) { + info->unicast = RX_STATE_NONE; + } else if (n->alluni) { + info->unicast = RX_STATE_ALL; + } else { + info->unicast = RX_STATE_NORMAL; + } + + if (n->nomulti) { + info->multicast = RX_STATE_NONE; + } else if (n->allmulti) { + info->multicast = RX_STATE_ALL; + } else { + info->multicast = RX_STATE_NORMAL; + } + + info->broadcast_allowed = n->nobcast; + info->multicast_overflow = n->mac_table.multi_overflow; + info->unicast_overflow = n->mac_table.uni_overflow; + + info->main_mac = mac_strdup_printf(n->mac); + + str_list = NULL; + for (i = 0; i < n->mac_table.first_multi; i++) { + entry = g_malloc0(sizeof(*entry)); + entry->value = mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN); + entry->next = str_list; + str_list = entry; + } + info->unicast_table = str_list; + + str_list = NULL; + for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) { + entry = g_malloc0(sizeof(*entry)); + entry->value = mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN); + entry->next = str_list; + str_list = entry; + } + info->multicast_table = str_list; + + int_list = NULL; + for (i = 0; i < MAX_VLAN >> 5; i++) { + for (j = 0; n->vlans[i] && j < 0x1f; j++) { + if (n->vlans[i] & (1U << j)) { + int_entry = g_malloc0(sizeof(*int_entry)); + int_entry->value = (i << 5) + j; + int_entry->next = int_list; + int_list = int_entry; + } + } + } + info->vlan_table = int_list; + + /* enable event notification after query */ + nc->rxfilter_notify_enabled = 1; + + return info; +} + static void virtio_net_reset(VirtIODevice *vdev) { VirtIONet *n = VIRTIO_NET(vdev); @@ -420,6 +521,7 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, { uint8_t on; size_t s; + NetClientState *nc = qemu_get_queue(n->nic); s = iov_to_buf(iov, iov_cnt, 0, &on, sizeof(on)); if (s != sizeof(on)) { @@ -442,6 +544,8 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, return VIRTIO_NET_ERR; } + rxfilter_notify(nc); + return VIRTIO_NET_OK; } @@ -487,6 +591,7 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, { struct virtio_net_ctrl_mac mac_data; size_t s; + NetClientState *nc = qemu_get_queue(n->nic); if (cmd == VIRTIO_NET_CTRL_MAC_ADDR_SET) { if (iov_size(iov, iov_cnt) != sizeof(n->mac)) { @@ -495,6 +600,8 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, s = iov_to_buf(iov, iov_cnt, 0, &n->mac, sizeof(n->mac)); assert(s == sizeof(n->mac)); qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); + rxfilter_notify(nc); + return VIRTIO_NET_OK; } @@ -512,19 +619,19 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, sizeof(mac_data.entries)); mac_data.entries = ldl_p(&mac_data.entries); if (s != sizeof(mac_data.entries)) { - return VIRTIO_NET_ERR; + goto error; } iov_discard_front(&iov, &iov_cnt, s); if (mac_data.entries * ETH_ALEN > iov_size(iov, iov_cnt)) { - return VIRTIO_NET_ERR; + goto error; } if (mac_data.entries <= MAC_TABLE_ENTRIES) { s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs, mac_data.entries * ETH_ALEN); if (s != mac_data.entries * ETH_ALEN) { - return VIRTIO_NET_ERR; + goto error; } n->mac_table.in_use += mac_data.entries; } else { @@ -539,27 +646,33 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, sizeof(mac_data.entries)); mac_data.entries = ldl_p(&mac_data.entries); if (s != sizeof(mac_data.entries)) { - return VIRTIO_NET_ERR; + goto error; } iov_discard_front(&iov, &iov_cnt, s); if (mac_data.entries * ETH_ALEN != iov_size(iov, iov_cnt)) { - return VIRTIO_NET_ERR; + goto error; } if (n->mac_table.in_use + mac_data.entries <= MAC_TABLE_ENTRIES) { s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs, mac_data.entries * ETH_ALEN); if (s != mac_data.entries * ETH_ALEN) { - return VIRTIO_NET_ERR; + goto error; } n->mac_table.in_use += mac_data.entries; } else { n->mac_table.multi_overflow = 1; } + rxfilter_notify(nc); + return VIRTIO_NET_OK; + +error: + rxfilter_notify(nc); + return VIRTIO_NET_ERR; } static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd, @@ -567,6 +680,7 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd, { uint16_t vid; size_t s; + NetClientState *nc = qemu_get_queue(n->nic); s = iov_to_buf(iov, iov_cnt, 0, &vid, sizeof(vid)); vid = lduw_p(&vid); @@ -584,6 +698,8 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd, else return VIRTIO_NET_ERR; + rxfilter_notify(nc); + return VIRTIO_NET_OK; } @@ -1312,6 +1428,7 @@ static NetClientInfo net_virtio_info = { .receive = virtio_net_receive, .cleanup = virtio_net_cleanup, .link_status_changed = virtio_net_set_link_status, + .query_rx_filter = virtio_net_query_rxfilter, }; static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) @@ -1373,6 +1490,7 @@ static int virtio_net_device_init(VirtIODevice *vdev) DeviceState *qdev = DEVICE(vdev); VirtIONet *n = VIRTIO_NET(vdev); + NetClientState *nc; virtio_init(VIRTIO_DEVICE(n), "virtio-net", VIRTIO_ID_NET, n->config_size); @@ -1439,6 +1557,9 @@ static int virtio_net_device_init(VirtIODevice *vdev) n->vlans = g_malloc0(MAX_VLAN >> 3); + nc = qemu_get_queue(n->nic); + nc->rxfilter_notify_enabled = 1; + n->qdev = qdev; register_savevm(qdev, "virtio-net", -1, VIRTIO_NET_VM_VERSION, virtio_net_save, virtio_net_load, n); diff --git a/hw/pci-bridge/i82801b11.c b/hw/pci-bridge/i82801b11.c index 5807a92d7f..b98bfb0664 100644 --- a/hw/pci-bridge/i82801b11.c +++ b/hw/pci-bridge/i82801b11.c @@ -69,7 +69,7 @@ static int i82801b11_bridge_initfn(PCIDevice *d) if (rc < 0) { goto err_bridge; } - pci_config_set_prog_interface(d->config, PCI_CLASS_BRDIGE_PCI_INF_SUB); + pci_config_set_prog_interface(d->config, PCI_CLASS_BRIDGE_PCI_INF_SUB); return 0; err_bridge: diff --git a/hw/pci/pci.c b/hw/pci/pci.c index dcc85ef0af..81cf5a958c 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -378,6 +378,7 @@ int pci_bus_num(PCIBus *s) static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) { PCIDevice *s = container_of(pv, PCIDevice, config); + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(s); uint8_t *config; int i; @@ -395,6 +396,10 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) memcpy(s->config, config, size); pci_update_mappings(s); + if (pc->is_bridge) { + PCIBridge *b = container_of(s, PCIBridge, dev); + pci_bridge_update_mappings(b); + } memory_region_set_enabled(&s->bus_master_enable_region, pci_get_word(s->config + PCI_COMMAND) diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index ecdeab0d58..02a396b01c 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -224,7 +224,7 @@ static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w) g_free(w); } -static void pci_bridge_update_mappings(PCIBridge *br) +void pci_bridge_update_mappings(PCIBridge *br) { PCIBridgeWindows *w = br->windows; diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index e0d6e83625..82cc151b17 100644 --- a/hw/virtio/dataplane/vring.c +++ b/hw/virtio/dataplane/vring.c @@ -39,8 +39,8 @@ bool vring_setup(Vring *vring, VirtIODevice *vdev, int n) vring_init(&vring->vr, virtio_queue_get_num(vdev, n), vring_ptr, 4096); - vring->last_avail_idx = 0; - vring->last_used_idx = 0; + vring->last_avail_idx = virtio_queue_get_last_avail_idx(vdev, n); + vring->last_used_idx = vring->vr.used->idx; vring->signalled_used = 0; vring->signalled_used_valid = false; @@ -49,8 +49,10 @@ bool vring_setup(Vring *vring, VirtIODevice *vdev, int n) return true; } -void vring_teardown(Vring *vring) +void vring_teardown(Vring *vring, VirtIODevice *vdev, int n) { + virtio_queue_set_last_avail_idx(vdev, n, vring->last_avail_idx); + hostmem_finalize(&vring->hostmem); } diff --git a/include/block/aio.h b/include/block/aio.h index 183679374f..cc77771c46 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -17,6 +17,7 @@ #include "qemu-common.h" #include "qemu/queue.h" #include "qemu/event_notifier.h" +#include "qemu/thread.h" typedef struct BlockDriverAIOCB BlockDriverAIOCB; typedef void BlockDriverCompletionFunc(void *opaque, int ret); @@ -53,6 +54,8 @@ typedef struct AioContext { */ int walking_handlers; + /* lock to protect between bh's adders and deleter */ + QemuMutex bh_lock; /* Anchor of the list of Bottom Halves belonging to the context */ struct QEMUBH *first_bh; @@ -127,6 +130,8 @@ void aio_notify(AioContext *ctx); * aio_bh_poll: Poll bottom halves for an AioContext. * * These are internal functions used by the QEMU main loop. + * And notice that multiple occurrences of aio_bh_poll cannot + * be called concurrently */ int aio_bh_poll(AioContext *ctx); @@ -163,6 +168,8 @@ void qemu_bh_cancel(QEMUBH *bh); * Deleting a bottom half frees the memory that was allocated for it by * qemu_bh_new. It also implies canceling the bottom half if it was * scheduled. + * This func is async. The bottom half will do the delete action at the finial + * end. * * @bh: The bottom half to be deleted. */ diff --git a/include/block/block.h b/include/block/block.h index b6b9014a9c..742fce5f7f 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -157,6 +157,8 @@ int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors); 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); int bdrv_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov); int bdrv_pread(BlockDriverState *bs, int64_t offset, void *buf, int count); diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 61ff154c7d..7fb97b08a2 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -231,6 +231,10 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); .driver = "Nehalem-" TYPE_X86_CPU,\ .property = "level",\ .value = stringify(2),\ + },{\ + .driver = "virtio-net-pci",\ + .property = "any_layout",\ + .value = "off",\ } #define PC_COMPAT_1_4 \ diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h index 1868f7aea8..1d8f9973c7 100644 --- a/include/hw/pci/pci_bridge.h +++ b/include/hw/pci/pci_bridge.h @@ -37,6 +37,7 @@ PCIBus *pci_bridge_get_sec_bus(PCIBridge *br); pcibus_t pci_bridge_get_base(const PCIDevice *bridge, uint8_t type); pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type); +void pci_bridge_update_mappings(PCIBridge *br); void pci_bridge_write_config(PCIDevice *d, uint32_t address, uint32_t val, int len); void pci_bridge_disable_base_limit(PCIDevice *dev); diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index 08f8161524..d7933bfd16 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -39,7 +39,7 @@ #define PCI_CLASS_BRIDGE_HOST 0x0600 #define PCI_CLASS_BRIDGE_ISA 0x0601 #define PCI_CLASS_BRIDGE_PCI 0x0604 -#define PCI_CLASS_BRDIGE_PCI_INF_SUB 0x01 +#define PCI_CLASS_BRIDGE_PCI_INF_SUB 0x01 #define PCI_CLASS_BRIDGE_OTHER 0x0680 #define PCI_CLASS_COMMUNICATION_SERIAL 0x0700 diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h index 9380cb5413..c0b69ff18f 100644 --- a/include/hw/virtio/dataplane/vring.h +++ b/include/hw/virtio/dataplane/vring.h @@ -50,7 +50,7 @@ static inline void vring_set_broken(Vring *vring) } bool vring_setup(Vring *vring, VirtIODevice *vdev, int n); -void vring_teardown(Vring *vring); +void vring_teardown(Vring *vring, VirtIODevice *vdev, int n); void vring_disable_notification(VirtIODevice *vdev, Vring *vring); bool vring_enable_notification(VirtIODevice *vdev, Vring *vring); bool vring_should_notify(VirtIODevice *vdev, Vring *vring); diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index b315ac91a4..df60f16a3e 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -243,6 +243,7 @@ struct virtio_net_ctrl_mq { #define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \ DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \ + DEFINE_PROP_BIT("any_layout", _state, _field, VIRTIO_F_ANY_LAYOUT, true), \ DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \ DEFINE_PROP_BIT("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \ DEFINE_PROP_BIT("gso", _state, _field, VIRTIO_NET_F_GSO, true), \ diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index a6c5c5380c..5d1d2be295 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -43,6 +43,8 @@ /* We notify when the ring is completely used, even if the guest is suppressing * callbacks */ #define VIRTIO_F_NOTIFY_ON_EMPTY 24 +/* Can the device handle any descriptor layout? */ +#define VIRTIO_F_ANY_LAYOUT 27 /* We support indirect buffer descriptors */ #define VIRTIO_RING_F_INDIRECT_DESC 28 /* The Guest publishes the used index for which it expects an interrupt diff --git a/include/migration/migration.h b/include/migration/migration.h index bc9fde0b2a..701709a1e9 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -124,6 +124,7 @@ void migrate_add_blocker(Error *reason); void migrate_del_blocker(Error *reason); bool migrate_rdma_pin_all(void); +bool migrate_zero_blocks(void); bool migrate_auto_converge(void); diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index 1a6cfcf687..1942cc42fe 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -41,6 +41,7 @@ typedef enum MonitorEvent { QEVENT_BLOCK_JOB_READY, QEVENT_DEVICE_DELETED, QEVENT_DEVICE_TRAY_MOVED, + QEVENT_NIC_RX_FILTER_CHANGED, QEVENT_SUSPEND, QEVENT_SUSPEND_DISK, QEVENT_WAKEUP, diff --git a/include/net/net.h b/include/net/net.h index 43d85a16eb..30e4b04066 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -49,6 +49,7 @@ typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int); typedef void (NetCleanup) (NetClientState *); typedef void (LinkStatusChanged)(NetClientState *); typedef void (NetClientDestructor)(NetClientState *); +typedef RxFilterInfo *(QueryRxFilter)(NetClientState *); typedef struct NetClientInfo { NetClientOptionsKind type; @@ -59,6 +60,7 @@ typedef struct NetClientInfo { NetCanReceive *can_receive; NetCleanup *cleanup; LinkStatusChanged *link_status_changed; + QueryRxFilter *query_rx_filter; NetPoll *poll; } NetClientInfo; @@ -74,6 +76,7 @@ struct NetClientState { unsigned receive_disabled : 1; NetClientDestructor *destructor; unsigned int queue_index; + unsigned rxfilter_notify_enabled:1; }; typedef struct NICState { diff --git a/linux-user/main.c b/linux-user/main.c index 7f15d3da2b..99c3b3f5ef 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2028,7 +2028,7 @@ static const uint8_t mips_syscall_args[] = { MIPS_SYS(sys_fremovexattr, 2) /* 4235 */ MIPS_SYS(sys_tkill , 2) MIPS_SYS(sys_sendfile64 , 5) - MIPS_SYS(sys_futex , 2) + MIPS_SYS(sys_futex , 6) MIPS_SYS(sys_sched_setaffinity, 3) MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */ MIPS_SYS(sys_io_setup , 2) diff --git a/migration.c b/migration.c index 9f5a4230d1..a9c042186d 100644 --- a/migration.c +++ b/migration.c @@ -493,6 +493,15 @@ bool migrate_auto_converge(void) return s->enabled_capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE]; } +bool migrate_zero_blocks(void) +{ + MigrationState *s; + + s = migrate_get_current(); + + return s->enabled_capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS]; +} + int migrate_use_xbzrle(void) { MigrationState *s; diff --git a/monitor.c b/monitor.c index 2ba7876b56..6db2ba4d7a 100644 --- a/monitor.c +++ b/monitor.c @@ -189,6 +189,7 @@ struct Monitor { int suspend_cnt; bool skip_flush; QString *outbuf; + guint watch; ReadLineState *rs; MonitorControl *mc; CPUState *mon_cpu; @@ -263,7 +264,10 @@ int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond, void *opaque) { - monitor_flush(opaque); + Monitor *mon = opaque; + + mon->watch = 0; + monitor_flush(mon); return FALSE; } @@ -294,7 +298,10 @@ void monitor_flush(Monitor *mon) QDECREF(mon->outbuf); mon->outbuf = tmp; } - qemu_chr_fe_add_watch(mon->chr, G_IO_OUT, monitor_unblocked, mon); + if (mon->watch == 0) { + mon->watch = qemu_chr_fe_add_watch(mon->chr, G_IO_OUT, + monitor_unblocked, mon); + } } } @@ -490,6 +497,7 @@ static const char *monitor_event_names[] = { [QEVENT_BLOCK_JOB_READY] = "BLOCK_JOB_READY", [QEVENT_DEVICE_DELETED] = "DEVICE_DELETED", [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED", + [QEVENT_NIC_RX_FILTER_CHANGED] = "NIC_RX_FILTER_CHANGED", [QEVENT_SUSPEND] = "SUSPEND", [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK", [QEVENT_WAKEUP] = "WAKEUP", diff --git a/net/net.c b/net/net.c index 43a74e43ae..c0d61bf78b 100644 --- a/net/net.c +++ b/net/net.c @@ -961,6 +961,54 @@ void print_net_client(Monitor *mon, NetClientState *nc) nc->info_str); } +RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name, + Error **errp) +{ + NetClientState *nc; + RxFilterInfoList *filter_list = NULL, *last_entry = NULL; + + QTAILQ_FOREACH(nc, &net_clients, next) { + RxFilterInfoList *entry; + RxFilterInfo *info; + + if (has_name && strcmp(nc->name, name) != 0) { + continue; + } + + /* only query rx-filter information of NIC */ + if (nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC) { + if (has_name) { + error_setg(errp, "net client(%s) isn't a NIC", name); + break; + } + continue; + } + + if (nc->info->query_rx_filter) { + info = nc->info->query_rx_filter(nc); + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + + if (!filter_list) { + filter_list = entry; + } else { + last_entry->next = entry; + } + last_entry = entry; + } else if (has_name) { + error_setg(errp, "net client(%s) doesn't support" + " rx-filter querying", name); + break; + } + } + + if (filter_list == NULL && !error_is_set(errp) && has_name) { + error_setg(errp, "invalid net client name: %s", name); + } + + return filter_list; +} + void do_info_network(Monitor *mon, const QDict *qdict) { NetClientState *nc, *peer; diff --git a/pc-bios/README b/pc-bios/README index 030d92a049..53b52894f7 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -40,4 +40,4 @@ git://repo.or.cz/s390-tools.git - The sources for the Alpha palcode image is available from: - git://repo.or.cz/qemu-palcode.git + git://github.com/rth7680/qemu-palcode.git diff --git a/pc-bios/palcode-clipper b/pc-bios/palcode-clipper index a92372c107..9956340cd1 100755 --- a/pc-bios/palcode-clipper +++ b/pc-bios/palcode-clipper Binary files differdiff --git a/qapi-schema.json b/qapi-schema.json index 7b9fef1bd1..592bb9c7a1 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -613,10 +613,16 @@ # Disabled by default. Experimental: may (or may not) be renamed after # further testing is complete. (since 1.6) # +# @zero-blocks: During storage migration encode blocks of zeroes efficiently. This +# essentially saves 1MB of zeroes per block on the wire. Enabling requires +# source and target VM to support this feature. To enable it is sufficient +# to enable the capability on the source VM. The feature is disabled by +# default. (since 1.6) +# # Since: 1.2 ## { 'enum': 'MigrationCapability', - 'data': ['xbzrle', 'x-rdma-pin-all', 'auto-converge'] } + 'data': ['xbzrle', 'x-rdma-pin-all', 'auto-converge', 'zero-blocks'] } ## # @MigrationCapabilityStatus @@ -3679,3 +3685,79 @@ '*cpuid-input-ecx': 'int', 'cpuid-register': 'X86CPURegister32', 'features': 'int' } } + +## +# @RxState: +# +# Packets receiving state +# +# @normal: filter assigned packets according to the mac-table +# +# @none: don't receive any assigned packet +# +# @all: receive all assigned packets +# +# Since: 1.6 +## +{ 'enum': 'RxState', 'data': [ 'normal', 'none', 'all' ] } + +## +# @RxFilterInfo: +# +# Rx-filter information for a NIC. +# +# @name: net client name +# +# @promiscuous: whether promiscuous mode is enabled +# +# @multicast: multicast receive state +# +# @unicast: unicast receive state +# +# @broadcast-allowed: whether to receive broadcast +# +# @multicast-overflow: multicast table is overflowed or not +# +# @unicast-overflow: unicast table is overflowed or not +# +# @main-mac: the main macaddr string +# +# @vlan-table: a list of active vlan id +# +# @unicast-table: a list of unicast macaddr string +# +# @multicast-table: a list of multicast macaddr string +# +# Since 1.6 +## + +{ 'type': 'RxFilterInfo', + 'data': { + 'name': 'str', + 'promiscuous': 'bool', + 'multicast': 'RxState', + 'unicast': 'RxState', + 'broadcast-allowed': 'bool', + 'multicast-overflow': 'bool', + 'unicast-overflow': 'bool', + 'main-mac': 'str', + 'vlan-table': ['int'], + 'unicast-table': ['str'], + 'multicast-table': ['str'] }} + +## +# @query-rx-filter: +# +# Return rx-filter information for all NICs (or for the given NIC). +# +# @name: #optional net client name +# +# Returns: list of @RxFilterInfo for all NICs (or for the given NIC). +# Returns an error if the given @name doesn't exist, or given +# NIC doesn't support rx-filter querying, or given net client +# isn't a NIC. +# +# Since: 1.6 +## +{ 'command': 'query-rx-filter', 'data': { '*name': 'str' }, + 'returns': ['RxFilterInfo'] } diff --git a/qemu-char.c b/qemu-char.c index 800d6a62f9..c86ce4ba2e 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -720,35 +720,32 @@ static GIOChannel *io_channel_from_socket(int fd) static int io_channel_send(GIOChannel *fd, const void *buf, size_t len) { - GIOStatus status; - size_t offset; + size_t offset = 0; + GIOStatus status = G_IO_STATUS_NORMAL; - offset = 0; - while (offset < len) { - gsize bytes_written; + while (offset < len && status == G_IO_STATUS_NORMAL) { + gsize bytes_written = 0; status = g_io_channel_write_chars(fd, buf + offset, len - offset, &bytes_written, NULL); - if (status != G_IO_STATUS_NORMAL) { - if (status == G_IO_STATUS_AGAIN) { - /* If we've written any data, return a partial write. */ - if (offset) { - break; - } - errno = EAGAIN; - } else { - errno = EINVAL; - } - - return -1; - } else if (status == G_IO_STATUS_EOF) { - break; - } - offset += bytes_written; } - return offset; + if (offset > 0) { + return offset; + } + switch (status) { + case G_IO_STATUS_NORMAL: + g_assert(len == 0); + return 0; + case G_IO_STATUS_AGAIN: + errno = EAGAIN; + return -1; + default: + break; + } + errno = EINVAL; + return -1; } #ifndef _WIN32 diff --git a/qemu-options.hx b/qemu-options.hx index 4e98b4f483..2dbfd42a8c 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2493,8 +2493,8 @@ listening on port 4444 would be: @table @code @item -serial mon:telnet::4444,server,nowait @end table -When monitor is multiplexed to stdio this way, Ctrl+C will not terminate -QEMU anymore but will be passed to the guest instead. +When the monitor is multiplexed to stdio in this way, Ctrl+C will not terminate +QEMU any more but will be passed to the guest instead. @item braille Braille device. This will use BrlAPI to display the braille output on a real diff --git a/qemu.sasl b/qemu.sasl index cf19cf8d07..9dc8323f1d 100644 --- a/qemu.sasl +++ b/qemu.sasl @@ -26,7 +26,7 @@ keytab: /etc/qemu/krb5.tab # If using digest-md5 for username/passwds, then this is the file # containing the passwds. Use 'saslpasswd2 -a qemu [username]' -# to add entries, and 'sasldblistusers2 -a qemu' to browse it +# to add entries, and 'sasldblistusers2 -f [sasldb_path]' to browse it sasldb_path: /etc/qemu/passwd.db diff --git a/qmp-commands.hx b/qmp-commands.hx index e075df423a..65a9e26423 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -346,7 +346,8 @@ Send keys to VM. Arguments: keys array: - - "key": key sequence (a json-array of key enum values) + - "key": key sequence (a json-array of key union values, + union can be number or qcode enum) - hold-time: time to delay key up events, milliseconds. Defaults to 100 (json-int, optional) @@ -354,7 +355,9 @@ keys array: Example: -> { "execute": "send-key", - "arguments": { 'keys': [ 'ctrl', 'alt', 'delete' ] } } + "arguments": { "keys": [ { "type": "qcode", "data": "ctrl" }, + { "type": "qcode", "data": "alt" }, + { "type": "qcode", "data": "delete" } ] } } <- { "return": {} } EQMP @@ -3047,3 +3050,66 @@ Example: <- { "return": {} } EQMP + { + .name = "query-rx-filter", + .args_type = "name:s?", + .mhandler.cmd_new = qmp_marshal_input_query_rx_filter, + }, + +SQMP +query-rx-filter +--------------- + +Show rx-filter information. + +Returns a json-array of rx-filter information for all NICs (or for the +given NIC), returning an error if the given NIC doesn't exist, or +given NIC doesn't support rx-filter querying, or given net client +isn't a NIC. + +The query will clear the event notification flag of each NIC, then qemu +will start to emit event to QMP monitor. + +Each array entry contains the following: + +- "name": net client name (json-string) +- "promiscuous": promiscuous mode is enabled (json-bool) +- "multicast": multicast receive state (one of 'normal', 'none', 'all') +- "unicast": unicast receive state (one of 'normal', 'none', 'all') +- "broadcast-allowed": allow to receive broadcast (json-bool) +- "multicast-overflow": multicast table is overflowed (json-bool) +- "unicast-overflow": unicast table is overflowed (json-bool) +- "main-mac": main macaddr string (json-string) +- "vlan-table": a json-array of active vlan id +- "unicast-table": a json-array of unicast macaddr string +- "multicast-table": a json-array of multicast macaddr string + +Example: + +-> { "execute": "query-rx-filter", "arguments": { "name": "vnet0" } } +<- { "return": [ + { + "promiscuous": true, + "name": "vnet0", + "main-mac": "52:54:00:12:34:56", + "unicast": "normal", + "vlan-table": [ + 4, + 0 + ], + "unicast-table": [ + ], + "multicast": "normal", + "multicast-overflow": false, + "unicast-overflow": false, + "multicast-table": [ + "01:00:5e:00:00:01", + "33:33:00:00:00:01", + "33:33:ff:12:34:56" + ], + "broadcast-allowed": false + } + ] + } + +EQMP diff --git a/qtest.c b/qtest.c index 07a96120dc..74f1842c1e 100644 --- a/qtest.c +++ b/qtest.c @@ -472,7 +472,12 @@ static void qtest_event(void *opaque, int event) switch (event) { case CHR_EVENT_OPENED: - qemu_system_reset(false); + /* + * We used to call qemu_system_reset() here, hoping we could + * use the same process for multiple tests that way. Never + * used. Injects an extra reset even when it's not used, and + * that can mess up tests, e.g. -boot once. + */ for (i = 0; i < ARRAY_SIZE(irq_levels); i++) { irq_levels[i] = 0; } diff --git a/roms/qemu-palcode b/roms/qemu-palcode -Subproject 7abb12f60eb3069019e9497e193733d77d8f072 +Subproject c87a92639b28ac42bc8f6c67443543b405dc479 diff --git a/scripts/cleanup-trace-events.pl b/scripts/cleanup-trace-events.pl new file mode 100755 index 0000000000..cffbf165dc --- /dev/null +++ b/scripts/cleanup-trace-events.pl @@ -0,0 +1,51 @@ +#!/usr/bin/perl +# Copyright (C) 2013 Red Hat, Inc. +# +# Authors: +# Markus Armbruster <armbru@redhat.com> +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +# Usage: cleanup-trace-events.pl trace-events +# +# Print cleaned up trace-events to standard output. + +use warnings; +use strict; + +my $buf = ''; +my %seen = (); + +sub out { + print $buf; + $buf = ''; + %seen = (); +} + +while (<>) { + if (/^(disable )?([a-z_0-9]+)\(/) { + open GREP, '-|', 'git', 'grep', '-l', "trace_$2" + or die "run git grep: $!"; + my $fname; + while ($fname = <GREP>) { + chomp $fname; + next if $seen{$fname} || $fname eq 'trace-events'; + $seen{$fname} = 1; + $buf = "# $fname\n" . $buf; + } + unless (close GREP) { + die "close git grep: $!" + if $!; + next; + } + } elsif (/^# ([^ ]*\.[ch])$/) { + out; + next; + } elsif (!/^#|^$/) { + warn "unintelligible line"; + } + $buf .= $_; +} + +out; diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index e06332bd55..b12b6964ef 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -128,12 +128,15 @@ bool has_%(argname)s = false; def gen_visitor_input_block(args, obj, dealloc=False): ret = "" + errparg = 'errp' + if len(args) == 0: return ret push_indent() if dealloc: + errparg = 'NULL' ret += mcgen(''' md = qapi_dealloc_visitor_new(); v = qapi_dealloc_get_visitor(md); @@ -148,22 +151,22 @@ v = qmp_input_get_visitor(mi); for argname, argtype, optional, structured in parse_args(args): if optional: ret += mcgen(''' -visit_start_optional(v, &has_%(c_name)s, "%(name)s", errp); +visit_start_optional(v, &has_%(c_name)s, "%(name)s", %(errp)s); if (has_%(c_name)s) { ''', - c_name=c_var(argname), name=argname) + c_name=c_var(argname), name=argname, errp=errparg) push_indent() ret += mcgen(''' -%(visitor)s(v, &%(c_name)s, "%(name)s", errp); +%(visitor)s(v, &%(c_name)s, "%(name)s", %(errp)s); ''', c_name=c_var(argname), name=argname, argtype=argtype, - visitor=type_visitor(argtype)) + visitor=type_visitor(argtype), errp=errparg) if optional: pop_indent() ret += mcgen(''' } -visit_end_optional(v, errp); -''') +visit_end_optional(v, %(errp)s); +''', errp=errparg) if dealloc: ret += mcgen(''' @@ -194,7 +197,7 @@ static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_o } qmp_output_visitor_cleanup(mo); v = qapi_dealloc_get_visitor(md); - %(visitor)s(v, &ret_in, "unused", errp); + %(visitor)s(v, &ret_in, "unused", NULL); qapi_dealloc_visitor_cleanup(md); } ''', diff --git a/slirp/mbuf.h b/slirp/mbuf.h index 3f3ab095b1..b144f1ce3a 100644 --- a/slirp/mbuf.h +++ b/slirp/mbuf.h @@ -49,22 +49,6 @@ * free the m_ext. This is inefficient memory-wise, but who cares. */ -/* XXX should union some of these! */ -/* header at beginning of each mbuf: */ -struct m_hdr { - struct mbuf *mh_next; /* Linked list of mbufs */ - struct mbuf *mh_prev; - struct mbuf *mh_nextpkt; /* Next packet in queue/record */ - struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */ - int mh_flags; /* Misc flags */ - - int mh_size; /* Size of data */ - struct socket *mh_so; - - caddr_t mh_data; /* Location of data */ - int mh_len; /* Amount of data in this mbuf */ -}; - /* * How much room is in the mbuf, from m_data to the end of the mbuf */ @@ -80,29 +64,30 @@ struct m_hdr { #define M_TRAILINGSPACE M_FREEROOM struct mbuf { - struct m_hdr m_hdr; + /* XXX should union some of these! */ + /* header at beginning of each mbuf: */ + struct mbuf *m_next; /* Linked list of mbufs */ + struct mbuf *m_prev; + struct mbuf *m_nextpkt; /* Next packet in queue/record */ + struct mbuf *m_prevpkt; /* Flags aren't used in the output queue */ + int m_flags; /* Misc flags */ + + int m_size; /* Size of data */ + struct socket *m_so; + + caddr_t m_data; /* Location of data */ + int m_len; /* Amount of data in this mbuf */ + Slirp *slirp; bool arp_requested; uint64_t expiration_date; /* start of dynamic buffer area, must be last element */ - union M_dat { - char m_dat_[1]; /* ANSI don't like 0 sized arrays */ - char *m_ext_; - } M_dat; + union { + char m_dat[1]; /* ANSI don't like 0 sized arrays */ + char *m_ext; + }; }; -#define m_next m_hdr.mh_next -#define m_prev m_hdr.mh_prev -#define m_nextpkt m_hdr.mh_nextpkt -#define m_prevpkt m_hdr.mh_prevpkt -#define m_flags m_hdr.mh_flags -#define m_len m_hdr.mh_len -#define m_data m_hdr.mh_data -#define m_size m_hdr.mh_size -#define m_dat M_dat.m_dat_ -#define m_ext M_dat.m_ext_ -#define m_so m_hdr.mh_so - #define ifq_prev m_prev #define ifq_next m_next #define ifs_prev m_prevpkt diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index e98ce1a50c..043f28fcae 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -647,7 +647,7 @@ tcp_emu(struct socket *so, struct mbuf *m) n4 = (laddr & 0xff); m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += snprintf(bptr, m->m_hdr.mh_size - m->m_len, + m->m_len += snprintf(bptr, m->m_size - m->m_len, "ORT %d,%d,%d,%d,%d,%d\r\n%s", n1, n2, n3, n4, n5, n6, x==7?buff:""); return 1; @@ -680,7 +680,7 @@ tcp_emu(struct socket *so, struct mbuf *m) n4 = (laddr & 0xff); m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += snprintf(bptr, m->m_hdr.mh_size - m->m_len, + m->m_len += snprintf(bptr, m->m_size - m->m_len, "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s", n1, n2, n3, n4, n5, n6, x==7?buff:""); @@ -706,7 +706,7 @@ tcp_emu(struct socket *so, struct mbuf *m) if (m->m_data[m->m_len-1] == '\0' && lport != 0 && (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL) - m->m_len = snprintf(m->m_data, m->m_hdr.mh_size, "%d", + m->m_len = snprintf(m->m_data, m->m_size, "%d", ntohs(so->so_fport)) + 1; return 1; @@ -726,7 +726,7 @@ tcp_emu(struct socket *so, struct mbuf *m) return 1; } m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += snprintf(bptr, m->m_hdr.mh_size, + m->m_len += snprintf(bptr, m->m_size, "DCC CHAT chat %lu %u%c\n", (unsigned long)ntohl(so->so_faddr.s_addr), ntohs(so->so_fport), 1); @@ -737,7 +737,7 @@ tcp_emu(struct socket *so, struct mbuf *m) return 1; } m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += snprintf(bptr, m->m_hdr.mh_size, + m->m_len += snprintf(bptr, m->m_size, "DCC SEND %s %lu %u %u%c\n", buff, (unsigned long)ntohl(so->so_faddr.s_addr), ntohs(so->so_fport), n1, 1); @@ -748,7 +748,7 @@ tcp_emu(struct socket *so, struct mbuf *m) return 1; } m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += snprintf(bptr, m->m_hdr.mh_size, + m->m_len += snprintf(bptr, m->m_size, "DCC MOVE %s %lu %u %u%c\n", buff, (unsigned long)ntohl(so->so_faddr.s_addr), ntohs(so->so_fport), n1, 1); diff --git a/target-alpha/helper.h b/target-alpha/helper.h index 3321fde916..0e425cfc08 100644 --- a/target-alpha/helper.h +++ b/target-alpha/helper.h @@ -114,7 +114,8 @@ DEF_HELPER_FLAGS_2(tbis, TCG_CALL_NO_RWG, void, env, i64) DEF_HELPER_1(halt, void, i64); -DEF_HELPER_FLAGS_0(get_time, TCG_CALL_NO_RWG, i64) +DEF_HELPER_FLAGS_0(get_vmtime, TCG_CALL_NO_RWG, i64) +DEF_HELPER_FLAGS_0(get_walltime, TCG_CALL_NO_RWG, i64) DEF_HELPER_FLAGS_2(set_alarm, TCG_CALL_NO_RWG, void, env, i64) #endif diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c index 339501af90..bd94597d36 100644 --- a/target-alpha/sys_helper.c +++ b/target-alpha/sys_helper.c @@ -70,7 +70,12 @@ void helper_halt(uint64_t restart) } } -uint64_t helper_get_time(void) +uint64_t helper_get_vmtime(void) +{ + return qemu_get_clock_ns(vm_clock); +} + +uint64_t helper_get_walltime(void) { return qemu_get_clock_ns(rtc_clock); } diff --git a/target-alpha/translate.c b/target-alpha/translate.c index dd7f0fbf94..5558b728dd 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -1634,15 +1634,19 @@ static ExitStatus gen_mfpr(int ra, int regno) return NO_EXIT; } - if (regno == 250) { - /* WALL_TIME */ + /* Special help for VMTIME and WALLTIME. */ + if (regno == 250 || regno == 249) { + void (*helper)(TCGv) = gen_helper_get_walltime; + if (regno == 249) { + helper = gen_helper_get_vmtime; + } if (use_icount) { gen_io_start(); - gen_helper_get_time(cpu_ir[ra]); + helper(cpu_ir[ra]); gen_io_end(); return EXIT_PC_STALE; } else { - gen_helper_get_time(cpu_ir[ra]); + helper(cpu_ir[ra]); return NO_EXIT; } } diff --git a/tests/Makefile b/tests/Makefile index 279d5f8307..425a9a8c4b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -57,6 +57,7 @@ gcov-files-i386-y = hw/fdc.c check-qtest-i386-y += tests/ide-test$(EXESUF) check-qtest-i386-y += tests/hd-geo-test$(EXESUF) gcov-files-i386-y += hw/hd-geometry.c +check-qtest-i386-y += tests/boot-order-test$(EXESUF) check-qtest-i386-y += tests/rtc-test$(EXESUF) check-qtest-i386-y += tests/i440fx-test$(EXESUF) check-qtest-i386-y += tests/fw_cfg-test$(EXESUF) @@ -69,6 +70,8 @@ gcov-files-sparc-y += hw/m48t59.c gcov-files-sparc64-y += hw/m48t59.c check-qtest-arm-y = tests/tmp105-test$(EXESUF) gcov-files-arm-y += hw/tmp105.c +check-qtest-ppc-y += tests/boot-order-test$(EXESUF) +check-qtest-ppc64-y += tests/boot-order-test$(EXESUF) GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h @@ -125,7 +128,7 @@ tests/test-mul64$(EXESUF): tests/test-mul64.o libqemuutil.a libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o libqos-obj-y += tests/libqos/i2c.o -libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o tests/libqos/fw_cfg-pc.o +libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o libqos-pc-obj-y += tests/libqos/malloc-pc.o libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o @@ -134,6 +137,7 @@ tests/m48t59-test$(EXESUF): tests/m48t59-test.o tests/fdc-test$(EXESUF): tests/fdc-test.o tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y) tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o +tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y) tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y) tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y) @@ -226,3 +230,4 @@ check-block: $(patsubst %,check-%, $(check-block-y)) check: check-unit check-qtest -include $(wildcard tests/*.d) +-include $(wildcard tests/libqos/*.d) diff --git a/tests/boot-order-test.c b/tests/boot-order-test.c new file mode 100644 index 0000000000..4b233d0b24 --- /dev/null +++ b/tests/boot-order-test.c @@ -0,0 +1,209 @@ +/* + * Boot order test cases. + * + * Copyright (c) 2013 Red Hat Inc. + * + * Authors: + * Markus Armbruster <armbru@redhat.com>, + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <string.h> +#include <glib.h> +#include "libqos/fw_cfg.h" +#include "libqtest.h" + +#define NO_QEMU_PROTOS +#include "hw/nvram/fw_cfg.h" +#undef NO_QEMU_PROTOS + +typedef struct { + const char *args; + uint64_t expected_boot; + uint64_t expected_reboot; +} boot_order_test; + +static void test_a_boot_order(const char *machine, + const char *test_args, + uint64_t (*read_boot_order)(void), + uint64_t expected_boot, + uint64_t expected_reboot) +{ + char *args; + uint64_t actual; + + args = g_strdup_printf("-nodefaults -display none%s%s %s", + machine ? " -M " : "", + machine ?: "", + test_args); + qtest_start(args); + actual = read_boot_order(); + g_assert_cmphex(actual, ==, expected_boot); + qmp("{ 'execute': 'system_reset' }"); + /* + * system_reset only requests reset. We get a RESET event after + * the actual reset completes. Need to wait for that. + */ + qmp(""); /* HACK: wait for event */ + actual = read_boot_order(); + g_assert_cmphex(actual, ==, expected_reboot); + qtest_quit(global_qtest); + g_free(args); +} + +static void test_boot_orders(const char *machine, + uint64_t (*read_boot_order)(void), + const boot_order_test *tests) +{ + int i; + + for (i = 0; tests[i].args; i++) { + test_a_boot_order(machine, tests[i].args, + read_boot_order, + tests[i].expected_boot, + tests[i].expected_reboot); + } +} + +static uint8_t read_mc146818(uint16_t port, uint8_t reg) +{ + outb(port, reg); + return inb(port + 1); +} + +static uint64_t read_boot_order_pc(void) +{ + uint8_t b1 = read_mc146818(0x70, 0x38); + uint8_t b2 = read_mc146818(0x70, 0x3d); + + return b1 | (b2 << 8); +} + +static const boot_order_test test_cases_pc[] = { + { "", + 0x1230, 0x1230 }, + { "-no-fd-bootchk", + 0x1231, 0x1231 }, + { "-boot c", + 0x0200, 0x0200 }, + { "-boot nda", + 0x3410, 0x3410 }, + { "-boot order=", + 0, 0 }, + { "-boot order= -boot order=c", + 0x0200, 0x0200 }, + { "-boot once=a", + 0x0100, 0x1230 }, + { "-boot once=a -no-fd-bootchk", + 0x0101, 0x1231 }, + { "-boot once=a,order=c", + 0x0100, 0x0200 }, + { "-boot once=d -boot order=nda", + 0x0300, 0x3410 }, + { "-boot once=a -boot once=b -boot once=c", + 0x0200, 0x1230 }, + {} +}; + +static void test_pc_boot_order(void) +{ + test_boot_orders(NULL, read_boot_order_pc, test_cases_pc); +} + +static uint8_t read_m48t59(uint64_t addr, uint16_t reg) +{ + writeb(addr, reg & 0xff); + writeb(addr + 1, reg >> 8); + return readb(addr + 3); +} + +static uint64_t read_boot_order_prep(void) +{ + return read_m48t59(0x80000000 + 0x74, 0x34); +} + +static const boot_order_test test_cases_prep[] = { + { "", 'c', 'c' }, + { "-boot c", 'c', 'c' }, + { "-boot d", 'd', 'd' }, + {} +}; + +static void test_prep_boot_order(void) +{ + test_boot_orders("prep", read_boot_order_prep, test_cases_prep); +} + +static uint64_t read_boot_order_pmac(void) +{ + QFWCFG *fw_cfg = mm_fw_cfg_init(0xf0000510); + + return qfw_cfg_get_u16(fw_cfg, FW_CFG_BOOT_DEVICE); +} + +static const boot_order_test test_cases_fw_cfg[] = { + { "", 'c', 'c' }, + { "-boot c", 'c', 'c' }, + { "-boot d", 'd', 'd' }, + { "-boot once=d,order=c", 'd', 'c' }, + {} +}; + +static void test_pmac_oldworld_boot_order(void) +{ + test_boot_orders("g3beige", read_boot_order_pmac, test_cases_fw_cfg); +} + +static void test_pmac_newworld_boot_order(void) +{ + test_boot_orders("mac99", read_boot_order_pmac, test_cases_fw_cfg); +} + +static uint64_t read_boot_order_sun4m(void) +{ + QFWCFG *fw_cfg = mm_fw_cfg_init(0xd00000510ULL); + + return qfw_cfg_get_u16(fw_cfg, FW_CFG_BOOT_DEVICE); +} + +static void test_sun4m_boot_order(void) +{ + test_boot_orders("SS-5", read_boot_order_sun4m, test_cases_fw_cfg); +} + +static uint64_t read_boot_order_sun4u(void) +{ + QFWCFG *fw_cfg = io_fw_cfg_init(0x510); + + return qfw_cfg_get_u16(fw_cfg, FW_CFG_BOOT_DEVICE); +} + +static void test_sun4u_boot_order(void) +{ + test_boot_orders("sun4u", read_boot_order_sun4u, test_cases_fw_cfg); +} + +int main(int argc, char *argv[]) +{ + const char *arch = qtest_get_arch(); + + g_test_init(&argc, &argv, NULL); + + if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { + qtest_add_func("boot-order/pc", test_pc_boot_order); + } else if (strcmp(arch, "ppc") == 0 || strcmp(arch, "ppc64") == 0) { + qtest_add_func("boot-order/prep", test_prep_boot_order); + qtest_add_func("boot-order/pmac_oldworld", + test_pmac_oldworld_boot_order); + qtest_add_func("boot-order/pmac_newworld", + test_pmac_newworld_boot_order); + } else if (strcmp(arch, "sparc") == 0) { + qtest_add_func("boot-order/sun4m", test_sun4m_boot_order); + } else if (strcmp(arch, "sparc64") == 0) { + qtest_add_func("boot-order/sun4u", test_sun4u_boot_order); + } + + return g_test_run(); +} diff --git a/tests/fdc-test.c b/tests/fdc-test.c index 4b0301da46..fd198dcf8b 100644 --- a/tests/fdc-test.c +++ b/tests/fdc-test.c @@ -556,7 +556,7 @@ int main(int argc, char **argv) ret = g_test_run(); /* Cleanup */ - qtest_quit(global_qtest); + qtest_end(); unlink(test_image); return ret; diff --git a/tests/fw_cfg-test.c b/tests/fw_cfg-test.c index c284c4d743..b86e49ab09 100644 --- a/tests/fw_cfg-test.c +++ b/tests/fw_cfg-test.c @@ -14,7 +14,7 @@ #include "libqtest.h" #include "hw/nvram/fw_cfg.h" -#include "libqos/fw_cfg-pc.h" +#include "libqos/fw_cfg.h" #include <string.h> #include <glib.h> diff --git a/tests/hd-geo-test.c b/tests/hd-geo-test.c index 9a31e8587f..b72042e59d 100644 --- a/tests/hd-geo-test.c +++ b/tests/hd-geo-test.c @@ -244,7 +244,7 @@ static void test_ide_none(void) setup_common(argv, ARRAY_SIZE(argv)); qtest_start(g_strjoinv(" ", argv)); test_cmos(); - qtest_quit(global_qtest); + qtest_end(); } static void test_ide_mbr(bool use_device, MBRcontents mbr) @@ -262,7 +262,7 @@ static void test_ide_mbr(bool use_device, MBRcontents mbr) } qtest_start(g_strjoinv(" ", argv)); test_cmos(); - qtest_quit(global_qtest); + qtest_end(); } /* @@ -334,7 +334,7 @@ static void test_ide_drive_user(const char *dev, bool trans) g_free(opts); qtest_start(g_strjoinv(" ", argv)); test_cmos(); - qtest_quit(global_qtest); + qtest_end(); } /* @@ -387,7 +387,7 @@ static void test_ide_drive_cd_0(void) } qtest_start(g_strjoinv(" ", argv)); test_cmos(); - qtest_quit(global_qtest); + qtest_end(); } int main(int argc, char **argv) diff --git a/tests/ide-test.c b/tests/ide-test.c index 7e2eb9455a..7307f1d336 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -122,7 +122,7 @@ static void ide_test_start(const char *cmdline_fmt, ...) static void ide_test_quit(void) { - qtest_quit(global_qtest); + qtest_end(); } static QPCIDevice *get_pci_device(uint16_t *bmdma_base) diff --git a/tests/libqos/fw_cfg-pc.c b/tests/libqos/fw_cfg-pc.c deleted file mode 100644 index 613604db77..0000000000 --- a/tests/libqos/fw_cfg-pc.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * libqos fw_cfg support for PC - * - * Copyright IBM, Corp. 2012-2013 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.com> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include "libqos/fw_cfg-pc.h" -#include "libqtest.h" -#include <glib.h> - -static void pc_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key) -{ - outw(0x510, key); -} - -static void pc_fw_cfg_read(QFWCFG *fw_cfg, void *data, size_t len) -{ - uint8_t *ptr = data; - int i; - - for (i = 0; i < len; i++) { - ptr[i] = inb(0x511); - } -} - -QFWCFG *pc_fw_cfg_init(void) -{ - QFWCFG *fw_cfg = g_malloc0(sizeof(*fw_cfg)); - - fw_cfg->select = pc_fw_cfg_select; - fw_cfg->read = pc_fw_cfg_read; - - return fw_cfg; -} diff --git a/tests/libqos/fw_cfg-pc.h b/tests/libqos/fw_cfg-pc.h deleted file mode 100644 index 444bd7975a..0000000000 --- a/tests/libqos/fw_cfg-pc.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * libqos fw_cfg support for PC - * - * Copyright IBM, Corp. 2012-2013 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.com> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#ifndef LIBQOS_FW_CFG_PC_H -#define LIBQOS_FW_CFG_PC_H - -#include "libqos/fw_cfg.h" - -QFWCFG *pc_fw_cfg_init(void); - -#endif diff --git a/tests/libqos/fw_cfg.c b/tests/libqos/fw_cfg.c index e386ff7ba7..ef00fedf1a 100644 --- a/tests/libqos/fw_cfg.c +++ b/tests/libqos/fw_cfg.c @@ -2,15 +2,19 @@ * libqos fw_cfg support * * Copyright IBM, Corp. 2012-2013 + * Copyright (C) 2013 Red Hat Inc. * * Authors: * Anthony Liguori <aliguori@us.ibm.com> + * Markus Armbruster <armbru@redhat.com> * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. */ +#include <glib.h> #include "libqos/fw_cfg.h" +#include "libqtest.h" #include "qemu/bswap.h" void qfw_cfg_select(QFWCFG *fw_cfg, uint16_t key) @@ -50,3 +54,54 @@ uint64_t qfw_cfg_get_u64(QFWCFG *fw_cfg, uint16_t key) return le64_to_cpu(value); } +static void mm_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key) +{ + writew(fw_cfg->base, key); +} + +static void mm_fw_cfg_read(QFWCFG *fw_cfg, void *data, size_t len) +{ + uint8_t *ptr = data; + int i; + + for (i = 0; i < len; i++) { + ptr[i] = readb(fw_cfg->base + 2); + } +} + +QFWCFG *mm_fw_cfg_init(uint64_t base) +{ + QFWCFG *fw_cfg = g_malloc0(sizeof(*fw_cfg)); + + fw_cfg->base = base; + fw_cfg->select = mm_fw_cfg_select; + fw_cfg->read = mm_fw_cfg_read; + + return fw_cfg; +} + +static void io_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key) +{ + outw(fw_cfg->base, key); +} + +static void io_fw_cfg_read(QFWCFG *fw_cfg, void *data, size_t len) +{ + uint8_t *ptr = data; + int i; + + for (i = 0; i < len; i++) { + ptr[i] = inb(fw_cfg->base + 1); + } +} + +QFWCFG *io_fw_cfg_init(uint16_t base) +{ + QFWCFG *fw_cfg = g_malloc0(sizeof(*fw_cfg)); + + fw_cfg->base = base; + fw_cfg->select = io_fw_cfg_select; + fw_cfg->read = io_fw_cfg_read; + + return fw_cfg; +} diff --git a/tests/libqos/fw_cfg.h b/tests/libqos/fw_cfg.h index 44fc42ba11..61b1548b4e 100644 --- a/tests/libqos/fw_cfg.h +++ b/tests/libqos/fw_cfg.h @@ -20,6 +20,7 @@ typedef struct QFWCFG QFWCFG; struct QFWCFG { + uint64_t base; void (*select)(QFWCFG *fw_cfg, uint16_t key); void (*read)(QFWCFG *fw_cfg, void *data, size_t len); }; @@ -31,4 +32,12 @@ uint16_t qfw_cfg_get_u16(QFWCFG *fw_cfg, uint16_t key); uint32_t qfw_cfg_get_u32(QFWCFG *fw_cfg, uint16_t key); uint64_t qfw_cfg_get_u64(QFWCFG *fw_cfg, uint16_t key); +QFWCFG *mm_fw_cfg_init(uint64_t base); +QFWCFG *io_fw_cfg_init(uint16_t base); + +static inline QFWCFG *pc_fw_cfg_init(void) +{ + return io_fw_cfg_init(0x510); +} + #endif diff --git a/tests/libqos/malloc-pc.c b/tests/libqos/malloc-pc.c index adc36c4731..db1496c667 100644 --- a/tests/libqos/malloc-pc.c +++ b/tests/libqos/malloc-pc.c @@ -11,7 +11,7 @@ */ #include "libqos/malloc-pc.h" -#include "libqos/fw_cfg-pc.h" +#include "libqos/fw_cfg.h" #define NO_QEMU_PROTOS #include "hw/nvram/fw_cfg.h" diff --git a/tests/libqtest.c b/tests/libqtest.c index 879ffe91dc..bb82069f5c 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -171,12 +171,16 @@ void qtest_quit(QTestState *s) waitpid(pid, &status, 0); } + close(s->fd); + close(s->qmp_fd); + g_string_free(s->rx, true); unlink(s->pid_file); unlink(s->socket_path); unlink(s->qmp_socket_path); g_free(s->pid_file); g_free(s->socket_path); g_free(s->qmp_socket_path); + g_free(s); } static void socket_sendf(int fd, const char *fmt, va_list ap) diff --git a/tests/libqtest.h b/tests/libqtest.h index 437bda39f3..0f6aade092 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -17,6 +17,7 @@ #ifndef LIBQTEST_H #define LIBQTEST_H +#include <stddef.h> #include <stdint.h> #include <stdbool.h> #include <stdarg.h> @@ -319,6 +320,17 @@ static inline QTestState *qtest_start(const char *args) } /** + * qtest_end: + * + * Shut down the QEMU process started by qtest_start(). + */ +static inline void qtest_end(void) +{ + qtest_quit(global_qtest); + global_qtest = NULL; +} + +/** * qmp: * @fmt...: QMP message to send to qemu * diff --git a/trace-events b/trace-events index 7f6d9625a7..002df83b9d 100644 --- a/trace-events +++ b/trace-events @@ -25,18 +25,14 @@ # # The <format-string> should be a sprintf()-compatible format string. -# qemu-malloc.c -g_malloc(size_t size, void *ptr) "size %zu ptr %p" -g_realloc(void *ptr, size_t size, void *newptr) "ptr %p size %zu newptr %p" -g_free(void *ptr) "ptr %p" - -# osdep.c +# util/oslib-win32.c +# util/oslib-posix.c qemu_memalign(size_t alignment, size_t size, void *ptr) "alignment %zu size %zu ptr %p" qemu_anon_ram_alloc(size_t size, void *ptr) "size %zu ptr %p" qemu_vfree(void *ptr) "ptr %p" qemu_anon_ram_free(void *ptr, size_t size) "ptr %p size %zu" -# hw/virtio.c +# hw/virtio/virtio.c virtqueue_fill(void *vq, const void *elem, unsigned int len, unsigned int idx) "vq %p elem %p len %u idx %u" virtqueue_flush(void *vq, unsigned int count) "vq %p count %u" virtqueue_pop(void *vq, void *elem, unsigned int in_num, unsigned int out_num) "vq %p elem %p in_num %u out_num %u" @@ -45,13 +41,13 @@ virtio_irq(void *vq) "vq %p" virtio_notify(void *vdev, void *vq) "vdev %p vq %p" virtio_set_status(void *vdev, uint8_t val) "vdev %p val %u" -# hw/virtio-serial-bus.c +# hw/char/virtio-serial-bus.c virtio_serial_send_control_event(unsigned int port, uint16_t event, uint16_t value) "port %u, event %u, value %u" virtio_serial_throttle_port(unsigned int port, bool throttle) "port %u, throttle %d" virtio_serial_handle_control_message(uint16_t event, uint16_t value) "event %u, value %u" virtio_serial_handle_control_message_port(unsigned int port) "port %u" -# hw/virtio-console.c +# hw/char/virtio-console.c virtio_console_flush_buf(unsigned int port, size_t len, ssize_t ret) "port %u, in_len %zu, out_len %zd" virtio_console_chr_read(unsigned int port, int size) "port %u, size %d" virtio_console_chr_event(unsigned int port, int event) "port %u, event %d" @@ -75,6 +71,8 @@ bdrv_co_do_copy_on_readv(void *bs, int64_t sector_num, int nb_sectors, int64_t c # block/stream.c stream_one_iteration(void *s, int64_t sector_num, int nb_sectors, int is_allocated) "s %p sector_num %"PRId64" nb_sectors %d is_allocated %d" stream_start(void *bs, void *base, void *s, void *co, void *opaque) "bs %p base %p s %p co %p opaque %p" + +# block/commit.c commit_one_iteration(void *s, int64_t sector_num, int nb_sectors, int is_allocated) "s %p sector_num %"PRId64" nb_sectors %d is_allocated %d" commit_start(void *bs, void *base, void *top, void *s, void *co, void *opaque) "bs %p base %p top %p s %p co %p opaque %p" @@ -85,7 +83,6 @@ mirror_before_flush(void *s) "s %p" mirror_before_drain(void *s, int64_t cnt) "s %p dirty count %"PRId64 mirror_before_sleep(void *s, int64_t cnt, int synced) "s %p dirty count %"PRId64" synced %d" mirror_one_iteration(void *s, int64_t sector_num, int nb_sectors) "s %p sector_num %"PRId64" nb_sectors %d" -mirror_cow(void *s, int64_t sector_num) "s %p sector_num %"PRId64 mirror_iteration_done(void *s, int64_t sector_num, int nb_sectors, int ret) "s %p sector_num %"PRId64" nb_sectors %d ret %d" mirror_yield(void *s, int64_t cnt, int buf_free_count, int in_flight) "s %p dirty count %"PRId64" free buffers %d in_flight %d" mirror_yield_in_flight(void *s, int64_t sector_num, int in_flight) "s %p sector_num %"PRId64" in_flight %d" @@ -108,19 +105,19 @@ qmp_block_job_complete(void *job) "job %p" block_job_cb(void *bs, void *job, int ret) "bs %p job %p ret %d" qmp_block_stream(void *bs, void *job) "bs %p job %p" -# hw/virtio-blk.c +# hw/block/virtio-blk.c virtio_blk_req_complete(void *req, int status) "req %p status %d" virtio_blk_rw_complete(void *req, int ret) "req %p ret %d" virtio_blk_handle_write(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu" virtio_blk_handle_read(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu" -# hw/dataplane/virtio-blk.c +# hw/block/dataplane/virtio-blk.c virtio_blk_data_plane_start(void *s) "dataplane %p" virtio_blk_data_plane_stop(void *s) "dataplane %p" virtio_blk_data_plane_process_request(void *s, unsigned int out_num, unsigned int in_num, unsigned int head) "dataplane %p out_num %u in_num %u head %u" virtio_blk_data_plane_complete_request(void *s, unsigned int head, int ret) "dataplane %p head %u ret %d" -# hw/dataplane/vring.c +# hw/virtio/dataplane/vring.c vring_setup(uint64_t physical, void *desc, void *avail, void *used) "vring physical %#"PRIx64" desc %p avail %p used %p" # thread-pool.c @@ -128,10 +125,9 @@ thread_pool_submit(void *pool, void *req, void *opaque) "pool %p req %p opaque % thread_pool_complete(void *pool, void *req, void *opaque, int ret) "pool %p req %p opaque %p ret %d" thread_pool_cancel(void *req, void *opaque) "req %p opaque %p" -# posix-aio-compat.c +# block/raw-win32.c +# block/raw-posix.c paio_submit(void *acb, void *opaque, int64_t sector_num, int nb_sectors, int type) "acb %p opaque %p sector_num %"PRId64" nb_sectors %d type %d" -paio_complete(void *acb, void *opaque, int ret) "acb %p opaque %p ret %d" -paio_cancel(void *acb, void *opaque) "acb %p opaque %p" # ioport.c cpu_in(unsigned int addr, unsigned int val) "addr %#x value %u" @@ -141,29 +137,31 @@ cpu_out(unsigned int addr, unsigned int val) "addr %#x value %u" # Since requests are raised via monitor, not many tracepoints are needed. balloon_event(void *opaque, unsigned long addr) "opaque %p addr %lu" -# hw/apic.c -apic_local_deliver(int vector, uint32_t lvt) "vector %d delivery mode %d" -apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode) "dest %d dest_mode %d delivery_mode %d vector %d trigger_mode %d" +# hw/intc/apic_common.c cpu_set_apic_base(uint64_t val) "%016"PRIx64 cpu_get_apic_base(uint64_t val) "%016"PRIx64 -apic_mem_readl(uint64_t addr, uint32_t val) "%"PRIx64" = %08x" -apic_mem_writel(uint64_t addr, uint32_t val) "%"PRIx64" = %08x" # coalescing apic_report_irq_delivered(int apic_irq_delivered) "coalescing %d" apic_reset_irq_delivered(int apic_irq_delivered) "old coalescing %d" apic_get_irq_delivered(int apic_irq_delivered) "returning coalescing %d" -# hw/cs4231.c +# hw/intc/apic.c +apic_local_deliver(int vector, uint32_t lvt) "vector %d delivery mode %d" +apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode) "dest %d dest_mode %d delivery_mode %d vector %d trigger_mode %d" +apic_mem_readl(uint64_t addr, uint32_t val) "%"PRIx64" = %08x" +apic_mem_writel(uint64_t addr, uint32_t val) "%"PRIx64" = %08x" + +# hw/audio/cs4231.c cs4231_mem_readl_dreg(uint32_t reg, uint32_t ret) "read dreg %d: 0x%02x" cs4231_mem_readl_reg(uint32_t reg, uint32_t ret) "read reg %d: 0x%08x" cs4231_mem_writel_reg(uint32_t reg, uint32_t old, uint32_t val) "write reg %d: 0x%08x -> 0x%08x" cs4231_mem_writel_dreg(uint32_t reg, uint32_t old, uint32_t val) "write dreg %d: 0x%02x -> 0x%02x" -# hw/ds1225y.c +# hw/nvram/ds1225y.c nvram_read(uint32_t addr, uint32_t ret) "read addr %d: 0x%02x" nvram_write(uint32_t addr, uint32_t old, uint32_t val) "write addr %d: 0x%02x -> 0x%02x" -# hw/eccmemctl.c +# hw/misc/eccmemctl.c ecc_mem_writel_mer(uint32_t val) "Write memory enable %08x" ecc_mem_writel_mdr(uint32_t val) "Write memory delay %08x" ecc_mem_writel_mfsr(uint32_t val) "Write memory fault status %08x" @@ -183,26 +181,26 @@ ecc_mem_readl_ecr1(uint32_t ret) "Read event count 2 %08x" ecc_diag_mem_writeb(uint64_t addr, uint32_t val) "Write diagnostic %"PRId64" = %02x" ecc_diag_mem_readb(uint64_t addr, uint32_t ret) "Read diagnostic %"PRId64"= %02x" -# hw/fw_cfg.c +# hw/nvram/fw_cfg.c fw_cfg_write(void *s, uint8_t value) "%p %d" fw_cfg_select(void *s, uint16_t key, int ret) "%p key %d = %d" fw_cfg_read(void *s, uint8_t ret) "%p = %d" 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/hd-geometry.c +# 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" -# hw/jazz-led.c +# hw/display/jazz_led.c jazz_led_read(uint64_t addr, uint8_t val) "read addr=0x%"PRIx64": 0x%x" jazz_led_write(uint64_t addr, uint8_t new) "write addr=0x%"PRIx64": 0x%x" -# hw/lance.c +# hw/net/lance.c lance_mem_readw(uint64_t addr, uint32_t ret) "addr=%"PRIx64"val=0x%04x" lance_mem_writew(uint64_t addr, uint32_t val) "addr=%"PRIx64"val=0x%04x" -# hw/slavio_intctl.c +# hw/intc/slavio_intctl.c slavio_intctl_mem_readl(uint32_t cpu, uint64_t addr, uint32_t ret) "read cpu %d reg 0x%"PRIx64" = %x" slavio_intctl_mem_writel(uint32_t cpu, uint64_t addr, uint32_t val) "write cpu %d reg 0x%"PRIx64" = %x" slavio_intctl_mem_writel_clear(uint32_t cpu, uint32_t val, uint32_t intreg_pending) "Cleared cpu %d irq mask %x, curmask %x" @@ -216,7 +214,7 @@ slavio_check_interrupts(uint32_t pending, uint32_t intregm_disabled) "pending %x slavio_set_irq(uint32_t target_cpu, int irq, uint32_t pil, int level) "Set cpu %d irq %d -> pil %d level %d" slavio_set_timer_irq_cpu(int cpu, int level) "Set cpu %d local timer level %d" -# hw/slavio_misc.c +# hw/misc/slavio_misc.c slavio_misc_update_irq_raise(void) "Raise IRQ" slavio_misc_update_irq_lower(void) "Lower IRQ" slavio_set_power_fail(int power_failing, uint8_t config) "Power fail: %d, config: %d" @@ -237,7 +235,7 @@ slavio_sysctrl_mem_readl(uint32_t ret) "Read system control %08x" slavio_led_mem_writew(uint32_t val) "Write diagnostic LED %04x" slavio_led_mem_readw(uint32_t ret) "Read diagnostic LED %04x" -# hw/slavio_timer.c +# hw/timer/slavio_timer.c slavio_timer_get_out(uint64_t limit, uint32_t counthigh, uint32_t count) "limit %"PRIx64" count %x%08x" slavio_timer_irq(uint32_t counthigh, uint32_t count) "callback: count %x%08x" slavio_timer_mem_readl_invalid(uint64_t addr) "invalid read address %"PRIx64 @@ -252,7 +250,7 @@ slavio_timer_mem_writel_mode_counter(unsigned int timer_index) "processor %d cha slavio_timer_mem_writel_mode_invalid(void) "not system timer" slavio_timer_mem_writel_invalid(uint64_t addr) "invalid write address %"PRIx64 -# hw/sparc32_dma.c +# hw/dma/sparc32_dma.c ledma_memory_read(uint64_t addr) "DMA read addr 0x%"PRIx64 ledma_memory_write(uint64_t addr) "DMA write addr 0x%"PRIx64 sparc32_dma_set_irq_raise(void) "Raise IRQ" @@ -264,13 +262,13 @@ sparc32_dma_mem_writel(uint64_t addr, uint32_t old, uint32_t val) "write dmareg sparc32_dma_enable_raise(void) "Raise DMA enable" sparc32_dma_enable_lower(void) "Lower DMA enable" -# hw/sun4m.c +# hw/sparc/sun4m.c sun4m_cpu_interrupt(unsigned int level) "Set CPU IRQ %d" sun4m_cpu_reset_interrupt(unsigned int level) "Reset CPU IRQ %d" sun4m_cpu_set_irq_raise(int level) "Raise CPU IRQ %d" sun4m_cpu_set_irq_lower(int level) "Lower CPU IRQ %d" -# hw/sun4m_iommu.c +# hw/dma/sun4m_iommu.c sun4m_iommu_mem_readl(uint64_t addr, uint32_t ret) "read reg[%"PRIx64"] = %x" sun4m_iommu_mem_writel(uint64_t addr, uint32_t val) "write reg[%"PRIx64"] = %x" sun4m_iommu_mem_writel_ctrl(uint64_t iostart) "iostart = %"PRIx64 @@ -311,7 +309,6 @@ usb_ehci_sitd(uint32_t addr, uint32_t nxt, uint32_t active) "ITD @ %08x: next %0 usb_ehci_port_attach(uint32_t port, const char *owner, const char *device) "attach port #%d, owner %s, device %s" usb_ehci_port_detach(uint32_t port, const char *owner) "detach port #%d, owner %s" usb_ehci_port_reset(uint32_t port, int enable) "reset port #%d - %d" -usb_ehci_data(int rw, uint32_t cpage, uint32_t offset, uint32_t addr, uint32_t len, uint32_t bufpos) "write %d, cpage %d, offset 0x%03x, addr 0x%08x, len %d, bufpos %d" usb_ehci_queue_action(void *q, const char *action) "q %p: %s" usb_ehci_packet_action(void *q, void *p, const char *action) "q %p p %p: %s" usb_ehci_irq(uint32_t level, uint32_t frindex, uint32_t sts, uint32_t mask) "level %d, frindex 0x%04x, sts 0x%x, mask 0x%x" @@ -429,6 +426,7 @@ usb_uas_tmf_logical_unit_reset(int addr, uint16_t tag, int lun) "dev %d, tag 0x% usb_uas_tmf_unsupported(int addr, uint16_t tag, uint32_t function) "dev %d, tag 0x%x, function 0x%x" # hw/usb/host-linux.c +# hw/usb/host-libusb.c usb_host_open_started(int bus, int addr) "dev %d:%d" usb_host_open_success(int bus, int addr) "dev %d:%d" usb_host_open_failure(int bus, int addr) "dev %d:%d" @@ -468,7 +466,7 @@ usb_host_parse_endpoint(int bus, int addr, int ep, const char *dir, const char * usb_host_parse_unknown(int bus, int addr, int len, int type) "dev %d:%d, len %d, type %d" usb_host_parse_error(int bus, int addr, const char *errmsg) "dev %d:%d, msg %s" -# hw/scsi-bus.c +# hw/scsi/scsi-bus.c scsi_req_alloc(int target, int lun, int tag) "target %d lun %d tag %d" scsi_req_cancel(int target, int lun, int tag) "target %d lun %d tag %d" scsi_req_data(int target, int lun, int tag, int len) "target %d lun %d tag %d len %d" @@ -490,6 +488,9 @@ scsi_request_sense(int target, int lun, int tag) "target %d lun %d tag %d" vm_state_notify(int running, int reason) "running %d reason %d" load_file(const char *name, const char *path) "name %s location %s" runstate_set(int new_state) "new state %d" +g_malloc(size_t size, void *ptr) "size %zu ptr %p" +g_realloc(void *ptr, size_t size, void *newptr) "ptr %p size %zu newptr %p" +g_free(void *ptr) "ptr %p" # block/qcow2.c qcow2_writev_start_req(void *co, int64_t sector, int nb_sectors) "co %p sector %" PRIx64 " nb_sectors %d" @@ -498,6 +499,7 @@ qcow2_writev_start_part(void *co) "co %p" qcow2_writev_done_part(void *co, int cur_nr_sectors) "co %p cur_nr_sectors %d" qcow2_writev_data(void *co, uint64_t offset) "co %p offset %" PRIx64 +# block/qcow2-cluster.c qcow2_alloc_clusters_offset(void *co, uint64_t offset, int n_start, int n_end) "co %p offet %" PRIx64 " n_start %d n_end %d" qcow2_handle_copied(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64 qcow2_handle_alloc(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64 @@ -511,6 +513,7 @@ qcow2_l2_allocate_write_l2(void *bs, int l1_index) "bs %p l1_index %d" qcow2_l2_allocate_write_l1(void *bs, int l1_index) "bs %p l1_index %d" qcow2_l2_allocate_done(void *bs, int l1_index, int ret) "bs %p l1_index %d ret %d" +# block/qcow2-cache.c qcow2_cache_get(void *co, int c, uint64_t offset, bool read_from_disk) "co %p is_l2_cache %d offset %" PRIx64 " read_from_disk %d" qcow2_cache_get_replace_entry(void *co, int c, int i) "co %p is_l2_cache %d index %d" qcow2_cache_get_read(void *co, int c, int i) "co %p is_l2_cache %d index %d" @@ -542,11 +545,11 @@ qed_aio_write_prefill(void *s, void *acb, uint64_t start, size_t len, uint64_t o qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64 qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu" -# hw/g364fb.c +# hw/display/g364fb.c g364fb_read(uint64_t addr, uint32_t val) "read addr=0x%"PRIx64": 0x%x" g364fb_write(uint64_t addr, uint32_t new) "write addr=0x%"PRIx64": 0x%x" -# hw/grlib_gptimer.c +# hw/timer/grlib_gptimer.c grlib_gptimer_enable(int id, uint32_t count) "timer:%d set count 0x%x and run" grlib_gptimer_disabled(int id, uint32_t config) "timer:%d Timer disable config 0x%x" grlib_gptimer_restart(int id, uint32_t reload) "timer:%d reload val: 0x%x" @@ -555,19 +558,19 @@ grlib_gptimer_hit(int id) "timer:%d HIT" grlib_gptimer_readl(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x" grlib_gptimer_writel(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x" -# hw/grlib_irqmp.c +# hw/intc/grlib_irqmp.c grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uint32_t lvl1, uint32_t lvl2) "pend:0x%04x force:0x%04x mask:0x%04x lvl1:0x%04x lvl0:0x%04x" grlib_irqmp_ack(int intno) "interrupt:%d" grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d" grlib_irqmp_readl_unknown(uint64_t addr) "addr 0x%"PRIx64 grlib_irqmp_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x" -# hw/grlib_apbuart.c +# hw/char/grlib_apbuart.c grlib_apbuart_event(int event) "event:%d" grlib_apbuart_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x" grlib_apbuart_readl_unknown(uint64_t addr) "addr 0x%"PRIx64"" -# hw/leon3.c +# hw/sparc/leon3.c leon3_set_irq(int intno) "Set CPU IRQ %d" leon3_reset_irq(int intno) "Reset CPU IRQ %d" @@ -578,7 +581,7 @@ spice_vmc_register_interface(void *scd) "spice vmc registered interface %p" spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p" spice_vmc_event(int event) "spice vmc event %d" -# hw/lm32_pic.c +# hw/intc/lm32_pic.c lm32_pic_raise_irq(void) "Raise CPU interrupt" lm32_pic_lower_irq(void) "Lower CPU interrupt" lm32_pic_interrupt(int irq, int level) "Set IRQ%d %d" @@ -587,27 +590,27 @@ lm32_pic_set_ip(uint32_t ip) "ip 0x%08x" lm32_pic_get_im(uint32_t im) "im 0x%08x" lm32_pic_get_ip(uint32_t ip) "ip 0x%08x" -# hw/lm32_juart.c +# hw/char/lm32_juart.c lm32_juart_get_jtx(uint32_t value) "jtx 0x%08x" lm32_juart_set_jtx(uint32_t value) "jtx 0x%08x" lm32_juart_get_jrx(uint32_t value) "jrx 0x%08x" lm32_juart_set_jrx(uint32_t value) "jrx 0x%08x" -# hw/lm32_timer.c +# hw/timer/lm32_timer.c lm32_timer_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" lm32_timer_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" lm32_timer_hit(void) "timer hit" lm32_timer_irq_state(int level) "irq state %d" -# hw/lm32_uart.c +# hw/char/lm32_uart.c lm32_uart_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" lm32_uart_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" lm32_uart_irq_state(int level) "irq state %d" -# hw/lm32_sys.c +# hw/misc/lm32_sys.c lm32_sys_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -# hw/megasas.c +# hw/scsi/megasas.c megasas_init_firmware(uint64_t pa) "pa %" PRIx64 " " megasas_init_queue(uint64_t queue_pa, int queue_len, uint64_t head, uint64_t tail, uint32_t flags) "queue at %" PRIx64 " len %d head %" PRIx64 " tail %" PRIx64 " flags %x" megasas_initq_map_failed(int frame) "scmd %d: failed to map queue" @@ -617,11 +620,9 @@ megasas_qf_new(unsigned int index, void *cmd) "return new frame %x cmd %p" megasas_qf_failed(unsigned long pa) "all frames busy for frame %lx" megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, unsigned int tail, int busy) "enqueue frame %x count %d context %" PRIx64 " tail %x busy %d" megasas_qf_update(unsigned int head, unsigned int busy) "update reply queue head %x busy %d" -megasas_qf_dequeue(unsigned int index) "dequeue frame %x" megasas_qf_map_failed(int cmd, unsigned long frame) "scmd %d: frame %lu" megasas_qf_complete_noirq(uint64_t context) "context %" PRIx64 " " megasas_qf_complete(uint64_t context, unsigned int tail, unsigned int offset, int busy, unsigned int doorbell) "context %" PRIx64 " tail %x offset %d busy %d doorbell %x" -megasas_handle_frame(const char *cmd, uint64_t addr, uint64_t context, uint32_t count) "MFI cmd %s addr %" PRIx64 " context %" PRIx64 " count %d" megasas_frame_busy(uint64_t addr) "frame %" PRIx64 " busy" megasas_unhandled_frame_cmd(int cmd, uint8_t frame_cmd) "scmd %d: Unhandled MFI cmd %x" megasas_handle_scsi(const char *frame, int bus, int dev, int lun, void *sdev, unsigned long size) "%s dev %x/%x/%x sdev %p xfer %lu" @@ -644,8 +645,6 @@ megasas_io_write_start(int cmd, unsigned long lba, unsigned long count, unsigned megasas_io_complete(int cmd, uint32_t len) "scmd %d: %d bytes completed" megasas_io_read(int cmd, int bytes, int len, unsigned long offset) "scmd %d: %d/%d bytes, iov offset %lu" megasas_io_write(int cmd, int bytes, int len, unsigned long offset) "scmd %d: %d/%d bytes, iov offset %lu" -megasas_io_continue(int cmd, int bytes) "scmd %d: %d bytes left" -megasas_iovec_map_failed(int cmd, int index, unsigned long iov_size) "scmd %d: iovec %d size %lu" megasas_iovec_sgl_overflow(int cmd, int index, int limit) "scmd %d: iovec count %d limit %d" megasas_iovec_sgl_underflow(int cmd, int index) "scmd %d: iovec count %d" megasas_iovec_sgl_invalid(int cmd, int index, uint64_t pa, uint32_t len) "scmd %d: element %d pa %" PRIx64 " len %u" @@ -660,7 +659,6 @@ megasas_dcmd_internal_invalid(int cmd, int opcode) "scmd %d: Invalid internal DC megasas_dcmd_unhandled(int cmd, int opcode, int len) "scmd %d: opcode %x, len %d" megasas_dcmd_zero_sge(int cmd) "scmd %d: zero DCMD sge count" megasas_dcmd_invalid_sge(int cmd, int count) "scmd %d: invalid DCMD sge count %d" -megasas_dcmd_map_failed(int cmd) "scmd %d: Failed to map DCMD buffer" megasas_dcmd_invalid_xfer_len(int cmd, unsigned long size, unsigned long max) "scmd %d: invalid xfer len %ld, max %ld" megasas_dcmd_enter(int cmd, const char *dcmd, int len) "scmd %d: DCMD %s len %d" megasas_dcmd_dummy(int cmd, unsigned long size) "scmd %d: DCMD dummy xfer len %ld" @@ -686,7 +684,7 @@ megasas_mmio_invalid_readl(unsigned long addr) "addr 0x%lx" megasas_mmio_writel(uint32_t addr, uint32_t val) "addr 0x%x: 0x%x" megasas_mmio_invalid_writel(uint32_t addr, uint32_t val) "addr 0x%x: 0x%x" -# hw/milkymist-ac97.c +# hw/audio/milkymist-ac97.c milkymist_ac97_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_ac97_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_ac97_pulse_irq_crrequest(void) "Pulse IRQ CR request" @@ -698,15 +696,15 @@ milkymist_ac97_in_cb_transferred(int transferred) "transferred %d" milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d remaining %u" milkymist_ac97_out_cb_transferred(int transferred) "transferred %d" -# hw/milkymist-hpdmc.c +# hw/misc/milkymist-hpdmc.c milkymist_hpdmc_memory_read(uint32_t addr, uint32_t value) "addr=%08x value=%08x" milkymist_hpdmc_memory_write(uint32_t addr, uint32_t value) "addr=%08x value=%08x" -# hw/milkymist-memcard.c +# hw/sd/milkymist-memcard.c milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" -# hw/milkymist-minimac2.c +# hw/net/milkymist-minimac2.c milkymist_minimac2_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_minimac2_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_minimac2_mdio_write(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x" @@ -719,21 +717,20 @@ milkymist_minimac2_raise_irq_rx(void) "Raise IRQ RX" milkymist_minimac2_lower_irq_rx(void) "Lower IRQ RX" milkymist_minimac2_pulse_irq_tx(void) "Pulse IRQ TX" -# hw/milkymist-pfpu.c +# hw/misc/milkymist-pfpu.c milkymist_pfpu_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_pfpu_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_pfpu_vectout(uint32_t a, uint32_t b, uint32_t dma_ptr) "a %08x b %08x dma_ptr %08x" milkymist_pfpu_pulse_irq(void) "Pulse IRQ" -# hw/milkymist-softusb.c +# hw/input/milkymist-softusb.c milkymist_softusb_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_softusb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_softusb_mevt(uint8_t m) "m %d" milkymist_softusb_kevt(uint8_t m) "m %d" -milkymist_softusb_mouse_event(int dx, int dy, int dz, int bs) "dx %d dy %d dz %d bs %02x" milkymist_softusb_pulse_irq(void) "Pulse IRQ" -# hw/milkymist-sysctl.c +# hw/timer/milkymist-sysctl.c milkymist_sysctl_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_sysctl_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_sysctl_icap_write(uint32_t value) "value %08x" @@ -744,30 +741,30 @@ milkymist_sysctl_stop_timer1(void) "Stop timer1" milkymist_sysctl_pulse_irq_timer0(void) "Pulse IRQ Timer0" milkymist_sysctl_pulse_irq_timer1(void) "Pulse IRQ Timer1" -# hw/milkymist-tmu2.c +# hw/display/milkymist-tmu2.c milkymist_tmu2_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_tmu2_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_tmu2_start(void) "Start TMU" milkymist_tmu2_pulse_irq(void) "Pulse IRQ" -# hw/milkymist-uart.c +# hw/char/milkymist-uart.c milkymist_uart_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_uart_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_uart_raise_irq(void) "Raise IRQ" milkymist_uart_lower_irq(void) "Lower IRQ" -# hw/milkymist-vgafb.c +# hw/display/milkymist-vgafb.c milkymist_vgafb_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" milkymist_vgafb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" -# hw/mipsnet.c +# hw/net/mipsnet.c mipsnet_send(uint32_t size) "sending len=%u" mipsnet_receive(uint32_t size) "receiving len=%u" mipsnet_read(uint64_t addr, uint32_t val) "read addr=0x%" PRIx64 " val=0x%x" mipsnet_write(uint64_t addr, uint64_t val) "write addr=0x%" PRIx64 " val=0x%" PRIx64 "" mipsnet_irq(uint32_t isr, uint32_t intctl) "set irq to %d (%02x)" -# hw/pc87312.c +# hw/isa/pc87312.c pc87312_io_read(uint32_t addr, uint32_t val) "read addr=%x val=%x" pc87312_io_write(uint32_t addr, uint32_t val) "write addr=%x val=%x" pc87312_info_floppy(uint32_t base) "base 0x%x" @@ -818,10 +815,8 @@ xen_client_set_memory(uint64_t start_addr, unsigned long size, bool log_dirty) " xen_map_cache(uint64_t phys_addr) "want %#"PRIx64 xen_remap_bucket(uint64_t index) "index %#"PRIx64 xen_map_cache_return(void* ptr) "%p" -xen_map_block(uint64_t phys_addr, uint64_t size) "%#"PRIx64", size %#"PRIx64 -xen_unmap_block(void* addr, unsigned long size) "%p, size %#lx" -# hw/xen_platform.c +# hw/xen/xen_platform.c xen_platform_log(char *s) "xen platform: %s" # qemu-coroutine.c @@ -837,7 +832,7 @@ qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p" qemu_co_mutex_unlock_entry(void *mutex, void *self) "mutex %p self %p" qemu_co_mutex_unlock_return(void *mutex, void *self) "mutex %p self %p" -# hw/escc.c +# hw/char/escc.c escc_put_queue(char channel, int b) "channel %c put: 0x%02x" escc_get_queue(char channel, int val) "channel %c get 0x%02x" escc_update_irq(int irq) "IRQ = %d" @@ -858,7 +853,7 @@ iscsi_aio_writev(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, iscsi_aio_read16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d" iscsi_aio_readv(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p" -# hw/esp.c +# hw/scsi/esp.c esp_error_fifo_overrun(void) "FIFO overrun" esp_error_unhandled_command(uint32_t val) "unhandled command (%2.2x)" esp_error_invalid_write(uint32_t val, uint32_t addr) "invalid write of 0x%02x at [0x%x]" @@ -893,6 +888,8 @@ esp_mem_writeb_cmd_selatn(uint32_t val) "Select with ATN (%2.2x)" esp_mem_writeb_cmd_selatns(uint32_t val) "Select with ATN & stop (%2.2x)" esp_mem_writeb_cmd_ensel(uint32_t val) "Enable selection (%2.2x)" esp_mem_writeb_cmd_dissel(uint32_t val) "Disable selection (%2.2x)" + +# hw/scsi/esp-pci.c esp_pci_error_invalid_dma_direction(void) "invalid DMA transfer direction" esp_pci_error_invalid_read(uint32_t reg) "read access outside bounds (reg 0x%x)" esp_pci_error_invalid_write(uint32_t reg) "write access outside bounds (reg 0x%x)" @@ -915,7 +912,7 @@ monitor_protocol_event_emit(uint32_t event, void *data) "event=%d data=%p" monitor_protocol_event_queue(uint32_t event, void *data, uint64_t rate, uint64_t last, uint64_t now) "event=%d data=%p rate=%" PRId64 " last=%" PRId64 " now=%" PRId64 monitor_protocol_event_throttle(uint32_t event, uint64_t rate) "event=%d rate=%" PRId64 -# hw/opencores_eth.c +# hw/net/opencores_eth.c open_eth_mii_write(unsigned idx, uint16_t v) "MII[%02x] <- %04x" open_eth_mii_read(unsigned idx, uint16_t v) "MII[%02x] -> %04x" open_eth_update_irq(uint32_t v) "IRQ <- %x" @@ -985,10 +982,12 @@ mmu_helper_get_phys_addr_code(uint32_t tl, int mmu_idx, uint64_t prim_context, u mmu_helper_get_phys_addr_data(uint32_t tl, int mmu_idx, uint64_t prim_context, uint64_t sec_context, uint64_t address) "tl=%d mmu_idx=%d primary context=%"PRIx64" secondary context=%"PRIx64" address=%"PRIx64"" mmu_helper_mmu_fault(uint64_t address, uint64_t paddr, int mmu_idx, uint32_t tl, uint64_t prim_context, uint64_t sec_context) "Translate at %"PRIx64" -> %"PRIx64", mmu_idx=%d tl=%d primary context=%"PRIx64" secondary context=%"PRIx64"" -# target-sparc/int_helper.c +# target-sparc/int64_helper.c int_helper_set_softint(uint32_t softint) "new %08x" int_helper_clear_softint(uint32_t softint) "new %08x" int_helper_write_softint(uint32_t softint) "new %08x" + +# target-sparc/int32_helper.c int_helper_icache_freeze(void) "Instruction cache: freeze" int_helper_dcache_freeze(void) "Data cache: freeze" @@ -1007,7 +1006,7 @@ 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_map_wait(void *dbs) "dbs=%p" -# console.h +# ui/console.c console_gfx_new(void) "" console_txt_new(int w, int h) "%dx%d" console_select(int nr) "%d" @@ -1017,9 +1016,9 @@ displaysurface_create_from(void *display_surface, int w, int h, int bpp, int swa displaysurface_free(void *display_surface) "surface=%p" displaychangelistener_register(void *dcl, const char *name) "%p [ %s ]" displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]" - -# vga.c ppm_save(const char *filename, void *display_surface) "%s surface=%p" + +# hw/display/vmware_vga.c vmware_value_read(uint32_t index, uint32_t value) "index %d, value 0x%x" vmware_value_write(uint32_t index, uint32_t value) "index %d, value 0x%x" vmware_palette_read(uint32_t index, uint32_t value) "index %d, value 0x%x" @@ -1029,7 +1028,6 @@ vmware_scratch_write(uint32_t index, uint32_t value) "index %d, value 0x%x" vmware_setmode(uint32_t w, uint32_t h, uint32_t bpp) "%dx%d @ %d bpp" # savevm.c - savevm_section_start(void) "" savevm_section_end(unsigned int section_id) "section_id %u" @@ -1038,7 +1036,7 @@ migration_bitmap_sync_start(void) "" migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64"" migration_throttle(void) "" -# hw/qxl.c +# hw/display/qxl.c disable qxl_interface_set_mm_time(int qid, uint32_t mm_time) "%d %d" disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t val) "%d %s addr=%u val=%u" qxl_create_guest_primary(int qid, uint32_t width, uint32_t height, uint64_t mem, uint32_t format, uint32_t position) "%d %ux%u mem=%" PRIx64 " %u,%u" @@ -1076,14 +1074,6 @@ qxl_ring_res_push_rest(int qid, uint32_t ring_has, uint32_t ring_size, uint32_t qxl_ring_res_put(int qid, uint32_t free_res) "%d #res=%d" qxl_set_mode(int qid, int modenr, uint32_t x_res, uint32_t y_res, uint32_t bits, uint64_t devmem) "%d mode=%d [ x=%d y=%d @ bpp=%d devmem=0x%" PRIx64 " ]" qxl_soft_reset(int qid) "%d" -qemu_spice_add_memslot(int qid, uint32_t slot_id, unsigned long virt_start, unsigned long virt_end, int async) "%d %u: host virt 0x%lx - 0x%lx async=%d" -qemu_spice_del_memslot(int qid, uint32_t gid, uint32_t slot_id) "%d gid=%u sid=%u" -qemu_spice_create_primary_surface(int qid, uint32_t sid, void *surface, int async) "%d sid=%u surface=%p async=%d" -qemu_spice_destroy_primary_surface(int qid, uint32_t sid, int async) "%d sid=%u async=%d" -qemu_spice_wakeup(uint32_t qid) "%d" -qemu_spice_start(uint32_t qid) "%d" -qemu_spice_stop(uint32_t qid) "%d" -qemu_spice_create_update(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "lr %d -> %d, tb -> %d -> %d" qxl_spice_destroy_surfaces_complete(int qid) "%d" qxl_spice_destroy_surfaces(int qid, int async) "%d async=%d" qxl_spice_destroy_surface_wait_complete(int qid, uint32_t id) "%d sid=%d" @@ -1108,13 +1098,21 @@ qxl_client_monitors_config_capped(int qid, int requested, int limit) "%d %d %d" qxl_client_monitors_config_crc(int qid, unsigned size, uint32_t crc32) "%d %u %u" qxl_set_client_capabilities_unsupported_by_revision(int qid, int revision) "%d revision=%d" -# hw/qxl-render.c +# ui/spice-display.c +qemu_spice_add_memslot(int qid, uint32_t slot_id, unsigned long virt_start, unsigned long virt_end, int async) "%d %u: host virt 0x%lx - 0x%lx async=%d" +qemu_spice_del_memslot(int qid, uint32_t gid, uint32_t slot_id) "%d gid=%u sid=%u" +qemu_spice_create_primary_surface(int qid, uint32_t sid, void *surface, int async) "%d sid=%u surface=%p async=%d" +qemu_spice_destroy_primary_surface(int qid, uint32_t sid, int async) "%d sid=%u async=%d" +qemu_spice_wakeup(uint32_t qid) "%d" +qemu_spice_create_update(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "lr %d -> %d, tb -> %d -> %d" + +# hw/display/qxl-render.c qxl_render_blit_guest_primary_initialized(void) "" qxl_render_blit(int32_t stride, int32_t left, int32_t right, int32_t top, int32_t bottom) "stride=%d [%d, %d, %d, %d]" qxl_render_guest_primary_resized(int32_t width, int32_t height, int32_t stride, int32_t bytes_pp, int32_t bits_pp) "%dx%d, stride %d, bpp %d, depth %d" qxl_render_update_area_done(void *cookie) "%p" -# hw/spapr_pci.c +# hw/ppc/spapr_pci.c spapr_pci_msi(const char *msg, uint32_t n, uint32_t ca) "%s (device#%d, cfg=%x)" spapr_pci_msi_setup(const char *name, unsigned vector, uint64_t addr) "dev\"%s\" vector %u, addr=%"PRIx64 spapr_pci_rtas_ibm_change_msi(unsigned func, unsigned req) "func %u, requested %u" @@ -1122,7 +1120,7 @@ spapr_pci_rtas_ibm_query_interrupt_source_number(unsigned ioa, unsigned intr) "q spapr_pci_msi_write(uint64_t addr, uint64_t data, uint32_t dt_irq) "@%"PRIx64"<=%"PRIx64" IRQ %u" spapr_pci_lsi_set(const char *busname, int pin, uint32_t irq) "%s PIN%d IRQ %u" -# hw/xics.c +# hw/ppc/xics.c xics_icp_check_ipi(int server, uint8_t mfrr) "CPU %d can take IPI mfrr=%#x" xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR %#"PRIx32"->%#"PRIx32 xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d given XIRR %#"PRIx32" new XIRR %#"PRIx32 @@ -1135,7 +1133,7 @@ xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_ xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]" xics_ics_eoi(int nr) "ics_eoi: irq %#x" -# hbitmap.c +# util/hbitmap.c hbitmap_iter_skip_words(const void *hb, void *hbi, uint64_t pos, unsigned long cur) "hb %p hbi %p pos %"PRId64" cur 0x%lx" hbitmap_reset(void *hb, uint64_t start, uint64_t count, uint64_t sbit, uint64_t ebit) "hb %p items %"PRIu64",%"PRIu64" bits %"PRIu64"..%"PRIu64 hbitmap_set(void *hb, uint64_t start, uint64_t count, uint64_t sbit, uint64_t ebit) "hb %p items %"PRIu64",%"PRIu64" bits %"PRIu64"..%"PRIu64 |