From cd723b85601baa7a0eeffbac83421357a70d81ee Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 14 Sep 2016 18:17:03 +0800 Subject: [PATCH 01/17] scsi-disk: Cleaning up around tray open state Even if tray is not open, it can be empty (blk_is_inserted() == false). Handle both cases correctly by replacing the s->tray_open checks with blk_is_available(), which is an AND of the two. Also simplify successive checks of them into blk_is_available(), in a couple cases. Signed-off-by: Fam Zheng Message-Id: <1473848224-24809-2-git-send-email-famz@redhat.com> Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-disk.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 77cba31e30..88beaf4bb8 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -396,7 +396,7 @@ static void scsi_read_data(SCSIRequest *req) return; } - if (s->tray_open) { + if (!blk_is_available(req->dev->conf.blk)) { scsi_read_complete(r, -ENOMEDIUM); return; } @@ -519,7 +519,7 @@ static void scsi_write_data(SCSIRequest *req) scsi_write_complete_noio(r, 0); return; } - if (s->tray_open) { + if (!blk_is_available(req->dev->conf.blk)) { scsi_write_complete_noio(r, -ENOMEDIUM); return; } @@ -792,10 +792,7 @@ static inline bool media_is_dvd(SCSIDiskState *s) if (s->qdev.type != TYPE_ROM) { return false; } - if (!blk_is_inserted(s->qdev.conf.blk)) { - return false; - } - if (s->tray_open) { + if (!blk_is_available(s->qdev.conf.blk)) { return false; } blk_get_geometry(s->qdev.conf.blk, &nb_sectors); @@ -808,10 +805,7 @@ static inline bool media_is_cd(SCSIDiskState *s) if (s->qdev.type != TYPE_ROM) { return false; } - if (!blk_is_inserted(s->qdev.conf.blk)) { - return false; - } - if (s->tray_open) { + if (!blk_is_available(s->qdev.conf.blk)) { return false; } blk_get_geometry(s->qdev.conf.blk, &nb_sectors); @@ -875,7 +869,7 @@ static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r, } if (format != 0xff) { - if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) { + if (!blk_is_available(s->qdev.conf.blk)) { scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); return -1; } @@ -1857,7 +1851,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) break; default: - if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) { + if (!blk_is_available(s->qdev.conf.blk)) { scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); return 0; } @@ -1886,7 +1880,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) memset(outbuf, 0, r->buflen); switch (req->cmd.buf[0]) { case TEST_UNIT_READY: - assert(!s->tray_open && blk_is_inserted(s->qdev.conf.blk)); + assert(blk_is_available(s->qdev.conf.blk)); break; case INQUIRY: buflen = scsi_disk_emulate_inquiry(req, outbuf); @@ -2126,7 +2120,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) command = buf[0]; - if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) { + if (!blk_is_available(s->qdev.conf.blk)) { scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); return 0; } From 2a2d69f490c1b1dc6b6d2aef385ee7b654497a77 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 14 Sep 2016 18:17:04 +0800 Subject: [PATCH 02/17] virtio-scsi: Don't abort when media is ejected With an ejected block backend, blk_get_aio_context() would return qemu_aio_context. In this case don't assert. Signed-off-by: Fam Zheng Message-Id: <1473848224-24809-3-git-send-email-famz@redhat.com> Signed-off-by: Paolo Bonzini --- hw/scsi/virtio-scsi.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index ce57ef6248..e596b64741 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -236,6 +236,13 @@ static void virtio_scsi_cancel_notify(Notifier *notifier, void *data) g_free(n); } +static inline void virtio_scsi_ctx_check(VirtIOSCSI *s, SCSIDevice *d) +{ + if (s->dataplane_started && d && blk_is_available(d->conf.blk)) { + assert(blk_get_aio_context(d->conf.blk) == s->ctx); + } +} + /* Return 0 if the request is ready to be completed and return to guest; * -EINPROGRESS if the request is submitted and will be completed later, in the * case of async cancellation. */ @@ -247,9 +254,7 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) int target; int ret = 0; - if (s->dataplane_started && d) { - assert(blk_get_aio_context(d->conf.blk) == s->ctx); - } + virtio_scsi_ctx_check(s, d); /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */ req->resp.tmf.response = VIRTIO_SCSI_S_OK; @@ -539,9 +544,7 @@ static bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req virtio_scsi_complete_cmd_req(req); return false; } - if (s->dataplane_started) { - assert(blk_get_aio_context(d->conf.blk) == s->ctx); - } + virtio_scsi_ctx_check(s, d); req->sreq = scsi_req_new(d, req->req.cmd.tag, virtio_scsi_get_lun(req->req.cmd.lun), req->req.cmd.cdb, req); From 670e56d3ed2918b3861d9216f2c0540d9e9ae0d5 Mon Sep 17 00:00:00 2001 From: Li Qiang Date: Mon, 12 Sep 2016 18:14:11 +0530 Subject: [PATCH 03/17] scsi: mptsas: use g_new0 to allocate MPTSASRequest object When processing IO request in mptsas, it uses g_new to allocate a 'req' object. If an error occurs before 'req->sreq' is allocated, It could lead to an OOB write in mptsas_free_request function. Use g_new0 to avoid it. Reported-by: Li Qiang Signed-off-by: Prasad J Pandit Message-Id: <1473684251-17476-1-git-send-email-ppandit@redhat.com> Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini --- hw/scsi/mptsas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c index 0e0a22f696..eaae1bb182 100644 --- a/hw/scsi/mptsas.c +++ b/hw/scsi/mptsas.c @@ -304,7 +304,7 @@ static int mptsas_process_scsi_io_request(MPTSASState *s, goto bad; } - req = g_new(MPTSASRequest, 1); + req = g_new0(MPTSASRequest, 1); QTAILQ_INSERT_TAIL(&s->pending, req, next); req->scsi_io = *scsi_io; req->dev = s; From d9911d14e01f5e97c6ac1fe681ef15334250d149 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 13 Sep 2016 13:57:19 -0700 Subject: [PATCH 04/17] cutils: Rewrite x86 buffer zero checking Handle alignment of buffers, so that the vector paths can be used more often. Signed-off-by: Richard Henderson Signed-off-by: Paolo Bonzini Message-Id: <1473800239-13841-1-git-send-email-rth@twiddle.net> Signed-off-by: Paolo Bonzini --- util/bufferiszero.c | 231 ++++++++++++++++++++++++++++++-------------- 1 file changed, 156 insertions(+), 75 deletions(-) diff --git a/util/bufferiszero.c b/util/bufferiszero.c index abe65f9d88..eb974b7849 100644 --- a/util/bufferiszero.c +++ b/util/bufferiszero.c @@ -26,38 +26,6 @@ #include "qemu/cutils.h" #include "qemu/bswap.h" - -/* vector definitions */ - -extern void link_error(void); - -#define ACCEL_BUFFER_ZERO(NAME, SIZE, VECTYPE, NONZERO) \ -static bool NAME(const void *buf, size_t len) \ -{ \ - const void *end = buf + len; \ - do { \ - const VECTYPE *p = buf; \ - VECTYPE t; \ - __builtin_prefetch(buf + SIZE); \ - barrier(); \ - if (SIZE == sizeof(VECTYPE) * 4) { \ - t = (p[0] | p[1]) | (p[2] | p[3]); \ - } else if (SIZE == sizeof(VECTYPE) * 8) { \ - t = p[0] | p[1]; \ - t |= p[2] | p[3]; \ - t |= p[4] | p[5]; \ - t |= p[6] | p[7]; \ - } else { \ - link_error(); \ - } \ - if (unlikely(NONZERO(t))) { \ - return false; \ - } \ - buf += SIZE; \ - } while (buf < end); \ - return true; \ -} - static bool buffer_zero_int(const void *buf, size_t len) { @@ -96,47 +64,174 @@ buffer_zero_int(const void *buf, size_t len) } } -#if defined(CONFIG_AVX2_OPT) || (defined(CONFIG_CPUID_H) && defined(__SSE2__)) -#include - +#if defined(CONFIG_AVX2_OPT) || defined(__SSE2__) /* Do not use push_options pragmas unnecessarily, because clang * does not support them. */ -#ifndef __SSE2__ +#ifdef CONFIG_AVX2_OPT #pragma GCC push_options #pragma GCC target("sse2") #endif #include -#define SSE2_NONZERO(X) \ - (_mm_movemask_epi8(_mm_cmpeq_epi8((X), _mm_setzero_si128())) != 0xFFFF) -ACCEL_BUFFER_ZERO(buffer_zero_sse2, 64, __m128i, SSE2_NONZERO) -#ifndef __SSE2__ + +/* Note that each of these vectorized functions require len >= 64. */ + +static bool +buffer_zero_sse2(const void *buf, size_t len) +{ + __m128i t = _mm_loadu_si128(buf); + __m128i *p = (__m128i *)(((uintptr_t)buf + 5 * 16) & -16); + __m128i *e = (__m128i *)(((uintptr_t)buf + len) & -16); + __m128i zero = _mm_setzero_si128(); + + /* Loop over 16-byte aligned blocks of 64. */ + while (likely(p <= e)) { + __builtin_prefetch(p); + t = _mm_cmpeq_epi8(t, zero); + if (unlikely(_mm_movemask_epi8(t) != 0xFFFF)) { + return false; + } + t = p[-4] | p[-3] | p[-2] | p[-1]; + p += 4; + } + + /* Finish the aligned tail. */ + t |= e[-3]; + t |= e[-2]; + t |= e[-1]; + + /* Finish the unaligned tail. */ + t |= _mm_loadu_si128(buf + len - 16); + + return _mm_movemask_epi8(_mm_cmpeq_epi8(t, zero)) == 0xFFFF; +} +#ifdef CONFIG_AVX2_OPT #pragma GCC pop_options #endif #ifdef CONFIG_AVX2_OPT +/* Note that due to restrictions/bugs wrt __builtin functions in gcc <= 4.8, + * the includes have to be within the corresponding push_options region, and + * therefore the regions themselves have to be ordered with increasing ISA. + */ #pragma GCC push_options #pragma GCC target("sse4") #include -#define SSE4_NONZERO(X) !_mm_testz_si128((X), (X)) -ACCEL_BUFFER_ZERO(buffer_zero_sse4, 64, __m128i, SSE4_NONZERO) -#pragma GCC pop_options +static bool +buffer_zero_sse4(const void *buf, size_t len) +{ + __m128i t = _mm_loadu_si128(buf); + __m128i *p = (__m128i *)(((uintptr_t)buf + 5 * 16) & -16); + __m128i *e = (__m128i *)(((uintptr_t)buf + len) & -16); + + /* Loop over 16-byte aligned blocks of 64. */ + while (likely(p <= e)) { + __builtin_prefetch(p); + if (unlikely(!_mm_testz_si128(t, t))) { + return false; + } + t = p[-4] | p[-3] | p[-2] | p[-1]; + p += 4; + } + + /* Finish the aligned tail. */ + t |= e[-3]; + t |= e[-2]; + t |= e[-1]; + + /* Finish the unaligned tail. */ + t |= _mm_loadu_si128(buf + len - 16); + + return _mm_testz_si128(t, t); +} + +#pragma GCC pop_options #pragma GCC push_options #pragma GCC target("avx2") #include -#define AVX2_NONZERO(X) !_mm256_testz_si256((X), (X)) -ACCEL_BUFFER_ZERO(buffer_zero_avx2, 128, __m256i, AVX2_NONZERO) + +static bool +buffer_zero_avx2(const void *buf, size_t len) +{ + /* Begin with an unaligned head of 32 bytes. */ + __m256i t = _mm256_loadu_si256(buf); + __m256i *p = (__m256i *)(((uintptr_t)buf + 5 * 32) & -32); + __m256i *e = (__m256i *)(((uintptr_t)buf + len) & -32); + + if (likely(p <= e)) { + /* Loop over 32-byte aligned blocks of 128. */ + do { + __builtin_prefetch(p); + if (unlikely(!_mm256_testz_si256(t, t))) { + return false; + } + t = p[-4] | p[-3] | p[-2] | p[-1]; + p += 4; + } while (p <= e); + } else { + t |= _mm256_loadu_si256(buf + 32); + if (len <= 128) { + goto last2; + } + } + + /* Finish the last block of 128 unaligned. */ + t |= _mm256_loadu_si256(buf + len - 4 * 32); + t |= _mm256_loadu_si256(buf + len - 3 * 32); + last2: + t |= _mm256_loadu_si256(buf + len - 2 * 32); + t |= _mm256_loadu_si256(buf + len - 1 * 32); + + return _mm256_testz_si256(t, t); +} #pragma GCC pop_options +#endif /* CONFIG_AVX2_OPT */ + +/* Note that for test_buffer_is_zero_next_accel, the most preferred + * ISA must have the least significant bit. + */ +#define CACHE_AVX2 1 +#define CACHE_SSE4 2 +#define CACHE_SSE2 4 + +/* Make sure that these variables are appropriately initialized when + * SSE2 is enabled on the compiler command-line, but the compiler is + * too old to support . + */ +#ifdef CONFIG_AVX2_OPT +# define INIT_CACHE 0 +# define INIT_ACCEL buffer_zero_int +#else +# ifndef __SSE2__ +# error "ISA selection confusion" +# endif +# define INIT_CACHE CACHE_SSE2 +# define INIT_ACCEL buffer_zero_sse2 #endif -#define CACHE_AVX2 2 -#define CACHE_AVX1 4 -#define CACHE_SSE4 8 -#define CACHE_SSE2 16 +static unsigned cpuid_cache = INIT_CACHE; +static bool (*buffer_accel)(const void *, size_t) = INIT_ACCEL; -static unsigned cpuid_cache; +static void init_accel(unsigned cache) +{ + bool (*fn)(const void *, size_t) = buffer_zero_int; + if (cache & CACHE_SSE2) { + fn = buffer_zero_sse2; + } +#ifdef CONFIG_AVX2_OPT + if (cache & CACHE_SSE4) { + fn = buffer_zero_sse4; + } + if (cache & CACHE_AVX2) { + fn = buffer_zero_avx2; + } +#endif + buffer_accel = fn; +} +#ifdef CONFIG_AVX2_OPT +#include static void __attribute__((constructor)) init_cpuid_cache(void) { int max = __get_cpuid_max(0, NULL); @@ -154,24 +249,21 @@ static void __attribute__((constructor)) init_cpuid_cache(void) } /* We must check that AVX is not just available, but usable. */ - if ((c & bit_OSXSAVE) && (c & bit_AVX)) { - __asm("xgetbv" : "=a"(a), "=d"(d) : "c"(0)); - if ((a & 6) == 6) { - cache |= CACHE_AVX1; - if (max >= 7) { - __cpuid_count(7, 0, a, b, c, d); - if (b & bit_AVX2) { - cache |= CACHE_AVX2; - } - } + if ((c & bit_OSXSAVE) && (c & bit_AVX) && max >= 7) { + int bv; + __asm("xgetbv" : "=a"(bv), "=d"(d) : "c"(0)); + __cpuid_count(7, 0, a, b, c, d); + if ((bv & 6) == 6 && (b & bit_AVX2)) { + cache |= CACHE_AVX2; } } #endif } cpuid_cache = cache; + init_accel(cache); } +#endif /* CONFIG_AVX2_OPT */ -#define HAVE_NEXT_ACCEL bool test_buffer_is_zero_next_accel(void) { /* If no bits set, we just tested buffer_zero_int, and there @@ -181,31 +273,20 @@ bool test_buffer_is_zero_next_accel(void) } /* Disable the accelerator we used before and select a new one. */ cpuid_cache &= cpuid_cache - 1; + init_accel(cpuid_cache); return true; } static bool select_accel_fn(const void *buf, size_t len) { - uintptr_t ibuf = (uintptr_t)buf; -#ifdef CONFIG_AVX2_OPT - if (len % 128 == 0 && ibuf % 32 == 0 && (cpuid_cache & CACHE_AVX2)) { - return buffer_zero_avx2(buf, len); - } - if (len % 64 == 0 && ibuf % 16 == 0 && (cpuid_cache & CACHE_SSE4)) { - return buffer_zero_sse4(buf, len); - } -#endif - if (len % 64 == 0 && ibuf % 16 == 0 && (cpuid_cache & CACHE_SSE2)) { - return buffer_zero_sse2(buf, len); + if (likely(len >= 64)) { + return buffer_accel(buf, len); } return buffer_zero_int(buf, len); } #else #define select_accel_fn buffer_zero_int -#endif - -#ifndef HAVE_NEXT_ACCEL bool test_buffer_is_zero_next_accel(void) { return false; From 883e4f7624e10b98d16d9adaffb8b1795664d899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Sat, 18 Jun 2016 13:24:02 +0530 Subject: [PATCH 05/17] Change net/socket.c to use socket_*() functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use socket_*() functions from include/qemu/sockets.h instead of listen()/bind()/connect()/parse_host_port(). socket_*() fucntions are QAPI based and this patch performs this api conversion since everything will be using QAPI based sockets in the future. Also add a helper function socket_address_to_string() in util/qemu-sockets.c which returns the string representation of socket address. The task was listed on http://wiki.qemu.org/BiteSizedTasks page. Signed-off-by: Ashijeet Acharya Signed-off-by: Marc-André Lureau Signed-off-by: Paolo Bonzini --- net/socket.c | 127 ++++++++++++++++++++++++++++----------------------- 1 file changed, 71 insertions(+), 56 deletions(-) diff --git a/net/socket.c b/net/socket.c index 3f98eefb34..982c8debe4 100644 --- a/net/socket.c +++ b/net/socket.c @@ -489,90 +489,105 @@ static int net_socket_listen_init(NetClientState *peer, { NetClientState *nc; NetSocketState *s; - struct sockaddr_in saddr; - int fd, ret; + SocketAddress *saddr; + int ret; + Error *local_error = NULL; - if (parse_host_port(&saddr, host_str) < 0) - return -1; - - fd = qemu_socket(PF_INET, SOCK_STREAM, 0); - if (fd < 0) { - perror("socket"); + saddr = socket_parse(host_str, &local_error); + if (saddr == NULL) { + error_report_err(local_error); return -1; } - qemu_set_nonblock(fd); - socket_set_fast_reuse(fd); - - ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); + ret = socket_listen(saddr, &local_error); if (ret < 0) { - perror("bind"); - closesocket(fd); - return -1; - } - ret = listen(fd, 0); - if (ret < 0) { - perror("listen"); - closesocket(fd); + qapi_free_SocketAddress(saddr); + error_report_err(local_error); return -1; } nc = qemu_new_net_client(&net_socket_info, peer, model, name); s = DO_UPCAST(NetSocketState, nc, nc); s->fd = -1; - s->listen_fd = fd; + s->listen_fd = ret; s->nc.link_down = true; qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s); + qapi_free_SocketAddress(saddr); return 0; } +typedef struct { + NetClientState *peer; + SocketAddress *saddr; + char *model; + char *name; +} socket_connect_data; + +static void socket_connect_data_free(socket_connect_data *c) +{ + qapi_free_SocketAddress(c->saddr); + g_free(c->model); + g_free(c->name); + g_free(c); +} + +static void net_socket_connected(int fd, Error *err, void *opaque) +{ + socket_connect_data *c = opaque; + NetSocketState *s; + char *addr_str = NULL; + Error *local_error = NULL; + + addr_str = socket_address_to_string(c->saddr, &local_error); + if (addr_str == NULL) { + error_report_err(local_error); + closesocket(fd); + goto end; + } + + s = net_socket_fd_init(c->peer, c->model, c->name, fd, true); + if (!s) { + closesocket(fd); + goto end; + } + + snprintf(s->nc.info_str, sizeof(s->nc.info_str), + "socket: connect to %s", addr_str); + +end: + g_free(addr_str); + socket_connect_data_free(c); +} + static int net_socket_connect_init(NetClientState *peer, const char *model, const char *name, const char *host_str) { - NetSocketState *s; - int fd, connected, ret; - struct sockaddr_in saddr; + socket_connect_data *c = g_new0(socket_connect_data, 1); + int fd = -1; + Error *local_error = NULL; - if (parse_host_port(&saddr, host_str) < 0) - return -1; + c->peer = peer; + c->model = g_strdup(model); + c->name = g_strdup(name); + c->saddr = socket_parse(host_str, &local_error); + if (c->saddr == NULL) { + goto err; + } - fd = qemu_socket(PF_INET, SOCK_STREAM, 0); + fd = socket_connect(c->saddr, &local_error, net_socket_connected, c); if (fd < 0) { - perror("socket"); - return -1; + goto err; } - qemu_set_nonblock(fd); - connected = 0; - for(;;) { - ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); - if (ret < 0) { - if (errno == EINTR || errno == EWOULDBLOCK) { - /* continue */ - } else if (errno == EINPROGRESS || - errno == EALREADY || - errno == EINVAL) { - break; - } else { - perror("connect"); - closesocket(fd); - return -1; - } - } else { - connected = 1; - break; - } - } - s = net_socket_fd_init(peer, model, name, fd, connected); - if (!s) - return -1; - snprintf(s->nc.info_str, sizeof(s->nc.info_str), - "socket: connect to %s:%d", - inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); return 0; + +err: + error_report_err(local_error); + socket_connect_data_free(c); + return -1; } static int net_socket_mcast_init(NetClientState *peer, From 58268c8d3d051f7fe329dcd42a9284cb4e3b3e31 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 14 Sep 2016 11:05:59 +0200 Subject: [PATCH 06/17] memory: remove memory_region_destructor_rom_device It is equivalent to memory_region_destructor_ram, use that one. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- memory.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/memory.c b/memory.c index 0eb6895fe6..1a1baf574c 100644 --- a/memory.c +++ b/memory.c @@ -944,11 +944,6 @@ static void memory_region_destructor_ram(MemoryRegion *mr) qemu_ram_free(mr->ram_block); } -static void memory_region_destructor_rom_device(MemoryRegion *mr) -{ - qemu_ram_free(mr->ram_block); -} - static bool memory_region_need_escape(char c) { return c == '/' || c == '[' || c == '\\' || c == ']'; @@ -1405,7 +1400,7 @@ void memory_region_init_rom_device(MemoryRegion *mr, mr->opaque = opaque; mr->terminates = true; mr->rom_device = true; - mr->destructor = memory_region_destructor_rom_device; + mr->destructor = memory_region_destructor_ram; mr->ram_block = qemu_ram_alloc(size, mr, errp); } From d251157ac1928191af851d199a9ff255d330bec9 Mon Sep 17 00:00:00 2001 From: Prasad J Pandit Date: Wed, 14 Sep 2016 15:09:12 +0530 Subject: [PATCH 07/17] scsi: pvscsi: limit process IO loop to ring size Vmware Paravirtual SCSI emulator while processing IO requests could run into an infinite loop if 'pvscsi_ring_pop_req_descr' always returned positive value. Limit IO loop to the ring size. Cc: qemu-stable@nongnu.org Reported-by: Li Qiang Signed-off-by: Prasad J Pandit Message-Id: <1473845952-30785-1-git-send-email-ppandit@redhat.com> Signed-off-by: Paolo Bonzini --- hw/scsi/vmw_pvscsi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index babac5a68a..a5ce7dea8e 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -247,8 +247,11 @@ static hwaddr pvscsi_ring_pop_req_descr(PVSCSIRingInfo *mgr) { uint32_t ready_ptr = RS_GET_FIELD(mgr, reqProdIdx); + uint32_t ring_size = PVSCSI_MAX_NUM_PAGES_REQ_RING + * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE; - if (ready_ptr != mgr->consumed_ptr) { + if (ready_ptr != mgr->consumed_ptr + && ready_ptr - mgr->consumed_ptr < ring_size) { uint32_t next_ready_ptr = mgr->consumed_ptr++ & mgr->txr_len_mask; uint32_t next_ready_page = From bb93e099888e8e7e959aa610ac783f41036bcc94 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Wed, 14 Sep 2016 13:54:24 +0800 Subject: [PATCH 08/17] pc: apic: fix touch LAPIC when irqchip is split MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add -kernel_irqchip=split ./x86-run x86/eventinj.flat qemu-system-x86_64 -enable-kvm -machine kernel_irqchip=split -cpu host -device pc-testdev -device isa-debug-exit,iobase=0xf4,iosize=0x4 -vnc none -serial stdio -device pci-testdev -kernel x86/eventinj.flat enabling apic paging enabled cr0 = 80010011 cr3 = 7fff000 cr4 = 20 Sending vec 33 and 62 and mask one with TPR irq1 running irq1 running After 33/62 TPR test FAIL: TPR irq0 running irq0 running Both irq1 and irq0 are executing twice. kvm_entry: vcpu 0 kvm_exit: reason MSR_WRITE rip 0x401f33 info 0 0 kvm_apic: apic_write APIC_EOI = 0x0 kvm_eoi: apicid 0 vector 62 kvm_msr: msr_write 80b = 0x0 kvm_entry: vcpu 0 kvm_exit: reason PENDING_INTERRUPT rip 0x401f35 info 0 0 kvm_userspace_exit: reason KVM_EXIT_IRQ_WINDOW_OPEN (7) kvm_inj_virq: irq 62 kvm_entry: vcpu 0 kvm_exit: reason IO_INSTRUCTION rip 0x4016ec info 3fd0008 0 From the trace we can see there is an interrupt window exit after the first interrupt EOI(irq 62), and the same irq(62) is injected duplicately after the interrupt window. QEMU does KVM_INTERRUPT(62) ioctl after KVM exits with KVM_EXIT_IRQ_WINDOW_OPEN, which QEMU requested while the guest was printing. The printing calls serial_update_irq() -> qemu_irq_lower() -> qemu_set_irq() -> gsi_handler() -> qemu_set_irq() -> pic_irq_request() -> apic_deliver_pic_intr() -> kvm_handle_interrupt() kvm_handle_interrupt() does interrupt_request |= CPU_INTERRUPT_HARD which later calls cpu_get_pic_interrupt() in kvm_arch_pre_run(), but that function uses stale information from APIC and injects 62 again. If we synchronized the APIC, then the test would #GP, because there would be no injectable interrupt in LAPIC or PIC, so pic_read_irq() would return 15, thinking it was spurious. This patch fix it by don't touch LAPIC if LAPIC is in kernel. Suggested-by: Paolo Bonzini Suggested-by: Radim Krčmář Cc: qemu-stable@nongnu.org Cc: Paolo Bonzini Cc: Radim Krčmář Cc: Michael S. Tsirkin Cc: Eduardo Habkost Signed-off-by: Wanpeng Li Message-Id: <1473832464-3478-1-git-send-email-wanpeng.li@hotmail.com> Signed-off-by: Paolo Bonzini --- hw/i386/pc.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index e31f70f428..2d6d7920ff 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -161,13 +161,15 @@ int cpu_get_pic_interrupt(CPUX86State *env) X86CPU *cpu = x86_env_get_cpu(env); int intno; - intno = apic_get_interrupt(cpu->apic_state); - if (intno >= 0) { - return intno; - } - /* read the irq from the PIC */ - if (!apic_accept_pic_intr(cpu->apic_state)) { - return -1; + if (!kvm_irqchip_in_kernel()) { + intno = apic_get_interrupt(cpu->apic_state); + if (intno >= 0) { + return intno; + } + /* read the irq from the PIC */ + if (!apic_accept_pic_intr(cpu->apic_state)) { + return -1; + } } intno = pic_read_irq(isa_pic); @@ -180,7 +182,7 @@ static void pic_irq_request(void *opaque, int irq, int level) X86CPU *cpu = X86_CPU(cs); DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq); - if (cpu->apic_state) { + if (cpu->apic_state && !kvm_irqchip_in_kernel()) { CPU_FOREACH(cs) { cpu = X86_CPU(cs); if (apic_accept_pic_intr(cpu->apic_state)) { From 7616f1c2da1c0f336a474a56ad6d32e15ccd666e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 21 Aug 2016 23:16:12 +0200 Subject: [PATCH 09/17] target-i386: fix ordering of fields in CPUX86State Make sure reset zeroes TSC_AUX, XCR0, PKRU. Move XSTATE_BV from the "vmstate only" section to the "KVM only" section. Signed-off-by: Paolo Bonzini --- target-i386/cpu.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index bb3ffda244..58e43b6f4b 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1035,6 +1035,9 @@ typedef struct CPUX86State { uint64_t tsc; uint64_t tsc_adjust; uint64_t tsc_deadline; + uint64_t tsc_aux; + + uint64_t xcr0; uint64_t mcg_status; uint64_t msr_ia32_misc_enable; @@ -1051,6 +1054,8 @@ typedef struct CPUX86State { uint64_t pat; uint32_t smbase; + uint32_t pkru; + /* End of state preserved by INIT (dummy marker). */ struct {} end_init_save; @@ -1135,20 +1140,15 @@ typedef struct CPUX86State { uint64_t mcg_ctl; uint64_t mcg_ext_ctl; uint64_t mce_banks[MCE_BANKS_DEF*4]; - - uint64_t tsc_aux; + uint64_t xstate_bv; /* vmstate */ uint16_t fpus_vmstate; uint16_t fptag_vmstate; uint16_t fpregs_format_vmstate; - uint64_t xstate_bv; - uint64_t xcr0; uint64_t xss; - uint32_t pkru; - TPRAccess tpr_access_type; } CPUX86State; From b8da57fa1537347f54a0864c61a68b14b02ce911 Mon Sep 17 00:00:00 2001 From: Wei Jiangang Date: Thu, 7 Apr 2016 10:46:23 +0800 Subject: [PATCH 10/17] linux-user: complete omission of removing uses of strdup The 900cfbc just removed two unchecked uses of strdup in fill_psinfo and missed the rest in core_dump_filename. This patch fixes it. Signed-off-by: Wei Jiangang Message-Id: <1459997185-15669-2-git-send-email-weijg.fnst@cn.fujitsu.com> Signed-off-by: Paolo Bonzini --- linux-user/elfload.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index f807baf389..29455e4e47 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -2718,7 +2718,6 @@ static int core_dump_filename(const TaskState *ts, char *buf, size_t bufsize) { char timestamp[64]; - char *filename = NULL; char *base_filename = NULL; struct timeval tv; struct tm tm; @@ -2731,14 +2730,12 @@ static int core_dump_filename(const TaskState *ts, char *buf, return (-1); } - filename = strdup(ts->bprm->filename); - base_filename = strdup(basename(filename)); + base_filename = g_path_get_basename(ts->bprm->filename); (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S", localtime_r(&tv.tv_sec, &tm)); (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core", base_filename, timestamp, (int)getpid()); - free(base_filename); - free(filename); + g_free(base_filename); return (0); } From 0d8e065fc5f72462a4664cea501d45e508c5755c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 13 Sep 2016 18:20:33 +0400 Subject: [PATCH 11/17] build-sys: add make 'help' target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a make 'help', to print a summary of the main Makefile targets. The format is loosely inspired by Linux make 'help' output. Signed-off-by: Marc-André Lureau Message-Id: <20160913142033.7705-1-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- Makefile | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Makefile b/Makefile index 50b4b3afb9..1fad5b78e5 100644 --- a/Makefile +++ b/Makefile @@ -669,3 +669,40 @@ endif -include $(wildcard *.d tests/*.d) include $(SRC_PATH)/tests/docker/Makefile.include + +.PHONY: help +help: + @echo 'Generic targets:' + @echo ' all - Build all' + @echo ' dir/file.o - Build specified target only' + @echo ' install - Install QEMU, documentation and tools' + @echo ' ctags/TAGS - Generate tags file for editors' + @echo ' cscope - Generate cscope index' + @echo '' + @$(if $(TARGET_DIRS), \ + echo 'Architecture specific targets:'; \ + $(foreach t, $(TARGET_DIRS), \ + printf " %-30s - Build for %s\\n" $(patsubst %,subdir-%,$(t)) $(t);) \ + echo '') + @echo 'Cleaning targets:' + @echo ' clean - Remove most generated files but keep the config' + @echo ' distclean - Remove all generated files' + @echo ' dist - Build a distributable tarball' + @echo '' + @echo 'Test targets:' + @echo ' check - Run all tests (check-help for details)' + @echo ' docker - Help about targets running tests inside Docker containers' + @echo '' + @echo 'Documentation targets:' + @echo ' dvi html info pdf' + @echo ' - Build documentation in specified format' + @echo '' +ifdef CONFIG_WIN32 + @echo 'Windows targets:' + @echo ' installer - Build NSIS-based installer for qemu-ga' +ifdef QEMU_GA_MSI_ENABLED + @echo ' msi - Build MSI-based installer for qemu-ga' +endif + @echo '' +endif + @echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build' From 71200fb9664c2967a1cdd22b68b0da3a8b2b3eb7 Mon Sep 17 00:00:00 2001 From: Lin Ma Date: Wed, 14 Sep 2016 14:22:50 +0800 Subject: [PATCH 12/17] qemu-char: avoid segfault if user lacks of permisson of a given logfile Function qemu_chr_alloc returns NULL if it failed to open logfile by any reason, says no write permission. For backends tty, stdio and msmouse, They need to check this return value to avoid segfault in this case. Signed-off-by: Lin Ma Cc: qemu-stable Message-Id: <20160914062250.22226-1-lma@suse.com> Signed-off-by: Paolo Bonzini --- backends/msmouse.c | 3 +++ qemu-char.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/backends/msmouse.c b/backends/msmouse.c index aeb905562d..aceb6dc475 100644 --- a/backends/msmouse.c +++ b/backends/msmouse.c @@ -159,6 +159,9 @@ static CharDriverState *qemu_chr_open_msmouse(const char *id, CharDriverState *chr; chr = qemu_chr_alloc(common, errp); + if (!chr) { + return NULL; + } chr->chr_write = msmouse_chr_write; chr->chr_close = msmouse_chr_close; chr->chr_accept_input = msmouse_chr_accept_input; diff --git a/qemu-char.c b/qemu-char.c index 7fa87a8b6e..8826419d7d 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -1230,6 +1230,9 @@ static CharDriverState *qemu_chr_open_stdio(const char *id, sigaction(SIGCONT, &act, NULL); chr = qemu_chr_open_fd(0, 1, common, errp); + if (!chr) { + return NULL; + } chr->chr_close = qemu_chr_close_stdio; chr->chr_set_echo = qemu_chr_set_echo_stdio; if (opts->has_signal) { @@ -1686,6 +1689,9 @@ static CharDriverState *qemu_chr_open_tty_fd(int fd, tty_serial_init(fd, 115200, 'N', 8, 1); chr = qemu_chr_open_fd(fd, fd, backend, errp); + if (!chr) { + return NULL; + } chr->chr_ioctl = tty_serial_ioctl; chr->chr_close = qemu_chr_close_tty; return chr; From 89d0a64f496fb4248885ebf75216c49337951540 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 6 Sep 2016 19:25:43 +0100 Subject: [PATCH 13/17] log: fix parsing of multiple trace:PATTERN log args If giving QEMU a log arg which asks to enable multiple different trace event patterns such as $QEMU -d trace:qio*,trace:qcrypto* the parser will then invoke trace_enable_events("qio*,trace:qcrypto*") trace_enable_events("qcrypto*") as when finding a 'trace:' prefix, it is not clever enough to strip anything after the next comma. As a result only the last 'trace:' match ever works. Rather than trying to be more clever with parsing the command line arg in place, simplify the code by using g_strsplit to break it into individual strings on ','. These resulting pieces can be directly used without worrying about trailing data from the next option. Signed-off-by: Daniel P. Berrange Message-Id: <1473186343-16704-1-git-send-email-berrange@redhat.com> Signed-off-by: Paolo Bonzini --- util/log.c | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/util/log.c b/util/log.c index 54b54e868a..e077340ae1 100644 --- a/util/log.c +++ b/util/log.c @@ -275,53 +275,42 @@ const QEMULogItem qemu_log_items[] = { { 0, NULL, NULL }, }; -static int cmp1(const char *s1, int n, const char *s2) -{ - if (strlen(s2) != n) { - return 0; - } - return memcmp(s1, s2, n) == 0; -} - /* takes a comma separated list of log masks. Return 0 if error. */ int qemu_str_to_log_mask(const char *str) { const QEMULogItem *item; - int mask; - const char *p, *p1; + int mask = 0; + char **parts = g_strsplit(str, ",", 0); + char **tmp; - p = str; - mask = 0; - for (;;) { - p1 = strchr(p, ','); - if (!p1) { - p1 = p + strlen(p); - } - if (cmp1(p,p1-p,"all")) { + for (tmp = parts; tmp && *tmp; tmp++) { + if (g_str_equal(*tmp, "all")) { for (item = qemu_log_items; item->mask != 0; item++) { mask |= item->mask; } #ifdef CONFIG_TRACE_LOG - } else if (strncmp(p, "trace:", 6) == 0 && p + 6 != p1) { - trace_enable_events(p + 6); + } else if (g_str_has_prefix(*tmp, "trace:") && (*tmp)[6] != '\0') { + trace_enable_events((*tmp) + 6); mask |= LOG_TRACE; #endif } else { for (item = qemu_log_items; item->mask != 0; item++) { - if (cmp1(p, p1 - p, item->name)) { + if (g_str_equal(*tmp, item->name)) { goto found; } } - return 0; + goto error; found: mask |= item->mask; } - if (*p1 != ',') { - break; - } - p = p1 + 1; } + + g_strfreev(parts); return mask; + + error: + g_strfreev(parts); + return 0; } void qemu_print_log_usage(FILE *f) From 885b7c44e4f8b7a012a92770a0dba8b238662caa Mon Sep 17 00:00:00 2001 From: Stanislav Shmarov Date: Tue, 13 Sep 2016 16:23:28 +0300 Subject: [PATCH 14/17] target-i386: Fixed syscall posssible segfault In user-mode emulation env->idt.base memory is allocated in linux-user/main.c with size 8*512 = 4096 (for 64-bit). When fake interrupt EXCP_SYSCALL is thrown do_interrupt_user checks destination privilege level for this fake exception, and tries to read 4 bytes at address base + (256 * 2^4)=4096, that causes segfault. Privlege level was checked only for int's, so lets read dpl from memory only for this case. Signed-off-by: Stanislav Shmarov Message-Id: <1473773008-2588376-1-git-send-email-snarpix@gmail.com> Signed-off-by: Paolo Bonzini --- target-i386/seg_helper.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c index 6cbdf17426..fb79f3180d 100644 --- a/target-i386/seg_helper.c +++ b/target-i386/seg_helper.c @@ -1137,25 +1137,27 @@ static void do_interrupt_real(CPUX86State *env, int intno, int is_int, static void do_interrupt_user(CPUX86State *env, int intno, int is_int, int error_code, target_ulong next_eip) { - SegmentCache *dt; - target_ulong ptr; - int dpl, cpl, shift; - uint32_t e2; + if (is_int) { + SegmentCache *dt; + target_ulong ptr; + int dpl, cpl, shift; + uint32_t e2; - dt = &env->idt; - if (env->hflags & HF_LMA_MASK) { - shift = 4; - } else { - shift = 3; - } - ptr = dt->base + (intno << shift); - e2 = cpu_ldl_kernel(env, ptr + 4); + dt = &env->idt; + if (env->hflags & HF_LMA_MASK) { + shift = 4; + } else { + shift = 3; + } + ptr = dt->base + (intno << shift); + e2 = cpu_ldl_kernel(env, ptr + 4); - dpl = (e2 >> DESC_DPL_SHIFT) & 3; - cpl = env->hflags & HF_CPL_MASK; - /* check privilege if software int */ - if (is_int && dpl < cpl) { - raise_exception_err(env, EXCP0D_GPF, (intno << shift) + 2); + dpl = (e2 >> DESC_DPL_SHIFT) & 3; + cpl = env->hflags & HF_CPL_MASK; + /* check privilege if software int */ + if (dpl < cpl) { + raise_exception_err(env, EXCP0D_GPF, (intno << shift) + 2); + } } /* Since we emulate only user space, we cannot do more than From 927d5a1d98ff9177ec29e883c5361e0d247291d8 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Thu, 15 Sep 2016 15:15:59 +0800 Subject: [PATCH 15/17] pc: apic: introduce APIC macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a new APIC macro to replace APIC_COMMON macro in hw/intc/apic.c in order to capture access LAPIC in qemu even if LAPIC is emulated in kvm. Suggested-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Cc: Paolo Bonzini Cc: Radim Krčmář Cc: Michael S. Tsirkin Cc: Eduardo Habkost Signed-off-by: Wanpeng Li Message-Id: <1473923759-13912-1-git-send-email-wanpeng.li@hotmail.com> Signed-off-by: Paolo Bonzini --- hw/intc/apic.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 45887d99c0..7bd1d279c4 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -39,6 +39,10 @@ static APICCommonState *local_apics[MAX_APICS + 1]; +#define TYPE_APIC "apic" +#define APIC(obj) \ + OBJECT_CHECK(APICCommonState, (obj), TYPE_APIC) + static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode); static void apic_update_irq(APICCommonState *s); static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, @@ -163,7 +167,7 @@ static void apic_local_deliver(APICCommonState *s, int vector) void apic_deliver_pic_intr(DeviceState *dev, int level) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); if (level) { apic_local_deliver(s, APIC_LVT_LINT0); @@ -373,7 +377,7 @@ static void apic_update_irq(APICCommonState *s) void apic_poll_irq(DeviceState *dev) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); apic_sync_vapic(s, SYNC_FROM_VAPIC); apic_update_irq(s); @@ -479,7 +483,7 @@ static void apic_startup(APICCommonState *s, int vector_num) void apic_sipi(DeviceState *dev) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI); @@ -493,7 +497,7 @@ static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); uint32_t deliver_bitmask[MAX_APIC_WORDS]; int dest_shorthand = (s->icr[0] >> 18) & 3; APICCommonState *apic_iter; @@ -550,7 +554,7 @@ static bool apic_check_pic(APICCommonState *s) int apic_get_interrupt(DeviceState *dev) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); int intno; /* if the APIC is installed or enabled, we let the 8259 handle the @@ -584,7 +588,7 @@ int apic_get_interrupt(DeviceState *dev) int apic_accept_pic_intr(DeviceState *dev) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); uint32_t lvt0; if (!s) @@ -663,7 +667,7 @@ static uint32_t apic_mem_readl(void *opaque, hwaddr addr) if (!dev) { return 0; } - s = APIC_COMMON(dev); + s = APIC(dev); index = (addr >> 4) & 0xff; switch(index) { @@ -766,7 +770,7 @@ static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val) if (!dev) { return; } - s = APIC_COMMON(dev); + s = APIC(dev); trace_apic_mem_writel(addr, val); @@ -870,7 +874,7 @@ static const MemoryRegionOps apic_io_ops = { static void apic_realize(DeviceState *dev, Error **errp) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); if (s->id >= MAX_APICS) { error_setg(errp, "%s initialization failed. APIC ID %d is invalid", @@ -889,7 +893,7 @@ static void apic_realize(DeviceState *dev, Error **errp) static void apic_unrealize(DeviceState *dev, Error **errp) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); timer_del(s->timer); timer_free(s->timer); @@ -912,7 +916,7 @@ static void apic_class_init(ObjectClass *klass, void *data) } static const TypeInfo apic_info = { - .name = "apic", + .name = TYPE_APIC, .instance_size = sizeof(APICCommonState), .parent = TYPE_APIC_COMMON, .class_init = apic_class_init, From 46f5feaa0ac24c0dbe6e0d04d0b11ee1df7c3bfd Mon Sep 17 00:00:00 2001 From: Pavel Dovgalyuk Date: Thu, 15 Sep 2016 12:01:28 +0300 Subject: [PATCH 16/17] kvmvapic: fix state change handler This patch fixes kvmvapic state change handler. It clears vmsentry field to allow recreating it at further vmstate loads. Signed-off-by: Pavel Dovgalyuk Message-Id: <20160915090127.6440.48793.stgit@PASHA-ISP> Signed-off-by: Paolo Bonzini --- hw/i386/kvmvapic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c index 3bf1ddd976..a1cd9b5a29 100644 --- a/hw/i386/kvmvapic.c +++ b/hw/i386/kvmvapic.c @@ -768,6 +768,7 @@ static void kvmvapic_vm_state_change(void *opaque, int running, } qemu_del_vm_change_state_handler(s->vmsentry); + s->vmsentry = NULL; } static int vapic_post_load(void *opaque, int version_id) From 39c88f56977f9ad2451444d70dd21d8189d74f99 Mon Sep 17 00:00:00 2001 From: Pavel Dovgalyuk Date: Thu, 15 Sep 2016 12:01:33 +0300 Subject: [PATCH 17/17] pcspk: adding vmstate for save/restore VMState added by this patch preserves correct loading of the PC speaker device state. Signed-off-by: Pavel Dovgalyuk Message-Id: <20160915090133.6440.65457.stgit@PASHA-ISP> Signed-off-by: Paolo Bonzini --- hw/audio/pcspk.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index 42a6f4885a..984534b2d1 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -52,8 +52,8 @@ typedef struct { unsigned int pit_count; unsigned int samples; unsigned int play_pos; - int data_on; - int dummy_refresh_clock; + uint8_t data_on; + uint8_t dummy_refresh_clock; } PCSpkState; static const char *s_spk = "pcspk"; @@ -187,6 +187,18 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp) pcspk_state = s; } +static const VMStateDescription vmstate_spk = { + .name = "pcspk", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(data_on, PCSpkState), + VMSTATE_UINT8(dummy_refresh_clock, PCSpkState), + VMSTATE_END_OF_LIST() + } +}; + static Property pcspk_properties[] = { DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, -1), DEFINE_PROP_END_OF_LIST(), @@ -198,6 +210,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data) dc->realize = pcspk_realizefn; set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->vmsd = &vmstate_spk; dc->props = pcspk_properties; /* Reason: realize sets global pcspk_state */ dc->cannot_instantiate_with_device_add_yet = true;