diff options
123 files changed, 829 insertions, 454 deletions
diff --git a/Makefile.objs b/Makefile.objs index 6167e7b17d..2100845ce2 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -49,7 +49,6 @@ common-obj-$(CONFIG_POSIX) += os-posix.o common-obj-$(CONFIG_LINUX) += fsdev/ common-obj-y += migration/ -common-obj-y += page_cache.o #aio.o common-obj-$(CONFIG_SPICE) += spice-qemu-char.o diff --git a/block/curl.c b/block/curl.c index aa6e8cc0e5..2a244e2439 100644 --- a/block/curl.c +++ b/block/curl.c @@ -76,15 +76,12 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, #define CURL_TIMEOUT_DEFAULT 5 #define CURL_TIMEOUT_MAX 10000 -#define FIND_RET_NONE 0 -#define FIND_RET_OK 1 -#define FIND_RET_WAIT 2 - #define CURL_BLOCK_OPT_URL "url" #define CURL_BLOCK_OPT_READAHEAD "readahead" #define CURL_BLOCK_OPT_SSLVERIFY "sslverify" #define CURL_BLOCK_OPT_TIMEOUT "timeout" #define CURL_BLOCK_OPT_COOKIE "cookie" +#define CURL_BLOCK_OPT_COOKIE_SECRET "cookie-secret" #define CURL_BLOCK_OPT_USERNAME "username" #define CURL_BLOCK_OPT_PASSWORD_SECRET "password-secret" #define CURL_BLOCK_OPT_PROXY_USERNAME "proxy-username" @@ -93,14 +90,17 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, struct BDRVCURLState; typedef struct CURLAIOCB { - BlockAIOCB common; + Coroutine *co; QEMUIOVector *qiov; - int64_t sector_num; - int nb_sectors; + uint64_t offset; + uint64_t bytes; + int ret; size_t start; size_t end; + + QSIMPLEQ_ENTRY(CURLAIOCB) next; } CURLAIOCB; typedef struct CURLSocket { @@ -115,7 +115,7 @@ typedef struct CURLState CURL *curl; QLIST_HEAD(, CURLSocket) sockets; char *orig_buf; - size_t buf_start; + uint64_t buf_start; size_t buf_off; size_t buf_len; char range[128]; @@ -126,7 +126,7 @@ typedef struct CURLState typedef struct BDRVCURLState { CURLM *multi; QEMUTimer timer; - size_t len; + uint64_t len; CURLState states[CURL_NUM_STATES]; char *url; size_t readahead_size; @@ -136,6 +136,7 @@ typedef struct BDRVCURLState { bool accept_range; AioContext *aio_context; QemuMutex mutex; + QSIMPLEQ_HEAD(, CURLAIOCB) free_state_waitq; char *username; char *password; char *proxyusername; @@ -147,6 +148,7 @@ static void curl_multi_do(void *arg); static void curl_multi_read(void *arg); #ifdef NEED_CURL_TIMER_CALLBACK +/* Called from curl_multi_do_locked, with s->mutex held. */ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque) { BDRVCURLState *s = opaque; @@ -163,6 +165,7 @@ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque) } #endif +/* Called from curl_multi_do_locked, with s->mutex held. */ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, void *userp, void *sp) { @@ -212,6 +215,7 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, return 0; } +/* Called from curl_multi_do_locked, with s->mutex held. */ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) { BDRVCURLState *s = opaque; @@ -226,6 +230,7 @@ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) return realsize; } +/* Called from curl_multi_do_locked, with s->mutex held. */ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) { CURLState *s = ((CURLState*)opaque); @@ -253,7 +258,7 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) continue; if ((s->buf_off >= acb->end)) { - size_t request_length = acb->nb_sectors * BDRV_SECTOR_SIZE; + size_t request_length = acb->bytes; qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start, acb->end - acb->start); @@ -264,9 +269,11 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) request_length - offset); } - acb->common.cb(acb->common.opaque, 0); - qemu_aio_unref(acb); + acb->ret = 0; s->acb[i] = NULL; + qemu_mutex_unlock(&s->s->mutex); + aio_co_wake(acb->co); + qemu_mutex_lock(&s->s->mutex); } } @@ -275,18 +282,19 @@ read_end: return size * nmemb; } -static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len, - CURLAIOCB *acb) +/* Called with s->mutex held. */ +static bool curl_find_buf(BDRVCURLState *s, uint64_t start, uint64_t len, + CURLAIOCB *acb) { int i; - size_t end = start + len; - size_t clamped_end = MIN(end, s->len); - size_t clamped_len = clamped_end - start; + uint64_t end = start + len; + uint64_t clamped_end = MIN(end, s->len); + uint64_t clamped_len = clamped_end - start; for (i=0; i<CURL_NUM_STATES; i++) { CURLState *state = &s->states[i]; - size_t buf_end = (state->buf_start + state->buf_off); - size_t buf_fend = (state->buf_start + state->buf_len); + uint64_t buf_end = (state->buf_start + state->buf_off); + uint64_t buf_fend = (state->buf_start + state->buf_len); if (!state->orig_buf) continue; @@ -305,9 +313,8 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len, if (clamped_len < len) { qemu_iovec_memset(acb->qiov, clamped_len, 0, len - clamped_len); } - acb->common.cb(acb->common.opaque, 0); - - return FIND_RET_OK; + acb->ret = 0; + return true; } // Wait for unfinished chunks @@ -325,13 +332,13 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len, for (j=0; j<CURL_NUM_ACB; j++) { if (!state->acb[j]) { state->acb[j] = acb; - return FIND_RET_WAIT; + return true; } } } } - return FIND_RET_NONE; + return false; } /* Called with s->mutex held. */ @@ -376,11 +383,11 @@ static void curl_multi_check_completion(BDRVCURLState *s) continue; } + acb->ret = -EIO; + state->acb[i] = NULL; qemu_mutex_unlock(&s->mutex); - acb->common.cb(acb->common.opaque, -EIO); + aio_co_wake(acb->co); qemu_mutex_lock(&s->mutex); - qemu_aio_unref(acb); - state->acb[i] = NULL; } } @@ -449,32 +456,28 @@ static void curl_multi_timeout_do(void *arg) #endif } -static CURLState *curl_init_state(BlockDriverState *bs, BDRVCURLState *s) +/* Called with s->mutex held. */ +static CURLState *curl_find_state(BDRVCURLState *s) { CURLState *state = NULL; - int i, j; - - do { - for (i=0; i<CURL_NUM_STATES; i++) { - for (j=0; j<CURL_NUM_ACB; j++) - if (s->states[i].acb[j]) - continue; - if (s->states[i].in_use) - continue; + int i; + for (i = 0; i < CURL_NUM_STATES; i++) { + if (!s->states[i].in_use) { state = &s->states[i]; state->in_use = 1; break; } - if (!state) { - aio_poll(bdrv_get_aio_context(bs), true); - } - } while(!state); + } + return state; +} +static int curl_init_state(BDRVCURLState *s, CURLState *state) +{ if (!state->curl) { state->curl = curl_easy_init(); if (!state->curl) { - return NULL; + return -EIO; } curl_easy_setopt(state->curl, CURLOPT_URL, s->url); curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER, @@ -527,11 +530,18 @@ static CURLState *curl_init_state(BlockDriverState *bs, BDRVCURLState *s) QLIST_INIT(&state->sockets); state->s = s; - return state; + return 0; } +/* Called with s->mutex held. */ static void curl_clean_state(CURLState *s) { + CURLAIOCB *next; + int j; + for (j = 0; j < CURL_NUM_ACB; j++) { + assert(!s->acb[j]); + } + if (s->s->multi) curl_multi_remove_handle(s->s->multi, s->curl); @@ -543,6 +553,14 @@ static void curl_clean_state(CURLState *s) } s->in_use = 0; + + next = QSIMPLEQ_FIRST(&s->s->free_state_waitq); + if (next) { + QSIMPLEQ_REMOVE_HEAD(&s->s->free_state_waitq, next); + qemu_mutex_unlock(&s->s->mutex); + aio_co_wake(next->co); + qemu_mutex_lock(&s->s->mutex); + } } static void curl_parse_filename(const char *filename, QDict *options, @@ -556,6 +574,7 @@ static void curl_detach_aio_context(BlockDriverState *bs) BDRVCURLState *s = bs->opaque; int i; + qemu_mutex_lock(&s->mutex); for (i = 0; i < CURL_NUM_STATES; i++) { if (s->states[i].in_use) { curl_clean_state(&s->states[i]); @@ -571,6 +590,7 @@ static void curl_detach_aio_context(BlockDriverState *bs) curl_multi_cleanup(s->multi); s->multi = NULL; } + qemu_mutex_unlock(&s->mutex); timer_del(&s->timer); } @@ -624,6 +644,11 @@ static QemuOptsList runtime_opts = { .help = "Pass the cookie or list of cookies with each request" }, { + .name = CURL_BLOCK_OPT_COOKIE_SECRET, + .type = QEMU_OPT_STRING, + .help = "ID of secret used as cookie passed with each request" + }, + { .name = CURL_BLOCK_OPT_USERNAME, .type = QEMU_OPT_STRING, .help = "Username for HTTP auth" @@ -657,6 +682,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, Error *local_err = NULL; const char *file; const char *cookie; + const char *cookie_secret; double d; const char *secretid; const char *protocol_delimiter; @@ -668,6 +694,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, return -EROFS; } + qemu_mutex_init(&s->mutex); opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); if (local_err) { @@ -693,7 +720,22 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true); cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE); - s->cookie = g_strdup(cookie); + cookie_secret = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE_SECRET); + + if (cookie && cookie_secret) { + error_setg(errp, + "curl driver cannot handle both cookie and cookie secret"); + goto out_noclean; + } + + if (cookie_secret) { + s->cookie = qcrypto_secret_lookup_as_utf8(cookie_secret, errp); + if (!s->cookie) { + goto out_noclean; + } + } else { + s->cookie = g_strdup(cookie); + } file = qemu_opt_get(opts, CURL_BLOCK_OPT_URL); if (file == NULL) { @@ -736,14 +778,22 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, } DPRINTF("CURL: Opening %s\n", file); + QSIMPLEQ_INIT(&s->free_state_waitq); s->aio_context = bdrv_get_aio_context(bs); s->url = g_strdup(file); - state = curl_init_state(bs, s); - if (!state) + qemu_mutex_lock(&s->mutex); + state = curl_find_state(s); + qemu_mutex_unlock(&s->mutex); + if (!state) { goto out_noclean; + } // Get file size + if (curl_init_state(s, state) < 0) { + goto out; + } + s->accept_range = false; curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1); curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION, @@ -771,7 +821,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, } #endif - s->len = (size_t)d; + s->len = d; if ((!strncasecmp(s->url, "http://", strlen("http://")) || !strncasecmp(s->url, "https://", strlen("https://"))) @@ -780,13 +830,14 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, "Server does not support 'range' (byte ranges)."); goto out; } - DPRINTF("CURL: Size = %zd\n", s->len); + DPRINTF("CURL: Size = %" PRIu64 "\n", s->len); + qemu_mutex_lock(&s->mutex); curl_clean_state(state); + qemu_mutex_unlock(&s->mutex); curl_easy_cleanup(state->curl); state->curl = NULL; - qemu_mutex_init(&s->mutex); curl_attach_aio_context(bs, bdrv_get_aio_context(bs)); qemu_opts_del(opts); @@ -797,53 +848,51 @@ out: curl_easy_cleanup(state->curl); state->curl = NULL; out_noclean: + qemu_mutex_destroy(&s->mutex); g_free(s->cookie); g_free(s->url); qemu_opts_del(opts); return -EINVAL; } -static const AIOCBInfo curl_aiocb_info = { - .aiocb_size = sizeof(CURLAIOCB), -}; - - -static void curl_readv_bh_cb(void *p) +static void curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb) { CURLState *state; int running; - int ret = -EINPROGRESS; - CURLAIOCB *acb = p; - BlockDriverState *bs = acb->common.bs; BDRVCURLState *s = bs->opaque; - size_t start = acb->sector_num * BDRV_SECTOR_SIZE; - size_t end; + uint64_t start = acb->offset; + uint64_t end; qemu_mutex_lock(&s->mutex); // In case we have the requested data already (e.g. read-ahead), // we can just call the callback and be done. - switch (curl_find_buf(s, start, acb->nb_sectors * BDRV_SECTOR_SIZE, acb)) { - case FIND_RET_OK: - qemu_aio_unref(acb); - // fall through - case FIND_RET_WAIT: - goto out; - default: - break; + if (curl_find_buf(s, start, acb->bytes, acb)) { + goto out; } // No cache found, so let's start a new request - state = curl_init_state(acb->common.bs, s); - if (!state) { - ret = -EIO; + for (;;) { + state = curl_find_state(s); + if (state) { + break; + } + QSIMPLEQ_INSERT_TAIL(&s->free_state_waitq, acb, next); + qemu_mutex_unlock(&s->mutex); + qemu_coroutine_yield(); + qemu_mutex_lock(&s->mutex); + } + + if (curl_init_state(s, state) < 0) { + curl_clean_state(state); + acb->ret = -EIO; goto out; } acb->start = 0; - acb->end = MIN(acb->nb_sectors * BDRV_SECTOR_SIZE, s->len - start); + acb->end = MIN(acb->bytes, s->len - start); state->buf_off = 0; g_free(state->orig_buf); @@ -853,14 +902,14 @@ static void curl_readv_bh_cb(void *p) state->orig_buf = g_try_malloc(state->buf_len); if (state->buf_len && state->orig_buf == NULL) { curl_clean_state(state); - ret = -ENOMEM; + acb->ret = -ENOMEM; goto out; } state->acb[0] = acb; - snprintf(state->range, 127, "%zd-%zd", start, end); - DPRINTF("CURL (AIO): Reading %llu at %zd (%s)\n", - (acb->nb_sectors * BDRV_SECTOR_SIZE), start, state->range); + snprintf(state->range, 127, "%" PRIu64 "-%" PRIu64, start, end); + DPRINTF("CURL (AIO): Reading %" PRIu64 " at %" PRIu64 " (%s)\n", + acb->bytes, start, state->range); curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range); curl_multi_add_handle(s->multi, state->curl); @@ -870,26 +919,24 @@ static void curl_readv_bh_cb(void *p) out: qemu_mutex_unlock(&s->mutex); - if (ret != -EINPROGRESS) { - acb->common.cb(acb->common.opaque, ret); - qemu_aio_unref(acb); - } } -static BlockAIOCB *curl_aio_readv(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque) +static int coroutine_fn curl_co_preadv(BlockDriverState *bs, + uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags) { - CURLAIOCB *acb; - - acb = qemu_aio_get(&curl_aiocb_info, bs, cb, opaque); - - acb->qiov = qiov; - acb->sector_num = sector_num; - acb->nb_sectors = nb_sectors; - - aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), curl_readv_bh_cb, acb); - return &acb->common; + CURLAIOCB acb = { + .co = qemu_coroutine_self(), + .ret = -EINPROGRESS, + .qiov = qiov, + .offset = offset, + .bytes = bytes + }; + + curl_setup_preadv(bs, &acb); + while (acb.ret == -EINPROGRESS) { + qemu_coroutine_yield(); + } + return acb.ret; } static void curl_close(BlockDriverState *bs) @@ -920,7 +967,7 @@ static BlockDriver bdrv_http = { .bdrv_close = curl_close, .bdrv_getlength = curl_getlength, - .bdrv_aio_readv = curl_aio_readv, + .bdrv_co_preadv = curl_co_preadv, .bdrv_detach_aio_context = curl_detach_aio_context, .bdrv_attach_aio_context = curl_attach_aio_context, @@ -936,7 +983,7 @@ static BlockDriver bdrv_https = { .bdrv_close = curl_close, .bdrv_getlength = curl_getlength, - .bdrv_aio_readv = curl_aio_readv, + .bdrv_co_preadv = curl_co_preadv, .bdrv_detach_aio_context = curl_detach_aio_context, .bdrv_attach_aio_context = curl_attach_aio_context, @@ -952,7 +999,7 @@ static BlockDriver bdrv_ftp = { .bdrv_close = curl_close, .bdrv_getlength = curl_getlength, - .bdrv_aio_readv = curl_aio_readv, + .bdrv_co_preadv = curl_co_preadv, .bdrv_detach_aio_context = curl_detach_aio_context, .bdrv_attach_aio_context = curl_attach_aio_context, @@ -968,7 +1015,7 @@ static BlockDriver bdrv_ftps = { .bdrv_close = curl_close, .bdrv_getlength = curl_getlength, - .bdrv_aio_readv = curl_aio_readv, + .bdrv_co_preadv = curl_co_preadv, .bdrv_detach_aio_context = curl_detach_aio_context, .bdrv_attach_aio_context = curl_attach_aio_context, diff --git a/block/qcow.c b/block/qcow.c index 5d147b962e..95ab123407 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -32,7 +32,7 @@ #include <zlib.h> #include "qapi/qmp/qerror.h" #include "crypto/cipher.h" -#include "migration/migration.h" +#include "migration/blocker.h" /**************************************************************/ /* QEMU COW block driver with compression and encryption support */ diff --git a/block/vdi.c b/block/vdi.c index d12d9cdc79..79af47763b 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -55,7 +55,7 @@ #include "sysemu/block-backend.h" #include "qemu/module.h" #include "qemu/bswap.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qemu/coroutine.h" #include "qemu/cutils.h" #include "qemu/uuid.h" diff --git a/block/vhdx.c b/block/vhdx.c index e8fe3fb5e9..8b270b57c9 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -24,7 +24,7 @@ #include "qemu/crc32c.h" #include "qemu/bswap.h" #include "block/vhdx.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qemu/uuid.h" /* Options for VHDX creation */ diff --git a/block/vmdk.c b/block/vmdk.c index c61b9cc8e0..55581b03fe 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -31,7 +31,7 @@ #include "qemu/error-report.h" #include "qemu/module.h" #include "qemu/bswap.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qemu/cutils.h" #include <zlib.h> diff --git a/block/vpc.c b/block/vpc.c index ecfee77149..4240ba9d1c 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -28,7 +28,7 @@ #include "block/block_int.h" #include "sysemu/block-backend.h" #include "qemu/module.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qemu/bswap.h" #include "qemu/uuid.h" diff --git a/block/vvfat.c b/block/vvfat.c index 9c82371360..426ca70e35 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -28,7 +28,7 @@ #include "block/block_int.h" #include "qemu/module.h" #include "qemu/bswap.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qapi/qmp/qint.h" #include "qapi/qmp/qbool.h" #include "qapi/qmp/qstring.h" @@ -2015,7 +2015,7 @@ if test "$xen" != "no" ; then else xen_libs="-lxenstore -lxenctrl -lxenguest" - xen_stable_libs="-lxencall -lxenforeignmemory -lxengnttab -lxenevtchn" + xen_stable_libs="-lxenforeignmemory -lxengnttab -lxenevtchn" # First we test whether Xen headers and libraries are available. # If no, we are done and there is no Xen support. diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c index 61e1657e41..9efb9dac0e 100644 --- a/contrib/libvhost-user/libvhost-user.c +++ b/contrib/libvhost-user/libvhost-user.c @@ -1031,6 +1031,11 @@ vu_queue_get_avail_bytes(VuDev *dev, VuVirtq *vq, unsigned int *in_bytes, idx = vq->last_avail_idx; total_bufs = in_total = out_total = 0; + if (unlikely(dev->broken) || + unlikely(!vq->vring.avail)) { + goto done; + } + while ((rc = virtqueue_num_heads(dev, vq, idx)) > 0) { unsigned int max, num_bufs, indirect = 0; struct vring_desc *desc; @@ -1121,11 +1126,16 @@ vu_queue_avail_bytes(VuDev *dev, VuVirtq *vq, unsigned int in_bytes, /* Fetch avail_idx from VQ memory only when we really need to know if * guest has added some buffers. */ -int +bool vu_queue_empty(VuDev *dev, VuVirtq *vq) { + if (unlikely(dev->broken) || + unlikely(!vq->vring.avail)) { + return true; + } + if (vq->shadow_avail_idx != vq->last_avail_idx) { - return 0; + return false; } return vring_avail_idx(vq) == vq->last_avail_idx; @@ -1174,7 +1184,8 @@ vring_notify(VuDev *dev, VuVirtq *vq) void vu_queue_notify(VuDev *dev, VuVirtq *vq) { - if (unlikely(dev->broken)) { + if (unlikely(dev->broken) || + unlikely(!vq->vring.avail)) { return; } @@ -1291,7 +1302,8 @@ vu_queue_pop(VuDev *dev, VuVirtq *vq, size_t sz) struct vring_desc *desc; int rc; - if (unlikely(dev->broken)) { + if (unlikely(dev->broken) || + unlikely(!vq->vring.avail)) { return NULL; } @@ -1445,7 +1457,8 @@ vu_queue_fill(VuDev *dev, VuVirtq *vq, { struct vring_used_elem uelem; - if (unlikely(dev->broken)) { + if (unlikely(dev->broken) || + unlikely(!vq->vring.avail)) { return; } @@ -1474,7 +1487,8 @@ vu_queue_flush(VuDev *dev, VuVirtq *vq, unsigned int count) { uint16_t old, new; - if (unlikely(dev->broken)) { + if (unlikely(dev->broken) || + unlikely(!vq->vring.avail)) { return; } diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h index 156b50e989..af02a31ebe 100644 --- a/contrib/libvhost-user/libvhost-user.h +++ b/contrib/libvhost-user/libvhost-user.h @@ -327,13 +327,13 @@ void vu_queue_set_notification(VuDev *dev, VuVirtq *vq, int enable); bool vu_queue_enabled(VuDev *dev, VuVirtq *vq); /** - * vu_queue_enabled: + * vu_queue_empty: * @dev: a VuDev context * @vq: a VuVirtq queue * - * Returns: whether the queue is empty. + * Returns: true if the queue is empty or not ready. */ -int vu_queue_empty(VuDev *dev, VuVirtq *vq); +bool vu_queue_empty(VuDev *dev, VuVirtq *vq); /** * vu_queue_notify: @@ -465,18 +465,20 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x } /* Called from RCU critical section */ -IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr, - bool is_write) +static MemoryRegionSection address_space_do_translate(AddressSpace *as, + hwaddr addr, + hwaddr *xlat, + hwaddr *plen, + bool is_write, + bool is_mmio) { - IOMMUTLBEntry iotlb = {0}; + IOMMUTLBEntry iotlb; MemoryRegionSection *section; MemoryRegion *mr; for (;;) { AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch); - section = address_space_lookup_region(d, addr, false); - addr = addr - section->offset_within_address_space - + section->offset_within_region; + section = address_space_translate_internal(d, addr, &addr, plen, is_mmio); mr = section->mr; if (!mr->iommu_ops) { @@ -484,55 +486,88 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr, } iotlb = mr->iommu_ops->translate(mr, addr, is_write); + addr = ((iotlb.translated_addr & ~iotlb.addr_mask) + | (addr & iotlb.addr_mask)); + *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1); if (!(iotlb.perm & (1 << is_write))) { - iotlb.target_as = NULL; - break; + goto translate_fail; } - addr = ((iotlb.translated_addr & ~iotlb.addr_mask) - | (addr & iotlb.addr_mask)); as = iotlb.target_as; } - return iotlb; + *xlat = addr; + + return *section; + +translate_fail: + return (MemoryRegionSection) { .mr = &io_mem_unassigned }; } /* Called from RCU critical section */ -MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, - hwaddr *xlat, hwaddr *plen, - bool is_write) +IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr, + bool is_write) { - IOMMUTLBEntry iotlb; - MemoryRegionSection *section; - MemoryRegion *mr; + MemoryRegionSection section; + hwaddr xlat, plen; - for (;;) { - AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch); - section = address_space_translate_internal(d, addr, &addr, plen, true); - mr = section->mr; + /* Try to get maximum page mask during translation. */ + plen = (hwaddr)-1; - if (!mr->iommu_ops) { - break; - } + /* This can never be MMIO. */ + section = address_space_do_translate(as, addr, &xlat, &plen, + is_write, false); - iotlb = mr->iommu_ops->translate(mr, addr, is_write); - addr = ((iotlb.translated_addr & ~iotlb.addr_mask) - | (addr & iotlb.addr_mask)); - *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1); - if (!(iotlb.perm & (1 << is_write))) { - mr = &io_mem_unassigned; - break; - } + /* Illegal translation */ + if (section.mr == &io_mem_unassigned) { + goto iotlb_fail; + } - as = iotlb.target_as; + /* Convert memory region offset into address space offset */ + xlat += section.offset_within_address_space - + section.offset_within_region; + + if (plen == (hwaddr)-1) { + /* + * We use default page size here. Logically it only happens + * for identity mappings. + */ + plen = TARGET_PAGE_SIZE; } + /* Convert to address mask */ + plen -= 1; + + return (IOMMUTLBEntry) { + .target_as = section.address_space, + .iova = addr & ~plen, + .translated_addr = xlat & ~plen, + .addr_mask = plen, + /* IOTLBs are for DMAs, and DMA only allows on RAMs. */ + .perm = IOMMU_RW, + }; + +iotlb_fail: + return (IOMMUTLBEntry) {0}; +} + +/* Called from RCU critical section */ +MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, + hwaddr *xlat, hwaddr *plen, + bool is_write) +{ + MemoryRegion *mr; + MemoryRegionSection section; + + /* This can be MMIO, so setup MMIO bit. */ + section = address_space_do_translate(as, addr, xlat, plen, is_write, true); + mr = section.mr; + if (xen_enabled() && memory_access_is_direct(mr, is_write)) { hwaddr page = ((addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE) - addr; *plen = MIN(page, *plen); } - *xlat = addr; return mr; } @@ -2106,10 +2141,10 @@ void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr) * In that case just map until the end of the page. */ if (block->offset == 0) { - return xen_map_cache(addr, 0, 0); + return xen_map_cache(addr, 0, 0, false); } - block->host = xen_map_cache(block->offset, block->max_length, 1); + block->host = xen_map_cache(block->offset, block->max_length, 1, false); } return ramblock_ptr(block, addr); } @@ -2139,10 +2174,10 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr, * In that case just map the requested area. */ if (block->offset == 0) { - return xen_map_cache(addr, *size, 1); + return xen_map_cache(addr, *size, 1, true); } - block->host = xen_map_cache(block->offset, block->max_length, 1); + block->host = xen_map_cache(block->offset, block->max_length, 1, true); } return ramblock_ptr(block, addr); @@ -1275,17 +1275,22 @@ void hmp_loadvm(Monitor *mon, const QDict *qdict) { int saved_vm_running = runstate_is_running(); const char *name = qdict_get_str(qdict, "name"); + Error *err = NULL; vm_stop(RUN_STATE_RESTORE_VM); - if (load_vmstate(name) == 0 && saved_vm_running) { + if (load_vmstate(name, &err) == 0 && saved_vm_running) { vm_start(); } + hmp_handle_error(mon, &err); } void hmp_savevm(Monitor *mon, const QDict *qdict) { - save_vmstate(qdict_get_try_str(qdict, "name")); + Error *err = NULL; + + save_vmstate(qdict_get_try_str(qdict, "name"), &err); + hmp_handle_error(mon, &err); } void hmp_delvm(Monitor *mon, const QDict *qdict) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index c80ba67389..ab3e22f231 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -23,7 +23,7 @@ #include "9p-xattr.h" #include "coth.h" #include "trace.h" -#include "migration/migration.h" +#include "migration/blocker.h" int open_fd_hw; int total_open_fd; diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c index 9c7f41af99..5df97c90fa 100644 --- a/hw/9pfs/xen-9p-backend.c +++ b/hw/9pfs/xen-9p-backend.c @@ -332,12 +332,14 @@ static int xen_9pfs_connect(struct XenDevice *xendev) str = g_strdup_printf("ring-ref%u", i); if (xenstore_read_fe_int(&xen_9pdev->xendev, str, &xen_9pdev->rings[i].ref) == -1) { + g_free(str); goto out; } g_free(str); str = g_strdup_printf("event-channel-%u", i); if (xenstore_read_fe_int(&xen_9pdev->xendev, str, &xen_9pdev->rings[i].evtchn) == -1) { + g_free(str); goto out; } g_free(str); @@ -378,7 +380,7 @@ static int xen_9pfs_connect(struct XenDevice *xendev) if (xen_9pdev->rings[i].evtchndev == NULL) { goto out; } - fcntl(xenevtchn_fd(xen_9pdev->rings[i].evtchndev), F_SETFD, FD_CLOEXEC); + qemu_set_cloexec(xenevtchn_fd(xen_9pdev->rings[i].evtchndev)); xen_9pdev->rings[i].local_port = xenevtchn_bind_interdomain (xen_9pdev->rings[i].evtchndev, xendev->dom, diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index be496c817c..36a6cc450e 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -1600,6 +1600,33 @@ build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, (void *)rsdt, "RSDT", rsdt_len, 1, oem_id, oem_table_id); } +/* Build xsdt table */ +void +build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, + const char *oem_id, const char *oem_table_id) +{ + int i; + unsigned xsdt_entries_offset; + AcpiXsdtDescriptorRev2 *xsdt; + const unsigned table_data_len = (sizeof(uint64_t) * table_offsets->len); + const unsigned xsdt_entry_size = sizeof(xsdt->table_offset_entry[0]); + const size_t xsdt_len = sizeof(*xsdt) + table_data_len; + + xsdt = acpi_data_push(table_data, xsdt_len); + xsdt_entries_offset = (char *)xsdt->table_offset_entry - table_data->data; + for (i = 0; i < table_offsets->len; ++i) { + uint64_t ref_tbl_offset = g_array_index(table_offsets, uint32_t, i); + uint64_t xsdt_entry_offset = xsdt_entries_offset + xsdt_entry_size * i; + + /* xsdt->table_offset_entry to be filled by Guest linker */ + bios_linker_loader_add_pointer(linker, + ACPI_BUILD_TABLE_FILE, xsdt_entry_offset, xsdt_entry_size, + ACPI_BUILD_TABLE_FILE, ref_tbl_offset); + } + build_header(linker, table_data, + (void *)xsdt, "XSDT", xsdt_len, 1, oem_id, oem_table_id); +} + void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, uint64_t len, int node, MemoryAffinityFlags flags) { diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index a553a7e110..f276967365 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -385,7 +385,10 @@ static void piix4_device_plug_cb(HotplugHandler *hotplug_dev, dev, errp); } } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { - acpi_pcihp_device_plug_cb(hotplug_dev, &s->acpi_pci_hotplug, dev, errp); + if (!xen_enabled()) { + acpi_pcihp_device_plug_cb(hotplug_dev, &s->acpi_pci_hotplug, dev, + errp); + } } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { if (s->cpu_hotplug_legacy) { legacy_acpi_cpu_plug_cb(hotplug_dev, &s->gpe_cpu, dev, errp); @@ -408,8 +411,10 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev, acpi_memory_unplug_request_cb(hotplug_dev, &s->acpi_memory_hotplug, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { - acpi_pcihp_device_unplug_cb(hotplug_dev, &s->acpi_pci_hotplug, dev, - errp); + if (!xen_enabled()) { + acpi_pcihp_device_unplug_cb(hotplug_dev, &s->acpi_pci_hotplug, dev, + errp); + } } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) && !s->cpu_hotplug_legacy) { acpi_cpu_unplug_request_cb(hotplug_dev, &s->cpuhp_state, dev, errp); @@ -700,7 +705,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data) * Reason: part of PIIX4 southbridge, needs to be wired up, * e.g. by mips_malta_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->hotpluggable = false; hc->plug = piix4_device_plug_cb; hc->unplug_request = piix4_device_unplug_request_cb; diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index fe2d5a764c..324626847c 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -1076,7 +1076,7 @@ static void sl_nand_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_sl_nand_info; dc->props = sl_nand_properties; /* Reason: init() method uses drive_get() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo sl_nand_info = { diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index ce7499c9ca..e5852067f5 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -364,12 +364,12 @@ static void acpi_dsdt_add_power_button(Aml *scope) /* RSDP */ static GArray * -build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset) +build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned xsdt_tbl_offset) { AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp); - unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address); - unsigned rsdt_pa_offset = - (char *)&rsdp->rsdt_physical_address - rsdp_table->data; + unsigned xsdt_pa_size = sizeof(rsdp->xsdt_physical_address); + unsigned xsdt_pa_offset = + (char *)&rsdp->xsdt_physical_address - rsdp_table->data; bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16, true /* fseg memory */); @@ -381,8 +381,8 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset) /* Address to be filled by Guest linker */ bios_linker_loader_add_pointer(linker, - ACPI_BUILD_RSDP_FILE, rsdt_pa_offset, rsdt_pa_size, - ACPI_BUILD_TABLE_FILE, rsdt_tbl_offset); + ACPI_BUILD_RSDP_FILE, xsdt_pa_offset, xsdt_pa_size, + ACPI_BUILD_TABLE_FILE, xsdt_tbl_offset); /* Checksum to be filled by Guest linker */ bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE, @@ -654,7 +654,7 @@ static void build_fadt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms, unsigned dsdt_tbl_offset) { AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt)); - unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data; + unsigned xdsdt_entry_offset = (char *)&fadt->x_dsdt - table_data->data; uint16_t bootflags; switch (vms->psci_conduit) { @@ -680,7 +680,7 @@ static void build_fadt(GArray *table_data, BIOSLinker *linker, /* DSDT address to be filled by Guest linker */ bios_linker_loader_add_pointer(linker, - ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->dsdt), + ACPI_BUILD_TABLE_FILE, xdsdt_entry_offset, sizeof(fadt->x_dsdt), ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset); build_header(linker, table_data, @@ -743,7 +743,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) { VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); GArray *table_offsets; - unsigned dsdt, rsdt; + unsigned dsdt, xsdt; GArray *tables_blob = tables->table_data; table_offsets = g_array_new(false, true /* clear */, @@ -783,12 +783,12 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) build_iort(tables_blob, tables->linker); } - /* RSDT is pointed to by RSDP */ - rsdt = tables_blob->len; - build_rsdt(tables_blob, tables->linker, table_offsets, NULL, NULL); + /* XSDT is pointed to by RSDP */ + xsdt = tables_blob->len; + build_xsdt(tables_blob, tables->linker, table_offsets, NULL, NULL); /* RSDP is in FSEG memory, so allocate it separately */ - build_rsdp(tables->rsdp, tables->linker, rsdt); + build_rsdp(tables->rsdp, tables->linker, xsdt); /* Cleanup memory that's no longer used. */ g_array_free(table_offsets, true); diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c index 511b004287..4f65f8c199 100644 --- a/hw/audio/marvell_88w8618.c +++ b/hw/audio/marvell_88w8618.c @@ -292,7 +292,7 @@ static void mv88w8618_audio_class_init(ObjectClass *klass, void *data) dc->vmsd = &mv88w8618_audio_vmsd; dc->props = mv88w8618_audio_properties; /* Reason: pointer property "wm8750" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo mv88w8618_audio_info = { diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index 798002277b..9b99358d87 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -223,7 +223,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data) dc->vmsd = &vmstate_spk; dc->props = pcspk_properties; /* Reason: realize sets global pcspk_state */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo pcspk_info = { diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c index 1485d5b285..f9d76c4641 100644 --- a/hw/core/or-irq.c +++ b/hw/core/or-irq.c @@ -91,7 +91,7 @@ static void or_irq_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_or_irq; /* Reason: Needs to be wired up to work, e.g. see stm32f205_soc.c */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo or_irq_type_info = { diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 02b632f6b3..71ff95fd71 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -37,7 +37,7 @@ #include "hw/boards.h" #include "hw/sysbus.h" #include "qapi-event.h" -#include "migration/migration.h" +#include "migration/vmstate.h" bool qdev_hotplug = false; static bool qdev_hot_added = false; @@ -861,6 +861,20 @@ static bool device_get_realized(Object *obj, Error **errp) return dev->realized; } +static bool check_only_migratable(Object *obj, Error **err) +{ + DeviceClass *dc = DEVICE_GET_CLASS(obj); + + if (!vmstate_check_only_migratable(dc->vmsd)) { + error_setg(err, "Device %s is not migratable, but " + "--only-migratable was specified", + object_get_typename(obj)); + return false; + } + + return true; +} + static void device_set_realized(Object *obj, bool value, Error **errp) { DeviceState *dev = DEVICE(obj); @@ -870,7 +884,6 @@ static void device_set_realized(Object *obj, bool value, Error **errp) Error *local_err = NULL; bool unattached_parent = false; static int unattached_count; - int ret; if (dev->hotplugged && !dc->hotpluggable) { error_setg(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj)); @@ -878,8 +891,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp) } if (value && !dev->realized) { - ret = check_migratable(obj, &local_err); - if (ret < 0) { + if (!check_only_migratable(obj, &local_err)) { goto fail; } @@ -1118,6 +1130,7 @@ static void device_class_init(ObjectClass *class, void *data) * should override it in their class_init() */ dc->hotpluggable = true; + dc->user_creatable = true; } void device_reset(DeviceState *dev) diff --git a/hw/core/register.c b/hw/core/register.c index dc335a79a9..da38ef3a54 100644 --- a/hw/core/register.c +++ b/hw/core/register.c @@ -288,7 +288,7 @@ static void register_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); /* Reason: needs to be wired up to work */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo register_info = { diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c index c0f560b289..5d0887f499 100644 --- a/hw/core/sysbus.c +++ b/hw/core/sysbus.c @@ -326,6 +326,17 @@ static void sysbus_device_class_init(ObjectClass *klass, void *data) DeviceClass *k = DEVICE_CLASS(klass); k->init = sysbus_device_init; k->bus_type = TYPE_SYSTEM_BUS; + /* + * device_add plugs devices into a suitable bus. For "real" buses, + * that actually connects the device. For sysbus, the connections + * need to be made separately, and device_add can't do that. The + * device would be left unconnected, and will probably not work + * + * However, a few machines can handle device_add/-device with + * a few specific sysbus devices. In those cases, the device + * subclass needs to override it and set user_creatable=true. + */ + k->user_creatable = false; } static const TypeInfo sysbus_device_type_info = { diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 4d94cecd72..ad09bb98f9 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -26,7 +26,7 @@ #include "qemu/queue.h" #include "qemu/atomic.h" #include "sysemu/sysemu.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "trace.h" #include "qxl.h" diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index cfb5dfa336..58dc0b2737 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -19,7 +19,7 @@ #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-gpu.h" #include "hw/virtio/virtio-bus.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qemu/log.h" #include "qapi/error.h" diff --git a/hw/dma/i8257.c b/hw/dma/i8257.c index 8bd82e8bc8..bd23e893bf 100644 --- a/hw/dma/i8257.c +++ b/hw/dma/i8257.c @@ -601,7 +601,7 @@ static void i8257_class_init(ObjectClass *klass, void *data) idc->schedule = i8257_dma_schedule; idc->register_channel = i8257_dma_register_channel; /* Reason: needs to be wired up by isa_bus_dma() to work */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo i8257_info = { diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index 9d545e412e..9c6bdc6295 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -305,7 +305,7 @@ static void sparc32_dma_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_dma; dc->props = sparc32_dma_properties; /* Reason: pointer property "iommu_opaque" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo sparc32_dma_info = { diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c index dabef4a119..1df394eb12 100644 --- a/hw/gpio/omap_gpio.c +++ b/hw/gpio/omap_gpio.c @@ -773,7 +773,7 @@ static void omap_gpio_class_init(ObjectClass *klass, void *data) dc->reset = omap_gpif_reset; dc->props = omap_gpio_properties; /* Reason: pointer property "clk" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo omap_gpio_info = { @@ -804,7 +804,7 @@ static void omap2_gpio_class_init(ObjectClass *klass, void *data) dc->reset = omap2_gpif_reset; dc->props = omap2_gpio_properties; /* Reason: pointer properties "iclk", "fclk0", ..., "fclk5" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo omap2_gpio_info = { diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c index f7c92ea00c..f6e80bee25 100644 --- a/hw/i2c/omap_i2c.c +++ b/hw/i2c/omap_i2c.c @@ -491,7 +491,7 @@ static void omap_i2c_class_init(ObjectClass *klass, void *data) dc->props = omap_i2c_properties; dc->reset = omap_i2c_reset; /* Reason: pointer properties "iclk", "fclk" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->realize = omap_i2c_realize; } diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c index 5b7bd891bc..b13ec0fe7a 100644 --- a/hw/i2c/smbus_eeprom.c +++ b/hw/i2c/smbus_eeprom.c @@ -123,7 +123,7 @@ static void smbus_eeprom_class_initfn(ObjectClass *klass, void *data) sc->read_data = eeprom_read_data; dc->props = smbus_eeprom_properties; /* Reason: pointer property "data" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo smbus_eeprom_info = { diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c index 48fab22625..ea51e09186 100644 --- a/hw/i2c/smbus_ich9.c +++ b/hw/i2c/smbus_ich9.c @@ -103,7 +103,7 @@ static void ich9_smb_class_init(ObjectClass *klass, void *data) * Reason: part of ICH9 southbridge, needs to be wired up by * pc_q35_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } I2CBus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index cc0418f327..afcadacd2e 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -341,7 +341,7 @@ build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm, AcpiFadtDescriptorRev3 *fadt = acpi_data_push(table_data, sizeof(*fadt)); unsigned fw_ctrl_offset = (char *)&fadt->firmware_ctrl - table_data->data; unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data; - unsigned xdsdt_entry_offset = (char *)&fadt->Xdsdt - table_data->data; + unsigned xdsdt_entry_offset = (char *)&fadt->x_dsdt - table_data->data; /* FACS address to be filled by Guest linker */ bios_linker_loader_add_pointer(linker, @@ -354,7 +354,7 @@ build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm, ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->dsdt), ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset); bios_linker_loader_add_pointer(linker, - ACPI_BUILD_TABLE_FILE, xdsdt_entry_offset, sizeof(fadt->Xdsdt), + ACPI_BUILD_TABLE_FILE, xdsdt_entry_offset, sizeof(fadt->x_dsdt), ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset); build_header(linker, table_data, diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index f86a40aa30..329058dac8 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -21,6 +21,7 @@ */ #include "qemu/osdep.h" #include "hw/i386/amd_iommu.h" +#include "qapi/error.h" #include "qemu/error-report.h" #include "trace.h" @@ -1137,7 +1138,19 @@ static void amdvi_realize(DeviceState *dev, Error **err) int ret = 0; AMDVIState *s = AMD_IOMMU_DEVICE(dev); X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(dev); - PCIBus *bus = PC_MACHINE(qdev_get_machine())->bus; + MachineState *ms = MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(ms); + PCMachineState *pcms = + PC_MACHINE(object_dynamic_cast(OBJECT(ms), TYPE_PC_MACHINE)); + PCIBus *bus; + + if (!pcms) { + error_setg(err, "Machine-type '%s' not supported by amd-iommu", + mc->name); + return; + } + + bus = pcms->bus; s->iotlb = g_hash_table_new_full(amdvi_uint64_hash, amdvi_uint64_equal, g_free, g_free); @@ -1186,6 +1199,8 @@ static void amdvi_class_init(ObjectClass *klass, void* data) dc->vmsd = &vmstate_amdvi; dc->hotpluggable = false; dc_class->realize = amdvi_realize; + /* Supported by the pc-q35-* machine types */ + dc->user_creatable = true; } static const TypeInfo amdvi = { diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 02f047c8e3..9ba2162cd9 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -2969,11 +2969,21 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp) static void vtd_realize(DeviceState *dev, Error **errp) { - PCMachineState *pcms = PC_MACHINE(qdev_get_machine()); - PCIBus *bus = pcms->bus; + MachineState *ms = MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(ms); + PCMachineState *pcms = + PC_MACHINE(object_dynamic_cast(OBJECT(ms), TYPE_PC_MACHINE)); + PCIBus *bus; IntelIOMMUState *s = INTEL_IOMMU_DEVICE(dev); X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(dev); + if (!pcms) { + error_setg(errp, "Machine-type '%s' not supported by intel-iommu", + mc->name); + return; + } + + bus = pcms->bus; VTD_DPRINTF(GENERAL, ""); x86_iommu->type = TYPE_INTEL; @@ -3009,6 +3019,8 @@ static void vtd_class_init(ObjectClass *klass, void *data) dc->hotpluggable = false; x86_class->realize = vtd_realize; x86_class->int_remap = vtd_int_remap; + /* Supported by the pc-q35-* machine types */ + dc->user_creatable = true; } static const TypeInfo vtd_info = { diff --git a/hw/i386/pc.c b/hw/i386/pc.c index e36a375683..816bfa872c 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -597,7 +597,7 @@ static void port92_class_initfn(ObjectClass *klass, void *data) * wiring: its A20 output line needs to be wired up by * port92_init(). */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo port92_info = { @@ -1049,12 +1049,10 @@ static void load_linux(PCMachineState *pcms, fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size); fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size); - if (fw_cfg_dma_enabled(fw_cfg)) { + option_rom[nb_option_roms].bootindex = 0; + option_rom[nb_option_roms].name = "linuxboot.bin"; + if (pcmc->linuxboot_dma_enabled && fw_cfg_dma_enabled(fw_cfg)) { option_rom[nb_option_roms].name = "linuxboot_dma.bin"; - option_rom[nb_option_roms].bootindex = 0; - } else { - option_rom[nb_option_roms].name = "linuxboot.bin"; - option_rom[nb_option_roms].bootindex = 0; } nb_option_roms++; } @@ -2351,6 +2349,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) * to be used at the moment, 32K should be enough for a while. */ pcmc->acpi_data_size = 0x20000 + 0x8000; pcmc->save_tsc_khz = true; + pcmc->linuxboot_dma_enabled = true; mc->get_hotplug_handler = pc_get_hotpug_handler; mc->cpu_index_to_instance_props = pc_cpu_index_to_props; mc->possible_cpu_arch_ids = pc_possible_cpu_arch_ids; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index d468b963fb..2234bd0461 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -438,7 +438,7 @@ static void pc_i440fx_machine_options(MachineClass *m) m->default_display = "std"; } -static void pc_i440fx_2_9_machine_options(MachineClass *m) +static void pc_i440fx_2_10_machine_options(MachineClass *m) { pc_i440fx_machine_options(m); m->alias = "pc"; @@ -446,14 +446,23 @@ static void pc_i440fx_2_9_machine_options(MachineClass *m) m->numa_auto_assign_ram = numa_legacy_auto_assign_ram; } +DEFINE_I440FX_MACHINE(v2_10, "pc-i440fx-2.10", NULL, + pc_i440fx_2_10_machine_options); + +static void pc_i440fx_2_9_machine_options(MachineClass *m) +{ + pc_i440fx_2_10_machine_options(m); + m->is_default = 0; + m->alias = NULL; + SET_MACHINE_COMPAT(m, PC_COMPAT_2_9); +} + DEFINE_I440FX_MACHINE(v2_9, "pc-i440fx-2.9", NULL, pc_i440fx_2_9_machine_options); static void pc_i440fx_2_8_machine_options(MachineClass *m) { pc_i440fx_2_9_machine_options(m); - m->is_default = 0; - m->alias = NULL; SET_MACHINE_COMPAT(m, PC_COMPAT_2_8); } @@ -476,6 +485,7 @@ static void pc_i440fx_2_6_machine_options(MachineClass *m) PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_2_7_machine_options(m); pcmc->legacy_cpu_hotplug = true; + pcmc->linuxboot_dma_enabled = false; SET_MACHINE_COMPAT(m, PC_COMPAT_2_6); } diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 66303a78cf..f243203844 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -302,20 +302,29 @@ static void pc_q35_machine_options(MachineClass *m) m->max_cpus = 288; } -static void pc_q35_2_9_machine_options(MachineClass *m) +static void pc_q35_2_10_machine_options(MachineClass *m) { pc_q35_machine_options(m); m->alias = "q35"; m->numa_auto_assign_ram = numa_legacy_auto_assign_ram; } +DEFINE_Q35_MACHINE(v2_10, "pc-q35-2.10", NULL, + pc_q35_2_10_machine_options); + +static void pc_q35_2_9_machine_options(MachineClass *m) +{ + pc_q35_2_10_machine_options(m); + m->alias = NULL; + SET_MACHINE_COMPAT(m, PC_COMPAT_2_9); +} + DEFINE_Q35_MACHINE(v2_9, "pc-q35-2.9", NULL, pc_q35_2_9_machine_options); static void pc_q35_2_8_machine_options(MachineClass *m) { pc_q35_2_9_machine_options(m); - m->alias = NULL; SET_MACHINE_COMPAT(m, PC_COMPAT_2_8); } @@ -337,6 +346,7 @@ static void pc_q35_2_6_machine_options(MachineClass *m) PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_2_7_machine_options(m); pcmc->legacy_cpu_hotplug = true; + pcmc->linuxboot_dma_enabled = false; SET_MACHINE_COMPAT(m, PC_COMPAT_2_6); } diff --git a/hw/i386/xen/xen-mapcache.c b/hw/i386/xen/xen-mapcache.c index 31debdfb2c..e60156c04f 100644 --- a/hw/i386/xen/xen-mapcache.c +++ b/hw/i386/xen/xen-mapcache.c @@ -62,6 +62,7 @@ typedef struct MapCacheRev { hwaddr paddr_index; hwaddr size; QTAILQ_ENTRY(MapCacheRev) next; + bool dma; } MapCacheRev; typedef struct MapCache { @@ -202,7 +203,7 @@ static void xen_remap_bucket(MapCacheEntry *entry, } static uint8_t *xen_map_cache_unlocked(hwaddr phys_addr, hwaddr size, - uint8_t lock) + uint8_t lock, bool dma) { MapCacheEntry *entry, *pentry = NULL; hwaddr address_index; @@ -289,6 +290,7 @@ tryagain: if (lock) { MapCacheRev *reventry = g_malloc0(sizeof(MapCacheRev)); entry->lock++; + reventry->dma = dma; reventry->vaddr_req = mapcache->last_entry->vaddr_base + address_offset; reventry->paddr_index = mapcache->last_entry->paddr_index; reventry->size = entry->size; @@ -300,12 +302,12 @@ tryagain: } uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size, - uint8_t lock) + uint8_t lock, bool dma) { uint8_t *p; mapcache_lock(); - p = xen_map_cache_unlocked(phys_addr, size, lock); + p = xen_map_cache_unlocked(phys_addr, size, lock, dma); mapcache_unlock(); return p; } @@ -426,8 +428,11 @@ void xen_invalidate_map_cache(void) mapcache_lock(); QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) { - DPRINTF("There should be no locked mappings at this time, " - "but "TARGET_FMT_plx" -> %p is present\n", + if (!reventry->dma) { + continue; + } + fprintf(stderr, "Locked DMA mapping while invalidating mapcache!" + " "TARGET_FMT_plx" -> %p is present\n", reventry->paddr_index, reventry->vaddr_req); } diff --git a/hw/input/vmmouse.c b/hw/input/vmmouse.c index 6d15a887c6..4747da9a8d 100644 --- a/hw/input/vmmouse.c +++ b/hw/input/vmmouse.c @@ -286,7 +286,7 @@ static void vmmouse_class_initfn(ObjectClass *klass, void *data) dc->vmsd = &vmstate_vmmouse; dc->props = vmmouse_properties; /* Reason: pointer property "ps2_mouse" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo vmmouse_info = { diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index c3829e31b5..1ef56f8d10 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -501,7 +501,7 @@ static void apic_common_class_init(ObjectClass *klass, void *data) * Reason: APIC and CPU need to be wired up by * x86_cpu_apic_create() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo apic_common_type = { diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c index ec952ece93..af5cd367e9 100644 --- a/hw/intc/arm_gic_kvm.c +++ b/hw/intc/arm_gic_kvm.c @@ -24,7 +24,7 @@ #include "qemu-common.h" #include "cpu.h" #include "hw/sysbus.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "sysemu/kvm.h" #include "kvm_arm.h" #include "gic_internal.h" diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c index bd4f3aafc6..a0441d6bd1 100644 --- a/hw/intc/arm_gicv3_its_kvm.c +++ b/hw/intc/arm_gicv3_its_kvm.c @@ -24,7 +24,7 @@ #include "sysemu/sysemu.h" #include "sysemu/kvm.h" #include "kvm_arm.h" -#include "migration/migration.h" +#include "migration/blocker.h" #define TYPE_KVM_ARM_ITS "arm-its-kvm" #define KVM_ARM_ITS(obj) OBJECT_CHECK(GICv3ITSState, (obj), TYPE_KVM_ARM_ITS) diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c index 19aab56072..4ee2baa691 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c @@ -28,7 +28,7 @@ #include "kvm_arm.h" #include "gicv3_internal.h" #include "vgic_common.h" -#include "migration/migration.h" +#include "migration/blocker.h" #ifdef DEBUG_GICV3_KVM #define DPRINTF(fmt, ...) \ diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c index 64a6f4b4ba..1bfde2f09e 100644 --- a/hw/intc/etraxfs_pic.c +++ b/hw/intc/etraxfs_pic.c @@ -173,7 +173,7 @@ static void etraxfs_pic_class_init(ObjectClass *klass, void *data) dc->props = etraxfs_pic_properties; /* * Note: pointer property "interrupt_vector" may remain null, thus - * no need for dc->cannot_instantiate_with_device_add_yet = true; + * no need for dc->user_creatable = false; */ } diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c index ac7e63f38b..94659ee256 100644 --- a/hw/intc/grlib_irqmp.c +++ b/hw/intc/grlib_irqmp.c @@ -360,7 +360,7 @@ static void grlib_irqmp_class_init(ObjectClass *klass, void *data) dc->reset = grlib_irqmp_reset; dc->props = grlib_irqmp_properties; /* Reason: pointer properties "set_pil_in", "set_pil_in_opaque" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->realize = grlib_irqmp_realize; } diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c index d9a5e8b217..c2fd563b5b 100644 --- a/hw/intc/i8259_common.c +++ b/hw/intc/i8259_common.c @@ -144,7 +144,7 @@ static void pic_common_class_init(ObjectClass *klass, void *data) * wiring of the slave to the master is hard-coded in device model * code. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo pic_common_type = { diff --git a/hw/intc/nios2_iic.c b/hw/intc/nios2_iic.c index 190b6fdbf3..016426f964 100644 --- a/hw/intc/nios2_iic.c +++ b/hw/intc/nios2_iic.c @@ -80,7 +80,7 @@ static void altera_iic_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); /* Reason: needs to be wired up, e.g. by nios2_10m50_ghrd_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->realize = altera_iic_realize; } diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c index 877be67971..ccdda89dab 100644 --- a/hw/intc/omap_intc.c +++ b/hw/intc/omap_intc.c @@ -401,7 +401,7 @@ static void omap_intc_class_init(ObjectClass *klass, void *data) dc->reset = omap_inth_reset; dc->props = omap_intc_properties; /* Reason: pointer property "clk" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->realize = omap_intc_realize; } @@ -656,7 +656,7 @@ static void omap2_intc_class_init(ObjectClass *klass, void *data) dc->reset = omap_inth_reset; dc->props = omap2_intc_properties; /* Reason: pointer property "iclk", "fclk" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->realize = omap2_intc_realize; } diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index a0866c3856..e2215dcf4d 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -805,7 +805,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data) * Reason: part of ICH9 southbridge, needs to be wired up by * pc_q35_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; hc->plug = ich9_pm_device_plug_cb; hc->unplug_request = ich9_pm_device_unplug_request_cb; hc->unplug = ich9_pm_device_unplug_cb; diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 5500fcc4d6..f811eba59d 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -123,7 +123,7 @@ static void piix4_class_init(ObjectClass *klass, void *data) * Reason: part of PIIX4 southbridge, needs to be wired up, * e.g. by mips_malta_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->hotpluggable = false; } diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 41d5254f8e..50dc83df77 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -494,7 +494,7 @@ static void via_class_init(ObjectClass *klass, void *data) * Reason: part of VIA VT82C686 southbridge, needs to be wired up, * e.g. by mips_fulong2e_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo via_info = { diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c index 4811843ab6..e8b2eef688 100644 --- a/hw/mips/gt64xxx_pci.c +++ b/hw/mips/gt64xxx_pci.c @@ -1224,7 +1224,7 @@ static void gt64120_pci_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo gt64120_pci_info = { diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index 82ce8378bf..475e36a4c7 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -25,7 +25,7 @@ #include "hw/pci/msi.h" #include "hw/pci/msix.h" #include "sysemu/kvm.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qemu/error-report.h" #include "qemu/event_notifier.h" #include "qom/object_interfaces.h" diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c index be40930b8b..165500223f 100644 --- a/hw/misc/vmport.c +++ b/hw/misc/vmport.c @@ -163,7 +163,7 @@ static void vmport_class_initfn(ObjectClass *klass, void *data) dc->realize = vmport_realizefn; /* Reason: realize sets global port_state */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo vmport_info = { diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index efa33ad40a..b53fcaa8bc 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -934,7 +934,7 @@ static void dp8393x_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_dp8393x; dc->props = dp8393x_properties; /* Reason: dma_mr property can't be set */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo dp8393x_info = { diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c index efaa49faae..013c8d0a41 100644 --- a/hw/net/etraxfs_eth.c +++ b/hw/net/etraxfs_eth.c @@ -630,7 +630,7 @@ static void etraxfs_eth_class_init(ObjectClass *klass, void *data) k->init = fs_eth_init; dc->props = etraxfs_eth_properties; /* Reason: pointer properties "dma_out", "dma_in" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo etraxfs_eth_info = { diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c index aa2b0d5a85..9da1932970 100644 --- a/hw/net/fsl_etsec/etsec.c +++ b/hw/net/fsl_etsec/etsec.c @@ -416,6 +416,8 @@ static void etsec_class_init(ObjectClass *klass, void *data) dc->realize = etsec_realize; dc->reset = etsec_reset; dc->props = etsec_properties; + /* Supported by ppce500 machine */ + dc->user_creatable = true; } static TypeInfo etsec_info = { diff --git a/hw/net/lance.c b/hw/net/lance.c index 573d724bcf..92b0c68274 100644 --- a/hw/net/lance.c +++ b/hw/net/lance.c @@ -165,7 +165,7 @@ static void lance_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_lance; dc->props = lance_properties; /* Reason: pointer property "dma" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo lance_info = { diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c index 840c96198a..cca93620ac 100644 --- a/hw/pci-bridge/dec.c +++ b/hw/pci-bridge/dec.c @@ -128,7 +128,7 @@ static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo dec_21154_pci_host_info = { diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c index 647ad80155..5dbd933cc1 100644 --- a/hw/pci-bridge/pci_bridge_dev.c +++ b/hw/pci-bridge/pci_bridge_dev.c @@ -163,7 +163,7 @@ static Property pci_bridge_dev_properties[] = { DEFINE_PROP_ON_OFF_AUTO(PCI_BRIDGE_DEV_PROP_MSI, PCIBridgeDev, msi, ON_OFF_AUTO_AUTO), DEFINE_PROP_BIT(PCI_BRIDGE_DEV_PROP_SHPC, PCIBridgeDev, flags, - PCI_BRIDGE_DEV_F_SHPC_REQ, false), + PCI_BRIDGE_DEV_F_SHPC_REQ, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c index 6ac187fa32..ff59abf208 100644 --- a/hw/pci-bridge/pci_expander_bridge.c +++ b/hw/pci-bridge/pci_expander_bridge.c @@ -150,7 +150,7 @@ static void pxb_host_class_init(ObjectClass *class, void *data) dc->fw_name = "pci"; /* Reason: Internal part of the pxb/pxb-pcie device, not usable by itself */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address; hc->root_bus_path = pxb_host_root_bus_path; } diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 653e711121..edc88f4c65 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -810,7 +810,7 @@ static void pbm_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo pbm_pci_host_info = { diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index 1999ece590..85a3bb0dd2 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -825,7 +825,7 @@ static void bonito_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo bonito_info = { diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c index 66055ee5cc..e2629ce70d 100644 --- a/hw/pci-host/gpex.c +++ b/hw/pci-host/gpex.c @@ -136,7 +136,7 @@ static void gpex_root_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo gpex_root_info = { diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c index 2c8acdaaca..2e281f6155 100644 --- a/hw/pci-host/grackle.c +++ b/hw/pci-host/grackle.c @@ -134,7 +134,7 @@ static void grackle_pci_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo grackle_pci_info = { diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index bf4221d4bf..2d02de12d9 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -685,7 +685,7 @@ static void pci_piix3_class_init(ObjectClass *klass, void *data) * Reason: part of PIIX3 southbridge, needs to be wired up by * pc_piix.c's pc_init1() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo piix3_pci_type_info = { @@ -739,7 +739,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->hotpluggable = false; } @@ -868,7 +868,7 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) dc->fw_name = "pci"; dc->props = i440fx_props; /* Reason: needs to be wired up by pc_init1 */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo i440fx_pcihost_info = { diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c index e502bc0505..becc0eeb76 100644 --- a/hw/pci-host/ppce500.c +++ b/hw/pci-host/ppce500.c @@ -508,7 +508,7 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo e500_host_bridge_info = { diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index 260a119a9e..900a6edfcf 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -364,7 +364,7 @@ static void raven_class_init(ObjectClass *klass, void *data) * Reason: PCI-facing part of the host bridge, not usable without * the host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo raven_info = { diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 344f77b10c..cd5c49616e 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -156,7 +156,7 @@ static void q35_host_class_init(ObjectClass *klass, void *data) dc->realize = q35_host_realize; dc->props = mch_props; /* Reason: needs to be wired up by pc_q35_init */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->fw_name = "pci"; } @@ -549,7 +549,7 @@ static void mch_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo mch_info = { diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c index df342ac3cb..6cf5e59f86 100644 --- a/hw/pci-host/uninorth.c +++ b/hw/pci-host/uninorth.c @@ -366,7 +366,7 @@ static void unin_main_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo unin_main_pci_host_info = { @@ -390,7 +390,7 @@ static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo u3_agp_pci_host_info = { @@ -414,7 +414,7 @@ static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo unin_agp_pci_host_info = { @@ -438,7 +438,7 @@ static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo unin_internal_pci_host_info = { diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c index 27fde46126..aa1fdf75fd 100644 --- a/hw/pci-host/versatile.c +++ b/hw/pci-host/versatile.c @@ -479,7 +479,7 @@ static void versatile_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo versatile_pci_host_info = { diff --git a/hw/pci-host/xilinx-pcie.c b/hw/pci-host/xilinx-pcie.c index 8b71e2d950..a968cea2af 100644 --- a/hw/pci-host/xilinx-pcie.c +++ b/hw/pci-host/xilinx-pcie.c @@ -309,7 +309,7 @@ static void xilinx_pcie_root_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo xilinx_pcie_root_info = { diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 259483b1c0..98ccc27533 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1083,6 +1083,7 @@ static void pci_qdev_unrealize(DeviceState *dev, Error **errp) pc->exit(pci_dev); } + pci_device_deassert_intx(pci_dev); do_pci_unregister_device(pci_dev); } diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index dc19682970..6953f8b9ac 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -351,7 +351,7 @@ static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo ppc4xx_host_bridge_info = { diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index a1cdc875b1..9fa5545991 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -675,7 +675,7 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) /* * Reason: it crashes FIXME find and document the real reason */ - dk->cannot_instantiate_with_device_add_yet = true; + dk->user_creatable = false; } static const TypeInfo spapr_dr_connector_info = { diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index e7567e2e8f..a7cff32bbf 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1994,6 +1994,8 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) dc->props = spapr_phb_properties; dc->reset = spapr_phb_reset; dc->vmsd = &vmstate_spapr_pci; + /* Supported by TYPE_SPAPR_MACHINE */ + dc->user_creatable = true; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); hp->plug = spapr_phb_hot_plug_child; hp->unplug = spapr_phb_hot_unplug_child; diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index a8a1bab50a..66a6fbeb8c 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -872,7 +872,6 @@ static void s390_pcihost_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); - dc->cannot_instantiate_with_device_add_yet = true; dc->reset = s390_pcihost_reset; k->init = s390_pcihost_init; hc->plug = s390_pcihost_hot_plug; diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index 8f53ac3795..cd4ab05233 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -21,7 +21,7 @@ #include "qemu/error-report.h" #include "qemu/queue.h" #include "monitor/monitor.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "hw/virtio/vhost-scsi.h" #include "hw/virtio/vhost.h" #include "hw/virtio/virtio-scsi.h" diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index 1f2f0ed44a..4008c81002 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -299,7 +299,7 @@ static void milkymist_memcard_class_init(ObjectClass *klass, void *data) dc->reset = milkymist_memcard_reset; dc->vmsd = &vmstate_milkymist_memcard; /* Reason: init() method uses drive_get_next() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo milkymist_memcard_info = { diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c index 82c63a4fb5..55c8098ecd 100644 --- a/hw/sd/pl181.c +++ b/hw/sd/pl181.c @@ -515,7 +515,7 @@ static void pl181_class_init(ObjectClass *klass, void *data) k->vmsd = &vmstate_pl181; k->reset = pl181_reset; /* Reason: init() method uses drive_get_next() */ - k->cannot_instantiate_with_device_add_yet = true; + k->user_creatable = false; k->realize = pl181_realize; } diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c index 1747628f3d..38395c082b 100644 --- a/hw/sh4/sh_pci.c +++ b/hw/sh4/sh_pci.c @@ -171,7 +171,7 @@ static void sh_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo sh_pci_host_info = { diff --git a/hw/timer/i8254_common.c b/hw/timer/i8254_common.c index e18299a482..976d5200f1 100644 --- a/hw/timer/i8254_common.c +++ b/hw/timer/i8254_common.c @@ -287,7 +287,7 @@ static void pit_common_class_init(ObjectClass *klass, void *data) * wired to the HPET, and because of that, some wiring is always * done by board code. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo pit_common_type = { diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 4165450250..93de3e1cc5 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -973,7 +973,7 @@ static void rtc_class_initfn(ObjectClass *klass, void *data) dc->vmsd = &vmstate_rtc; dc->props = mc146818rtc_properties; /* Reason: needs to be wired up by rtc_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static void rtc_finalize(Object *obj) diff --git a/hw/vfio/amd-xgbe.c b/hw/vfio/amd-xgbe.c index 2c60310cf9..fab196cebf 100644 --- a/hw/vfio/amd-xgbe.c +++ b/hw/vfio/amd-xgbe.c @@ -38,6 +38,8 @@ static void vfio_amd_xgbe_class_init(ObjectClass *klass, void *data) dc->realize = amd_xgbe_realize; dc->desc = "VFIO AMD XGBE"; dc->vmsd = &vfio_platform_amd_xgbe_vmstate; + /* Supported by TYPE_VIRT_MACHINE */ + dc->user_creatable = true; } static const TypeInfo vfio_amd_xgbe_dev_info = { diff --git a/hw/vfio/calxeda-xgmac.c b/hw/vfio/calxeda-xgmac.c index bb15d588e5..7bb17af7ad 100644 --- a/hw/vfio/calxeda-xgmac.c +++ b/hw/vfio/calxeda-xgmac.c @@ -38,6 +38,8 @@ static void vfio_calxeda_xgmac_class_init(ObjectClass *klass, void *data) dc->realize = calxeda_xgmac_realize; dc->desc = "VFIO Calxeda XGMAC"; dc->vmsd = &vfio_platform_calxeda_xgmac_vmstate; + /* Supported by TYPE_VIRT_MACHINE */ + dc->user_creatable = true; } static const TypeInfo vfio_calxeda_xgmac_dev_info = { diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 9334a8ae22..32a95a8c69 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -163,22 +163,26 @@ fail: } static int process_message_reply(struct vhost_dev *dev, - VhostUserRequest request) + VhostUserMsg msg) { - VhostUserMsg msg; + VhostUserMsg msg_reply; - if (vhost_user_read(dev, &msg) < 0) { + if ((msg.flags & VHOST_USER_NEED_REPLY_MASK) == 0) { + return 0; + } + + if (vhost_user_read(dev, &msg_reply) < 0) { return -1; } - if (msg.request != request) { + if (msg_reply.request != msg.request) { error_report("Received unexpected msg type." "Expected %d received %d", - request, msg.request); + msg.request, msg_reply.request); return -1; } - return msg.payload.u64 ? -1 : 0; + return msg_reply.payload.u64 ? -1 : 0; } static bool vhost_user_one_time_request(VhostUserRequest request) @@ -208,6 +212,7 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg, * request, we just ignore it. */ if (vhost_user_one_time_request(msg->request) && dev->vq_index != 0) { + msg->flags &= ~VHOST_USER_NEED_REPLY_MASK; return 0; } @@ -320,7 +325,7 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, } if (reply_supported) { - return process_message_reply(dev, msg.request); + return process_message_reply(dev, msg); } return 0; @@ -712,7 +717,7 @@ static int vhost_user_net_set_mtu(struct vhost_dev *dev, uint16_t mtu) /* If reply_ack supported, slave has to ack specified MTU is valid */ if (reply_supported) { - return process_message_reply(dev, msg.request); + return process_message_reply(dev, msg); } return 0; diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 0001e60b77..03a46a7429 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -25,7 +25,7 @@ #include "exec/address-spaces.h" #include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-access.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "sysemu/dma.h" /* enabled until disconnected backend stabilizes */ diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 03592c542a..890b4d7eb7 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -2451,12 +2451,12 @@ void GCC_FMT_ATTR(2, 3) virtio_error(VirtIODevice *vdev, const char *fmt, ...) error_vreport(fmt, ap); va_end(ap); - vdev->broken = true; - if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { virtio_set_status(vdev, vdev->status | VIRTIO_CONFIG_S_NEEDS_RESET); virtio_notify_config(vdev); } + + vdev->broken = true; } static void virtio_memory_listener_commit(MemoryListener *listener) diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c index c85f1637e4..3570f37e56 100644 --- a/hw/xen/xen_backend.c +++ b/hw/xen/xen_backend.c @@ -147,7 +147,7 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev, qdev_unplug(DEVICE(xendev), NULL); return NULL; } - fcntl(xenevtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC); + qemu_set_cloexec(xenevtchn_fd(xendev->evtchndev)); if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) { xendev->gnttabdev = xengnttab_open(NULL, 0); @@ -619,6 +619,8 @@ static void xendev_class_init(ObjectClass *klass, void *data) dc->props = xendev_properties; set_bit(DEVICE_CATEGORY_MISC, dc->categories); + /* xen-backend devices can be plugged/unplugged dynamically */ + dc->user_creatable = true; } static const TypeInfo xendev_type_info = { diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index 293ee4524b..72be675dd6 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -81,8 +81,8 @@ typedef struct AcpiRsdpDescriptor AcpiRsdpDescriptor; uint32_t asl_compiler_revision; /* ASL compiler revision number */ -struct AcpiTableHeader /* ACPI common table header */ -{ +/* ACPI common table header */ +struct AcpiTableHeader { ACPI_TABLE_HEADER_DEF } QEMU_PACKED; typedef struct AcpiTableHeader AcpiTableHeader; @@ -144,8 +144,8 @@ typedef struct AcpiTableHeader AcpiTableHeader; /* ARM-Specific Boot Flags (see below for individual flags) (ACPI 5.1) */ \ uint16_t arm_boot_flags; \ uint8_t minor_revision; /* FADT Minor Revision (ACPI 5.1) */ \ - uint64_t Xfacs; /* 64-bit physical address of FACS */ \ - uint64_t Xdsdt; /* 64-bit physical address of DSDT */ \ + uint64_t x_facs; /* 64-bit physical address of FACS */ \ + uint64_t x_dsdt; /* 64-bit physical address of DSDT */ \ /* 64-bit Extended Power Mgt 1a Event Reg Blk address */ \ struct AcpiGenericAddress xpm1a_event_block; \ /* 64-bit Extended Power Mgt 1b Event Reg Blk address */ \ @@ -224,8 +224,7 @@ typedef struct AcpiSerialPortConsoleRedirection /* * ACPI 1.0 Root System Description Table (RSDT) */ -struct AcpiRsdtDescriptorRev1 -{ +struct AcpiRsdtDescriptorRev1 { ACPI_TABLE_HEADER_DEF /* ACPI common table header */ uint32_t table_offset_entry[0]; /* Array of pointers to other */ /* ACPI tables */ @@ -233,10 +232,19 @@ struct AcpiRsdtDescriptorRev1 typedef struct AcpiRsdtDescriptorRev1 AcpiRsdtDescriptorRev1; /* + * ACPI 2.0 eXtended System Description Table (XSDT) + */ +struct AcpiXsdtDescriptorRev2 { + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + uint64_t table_offset_entry[0]; /* Array of pointers to other */ + /* ACPI tables */ +} QEMU_PACKED; +typedef struct AcpiXsdtDescriptorRev2 AcpiXsdtDescriptorRev2; + +/* * ACPI 1.0 Firmware ACPI Control Structure (FACS) */ -struct AcpiFacsDescriptorRev1 -{ +struct AcpiFacsDescriptorRev1 { uint32_t signature; /* ACPI Signature */ uint32_t length; /* Length of structure, in bytes */ uint32_t hardware_signature; /* Hardware configuration signature */ @@ -262,8 +270,7 @@ typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1; /* Master MADT */ -struct AcpiMultipleApicTable -{ +struct AcpiMultipleApicTable { ACPI_TABLE_HEADER_DEF /* ACPI common table header */ uint32_t local_apic_address; /* Physical address of local APIC */ uint32_t flags; @@ -299,8 +306,7 @@ typedef struct AcpiMultipleApicTable AcpiMultipleApicTable; /* Sub-structures for MADT */ -struct AcpiMadtProcessorApic -{ +struct AcpiMadtProcessorApic { ACPI_SUB_HEADER_DEF uint8_t processor_id; /* ACPI processor id */ uint8_t local_apic_id; /* Processor's local APIC id */ @@ -308,8 +314,7 @@ struct AcpiMadtProcessorApic } QEMU_PACKED; typedef struct AcpiMadtProcessorApic AcpiMadtProcessorApic; -struct AcpiMadtIoApic -{ +struct AcpiMadtIoApic { ACPI_SUB_HEADER_DEF uint8_t io_apic_id; /* I/O APIC ID */ uint8_t reserved; /* Reserved - must be zero */ @@ -462,8 +467,7 @@ typedef struct Acpi20Hpet Acpi20Hpet; * SRAT (NUMA topology description) table */ -struct AcpiSystemResourceAffinityTable -{ +struct AcpiSystemResourceAffinityTable { ACPI_TABLE_HEADER_DEF uint32_t reserved1; uint32_t reserved2[2]; @@ -475,8 +479,7 @@ typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable; #define ACPI_SRAT_PROCESSOR_x2APIC 2 #define ACPI_SRAT_PROCESSOR_GICC 3 -struct AcpiSratProcessorAffinity -{ +struct AcpiSratProcessorAffinity { ACPI_SUB_HEADER_DEF uint8_t proximity_lo; uint8_t local_apic_id; @@ -498,8 +501,7 @@ struct AcpiSratProcessorX2ApicAffinity { } QEMU_PACKED; typedef struct AcpiSratProcessorX2ApicAffinity AcpiSratProcessorX2ApicAffinity; -struct AcpiSratMemoryAffinity -{ +struct AcpiSratMemoryAffinity { ACPI_SUB_HEADER_DEF uint32_t proximity; uint16_t reserved1; @@ -511,8 +513,7 @@ struct AcpiSratMemoryAffinity } QEMU_PACKED; typedef struct AcpiSratMemoryAffinity AcpiSratMemoryAffinity; -struct AcpiSratProcessorGiccAffinity -{ +struct AcpiSratProcessorGiccAffinity { ACPI_SUB_HEADER_DEF uint32_t proximity; uint32_t acpi_processor_uid; diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index 329a0d0c90..88d0738d76 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -381,6 +381,9 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre); void build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, const char *oem_id, const char *oem_table_id); +void +build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, + const char *oem_id, const char *oem_table_id); int build_append_named_dword(GArray *array, const char *name_format, ...) diff --git a/include/hw/compat.h b/include/hw/compat.h index 846b90eb67..55b176507a 100644 --- a/include/hw/compat.h +++ b/include/hw/compat.h @@ -2,7 +2,11 @@ #define HW_COMPAT_H #define HW_COMPAT_2_9 \ - /* empty */ + {\ + .driver = "pci-bridge",\ + .property = "shpc",\ + .value = "off",\ + }, #define HW_COMPAT_2_8 \ {\ diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 416aaa56ea..e447f5d8f4 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -151,6 +151,9 @@ struct PCMachineClass { bool save_tsc_khz; /* generate legacy CPU hotplug AML */ bool legacy_cpu_hotplug; + + /* use DMA capable linuxboot option rom */ + bool linuxboot_dma_enabled; }; #define TYPE_PC_MACHINE "generic-pc-machine" @@ -379,6 +382,9 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); int e820_get_num_entries(void); bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); +#define PC_COMPAT_2_9 \ + HW_COMPAT_2_9 \ + #define PC_COMPAT_2_8 \ HW_COMPAT_2_8 \ {\ @@ -438,10 +444,6 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); #define PC_COMPAT_2_6 \ HW_COMPAT_2_6 \ {\ - .driver = "fw_cfg_io",\ - .property = "dma_enabled",\ - .value = "off",\ - },{\ .driver = TYPE_X86_CPU,\ .property = "cpuid-0xb",\ .value = "off",\ diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 4bf86b0ad8..e69489ec6c 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -103,16 +103,17 @@ typedef struct DeviceClass { Property *props; /* - * Shall we hide this device model from -device / device_add? + * Can this device be instantiated with -device / device_add? * All devices should support instantiation with device_add, and * this flag should not exist. But we're not there, yet. Some * devices fail to instantiate with cryptic error messages. * Others instantiate, but don't work. Exposing users to such - * behavior would be cruel; this flag serves to protect them. It - * should never be set without a comment explaining why it is set. + * behavior would be cruel; clearing this flag will protect them. + * It should never be cleared without a comment explaining why it + * is cleared. * TODO remove once we're there */ - bool cannot_instantiate_with_device_add_yet; + bool user_creatable; bool hotpluggable; /* callbacks */ diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index 1d69fa7a8f..d206fc93dd 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -134,12 +134,12 @@ extern PropertyInfo qdev_prop_arraylen; * device_add, so add code like this: * |* Reason: pointer property "NAME-OF-YOUR-PROP" *| * DeviceClass *dc = DEVICE_CLASS(class); - * dc->cannot_instantiate_with_device_add_yet = true; + * dc->user_creatable = false; * * - If the property may safely remain null, document it like this: * |* * * Note: pointer property "interrupt_vector" may remain null, thus - * * no need for dc->cannot_instantiate_with_device_add_yet = true; + * * no need for dc->user_creatable = false; * *| */ #define DEFINE_PROP_PTR(_n, _s, _f) \ diff --git a/include/migration/blocker.h b/include/migration/blocker.h new file mode 100644 index 0000000000..acd27018e9 --- /dev/null +++ b/include/migration/blocker.h @@ -0,0 +1,35 @@ +/* + * QEMU migration blockers + * + * Copyright IBM, Corp. 2008 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#ifndef MIGRATION_BLOCKER_H +#define MIGRATION_BLOCKER_H + +/** + * @migrate_add_blocker - prevent migration from proceeding + * + * @reason - an error to be returned whenever migration is attempted + * + * @errp - [out] The reason (if any) we cannot block migration right now. + * + * @returns - 0 on success, -EBUSY/-EACCES on failure, with errp set. + */ +int migrate_add_blocker(Error *reason, Error **errp); + +/** + * @migrate_del_blocker - remove a blocking error from migration + * + * @reason - the error blocking migration + */ +void migrate_del_blocker(Error *reason); + +#endif diff --git a/include/migration/migration.h b/include/migration/migration.h index e29cb0144b..49ec5015e5 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -22,7 +22,6 @@ #include "qapi-types.h" #include "exec/cpu-common.h" #include "qemu/coroutine_int.h" -#include "qom/object.h" #define QEMU_VM_FILE_MAGIC 0x5145564d #define QEMU_VM_FILE_VERSION_COMPAT 0x00000002 @@ -39,9 +38,6 @@ #define QEMU_VM_COMMAND 0x08 #define QEMU_VM_SECTION_FOOTER 0x7e -/* for vl.c */ -extern int only_migratable; - struct MigrationParams { bool blk; bool shared; @@ -61,28 +57,6 @@ enum mig_rp_message_type { typedef QLIST_HEAD(, LoadStateEntry) LoadStateEntry_Head; -/* The current postcopy state is read/set by postcopy_state_get/set - * which update it atomically. - * The state is updated as postcopy messages are received, and - * in general only one thread should be writing to the state at any one - * time, initially the main thread and then the listen thread; - * Corner cases are where either thread finishes early and/or errors. - * The state is checked as messages are received to ensure that - * the source is sending us messages in the correct order. - * The state is also used by the RAM reception code to know if it - * has to place pages atomically, and the cleanup code at the end of - * the main thread to know if it has to delay cleanup until the end - * of postcopy. - */ -typedef enum { - POSTCOPY_INCOMING_NONE = 0, /* Initial state - no postcopy */ - POSTCOPY_INCOMING_ADVISE, - POSTCOPY_INCOMING_DISCARD, - POSTCOPY_INCOMING_LISTENING, - POSTCOPY_INCOMING_RUNNING, - POSTCOPY_INCOMING_END -} PostcopyState; - /* State for the incoming migration */ struct MigrationIncomingState { QEMUFile *from_src_file; @@ -275,26 +249,6 @@ int ram_discard_range(const char *block_name, uint64_t start, size_t length); int ram_postcopy_incoming_init(MigrationIncomingState *mis); void ram_postcopy_migrated_memory_release(MigrationState *ms); -/** - * @migrate_add_blocker - prevent migration from proceeding - * - * @reason - an error to be returned whenever migration is attempted - * - * @errp - [out] The reason (if any) we cannot block migration right now. - * - * @returns - 0 on success, -EBUSY/-EACCES on failure, with errp set. - */ -int migrate_add_blocker(Error *reason, Error **errp); - -/** - * @migrate_del_blocker - remove a blocking error from migration - * - * @reason - the error blocking migration - */ -void migrate_del_blocker(Error *reason); - -int check_migratable(Object *obj, Error **err); - bool migrate_release_ram(void); bool migrate_postcopy_ram(void); bool migrate_zero_blocks(void); @@ -357,8 +311,4 @@ void global_state_store_running(void); void migration_page_queue_free(void); int ram_save_queue_pages(const char *rbname, ram_addr_t start, ram_addr_t len); uint64_t ram_pagesize_summary(void); - -PostcopyState postcopy_state_get(void); -/* Set the state and return the old state */ -PostcopyState postcopy_state_set(PostcopyState new_state); #endif diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index f4bf3f1b4e..848965963a 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -1067,4 +1067,6 @@ int64_t self_announce_delay(int round) void dump_vmstate_json_to_file(FILE *out_fp); +bool vmstate_check_only_migratable(const VMStateDescription *vmsd); + #endif diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index be9e22c955..83c1ceb33e 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -15,7 +15,7 @@ /* vl.c */ extern const char *bios_name; - +extern int only_migratable; extern const char *qemu_name; extern QemuUUID qemu_uuid; extern bool qemu_uuid_set; @@ -75,8 +75,8 @@ void qemu_remove_exit_notifier(Notifier *notify); void qemu_add_machine_init_done_notifier(Notifier *notify); void qemu_remove_machine_init_done_notifier(Notifier *notify); -int save_vmstate(const char *name); -int load_vmstate(const char *name); +int save_vmstate(const char *name, Error **errp); +int load_vmstate(const char *name, Error **errp); void qemu_announce_self(void); diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h index b8c93b9bce..01daaad00c 100644 --- a/include/sysemu/xen-mapcache.h +++ b/include/sysemu/xen-mapcache.h @@ -17,7 +17,7 @@ typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr start_addr, void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque); uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size, - uint8_t lock); + uint8_t lock, bool dma); ram_addr_t xen_ram_addr_from_mapcache(void *ptr); void xen_invalidate_map_cache_entry(uint8_t *buffer); void xen_invalidate_map_cache(void); @@ -31,7 +31,8 @@ static inline void xen_map_cache_init(phys_offset_to_gaddr_t f, static inline uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size, - uint8_t lock) + uint8_t lock, + bool dma) { abort(); } diff --git a/migration/Makefile.objs b/migration/Makefile.objs index 480dd493a9..c1920b6fc0 100644 --- a/migration/Makefile.objs +++ b/migration/Makefile.objs @@ -1,7 +1,7 @@ common-obj-y += migration.o socket.o fd.o exec.o common-obj-y += tls.o common-obj-y += colo-comm.o colo.o colo-failover.o -common-obj-y += vmstate.o +common-obj-y += vmstate.o page_cache.o common-obj-y += qemu-file.o common-obj-y += qemu-file-channel.o common-obj-y += xbzrle.o postcopy-ram.o diff --git a/migration/migration.c b/migration/migration.c index a5ade23e24..0304c013f3 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -17,6 +17,7 @@ #include "qemu/cutils.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" +#include "migration/blocker.h" #include "migration/migration.h" #include "migration/qemu-file.h" #include "sysemu/sysemu.h" @@ -77,13 +78,6 @@ static NotifierList migration_state_notifiers = static bool deferred_incoming; -/* - * Current state of incoming postcopy; note this is not part of - * MigrationIncomingState since it's state is used during cleanup - * at the end as MIS is being freed. - */ -static PostcopyState incoming_postcopy_state; - /* When we add fault tolerance, we could have several migrations at once. For now we don't need to add dynamic creation of migration */ @@ -1149,21 +1143,6 @@ void migrate_del_blocker(Error *reason) migration_blockers = g_slist_remove(migration_blockers, reason); } -int check_migratable(Object *obj, Error **err) -{ - DeviceClass *dc = DEVICE_GET_CLASS(obj); - if (only_migratable && dc->vmsd) { - if (dc->vmsd->unmigratable) { - error_setg(err, "Device %s is not migratable, but " - "--only-migratable was specified", - object_get_typename(obj)); - return -1; - } - } - - return 0; -} - void qmp_migrate_incoming(const char *uri, Error **errp) { Error *local_err = NULL; @@ -2097,14 +2076,3 @@ void migrate_fd_connect(MigrationState *s) s->migration_thread_running = true; } -PostcopyState postcopy_state_get(void) -{ - return atomic_mb_read(&incoming_postcopy_state); -} - -/* Set the state and return the old state */ -PostcopyState postcopy_state_set(PostcopyState new_state) -{ - return atomic_xchg(&incoming_postcopy_state, new_state); -} - diff --git a/page_cache.c b/migration/page_cache.c index 5f8578736e..5f8578736e 100644 --- a/page_cache.c +++ b/migration/page_cache.c diff --git a/include/migration/page_cache.h b/migration/page_cache.h index 10ed53274c..10ed53274c 100644 --- a/include/migration/page_cache.h +++ b/migration/page_cache.h diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index cdadaf6578..a0489f6542 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -784,3 +784,21 @@ void postcopy_discard_send_finish(MigrationState *ms, PostcopyDiscardState *pds) g_free(pds); } + +/* + * Current state of incoming postcopy; note this is not part of + * MigrationIncomingState since it's state is used during cleanup + * at the end as MIS is being freed. + */ +static PostcopyState incoming_postcopy_state; + +PostcopyState postcopy_state_get(void) +{ + return atomic_mb_read(&incoming_postcopy_state); +} + +/* Set the state and return the old state */ +PostcopyState postcopy_state_set(PostcopyState new_state) +{ + return atomic_xchg(&incoming_postcopy_state, new_state); +} diff --git a/migration/postcopy-ram.h b/migration/postcopy-ram.h index 4c25f03be2..52d51e8007 100644 --- a/migration/postcopy-ram.h +++ b/migration/postcopy-ram.h @@ -81,6 +81,28 @@ int postcopy_place_page(MigrationIncomingState *mis, void *host, void *from, int postcopy_place_page_zero(MigrationIncomingState *mis, void *host, size_t pagesize); +/* The current postcopy state is read/set by postcopy_state_get/set + * which update it atomically. + * The state is updated as postcopy messages are received, and + * in general only one thread should be writing to the state at any one + * time, initially the main thread and then the listen thread; + * Corner cases are where either thread finishes early and/or errors. + * The state is checked as messages are received to ensure that + * the source is sending us messages in the correct order. + * The state is also used by the RAM reception code to know if it + * has to place pages atomically, and the cleanup code at the end of + * the main thread to know if it has to delay cleanup until the end + * of postcopy. + */ +typedef enum { + POSTCOPY_INCOMING_NONE = 0, /* Initial state - no postcopy */ + POSTCOPY_INCOMING_ADVISE, + POSTCOPY_INCOMING_DISCARD, + POSTCOPY_INCOMING_LISTENING, + POSTCOPY_INCOMING_RUNNING, + POSTCOPY_INCOMING_END +} PostcopyState; + /* * Allocate a page of memory that can be mapped at a later point in time * using postcopy_place_page @@ -88,4 +110,8 @@ int postcopy_place_page_zero(MigrationIncomingState *mis, void *host, */ void *postcopy_get_tmp_page(MigrationIncomingState *mis); +PostcopyState postcopy_state_get(void); +/* Set the state and return the old state */ +PostcopyState postcopy_state_set(PostcopyState new_state); + #endif diff --git a/migration/ram.c b/migration/ram.c index d88afeaddd..f59fdd41a4 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -48,8 +48,14 @@ /***********************************************************/ /* ram save/restore */ +/* RAM_SAVE_FLAG_ZERO used to be named RAM_SAVE_FLAG_COMPRESS, it + * worked for pages that where filled with the same char. We switched + * it to only search for the zero value. And to avoid confusion with + * RAM_SSAVE_FLAG_COMPRESS_PAGE just rename it. + */ + #define RAM_SAVE_FLAG_FULL 0x01 /* Obsolete, not used anymore */ -#define RAM_SAVE_FLAG_COMPRESS 0x02 +#define RAM_SAVE_FLAG_ZERO 0x02 #define RAM_SAVE_FLAG_MEM_SIZE 0x04 #define RAM_SAVE_FLAG_PAGE 0x08 #define RAM_SAVE_FLAG_EOS 0x10 @@ -436,20 +442,21 @@ void migrate_compress_threads_create(void) * @offset: offset inside the block for the page * in the lower bits, it contains flags */ -static size_t save_page_header(RAMState *rs, RAMBlock *block, ram_addr_t offset) +static size_t save_page_header(RAMState *rs, QEMUFile *f, RAMBlock *block, + ram_addr_t offset) { size_t size, len; if (block == rs->last_sent_block) { offset |= RAM_SAVE_FLAG_CONTINUE; } - qemu_put_be64(rs->f, offset); + qemu_put_be64(f, offset); size = 8; if (!(offset & RAM_SAVE_FLAG_CONTINUE)) { len = strlen(block->idstr); - qemu_put_byte(rs->f, len); - qemu_put_buffer(rs->f, (uint8_t *)block->idstr, len); + qemu_put_byte(f, len); + qemu_put_buffer(f, (uint8_t *)block->idstr, len); size += 1 + len; rs->last_sent_block = block; } @@ -571,7 +578,7 @@ static int save_xbzrle_page(RAMState *rs, uint8_t **current_data, } /* Send XBZRLE based compressed page */ - bytes_xbzrle = save_page_header(rs, block, + bytes_xbzrle = save_page_header(rs, rs->f, block, offset | RAM_SAVE_FLAG_XBZRLE); qemu_put_byte(rs->f, ENCODING_FLAG_XBZRLE); qemu_put_be16(rs->f, encoded_len); @@ -745,7 +752,7 @@ static int save_zero_page(RAMState *rs, RAMBlock *block, ram_addr_t offset, if (is_zero_range(p, TARGET_PAGE_SIZE)) { rs->zero_pages++; rs->bytes_transferred += - save_page_header(rs, block, offset | RAM_SAVE_FLAG_COMPRESS); + save_page_header(rs, rs->f, block, offset | RAM_SAVE_FLAG_ZERO); qemu_put_byte(rs->f, 0); rs->bytes_transferred += 1; pages = 1; @@ -834,7 +841,7 @@ static int ram_save_page(RAMState *rs, PageSearchStatus *pss, bool last_stage) /* XBZRLE overflow or normal page */ if (pages == -1) { - rs->bytes_transferred += save_page_header(rs, block, + rs->bytes_transferred += save_page_header(rs, rs->f, block, offset | RAM_SAVE_FLAG_PAGE); if (send_async) { qemu_put_buffer_async(rs->f, p, TARGET_PAGE_SIZE, @@ -860,7 +867,7 @@ static int do_compress_ram_page(QEMUFile *f, RAMBlock *block, int bytes_sent, blen; uint8_t *p = block->host + (offset & TARGET_PAGE_MASK); - bytes_sent = save_page_header(rs, block, offset | + bytes_sent = save_page_header(rs, f, block, offset | RAM_SAVE_FLAG_COMPRESS_PAGE); blen = qemu_put_compression_data(f, p, TARGET_PAGE_SIZE, migrate_compress_level()); @@ -991,7 +998,7 @@ static int ram_save_compressed_page(RAMState *rs, PageSearchStatus *pss, pages = save_zero_page(rs, block, offset, p); if (pages == -1) { /* Make sure the first page is sent out before other pages */ - bytes_xmit = save_page_header(rs, block, offset | + bytes_xmit = save_page_header(rs, rs->f, block, offset | RAM_SAVE_FLAG_COMPRESS_PAGE); blen = qemu_put_compression_data(rs->f, p, TARGET_PAGE_SIZE, migrate_compress_level()); @@ -2406,7 +2413,7 @@ static int ram_load_postcopy(QEMUFile *f) trace_ram_load_postcopy_loop((uint64_t)addr, flags); place_needed = false; - if (flags & (RAM_SAVE_FLAG_COMPRESS | RAM_SAVE_FLAG_PAGE)) { + if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE)) { block = ram_block_from_stream(f, flags); host = host_from_ram_block_offset(block, addr); @@ -2453,7 +2460,7 @@ static int ram_load_postcopy(QEMUFile *f) last_host = host; switch (flags & ~RAM_SAVE_FLAG_CONTINUE) { - case RAM_SAVE_FLAG_COMPRESS: + case RAM_SAVE_FLAG_ZERO: ch = qemu_get_byte(f); memset(page_buffer, ch, TARGET_PAGE_SIZE); if (ch) { @@ -2542,7 +2549,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) flags = addr & ~TARGET_PAGE_MASK; addr &= TARGET_PAGE_MASK; - if (flags & (RAM_SAVE_FLAG_COMPRESS | RAM_SAVE_FLAG_PAGE | + if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE | RAM_SAVE_FLAG_COMPRESS_PAGE | RAM_SAVE_FLAG_XBZRLE)) { RAMBlock *block = ram_block_from_stream(f, flags); @@ -2604,7 +2611,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) } break; - case RAM_SAVE_FLAG_COMPRESS: + case RAM_SAVE_FLAG_ZERO: ch = qemu_get_byte(f); ram_handle_compressed(host, ch, TARGET_PAGE_SIZE); break; diff --git a/migration/savevm.c b/migration/savevm.c index 7f66d58a7e..f5e81948e6 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2069,7 +2069,7 @@ int qemu_loadvm_state(QEMUFile *f) return ret; } -int save_vmstate(const char *name) +int save_vmstate(const char *name, Error **errp) { BlockDriverState *bs, *bs1; QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1; @@ -2079,29 +2079,27 @@ int save_vmstate(const char *name) uint64_t vm_state_size; qemu_timeval tv; struct tm tm; - Error *local_err = NULL; AioContext *aio_context; if (!bdrv_all_can_snapshot(&bs)) { - error_report("Device '%s' is writable but does not support snapshots", - bdrv_get_device_name(bs)); + error_setg(errp, "Device '%s' is writable but does not support " + "snapshots", bdrv_get_device_name(bs)); return ret; } /* Delete old snapshots of the same name */ if (name) { - ret = bdrv_all_delete_snapshot(name, &bs1, &local_err); + ret = bdrv_all_delete_snapshot(name, &bs1, errp); if (ret < 0) { - error_reportf_err(local_err, - "Error while deleting snapshot on device '%s': ", - bdrv_get_device_name(bs1)); + error_prepend(errp, "Error while deleting snapshot on device " + "'%s': ", bdrv_get_device_name(bs1)); return ret; } } bs = bdrv_all_find_vmstate_bs(); if (bs == NULL) { - error_report("No block device can accept snapshots"); + error_setg(errp, "No block device can accept snapshots"); return ret; } aio_context = bdrv_get_aio_context(bs); @@ -2110,7 +2108,7 @@ int save_vmstate(const char *name) ret = global_state_store(); if (ret) { - error_report("Error saving global state"); + error_setg(errp, "Error saving global state"); return ret; } vm_stop(RUN_STATE_SAVE_VM); @@ -2142,21 +2140,20 @@ int save_vmstate(const char *name) /* save the VM state */ f = qemu_fopen_bdrv(bs, 1); if (!f) { - error_report("Could not open VM state file"); + error_setg(errp, "Could not open VM state file"); goto the_end; } - ret = qemu_savevm_state(f, &local_err); + ret = qemu_savevm_state(f, errp); vm_state_size = qemu_ftell(f); qemu_fclose(f); if (ret < 0) { - error_report_err(local_err); goto the_end; } ret = bdrv_all_create_snapshot(sn, bs, vm_state_size, &bs); if (ret < 0) { - error_report("Error while creating snapshot on '%s'", - bdrv_get_device_name(bs)); + error_setg(errp, "Error while creating snapshot on '%s'", + bdrv_get_device_name(bs)); goto the_end; } @@ -2229,7 +2226,7 @@ void qmp_xen_load_devices_state(const char *filename, Error **errp) migration_incoming_state_destroy(); } -int load_vmstate(const char *name) +int load_vmstate(const char *name, Error **errp) { BlockDriverState *bs, *bs_vm_state; QEMUSnapshotInfo sn; @@ -2239,20 +2236,22 @@ int load_vmstate(const char *name) MigrationIncomingState *mis = migration_incoming_get_current(); if (!bdrv_all_can_snapshot(&bs)) { - error_report("Device '%s' is writable but does not support snapshots", - bdrv_get_device_name(bs)); + error_setg(errp, + "Device '%s' is writable but does not support snapshots", + bdrv_get_device_name(bs)); return -ENOTSUP; } ret = bdrv_all_find_snapshot(name, &bs); if (ret < 0) { - error_report("Device '%s' does not have the requested snapshot '%s'", - bdrv_get_device_name(bs), name); + error_setg(errp, + "Device '%s' does not have the requested snapshot '%s'", + bdrv_get_device_name(bs), name); return ret; } bs_vm_state = bdrv_all_find_vmstate_bs(); if (!bs_vm_state) { - error_report("No block device supports snapshots"); + error_setg(errp, "No block device supports snapshots"); return -ENOTSUP; } aio_context = bdrv_get_aio_context(bs_vm_state); @@ -2264,8 +2263,8 @@ int load_vmstate(const char *name) if (ret < 0) { return ret; } else if (sn.vm_state_size == 0) { - error_report("This is a disk-only snapshot. Revert to it offline " - "using qemu-img."); + error_setg(errp, "This is a disk-only snapshot. Revert to it " + " offline using qemu-img"); return -EINVAL; } @@ -2274,7 +2273,7 @@ int load_vmstate(const char *name) ret = bdrv_all_goto_snapshot(name, &bs); if (ret < 0) { - error_report("Error %d while activating snapshot '%s' on '%s'", + error_setg(errp, "Error %d while activating snapshot '%s' on '%s'", ret, name, bdrv_get_device_name(bs)); return ret; } @@ -2282,7 +2281,7 @@ int load_vmstate(const char *name) /* restore the VM state */ f = qemu_fopen_bdrv(bs_vm_state, 0); if (!f) { - error_report("Could not open VM state file"); + error_setg(errp, "Could not open VM state file"); return -EINVAL; } @@ -2296,7 +2295,7 @@ int load_vmstate(const char *name) migration_incoming_state_destroy(); if (ret < 0) { - error_report("Error %d while loading VM state", ret); + error_setg(errp, "Error %d while loading VM state", ret); return ret; } @@ -2318,3 +2317,13 @@ void vmstate_register_ram_global(MemoryRegion *mr) { vmstate_register_ram(mr, NULL); } + +bool vmstate_check_only_migratable(const VMStateDescription *vmsd) +{ + /* check needed if --only-migratable is specified */ + if (!only_migratable) { + return true; + } + + return !(vmsd && vmsd->unmigratable); +} @@ -3254,7 +3254,7 @@ void device_add_completion(ReadLineState *rs, int nb_args, const char *str) TYPE_DEVICE); name = object_class_get_name(OBJECT_CLASS(dc)); - if (!dc->cannot_instantiate_with_device_add_yet + if (dc->user_creatable && !strncmp(name, str, len)) { readline_add_completion(rs, name); } diff --git a/qapi/block-core.json b/qapi/block-core.json index 6b974b952f..ea0b3e8b13 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2813,11 +2813,15 @@ # "name1=content1; name2=content2;" as explained by # CURLOPT_COOKIE(3). Defaults to no cookies. # +# @cookie-secret: ID of a QCryptoSecret object providing the cookie data in a +# secure way. See @cookie for the format. (since 2.10) +# # Since: 2.9 ## { 'struct': 'BlockdevOptionsCurlHttp', 'base': 'BlockdevOptionsCurlBase', - 'data': { '*cookie': 'str' } } + 'data': { '*cookie': 'str', + '*cookie-secret': 'str'} } ## # @BlockdevOptionsCurlHttps: @@ -2832,12 +2836,16 @@ # @sslverify: Whether to verify the SSL certificate's validity (defaults to # true) # +# @cookie-secret: ID of a QCryptoSecret object providing the cookie data in a +# secure way. See @cookie for the format. (since 2.10) +# # Since: 2.9 ## { 'struct': 'BlockdevOptionsCurlHttps', 'base': 'BlockdevOptionsCurlBase', 'data': { '*cookie': 'str', - '*sslverify': 'bool' } } + '*sslverify': 'bool', + '*cookie-secret': 'str'} } ## # @BlockdevOptionsCurlFtp: diff --git a/qdev-monitor.c b/qdev-monitor.c index e61d596ef7..3ecbf0bd25 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -114,7 +114,7 @@ static void qdev_print_devinfo(DeviceClass *dc) if (dc->desc) { error_printf(", desc \"%s\"", dc->desc); } - if (dc->cannot_instantiate_with_device_add_yet) { + if (!dc->user_creatable) { error_printf(", no-user"); } error_printf("\n"); @@ -156,7 +156,7 @@ static void qdev_print_devinfos(bool show_no_user) ? !test_bit(i, dc->categories) : !bitmap_empty(dc->categories, DEVICE_CATEGORY_MAX)) || (!show_no_user - && dc->cannot_instantiate_with_device_add_yet)) { + && !dc->user_creatable)) { continue; } if (!cat_printed) { @@ -241,7 +241,7 @@ static DeviceClass *qdev_get_device_class(const char **driver, Error **errp) } dc = DEVICE_CLASS(oc); - if (dc->cannot_instantiate_with_device_add_yet || + if (!dc->user_creatable || (qdev_hotplug && !dc->hotpluggable)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver", "pluggable device type"); @@ -453,7 +453,7 @@ static void cpu_class_init(ObjectClass *klass, void *data) * Reason: CPUs still need special care by board code: wiring up * IRQs, adding reset handlers, halting non-first CPUs, ... */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo cpu_type_info = { diff --git a/replay/replay-snapshot.c b/replay/replay-snapshot.c index 8cced4604f..c75cd38ece 100644 --- a/replay/replay-snapshot.c +++ b/replay/replay-snapshot.c @@ -62,14 +62,18 @@ void replay_vmstate_register(void) void replay_vmstate_init(void) { + Error *err = NULL; + if (replay_snapshot) { if (replay_mode == REPLAY_MODE_RECORD) { - if (save_vmstate(replay_snapshot) != 0) { + if (save_vmstate(replay_snapshot, &err) != 0) { + error_report_err(err); error_report("Could not create snapshot for icount record"); exit(1); } } else if (replay_mode == REPLAY_MODE_PLAY) { - if (load_vmstate(replay_snapshot) != 0) { + if (load_vmstate(replay_snapshot, &err) != 0) { + error_report_err(err); error_report("Could not load snapshot for icount replay"); exit(1); } diff --git a/stubs/migr-blocker.c b/stubs/migr-blocker.c index a5ba18f53d..2b64ac9560 100644 --- a/stubs/migr-blocker.c +++ b/stubs/migr-blocker.c @@ -1,6 +1,6 @@ #include "qemu/osdep.h" #include "qemu-common.h" -#include "migration/migration.h" +#include "migration/blocker.h" int migrate_add_blocker(Error *reason, Error **errp) { diff --git a/stubs/vmstate.c b/stubs/vmstate.c index 6d52f29bb2..6399474e49 100644 --- a/stubs/vmstate.c +++ b/stubs/vmstate.c @@ -1,7 +1,6 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "migration/vmstate.h" -#include "migration/migration.h" const VMStateDescription vmstate_dummy = {}; @@ -21,7 +20,7 @@ void vmstate_unregister(DeviceState *dev, { } -int check_migratable(Object *obj, Error **err) +bool vmstate_check_only_migratable(const VMStateDescription *vmsd) { - return 0; + return true; } diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 5e768404a1..a41d595c23 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -4075,7 +4075,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) cc->cpu_exec_enter = x86_cpu_exec_enter; cc->cpu_exec_exit = x86_cpu_exec_exit; - dc->cannot_instantiate_with_device_add_yet = false; + dc->user_creatable = true; } static const TypeInfo x86_cpu_type_info = { diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 55865dbee0..011d4a55b1 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -43,7 +43,7 @@ #include "standard-headers/asm-x86/hyperv.h" #include "hw/pci/pci.h" #include "hw/pci/msi.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "exec/memattrs.h" #include "trace.h" diff --git a/tests/Makefile.include b/tests/Makefile.include index 16ff8f399f..4277597e93 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -554,7 +554,7 @@ tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y) tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y) tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o -tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o migration/xbzrle.o page_cache.o $(test-util-obj-y) +tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o migration/xbzrle.o migration/page_cache.o $(test-util-obj-y) tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o tests/test-int128$(EXESUF): tests/test-int128.o tests/rcutorture$(EXESUF): tests/rcutorture.o $(test-util-obj-y) diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index 4e5c65a022..63da978f0b 100644 --- a/tests/bios-tables-test.c +++ b/tests/bios-tables-test.c @@ -175,8 +175,8 @@ static void test_acpi_fadt_table(test_data *data) ACPI_READ_FIELD(fadt_table->reset_value, addr); ACPI_READ_FIELD(fadt_table->arm_boot_flags, addr); ACPI_READ_FIELD(fadt_table->minor_revision, addr); - ACPI_READ_FIELD(fadt_table->Xfacs, addr); - ACPI_READ_FIELD(fadt_table->Xdsdt, addr); + ACPI_READ_FIELD(fadt_table->x_facs, addr); + ACPI_READ_FIELD(fadt_table->x_dsdt, addr); ACPI_READ_GENERIC_ADDRESS(fadt_table->xpm1a_event_block, addr); ACPI_READ_GENERIC_ADDRESS(fadt_table->xpm1b_event_block, addr); ACPI_READ_GENERIC_ADDRESS(fadt_table->xpm1a_control_block, addr); diff --git a/tests/test-x86-cpuid-compat.c b/tests/test-x86-cpuid-compat.c index 79a2e69a28..6c71e46391 100644 --- a/tests/test-x86-cpuid-compat.c +++ b/tests/test-x86-cpuid-compat.c @@ -1,6 +1,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "qapi/qmp/qlist.h" +#include "qapi/qmp/qstring.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qint.h" #include "qapi/qmp/qbool.h" @@ -78,6 +79,90 @@ static void add_cpuid_test(const char *name, const char *cmdline, qtest_add_data_func(name, args, test_cpuid_prop); } + +/* Parameters to a add_feature_test() test case */ +typedef struct FeatureTestArgs { + /* cmdline to start QEMU */ + const char *cmdline; + /* + * cpuid-input-eax and cpuid-input-ecx values to look for, + * in "feature-words" and "filtered-features" properties. + */ + uint32_t in_eax, in_ecx; + /* The register name to look for, in the X86CPUFeatureWordInfo array */ + const char *reg; + /* The bit to check in X86CPUFeatureWordInfo.features */ + int bitnr; + /* The expected value for the bit in (X86CPUFeatureWordInfo.features) */ + bool expected_value; +} FeatureTestArgs; + +/* Get the value for a feature word in a X86CPUFeatureWordInfo list */ +static uint32_t get_feature_word(QList *features, uint32_t eax, uint32_t ecx, + const char *reg) +{ + const QListEntry *e; + + for (e = qlist_first(features); e; e = qlist_next(e)) { + QDict *w = qobject_to_qdict(qlist_entry_obj(e)); + const char *rreg = qdict_get_str(w, "cpuid-register"); + uint32_t reax = qdict_get_int(w, "cpuid-input-eax"); + bool has_ecx = qdict_haskey(w, "cpuid-input-ecx"); + uint32_t recx = 0; + + if (has_ecx) { + recx = qdict_get_int(w, "cpuid-input-ecx"); + } + if (eax == reax && (!has_ecx || ecx == recx) && !strcmp(rreg, reg)) { + return qint_get_int(qobject_to_qint(qdict_get(w, "features"))); + } + } + return 0; +} + +static void test_feature_flag(const void *data) +{ + const FeatureTestArgs *args = data; + char *path; + QList *present, *filtered; + uint32_t value; + + qtest_start(args->cmdline); + path = get_cpu0_qom_path(); + present = qobject_to_qlist(qom_get(path, "feature-words")); + filtered = qobject_to_qlist(qom_get(path, "filtered-features")); + value = get_feature_word(present, args->in_eax, args->in_ecx, args->reg); + value |= get_feature_word(filtered, args->in_eax, args->in_ecx, args->reg); + qtest_end(); + + g_assert(!!(value & (1U << args->bitnr)) == args->expected_value); + + QDECREF(present); + QDECREF(filtered); + g_free(path); +} + +/* + * Add test case to ensure that a given feature flag is set in + * either "feature-words" or "filtered-features", when running QEMU + * using cmdline + */ +static FeatureTestArgs *add_feature_test(const char *name, const char *cmdline, + uint32_t eax, uint32_t ecx, + const char *reg, int bitnr, + bool expected_value) +{ + FeatureTestArgs *args = g_new0(FeatureTestArgs, 1); + args->cmdline = cmdline; + args->in_eax = eax; + args->in_ecx = ecx; + args->reg = reg; + args->bitnr = bitnr; + args->expected_value = expected_value; + qtest_add_data_func(name, args, test_feature_flag); + return args; +} + #ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS static void test_plus_minus_subprocess(void) { @@ -229,5 +314,31 @@ int main(int argc, char **argv) "-machine pc-i440fx-2.7 -cpu 486,+xstore", "xlevel2", 0); + /* Test feature parsing */ + add_feature_test("x86/cpuid/features/plus", + "-cpu 486,+arat", + 6, 0, "EAX", 2, true); + add_feature_test("x86/cpuid/features/minus", + "-cpu pentium,-mmx", + 1, 0, "EDX", 23, false); + add_feature_test("x86/cpuid/features/on", + "-cpu 486,arat=on", + 6, 0, "EAX", 2, true); + add_feature_test("x86/cpuid/features/off", + "-cpu pentium,mmx=off", + 1, 0, "EDX", 23, false); + add_feature_test("x86/cpuid/features/max-plus-invtsc", + "-cpu max,+invtsc", + 0x80000007, 0, "EDX", 8, true); + add_feature_test("x86/cpuid/features/max-invtsc-on", + "-cpu max,invtsc=on", + 0x80000007, 0, "EDX", 8, true); + add_feature_test("x86/cpuid/features/max-minus-mmx", + "-cpu max,-mmx", + 1, 0, "EDX", 23, false); + add_feature_test("x86/cpuid/features/max-invtsc-on,mmx=off", + "-cpu max,mmx=off", + 1, 0, "EDX", 23, false); + return g_test_run(); } @@ -4701,7 +4701,9 @@ int main(int argc, char **argv, char **envp) if (replay_mode != REPLAY_MODE_NONE) { replay_vmstate_init(); } else if (loadvm) { - if (load_vmstate(loadvm) < 0) { + Error *local_err = NULL; + if (load_vmstate(loadvm, &local_err) < 0) { + error_report_err(local_err); autostart = 0; } } |