Compare commits
74
Commits
v0.10.4
...
stable-0.10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b38d3f24d2 | ||
|
|
5c59f6c246 | ||
|
|
36170c5faf | ||
|
|
c2723a9606 | ||
|
|
07ca62486b | ||
|
|
0cbbf2533e | ||
|
|
f3c7245f23 | ||
|
|
d4779e9572 | ||
|
|
18bae8a516 | ||
|
|
74ccfe8b7e | ||
|
|
e24c7580cb | ||
|
|
f16f83481c | ||
|
|
b358a08e7b | ||
|
|
f81eed9ddb | ||
|
|
0dd99a1e37 | ||
|
|
07fdfe83cf | ||
|
|
9eab386edb | ||
|
|
0def14568c | ||
|
|
ca888361bb | ||
|
|
df97ff696b | ||
|
|
cc15f92832 | ||
|
|
2670257db0 | ||
|
|
aae9547639 | ||
|
|
2872b8a445 | ||
|
|
51224c6f78 | ||
|
|
ed8f8da7a6 | ||
|
|
960b646371 | ||
|
|
fc78bd4503 | ||
|
|
259cf68eb1 | ||
|
|
41de90f32c | ||
|
|
3e6b53eb32 | ||
|
|
80de8ace66 | ||
|
|
ea0c91a0af | ||
|
|
71080d96fd | ||
|
|
a5617318fe | ||
|
|
73cf22cb60 | ||
|
|
04f4e710a0 | ||
|
|
accceed914 | ||
|
|
f29602ca0e | ||
|
|
17489dd7e9 | ||
|
|
936d7bf944 | ||
|
|
d13317e197 | ||
|
|
75204ffc5b | ||
|
|
9fb2ec9a1e | ||
|
|
a8bc8570fa | ||
|
|
700ece804f | ||
|
|
71c55593c0 | ||
|
|
5982abd9ca | ||
|
|
738208b656 | ||
|
|
61348b076b | ||
|
|
9e3a7df77c | ||
|
|
0926c7a4e5 | ||
|
|
a02ba54eed | ||
|
|
578485d835 | ||
|
|
a675d9b8b5 | ||
|
|
ce60db1da2 | ||
|
|
428009b4aa | ||
|
|
c87a097b4a | ||
|
|
2fbc3b4c81 | ||
|
|
8765893e9e | ||
|
|
822624e5d6 | ||
|
|
fe54857a13 | ||
|
|
ee60269c23 | ||
|
|
3978d7b4c8 | ||
|
|
dc0be040c2 | ||
|
|
1570841432 | ||
|
|
a59cc95e23 | ||
|
|
2058679372 | ||
|
|
f1cfb26c5a | ||
|
|
662524f5dc | ||
|
|
5f6521c78e | ||
|
|
abe73c324e | ||
|
|
ed16937820 | ||
|
|
faf8a63492 |
No files matched your search
@@ -1,3 +1,45 @@
|
||||
version 0.10.6:
|
||||
- e1000: ignore reset command (Kevin Wolf)
|
||||
- fix VNC memory allocation (Stefan Weil)
|
||||
- fix raw_pread_aligned return value (Christoph Hellwig)
|
||||
- allow monitor interaction when using -incoming exec: (Chris Lalancette)
|
||||
- fix -net socket,listen (Jan Kiszka)
|
||||
- live migration: don't send gratuitous packets all at once (Gleb Natapov)
|
||||
- serial: fix lost characters after sysrq (Jason Wessel)
|
||||
- Fix prototype of zfree (Stefan Weil)
|
||||
- Handle EINTR with exec: migration (Uri Lublin)
|
||||
- Delete io-handler before closing fd after migration (Uri Lublin)
|
||||
- Fix qemu_aio_flush (Andrea Arcangeli)
|
||||
- lsi53c895a: Implement additional registers (Sebastian Herbszt)
|
||||
- virtio-blk: fix warning (Gerd Hoffman)
|
||||
- i386: fix cpu reset (Nitin Kamble)
|
||||
- kvm: fix irq injection into full queue (Jan Kiszka)
|
||||
- Prevent CD-ROM eject while device is locked (Mark McLoughlin)
|
||||
- Fix screen dump with blank screen (Eduardo Habkost)
|
||||
- Fix memory leak with cpu_unregister_map_client (Isaku Yamahata)
|
||||
- Fix memory leak in SDL (Jan Kiszka)
|
||||
- Fix build on OS X 10.4 (John Arbuckle)
|
||||
- Fix leak of vlan clients after hot remove (Mark McLoughlin)
|
||||
- Fix migration after hot remove with eepro100 (Mark McLoughlin)
|
||||
- Don't start a VM after failed migration if stopped (Anthony Liguori)
|
||||
- Fix live migration under heavy IO load (Glauber Costa)
|
||||
- Honor -S on incoming migration (Paolo Bonzini)
|
||||
- Reset HPET config register on reset (Beth Kon)
|
||||
- Reset PS2 keyboard/mouse on reset (Dinesh Subraveti)
|
||||
|
||||
version 0.10.5:
|
||||
- kvm: trim unsupported cpu features from cpuid (Avi Kivity)
|
||||
- kvm: provide a better error message for -smp > 1 (Mark McLoughlin)
|
||||
- Remove initrd printfs (Richard Jones)
|
||||
- Initial variables found by valgrind (Jean-Christophe Dubois)
|
||||
- Fix -initrd with > 4GB guests (Glauber Costa)
|
||||
- Fix busy loop on live migration for certain platforms (Uri Lublin)
|
||||
- Remove GCC 3.x requirements from docs (Hollis Blanchard)
|
||||
- ETRAX: fixes for kernel command line, ethernet address, bmi (Edgar Iglesias)
|
||||
- CRIS: Fix bmi (Edgar Iglesias)
|
||||
- Fix bounce buffer errors (Avi Kivity)
|
||||
- Fix regression in -kernel (Anthony Liguori)
|
||||
|
||||
version 0.10.4:
|
||||
- Improve block range checks to remove integer overflow (Kevin Wolf)
|
||||
- e1000: do not re-init PCI config space 0 (Amit Shah)
|
||||
|
||||
@@ -103,12 +103,16 @@ void qemu_aio_flush(void)
|
||||
do {
|
||||
ret = 0;
|
||||
|
||||
/*
|
||||
* If there are pending emulated aio start them now so flush
|
||||
* will be able to return 1.
|
||||
*/
|
||||
qemu_aio_wait();
|
||||
|
||||
LIST_FOREACH(node, &aio_handlers, node) {
|
||||
ret |= node->io_flush(node->opaque);
|
||||
}
|
||||
|
||||
qemu_aio_wait();
|
||||
} while (ret > 0);
|
||||
} while (qemu_bh_poll() || ret > 0);
|
||||
}
|
||||
|
||||
void qemu_aio_wait(void)
|
||||
|
||||
+5
-1
@@ -75,7 +75,11 @@
|
||||
|
||||
/* OS X does not have O_DSYNC */
|
||||
#ifndef O_DSYNC
|
||||
#ifdef O_SYNC
|
||||
#define O_DSYNC O_SYNC
|
||||
#elif defined(O_FSYNC)
|
||||
#define O_DSYNC O_FSYNC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */
|
||||
@@ -234,7 +238,7 @@ static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
label__raw_read__success:
|
||||
|
||||
return ret;
|
||||
return (ret < 0) ? -errno : ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+15
-14
@@ -169,7 +169,7 @@ static int vmdk_is_cid_valid(BlockDriverState *bs)
|
||||
{
|
||||
#ifdef CHECK_CID
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
BlockDriverState *p_bs = s->hd->backing_hd;
|
||||
BlockDriverState *p_bs = bs->backing_hd;
|
||||
uint32_t cur_pcid;
|
||||
|
||||
if (p_bs) {
|
||||
@@ -337,26 +337,26 @@ static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
|
||||
p_name += sizeof("parentFileNameHint") + 1;
|
||||
if ((end_name = strchr(p_name,'\"')) == 0)
|
||||
return -1;
|
||||
if ((end_name - p_name) > sizeof (s->hd->backing_file) - 1)
|
||||
if ((end_name - p_name) > sizeof (bs->backing_file) - 1)
|
||||
return -1;
|
||||
|
||||
pstrcpy(s->hd->backing_file, end_name - p_name + 1, p_name);
|
||||
if (stat(s->hd->backing_file, &file_buf) != 0) {
|
||||
pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
|
||||
if (stat(bs->backing_file, &file_buf) != 0) {
|
||||
path_combine(parent_img_name, sizeof(parent_img_name),
|
||||
filename, s->hd->backing_file);
|
||||
filename, bs->backing_file);
|
||||
} else {
|
||||
pstrcpy(parent_img_name, sizeof(parent_img_name),
|
||||
s->hd->backing_file);
|
||||
bs->backing_file);
|
||||
}
|
||||
|
||||
s->hd->backing_hd = bdrv_new("");
|
||||
if (!s->hd->backing_hd) {
|
||||
bs->backing_hd = bdrv_new("");
|
||||
if (!bs->backing_hd) {
|
||||
failure:
|
||||
bdrv_close(s->hd);
|
||||
return -1;
|
||||
}
|
||||
parent_open = 1;
|
||||
if (bdrv_open(s->hd->backing_hd, parent_img_name, BDRV_O_RDONLY) < 0)
|
||||
if (bdrv_open(bs->backing_hd, parent_img_name, BDRV_O_RDONLY) < 0)
|
||||
goto failure;
|
||||
parent_open = 0;
|
||||
}
|
||||
@@ -463,13 +463,14 @@ static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
|
||||
|
||||
// we will be here if it's first write on non-exist grain(cluster).
|
||||
// try to read from parent image, if exist
|
||||
if (s->hd->backing_hd) {
|
||||
BDRVVmdkState *ps = s->hd->backing_hd->opaque;
|
||||
if (bs->backing_hd) {
|
||||
BDRVVmdkState *ps = bs->backing_hd->opaque;
|
||||
|
||||
if (!vmdk_is_cid_valid(bs))
|
||||
return -1;
|
||||
|
||||
parent_cluster_offset = get_cluster_offset(s->hd->backing_hd, NULL, offset, allocate);
|
||||
parent_cluster_offset = get_cluster_offset(bs->backing_hd, NULL,
|
||||
offset, allocate);
|
||||
|
||||
if (parent_cluster_offset) {
|
||||
BDRVVmdkState *act_s = activeBDRV.hd->opaque;
|
||||
@@ -620,10 +621,10 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
|
||||
n = nb_sectors;
|
||||
if (!cluster_offset) {
|
||||
// try to read from parent image, if exist
|
||||
if (s->hd->backing_hd) {
|
||||
if (bs->backing_hd) {
|
||||
if (!vmdk_is_cid_valid(bs))
|
||||
return -1;
|
||||
ret = bdrv_read(s->hd->backing_hd, sector_num, buf, n);
|
||||
ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
} else {
|
||||
|
||||
@@ -1332,31 +1332,32 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
|
||||
/**************************************************************/
|
||||
/* async I/Os */
|
||||
|
||||
typedef struct VectorTranslationState {
|
||||
typedef struct VectorTranslationAIOCB {
|
||||
BlockDriverAIOCB common;
|
||||
QEMUIOVector *iov;
|
||||
uint8_t *bounce;
|
||||
int is_write;
|
||||
BlockDriverAIOCB *aiocb;
|
||||
BlockDriverAIOCB *this_aiocb;
|
||||
} VectorTranslationState;
|
||||
} VectorTranslationAIOCB;
|
||||
|
||||
static void bdrv_aio_cancel_vector(BlockDriverAIOCB *acb)
|
||||
static void bdrv_aio_cancel_vector(BlockDriverAIOCB *_acb)
|
||||
{
|
||||
VectorTranslationState *s = acb->opaque;
|
||||
VectorTranslationAIOCB *acb
|
||||
= container_of(_acb, VectorTranslationAIOCB, common);
|
||||
|
||||
bdrv_aio_cancel(s->aiocb);
|
||||
bdrv_aio_cancel(acb->aiocb);
|
||||
}
|
||||
|
||||
static void bdrv_aio_rw_vector_cb(void *opaque, int ret)
|
||||
{
|
||||
VectorTranslationState *s = opaque;
|
||||
VectorTranslationAIOCB *s = (VectorTranslationAIOCB *)opaque;
|
||||
|
||||
if (!s->is_write) {
|
||||
qemu_iovec_from_buffer(s->iov, s->bounce, s->iov->size);
|
||||
}
|
||||
qemu_vfree(s->bounce);
|
||||
s->this_aiocb->cb(s->this_aiocb->opaque, ret);
|
||||
qemu_aio_release(s->this_aiocb);
|
||||
s->common.cb(s->common.opaque, ret);
|
||||
qemu_aio_release(s);
|
||||
}
|
||||
|
||||
static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
|
||||
@@ -1368,11 +1369,9 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
|
||||
int is_write)
|
||||
|
||||
{
|
||||
VectorTranslationState *s = qemu_mallocz(sizeof(*s));
|
||||
BlockDriverAIOCB *aiocb = qemu_aio_get_pool(&vectored_aio_pool, bs,
|
||||
cb, opaque);
|
||||
VectorTranslationAIOCB *s = qemu_aio_get_pool(&vectored_aio_pool, bs,
|
||||
cb, opaque);
|
||||
|
||||
s->this_aiocb = aiocb;
|
||||
s->iov = iov;
|
||||
s->bounce = qemu_memalign(512, nb_sectors * 512);
|
||||
s->is_write = is_write;
|
||||
@@ -1384,7 +1383,12 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
|
||||
s->aiocb = bdrv_aio_read(bs, sector_num, s->bounce, nb_sectors,
|
||||
bdrv_aio_rw_vector_cb, s);
|
||||
}
|
||||
return aiocb;
|
||||
if (!s->aiocb) {
|
||||
qemu_vfree(s->bounce);
|
||||
qemu_aio_release(s);
|
||||
return NULL;
|
||||
}
|
||||
return &s->common;
|
||||
}
|
||||
|
||||
BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
@@ -1560,7 +1564,7 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
void bdrv_init(void)
|
||||
{
|
||||
aio_pool_init(&vectored_aio_pool, sizeof(BlockDriverAIOCB),
|
||||
aio_pool_init(&vectored_aio_pool, sizeof(VectorTranslationAIOCB),
|
||||
bdrv_aio_cancel_vector);
|
||||
|
||||
bdrv_register(&bdrv_raw);
|
||||
@@ -1660,11 +1664,15 @@ int bdrv_media_changed(BlockDriverState *bs)
|
||||
/**
|
||||
* If eject_flag is TRUE, eject the media. Otherwise, close the tray
|
||||
*/
|
||||
void bdrv_eject(BlockDriverState *bs, int eject_flag)
|
||||
int bdrv_eject(BlockDriverState *bs, int eject_flag)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
int ret;
|
||||
|
||||
if (bs->locked) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!drv || !drv->bdrv_eject) {
|
||||
ret = -ENOTSUP;
|
||||
} else {
|
||||
@@ -1673,7 +1681,10 @@ void bdrv_eject(BlockDriverState *bs, int eject_flag)
|
||||
if (ret == -ENOTSUP) {
|
||||
if (eject_flag)
|
||||
bdrv_close(bs);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bdrv_is_locked(BlockDriverState *bs)
|
||||
|
||||
@@ -132,7 +132,7 @@ int bdrv_is_inserted(BlockDriverState *bs);
|
||||
int bdrv_media_changed(BlockDriverState *bs);
|
||||
int bdrv_is_locked(BlockDriverState *bs);
|
||||
void bdrv_set_locked(BlockDriverState *bs, int locked);
|
||||
void bdrv_eject(BlockDriverState *bs, int eject_flag);
|
||||
int bdrv_eject(BlockDriverState *bs, int eject_flag);
|
||||
void bdrv_set_change_cb(BlockDriverState *bs,
|
||||
void (*change_cb)(void *opaque), void *opaque);
|
||||
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
|
||||
|
||||
@@ -370,7 +370,4 @@ void curses_display_init(DisplayState *ds, int full_screen)
|
||||
ds->surface = qemu_create_displaysurface_from(640, 400, 0, 0, (uint8_t*) screen);
|
||||
|
||||
invalidate = 1;
|
||||
|
||||
/* Standard VGA initial text mode dimensions */
|
||||
curses_resize(ds);
|
||||
}
|
||||
+39
-21
@@ -39,6 +39,7 @@ void qemu_sglist_destroy(QEMUSGList *qsg)
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
BlockDriverAIOCB common;
|
||||
BlockDriverState *bs;
|
||||
BlockDriverAIOCB *acb;
|
||||
QEMUSGList *sg;
|
||||
@@ -48,13 +49,13 @@ typedef struct {
|
||||
target_phys_addr_t sg_cur_byte;
|
||||
QEMUIOVector iov;
|
||||
QEMUBH *bh;
|
||||
} DMABlockState;
|
||||
} DMAAIOCB;
|
||||
|
||||
static void dma_bdrv_cb(void *opaque, int ret);
|
||||
|
||||
static void reschedule_dma(void *opaque)
|
||||
{
|
||||
DMABlockState *dbs = (DMABlockState *)opaque;
|
||||
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
|
||||
|
||||
qemu_bh_delete(dbs->bh);
|
||||
dbs->bh = NULL;
|
||||
@@ -63,32 +64,38 @@ static void reschedule_dma(void *opaque)
|
||||
|
||||
static void continue_after_map_failure(void *opaque)
|
||||
{
|
||||
DMABlockState *dbs = (DMABlockState *)opaque;
|
||||
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
|
||||
|
||||
dbs->bh = qemu_bh_new(reschedule_dma, dbs);
|
||||
qemu_bh_schedule(dbs->bh);
|
||||
}
|
||||
|
||||
static void dma_bdrv_cb(void *opaque, int ret)
|
||||
static void dma_bdrv_unmap(DMAAIOCB *dbs)
|
||||
{
|
||||
DMABlockState *dbs = (DMABlockState *)opaque;
|
||||
target_phys_addr_t cur_addr, cur_len;
|
||||
void *mem;
|
||||
int i;
|
||||
|
||||
dbs->sector_num += dbs->iov.size / 512;
|
||||
for (i = 0; i < dbs->iov.niov; ++i) {
|
||||
cpu_physical_memory_unmap(dbs->iov.iov[i].iov_base,
|
||||
dbs->iov.iov[i].iov_len, !dbs->is_write,
|
||||
dbs->iov.iov[i].iov_len);
|
||||
}
|
||||
}
|
||||
|
||||
void dma_bdrv_cb(void *opaque, int ret)
|
||||
{
|
||||
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
|
||||
target_phys_addr_t cur_addr, cur_len;
|
||||
void *mem;
|
||||
|
||||
dbs->acb = NULL;
|
||||
dbs->sector_num += dbs->iov.size / 512;
|
||||
dma_bdrv_unmap(dbs);
|
||||
qemu_iovec_reset(&dbs->iov);
|
||||
|
||||
if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
|
||||
dbs->acb->cb(dbs->acb->opaque, ret);
|
||||
dbs->common.cb(dbs->common.opaque, ret);
|
||||
qemu_iovec_destroy(&dbs->iov);
|
||||
qemu_aio_release(dbs->acb);
|
||||
qemu_free(dbs);
|
||||
qemu_aio_release(dbs);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -112,11 +119,16 @@ static void dma_bdrv_cb(void *opaque, int ret)
|
||||
}
|
||||
|
||||
if (dbs->is_write) {
|
||||
bdrv_aio_writev(dbs->bs, dbs->sector_num, &dbs->iov,
|
||||
dbs->iov.size / 512, dma_bdrv_cb, dbs);
|
||||
dbs->acb = bdrv_aio_writev(dbs->bs, dbs->sector_num, &dbs->iov,
|
||||
dbs->iov.size / 512, dma_bdrv_cb, dbs);
|
||||
} else {
|
||||
bdrv_aio_readv(dbs->bs, dbs->sector_num, &dbs->iov,
|
||||
dbs->iov.size / 512, dma_bdrv_cb, dbs);
|
||||
dbs->acb = bdrv_aio_readv(dbs->bs, dbs->sector_num, &dbs->iov,
|
||||
dbs->iov.size / 512, dma_bdrv_cb, dbs);
|
||||
}
|
||||
if (!dbs->acb) {
|
||||
dma_bdrv_unmap(dbs);
|
||||
qemu_iovec_destroy(&dbs->iov);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,10 +137,10 @@ static BlockDriverAIOCB *dma_bdrv_io(
|
||||
BlockDriverCompletionFunc *cb, void *opaque,
|
||||
int is_write)
|
||||
{
|
||||
DMABlockState *dbs = qemu_malloc(sizeof(*dbs));
|
||||
DMAAIOCB *dbs = qemu_aio_get_pool(&dma_aio_pool, bs, cb, opaque);
|
||||
|
||||
dbs->acb = NULL;
|
||||
dbs->bs = bs;
|
||||
dbs->acb = qemu_aio_get_pool(&dma_aio_pool, bs, cb, opaque);
|
||||
dbs->sg = sg;
|
||||
dbs->sector_num = sector_num;
|
||||
dbs->sg_cur_index = 0;
|
||||
@@ -137,7 +149,11 @@ static BlockDriverAIOCB *dma_bdrv_io(
|
||||
dbs->bh = NULL;
|
||||
qemu_iovec_init(&dbs->iov, sg->nsg);
|
||||
dma_bdrv_cb(dbs, 0);
|
||||
return dbs->acb;
|
||||
if (!dbs->acb) {
|
||||
qemu_aio_release(dbs);
|
||||
return NULL;
|
||||
}
|
||||
return &dbs->common;
|
||||
}
|
||||
|
||||
|
||||
@@ -157,12 +173,14 @@ BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
|
||||
|
||||
static void dma_aio_cancel(BlockDriverAIOCB *acb)
|
||||
{
|
||||
DMABlockState *dbs = (DMABlockState *)acb->opaque;
|
||||
DMAAIOCB *dbs = container_of(acb, DMAAIOCB, common);
|
||||
|
||||
bdrv_aio_cancel(dbs->acb);
|
||||
if (dbs->acb) {
|
||||
bdrv_aio_cancel(dbs->acb);
|
||||
}
|
||||
}
|
||||
|
||||
void dma_helper_init(void)
|
||||
{
|
||||
aio_pool_init(&dma_aio_pool, sizeof(BlockDriverAIOCB), dma_aio_cancel);
|
||||
aio_pool_init(&dma_aio_pool, sizeof(DMAAIOCB), dma_aio_cancel);
|
||||
}
|
||||
+1
-1
@@ -35,7 +35,7 @@
|
||||
typedef struct TranslationBlock TranslationBlock;
|
||||
|
||||
/* XXX: make safe guess about sizes */
|
||||
#define MAX_OP_PER_INSTR 64
|
||||
#define MAX_OP_PER_INSTR 96
|
||||
/* A Call op needs up to 6 + 2N parameters (N = number of arguments). */
|
||||
#define MAX_OPC_PARAM 10
|
||||
#define OPC_BUF_SIZE 512
|
||||
|
||||
@@ -3110,6 +3110,7 @@ void cpu_unregister_map_client(void *_client)
|
||||
MapClient *client = (MapClient *)_client;
|
||||
|
||||
LIST_REMOVE(client, link);
|
||||
qemu_free(client);
|
||||
}
|
||||
|
||||
static void cpu_notify_map_clients(void)
|
||||
@@ -3119,7 +3120,7 @@ static void cpu_notify_map_clients(void)
|
||||
while (!LIST_EMPTY(&map_client_list)) {
|
||||
client = LIST_FIRST(&map_client_list);
|
||||
client->callback(client->opaque);
|
||||
LIST_REMOVE(client, link);
|
||||
cpu_unregister_map_client(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include "hw.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "primecell.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
@@ -70,8 +71,7 @@ static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset)
|
||||
case 0x58: /* BOOTCS */
|
||||
return 0;
|
||||
case 0x5c: /* 24MHz */
|
||||
/* ??? not implemented. */
|
||||
return 0;
|
||||
return muldiv64(qemu_get_clock(vm_clock), 24000000, ticks_per_sec);
|
||||
case 0x60: /* MISC */
|
||||
return 0;
|
||||
case 0x84: /* PROCID0 */
|
||||
|
||||
+2
-2
@@ -349,10 +349,10 @@ void axisdev88_init (ram_addr_t ram_size, int vga_ram_size,
|
||||
fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
|
||||
exit(1);
|
||||
}
|
||||
pstrcpy_targphys(high, 256, kernel_cmdline);
|
||||
/* Let the kernel know we are modifying the cmdline. */
|
||||
env->regs[10] = 0x87109563;
|
||||
env->regs[11] = high;
|
||||
env->regs[11] = 0x40000000;
|
||||
pstrcpy_targphys(env->regs[11], 256, kernel_cmdline);
|
||||
}
|
||||
}
|
||||
env->pc = bootstrap_pc;
|
||||
|
||||
+1
-6
@@ -55,12 +55,7 @@ void destroy_nic(dev_match_fn *match_fn, void *arg)
|
||||
nic = &nd_table[i];
|
||||
if (nic->used) {
|
||||
if (nic->private && match_fn(nic->private, arg)) {
|
||||
if (nic->vlan) {
|
||||
VLANClientState *vc;
|
||||
vc = qemu_find_vlan_client(nic->vlan, nic->private);
|
||||
if (vc)
|
||||
qemu_del_vlan_client(vc);
|
||||
}
|
||||
qemu_del_vlan_client(nic->vc);
|
||||
net_client_uninit(nic);
|
||||
}
|
||||
}
|
||||
|
||||
+23
-6
@@ -155,6 +155,7 @@ set_interrupt_cause(E1000State *s, int index, uint32_t val)
|
||||
if (val)
|
||||
val |= E1000_ICR_INT_ASSERTED;
|
||||
s->mac_reg[ICR] = val;
|
||||
s->mac_reg[ICS] = val;
|
||||
qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0);
|
||||
}
|
||||
|
||||
@@ -189,6 +190,13 @@ rxbufsize(uint32_t v)
|
||||
return 2048;
|
||||
}
|
||||
|
||||
static void
|
||||
set_ctrl(E1000State *s, int index, uint32_t val)
|
||||
{
|
||||
/* RST is self clearing */
|
||||
s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
|
||||
}
|
||||
|
||||
static void
|
||||
set_rx_control(E1000State *s, int index, uint32_t val)
|
||||
{
|
||||
@@ -255,6 +263,11 @@ set_eecd(E1000State *s, int index, uint32_t val)
|
||||
}
|
||||
if (!(val & E1000_EECD_CS)) { // rising, no CS (EEPROM reset)
|
||||
memset(&s->eecd_state, 0, sizeof s->eecd_state);
|
||||
/*
|
||||
* restore old_eecd's E1000_EECD_SK (known to be on)
|
||||
* to avoid false detection of a clock edge
|
||||
*/
|
||||
s->eecd_state.old_eecd = E1000_EECD_SK;
|
||||
return;
|
||||
}
|
||||
s->eecd_state.val_in <<= 1;
|
||||
@@ -275,10 +288,14 @@ flash_eerd_read(E1000State *s, int x)
|
||||
{
|
||||
unsigned int index, r = s->mac_reg[EERD] & ~E1000_EEPROM_RW_REG_START;
|
||||
|
||||
if ((s->mac_reg[EERD] & E1000_EEPROM_RW_REG_START) == 0)
|
||||
return (s->mac_reg[EERD]);
|
||||
|
||||
if ((index = r >> E1000_EEPROM_RW_ADDR_SHIFT) > EEPROM_CHECKSUM_REG)
|
||||
return 0;
|
||||
return (s->eeprom_data[index] << E1000_EEPROM_RW_REG_DATA) |
|
||||
E1000_EEPROM_RW_REG_DONE | r;
|
||||
return (E1000_EEPROM_RW_REG_DONE | r);
|
||||
|
||||
return ((s->eeprom_data[index] << E1000_EEPROM_RW_REG_DATA) |
|
||||
E1000_EEPROM_RW_REG_DONE | r);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -767,7 +784,7 @@ static uint32_t (*macreg_readops[])(E1000State *, int) = {
|
||||
getreg(WUFC), getreg(TDT), getreg(CTRL), getreg(LEDCTL),
|
||||
getreg(MANC), getreg(MDIC), getreg(SWSM), getreg(STATUS),
|
||||
getreg(TORL), getreg(TOTL), getreg(IMS), getreg(TCTL),
|
||||
getreg(RDH), getreg(RDT), getreg(VET),
|
||||
getreg(RDH), getreg(RDT), getreg(VET), getreg(ICS),
|
||||
|
||||
[TOTH] = mac_read_clr8, [TORH] = mac_read_clr8, [GPRC] = mac_read_clr4,
|
||||
[GPTC] = mac_read_clr4, [TPR] = mac_read_clr4, [TPT] = mac_read_clr4,
|
||||
@@ -783,12 +800,12 @@ enum { NREADOPS = ARRAY_SIZE(macreg_readops) };
|
||||
static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
|
||||
putreg(PBA), putreg(EERD), putreg(SWSM), putreg(WUFC),
|
||||
putreg(TDBAL), putreg(TDBAH), putreg(TXDCTL), putreg(RDBAH),
|
||||
putreg(RDBAL), putreg(LEDCTL), putreg(CTRL), putreg(VET),
|
||||
putreg(RDBAL), putreg(LEDCTL), putreg(VET),
|
||||
[TDLEN] = set_dlen, [RDLEN] = set_dlen, [TCTL] = set_tctl,
|
||||
[TDT] = set_tctl, [MDIC] = set_mdic, [ICS] = set_ics,
|
||||
[TDH] = set_16bit, [RDH] = set_16bit, [RDT] = set_rdt,
|
||||
[IMC] = set_imc, [IMS] = set_ims, [ICR] = set_icr,
|
||||
[EECD] = set_eecd, [RCTL] = set_rx_control,
|
||||
[EECD] = set_eecd, [RCTL] = set_rx_control, [CTRL] = set_ctrl,
|
||||
[RA ... RA+31] = &mac_writereg,
|
||||
[MTA ... MTA+127] = &mac_writereg,
|
||||
[VFTA ... VFTA+127] = &mac_writereg,
|
||||
|
||||
@@ -301,6 +301,7 @@ void eeprom93xx_free(eeprom_t *eeprom)
|
||||
{
|
||||
/* Destroy EEPROM. */
|
||||
logout("eeprom = 0x%p\n", eeprom);
|
||||
unregister_savevm("eeprom", eeprom);
|
||||
qemu_free(eeprom);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -140,10 +140,10 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size,
|
||||
fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
|
||||
exit(1);
|
||||
}
|
||||
pstrcpy_targphys(high, 256, kernel_cmdline);
|
||||
/* Let the kernel know we are modifying the cmdline. */
|
||||
env->regs[10] = 0x87109563;
|
||||
env->regs[11] = high;
|
||||
env->regs[11] = 0x40000000;
|
||||
pstrcpy_targphys(env->regs[11], 256, kernel_cmdline);
|
||||
}
|
||||
}
|
||||
env->pc = bootstrap_pc;
|
||||
|
||||
+5
-5
@@ -401,8 +401,8 @@ static void eth_update_ma(struct fs_eth *eth, int ma)
|
||||
eth->macaddr[ma][i++] = eth->regs[reg] >> 8;
|
||||
eth->macaddr[ma][i++] = eth->regs[reg] >> 16;
|
||||
eth->macaddr[ma][i++] = eth->regs[reg] >> 24;
|
||||
eth->macaddr[ma][i++] = eth->regs[reg + 4];
|
||||
eth->macaddr[ma][i++] = eth->regs[reg + 4] >> 8;
|
||||
eth->macaddr[ma][i++] = eth->regs[reg + 1];
|
||||
eth->macaddr[ma][i++] = eth->regs[reg + 1] >> 8;
|
||||
|
||||
D(printf("set mac%d=%x.%x.%x.%x.%x.%x\n", ma,
|
||||
eth->macaddr[ma][0], eth->macaddr[ma][1],
|
||||
@@ -594,9 +594,9 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
|
||||
eth->ethregs = cpu_register_io_memory(0, eth_read, eth_write, eth);
|
||||
cpu_register_physical_memory (base, 0x5c, eth->ethregs);
|
||||
|
||||
eth->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
eth_receive, eth_can_receive,
|
||||
eth_cleanup, eth);
|
||||
eth->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
eth_receive, eth_can_receive,
|
||||
eth_cleanup, eth);
|
||||
eth->vc->opaque = eth;
|
||||
eth->vc->link_status_changed = eth_set_link;
|
||||
|
||||
|
||||
@@ -554,6 +554,7 @@ static void hpet_reset(void *opaque) {
|
||||
/* 64-bit main counter; 3 timers supported; LegacyReplacementRoute. */
|
||||
s->capability = 0x8086a201ULL;
|
||||
s->capability |= ((HPET_CLK_PERIOD) << 32);
|
||||
s->config = 0ULL;
|
||||
if (count > 0)
|
||||
/* we don't enable pit when hpet_reset is first called (by hpet_init)
|
||||
* because hpet is taking over for pit here. On subsequent invocations,
|
||||
|
||||
@@ -37,6 +37,7 @@ QEMUFile *qemu_fopen(const char *filename, const char *mode);
|
||||
QEMUFile *qemu_fopen_socket(int fd);
|
||||
QEMUFile *qemu_popen(FILE *popen_file, const char *mode);
|
||||
QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
|
||||
int qemu_popen_fd(QEMUFile *f);
|
||||
void qemu_fflush(QEMUFile *f);
|
||||
int qemu_fclose(QEMUFile *f);
|
||||
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
|
||||
|
||||
@@ -359,6 +359,7 @@
|
||||
#define ASC_INCOMPATIBLE_FORMAT 0x30
|
||||
#define ASC_MEDIUM_NOT_PRESENT 0x3a
|
||||
#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39
|
||||
#define ASC_MEDIA_REMOVAL_PREVENTED 0x53
|
||||
|
||||
#define CFA_NO_ERROR 0x00
|
||||
#define CFA_MISC_ERROR 0x09
|
||||
@@ -417,6 +418,7 @@ typedef struct IDEState {
|
||||
/* ATAPI specific */
|
||||
uint8_t sense_key;
|
||||
uint8_t asc;
|
||||
uint8_t cdrom_changed;
|
||||
int packet_transfer_size;
|
||||
int elementary_transfer_size;
|
||||
int io_buffer_index;
|
||||
@@ -1639,9 +1641,10 @@ static void ide_atapi_cmd(IDEState *s)
|
||||
}
|
||||
switch(s->io_buffer[0]) {
|
||||
case GPCMD_TEST_UNIT_READY:
|
||||
if (bdrv_is_inserted(s->bs)) {
|
||||
if (bdrv_is_inserted(s->bs) && !s->cdrom_changed) {
|
||||
ide_atapi_cmd_ok(s);
|
||||
} else {
|
||||
s->cdrom_changed = 0;
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY,
|
||||
ASC_MEDIUM_NOT_PRESENT);
|
||||
}
|
||||
@@ -1818,18 +1821,27 @@ static void ide_atapi_cmd(IDEState *s)
|
||||
break;
|
||||
case GPCMD_START_STOP_UNIT:
|
||||
{
|
||||
int start, eject;
|
||||
int start, eject, err = 0;
|
||||
start = packet[4] & 1;
|
||||
eject = (packet[4] >> 1) & 1;
|
||||
|
||||
if (eject && !start) {
|
||||
/* eject the disk */
|
||||
bdrv_eject(s->bs, 1);
|
||||
} else if (eject && start) {
|
||||
/* close the tray */
|
||||
bdrv_eject(s->bs, 0);
|
||||
if (eject) {
|
||||
err = bdrv_eject(s->bs, !start);
|
||||
}
|
||||
|
||||
switch (err) {
|
||||
case 0:
|
||||
ide_atapi_cmd_ok(s);
|
||||
break;
|
||||
case -EBUSY:
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY,
|
||||
ASC_MEDIA_REMOVAL_PREVENTED);
|
||||
break;
|
||||
default:
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY,
|
||||
ASC_MEDIUM_NOT_PRESENT);
|
||||
break;
|
||||
}
|
||||
ide_atapi_cmd_ok(s);
|
||||
}
|
||||
break;
|
||||
case GPCMD_MECHANISM_STATUS:
|
||||
@@ -2092,7 +2104,7 @@ static void cdrom_change_cb(void *opaque)
|
||||
|
||||
s->sense_key = SENSE_UNIT_ATTENTION;
|
||||
s->asc = ASC_MEDIUM_MAY_HAVE_CHANGED;
|
||||
|
||||
s->cdrom_changed = 1;
|
||||
ide_set_irq(s);
|
||||
}
|
||||
|
||||
@@ -2860,7 +2872,7 @@ static void ide_save(QEMUFile* f, IDEState *s)
|
||||
}
|
||||
|
||||
/* load per IDE drive data */
|
||||
static void ide_load(QEMUFile* f, IDEState *s)
|
||||
static void ide_load(QEMUFile* f, IDEState *s, int version_id)
|
||||
{
|
||||
s->mult_sectors=qemu_get_be32(f);
|
||||
s->identify_set=qemu_get_be32(f);
|
||||
@@ -2884,6 +2896,13 @@ static void ide_load(QEMUFile* f, IDEState *s)
|
||||
|
||||
qemu_get_8s(f, &s->sense_key);
|
||||
qemu_get_8s(f, &s->asc);
|
||||
if (version_id == 3) {
|
||||
qemu_get_8s(f, &s->cdrom_changed);
|
||||
} else {
|
||||
if (s->sense_key == SENSE_UNIT_ATTENTION &&
|
||||
s->asc == ASC_MEDIUM_MAY_HAVE_CHANGED)
|
||||
s->cdrom_changed = 1;
|
||||
}
|
||||
/* XXX: if a transfer is pending, we do not save it yet */
|
||||
}
|
||||
|
||||
@@ -3205,7 +3224,7 @@ static int pci_ide_load(QEMUFile* f, void *opaque, int version_id)
|
||||
PCIIDEState *d = opaque;
|
||||
int ret, i;
|
||||
|
||||
if (version_id != 2)
|
||||
if (version_id != 2 && version_id != 3)
|
||||
return -EINVAL;
|
||||
ret = pci_device_load(&d->dev, f);
|
||||
if (ret < 0)
|
||||
@@ -3235,7 +3254,7 @@ static int pci_ide_load(QEMUFile* f, void *opaque, int version_id)
|
||||
|
||||
/* per IDE drive data */
|
||||
for(i = 0; i < 4; i++) {
|
||||
ide_load(f, &d->ide_if[i]);
|
||||
ide_load(f, &d->ide_if[i], version_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -3325,7 +3344,7 @@ void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table,
|
||||
ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], irq[0]);
|
||||
ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], irq[1]);
|
||||
|
||||
register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d);
|
||||
register_savevm("ide", 0, 3, pci_ide_save, pci_ide_load, d);
|
||||
qemu_register_reset(cmd646_reset, d);
|
||||
cmd646_reset(d);
|
||||
}
|
||||
@@ -3384,7 +3403,7 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
|
||||
if (hd_table[i])
|
||||
hd_table[i]->private = &d->dev;
|
||||
|
||||
register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d);
|
||||
register_savevm("ide", 0, 3, pci_ide_save, pci_ide_load, d);
|
||||
}
|
||||
|
||||
/* hd_table must contain 4 block drivers */
|
||||
@@ -3420,7 +3439,7 @@ void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
|
||||
ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
|
||||
ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
|
||||
|
||||
register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d);
|
||||
register_savevm("ide", 0, 3, pci_ide_save, pci_ide_load, d);
|
||||
}
|
||||
|
||||
#if defined(TARGET_PPC)
|
||||
@@ -3708,7 +3727,7 @@ static int pmac_ide_load(QEMUFile *f, void *opaque, int version_id)
|
||||
uint8_t drive1_selected;
|
||||
unsigned int i;
|
||||
|
||||
if (version_id != 1)
|
||||
if (version_id != 1 && version_id != 3)
|
||||
return -EINVAL;
|
||||
|
||||
/* per IDE interface data */
|
||||
@@ -3718,7 +3737,7 @@ static int pmac_ide_load(QEMUFile *f, void *opaque, int version_id)
|
||||
|
||||
/* per IDE drive data */
|
||||
for(i = 0; i < 2; i++) {
|
||||
ide_load(f, &s[i]);
|
||||
ide_load(f, &s[i], version_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -3749,7 +3768,7 @@ int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq,
|
||||
|
||||
pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read,
|
||||
pmac_ide_write, d);
|
||||
register_savevm("ide", 0, 1, pmac_ide_save, pmac_ide_load, d);
|
||||
register_savevm("ide", 0, 3, pmac_ide_save, pmac_ide_load, d);
|
||||
qemu_register_reset(pmac_ide_reset, d);
|
||||
pmac_ide_reset(d);
|
||||
|
||||
@@ -4142,6 +4161,9 @@ static int md_load(QEMUFile *f, void *opaque, int version_id)
|
||||
int i;
|
||||
uint8_t drive1_selected;
|
||||
|
||||
if (version_id != 0 && version_id != 3)
|
||||
return -EINVAL;
|
||||
|
||||
qemu_get_8s(f, &s->opt);
|
||||
qemu_get_8s(f, &s->stat);
|
||||
qemu_get_8s(f, &s->pins);
|
||||
@@ -4155,7 +4177,7 @@ static int md_load(QEMUFile *f, void *opaque, int version_id)
|
||||
s->ide->cur_drive = &s->ide[(drive1_selected != 0)];
|
||||
|
||||
for (i = 0; i < 2; i ++)
|
||||
ide_load(f, &s->ide[i]);
|
||||
ide_load(f, &s->ide[i], version_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4386,7 +4408,7 @@ struct pcmcia_card_s *dscm1xxxx_init(BlockDriverState *bdrv)
|
||||
md->ide->mdata_size = METADATA_SIZE;
|
||||
md->ide->mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
|
||||
|
||||
register_savevm("microdrive", -1, 0, md_save, md_load, md);
|
||||
register_savevm("microdrive", -1, 3, md_save, md_load, md);
|
||||
|
||||
return &md->card;
|
||||
}
|
||||
+189
@@ -10,6 +10,8 @@
|
||||
/* ??? Need to check if the {read,write}[wl] routines work properly on
|
||||
big-endian targets. */
|
||||
|
||||
#include <assert.h> \
|
||||
|
||||
#include "hw.h"
|
||||
#include "pci.h"
|
||||
#include "scsi-disk.h"
|
||||
@@ -262,6 +264,7 @@ typedef struct {
|
||||
uint32_t sbc;
|
||||
uint32_t csbc;
|
||||
uint32_t scratch[18]; /* SCRATCHA-SCRATCHR */
|
||||
uint8_t sbr;
|
||||
|
||||
/* Script ram is stored as 32-bit words in host byteorder. */
|
||||
uint32_t script_ram[2048];
|
||||
@@ -330,6 +333,7 @@ static void lsi_soft_reset(LSIState *s)
|
||||
s->ia = 0;
|
||||
s->sbc = 0;
|
||||
s->csbc = 0;
|
||||
s->sbr = 0;
|
||||
}
|
||||
|
||||
static int lsi_dma_40bit(LSIState *s)
|
||||
@@ -1400,6 +1404,7 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
|
||||
CASE_GET_REG24(dbc, 0x24)
|
||||
case 0x27: /* DCMD */
|
||||
return s->dcmd;
|
||||
CASE_GET_REG32(dnad, 0x28)
|
||||
CASE_GET_REG32(dsp, 0x2c)
|
||||
CASE_GET_REG32(dsps, 0x30)
|
||||
CASE_GET_REG32(scratch[0], 0x34)
|
||||
@@ -1407,6 +1412,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
|
||||
return s->dmode;
|
||||
case 0x39: /* DIEN */
|
||||
return s->dien;
|
||||
case 0x3a: /* SBR */
|
||||
return s->sbr;
|
||||
case 0x3b: /* DCNTL */
|
||||
return s->dcntl;
|
||||
case 0x40: /* SIEN0 */
|
||||
@@ -1486,6 +1493,11 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
|
||||
|
||||
static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
|
||||
{
|
||||
#define CASE_SET_REG24(name, addr) \
|
||||
case addr : s->name &= 0xffffff00; s->name |= val; break; \
|
||||
case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8; break; \
|
||||
case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break;
|
||||
|
||||
#define CASE_SET_REG32(name, addr) \
|
||||
case addr : s->name &= 0xffffff00; s->name |= val; break; \
|
||||
case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8; break; \
|
||||
@@ -1590,6 +1602,8 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
|
||||
}
|
||||
s->ctest5 = val;
|
||||
break;
|
||||
CASE_SET_REG24(dbc, 0x24)
|
||||
CASE_SET_REG32(dnad, 0x28)
|
||||
case 0x2c: /* DSP[0:7] */
|
||||
s->dsp &= 0xffffff00;
|
||||
s->dsp |= val;
|
||||
@@ -1621,6 +1635,9 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
|
||||
s->dien = val;
|
||||
lsi_update_irq(s);
|
||||
break;
|
||||
case 0x3a: /* SBR */
|
||||
s->sbr = val;
|
||||
break;
|
||||
case 0x3b: /* DCNTL */
|
||||
s->dcntl = val & ~(LSI_DCNTL_PFF | LSI_DCNTL_STD);
|
||||
if ((val & LSI_DCNTL_STD) && (s->istat1 & LSI_ISTAT1_SRUN) == 0)
|
||||
@@ -1700,6 +1717,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
|
||||
BADF("Unhandled writeb 0x%x = 0x%x\n", offset, val);
|
||||
}
|
||||
}
|
||||
#undef CASE_SET_REG24
|
||||
#undef CASE_SET_REG32
|
||||
}
|
||||
|
||||
@@ -1964,6 +1982,174 @@ void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id)
|
||||
bd->private = &s->pci_dev;
|
||||
}
|
||||
|
||||
static void lsi_scsi_save(QEMUFile *f, void *opaque)
|
||||
{
|
||||
LSIState *s = opaque;
|
||||
|
||||
assert(s->dma_buf == NULL);
|
||||
assert(s->current_dma_len == 0);
|
||||
assert(s->active_commands == 0);
|
||||
|
||||
pci_device_save(&s->pci_dev, f);
|
||||
|
||||
qemu_put_sbe32s(f, &s->carry);
|
||||
qemu_put_sbe32s(f, &s->sense);
|
||||
qemu_put_sbe32s(f, &s->msg_action);
|
||||
qemu_put_sbe32s(f, &s->msg_len);
|
||||
qemu_put_buffer(f, s->msg, sizeof (s->msg));
|
||||
qemu_put_sbe32s(f, &s->waiting);
|
||||
|
||||
qemu_put_be32s(f, &s->dsa);
|
||||
qemu_put_be32s(f, &s->temp);
|
||||
qemu_put_be32s(f, &s->dnad);
|
||||
qemu_put_be32s(f, &s->dbc);
|
||||
qemu_put_8s(f, &s->istat0);
|
||||
qemu_put_8s(f, &s->istat1);
|
||||
qemu_put_8s(f, &s->dcmd);
|
||||
qemu_put_8s(f, &s->dstat);
|
||||
qemu_put_8s(f, &s->dien);
|
||||
qemu_put_8s(f, &s->sist0);
|
||||
qemu_put_8s(f, &s->sist1);
|
||||
qemu_put_8s(f, &s->sien0);
|
||||
qemu_put_8s(f, &s->sien1);
|
||||
qemu_put_8s(f, &s->mbox0);
|
||||
qemu_put_8s(f, &s->mbox1);
|
||||
qemu_put_8s(f, &s->dfifo);
|
||||
qemu_put_8s(f, &s->ctest2);
|
||||
qemu_put_8s(f, &s->ctest3);
|
||||
qemu_put_8s(f, &s->ctest4);
|
||||
qemu_put_8s(f, &s->ctest5);
|
||||
qemu_put_8s(f, &s->ccntl0);
|
||||
qemu_put_8s(f, &s->ccntl1);
|
||||
qemu_put_be32s(f, &s->dsp);
|
||||
qemu_put_be32s(f, &s->dsps);
|
||||
qemu_put_8s(f, &s->dmode);
|
||||
qemu_put_8s(f, &s->dcntl);
|
||||
qemu_put_8s(f, &s->scntl0);
|
||||
qemu_put_8s(f, &s->scntl1);
|
||||
qemu_put_8s(f, &s->scntl2);
|
||||
qemu_put_8s(f, &s->scntl3);
|
||||
qemu_put_8s(f, &s->sstat0);
|
||||
qemu_put_8s(f, &s->sstat1);
|
||||
qemu_put_8s(f, &s->scid);
|
||||
qemu_put_8s(f, &s->sxfer);
|
||||
qemu_put_8s(f, &s->socl);
|
||||
qemu_put_8s(f, &s->sdid);
|
||||
qemu_put_8s(f, &s->ssid);
|
||||
qemu_put_8s(f, &s->sfbr);
|
||||
qemu_put_8s(f, &s->stest1);
|
||||
qemu_put_8s(f, &s->stest2);
|
||||
qemu_put_8s(f, &s->stest3);
|
||||
qemu_put_8s(f, &s->sidl);
|
||||
qemu_put_8s(f, &s->stime0);
|
||||
qemu_put_8s(f, &s->respid0);
|
||||
qemu_put_8s(f, &s->respid1);
|
||||
qemu_put_be32s(f, &s->mmrs);
|
||||
qemu_put_be32s(f, &s->mmws);
|
||||
qemu_put_be32s(f, &s->sfs);
|
||||
qemu_put_be32s(f, &s->drs);
|
||||
qemu_put_be32s(f, &s->sbms);
|
||||
qemu_put_be32s(f, &s->dbms);
|
||||
qemu_put_be32s(f, &s->dnad64);
|
||||
qemu_put_be32s(f, &s->pmjad1);
|
||||
qemu_put_be32s(f, &s->pmjad2);
|
||||
qemu_put_be32s(f, &s->rbc);
|
||||
qemu_put_be32s(f, &s->ua);
|
||||
qemu_put_be32s(f, &s->ia);
|
||||
qemu_put_be32s(f, &s->sbc);
|
||||
qemu_put_be32s(f, &s->csbc);
|
||||
qemu_put_buffer(f, (uint8_t *)s->scratch, sizeof (s->scratch));
|
||||
qemu_put_8s(f, &s->sbr);
|
||||
|
||||
qemu_put_buffer(f, (uint8_t *)s->script_ram, sizeof (s->script_ram));
|
||||
}
|
||||
|
||||
static int lsi_scsi_load(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
LSIState *s = opaque;
|
||||
int ret;
|
||||
|
||||
if (version_id > 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((ret = pci_device_load(&s->pci_dev, f)) < 0)
|
||||
return ret;
|
||||
|
||||
qemu_get_sbe32s(f, &s->carry);
|
||||
qemu_get_sbe32s(f, &s->sense);
|
||||
qemu_get_sbe32s(f, &s->msg_action);
|
||||
qemu_get_sbe32s(f, &s->msg_len);
|
||||
qemu_get_buffer(f, s->msg, sizeof (s->msg));
|
||||
qemu_get_sbe32s(f, &s->waiting);
|
||||
|
||||
qemu_get_be32s(f, &s->dsa);
|
||||
qemu_get_be32s(f, &s->temp);
|
||||
qemu_get_be32s(f, &s->dnad);
|
||||
qemu_get_be32s(f, &s->dbc);
|
||||
qemu_get_8s(f, &s->istat0);
|
||||
qemu_get_8s(f, &s->istat1);
|
||||
qemu_get_8s(f, &s->dcmd);
|
||||
qemu_get_8s(f, &s->dstat);
|
||||
qemu_get_8s(f, &s->dien);
|
||||
qemu_get_8s(f, &s->sist0);
|
||||
qemu_get_8s(f, &s->sist1);
|
||||
qemu_get_8s(f, &s->sien0);
|
||||
qemu_get_8s(f, &s->sien1);
|
||||
qemu_get_8s(f, &s->mbox0);
|
||||
qemu_get_8s(f, &s->mbox1);
|
||||
qemu_get_8s(f, &s->dfifo);
|
||||
qemu_get_8s(f, &s->ctest2);
|
||||
qemu_get_8s(f, &s->ctest3);
|
||||
qemu_get_8s(f, &s->ctest4);
|
||||
qemu_get_8s(f, &s->ctest5);
|
||||
qemu_get_8s(f, &s->ccntl0);
|
||||
qemu_get_8s(f, &s->ccntl1);
|
||||
qemu_get_be32s(f, &s->dsp);
|
||||
qemu_get_be32s(f, &s->dsps);
|
||||
qemu_get_8s(f, &s->dmode);
|
||||
qemu_get_8s(f, &s->dcntl);
|
||||
qemu_get_8s(f, &s->scntl0);
|
||||
qemu_get_8s(f, &s->scntl1);
|
||||
qemu_get_8s(f, &s->scntl2);
|
||||
qemu_get_8s(f, &s->scntl3);
|
||||
qemu_get_8s(f, &s->sstat0);
|
||||
qemu_get_8s(f, &s->sstat1);
|
||||
qemu_get_8s(f, &s->scid);
|
||||
qemu_get_8s(f, &s->sxfer);
|
||||
qemu_get_8s(f, &s->socl);
|
||||
qemu_get_8s(f, &s->sdid);
|
||||
qemu_get_8s(f, &s->ssid);
|
||||
qemu_get_8s(f, &s->sfbr);
|
||||
qemu_get_8s(f, &s->stest1);
|
||||
qemu_get_8s(f, &s->stest2);
|
||||
qemu_get_8s(f, &s->stest3);
|
||||
qemu_get_8s(f, &s->sidl);
|
||||
qemu_get_8s(f, &s->stime0);
|
||||
qemu_get_8s(f, &s->respid0);
|
||||
qemu_get_8s(f, &s->respid1);
|
||||
qemu_get_be32s(f, &s->mmrs);
|
||||
qemu_get_be32s(f, &s->mmws);
|
||||
qemu_get_be32s(f, &s->sfs);
|
||||
qemu_get_be32s(f, &s->drs);
|
||||
qemu_get_be32s(f, &s->sbms);
|
||||
qemu_get_be32s(f, &s->dbms);
|
||||
qemu_get_be32s(f, &s->dnad64);
|
||||
qemu_get_be32s(f, &s->pmjad1);
|
||||
qemu_get_be32s(f, &s->pmjad2);
|
||||
qemu_get_be32s(f, &s->rbc);
|
||||
qemu_get_be32s(f, &s->ua);
|
||||
qemu_get_be32s(f, &s->ia);
|
||||
qemu_get_be32s(f, &s->sbc);
|
||||
qemu_get_be32s(f, &s->csbc);
|
||||
qemu_get_buffer(f, (uint8_t *)s->scratch, sizeof (s->scratch));
|
||||
qemu_get_8s(f, &s->sbr);
|
||||
|
||||
qemu_get_buffer(f, (uint8_t *)s->script_ram, sizeof (s->script_ram));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lsi_scsi_uninit(PCIDevice *d)
|
||||
{
|
||||
LSIState *s = (LSIState *) d;
|
||||
@@ -2022,5 +2208,8 @@ void *lsi_scsi_init(PCIBus *bus, int devfn)
|
||||
|
||||
lsi_soft_reset(s);
|
||||
|
||||
register_savevm("lsiscsi", -1, 0, lsi_scsi_save, lsi_scsi_load, s);
|
||||
|
||||
return s;
|
||||
|
||||
}
|
||||
+3
-3
@@ -463,9 +463,9 @@ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq)
|
||||
mcf_fec_writefn, s);
|
||||
cpu_register_physical_memory(base, 0x400, s->mmio_index);
|
||||
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
mcf_fec_receive, mcf_fec_can_receive,
|
||||
mcf_fec_cleanup, s);
|
||||
s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
mcf_fec_receive, mcf_fec_can_receive,
|
||||
mcf_fec_cleanup, s);
|
||||
memcpy(s->macaddr, nd->macaddr, 6);
|
||||
qemu_format_nic_info_str(s->vc, s->macaddr);
|
||||
}
|
||||
+4
-3
@@ -261,9 +261,10 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
|
||||
s->io_base = base;
|
||||
s->irq = irq;
|
||||
if (nd && nd->vlan) {
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
mipsnet_receive, mipsnet_can_receive,
|
||||
mipsnet_cleanup, s);
|
||||
s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
mipsnet_receive,
|
||||
mipsnet_can_receive,
|
||||
mipsnet_cleanup, s);
|
||||
} else {
|
||||
s->vc = NULL;
|
||||
}
|
||||
|
||||
+3
-3
@@ -756,9 +756,9 @@ void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd)
|
||||
|
||||
ne2000_reset(s);
|
||||
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
ne2000_receive, ne2000_can_receive,
|
||||
isa_ne2000_cleanup, s);
|
||||
s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
ne2000_receive, ne2000_can_receive,
|
||||
isa_ne2000_cleanup, s);
|
||||
|
||||
qemu_format_nic_info_str(s->vc, s->macaddr);
|
||||
|
||||
|
||||
@@ -566,7 +566,8 @@ static long get_file_size(FILE *f)
|
||||
static void load_linux(target_phys_addr_t option_rom,
|
||||
const char *kernel_filename,
|
||||
const char *initrd_filename,
|
||||
const char *kernel_cmdline)
|
||||
const char *kernel_cmdline,
|
||||
target_phys_addr_t max_ram_size)
|
||||
{
|
||||
uint16_t protocol;
|
||||
uint32_t gpr[8];
|
||||
@@ -632,8 +633,8 @@ static void load_linux(target_phys_addr_t option_rom,
|
||||
else
|
||||
initrd_max = 0x37ffffff;
|
||||
|
||||
if (initrd_max >= ram_size-ACPI_DATA_SIZE)
|
||||
initrd_max = ram_size-ACPI_DATA_SIZE-1;
|
||||
if (initrd_max >= max_ram_size-ACPI_DATA_SIZE)
|
||||
initrd_max = max_ram_size-ACPI_DATA_SIZE-1;
|
||||
|
||||
/* kernel command line */
|
||||
pstrcpy_targphys(cmdline_addr, 4096, kernel_cmdline);
|
||||
@@ -675,9 +676,6 @@ static void load_linux(target_phys_addr_t option_rom,
|
||||
initrd_size = get_file_size(fi);
|
||||
initrd_addr = (initrd_max-initrd_size) & ~4095;
|
||||
|
||||
fprintf(stderr, "qemu: loading initrd (%#x bytes) at 0x" TARGET_FMT_plx
|
||||
"\n", initrd_size, initrd_addr);
|
||||
|
||||
if (!fread_targphys_ok(initrd_addr, initrd_size, fi)) {
|
||||
fprintf(stderr, "qemu: read error on initial ram disk '%s'\n",
|
||||
initrd_filename);
|
||||
@@ -927,10 +925,10 @@ vga_bios_error:
|
||||
offset = 0;
|
||||
if (linux_boot) {
|
||||
option_rom_offset = qemu_ram_alloc(TARGET_PAGE_SIZE);
|
||||
load_linux(option_rom_offset,
|
||||
kernel_filename, initrd_filename, kernel_cmdline);
|
||||
cpu_register_physical_memory(0xd0000, TARGET_PAGE_SIZE,
|
||||
option_rom_offset);
|
||||
load_linux(0xd0000,
|
||||
kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
|
||||
offset = TARGET_PAGE_SIZE;
|
||||
}
|
||||
|
||||
|
||||
@@ -488,9 +488,8 @@ void ps2_write_mouse(void *opaque, int val)
|
||||
}
|
||||
}
|
||||
|
||||
static void ps2_reset(void *opaque)
|
||||
static void ps2_common_reset(PS2State *s)
|
||||
{
|
||||
PS2State *s = (PS2State *)opaque;
|
||||
PS2Queue *q;
|
||||
s->write_cmd = -1;
|
||||
q = &s->queue;
|
||||
@@ -500,6 +499,33 @@ static void ps2_reset(void *opaque)
|
||||
s->update_irq(s->update_arg, 0);
|
||||
}
|
||||
|
||||
static void ps2_kbd_reset(void *opaque)
|
||||
{
|
||||
PS2KbdState *s = (PS2KbdState *) opaque;
|
||||
|
||||
ps2_common_reset(&s->common);
|
||||
s->scan_enabled = 0;
|
||||
s->translate = 0;
|
||||
s->scancode_set = 0;
|
||||
}
|
||||
|
||||
static void ps2_mouse_reset(void *opaque)
|
||||
{
|
||||
PS2MouseState *s = (PS2MouseState *) opaque;
|
||||
|
||||
ps2_common_reset(&s->common);
|
||||
s->mouse_status = 0;
|
||||
s->mouse_resolution = 0;
|
||||
s->mouse_sample_rate = 0;
|
||||
s->mouse_wrap = 0;
|
||||
s->mouse_type = 0;
|
||||
s->mouse_detect_state = 0;
|
||||
s->mouse_dx = 0;
|
||||
s->mouse_dy = 0;
|
||||
s->mouse_dz = 0;
|
||||
s->mouse_buttons = 0;
|
||||
}
|
||||
|
||||
static void ps2_common_save (QEMUFile *f, PS2State *s)
|
||||
{
|
||||
qemu_put_be32 (f, s->write_cmd);
|
||||
@@ -590,10 +616,10 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
|
||||
s->common.update_irq = update_irq;
|
||||
s->common.update_arg = update_arg;
|
||||
s->scancode_set = 2;
|
||||
ps2_reset(&s->common);
|
||||
ps2_kbd_reset(s);
|
||||
register_savevm("ps2kbd", 0, 3, ps2_kbd_save, ps2_kbd_load, s);
|
||||
qemu_add_kbd_event_handler(ps2_put_keycode, s);
|
||||
qemu_register_reset(ps2_reset, &s->common);
|
||||
qemu_register_reset(ps2_kbd_reset, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -603,9 +629,9 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
|
||||
|
||||
s->common.update_irq = update_irq;
|
||||
s->common.update_arg = update_arg;
|
||||
ps2_reset(&s->common);
|
||||
ps2_mouse_reset(s);
|
||||
register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
|
||||
qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
|
||||
qemu_register_reset(ps2_reset, &s->common);
|
||||
qemu_register_reset(ps2_mouse_reset, s);
|
||||
return s;
|
||||
}
|
||||
@@ -586,6 +586,8 @@ static int serial_can_receive(SerialState *s)
|
||||
static void serial_receive_break(SerialState *s)
|
||||
{
|
||||
s->rbr = 0;
|
||||
/* When the LSR_DR is set a null byte is pushed into the fifo */
|
||||
fifo_put(s, RECV_FIFO, '\0');
|
||||
s->lsr |= UART_LSR_BI | UART_LSR_DR;
|
||||
serial_update_irq(s);
|
||||
}
|
||||
|
||||
+4
-4
@@ -1457,10 +1457,10 @@ USBDevice *usb_net_init(NICInfo *nd)
|
||||
|
||||
pstrcpy(s->dev.devname, sizeof(s->dev.devname),
|
||||
"QEMU USB Network Interface");
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
usbnet_receive,
|
||||
usbnet_can_receive,
|
||||
usbnet_cleanup, s);
|
||||
s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
usbnet_receive,
|
||||
usbnet_can_receive,
|
||||
usbnet_cleanup, s);
|
||||
|
||||
qemu_format_nic_info_str(s->vc, s->mac);
|
||||
|
||||
|
||||
@@ -2606,8 +2606,9 @@ static void vga_screen_dump_blank(VGAState *s, const char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
unsigned int y, x, w, h;
|
||||
unsigned char blank_sample[3] = { 0, 0, 0 };
|
||||
|
||||
w = s->last_scr_width * sizeof(uint32_t);
|
||||
w = s->last_scr_width;
|
||||
h = s->last_scr_height;
|
||||
|
||||
f = fopen(filename, "wb");
|
||||
@@ -2616,7 +2617,7 @@ static void vga_screen_dump_blank(VGAState *s, const char *filename)
|
||||
fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
|
||||
for (y = 0; y < h; y++) {
|
||||
for (x = 0; x < w; x++) {
|
||||
fputc(0, f);
|
||||
fwrite(blank_sample, 3, 1, f);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
@@ -247,6 +247,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
|
||||
|
||||
bdrv_get_geometry(s->bs, &capacity);
|
||||
bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
|
||||
memset(&blkcfg, 0, sizeof(blkcfg));
|
||||
stq_raw(&blkcfg.capacity, capacity);
|
||||
stl_raw(&blkcfg.seg_max, 128 - 2);
|
||||
stw_raw(&blkcfg.cylinders, cylinders);
|
||||
|
||||
+1
-1
@@ -160,7 +160,7 @@ static CPUWriteMemoryFunc *scoop_writefn[] = {
|
||||
|
||||
void scoop_gpio_set(void *opaque, int line, int level)
|
||||
{
|
||||
struct scoop_info_s *s = (struct scoop_info_s *) s;
|
||||
struct scoop_info_s *s = (struct scoop_info_s *) opaque;
|
||||
|
||||
if (level)
|
||||
s->gpio_level |= (1 << line);
|
||||
|
||||
@@ -280,14 +280,28 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int kvm_check_extension(KVMState *s, unsigned int extension)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, extension);
|
||||
if (ret < 0) {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int kvm_init(int smp_cpus)
|
||||
{
|
||||
KVMState *s;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (smp_cpus > 1)
|
||||
if (smp_cpus > 1) {
|
||||
fprintf(stderr, "No SMP KVM support, use '-smp 1'\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s = qemu_mallocz(sizeof(KVMState));
|
||||
|
||||
@@ -325,10 +339,8 @@ int kvm_init(int smp_cpus)
|
||||
* just use a user allocated buffer so we can use phys_ram_base
|
||||
* unmodified. Make sure we have a sufficiently modern version of KVM.
|
||||
*/
|
||||
ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_USER_MEMORY);
|
||||
if (ret <= 0) {
|
||||
if (ret == 0)
|
||||
ret = -EINVAL;
|
||||
if (!kvm_check_extension(s, KVM_CAP_USER_MEMORY)) {
|
||||
ret = -EINVAL;
|
||||
fprintf(stderr, "kvm does not support KVM_CAP_USER_MEMORY\n");
|
||||
goto err;
|
||||
}
|
||||
@@ -336,11 +348,8 @@ int kvm_init(int smp_cpus)
|
||||
/* There was a nasty bug in < kvm-80 that prevents memory slots from being
|
||||
* destroyed properly. Since we rely on this capability, refuse to work
|
||||
* with any kernel without this capability. */
|
||||
ret = kvm_ioctl(s, KVM_CHECK_EXTENSION,
|
||||
KVM_CAP_DESTROY_MEMORY_REGION_WORKS);
|
||||
if (ret <= 0) {
|
||||
if (ret == 0)
|
||||
ret = -EINVAL;
|
||||
if (!kvm_check_extension(s, KVM_CAP_DESTROY_MEMORY_REGION_WORKS)) {
|
||||
ret = -EINVAL;
|
||||
|
||||
fprintf(stderr,
|
||||
"KVM kernel module broken (DESTROY_MEMORY_REGION)\n"
|
||||
@@ -348,11 +357,10 @@ int kvm_init(int smp_cpus)
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->coalesced_mmio = 0;
|
||||
#ifdef KVM_CAP_COALESCED_MMIO
|
||||
ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO);
|
||||
if (ret > 0)
|
||||
s->coalesced_mmio = ret;
|
||||
s->coalesced_mmio = kvm_check_extension(s, KVM_CAP_COALESCED_MMIO);
|
||||
#else
|
||||
s->coalesced_mmio = 0;
|
||||
#endif
|
||||
|
||||
ret = kvm_arch_init(s, smp_cpus);
|
||||
@@ -443,14 +451,13 @@ int kvm_cpu_exec(CPUState *env)
|
||||
dprintf("kvm_cpu_exec()\n");
|
||||
|
||||
do {
|
||||
kvm_arch_pre_run(env, run);
|
||||
|
||||
if (env->exit_request) {
|
||||
dprintf("interrupt exit requested\n");
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
kvm_arch_pre_run(env, run);
|
||||
ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
|
||||
kvm_arch_post_run(env, run);
|
||||
|
||||
@@ -650,11 +657,10 @@ int kvm_has_sync_mmu(void)
|
||||
#ifdef KVM_CAP_SYNC_MMU
|
||||
KVMState *s = kvm_state;
|
||||
|
||||
if (kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_SYNC_MMU) > 0)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
return kvm_check_extension(s, KVM_CAP_SYNC_MMU);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void kvm_setup_guest_memory(void *start, size_t size)
|
||||
|
||||
@@ -78,4 +78,8 @@ int kvm_arch_init(KVMState *s, int smp_cpus);
|
||||
|
||||
int kvm_arch_init_vcpu(CPUState *env);
|
||||
|
||||
int kvm_check_extension(KVMState *s, unsigned int extension);
|
||||
|
||||
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
|
||||
int reg);
|
||||
#endif
|
||||
@@ -383,7 +383,7 @@ static void *zalloc(void *x, unsigned items, unsigned size)
|
||||
return (p);
|
||||
}
|
||||
|
||||
static void zfree(void *x, void *addr, unsigned nb)
|
||||
static void zfree(void *x, void *addr)
|
||||
{
|
||||
qemu_free(addr);
|
||||
}
|
||||
@@ -431,7 +431,7 @@ static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src,
|
||||
}
|
||||
|
||||
s.zalloc = zalloc;
|
||||
s.zfree = (free_func)zfree;
|
||||
s.zfree = zfree;
|
||||
|
||||
r = inflateInit2(&s, -MAX_WBITS);
|
||||
if (r != Z_OK) {
|
||||
|
||||
+27
-19
@@ -74,10 +74,7 @@ MigrationState *exec_start_outgoing_migration(const char *command,
|
||||
goto err_after_open;
|
||||
}
|
||||
|
||||
if (fcntl(s->fd, F_SETFD, O_NONBLOCK) == -1) {
|
||||
dprintf("Unable to set nonblocking mode on file descriptor\n");
|
||||
goto err_after_open;
|
||||
}
|
||||
socket_set_nonblock(s->fd);
|
||||
|
||||
s->opaque = qemu_popen(f, "w");
|
||||
|
||||
@@ -108,9 +105,29 @@ err_after_alloc:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void exec_accept_incoming_migration(void *opaque)
|
||||
{
|
||||
QEMUFile *f = opaque;
|
||||
int ret;
|
||||
|
||||
ret = qemu_loadvm_state(f);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "load of migration failed\n");
|
||||
goto err;
|
||||
}
|
||||
qemu_announce_self();
|
||||
dprintf("successfully loaded vm state\n");
|
||||
/* we've successfully migrated, close the fd */
|
||||
qemu_set_fd_handler2(qemu_popen_fd(f), NULL, NULL, NULL, NULL);
|
||||
if (autostart)
|
||||
vm_start();
|
||||
|
||||
err:
|
||||
qemu_fclose(f);
|
||||
}
|
||||
|
||||
int exec_start_incoming_migration(const char *command)
|
||||
{
|
||||
int ret;
|
||||
QEMUFile *f;
|
||||
|
||||
dprintf("Attempting to start an incoming migration\n");
|
||||
@@ -119,19 +136,10 @@ int exec_start_incoming_migration(const char *command)
|
||||
dprintf("Unable to apply qemu wrapper to popen file\n");
|
||||
return -errno;
|
||||
}
|
||||
vm_stop(0); /* just in case */
|
||||
ret = qemu_loadvm_state(f);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "load of migration failed\n");
|
||||
goto err;
|
||||
}
|
||||
qemu_announce_self();
|
||||
dprintf("successfully loaded vm state\n");
|
||||
vm_start();
|
||||
qemu_fclose(f);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
qemu_fclose(f);
|
||||
return -errno;
|
||||
qemu_set_fd_handler2(qemu_popen_fd(f), NULL,
|
||||
exec_accept_incoming_migration, NULL,
|
||||
(void *)(unsigned long)f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+2
-3
@@ -159,7 +159,6 @@ static void tcp_accept_incoming_migration(void *opaque)
|
||||
goto out;
|
||||
}
|
||||
|
||||
vm_stop(0); /* just in case */
|
||||
ret = qemu_loadvm_state(f);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "load of migration failed\n");
|
||||
@@ -171,8 +170,8 @@ static void tcp_accept_incoming_migration(void *opaque)
|
||||
/* we've successfully migrated, close the server socket */
|
||||
qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
|
||||
close(s);
|
||||
|
||||
vm_start();
|
||||
if (autostart)
|
||||
vm_start();
|
||||
|
||||
out_fopen:
|
||||
qemu_fclose(f);
|
||||
|
||||
+9
-2
@@ -168,7 +168,7 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
|
||||
|
||||
do {
|
||||
ret = s->write(s, data, size);
|
||||
} while (ret == -1 && ((s->get_error(s)) == EINTR || (s->get_error(s)) == EWOULDBLOCK));
|
||||
} while (ret == -1 && ((s->get_error(s)) == EINTR));
|
||||
|
||||
if (ret == -1)
|
||||
ret = -(s->get_error(s));
|
||||
@@ -213,12 +213,17 @@ void migrate_fd_put_ready(void *opaque)
|
||||
dprintf("iterate\n");
|
||||
if (qemu_savevm_state_iterate(s->file) == 1) {
|
||||
int state;
|
||||
int old_vm_running = vm_running;
|
||||
|
||||
dprintf("done iterating\n");
|
||||
vm_stop(0);
|
||||
|
||||
qemu_aio_flush();
|
||||
bdrv_flush_all();
|
||||
if ((qemu_savevm_state_complete(s->file)) < 0) {
|
||||
vm_start();
|
||||
if (old_vm_running) {
|
||||
vm_start();
|
||||
}
|
||||
state = MIG_STATE_ERROR;
|
||||
} else {
|
||||
state = MIG_STATE_COMPLETED;
|
||||
@@ -283,5 +288,7 @@ void migrate_fd_wait_for_unfreeze(void *opaque)
|
||||
int migrate_fd_close(void *opaque)
|
||||
{
|
||||
FdMigrationState *s = opaque;
|
||||
|
||||
qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
|
||||
return s->close(s);
|
||||
}
|
||||
@@ -1468,7 +1468,7 @@ static int net_socket_listen_init(VLANState *vlan,
|
||||
}
|
||||
s->vlan = vlan;
|
||||
s->model = strdup(model);
|
||||
s->name = strdup(name);
|
||||
s->name = name ? strdup(name) : NULL;
|
||||
s->fd = fd;
|
||||
qemu_set_fd_handler(fd, net_socket_accept, NULL, s);
|
||||
return 0;
|
||||
|
||||
@@ -68,6 +68,7 @@ struct NICInfo {
|
||||
const char *model;
|
||||
const char *name;
|
||||
VLANState *vlan;
|
||||
VLANClientState *vc;
|
||||
void *private;
|
||||
int used;
|
||||
};
|
||||
|
||||
+4
-3
@@ -24,9 +24,10 @@ typedef int (AioFlushHandler)(void *opaque);
|
||||
* outstanding AIO operations have been completed or cancelled. */
|
||||
void qemu_aio_flush(void);
|
||||
|
||||
/* Wait for a single AIO completion to occur. This function will until a
|
||||
* single AIO opeartion has completed. It is intended to be used as a looping
|
||||
* primative when simulating synchronous IO based on asynchronous IO. */
|
||||
/* Wait for a single AIO completion to occur. This function will wait
|
||||
* until a single AIO event has completed and it will ensure something
|
||||
* has moved before returning. This can issue new pending aio as
|
||||
* result of executing I/O completion or bh callbacks. */
|
||||
void qemu_aio_wait(void);
|
||||
|
||||
/* Register a file descriptor and associated callbacks. Behaves very similarly
|
||||
|
||||
@@ -3413,16 +3413,6 @@ make install
|
||||
@end example
|
||||
to install QEMU in @file{/usr/local}.
|
||||
|
||||
@subsection GCC version
|
||||
|
||||
In order to compile QEMU successfully, it is very important that you
|
||||
have the right tools. The most important one is gcc. On most hosts and
|
||||
in particular on x86 ones, @emph{gcc 4.x is not supported}. If your
|
||||
Linux distribution includes a gcc 4.x compiler, you can usually
|
||||
install an older version (it is invoked by @code{gcc32} or
|
||||
@code{gcc34}). The QEMU configure script automatically probes for
|
||||
these older versions so that usually you don't have to do anything.
|
||||
|
||||
@node Windows
|
||||
@section Windows
|
||||
|
||||
|
||||
@@ -103,31 +103,46 @@ static int announce_self_create(uint8_t *buf,
|
||||
|
||||
/* FIXME: should we send a different packet (arp/rarp/ping)? */
|
||||
|
||||
memset(buf, 0, 64);
|
||||
memset(buf, 0xff, 6); /* h_dst */
|
||||
memcpy(buf + 6, mac_addr, 6); /* h_src */
|
||||
memcpy(buf + 12, &proto, 2); /* h_proto */
|
||||
memcpy(buf + 14, &magic, 4); /* magic */
|
||||
|
||||
return 18; /* len */
|
||||
return 64; /* len */
|
||||
}
|
||||
|
||||
void qemu_announce_self(void)
|
||||
static void qemu_announce_self_once(void *opaque)
|
||||
{
|
||||
int i, j, len;
|
||||
int i, len;
|
||||
VLANState *vlan;
|
||||
VLANClientState *vc;
|
||||
uint8_t buf[256];
|
||||
static int count = SELF_ANNOUNCE_ROUNDS;
|
||||
QEMUTimer *timer = *(QEMUTimer **)opaque;
|
||||
|
||||
for (i = 0; i < MAX_NICS; i++) {
|
||||
if (!nd_table[i].used)
|
||||
continue;
|
||||
len = announce_self_create(buf, nd_table[i].macaddr);
|
||||
vlan = nd_table[i].vlan;
|
||||
for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
|
||||
for (j=0; j < SELF_ANNOUNCE_ROUNDS; j++)
|
||||
vc->fd_read(vc->opaque, buf, len);
|
||||
for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
|
||||
vc->fd_read(vc->opaque, buf, len);
|
||||
}
|
||||
}
|
||||
if (count--) {
|
||||
qemu_mod_timer(timer, qemu_get_clock(rt_clock) + 100);
|
||||
} else {
|
||||
qemu_del_timer(timer);
|
||||
qemu_free_timer(timer);
|
||||
}
|
||||
}
|
||||
|
||||
void qemu_announce_self(void)
|
||||
{
|
||||
static QEMUTimer *timer;
|
||||
timer = qemu_new_timer(rt_clock, qemu_announce_self_once, &timer);
|
||||
qemu_announce_self_once(&timer);
|
||||
}
|
||||
|
||||
/***********************************************************/
|
||||
@@ -195,7 +210,14 @@ static int popen_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int s
|
||||
static int popen_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
|
||||
{
|
||||
QEMUFilePopen *s = opaque;
|
||||
return fread(buf, 1, size, s->popen_file);
|
||||
FILE *fp = s->popen_file;
|
||||
int bytes;
|
||||
|
||||
do {
|
||||
clearerr(fp);
|
||||
bytes = fread(buf, 1, size, fp);
|
||||
} while ((bytes == 0) && ferror(fp) && (errno == EINTR));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static int popen_close(void *opaque)
|
||||
@@ -224,7 +246,6 @@ QEMUFile *qemu_popen(FILE *popen_file, const char *mode)
|
||||
} else {
|
||||
s->file = qemu_fopen_ops(s, popen_put_buffer, NULL, popen_close, NULL);
|
||||
}
|
||||
fprintf(stderr, "qemu_popen: returning result of qemu_fopen_ops\n");
|
||||
return s->file;
|
||||
}
|
||||
|
||||
@@ -240,6 +261,17 @@ QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
|
||||
return qemu_popen(popen_file, mode);
|
||||
}
|
||||
|
||||
int qemu_popen_fd(QEMUFile *f)
|
||||
{
|
||||
QEMUFilePopen *p;
|
||||
int fd;
|
||||
|
||||
p = (QEMUFilePopen *)f->opaque;
|
||||
fd = fileno(p->popen_file);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
QEMUFile *qemu_fopen_socket(int fd)
|
||||
{
|
||||
QEMUFileSocket *s = qemu_mallocz(sizeof(QEMUFileSocket));
|
||||
|
||||
@@ -144,32 +144,35 @@ static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
|
||||
static int check_for_evdev(void)
|
||||
{
|
||||
SDL_SysWMinfo info;
|
||||
XkbDescPtr desc;
|
||||
XkbDescPtr desc = NULL;
|
||||
int has_evdev = 0;
|
||||
const char *keycodes;
|
||||
char *keycodes = NULL;
|
||||
|
||||
SDL_VERSION(&info.version);
|
||||
if (!SDL_GetWMInfo(&info))
|
||||
if (!SDL_GetWMInfo(&info)) {
|
||||
return 0;
|
||||
|
||||
}
|
||||
desc = XkbGetKeyboard(info.info.x11.display,
|
||||
XkbGBN_AllComponentsMask,
|
||||
XkbUseCoreKbd);
|
||||
if (desc == NULL || desc->names == NULL)
|
||||
return 0;
|
||||
|
||||
keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes);
|
||||
if (keycodes == NULL)
|
||||
fprintf(stderr, "could not lookup keycode name\n");
|
||||
else if (strstart(keycodes, "evdev", NULL))
|
||||
has_evdev = 1;
|
||||
else if (!strstart(keycodes, "xfree86", NULL))
|
||||
fprintf(stderr,
|
||||
"unknown keycodes `%s', please report to qemu-devel@nongnu.org\n",
|
||||
keycodes);
|
||||
|
||||
XkbFreeClientMap(desc, XkbGBN_AllComponentsMask, True);
|
||||
if (desc && desc->names) {
|
||||
keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes);
|
||||
if (keycodes == NULL) {
|
||||
fprintf(stderr, "could not lookup keycode name\n");
|
||||
} else if (strstart(keycodes, "evdev", NULL)) {
|
||||
has_evdev = 1;
|
||||
} else if (!strstart(keycodes, "xfree86", NULL)) {
|
||||
fprintf(stderr, "unknown keycodes `%s', please report to "
|
||||
"qemu-devel@nongnu.org\n", keycodes);
|
||||
}
|
||||
}
|
||||
|
||||
if (desc) {
|
||||
XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True);
|
||||
}
|
||||
if (keycodes) {
|
||||
XFree(keycodes);
|
||||
}
|
||||
return has_evdev;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -77,6 +77,7 @@ int tap_win32_init(VLANState *vlan, const char *model,
|
||||
/* SLIRP */
|
||||
void do_info_slirp(void);
|
||||
|
||||
extern int autostart;
|
||||
extern int bios_size;
|
||||
extern int cirrus_vga_enabled;
|
||||
extern int std_vga_enabled;
|
||||
|
||||
@@ -957,7 +957,8 @@ static void gen_tst_cc (DisasContext *dc, TCGv cc, int cond)
|
||||
else if (dc->cc_size == 2)
|
||||
bits = 15;
|
||||
|
||||
tcg_gen_shri_tl(cc, cc_result, 31);
|
||||
tcg_gen_shri_tl(cc, cc_result, bits);
|
||||
tcg_gen_andi_tl(cc, cc, 1);
|
||||
}
|
||||
else {
|
||||
cris_evaluate_flags(dc);
|
||||
|
||||
+77
-38
@@ -32,61 +32,79 @@
|
||||
|
||||
//#define DEBUG_MMU
|
||||
|
||||
/* feature flags taken from "Intel Processor Identification and the CPUID
|
||||
* Instruction" and AMD's "CPUID Specification". In cases of disagreement
|
||||
* about feature names, the Linux name is used. */
|
||||
static const char *feature_name[] = {
|
||||
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
||||
"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
|
||||
"pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx",
|
||||
"fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
|
||||
};
|
||||
static const char *ext_feature_name[] = {
|
||||
"pni" /* Intel,AMD sse3 */, NULL, NULL, "monitor", "ds_cpl", "vmx", NULL /* Linux smx */, "est",
|
||||
"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
|
||||
NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
};
|
||||
static const char *ext2_feature_name[] = {
|
||||
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
||||
"cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mtrr", "pge", "mca", "cmov",
|
||||
"pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx",
|
||||
"fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
|
||||
};
|
||||
static const char *ext3_feature_name[] = {
|
||||
"lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
|
||||
"3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
};
|
||||
|
||||
static void add_flagname_to_bitmaps(char *flagname, uint32_t *features,
|
||||
uint32_t *ext_features,
|
||||
uint32_t *ext2_features,
|
||||
uint32_t *ext3_features)
|
||||
{
|
||||
int i;
|
||||
/* feature flags taken from "Intel Processor Identification and the CPUID
|
||||
* Instruction" and AMD's "CPUID Specification". In cases of disagreement
|
||||
* about feature names, the Linux name is used. */
|
||||
static const char *feature_name[] = {
|
||||
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
||||
"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
|
||||
"pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx",
|
||||
"fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
|
||||
};
|
||||
static const char *ext_feature_name[] = {
|
||||
"pni" /* Intel,AMD sse3 */, NULL, NULL, "monitor", "ds_cpl", "vmx", NULL /* Linux smx */, "est",
|
||||
"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
|
||||
NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
};
|
||||
static const char *ext2_feature_name[] = {
|
||||
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
||||
"cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mtrr", "pge", "mca", "cmov",
|
||||
"pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx",
|
||||
"fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
|
||||
};
|
||||
static const char *ext3_feature_name[] = {
|
||||
"lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
|
||||
"3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
};
|
||||
int found = 0;
|
||||
|
||||
for ( i = 0 ; i < 32 ; i++ )
|
||||
if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
|
||||
*features |= 1 << i;
|
||||
return;
|
||||
found = 1;
|
||||
}
|
||||
for ( i = 0 ; i < 32 ; i++ )
|
||||
if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
|
||||
*ext_features |= 1 << i;
|
||||
return;
|
||||
found = 1;
|
||||
}
|
||||
for ( i = 0 ; i < 32 ; i++ )
|
||||
if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
|
||||
*ext2_features |= 1 << i;
|
||||
return;
|
||||
found = 1;
|
||||
}
|
||||
for ( i = 0 ; i < 32 ; i++ )
|
||||
if (ext3_feature_name[i] && !strcmp (flagname, ext3_feature_name[i])) {
|
||||
*ext3_features |= 1 << i;
|
||||
return;
|
||||
found = 1;
|
||||
}
|
||||
fprintf(stderr, "CPU feature %s not found\n", flagname);
|
||||
if (!found) {
|
||||
fprintf(stderr, "CPU feature %s not found\n", flagname);
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_trim_features(uint32_t *features, uint32_t supported,
|
||||
const char *names[])
|
||||
{
|
||||
int i;
|
||||
uint32_t mask;
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
mask = 1U << i;
|
||||
if ((*features & mask) && !(supported & mask)) {
|
||||
*features &= ~mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct x86_def_t {
|
||||
@@ -476,17 +494,23 @@ void cpu_reset(CPUX86State *env)
|
||||
env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
|
||||
|
||||
cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK | DESC_R_MASK);
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
|
||||
DESC_R_MASK | DESC_A_MASK);
|
||||
cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
|
||||
DESC_A_MASK);
|
||||
cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
|
||||
DESC_A_MASK);
|
||||
cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
|
||||
DESC_A_MASK);
|
||||
cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
|
||||
DESC_A_MASK);
|
||||
cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
|
||||
DESC_A_MASK);
|
||||
|
||||
env->eip = 0xfff0;
|
||||
env->regs[R_EDX] = env->cpuid_version;
|
||||
@@ -1670,5 +1694,20 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
|
||||
#endif
|
||||
if (kvm_enabled())
|
||||
kvm_init_vcpu(env);
|
||||
if (kvm_enabled()) {
|
||||
kvm_trim_features(&env->cpuid_features,
|
||||
kvm_arch_get_supported_cpuid(env, 1, R_EDX),
|
||||
feature_name);
|
||||
kvm_trim_features(&env->cpuid_ext_features,
|
||||
kvm_arch_get_supported_cpuid(env, 1, R_ECX),
|
||||
ext_feature_name);
|
||||
kvm_trim_features(&env->cpuid_ext2_features,
|
||||
kvm_arch_get_supported_cpuid(env, 0x80000001, R_EDX),
|
||||
ext2_feature_name);
|
||||
kvm_trim_features(&env->cpuid_ext3_features,
|
||||
kvm_arch_get_supported_cpuid(env, 0x80000001, R_ECX),
|
||||
ext3_feature_name);
|
||||
}
|
||||
|
||||
return env;
|
||||
}
|
||||
@@ -33,6 +33,89 @@
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
#ifdef KVM_CAP_EXT_CPUID
|
||||
|
||||
static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
|
||||
{
|
||||
struct kvm_cpuid2 *cpuid;
|
||||
int r, size;
|
||||
|
||||
size = sizeof(*cpuid) + max * sizeof(*cpuid->entries);
|
||||
cpuid = (struct kvm_cpuid2 *)qemu_mallocz(size);
|
||||
cpuid->nent = max;
|
||||
r = kvm_ioctl(s, KVM_GET_SUPPORTED_CPUID, cpuid);
|
||||
if (r == 0 && cpuid->nent >= max) {
|
||||
r = -E2BIG;
|
||||
}
|
||||
if (r < 0) {
|
||||
if (r == -E2BIG) {
|
||||
qemu_free(cpuid);
|
||||
return NULL;
|
||||
} else {
|
||||
fprintf(stderr, "KVM_GET_SUPPORTED_CPUID failed: %s\n",
|
||||
strerror(-r));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
return cpuid;
|
||||
}
|
||||
|
||||
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg)
|
||||
{
|
||||
struct kvm_cpuid2 *cpuid;
|
||||
int i, max;
|
||||
uint32_t ret = 0;
|
||||
uint32_t cpuid_1_edx;
|
||||
|
||||
if (!kvm_check_extension(env->kvm_state, KVM_CAP_EXT_CPUID)) {
|
||||
return -1U;
|
||||
}
|
||||
|
||||
max = 1;
|
||||
while ((cpuid = try_get_cpuid(env->kvm_state, max)) == NULL) {
|
||||
max *= 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < cpuid->nent; ++i) {
|
||||
if (cpuid->entries[i].function == function) {
|
||||
switch (reg) {
|
||||
case R_EAX:
|
||||
ret = cpuid->entries[i].eax;
|
||||
break;
|
||||
case R_EBX:
|
||||
ret = cpuid->entries[i].ebx;
|
||||
break;
|
||||
case R_ECX:
|
||||
ret = cpuid->entries[i].ecx;
|
||||
break;
|
||||
case R_EDX:
|
||||
ret = cpuid->entries[i].edx;
|
||||
if (function == 0x80000001) {
|
||||
/* On Intel, kvm returns cpuid according to the Intel spec,
|
||||
* so add missing bits according to the AMD spec:
|
||||
*/
|
||||
cpuid_1_edx = kvm_arch_get_supported_cpuid(env, 1, R_EDX);
|
||||
ret |= cpuid_1_edx & 0xdfeff7ff;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qemu_free(cpuid);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg)
|
||||
{
|
||||
return -1U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int kvm_arch_init_vcpu(CPUState *env)
|
||||
{
|
||||
struct {
|
||||
|
||||
@@ -201,7 +201,7 @@ ram_addr_t ram_size;
|
||||
int nb_nics;
|
||||
NICInfo nd_table[MAX_NICS];
|
||||
int vm_running;
|
||||
static int autostart;
|
||||
int autostart;
|
||||
static int rtc_utc = 1;
|
||||
static int rtc_date_offset = -1; /* -1 means no change */
|
||||
int cirrus_vga_enabled = 1;
|
||||
@@ -894,7 +894,7 @@ struct qemu_alarm_timer {
|
||||
|
||||
static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
|
||||
{
|
||||
return t->flags & ALARM_FLAG_DYNTICKS;
|
||||
return t && (t->flags & ALARM_FLAG_DYNTICKS);
|
||||
}
|
||||
|
||||
static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
|
||||
@@ -1338,7 +1338,7 @@ static void host_alarm_handler(int host_signum)
|
||||
static const char byte = 0;
|
||||
write(alarm_timer_wfd, &byte, sizeof(byte));
|
||||
#endif
|
||||
alarm_timer->flags |= ALARM_FLAG_EXPIRED;
|
||||
if (alarm_timer) alarm_timer->flags |= ALARM_FLAG_EXPIRED;
|
||||
|
||||
if (env) {
|
||||
/* stop the currently executing cpu because a timer occured */
|
||||
@@ -1528,6 +1528,11 @@ static int dynticks_start_timer(struct qemu_alarm_timer *t)
|
||||
|
||||
sigaction(SIGALRM, &act, NULL);
|
||||
|
||||
/*
|
||||
* Initialize ev struct to 0 to avoid valgrind complaining
|
||||
* about uninitialized data in timer_create call
|
||||
*/
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.sigev_value.sival_int = 0;
|
||||
ev.sigev_notify = SIGEV_SIGNAL;
|
||||
ev.sigev_signo = SIGALRM;
|
||||
@@ -5717,11 +5722,11 @@ int main(int argc, char **argv, char **envp)
|
||||
do_loadvm(loadvm);
|
||||
|
||||
if (incoming) {
|
||||
autostart = 0; /* fixme how to deal with -daemonize */
|
||||
autostart = 0;
|
||||
qemu_start_incoming_migration(incoming);
|
||||
}
|
||||
|
||||
if (autostart)
|
||||
else if (autostart)
|
||||
vm_start();
|
||||
|
||||
if (daemonize) {
|
||||
|
||||
@@ -200,6 +200,8 @@ static void vnc_write_u16(VncState *vs, uint16_t value);
|
||||
static void vnc_write_u8(VncState *vs, uint8_t value);
|
||||
static void vnc_flush(VncState *vs);
|
||||
static void vnc_update_client(void *opaque);
|
||||
static void vnc_disconnect_start(VncState *vs);
|
||||
static void vnc_disconnect_finish(VncState *vs);
|
||||
static void vnc_client_read(void *opaque);
|
||||
|
||||
static void vnc_colordepth(VncState *vs);
|
||||
@@ -633,8 +635,14 @@ static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
|
||||
|
||||
static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
|
||||
{
|
||||
|
||||
uint8_t *src_row;
|
||||
uint8_t *dst_row;
|
||||
int y,pitch,depth;
|
||||
|
||||
vnc_update_client(vs);
|
||||
|
||||
/* send bitblit op to the vnc client */
|
||||
vnc_write_u8(vs, 0); /* msg id */
|
||||
vnc_write_u8(vs, 0);
|
||||
vnc_write_u16(vs, 1); /* number of rects */
|
||||
@@ -642,18 +650,43 @@ static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, i
|
||||
vnc_write_u16(vs, src_x);
|
||||
vnc_write_u16(vs, src_y);
|
||||
vnc_flush(vs);
|
||||
|
||||
/* do bitblit op on the local surface too */
|
||||
pitch = ds_get_linesize(vs->ds);
|
||||
depth = ds_get_bytes_per_pixel(vs->ds);
|
||||
src_row = ds_get_data(vs->ds) + pitch * src_y + depth * src_x;
|
||||
dst_row = ds_get_data(vs->ds) + pitch * dst_y + depth * dst_x;
|
||||
if (dst_y > src_y) {
|
||||
/* copy backwards */
|
||||
src_row += pitch * (h-1);
|
||||
dst_row += pitch * (h-1);
|
||||
pitch = -pitch;
|
||||
}
|
||||
for (y = 0; y < h; y++) {
|
||||
memmove(dst_row, src_row, w * depth);
|
||||
src_row += pitch;
|
||||
dst_row += pitch;
|
||||
}
|
||||
}
|
||||
|
||||
static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
|
||||
{
|
||||
VncDisplay *vd = ds->opaque;
|
||||
VncState *vs = vd->clients;
|
||||
while (vs != NULL) {
|
||||
VncState *vs, *vn;
|
||||
|
||||
for (vs = vd->clients; vs != NULL; vs = vn) {
|
||||
vn = vs->next;
|
||||
if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
|
||||
vnc_update_client(vs);
|
||||
/* vs might be free()ed here */
|
||||
}
|
||||
}
|
||||
|
||||
for (vs = vd->clients; vs != NULL; vs = vs->next) {
|
||||
if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT))
|
||||
vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
|
||||
else /* TODO */
|
||||
vnc_update(vs, dst_x, dst_y, w, h);
|
||||
vs = vs->next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,6 +796,8 @@ static void vnc_update_client(void *opaque)
|
||||
|
||||
if (vs->csock != -1) {
|
||||
qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
|
||||
} else {
|
||||
vnc_disconnect_finish(vs);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -832,6 +867,47 @@ static void audio_del(VncState *vs)
|
||||
}
|
||||
}
|
||||
|
||||
static void vnc_disconnect_start(VncState *vs)
|
||||
{
|
||||
if (vs->csock == -1)
|
||||
return;
|
||||
qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
|
||||
closesocket(vs->csock);
|
||||
vs->csock = -1;
|
||||
}
|
||||
|
||||
static void vnc_disconnect_finish(VncState *vs)
|
||||
{
|
||||
qemu_del_timer(vs->timer);
|
||||
qemu_free_timer(vs->timer);
|
||||
if (vs->input.buffer) qemu_free(vs->input.buffer);
|
||||
if (vs->output.buffer) qemu_free(vs->output.buffer);
|
||||
#ifdef CONFIG_VNC_TLS
|
||||
if (vs->tls_session) {
|
||||
gnutls_deinit(vs->tls_session);
|
||||
vs->tls_session = NULL;
|
||||
}
|
||||
#endif /* CONFIG_VNC_TLS */
|
||||
audio_del(vs);
|
||||
|
||||
VncState *p, *parent = NULL;
|
||||
for (p = vs->vd->clients; p != NULL; p = p->next) {
|
||||
if (p == vs) {
|
||||
if (parent)
|
||||
parent->next = p->next;
|
||||
else
|
||||
vs->vd->clients = p->next;
|
||||
break;
|
||||
}
|
||||
parent = p;
|
||||
}
|
||||
if (!vs->vd->clients)
|
||||
dcl->idle = 1;
|
||||
|
||||
qemu_free(vs->old_data);
|
||||
qemu_free(vs);
|
||||
}
|
||||
|
||||
static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
|
||||
{
|
||||
if (ret == 0 || ret == -1) {
|
||||
@@ -849,36 +925,7 @@ static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
|
||||
}
|
||||
|
||||
VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno : 0);
|
||||
qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
|
||||
closesocket(vs->csock);
|
||||
qemu_del_timer(vs->timer);
|
||||
qemu_free_timer(vs->timer);
|
||||
if (vs->input.buffer) qemu_free(vs->input.buffer);
|
||||
if (vs->output.buffer) qemu_free(vs->output.buffer);
|
||||
#ifdef CONFIG_VNC_TLS
|
||||
if (vs->tls_session) {
|
||||
gnutls_deinit(vs->tls_session);
|
||||
vs->tls_session = NULL;
|
||||
}
|
||||
#endif /* CONFIG_VNC_TLS */
|
||||
audio_del(vs);
|
||||
|
||||
VncState *p, *parent = NULL;
|
||||
for (p = vs->vd->clients; p != NULL; p = p->next) {
|
||||
if (p == vs) {
|
||||
if (parent)
|
||||
parent->next = p->next;
|
||||
else
|
||||
vs->vd->clients = p->next;
|
||||
break;
|
||||
}
|
||||
parent = p;
|
||||
}
|
||||
if (!vs->vd->clients)
|
||||
dcl->idle = 1;
|
||||
|
||||
qemu_free(vs->old_data);
|
||||
qemu_free(vs);
|
||||
vnc_disconnect_start(vs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -887,7 +934,8 @@ static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
|
||||
|
||||
static void vnc_client_error(VncState *vs)
|
||||
{
|
||||
vnc_client_io_error(vs, -1, EINVAL);
|
||||
VNC_DEBUG("Closing down client sock: protocol error\n");
|
||||
vnc_disconnect_start(vs);
|
||||
}
|
||||
|
||||
static void vnc_client_write(void *opaque)
|
||||
@@ -947,8 +995,11 @@ static void vnc_client_read(void *opaque)
|
||||
#endif /* CONFIG_VNC_TLS */
|
||||
ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
|
||||
ret = vnc_client_io_error(vs, ret, socket_error());
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
if (vs->csock == -1)
|
||||
vnc_disconnect_finish(vs);
|
||||
return;
|
||||
}
|
||||
|
||||
vs->input.offset += ret;
|
||||
|
||||
@@ -957,8 +1008,10 @@ static void vnc_client_read(void *opaque)
|
||||
int ret;
|
||||
|
||||
ret = vs->read_handler(vs, vs->input.buffer, len);
|
||||
if (vs->csock == -1)
|
||||
if (vs->csock == -1) {
|
||||
vnc_disconnect_finish(vs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
|
||||
@@ -973,7 +1026,7 @@ static void vnc_write(VncState *vs, const void *data, size_t len)
|
||||
{
|
||||
buffer_reserve(&vs->output, len);
|
||||
|
||||
if (buffer_empty(&vs->output)) {
|
||||
if (vs->csock != -1 && buffer_empty(&vs->output)) {
|
||||
qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
|
||||
}
|
||||
|
||||
@@ -1014,7 +1067,7 @@ static void vnc_write_u8(VncState *vs, uint8_t value)
|
||||
|
||||
static void vnc_flush(VncState *vs)
|
||||
{
|
||||
if (vs->output.offset)
|
||||
if (vs->csock != -1 && vs->output.offset)
|
||||
vnc_client_write(vs);
|
||||
}
|
||||
|
||||
@@ -2282,11 +2335,13 @@ static void vnc_connect(VncDisplay *vd, int csock)
|
||||
vnc_read_when(vs, protocol_version, 12);
|
||||
memset(vs->old_data, 0, ds_get_linesize(vs->ds) * ds_get_height(vs->ds));
|
||||
memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
|
||||
vnc_update_client(vs);
|
||||
reset_keys(vs);
|
||||
|
||||
vs->next = vd->clients;
|
||||
vd->clients = vs;
|
||||
|
||||
vnc_update_client(vs);
|
||||
/* vs might be free()ed here */
|
||||
}
|
||||
|
||||
static void vnc_listen_read(void *opaque)
|
||||
@@ -2306,9 +2361,8 @@ static void vnc_listen_read(void *opaque)
|
||||
|
||||
void vnc_display_init(DisplayState *ds)
|
||||
{
|
||||
VncDisplay *vs;
|
||||
VncDisplay *vs = qemu_mallocz(sizeof(*vs));
|
||||
|
||||
vs = qemu_mallocz(sizeof(VncState));
|
||||
dcl = qemu_mallocz(sizeof(DisplayChangeListener));
|
||||
|
||||
ds->opaque = vs;
|
||||
@@ -2416,6 +2470,10 @@ int vnc_display_password(DisplayState *ds, const char *password)
|
||||
{
|
||||
VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
|
||||
|
||||
if (!vs) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vs->password) {
|
||||
qemu_free(vs->password);
|
||||
vs->password = NULL;
|
||||
|
||||
Reference in new issue
Block a user