Compare commits
67 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c0b1a7e207 | ||
|
4f8dca7333 | ||
|
88cc6975fe | ||
|
91f92915f9 | ||
|
9975e9916e | ||
|
58ef8c530c | ||
|
8d676daf6d | ||
|
6bf6fcd181 | ||
|
ccf279824c | ||
|
30c2463271 | ||
|
d55fc47517 | ||
|
82487399a4 | ||
|
4055390051 | ||
|
ca73e42f6d | ||
|
7f91e37c5a | ||
|
0b85017dfc | ||
|
6499aa6dcc | ||
|
283d8f93e5 | ||
|
a3ea885abd | ||
|
bb4d73c44b | ||
|
8707cd1ec0 | ||
|
2b7e5f19dc | ||
|
27c59dad11 | ||
|
390880f3d3 | ||
|
f3249bf62c | ||
|
a95bc779f2 | ||
|
a561fcfed6 | ||
|
685803fcf7 | ||
|
32d1d7ff51 | ||
|
f823845309 | ||
|
7fbd2301a4 | ||
|
404fbe4743 | ||
|
ff57f145c1 | ||
|
e6f5128dcf | ||
|
aa83f2e427 | ||
|
a5d14facb1 | ||
|
9f8daa796b | ||
|
ed448b82bd | ||
|
f8cd6dfdd8 | ||
|
b5bfb026e4 | ||
|
cbf70c2f27 | ||
|
0320902109 | ||
|
7d4d902a59 | ||
|
91d66fb4b9 | ||
|
39b04be6ad | ||
|
1eeacd413a | ||
|
f7fe3d2f77 | ||
|
9f60383b41 | ||
|
64a72fa71f | ||
|
d306fd5f4a | ||
|
eedc9f46cf | ||
|
90ce84993a | ||
|
89ca606d49 | ||
|
5e2053dd15 | ||
|
045ccf7056 | ||
|
820508eea6 | ||
|
1e3043a702 | ||
|
a678b16bb3 | ||
|
208ddea6b5 | ||
|
4bf0901ff8 | ||
|
717086d0e8 | ||
|
ff4be47d1b | ||
|
be161ae35d | ||
|
bb31546dfa | ||
|
af0bbf8eb8 | ||
|
31c6ed2077 | ||
|
c432c7d85a |
27
arch_init.c
27
arch_init.c
@@ -457,15 +457,10 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
|
|||||||
bytes_sent = -1;
|
bytes_sent = -1;
|
||||||
if (is_zero_page(p)) {
|
if (is_zero_page(p)) {
|
||||||
acct_info.dup_pages++;
|
acct_info.dup_pages++;
|
||||||
if (!ram_bulk_stage) {
|
bytes_sent = save_block_hdr(f, block, offset, cont,
|
||||||
bytes_sent = save_block_hdr(f, block, offset, cont,
|
RAM_SAVE_FLAG_COMPRESS);
|
||||||
RAM_SAVE_FLAG_COMPRESS);
|
qemu_put_byte(f, 0);
|
||||||
qemu_put_byte(f, 0);
|
bytes_sent++;
|
||||||
bytes_sent++;
|
|
||||||
} else {
|
|
||||||
acct_info.skipped_pages++;
|
|
||||||
bytes_sent = 0;
|
|
||||||
}
|
|
||||||
} else if (!ram_bulk_stage && migrate_use_xbzrle()) {
|
} else if (!ram_bulk_stage && migrate_use_xbzrle()) {
|
||||||
current_addr = block->offset + offset;
|
current_addr = block->offset + offset;
|
||||||
bytes_sent = save_xbzrle_page(f, p, current_addr, block,
|
bytes_sent = save_xbzrle_page(f, p, current_addr, block,
|
||||||
@@ -837,14 +832,16 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ch = qemu_get_byte(f);
|
ch = qemu_get_byte(f);
|
||||||
memset(host, ch, TARGET_PAGE_SIZE);
|
if (ch != 0 || !is_zero_page(host)) {
|
||||||
|
memset(host, ch, TARGET_PAGE_SIZE);
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
if (ch == 0 &&
|
if (ch == 0 &&
|
||||||
(!kvm_enabled() || kvm_has_sync_mmu()) &&
|
(!kvm_enabled() || kvm_has_sync_mmu()) &&
|
||||||
getpagesize() <= TARGET_PAGE_SIZE) {
|
getpagesize() <= TARGET_PAGE_SIZE) {
|
||||||
qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
|
qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
} else if (flags & RAM_SAVE_FLAG_PAGE) {
|
} else if (flags & RAM_SAVE_FLAG_PAGE) {
|
||||||
void *host;
|
void *host;
|
||||||
|
|
||||||
|
15
block.c
15
block.c
@@ -1349,11 +1349,12 @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state)
|
|||||||
|
|
||||||
void bdrv_close(BlockDriverState *bs)
|
void bdrv_close(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
bdrv_flush(bs);
|
|
||||||
if (bs->job) {
|
if (bs->job) {
|
||||||
block_job_cancel_sync(bs->job);
|
block_job_cancel_sync(bs->job);
|
||||||
}
|
}
|
||||||
bdrv_drain_all();
|
bdrv_drain_all(); /* complete I/O */
|
||||||
|
bdrv_flush(bs);
|
||||||
|
bdrv_drain_all(); /* in case flush left pending I/O */
|
||||||
notifier_list_notify(&bs->close_notifiers, bs);
|
notifier_list_notify(&bs->close_notifiers, bs);
|
||||||
|
|
||||||
if (bs->drv) {
|
if (bs->drv) {
|
||||||
@@ -2906,13 +2907,19 @@ int bdrv_get_flags(BlockDriverState *bs)
|
|||||||
return bs->open_flags;
|
return bs->open_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bdrv_flush_all(void)
|
int bdrv_flush_all(void)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
QTAILQ_FOREACH(bs, &bdrv_states, list) {
|
QTAILQ_FOREACH(bs, &bdrv_states, list) {
|
||||||
bdrv_flush(bs);
|
int ret = bdrv_flush(bs);
|
||||||
|
if (ret < 0 && !result) {
|
||||||
|
result = ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdrv_has_zero_init(BlockDriverState *bs)
|
int bdrv_has_zero_init(BlockDriverState *bs)
|
||||||
|
@@ -574,6 +574,12 @@ static void qemu_gluster_close(BlockDriverState *bs)
|
|||||||
glfs_fini(s->glfs);
|
glfs_fini(s->glfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qemu_gluster_has_zero_init(BlockDriverState *bs)
|
||||||
|
{
|
||||||
|
/* GlusterFS volume could be backed by a block device */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static QEMUOptionParameter qemu_gluster_create_options[] = {
|
static QEMUOptionParameter qemu_gluster_create_options[] = {
|
||||||
{
|
{
|
||||||
.name = BLOCK_OPT_SIZE,
|
.name = BLOCK_OPT_SIZE,
|
||||||
@@ -595,6 +601,7 @@ static BlockDriver bdrv_gluster = {
|
|||||||
.bdrv_aio_readv = qemu_gluster_aio_readv,
|
.bdrv_aio_readv = qemu_gluster_aio_readv,
|
||||||
.bdrv_aio_writev = qemu_gluster_aio_writev,
|
.bdrv_aio_writev = qemu_gluster_aio_writev,
|
||||||
.bdrv_aio_flush = qemu_gluster_aio_flush,
|
.bdrv_aio_flush = qemu_gluster_aio_flush,
|
||||||
|
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
|
||||||
.create_options = qemu_gluster_create_options,
|
.create_options = qemu_gluster_create_options,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -610,6 +617,7 @@ static BlockDriver bdrv_gluster_tcp = {
|
|||||||
.bdrv_aio_readv = qemu_gluster_aio_readv,
|
.bdrv_aio_readv = qemu_gluster_aio_readv,
|
||||||
.bdrv_aio_writev = qemu_gluster_aio_writev,
|
.bdrv_aio_writev = qemu_gluster_aio_writev,
|
||||||
.bdrv_aio_flush = qemu_gluster_aio_flush,
|
.bdrv_aio_flush = qemu_gluster_aio_flush,
|
||||||
|
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
|
||||||
.create_options = qemu_gluster_create_options,
|
.create_options = qemu_gluster_create_options,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -625,6 +633,7 @@ static BlockDriver bdrv_gluster_unix = {
|
|||||||
.bdrv_aio_readv = qemu_gluster_aio_readv,
|
.bdrv_aio_readv = qemu_gluster_aio_readv,
|
||||||
.bdrv_aio_writev = qemu_gluster_aio_writev,
|
.bdrv_aio_writev = qemu_gluster_aio_writev,
|
||||||
.bdrv_aio_flush = qemu_gluster_aio_flush,
|
.bdrv_aio_flush = qemu_gluster_aio_flush,
|
||||||
|
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
|
||||||
.create_options = qemu_gluster_create_options,
|
.create_options = qemu_gluster_create_options,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -640,6 +649,7 @@ static BlockDriver bdrv_gluster_rdma = {
|
|||||||
.bdrv_aio_readv = qemu_gluster_aio_readv,
|
.bdrv_aio_readv = qemu_gluster_aio_readv,
|
||||||
.bdrv_aio_writev = qemu_gluster_aio_writev,
|
.bdrv_aio_writev = qemu_gluster_aio_writev,
|
||||||
.bdrv_aio_flush = qemu_gluster_aio_flush,
|
.bdrv_aio_flush = qemu_gluster_aio_flush,
|
||||||
|
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
|
||||||
.create_options = qemu_gluster_create_options,
|
.create_options = qemu_gluster_create_options,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include "block/block_int.h"
|
#include "block/block_int.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "block/scsi.h"
|
#include "block/scsi.h"
|
||||||
|
#include "qemu/iov.h"
|
||||||
|
|
||||||
#include <iscsi/iscsi.h>
|
#include <iscsi/iscsi.h>
|
||||||
#include <iscsi/scsi-lowlevel.h>
|
#include <iscsi/scsi-lowlevel.h>
|
||||||
@@ -61,8 +62,6 @@ typedef struct IscsiAIOCB {
|
|||||||
int status;
|
int status;
|
||||||
int canceled;
|
int canceled;
|
||||||
int retries;
|
int retries;
|
||||||
size_t read_size;
|
|
||||||
size_t read_offset;
|
|
||||||
int64_t sector_num;
|
int64_t sector_num;
|
||||||
int nb_sectors;
|
int nb_sectors;
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@@ -238,6 +237,18 @@ static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
|
|||||||
return sector * BDRV_SECTOR_SIZE / iscsilun->block_size;
|
return sector * BDRV_SECTOR_SIZE / iscsilun->block_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_request_lun_aligned(int64_t sector_num, int nb_sectors,
|
||||||
|
IscsiLun *iscsilun)
|
||||||
|
{
|
||||||
|
if ((sector_num * BDRV_SECTOR_SIZE) % iscsilun->block_size ||
|
||||||
|
(nb_sectors * BDRV_SECTOR_SIZE) % iscsilun->block_size) {
|
||||||
|
error_report("iSCSI misaligned request: iscsilun->block_size %u, sector_num %ld, nb_sectors %d",
|
||||||
|
iscsilun->block_size, sector_num, nb_sectors);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
iscsi_aio_writev_acb(IscsiAIOCB *acb)
|
iscsi_aio_writev_acb(IscsiAIOCB *acb)
|
||||||
{
|
{
|
||||||
@@ -322,6 +333,10 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
|
|||||||
IscsiLun *iscsilun = bs->opaque;
|
IscsiLun *iscsilun = bs->opaque;
|
||||||
IscsiAIOCB *acb;
|
IscsiAIOCB *acb;
|
||||||
|
|
||||||
|
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
|
acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
|
||||||
trace_iscsi_aio_writev(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb);
|
trace_iscsi_aio_writev(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb);
|
||||||
|
|
||||||
@@ -379,6 +394,7 @@ static int
|
|||||||
iscsi_aio_readv_acb(IscsiAIOCB *acb)
|
iscsi_aio_readv_acb(IscsiAIOCB *acb)
|
||||||
{
|
{
|
||||||
struct iscsi_context *iscsi = acb->iscsilun->iscsi;
|
struct iscsi_context *iscsi = acb->iscsilun->iscsi;
|
||||||
|
size_t size;
|
||||||
uint64_t lba;
|
uint64_t lba;
|
||||||
uint32_t num_sectors;
|
uint32_t num_sectors;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -391,20 +407,7 @@ iscsi_aio_readv_acb(IscsiAIOCB *acb)
|
|||||||
acb->status = -EINPROGRESS;
|
acb->status = -EINPROGRESS;
|
||||||
acb->buf = NULL;
|
acb->buf = NULL;
|
||||||
|
|
||||||
/* If LUN blocksize is bigger than BDRV_BLOCK_SIZE a read from QEMU
|
size = acb->nb_sectors * BDRV_SECTOR_SIZE;
|
||||||
* may be misaligned to the LUN, so we may need to read some extra
|
|
||||||
* data.
|
|
||||||
*/
|
|
||||||
acb->read_offset = 0;
|
|
||||||
if (acb->iscsilun->block_size > BDRV_SECTOR_SIZE) {
|
|
||||||
uint64_t bdrv_offset = BDRV_SECTOR_SIZE * acb->sector_num;
|
|
||||||
|
|
||||||
acb->read_offset = bdrv_offset % acb->iscsilun->block_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
num_sectors = (acb->read_size + acb->iscsilun->block_size
|
|
||||||
+ acb->read_offset - 1)
|
|
||||||
/ acb->iscsilun->block_size;
|
|
||||||
|
|
||||||
acb->task = malloc(sizeof(struct scsi_task));
|
acb->task = malloc(sizeof(struct scsi_task));
|
||||||
if (acb->task == NULL) {
|
if (acb->task == NULL) {
|
||||||
@@ -415,8 +418,9 @@ iscsi_aio_readv_acb(IscsiAIOCB *acb)
|
|||||||
memset(acb->task, 0, sizeof(struct scsi_task));
|
memset(acb->task, 0, sizeof(struct scsi_task));
|
||||||
|
|
||||||
acb->task->xfer_dir = SCSI_XFER_READ;
|
acb->task->xfer_dir = SCSI_XFER_READ;
|
||||||
|
acb->task->expxferlen = size;
|
||||||
lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
|
lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
|
||||||
acb->task->expxferlen = acb->read_size;
|
num_sectors = sector_qemu2lun(acb->nb_sectors, acb->iscsilun);
|
||||||
|
|
||||||
switch (acb->iscsilun->type) {
|
switch (acb->iscsilun->type) {
|
||||||
case TYPE_DISK:
|
case TYPE_DISK:
|
||||||
@@ -464,6 +468,10 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
|
|||||||
IscsiLun *iscsilun = bs->opaque;
|
IscsiLun *iscsilun = bs->opaque;
|
||||||
IscsiAIOCB *acb;
|
IscsiAIOCB *acb;
|
||||||
|
|
||||||
|
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
|
acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
|
||||||
trace_iscsi_aio_readv(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb);
|
trace_iscsi_aio_readv(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb);
|
||||||
|
|
||||||
@@ -471,7 +479,6 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
|
|||||||
acb->sector_num = sector_num;
|
acb->sector_num = sector_num;
|
||||||
acb->iscsilun = iscsilun;
|
acb->iscsilun = iscsilun;
|
||||||
acb->qiov = qiov;
|
acb->qiov = qiov;
|
||||||
acb->read_size = BDRV_SECTOR_SIZE * (size_t)acb->nb_sectors;
|
|
||||||
acb->retries = ISCSI_CMD_RETRIES;
|
acb->retries = ISCSI_CMD_RETRIES;
|
||||||
|
|
||||||
if (iscsi_aio_readv_acb(acb) != 0) {
|
if (iscsi_aio_readv_acb(acb) != 0) {
|
||||||
@@ -651,6 +658,9 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
|
|||||||
{
|
{
|
||||||
IscsiAIOCB *acb = opaque;
|
IscsiAIOCB *acb = opaque;
|
||||||
|
|
||||||
|
g_free(acb->buf);
|
||||||
|
acb->buf = NULL;
|
||||||
|
|
||||||
if (acb->canceled != 0) {
|
if (acb->canceled != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -727,14 +737,30 @@ static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
|
|||||||
memcpy(&acb->task->cdb[0], acb->ioh->cmdp, acb->ioh->cmd_len);
|
memcpy(&acb->task->cdb[0], acb->ioh->cmdp, acb->ioh->cmd_len);
|
||||||
acb->task->expxferlen = acb->ioh->dxfer_len;
|
acb->task->expxferlen = acb->ioh->dxfer_len;
|
||||||
|
|
||||||
|
data.size = 0;
|
||||||
if (acb->task->xfer_dir == SCSI_XFER_WRITE) {
|
if (acb->task->xfer_dir == SCSI_XFER_WRITE) {
|
||||||
data.data = acb->ioh->dxferp;
|
if (acb->ioh->iovec_count == 0) {
|
||||||
data.size = acb->ioh->dxfer_len;
|
data.data = acb->ioh->dxferp;
|
||||||
|
data.size = acb->ioh->dxfer_len;
|
||||||
|
} else {
|
||||||
|
#if defined(LIBISCSI_FEATURE_IOVECTOR)
|
||||||
|
scsi_task_set_iov_out(acb->task,
|
||||||
|
(struct scsi_iovec *) acb->ioh->dxferp,
|
||||||
|
acb->ioh->iovec_count);
|
||||||
|
#else
|
||||||
|
struct iovec *iov = (struct iovec *)acb->ioh->dxferp;
|
||||||
|
|
||||||
|
acb->buf = g_malloc(acb->ioh->dxfer_len);
|
||||||
|
data.data = acb->buf;
|
||||||
|
data.size = iov_to_buf(iov, acb->ioh->iovec_count, 0,
|
||||||
|
acb->buf, acb->ioh->dxfer_len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
|
if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
|
||||||
iscsi_aio_ioctl_cb,
|
iscsi_aio_ioctl_cb,
|
||||||
(acb->task->xfer_dir == SCSI_XFER_WRITE) ?
|
(data.size > 0) ? &data : NULL,
|
||||||
&data : NULL,
|
|
||||||
acb) != 0) {
|
acb) != 0) {
|
||||||
scsi_free_scsi_task(acb->task);
|
scsi_free_scsi_task(acb->task);
|
||||||
qemu_aio_release(acb);
|
qemu_aio_release(acb);
|
||||||
@@ -743,9 +769,26 @@ static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
|
|||||||
|
|
||||||
/* tell libiscsi to read straight into the buffer we got from ioctl */
|
/* tell libiscsi to read straight into the buffer we got from ioctl */
|
||||||
if (acb->task->xfer_dir == SCSI_XFER_READ) {
|
if (acb->task->xfer_dir == SCSI_XFER_READ) {
|
||||||
scsi_task_add_data_in_buffer(acb->task,
|
if (acb->ioh->iovec_count == 0) {
|
||||||
acb->ioh->dxfer_len,
|
scsi_task_add_data_in_buffer(acb->task,
|
||||||
acb->ioh->dxferp);
|
acb->ioh->dxfer_len,
|
||||||
|
acb->ioh->dxferp);
|
||||||
|
} else {
|
||||||
|
#if defined(LIBISCSI_FEATURE_IOVECTOR)
|
||||||
|
scsi_task_set_iov_in(acb->task,
|
||||||
|
(struct scsi_iovec *) acb->ioh->dxferp,
|
||||||
|
acb->ioh->iovec_count);
|
||||||
|
#else
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < acb->ioh->iovec_count; i++) {
|
||||||
|
struct iovec *iov = (struct iovec *)acb->ioh->dxferp;
|
||||||
|
|
||||||
|
scsi_task_add_data_in_buffer(acb->task,
|
||||||
|
iov[i].iov_len,
|
||||||
|
iov[i].iov_base);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iscsi_set_events(iscsilun);
|
iscsi_set_events(iscsilun);
|
||||||
@@ -1235,6 +1278,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options)
|
|||||||
}
|
}
|
||||||
if (bs.total_sectors < total_size) {
|
if (bs.total_sectors < total_size) {
|
||||||
ret = -ENOSPC;
|
ret = -ENOSPC;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@@ -1350,6 +1350,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags)
|
|||||||
qemu_close(fd);
|
qemu_close(fd);
|
||||||
}
|
}
|
||||||
filename = bsdPath;
|
filename = bsdPath;
|
||||||
|
qdict_put(options, "filename", qstring_from_str(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( mediaIterator )
|
if ( mediaIterator )
|
||||||
|
16
block/ssh.c
16
block/ssh.c
@@ -716,6 +716,21 @@ static void ssh_close(BlockDriverState *bs)
|
|||||||
ssh_state_free(s);
|
ssh_state_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ssh_has_zero_init(BlockDriverState *bs)
|
||||||
|
{
|
||||||
|
BDRVSSHState *s = bs->opaque;
|
||||||
|
/* Assume false, unless we can positively prove it's true. */
|
||||||
|
int has_zero_init = 0;
|
||||||
|
|
||||||
|
if (s->attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
|
||||||
|
if (s->attrs.permissions & LIBSSH2_SFTP_S_IFREG) {
|
||||||
|
has_zero_init = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return has_zero_init;
|
||||||
|
}
|
||||||
|
|
||||||
static void restart_coroutine(void *opaque)
|
static void restart_coroutine(void *opaque)
|
||||||
{
|
{
|
||||||
Coroutine *co = opaque;
|
Coroutine *co = opaque;
|
||||||
@@ -1037,6 +1052,7 @@ static BlockDriver bdrv_ssh = {
|
|||||||
.bdrv_file_open = ssh_file_open,
|
.bdrv_file_open = ssh_file_open,
|
||||||
.bdrv_create = ssh_create,
|
.bdrv_create = ssh_create,
|
||||||
.bdrv_close = ssh_close,
|
.bdrv_close = ssh_close,
|
||||||
|
.bdrv_has_zero_init = ssh_has_zero_init,
|
||||||
.bdrv_co_readv = ssh_co_readv,
|
.bdrv_co_readv = ssh_co_readv,
|
||||||
.bdrv_co_writev = ssh_co_writev,
|
.bdrv_co_writev = ssh_co_writev,
|
||||||
.bdrv_getlength = ssh_getlength,
|
.bdrv_getlength = ssh_getlength,
|
||||||
|
44
block/vmdk.c
44
block/vmdk.c
@@ -1465,45 +1465,6 @@ static int filename_decompose(const char *filename, char *path, char *prefix,
|
|||||||
return VMDK_OK;
|
return VMDK_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int relative_path(char *dest, int dest_size,
|
|
||||||
const char *base, const char *target)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
int n = 0;
|
|
||||||
const char *p, *q;
|
|
||||||
#ifdef _WIN32
|
|
||||||
const char *sep = "\\";
|
|
||||||
#else
|
|
||||||
const char *sep = "/";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!(dest && base && target)) {
|
|
||||||
return VMDK_ERROR;
|
|
||||||
}
|
|
||||||
if (path_is_absolute(target)) {
|
|
||||||
pstrcpy(dest, dest_size, target);
|
|
||||||
return VMDK_OK;
|
|
||||||
}
|
|
||||||
while (base[i] == target[i]) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
p = &base[i];
|
|
||||||
q = &target[i];
|
|
||||||
while (*p) {
|
|
||||||
if (*p == *sep) {
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
dest[0] = '\0';
|
|
||||||
for (; n; n--) {
|
|
||||||
pstrcat(dest, dest_size, "..");
|
|
||||||
pstrcat(dest, dest_size, sep);
|
|
||||||
}
|
|
||||||
pstrcat(dest, dest_size, q);
|
|
||||||
return VMDK_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vmdk_create(const char *filename, QEMUOptionParameter *options)
|
static int vmdk_create(const char *filename, QEMUOptionParameter *options)
|
||||||
{
|
{
|
||||||
int fd, idx = 0;
|
int fd, idx = 0;
|
||||||
@@ -1603,7 +1564,6 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
|
|||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
if (backing_file) {
|
if (backing_file) {
|
||||||
char parent_filename[PATH_MAX];
|
|
||||||
BlockDriverState *bs = bdrv_new("");
|
BlockDriverState *bs = bdrv_new("");
|
||||||
ret = bdrv_open(bs, backing_file, NULL, 0, NULL);
|
ret = bdrv_open(bs, backing_file, NULL, 0, NULL);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@@ -1616,10 +1576,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
|
|||||||
}
|
}
|
||||||
parent_cid = vmdk_read_cid(bs, 0);
|
parent_cid = vmdk_read_cid(bs, 0);
|
||||||
bdrv_delete(bs);
|
bdrv_delete(bs);
|
||||||
relative_path(parent_filename, sizeof(parent_filename),
|
|
||||||
filename, backing_file);
|
|
||||||
snprintf(parent_desc_line, sizeof(parent_desc_line),
|
snprintf(parent_desc_line, sizeof(parent_desc_line),
|
||||||
"parentFileNameHint=\"%s\"", parent_filename);
|
"parentFileNameHint=\"%s\"", backing_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create extents */
|
/* Create extents */
|
||||||
|
25
cpus.c
25
cpus.c
@@ -437,17 +437,22 @@ bool cpu_is_stopped(CPUState *cpu)
|
|||||||
return !runstate_is_running() || cpu->stopped;
|
return !runstate_is_running() || cpu->stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_vm_stop(RunState state)
|
static int do_vm_stop(RunState state)
|
||||||
{
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (runstate_is_running()) {
|
if (runstate_is_running()) {
|
||||||
cpu_disable_ticks();
|
cpu_disable_ticks();
|
||||||
pause_all_vcpus();
|
pause_all_vcpus();
|
||||||
runstate_set(state);
|
runstate_set(state);
|
||||||
vm_state_notify(0, state);
|
vm_state_notify(0, state);
|
||||||
bdrv_drain_all();
|
|
||||||
bdrv_flush_all();
|
|
||||||
monitor_protocol_event(QEVENT_STOP, NULL);
|
monitor_protocol_event(QEVENT_STOP, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bdrv_drain_all();
|
||||||
|
ret = bdrv_flush_all();
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cpu_can_run(CPUState *cpu)
|
static bool cpu_can_run(CPUState *cpu)
|
||||||
@@ -1093,7 +1098,7 @@ void cpu_stop_current(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_stop(RunState state)
|
int vm_stop(RunState state)
|
||||||
{
|
{
|
||||||
if (qemu_in_vcpu_thread()) {
|
if (qemu_in_vcpu_thread()) {
|
||||||
qemu_system_vmstop_request(state);
|
qemu_system_vmstop_request(state);
|
||||||
@@ -1102,19 +1107,23 @@ void vm_stop(RunState state)
|
|||||||
* vm_stop() has been requested.
|
* vm_stop() has been requested.
|
||||||
*/
|
*/
|
||||||
cpu_stop_current();
|
cpu_stop_current();
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
do_vm_stop(state);
|
|
||||||
|
return do_vm_stop(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* does a state transition even if the VM is already stopped,
|
/* does a state transition even if the VM is already stopped,
|
||||||
current state is forgotten forever */
|
current state is forgotten forever */
|
||||||
void vm_stop_force_state(RunState state)
|
int vm_stop_force_state(RunState state)
|
||||||
{
|
{
|
||||||
if (runstate_is_running()) {
|
if (runstate_is_running()) {
|
||||||
vm_stop(state);
|
return vm_stop(state);
|
||||||
} else {
|
} else {
|
||||||
runstate_set(state);
|
runstate_set(state);
|
||||||
|
/* Make sure to return an error if the flush in a previous vm_stop()
|
||||||
|
* failed. */
|
||||||
|
return bdrv_flush_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -238,14 +238,14 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
|
|||||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, binfo->dtb_filename);
|
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, binfo->dtb_filename);
|
||||||
if (!filename) {
|
if (!filename) {
|
||||||
fprintf(stderr, "Couldn't open dtb file %s\n", binfo->dtb_filename);
|
fprintf(stderr, "Couldn't open dtb file %s\n", binfo->dtb_filename);
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
fdt = load_device_tree(filename, &size);
|
fdt = load_device_tree(filename, &size);
|
||||||
if (!fdt) {
|
if (!fdt) {
|
||||||
fprintf(stderr, "Couldn't open dtb file %s\n", filename);
|
fprintf(stderr, "Couldn't open dtb file %s\n", filename);
|
||||||
g_free(filename);
|
g_free(filename);
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
g_free(filename);
|
g_free(filename);
|
||||||
|
|
||||||
@@ -253,7 +253,7 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
|
|||||||
scells = qemu_devtree_getprop_cell(fdt, "/", "#size-cells");
|
scells = qemu_devtree_getprop_cell(fdt, "/", "#size-cells");
|
||||||
if (acells == 0 || scells == 0) {
|
if (acells == 0 || scells == 0) {
|
||||||
fprintf(stderr, "dtb file invalid (#address-cells or #size-cells 0)\n");
|
fprintf(stderr, "dtb file invalid (#address-cells or #size-cells 0)\n");
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_reg_propsize = acells + scells;
|
mem_reg_propsize = acells + scells;
|
||||||
@@ -265,7 +265,7 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
|
|||||||
} else if (hival != 0) {
|
} else if (hival != 0) {
|
||||||
fprintf(stderr, "qemu: dtb file not compatible with "
|
fprintf(stderr, "qemu: dtb file not compatible with "
|
||||||
"RAM start address > 4GB\n");
|
"RAM start address > 4GB\n");
|
||||||
exit(1);
|
goto fail;
|
||||||
}
|
}
|
||||||
mem_reg_property[acells + scells - 1] = cpu_to_be32(binfo->ram_size);
|
mem_reg_property[acells + scells - 1] = cpu_to_be32(binfo->ram_size);
|
||||||
hival = cpu_to_be32(binfo->ram_size >> 32);
|
hival = cpu_to_be32(binfo->ram_size >> 32);
|
||||||
@@ -274,13 +274,14 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
|
|||||||
} else if (hival != 0) {
|
} else if (hival != 0) {
|
||||||
fprintf(stderr, "qemu: dtb file not compatible with "
|
fprintf(stderr, "qemu: dtb file not compatible with "
|
||||||
"RAM size > 4GB\n");
|
"RAM size > 4GB\n");
|
||||||
exit(1);
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
|
rc = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
|
||||||
mem_reg_propsize * sizeof(uint32_t));
|
mem_reg_propsize * sizeof(uint32_t));
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
fprintf(stderr, "couldn't set /memory/reg\n");
|
fprintf(stderr, "couldn't set /memory/reg\n");
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (binfo->kernel_cmdline && *binfo->kernel_cmdline) {
|
if (binfo->kernel_cmdline && *binfo->kernel_cmdline) {
|
||||||
@@ -288,6 +289,7 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
|
|||||||
binfo->kernel_cmdline);
|
binfo->kernel_cmdline);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
fprintf(stderr, "couldn't set /chosen/bootargs\n");
|
fprintf(stderr, "couldn't set /chosen/bootargs\n");
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,19 +298,27 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
|
|||||||
binfo->initrd_start);
|
binfo->initrd_start);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
|
fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
|
rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
|
||||||
binfo->initrd_start + binfo->initrd_size);
|
binfo->initrd_start + binfo->initrd_size);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
|
fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_physical_memory_write(addr, fdt, size);
|
cpu_physical_memory_write(addr, fdt, size);
|
||||||
|
|
||||||
|
g_free(fdt);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
g_free(fdt);
|
||||||
|
return -1;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
fprintf(stderr, "Device tree requested, "
|
fprintf(stderr, "Device tree requested, "
|
||||||
"but qemu was compiled without fdt support\n");
|
"but qemu was compiled without fdt support\n");
|
||||||
|
@@ -418,6 +418,14 @@ bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If dataplane is (re-)enabled while the guest is running there could be
|
||||||
|
* block jobs that can conflict.
|
||||||
|
*/
|
||||||
|
if (bdrv_in_use(blk->conf.bs)) {
|
||||||
|
error_report("cannot start dataplane thread while device is in use");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
fd = raw_get_aio_fd(blk->conf.bs);
|
fd = raw_get_aio_fd(blk->conf.bs);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
error_report("drive is incompatible with x-data-plane, "
|
error_report("drive is incompatible with x-data-plane, "
|
||||||
@@ -537,7 +545,7 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
|
|||||||
/* Clean up guest notifier (irq) */
|
/* Clean up guest notifier (irq) */
|
||||||
k->set_guest_notifiers(qbus->parent, 1, false);
|
k->set_guest_notifiers(qbus->parent, 1, false);
|
||||||
|
|
||||||
vring_teardown(&s->vring);
|
vring_teardown(&s->vring, s->vdev, 0);
|
||||||
s->started = false;
|
s->started = false;
|
||||||
s->stopping = false;
|
s->stopping = false;
|
||||||
}
|
}
|
||||||
|
@@ -185,6 +185,7 @@ static void virtserialport_class_init(ObjectClass *klass, void *data)
|
|||||||
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
|
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
|
||||||
|
|
||||||
k->init = virtconsole_initfn;
|
k->init = virtconsole_initfn;
|
||||||
|
k->exit = virtconsole_exitfn;
|
||||||
k->have_data = flush_buf;
|
k->have_data = flush_buf;
|
||||||
k->set_guest_connected = set_guest_connected;
|
k->set_guest_connected = set_guest_connected;
|
||||||
dc->props = virtserialport_properties;
|
dc->props = virtserialport_properties;
|
||||||
|
@@ -779,9 +779,6 @@ int rom_copy(uint8_t *dest, hwaddr addr, size_t size)
|
|||||||
if (rom->addr > end) {
|
if (rom->addr > end) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!rom->data) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
d = dest + (rom->addr - addr);
|
d = dest + (rom->addr - addr);
|
||||||
s = rom->data;
|
s = rom->data;
|
||||||
@@ -791,7 +788,9 @@ int rom_copy(uint8_t *dest, hwaddr addr, size_t size)
|
|||||||
l = dest - d;
|
l = dest - d;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(d, s, l);
|
if (l > 0) {
|
||||||
|
memcpy(d, s, l);
|
||||||
|
}
|
||||||
|
|
||||||
if (rom->romsize > rom->datasize) {
|
if (rom->romsize > rom->datasize) {
|
||||||
/* If datasize is less than romsize, it means that we didn't
|
/* If datasize is less than romsize, it means that we didn't
|
||||||
|
@@ -387,6 +387,7 @@ static void init_qxl_ram(PCIQXLDevice *d)
|
|||||||
d->ram->int_pending = cpu_to_le32(0);
|
d->ram->int_pending = cpu_to_le32(0);
|
||||||
d->ram->int_mask = cpu_to_le32(0);
|
d->ram->int_mask = cpu_to_le32(0);
|
||||||
d->ram->update_surface = 0;
|
d->ram->update_surface = 0;
|
||||||
|
d->ram->monitors_config = 0;
|
||||||
SPICE_RING_INIT(&d->ram->cmd_ring);
|
SPICE_RING_INIT(&d->ram->cmd_ring);
|
||||||
SPICE_RING_INIT(&d->ram->cursor_ring);
|
SPICE_RING_INIT(&d->ram->cursor_ring);
|
||||||
SPICE_RING_INIT(&d->ram->release_ring);
|
SPICE_RING_INIT(&d->ram->release_ring);
|
||||||
|
@@ -28,38 +28,6 @@ typedef struct KVMClockState {
|
|||||||
bool clock_valid;
|
bool clock_valid;
|
||||||
} KVMClockState;
|
} KVMClockState;
|
||||||
|
|
||||||
static void kvmclock_pre_save(void *opaque)
|
|
||||||
{
|
|
||||||
KVMClockState *s = opaque;
|
|
||||||
struct kvm_clock_data data;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (s->clock_valid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
|
|
||||||
if (ret < 0) {
|
|
||||||
fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
|
|
||||||
data.clock = 0;
|
|
||||||
}
|
|
||||||
s->clock = data.clock;
|
|
||||||
/*
|
|
||||||
* If the VM is stopped, declare the clock state valid to avoid re-reading
|
|
||||||
* it on next vmsave (which would return a different value). Will be reset
|
|
||||||
* when the VM is continued.
|
|
||||||
*/
|
|
||||||
s->clock_valid = !runstate_is_running();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int kvmclock_post_load(void *opaque, int version_id)
|
|
||||||
{
|
|
||||||
KVMClockState *s = opaque;
|
|
||||||
struct kvm_clock_data data;
|
|
||||||
|
|
||||||
data.clock = s->clock;
|
|
||||||
data.flags = 0;
|
|
||||||
return kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void kvmclock_vm_state_change(void *opaque, int running,
|
static void kvmclock_vm_state_change(void *opaque, int running,
|
||||||
RunState state)
|
RunState state)
|
||||||
@@ -70,8 +38,18 @@ static void kvmclock_vm_state_change(void *opaque, int running,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (running) {
|
if (running) {
|
||||||
|
struct kvm_clock_data data;
|
||||||
|
|
||||||
s->clock_valid = false;
|
s->clock_valid = false;
|
||||||
|
|
||||||
|
data.clock = s->clock;
|
||||||
|
data.flags = 0;
|
||||||
|
ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "KVM_SET_CLOCK failed: %s\n", strerror(ret));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
if (!cap_clock_ctrl) {
|
if (!cap_clock_ctrl) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -84,6 +62,26 @@ static void kvmclock_vm_state_change(void *opaque, int running,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
struct kvm_clock_data data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (s->clock_valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
s->clock = data.clock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the VM is stopped, declare the clock state valid to
|
||||||
|
* avoid re-reading it on next vmsave (which would return
|
||||||
|
* a different value). Will be reset when the VM is continued.
|
||||||
|
*/
|
||||||
|
s->clock_valid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,8 +98,6 @@ static const VMStateDescription kvmclock_vmsd = {
|
|||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
.minimum_version_id_old = 1,
|
||||||
.pre_save = kvmclock_pre_save,
|
|
||||||
.post_load = kvmclock_post_load,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT64(clock, KVMClockState),
|
VMSTATE_UINT64(clock, KVMClockState),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
|
13
hw/i386/pc.c
13
hw/i386/pc.c
@@ -902,20 +902,19 @@ static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id,
|
|||||||
X86CPU *cpu;
|
X86CPU *cpu;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
cpu = cpu_x86_create(cpu_model, icc_bridge, errp);
|
cpu = cpu_x86_create(cpu_model, icc_bridge, &local_err);
|
||||||
if (!cpu) {
|
if (local_err != NULL) {
|
||||||
return cpu;
|
error_propagate(errp, local_err);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err);
|
object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err);
|
||||||
object_property_set_bool(OBJECT(cpu), true, "realized", &local_err);
|
object_property_set_bool(OBJECT(cpu), true, "realized", &local_err);
|
||||||
|
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
if (cpu != NULL) {
|
|
||||||
object_unref(OBJECT(cpu));
|
|
||||||
cpu = NULL;
|
|
||||||
}
|
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
|
object_unref(OBJECT(cpu));
|
||||||
|
cpu = NULL;
|
||||||
}
|
}
|
||||||
return cpu;
|
return cpu;
|
||||||
}
|
}
|
||||||
|
@@ -250,6 +250,7 @@ static void pc_init_pci_1_4(QEMUMachineInitArgs *args)
|
|||||||
{
|
{
|
||||||
has_pvpanic = false;
|
has_pvpanic = false;
|
||||||
x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
|
x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
|
||||||
|
x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
|
||||||
pc_init_pci(args);
|
pc_init_pci(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -212,6 +212,7 @@ static void pc_q35_init_1_4(QEMUMachineInitArgs *args)
|
|||||||
{
|
{
|
||||||
has_pvpanic = false;
|
has_pvpanic = false;
|
||||||
x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
|
x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
|
||||||
|
x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
|
||||||
pc_q35_init(args);
|
pc_q35_init(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1103,10 +1103,15 @@ static int ahci_dma_add_status(IDEDMA *dma, int status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int ahci_dma_set_inactive(IDEDMA *dma)
|
static int ahci_dma_set_inactive(IDEDMA *dma)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ahci_async_cmd_done(IDEDMA *dma)
|
||||||
{
|
{
|
||||||
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
|
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
|
||||||
|
|
||||||
DPRINTF(ad->port_no, "dma done\n");
|
DPRINTF(ad->port_no, "async cmd done\n");
|
||||||
|
|
||||||
/* update d2h status */
|
/* update d2h status */
|
||||||
ahci_write_fis_d2h(ad, NULL);
|
ahci_write_fis_d2h(ad, NULL);
|
||||||
@@ -1141,6 +1146,7 @@ static const IDEDMAOps ahci_dma_ops = {
|
|||||||
.set_unit = ahci_dma_set_unit,
|
.set_unit = ahci_dma_set_unit,
|
||||||
.add_status = ahci_dma_add_status,
|
.add_status = ahci_dma_add_status,
|
||||||
.set_inactive = ahci_dma_set_inactive,
|
.set_inactive = ahci_dma_set_inactive,
|
||||||
|
.async_cmd_done = ahci_async_cmd_done,
|
||||||
.restart_cb = ahci_dma_restart_cb,
|
.restart_cb = ahci_dma_restart_cb,
|
||||||
.reset = ahci_dma_reset,
|
.reset = ahci_dma_reset,
|
||||||
};
|
};
|
||||||
|
@@ -568,10 +568,18 @@ static void dma_buf_commit(IDEState *s)
|
|||||||
qemu_sglist_destroy(&s->sg);
|
qemu_sglist_destroy(&s->sg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ide_async_cmd_done(IDEState *s)
|
||||||
|
{
|
||||||
|
if (s->bus->dma->ops->async_cmd_done) {
|
||||||
|
s->bus->dma->ops->async_cmd_done(s->bus->dma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ide_set_inactive(IDEState *s)
|
void ide_set_inactive(IDEState *s)
|
||||||
{
|
{
|
||||||
s->bus->dma->aiocb = NULL;
|
s->bus->dma->aiocb = NULL;
|
||||||
s->bus->dma->ops->set_inactive(s->bus->dma);
|
s->bus->dma->ops->set_inactive(s->bus->dma);
|
||||||
|
ide_async_cmd_done(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ide_dma_error(IDEState *s)
|
void ide_dma_error(IDEState *s)
|
||||||
@@ -804,6 +812,7 @@ static void ide_flush_cb(void *opaque, int ret)
|
|||||||
|
|
||||||
bdrv_acct_done(s->bs, &s->acct);
|
bdrv_acct_done(s->bs, &s->acct);
|
||||||
s->status = READY_STAT | SEEK_STAT;
|
s->status = READY_STAT | SEEK_STAT;
|
||||||
|
ide_async_cmd_done(s);
|
||||||
ide_set_irq(s->bus);
|
ide_set_irq(s->bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -433,6 +433,7 @@ struct IDEDMAOps {
|
|||||||
DMAIntFunc *set_unit;
|
DMAIntFunc *set_unit;
|
||||||
DMAIntFunc *add_status;
|
DMAIntFunc *add_status;
|
||||||
DMAFunc *set_inactive;
|
DMAFunc *set_inactive;
|
||||||
|
DMAFunc *async_cmd_done;
|
||||||
DMARestartFunc *restart_cb;
|
DMARestartFunc *restart_cb;
|
||||||
DMAFunc *reset;
|
DMAFunc *reset;
|
||||||
};
|
};
|
||||||
|
@@ -87,6 +87,7 @@ static void i82801b11_bridge_class_init(ObjectClass *klass, void *data)
|
|||||||
k->device_id = PCI_DEVICE_ID_INTEL_82801BA_11;
|
k->device_id = PCI_DEVICE_ID_INTEL_82801BA_11;
|
||||||
k->revision = ICH9_D2P_A2_REVISION;
|
k->revision = ICH9_D2P_A2_REVISION;
|
||||||
k->init = i82801b11_bridge_initfn;
|
k->init = i82801b11_bridge_initfn;
|
||||||
|
k->config_write = pci_bridge_write_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo i82801b11_bridge_info = {
|
static const TypeInfo i82801b11_bridge_info = {
|
||||||
|
@@ -30,6 +30,8 @@
|
|||||||
#include "monitor/monitor.h"
|
#include "monitor/monitor.h"
|
||||||
#include "hw/scsi/scsi.h"
|
#include "hw/scsi/scsi.h"
|
||||||
#include "hw/virtio/virtio-blk.h"
|
#include "hw/virtio/virtio-blk.h"
|
||||||
|
#include "hw/virtio/virtio-scsi.h"
|
||||||
|
#include "hw/virtio/virtio-pci.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
#include "sysemu/blockdev.h"
|
#include "sysemu/blockdev.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
@@ -79,13 +81,26 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
|
|||||||
{
|
{
|
||||||
SCSIBus *scsibus;
|
SCSIBus *scsibus;
|
||||||
SCSIDevice *scsidev;
|
SCSIDevice *scsidev;
|
||||||
|
VirtIOPCIProxy *virtio_proxy;
|
||||||
|
|
||||||
scsibus = (SCSIBus *)
|
scsibus = (SCSIBus *)
|
||||||
object_dynamic_cast(OBJECT(QLIST_FIRST(&adapter->child_bus)),
|
object_dynamic_cast(OBJECT(QLIST_FIRST(&adapter->child_bus)),
|
||||||
TYPE_SCSI_BUS);
|
TYPE_SCSI_BUS);
|
||||||
if (!scsibus) {
|
if (!scsibus) {
|
||||||
error_report("Device is not a SCSI adapter");
|
/*
|
||||||
return -1;
|
* Check if the adapter is a virtio-scsi-pci, and forward scsi_hot_add
|
||||||
|
* to the virtio-scsi-device.
|
||||||
|
*/
|
||||||
|
if (!object_dynamic_cast(OBJECT(adapter), TYPE_VIRTIO_SCSI_PCI)) {
|
||||||
|
error_report("Device is not a SCSI adapter");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
virtio_proxy = VIRTIO_PCI(adapter);
|
||||||
|
adapter = DEVICE(virtio_proxy->bus.vdev);
|
||||||
|
scsibus = (SCSIBus *)
|
||||||
|
object_dynamic_cast(OBJECT(QLIST_FIRST(&adapter->child_bus)),
|
||||||
|
TYPE_SCSI_BUS);
|
||||||
|
assert(scsibus);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -373,6 +373,7 @@ int pci_bus_num(PCIBus *s)
|
|||||||
static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
|
static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
|
||||||
{
|
{
|
||||||
PCIDevice *s = container_of(pv, PCIDevice, config);
|
PCIDevice *s = container_of(pv, PCIDevice, config);
|
||||||
|
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(s);
|
||||||
uint8_t *config;
|
uint8_t *config;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -390,6 +391,10 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
|
|||||||
memcpy(s->config, config, size);
|
memcpy(s->config, config, size);
|
||||||
|
|
||||||
pci_update_mappings(s);
|
pci_update_mappings(s);
|
||||||
|
if (pc->is_bridge) {
|
||||||
|
PCIBridge *b = container_of(s, PCIBridge, dev);
|
||||||
|
pci_bridge_update_mappings(b);
|
||||||
|
}
|
||||||
|
|
||||||
memory_region_set_enabled(&s->bus_master_enable_region,
|
memory_region_set_enabled(&s->bus_master_enable_region,
|
||||||
pci_get_word(s->config + PCI_COMMAND)
|
pci_get_word(s->config + PCI_COMMAND)
|
||||||
|
@@ -224,7 +224,7 @@ static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w)
|
|||||||
g_free(w);
|
g_free(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pci_bridge_update_mappings(PCIBridge *br)
|
void pci_bridge_update_mappings(PCIBridge *br)
|
||||||
{
|
{
|
||||||
PCIBridgeWindows *w = br->windows;
|
PCIBridgeWindows *w = br->windows;
|
||||||
|
|
||||||
|
@@ -154,17 +154,19 @@ static void s390_ipl_reset(DeviceState *dev)
|
|||||||
env->psw.mask = IPL_PSW_MASK;
|
env->psw.mask = IPL_PSW_MASK;
|
||||||
|
|
||||||
if (!ipl->kernel) {
|
if (!ipl->kernel) {
|
||||||
/* booting firmware, tell what device to boot from */
|
/* Tell firmware, if there is a preferred boot device */
|
||||||
|
env->regs[7] = -1;
|
||||||
DeviceState *dev_st = get_boot_device(0);
|
DeviceState *dev_st = get_boot_device(0);
|
||||||
VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast(
|
if (dev_st) {
|
||||||
OBJECT(&(dev_st->parent_obj)), "virtio-blk-ccw");
|
VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast(
|
||||||
|
OBJECT(qdev_get_parent_bus(dev_st)->parent),
|
||||||
|
TYPE_VIRTIO_CCW_DEVICE);
|
||||||
|
|
||||||
if (ccw_dev) {
|
if (ccw_dev) {
|
||||||
env->regs[7] = ccw_dev->sch->cssid << 24 |
|
env->regs[7] = ccw_dev->sch->cssid << 24 |
|
||||||
ccw_dev->sch->ssid << 16 |
|
ccw_dev->sch->ssid << 16 |
|
||||||
ccw_dev->sch->devno;
|
ccw_dev->sch->devno;
|
||||||
} else {
|
}
|
||||||
env->regs[7] = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -803,6 +803,8 @@ static void virtio_ccw_reset(DeviceState *d)
|
|||||||
|
|
||||||
virtio_reset(dev->vdev);
|
virtio_reset(dev->vdev);
|
||||||
css_reset_sch(dev->sch);
|
css_reset_sch(dev->sch);
|
||||||
|
dev->indicators = 0;
|
||||||
|
dev->indicators2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************** Virtio-ccw Bus Device Descriptions *******************/
|
/**************** Virtio-ccw Bus Device Descriptions *******************/
|
||||||
|
@@ -2088,6 +2088,7 @@ static const struct SCSIBusInfo megasas_scsi_info = {
|
|||||||
|
|
||||||
static int megasas_scsi_init(PCIDevice *dev)
|
static int megasas_scsi_init(PCIDevice *dev)
|
||||||
{
|
{
|
||||||
|
DeviceState *d = DEVICE(dev);
|
||||||
MegasasState *s = DO_UPCAST(MegasasState, dev, dev);
|
MegasasState *s = DO_UPCAST(MegasasState, dev, dev);
|
||||||
uint8_t *pci_conf;
|
uint8_t *pci_conf;
|
||||||
int i, bar_type;
|
int i, bar_type;
|
||||||
@@ -2160,7 +2161,9 @@ static int megasas_scsi_init(PCIDevice *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
scsi_bus_new(&s->bus, &dev->qdev, &megasas_scsi_info, NULL);
|
scsi_bus_new(&s->bus, &dev->qdev, &megasas_scsi_info, NULL);
|
||||||
scsi_bus_legacy_handle_cmdline(&s->bus);
|
if (!d->hotplugged) {
|
||||||
|
return scsi_bus_legacy_handle_cmdline(&s->bus);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1395,7 +1395,6 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid,
|
|||||||
{
|
{
|
||||||
XHCISlot *slot;
|
XHCISlot *slot;
|
||||||
XHCIEPContext *epctx;
|
XHCIEPContext *epctx;
|
||||||
USBDevice *dev;
|
|
||||||
|
|
||||||
trace_usb_xhci_ep_reset(slotid, epid);
|
trace_usb_xhci_ep_reset(slotid, epid);
|
||||||
assert(slotid >= 1 && slotid <= xhci->numslots);
|
assert(slotid >= 1 && slotid <= xhci->numslots);
|
||||||
@@ -1431,8 +1430,8 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid,
|
|||||||
ep |= 0x80;
|
ep |= 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = xhci->slots[slotid-1].uport->dev;
|
if (!xhci->slots[slotid-1].uport ||
|
||||||
if (!dev) {
|
!xhci->slots[slotid-1].uport->dev) {
|
||||||
return CC_USB_TRANSACTION_ERROR;
|
return CC_USB_TRANSACTION_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1707,6 +1706,7 @@ static int xhci_complete_packet(XHCITransfer *xfer)
|
|||||||
trace_usb_xhci_xfer_error(xfer, xfer->packet.status);
|
trace_usb_xhci_xfer_error(xfer, xfer->packet.status);
|
||||||
switch (xfer->packet.status) {
|
switch (xfer->packet.status) {
|
||||||
case USB_RET_NODEV:
|
case USB_RET_NODEV:
|
||||||
|
case USB_RET_IOERROR:
|
||||||
xfer->status = CC_USB_TRANSACTION_ERROR;
|
xfer->status = CC_USB_TRANSACTION_ERROR;
|
||||||
xhci_xfer_report(xfer);
|
xhci_xfer_report(xfer);
|
||||||
xhci_stall_ep(xfer);
|
xhci_stall_ep(xfer);
|
||||||
|
@@ -891,6 +891,7 @@ static int usb_host_initfn(USBDevice *udev)
|
|||||||
USBHostDevice *s = USB_HOST_DEVICE(udev);
|
USBHostDevice *s = USB_HOST_DEVICE(udev);
|
||||||
|
|
||||||
loglevel = s->loglevel;
|
loglevel = s->loglevel;
|
||||||
|
udev->flags |= (1 << USB_DEV_FLAG_IS_HOST);
|
||||||
udev->auto_attach = 0;
|
udev->auto_attach = 0;
|
||||||
QTAILQ_INIT(&s->requests);
|
QTAILQ_INIT(&s->requests);
|
||||||
QTAILQ_INIT(&s->isorings);
|
QTAILQ_INIT(&s->isorings);
|
||||||
|
@@ -39,8 +39,8 @@ bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
|
|||||||
|
|
||||||
vring_init(&vring->vr, virtio_queue_get_num(vdev, n), vring_ptr, 4096);
|
vring_init(&vring->vr, virtio_queue_get_num(vdev, n), vring_ptr, 4096);
|
||||||
|
|
||||||
vring->last_avail_idx = 0;
|
vring->last_avail_idx = virtio_queue_get_last_avail_idx(vdev, n);
|
||||||
vring->last_used_idx = 0;
|
vring->last_used_idx = vring->vr.used->idx;
|
||||||
vring->signalled_used = 0;
|
vring->signalled_used = 0;
|
||||||
vring->signalled_used_valid = false;
|
vring->signalled_used_valid = false;
|
||||||
|
|
||||||
@@ -49,8 +49,11 @@ bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vring_teardown(Vring *vring)
|
void vring_teardown(Vring *vring, VirtIODevice *vdev, int n)
|
||||||
{
|
{
|
||||||
|
virtio_queue_set_last_avail_idx(vdev, n, vring->last_avail_idx);
|
||||||
|
virtio_queue_invalidate_signalled_used(vdev, n);
|
||||||
|
|
||||||
hostmem_finalize(&vring->hostmem);
|
hostmem_finalize(&vring->hostmem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -761,6 +761,7 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
|
|||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
virtio_queue_set_last_avail_idx(vdev, idx, state.num);
|
virtio_queue_set_last_avail_idx(vdev, idx, state.num);
|
||||||
|
virtio_queue_invalidate_signalled_used(vdev, idx);
|
||||||
assert (r >= 0);
|
assert (r >= 0);
|
||||||
cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx),
|
cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx),
|
||||||
0, virtio_queue_get_ring_size(vdev, idx));
|
0, virtio_queue_get_ring_size(vdev, idx));
|
||||||
|
@@ -1025,6 +1025,11 @@ void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx)
|
|||||||
vdev->vq[n].last_avail_idx = idx;
|
vdev->vq[n].last_avail_idx = idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n)
|
||||||
|
{
|
||||||
|
vdev->vq[n].signalled_used_valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n)
|
VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n)
|
||||||
{
|
{
|
||||||
return vdev->vq + n;
|
return vdev->vq + n;
|
||||||
|
@@ -276,7 +276,7 @@ void bdrv_clear_incoming_migration_all(void);
|
|||||||
/* Ensure contents are flushed to disk. */
|
/* Ensure contents are flushed to disk. */
|
||||||
int bdrv_flush(BlockDriverState *bs);
|
int bdrv_flush(BlockDriverState *bs);
|
||||||
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
|
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
|
||||||
void bdrv_flush_all(void);
|
int bdrv_flush_all(void);
|
||||||
void bdrv_close_all(void);
|
void bdrv_close_all(void);
|
||||||
void bdrv_drain_all(void);
|
void bdrv_drain_all(void);
|
||||||
|
|
||||||
|
@@ -37,6 +37,7 @@ PCIBus *pci_bridge_get_sec_bus(PCIBridge *br);
|
|||||||
pcibus_t pci_bridge_get_base(const PCIDevice *bridge, uint8_t type);
|
pcibus_t pci_bridge_get_base(const PCIDevice *bridge, uint8_t type);
|
||||||
pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type);
|
pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type);
|
||||||
|
|
||||||
|
void pci_bridge_update_mappings(PCIBridge *br);
|
||||||
void pci_bridge_write_config(PCIDevice *d,
|
void pci_bridge_write_config(PCIDevice *d,
|
||||||
uint32_t address, uint32_t val, int len);
|
uint32_t address, uint32_t val, int len);
|
||||||
void pci_bridge_disable_base_limit(PCIDevice *dev);
|
void pci_bridge_disable_base_limit(PCIDevice *dev);
|
||||||
|
@@ -50,7 +50,7 @@ static inline void vring_set_broken(Vring *vring)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool vring_setup(Vring *vring, VirtIODevice *vdev, int n);
|
bool vring_setup(Vring *vring, VirtIODevice *vdev, int n);
|
||||||
void vring_teardown(Vring *vring);
|
void vring_teardown(Vring *vring, VirtIODevice *vdev, int n);
|
||||||
void vring_disable_notification(VirtIODevice *vdev, Vring *vring);
|
void vring_disable_notification(VirtIODevice *vdev, Vring *vring);
|
||||||
bool vring_enable_notification(VirtIODevice *vdev, Vring *vring);
|
bool vring_enable_notification(VirtIODevice *vdev, Vring *vring);
|
||||||
bool vring_should_notify(VirtIODevice *vdev, Vring *vring);
|
bool vring_should_notify(VirtIODevice *vdev, Vring *vring);
|
||||||
|
@@ -233,6 +233,7 @@ hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n);
|
|||||||
hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n);
|
hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n);
|
||||||
uint16_t virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n);
|
uint16_t virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n);
|
||||||
void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx);
|
void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx);
|
||||||
|
void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n);
|
||||||
VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n);
|
VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n);
|
||||||
uint16_t virtio_get_queue_index(VirtQueue *vq);
|
uint16_t virtio_get_queue_index(VirtQueue *vq);
|
||||||
int virtio_queue_get_id(VirtQueue *vq);
|
int virtio_queue_get_id(VirtQueue *vq);
|
||||||
|
@@ -15,7 +15,7 @@ struct QemuSemaphore {
|
|||||||
#if defined(__APPLE__) || defined(__NetBSD__)
|
#if defined(__APPLE__) || defined(__NetBSD__)
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
int count;
|
unsigned int count;
|
||||||
#else
|
#else
|
||||||
sem_t sem;
|
sem_t sem;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -77,6 +77,7 @@ struct CharDriverState {
|
|||||||
int explicit_fe_open;
|
int explicit_fe_open;
|
||||||
int explicit_be_open;
|
int explicit_be_open;
|
||||||
int avail_connections;
|
int avail_connections;
|
||||||
|
int is_mux;
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
QTAILQ_ENTRY(CharDriverState) next;
|
QTAILQ_ENTRY(CharDriverState) next;
|
||||||
};
|
};
|
||||||
|
@@ -35,8 +35,8 @@ void vm_state_notify(int running, RunState state);
|
|||||||
#define VMRESET_REPORT true
|
#define VMRESET_REPORT true
|
||||||
|
|
||||||
void vm_start(void);
|
void vm_start(void);
|
||||||
void vm_stop(RunState state);
|
int vm_stop(RunState state);
|
||||||
void vm_stop_force_state(RunState state);
|
int vm_stop_force_state(RunState state);
|
||||||
|
|
||||||
typedef enum WakeupReason {
|
typedef enum WakeupReason {
|
||||||
QEMU_WAKEUP_REASON_OTHER = 0,
|
QEMU_WAKEUP_REASON_OTHER = 0,
|
||||||
|
@@ -3288,9 +3288,9 @@
|
|||||||
##
|
##
|
||||||
# @ChardevRingbuf:
|
# @ChardevRingbuf:
|
||||||
#
|
#
|
||||||
# Configuration info for memory chardevs
|
# Configuration info for ring buffer chardevs.
|
||||||
#
|
#
|
||||||
# @size: #optional Ringbuffer size, must be power of two, default is 65536
|
# @size: #optional ring buffer size, must be power of two, default is 65536
|
||||||
#
|
#
|
||||||
# Since: 1.5
|
# Since: 1.5
|
||||||
##
|
##
|
||||||
@@ -3321,6 +3321,8 @@
|
|||||||
'spicevmc' : 'ChardevSpiceChannel',
|
'spicevmc' : 'ChardevSpiceChannel',
|
||||||
'spiceport' : 'ChardevSpicePort',
|
'spiceport' : 'ChardevSpicePort',
|
||||||
'vc' : 'ChardevVC',
|
'vc' : 'ChardevVC',
|
||||||
|
'ringbuf': 'ChardevRingbuf',
|
||||||
|
# next one is just for compatibility
|
||||||
'memory' : 'ChardevRingbuf' } }
|
'memory' : 'ChardevRingbuf' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
|
69
qemu-char.c
69
qemu-char.c
@@ -478,6 +478,46 @@ static void mux_chr_update_read_handler(CharDriverState *chr)
|
|||||||
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
|
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool muxes_realized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after processing of default and command-line-specified
|
||||||
|
* chardevs to deliver CHR_EVENT_OPENED events to any FEs attached
|
||||||
|
* to a mux chardev. This is done here to ensure that
|
||||||
|
* output/prompts/banners are only displayed for the FE that has
|
||||||
|
* focus when initial command-line processing/machine init is
|
||||||
|
* completed.
|
||||||
|
*
|
||||||
|
* After this point, any new FE attached to any new or existing
|
||||||
|
* mux will receive CHR_EVENT_OPENED notifications for the BE
|
||||||
|
* immediately.
|
||||||
|
*/
|
||||||
|
static void muxes_realize_done(Notifier *notifier, void *unused)
|
||||||
|
{
|
||||||
|
CharDriverState *chr;
|
||||||
|
|
||||||
|
QTAILQ_FOREACH(chr, &chardevs, next) {
|
||||||
|
if (chr->is_mux) {
|
||||||
|
MuxDriver *d = chr->opaque;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* send OPENED to all already-attached FEs */
|
||||||
|
for (i = 0; i < d->mux_cnt; i++) {
|
||||||
|
mux_chr_send_event(d, i, CHR_EVENT_OPENED);
|
||||||
|
}
|
||||||
|
/* mark mux as OPENED so any new FEs will immediately receive
|
||||||
|
* OPENED event
|
||||||
|
*/
|
||||||
|
qemu_chr_be_generic_open(chr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
muxes_realized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Notifier muxes_realize_notify = {
|
||||||
|
.notify = muxes_realize_done,
|
||||||
|
};
|
||||||
|
|
||||||
static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
|
static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
|
||||||
{
|
{
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
@@ -494,6 +534,11 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
|
|||||||
chr->chr_accept_input = mux_chr_accept_input;
|
chr->chr_accept_input = mux_chr_accept_input;
|
||||||
/* Frontend guest-open / -close notification is not support with muxes */
|
/* Frontend guest-open / -close notification is not support with muxes */
|
||||||
chr->chr_set_fe_open = NULL;
|
chr->chr_set_fe_open = NULL;
|
||||||
|
/* only default to opened state if we've realized the initial
|
||||||
|
* set of muxes
|
||||||
|
*/
|
||||||
|
chr->explicit_be_open = muxes_realized ? 0 : 1;
|
||||||
|
chr->is_mux = 1;
|
||||||
|
|
||||||
return chr;
|
return chr;
|
||||||
}
|
}
|
||||||
@@ -1104,8 +1149,8 @@ static void pty_chr_state(CharDriverState *chr, int connected)
|
|||||||
s->timer_tag = 0;
|
s->timer_tag = 0;
|
||||||
}
|
}
|
||||||
if (!s->connected) {
|
if (!s->connected) {
|
||||||
qemu_chr_be_generic_open(chr);
|
|
||||||
s->connected = 1;
|
s->connected = 1;
|
||||||
|
qemu_chr_be_generic_open(chr);
|
||||||
s->fd_tag = io_add_watch_poll(s->fd, pty_chr_read_poll, pty_chr_read, chr);
|
s->fd_tag = io_add_watch_poll(s->fd, pty_chr_read_poll, pty_chr_read, chr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3115,12 +3160,12 @@ static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
|
|||||||
{
|
{
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
backend->memory = g_new0(ChardevRingbuf, 1);
|
backend->ringbuf = g_new0(ChardevRingbuf, 1);
|
||||||
|
|
||||||
val = qemu_opt_get_number(opts, "size", 0);
|
val = qemu_opt_get_size(opts, "size", 0);
|
||||||
if (val != 0) {
|
if (val != 0) {
|
||||||
backend->memory->has_size = true;
|
backend->ringbuf->has_size = true;
|
||||||
backend->memory->size = val;
|
backend->ringbuf->size = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3228,6 +3273,7 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
|
|||||||
}
|
}
|
||||||
|
|
||||||
chr = qemu_chr_find(id);
|
chr = qemu_chr_find(id);
|
||||||
|
chr->opts = opts;
|
||||||
|
|
||||||
qapi_out:
|
qapi_out:
|
||||||
qapi_free_ChardevBackend(backend);
|
qapi_free_ChardevBackend(backend);
|
||||||
@@ -3712,8 +3758,9 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
|
|||||||
case CHARDEV_BACKEND_KIND_VC:
|
case CHARDEV_BACKEND_KIND_VC:
|
||||||
chr = vc_init(backend->vc);
|
chr = vc_init(backend->vc);
|
||||||
break;
|
break;
|
||||||
|
case CHARDEV_BACKEND_KIND_RINGBUF:
|
||||||
case CHARDEV_BACKEND_KIND_MEMORY:
|
case CHARDEV_BACKEND_KIND_MEMORY:
|
||||||
chr = qemu_chr_open_ringbuf(backend->memory, errp);
|
chr = qemu_chr_open_ringbuf(backend->ringbuf, errp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error_setg(errp, "unknown chardev backend (%d)", backend->kind);
|
error_setg(errp, "unknown chardev backend (%d)", backend->kind);
|
||||||
@@ -3763,7 +3810,7 @@ static void register_types(void)
|
|||||||
register_char_driver_qapi("null", CHARDEV_BACKEND_KIND_NULL, NULL);
|
register_char_driver_qapi("null", CHARDEV_BACKEND_KIND_NULL, NULL);
|
||||||
register_char_driver("socket", qemu_chr_open_socket);
|
register_char_driver("socket", qemu_chr_open_socket);
|
||||||
register_char_driver("udp", qemu_chr_open_udp);
|
register_char_driver("udp", qemu_chr_open_udp);
|
||||||
register_char_driver_qapi("memory", CHARDEV_BACKEND_KIND_MEMORY,
|
register_char_driver_qapi("ringbuf", CHARDEV_BACKEND_KIND_RINGBUF,
|
||||||
qemu_chr_parse_ringbuf);
|
qemu_chr_parse_ringbuf);
|
||||||
register_char_driver_qapi("file", CHARDEV_BACKEND_KIND_FILE,
|
register_char_driver_qapi("file", CHARDEV_BACKEND_KIND_FILE,
|
||||||
qemu_chr_parse_file_out);
|
qemu_chr_parse_file_out);
|
||||||
@@ -3781,6 +3828,14 @@ static void register_types(void)
|
|||||||
register_char_driver_qapi("console", CHARDEV_BACKEND_KIND_CONSOLE, NULL);
|
register_char_driver_qapi("console", CHARDEV_BACKEND_KIND_CONSOLE, NULL);
|
||||||
register_char_driver_qapi("pipe", CHARDEV_BACKEND_KIND_PIPE,
|
register_char_driver_qapi("pipe", CHARDEV_BACKEND_KIND_PIPE,
|
||||||
qemu_chr_parse_pipe);
|
qemu_chr_parse_pipe);
|
||||||
|
/* Bug-compatibility: */
|
||||||
|
register_char_driver_qapi("memory", CHARDEV_BACKEND_KIND_MEMORY,
|
||||||
|
qemu_chr_parse_ringbuf);
|
||||||
|
/* this must be done after machine init, since we register FEs with muxes
|
||||||
|
* as part of realize functions like serial_isa_realizefn when -nographic
|
||||||
|
* is specified
|
||||||
|
*/
|
||||||
|
qemu_add_machine_init_done_notifier(&muxes_realize_notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_init(register_types);
|
type_init(register_types);
|
||||||
|
@@ -2460,6 +2460,10 @@ int main(int argc, char **argv)
|
|||||||
const img_cmd_t *cmd;
|
const img_cmd_t *cmd;
|
||||||
const char *cmdname;
|
const char *cmdname;
|
||||||
|
|
||||||
|
#ifdef CONFIG_POSIX
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
|
||||||
error_set_progname(argv[0]);
|
error_set_progname(argv[0]);
|
||||||
|
|
||||||
qemu_init_main_loop();
|
qemu_init_main_loop();
|
||||||
|
@@ -1920,6 +1920,10 @@ int main(int argc, char **argv)
|
|||||||
int opt_index = 0;
|
int opt_index = 0;
|
||||||
int flags = BDRV_O_UNMAP;
|
int flags = BDRV_O_UNMAP;
|
||||||
|
|
||||||
|
#ifdef CONFIG_POSIX
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
|
||||||
progname = basename(argv[0]);
|
progname = basename(argv[0]);
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
|
while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
|
||||||
|
@@ -33,6 +33,7 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
|
|||||||
{ SCMP_SYS(socketcall), 250 },
|
{ SCMP_SYS(socketcall), 250 },
|
||||||
#endif
|
#endif
|
||||||
{ SCMP_SYS(read), 249 },
|
{ SCMP_SYS(read), 249 },
|
||||||
|
{ SCMP_SYS(io_submit), 249 },
|
||||||
{ SCMP_SYS(brk), 248 },
|
{ SCMP_SYS(brk), 248 },
|
||||||
{ SCMP_SYS(clone), 247 },
|
{ SCMP_SYS(clone), 247 },
|
||||||
{ SCMP_SYS(mmap), 247 },
|
{ SCMP_SYS(mmap), 247 },
|
||||||
@@ -87,6 +88,7 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
|
|||||||
{ SCMP_SYS(stat), 245 },
|
{ SCMP_SYS(stat), 245 },
|
||||||
{ SCMP_SYS(uname), 245 },
|
{ SCMP_SYS(uname), 245 },
|
||||||
{ SCMP_SYS(eventfd2), 245 },
|
{ SCMP_SYS(eventfd2), 245 },
|
||||||
|
{ SCMP_SYS(io_getevents), 245 },
|
||||||
{ SCMP_SYS(dup), 245 },
|
{ SCMP_SYS(dup), 245 },
|
||||||
{ SCMP_SYS(dup2), 245 },
|
{ SCMP_SYS(dup2), 245 },
|
||||||
{ SCMP_SYS(dup3), 245 },
|
{ SCMP_SYS(dup3), 245 },
|
||||||
@@ -229,7 +231,11 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
|
|||||||
{ SCMP_SYS(sendmmsg), 241 },
|
{ SCMP_SYS(sendmmsg), 241 },
|
||||||
{ SCMP_SYS(recvmmsg), 241 },
|
{ SCMP_SYS(recvmmsg), 241 },
|
||||||
{ SCMP_SYS(prlimit64), 241 },
|
{ SCMP_SYS(prlimit64), 241 },
|
||||||
{ SCMP_SYS(waitid), 241 }
|
{ SCMP_SYS(waitid), 241 },
|
||||||
|
{ SCMP_SYS(io_cancel), 241 },
|
||||||
|
{ SCMP_SYS(io_setup), 241 },
|
||||||
|
{ SCMP_SYS(io_destroy), 241 },
|
||||||
|
{ SCMP_SYS(arch_prctl), 240 }
|
||||||
};
|
};
|
||||||
|
|
||||||
int seccomp_start(void)
|
int seccomp_start(void)
|
||||||
|
@@ -1002,7 +1002,8 @@ int main(int argc, char **argv)
|
|||||||
case 's':
|
case 's':
|
||||||
service = optarg;
|
service = optarg;
|
||||||
if (strcmp(service, "install") == 0) {
|
if (strcmp(service, "install") == 0) {
|
||||||
return ga_install_service(path, log_filepath);
|
const char *fixed_state_dir;
|
||||||
|
return ga_install_service(path, log_filepath, state_dir);
|
||||||
} else if (strcmp(service, "uninstall") == 0) {
|
} else if (strcmp(service, "uninstall") == 0) {
|
||||||
return ga_uninstall_service();
|
return ga_uninstall_service();
|
||||||
} else {
|
} else {
|
||||||
|
@@ -29,58 +29,136 @@ static int printf_win_error(const char *text)
|
|||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
(char *)&message, 0,
|
(char *)&message, 0,
|
||||||
NULL);
|
NULL);
|
||||||
n = printf("%s. (Error: %d) %s", text, (int)err, message);
|
n = fprintf(stderr, "%s. (Error: %d) %s", text, (int)err, message);
|
||||||
LocalFree(message);
|
LocalFree(message);
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ga_install_service(const char *path, const char *logfile)
|
/* Windows command line escaping. Based on
|
||||||
|
* <http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx> and
|
||||||
|
* <http://msdn.microsoft.com/en-us/library/windows/desktop/17w5ykft%28v=vs.85%29.aspx>.
|
||||||
|
*
|
||||||
|
* The caller is responsible for initializing @buffer; prior contents are lost.
|
||||||
|
*/
|
||||||
|
static const char *win_escape_arg(const char *to_escape, GString *buffer)
|
||||||
{
|
{
|
||||||
|
size_t backslash_count;
|
||||||
|
const char *c;
|
||||||
|
|
||||||
|
/* open with a double quote */
|
||||||
|
g_string_assign(buffer, "\"");
|
||||||
|
|
||||||
|
backslash_count = 0;
|
||||||
|
for (c = to_escape; *c != '\0'; ++c) {
|
||||||
|
switch (*c) {
|
||||||
|
case '\\':
|
||||||
|
/* The meaning depends on the first non-backslash character coming
|
||||||
|
* up.
|
||||||
|
*/
|
||||||
|
++backslash_count;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
/* We must escape each pending backslash, then escape the double
|
||||||
|
* quote. This creates a case of "odd number of backslashes [...]
|
||||||
|
* followed by a double quotation mark".
|
||||||
|
*/
|
||||||
|
while (backslash_count) {
|
||||||
|
--backslash_count;
|
||||||
|
g_string_append(buffer, "\\\\");
|
||||||
|
}
|
||||||
|
g_string_append(buffer, "\\\"");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Any pending backslashes are without special meaning, flush them.
|
||||||
|
* "Backslashes are interpreted literally, unless they immediately
|
||||||
|
* precede a double quotation mark."
|
||||||
|
*/
|
||||||
|
while (backslash_count) {
|
||||||
|
--backslash_count;
|
||||||
|
g_string_append_c(buffer, '\\');
|
||||||
|
}
|
||||||
|
g_string_append_c(buffer, *c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We're about to close with a double quote in string delimiter role.
|
||||||
|
* Double all pending backslashes, creating a case of "even number of
|
||||||
|
* backslashes [...] followed by a double quotation mark".
|
||||||
|
*/
|
||||||
|
while (backslash_count) {
|
||||||
|
--backslash_count;
|
||||||
|
g_string_append(buffer, "\\\\");
|
||||||
|
}
|
||||||
|
g_string_append_c(buffer, '"');
|
||||||
|
|
||||||
|
return buffer->str;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ga_install_service(const char *path, const char *logfile,
|
||||||
|
const char *state_dir)
|
||||||
|
{
|
||||||
|
int ret = EXIT_FAILURE;
|
||||||
SC_HANDLE manager;
|
SC_HANDLE manager;
|
||||||
SC_HANDLE service;
|
SC_HANDLE service;
|
||||||
TCHAR cmdline[MAX_PATH];
|
TCHAR module_fname[MAX_PATH];
|
||||||
|
GString *esc;
|
||||||
|
GString *cmdline;
|
||||||
|
SERVICE_DESCRIPTION desc = { (char *)QGA_SERVICE_DESCRIPTION };
|
||||||
|
|
||||||
if (GetModuleFileName(NULL, cmdline, MAX_PATH) == 0) {
|
if (GetModuleFileName(NULL, module_fname, MAX_PATH) == 0) {
|
||||||
printf_win_error("No full path to service's executable");
|
printf_win_error("No full path to service's executable");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_snprintf(cmdline, MAX_PATH - strlen(cmdline), "%s -d", cmdline);
|
esc = g_string_new("");
|
||||||
|
cmdline = g_string_new("");
|
||||||
|
|
||||||
|
g_string_append_printf(cmdline, "%s -d",
|
||||||
|
win_escape_arg(module_fname, esc));
|
||||||
|
|
||||||
if (path) {
|
if (path) {
|
||||||
_snprintf(cmdline, MAX_PATH - strlen(cmdline), "%s -p %s", cmdline, path);
|
g_string_append_printf(cmdline, " -p %s", win_escape_arg(path, esc));
|
||||||
}
|
}
|
||||||
if (logfile) {
|
if (logfile) {
|
||||||
_snprintf(cmdline, MAX_PATH - strlen(cmdline), "%s -l %s -v",
|
g_string_append_printf(cmdline, " -l %s -v",
|
||||||
cmdline, logfile);
|
win_escape_arg(logfile, esc));
|
||||||
|
}
|
||||||
|
if (state_dir) {
|
||||||
|
g_string_append_printf(cmdline, " -t %s",
|
||||||
|
win_escape_arg(state_dir, esc));
|
||||||
}
|
}
|
||||||
|
|
||||||
g_debug("service's cmdline: %s", cmdline);
|
g_debug("service's cmdline: %s", cmdline->str);
|
||||||
|
|
||||||
manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||||
if (manager == NULL) {
|
if (manager == NULL) {
|
||||||
printf_win_error("No handle to service control manager");
|
printf_win_error("No handle to service control manager");
|
||||||
return EXIT_FAILURE;
|
goto out_strings;
|
||||||
}
|
}
|
||||||
|
|
||||||
service = CreateService(manager, QGA_SERVICE_NAME, QGA_SERVICE_DISPLAY_NAME,
|
service = CreateService(manager, QGA_SERVICE_NAME, QGA_SERVICE_DISPLAY_NAME,
|
||||||
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
|
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
|
||||||
SERVICE_ERROR_NORMAL, cmdline, NULL, NULL, NULL, NULL, NULL);
|
SERVICE_ERROR_NORMAL, cmdline->str, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (service == NULL) {
|
||||||
if (service) {
|
|
||||||
SERVICE_DESCRIPTION desc = { (char *)QGA_SERVICE_DESCRIPTION };
|
|
||||||
ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &desc);
|
|
||||||
|
|
||||||
printf("Service was installed successfully.\n");
|
|
||||||
} else {
|
|
||||||
printf_win_error("Failed to install service");
|
printf_win_error("Failed to install service");
|
||||||
|
goto out_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &desc);
|
||||||
|
fprintf(stderr, "Service was installed successfully.\n");
|
||||||
|
ret = EXIT_SUCCESS;
|
||||||
CloseServiceHandle(service);
|
CloseServiceHandle(service);
|
||||||
|
|
||||||
|
out_manager:
|
||||||
CloseServiceHandle(manager);
|
CloseServiceHandle(manager);
|
||||||
|
|
||||||
return (service == NULL);
|
out_strings:
|
||||||
|
g_string_free(cmdline, TRUE);
|
||||||
|
g_string_free(esc, TRUE);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ga_uninstall_service(void)
|
int ga_uninstall_service(void)
|
||||||
@@ -104,7 +182,7 @@ int ga_uninstall_service(void)
|
|||||||
if (DeleteService(service) == FALSE) {
|
if (DeleteService(service) == FALSE) {
|
||||||
printf_win_error("Failed to delete service");
|
printf_win_error("Failed to delete service");
|
||||||
} else {
|
} else {
|
||||||
printf("Service was deleted successfully.\n");
|
fprintf(stderr, "Service was deleted successfully.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseServiceHandle(service);
|
CloseServiceHandle(service);
|
||||||
|
@@ -24,7 +24,8 @@ typedef struct GAService {
|
|||||||
SERVICE_STATUS_HANDLE status_handle;
|
SERVICE_STATUS_HANDLE status_handle;
|
||||||
} GAService;
|
} GAService;
|
||||||
|
|
||||||
int ga_install_service(const char *path, const char *logfile);
|
int ga_install_service(const char *path, const char *logfile,
|
||||||
|
const char *state_dir);
|
||||||
int ga_uninstall_service(void);
|
int ga_uninstall_service(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -531,14 +531,14 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
|
|||||||
#ifdef CONFIG_QOM_CAST_DEBUG
|
#ifdef CONFIG_QOM_CAST_DEBUG
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < OBJECT_CLASS_CAST_CACHE; i++) {
|
for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
|
||||||
if (class->cast_cache[i] == typename) {
|
if (class->cast_cache[i] == typename) {
|
||||||
ret = class;
|
ret = class;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (!class->interfaces) {
|
if (!class || !class->interfaces) {
|
||||||
return class;
|
return class;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -551,7 +551,7 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_QOM_CAST_DEBUG
|
#ifdef CONFIG_QOM_CAST_DEBUG
|
||||||
if (ret == class) {
|
if (class && ret == class) {
|
||||||
for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
|
for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
|
||||||
class->cast_cache[i - 1] = class->cast_cache[i];
|
class->cast_cache[i - 1] = class->cast_cache[i];
|
||||||
}
|
}
|
||||||
|
@@ -128,12 +128,15 @@ bool has_%(argname)s = false;
|
|||||||
|
|
||||||
def gen_visitor_input_block(args, obj, dealloc=False):
|
def gen_visitor_input_block(args, obj, dealloc=False):
|
||||||
ret = ""
|
ret = ""
|
||||||
|
errparg = 'errp'
|
||||||
|
|
||||||
if len(args) == 0:
|
if len(args) == 0:
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
push_indent()
|
push_indent()
|
||||||
|
|
||||||
if dealloc:
|
if dealloc:
|
||||||
|
errparg = 'NULL'
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
md = qapi_dealloc_visitor_new();
|
md = qapi_dealloc_visitor_new();
|
||||||
v = qapi_dealloc_get_visitor(md);
|
v = qapi_dealloc_get_visitor(md);
|
||||||
@@ -148,22 +151,22 @@ v = qmp_input_get_visitor(mi);
|
|||||||
for argname, argtype, optional, structured in parse_args(args):
|
for argname, argtype, optional, structured in parse_args(args):
|
||||||
if optional:
|
if optional:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
visit_start_optional(v, &has_%(c_name)s, "%(name)s", errp);
|
visit_start_optional(v, &has_%(c_name)s, "%(name)s", %(errp)s);
|
||||||
if (has_%(c_name)s) {
|
if (has_%(c_name)s) {
|
||||||
''',
|
''',
|
||||||
c_name=c_var(argname), name=argname)
|
c_name=c_var(argname), name=argname, errp=errparg)
|
||||||
push_indent()
|
push_indent()
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
%(visitor)s(v, &%(c_name)s, "%(name)s", errp);
|
%(visitor)s(v, &%(c_name)s, "%(name)s", %(errp)s);
|
||||||
''',
|
''',
|
||||||
c_name=c_var(argname), name=argname, argtype=argtype,
|
c_name=c_var(argname), name=argname, argtype=argtype,
|
||||||
visitor=type_visitor(argtype))
|
visitor=type_visitor(argtype), errp=errparg)
|
||||||
if optional:
|
if optional:
|
||||||
pop_indent()
|
pop_indent()
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
}
|
}
|
||||||
visit_end_optional(v, errp);
|
visit_end_optional(v, %(errp)s);
|
||||||
''')
|
''', errp=errparg)
|
||||||
|
|
||||||
if dealloc:
|
if dealloc:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
@@ -194,7 +197,7 @@ static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_o
|
|||||||
}
|
}
|
||||||
qmp_output_visitor_cleanup(mo);
|
qmp_output_visitor_cleanup(mo);
|
||||||
v = qapi_dealloc_get_visitor(md);
|
v = qapi_dealloc_get_visitor(md);
|
||||||
%(visitor)s(v, &ret_in, "unused", errp);
|
%(visitor)s(v, &ret_in, "unused", NULL);
|
||||||
qapi_dealloc_visitor_cleanup(md);
|
qapi_dealloc_visitor_cleanup(md);
|
||||||
}
|
}
|
||||||
''',
|
''',
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
|
|
||||||
void vm_stop(RunState state)
|
int vm_stop(RunState state)
|
||||||
{
|
{
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@@ -3161,7 +3161,7 @@ static void check_breakpoint(CPUCRISState *env, DisasContext *dc)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* generate intermediate code for basic block 'tb'. */
|
/* generate intermediate code for basic block 'tb'. */
|
||||||
static void
|
static inline void
|
||||||
gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
|
gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
|
||||||
int search_pc)
|
int search_pc)
|
||||||
{
|
{
|
||||||
|
@@ -1820,7 +1820,11 @@ X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
error_propagate(errp, error);
|
if (error != NULL) {
|
||||||
|
error_propagate(errp, error);
|
||||||
|
object_unref(OBJECT(cpu));
|
||||||
|
cpu = NULL;
|
||||||
|
}
|
||||||
g_strfreev(model_pieces);
|
g_strfreev(model_pieces);
|
||||||
return cpu;
|
return cpu;
|
||||||
}
|
}
|
||||||
|
@@ -1011,8 +1011,9 @@ static void check_breakpoint(CPULM32State *env, DisasContext *dc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* generate intermediate code for basic block 'tb'. */
|
/* generate intermediate code for basic block 'tb'. */
|
||||||
static void gen_intermediate_code_internal(CPULM32State *env,
|
static inline
|
||||||
TranslationBlock *tb, int search_pc)
|
void gen_intermediate_code_internal(CPULM32State *env,
|
||||||
|
TranslationBlock *tb, int search_pc)
|
||||||
{
|
{
|
||||||
struct DisasContext ctx, *dc = &ctx;
|
struct DisasContext ctx, *dc = &ctx;
|
||||||
uint16_t *gen_opc_end;
|
uint16_t *gen_opc_end;
|
||||||
|
@@ -1737,7 +1737,7 @@ static void check_breakpoint(CPUMBState *env, DisasContext *dc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* generate intermediate code for basic block 'tb'. */
|
/* generate intermediate code for basic block 'tb'. */
|
||||||
static void
|
static inline void
|
||||||
gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
|
gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
|
||||||
int search_pc)
|
int search_pc)
|
||||||
{
|
{
|
||||||
|
@@ -818,7 +818,7 @@ static int decode_opc(MoxieCPU *cpu, DisasContext *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* generate intermediate code for basic block 'tb'. */
|
/* generate intermediate code for basic block 'tb'. */
|
||||||
static void
|
static inline void
|
||||||
gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
|
gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
|
||||||
bool search_pc)
|
bool search_pc)
|
||||||
{
|
{
|
||||||
|
@@ -97,12 +97,14 @@ static void openrisc_cpu_initfn(Object *obj)
|
|||||||
static ObjectClass *openrisc_cpu_class_by_name(const char *cpu_model)
|
static ObjectClass *openrisc_cpu_class_by_name(const char *cpu_model)
|
||||||
{
|
{
|
||||||
ObjectClass *oc;
|
ObjectClass *oc;
|
||||||
|
char *typename;
|
||||||
|
|
||||||
if (cpu_model == NULL) {
|
if (cpu_model == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
oc = object_class_by_name(cpu_model);
|
typename = g_strdup_printf("%s-" TYPE_OPENRISC_CPU, cpu_model);
|
||||||
|
oc = object_class_by_name(typename);
|
||||||
if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_OPENRISC_CPU) ||
|
if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_OPENRISC_CPU) ||
|
||||||
object_class_is_abstract(oc))) {
|
object_class_is_abstract(oc))) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@@ -4980,11 +4980,6 @@ static void init_proc_603E (CPUPPCState *env)
|
|||||||
SPR_NOACCESS, SPR_NOACCESS,
|
SPR_NOACCESS, SPR_NOACCESS,
|
||||||
&spr_read_generic, &spr_write_generic,
|
&spr_read_generic, &spr_write_generic,
|
||||||
0x00000000);
|
0x00000000);
|
||||||
/* XXX : not implemented */
|
|
||||||
spr_register(env, SPR_IABR, "IABR",
|
|
||||||
SPR_NOACCESS, SPR_NOACCESS,
|
|
||||||
&spr_read_generic, &spr_write_generic,
|
|
||||||
0x00000000);
|
|
||||||
/* Memory management */
|
/* Memory management */
|
||||||
gen_low_BATs(env);
|
gen_low_BATs(env);
|
||||||
gen_6xx_7xx_soft_tlb(env, 64, 2);
|
gen_6xx_7xx_soft_tlb(env, 64, 2);
|
||||||
|
@@ -2875,8 +2875,9 @@ static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_intermediate_code_internal(
|
static inline
|
||||||
CPUXtensaState *env, TranslationBlock *tb, int search_pc)
|
void gen_intermediate_code_internal(CPUXtensaState *env,
|
||||||
|
TranslationBlock *tb, int search_pc)
|
||||||
{
|
{
|
||||||
DisasContext dc;
|
DisasContext dc;
|
||||||
int insn_count = 0;
|
int insn_count = 0;
|
||||||
|
4
ui/gtk.c
4
ui/gtk.c
@@ -377,7 +377,11 @@ static void gd_cursor_define(DisplayChangeListener *dcl,
|
|||||||
pixbuf, c->hot_x, c->hot_y);
|
pixbuf, c->hot_x, c->hot_y);
|
||||||
gdk_window_set_cursor(gtk_widget_get_window(s->drawing_area), cursor);
|
gdk_window_set_cursor(gtk_widget_get_window(s->drawing_area), cursor);
|
||||||
g_object_unref(pixbuf);
|
g_object_unref(pixbuf);
|
||||||
|
#if !GTK_CHECK_VERSION(3, 0, 0)
|
||||||
|
gdk_cursor_unref(cursor);
|
||||||
|
#else
|
||||||
g_object_unref(cursor);
|
g_object_unref(cursor);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gd_switch(DisplayChangeListener *dcl,
|
static void gd_switch(DisplayChangeListener *dcl,
|
||||||
|
@@ -138,9 +138,9 @@ int qemu_acl_insert(qemu_acl *acl,
|
|||||||
|
|
||||||
if (index <= 0)
|
if (index <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (index >= acl->nentries)
|
if (index > acl->nentries) {
|
||||||
return qemu_acl_append(acl, deny, match);
|
return qemu_acl_append(acl, deny, match);
|
||||||
|
}
|
||||||
|
|
||||||
entry = g_malloc(sizeof(*entry));
|
entry = g_malloc(sizeof(*entry));
|
||||||
entry->match = g_strdup(match);
|
entry->match = g_strdup(match);
|
||||||
|
@@ -202,6 +202,12 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret == 0 && !do_send) {
|
||||||
|
/* recv returns 0 when the peer has performed an orderly
|
||||||
|
* shutdown. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Prepare for the next iteration */
|
/* Prepare for the next iteration */
|
||||||
offset += ret;
|
offset += ret;
|
||||||
total += ret;
|
total += ret;
|
||||||
|
@@ -170,12 +170,11 @@ void qemu_sem_post(QemuSemaphore *sem)
|
|||||||
|
|
||||||
#if defined(__APPLE__) || defined(__NetBSD__)
|
#if defined(__APPLE__) || defined(__NetBSD__)
|
||||||
pthread_mutex_lock(&sem->lock);
|
pthread_mutex_lock(&sem->lock);
|
||||||
if (sem->count == INT_MAX) {
|
if (sem->count == UINT_MAX) {
|
||||||
rc = EINVAL;
|
rc = EINVAL;
|
||||||
} else if (sem->count++ < 0) {
|
|
||||||
rc = pthread_cond_signal(&sem->cond);
|
|
||||||
} else {
|
} else {
|
||||||
rc = 0;
|
sem->count++;
|
||||||
|
rc = pthread_cond_signal(&sem->cond);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&sem->lock);
|
pthread_mutex_unlock(&sem->lock);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
@@ -207,19 +206,21 @@ int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
|
|||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__NetBSD__)
|
#if defined(__APPLE__) || defined(__NetBSD__)
|
||||||
|
rc = 0;
|
||||||
compute_abs_deadline(&ts, ms);
|
compute_abs_deadline(&ts, ms);
|
||||||
pthread_mutex_lock(&sem->lock);
|
pthread_mutex_lock(&sem->lock);
|
||||||
--sem->count;
|
while (sem->count == 0) {
|
||||||
while (sem->count < 0) {
|
|
||||||
rc = pthread_cond_timedwait(&sem->cond, &sem->lock, &ts);
|
rc = pthread_cond_timedwait(&sem->cond, &sem->lock, &ts);
|
||||||
if (rc == ETIMEDOUT) {
|
if (rc == ETIMEDOUT) {
|
||||||
++sem->count;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
error_exit(rc, __func__);
|
error_exit(rc, __func__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rc != ETIMEDOUT) {
|
||||||
|
--sem->count;
|
||||||
|
}
|
||||||
pthread_mutex_unlock(&sem->lock);
|
pthread_mutex_unlock(&sem->lock);
|
||||||
return (rc == ETIMEDOUT ? -1 : 0);
|
return (rc == ETIMEDOUT ? -1 : 0);
|
||||||
#else
|
#else
|
||||||
@@ -249,16 +250,19 @@ int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
|
|||||||
|
|
||||||
void qemu_sem_wait(QemuSemaphore *sem)
|
void qemu_sem_wait(QemuSemaphore *sem)
|
||||||
{
|
{
|
||||||
#if defined(__APPLE__) || defined(__NetBSD__)
|
|
||||||
pthread_mutex_lock(&sem->lock);
|
|
||||||
--sem->count;
|
|
||||||
while (sem->count < 0) {
|
|
||||||
pthread_cond_wait(&sem->cond, &sem->lock);
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&sem->lock);
|
|
||||||
#else
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
#if defined(__APPLE__) || defined(__NetBSD__)
|
||||||
|
pthread_mutex_lock(&sem->lock);
|
||||||
|
while (sem->count == 0) {
|
||||||
|
rc = pthread_cond_wait(&sem->cond, &sem->lock);
|
||||||
|
if (rc != 0) {
|
||||||
|
error_exit(rc, __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--sem->count;
|
||||||
|
pthread_mutex_unlock(&sem->lock);
|
||||||
|
#else
|
||||||
do {
|
do {
|
||||||
rc = sem_wait(&sem->sem);
|
rc = sem_wait(&sem->sem);
|
||||||
} while (rc == -1 && errno == EINTR);
|
} while (rc == -1 && errno == EINTR);
|
||||||
|
Reference in New Issue
Block a user