Compare commits
66 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
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 | ||
|
34aee2552f | ||
|
9fd0e57dc9 | ||
|
2fd0f93286 | ||
|
8bd8199f70 | ||
|
2da1e39864 | ||
|
b468f27acd | ||
|
8bc2ad6a6a | ||
|
f24f1e2a85 |
50
Changelog
50
Changelog
@@ -1,3 +1,53 @@
|
||||
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)
|
||||
- fix AIO deletion race (Alex Graf)
|
||||
- reset option roms on reboot (Glauber Costa)
|
||||
- fix qcow2 corruption in cluster freeing (Gleb Natapov)
|
||||
- Enable power button event generation (Gleb Natapov)
|
||||
|
||||
version 0.10.3:
|
||||
- fix AIO cancellations (Avi Kivity)
|
||||
- fix live migration error path on incoming
|
||||
|
11
aio.c
11
aio.c
@@ -44,7 +44,8 @@ static AioHandler *find_aio_handler(int fd)
|
||||
|
||||
LIST_FOREACH(node, &aio_handlers, node) {
|
||||
if (node->fd == fd)
|
||||
return node;
|
||||
if (!node->deleted)
|
||||
return node;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -102,11 +103,15 @@ 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);
|
||||
}
|
||||
|
||||
|
@@ -903,6 +903,12 @@ static int alloc_cluster_link_l2(BlockDriverState *bs, uint64_t cluster_offset,
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < m->nb_clusters; i++) {
|
||||
/* if two concurrent writes happen to the same unallocated cluster
|
||||
* each write allocates separate cluster and writes data concurrently.
|
||||
* The first one to complete updates l2 table with pointer to its
|
||||
* cluster the second one has to do RMW (which is done above by
|
||||
* copy_sectors()), update l2 table with its cluster pointer and free
|
||||
* old cluster. This is what this loop does */
|
||||
if(l2_table[l2_index + i] != 0)
|
||||
old_cluster[j++] = l2_table[l2_index + i];
|
||||
|
||||
@@ -916,7 +922,8 @@ static int alloc_cluster_link_l2(BlockDriverState *bs, uint64_t cluster_offset,
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < j; i++)
|
||||
free_any_clusters(bs, be64_to_cpu(old_cluster[i]), 1);
|
||||
free_any_clusters(bs, be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED,
|
||||
1);
|
||||
|
||||
ret = 0;
|
||||
err:
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
50
block.c
50
block.c
@@ -533,7 +533,10 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
len = bdrv_getlength(bs);
|
||||
|
||||
if ((offset + size) > len)
|
||||
if (offset < 0)
|
||||
return -EIO;
|
||||
|
||||
if ((offset > len) || (len - offset < size))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
@@ -1170,6 +1173,8 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_write_compressed)
|
||||
return -ENOTSUP;
|
||||
if (bdrv_check_request(bs, sector_num, nb_sectors))
|
||||
return -EIO;
|
||||
return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
|
||||
}
|
||||
|
||||
@@ -1327,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,
|
||||
@@ -1363,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;
|
||||
@@ -1379,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,
|
||||
@@ -1555,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);
|
||||
@@ -1655,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 {
|
||||
@@ -1668,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)
|
||||
|
2
block.h
2
block.h
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
3
exec.c
3
exec.c
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
12
hw/e1000.c
12
hw/e1000.c
@@ -189,6 +189,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)
|
||||
{
|
||||
@@ -783,12 +790,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,
|
||||
@@ -1067,7 +1074,6 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
return NULL;
|
||||
|
||||
pci_conf = d->dev.config;
|
||||
memset(pci_conf, 0, 256);
|
||||
|
||||
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
|
||||
pci_config_set_device_id(pci_conf, E1000_DEVID);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
1
hw/hw.h
1
hw/hw.h
@@ -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);
|
||||
|
26
hw/ide.c
26
hw/ide.c
@@ -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
|
||||
@@ -1818,18 +1819,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:
|
||||
|
@@ -262,6 +262,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 +331,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 +1402,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 +1410,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 +1491,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 +1600,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 +1633,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 +1715,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
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
51
hw/pc.c
51
hw/pc.c
@@ -63,6 +63,30 @@ static PITState *pit;
|
||||
static IOAPICState *ioapic;
|
||||
static PCIDevice *i440fx_state;
|
||||
|
||||
typedef struct rom_reset_data {
|
||||
uint8_t *data;
|
||||
target_phys_addr_t addr;
|
||||
unsigned size;
|
||||
} RomResetData;
|
||||
|
||||
static void option_rom_reset(void *_rrd)
|
||||
{
|
||||
RomResetData *rrd = _rrd;
|
||||
|
||||
cpu_physical_memory_write_rom(rrd->addr, rrd->data, rrd->size);
|
||||
}
|
||||
|
||||
static void option_rom_setup_reset(target_phys_addr_t addr, unsigned size)
|
||||
{
|
||||
RomResetData *rrd = qemu_malloc(sizeof *rrd);
|
||||
|
||||
rrd->data = qemu_malloc(size);
|
||||
cpu_physical_memory_read(addr, rrd->data, size);
|
||||
rrd->addr = addr;
|
||||
rrd->size = size;
|
||||
qemu_register_reset(option_rom_reset, rrd);
|
||||
}
|
||||
|
||||
static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
|
||||
{
|
||||
}
|
||||
@@ -447,7 +471,7 @@ static void bochs_bios_init(void)
|
||||
|
||||
/* Generate an initial boot sector which sets state and jump to
|
||||
a specified vector */
|
||||
static void generate_bootsect(uint8_t *option_rom,
|
||||
static void generate_bootsect(target_phys_addr_t option_rom,
|
||||
uint32_t gpr[8], uint16_t segs[6], uint16_t ip)
|
||||
{
|
||||
uint8_t rom[512], *p, *reloc;
|
||||
@@ -521,7 +545,8 @@ static void generate_bootsect(uint8_t *option_rom,
|
||||
sum += rom[i];
|
||||
rom[sizeof(rom) - 1] = -sum;
|
||||
|
||||
memcpy(option_rom, rom, sizeof(rom));
|
||||
cpu_physical_memory_write_rom(option_rom, rom, sizeof(rom));
|
||||
option_rom_setup_reset(option_rom, sizeof (rom));
|
||||
}
|
||||
|
||||
static long get_file_size(FILE *f)
|
||||
@@ -538,10 +563,11 @@ static long get_file_size(FILE *f)
|
||||
return size;
|
||||
}
|
||||
|
||||
static void load_linux(uint8_t *option_rom,
|
||||
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];
|
||||
@@ -607,8 +633,8 @@ static void load_linux(uint8_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);
|
||||
@@ -650,9 +676,6 @@ static void load_linux(uint8_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);
|
||||
@@ -689,6 +712,12 @@ static void load_linux(uint8_t *option_rom,
|
||||
memset(gpr, 0, sizeof gpr);
|
||||
gpr[4] = cmdline_addr-real_addr-16; /* SP (-16 is paranoia) */
|
||||
|
||||
option_rom_setup_reset(real_addr, setup_size);
|
||||
option_rom_setup_reset(prot_addr, kernel_size);
|
||||
option_rom_setup_reset(cmdline_addr, cmdline_size);
|
||||
if (initrd_filename)
|
||||
option_rom_setup_reset(initrd_addr, initrd_size);
|
||||
|
||||
generate_bootsect(option_rom, gpr, seg, 0);
|
||||
}
|
||||
|
||||
@@ -896,10 +925,10 @@ vga_bios_error:
|
||||
offset = 0;
|
||||
if (linux_boot) {
|
||||
option_rom_offset = qemu_ram_alloc(TARGET_PAGE_SIZE);
|
||||
load_linux(phys_ram_base + 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;
|
||||
}
|
||||
|
||||
|
38
hw/ps2.c
38
hw/ps2.c
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
5
hw/vga.c
5
hw/vga.c
@@ -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);
|
||||
|
46
kvm-all.c
46
kvm-all.c
@@ -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)
|
||||
|
4
kvm.h
4
kvm.h
@@ -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
|
||||
|
4
loader.c
4
loader.c
@@ -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) {
|
||||
|
@@ -108,9 +108,27 @@ 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);
|
||||
|
||||
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 +137,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;
|
||||
}
|
||||
|
@@ -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");
|
||||
@@ -172,8 +171,6 @@ static void tcp_accept_incoming_migration(void *opaque)
|
||||
qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
|
||||
close(s);
|
||||
|
||||
vm_start();
|
||||
|
||||
out_fopen:
|
||||
qemu_fclose(f);
|
||||
out:
|
||||
|
11
migration.c
11
migration.c
@@ -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);
|
||||
}
|
||||
|
2
net.c
2
net.c
@@ -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;
|
||||
|
1
net.h
1
net.h
@@ -68,6 +68,7 @@ struct NICInfo {
|
||||
const char *model;
|
||||
const char *name;
|
||||
VLANState *vlan;
|
||||
VLANClientState *vc;
|
||||
void *private;
|
||||
int used;
|
||||
};
|
||||
|
@@ -0,0 +1,20 @@
|
||||
Enable power button event generation.
|
||||
|
||||
Signed-off-by: Gleb Natapov <gleb@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
|
||||
diff --git a/bios/rombios32.c b/bios/rombios32.c
|
||||
index 81e3bad..9986531 100644
|
||||
--- a/bios/rombios32.c
|
||||
+++ b/bios/rombios32.c
|
||||
@@ -1767,8 +1767,8 @@ void acpi_bios_init(void)
|
||||
fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
|
||||
fadt->gpe0_blk = cpu_to_le32(0xafe0);
|
||||
fadt->gpe0_blk_len = 4;
|
||||
- /* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */
|
||||
- fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6));
|
||||
+ /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */
|
||||
+ fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 6));
|
||||
acpi_build_table_header((struct acpi_table_header *)fadt, "FACP",
|
||||
sizeof(*fadt), 1);
|
||||
|
@@ -10,3 +10,4 @@
|
||||
0010_bios-mark-the-acpi-sci-interrupt-as-connected-to-irq-9.patch
|
||||
0011_read-additional-acpi-tables-from-a-vm.patch
|
||||
0013_fix-non-acpi-timer-interrupt-routing.patch
|
||||
0015_enable-power-button-even-generation.patch
|
||||
|
BIN
pc-bios/bios.bin
BIN
pc-bios/bios.bin
Binary file not shown.
@@ -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
|
||||
|
||||
|
48
savevm.c
48
savevm.c
@@ -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));
|
||||
|
39
sdl.c
39
sdl.c
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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 {
|
||||
|
13
vl.c
13
vl.c
@@ -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;
|
||||
@@ -5716,10 +5721,8 @@ int main(int argc, char **argv, char **envp)
|
||||
if (loadvm)
|
||||
do_loadvm(loadvm);
|
||||
|
||||
if (incoming) {
|
||||
autostart = 0; /* fixme how to deal with -daemonize */
|
||||
if (incoming)
|
||||
qemu_start_incoming_migration(incoming);
|
||||
}
|
||||
|
||||
if (autostart)
|
||||
vm_start();
|
||||
|
Reference in New Issue
Block a user