aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-04-09 17:51:08 +0300
committerAvi Kivity <avi@redhat.com>2009-04-09 17:51:08 +0300
commit7756cbe81190ab846ad09ce81fe6101a798eb646 (patch)
treed1496195da1826da9cd5f2b9ccd2dbb103677eda
parent67afa42dada0e8eab8b88bcc12447bddfccad5f7 (diff)
parent9d1b494a2d5dd2c129994edcf4eb7630bb554964 (diff)
Merge commit 'qemu-svn/trunk'
-rw-r--r--CODING_STYLE2
-rw-r--r--Changelog16
-rw-r--r--block-qcow.c112
-rw-r--r--block-qcow2.c122
-rw-r--r--block-raw-posix.c113
-rw-r--r--block-raw-win32.c33
-rw-r--r--block.c189
-rw-r--r--block.h7
-rw-r--r--block_int.h8
-rw-r--r--cmd.c2
-rw-r--r--cmd.h2
-rwxr-xr-xconfigure19
-rw-r--r--dma-helpers.c2
-rw-r--r--hw/bt-hci.c26
-rw-r--r--hw/bt-hid.c2
-rw-r--r--hw/cirrus_vga.c11
-rw-r--r--hw/fw_cfg.c4
-rw-r--r--hw/ide.c10
-rw-r--r--hw/lm832x.c6
-rw-r--r--hw/scsi-disk.c125
-rw-r--r--hw/vga.c276
-rw-r--r--hw/vga_int.h4
-rw-r--r--hw/wm8750.c2
-rw-r--r--posix-aio-compat.c197
-rw-r--r--posix-aio-compat.h9
-rw-r--r--target-mips/helper.h8
-rw-r--r--tcg/tcg.c12
-rw-r--r--tcg/tcg.h8
-rw-r--r--vnc.c2
29 files changed, 736 insertions, 593 deletions
diff --git a/CODING_STYLE b/CODING_STYLE
index 1ab13b686..a579cb1b5 100644
--- a/CODING_STYLE
+++ b/CODING_STYLE
@@ -10,7 +10,7 @@ of approximately fifteen parsecs. Many a flamewar have been fought and
lost on this issue.
QEMU indents are four spaces. Tabs are never used, except in Makefiles
-where they have been irreversibly coded into the syntax by some moron.
+where they have been irreversibly coded into the syntax.
Spaces of course are superior to tabs because:
- You have just one way to specify whitespace, not two. Ambiguity breeds
diff --git a/Changelog b/Changelog
index 9659be4ef..2a3e37d2b 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,19 @@
+version 0.10.2:
+
+ - fix savevm/loadvm (Anthony Liguori)
+ - live migration: fix dirty tracking windows (Glauber Costa)
+ - live migration: improve error propogation (Glauber Costa)
+ - qcow2: fix image creation for > ~2TB images (Chris Wright)
+ - hotplug: fix error handling for if= parameter (Eduardo Habkost)
+ - qcow2: fix data corruption (Nolan Leake)
+ - virtio: fix guest oops with 2.6.25 kernels (Rusty Russell)
+ - SH4: add support for -kernel (Takashi Yoshii, Aurelien Jarno)
+ - hotplug: fix closing of char devices (Jan Kiszka)
+ - hotplug: remove incorrect check for device name (Eduardo Habkost)
+ - enable -k on win32 (Herve Poussineau)
+ - configure: use LANG=C for grep (Andreas Faerber)
+ - fix VGA regression (malc)
+
version 0.10.1:
- virtio-net: check right return size on sg list (Alex Williamson)
diff --git a/block-qcow.c b/block-qcow.c
index 1fabc494d..b60f4c192 100644
--- a/block-qcow.c
+++ b/block-qcow.c
@@ -525,11 +525,15 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
typedef struct QCowAIOCB {
BlockDriverAIOCB common;
int64_t sector_num;
+ QEMUIOVector *qiov;
uint8_t *buf;
+ void *orig_buf;
int nb_sectors;
int n;
uint64_t cluster_offset;
uint8_t *cluster_data;
+ struct iovec hd_iov;
+ QEMUIOVector hd_qiov;
BlockDriverAIOCB *hd_aiocb;
} QCowAIOCB;
@@ -541,12 +545,8 @@ static void qcow_aio_read_cb(void *opaque, int ret)
int index_in_cluster;
acb->hd_aiocb = NULL;
- if (ret < 0) {
- fail:
- acb->common.cb(acb->common.opaque, ret);
- qemu_aio_release(acb);
- return;
- }
+ if (ret < 0)
+ goto done;
redo:
/* post process the read buffer */
@@ -568,9 +568,8 @@ static void qcow_aio_read_cb(void *opaque, int ret)
if (acb->nb_sectors == 0) {
/* request completed */
- acb->common.cb(acb->common.opaque, 0);
- qemu_aio_release(acb);
- return;
+ ret = 0;
+ goto done;
}
/* prepare next AIO request */
@@ -584,10 +583,13 @@ static void qcow_aio_read_cb(void *opaque, int ret)
if (!acb->cluster_offset) {
if (bs->backing_hd) {
/* read from the base image */
- acb->hd_aiocb = bdrv_aio_read(bs->backing_hd,
- acb->sector_num, acb->buf, acb->n, qcow_aio_read_cb, acb);
+ acb->hd_iov.iov_base = acb->buf;
+ acb->hd_iov.iov_len = acb->n * 512;
+ qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
+ acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
+ &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
if (acb->hd_aiocb == NULL)
- goto fail;
+ goto done;
} else {
/* Note: in this case, no need to wait */
memset(acb->buf, 0, 512 * acb->n);
@@ -596,25 +598,38 @@ static void qcow_aio_read_cb(void *opaque, int ret)
} else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
/* add AIO support for compressed blocks ? */
if (decompress_cluster(s, acb->cluster_offset) < 0)
- goto fail;
+ goto done;
memcpy(acb->buf,
s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
goto redo;
} else {
if ((acb->cluster_offset & 511) != 0) {
ret = -EIO;
- goto fail;
+ goto done;
}
- acb->hd_aiocb = bdrv_aio_read(s->hd,
+ acb->hd_iov.iov_base = acb->buf;
+ acb->hd_iov.iov_len = acb->n * 512;
+ qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
+ acb->hd_aiocb = bdrv_aio_readv(s->hd,
(acb->cluster_offset >> 9) + index_in_cluster,
- acb->buf, acb->n, qcow_aio_read_cb, acb);
+ &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
if (acb->hd_aiocb == NULL)
- goto fail;
+ goto done;
}
+
+ return;
+
+done:
+ if (acb->qiov->niov > 1) {
+ qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size);
+ qemu_vfree(acb->orig_buf);
+ }
+ acb->common.cb(acb->common.opaque, ret);
+ qemu_aio_release(acb);
}
-static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
- int64_t sector_num, uint8_t *buf, int nb_sectors,
+static BlockDriverAIOCB *qcow_aio_readv(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
QCowAIOCB *acb;
@@ -624,7 +639,11 @@ static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
return NULL;
acb->hd_aiocb = NULL;
acb->sector_num = sector_num;
- acb->buf = buf;
+ acb->qiov = qiov;
+ if (qiov->niov > 1)
+ acb->buf = acb->orig_buf = qemu_memalign(512, qiov->size);
+ else
+ acb->buf = qiov->iov->iov_base;
acb->nb_sectors = nb_sectors;
acb->n = 0;
acb->cluster_offset = 0;
@@ -644,12 +663,8 @@ static void qcow_aio_write_cb(void *opaque, int ret)
acb->hd_aiocb = NULL;
- if (ret < 0) {
- fail:
- acb->common.cb(acb->common.opaque, ret);
- qemu_aio_release(acb);
- return;
- }
+ if (ret < 0)
+ goto done;
acb->nb_sectors -= acb->n;
acb->sector_num += acb->n;
@@ -657,9 +672,8 @@ static void qcow_aio_write_cb(void *opaque, int ret)
if (acb->nb_sectors == 0) {
/* request completed */
- acb->common.cb(acb->common.opaque, 0);
- qemu_aio_release(acb);
- return;
+ ret = 0;
+ goto done;
}
index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
@@ -671,14 +685,14 @@ static void qcow_aio_write_cb(void *opaque, int ret)
index_in_cluster + acb->n);
if (!cluster_offset || (cluster_offset & 511) != 0) {
ret = -EIO;
- goto fail;
+ goto done;
}
if (s->crypt_method) {
if (!acb->cluster_data) {
acb->cluster_data = qemu_mallocz(s->cluster_size);
if (!acb->cluster_data) {
ret = -ENOMEM;
- goto fail;
+ goto done;
}
}
encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf,
@@ -687,16 +701,27 @@ static void qcow_aio_write_cb(void *opaque, int ret)
} else {
src_buf = acb->buf;
}
- acb->hd_aiocb = bdrv_aio_write(s->hd,
- (cluster_offset >> 9) + index_in_cluster,
- src_buf, acb->n,
- qcow_aio_write_cb, acb);
+
+ acb->hd_iov.iov_base = (void *)src_buf;
+ acb->hd_iov.iov_len = acb->n * 512;
+ qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
+ acb->hd_aiocb = bdrv_aio_writev(s->hd,
+ (cluster_offset >> 9) + index_in_cluster,
+ &acb->hd_qiov, acb->n,
+ qcow_aio_write_cb, acb);
if (acb->hd_aiocb == NULL)
- goto fail;
+ goto done;
+ return;
+
+done:
+ if (acb->qiov->niov > 1)
+ qemu_vfree(acb->orig_buf);
+ acb->common.cb(acb->common.opaque, ret);
+ qemu_aio_release(acb);
}
-static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
- int64_t sector_num, const uint8_t *buf, int nb_sectors,
+static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BDRVQcowState *s = bs->opaque;
@@ -709,7 +734,12 @@ static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
return NULL;
acb->hd_aiocb = NULL;
acb->sector_num = sector_num;
- acb->buf = (uint8_t *)buf;
+ acb->qiov = qiov;
+ if (qiov->niov > 1) {
+ acb->buf = acb->orig_buf = qemu_memalign(512, qiov->size);
+ qemu_iovec_to_buffer(qiov, acb->buf);
+ } else
+ acb->buf = qiov->iov->iov_base;
acb->nb_sectors = nb_sectors;
acb->n = 0;
@@ -897,8 +927,8 @@ BlockDriver bdrv_qcow = {
.bdrv_is_allocated = qcow_is_allocated,
.bdrv_set_key = qcow_set_key,
.bdrv_make_empty = qcow_make_empty,
- .bdrv_aio_read = qcow_aio_read,
- .bdrv_aio_write = qcow_aio_write,
+ .bdrv_aio_readv = qcow_aio_readv,
+ .bdrv_aio_writev = qcow_aio_writev,
.bdrv_aio_cancel = qcow_aio_cancel,
.aiocb_size = sizeof(QCowAIOCB),
.bdrv_write_compressed = qcow_write_compressed,
diff --git a/block-qcow2.c b/block-qcow2.c
index 6eba524a2..3bd38b0d9 100644
--- a/block-qcow2.c
+++ b/block-qcow2.c
@@ -1264,12 +1264,16 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
typedef struct QCowAIOCB {
BlockDriverAIOCB common;
int64_t sector_num;
+ QEMUIOVector *qiov;
uint8_t *buf;
+ void *orig_buf;
int nb_sectors;
int n;
uint64_t cluster_offset;
uint8_t *cluster_data;
BlockDriverAIOCB *hd_aiocb;
+ struct iovec hd_iov;
+ QEMUIOVector hd_qiov;
QEMUBH *bh;
QCowL2Meta l2meta;
} QCowAIOCB;
@@ -1305,12 +1309,8 @@ static void qcow_aio_read_cb(void *opaque, int ret)
int index_in_cluster, n1;
acb->hd_aiocb = NULL;
- if (ret < 0) {
-fail:
- acb->common.cb(acb->common.opaque, ret);
- qemu_aio_release(acb);
- return;
- }
+ if (ret < 0)
+ goto done;
/* post process the read buffer */
if (!acb->cluster_offset) {
@@ -1331,9 +1331,8 @@ fail:
if (acb->nb_sectors == 0) {
/* request completed */
- acb->common.cb(acb->common.opaque, 0);
- qemu_aio_release(acb);
- return;
+ ret = 0;
+ goto done;
}
/* prepare next AIO request */
@@ -1347,47 +1346,64 @@ fail:
n1 = backing_read1(bs->backing_hd, acb->sector_num,
acb->buf, acb->n);
if (n1 > 0) {
- acb->hd_aiocb = bdrv_aio_read(bs->backing_hd, acb->sector_num,
- acb->buf, acb->n, qcow_aio_read_cb, acb);
+ acb->hd_iov.iov_base = acb->buf;
+ acb->hd_iov.iov_len = acb->n * 512;
+ qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
+ acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
+ &acb->hd_qiov, acb->n,
+ qcow_aio_read_cb, acb);
if (acb->hd_aiocb == NULL)
- goto fail;
+ goto done;
} else {
ret = qcow_schedule_bh(qcow_aio_read_bh, acb);
if (ret < 0)
- goto fail;
+ goto done;
}
} else {
/* Note: in this case, no need to wait */
memset(acb->buf, 0, 512 * acb->n);
ret = qcow_schedule_bh(qcow_aio_read_bh, acb);
if (ret < 0)
- goto fail;
+ goto done;
}
} else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
/* add AIO support for compressed blocks ? */
if (decompress_cluster(s, acb->cluster_offset) < 0)
- goto fail;
+ goto done;
memcpy(acb->buf,
s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
ret = qcow_schedule_bh(qcow_aio_read_bh, acb);
if (ret < 0)
- goto fail;
+ goto done;
} else {
if ((acb->cluster_offset & 511) != 0) {
ret = -EIO;
- goto fail;
+ goto done;
}
- acb->hd_aiocb = bdrv_aio_read(s->hd,
+
+ acb->hd_iov.iov_base = acb->buf;
+ acb->hd_iov.iov_len = acb->n * 512;
+ qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
+ acb->hd_aiocb = bdrv_aio_readv(s->hd,
(acb->cluster_offset >> 9) + index_in_cluster,
- acb->buf, acb->n, qcow_aio_read_cb, acb);
+ &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
if (acb->hd_aiocb == NULL)
- goto fail;
+ goto done;
+ }
+
+ return;
+done:
+ if (acb->qiov->niov > 1) {
+ qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size);
+ qemu_vfree(acb->orig_buf);
}
+ acb->common.cb(acb->common.opaque, ret);
+ qemu_aio_release(acb);
}
static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
- int64_t sector_num, uint8_t *buf, int nb_sectors,
- BlockDriverCompletionFunc *cb, void *opaque)
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+ BlockDriverCompletionFunc *cb, void *opaque, int is_write)
{
QCowAIOCB *acb;
@@ -1396,7 +1412,13 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
return NULL;
acb->hd_aiocb = NULL;
acb->sector_num = sector_num;
- acb->buf = buf;
+ acb->qiov = qiov;
+ if (qiov->niov > 1) {
+ acb->buf = acb->orig_buf = qemu_memalign(512, qiov->size);
+ if (is_write)
+ qemu_iovec_to_buffer(qiov, acb->buf);
+ } else
+ acb->buf = qiov->iov->iov_base;
acb->nb_sectors = nb_sectors;
acb->n = 0;
acb->cluster_offset = 0;
@@ -1404,13 +1426,13 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
return acb;
}
-static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
- int64_t sector_num, uint8_t *buf, int nb_sectors,
+static BlockDriverAIOCB *qcow_aio_readv(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
QCowAIOCB *acb;
- acb = qcow_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
+ acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
if (!acb)
return NULL;
@@ -1429,16 +1451,12 @@ static void qcow_aio_write_cb(void *opaque, int ret)
acb->hd_aiocb = NULL;
- if (ret < 0) {
- fail:
- acb->common.cb(acb->common.opaque, ret);
- qemu_aio_release(acb);
- return;
- }
+ if (ret < 0)
+ goto done;
if (alloc_cluster_link_l2(bs, acb->cluster_offset, &acb->l2meta) < 0) {
free_any_clusters(bs, acb->cluster_offset, acb->l2meta.nb_clusters);
- goto fail;
+ goto done;
}
acb->nb_sectors -= acb->n;
@@ -1447,9 +1465,8 @@ static void qcow_aio_write_cb(void *opaque, int ret)
if (acb->nb_sectors == 0) {
/* request completed */
- acb->common.cb(acb->common.opaque, 0);
- qemu_aio_release(acb);
- return;
+ ret = 0;
+ goto done;
}
index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
@@ -1463,7 +1480,7 @@ static void qcow_aio_write_cb(void *opaque, int ret)
n_end, &acb->n, &acb->l2meta);
if (!acb->cluster_offset || (acb->cluster_offset & 511) != 0) {
ret = -EIO;
- goto fail;
+ goto done;
}
if (s->crypt_method) {
if (!acb->cluster_data) {
@@ -1476,16 +1493,27 @@ static void qcow_aio_write_cb(void *opaque, int ret)
} else {
src_buf = acb->buf;
}
- acb->hd_aiocb = bdrv_aio_write(s->hd,
- (acb->cluster_offset >> 9) + index_in_cluster,
- src_buf, acb->n,
- qcow_aio_write_cb, acb);
+ acb->hd_iov.iov_base = (void *)src_buf;
+ acb->hd_iov.iov_len = acb->n * 512;
+ qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
+ acb->hd_aiocb = bdrv_aio_writev(s->hd,
+ (acb->cluster_offset >> 9) + index_in_cluster,
+ &acb->hd_qiov, acb->n,
+ qcow_aio_write_cb, acb);
if (acb->hd_aiocb == NULL)
- goto fail;
+ goto done;
+
+ return;
+
+done:
+ if (acb->qiov->niov > 1)
+ qemu_vfree(acb->orig_buf);
+ acb->common.cb(acb->common.opaque, ret);
+ qemu_aio_release(acb);
}
-static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
- int64_t sector_num, const uint8_t *buf, int nb_sectors,
+static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BDRVQcowState *s = bs->opaque;
@@ -1493,7 +1521,7 @@ static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
s->cluster_cache_offset = -1; /* disable compressed cache */
- acb = qcow_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
+ acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
if (!acb)
return NULL;
@@ -2758,8 +2786,8 @@ BlockDriver bdrv_qcow2 = {
.bdrv_set_key = qcow_set_key,
.bdrv_make_empty = qcow_make_empty,
- .bdrv_aio_read = qcow_aio_read,
- .bdrv_aio_write = qcow_aio_write,
+ .bdrv_aio_readv = qcow_aio_readv,
+ .bdrv_aio_writev = qcow_aio_writev,
.bdrv_aio_cancel = qcow_aio_cancel,
.aiocb_size = sizeof(QCowAIOCB),
.bdrv_write_compressed = qcow_write_compressed,
diff --git a/block-raw-posix.c b/block-raw-posix.c
index a972f80ae..f033baee5 100644
--- a/block-raw-posix.c
+++ b/block-raw-posix.c
@@ -596,8 +596,8 @@ static int posix_aio_init(void)
return 0;
}
-static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
- int64_t sector_num, uint8_t *buf, int nb_sectors,
+static RawAIOCB *raw_aio_setup(BlockDriverState *bs, int64_t sector_num,
+ QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BDRVRawState *s = bs->opaque;
@@ -611,24 +611,25 @@ static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
return NULL;
acb->aiocb.aio_fildes = s->fd;
acb->aiocb.ev_signo = SIGUSR2;
- acb->aiocb.aio_buf = buf;
- if (nb_sectors < 0)
- acb->aiocb.aio_nbytes = -nb_sectors;
- else
- acb->aiocb.aio_nbytes = nb_sectors * 512;
+ acb->aiocb.aio_iov = qiov->iov;
+ acb->aiocb.aio_niov = qiov->niov;
+ acb->aiocb.aio_nbytes = nb_sectors * 512;
acb->aiocb.aio_offset = sector_num * 512;
+ acb->aiocb.aio_flags = 0;
+
+ /*
+ * If O_DIRECT is used the buffer needs to be aligned on a sector
+ * boundary. Tell the low level code to ensure that in case it's
+ * not done yet.
+ */
+ if (s->aligned_buf)
+ acb->aiocb.aio_flags |= QEMU_AIO_SECTOR_ALIGNED;
+
acb->next = posix_aio_state->first_aio;
posix_aio_state->first_aio = acb;
return acb;
}
-static void raw_aio_em_cb(void* opaque)
-{
- RawAIOCB *acb = opaque;
- acb->common.cb(acb->common.opaque, acb->ret);
- qemu_aio_release(acb);
-}
-
static void raw_aio_remove(RawAIOCB *acb)
{
RawAIOCB **pacb;
@@ -648,28 +649,13 @@ static void raw_aio_remove(RawAIOCB *acb)
}
}
-static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
- int64_t sector_num, uint8_t *buf, int nb_sectors,
+static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
RawAIOCB *acb;
- /*
- * If O_DIRECT is used and the buffer is not aligned fall back
- * to synchronous IO.
- */
- BDRVRawState *s = bs->opaque;
-
- if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
- QEMUBH *bh;
- acb = qemu_aio_get(bs, cb, opaque);
- acb->ret = raw_pread(bs, 512 * sector_num, buf, 512 * nb_sectors);
- bh = qemu_bh_new(raw_aio_em_cb, acb);
- qemu_bh_schedule(bh);
- return &acb->common;
- }
-
- acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
+ acb = raw_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque);
if (!acb)
return NULL;
if (qemu_paio_read(&acb->aiocb) < 0) {
@@ -679,28 +665,13 @@ static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
return &acb->common;
}
-static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
- int64_t sector_num, const uint8_t *buf, int nb_sectors,
+static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
RawAIOCB *acb;
- /*
- * If O_DIRECT is used and the buffer is not aligned fall back
- * to synchronous IO.
- */
- BDRVRawState *s = bs->opaque;
-
- if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
- QEMUBH *bh;
- acb = qemu_aio_get(bs, cb, opaque);
- acb->ret = raw_pwrite(bs, 512 * sector_num, buf, 512 * nb_sectors);
- bh = qemu_bh_new(raw_aio_em_cb, acb);
- qemu_bh_schedule(bh);
- return &acb->common;
- }
-
- acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
+ acb = raw_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque);
if (!acb)
return NULL;
if (qemu_paio_write(&acb->aiocb) < 0) {
@@ -873,25 +844,23 @@ static void raw_flush(BlockDriverState *bs)
}
BlockDriver bdrv_raw = {
- "raw",
- sizeof(BDRVRawState),
- NULL, /* no probe for protocols */
- raw_open,
- NULL,
- NULL,
- raw_close,
- raw_create,
- raw_flush,
+ .format_name = "raw",
+ .instance_size = sizeof(BDRVRawState),
+ .bdrv_probe = NULL, /* no probe for protocols */
+ .bdrv_open = raw_open,
+ .bdrv_read = raw_read,
+ .bdrv_write = raw_write,
+ .bdrv_close = raw_close,
+ .bdrv_create = raw_create,
+ .bdrv_flush = raw_flush,
#ifdef CONFIG_AIO
- .bdrv_aio_read = raw_aio_read,
- .bdrv_aio_write = raw_aio_write,
+ .bdrv_aio_readv = raw_aio_readv,
+ .bdrv_aio_writev = raw_aio_writev,
.bdrv_aio_cancel = raw_aio_cancel,
.aiocb_size = sizeof(RawAIOCB),
#endif
- .bdrv_read = raw_read,
- .bdrv_write = raw_write,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
};
@@ -1214,12 +1183,24 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
unsigned long int req, void *buf,
BlockDriverCompletionFunc *cb, void *opaque)
{
+ BDRVRawState *s = bs->opaque;
RawAIOCB *acb;
- acb = raw_aio_setup(bs, 0, buf, 0, cb, opaque);
+ if (fd_open(bs) < 0)
+ return NULL;
+
+ acb = qemu_aio_get(bs, cb, opaque);
if (!acb)
return NULL;
+ acb->aiocb.aio_fildes = s->fd;
+ acb->aiocb.ev_signo = SIGUSR2;
+ acb->aiocb.aio_offset = 0;
+ acb->aiocb.aio_flags = 0;
+
+ acb->next = posix_aio_state->first_aio;
+ posix_aio_state->first_aio = acb;
+ acb->aiocb.aio_ioctl_buf = buf;
acb->aiocb.aio_ioctl_cmd = req;
if (qemu_paio_ioctl(&acb->aiocb) < 0) {
raw_aio_remove(acb);
@@ -1423,8 +1404,8 @@ BlockDriver bdrv_host_device = {
.bdrv_flush = raw_flush,
#ifdef CONFIG_AIO
- .bdrv_aio_read = raw_aio_read,
- .bdrv_aio_write = raw_aio_write,
+ .bdrv_aio_readv = raw_aio_readv,
+ .bdrv_aio_writev = raw_aio_writev,
.bdrv_aio_cancel = raw_aio_cancel,
.aiocb_size = sizeof(RawAIOCB),
#endif
diff --git a/block-raw-win32.c b/block-raw-win32.c
index af9cc6db3..b5287d2a5 100644
--- a/block-raw-win32.c
+++ b/block-raw-win32.c
@@ -229,20 +229,16 @@ static int raw_create(const char *filename, int64_t total_size,
}
BlockDriver bdrv_raw = {
- "raw",
- sizeof(BDRVRawState),
- NULL, /* no probe for protocols */
- raw_open,
- NULL,
- NULL,
- raw_close,
- raw_create,
- raw_flush,
-
- .bdrv_read = raw_read,
- .bdrv_write = raw_write,
- .bdrv_truncate = raw_truncate,
- .bdrv_getlength = raw_getlength,
+ .format_name = "raw",
+ .instance_size = sizeof(BDRVRawState),
+ .bdrv_open = raw_open,
+ .bdrv_close = raw_close,
+ .bdrv_create = raw_create,
+ .bdrv_flush = raw_flush,
+ .bdrv_read = raw_read,
+ .bdrv_write = raw_write,
+ .bdrv_truncate = raw_truncate,
+ .bdrv_getlength = raw_getlength,
};
/***********************************************/
@@ -280,10 +276,15 @@ static int find_device_type(BlockDriverState *bs, const char *filename)
return FTYPE_HARDDISK;
snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
type = GetDriveType(s->drive_path);
- if (type == DRIVE_CDROM)
+ switch (type) {
+ case DRIVE_REMOVABLE:
+ case DRIVE_FIXED:
+ return FTYPE_HARDDISK;
+ case DRIVE_CDROM:
return FTYPE_CD;
- else
+ default:
return FTYPE_FILE;
+ }
} else {
return FTYPE_FILE;
}
diff --git a/block.c b/block.c
index 657de8107..98f844157 100644
--- a/block.c
+++ b/block.c
@@ -48,19 +48,21 @@
#define SECTOR_BITS 9
#define SECTOR_SIZE (1 << SECTOR_BITS)
-static AIOPool vectored_aio_pool;
-
typedef struct BlockDriverAIOCBSync {
BlockDriverAIOCB common;
QEMUBH *bh;
int ret;
+ /* vector translation state */
+ QEMUIOVector *qiov;
+ uint8_t *bounce;
+ int is_write;
} BlockDriverAIOCBSync;
-static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
- int64_t sector_num, uint8_t *buf, int nb_sectors,
+static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
-static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
- int64_t sector_num, const uint8_t *buf, int nb_sectors,
+static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
@@ -139,10 +141,10 @@ void path_combine(char *dest, int dest_size,
static void bdrv_register(BlockDriver *bdrv)
{
- if (!bdrv->bdrv_aio_read) {
+ if (!bdrv->bdrv_aio_readv) {
/* add AIO emulation layer */
- bdrv->bdrv_aio_read = bdrv_aio_read_em;
- bdrv->bdrv_aio_write = bdrv_aio_write_em;
+ bdrv->bdrv_aio_readv = bdrv_aio_readv_em;
+ bdrv->bdrv_aio_writev = bdrv_aio_writev_em;
bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync);
} else if (!bdrv->bdrv_read) {
@@ -1298,91 +1300,10 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
/**************************************************************/
/* async I/Os */
-typedef struct VectorTranslationAIOCB {
- BlockDriverAIOCB common;
- QEMUIOVector *iov;
- uint8_t *bounce;
- int is_write;
- BlockDriverAIOCB *aiocb;
-} VectorTranslationAIOCB;
-
-static void bdrv_aio_cancel_vector(BlockDriverAIOCB *_acb)
-{
- VectorTranslationAIOCB *acb
- = container_of(_acb, VectorTranslationAIOCB, common);
-
- bdrv_aio_cancel(acb->aiocb);
-}
-
-static void bdrv_aio_rw_vector_cb(void *opaque, int ret)
-{
- VectorTranslationAIOCB *s = (VectorTranslationAIOCB *)opaque;
-
- if (!s->is_write) {
- qemu_iovec_from_buffer(s->iov, s->bounce, s->iov->size);
- }
- qemu_vfree(s->bounce);
- s->common.cb(s->common.opaque, ret);
- qemu_aio_release(s);
-}
-
-static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
- int64_t sector_num,
- QEMUIOVector *iov,
- int nb_sectors,
- BlockDriverCompletionFunc *cb,
- void *opaque,
- int is_write)
-
-{
- VectorTranslationAIOCB *s = qemu_aio_get_pool(&vectored_aio_pool, bs,
- cb, opaque);
-
- s->iov = iov;
- s->bounce = qemu_memalign(512, nb_sectors * 512);
- s->is_write = is_write;
- if (is_write) {
- qemu_iovec_to_buffer(s->iov, s->bounce);
- s->aiocb = bdrv_aio_write(bs, sector_num, s->bounce, nb_sectors,
- bdrv_aio_rw_vector_cb, s);
- } else {
- s->aiocb = bdrv_aio_read(bs, sector_num, s->bounce, nb_sectors,
- bdrv_aio_rw_vector_cb, s);
- }
- if (!s->aiocb) {
- qemu_vfree(s->bounce);
- qemu_aio_release(s);
- return NULL;
- }
- return &s->common;
-}
-
BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
- QEMUIOVector *iov, int nb_sectors,
+ QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
- if (bdrv_check_request(bs, sector_num, nb_sectors))
- return NULL;
-
- return bdrv_aio_rw_vector(bs, sector_num, iov, nb_sectors,
- cb, opaque, 0);
-}
-
-BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
- QEMUIOVector *iov, int nb_sectors,
- BlockDriverCompletionFunc *cb, void *opaque)
-{
- if (bdrv_check_request(bs, sector_num, nb_sectors))
- return NULL;
-
- return bdrv_aio_rw_vector(bs, sector_num, iov, nb_sectors,
- cb, opaque, 1);
-}
-
-BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
- uint8_t *buf, int nb_sectors,
- BlockDriverCompletionFunc *cb, void *opaque)
-{
BlockDriver *drv = bs->drv;
BlockDriverAIOCB *ret;
@@ -1391,7 +1312,8 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
if (bdrv_check_request(bs, sector_num, nb_sectors))
return NULL;
- ret = drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
+ ret = drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors,
+ cb, opaque);
if (ret) {
/* Update stats even though technically transfer has not happened. */
@@ -1402,9 +1324,9 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
return ret;
}
-BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
- const uint8_t *buf, int nb_sectors,
- BlockDriverCompletionFunc *cb, void *opaque)
+BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
+ QEMUIOVector *qiov, int nb_sectors,
+ BlockDriverCompletionFunc *cb, void *opaque)
{
BlockDriver *drv = bs->drv;
BlockDriverAIOCB *ret;
@@ -1416,7 +1338,8 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
if (bdrv_check_request(bs, sector_num, nb_sectors))
return NULL;
- ret = drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
+ ret = drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors,
+ cb, opaque);
if (ret) {
/* Update stats even though technically transfer has not happened. */
@@ -1439,42 +1362,61 @@ void bdrv_aio_cancel(BlockDriverAIOCB *acb)
static void bdrv_aio_bh_cb(void *opaque)
{
BlockDriverAIOCBSync *acb = opaque;
+
+ if (!acb->is_write)
+ qemu_iovec_from_buffer(acb->qiov, acb->bounce, acb->qiov->size);
+ qemu_vfree(acb->bounce);
acb->common.cb(acb->common.opaque, acb->ret);
+
qemu_aio_release(acb);
}
-static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
- int64_t sector_num, uint8_t *buf, int nb_sectors,
- BlockDriverCompletionFunc *cb, void *opaque)
+static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
+ int64_t sector_num,
+ QEMUIOVector *qiov,
+ int nb_sectors,
+ BlockDriverCompletionFunc *cb,
+ void *opaque,
+ int is_write)
+
{
BlockDriverAIOCBSync *acb;
- int ret;
acb = qemu_aio_get(bs, cb, opaque);
+ acb->is_write = is_write;
+ acb->qiov = qiov;
+ acb->bounce = qemu_memalign(512, qiov->size);
+
if (!acb->bh)
acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
- ret = bdrv_read(bs, sector_num, buf, nb_sectors);
- acb->ret = ret;
+
+ if (is_write) {
+ qemu_iovec_to_buffer(acb->qiov, acb->bounce);
+ acb->ret = bdrv_write(bs, sector_num, acb->bounce, nb_sectors);
+ } else {
+ acb->ret = bdrv_read(bs, sector_num, acb->bounce, nb_sectors);
+ }
+
qemu_bh_schedule(acb->bh);
+
return &acb->common;
}
-static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
- int64_t sector_num, const uint8_t *buf, int nb_sectors,
+static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
- BlockDriverAIOCBSync *acb;
- int ret;
+ return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
+}
- acb = qemu_aio_get(bs, cb, opaque);
- if (!acb->bh)
- acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
- ret = bdrv_write(bs, sector_num, buf, nb_sectors);
- acb->ret = ret;
- qemu_bh_schedule(acb->bh);
- return &acb->common;
+static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+ BlockDriverCompletionFunc *cb, void *opaque)
+{
+ return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
}
+
static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
{
BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
@@ -1497,10 +1439,15 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
{
int async_ret;
BlockDriverAIOCB *acb;
+ struct iovec iov;
+ QEMUIOVector qiov;
async_ret = NOT_DONE;
- acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors,
- bdrv_rw_em_cb, &async_ret);
+ iov.iov_base = buf;
+ iov.iov_len = nb_sectors * 512;
+ qemu_iovec_init_external(&qiov, &iov, 1);
+ acb = bdrv_aio_readv(bs, sector_num, &qiov, nb_sectors,
+ bdrv_rw_em_cb, &async_ret);
if (acb == NULL)
return -1;
@@ -1516,10 +1463,15 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
{
int async_ret;
BlockDriverAIOCB *acb;
+ struct iovec iov;
+ QEMUIOVector qiov;
async_ret = NOT_DONE;
- acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors,
- bdrv_rw_em_cb, &async_ret);
+ iov.iov_base = (void *)buf;
+ iov.iov_len = nb_sectors * 512;
+ qemu_iovec_init_external(&qiov, &iov, 1);
+ acb = bdrv_aio_writev(bs, sector_num, &qiov, nb_sectors,
+ bdrv_rw_em_cb, &async_ret);
if (acb == NULL)
return -1;
while (async_ret == NOT_DONE) {
@@ -1530,9 +1482,6 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
void bdrv_init(void)
{
- aio_pool_init(&vectored_aio_pool, sizeof(VectorTranslationAIOCB),
- bdrv_aio_cancel_vector);
-
bdrv_register(&bdrv_raw);
bdrv_register(&bdrv_host_device);
#ifndef _WIN32
diff --git a/block.h b/block.h
index f1919b668..ca672a130 100644
--- a/block.h
+++ b/block.h
@@ -96,13 +96,6 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
QEMUIOVector *iov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
-
-BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
- uint8_t *buf, int nb_sectors,
- BlockDriverCompletionFunc *cb, void *opaque);
-BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
- const uint8_t *buf, int nb_sectors,
- BlockDriverCompletionFunc *cb, void *opaque);
void bdrv_aio_cancel(BlockDriverAIOCB *acb);
/* sg packet commands */
diff --git a/block_int.h b/block_int.h
index a59f54c4c..31609aa01 100644
--- a/block_int.h
+++ b/block_int.h
@@ -54,11 +54,11 @@ struct BlockDriver {
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
int (*bdrv_make_empty)(BlockDriverState *bs);
/* aio */
- BlockDriverAIOCB *(*bdrv_aio_read)(BlockDriverState *bs,
- int64_t sector_num, uint8_t *buf, int nb_sectors,
+ BlockDriverAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
- BlockDriverAIOCB *(*bdrv_aio_write)(BlockDriverState *bs,
- int64_t sector_num, const uint8_t *buf, int nb_sectors,
+ BlockDriverAIOCB *(*bdrv_aio_writev)(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
void (*bdrv_aio_cancel)(BlockDriverAIOCB *acb);
int aiocb_size;
diff --git a/cmd.c b/cmd.c
index e2f4486a1..1dc5dbd68 100644
--- a/cmd.c
+++ b/cmd.c
@@ -212,8 +212,6 @@ command_loop(void)
# include <histedit.h>
#endif
-extern char *progname;
-
static char *
get_prompt(void)
{
diff --git a/cmd.h b/cmd.h
index 5ca8fcf07..c5be50f80 100644
--- a/cmd.h
+++ b/cmd.h
@@ -75,4 +75,6 @@ enum {
extern void timestr(struct timeval *tv, char *str, size_t sz, int flags);
+extern char *progname;
+
#endif /* __COMMAND_H__ */
diff --git a/configure b/configure
index 8b6b69365..fe94f9650 100755
--- a/configure
+++ b/configure
@@ -572,6 +572,8 @@ echo " --source-path=PATH path of source code [$source_path]"
echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
echo " --cc=CC use C compiler CC [$cc]"
echo " --host-cc=CC use C compiler CC [$host_cc] for dyngen etc."
+echo " --extra-cflags=CFLAGS add C compiler flags CFLAGS"
+echo " --extra-ldflags=LDFLAGS add linker flags LDFLAGS"
echo " --make=MAKE use specified make [$make]"
echo " --install=INSTALL use specified install [$install]"
echo " --static enable static build [$static]"
@@ -1179,6 +1181,19 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then
fi
##########################################
+# preadv probe
+cat > $TMPC <<EOF
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+int main(void) { preadv; }
+EOF
+preadv=no
+if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then
+ preadv=yes
+fi
+
+##########################################
# fdt probe
if test "$fdt" = "yes" ; then
fdt=no
@@ -1321,6 +1336,7 @@ echo "AIO support $aio"
echo "Install blobs $blobs"
echo "KVM support $kvm"
echo "fdt support $fdt"
+echo "preadv support $preadv"
if test $sdl_too_old = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -1623,6 +1639,9 @@ fi
if test "$iovec" = "yes" ; then
echo "#define HAVE_IOVEC 1" >> $config_h
fi
+if test "$preadv" = "yes" ; then
+ echo "#define HAVE_PREADV 1" >> $config_h
+fi
if test "$fdt" = "yes" ; then
echo "#define HAVE_FDT 1" >> $config_h
echo "FDT_LIBS=-lfdt" >> $config_mak
diff --git a/dma-helpers.c b/dma-helpers.c
index 1469e34df..f9eb2240b 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -81,7 +81,7 @@ static void dma_bdrv_unmap(DMAAIOCB *dbs)
}
}
-void dma_bdrv_cb(void *opaque, int ret)
+static void dma_bdrv_cb(void *opaque, int ret)
{
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
target_phys_addr_t cur_addr, cur_len;
diff --git a/hw/bt-hci.c b/hw/bt-hci.c
index 7e93e26c8..a5902b03f 100644
--- a/hw/bt-hci.c
+++ b/hw/bt-hci.c
@@ -564,9 +564,11 @@ static void bt_hci_inquiry_result(struct bt_hci_s *hci,
switch (hci->lm.inquiry_mode) {
case 0x00:
- return bt_hci_inquiry_result_standard(hci, slave);
+ bt_hci_inquiry_result_standard(hci, slave);
+ return;
case 0x01:
- return bt_hci_inquiry_result_with_rssi(hci, slave);
+ bt_hci_inquiry_result_with_rssi(hci, slave);
+ return;
default:
fprintf(stderr, "%s: bad inquiry mode %02x\n", __FUNCTION__,
hci->lm.inquiry_mode);
@@ -771,9 +773,11 @@ static void bt_hci_lmp_connection_request(struct bt_link_s *link)
struct bt_hci_s *hci = hci_from_device(link->slave);
evt_conn_request params;
- if (hci->conn_req_host)
- return bt_hci_connection_reject(hci, link->host,
- HCI_REJECTED_LIMITED_RESOURCES);
+ if (hci->conn_req_host) {
+ bt_hci_connection_reject(hci, link->host,
+ HCI_REJECTED_LIMITED_RESOURCES);
+ return;
+ }
hci->conn_req_host = link->host;
/* TODO: if masked and auto-accept, then auto-accept,
* if masked and not auto-accept, then auto-reject */
@@ -2125,7 +2129,7 @@ static void bt_hci_evt_submit(void *opaque, int len)
/* TODO: notify upper layer */
struct bt_hci_s *s = opaque;
- return s->info.evt_recv(s->info.opaque, s->evt_buf, len);
+ s->info.evt_recv(s->info.opaque, s->evt_buf, len);
}
static int bt_hci_bdaddr_set(struct HCIInfo *info, const uint8_t *bd_addr)
@@ -2141,7 +2145,7 @@ static void bt_hci_destroy(struct bt_device_s *dev)
{
struct bt_hci_s *hci = hci_from_device(dev);
- return bt_hci_done(&hci->info);
+ bt_hci_done(&hci->info);
}
struct HCIInfo *bt_new_hci(struct bt_scatternet_s *net)
@@ -2196,9 +2200,11 @@ static void bt_hci_done(struct HCIInfo *info)
/* Be gentle and send DISCONNECT to all connected peers and those
* currently waiting for us to accept or reject a connection request.
* This frees the links. */
- if (hci->conn_req_host)
- return bt_hci_connection_reject(hci,
- hci->conn_req_host, HCI_OE_POWER_OFF);
+ if (hci->conn_req_host) {
+ bt_hci_connection_reject(hci,
+ hci->conn_req_host, HCI_OE_POWER_OFF);
+ return;
+ }
for (handle = HCI_HANDLE_OFFSET;
handle < (HCI_HANDLE_OFFSET | HCI_HANDLES_MAX); handle ++)
diff --git a/hw/bt-hid.c b/hw/bt-hid.c
index 3317ecc03..af0c3d5f2 100644
--- a/hw/bt-hid.c
+++ b/hw/bt-hid.c
@@ -383,7 +383,7 @@ static void bt_hid_control_sdu(void *opaque, const uint8_t *data, int len)
{
struct bt_hid_device_s *hid = opaque;
- return bt_hid_control_transaction(hid, data, len);
+ bt_hid_control_transaction(hid, data, len);
}
static void bt_hid_datain(void *opaque)
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index e79dd1765..dfbb59ad7 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -1393,8 +1393,6 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value)
break;
}
- vga_update_resolution((VGAState *)s);
-
return CIRRUS_HOOK_HANDLED;
}
@@ -1422,7 +1420,6 @@ static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
#endif
}
s->cirrus_hidden_dac_lockindex = 0;
- vga_update_resolution((VGAState *)s);
}
/***************************************
@@ -1709,8 +1706,6 @@ cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value)
break;
}
- vga_update_resolution((VGAState *)s);
-
return CIRRUS_HOOK_HANDLED;
}
@@ -2838,7 +2833,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
if (s->ar_flip_flop == 0) {
val &= 0x3f;
s->ar_index = val;
- vga_update_resolution((VGAState *)s);
} else {
index = s->ar_index & 0x1f;
switch (index) {
@@ -2932,7 +2926,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
/* can always write bit 4 of CR7 */
if (s->cr_index == 7)
s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
- vga_update_resolution((VGAState *)s);
return;
}
switch (s->cr_index) {
@@ -2961,7 +2954,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
s->update_retrace_info((VGAState *) s);
break;
}
- vga_update_resolution((VGAState *)s);
break;
case 0x3ba:
case 0x3da:
@@ -3168,8 +3160,7 @@ static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
cirrus_update_memory_access(s);
/* force refresh */
- vga_update_resolution((VGAState *)s);
- s->want_full_update = 1;
+ s->graphic_mode = -1;
cirrus_update_bank_ptr(s, 0);
cirrus_update_bank_ptr(s, 1);
return 0;
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index e324e8d7b..e1b19d72e 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -108,7 +108,7 @@ static uint32_t fw_cfg_io_readb(void *opaque, uint32_t addr)
static void fw_cfg_io_writeb(void *opaque, uint32_t addr, uint32_t value)
{
- return fw_cfg_write(opaque, (uint8_t)value);
+ fw_cfg_write(opaque, (uint8_t)value);
}
static void fw_cfg_io_writew(void *opaque, uint32_t addr, uint32_t value)
@@ -124,7 +124,7 @@ static uint32_t fw_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
static void fw_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
uint32_t value)
{
- return fw_cfg_write(opaque, (uint8_t)value);
+ fw_cfg_write(opaque, (uint8_t)value);
}
static void fw_cfg_mem_writew(void *opaque, target_phys_addr_t addr,
diff --git a/hw/ide.c b/hw/ide.c
index 96bc17603..f187546b4 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -496,6 +496,8 @@ typedef struct BMDMAState {
IDEState *ide_if;
BlockDriverCompletionFunc *dma_cb;
BlockDriverAIOCB *aiocb;
+ struct iovec iov;
+ QEMUIOVector qiov;
int64_t sector_num;
uint32_t nsector;
} BMDMAState;
@@ -1467,9 +1469,11 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
#ifdef DEBUG_AIO
printf("aio_read_cd: lba=%u n=%d\n", s->lba, n);
#endif
- bm->aiocb = bdrv_aio_read(s->bs, (int64_t)s->lba << 2,
- s->io_buffer + data_offset, n * 4,
- ide_atapi_cmd_read_dma_cb, bm);
+ bm->iov.iov_base = s->io_buffer + data_offset;
+ bm->iov.iov_len = n * 4 * 512;
+ qemu_iovec_init_external(&bm->qiov, &bm->iov, 1);
+ bm->aiocb = bdrv_aio_readv(s->bs, (int64_t)s->lba << 2, &bm->qiov,
+ n * 4, ide_atapi_cmd_read_dma_cb, bm);
if (!bm->aiocb) {
/* Note: media not present is the most likely case */
ide_atapi_cmd_error(s, SENSE_NOT_READY,
diff --git a/hw/lm832x.c b/hw/lm832x.c
index dd94310f6..6479e1487 100644
--- a/hw/lm832x.c
+++ b/hw/lm832x.c
@@ -519,8 +519,10 @@ void lm832x_key_event(struct i2c_slave *i2c, int key, int state)
if ((s->status & INT_ERROR) && (s->error & ERR_FIFOOVR))
return;
- if (s->kbd.len >= sizeof(s->kbd.fifo))
- return lm_kbd_error(s, ERR_FIFOOVR);
+ if (s->kbd.len >= sizeof(s->kbd.fifo)) {
+ lm_kbd_error(s, ERR_FIFOOVR);
+ return;
+ }
s->kbd.fifo[(s->kbd.start + s->kbd.len ++) & (sizeof(s->kbd.fifo) - 1)] =
key | (state << 7);
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index c7b2febd8..2edd047a8 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -52,9 +52,8 @@ typedef struct SCSIRequest {
/* Both sector and sector_count are in terms of qemu 512 byte blocks. */
uint64_t sector;
uint32_t sector_count;
- /* The amounnt of data in the buffer. */
- int buf_len;
- uint8_t *dma_buf;
+ struct iovec iov;
+ QEMUIOVector qiov;
BlockDriverAIOCB *aiocb;
struct SCSIRequest *next;
uint32_t status;
@@ -89,12 +88,12 @@ static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
free_requests = r->next;
} else {
r = qemu_malloc(sizeof(SCSIRequest));
- r->dma_buf = qemu_memalign(512, SCSI_DMA_BUF_SIZE);
+ r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE);
}
r->dev = s;
r->tag = tag;
r->sector_count = 0;
- r->buf_len = 0;
+ r->iov.iov_len = 0;
r->aiocb = NULL;
r->status = 0;
@@ -173,9 +172,9 @@ static void scsi_read_complete(void * opaque, int ret)
scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NO_SENSE);
return;
}
- DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, r->buf_len);
+ DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, r->iov.iov_len);
- s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len);
+ s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->iov.iov_len);
}
/* Read more data from scsi device into buffer. */
@@ -193,9 +192,9 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
return;
}
if (r->sector_count == (uint32_t)-1) {
- DPRINTF("Read buf_len=%d\n", r->buf_len);
+ DPRINTF("Read buf_len=%d\n", r->iov.iov_len);
r->sector_count = 0;
- s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len);
+ s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->iov.iov_len);
return;
}
DPRINTF("Read sector_count=%d\n", r->sector_count);
@@ -208,9 +207,10 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
if (n > SCSI_DMA_BUF_SIZE / 512)
n = SCSI_DMA_BUF_SIZE / 512;
- r->buf_len = n * 512;
- r->aiocb = bdrv_aio_read(s->bdrv, r->sector, r->dma_buf, n,
- scsi_read_complete, r);
+ r->iov.iov_len = n * 512;
+ qemu_iovec_init_external(&r->qiov, &r->iov, 1);
+ r->aiocb = bdrv_aio_readv(s->bdrv, r->sector, &r->qiov, n,
+ scsi_read_complete, r);
if (r->aiocb == NULL)
scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
r->sector += n;
@@ -250,7 +250,7 @@ static void scsi_write_complete(void * opaque, int ret)
return;
}
- n = r->buf_len / 512;
+ n = r->iov.iov_len / 512;
r->sector += n;
r->sector_count -= n;
if (r->sector_count == 0) {
@@ -260,7 +260,7 @@ static void scsi_write_complete(void * opaque, int ret)
if (len > SCSI_DMA_BUF_SIZE) {
len = SCSI_DMA_BUF_SIZE;
}
- r->buf_len = len;
+ r->iov.iov_len = len;
DPRINTF("Write complete tag=0x%x more=%d\n", r->tag, len);
s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
}
@@ -271,10 +271,11 @@ static void scsi_write_request(SCSIRequest *r)
SCSIDeviceState *s = r->dev;
uint32_t n;
- n = r->buf_len / 512;
+ n = r->iov.iov_len / 512;
if (n) {
- r->aiocb = bdrv_aio_write(s->bdrv, r->sector, r->dma_buf, n,
- scsi_write_complete, r);
+ qemu_iovec_init_external(&r->qiov, &r->iov, 1);
+ r->aiocb = bdrv_aio_writev(s->bdrv, r->sector, &r->qiov, n,
+ scsi_write_complete, r);
if (r->aiocb == NULL)
scsi_command_complete(r, STATUS_CHECK_CONDITION,
SENSE_HARDWARE_ERROR);
@@ -334,7 +335,7 @@ static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
BADF("Bad buffer tag 0x%x\n", tag);
return NULL;
}
- return r->dma_buf;
+ return r->iov.iov_base;
}
/* Execute a scsi command. Returns the length of the data expected by the
@@ -364,7 +365,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
/* ??? Tags are not unique for different luns. We only implement a
single lun, so this should not matter. */
r = scsi_new_request(s, tag);
- outbuf = r->dma_buf;
+ outbuf = r->iov.iov_base;
is_write = 0;
DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
switch (command >> 5) {
@@ -425,10 +426,10 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
if (len < 4)
goto fail;
memset(outbuf, 0, 4);
- r->buf_len = 4;
+ r->iov.iov_len = 4;
if (s->sense == SENSE_NOT_READY && len >= 18) {
memset(outbuf, 0, 18);
- r->buf_len = 18;
+ r->iov.iov_len = 18;
outbuf[7] = 10;
/* asc 0x3a, ascq 0: Medium not present */
outbuf[12] = 0x3a;
@@ -461,20 +462,20 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
DPRINTF("Inquiry EVPD[Supported pages] "
"buffer size %d\n", len);
- r->buf_len = 0;
+ r->iov.iov_len = 0;
if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
- outbuf[r->buf_len++] = 5;
+ outbuf[r->iov.iov_len++] = 5;
} else {
- outbuf[r->buf_len++] = 0;
+ outbuf[r->iov.iov_len++] = 0;
}
- outbuf[r->buf_len++] = 0x00; // this page
- outbuf[r->buf_len++] = 0x00;
- outbuf[r->buf_len++] = 3; // number of pages
- outbuf[r->buf_len++] = 0x00; // list of supported pages (this page)
- outbuf[r->buf_len++] = 0x80; // unit serial number
- outbuf[r->buf_len++] = 0x83; // device identification
+ outbuf[r->iov.iov_len++] = 0x00; // this page
+ outbuf[r->iov.iov_len++] = 0x00;
+ outbuf[r->iov.iov_len++] = 3; // number of pages
+ outbuf[r->iov.iov_len++] = 0x00; // list of supported pages (this page)
+ outbuf[r->iov.iov_len++] = 0x80; // unit serial number
+ outbuf[r->iov.iov_len++] = 0x83; // device identification
}
break;
case 0x80:
@@ -491,20 +492,20 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
DPRINTF("Inquiry EVPD[Serial number] buffer size %d\n", len);
l = MIN(len, strlen(s->drive_serial_str));
- r->buf_len = 0;
+ r->iov.iov_len = 0;
/* Supported page codes */
if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
- outbuf[r->buf_len++] = 5;
+ outbuf[r->iov.iov_len++] = 5;
} else {
- outbuf[r->buf_len++] = 0;
+ outbuf[r->iov.iov_len++] = 0;
}
- outbuf[r->buf_len++] = 0x80; // this page
- outbuf[r->buf_len++] = 0x00;
- outbuf[r->buf_len++] = l;
- memcpy(&outbuf[r->buf_len], s->drive_serial_str, l);
- r->buf_len += l;
+ outbuf[r->iov.iov_len++] = 0x80; // this page
+ outbuf[r->iov.iov_len++] = 0x00;
+ outbuf[r->iov.iov_len++] = l;
+ memcpy(&outbuf[r->iov.iov_len], s->drive_serial_str, l);
+ r->iov.iov_len += l;
}
break;
@@ -518,25 +519,25 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
DPRINTF("Inquiry EVPD[Device identification] "
"buffer size %d\n", len);
- r->buf_len = 0;
+ r->iov.iov_len = 0;
if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
- outbuf[r->buf_len++] = 5;
+ outbuf[r->iov.iov_len++] = 5;
} else {
- outbuf[r->buf_len++] = 0;
+ outbuf[r->iov.iov_len++] = 0;
}
- outbuf[r->buf_len++] = 0x83; // this page
- outbuf[r->buf_len++] = 0x00;
- outbuf[r->buf_len++] = 3 + id_len;
+ outbuf[r->iov.iov_len++] = 0x83; // this page
+ outbuf[r->iov.iov_len++] = 0x00;
+ outbuf[r->iov.iov_len++] = 3 + id_len;
- outbuf[r->buf_len++] = 0x2; // ASCII
- outbuf[r->buf_len++] = 0; // not officially assigned
- outbuf[r->buf_len++] = 0; // reserved
- outbuf[r->buf_len++] = id_len; // length of data following
+ outbuf[r->iov.iov_len++] = 0x2; // ASCII
+ outbuf[r->iov.iov_len++] = 0; // not officially assigned
+ outbuf[r->iov.iov_len++] = 0; // reserved
+ outbuf[r->iov.iov_len++] = id_len; // length of data following
- memcpy(&outbuf[r->buf_len],
+ memcpy(&outbuf[r->iov.iov_len],
bdrv_get_device_name(s->bdrv), id_len);
- r->buf_len += id_len;
+ r->iov.iov_len += id_len;
}
break;
default:
@@ -592,7 +593,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf[4] = len - 5; /* Additional Length = (Len - 1) - 4 */
/* Sync data transfer and TCQ. */
outbuf[7] = 0x10 | (s->tcq ? 0x02 : 0);
- r->buf_len = len;
+ r->iov.iov_len = len;
break;
case 0x16:
DPRINTF("Reserve(6)\n");
@@ -727,10 +728,10 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
p[21] = (16 * 176) & 0xff;
p += 22;
}
- r->buf_len = p - outbuf;
- outbuf[0] = r->buf_len - 4;
- if (r->buf_len > len)
- r->buf_len = len;
+ r->iov.iov_len = p - outbuf;
+ outbuf[0] = r->iov.iov_len - 4;
+ if (r->iov.iov_len > len)
+ r->iov.iov_len = len;
}
break;
case 0x1b:
@@ -766,7 +767,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf[5] = 0;
outbuf[6] = s->cluster_size * 2;
outbuf[7] = 0;
- r->buf_len = 8;
+ r->iov.iov_len = 8;
} else {
notready:
scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY);
@@ -827,7 +828,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
if (toclen > 0) {
if (len > toclen)
len = toclen;
- r->buf_len = len;
+ r->iov.iov_len = len;
break;
}
error_cmd:
@@ -840,7 +841,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
/* ??? This should probably return much more information. For now
just return the basic header indicating the CD-ROM profile. */
outbuf[7] = 8; // CD-ROM
- r->buf_len = 8;
+ r->iov.iov_len = 8;
break;
case 0x56:
DPRINTF("Reserve(10)\n");
@@ -877,7 +878,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf[10] = s->cluster_size * 2;
outbuf[11] = 0;
/* Protection, exponent and lowest lba field left blank. */
- r->buf_len = len;
+ r->iov.iov_len = len;
} else {
scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY);
return 0;
@@ -892,7 +893,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
goto fail;
memset(outbuf, 0, 16);
outbuf[3] = 8;
- r->buf_len = 16;
+ r->iov.iov_len = 16;
break;
case 0x2f:
DPRINTF("Verify (sector %d, count %d)\n", lba, len);
@@ -906,10 +907,10 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
return 0;
}
- if (r->sector_count == 0 && r->buf_len == 0) {
+ if (r->sector_count == 0 && r->iov.iov_len == 0) {
scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
}
- len = r->sector_count * 512 + r->buf_len;
+ len = r->sector_count * 512 + r->iov.iov_len;
if (is_write) {
return -len;
} else {
diff --git a/hw/vga.c b/hw/vga.c
index 4a081ce28..5639904b0 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -37,10 +37,6 @@
//#define DEBUG_BOCHS_VBE
-#define GMODE_TEXT 0
-#define GMODE_GRAPH 1
-#define GMODE_BLANK 2
-
/* force some bits to zero */
const uint8_t sr_mask[8] = {
0x03,
@@ -398,7 +394,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
if (s->ar_flip_flop == 0) {
val &= 0x3f;
s->ar_index = val;
- vga_update_resolution(s);
} else {
index = s->ar_index & 0x1f;
switch(index) {
@@ -439,7 +434,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
#endif
s->sr[s->sr_index] = val & sr_mask[s->sr_index];
if (s->sr_index == 1) s->update_retrace_info(s);
- vga_update_resolution(s);
break;
case 0x3c7:
s->dac_read_index = val;
@@ -467,7 +461,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
#endif
s->gr[s->gr_index] = val & gr_mask[s->gr_index];
- vga_update_resolution(s);
break;
case 0x3b4:
case 0x3d4:
@@ -483,7 +476,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
/* can always write bit 4 of CR7 */
if (s->cr_index == 7)
s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
- vga_update_resolution(s);
return;
}
switch(s->cr_index) {
@@ -511,7 +503,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
s->update_retrace_info(s);
break;
}
- vga_update_resolution(s);
break;
case 0x3ba:
case 0x3da:
@@ -591,13 +582,11 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
s->vbe_regs[s->vbe_index] = val;
}
- vga_update_resolution(s);
break;
case VBE_DISPI_INDEX_YRES:
if (val <= VBE_DISPI_MAX_YRES) {
s->vbe_regs[s->vbe_index] = val;
}
- vga_update_resolution(s);
break;
case VBE_DISPI_INDEX_BPP:
if (val == 0)
@@ -606,7 +595,6 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
val == 16 || val == 24 || val == 32) {
s->vbe_regs[s->vbe_index] = val;
}
- vga_update_resolution(s);
break;
case VBE_DISPI_INDEX_BANK:
if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
@@ -675,7 +663,6 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
}
s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
s->vbe_regs[s->vbe_index] = val;
- vga_update_resolution(s);
break;
case VBE_DISPI_INDEX_VIRT_WIDTH:
{
@@ -696,7 +683,6 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
s->vbe_line_offset = line_offset;
}
- vga_update_resolution(s);
break;
case VBE_DISPI_INDEX_X_OFFSET:
case VBE_DISPI_INDEX_Y_OFFSET:
@@ -711,7 +697,6 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
s->vbe_start_addr >>= 2;
}
- vga_update_resolution(s);
break;
default:
break;
@@ -1318,6 +1303,7 @@ static void vga_draw_text(VGAState *s, int full_update)
s->plane_updated = 0;
full_update = 1;
}
+ full_update |= update_basic_params(s);
line_offset = s->line_offset;
s1 = s->vram_ptr + (s->start_addr * 4);
@@ -1329,6 +1315,18 @@ static void vga_draw_text(VGAState *s, int full_update)
return;
}
+ if (width != s->last_width || height != s->last_height ||
+ cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
+ s->last_scr_width = width * cw;
+ s->last_scr_height = height * cheight;
+ qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
+ s->last_depth = 0;
+ s->last_width = width;
+ s->last_height = height;
+ s->last_ch = cheight;
+ s->last_cw = cw;
+ full_update = 1;
+ }
s->rgb_to_pixel =
rgb_to_pixel_dup_table[get_depth_index(s->ds)];
full_update |= update_palette16(s);
@@ -1585,21 +1583,39 @@ static void vga_sync_dirty_bitmap(VGAState *s)
vga_dirty_log_start(s);
}
-static void vga_update_resolution_graphics(VGAState *s)
+/*
+ * graphic modes
+ */
+static void vga_draw_graphic(VGAState *s, int full_update)
{
- int depth = s->get_bpp(s);
- int width, height, shift_control, double_scan;
+ int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask, depth;
+ int width, height, shift_control, line_offset, page0, page1, bwidth, bits;
int disp_width, multi_scan, multi_run;
+ uint8_t *d;
+ uint32_t v, addr1, addr;
+ vga_draw_line_func *vga_draw_line;
+
+ full_update |= update_basic_params(s);
+
+ if (!full_update)
+ vga_sync_dirty_bitmap(s);
s->get_resolution(s, &width, &height);
disp_width = width;
shift_control = (s->gr[0x05] >> 5) & 3;
double_scan = (s->cr[0x09] >> 7);
-
+ if (shift_control != 1) {
+ multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
+ } else {
+ /* in CGA modes, multi_scan is ignored */
+ /* XXX: is it correct ? */
+ multi_scan = double_scan;
+ }
+ multi_run = multi_scan;
if (shift_control != s->shift_control ||
double_scan != s->double_scan) {
- s->want_full_update = 1;
+ full_update = 1;
s->shift_control = shift_control;
s->double_scan = double_scan;
}
@@ -1613,28 +1629,12 @@ static void vga_update_resolution_graphics(VGAState *s)
disp_width <<= 1;
}
}
- disp_width = width;
-
- if (shift_control != 1) {
- multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
- } else {
- /* in CGA modes, multi_scan is ignored */
- /* XXX: is it correct ? */
- multi_scan = double_scan;
- }
-
- multi_run = multi_scan;
+ depth = s->get_bpp(s);
if (s->line_offset != s->last_line_offset ||
disp_width != s->last_width ||
height != s->last_height ||
- s->last_depth != depth ||
- s->multi_run != multi_run ||
- s->multi_scan != multi_scan ||
- s->want_full_update) {
- if (s->ds->surface->pf.depth == 0) {
- goto dont_touch_display_surface;
- }
+ s->last_depth != depth) {
#if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
if (depth == 16 || depth == 32) {
#else
@@ -1651,91 +1651,14 @@ static void vga_update_resolution_graphics(VGAState *s)
} else {
qemu_console_resize(s->ds, disp_width, height);
}
- dont_touch_display_surface:
s->last_scr_width = disp_width;
s->last_scr_height = height;
s->last_width = disp_width;
s->last_height = height;
s->last_line_offset = s->line_offset;
s->last_depth = depth;
- s->multi_run = multi_run;
- s->multi_scan = multi_scan;
- s->want_full_update = 1;
- }
-}
-
-static void vga_update_resolution_text(VGAState *s)
-{
- int width, height, cw, cheight;
-
- vga_get_text_resolution(s, &width, &height, &cw, &cheight);
- if (width != s->last_width || height != s->last_height ||
- cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
- s->last_scr_width = width * cw;
- s->last_scr_height = height * cheight;
- if (s->ds->surface->pf.depth != 0) {
- qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
- } else {
- /*
- * curses expects width and height to be in character cell
- * dimensions, not pixels.
- */
- s->ds->surface->width = width;
- s->ds->surface->height = height;
- dpy_resize(s->ds);
- }
- s->last_depth = 0;
- s->last_width = width;
- s->last_height = height;
- s->last_ch = cheight;
- s->last_cw = cw;
- s->want_full_update = 1;
- }
-}
-
-void vga_update_resolution(VGAState *s)
-{
- int graphic_mode;
-
- if (!(s->ar_index & 0x20)) {
- graphic_mode = GMODE_BLANK;
- } else {
- graphic_mode = s->gr[6] & 1;
- }
- if (graphic_mode != s->graphic_mode) {
- s->graphic_mode = graphic_mode;
- s->want_full_update = 1;
- }
- s->want_full_update |= update_basic_params(s);
- switch (graphic_mode) {
- case GMODE_TEXT:
- vga_update_resolution_text(s);
- break;
- case GMODE_GRAPH:
- vga_update_resolution_graphics(s);
- break;
- }
-}
-
-/*
- * graphic modes
- */
-static void vga_draw_graphic(VGAState *s, int full_update)
-{
- int y1, y, update, linesize, y_start, mask;
- int width, height, line_offset, bwidth, bits;
- int multi_run;
- uint8_t *d;
- uint32_t v, addr1, addr;
- long page0, page1, page_min, page_max;
- vga_draw_line_func *vga_draw_line;
-
- if (!full_update)
- vga_sync_dirty_bitmap(s);
-
- s->get_resolution(s, &width, &height);
- multi_run = s->multi_run;
- if (is_buffer_shared(s->ds->surface) &&
+ full_update = 1;
+ } else if (is_buffer_shared(s->ds->surface) &&
(full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
dpy_setdata(s->ds);
@@ -1744,7 +1667,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
s->rgb_to_pixel =
rgb_to_pixel_dup_table[get_depth_index(s->ds)];
- if (s->shift_control == 0) {
+ if (shift_control == 0) {
full_update |= update_palette16(s);
if (s->sr[0x01] & 8) {
v = VGA_DRAW_LINE4D2;
@@ -1752,7 +1675,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
v = VGA_DRAW_LINE4;
}
bits = 4;
- } else if (s->shift_control == 1) {
+ } else if (shift_control == 1) {
full_update |= update_palette16(s);
if (s->sr[0x01] & 8) {
v = VGA_DRAW_LINE2D2;
@@ -1848,7 +1771,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
if (y_start >= 0) {
/* flush to display */
dpy_update(s->ds, 0, y_start,
- s->last_width, y - y_start);
+ disp_width, y - y_start);
y_start = -1;
}
}
@@ -1857,7 +1780,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
if ((y1 & mask) == mask)
addr1 += line_offset;
y1++;
- multi_run = s->multi_scan;
+ multi_run = multi_scan;
} else {
multi_run--;
}
@@ -1869,7 +1792,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
if (y_start >= 0) {
/* flush to display */
dpy_update(s->ds, 0, y_start,
- s->last_width, y - y_start);
+ disp_width, y - y_start);
}
/* reset modified pages */
if (page_max != -1) {
@@ -1906,17 +1829,29 @@ static void vga_draw_blank(VGAState *s, int full_update)
s->last_scr_width, s->last_scr_height);
}
+#define GMODE_TEXT 0
+#define GMODE_GRAPH 1
+#define GMODE_BLANK 2
+
static void vga_update_display(void *opaque)
{
VGAState *s = (VGAState *)opaque;
- int full_update;
+ int full_update, graphic_mode;
if (ds_get_bits_per_pixel(s->ds) == 0) {
/* nothing to do */
} else {
- full_update = s->want_full_update;
- s->want_full_update = 0;
- switch(s->graphic_mode) {
+ full_update = 0;
+ if (!(s->ar_index & 0x20)) {
+ graphic_mode = GMODE_BLANK;
+ } else {
+ graphic_mode = s->gr[6] & 1;
+ }
+ if (graphic_mode != s->graphic_mode) {
+ s->graphic_mode = graphic_mode;
+ full_update = 1;
+ }
+ switch(graphic_mode) {
case GMODE_TEXT:
vga_draw_text(s, full_update);
break;
@@ -1939,8 +1874,8 @@ static void vga_invalidate_display(void *opaque)
{
VGAState *s = (VGAState *)opaque;
- vga_update_resolution(s);
- s->want_full_update = 1;
+ s->last_width = -1;
+ s->last_height = -1;
}
void vga_reset(void *opaque)
@@ -1984,6 +1919,7 @@ void vga_reset(void *opaque)
s->vbe_bank_mask = (s->vram_size >> 16) - 1;
#endif
memset(s->font_offsets, '\0', sizeof(s->font_offsets));
+ s->graphic_mode = -1; /* force full update */
s->shift_control = 0;
s->double_scan = 0;
s->line_offset = 0;
@@ -2009,7 +1945,6 @@ void vga_reset(void *opaque)
memset(&s->retrace_info, 0, sizeof (s->retrace_info));
break;
}
- vga_update_resolution(s);
}
#define TEXTMODE_X(x) ((x) % width)
@@ -2021,28 +1956,50 @@ void vga_reset(void *opaque)
static void vga_update_text(void *opaque, console_ch_t *chardata)
{
VGAState *s = (VGAState *) opaque;
- int i, cursor_offset, cursor_visible;
+ int graphic_mode, i, cursor_offset, cursor_visible;
int cw, cheight, width, height, size, c_min, c_max;
uint32_t *src;
console_ch_t *dst, val;
char msg_buffer[80];
- int full_update = s->want_full_update;
+ int full_update = 0;
+
+ if (!(s->ar_index & 0x20)) {
+ graphic_mode = GMODE_BLANK;
+ } else {
+ graphic_mode = s->gr[6] & 1;
+ }
+ if (graphic_mode != s->graphic_mode) {
+ s->graphic_mode = graphic_mode;
+ full_update = 1;
+ }
+ if (s->last_width == -1) {
+ s->last_width = 0;
+ full_update = 1;
+ }
- s->want_full_update = 0;
- switch (s->graphic_mode) {
+ switch (graphic_mode) {
case GMODE_TEXT:
/* TODO: update palette */
+ full_update |= update_basic_params(s);
- vga_get_text_resolution(s, &width, &height, &cw, &cheight);
-
- if (s->ds->surface->width != width
- || s->ds->surface->height != height) {
- s->ds->surface->width = width;
- s->ds->surface->height = height;
- dpy_resize(s->ds);
+ /* total width & height */
+ cheight = (s->cr[9] & 0x1f) + 1;
+ cw = 8;
+ if (!(s->sr[1] & 0x01))
+ cw = 9;
+ if (s->sr[1] & 0x08)
+ cw = 16; /* NOTE: no 18 pixel wide */
+ width = (s->cr[0x01] + 1);
+ if (s->cr[0x06] == 100) {
+ /* ugly hack for CGA 160x100x16 - explain me the logic */
+ height = 100;
+ } else {
+ height = s->cr[0x12] |
+ ((s->cr[0x07] & 0x02) << 7) |
+ ((s->cr[0x07] & 0x40) << 3);
+ height = (height + 1) / cheight;
}
- /* total width & height */
size = (height * width);
if (size > CH_ATTR_SIZE) {
if (!full_update)
@@ -2053,6 +2010,20 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
break;
}
+ if (width != s->last_width || height != s->last_height ||
+ cw != s->last_cw || cheight != s->last_ch) {
+ s->last_scr_width = width * cw;
+ s->last_scr_height = height * cheight;
+ s->ds->surface->width = width;
+ s->ds->surface->height = height;
+ dpy_resize(s->ds);
+ s->last_width = width;
+ s->last_height = height;
+ s->last_ch = cheight;
+ s->last_cw = cw;
+ full_update = 1;
+ }
+
/* Update "hardware" cursor */
cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
if (cursor_offset != s->cursor_offset ||
@@ -2251,8 +2222,7 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id)
#endif
/* force refresh */
- vga_update_resolution(s);
- s->want_full_update = 1;
+ s->graphic_mode = -1;
return 0;
}
@@ -2834,8 +2804,7 @@ static void vga_screen_dump_common(VGAState *s, const char *filename,
ds->surface = qemu_create_displaysurface(ds, w, h);
s->ds = ds;
- vga_update_resolution(s);
- s->want_full_update = 1;
+ s->graphic_mode = -1;
vga_update_display(s);
ppm_save(filename, ds->surface);
@@ -2866,16 +2835,11 @@ static void vga_screen_dump(void *opaque, const char *filename)
{
VGAState *s = (VGAState *)opaque;
- switch (s->graphic_mode) {
- case GMODE_TEXT:
- vga_screen_dump_text(s, filename);
- break;
- case GMODE_GRAPH:
- vga_screen_dump_graphic(s, filename);
- break;
- case GMODE_BLANK:
- default:
+ if (!(s->ar_index & 0x20))
vga_screen_dump_blank(s, filename);
- break;
- }
+ else if (s->gr[6] & 1)
+ vga_screen_dump_graphic(s, filename);
+ else
+ vga_screen_dump_text(s, filename);
+ vga_invalidate_display(s);
}
diff --git a/hw/vga_int.h b/hw/vga_int.h
index 71ffeb569..8ba8a60f2 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -147,11 +147,8 @@ typedef void (* vga_update_retrace_info_fn)(struct VGAState *s);
DisplayState *ds; \
uint32_t font_offsets[2]; \
int graphic_mode; \
- int want_full_update; \
uint8_t shift_control; \
uint8_t double_scan; \
- uint8_t multi_run; \
- uint8_t multi_scan; \
uint32_t line_offset; \
uint32_t line_compare; \
uint32_t start_addr; \
@@ -198,7 +195,6 @@ void vga_common_init(VGAState *s, uint8_t *vga_ram_base,
ram_addr_t vga_ram_offset, int vga_ram_size);
void vga_init(VGAState *s);
void vga_reset(void *s);
-void vga_update_resolution(VGAState *s);
void vga_dirty_log_start(VGAState *s);
void vga_dirty_log_stop(VGAState *s);
diff --git a/hw/wm8750.c b/hw/wm8750.c
index e5324ec41..02d5f5e5b 100644
--- a/hw/wm8750.c
+++ b/hw/wm8750.c
@@ -706,7 +706,7 @@ void wm8750_dac_commit(void *opaque)
{
struct wm8750_s *s = (struct wm8750_s *) opaque;
- return wm8750_out_flush(s);
+ wm8750_out_flush(s);
}
uint32_t wm8750_adc_dat(void *opaque)
diff --git a/posix-aio-compat.c b/posix-aio-compat.c
index 65c80ecc3..c7fdac70b 100644
--- a/posix-aio-compat.c
+++ b/posix-aio-compat.c
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <stdio.h>
#include "osdep.h"
+#include "qemu-common.h"
#include "posix-aio-compat.h"
@@ -32,6 +33,12 @@ static int cur_threads = 0;
static int idle_threads = 0;
static TAILQ_HEAD(, qemu_paiocb) request_list;
+#ifdef HAVE_PREADV
+static int preadv_present = 1;
+#else
+static int preadv_present = 0;
+#endif
+
static void die2(int err, const char *what)
{
fprintf(stderr, "%s failed: %s\n", what, strerror(err));
@@ -76,45 +83,185 @@ static void thread_create(pthread_t *thread, pthread_attr_t *attr,
if (ret) die2(ret, "pthread_create");
}
-static size_t handle_aiocb_readwrite(struct qemu_paiocb *aiocb)
+static size_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb)
+{
+ int ret;
+
+ ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_ioctl_buf);
+ if (ret == -1)
+ return -errno;
+ return ret;
+}
+
+#ifdef HAVE_PREADV
+
+static ssize_t
+qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+ return preadv(fd, iov, nr_iov, offset);
+}
+
+static ssize_t
+qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+ return pwritev(fd, iov, nr_iov, offset);
+}
+
+#else
+
+static ssize_t
+qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+ return -ENOSYS;
+}
+
+static ssize_t
+qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+ return -ENOSYS;
+}
+
+#endif
+
+/*
+ * Check if we need to copy the data in the aiocb into a new
+ * properly aligned buffer.
+ */
+static int aiocb_needs_copy(struct qemu_paiocb *aiocb)
+{
+ if (aiocb->aio_flags & QEMU_AIO_SECTOR_ALIGNED) {
+ int i;
+
+ for (i = 0; i < aiocb->aio_niov; i++)
+ if ((uintptr_t) aiocb->aio_iov[i].iov_base % 512)
+ return 1;
+ }
+
+ return 0;
+}
+
+static size_t handle_aiocb_rw_vector(struct qemu_paiocb *aiocb)
{
size_t offset = 0;
ssize_t len;
- while (offset < aiocb->aio_nbytes) {
+ do {
if (aiocb->aio_type == QEMU_PAIO_WRITE)
- len = pwrite(aiocb->aio_fildes,
- (const char *)aiocb->aio_buf + offset,
+ len = qemu_pwritev(aiocb->aio_fildes,
+ aiocb->aio_iov,
+ aiocb->aio_niov,
+ aiocb->aio_offset + offset);
+ else
+ len = qemu_preadv(aiocb->aio_fildes,
+ aiocb->aio_iov,
+ aiocb->aio_niov,
+ aiocb->aio_offset + offset);
+ } while (len == -1 && errno == EINTR);
+
+ if (len == -1)
+ return -errno;
+ return len;
+}
+
+static size_t handle_aiocb_rw_linear(struct qemu_paiocb *aiocb, char *buf)
+{
+ size_t offset = 0;
+ size_t len;
+
+ while (offset < aiocb->aio_nbytes) {
+ if (aiocb->aio_type == QEMU_PAIO_WRITE)
+ len = pwrite(aiocb->aio_fildes,
+ (const char *)buf + offset,
+ aiocb->aio_nbytes - offset,
+ aiocb->aio_offset + offset);
+ else
+ len = pread(aiocb->aio_fildes,
+ buf + offset,
aiocb->aio_nbytes - offset,
aiocb->aio_offset + offset);
- else
- len = pread(aiocb->aio_fildes,
- (char *)aiocb->aio_buf + offset,
- aiocb->aio_nbytes - offset,
- aiocb->aio_offset + offset);
-
- if (len == -1 && errno == EINTR)
- continue;
- else if (len == -1) {
- offset = -errno;
- break;
- } else if (len == 0)
- break;
- offset += len;
+ if (len == -1 && errno == EINTR)
+ continue;
+ else if (len == -1) {
+ offset = -errno;
+ break;
+ } else if (len == 0)
+ break;
+
+ offset += len;
}
return offset;
}
-static size_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb)
+static size_t handle_aiocb_rw(struct qemu_paiocb *aiocb)
{
- int ret;
+ size_t nbytes;
+ char *buf;
+
+ if (!aiocb_needs_copy(aiocb)) {
+ /*
+ * If there is just a single buffer, and it is properly aligned
+ * we can just use plain pread/pwrite without any problems.
+ */
+ if (aiocb->aio_niov == 1)
+ return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base);
+
+ /*
+ * We have more than one iovec, and all are properly aligned.
+ *
+ * Try preadv/pwritev first and fall back to linearizing the
+ * buffer if it's not supported.
+ */
+ if (preadv_present) {
+ nbytes = handle_aiocb_rw_vector(aiocb);
+ if (nbytes == aiocb->aio_nbytes)
+ return nbytes;
+ if (nbytes < 0 && nbytes != -ENOSYS)
+ return nbytes;
+ preadv_present = 0;
+ }
- ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_buf);
- if (ret == -1)
- return -errno;
- return ret;
+ /*
+ * XXX(hch): short read/write. no easy way to handle the reminder
+ * using these interfaces. For now retry using plain
+ * pread/pwrite?
+ */
+ }
+
+ /*
+ * Ok, we have to do it the hard way, copy all segments into
+ * a single aligned buffer.
+ */
+ buf = qemu_memalign(512, aiocb->aio_nbytes);
+ if (aiocb->aio_type == QEMU_PAIO_WRITE) {
+ char *p = buf;
+ int i;
+
+ for (i = 0; i < aiocb->aio_niov; ++i) {
+ memcpy(p, aiocb->aio_iov[i].iov_base, aiocb->aio_iov[i].iov_len);
+ p += aiocb->aio_iov[i].iov_len;
+ }
+ }
+
+ nbytes = handle_aiocb_rw_linear(aiocb, buf);
+ if (aiocb->aio_type != QEMU_PAIO_WRITE) {
+ char *p = buf;
+ size_t count = aiocb->aio_nbytes, copy;
+ int i;
+
+ for (i = 0; i < aiocb->aio_niov && count; ++i) {
+ copy = count;
+ if (copy > aiocb->aio_iov[i].iov_len)
+ copy = aiocb->aio_iov[i].iov_len;
+ memcpy(aiocb->aio_iov[i].iov_base, p, copy);
+ p += copy;
+ count -= copy;
+ }
+ }
+ qemu_vfree(buf);
+
+ return nbytes;
}
static void *aio_thread(void *unused)
@@ -157,7 +304,7 @@ static void *aio_thread(void *unused)
switch (aiocb->aio_type) {
case QEMU_PAIO_READ:
case QEMU_PAIO_WRITE:
- ret = handle_aiocb_readwrite(aiocb);
+ ret = handle_aiocb_rw(aiocb);
break;
case QEMU_PAIO_IOCTL:
ret = handle_aiocb_ioctl(aiocb);
diff --git a/posix-aio-compat.h b/posix-aio-compat.h
index a1cdfd7f1..1c5dcbd92 100644
--- a/posix-aio-compat.h
+++ b/posix-aio-compat.h
@@ -27,11 +27,18 @@
struct qemu_paiocb
{
int aio_fildes;
- void *aio_buf;
+ union {
+ struct iovec *aio_iov;
+ void *aio_ioctl_buf;
+ };
+ int aio_niov;
size_t aio_nbytes;
#define aio_ioctl_cmd aio_nbytes /* for QEMU_PAIO_IOCTL */
int ev_signo;
off_t aio_offset;
+ unsigned aio_flags;
+/* 512 byte alignment required for buffer, offset and length */
+#define QEMU_AIO_SECTOR_ALIGNED 0x01
/* private */
TAILQ_ENTRY(qemu_paiocb) node;
diff --git a/target-mips/helper.h b/target-mips/helper.h
index e44657837..b8ec15eab 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -15,11 +15,11 @@ DEF_HELPER_3(lwr, tl, tl, tl, int)
DEF_HELPER_3(swl, void, tl, tl, int)
DEF_HELPER_3(swr, void, tl, tl, int)
-DEF_HELPER_1(clo, tl, tl)
-DEF_HELPER_1(clz, tl, tl)
+DEF_HELPER_FLAGS_1(clo, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(clz, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
#ifdef TARGET_MIPS64
-DEF_HELPER_1(dclo, tl, tl)
-DEF_HELPER_1(dclz, tl, tl)
+DEF_HELPER_FLAGS_1(dclo, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(dclz, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
DEF_HELPER_2(dmult, void, tl, tl)
DEF_HELPER_2(dmultu, void, tl, tl)
#endif
diff --git a/tcg/tcg.c b/tcg/tcg.c
index e5508507e..c64043f69 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1122,9 +1122,11 @@ static void tcg_liveness_analysis(TCGContext *s)
dead_temps[arg] = 1;
}
- /* globals are live (they may be used by the call) */
- memset(dead_temps, 0, s->nb_globals);
-
+ if (!(call_flags & TCG_CALL_CONST)) {
+ /* globals are live (they may be used by the call) */
+ memset(dead_temps, 0, s->nb_globals);
+ }
+
/* input args are live */
dead_iargs = 0;
for(i = 0; i < nb_iargs; i++) {
@@ -1821,7 +1823,9 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
/* store globals and free associated registers (we assume the call
can modify any global. */
- save_globals(s, allocated_regs);
+ if (!(flags & TCG_CALL_CONST)) {
+ save_globals(s, allocated_regs);
+ }
tcg_out_op(s, opc, &func_arg, &const_func_arg);
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 1ffeca6e6..bf95d7e49 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -174,10 +174,14 @@ typedef int TCGv_i64;
#define TCG_CALL_TYPE_REGPARM_1 0x0001 /* i386 style regparm call (1 reg) */
#define TCG_CALL_TYPE_REGPARM_2 0x0002 /* i386 style regparm call (2 regs) */
#define TCG_CALL_TYPE_REGPARM 0x0003 /* i386 style regparm call (3 regs) */
-/* A pure function only reads its arguments and globals variables and
- cannot raise exceptions. Hence a call to a pure function can be
+/* A pure function only reads its arguments and TCG global variables
+ and cannot raise exceptions. Hence a call to a pure function can be
safely suppressed if the return value is not used. */
#define TCG_CALL_PURE 0x0010
+/* A const function only reads its arguments and does not use TCG
+ global variables. Hence a call to such a function does not
+ save TCG global variables back to their canonical location. */
+#define TCG_CALL_CONST 0x0020
/* used to align parameters */
#define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1)
diff --git a/vnc.c b/vnc.c
index 6d9321584..ab1f04448 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1598,7 +1598,7 @@ static void pixel_format_message (VncState *vs) {
else if (vs->ds->surface->pf.bits_per_pixel == 8)
vs->send_hextile_tile = send_hextile_tile_8;
vs->clientds = *(vs->ds->surface);
- vs->clientds.flags |= ~QEMU_ALLOCATED_FLAG;
+ vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG;
vs->write_pixels = vnc_write_pixels_copy;
vnc_write(vs, pad, 3); /* padding */