Compare commits
84 Commits
v1.1.0-rc2
...
v1.1.0
Author | SHA1 | Date | |
---|---|---|---|
|
78260a5f08 | ||
|
b3dbb9546a | ||
|
272d28ecf2 | ||
|
6f12926142 | ||
|
d6111501c1 | ||
|
eba25057b9 | ||
|
e78bd5ab07 | ||
|
1643f2b232 | ||
|
1352672860 | ||
|
9e2fa418fb | ||
|
eecae14724 | ||
|
a6de8ed80e | ||
|
9c3a596a03 | ||
|
8294a64d7f | ||
|
1c4ad9d2b4 | ||
|
60b46aa2f3 | ||
|
f283edc482 | ||
|
dd86df756e | ||
|
422831fc81 | ||
|
306761537f | ||
|
7943df571a | ||
|
d501f8478a | ||
|
917cfc1f26 | ||
|
9b24d8e987 | ||
|
f4dfa67f04 | ||
|
6bcd1346bb | ||
|
dbfff6d776 | ||
|
c7b4a95202 | ||
|
c9b9f6824f | ||
|
e20e48a802 | ||
|
24f50d7ea5 | ||
|
7cd331617a | ||
|
cfb08fbafc | ||
|
9ecd394753 | ||
|
b84762e245 | ||
|
df02179189 | ||
|
b6fc8245e9 | ||
|
cb595887cc | ||
|
622b6057be | ||
|
9fda6ab1d9 | ||
|
b6c147622d | ||
|
12badfc238 | ||
|
2c02cbf6e9 | ||
|
8ab1bf120d | ||
|
aeb29b6459 | ||
|
f8687bab91 | ||
|
c48b0c80fc | ||
|
4accd107d0 | ||
|
a340046614 | ||
|
2a633c461e | ||
|
a6c5c84ae2 | ||
|
12c5674b84 | ||
|
0e47931b88 | ||
|
f34e73cd69 | ||
|
80a2ba3d3c | ||
|
b4f1a7ca72 | ||
|
fba0c40bb7 | ||
|
fd4567d9a6 | ||
|
d7f66b52de | ||
|
77a8f1a512 | ||
|
4636b9d146 | ||
|
5f2bf0fe55 | ||
|
a28853871d | ||
|
ace2e4dad7 | ||
|
180640ea07 | ||
|
a4f1a7589a | ||
|
ed54776643 | ||
|
c6961b7d38 | ||
|
ba1dffed63 | ||
|
95d5d75ede | ||
|
c2d8d311c1 | ||
|
8efacc43ae | ||
|
6c615ec57e | ||
|
3674838cd0 | ||
|
d5dd3498eb | ||
|
dc8764f061 | ||
|
226a48949c | ||
|
04b4e75f33 | ||
|
d9fcd2a1c8 | ||
|
432d29db0d | ||
|
c6fcc10ab3 | ||
|
8926817219 | ||
|
ce8c8b7bd8 | ||
|
d34b867d81 |
@@ -100,6 +100,10 @@ const uint32_t arch_type = QEMU_ARCH;
|
||||
#define VECTYPE vector unsigned char
|
||||
#define SPLAT(p) vec_splat(vec_ld(0, p), 0)
|
||||
#define ALL_EQ(v1, v2) vec_all_eq(v1, v2)
|
||||
/* altivec.h may redefine the bool macro as vector type.
|
||||
* Reset it to POSIX semantics. */
|
||||
#undef bool
|
||||
#define bool _Bool
|
||||
#elif defined __SSE2__
|
||||
#include <emmintrin.h>
|
||||
#define VECTYPE __m128i
|
||||
|
@@ -1775,10 +1775,12 @@ static void audio_atexit (void)
|
||||
HWVoiceOut *hwo = NULL;
|
||||
HWVoiceIn *hwi = NULL;
|
||||
|
||||
while ((hwo = audio_pcm_hw_find_any_enabled_out (hwo))) {
|
||||
while ((hwo = audio_pcm_hw_find_any_out (hwo))) {
|
||||
SWVoiceCap *sc;
|
||||
|
||||
hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
|
||||
if (hwo->enabled) {
|
||||
hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
|
||||
}
|
||||
hwo->pcm_ops->fini_out (hwo);
|
||||
|
||||
for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) {
|
||||
@@ -1791,8 +1793,10 @@ static void audio_atexit (void)
|
||||
}
|
||||
}
|
||||
|
||||
while ((hwi = audio_pcm_hw_find_any_enabled_in (hwi))) {
|
||||
hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
|
||||
while ((hwi = audio_pcm_hw_find_any_in (hwi))) {
|
||||
if (hwi->enabled) {
|
||||
hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
|
||||
}
|
||||
hwi->pcm_ops->fini_in (hwi);
|
||||
}
|
||||
|
||||
|
@@ -33,7 +33,8 @@
|
||||
#define ENDIAN_CONVERT(v) (v)
|
||||
|
||||
/* Signed 8 bit */
|
||||
#define IN_T int8_t
|
||||
#define BSIZE 8
|
||||
#define ITYPE int
|
||||
#define IN_MIN SCHAR_MIN
|
||||
#define IN_MAX SCHAR_MAX
|
||||
#define SIGNED
|
||||
@@ -42,25 +43,29 @@
|
||||
#undef SIGNED
|
||||
#undef IN_MAX
|
||||
#undef IN_MIN
|
||||
#undef IN_T
|
||||
#undef BSIZE
|
||||
#undef ITYPE
|
||||
#undef SHIFT
|
||||
|
||||
/* Unsigned 8 bit */
|
||||
#define IN_T uint8_t
|
||||
#define BSIZE 8
|
||||
#define ITYPE uint
|
||||
#define IN_MIN 0
|
||||
#define IN_MAX UCHAR_MAX
|
||||
#define SHIFT 8
|
||||
#include "mixeng_template.h"
|
||||
#undef IN_MAX
|
||||
#undef IN_MIN
|
||||
#undef IN_T
|
||||
#undef BSIZE
|
||||
#undef ITYPE
|
||||
#undef SHIFT
|
||||
|
||||
#undef ENDIAN_CONVERT
|
||||
#undef ENDIAN_CONVERSION
|
||||
|
||||
/* Signed 16 bit */
|
||||
#define IN_T int16_t
|
||||
#define BSIZE 16
|
||||
#define ITYPE int
|
||||
#define IN_MIN SHRT_MIN
|
||||
#define IN_MAX SHRT_MAX
|
||||
#define SIGNED
|
||||
@@ -78,11 +83,13 @@
|
||||
#undef SIGNED
|
||||
#undef IN_MAX
|
||||
#undef IN_MIN
|
||||
#undef IN_T
|
||||
#undef BSIZE
|
||||
#undef ITYPE
|
||||
#undef SHIFT
|
||||
|
||||
/* Unsigned 16 bit */
|
||||
#define IN_T uint16_t
|
||||
#define BSIZE 16
|
||||
#define ITYPE uint
|
||||
#define IN_MIN 0
|
||||
#define IN_MAX USHRT_MAX
|
||||
#define SHIFT 16
|
||||
@@ -98,11 +105,13 @@
|
||||
#undef ENDIAN_CONVERSION
|
||||
#undef IN_MAX
|
||||
#undef IN_MIN
|
||||
#undef IN_T
|
||||
#undef BSIZE
|
||||
#undef ITYPE
|
||||
#undef SHIFT
|
||||
|
||||
/* Signed 32 bit */
|
||||
#define IN_T int32_t
|
||||
#define BSIZE 32
|
||||
#define ITYPE int
|
||||
#define IN_MIN INT32_MIN
|
||||
#define IN_MAX INT32_MAX
|
||||
#define SIGNED
|
||||
@@ -120,11 +129,13 @@
|
||||
#undef SIGNED
|
||||
#undef IN_MAX
|
||||
#undef IN_MIN
|
||||
#undef IN_T
|
||||
#undef BSIZE
|
||||
#undef ITYPE
|
||||
#undef SHIFT
|
||||
|
||||
/* Unsigned 32 bit */
|
||||
#define IN_T uint32_t
|
||||
#define BSIZE 32
|
||||
#define ITYPE uint
|
||||
#define IN_MIN 0
|
||||
#define IN_MAX UINT32_MAX
|
||||
#define SHIFT 32
|
||||
@@ -140,7 +151,8 @@
|
||||
#undef ENDIAN_CONVERSION
|
||||
#undef IN_MAX
|
||||
#undef IN_MIN
|
||||
#undef IN_T
|
||||
#undef BSIZE
|
||||
#undef ITYPE
|
||||
#undef SHIFT
|
||||
|
||||
t_sample *mixeng_conv[2][2][2][3] = {
|
||||
|
@@ -31,7 +31,8 @@
|
||||
#define HALF (IN_MAX >> 1)
|
||||
#endif
|
||||
|
||||
#define ET glue (ENDIAN_CONVERSION, glue (_, IN_T))
|
||||
#define ET glue (ENDIAN_CONVERSION, glue (glue (glue (_, ITYPE), BSIZE), _t))
|
||||
#define IN_T glue (glue (ITYPE, BSIZE), _t)
|
||||
|
||||
#ifdef FLOAT_MIXENG
|
||||
static mixeng_real inline glue (conv_, ET) (IN_T v)
|
||||
@@ -150,3 +151,4 @@ static void glue (glue (clip_, ET), _from_mono)
|
||||
|
||||
#undef ET
|
||||
#undef HALF
|
||||
#undef IN_T
|
||||
|
37
block.c
37
block.c
@@ -409,28 +409,36 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
|
||||
return bdrv_create(drv, filename, options);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a uniquely-named empty temporary file.
|
||||
* Return 0 upon success, otherwise a negative errno value.
|
||||
*/
|
||||
int get_tmp_filename(char *filename, int size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
void get_tmp_filename(char *filename, int size)
|
||||
{
|
||||
char temp_dir[MAX_PATH];
|
||||
|
||||
GetTempPath(MAX_PATH, temp_dir);
|
||||
GetTempFileName(temp_dir, "qem", 0, filename);
|
||||
}
|
||||
/* GetTempFileName requires that its output buffer (4th param)
|
||||
have length MAX_PATH or greater. */
|
||||
assert(size >= MAX_PATH);
|
||||
return (GetTempPath(MAX_PATH, temp_dir)
|
||||
&& GetTempFileName(temp_dir, "qem", 0, filename)
|
||||
? 0 : -GetLastError());
|
||||
#else
|
||||
void get_tmp_filename(char *filename, int size)
|
||||
{
|
||||
int fd;
|
||||
const char *tmpdir;
|
||||
/* XXX: race condition possible */
|
||||
tmpdir = getenv("TMPDIR");
|
||||
if (!tmpdir)
|
||||
tmpdir = "/tmp";
|
||||
snprintf(filename, size, "%s/vl.XXXXXX", tmpdir);
|
||||
if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
fd = mkstemp(filename);
|
||||
close(fd);
|
||||
}
|
||||
if (fd < 0 || close(fd)) {
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect host devices. By convention, /dev/cdrom[N] is always
|
||||
@@ -753,7 +761,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
|
||||
|
||||
bdrv_delete(bs1);
|
||||
|
||||
get_tmp_filename(tmp_filename, sizeof(tmp_filename));
|
||||
ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Real path is meaningless for protocols */
|
||||
if (is_protocol)
|
||||
|
240
block/iscsi.c
240
block/iscsi.c
@@ -25,10 +25,12 @@
|
||||
#include "config-host.h"
|
||||
|
||||
#include <poll.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "qemu-common.h"
|
||||
#include "qemu-error.h"
|
||||
#include "block_int.h"
|
||||
#include "trace.h"
|
||||
#include "hw/scsi-defs.h"
|
||||
|
||||
#include <iscsi/iscsi.h>
|
||||
#include <iscsi/scsi-lowlevel.h>
|
||||
@@ -37,8 +39,10 @@
|
||||
typedef struct IscsiLun {
|
||||
struct iscsi_context *iscsi;
|
||||
int lun;
|
||||
enum scsi_inquiry_peripheral_device_type type;
|
||||
int block_size;
|
||||
unsigned long num_blocks;
|
||||
uint64_t num_blocks;
|
||||
int events;
|
||||
} IscsiLun;
|
||||
|
||||
typedef struct IscsiAIOCB {
|
||||
@@ -104,11 +108,27 @@ static void
|
||||
iscsi_set_events(IscsiLun *iscsilun)
|
||||
{
|
||||
struct iscsi_context *iscsi = iscsilun->iscsi;
|
||||
int ev;
|
||||
|
||||
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), iscsi_process_read,
|
||||
(iscsi_which_events(iscsi) & POLLOUT)
|
||||
? iscsi_process_write : NULL,
|
||||
iscsi_process_flush, iscsilun);
|
||||
/* We always register a read handler. */
|
||||
ev = POLLIN;
|
||||
ev |= iscsi_which_events(iscsi);
|
||||
if (ev != iscsilun->events) {
|
||||
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
|
||||
iscsi_process_read,
|
||||
(ev & POLLOUT) ? iscsi_process_write : NULL,
|
||||
iscsi_process_flush,
|
||||
iscsilun);
|
||||
|
||||
}
|
||||
|
||||
/* If we just added an event, the callback might be delayed
|
||||
* unless we call qemu_notify_event().
|
||||
*/
|
||||
if (ev & ~iscsilun->events) {
|
||||
qemu_notify_event();
|
||||
}
|
||||
iscsilun->events = ev;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -161,12 +181,12 @@ iscsi_readv_writev_bh_cb(void *p)
|
||||
|
||||
|
||||
static void
|
||||
iscsi_aio_write10_cb(struct iscsi_context *iscsi, int status,
|
||||
iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
|
||||
void *command_data, void *opaque)
|
||||
{
|
||||
IscsiAIOCB *acb = opaque;
|
||||
|
||||
trace_iscsi_aio_write10_cb(iscsi, status, acb, acb->canceled);
|
||||
trace_iscsi_aio_write16_cb(iscsi, status, acb, acb->canceled);
|
||||
|
||||
g_free(acb->buf);
|
||||
|
||||
@@ -179,7 +199,7 @@ iscsi_aio_write10_cb(struct iscsi_context *iscsi, int status,
|
||||
|
||||
acb->status = 0;
|
||||
if (status < 0) {
|
||||
error_report("Failed to write10 data to iSCSI lun. %s",
|
||||
error_report("Failed to write16 data to iSCSI lun. %s",
|
||||
iscsi_get_error(iscsi));
|
||||
acb->status = -EIO;
|
||||
}
|
||||
@@ -204,12 +224,9 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
struct iscsi_context *iscsi = iscsilun->iscsi;
|
||||
IscsiAIOCB *acb;
|
||||
size_t size;
|
||||
int fua = 0;
|
||||
|
||||
/* set FUA on writes when cache mode is write through */
|
||||
if (!(bs->open_flags & BDRV_O_CACHE_WB)) {
|
||||
fua = 1;
|
||||
}
|
||||
uint32_t num_sectors;
|
||||
uint64_t lba;
|
||||
struct iscsi_data data;
|
||||
|
||||
acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
|
||||
trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
|
||||
@@ -219,18 +236,44 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
acb->canceled = 0;
|
||||
|
||||
/* XXX we should pass the iovec to write10 to avoid the extra copy */
|
||||
/* XXX we should pass the iovec to write16 to avoid the extra copy */
|
||||
/* this will allow us to get rid of 'buf' completely */
|
||||
size = nb_sectors * BDRV_SECTOR_SIZE;
|
||||
acb->buf = g_malloc(size);
|
||||
qemu_iovec_to_buffer(acb->qiov, acb->buf);
|
||||
acb->task = iscsi_write10_task(iscsi, iscsilun->lun, acb->buf, size,
|
||||
sector_qemu2lun(sector_num, iscsilun),
|
||||
fua, 0, iscsilun->block_size,
|
||||
iscsi_aio_write10_cb, acb);
|
||||
|
||||
|
||||
acb->task = malloc(sizeof(struct scsi_task));
|
||||
if (acb->task == NULL) {
|
||||
error_report("iSCSI: Failed to send write10 command. %s",
|
||||
iscsi_get_error(iscsi));
|
||||
error_report("iSCSI: Failed to allocate task for scsi WRITE16 "
|
||||
"command. %s", iscsi_get_error(iscsi));
|
||||
qemu_aio_release(acb);
|
||||
return NULL;
|
||||
}
|
||||
memset(acb->task, 0, sizeof(struct scsi_task));
|
||||
|
||||
acb->task->xfer_dir = SCSI_XFER_WRITE;
|
||||
acb->task->cdb_size = 16;
|
||||
acb->task->cdb[0] = 0x8a;
|
||||
if (!(bs->open_flags & BDRV_O_CACHE_WB)) {
|
||||
/* set FUA on writes when cache mode is write through */
|
||||
acb->task->cdb[1] |= 0x04;
|
||||
}
|
||||
lba = sector_qemu2lun(sector_num, iscsilun);
|
||||
*(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32);
|
||||
*(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff);
|
||||
num_sectors = size / iscsilun->block_size;
|
||||
*(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
|
||||
acb->task->expxferlen = size;
|
||||
|
||||
data.data = acb->buf;
|
||||
data.size = size;
|
||||
|
||||
if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
|
||||
iscsi_aio_write16_cb,
|
||||
&data,
|
||||
acb) != 0) {
|
||||
scsi_free_scsi_task(acb->task);
|
||||
g_free(acb->buf);
|
||||
qemu_aio_release(acb);
|
||||
return NULL;
|
||||
@@ -242,12 +285,12 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_aio_read10_cb(struct iscsi_context *iscsi, int status,
|
||||
iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
|
||||
void *command_data, void *opaque)
|
||||
{
|
||||
IscsiAIOCB *acb = opaque;
|
||||
|
||||
trace_iscsi_aio_read10_cb(iscsi, status, acb, acb->canceled);
|
||||
trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled);
|
||||
|
||||
if (acb->canceled != 0) {
|
||||
qemu_aio_release(acb);
|
||||
@@ -258,7 +301,7 @@ iscsi_aio_read10_cb(struct iscsi_context *iscsi, int status,
|
||||
|
||||
acb->status = 0;
|
||||
if (status != 0) {
|
||||
error_report("Failed to read10 data from iSCSI lun. %s",
|
||||
error_report("Failed to read16 data from iSCSI lun. %s",
|
||||
iscsi_get_error(iscsi));
|
||||
acb->status = -EIO;
|
||||
}
|
||||
@@ -277,8 +320,10 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
struct iscsi_context *iscsi = iscsilun->iscsi;
|
||||
IscsiAIOCB *acb;
|
||||
size_t qemu_read_size, lun_read_size;
|
||||
size_t qemu_read_size;
|
||||
int i;
|
||||
uint64_t lba;
|
||||
uint32_t num_sectors;
|
||||
|
||||
qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
|
||||
|
||||
@@ -303,16 +348,44 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
acb->read_offset = bdrv_offset % iscsilun->block_size;
|
||||
}
|
||||
|
||||
lun_read_size = (qemu_read_size + iscsilun->block_size
|
||||
+ acb->read_offset - 1)
|
||||
/ iscsilun->block_size * iscsilun->block_size;
|
||||
acb->task = iscsi_read10_task(iscsi, iscsilun->lun,
|
||||
sector_qemu2lun(sector_num, iscsilun),
|
||||
lun_read_size, iscsilun->block_size,
|
||||
iscsi_aio_read10_cb, acb);
|
||||
num_sectors = (qemu_read_size + iscsilun->block_size
|
||||
+ acb->read_offset - 1)
|
||||
/ iscsilun->block_size;
|
||||
|
||||
acb->task = malloc(sizeof(struct scsi_task));
|
||||
if (acb->task == NULL) {
|
||||
error_report("iSCSI: Failed to send read10 command. %s",
|
||||
iscsi_get_error(iscsi));
|
||||
error_report("iSCSI: Failed to allocate task for scsi READ16 "
|
||||
"command. %s", iscsi_get_error(iscsi));
|
||||
qemu_aio_release(acb);
|
||||
return NULL;
|
||||
}
|
||||
memset(acb->task, 0, sizeof(struct scsi_task));
|
||||
|
||||
acb->task->xfer_dir = SCSI_XFER_READ;
|
||||
lba = sector_qemu2lun(sector_num, iscsilun);
|
||||
acb->task->expxferlen = qemu_read_size;
|
||||
|
||||
switch (iscsilun->type) {
|
||||
case TYPE_DISK:
|
||||
acb->task->cdb_size = 16;
|
||||
acb->task->cdb[0] = 0x88;
|
||||
*(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32);
|
||||
*(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff);
|
||||
*(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
|
||||
break;
|
||||
default:
|
||||
acb->task->cdb_size = 10;
|
||||
acb->task->cdb[0] = 0x28;
|
||||
*(uint32_t *)&acb->task->cdb[2] = htonl(lba);
|
||||
*(uint16_t *)&acb->task->cdb[7] = htons(num_sectors);
|
||||
break;
|
||||
}
|
||||
|
||||
if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
|
||||
iscsi_aio_read16_cb,
|
||||
NULL,
|
||||
acb) != 0) {
|
||||
scsi_free_scsi_task(acb->task);
|
||||
qemu_aio_release(acb);
|
||||
return NULL;
|
||||
}
|
||||
@@ -490,6 +563,98 @@ iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status,
|
||||
scsi_free_scsi_task(task);
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
|
||||
void *command_data, void *opaque)
|
||||
{
|
||||
struct IscsiTask *itask = opaque;
|
||||
struct scsi_readcapacity10 *rc10;
|
||||
struct scsi_task *task = command_data;
|
||||
|
||||
if (status != 0) {
|
||||
error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
|
||||
iscsi_get_error(iscsi));
|
||||
itask->status = 1;
|
||||
itask->complete = 1;
|
||||
scsi_free_scsi_task(task);
|
||||
return;
|
||||
}
|
||||
|
||||
rc10 = scsi_datain_unmarshall(task);
|
||||
if (rc10 == NULL) {
|
||||
error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
|
||||
itask->status = 1;
|
||||
itask->complete = 1;
|
||||
scsi_free_scsi_task(task);
|
||||
return;
|
||||
}
|
||||
|
||||
itask->iscsilun->block_size = rc10->block_size;
|
||||
itask->iscsilun->num_blocks = rc10->lba + 1;
|
||||
itask->bs->total_sectors = itask->iscsilun->num_blocks *
|
||||
itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
|
||||
|
||||
itask->status = 0;
|
||||
itask->complete = 1;
|
||||
scsi_free_scsi_task(task);
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data,
|
||||
void *opaque)
|
||||
{
|
||||
struct IscsiTask *itask = opaque;
|
||||
struct scsi_task *task = command_data;
|
||||
struct scsi_inquiry_standard *inq;
|
||||
|
||||
if (status != 0) {
|
||||
itask->status = 1;
|
||||
itask->complete = 1;
|
||||
scsi_free_scsi_task(task);
|
||||
return;
|
||||
}
|
||||
|
||||
inq = scsi_datain_unmarshall(task);
|
||||
if (inq == NULL) {
|
||||
error_report("iSCSI: Failed to unmarshall inquiry data.");
|
||||
itask->status = 1;
|
||||
itask->complete = 1;
|
||||
scsi_free_scsi_task(task);
|
||||
return;
|
||||
}
|
||||
|
||||
itask->iscsilun->type = inq->periperal_device_type;
|
||||
|
||||
scsi_free_scsi_task(task);
|
||||
|
||||
switch (itask->iscsilun->type) {
|
||||
case TYPE_DISK:
|
||||
task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun,
|
||||
iscsi_readcapacity16_cb, opaque);
|
||||
if (task == NULL) {
|
||||
error_report("iSCSI: failed to send readcapacity16 command.");
|
||||
itask->status = 1;
|
||||
itask->complete = 1;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case TYPE_ROM:
|
||||
task = iscsi_readcapacity10_task(iscsi, itask->iscsilun->lun,
|
||||
0, 0,
|
||||
iscsi_readcapacity10_cb, opaque);
|
||||
if (task == NULL) {
|
||||
error_report("iSCSI: failed to send readcapacity16 command.");
|
||||
itask->status = 1;
|
||||
itask->complete = 1;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
itask->status = 0;
|
||||
itask->complete = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
|
||||
void *opaque)
|
||||
@@ -503,10 +668,11 @@ iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
|
||||
return;
|
||||
}
|
||||
|
||||
task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun,
|
||||
iscsi_readcapacity16_cb, opaque);
|
||||
task = iscsi_inquiry_task(iscsi, itask->iscsilun->lun,
|
||||
0, 0, 36,
|
||||
iscsi_inquiry_cb, opaque);
|
||||
if (task == NULL) {
|
||||
error_report("iSCSI: failed to send readcapacity16 command.");
|
||||
error_report("iSCSI: failed to send inquiry command.");
|
||||
itask->status = 1;
|
||||
itask->complete = 1;
|
||||
return;
|
||||
|
@@ -762,7 +762,6 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
|
||||
uint64_t *host_offset, unsigned int *nb_clusters)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
int64_t cluster_offset;
|
||||
QCowL2Meta *old_alloc;
|
||||
|
||||
trace_qcow2_do_alloc_clusters_offset(qemu_coroutine_self(), guest_offset,
|
||||
@@ -808,17 +807,21 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
|
||||
/* Allocate new clusters */
|
||||
trace_qcow2_cluster_alloc_phys(qemu_coroutine_self());
|
||||
if (*host_offset == 0) {
|
||||
cluster_offset = qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size);
|
||||
int64_t cluster_offset =
|
||||
qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size);
|
||||
if (cluster_offset < 0) {
|
||||
return cluster_offset;
|
||||
}
|
||||
*host_offset = cluster_offset;
|
||||
return 0;
|
||||
} else {
|
||||
cluster_offset = *host_offset;
|
||||
*nb_clusters = qcow2_alloc_clusters_at(bs, cluster_offset, *nb_clusters);
|
||||
int ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
*nb_clusters = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cluster_offset < 0) {
|
||||
return cluster_offset;
|
||||
}
|
||||
*host_offset = cluster_offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -919,7 +919,8 @@ int qcow2_update_header(BlockDriverState *bs)
|
||||
ret = sizeof(*header);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
buf += ret;
|
||||
|
113
block/sheepdog.c
113
block/sheepdog.c
@@ -468,7 +468,7 @@ static int connect_to_sdog(const char *addr, const char *port)
|
||||
if (ret) {
|
||||
error_report("unable to get address info %s, %s",
|
||||
addr, strerror(errno));
|
||||
return -1;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
@@ -495,7 +495,7 @@ static int connect_to_sdog(const char *addr, const char *port)
|
||||
dprintf("connected to %s:%s\n", addr, port);
|
||||
goto success;
|
||||
}
|
||||
fd = -1;
|
||||
fd = -errno;
|
||||
error_report("failed connect to %s:%s", addr, port);
|
||||
success:
|
||||
freeaddrinfo(res0);
|
||||
@@ -510,12 +510,13 @@ static int send_req(int sockfd, SheepdogReq *hdr, void *data,
|
||||
ret = qemu_send_full(sockfd, hdr, sizeof(*hdr), 0);
|
||||
if (ret < sizeof(*hdr)) {
|
||||
error_report("failed to send a req, %s", strerror(errno));
|
||||
return ret;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
ret = qemu_send_full(sockfd, data, *wlen, 0);
|
||||
if (ret < *wlen) {
|
||||
error_report("failed to send a req, %s", strerror(errno));
|
||||
ret = -errno;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -553,6 +554,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
|
||||
ret = qemu_recv_full(sockfd, hdr, sizeof(*hdr), 0);
|
||||
if (ret < sizeof(*hdr)) {
|
||||
error_report("failed to get a rsp, %s", strerror(errno));
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -564,6 +566,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
|
||||
ret = qemu_recv_full(sockfd, data, *rlen, 0);
|
||||
if (ret < *rlen) {
|
||||
error_report("failed to get the data, %s", strerror(errno));
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -587,6 +590,7 @@ static int do_co_req(int sockfd, SheepdogReq *hdr, void *data,
|
||||
ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
|
||||
if (ret < sizeof(*hdr)) {
|
||||
error_report("failed to get a rsp, %s", strerror(errno));
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -598,6 +602,7 @@ static int do_co_req(int sockfd, SheepdogReq *hdr, void *data,
|
||||
ret = qemu_co_recv(sockfd, data, *rlen);
|
||||
if (ret < *rlen) {
|
||||
error_report("failed to get the data, %s", strerror(errno));
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -787,7 +792,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
error_report("%s", strerror(errno));
|
||||
return -1;
|
||||
return fd;
|
||||
}
|
||||
|
||||
socket_set_nonblock(fd);
|
||||
@@ -796,7 +801,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
|
||||
if (ret) {
|
||||
error_report("%s", strerror(errno));
|
||||
closesocket(fd);
|
||||
return -1;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
qemu_aio_set_fd_handler(fd, co_read_response, NULL, aio_flush_request, s);
|
||||
@@ -883,7 +888,7 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
|
||||
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
return fd;
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
@@ -904,14 +909,17 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
|
||||
|
||||
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
|
||||
if (ret) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rsp->result != SD_RES_SUCCESS) {
|
||||
error_report("cannot get vdi info, %s, %s %d %s",
|
||||
sd_strerror(rsp->result), filename, snapid, tag);
|
||||
ret = -1;
|
||||
if (rsp->result == SD_RES_NO_VDI) {
|
||||
ret = -ENOENT;
|
||||
} else {
|
||||
ret = -EIO;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
*vid = rsp->vdi_id;
|
||||
@@ -980,7 +988,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
||||
if (ret < 0) {
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
error_report("failed to send a req, %s", strerror(errno));
|
||||
return -EIO;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (wlen) {
|
||||
@@ -988,7 +996,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
||||
if (ret < 0) {
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
error_report("failed to send a data, %s", strerror(errno));
|
||||
return -EIO;
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1038,7 +1046,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
|
||||
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
|
||||
if (ret) {
|
||||
error_report("failed to send a request to the sheep");
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (rsp->result) {
|
||||
@@ -1046,7 +1054,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
|
||||
return 0;
|
||||
default:
|
||||
error_report("%s", sd_strerror(rsp->result));
|
||||
return -1;
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1082,10 +1090,12 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
|
||||
memset(vdi, 0, sizeof(vdi));
|
||||
memset(tag, 0, sizeof(tag));
|
||||
if (parse_vdiname(s, filename, vdi, &snapid, tag) < 0) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
s->fd = get_sheep_fd(s);
|
||||
if (s->fd < 0) {
|
||||
ret = s->fd;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1099,11 +1109,12 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
|
||||
s->flush_fd = connect_to_sdog(s->addr, s->port);
|
||||
if (s->flush_fd < 0) {
|
||||
error_report("failed to connect");
|
||||
ret = s->flush_fd;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (snapid) {
|
||||
if (snapid || tag[0] != '\0') {
|
||||
dprintf("%" PRIx32 " snapshot inode was open.\n", vid);
|
||||
s->is_snapshot = 1;
|
||||
}
|
||||
@@ -1111,6 +1122,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
error_report("failed to connect");
|
||||
ret = fd;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1139,7 +1151,7 @@ out:
|
||||
closesocket(s->fd);
|
||||
}
|
||||
g_free(buf);
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int do_sd_create(char *filename, int64_t vdi_size,
|
||||
@@ -1154,7 +1166,7 @@ static int do_sd_create(char *filename, int64_t vdi_size,
|
||||
|
||||
fd = connect_to_sdog(addr, port);
|
||||
if (fd < 0) {
|
||||
return -EIO;
|
||||
return fd;
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
@@ -1177,7 +1189,7 @@ static int do_sd_create(char *filename, int64_t vdi_size,
|
||||
closesocket(fd);
|
||||
|
||||
if (ret) {
|
||||
return -EIO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rsp->result != SD_RES_SUCCESS) {
|
||||
@@ -1237,24 +1249,26 @@ out:
|
||||
|
||||
static int sd_create(const char *filename, QEMUOptionParameter *options)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
uint32_t vid = 0, base_vid = 0;
|
||||
int64_t vdi_size = 0;
|
||||
char *backing_file = NULL;
|
||||
BDRVSheepdogState s;
|
||||
BDRVSheepdogState *s;
|
||||
char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
|
||||
uint32_t snapid;
|
||||
int prealloc = 0;
|
||||
const char *vdiname;
|
||||
|
||||
s = g_malloc0(sizeof(BDRVSheepdogState));
|
||||
|
||||
strstart(filename, "sheepdog:", &vdiname);
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
memset(vdi, 0, sizeof(vdi));
|
||||
memset(tag, 0, sizeof(tag));
|
||||
if (parse_vdiname(&s, vdiname, vdi, &snapid, tag) < 0) {
|
||||
if (parse_vdiname(s, vdiname, vdi, &snapid, tag) < 0) {
|
||||
error_report("invalid filename");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (options && options->name) {
|
||||
@@ -1270,7 +1284,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
|
||||
} else {
|
||||
error_report("Invalid preallocation mode: '%s'",
|
||||
options->value.s);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
options++;
|
||||
@@ -1278,7 +1293,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
|
||||
|
||||
if (vdi_size > SD_MAX_VDI_SIZE) {
|
||||
error_report("too big image size");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (backing_file) {
|
||||
@@ -1290,31 +1306,37 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
|
||||
drv = bdrv_find_protocol(backing_file);
|
||||
if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
|
||||
error_report("backing_file must be a sheepdog image");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = bdrv_file_open(&bs, backing_file, 0);
|
||||
if (ret < 0)
|
||||
return -EIO;
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
s = bs->opaque;
|
||||
|
||||
if (!is_snapshot(&s->inode)) {
|
||||
error_report("cannot clone from a non snapshot vdi");
|
||||
bdrv_delete(bs);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
base_vid = s->inode.vdi_id;
|
||||
bdrv_delete(bs);
|
||||
}
|
||||
|
||||
ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
|
||||
ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s->addr, s->port);
|
||||
if (!prealloc || ret) {
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return sd_prealloc(filename);
|
||||
ret = sd_prealloc(filename);
|
||||
out:
|
||||
g_free(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sd_close(BlockDriverState *bs)
|
||||
@@ -1379,7 +1401,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
|
||||
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
return -EIO;
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* we don't need to update entire object */
|
||||
@@ -1391,10 +1413,9 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
|
||||
|
||||
if (ret < 0) {
|
||||
error_report("failed to update an inode.");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1464,6 +1485,7 @@ static int sd_create_branch(BDRVSheepdogState *s)
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
error_report("failed to connect");
|
||||
ret = fd;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1606,8 +1628,9 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
if (bs->growable && sector_num + nb_sectors > bs->total_sectors) {
|
||||
/* TODO: shouldn't block here */
|
||||
if (sd_truncate(bs, (sector_num + nb_sectors) * SECTOR_SIZE) < 0) {
|
||||
return -EIO;
|
||||
ret = sd_truncate(bs, (sector_num + nb_sectors) * SECTOR_SIZE);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
bs->total_sectors = sector_num + nb_sectors;
|
||||
}
|
||||
@@ -1724,7 +1747,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
/* refresh inode. */
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
ret = -EIO;
|
||||
ret = fd;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -1732,7 +1755,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
s->inode.nr_copies, datalen, 0, 0, s->cache_enabled);
|
||||
if (ret < 0) {
|
||||
error_report("failed to write snapshot's inode.");
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -1741,7 +1763,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
if (ret < 0) {
|
||||
error_report("failed to create inode for snapshot. %s",
|
||||
strerror(errno));
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -1752,7 +1773,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
|
||||
if (ret < 0) {
|
||||
error_report("failed to read new inode info. %s", strerror(errno));
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -1773,7 +1793,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
||||
char *buf = NULL;
|
||||
uint32_t vid;
|
||||
uint32_t snapid = 0;
|
||||
int ret = -ENOENT, fd;
|
||||
int ret = 0, fd;
|
||||
|
||||
old_s = g_malloc(sizeof(BDRVSheepdogState));
|
||||
|
||||
@@ -1791,13 +1811,13 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
||||
ret = find_vdi_name(s, vdi, snapid, tag, &vid, 1);
|
||||
if (ret) {
|
||||
error_report("Failed to find_vdi_name");
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
error_report("failed to connect");
|
||||
ret = fd;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1808,7 +1828,6 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
||||
closesocket(fd);
|
||||
|
||||
if (ret) {
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1861,6 +1880,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
||||
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
ret = fd;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1888,6 +1908,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
error_report("failed to connect");
|
||||
ret = fd;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1925,6 +1946,10 @@ out:
|
||||
|
||||
g_free(vdi_inuse);
|
||||
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
@@ -1940,8 +1965,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
|
||||
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
return fd;
|
||||
}
|
||||
|
||||
while (size) {
|
||||
@@ -1965,7 +1989,6 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
|
||||
|
||||
if (ret < 0) {
|
||||
error_report("failed to save vmstate %s", strerror(errno));
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@@ -2808,7 +2808,12 @@ static int enable_write_target(BDRVVVFATState *s)
|
||||
array_init(&(s->commits), sizeof(commit_t));
|
||||
|
||||
s->qcow_filename = g_malloc(1024);
|
||||
get_tmp_filename(s->qcow_filename, 1024);
|
||||
ret = get_tmp_filename(s->qcow_filename, 1024);
|
||||
if (ret < 0) {
|
||||
g_free(s->qcow_filename);
|
||||
s->qcow_filename = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bdrv_qcow = bdrv_find_format("qcow");
|
||||
options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
|
||||
|
@@ -335,7 +335,7 @@ struct BlockDriverState {
|
||||
BlockJob *job;
|
||||
};
|
||||
|
||||
void get_tmp_filename(char *filename, int size);
|
||||
int get_tmp_filename(char *filename, int size);
|
||||
|
||||
void bdrv_set_io_limits(BlockDriverState *bs,
|
||||
BlockIOLimit *io_limits);
|
||||
|
19
configure
vendored
19
configure
vendored
@@ -2831,6 +2831,21 @@ if compile_prog "" "" ; then
|
||||
linux_magic_h=yes
|
||||
fi
|
||||
|
||||
########################################
|
||||
# check if environ is declared
|
||||
|
||||
has_environ=no
|
||||
cat > $TMPC << EOF
|
||||
#include <unistd.h>
|
||||
int main(void) {
|
||||
environ = environ;
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
if compile_prog "" "" ; then
|
||||
has_environ=yes
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# End of CC checks
|
||||
# After here, no more $cc or $ld runs
|
||||
@@ -3342,6 +3357,10 @@ if test "$linux_magic_h" = "yes" ; then
|
||||
echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$has_environ" = "yes" ; then
|
||||
echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
# USB host support
|
||||
case "$usb" in
|
||||
linux)
|
||||
|
@@ -55,6 +55,21 @@ try ...
|
||||
... then use "bus=ehci.0" to assign your usb devices to that bus.
|
||||
|
||||
|
||||
xhci controller support
|
||||
-----------------------
|
||||
|
||||
There also is xhci host controller support available. It got alot
|
||||
less testing than ehci and there are a bunch of known limitations, so
|
||||
ehci may work better for you. On the other hand the xhci hardware
|
||||
design is much more virtualization-friendly, thus xhci emulation uses
|
||||
less ressources (especially cpu). If you wanna give xhci a try
|
||||
use this to add the host controller ...
|
||||
|
||||
qemu -device nec-usb-xhci,id=xhci
|
||||
|
||||
... then use "bus=xhci.0" when assigning usb devices.
|
||||
|
||||
|
||||
More USB tips & tricks
|
||||
======================
|
||||
|
||||
|
@@ -96,6 +96,8 @@ void QEMU_NORETURN cpu_loop_exit(CPUArchState *env1);
|
||||
int page_unprotect(target_ulong address, uintptr_t pc, void *puc);
|
||||
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
|
||||
int is_cpu_write_access);
|
||||
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end,
|
||||
int is_cpu_write_access);
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* cputlb.c */
|
||||
void tlb_flush_page(CPUArchState *env, target_ulong addr);
|
||||
|
17
exec.c
17
exec.c
@@ -1075,6 +1075,23 @@ TranslationBlock *tb_gen_code(CPUArchState *env,
|
||||
return tb;
|
||||
}
|
||||
|
||||
/*
|
||||
* invalidate all TBs which intersect with the target physical pages
|
||||
* starting in range [start;end[. NOTE: start and end may refer to
|
||||
* different physical pages. 'is_cpu_write_access' should be true if called
|
||||
* from a real cpu write access: the virtual CPU will exit the current
|
||||
* TB if code is modified inside this TB.
|
||||
*/
|
||||
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end,
|
||||
int is_cpu_write_access)
|
||||
{
|
||||
while (start < end) {
|
||||
tb_invalidate_phys_page_range(start, end, is_cpu_write_access);
|
||||
start &= TARGET_PAGE_MASK;
|
||||
start += TARGET_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/* invalidate all TBs which intersect with the target physical page
|
||||
starting in range [start;end[. NOTE: start and end must refer to
|
||||
the same physical page. 'is_cpu_write_access' should be true if called
|
||||
|
@@ -299,6 +299,7 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
|
||||
if (pc->no_hotplug) {
|
||||
slot_free = false;
|
||||
} else {
|
||||
object_unparent(OBJECT(dev));
|
||||
qdev_free(qdev);
|
||||
}
|
||||
}
|
||||
|
11
hw/es1370.c
11
hw/es1370.c
@@ -410,7 +410,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl)
|
||||
|
||||
if ((old_fmt != new_fmt) || (old_freq != new_freq)) {
|
||||
d->shift = (new_fmt & 1) + (new_fmt >> 1);
|
||||
ldebug ("channel %d, freq = %d, nchannels %d, fmt %d, shift %d\n",
|
||||
ldebug ("channel %zu, freq = %d, nchannels %d, fmt %d, shift %d\n",
|
||||
i,
|
||||
new_freq,
|
||||
1 << (new_fmt & 1),
|
||||
@@ -578,7 +578,7 @@ IO_WRITE_PROTO (es1370_writel)
|
||||
d++;
|
||||
case ES1370_REG_DAC1_SCOUNT:
|
||||
d->scount = (val & 0xffff) | (d->scount & ~0xffff);
|
||||
ldebug ("chan %d CURR_SAMP_CT %d, SAMP_CT %d\n",
|
||||
ldebug ("chan %td CURR_SAMP_CT %d, SAMP_CT %d\n",
|
||||
d - &s->chan[0], val >> 16, (val & 0xffff));
|
||||
break;
|
||||
|
||||
@@ -588,7 +588,7 @@ IO_WRITE_PROTO (es1370_writel)
|
||||
d++;
|
||||
case ES1370_REG_DAC1_FRAMEADR:
|
||||
d->frame_addr = val;
|
||||
ldebug ("chan %d frame address %#x\n", d - &s->chan[0], val);
|
||||
ldebug ("chan %td frame address %#x\n", d - &s->chan[0], val);
|
||||
break;
|
||||
|
||||
case ES1370_REG_PHANTOM_FRAMECNT:
|
||||
@@ -605,7 +605,7 @@ IO_WRITE_PROTO (es1370_writel)
|
||||
case ES1370_REG_DAC1_FRAMECNT:
|
||||
d->frame_cnt = val;
|
||||
d->leftover = 0;
|
||||
ldebug ("chan %d frame count %d, buffer size %d\n",
|
||||
ldebug ("chan %td frame count %d, buffer size %d\n",
|
||||
d - &s->chan[0], val >> 16, val & 0xffff);
|
||||
break;
|
||||
|
||||
@@ -745,9 +745,10 @@ IO_READ_PROTO (es1370_readl)
|
||||
{
|
||||
uint32_t size = ((d->frame_cnt & 0xffff) + 1) << 2;
|
||||
uint32_t curr = ((d->frame_cnt >> 16) + 1) << 2;
|
||||
if (curr > size)
|
||||
if (curr > size) {
|
||||
dolog ("read framecnt curr %d, size %d %d\n", curr, size,
|
||||
curr > size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
14
hw/fdc.c
14
hw/fdc.c
@@ -179,12 +179,14 @@ static void fd_revalidate(FDrive *drv)
|
||||
FDriveRate rate;
|
||||
|
||||
FLOPPY_DPRINTF("revalidate\n");
|
||||
if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
|
||||
if (drv->bs != NULL) {
|
||||
ro = bdrv_is_read_only(drv->bs);
|
||||
bdrv_get_floppy_geometry_hint(drv->bs, &nb_heads, &max_track,
|
||||
&last_sect, drv->drive, &drive, &rate);
|
||||
if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
|
||||
FLOPPY_DPRINTF("User defined disk (%d %d %d)",
|
||||
if (!bdrv_is_inserted(drv->bs)) {
|
||||
FLOPPY_DPRINTF("No disk in drive\n");
|
||||
} else if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
|
||||
FLOPPY_DPRINTF("User defined disk (%d %d %d)\n",
|
||||
nb_heads - 1, max_track, last_sect);
|
||||
} else {
|
||||
FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads,
|
||||
@@ -201,7 +203,7 @@ static void fd_revalidate(FDrive *drv)
|
||||
drv->drive = drive;
|
||||
drv->media_rate = rate;
|
||||
} else {
|
||||
FLOPPY_DPRINTF("No disk in drive\n");
|
||||
FLOPPY_DPRINTF("No drive connected\n");
|
||||
drv->last_sect = 0;
|
||||
drv->max_track = 0;
|
||||
drv->flags &= ~FDISK_DBL_SIDES;
|
||||
@@ -709,7 +711,7 @@ static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0)
|
||||
FDrive *cur_drv;
|
||||
/* A seek clears the disk change line (if a disk is inserted) */
|
||||
cur_drv = get_cur_drv(fdctrl);
|
||||
if (cur_drv->max_track) {
|
||||
if (cur_drv->bs != NULL && bdrv_is_inserted(cur_drv->bs)) {
|
||||
cur_drv->media_changed = 0;
|
||||
}
|
||||
}
|
||||
@@ -1878,7 +1880,7 @@ static int fdctrl_connect_drives(FDCtrl *fdctrl)
|
||||
}
|
||||
|
||||
fd_init(drive);
|
||||
fd_revalidate(drive);
|
||||
fdctrl_change_cb(drive, 0);
|
||||
if (drive->bs) {
|
||||
bdrv_set_dev_ops(drive->bs, &fdctrl_block_ops, drive);
|
||||
}
|
||||
|
@@ -103,7 +103,7 @@ ssize_t read_targphys(const char *name,
|
||||
|
||||
/* return the size or -1 if error */
|
||||
int load_image_targphys(const char *filename,
|
||||
target_phys_addr_t addr, int max_sz)
|
||||
target_phys_addr_t addr, uint64_t max_sz)
|
||||
{
|
||||
int size;
|
||||
|
||||
|
@@ -4,7 +4,8 @@
|
||||
/* loader.c */
|
||||
int get_image_size(const char *filename);
|
||||
int load_image(const char *filename, uint8_t *addr); /* deprecated */
|
||||
int load_image_targphys(const char *filename, target_phys_addr_t, int max_sz);
|
||||
int load_image_targphys(const char *filename, target_phys_addr_t,
|
||||
uint64_t max_sz);
|
||||
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
|
||||
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
|
||||
uint64_t *highaddr, int big_endian, int elf_machine,
|
||||
|
@@ -202,10 +202,16 @@ int load_multiboot(void *fw_cfg,
|
||||
uint32_t mh_bss_end_addr = ldl_p(header+i+24);
|
||||
mh_load_addr = ldl_p(header+i+16);
|
||||
uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr);
|
||||
uint32_t mb_load_size = mh_load_end_addr - mh_load_addr;
|
||||
|
||||
uint32_t mb_load_size = 0;
|
||||
mh_entry_addr = ldl_p(header+i+28);
|
||||
mb_kernel_size = mh_bss_end_addr - mh_load_addr;
|
||||
|
||||
if (mh_load_end_addr) {
|
||||
mb_kernel_size = mh_bss_end_addr - mh_load_addr;
|
||||
mb_load_size = mh_load_end_addr - mh_load_addr;
|
||||
} else {
|
||||
mb_kernel_size = kernel_file_size - mb_kernel_text_offset;
|
||||
mb_load_size = mb_kernel_size;
|
||||
}
|
||||
|
||||
/* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE.
|
||||
uint32_t mh_mode_type = ldl_p(header+i+32);
|
||||
|
25
hw/pc.c
25
hw/pc.c
@@ -47,6 +47,7 @@
|
||||
#include "ui/qemu-spice.h"
|
||||
#include "memory.h"
|
||||
#include "exec-memory.h"
|
||||
#include "arch_init.h"
|
||||
|
||||
/* output Bochs bios info messages */
|
||||
//#define DEBUG_BIOS
|
||||
@@ -382,7 +383,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
|
||||
if (floppy) {
|
||||
fdc_get_bs(fd, floppy);
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (fd[i] && bdrv_is_inserted(fd[i])) {
|
||||
if (fd[i]) {
|
||||
bdrv_get_floppy_geometry_hint(fd[i], &nb_heads, &max_track,
|
||||
&last_sect, FDRIVE_DRV_NONE,
|
||||
&fd_type[i], &rate);
|
||||
@@ -1097,7 +1098,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
|
||||
qemu_irq pit_alt_irq = NULL;
|
||||
qemu_irq rtc_irq = NULL;
|
||||
qemu_irq *a20_line;
|
||||
ISADevice *i8042, *port92, *vmmouse, *pit;
|
||||
ISADevice *i8042, *port92, *vmmouse, *pit = NULL;
|
||||
qemu_irq *cpu_exit_irq;
|
||||
|
||||
register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
|
||||
@@ -1126,16 +1127,18 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
|
||||
|
||||
qemu_register_boot_set(pc_boot_set, *rtc_state);
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
pit = kvm_pit_init(isa_bus, 0x40);
|
||||
} else {
|
||||
pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
|
||||
if (!xen_enabled()) {
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
pit = kvm_pit_init(isa_bus, 0x40);
|
||||
} else {
|
||||
pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
|
||||
}
|
||||
if (hpet) {
|
||||
/* connect PIT to output control line of the HPET */
|
||||
qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
|
||||
}
|
||||
pcspk_init(isa_bus, pit);
|
||||
}
|
||||
if (hpet) {
|
||||
/* connect PIT to output control line of the HPET */
|
||||
qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
|
||||
}
|
||||
pcspk_init(isa_bus, pit);
|
||||
|
||||
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
|
||||
if (serial_hds[i]) {
|
||||
|
1
hw/pci.c
1
hw/pci.c
@@ -1527,7 +1527,6 @@ static int pci_unplug_device(DeviceState *qdev)
|
||||
qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev)));
|
||||
return -1;
|
||||
}
|
||||
object_unparent(OBJECT(dev));
|
||||
return dev->bus->hotplug(dev->bus->hotplug_qdev, dev,
|
||||
PCI_HOTPLUG_DISABLED);
|
||||
}
|
||||
|
@@ -753,10 +753,12 @@ static void set_mac(Object *obj, Visitor *v, void *opaque,
|
||||
}
|
||||
mac->a[i] = strtol(str+pos, &p, 16);
|
||||
}
|
||||
g_free(str);
|
||||
return;
|
||||
|
||||
inval:
|
||||
error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_macaddr = {
|
||||
@@ -825,7 +827,7 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
|
||||
uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
|
||||
unsigned int slot, fn, n;
|
||||
Error *local_err = NULL;
|
||||
char *str = (char *)"";
|
||||
char *str;
|
||||
|
||||
if (dev->state != DEV_STATE_CREATED) {
|
||||
error_set(errp, QERR_PERMISSION_DENIED);
|
||||
@@ -848,10 +850,12 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
|
||||
goto invalid;
|
||||
}
|
||||
*ptr = slot << 3 | fn;
|
||||
g_free(str);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
|
||||
|
@@ -163,8 +163,7 @@ static int s390_virtio_blk_init(VirtIOS390Device *dev)
|
||||
{
|
||||
VirtIODevice *vdev;
|
||||
|
||||
vdev = virtio_blk_init((DeviceState *)dev, &dev->block,
|
||||
&dev->block_serial);
|
||||
vdev = virtio_blk_init((DeviceState *)dev, &dev->blk);
|
||||
if (!vdev) {
|
||||
return -1;
|
||||
}
|
||||
@@ -400,8 +399,11 @@ static TypeInfo s390_virtio_net = {
|
||||
};
|
||||
|
||||
static Property s390_virtio_blk_properties[] = {
|
||||
DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, block),
|
||||
DEFINE_PROP_STRING("serial", VirtIOS390Device, block_serial),
|
||||
DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, blk.conf),
|
||||
DEFINE_PROP_STRING("serial", VirtIOS390Device, blk.serial),
|
||||
#ifdef __linux__
|
||||
DEFINE_PROP_BIT("scsi", VirtIOS390Device, blk.scsi, 0, true),
|
||||
#endif
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@@ -17,6 +17,7 @@
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "virtio-blk.h"
|
||||
#include "virtio-net.h"
|
||||
#include "virtio-serial.h"
|
||||
#include "virtio-scsi.h"
|
||||
@@ -64,8 +65,7 @@ struct VirtIOS390Device {
|
||||
ram_addr_t feat_offs;
|
||||
uint8_t feat_len;
|
||||
VirtIODevice *vdev;
|
||||
BlockConf block;
|
||||
char *block_serial;
|
||||
VirtIOBlkConf blk;
|
||||
NICConf nic;
|
||||
uint32_t host_features;
|
||||
virtio_serial_conf serial;
|
||||
|
@@ -1561,7 +1561,7 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VMStateInfo vmstate_info_scsi_requests = {
|
||||
static const VMStateInfo vmstate_info_scsi_requests = {
|
||||
.name = "scsi-requests",
|
||||
.get = get_scsi_requests,
|
||||
.put = put_scsi_requests,
|
||||
|
56
hw/sun4u.c
56
hw/sun4u.c
@@ -67,7 +67,6 @@
|
||||
|
||||
#define KERNEL_LOAD_ADDR 0x00404000
|
||||
#define CMDLINE_ADDR 0x003ff000
|
||||
#define INITRD_LOAD_ADDR 0x00300000
|
||||
#define PROM_SIZE_MAX (4 * 1024 * 1024)
|
||||
#define PROM_VADDR 0x000ffd00000ULL
|
||||
#define APB_SPECIAL_BASE 0x1fe00000000ULL
|
||||
@@ -181,14 +180,18 @@ static int sun4u_NVRAM_set_params(M48t59State *nvram, uint16_t NVRAM_size,
|
||||
|
||||
return 0;
|
||||
}
|
||||
static unsigned long sun4u_load_kernel(const char *kernel_filename,
|
||||
const char *initrd_filename,
|
||||
ram_addr_t RAM_size, long *initrd_size)
|
||||
|
||||
static uint64_t sun4u_load_kernel(const char *kernel_filename,
|
||||
const char *initrd_filename,
|
||||
ram_addr_t RAM_size, uint64_t *initrd_size,
|
||||
uint64_t *initrd_addr, uint64_t *kernel_addr,
|
||||
uint64_t *kernel_entry)
|
||||
{
|
||||
int linux_boot;
|
||||
unsigned int i;
|
||||
long kernel_size;
|
||||
uint8_t *ptr;
|
||||
uint64_t kernel_top;
|
||||
|
||||
linux_boot = (kernel_filename != NULL);
|
||||
|
||||
@@ -201,29 +204,34 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename,
|
||||
#else
|
||||
bswap_needed = 0;
|
||||
#endif
|
||||
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
|
||||
NULL, NULL, 1, ELF_MACHINE, 0);
|
||||
if (kernel_size < 0)
|
||||
kernel_size = load_elf(kernel_filename, NULL, NULL, kernel_entry,
|
||||
kernel_addr, &kernel_top, 1, ELF_MACHINE, 0);
|
||||
if (kernel_size < 0) {
|
||||
*kernel_addr = KERNEL_LOAD_ADDR;
|
||||
*kernel_entry = KERNEL_LOAD_ADDR;
|
||||
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
|
||||
RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
|
||||
TARGET_PAGE_SIZE);
|
||||
if (kernel_size < 0)
|
||||
}
|
||||
if (kernel_size < 0) {
|
||||
kernel_size = load_image_targphys(kernel_filename,
|
||||
KERNEL_LOAD_ADDR,
|
||||
RAM_size - KERNEL_LOAD_ADDR);
|
||||
}
|
||||
if (kernel_size < 0) {
|
||||
fprintf(stderr, "qemu: could not load kernel '%s'\n",
|
||||
kernel_filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* load initrd */
|
||||
/* load initrd above kernel */
|
||||
*initrd_size = 0;
|
||||
if (initrd_filename) {
|
||||
*initrd_addr = TARGET_PAGE_ALIGN(kernel_top);
|
||||
|
||||
*initrd_size = load_image_targphys(initrd_filename,
|
||||
INITRD_LOAD_ADDR,
|
||||
RAM_size - INITRD_LOAD_ADDR);
|
||||
if (*initrd_size < 0) {
|
||||
*initrd_addr,
|
||||
RAM_size - *initrd_addr);
|
||||
if ((int)*initrd_size < 0) {
|
||||
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
|
||||
initrd_filename);
|
||||
exit(1);
|
||||
@@ -231,9 +239,9 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename,
|
||||
}
|
||||
if (*initrd_size > 0) {
|
||||
for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
|
||||
ptr = rom_ptr(KERNEL_LOAD_ADDR + i);
|
||||
ptr = rom_ptr(*kernel_addr + i);
|
||||
if (ldl_p(ptr + 8) == 0x48647253) { /* HdrS */
|
||||
stl_p(ptr + 24, INITRD_LOAD_ADDR + KERNEL_LOAD_ADDR - 0x4000);
|
||||
stl_p(ptr + 24, *initrd_addr + *kernel_addr);
|
||||
stl_p(ptr + 28, *initrd_size);
|
||||
break;
|
||||
}
|
||||
@@ -788,7 +796,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
|
||||
CPUSPARCState *env;
|
||||
M48t59State *nvram;
|
||||
unsigned int i;
|
||||
long initrd_size, kernel_size;
|
||||
uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
|
||||
PCIBus *pci_bus, *pci_bus2, *pci_bus3;
|
||||
ISABus *isa_bus;
|
||||
qemu_irq *ivec_irqs, *pbm_irqs;
|
||||
@@ -845,13 +853,15 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
|
||||
nvram = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 59);
|
||||
|
||||
initrd_size = 0;
|
||||
initrd_addr = 0;
|
||||
kernel_size = sun4u_load_kernel(kernel_filename, initrd_filename,
|
||||
ram_size, &initrd_size);
|
||||
ram_size, &initrd_size, &initrd_addr,
|
||||
&kernel_addr, &kernel_entry);
|
||||
|
||||
sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices,
|
||||
KERNEL_LOAD_ADDR, kernel_size,
|
||||
kernel_addr, kernel_size,
|
||||
kernel_cmdline,
|
||||
INITRD_LOAD_ADDR, initrd_size,
|
||||
initrd_addr, initrd_size,
|
||||
/* XXX: need an option to load a NVRAM image */
|
||||
0,
|
||||
graphic_width, graphic_height, graphic_depth,
|
||||
@@ -861,8 +871,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
|
||||
if (kernel_cmdline) {
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
|
||||
strlen(kernel_cmdline) + 1);
|
||||
@@ -872,8 +882,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
|
||||
} else {
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
|
||||
}
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_devices[0]);
|
||||
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width);
|
||||
|
7
hw/vga.c
7
hw/vga.c
@@ -2357,10 +2357,15 @@ void vga_init(VGACommonState *s, MemoryRegion *address_space,
|
||||
void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory)
|
||||
{
|
||||
#ifdef CONFIG_BOCHS_VBE
|
||||
/* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region,
|
||||
* so use an alias to avoid double-mapping the same region.
|
||||
*/
|
||||
memory_region_init_alias(&s->vram_vbe, "vram.vbe",
|
||||
&s->vram, 0, memory_region_size(&s->vram));
|
||||
/* XXX: use optimized standard vga accesses */
|
||||
memory_region_add_subregion(system_memory,
|
||||
VBE_DISPI_LFB_PHYSICAL_ADDRESS,
|
||||
&s->vram);
|
||||
&s->vram_vbe);
|
||||
s->vbe_mapped = 1;
|
||||
#endif
|
||||
}
|
||||
|
@@ -105,6 +105,7 @@ typedef struct VGACommonState {
|
||||
MemoryRegion *legacy_address_space;
|
||||
uint8_t *vram_ptr;
|
||||
MemoryRegion vram;
|
||||
MemoryRegion vram_vbe;
|
||||
uint32_t vram_size;
|
||||
uint32_t latch;
|
||||
MemoryRegion *chain4_alias;
|
||||
|
@@ -211,11 +211,15 @@ static void virtio_balloon_save(QEMUFile *f, void *opaque)
|
||||
static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
VirtIOBalloon *s = opaque;
|
||||
int ret;
|
||||
|
||||
if (version_id != 1)
|
||||
return -EINVAL;
|
||||
|
||||
virtio_load(&s->vdev, f);
|
||||
ret = virtio_load(&s->vdev, f);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
s->num_pages = qemu_get_be32(f);
|
||||
s->actual = qemu_get_be32(f);
|
||||
|
@@ -29,7 +29,7 @@ typedef struct VirtIOBlock
|
||||
void *rq;
|
||||
QEMUBH *bh;
|
||||
BlockConf *conf;
|
||||
char *serial;
|
||||
VirtIOBlkConf *blk;
|
||||
unsigned short sector_mask;
|
||||
DeviceState *qdev;
|
||||
} VirtIOBlock;
|
||||
@@ -145,20 +145,12 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
|
||||
return req;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
{
|
||||
struct sg_io_hdr hdr;
|
||||
int ret;
|
||||
int status;
|
||||
int status = VIRTIO_BLK_S_OK;
|
||||
int i;
|
||||
|
||||
if ((req->dev->vdev.guest_features & (1 << VIRTIO_BLK_F_SCSI)) == 0) {
|
||||
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
|
||||
g_free(req);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We require at least one output segment each for the virtio_blk_outhdr
|
||||
* and the SCSI command block.
|
||||
@@ -172,21 +164,27 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* No support for bidirection commands yet.
|
||||
*/
|
||||
if (req->elem.out_num > 2 && req->elem.in_num > 3) {
|
||||
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
|
||||
g_free(req);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The scsi inhdr is placed in the second-to-last input segment, just
|
||||
* before the regular inhdr.
|
||||
*/
|
||||
req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
|
||||
|
||||
if (!req->dev->blk->scsi) {
|
||||
status = VIRTIO_BLK_S_UNSUPP;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* No support for bidirection commands yet.
|
||||
*/
|
||||
if (req->elem.out_num > 2 && req->elem.in_num > 3) {
|
||||
status = VIRTIO_BLK_S_UNSUPP;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
struct sg_io_hdr hdr;
|
||||
memset(&hdr, 0, sizeof(struct sg_io_hdr));
|
||||
hdr.interface_id = 'S';
|
||||
hdr.cmd_len = req->elem.out_sg[1].iov_len;
|
||||
@@ -230,12 +228,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
ret = bdrv_ioctl(req->dev->bs, SG_IO, &hdr);
|
||||
if (ret) {
|
||||
status = VIRTIO_BLK_S_UNSUPP;
|
||||
hdr.status = ret;
|
||||
hdr.resid = hdr.dxfer_len;
|
||||
} else if (hdr.status) {
|
||||
status = VIRTIO_BLK_S_IOERR;
|
||||
} else {
|
||||
status = VIRTIO_BLK_S_OK;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -258,14 +251,16 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
|
||||
virtio_blk_req_complete(req, status);
|
||||
g_free(req);
|
||||
}
|
||||
#else
|
||||
static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
{
|
||||
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
|
||||
abort();
|
||||
#endif
|
||||
|
||||
fail:
|
||||
/* Just put anything nonzero so that the ioctl fails in the guest. */
|
||||
stl_p(&req->scsi->errors, 255);
|
||||
virtio_blk_req_complete(req, status);
|
||||
g_free(req);
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
typedef struct MultiReqBuffer {
|
||||
BlockRequest blkreq[32];
|
||||
@@ -394,7 +389,7 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
|
||||
* terminated by '\0' only when shorter than buffer.
|
||||
*/
|
||||
strncpy(req->elem.in_sg[0].iov_base,
|
||||
s->serial ? s->serial : "",
|
||||
s->blk->serial ? s->blk->serial : "",
|
||||
MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
|
||||
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
|
||||
g_free(req);
|
||||
@@ -509,6 +504,7 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
|
||||
features |= (1 << VIRTIO_BLK_F_GEOMETRY);
|
||||
features |= (1 << VIRTIO_BLK_F_TOPOLOGY);
|
||||
features |= (1 << VIRTIO_BLK_F_BLK_SIZE);
|
||||
features |= (1 << VIRTIO_BLK_F_SCSI);
|
||||
|
||||
if (bdrv_enable_write_cache(s->bs))
|
||||
features |= (1 << VIRTIO_BLK_F_WCACHE);
|
||||
@@ -537,11 +533,16 @@ static void virtio_blk_save(QEMUFile *f, void *opaque)
|
||||
static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
VirtIOBlock *s = opaque;
|
||||
int ret;
|
||||
|
||||
if (version_id != 2)
|
||||
return -EINVAL;
|
||||
|
||||
virtio_load(&s->vdev, f);
|
||||
ret = virtio_load(&s->vdev, f);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (qemu_get_sbyte(f)) {
|
||||
VirtIOBlockReq *req = virtio_blk_alloc_request(s);
|
||||
qemu_get_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
|
||||
@@ -568,28 +569,27 @@ static const BlockDevOps virtio_block_ops = {
|
||||
.resize_cb = virtio_blk_resize,
|
||||
};
|
||||
|
||||
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
|
||||
char **serial)
|
||||
VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
|
||||
{
|
||||
VirtIOBlock *s;
|
||||
int cylinders, heads, secs;
|
||||
static int virtio_blk_id;
|
||||
DriveInfo *dinfo;
|
||||
|
||||
if (!conf->bs) {
|
||||
if (!blk->conf.bs) {
|
||||
error_report("drive property not set");
|
||||
return NULL;
|
||||
}
|
||||
if (!bdrv_is_inserted(conf->bs)) {
|
||||
if (!bdrv_is_inserted(blk->conf.bs)) {
|
||||
error_report("Device needs media, but drive is empty");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!*serial) {
|
||||
if (!blk->serial) {
|
||||
/* try to fall back to value set with legacy -drive serial=... */
|
||||
dinfo = drive_get_by_blockdev(conf->bs);
|
||||
dinfo = drive_get_by_blockdev(blk->conf.bs);
|
||||
if (*dinfo->serial) {
|
||||
*serial = strdup(dinfo->serial);
|
||||
blk->serial = strdup(dinfo->serial);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -600,9 +600,9 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
|
||||
s->vdev.get_config = virtio_blk_update_config;
|
||||
s->vdev.get_features = virtio_blk_get_features;
|
||||
s->vdev.reset = virtio_blk_reset;
|
||||
s->bs = conf->bs;
|
||||
s->conf = conf;
|
||||
s->serial = *serial;
|
||||
s->bs = blk->conf.bs;
|
||||
s->conf = &blk->conf;
|
||||
s->blk = blk;
|
||||
s->rq = NULL;
|
||||
s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
|
||||
bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
|
||||
@@ -614,10 +614,10 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
|
||||
register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
|
||||
virtio_blk_save, virtio_blk_load, s);
|
||||
bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
|
||||
bdrv_set_buffer_alignment(s->bs, conf->logical_block_size);
|
||||
bdrv_set_buffer_alignment(s->bs, s->conf->logical_block_size);
|
||||
|
||||
bdrv_iostatus_enable(s->bs);
|
||||
add_boot_device_path(conf->bootindex, dev, "/disk@0,0");
|
||||
add_boot_device_path(s->conf->bootindex, dev, "/disk@0,0");
|
||||
|
||||
return &s->vdev;
|
||||
}
|
||||
@@ -626,5 +626,6 @@ void virtio_blk_exit(VirtIODevice *vdev)
|
||||
{
|
||||
VirtIOBlock *s = to_virtio_blk(vdev);
|
||||
unregister_savevm(s->qdev, "virtio-blk", s);
|
||||
blockdev_mark_auto_del(s->bs);
|
||||
virtio_cleanup(vdev);
|
||||
}
|
||||
|
@@ -97,12 +97,14 @@ struct virtio_scsi_inhdr
|
||||
uint32_t residual;
|
||||
};
|
||||
|
||||
#ifdef __linux__
|
||||
#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
|
||||
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
|
||||
DEFINE_PROP_BIT("scsi", _state, _field, VIRTIO_BLK_F_SCSI, true)
|
||||
#else
|
||||
struct VirtIOBlkConf
|
||||
{
|
||||
BlockConf conf;
|
||||
char *serial;
|
||||
uint32_t scsi;
|
||||
};
|
||||
|
||||
#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
|
||||
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@@ -891,11 +891,15 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
VirtIONet *n = opaque;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION)
|
||||
return -EINVAL;
|
||||
|
||||
virtio_load(&n->vdev, f);
|
||||
ret = virtio_load(&n->vdev, f);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
qemu_get_buffer(f, n->mac, ETH_ALEN);
|
||||
n->tx_waiting = qemu_get_be32(f);
|
||||
|
@@ -491,7 +491,7 @@ static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
|
||||
virtio_config_writel(proxy->vdev, addr, val);
|
||||
}
|
||||
|
||||
const MemoryRegionPortio virtio_portio[] = {
|
||||
static const MemoryRegionPortio virtio_portio[] = {
|
||||
{ 0, 0x10000, 1, .write = virtio_pci_config_writeb, },
|
||||
{ 0, 0x10000, 2, .write = virtio_pci_config_writew, },
|
||||
{ 0, 0x10000, 4, .write = virtio_pci_config_writel, },
|
||||
@@ -697,8 +697,7 @@ static int virtio_blk_init_pci(PCIDevice *pci_dev)
|
||||
proxy->class_code != PCI_CLASS_STORAGE_OTHER)
|
||||
proxy->class_code = PCI_CLASS_STORAGE_SCSI;
|
||||
|
||||
vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block,
|
||||
&proxy->block_serial);
|
||||
vdev = virtio_blk_init(&pci_dev->qdev, &proxy->blk);
|
||||
if (!vdev) {
|
||||
return -1;
|
||||
}
|
||||
@@ -726,7 +725,6 @@ static int virtio_blk_exit_pci(PCIDevice *pci_dev)
|
||||
|
||||
virtio_pci_stop_ioeventfd(proxy);
|
||||
virtio_blk_exit(proxy->vdev);
|
||||
blockdev_mark_auto_del(proxy->block.bs);
|
||||
return virtio_exit_pci(pci_dev);
|
||||
}
|
||||
|
||||
@@ -814,8 +812,11 @@ static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
|
||||
|
||||
static Property virtio_blk_properties[] = {
|
||||
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
|
||||
DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
|
||||
DEFINE_PROP_STRING("serial", VirtIOPCIProxy, block_serial),
|
||||
DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf),
|
||||
DEFINE_PROP_STRING("serial", VirtIOPCIProxy, blk.serial),
|
||||
#ifdef __linux__
|
||||
DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
|
||||
#endif
|
||||
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
|
||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
|
||||
DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#ifndef QEMU_VIRTIO_PCI_H
|
||||
#define QEMU_VIRTIO_PCI_H
|
||||
|
||||
#include "virtio-blk.h"
|
||||
#include "virtio-net.h"
|
||||
#include "virtio-serial.h"
|
||||
#include "virtio-scsi.h"
|
||||
@@ -32,8 +33,7 @@ typedef struct {
|
||||
uint32_t flags;
|
||||
uint32_t class_code;
|
||||
uint32_t nvectors;
|
||||
BlockConf block;
|
||||
char *block_serial;
|
||||
VirtIOBlkConf blk;
|
||||
NICConf nic;
|
||||
uint32_t host_features;
|
||||
#ifdef CONFIG_LINUX
|
||||
|
@@ -564,7 +564,12 @@ static void virtio_scsi_save(QEMUFile *f, void *opaque)
|
||||
static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
VirtIOSCSI *s = opaque;
|
||||
virtio_load(&s->vdev, f);
|
||||
int ret;
|
||||
|
||||
ret = virtio_load(&s->vdev, f);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -637,13 +637,17 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
|
||||
VirtIOSerialPort *port;
|
||||
uint32_t max_nr_ports, nr_active_ports, ports_map;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (version_id > 3) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The virtio device */
|
||||
virtio_load(&s->vdev, f);
|
||||
ret = virtio_load(&s->vdev, f);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (version_id < 2) {
|
||||
return 0;
|
||||
|
@@ -191,8 +191,8 @@ void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
|
||||
void *opaque);
|
||||
|
||||
/* Base devices. */
|
||||
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
|
||||
char **serial);
|
||||
typedef struct VirtIOBlkConf VirtIOBlkConf;
|
||||
VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk);
|
||||
struct virtio_net_conf;
|
||||
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
|
||||
struct virtio_net_conf *net);
|
||||
|
@@ -148,6 +148,6 @@ static inline int xen_xc_hvm_inject_msi(XenXC xen_xc, domid_t dom,
|
||||
}
|
||||
#endif
|
||||
|
||||
void destroy_hvm_domain(void);
|
||||
void destroy_hvm_domain(bool reboot);
|
||||
|
||||
#endif /* QEMU_HW_XEN_COMMON_H */
|
||||
|
@@ -48,7 +48,6 @@
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
static int syncwrite = 0;
|
||||
static int batch_maps = 0;
|
||||
|
||||
static int max_requests = 32;
|
||||
@@ -67,6 +66,7 @@ struct ioreq {
|
||||
QEMUIOVector v;
|
||||
int presync;
|
||||
int postsync;
|
||||
uint8_t mapped;
|
||||
|
||||
/* grant mapping */
|
||||
uint32_t domids[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||
@@ -154,7 +154,7 @@ static void ioreq_finish(struct ioreq *ioreq)
|
||||
blkdev->requests_finished++;
|
||||
}
|
||||
|
||||
static void ioreq_release(struct ioreq *ioreq)
|
||||
static void ioreq_release(struct ioreq *ioreq, bool finish)
|
||||
{
|
||||
struct XenBlkDev *blkdev = ioreq->blkdev;
|
||||
|
||||
@@ -162,7 +162,11 @@ static void ioreq_release(struct ioreq *ioreq)
|
||||
memset(ioreq, 0, sizeof(*ioreq));
|
||||
ioreq->blkdev = blkdev;
|
||||
QLIST_INSERT_HEAD(&blkdev->freelist, ioreq, list);
|
||||
blkdev->requests_finished--;
|
||||
if (finish) {
|
||||
blkdev->requests_finished--;
|
||||
} else {
|
||||
blkdev->requests_inflight--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -189,15 +193,10 @@ static int ioreq_parse(struct ioreq *ioreq)
|
||||
ioreq->presync = 1;
|
||||
return 0;
|
||||
}
|
||||
if (!syncwrite) {
|
||||
ioreq->presync = ioreq->postsync = 1;
|
||||
}
|
||||
ioreq->presync = ioreq->postsync = 1;
|
||||
/* fall through */
|
||||
case BLKIF_OP_WRITE:
|
||||
ioreq->prot = PROT_READ; /* from memory */
|
||||
if (syncwrite) {
|
||||
ioreq->postsync = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
xen_be_printf(&blkdev->xendev, 0, "error: unknown operation (%d)\n",
|
||||
@@ -248,7 +247,7 @@ static void ioreq_unmap(struct ioreq *ioreq)
|
||||
XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev;
|
||||
int i;
|
||||
|
||||
if (ioreq->v.niov == 0) {
|
||||
if (ioreq->v.niov == 0 || ioreq->mapped == 0) {
|
||||
return;
|
||||
}
|
||||
if (batch_maps) {
|
||||
@@ -274,6 +273,7 @@ static void ioreq_unmap(struct ioreq *ioreq)
|
||||
ioreq->page[i] = NULL;
|
||||
}
|
||||
}
|
||||
ioreq->mapped = 0;
|
||||
}
|
||||
|
||||
static int ioreq_map(struct ioreq *ioreq)
|
||||
@@ -281,7 +281,7 @@ static int ioreq_map(struct ioreq *ioreq)
|
||||
XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev;
|
||||
int i;
|
||||
|
||||
if (ioreq->v.niov == 0) {
|
||||
if (ioreq->v.niov == 0 || ioreq->mapped == 1) {
|
||||
return 0;
|
||||
}
|
||||
if (batch_maps) {
|
||||
@@ -313,9 +313,12 @@ static int ioreq_map(struct ioreq *ioreq)
|
||||
ioreq->blkdev->cnt_map++;
|
||||
}
|
||||
}
|
||||
ioreq->mapped = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ioreq_runio_qemu_aio(struct ioreq *ioreq);
|
||||
|
||||
static void qemu_aio_complete(void *opaque, int ret)
|
||||
{
|
||||
struct ioreq *ioreq = opaque;
|
||||
@@ -327,11 +330,19 @@ static void qemu_aio_complete(void *opaque, int ret)
|
||||
}
|
||||
|
||||
ioreq->aio_inflight--;
|
||||
if (ioreq->presync) {
|
||||
ioreq->presync = 0;
|
||||
ioreq_runio_qemu_aio(ioreq);
|
||||
return;
|
||||
}
|
||||
if (ioreq->aio_inflight > 0) {
|
||||
return;
|
||||
}
|
||||
if (ioreq->postsync) {
|
||||
bdrv_flush(ioreq->blkdev->bs);
|
||||
ioreq->postsync = 0;
|
||||
ioreq->aio_inflight++;
|
||||
bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq);
|
||||
return;
|
||||
}
|
||||
|
||||
ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY;
|
||||
@@ -351,7 +362,8 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
|
||||
|
||||
ioreq->aio_inflight++;
|
||||
if (ioreq->presync) {
|
||||
bdrv_flush(blkdev->bs); /* FIXME: aio_flush() ??? */
|
||||
bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (ioreq->req.operation) {
|
||||
@@ -449,7 +461,7 @@ static void blk_send_response_all(struct XenBlkDev *blkdev)
|
||||
while (!QLIST_EMPTY(&blkdev->finished)) {
|
||||
ioreq = QLIST_FIRST(&blkdev->finished);
|
||||
send_notify += blk_send_response_one(ioreq);
|
||||
ioreq_release(ioreq);
|
||||
ioreq_release(ioreq, true);
|
||||
}
|
||||
if (send_notify) {
|
||||
xen_be_send_notify(&blkdev->xendev);
|
||||
@@ -505,7 +517,7 @@ static void blk_handle_requests(struct XenBlkDev *blkdev)
|
||||
if (blk_send_response_one(ioreq)) {
|
||||
xen_be_send_notify(&blkdev->xendev);
|
||||
}
|
||||
ioreq_release(ioreq);
|
||||
ioreq_release(ioreq, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@@ -87,7 +87,10 @@ static void unplug_nic(PCIBus *b, PCIDevice *d)
|
||||
{
|
||||
if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
|
||||
PCI_CLASS_NETWORK_ETHERNET) {
|
||||
qdev_unplug(&(d->qdev), NULL);
|
||||
/* Until qdev_free includes a call to object_unparent, we call it here
|
||||
*/
|
||||
object_unparent(&d->qdev.parent_obj);
|
||||
qdev_free(&d->qdev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -573,6 +573,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
page_dump(stdout);
|
||||
printf("\n");
|
||||
#endif
|
||||
tb_invalidate_phys_range(start, start + len, 0);
|
||||
mmap_unlock();
|
||||
return start;
|
||||
fail:
|
||||
@@ -675,8 +676,10 @@ int target_munmap(abi_ulong start, abi_ulong len)
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
if (ret == 0) {
|
||||
page_set_flags(start, start + len, 0);
|
||||
tb_invalidate_phys_range(start, start + len, 0);
|
||||
}
|
||||
mmap_unlock();
|
||||
return ret;
|
||||
}
|
||||
@@ -754,6 +757,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
|
||||
page_set_flags(old_addr, old_addr + old_size, 0);
|
||||
page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);
|
||||
}
|
||||
tb_invalidate_phys_range(new_addr, new_addr + new_size, 0);
|
||||
mmap_unlock();
|
||||
return new_addr;
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@
|
||||
1275-1994 (referred to as Open Firmware) compliant firmware.
|
||||
The included images for PowerPC (for 32 and 64 bit PPC CPUs),
|
||||
Sparc32 and Sparc64 are built from OpenBIOS SVN revision
|
||||
1056.
|
||||
1060.
|
||||
|
||||
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
|
||||
implementation for certain IBM POWER hardware. The sources are at
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -126,16 +126,19 @@
|
||||
# @guest-shutdown:
|
||||
#
|
||||
# Initiate guest-activated shutdown. Note: this is an asynchronous
|
||||
# shutdown request, with no guaruntee of successful shutdown. Errors
|
||||
# will be logged to guest's syslog.
|
||||
# shutdown request, with no guarantee of successful shutdown.
|
||||
#
|
||||
# @mode: #optional "halt", "powerdown" (default), or "reboot"
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# This command does NOT return a response on success. Success condition
|
||||
# is indicated by the VM exiting with a zero exit status or, when
|
||||
# running with --no-shutdown, by issuing the query-status QMP command
|
||||
# to confirm the VM status is "shutdown".
|
||||
#
|
||||
# Since: 0.15.0
|
||||
##
|
||||
{ 'command': 'guest-shutdown', 'data': { '*mode': 'str' } }
|
||||
{ 'command': 'guest-shutdown', 'data': { '*mode': 'str' },
|
||||
'success-response': 'no' }
|
||||
|
||||
##
|
||||
# @guest-file-open:
|
||||
@@ -359,17 +362,21 @@
|
||||
# For the best results it's strongly recommended to have the pm-utils
|
||||
# package installed in the guest.
|
||||
#
|
||||
# Returns: nothing on success
|
||||
# This command does NOT return a response on success. There is a high chance
|
||||
# the command succeeded if the VM exits with a zero exit status or, when
|
||||
# running with --no-shutdown, by issuing the query-status QMP command to
|
||||
# to confirm the VM status is "shutdown". However, the VM could also exit
|
||||
# (or set its status to "shutdown") due to other reasons.
|
||||
#
|
||||
# The following errors may be returned:
|
||||
# If suspend to disk is not supported, Unsupported
|
||||
#
|
||||
# Notes: o This is an asynchronous request. There's no guarantee a response
|
||||
# will be sent
|
||||
# o It's strongly recommended to issue the guest-sync command before
|
||||
# sending commands when the guest resumes
|
||||
# Notes: It's strongly recommended to issue the guest-sync command before
|
||||
# sending commands when the guest resumes
|
||||
#
|
||||
# Since: 1.1
|
||||
##
|
||||
{ 'command': 'guest-suspend-disk' }
|
||||
{ 'command': 'guest-suspend-disk', 'success-response': 'no' }
|
||||
|
||||
##
|
||||
# @guest-suspend-ram
|
||||
@@ -387,17 +394,21 @@
|
||||
# command. Thus, it's *required* to query QEMU for the presence of the
|
||||
# 'system_wakeup' command before issuing guest-suspend-ram.
|
||||
#
|
||||
# Returns: nothing on success
|
||||
# This command does NOT return a response on success. There are two options
|
||||
# to check for success:
|
||||
# 1. Wait for the SUSPEND QMP event from QEMU
|
||||
# 2. Issue the query-status QMP command to confirm the VM status is
|
||||
# "suspended"
|
||||
#
|
||||
# The following errors may be returned:
|
||||
# If suspend to ram is not supported, Unsupported
|
||||
#
|
||||
# Notes: o This is an asynchronous request. There's no guarantee a response
|
||||
# will be sent
|
||||
# o It's strongly recommended to issue the guest-sync command before
|
||||
# sending commands when the guest resumes
|
||||
# Notes: It's strongly recommended to issue the guest-sync command before
|
||||
# sending commands when the guest resumes
|
||||
#
|
||||
# Since: 1.1
|
||||
##
|
||||
{ 'command': 'guest-suspend-ram' }
|
||||
{ 'command': 'guest-suspend-ram', 'success-response': 'no' }
|
||||
|
||||
##
|
||||
# @guest-suspend-hybrid
|
||||
@@ -410,17 +421,21 @@
|
||||
# command. Thus, it's *required* to query QEMU for the presence of the
|
||||
# 'system_wakeup' command before issuing guest-suspend-hybrid.
|
||||
#
|
||||
# Returns: nothing on success
|
||||
# This command does NOT return a response on success. There are two options
|
||||
# to check for success:
|
||||
# 1. Wait for the SUSPEND QMP event from QEMU
|
||||
# 2. Issue the query-status QMP command to confirm the VM status is
|
||||
# "suspended"
|
||||
#
|
||||
# The following errors may be returned:
|
||||
# If hybrid suspend is not supported, Unsupported
|
||||
#
|
||||
# Notes: o This is an asynchronous request. There's no guarantee a response
|
||||
# will be sent
|
||||
# o It's strongly recommended to issue the guest-sync command before
|
||||
# sending commands when the guest resumes
|
||||
# Notes: It's strongly recommended to issue the guest-sync command before
|
||||
# sending commands when the guest resumes
|
||||
#
|
||||
# Since: 1.1
|
||||
##
|
||||
{ 'command': 'guest-suspend-hybrid' }
|
||||
{ 'command': 'guest-suspend-hybrid', 'success-response': 'no' }
|
||||
|
||||
##
|
||||
# @GuestIpAddressType:
|
||||
|
@@ -25,16 +25,24 @@ typedef enum QmpCommandType
|
||||
QCT_NORMAL,
|
||||
} QmpCommandType;
|
||||
|
||||
typedef enum QmpCommandOptions
|
||||
{
|
||||
QCO_NO_OPTIONS = 0x0,
|
||||
QCO_NO_SUCCESS_RESP = 0x1,
|
||||
} QmpCommandOptions;
|
||||
|
||||
typedef struct QmpCommand
|
||||
{
|
||||
const char *name;
|
||||
QmpCommandType type;
|
||||
QmpCommandFunc *fn;
|
||||
QmpCommandOptions options;
|
||||
QTAILQ_ENTRY(QmpCommand) node;
|
||||
bool enabled;
|
||||
} QmpCommand;
|
||||
|
||||
void qmp_register_command(const char *name, QmpCommandFunc *fn);
|
||||
void qmp_register_command(const char *name, QmpCommandFunc *fn,
|
||||
QmpCommandOptions options);
|
||||
QmpCommand *qmp_find_command(const char *name);
|
||||
QObject *qmp_dispatch(QObject *request);
|
||||
void qmp_disable_command(const char *name);
|
||||
|
@@ -94,8 +94,12 @@ static QObject *do_qmp_dispatch(QObject *request, Error **errp)
|
||||
switch (cmd->type) {
|
||||
case QCT_NORMAL:
|
||||
cmd->fn(args, &ret, errp);
|
||||
if (!error_is_set(errp) && ret == NULL) {
|
||||
ret = QOBJECT(qdict_new());
|
||||
if (!error_is_set(errp)) {
|
||||
if (cmd->options & QCO_NO_SUCCESS_RESP) {
|
||||
g_assert(!ret);
|
||||
} else if (!ret) {
|
||||
ret = QOBJECT(qdict_new());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@@ -17,7 +17,8 @@
|
||||
static QTAILQ_HEAD(QmpCommandList, QmpCommand) qmp_commands =
|
||||
QTAILQ_HEAD_INITIALIZER(qmp_commands);
|
||||
|
||||
void qmp_register_command(const char *name, QmpCommandFunc *fn)
|
||||
void qmp_register_command(const char *name, QmpCommandFunc *fn,
|
||||
QmpCommandOptions options)
|
||||
{
|
||||
QmpCommand *cmd = g_malloc0(sizeof(*cmd));
|
||||
|
||||
@@ -25,6 +26,7 @@ void qmp_register_command(const char *name, QmpCommandFunc *fn)
|
||||
cmd->type = QCT_NORMAL;
|
||||
cmd->fn = fn;
|
||||
cmd->enabled = true;
|
||||
cmd->options = options;
|
||||
QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node);
|
||||
}
|
||||
|
||||
|
49
qemu-ga.c
49
qemu-ga.c
@@ -104,16 +104,9 @@ static void quit_handler(int sig)
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
/* reap _all_ terminated children */
|
||||
static void child_handler(int sig)
|
||||
{
|
||||
int status;
|
||||
while (waitpid(-1, &status, WNOHANG) > 0) /* NOTHING */;
|
||||
}
|
||||
|
||||
static gboolean register_signal_handlers(void)
|
||||
{
|
||||
struct sigaction sigact, sigact_chld;
|
||||
struct sigaction sigact;
|
||||
int ret;
|
||||
|
||||
memset(&sigact, 0, sizeof(struct sigaction));
|
||||
@@ -130,15 +123,24 @@ static gboolean register_signal_handlers(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(&sigact_chld, 0, sizeof(struct sigaction));
|
||||
sigact_chld.sa_handler = child_handler;
|
||||
sigact_chld.sa_flags = SA_NOCLDSTOP;
|
||||
ret = sigaction(SIGCHLD, &sigact_chld, NULL);
|
||||
if (ret == -1) {
|
||||
g_error("error configuring signal handler: %s", strerror(errno));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* TODO: use this in place of all post-fork() fclose(std*) callers */
|
||||
void reopen_fd_to_null(int fd)
|
||||
{
|
||||
int nullfd;
|
||||
|
||||
nullfd = open("/dev/null", O_RDWR);
|
||||
if (nullfd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
return true;
|
||||
dup2(nullfd, fd);
|
||||
|
||||
if (nullfd != fd) {
|
||||
close(nullfd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -167,7 +169,7 @@ static void usage(const char *cmd)
|
||||
" -h, --help display this help and exit\n"
|
||||
"\n"
|
||||
"Report bugs to <mdroth@linux.vnet.ibm.com>\n"
|
||||
, cmd, QGA_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT,
|
||||
, cmd, QEMU_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT,
|
||||
QGA_STATEDIR_DEFAULT);
|
||||
}
|
||||
|
||||
@@ -428,9 +430,9 @@ static void become_daemon(const char *pidfile)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
reopen_fd_to_null(STDIN_FILENO);
|
||||
reopen_fd_to_null(STDOUT_FILENO);
|
||||
reopen_fd_to_null(STDERR_FILENO);
|
||||
return;
|
||||
|
||||
fail:
|
||||
@@ -488,8 +490,6 @@ static void process_command(GAState *s, QDict *req)
|
||||
g_warning("error sending response: %s", strerror(ret));
|
||||
}
|
||||
qobject_decref(rsp);
|
||||
} else {
|
||||
g_warning("error getting response");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -729,7 +729,7 @@ int main(int argc, char **argv)
|
||||
log_level = G_LOG_LEVEL_MASK;
|
||||
break;
|
||||
case 'V':
|
||||
printf("QEMU Guest Agent %s\n", QGA_VERSION);
|
||||
printf("QEMU Guest Agent %s\n", QEMU_VERSION);
|
||||
return 0;
|
||||
case 'd':
|
||||
daemonize = 1;
|
||||
@@ -836,12 +836,13 @@ int main(int argc, char **argv)
|
||||
become_daemon(pid_filepath);
|
||||
}
|
||||
if (log_filepath) {
|
||||
s->log_file = fopen(log_filepath, "a");
|
||||
if (!s->log_file) {
|
||||
FILE *log_file = fopen(log_filepath, "a");
|
||||
if (!log_file) {
|
||||
g_critical("unable to open specified log file: %s",
|
||||
strerror(errno));
|
||||
goto out_bad;
|
||||
}
|
||||
s->log_file = log_file;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -159,6 +159,24 @@ It can be used without an accessible old backing file, i.e. you can use it to
|
||||
fix an image whose backing file has already been moved/renamed.
|
||||
@end table
|
||||
|
||||
You can use @code{rebase} to perform a ``diff'' operation on two
|
||||
disk images. This can be useful when you have copied or cloned
|
||||
a guest, and you want to get back to a thin image on top of a
|
||||
template or base image.
|
||||
|
||||
Say that @code{base.img} has been cloned as @code{modified.img} by
|
||||
copying it, and that the @code{modified.img} guest has run so there
|
||||
are now some changes compared to @code{base.img}. To construct a thin
|
||||
image called @code{diff.qcow2} that contains just the differences, do:
|
||||
|
||||
@example
|
||||
qemu-img create -f qcow2 -b modified.img diff.qcow2
|
||||
qemu-img rebase -b base.img diff.qcow2
|
||||
@end example
|
||||
|
||||
At this point, @code{modified.img} can be discarded, since
|
||||
@code{base.img + diff.qcow2} contains the same information.
|
||||
|
||||
@item resize @var{filename} [+ | -]@var{size}
|
||||
|
||||
Change the disk image as if it had been created with @var{size}.
|
||||
|
@@ -14,12 +14,22 @@
|
||||
#include <glib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include "qga/guest-agent-core.h"
|
||||
#include "qga-qmp-commands.h"
|
||||
#include "qerror.h"
|
||||
#include "qemu-queue.h"
|
||||
#include "host-utils.h"
|
||||
|
||||
#ifndef CONFIG_HAS_ENVIRON
|
||||
#ifdef __APPLE__
|
||||
#include <crt_externs.h>
|
||||
#define environ (*_NSGetEnviron())
|
||||
#else
|
||||
extern char **environ;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <mntent.h>
|
||||
#include <linux/fs.h>
|
||||
@@ -27,36 +37,17 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#if defined(__linux__) && defined(FIFREEZE)
|
||||
#define CONFIG_FSFREEZE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
/* TODO: use this in place of all post-fork() fclose(std*) callers */
|
||||
static void reopen_fd_to_null(int fd)
|
||||
{
|
||||
int nullfd;
|
||||
|
||||
nullfd = open("/dev/null", O_RDWR);
|
||||
if (nullfd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
dup2(nullfd, fd);
|
||||
|
||||
if (nullfd != fd) {
|
||||
close(nullfd);
|
||||
}
|
||||
}
|
||||
#endif /* defined(__linux__) */
|
||||
|
||||
void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
|
||||
{
|
||||
int ret;
|
||||
const char *shutdown_flag;
|
||||
pid_t rpid, pid;
|
||||
int status;
|
||||
|
||||
slog("guest-shutdown called, mode: %s", mode);
|
||||
if (!has_mode || strcmp(mode, "powerdown") == 0) {
|
||||
@@ -71,23 +62,30 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = fork();
|
||||
if (ret == 0) {
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
/* child, start the shutdown */
|
||||
setsid();
|
||||
fclose(stdin);
|
||||
fclose(stdout);
|
||||
fclose(stderr);
|
||||
reopen_fd_to_null(0);
|
||||
reopen_fd_to_null(1);
|
||||
reopen_fd_to_null(2);
|
||||
|
||||
ret = execl("/sbin/shutdown", "shutdown", shutdown_flag, "+0",
|
||||
"hypervisor initiated shutdown", (char*)NULL);
|
||||
if (ret) {
|
||||
slog("guest-shutdown failed: %s", strerror(errno));
|
||||
}
|
||||
exit(!!ret);
|
||||
} else if (ret < 0) {
|
||||
error_set(err, QERR_UNDEFINED_ERROR);
|
||||
execle("/sbin/shutdown", "shutdown", shutdown_flag, "+0",
|
||||
"hypervisor initiated shutdown", (char*)NULL, environ);
|
||||
_exit(EXIT_FAILURE);
|
||||
} else if (pid < 0) {
|
||||
goto exit_err;
|
||||
}
|
||||
|
||||
do {
|
||||
rpid = waitpid(pid, &status, 0);
|
||||
} while (rpid == -1 && errno == EINTR);
|
||||
if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
exit_err:
|
||||
error_set(err, QERR_UNDEFINED_ERROR);
|
||||
}
|
||||
|
||||
typedef struct GuestFileHandle {
|
||||
@@ -347,7 +345,7 @@ static int guest_fsfreeze_build_mount_list(GuestFsfreezeMountList *mounts)
|
||||
{
|
||||
struct mntent *ment;
|
||||
GuestFsfreezeMount *mount;
|
||||
char const *mtab = MOUNTED;
|
||||
char const *mtab = "/proc/self/mounts";
|
||||
FILE *fp;
|
||||
|
||||
fp = setmntent(mtab, "r");
|
||||
@@ -531,117 +529,88 @@ static void guest_fsfreeze_cleanup(void)
|
||||
#define SUSPEND_SUPPORTED 0
|
||||
#define SUSPEND_NOT_SUPPORTED 1
|
||||
|
||||
/**
|
||||
* This function forks twice and the information about the mode support
|
||||
* status is passed to the qemu-ga process via a pipe.
|
||||
*
|
||||
* This approach allows us to keep the way we reap terminated children
|
||||
* in qemu-ga quite simple.
|
||||
*/
|
||||
static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg,
|
||||
const char *sysfile_str, Error **err)
|
||||
{
|
||||
pid_t pid;
|
||||
ssize_t ret;
|
||||
char *pmutils_path;
|
||||
int status, pipefds[2];
|
||||
|
||||
if (pipe(pipefds) < 0) {
|
||||
error_set(err, QERR_UNDEFINED_ERROR);
|
||||
return;
|
||||
}
|
||||
pid_t pid, rpid;
|
||||
int status;
|
||||
|
||||
pmutils_path = g_find_program_in_path(pmutils_bin);
|
||||
|
||||
pid = fork();
|
||||
if (!pid) {
|
||||
struct sigaction act;
|
||||
|
||||
memset(&act, 0, sizeof(act));
|
||||
act.sa_handler = SIG_DFL;
|
||||
sigaction(SIGCHLD, &act, NULL);
|
||||
char buf[32]; /* hopefully big enough */
|
||||
ssize_t ret;
|
||||
int fd;
|
||||
|
||||
setsid();
|
||||
close(pipefds[0]);
|
||||
reopen_fd_to_null(0);
|
||||
reopen_fd_to_null(1);
|
||||
reopen_fd_to_null(2);
|
||||
|
||||
pid = fork();
|
||||
if (!pid) {
|
||||
int fd;
|
||||
char buf[32]; /* hopefully big enough */
|
||||
if (pmutils_path) {
|
||||
execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
|
||||
}
|
||||
|
||||
if (pmutils_path) {
|
||||
execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get here either pm-utils is not installed or execle() has
|
||||
* failed. Let's try the manual method if the caller wants it.
|
||||
*/
|
||||
|
||||
if (!sysfile_str) {
|
||||
_exit(SUSPEND_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
_exit(SUSPEND_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
ret = read(fd, buf, sizeof(buf)-1);
|
||||
if (ret <= 0) {
|
||||
_exit(SUSPEND_NOT_SUPPORTED);
|
||||
}
|
||||
buf[ret] = '\0';
|
||||
|
||||
if (strstr(buf, sysfile_str)) {
|
||||
_exit(SUSPEND_SUPPORTED);
|
||||
}
|
||||
/*
|
||||
* If we get here either pm-utils is not installed or execle() has
|
||||
* failed. Let's try the manual method if the caller wants it.
|
||||
*/
|
||||
|
||||
if (!sysfile_str) {
|
||||
_exit(SUSPEND_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
wait(&status);
|
||||
} else {
|
||||
status = SUSPEND_NOT_SUPPORTED;
|
||||
fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
_exit(SUSPEND_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
ret = write(pipefds[1], &status, sizeof(status));
|
||||
if (ret != sizeof(status)) {
|
||||
_exit(EXIT_FAILURE);
|
||||
ret = read(fd, buf, sizeof(buf)-1);
|
||||
if (ret <= 0) {
|
||||
_exit(SUSPEND_NOT_SUPPORTED);
|
||||
}
|
||||
buf[ret] = '\0';
|
||||
|
||||
if (strstr(buf, sysfile_str)) {
|
||||
_exit(SUSPEND_SUPPORTED);
|
||||
}
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
_exit(SUSPEND_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
close(pipefds[1]);
|
||||
g_free(pmutils_path);
|
||||
|
||||
if (pid < 0) {
|
||||
error_set(err, QERR_UNDEFINED_ERROR);
|
||||
goto out;
|
||||
goto undef_err;
|
||||
}
|
||||
|
||||
ret = read(pipefds[0], &status, sizeof(status));
|
||||
if (ret == sizeof(status) && WIFEXITED(status) &&
|
||||
WEXITSTATUS(status) == SUSPEND_SUPPORTED) {
|
||||
goto out;
|
||||
do {
|
||||
rpid = waitpid(pid, &status, 0);
|
||||
} while (rpid == -1 && errno == EINTR);
|
||||
if (rpid == pid && WIFEXITED(status)) {
|
||||
switch (WEXITSTATUS(status)) {
|
||||
case SUSPEND_SUPPORTED:
|
||||
return;
|
||||
case SUSPEND_NOT_SUPPORTED:
|
||||
error_set(err, QERR_UNSUPPORTED);
|
||||
return;
|
||||
default:
|
||||
goto undef_err;
|
||||
}
|
||||
}
|
||||
|
||||
error_set(err, QERR_UNSUPPORTED);
|
||||
|
||||
out:
|
||||
close(pipefds[0]);
|
||||
undef_err:
|
||||
error_set(err, QERR_UNDEFINED_ERROR);
|
||||
}
|
||||
|
||||
static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
|
||||
Error **err)
|
||||
{
|
||||
pid_t pid;
|
||||
char *pmutils_path;
|
||||
pid_t rpid, pid;
|
||||
int status;
|
||||
|
||||
pmutils_path = g_find_program_in_path(pmutils_bin);
|
||||
|
||||
@@ -683,9 +652,18 @@ static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
|
||||
g_free(pmutils_path);
|
||||
|
||||
if (pid < 0) {
|
||||
error_set(err, QERR_UNDEFINED_ERROR);
|
||||
goto exit_err;
|
||||
}
|
||||
|
||||
do {
|
||||
rpid = waitpid(pid, &status, 0);
|
||||
} while (rpid == -1 && errno == EINTR);
|
||||
if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
exit_err:
|
||||
error_set(err, QERR_UNDEFINED_ERROR);
|
||||
}
|
||||
|
||||
void qmp_guest_suspend_disk(Error **err)
|
||||
|
@@ -52,7 +52,7 @@ struct GuestAgentInfo *qmp_guest_info(Error **err)
|
||||
GuestAgentCommandInfoList *cmd_info_list;
|
||||
char **cmd_list_head, **cmd_list;
|
||||
|
||||
info->version = g_strdup(QGA_VERSION);
|
||||
info->version = g_strdup(QEMU_VERSION);
|
||||
|
||||
cmd_list_head = cmd_list = qmp_get_command_list();
|
||||
if (*cmd_list_head == NULL) {
|
||||
|
@@ -13,7 +13,6 @@
|
||||
#include "qapi/qmp-core.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
#define QGA_VERSION "1.0"
|
||||
#define QGA_READ_COUNT_DEFAULT 4096
|
||||
|
||||
typedef struct GAState GAState;
|
||||
@@ -35,3 +34,7 @@ void ga_set_response_delimited(GAState *s);
|
||||
bool ga_is_frozen(GAState *s);
|
||||
void ga_set_frozen(GAState *s);
|
||||
void ga_unset_frozen(GAState *s);
|
||||
|
||||
#ifndef _WIN32
|
||||
void reopen_fd_to_null(int fd);
|
||||
#endif
|
||||
|
Submodule roms/openbios updated: ff61d973e5...d1d2787f87
@@ -291,14 +291,24 @@ out:
|
||||
|
||||
return ret
|
||||
|
||||
def option_value_matches(opt, val, cmd):
|
||||
if opt in cmd and cmd[opt] == val:
|
||||
return True
|
||||
return False
|
||||
|
||||
def gen_registry(commands):
|
||||
registry=""
|
||||
push_indent()
|
||||
for cmd in commands:
|
||||
options = 'QCO_NO_OPTIONS'
|
||||
if option_value_matches('success-response', 'no', cmd):
|
||||
options = 'QCO_NO_SUCCESS_RESP'
|
||||
|
||||
registry += mcgen('''
|
||||
qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s);
|
||||
qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s, %(opts)s);
|
||||
''',
|
||||
name=cmd['command'], c_name=c_fun(cmd['command']))
|
||||
name=cmd['command'], c_name=c_fun(cmd['command']),
|
||||
opts=options)
|
||||
pop_indent()
|
||||
ret = mcgen('''
|
||||
static void qmp_init_marshal(void)
|
||||
|
20
slirp/ip.h
20
slirp/ip.h
@@ -34,18 +34,14 @@
|
||||
#define _IP_H_
|
||||
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
# ifndef NTOHL
|
||||
# define NTOHL(d)
|
||||
# endif
|
||||
# ifndef NTOHS
|
||||
# define NTOHS(d)
|
||||
# endif
|
||||
# ifndef HTONL
|
||||
# define HTONL(d)
|
||||
# endif
|
||||
# ifndef HTONS
|
||||
# define HTONS(d)
|
||||
# endif
|
||||
# undef NTOHL
|
||||
# undef NTOHS
|
||||
# undef HTONL
|
||||
# undef HTONS
|
||||
# define NTOHL(d)
|
||||
# define NTOHS(d)
|
||||
# define HTONL(d)
|
||||
# define HTONS(d)
|
||||
#else
|
||||
# ifndef NTOHL
|
||||
# define NTOHL(d) ((d) = ntohl((d)))
|
||||
|
13
slirp/tcp.h
13
slirp/tcp.h
@@ -79,20 +79,23 @@ struct tcphdr {
|
||||
#define TCPOPT_EOL 0
|
||||
#define TCPOPT_NOP 1
|
||||
#define TCPOPT_MAXSEG 2
|
||||
#define TCPOLEN_MAXSEG 4
|
||||
#define TCPOPT_WINDOW 3
|
||||
#define TCPOLEN_WINDOW 3
|
||||
#define TCPOPT_SACK_PERMITTED 4 /* Experimental */
|
||||
#define TCPOLEN_SACK_PERMITTED 2
|
||||
#define TCPOPT_SACK 5 /* Experimental */
|
||||
#define TCPOPT_TIMESTAMP 8
|
||||
#define TCPOLEN_TIMESTAMP 10
|
||||
#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
|
||||
|
||||
#define TCPOPT_TSTAMP_HDR \
|
||||
(TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
|
||||
#endif
|
||||
|
||||
#ifndef TCPOLEN_MAXSEG
|
||||
#define TCPOLEN_MAXSEG 4
|
||||
#define TCPOLEN_WINDOW 3
|
||||
#define TCPOLEN_SACK_PERMITTED 2
|
||||
#define TCPOLEN_TIMESTAMP 10
|
||||
#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Default maximum segment size for TCP.
|
||||
* With an IP MSS of 576, this is 536,
|
||||
|
@@ -47,6 +47,7 @@ static const u_char tcp_outflags[TCP_NSTATES] = {
|
||||
};
|
||||
|
||||
|
||||
#undef MAX_TCPOPTLEN
|
||||
#define MAX_TCPOPTLEN 32 /* max # bytes that go in options */
|
||||
|
||||
/*
|
||||
|
@@ -238,6 +238,8 @@ typedef struct x86_def_t {
|
||||
/* Store the results of Centaur's CPUID instructions */
|
||||
uint32_t ext4_features;
|
||||
uint32_t xlevel2;
|
||||
/* The feature bits on CPUID[EAX=7,ECX=0].EBX */
|
||||
uint32_t cpuid_7_0_ebx_features;
|
||||
} x86_def_t;
|
||||
|
||||
#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
|
||||
@@ -521,6 +523,12 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
|
||||
x86_cpu_def->ext_features = ecx;
|
||||
x86_cpu_def->features = edx;
|
||||
|
||||
if (kvm_enabled() && x86_cpu_def->level >= 7) {
|
||||
x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX);
|
||||
} else {
|
||||
x86_cpu_def->cpuid_7_0_ebx_features = 0;
|
||||
}
|
||||
|
||||
host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
|
||||
x86_cpu_def->xlevel = eax;
|
||||
|
||||
@@ -1185,6 +1193,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model)
|
||||
env->cpuid_kvm_features = def->kvm_features;
|
||||
env->cpuid_svm_features = def->svm_features;
|
||||
env->cpuid_ext4_features = def->ext4_features;
|
||||
env->cpuid_7_0_ebx = def->cpuid_7_0_ebx_features;
|
||||
env->cpuid_xlevel2 = def->xlevel2;
|
||||
object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000,
|
||||
"tsc-frequency", &error);
|
||||
@@ -1451,13 +1460,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||
*edx = 0;
|
||||
break;
|
||||
case 7:
|
||||
if (kvm_enabled()) {
|
||||
KVMState *s = env->kvm_state;
|
||||
|
||||
*eax = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EAX);
|
||||
*ebx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EBX);
|
||||
*ecx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_ECX);
|
||||
*edx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EDX);
|
||||
/* Structured Extended Feature Flags Enumeration Leaf */
|
||||
if (count == 0) {
|
||||
*eax = 0; /* Maximum ECX value for sub-leaves */
|
||||
*ebx = env->cpuid_7_0_ebx; /* Feature flags */
|
||||
*ecx = 0; /* Reserved */
|
||||
*edx = 0; /* Reserved */
|
||||
} else {
|
||||
*eax = 0;
|
||||
*ebx = 0;
|
||||
|
@@ -741,6 +741,8 @@ typedef struct CPUX86State {
|
||||
/* Store the results of Centaur's CPUID instructions */
|
||||
uint32_t cpuid_xlevel2;
|
||||
uint32_t cpuid_ext4_features;
|
||||
/* Flags from CPUID[EAX=7,ECX=0].EBX */
|
||||
uint32_t cpuid_7_0_ebx;
|
||||
|
||||
/* MTRRs */
|
||||
uint64_t mtrr_fixed[11];
|
||||
|
@@ -743,7 +743,7 @@ static void dec_bit(DisasContext *dc)
|
||||
unsigned int op;
|
||||
int mem_index = cpu_mmu_index(dc->env);
|
||||
|
||||
op = dc->ir & ((1 << 8) - 1);
|
||||
op = dc->ir & ((1 << 9) - 1);
|
||||
switch (op) {
|
||||
case 0x21:
|
||||
/* src. */
|
||||
@@ -825,6 +825,16 @@ static void dec_bit(DisasContext *dc)
|
||||
gen_helper_clz(cpu_R[dc->rd], cpu_R[dc->ra]);
|
||||
}
|
||||
break;
|
||||
case 0x1e0:
|
||||
/* swapb */
|
||||
LOG_DIS("swapb r%d r%d\n", dc->rd, dc->ra);
|
||||
tcg_gen_bswap32_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
|
||||
break;
|
||||
case 0x1e1:
|
||||
/*swaph */
|
||||
LOG_DIS("swaph r%d r%d\n", dc->rd, dc->ra);
|
||||
tcg_gen_rotri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 16);
|
||||
break;
|
||||
default:
|
||||
cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
|
||||
dc->pc, op, dc->rd, dc->ra, dc->rb);
|
||||
|
@@ -6099,7 +6099,7 @@ static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
|
||||
tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
|
||||
tcg_gen_nor_i32(t0, t0, t1);
|
||||
tcg_gen_nand_i32(t0, t0, t1);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_gen_andi_i32(t0, t0, 1);
|
||||
tcg_gen_extu_i32_tl(bcond, t0);
|
||||
@@ -6123,11 +6123,11 @@ static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
|
||||
tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
|
||||
tcg_gen_or_i32(t0, t0, t1);
|
||||
tcg_gen_and_i32(t0, t0, t1);
|
||||
tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
|
||||
tcg_gen_or_i32(t0, t0, t1);
|
||||
tcg_gen_and_i32(t0, t0, t1);
|
||||
tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
|
||||
tcg_gen_nor_i32(t0, t0, t1);
|
||||
tcg_gen_nand_i32(t0, t0, t1);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_gen_andi_i32(t0, t0, 1);
|
||||
tcg_gen_extu_i32_tl(bcond, t0);
|
||||
|
@@ -24,7 +24,11 @@
|
||||
|
||||
static uint8_t *tb_ret_addr;
|
||||
|
||||
#ifdef _CALL_DARWIN
|
||||
#if defined _CALL_DARWIN || defined __APPLE__
|
||||
#define TCG_TARGET_CALL_DARWIN
|
||||
#endif
|
||||
|
||||
#ifdef TCG_TARGET_CALL_DARWIN
|
||||
#define LINKAGE_AREA_SIZE 24
|
||||
#define LR_OFFSET 8
|
||||
#elif defined _CALL_AIX
|
||||
@@ -99,7 +103,7 @@ static const int tcg_target_reg_alloc_order[] = {
|
||||
TCG_REG_R29,
|
||||
TCG_REG_R30,
|
||||
TCG_REG_R31,
|
||||
#ifdef _CALL_DARWIN
|
||||
#ifdef TCG_TARGET_CALL_DARWIN
|
||||
TCG_REG_R2,
|
||||
#endif
|
||||
TCG_REG_R3,
|
||||
@@ -110,7 +114,7 @@ static const int tcg_target_reg_alloc_order[] = {
|
||||
TCG_REG_R8,
|
||||
TCG_REG_R9,
|
||||
TCG_REG_R10,
|
||||
#ifndef _CALL_DARWIN
|
||||
#ifndef TCG_TARGET_CALL_DARWIN
|
||||
TCG_REG_R11,
|
||||
#endif
|
||||
TCG_REG_R12,
|
||||
@@ -140,7 +144,7 @@ static const int tcg_target_call_oarg_regs[2] = {
|
||||
};
|
||||
|
||||
static const int tcg_target_callee_save_regs[] = {
|
||||
#ifdef _CALL_DARWIN
|
||||
#ifdef TCG_TARGET_CALL_DARWIN
|
||||
TCG_REG_R11,
|
||||
TCG_REG_R13,
|
||||
#endif
|
||||
@@ -1965,7 +1969,7 @@ static void tcg_target_init(TCGContext *s)
|
||||
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
|
||||
tcg_regset_set32(tcg_target_call_clobber_regs, 0,
|
||||
(1 << TCG_REG_R0) |
|
||||
#ifdef _CALL_DARWIN
|
||||
#ifdef TCG_TARGET_CALL_DARWIN
|
||||
(1 << TCG_REG_R2) |
|
||||
#endif
|
||||
(1 << TCG_REG_R3) |
|
||||
@@ -1983,7 +1987,7 @@ static void tcg_target_init(TCGContext *s)
|
||||
tcg_regset_clear(s->reserved_regs);
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);
|
||||
#ifndef _CALL_DARWIN
|
||||
#ifndef TCG_TARGET_CALL_DARWIN
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2);
|
||||
#endif
|
||||
#ifdef _CALL_SYSV
|
||||
|
@@ -18,8 +18,8 @@ check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
|
||||
|
||||
# All QTests for now are POSIX-only, but the dependencies are
|
||||
# really in libqtest, not in the testcases themselves.
|
||||
check-qtest-i386-y = tests/rtc-test$(EXESUF)
|
||||
check-qtest-i386-y = tests/fdc-test$(EXESUF)
|
||||
check-qtest-i386-y += tests/rtc-test$(EXESUF)
|
||||
check-qtest-x86_64-y = $(check-qtest-i386-y)
|
||||
check-qtest-sparc-y = tests/m48t59-test$(EXESUF)
|
||||
check-qtest-sparc64-y = tests/m48t59-test$(EXESUF)
|
||||
@@ -68,7 +68,7 @@ tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marsh
|
||||
|
||||
tests/rtc-test$(EXESUF): tests/rtc-test.o $(trace-obj-y)
|
||||
tests/m48t59-test$(EXESUF): tests/m48t59-test.o $(trace-obj-y)
|
||||
tests/fdc-test$(EXESUF): tests/fdc-test.o tests/libqtest.o
|
||||
tests/fdc-test$(EXESUF): tests/fdc-test.o tests/libqtest.o $(trace-obj-y)
|
||||
|
||||
# QTest rules
|
||||
|
||||
|
@@ -63,6 +63,12 @@ char test_image[] = "/tmp/qtest.XXXXXX";
|
||||
#define assert_bit_set(data, mask) g_assert_cmphex((data) & (mask), ==, (mask))
|
||||
#define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0)
|
||||
|
||||
static uint8_t base = 0x70;
|
||||
|
||||
enum {
|
||||
CMOS_FLOPPY = 0x10,
|
||||
};
|
||||
|
||||
static void floppy_send(uint8_t byte)
|
||||
{
|
||||
uint8_t msr;
|
||||
@@ -108,16 +114,59 @@ static void send_step_pulse(void)
|
||||
cyl = (cyl + 1) % 4;
|
||||
}
|
||||
|
||||
static uint8_t cmos_read(uint8_t reg)
|
||||
{
|
||||
outb(base + 0, reg);
|
||||
return inb(base + 1);
|
||||
}
|
||||
|
||||
static void test_cmos(void)
|
||||
{
|
||||
uint8_t cmos;
|
||||
|
||||
cmos = cmos_read(CMOS_FLOPPY);
|
||||
g_assert(cmos == 0x40);
|
||||
}
|
||||
|
||||
static void test_no_media_on_start(void)
|
||||
{
|
||||
uint8_t dir;
|
||||
|
||||
/* Media changed bit must be set all time after start if there is
|
||||
* no media in drive. */
|
||||
dir = inb(FLOPPY_BASE + reg_dir);
|
||||
assert_bit_set(dir, DSKCHG);
|
||||
dir = inb(FLOPPY_BASE + reg_dir);
|
||||
assert_bit_set(dir, DSKCHG);
|
||||
send_step_pulse();
|
||||
send_step_pulse();
|
||||
dir = inb(FLOPPY_BASE + reg_dir);
|
||||
assert_bit_set(dir, DSKCHG);
|
||||
dir = inb(FLOPPY_BASE + reg_dir);
|
||||
assert_bit_set(dir, DSKCHG);
|
||||
}
|
||||
|
||||
static void test_media_change(void)
|
||||
{
|
||||
uint8_t dir;
|
||||
|
||||
/* Media changed bit must be up-to-date after step pulse. Do two SEEKs
|
||||
* because we may already happen to be on the right cylinder initially. */
|
||||
send_step_pulse();
|
||||
/* Insert media in drive. DSKCHK should not be reset until a step pulse
|
||||
* is sent. */
|
||||
qmp("{'execute':'change', 'arguments':{ 'device':'floppy0', "
|
||||
"'target': '%s' }}", test_image);
|
||||
qmp(""); /* ignore event (FIXME open -> open transition?!) */
|
||||
qmp(""); /* ignore event */
|
||||
|
||||
dir = inb(FLOPPY_BASE + reg_dir);
|
||||
assert_bit_set(dir, DSKCHG);
|
||||
dir = inb(FLOPPY_BASE + reg_dir);
|
||||
assert_bit_set(dir, DSKCHG);
|
||||
|
||||
send_step_pulse();
|
||||
dir = inb(FLOPPY_BASE + reg_dir);
|
||||
assert_bit_clear(dir, DSKCHG);
|
||||
dir = inb(FLOPPY_BASE + reg_dir);
|
||||
assert_bit_clear(dir, DSKCHG);
|
||||
|
||||
/* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
|
||||
* reset the bit. */
|
||||
@@ -134,24 +183,6 @@ static void test_media_change(void)
|
||||
assert_bit_set(dir, DSKCHG);
|
||||
dir = inb(FLOPPY_BASE + reg_dir);
|
||||
assert_bit_set(dir, DSKCHG);
|
||||
|
||||
/* And then insert it again. DSKCHK should not be reset until a step pulse
|
||||
* is sent. */
|
||||
qmp("{'execute':'change', 'arguments':{ 'device':'floppy0', "
|
||||
"'target': '%s' }}", test_image);
|
||||
qmp(""); /* ignore event (FIXME open -> open transition?!) */
|
||||
qmp(""); /* ignore event */
|
||||
|
||||
dir = inb(FLOPPY_BASE + reg_dir);
|
||||
assert_bit_set(dir, DSKCHG);
|
||||
dir = inb(FLOPPY_BASE + reg_dir);
|
||||
assert_bit_set(dir, DSKCHG);
|
||||
|
||||
send_step_pulse();
|
||||
dir = inb(FLOPPY_BASE + reg_dir);
|
||||
assert_bit_clear(dir, DSKCHG);
|
||||
dir = inb(FLOPPY_BASE + reg_dir);
|
||||
assert_bit_clear(dir, DSKCHG);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@@ -177,12 +208,12 @@ int main(int argc, char **argv)
|
||||
/* Run the tests */
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
cmdline = g_strdup_printf("-vnc none "
|
||||
"-drive file=%s,if=floppy,cache=writeback ",
|
||||
test_image);
|
||||
cmdline = g_strdup_printf("-vnc none ");
|
||||
|
||||
qtest_start(cmdline);
|
||||
qtest_irq_intercept_in(global_qtest, "ioapic");
|
||||
qtest_add_func("/fdc/cmos", test_cmos);
|
||||
qtest_add_func("/fdc/no_media_on_start", test_no_media_on_start);
|
||||
qtest_add_func("/fdc/media_change", test_media_change);
|
||||
|
||||
ret = g_test_run();
|
||||
|
@@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt generic
|
||||
_supported_fmt qcow2
|
||||
_supported_proto generic
|
||||
_supported_os Linux
|
||||
|
||||
|
@@ -602,9 +602,9 @@ escc_kbd_command(int val) "Command %d"
|
||||
escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x"
|
||||
|
||||
# block/iscsi.c
|
||||
iscsi_aio_write10_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
|
||||
iscsi_aio_write16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
|
||||
iscsi_aio_writev(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p"
|
||||
iscsi_aio_read10_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
|
||||
iscsi_aio_read16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
|
||||
iscsi_aio_readv(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p"
|
||||
|
||||
# hw/esp.c
|
||||
|
@@ -879,7 +879,8 @@ int main (int argc, const char * argv[]) {
|
||||
!strcmp(opt, "-vnc") ||
|
||||
!strcmp(opt, "-nographic") ||
|
||||
!strcmp(opt, "-version") ||
|
||||
!strcmp(opt, "-curses")) {
|
||||
!strcmp(opt, "-curses") ||
|
||||
!strcmp(opt, "-qtest")) {
|
||||
return qemu_main(gArgc, gArgv, *_NSGetEnviron());
|
||||
}
|
||||
}
|
||||
|
4
ui/vnc.c
4
ui/vnc.c
@@ -2849,6 +2849,10 @@ int vnc_display_pw_expire(DisplayState *ds, time_t expires)
|
||||
{
|
||||
VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
|
||||
|
||||
if (!vs) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vs->expires = expires;
|
||||
return 0;
|
||||
}
|
||||
|
22
xen-all.c
22
xen-all.c
@@ -603,6 +603,10 @@ void xen_vcpu_init(void)
|
||||
qemu_register_reset(xen_reset_vcpu, first_cpu);
|
||||
xen_reset_vcpu(first_cpu);
|
||||
}
|
||||
/* if rtc_clock is left to default (host_clock), disable it */
|
||||
if (rtc_clock == host_clock) {
|
||||
qemu_clock_enable(rtc_clock, false);
|
||||
}
|
||||
}
|
||||
|
||||
/* get the ioreq packets from share mem */
|
||||
@@ -856,7 +860,7 @@ static void cpu_handle_ioreq(void *opaque)
|
||||
"data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
|
||||
req->state, req->data_is_ptr, req->addr,
|
||||
req->data, req->count, req->size);
|
||||
destroy_hvm_domain();
|
||||
destroy_hvm_domain(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -870,10 +874,11 @@ static void cpu_handle_ioreq(void *opaque)
|
||||
*/
|
||||
if (runstate_is_running()) {
|
||||
if (qemu_shutdown_requested_get()) {
|
||||
destroy_hvm_domain();
|
||||
destroy_hvm_domain(false);
|
||||
}
|
||||
if (qemu_reset_requested_get()) {
|
||||
qemu_system_reset(VMRESET_REPORT);
|
||||
destroy_hvm_domain(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1159,7 +1164,7 @@ int xen_hvm_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void destroy_hvm_domain(void)
|
||||
void destroy_hvm_domain(bool reboot)
|
||||
{
|
||||
XenXC xc_handle;
|
||||
int sts;
|
||||
@@ -1168,12 +1173,15 @@ void destroy_hvm_domain(void)
|
||||
if (xc_handle == XC_HANDLER_INITIAL_VALUE) {
|
||||
fprintf(stderr, "Cannot acquire xenctrl handle\n");
|
||||
} else {
|
||||
sts = xc_domain_shutdown(xc_handle, xen_domid, SHUTDOWN_poweroff);
|
||||
sts = xc_domain_shutdown(xc_handle, xen_domid,
|
||||
reboot ? SHUTDOWN_reboot : SHUTDOWN_poweroff);
|
||||
if (sts != 0) {
|
||||
fprintf(stderr, "? xc_domain_shutdown failed to issue poweroff, "
|
||||
"sts %d, %s\n", sts, strerror(errno));
|
||||
fprintf(stderr, "xc_domain_shutdown failed to issue %s, "
|
||||
"sts %d, %s\n", reboot ? "reboot" : "poweroff",
|
||||
sts, strerror(errno));
|
||||
} else {
|
||||
fprintf(stderr, "Issued domain %d poweroff\n", xen_domid);
|
||||
fprintf(stderr, "Issued domain %d %s\n", xen_domid,
|
||||
reboot ? "reboot" : "poweroff");
|
||||
}
|
||||
xc_interface_close(xc_handle);
|
||||
}
|
||||
|
Reference in New Issue
Block a user