diff options
-rw-r--r-- | block/file-posix.c | 50 | ||||
-rw-r--r-- | block/mirror.c | 5 | ||||
-rw-r--r-- | block/nbd-client.c | 12 | ||||
-rw-r--r-- | disas/microblaze.c | 2 | ||||
-rw-r--r-- | hw/display/cirrus_vga_rop2.h | 4 | ||||
-rw-r--r-- | hw/i386/amd_iommu.c | 3 | ||||
-rw-r--r-- | hw/i386/trace-events | 1 | ||||
-rw-r--r-- | hw/input/virtio-input.c | 33 | ||||
-rw-r--r-- | hw/scsi/megasas.c | 6 | ||||
-rw-r--r-- | include/hw/virtio/virtio-input.h | 5 | ||||
-rw-r--r-- | nbd/client.c | 2 | ||||
-rw-r--r-- | qemu-img.c | 196 | ||||
-rw-r--r-- | tests/boot-serial-test.c | 4 | ||||
-rw-r--r-- | ui/egl-helpers.c | 58 | ||||
-rw-r--r-- | ui/vnc.c | 17 |
15 files changed, 276 insertions, 122 deletions
diff --git a/block/file-posix.c b/block/file-posix.c index 53febd3767..0841a08785 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -144,6 +144,7 @@ typedef struct BDRVRawState { bool has_write_zeroes:1; bool discard_zeroes:1; bool use_linux_aio:1; + bool page_cache_inconsistent:1; bool has_fallocate; bool needs_alignment; } BDRVRawState; @@ -219,28 +220,28 @@ static int probe_logical_blocksize(int fd, unsigned int *sector_size_p) { unsigned int sector_size; bool success = false; + int i; errno = ENOTSUP; - - /* Try a few ioctls to get the right size */ + static const unsigned long ioctl_list[] = { #ifdef BLKSSZGET - if (ioctl(fd, BLKSSZGET, §or_size) >= 0) { - *sector_size_p = sector_size; - success = true; - } + BLKSSZGET, #endif #ifdef DKIOCGETBLOCKSIZE - if (ioctl(fd, DKIOCGETBLOCKSIZE, §or_size) >= 0) { - *sector_size_p = sector_size; - success = true; - } + DKIOCGETBLOCKSIZE, #endif #ifdef DIOCGSECTORSIZE - if (ioctl(fd, DIOCGSECTORSIZE, §or_size) >= 0) { - *sector_size_p = sector_size; - success = true; - } + DIOCGSECTORSIZE, #endif + }; + + /* Try a few ioctls to get the right size */ + for (i = 0; i < (int)ARRAY_SIZE(ioctl_list); i++) { + if (ioctl(fd, ioctl_list[i], §or_size) >= 0) { + *sector_size_p = sector_size; + success = true; + } + } return success ? 0 : -errno; } @@ -824,10 +825,31 @@ static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb) static ssize_t handle_aiocb_flush(RawPosixAIOData *aiocb) { + BDRVRawState *s = aiocb->bs->opaque; int ret; + if (s->page_cache_inconsistent) { + return -EIO; + } + ret = qemu_fdatasync(aiocb->aio_fildes); if (ret == -1) { + /* There is no clear definition of the semantics of a failing fsync(), + * so we may have to assume the worst. The sad truth is that this + * assumption is correct for Linux. Some pages are now probably marked + * clean in the page cache even though they are inconsistent with the + * on-disk contents. The next fdatasync() call would succeed, but no + * further writeback attempt will be made. We can't get back to a state + * in which we know what is on disk (we would have to rewrite + * everything that was touched since the last fdatasync() at least), so + * make bdrv_flush() fail permanently. Given that the behaviour isn't + * really defined, I have little hope that other OSes are doing better. + * + * Obviously, this doesn't affect O_DIRECT, which bypasses the page + * cache. */ + if ((s->open_flags & O_DIRECT) == 0) { + s->page_cache_inconsistent = true; + } return -errno; } return 0; diff --git a/block/mirror.c b/block/mirror.c index ca4baa510a..9e2fecc15e 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -634,7 +634,8 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s) } if (s->in_flight >= MAX_IN_FLIGHT) { - trace_mirror_yield(s, s->in_flight, s->buf_free_count, -1); + trace_mirror_yield(s, UINT64_MAX, s->buf_free_count, + s->in_flight); mirror_wait_for_io(s); continue; } @@ -809,7 +810,7 @@ static void coroutine_fn mirror_run(void *opaque) s->common.iostatus == BLOCK_DEVICE_IO_STATUS_OK) { if (s->in_flight >= MAX_IN_FLIGHT || s->buf_free_count == 0 || (cnt == 0 && s->in_flight > 0)) { - trace_mirror_yield(s, s->in_flight, s->buf_free_count, cnt); + trace_mirror_yield(s, cnt, s->buf_free_count, s->in_flight); mirror_wait_for_io(s); continue; } else if (cnt != 0) { diff --git a/block/nbd-client.c b/block/nbd-client.c index 0dc12c2d67..1e2952fdae 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -33,17 +33,15 @@ #define HANDLE_TO_INDEX(bs, handle) ((handle) ^ ((uint64_t)(intptr_t)bs)) #define INDEX_TO_HANDLE(bs, index) ((index) ^ ((uint64_t)(intptr_t)bs)) -static void nbd_recv_coroutines_enter_all(BlockDriverState *bs) +static void nbd_recv_coroutines_enter_all(NBDClientSession *s) { - NBDClientSession *s = nbd_get_client_session(bs); int i; for (i = 0; i < MAX_NBD_REQUESTS; i++) { if (s->recv_coroutine[i]) { - qemu_coroutine_enter(s->recv_coroutine[i]); + aio_co_wake(s->recv_coroutine[i]); } } - BDRV_POLL_WHILE(bs, s->read_reply_co); } static void nbd_teardown_connection(BlockDriverState *bs) @@ -58,7 +56,7 @@ static void nbd_teardown_connection(BlockDriverState *bs) qio_channel_shutdown(client->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); - nbd_recv_coroutines_enter_all(bs); + BDRV_POLL_WHILE(bs, client->read_reply_co); nbd_client_detach_aio_context(bs); object_unref(OBJECT(client->sioc)); @@ -76,7 +74,7 @@ static coroutine_fn void nbd_read_reply_entry(void *opaque) for (;;) { assert(s->reply.handle == 0); ret = nbd_receive_reply(s->ioc, &s->reply); - if (ret < 0) { + if (ret <= 0) { break; } @@ -103,6 +101,8 @@ static coroutine_fn void nbd_read_reply_entry(void *opaque) aio_co_wake(s->recv_coroutine[i]); qemu_coroutine_yield(); } + + nbd_recv_coroutines_enter_all(s); s->read_reply_co = NULL; } diff --git a/disas/microblaze.c b/disas/microblaze.c index 407c0a3ffa..7795a0bdb9 100644 --- a/disas/microblaze.c +++ b/disas/microblaze.c @@ -159,7 +159,7 @@ enum microblaze_instr_type { #define MIN_PVR_REGNUM 0 #define MAX_PVR_REGNUM 15 -#define REG_PC 32 /* PC */ +/* 32 is REG_PC */ #define REG_MSR 33 /* machine status reg */ #define REG_EAR 35 /* Exception reg */ #define REG_ESR 37 /* Exception reg */ diff --git a/hw/display/cirrus_vga_rop2.h b/hw/display/cirrus_vga_rop2.h index b86bcd6e09..b208b7348a 100644 --- a/hw/display/cirrus_vga_rop2.h +++ b/hw/display/cirrus_vga_rop2.h @@ -29,8 +29,8 @@ #elif DEPTH == 24 #define PUTPIXEL(s, a, c) do { \ ROP_OP(s, a, c); \ - ROP_OP(s, a + 1, (col >> 8)); \ - ROP_OP(s, a + 2, (col >> 16)); \ + ROP_OP(s, a + 1, (c >> 8)); \ + ROP_OP(s, a + 2, (c >> 16)); \ } while (0) #elif DEPTH == 32 #define PUTPIXEL(s, a, c) ROP_OP_32(s, a, c) diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index e0732ccaf1..f86a40aa30 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -572,8 +572,7 @@ static uint64_t amdvi_mmio_read(void *opaque, hwaddr addr, unsigned size) uint64_t val = -1; if (addr + size > AMDVI_MMIO_SIZE) { - trace_amdvi_mmio_read("error: addr outside region: max ", - (uint64_t)AMDVI_MMIO_SIZE, addr, size); + trace_amdvi_mmio_read_invalid(AMDVI_MMIO_SIZE, addr, size); return (uint64_t)-1; } diff --git a/hw/i386/trace-events b/hw/i386/trace-events index 88ad5e4c43..baed874a80 100644 --- a/hw/i386/trace-events +++ b/hw/i386/trace-events @@ -37,6 +37,7 @@ amdvi_cache_update(uint16_t domid, uint8_t bus, uint8_t slot, uint8_t func, uint amdvi_completion_wait_fail(uint64_t addr) "error: fail to write at address 0x%"PRIx64 amdvi_mmio_write(const char *reg, uint64_t addr, unsigned size, uint64_t val, uint64_t offset) "%s write addr 0x%"PRIx64", size %u, val 0x%"PRIx64", offset 0x%"PRIx64 amdvi_mmio_read(const char *reg, uint64_t addr, unsigned size, uint64_t offset) "%s read addr 0x%"PRIx64", size %u offset 0x%"PRIx64 +amdvi_mmio_read_invalid(int max, uint64_t addr, unsigned size) "error: addr outside region (max 0x%x): read addr 0x%" PRIx64 ", size %u" amdvi_command_error(uint64_t status) "error: Executing commands with command buffer disabled 0x%"PRIx64 amdvi_command_read_fail(uint64_t addr, uint32_t head) "error: fail to access memory at 0x%"PRIx64" + 0x%"PRIx32 amdvi_command_exec(uint32_t head, uint32_t tail, uint64_t buf) "command buffer head at 0x%"PRIx32" command buffer tail at 0x%"PRIx32" command buffer base at 0x%"PRIx64 diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c index b678ee9f20..0e42f0d02c 100644 --- a/hw/input/virtio-input.c +++ b/hw/input/virtio-input.c @@ -22,7 +22,6 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event) { VirtQueueElement *elem; - unsigned have, need; int i, len; if (!vinput->active) { @@ -32,10 +31,10 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event) /* queue up events ... */ if (vinput->qindex == vinput->qsize) { vinput->qsize++; - vinput->queue = realloc(vinput->queue, vinput->qsize * - sizeof(virtio_input_event)); + vinput->queue = g_realloc(vinput->queue, vinput->qsize * + sizeof(vinput->queue[0])); } - vinput->queue[vinput->qindex++] = *event; + vinput->queue[vinput->qindex++].event = *event; /* ... until we see a report sync ... */ if (event->type != cpu_to_le16(EV_SYN) || @@ -44,24 +43,24 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event) } /* ... then check available space ... */ - need = sizeof(virtio_input_event) * vinput->qindex; - virtqueue_get_avail_bytes(vinput->evt, &have, NULL, need, 0); - if (have < need) { - vinput->qindex = 0; - trace_virtio_input_queue_full(); - return; - } - - /* ... and finally pass them to the guest */ for (i = 0; i < vinput->qindex; i++) { elem = virtqueue_pop(vinput->evt, sizeof(VirtQueueElement)); if (!elem) { - /* should not happen, we've checked for space beforehand */ - fprintf(stderr, "%s: Huh? No vq elem available ...\n", __func__); + while (--i >= 0) { + virtqueue_unpop(vinput->evt, vinput->queue[i].elem, 0); + } + vinput->qindex = 0; + trace_virtio_input_queue_full(); return; } + vinput->queue[i].elem = elem; + } + + /* ... and finally pass them to the guest */ + for (i = 0; i < vinput->qindex; i++) { + elem = vinput->queue[i].elem; len = iov_from_buf(elem->in_sg, elem->in_num, - 0, vinput->queue+i, sizeof(virtio_input_event)); + 0, &vinput->queue[i].event, sizeof(virtio_input_event)); virtqueue_push(vinput->evt, elem, len); g_free(elem); } @@ -272,6 +271,8 @@ static void virtio_input_finalize(Object *obj) QTAILQ_REMOVE(&vinput->cfg_list, cfg, node); g_free(cfg); } + + g_free(vinput->queue); } static void virtio_input_device_unrealize(DeviceState *dev, Error **errp) { diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index e3d59b7c83..84b8caf901 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -291,7 +291,7 @@ static int megasas_map_sgl(MegasasState *s, MegasasCmd *cmd, union mfi_sgl *sgl) if (cmd->iov_size > iov_size) { trace_megasas_iovec_overflow(cmd->index, iov_size, cmd->iov_size); } else if (cmd->iov_size < iov_size) { - trace_megasas_iovec_underflow(cmd->iov_size, iov_size, cmd->iov_size); + trace_megasas_iovec_underflow(cmd->index, iov_size, cmd->iov_size); } cmd->iov_offset = 0; return 0; @@ -1924,8 +1924,8 @@ static int megasas_handle_abort(MegasasState *s, MegasasCmd *cmd) abort_ctx &= (uint64_t)0xFFFFFFFF; } if (abort_cmd->context != abort_ctx) { - trace_megasas_abort_invalid_context(cmd->index, abort_cmd->index, - abort_cmd->context); + trace_megasas_abort_invalid_context(cmd->index, abort_cmd->context, + abort_cmd->index); s->event_count++; return MFI_STAT_ABORT_NOT_POSSIBLE; } diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h index 55db31087a..91df57eca4 100644 --- a/include/hw/virtio/virtio-input.h +++ b/include/hw/virtio/virtio-input.h @@ -62,7 +62,10 @@ struct VirtIOInput { VirtQueue *evt, *sts; char *serial; - virtio_input_event *queue; + struct { + virtio_input_event event; + VirtQueueElement *elem; + } *queue; uint32_t qindex, qsize; bool active; diff --git a/nbd/client.c b/nbd/client.c index 3dc2564cd0..a58fb02cb4 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -812,6 +812,6 @@ ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply) LOG("invalid magic (got 0x%" PRIx32 ")", magic); return -EINVAL; } - return 0; + return sizeof(buf); } diff --git a/qemu-img.c b/qemu-img.c index 98b836b030..b220cf71d7 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -88,6 +88,16 @@ static void QEMU_NORETURN GCC_FMT_ATTR(1, 2) error_exit(const char *fmt, ...) exit(EXIT_FAILURE); } +static void QEMU_NORETURN missing_argument(const char *option) +{ + error_exit("missing argument for option '%s'", option); +} + +static void QEMU_NORETURN unrecognized_option(const char *option) +{ + error_exit("unrecognized option '%s'", option); +} + /* Please keep in synch with qemu-img.texi */ static void QEMU_NORETURN help(void) { @@ -406,13 +416,18 @@ static int img_create(int argc, char **argv) {"object", required_argument, 0, OPTION_OBJECT}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "F:b:f:he6o:q", + c = getopt_long(argc, argv, ":F:b:f:he6o:q", long_options, NULL); if (c == -1) { break; } switch(c) { + case ':': + missing_argument(argv[optind - 1]); + break; case '?': + unrecognized_option(argv[optind - 1]); + break; case 'h': help(); break; @@ -651,13 +666,18 @@ static int img_check(int argc, char **argv) {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "hf:r:T:q", + c = getopt_long(argc, argv, ":hf:r:T:q", long_options, &option_index); if (c == -1) { break; } switch(c) { + case ':': + missing_argument(argv[optind - 1]); + break; case '?': + unrecognized_option(argv[optind - 1]); + break; case 'h': help(); break; @@ -855,13 +875,18 @@ static int img_commit(int argc, char **argv) {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "f:ht:b:dpq", + c = getopt_long(argc, argv, ":f:ht:b:dpq", long_options, NULL); if (c == -1) { break; } switch(c) { + case ':': + missing_argument(argv[optind - 1]); + break; case '?': + unrecognized_option(argv[optind - 1]); + break; case 'h': help(); break; @@ -1190,13 +1215,18 @@ static int img_compare(int argc, char **argv) {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "hf:F:T:pqs", + c = getopt_long(argc, argv, ":hf:F:T:pqs", long_options, NULL); if (c == -1) { break; } switch (c) { + case ':': + missing_argument(argv[optind - 1]); + break; case '?': + unrecognized_option(argv[optind - 1]); + break; case 'h': help(); break; @@ -1926,13 +1956,18 @@ static int img_convert(int argc, char **argv) {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "hf:O:B:ce6o:s:l:S:pt:T:qnm:W", + c = getopt_long(argc, argv, ":hf:O:B:ce6o:s:l:S:pt:T:qnm:W", long_options, NULL); if (c == -1) { break; } switch(c) { + case ':': + missing_argument(argv[optind - 1]); + break; case '?': + unrecognized_option(argv[optind - 1]); + break; case 'h': help(); break; @@ -2502,13 +2537,18 @@ static int img_info(int argc, char **argv) {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "f:h", + c = getopt_long(argc, argv, ":f:h", long_options, &option_index); if (c == -1) { break; } switch(c) { + case ':': + missing_argument(argv[optind - 1]); + break; case '?': + unrecognized_option(argv[optind - 1]); + break; case 'h': help(); break; @@ -2713,13 +2753,18 @@ static int img_map(int argc, char **argv) {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "f:h", + c = getopt_long(argc, argv, ":f:h", long_options, &option_index); if (c == -1) { break; } switch (c) { + case ':': + missing_argument(argv[optind - 1]); + break; case '?': + unrecognized_option(argv[optind - 1]); + break; case 'h': help(); break; @@ -2835,13 +2880,18 @@ static int img_snapshot(int argc, char **argv) {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "la:c:d:hq", + c = getopt_long(argc, argv, ":la:c:d:hq", long_options, NULL); if (c == -1) { break; } switch(c) { + case ':': + missing_argument(argv[optind - 1]); + break; case '?': + unrecognized_option(argv[optind - 1]); + break; case 'h': help(); return 0; @@ -2988,13 +3038,18 @@ static int img_rebase(int argc, char **argv) {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "hf:F:b:upt:T:q", + c = getopt_long(argc, argv, ":hf:F:b:upt:T:q", long_options, NULL); if (c == -1) { break; } switch(c) { + case ':': + missing_argument(argv[optind - 1]); + break; case '?': + unrecognized_option(argv[optind - 1]); + break; case 'h': help(); return 0; @@ -3355,13 +3410,18 @@ static int img_resize(int argc, char **argv) {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "f:hq", + c = getopt_long(argc, argv, ":f:hq", long_options, NULL); if (c == -1) { break; } switch(c) { + case ':': + missing_argument(argv[optind - 1]); + break; case '?': + unrecognized_option(argv[optind - 1]); + break; case 'h': help(); break; @@ -3493,54 +3553,59 @@ static int img_amend(int argc, char **argv) {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "ho:f:t:pq", + c = getopt_long(argc, argv, ":ho:f:t:pq", long_options, NULL); if (c == -1) { break; } switch (c) { - case 'h': - case '?': - help(); - break; - case 'o': - if (!is_valid_option_list(optarg)) { - error_report("Invalid option list: %s", optarg); - ret = -1; - goto out_no_progress; - } - if (!options) { - options = g_strdup(optarg); - } else { - char *old_options = options; - options = g_strdup_printf("%s,%s", options, optarg); - g_free(old_options); - } - break; - case 'f': - fmt = optarg; - break; - case 't': - cache = optarg; - break; - case 'p': - progress = true; - break; - case 'q': - quiet = true; - break; - case OPTION_OBJECT: - opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!opts) { - ret = -1; - goto out_no_progress; - } - break; - case OPTION_IMAGE_OPTS: - image_opts = true; - break; + case ':': + missing_argument(argv[optind - 1]); + break; + case '?': + unrecognized_option(argv[optind - 1]); + break; + case 'h': + help(); + break; + case 'o': + if (!is_valid_option_list(optarg)) { + error_report("Invalid option list: %s", optarg); + ret = -1; + goto out_no_progress; + } + if (!options) { + options = g_strdup(optarg); + } else { + char *old_options = options; + options = g_strdup_printf("%s,%s", options, optarg); + g_free(old_options); + } + break; + case 'f': + fmt = optarg; + break; + case 't': + cache = optarg; + break; + case 'p': + progress = true; + break; + case 'q': + quiet = true; + break; + case OPTION_OBJECT: + opts = qemu_opts_parse_noisily(&qemu_object_opts, + optarg, true); + if (!opts) { + ret = -1; + goto out_no_progress; + } + break; + case OPTION_IMAGE_OPTS: + image_opts = true; + break; } } @@ -3759,14 +3824,19 @@ static int img_bench(int argc, char **argv) {"no-drain", no_argument, 0, OPTION_NO_DRAIN}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "hc:d:f:no:qs:S:t:w", long_options, NULL); + c = getopt_long(argc, argv, ":hc:d:f:no:qs:S:t:w", long_options, NULL); if (c == -1) { break; } switch (c) { - case 'h': + case ':': + missing_argument(argv[optind - 1]); + break; case '?': + unrecognized_option(argv[optind - 1]); + break; + case 'h': help(); break; case 'c': @@ -4093,7 +4163,7 @@ static int img_dd(int argc, char **argv) { 0, 0, 0, 0 } }; - while ((c = getopt_long(argc, argv, "hf:O:", long_options, NULL))) { + while ((c = getopt_long(argc, argv, ":hf:O:", long_options, NULL))) { if (c == EOF) { break; } @@ -4104,10 +4174,12 @@ static int img_dd(int argc, char **argv) case 'f': fmt = optarg; break; + case ':': + missing_argument(argv[optind - 1]); + break; case '?': - error_report("Try 'qemu-img --help' for more information."); - ret = -1; - goto out; + unrecognized_option(argv[optind - 1]); + break; case 'h': help(); break; @@ -4336,8 +4408,14 @@ int main(int argc, char **argv) qemu_add_opts(&qemu_source_opts); qemu_add_opts(&qemu_trace_opts); - while ((c = getopt_long(argc, argv, "+hVT:", long_options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "+:hVT:", long_options, NULL)) != -1) { switch (c) { + case ':': + missing_argument(argv[optind - 1]); + return 0; + case '?': + unrecognized_option(argv[optind - 1]); + return 0; case 'h': help(); return 0; diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c index 57edf6af33..11f48b049c 100644 --- a/tests/boot-serial-test.c +++ b/tests/boot-serial-test.c @@ -79,8 +79,8 @@ static void test_machine(const void *data) g_assert(fd != -1); args = g_strdup_printf("-M %s,accel=tcg -chardev file,id=serial0,path=%s" - " -serial chardev:serial0 %s", test->machine, - tmpname, test->extra); + " -no-shutdown -serial chardev:serial0 %s", + test->machine, tmpname, test->extra); qtest_start(args); unlink(tmpname); diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 584dd1b04d..b7b6b2e3cc 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -192,6 +192,56 @@ EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win) /* ---------------------------------------------------------------------- */ +/* + * Taken from glamor_egl.h from the Xorg xserver, which is MIT licensed + * + * Create an EGLDisplay from a native display type. This is a little quirky + * for a few reasons. + * + * 1: GetPlatformDisplayEXT and GetPlatformDisplay are the API you want to + * use, but have different function signatures in the third argument; this + * happens not to matter for us, at the moment, but it means epoxy won't alias + * them together. + * + * 2: epoxy 1.3 and earlier don't understand EGL client extensions, which + * means you can't call "eglGetPlatformDisplayEXT" directly, as the resolver + * will crash. + * + * 3: You can't tell whether you have EGL 1.5 at this point, because + * eglQueryString(EGL_VERSION) is a property of the display, which we don't + * have yet. So you have to query for extensions no matter what. Fortunately + * epoxy_has_egl_extension _does_ let you query for client extensions, so + * we don't have to write our own extension string parsing. + * + * 4. There is no EGL_KHR_platform_base to complement the EXT one, thus one + * needs to know EGL 1.5 is supported in order to use the eglGetPlatformDisplay + * function pointer. + * We can workaround this (circular dependency) by probing for the EGL 1.5 + * platform extensions (EGL_KHR_platform_gbm and friends) yet it doesn't seem + * like mesa will be able to advertise these (even though it can do EGL 1.5). + */ +static EGLDisplay qemu_egl_get_display(void *native) +{ + EGLDisplay dpy = EGL_NO_DISPLAY; + +#ifdef EGL_MESA_platform_gbm + /* In practise any EGL 1.5 implementation would support the EXT extension */ + if (epoxy_has_egl_extension(NULL, "EGL_EXT_platform_base")) { + PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplayEXT = + (void *) eglGetProcAddress("eglGetPlatformDisplayEXT"); + if (getPlatformDisplayEXT) { + dpy = getPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, native, NULL); + } + } +#endif + + if (dpy == EGL_NO_DISPLAY) { + /* fallback */ + dpy = eglGetDisplay(native); + } + return dpy; +} + int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug) { static const EGLint conf_att_gl[] = { @@ -222,12 +272,8 @@ int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug) setenv("LIBGL_DEBUG", "verbose", true); } - egl_dbg("eglGetDisplay (dpy %p) ...\n", dpy); -#ifdef EGL_MESA_platform_gbm - qemu_egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, dpy, NULL); -#else - qemu_egl_display = eglGetDisplay(dpy); -#endif + egl_dbg("qemu_egl_get_display (dpy %p) ...\n", dpy); + qemu_egl_display = qemu_egl_get_display(dpy); if (qemu_egl_display == EGL_NO_DISPLAY) { error_report("egl: eglGetDisplay failed"); return -1; @@ -3401,6 +3401,7 @@ vnc_display_create_creds(bool x509, static int vnc_display_get_address(const char *addrstr, bool websocket, + bool reverse, int displaynum, int to, bool has_ipv4, @@ -3480,21 +3481,22 @@ static int vnc_display_get_address(const char *addrstr, inet->port = g_strdup(port); } } else { + int offset = reverse ? 0 : 5900; if (parse_uint_full(port, &baseport, 10) < 0) { error_setg(errp, "can't convert to a number: %s", port); goto cleanup; } if (baseport > 65535 || - baseport + 5900 > 65535) { + baseport + offset > 65535) { error_setg(errp, "port %s out of range", port); goto cleanup; } inet->port = g_strdup_printf( - "%d", (int)baseport + 5900); + "%d", (int)baseport + offset); if (to) { inet->has_to = true; - inet->to = to + 5900; + inet->to = to + offset; } } @@ -3516,6 +3518,7 @@ static int vnc_display_get_address(const char *addrstr, } static int vnc_display_get_addresses(QemuOpts *opts, + bool reverse, SocketAddress ***retsaddr, size_t *retnsaddr, SocketAddress ***retwsaddr, @@ -3555,7 +3558,7 @@ static int vnc_display_get_addresses(QemuOpts *opts, qemu_opt_iter_init(&addriter, opts, "vnc"); while ((addr = qemu_opt_iter_next(&addriter)) != NULL) { int rv; - rv = vnc_display_get_address(addr, false, 0, to, + rv = vnc_display_get_address(addr, false, reverse, 0, to, has_ipv4, has_ipv6, ipv4, ipv6, &saddr, errp); @@ -3580,7 +3583,7 @@ static int vnc_display_get_addresses(QemuOpts *opts, qemu_opt_iter_init(&addriter, opts, "websocket"); while ((addr = qemu_opt_iter_next(&addriter)) != NULL) { - if (vnc_display_get_address(addr, true, displaynum, to, + if (vnc_display_get_address(addr, true, reverse, displaynum, to, has_ipv4, has_ipv6, ipv4, ipv6, &wsaddr, errp) < 0) { @@ -3777,7 +3780,8 @@ void vnc_display_open(const char *id, Error **errp) return; } - if (vnc_display_get_addresses(opts, &saddr, &nsaddr, + reverse = qemu_opt_get_bool(opts, "reverse", false); + if (vnc_display_get_addresses(opts, reverse, &saddr, &nsaddr, &wsaddr, &nwsaddr, errp) < 0) { goto fail; } @@ -3803,7 +3807,6 @@ void vnc_display_open(const char *id, Error **errp) } } - reverse = qemu_opt_get_bool(opts, "reverse", false); lock_key_sync = qemu_opt_get_bool(opts, "lock-key-sync", true); key_delay_ms = qemu_opt_get_number(opts, "key-delay-ms", 1); sasl = qemu_opt_get_bool(opts, "sasl", false); |