diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2012-05-31 22:19:22 -0300 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2012-05-31 22:19:22 -0300 |
commit | 9688c60477f178d4a838c2e778e8d3281c69119d (patch) | |
tree | 70c0418beedc0a0b8e1e8ec97ac444b8466bc229 | |
parent | qemu-kvm: Drop support for raw ioport access (diff) | |
parent | Merge commit 'b3dbb9546ade0108156a04b4983cd3057fd77563' into upstream-merge (diff) | |
download | qemu-kvm-9688c60477f178d4a838c2e778e8d3281c69119d.tar.gz qemu-kvm-9688c60477f178d4a838c2e778e8d3281c69119d.tar.bz2 qemu-kvm-9688c60477f178d4a838c2e778e8d3281c69119d.zip |
Merge branch 'upstream-merge'
* upstream-merge: (44 commits)
Update version for 1.1.0-rc4 release
pc-bios: Update OpenBIOS images
block: prevent snapshot mode $TMPDIR symlink attack
xhci: add usage info to docs
vnc: fix segfault in vnc_display_pw_expire()
Expose CPUID leaf 7 only for -cpu host
qemu-ga: avoid blocking on atime update when reading /etc/mtab
qemu-ga: Fix use of environ on Darwin
pci: call object_unparent() before free_qdev()
fix multiboot loading if load_end_addr == 0
vga: fix vram double-mapping with -vga std and -M pc-0.12
cocoa: Suppress Cocoa frontend for -qtest
arch_init: Fix AltiVec build on Darwin/ppc
slirp: Avoid redefining MAX_TCPOPTLEN
slirp: Avoid statements without effect on Big Endian host
ISCSI: Switch to using READ16/WRITE16 for I/O to the LUN
ISCSI: Only call READCAPACITY16 for SBC devices, use READCAPACITY10 for MMC
ISCSI: get device type at connection time
ISCSI: change num_blocks to 64-bit
ISCSI: redo how we set up the events
...
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | arch_init.c | 4 | ||||
-rw-r--r-- | audio/audio.c | 12 | ||||
-rw-r--r-- | block.c | 37 | ||||
-rw-r--r-- | block/iscsi.c | 240 | ||||
-rw-r--r-- | block/qcow2-cluster.c | 23 | ||||
-rw-r--r-- | block/qcow2.c | 3 | ||||
-rw-r--r-- | block/sheepdog.c | 113 | ||||
-rw-r--r-- | block/vvfat.c | 7 | ||||
-rw-r--r-- | block_int.h | 2 | ||||
-rwxr-xr-x | configure | 19 | ||||
-rw-r--r-- | docs/usb2.txt | 15 | ||||
-rw-r--r-- | hw/acpi_piix4.c | 1 | ||||
-rw-r--r-- | hw/es1370.c | 11 | ||||
-rw-r--r-- | hw/fdc.c | 14 | ||||
-rw-r--r-- | hw/multiboot.c | 12 | ||||
-rw-r--r-- | hw/pc.c | 25 | ||||
-rw-r--r-- | hw/pci.c | 1 | ||||
-rw-r--r-- | hw/scsi-bus.c | 2 | ||||
-rw-r--r-- | hw/vga.c | 7 | ||||
-rw-r--r-- | hw/vga_int.h | 1 | ||||
-rw-r--r-- | hw/xen_common.h | 2 | ||||
-rw-r--r-- | hw/xen_disk.c | 42 | ||||
-rw-r--r-- | pc-bios/README | 2 | ||||
-rw-r--r-- | pc-bios/openbios-ppc | bin | 729876 -> 729876 bytes | |||
-rw-r--r-- | pc-bios/openbios-sparc32 | bin | 381764 -> 381764 bytes | |||
-rw-r--r-- | pc-bios/openbios-sparc64 | bin | 1598648 -> 1598648 bytes | |||
-rw-r--r-- | qemu-img.texi | 18 | ||||
-rw-r--r-- | qga/commands-posix.c | 13 | ||||
m--------- | roms/openbios | 0 | ||||
-rw-r--r-- | slirp/ip.h | 20 | ||||
-rw-r--r-- | slirp/tcp.h | 13 | ||||
-rw-r--r-- | slirp/tcp_output.c | 1 | ||||
-rw-r--r-- | target-i386/cpu.c | 22 | ||||
-rw-r--r-- | target-i386/cpu.h | 2 | ||||
-rw-r--r-- | tcg/ppc/tcg-target.c | 16 | ||||
-rw-r--r-- | tests/fdc-test.c | 65 | ||||
-rwxr-xr-x | tests/qemu-iotests/035 | 2 | ||||
-rw-r--r-- | trace-events | 4 | ||||
-rw-r--r-- | ui/cocoa.m | 3 | ||||
-rw-r--r-- | ui/vnc.c | 4 | ||||
-rw-r--r-- | xen-all.c | 22 |
42 files changed, 584 insertions, 218 deletions
@@ -1 +1 @@ -1.0.93 +1.0.94 diff --git a/arch_init.c b/arch_init.c index 988adcae0..a9e8b7442 100644 --- a/arch_init.c +++ b/arch_init.c @@ -100,6 +100,10 @@ const uint32_t arch_type = QEMU_ARCH; #define VECTYPE vector unsigned char #define SPLAT(p) vec_splat(vec_ld(0, p), 0) #define ALL_EQ(v1, v2) vec_all_eq(v1, v2) +/* altivec.h may redefine the bool macro as vector type. + * Reset it to POSIX semantics. */ +#undef bool +#define bool _Bool #elif defined __SSE2__ #include <emmintrin.h> #define VECTYPE __m128i diff --git a/audio/audio.c b/audio/audio.c index bd9237e9d..583ee51ea 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1775,10 +1775,12 @@ static void audio_atexit (void) HWVoiceOut *hwo = NULL; HWVoiceIn *hwi = NULL; - while ((hwo = audio_pcm_hw_find_any_enabled_out (hwo))) { + while ((hwo = audio_pcm_hw_find_any_out (hwo))) { SWVoiceCap *sc; - hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE); + if (hwo->enabled) { + hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE); + } hwo->pcm_ops->fini_out (hwo); for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) { @@ -1791,8 +1793,10 @@ static void audio_atexit (void) } } - while ((hwi = audio_pcm_hw_find_any_enabled_in (hwi))) { - hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE); + while ((hwi = audio_pcm_hw_find_any_in (hwi))) { + if (hwi->enabled) { + hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE); + } hwi->pcm_ops->fini_in (hwi); } @@ -409,28 +409,36 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options) return bdrv_create(drv, filename, options); } -#ifdef _WIN32 -void get_tmp_filename(char *filename, int size) +/* + * Create a uniquely-named empty temporary file. + * Return 0 upon success, otherwise a negative errno value. + */ +int get_tmp_filename(char *filename, int size) { +#ifdef _WIN32 char temp_dir[MAX_PATH]; - - GetTempPath(MAX_PATH, temp_dir); - GetTempFileName(temp_dir, "qem", 0, filename); -} + /* GetTempFileName requires that its output buffer (4th param) + have length MAX_PATH or greater. */ + assert(size >= MAX_PATH); + return (GetTempPath(MAX_PATH, temp_dir) + && GetTempFileName(temp_dir, "qem", 0, filename) + ? 0 : -GetLastError()); #else -void get_tmp_filename(char *filename, int size) -{ int fd; const char *tmpdir; - /* XXX: race condition possible */ tmpdir = getenv("TMPDIR"); if (!tmpdir) tmpdir = "/tmp"; - snprintf(filename, size, "%s/vl.XXXXXX", tmpdir); + if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) { + return -EOVERFLOW; + } fd = mkstemp(filename); - close(fd); -} + if (fd < 0 || close(fd)) { + return -errno; + } + return 0; #endif +} /* * Detect host devices. By convention, /dev/cdrom[N] is always @@ -753,7 +761,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, bdrv_delete(bs1); - get_tmp_filename(tmp_filename, sizeof(tmp_filename)); + ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename)); + if (ret < 0) { + return ret; + } /* Real path is meaningless for protocols */ if (is_protocol) diff --git a/block/iscsi.c b/block/iscsi.c index d37c4ee17..22888a084 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -25,10 +25,12 @@ #include "config-host.h" #include <poll.h> +#include <arpa/inet.h> #include "qemu-common.h" #include "qemu-error.h" #include "block_int.h" #include "trace.h" +#include "hw/scsi-defs.h" #include <iscsi/iscsi.h> #include <iscsi/scsi-lowlevel.h> @@ -37,8 +39,10 @@ typedef struct IscsiLun { struct iscsi_context *iscsi; int lun; + enum scsi_inquiry_peripheral_device_type type; int block_size; - unsigned long num_blocks; + uint64_t num_blocks; + int events; } IscsiLun; typedef struct IscsiAIOCB { @@ -104,11 +108,27 @@ static void iscsi_set_events(IscsiLun *iscsilun) { struct iscsi_context *iscsi = iscsilun->iscsi; + int ev; - qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), iscsi_process_read, - (iscsi_which_events(iscsi) & POLLOUT) - ? iscsi_process_write : NULL, - iscsi_process_flush, iscsilun); + /* We always register a read handler. */ + ev = POLLIN; + ev |= iscsi_which_events(iscsi); + if (ev != iscsilun->events) { + qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), + iscsi_process_read, + (ev & POLLOUT) ? iscsi_process_write : NULL, + iscsi_process_flush, + iscsilun); + + } + + /* If we just added an event, the callback might be delayed + * unless we call qemu_notify_event(). + */ + if (ev & ~iscsilun->events) { + qemu_notify_event(); + } + iscsilun->events = ev; } static void @@ -161,12 +181,12 @@ iscsi_readv_writev_bh_cb(void *p) static void -iscsi_aio_write10_cb(struct iscsi_context *iscsi, int status, +iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, void *command_data, void *opaque) { IscsiAIOCB *acb = opaque; - trace_iscsi_aio_write10_cb(iscsi, status, acb, acb->canceled); + trace_iscsi_aio_write16_cb(iscsi, status, acb, acb->canceled); g_free(acb->buf); @@ -179,7 +199,7 @@ iscsi_aio_write10_cb(struct iscsi_context *iscsi, int status, acb->status = 0; if (status < 0) { - error_report("Failed to write10 data to iSCSI lun. %s", + error_report("Failed to write16 data to iSCSI lun. %s", iscsi_get_error(iscsi)); acb->status = -EIO; } @@ -204,12 +224,9 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, struct iscsi_context *iscsi = iscsilun->iscsi; IscsiAIOCB *acb; size_t size; - int fua = 0; - - /* set FUA on writes when cache mode is write through */ - if (!(bs->open_flags & BDRV_O_CACHE_WB)) { - fua = 1; - } + uint32_t num_sectors; + uint64_t lba; + struct iscsi_data data; acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque); trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb); @@ -219,18 +236,44 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, acb->canceled = 0; - /* XXX we should pass the iovec to write10 to avoid the extra copy */ + /* XXX we should pass the iovec to write16 to avoid the extra copy */ /* this will allow us to get rid of 'buf' completely */ size = nb_sectors * BDRV_SECTOR_SIZE; acb->buf = g_malloc(size); qemu_iovec_to_buffer(acb->qiov, acb->buf); - acb->task = iscsi_write10_task(iscsi, iscsilun->lun, acb->buf, size, - sector_qemu2lun(sector_num, iscsilun), - fua, 0, iscsilun->block_size, - iscsi_aio_write10_cb, acb); + + + acb->task = malloc(sizeof(struct scsi_task)); if (acb->task == NULL) { - error_report("iSCSI: Failed to send write10 command. %s", - iscsi_get_error(iscsi)); + error_report("iSCSI: Failed to allocate task for scsi WRITE16 " + "command. %s", iscsi_get_error(iscsi)); + qemu_aio_release(acb); + return NULL; + } + memset(acb->task, 0, sizeof(struct scsi_task)); + + acb->task->xfer_dir = SCSI_XFER_WRITE; + acb->task->cdb_size = 16; + acb->task->cdb[0] = 0x8a; + if (!(bs->open_flags & BDRV_O_CACHE_WB)) { + /* set FUA on writes when cache mode is write through */ + acb->task->cdb[1] |= 0x04; + } + lba = sector_qemu2lun(sector_num, iscsilun); + *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32); + *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff); + num_sectors = size / iscsilun->block_size; + *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors); + acb->task->expxferlen = size; + + data.data = acb->buf; + data.size = size; + + if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task, + iscsi_aio_write16_cb, + &data, + acb) != 0) { + scsi_free_scsi_task(acb->task); g_free(acb->buf); qemu_aio_release(acb); return NULL; @@ -242,12 +285,12 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, } static void -iscsi_aio_read10_cb(struct iscsi_context *iscsi, int status, +iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status, void *command_data, void *opaque) { IscsiAIOCB *acb = opaque; - trace_iscsi_aio_read10_cb(iscsi, status, acb, acb->canceled); + trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled); if (acb->canceled != 0) { qemu_aio_release(acb); @@ -258,7 +301,7 @@ iscsi_aio_read10_cb(struct iscsi_context *iscsi, int status, acb->status = 0; if (status != 0) { - error_report("Failed to read10 data from iSCSI lun. %s", + error_report("Failed to read16 data from iSCSI lun. %s", iscsi_get_error(iscsi)); acb->status = -EIO; } @@ -277,8 +320,10 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num, IscsiLun *iscsilun = bs->opaque; struct iscsi_context *iscsi = iscsilun->iscsi; IscsiAIOCB *acb; - size_t qemu_read_size, lun_read_size; + size_t qemu_read_size; int i; + uint64_t lba; + uint32_t num_sectors; qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors; @@ -303,16 +348,44 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num, acb->read_offset = bdrv_offset % iscsilun->block_size; } - lun_read_size = (qemu_read_size + iscsilun->block_size - + acb->read_offset - 1) - / iscsilun->block_size * iscsilun->block_size; - acb->task = iscsi_read10_task(iscsi, iscsilun->lun, - sector_qemu2lun(sector_num, iscsilun), - lun_read_size, iscsilun->block_size, - iscsi_aio_read10_cb, acb); + num_sectors = (qemu_read_size + iscsilun->block_size + + acb->read_offset - 1) + / iscsilun->block_size; + + acb->task = malloc(sizeof(struct scsi_task)); if (acb->task == NULL) { - error_report("iSCSI: Failed to send read10 command. %s", - iscsi_get_error(iscsi)); + error_report("iSCSI: Failed to allocate task for scsi READ16 " + "command. %s", iscsi_get_error(iscsi)); + qemu_aio_release(acb); + return NULL; + } + memset(acb->task, 0, sizeof(struct scsi_task)); + + acb->task->xfer_dir = SCSI_XFER_READ; + lba = sector_qemu2lun(sector_num, iscsilun); + acb->task->expxferlen = qemu_read_size; + + switch (iscsilun->type) { + case TYPE_DISK: + acb->task->cdb_size = 16; + acb->task->cdb[0] = 0x88; + *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32); + *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff); + *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors); + break; + default: + acb->task->cdb_size = 10; + acb->task->cdb[0] = 0x28; + *(uint32_t *)&acb->task->cdb[2] = htonl(lba); + *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors); + break; + } + + if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task, + iscsi_aio_read16_cb, + NULL, + acb) != 0) { + scsi_free_scsi_task(acb->task); qemu_aio_release(acb); return NULL; } @@ -491,6 +564,98 @@ iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status, } static void +iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status, + void *command_data, void *opaque) +{ + struct IscsiTask *itask = opaque; + struct scsi_readcapacity10 *rc10; + struct scsi_task *task = command_data; + + if (status != 0) { + error_report("iSCSI: Failed to read capacity of iSCSI lun. %s", + iscsi_get_error(iscsi)); + itask->status = 1; + itask->complete = 1; + scsi_free_scsi_task(task); + return; + } + + rc10 = scsi_datain_unmarshall(task); + if (rc10 == NULL) { + error_report("iSCSI: Failed to unmarshall readcapacity10 data."); + itask->status = 1; + itask->complete = 1; + scsi_free_scsi_task(task); + return; + } + + itask->iscsilun->block_size = rc10->block_size; + itask->iscsilun->num_blocks = rc10->lba + 1; + itask->bs->total_sectors = itask->iscsilun->num_blocks * + itask->iscsilun->block_size / BDRV_SECTOR_SIZE ; + + itask->status = 0; + itask->complete = 1; + scsi_free_scsi_task(task); +} + +static void +iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data, + void *opaque) +{ + struct IscsiTask *itask = opaque; + struct scsi_task *task = command_data; + struct scsi_inquiry_standard *inq; + + if (status != 0) { + itask->status = 1; + itask->complete = 1; + scsi_free_scsi_task(task); + return; + } + + inq = scsi_datain_unmarshall(task); + if (inq == NULL) { + error_report("iSCSI: Failed to unmarshall inquiry data."); + itask->status = 1; + itask->complete = 1; + scsi_free_scsi_task(task); + return; + } + + itask->iscsilun->type = inq->periperal_device_type; + + scsi_free_scsi_task(task); + + switch (itask->iscsilun->type) { + case TYPE_DISK: + task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun, + iscsi_readcapacity16_cb, opaque); + if (task == NULL) { + error_report("iSCSI: failed to send readcapacity16 command."); + itask->status = 1; + itask->complete = 1; + return; + } + break; + case TYPE_ROM: + task = iscsi_readcapacity10_task(iscsi, itask->iscsilun->lun, + 0, 0, + iscsi_readcapacity10_cb, opaque); + if (task == NULL) { + error_report("iSCSI: failed to send readcapacity16 command."); + itask->status = 1; + itask->complete = 1; + return; + } + break; + default: + itask->status = 0; + itask->complete = 1; + } +} + +static void iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data, void *opaque) { @@ -503,10 +668,11 @@ iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data, return; } - task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun, - iscsi_readcapacity16_cb, opaque); + task = iscsi_inquiry_task(iscsi, itask->iscsilun->lun, + 0, 0, 36, + iscsi_inquiry_cb, opaque); if (task == NULL) { - error_report("iSCSI: failed to send readcapacity16 command."); + error_report("iSCSI: failed to send inquiry command."); itask->status = 1; itask->complete = 1; return; diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 10c22fe12..4b3345b11 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -762,7 +762,6 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset, uint64_t *host_offset, unsigned int *nb_clusters) { BDRVQcowState *s = bs->opaque; - int64_t cluster_offset; QCowL2Meta *old_alloc; trace_qcow2_do_alloc_clusters_offset(qemu_coroutine_self(), guest_offset, @@ -808,17 +807,21 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset, /* Allocate new clusters */ trace_qcow2_cluster_alloc_phys(qemu_coroutine_self()); if (*host_offset == 0) { - cluster_offset = qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size); + int64_t cluster_offset = + qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size); + if (cluster_offset < 0) { + return cluster_offset; + } + *host_offset = cluster_offset; + return 0; } else { - cluster_offset = *host_offset; - *nb_clusters = qcow2_alloc_clusters_at(bs, cluster_offset, *nb_clusters); - } - - if (cluster_offset < 0) { - return cluster_offset; + int ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters); + if (ret < 0) { + return ret; + } + *nb_clusters = ret; + return 0; } - *host_offset = cluster_offset; - return 0; } /* diff --git a/block/qcow2.c b/block/qcow2.c index 655799c6a..c2e49cded 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -919,7 +919,8 @@ int qcow2_update_header(BlockDriverState *bs) ret = sizeof(*header); break; default: - return -EINVAL; + ret = -EINVAL; + goto fail; } buf += ret; diff --git a/block/sheepdog.c b/block/sheepdog.c index e01d37168..6d52277a8 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -468,7 +468,7 @@ static int connect_to_sdog(const char *addr, const char *port) if (ret) { error_report("unable to get address info %s, %s", addr, strerror(errno)); - return -1; + return -errno; } for (res = res0; res; res = res->ai_next) { @@ -495,7 +495,7 @@ static int connect_to_sdog(const char *addr, const char *port) dprintf("connected to %s:%s\n", addr, port); goto success; } - fd = -1; + fd = -errno; error_report("failed connect to %s:%s", addr, port); success: freeaddrinfo(res0); @@ -510,12 +510,13 @@ static int send_req(int sockfd, SheepdogReq *hdr, void *data, ret = qemu_send_full(sockfd, hdr, sizeof(*hdr), 0); if (ret < sizeof(*hdr)) { error_report("failed to send a req, %s", strerror(errno)); - return ret; + return -errno; } ret = qemu_send_full(sockfd, data, *wlen, 0); if (ret < *wlen) { error_report("failed to send a req, %s", strerror(errno)); + ret = -errno; } return ret; @@ -553,6 +554,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data, ret = qemu_recv_full(sockfd, hdr, sizeof(*hdr), 0); if (ret < sizeof(*hdr)) { error_report("failed to get a rsp, %s", strerror(errno)); + ret = -errno; goto out; } @@ -564,6 +566,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data, ret = qemu_recv_full(sockfd, data, *rlen, 0); if (ret < *rlen) { error_report("failed to get the data, %s", strerror(errno)); + ret = -errno; goto out; } } @@ -587,6 +590,7 @@ static int do_co_req(int sockfd, SheepdogReq *hdr, void *data, ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr)); if (ret < sizeof(*hdr)) { error_report("failed to get a rsp, %s", strerror(errno)); + ret = -errno; goto out; } @@ -598,6 +602,7 @@ static int do_co_req(int sockfd, SheepdogReq *hdr, void *data, ret = qemu_co_recv(sockfd, data, *rlen); if (ret < *rlen) { error_report("failed to get the data, %s", strerror(errno)); + ret = -errno; goto out; } } @@ -787,7 +792,7 @@ static int get_sheep_fd(BDRVSheepdogState *s) fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { error_report("%s", strerror(errno)); - return -1; + return fd; } socket_set_nonblock(fd); @@ -796,7 +801,7 @@ static int get_sheep_fd(BDRVSheepdogState *s) if (ret) { error_report("%s", strerror(errno)); closesocket(fd); - return -1; + return -errno; } qemu_aio_set_fd_handler(fd, co_read_response, NULL, aio_flush_request, s); @@ -883,7 +888,7 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid, fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { - return -1; + return fd; } memset(buf, 0, sizeof(buf)); @@ -904,14 +909,17 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid, ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen); if (ret) { - ret = -1; goto out; } if (rsp->result != SD_RES_SUCCESS) { error_report("cannot get vdi info, %s, %s %d %s", sd_strerror(rsp->result), filename, snapid, tag); - ret = -1; + if (rsp->result == SD_RES_NO_VDI) { + ret = -ENOENT; + } else { + ret = -EIO; + } goto out; } *vid = rsp->vdi_id; @@ -980,7 +988,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, if (ret < 0) { qemu_co_mutex_unlock(&s->lock); error_report("failed to send a req, %s", strerror(errno)); - return -EIO; + return -errno; } if (wlen) { @@ -988,7 +996,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, if (ret < 0) { qemu_co_mutex_unlock(&s->lock); error_report("failed to send a data, %s", strerror(errno)); - return -EIO; + return -errno; } } @@ -1038,7 +1046,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies, ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen); if (ret) { error_report("failed to send a request to the sheep"); - return -1; + return ret; } switch (rsp->result) { @@ -1046,7 +1054,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies, return 0; default: error_report("%s", sd_strerror(rsp->result)); - return -1; + return -EIO; } } @@ -1082,10 +1090,12 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags) memset(vdi, 0, sizeof(vdi)); memset(tag, 0, sizeof(tag)); if (parse_vdiname(s, filename, vdi, &snapid, tag) < 0) { + ret = -EINVAL; goto out; } s->fd = get_sheep_fd(s); if (s->fd < 0) { + ret = s->fd; goto out; } @@ -1099,11 +1109,12 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags) s->flush_fd = connect_to_sdog(s->addr, s->port); if (s->flush_fd < 0) { error_report("failed to connect"); + ret = s->flush_fd; goto out; } } - if (snapid) { + if (snapid || tag[0] != '\0') { dprintf("%" PRIx32 " snapshot inode was open.\n", vid); s->is_snapshot = 1; } @@ -1111,6 +1122,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags) fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { error_report("failed to connect"); + ret = fd; goto out; } @@ -1139,7 +1151,7 @@ out: closesocket(s->fd); } g_free(buf); - return -1; + return ret; } static int do_sd_create(char *filename, int64_t vdi_size, @@ -1154,7 +1166,7 @@ static int do_sd_create(char *filename, int64_t vdi_size, fd = connect_to_sdog(addr, port); if (fd < 0) { - return -EIO; + return fd; } memset(buf, 0, sizeof(buf)); @@ -1177,7 +1189,7 @@ static int do_sd_create(char *filename, int64_t vdi_size, closesocket(fd); if (ret) { - return -EIO; + return ret; } if (rsp->result != SD_RES_SUCCESS) { @@ -1237,24 +1249,26 @@ out: static int sd_create(const char *filename, QEMUOptionParameter *options) { - int ret; + int ret = 0; uint32_t vid = 0, base_vid = 0; int64_t vdi_size = 0; char *backing_file = NULL; - BDRVSheepdogState s; + BDRVSheepdogState *s; char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN]; uint32_t snapid; int prealloc = 0; const char *vdiname; + s = g_malloc0(sizeof(BDRVSheepdogState)); + strstart(filename, "sheepdog:", &vdiname); - memset(&s, 0, sizeof(s)); memset(vdi, 0, sizeof(vdi)); memset(tag, 0, sizeof(tag)); - if (parse_vdiname(&s, vdiname, vdi, &snapid, tag) < 0) { + if (parse_vdiname(s, vdiname, vdi, &snapid, tag) < 0) { error_report("invalid filename"); - return -EINVAL; + ret = -EINVAL; + goto out; } while (options && options->name) { @@ -1270,7 +1284,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) } else { error_report("Invalid preallocation mode: '%s'", options->value.s); - return -EINVAL; + ret = -EINVAL; + goto out; } } options++; @@ -1278,7 +1293,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) if (vdi_size > SD_MAX_VDI_SIZE) { error_report("too big image size"); - return -EINVAL; + ret = -EINVAL; + goto out; } if (backing_file) { @@ -1290,31 +1306,37 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) drv = bdrv_find_protocol(backing_file); if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) { error_report("backing_file must be a sheepdog image"); - return -EINVAL; + ret = -EINVAL; + goto out; } ret = bdrv_file_open(&bs, backing_file, 0); - if (ret < 0) - return -EIO; + if (ret < 0) { + goto out; + } s = bs->opaque; if (!is_snapshot(&s->inode)) { error_report("cannot clone from a non snapshot vdi"); bdrv_delete(bs); - return -EINVAL; + ret = -EINVAL; + goto out; } base_vid = s->inode.vdi_id; bdrv_delete(bs); } - ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port); + ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s->addr, s->port); if (!prealloc || ret) { - return ret; + goto out; } - return sd_prealloc(filename); + ret = sd_prealloc(filename); +out: + g_free(s); + return ret; } static void sd_close(BlockDriverState *bs) @@ -1379,7 +1401,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset) fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { - return -EIO; + return fd; } /* we don't need to update entire object */ @@ -1391,10 +1413,9 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset) if (ret < 0) { error_report("failed to update an inode."); - return -EIO; } - return 0; + return ret; } /* @@ -1464,6 +1485,7 @@ static int sd_create_branch(BDRVSheepdogState *s) fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { error_report("failed to connect"); + ret = fd; goto out; } @@ -1606,8 +1628,9 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num, if (bs->growable && sector_num + nb_sectors > bs->total_sectors) { /* TODO: shouldn't block here */ - if (sd_truncate(bs, (sector_num + nb_sectors) * SECTOR_SIZE) < 0) { - return -EIO; + ret = sd_truncate(bs, (sector_num + nb_sectors) * SECTOR_SIZE); + if (ret < 0) { + return ret; } bs->total_sectors = sector_num + nb_sectors; } @@ -1724,7 +1747,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) /* refresh inode. */ fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { - ret = -EIO; + ret = fd; goto cleanup; } @@ -1732,7 +1755,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) s->inode.nr_copies, datalen, 0, 0, s->cache_enabled); if (ret < 0) { error_report("failed to write snapshot's inode."); - ret = -EIO; goto cleanup; } @@ -1741,7 +1763,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) if (ret < 0) { error_report("failed to create inode for snapshot. %s", strerror(errno)); - ret = -EIO; goto cleanup; } @@ -1752,7 +1773,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) if (ret < 0) { error_report("failed to read new inode info. %s", strerror(errno)); - ret = -EIO; goto cleanup; } @@ -1773,7 +1793,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) char *buf = NULL; uint32_t vid; uint32_t snapid = 0; - int ret = -ENOENT, fd; + int ret = 0, fd; old_s = g_malloc(sizeof(BDRVSheepdogState)); @@ -1791,13 +1811,13 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) ret = find_vdi_name(s, vdi, snapid, tag, &vid, 1); if (ret) { error_report("Failed to find_vdi_name"); - ret = -ENOENT; goto out; } fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { error_report("failed to connect"); + ret = fd; goto out; } @@ -1808,7 +1828,6 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) closesocket(fd); if (ret) { - ret = -ENOENT; goto out; } @@ -1861,6 +1880,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { + ret = fd; goto out; } @@ -1888,6 +1908,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { error_report("failed to connect"); + ret = fd; goto out; } @@ -1925,6 +1946,10 @@ out: g_free(vdi_inuse); + if (ret < 0) { + return ret; + } + return found; } @@ -1940,8 +1965,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { - ret = -EIO; - goto cleanup; + return fd; } while (size) { @@ -1965,7 +1989,6 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, if (ret < 0) { error_report("failed to save vmstate %s", strerror(errno)); - ret = -EIO; goto cleanup; } diff --git a/block/vvfat.c b/block/vvfat.c index 2dc9d5088..0fd3367d8 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -2808,7 +2808,12 @@ static int enable_write_target(BDRVVVFATState *s) array_init(&(s->commits), sizeof(commit_t)); s->qcow_filename = g_malloc(1024); - get_tmp_filename(s->qcow_filename, 1024); + ret = get_tmp_filename(s->qcow_filename, 1024); + if (ret < 0) { + g_free(s->qcow_filename); + s->qcow_filename = NULL; + return ret; + } bdrv_qcow = bdrv_find_format("qcow"); options = parse_option_parameters("", bdrv_qcow->create_options, NULL); diff --git a/block_int.h b/block_int.h index b80e66db6..3d4abc657 100644 --- a/block_int.h +++ b/block_int.h @@ -335,7 +335,7 @@ struct BlockDriverState { BlockJob *job; }; -void get_tmp_filename(char *filename, int size); +int get_tmp_filename(char *filename, int size); void bdrv_set_io_limits(BlockDriverState *bs, BlockIOLimit *io_limits); @@ -2848,6 +2848,21 @@ if compile_prog "" "" ; then linux_magic_h=yes fi +######################################## +# check if environ is declared + +has_environ=no +cat > $TMPC << EOF +#include <unistd.h> +int main(void) { + environ = environ; + return 0; +} +EOF +if compile_prog "" "" ; then + has_environ=yes +fi + ########################################## # End of CC checks # After here, no more $cc or $ld runs @@ -3360,6 +3375,10 @@ if test "$linux_magic_h" = "yes" ; then echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak fi +if test "$has_environ" = "yes" ; then + echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak +fi + # USB host support case "$usb" in linux) diff --git a/docs/usb2.txt b/docs/usb2.txt index 228aa33ce..d17e3c004 100644 --- a/docs/usb2.txt +++ b/docs/usb2.txt @@ -55,6 +55,21 @@ try ... ... then use "bus=ehci.0" to assign your usb devices to that bus. +xhci controller support +----------------------- + +There also is xhci host controller support available. It got alot +less testing than ehci and there are a bunch of known limitations, so +ehci may work better for you. On the other hand the xhci hardware +design is much more virtualization-friendly, thus xhci emulation uses +less ressources (especially cpu). If you wanna give xhci a try +use this to add the host controller ... + + qemu -device nec-usb-xhci,id=xhci + +... then use "bus=xhci.0" when assigning usb devices. + + More USB tips & tricks ====================== diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 368bbe5a9..1fbc3149b 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -305,6 +305,7 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots) if (pc->no_hotplug) { slot_free = false; } else { + object_unparent(OBJECT(dev)); qdev_free(qdev); } } diff --git a/hw/es1370.c b/hw/es1370.c index f19cef31a..573f74736 100644 --- a/hw/es1370.c +++ b/hw/es1370.c @@ -410,7 +410,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl) if ((old_fmt != new_fmt) || (old_freq != new_freq)) { d->shift = (new_fmt & 1) + (new_fmt >> 1); - ldebug ("channel %d, freq = %d, nchannels %d, fmt %d, shift %d\n", + ldebug ("channel %zu, freq = %d, nchannels %d, fmt %d, shift %d\n", i, new_freq, 1 << (new_fmt & 1), @@ -578,7 +578,7 @@ IO_WRITE_PROTO (es1370_writel) d++; case ES1370_REG_DAC1_SCOUNT: d->scount = (val & 0xffff) | (d->scount & ~0xffff); - ldebug ("chan %d CURR_SAMP_CT %d, SAMP_CT %d\n", + ldebug ("chan %td CURR_SAMP_CT %d, SAMP_CT %d\n", d - &s->chan[0], val >> 16, (val & 0xffff)); break; @@ -588,7 +588,7 @@ IO_WRITE_PROTO (es1370_writel) d++; case ES1370_REG_DAC1_FRAMEADR: d->frame_addr = val; - ldebug ("chan %d frame address %#x\n", d - &s->chan[0], val); + ldebug ("chan %td frame address %#x\n", d - &s->chan[0], val); break; case ES1370_REG_PHANTOM_FRAMECNT: @@ -605,7 +605,7 @@ IO_WRITE_PROTO (es1370_writel) case ES1370_REG_DAC1_FRAMECNT: d->frame_cnt = val; d->leftover = 0; - ldebug ("chan %d frame count %d, buffer size %d\n", + ldebug ("chan %td frame count %d, buffer size %d\n", d - &s->chan[0], val >> 16, val & 0xffff); break; @@ -745,9 +745,10 @@ IO_READ_PROTO (es1370_readl) { uint32_t size = ((d->frame_cnt & 0xffff) + 1) << 2; uint32_t curr = ((d->frame_cnt >> 16) + 1) << 2; - if (curr > size) + if (curr > size) { dolog ("read framecnt curr %d, size %d %d\n", curr, size, curr > size); + } } #endif break; @@ -179,12 +179,14 @@ static void fd_revalidate(FDrive *drv) FDriveRate rate; FLOPPY_DPRINTF("revalidate\n"); - if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) { + if (drv->bs != NULL) { ro = bdrv_is_read_only(drv->bs); bdrv_get_floppy_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect, drv->drive, &drive, &rate); - if (nb_heads != 0 && max_track != 0 && last_sect != 0) { - FLOPPY_DPRINTF("User defined disk (%d %d %d)", + if (!bdrv_is_inserted(drv->bs)) { + FLOPPY_DPRINTF("No disk in drive\n"); + } else if (nb_heads != 0 && max_track != 0 && last_sect != 0) { + FLOPPY_DPRINTF("User defined disk (%d %d %d)\n", nb_heads - 1, max_track, last_sect); } else { FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads, @@ -201,7 +203,7 @@ static void fd_revalidate(FDrive *drv) drv->drive = drive; drv->media_rate = rate; } else { - FLOPPY_DPRINTF("No disk in drive\n"); + FLOPPY_DPRINTF("No drive connected\n"); drv->last_sect = 0; drv->max_track = 0; drv->flags &= ~FDISK_DBL_SIDES; @@ -709,7 +711,7 @@ static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0) FDrive *cur_drv; /* A seek clears the disk change line (if a disk is inserted) */ cur_drv = get_cur_drv(fdctrl); - if (cur_drv->max_track) { + if (cur_drv->bs != NULL && bdrv_is_inserted(cur_drv->bs)) { cur_drv->media_changed = 0; } } @@ -1878,7 +1880,7 @@ static int fdctrl_connect_drives(FDCtrl *fdctrl) } fd_init(drive); - fd_revalidate(drive); + fdctrl_change_cb(drive, 0); if (drive->bs) { bdrv_set_dev_ops(drive->bs, &fdctrl_block_ops, drive); } diff --git a/hw/multiboot.c b/hw/multiboot.c index b4484a326..b1e04c571 100644 --- a/hw/multiboot.c +++ b/hw/multiboot.c @@ -202,10 +202,16 @@ int load_multiboot(void *fw_cfg, uint32_t mh_bss_end_addr = ldl_p(header+i+24); mh_load_addr = ldl_p(header+i+16); uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr); - uint32_t mb_load_size = mh_load_end_addr - mh_load_addr; - + uint32_t mb_load_size = 0; mh_entry_addr = ldl_p(header+i+28); - mb_kernel_size = mh_bss_end_addr - mh_load_addr; + + if (mh_load_end_addr) { + mb_kernel_size = mh_bss_end_addr - mh_load_addr; + mb_load_size = mh_load_end_addr - mh_load_addr; + } else { + mb_kernel_size = kernel_file_size - mb_kernel_text_offset; + mb_load_size = mb_kernel_size; + } /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE. uint32_t mh_mode_type = ldl_p(header+i+32); @@ -47,6 +47,7 @@ #include "ui/qemu-spice.h" #include "memory.h" #include "exec-memory.h" +#include "arch_init.h" /* output Bochs bios info messages */ //#define DEBUG_BIOS @@ -382,7 +383,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, if (floppy) { fdc_get_bs(fd, floppy); for (i = 0; i < 2; i++) { - if (fd[i] && bdrv_is_inserted(fd[i])) { + if (fd[i]) { bdrv_get_floppy_geometry_hint(fd[i], &nb_heads, &max_track, &last_sect, FDRIVE_DRV_NONE, &fd_type[i], &rate); @@ -1101,7 +1102,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, qemu_irq pit_alt_irq = NULL; qemu_irq rtc_irq = NULL; qemu_irq *a20_line; - ISADevice *i8042, *port92, *vmmouse, *pit; + ISADevice *i8042, *port92, *vmmouse, *pit = NULL; qemu_irq *cpu_exit_irq; register_ioport_write(0x80, 1, 1, ioport80_write, NULL); @@ -1130,16 +1131,18 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, qemu_register_boot_set(pc_boot_set, *rtc_state); - if (kvm_irqchip_in_kernel()) { - pit = kvm_pit_init(isa_bus, 0x40); - } else { - pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq); - } - if (hpet) { - /* connect PIT to output control line of the HPET */ - qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0)); + if (!xen_enabled()) { + if (kvm_irqchip_in_kernel()) { + pit = kvm_pit_init(isa_bus, 0x40); + } else { + pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq); + } + if (hpet) { + /* connect PIT to output control line of the HPET */ + qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0)); + } + pcspk_init(isa_bus, pit); } - pcspk_init(isa_bus, pit); for(i = 0; i < MAX_SERIAL_PORTS; i++) { if (serial_hds[i]) { @@ -1622,7 +1622,6 @@ static int pci_unplug_device(DeviceState *qdev) qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev))); return -1; } - object_unparent(OBJECT(dev)); return dev->bus->hotplug(dev->bus->hotplug_qdev, dev, PCI_HOTPLUG_DISABLED); } diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 8ab9bcda8..f10f3ec25 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -1561,7 +1561,7 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size) return 0; } -const VMStateInfo vmstate_info_scsi_requests = { +static const VMStateInfo vmstate_info_scsi_requests = { .name = "scsi-requests", .get = get_scsi_requests, .put = put_scsi_requests, @@ -2357,10 +2357,15 @@ void vga_init(VGACommonState *s, MemoryRegion *address_space, void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory) { #ifdef CONFIG_BOCHS_VBE + /* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region, + * so use an alias to avoid double-mapping the same region. + */ + memory_region_init_alias(&s->vram_vbe, "vram.vbe", + &s->vram, 0, memory_region_size(&s->vram)); /* XXX: use optimized standard vga accesses */ memory_region_add_subregion(system_memory, VBE_DISPI_LFB_PHYSICAL_ADDRESS, - &s->vram); + &s->vram_vbe); s->vbe_mapped = 1; #endif } diff --git a/hw/vga_int.h b/hw/vga_int.h index 9bf9e8f72..6f696b69b 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -105,6 +105,7 @@ typedef struct VGACommonState { MemoryRegion *legacy_address_space; uint8_t *vram_ptr; MemoryRegion vram; + MemoryRegion vram_vbe; uint32_t vram_size; uint32_t latch; MemoryRegion *chain4_alias; diff --git a/hw/xen_common.h b/hw/xen_common.h index 7043c14ca..fe7f227f9 100644 --- a/hw/xen_common.h +++ b/hw/xen_common.h @@ -148,6 +148,6 @@ static inline int xen_xc_hvm_inject_msi(XenXC xen_xc, domid_t dom, } #endif -void destroy_hvm_domain(void); +void destroy_hvm_domain(bool reboot); #endif /* QEMU_HW_XEN_COMMON_H */ diff --git a/hw/xen_disk.c b/hw/xen_disk.c index 22dbd1030..07594bc0c 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -48,7 +48,6 @@ /* ------------------------------------------------------------- */ -static int syncwrite = 0; static int batch_maps = 0; static int max_requests = 32; @@ -67,6 +66,7 @@ struct ioreq { QEMUIOVector v; int presync; int postsync; + uint8_t mapped; /* grant mapping */ uint32_t domids[BLKIF_MAX_SEGMENTS_PER_REQUEST]; @@ -154,7 +154,7 @@ static void ioreq_finish(struct ioreq *ioreq) blkdev->requests_finished++; } -static void ioreq_release(struct ioreq *ioreq) +static void ioreq_release(struct ioreq *ioreq, bool finish) { struct XenBlkDev *blkdev = ioreq->blkdev; @@ -162,7 +162,11 @@ static void ioreq_release(struct ioreq *ioreq) memset(ioreq, 0, sizeof(*ioreq)); ioreq->blkdev = blkdev; QLIST_INSERT_HEAD(&blkdev->freelist, ioreq, list); - blkdev->requests_finished--; + if (finish) { + blkdev->requests_finished--; + } else { + blkdev->requests_inflight--; + } } /* @@ -189,15 +193,10 @@ static int ioreq_parse(struct ioreq *ioreq) ioreq->presync = 1; return 0; } - if (!syncwrite) { - ioreq->presync = ioreq->postsync = 1; - } + ioreq->presync = ioreq->postsync = 1; /* fall through */ case BLKIF_OP_WRITE: ioreq->prot = PROT_READ; /* from memory */ - if (syncwrite) { - ioreq->postsync = 1; - } break; default: xen_be_printf(&blkdev->xendev, 0, "error: unknown operation (%d)\n", @@ -248,7 +247,7 @@ static void ioreq_unmap(struct ioreq *ioreq) XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev; int i; - if (ioreq->v.niov == 0) { + if (ioreq->v.niov == 0 || ioreq->mapped == 0) { return; } if (batch_maps) { @@ -274,6 +273,7 @@ static void ioreq_unmap(struct ioreq *ioreq) ioreq->page[i] = NULL; } } + ioreq->mapped = 0; } static int ioreq_map(struct ioreq *ioreq) @@ -281,7 +281,7 @@ static int ioreq_map(struct ioreq *ioreq) XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev; int i; - if (ioreq->v.niov == 0) { + if (ioreq->v.niov == 0 || ioreq->mapped == 1) { return 0; } if (batch_maps) { @@ -313,9 +313,12 @@ static int ioreq_map(struct ioreq *ioreq) ioreq->blkdev->cnt_map++; } } + ioreq->mapped = 1; return 0; } +static int ioreq_runio_qemu_aio(struct ioreq *ioreq); + static void qemu_aio_complete(void *opaque, int ret) { struct ioreq *ioreq = opaque; @@ -327,11 +330,19 @@ static void qemu_aio_complete(void *opaque, int ret) } ioreq->aio_inflight--; + if (ioreq->presync) { + ioreq->presync = 0; + ioreq_runio_qemu_aio(ioreq); + return; + } if (ioreq->aio_inflight > 0) { return; } if (ioreq->postsync) { - bdrv_flush(ioreq->blkdev->bs); + ioreq->postsync = 0; + ioreq->aio_inflight++; + bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq); + return; } ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY; @@ -351,7 +362,8 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) ioreq->aio_inflight++; if (ioreq->presync) { - bdrv_flush(blkdev->bs); /* FIXME: aio_flush() ??? */ + bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq); + return 0; } switch (ioreq->req.operation) { @@ -449,7 +461,7 @@ static void blk_send_response_all(struct XenBlkDev *blkdev) while (!QLIST_EMPTY(&blkdev->finished)) { ioreq = QLIST_FIRST(&blkdev->finished); send_notify += blk_send_response_one(ioreq); - ioreq_release(ioreq); + ioreq_release(ioreq, true); } if (send_notify) { xen_be_send_notify(&blkdev->xendev); @@ -505,7 +517,7 @@ static void blk_handle_requests(struct XenBlkDev *blkdev) if (blk_send_response_one(ioreq)) { xen_be_send_notify(&blkdev->xendev); } - ioreq_release(ioreq); + ioreq_release(ioreq, false); continue; } diff --git a/pc-bios/README b/pc-bios/README index 6b64d6868..e56e9e5f0 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -12,7 +12,7 @@ 1275-1994 (referred to as Open Firmware) compliant firmware. The included images for PowerPC (for 32 and 64 bit PPC CPUs), Sparc32 and Sparc64 are built from OpenBIOS SVN revision - 1056. + 1060. - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc Binary files differindex d4656db8b..aeae26588 100644 --- a/pc-bios/openbios-ppc +++ b/pc-bios/openbios-ppc diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32 Binary files differindex 4312c690a..d90c4e59a 100644 --- a/pc-bios/openbios-sparc32 +++ b/pc-bios/openbios-sparc32 diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64 Binary files differindex b18610508..457d26422 100644 --- a/pc-bios/openbios-sparc64 +++ b/pc-bios/openbios-sparc64 diff --git a/qemu-img.texi b/qemu-img.texi index b2ca3a542..6fc3c28e0 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -159,6 +159,24 @@ It can be used without an accessible old backing file, i.e. you can use it to fix an image whose backing file has already been moved/renamed. @end table +You can use @code{rebase} to perform a ``diff'' operation on two +disk images. This can be useful when you have copied or cloned +a guest, and you want to get back to a thin image on top of a +template or base image. + +Say that @code{base.img} has been cloned as @code{modified.img} by +copying it, and that the @code{modified.img} guest has run so there +are now some changes compared to @code{base.img}. To construct a thin +image called @code{diff.qcow2} that contains just the differences, do: + +@example +qemu-img create -f qcow2 -b modified.img diff.qcow2 +qemu-img rebase -b base.img diff.qcow2 +@end example + +At this point, @code{modified.img} can be discarded, since +@code{base.img + diff.qcow2} contains the same information. + @item resize @var{filename} [+ | -]@var{size} Change the disk image as if it had been created with @var{size}. diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 7664be10a..00d035da9 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -14,12 +14,22 @@ #include <glib.h> #include <sys/types.h> #include <sys/ioctl.h> +#include <sys/wait.h> #include "qga/guest-agent-core.h" #include "qga-qmp-commands.h" #include "qerror.h" #include "qemu-queue.h" #include "host-utils.h" +#ifndef CONFIG_HAS_ENVIRON +#ifdef __APPLE__ +#include <crt_externs.h> +#define environ (*_NSGetEnviron()) +#else +extern char **environ; +#endif +#endif + #if defined(__linux__) #include <mntent.h> #include <linux/fs.h> @@ -27,7 +37,6 @@ #include <arpa/inet.h> #include <sys/socket.h> #include <net/if.h> -#include <sys/wait.h> #if defined(__linux__) && defined(FIFREEZE) #define CONFIG_FSFREEZE @@ -336,7 +345,7 @@ static int guest_fsfreeze_build_mount_list(GuestFsfreezeMountList *mounts) { struct mntent *ment; GuestFsfreezeMount *mount; - char const *mtab = MOUNTED; + char const *mtab = "/proc/self/mounts"; FILE *fp; fp = setmntent(mtab, "r"); diff --git a/roms/openbios b/roms/openbios -Subproject ff61d973e5a4a68b29e485b3f88e6a2d1d96cf4 +Subproject d1d2787f87167edf487a60e61b9168514d5a743 diff --git a/slirp/ip.h b/slirp/ip.h index 88c903fcc..e2ee5e304 100644 --- a/slirp/ip.h +++ b/slirp/ip.h @@ -34,18 +34,14 @@ #define _IP_H_ #ifdef HOST_WORDS_BIGENDIAN -# ifndef NTOHL -# define NTOHL(d) -# endif -# ifndef NTOHS -# define NTOHS(d) -# endif -# ifndef HTONL -# define HTONL(d) -# endif -# ifndef HTONS -# define HTONS(d) -# endif +# undef NTOHL +# undef NTOHS +# undef HTONL +# undef HTONS +# define NTOHL(d) +# define NTOHS(d) +# define HTONL(d) +# define HTONS(d) #else # ifndef NTOHL # define NTOHL(d) ((d) = ntohl((d))) diff --git a/slirp/tcp.h b/slirp/tcp.h index 82996031e..2e2b4033a 100644 --- a/slirp/tcp.h +++ b/slirp/tcp.h @@ -79,20 +79,23 @@ struct tcphdr { #define TCPOPT_EOL 0 #define TCPOPT_NOP 1 #define TCPOPT_MAXSEG 2 -#define TCPOLEN_MAXSEG 4 #define TCPOPT_WINDOW 3 -#define TCPOLEN_WINDOW 3 #define TCPOPT_SACK_PERMITTED 4 /* Experimental */ -#define TCPOLEN_SACK_PERMITTED 2 #define TCPOPT_SACK 5 /* Experimental */ #define TCPOPT_TIMESTAMP 8 -#define TCPOLEN_TIMESTAMP 10 -#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ #define TCPOPT_TSTAMP_HDR \ (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP) #endif +#ifndef TCPOLEN_MAXSEG +#define TCPOLEN_MAXSEG 4 +#define TCPOLEN_WINDOW 3 +#define TCPOLEN_SACK_PERMITTED 2 +#define TCPOLEN_TIMESTAMP 10 +#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ +#endif + /* * Default maximum segment size for TCP. * With an IP MSS of 576, this is 536, diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c index 779314bf9..8aa3d9047 100644 --- a/slirp/tcp_output.c +++ b/slirp/tcp_output.c @@ -47,6 +47,7 @@ static const u_char tcp_outflags[TCP_NSTATES] = { }; +#undef MAX_TCPOPTLEN #define MAX_TCPOPTLEN 32 /* max # bytes that go in options */ /* diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 89b4ac7ec..388bc5c52 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -238,6 +238,8 @@ typedef struct x86_def_t { /* Store the results of Centaur's CPUID instructions */ uint32_t ext4_features; uint32_t xlevel2; + /* The feature bits on CPUID[EAX=7,ECX=0].EBX */ + uint32_t cpuid_7_0_ebx_features; } x86_def_t; #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE) @@ -521,6 +523,12 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def->ext_features = ecx; x86_cpu_def->features = edx; + if (kvm_enabled() && x86_cpu_def->level >= 7) { + x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX); + } else { + x86_cpu_def->cpuid_7_0_ebx_features = 0; + } + host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx); x86_cpu_def->xlevel = eax; @@ -1185,6 +1193,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_kvm_features = def->kvm_features; env->cpuid_svm_features = def->svm_features; env->cpuid_ext4_features = def->ext4_features; + env->cpuid_7_0_ebx = def->cpuid_7_0_ebx_features; env->cpuid_xlevel2 = def->xlevel2; object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000, "tsc-frequency", &error); @@ -1451,13 +1460,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *edx = 0; break; case 7: - if (kvm_enabled()) { - KVMState *s = env->kvm_state; - - *eax = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EAX); - *ebx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EBX); - *ecx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_ECX); - *edx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EDX); + /* Structured Extended Feature Flags Enumeration Leaf */ + if (count == 0) { + *eax = 0; /* Maximum ECX value for sub-leaves */ + *ebx = env->cpuid_7_0_ebx; /* Feature flags */ + *ecx = 0; /* Reserved */ + *edx = 0; /* Reserved */ } else { *eax = 0; *ebx = 0; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 57e5682c1..0ea47b5ed 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -741,6 +741,8 @@ typedef struct CPUX86State { /* Store the results of Centaur's CPUID instructions */ uint32_t cpuid_xlevel2; uint32_t cpuid_ext4_features; + /* Flags from CPUID[EAX=7,ECX=0].EBX */ + uint32_t cpuid_7_0_ebx; /* MTRRs */ uint64_t mtrr_fixed[11]; diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 4cde48d2f..d26569715 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -24,7 +24,11 @@ static uint8_t *tb_ret_addr; -#ifdef _CALL_DARWIN +#if defined _CALL_DARWIN || defined __APPLE__ +#define TCG_TARGET_CALL_DARWIN +#endif + +#ifdef TCG_TARGET_CALL_DARWIN #define LINKAGE_AREA_SIZE 24 #define LR_OFFSET 8 #elif defined _CALL_AIX @@ -99,7 +103,7 @@ static const int tcg_target_reg_alloc_order[] = { TCG_REG_R29, TCG_REG_R30, TCG_REG_R31, -#ifdef _CALL_DARWIN +#ifdef TCG_TARGET_CALL_DARWIN TCG_REG_R2, #endif TCG_REG_R3, @@ -110,7 +114,7 @@ static const int tcg_target_reg_alloc_order[] = { TCG_REG_R8, TCG_REG_R9, TCG_REG_R10, -#ifndef _CALL_DARWIN +#ifndef TCG_TARGET_CALL_DARWIN TCG_REG_R11, #endif TCG_REG_R12, @@ -140,7 +144,7 @@ static const int tcg_target_call_oarg_regs[2] = { }; static const int tcg_target_callee_save_regs[] = { -#ifdef _CALL_DARWIN +#ifdef TCG_TARGET_CALL_DARWIN TCG_REG_R11, TCG_REG_R13, #endif @@ -1965,7 +1969,7 @@ static void tcg_target_init(TCGContext *s) tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff); tcg_regset_set32(tcg_target_call_clobber_regs, 0, (1 << TCG_REG_R0) | -#ifdef _CALL_DARWIN +#ifdef TCG_TARGET_CALL_DARWIN (1 << TCG_REG_R2) | #endif (1 << TCG_REG_R3) | @@ -1983,7 +1987,7 @@ static void tcg_target_init(TCGContext *s) tcg_regset_clear(s->reserved_regs); tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1); -#ifndef _CALL_DARWIN +#ifndef TCG_TARGET_CALL_DARWIN tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2); #endif #ifdef _CALL_SYSV diff --git a/tests/fdc-test.c b/tests/fdc-test.c index 5b5dd7481..22d24ac7d 100644 --- a/tests/fdc-test.c +++ b/tests/fdc-test.c @@ -63,6 +63,12 @@ char test_image[] = "/tmp/qtest.XXXXXX"; #define assert_bit_set(data, mask) g_assert_cmphex((data) & (mask), ==, (mask)) #define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0) +static uint8_t base = 0x70; + +enum { + CMOS_FLOPPY = 0x10, +}; + static void floppy_send(uint8_t byte) { uint8_t msr; @@ -108,34 +114,43 @@ static void send_step_pulse(void) cyl = (cyl + 1) % 4; } -static void test_media_change(void) +static uint8_t cmos_read(uint8_t reg) { - uint8_t dir; + outb(base + 0, reg); + return inb(base + 1); +} - /* Media changed bit must be up-to-date after step pulse. Do two SEEKs - * because we may already happen to be on the right cylinder initially. */ - send_step_pulse(); - send_step_pulse(); - dir = inb(FLOPPY_BASE + reg_dir); - assert_bit_clear(dir, DSKCHG); +static void test_cmos(void) +{ + uint8_t cmos; - /* Eject the floppy and check that DSKCHG is set. Reading it out doesn't - * reset the bit. */ - qmp("{'execute':'eject', 'arguments':{ 'device':'floppy0' }}"); - qmp(""); /* ignore event */ + cmos = cmos_read(CMOS_FLOPPY); + g_assert(cmos == 0x40); +} +static void test_no_media_on_start(void) +{ + uint8_t dir; + + /* Media changed bit must be set all time after start if there is + * no media in drive. */ dir = inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG); dir = inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG); - + send_step_pulse(); send_step_pulse(); dir = inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG); dir = inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG); +} + +static void test_media_change(void) +{ + uint8_t dir; - /* And then insert it again. DSKCHK should not be reset until a step pulse + /* Insert media in drive. DSKCHK should not be reset until a step pulse * is sent. */ qmp("{'execute':'change', 'arguments':{ 'device':'floppy0', " "'target': '%s' }}", test_image); @@ -152,6 +167,22 @@ static void test_media_change(void) assert_bit_clear(dir, DSKCHG); dir = inb(FLOPPY_BASE + reg_dir); assert_bit_clear(dir, DSKCHG); + + /* Eject the floppy and check that DSKCHG is set. Reading it out doesn't + * reset the bit. */ + qmp("{'execute':'eject', 'arguments':{ 'device':'floppy0' }}"); + qmp(""); /* ignore event */ + + dir = inb(FLOPPY_BASE + reg_dir); + assert_bit_set(dir, DSKCHG); + dir = inb(FLOPPY_BASE + reg_dir); + assert_bit_set(dir, DSKCHG); + + send_step_pulse(); + dir = inb(FLOPPY_BASE + reg_dir); + assert_bit_set(dir, DSKCHG); + dir = inb(FLOPPY_BASE + reg_dir); + assert_bit_set(dir, DSKCHG); } int main(int argc, char **argv) @@ -177,12 +208,12 @@ int main(int argc, char **argv) /* Run the tests */ g_test_init(&argc, &argv, NULL); - cmdline = g_strdup_printf("-vnc none " - "-drive file=%s,if=floppy,cache=writeback ", - test_image); + cmdline = g_strdup_printf("-vnc none "); qtest_start(cmdline); qtest_irq_intercept_in(global_qtest, "ioapic"); + qtest_add_func("/fdc/cmos", test_cmos); + qtest_add_func("/fdc/no_media_on_start", test_no_media_on_start); qtest_add_func("/fdc/media_change", test_media_change); ret = g_test_run(); diff --git a/tests/qemu-iotests/035 b/tests/qemu-iotests/035 index 56616a1b7..9d2d3472e 100755 --- a/tests/qemu-iotests/035 +++ b/tests/qemu-iotests/035 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.rc . ./common.filter -_supported_fmt generic +_supported_fmt qcow2 _supported_proto generic _supported_os Linux diff --git a/trace-events b/trace-events index 87cb96cab..45c6bc127 100644 --- a/trace-events +++ b/trace-events @@ -602,9 +602,9 @@ escc_kbd_command(int val) "Command %d" escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x" # block/iscsi.c -iscsi_aio_write10_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d" +iscsi_aio_write16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d" iscsi_aio_writev(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p" -iscsi_aio_read10_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d" +iscsi_aio_read16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d" iscsi_aio_readv(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p" # hw/esp.c diff --git a/ui/cocoa.m b/ui/cocoa.m index e7d6e898e..2383646dc 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -879,7 +879,8 @@ int main (int argc, const char * argv[]) { !strcmp(opt, "-vnc") || !strcmp(opt, "-nographic") || !strcmp(opt, "-version") || - !strcmp(opt, "-curses")) { + !strcmp(opt, "-curses") || + !strcmp(opt, "-qtest")) { return qemu_main(gArgc, gArgv, *_NSGetEnviron()); } } @@ -2849,6 +2849,10 @@ int vnc_display_pw_expire(DisplayState *ds, time_t expires) { VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + if (!vs) { + return -EINVAL; + } + vs->expires = expires; return 0; } @@ -603,6 +603,10 @@ void xen_vcpu_init(void) qemu_register_reset(xen_reset_vcpu, first_cpu); xen_reset_vcpu(first_cpu); } + /* if rtc_clock is left to default (host_clock), disable it */ + if (rtc_clock == host_clock) { + qemu_clock_enable(rtc_clock, false); + } } /* get the ioreq packets from share mem */ @@ -856,7 +860,7 @@ static void cpu_handle_ioreq(void *opaque) "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n", req->state, req->data_is_ptr, req->addr, req->data, req->count, req->size); - destroy_hvm_domain(); + destroy_hvm_domain(false); return; } @@ -870,10 +874,11 @@ static void cpu_handle_ioreq(void *opaque) */ if (runstate_is_running()) { if (qemu_shutdown_requested_get()) { - destroy_hvm_domain(); + destroy_hvm_domain(false); } if (qemu_reset_requested_get()) { qemu_system_reset(VMRESET_REPORT); + destroy_hvm_domain(true); } } @@ -1159,7 +1164,7 @@ int xen_hvm_init(void) return 0; } -void destroy_hvm_domain(void) +void destroy_hvm_domain(bool reboot) { XenXC xc_handle; int sts; @@ -1168,12 +1173,15 @@ void destroy_hvm_domain(void) if (xc_handle == XC_HANDLER_INITIAL_VALUE) { fprintf(stderr, "Cannot acquire xenctrl handle\n"); } else { - sts = xc_domain_shutdown(xc_handle, xen_domid, SHUTDOWN_poweroff); + sts = xc_domain_shutdown(xc_handle, xen_domid, + reboot ? SHUTDOWN_reboot : SHUTDOWN_poweroff); if (sts != 0) { - fprintf(stderr, "? xc_domain_shutdown failed to issue poweroff, " - "sts %d, %s\n", sts, strerror(errno)); + fprintf(stderr, "xc_domain_shutdown failed to issue %s, " + "sts %d, %s\n", reboot ? "reboot" : "poweroff", + sts, strerror(errno)); } else { - fprintf(stderr, "Issued domain %d poweroff\n", xen_domid); + fprintf(stderr, "Issued domain %d %s\n", xen_domid, + reboot ? "reboot" : "poweroff"); } xc_interface_close(xc_handle); } |