Compare commits
32 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
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 |
21
Changelog
21
Changelog
@@ -1,3 +1,24 @@
|
||||
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
|
||||
|
3
aio.c
3
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;
|
||||
|
@@ -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:
|
||||
|
41
block.c
41
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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -1067,7 +1067,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);
|
||||
|
@@ -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],
|
||||
|
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;
|
||||
}
|
||||
|
||||
|
43
kvm-all.c
43
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);
|
||||
@@ -650,11 +658,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
|
||||
|
@@ -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));
|
||||
|
@@ -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.
@@ -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
|
||||
|
||||
|
@@ -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 {
|
||||
@@ -1670,5 +1688,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 {
|
||||
|
9
vl.c
9
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;
|
||||
|
Reference in New Issue
Block a user