aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2012-05-31 22:19:22 -0300
committerMarcelo Tosatti <mtosatti@redhat.com>2012-05-31 22:19:22 -0300
commit9688c60477f178d4a838c2e778e8d3281c69119d (patch)
tree70c0418beedc0a0b8e1e8ec97ac444b8466bc229
parentf9dc38843a540d8e5a5a851da260e5372a941f1c (diff)
parent518e16b43905def4c7b8aefbb7302c225b896c28 (diff)
Merge branch 'upstream-merge'qemu-kvm-1.1-rc4
* 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--VERSION2
-rw-r--r--arch_init.c4
-rw-r--r--audio/audio.c12
-rw-r--r--block.c37
-rw-r--r--block/iscsi.c240
-rw-r--r--block/qcow2-cluster.c23
-rw-r--r--block/qcow2.c3
-rw-r--r--block/sheepdog.c113
-rw-r--r--block/vvfat.c7
-rw-r--r--block_int.h2
-rwxr-xr-xconfigure19
-rw-r--r--docs/usb2.txt15
-rw-r--r--hw/acpi_piix4.c1
-rw-r--r--hw/es1370.c11
-rw-r--r--hw/fdc.c14
-rw-r--r--hw/multiboot.c12
-rw-r--r--hw/pc.c25
-rw-r--r--hw/pci.c1
-rw-r--r--hw/scsi-bus.c2
-rw-r--r--hw/vga.c7
-rw-r--r--hw/vga_int.h1
-rw-r--r--hw/xen_common.h2
-rw-r--r--hw/xen_disk.c42
-rw-r--r--pc-bios/README2
-rw-r--r--pc-bios/openbios-ppcbin729876 -> 729876 bytes
-rw-r--r--pc-bios/openbios-sparc32bin381764 -> 381764 bytes
-rw-r--r--pc-bios/openbios-sparc64bin1598648 -> 1598648 bytes
-rw-r--r--qemu-img.texi18
-rw-r--r--qga/commands-posix.c13
m---------roms/openbios0
-rw-r--r--slirp/ip.h20
-rw-r--r--slirp/tcp.h13
-rw-r--r--slirp/tcp_output.c1
-rw-r--r--target-i386/cpu.c22
-rw-r--r--target-i386/cpu.h2
-rw-r--r--tcg/ppc/tcg-target.c16
-rw-r--r--tests/fdc-test.c65
-rwxr-xr-xtests/qemu-iotests/0352
-rw-r--r--trace-events4
-rw-r--r--ui/cocoa.m3
-rw-r--r--ui/vnc.c4
-rw-r--r--xen-all.c22
42 files changed, 584 insertions, 218 deletions
diff --git a/VERSION b/VERSION
index 87903b67d..00572cea3 100644
--- a/VERSION
+++ b/VERSION
@@ -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);
}
diff --git a/block.c b/block.c
index af2ab4f3e..7547051ec 100644
--- a/block.c
+++ b/block.c
@@ -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);
diff --git a/configure b/configure
index 6704f265d..38dafec8a 100755
--- a/configure
+++ b/configure
@@ -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;
diff --git a/hw/fdc.c b/hw/fdc.c
index cb4cd25c1..30d34e3f1 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -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);
diff --git a/hw/pc.c b/hw/pc.c
index bc002f701..dc3193379 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -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]) {
diff --git a/hw/pci.c b/hw/pci.c
index 68e5232ed..e4fefb311 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -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,
diff --git a/hw/vga.c b/hw/vga.c
index 5824f85d0..d784df7df 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -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
index d4656db8b..aeae26588 100644
--- a/pc-bios/openbios-ppc
+++ b/pc-bios/openbios-ppc
Binary files differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index 4312c690a..d90c4e59a 100644
--- a/pc-bios/openbios-sparc32
+++ b/pc-bios/openbios-sparc32
Binary files differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index b18610508..457d26422 100644
--- a/pc-bios/openbios-sparc64
+++ b/pc-bios/openbios-sparc64
Binary files differ
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());
}
}
diff --git a/ui/vnc.c b/ui/vnc.c
index be384a531..54bc5adab 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -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;
}
diff --git a/xen-all.c b/xen-all.c
index bdf9c0fc7..b5220cc6a 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -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);
}