Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
5558e88318 | ||
|
06b393452f | ||
|
b7d11af2e0 | ||
|
8d47bb6162 | ||
|
80acab6c50 | ||
|
da0ac2bc13 | ||
|
d3c2632047 | ||
|
7cc73776e7 | ||
|
937e9a1c83 | ||
|
4498819404 | ||
|
c61ad61830 | ||
|
65297bc408 | ||
|
02d400ead7 | ||
|
20a9c6ac7f | ||
|
bd0b264c21 | ||
|
0f31aac44f | ||
|
30b15843b2 | ||
|
04ffdd7f94 |
16
Changelog
16
Changelog
@@ -1,3 +1,19 @@
|
||||
version 0.10.2:
|
||||
|
||||
- fix savevm/loadvm (Anthony Liguori)
|
||||
- live migration: fix dirty tracking windows (Glauber Costa)
|
||||
- live migration: improve error propogation (Glauber Costa)
|
||||
- qcow2: fix image creation for > ~2TB images (Chris Wright)
|
||||
- hotplug: fix error handling for if= parameter (Eduardo Habkost)
|
||||
- qcow2: fix data corruption (Nolan Leake)
|
||||
- virtio: fix guest oops with 2.6.25 kernels (Rusty Russell)
|
||||
- SH4: add support for -kernel (Takashi Yoshii, Aurelien Jarno)
|
||||
- hotplug: fix closing of char devices (Jan Kiszka)
|
||||
- hotplug: remove incorrect check for device name (Eduardo Habkost)
|
||||
- enable -k on win32 (Herve Poussineau)
|
||||
- configure: use LANG=C for grep (Andreas Faerber)
|
||||
- fix VGA regression (malc)
|
||||
|
||||
version 0.10.1:
|
||||
|
||||
- virtio-net: allow masking of notifications on empty queue (Alex Williamson)
|
||||
|
@@ -670,6 +670,10 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
|
||||
|
||||
nb_available = (nb_available >> 9) + index_in_cluster;
|
||||
|
||||
if (nb_needed > nb_available) {
|
||||
nb_needed = nb_available;
|
||||
}
|
||||
|
||||
cluster_offset = 0;
|
||||
|
||||
/* seek the the l2 offset in the l1 table */
|
||||
@@ -1458,6 +1462,7 @@ static int qcow_create(const char *filename, int64_t total_size,
|
||||
const char *backing_file, int flags)
|
||||
{
|
||||
int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
|
||||
int ref_clusters;
|
||||
QCowHeader header;
|
||||
uint64_t tmp, offset;
|
||||
QCowCreateState s1, *s = &s1;
|
||||
@@ -1498,22 +1503,28 @@ static int qcow_create(const char *filename, int64_t total_size,
|
||||
offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
|
||||
|
||||
s->refcount_table = qemu_mallocz(s->cluster_size);
|
||||
s->refcount_block = qemu_mallocz(s->cluster_size);
|
||||
|
||||
s->refcount_table_offset = offset;
|
||||
header.refcount_table_offset = cpu_to_be64(offset);
|
||||
header.refcount_table_clusters = cpu_to_be32(1);
|
||||
offset += s->cluster_size;
|
||||
|
||||
s->refcount_table[0] = cpu_to_be64(offset);
|
||||
s->refcount_block_offset = offset;
|
||||
offset += s->cluster_size;
|
||||
|
||||
/* count how many refcount blocks needed */
|
||||
tmp = offset >> s->cluster_bits;
|
||||
ref_clusters = (tmp >> (s->cluster_bits - REFCOUNT_SHIFT)) + 1;
|
||||
for (i=0; i < ref_clusters; i++) {
|
||||
s->refcount_table[i] = cpu_to_be64(offset);
|
||||
offset += s->cluster_size;
|
||||
}
|
||||
|
||||
s->refcount_block = qemu_mallocz(ref_clusters * s->cluster_size);
|
||||
|
||||
/* update refcounts */
|
||||
create_refcount_update(s, 0, header_size);
|
||||
create_refcount_update(s, s->l1_table_offset, l1_size * sizeof(uint64_t));
|
||||
create_refcount_update(s, s->refcount_table_offset, s->cluster_size);
|
||||
create_refcount_update(s, s->refcount_block_offset, s->cluster_size);
|
||||
create_refcount_update(s, s->refcount_block_offset, ref_clusters * s->cluster_size);
|
||||
|
||||
/* write all the data */
|
||||
write(fd, &header, sizeof(header));
|
||||
@@ -1529,7 +1540,7 @@ static int qcow_create(const char *filename, int64_t total_size,
|
||||
write(fd, s->refcount_table, s->cluster_size);
|
||||
|
||||
lseek(fd, s->refcount_block_offset, SEEK_SET);
|
||||
write(fd, s->refcount_block, s->cluster_size);
|
||||
write(fd, s->refcount_block, ref_clusters * s->cluster_size);
|
||||
|
||||
qemu_free(s->refcount_table);
|
||||
qemu_free(s->refcount_block);
|
||||
@@ -2590,6 +2601,31 @@ static void dump_refcounts(BlockDriverState *bs)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int qcow_put_buffer(BlockDriverState *bs, const uint8_t *buf,
|
||||
int64_t pos, int size)
|
||||
{
|
||||
int growable = bs->growable;
|
||||
|
||||
bs->growable = 1;
|
||||
bdrv_pwrite(bs, pos, buf, size);
|
||||
bs->growable = growable;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int qcow_get_buffer(BlockDriverState *bs, uint8_t *buf,
|
||||
int64_t pos, int size)
|
||||
{
|
||||
int growable = bs->growable;
|
||||
int ret;
|
||||
|
||||
bs->growable = 1;
|
||||
ret = bdrv_pread(bs, pos, buf, size);
|
||||
bs->growable = growable;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BlockDriver bdrv_qcow2 = {
|
||||
"qcow2",
|
||||
sizeof(BDRVQcowState),
|
||||
@@ -2615,4 +2651,7 @@ BlockDriver bdrv_qcow2 = {
|
||||
.bdrv_snapshot_delete = qcow_snapshot_delete,
|
||||
.bdrv_snapshot_list = qcow_snapshot_list,
|
||||
.bdrv_get_info = qcow_get_info,
|
||||
|
||||
.bdrv_put_buffer = qcow_put_buffer,
|
||||
.bdrv_get_buffer = qcow_get_buffer,
|
||||
};
|
||||
|
@@ -399,10 +399,15 @@ static int find_device_type(BlockDriverState *bs, const char *filename)
|
||||
return FTYPE_HARDDISK;
|
||||
snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
|
||||
type = GetDriveType(s->drive_path);
|
||||
if (type == DRIVE_CDROM)
|
||||
switch (type) {
|
||||
case DRIVE_REMOVABLE:
|
||||
case DRIVE_FIXED:
|
||||
return FTYPE_HARDDISK;
|
||||
case DRIVE_CDROM:
|
||||
return FTYPE_CD;
|
||||
else
|
||||
default:
|
||||
return FTYPE_FILE;
|
||||
}
|
||||
} else {
|
||||
return FTYPE_FILE;
|
||||
}
|
||||
|
20
block.c
20
block.c
@@ -1181,6 +1181,26 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
return drv->bdrv_get_info(bs, bdi);
|
||||
}
|
||||
|
||||
int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf, int64_t pos, int size)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_put_buffer)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_put_buffer(bs, buf, pos, size);
|
||||
}
|
||||
|
||||
int bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_get_buffer)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_get_buffer(bs, buf, pos, size);
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
/* handling of snapshots */
|
||||
|
||||
|
5
block.h
5
block.h
@@ -169,4 +169,9 @@ void path_combine(char *dest, int dest_size,
|
||||
const char *base_path,
|
||||
const char *filename);
|
||||
|
||||
int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf,
|
||||
int64_t pos, int size);
|
||||
|
||||
int bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size);
|
||||
|
||||
#endif
|
||||
|
@@ -76,6 +76,11 @@ struct BlockDriver {
|
||||
QEMUSnapshotInfo **psn_info);
|
||||
int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
|
||||
|
||||
int (*bdrv_put_buffer)(BlockDriverState *bs, const uint8_t *buf,
|
||||
int64_t pos, int size);
|
||||
int (*bdrv_get_buffer)(BlockDriverState *bs, uint8_t *buf,
|
||||
int64_t pos, int size);
|
||||
|
||||
/* removable device specific */
|
||||
int (*bdrv_is_inserted)(BlockDriverState *bs);
|
||||
int (*bdrv_media_changed)(BlockDriverState *bs);
|
||||
|
2
configure
vendored
2
configure
vendored
@@ -1013,7 +1013,7 @@ EOF
|
||||
kvm="no";
|
||||
if [ -x "`which awk 2>/dev/null`" ] && \
|
||||
[ -x "`which grep 2>/dev/null`" ]; then
|
||||
kvmerr=`$cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $kvm_cflags $TMPC 2>&1 \
|
||||
kvmerr=`LANG=C $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $kvm_cflags $TMPC 2>&1 \
|
||||
| grep "error: " \
|
||||
| awk -F "error: " '{if (NR>1) printf(", "); printf("%s",$2);}'`
|
||||
if test "$kvmerr" != "" ; then
|
||||
|
1
hw/hw.h
1
hw/hw.h
@@ -67,6 +67,7 @@ unsigned int qemu_get_be32(QEMUFile *f);
|
||||
uint64_t qemu_get_be64(QEMUFile *f);
|
||||
int qemu_file_rate_limit(QEMUFile *f);
|
||||
int qemu_file_has_error(QEMUFile *f);
|
||||
void qemu_file_set_error(QEMUFile *f);
|
||||
|
||||
/* Try to send any outstanding data. This function is useful when output is
|
||||
* halted due to rate limiting or EAGAIN errors occur as it can be used to
|
||||
|
@@ -95,19 +95,22 @@ static PCIDevice *qemu_pci_hot_add_storage(PCIBus *pci_bus, const char *opts)
|
||||
type = IF_SCSI;
|
||||
else if (!strcmp(buf, "virtio")) {
|
||||
type = IF_VIRTIO;
|
||||
} else {
|
||||
term_printf("type %s not a hotpluggable PCI device.\n", buf);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
term_printf("no if= specified\n");
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (get_param_value(buf, sizeof(buf), "file", opts)) {
|
||||
drive_idx = add_init_drive(opts);
|
||||
if (drive_idx < 0)
|
||||
return NULL;
|
||||
goto out;
|
||||
} else if (type == IF_VIRTIO) {
|
||||
term_printf("virtio requires a backing file/device.\n");
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
@@ -120,10 +123,9 @@ static PCIDevice *qemu_pci_hot_add_storage(PCIBus *pci_bus, const char *opts)
|
||||
case IF_VIRTIO:
|
||||
opaque = virtio_blk_init (pci_bus, drives_table[drive_idx].bdrv);
|
||||
break;
|
||||
default:
|
||||
term_printf ("type %s not a hotpluggable PCI device.\n", buf);
|
||||
}
|
||||
|
||||
out:
|
||||
return opaque;
|
||||
}
|
||||
|
||||
|
18
hw/r2d.c
18
hw/r2d.c
@@ -37,6 +37,9 @@
|
||||
|
||||
#define SM501_VRAM_SIZE 0x800000
|
||||
|
||||
/* CONFIG_BOOT_LINK_OFFSET of Linux kernel */
|
||||
#define LINUX_LOAD_OFFSET 0x800000
|
||||
|
||||
#define PA_IRLMSK 0x00
|
||||
#define PA_POWOFF 0x30
|
||||
#define PA_VERREG 0x32
|
||||
@@ -233,20 +236,27 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size,
|
||||
pci_nic_init(pci, &nd_table[i], (i==0)? 2<<3: -1, "rtl8139");
|
||||
|
||||
/* Todo: register on board registers */
|
||||
{
|
||||
if (kernel_filename) {
|
||||
int kernel_size;
|
||||
/* initialization which should be done by firmware */
|
||||
stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
|
||||
stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
|
||||
|
||||
kernel_size = load_image(kernel_filename, phys_ram_base);
|
||||
if (kernel_cmdline) {
|
||||
kernel_size = load_image_targphys(kernel_filename,
|
||||
SDRAM_BASE + LINUX_LOAD_OFFSET,
|
||||
SDRAM_SIZE - LINUX_LOAD_OFFSET);
|
||||
env->pc = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000;
|
||||
pstrcpy_targphys(SDRAM_BASE + 0x10100, 256, kernel_cmdline);
|
||||
} else {
|
||||
kernel_size = load_image_targphys(kernel_filename, SDRAM_BASE, SDRAM_SIZE);
|
||||
env->pc = SDRAM_BASE | 0xa0000000; /* Start from P2 area */
|
||||
}
|
||||
|
||||
if (kernel_size < 0) {
|
||||
fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
env->pc = SDRAM_BASE | 0xa0000000; /* Start from P2 area */
|
||||
}
|
||||
}
|
||||
|
||||
|
12
hw/vga.c
12
hw/vga.c
@@ -1616,6 +1616,16 @@ static void vga_draw_graphic(VGAState *s, int full_update)
|
||||
s->double_scan = double_scan;
|
||||
}
|
||||
|
||||
if (shift_control == 0) {
|
||||
if (s->sr[0x01] & 8) {
|
||||
disp_width <<= 1;
|
||||
}
|
||||
} else if (shift_control == 1) {
|
||||
if (s->sr[0x01] & 8) {
|
||||
disp_width <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
depth = s->get_bpp(s);
|
||||
if (s->line_offset != s->last_line_offset ||
|
||||
disp_width != s->last_width ||
|
||||
@@ -1661,7 +1671,6 @@ static void vga_draw_graphic(VGAState *s, int full_update)
|
||||
full_update |= update_palette16(s);
|
||||
if (s->sr[0x01] & 8) {
|
||||
v = VGA_DRAW_LINE4D2;
|
||||
disp_width <<= 1;
|
||||
} else {
|
||||
v = VGA_DRAW_LINE4;
|
||||
}
|
||||
@@ -1670,7 +1679,6 @@ static void vga_draw_graphic(VGAState *s, int full_update)
|
||||
full_update |= update_palette16(s);
|
||||
if (s->sr[0x01] & 8) {
|
||||
v = VGA_DRAW_LINE2D2;
|
||||
disp_width <<= 1;
|
||||
} else {
|
||||
v = VGA_DRAW_LINE2;
|
||||
}
|
||||
|
@@ -113,6 +113,21 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev)
|
||||
return features;
|
||||
}
|
||||
|
||||
static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
|
||||
{
|
||||
uint32_t features = 0;
|
||||
|
||||
/* Linux kernel 2.6.25. It understood MAC (as everyone must),
|
||||
* but also these: */
|
||||
features |= (1 << VIRTIO_NET_F_MAC);
|
||||
features |= (1 << VIRTIO_NET_F_GUEST_CSUM);
|
||||
features |= (1 << VIRTIO_NET_F_GUEST_TSO4);
|
||||
features |= (1 << VIRTIO_NET_F_GUEST_TSO6);
|
||||
features |= (1 << VIRTIO_NET_F_GUEST_ECN);
|
||||
|
||||
return features & virtio_net_get_features(vdev);
|
||||
}
|
||||
|
||||
static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
|
||||
{
|
||||
VirtIONet *n = to_virtio_net(vdev);
|
||||
@@ -580,6 +595,7 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
n->vdev.set_config = virtio_net_set_config;
|
||||
n->vdev.get_features = virtio_net_get_features;
|
||||
n->vdev.set_features = virtio_net_set_features;
|
||||
n->vdev.bad_features = virtio_net_bad_features;
|
||||
n->vdev.reset = virtio_net_reset;
|
||||
n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
|
||||
n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx);
|
||||
|
@@ -516,6 +516,13 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
|
||||
switch (addr) {
|
||||
case VIRTIO_PCI_GUEST_FEATURES:
|
||||
/* Guest does not negotiate properly? We have to assume nothing. */
|
||||
if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
|
||||
if (vdev->bad_features)
|
||||
val = vdev->bad_features(vdev);
|
||||
else
|
||||
val = 0;
|
||||
}
|
||||
if (vdev->set_features)
|
||||
vdev->set_features(vdev, val);
|
||||
vdev->features = val;
|
||||
@@ -555,7 +562,7 @@ static uint32_t virtio_ioport_read(void *opaque, uint32_t addr)
|
||||
switch (addr) {
|
||||
case VIRTIO_PCI_HOST_FEATURES:
|
||||
ret = vdev->get_features(vdev);
|
||||
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY) | (1 << VIRTIO_F_BAD_FEATURE);
|
||||
break;
|
||||
case VIRTIO_PCI_GUEST_FEATURES:
|
||||
ret = vdev->features;
|
||||
|
@@ -32,6 +32,8 @@
|
||||
/* We notify when the ring is completely used, even if the guest is supressing
|
||||
* callbacks */
|
||||
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
|
||||
/* A guest should never accept this. It implies negotiation is broken. */
|
||||
#define VIRTIO_F_BAD_FEATURE 30
|
||||
|
||||
/* from Linux's linux/virtio_ring.h */
|
||||
|
||||
@@ -82,6 +84,7 @@ struct VirtIODevice
|
||||
size_t config_len;
|
||||
void *config;
|
||||
uint32_t (*get_features)(VirtIODevice *vdev);
|
||||
uint32_t (*bad_features)(VirtIODevice *vdev);
|
||||
void (*set_features)(VirtIODevice *vdev, uint32_t val);
|
||||
void (*get_config)(VirtIODevice *vdev, uint8_t *config);
|
||||
void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
|
||||
|
3
loader.c
3
loader.c
@@ -90,11 +90,12 @@ int fread_targphys(target_phys_addr_t dst_addr, size_t nbytes, FILE *f)
|
||||
while (nbytes) {
|
||||
want = nbytes > sizeof(buf) ? sizeof(buf) : nbytes;
|
||||
did = fread(buf, 1, want, f);
|
||||
if (did != want) break;
|
||||
|
||||
cpu_physical_memory_write_rom(dst_addr, buf, did);
|
||||
dst_addr += did;
|
||||
nbytes -= did;
|
||||
if (did != want)
|
||||
break;
|
||||
}
|
||||
return dst_addr - dst_begin;
|
||||
}
|
||||
|
10
migration.c
10
migration.c
@@ -212,13 +212,19 @@ void migrate_fd_put_ready(void *opaque)
|
||||
|
||||
dprintf("iterate\n");
|
||||
if (qemu_savevm_state_iterate(s->file) == 1) {
|
||||
int state;
|
||||
dprintf("done iterating\n");
|
||||
vm_stop(0);
|
||||
|
||||
bdrv_flush_all();
|
||||
qemu_savevm_state_complete(s->file);
|
||||
s->state = MIG_STATE_COMPLETED;
|
||||
if ((qemu_savevm_state_complete(s->file)) < 0) {
|
||||
vm_start();
|
||||
state = MIG_STATE_ERROR;
|
||||
} else {
|
||||
state = MIG_STATE_COMPLETED;
|
||||
}
|
||||
migrate_fd_cleanup(s);
|
||||
s->state = state;
|
||||
}
|
||||
}
|
||||
|
||||
|
5
net.c
5
net.c
@@ -1818,11 +1818,6 @@ void net_host_device_remove(int vlan_id, const char *device)
|
||||
VLANState *vlan;
|
||||
VLANClientState *vc;
|
||||
|
||||
if (!net_host_check_device(device)) {
|
||||
term_printf("invalid host network device %s\n", device);
|
||||
return;
|
||||
}
|
||||
|
||||
vlan = qemu_find_vlan(vlan_id);
|
||||
if (!vlan) {
|
||||
term_printf("can't find vlan %d\n", vlan_id);
|
||||
|
21
qemu-char.c
21
qemu-char.c
@@ -917,6 +917,8 @@ static void pty_chr_close(struct CharDriverState *chr)
|
||||
|
||||
qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
|
||||
close(s->fd);
|
||||
qemu_del_timer(s->timer);
|
||||
qemu_free_timer(s->timer);
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
@@ -1746,6 +1748,16 @@ static void udp_chr_update_read_handler(CharDriverState *chr)
|
||||
}
|
||||
}
|
||||
|
||||
static void udp_chr_close(CharDriverState *chr)
|
||||
{
|
||||
NetCharDriver *s = chr->opaque;
|
||||
if (s->fd >= 0) {
|
||||
qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
|
||||
closesocket(s->fd);
|
||||
}
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
static CharDriverState *qemu_chr_open_udp(const char *def)
|
||||
{
|
||||
CharDriverState *chr = NULL;
|
||||
@@ -1779,6 +1791,7 @@ static CharDriverState *qemu_chr_open_udp(const char *def)
|
||||
chr->opaque = s;
|
||||
chr->chr_write = udp_chr_write;
|
||||
chr->chr_update_read_handler = udp_chr_update_read_handler;
|
||||
chr->chr_close = udp_chr_close;
|
||||
return chr;
|
||||
|
||||
return_err:
|
||||
@@ -1981,10 +1994,14 @@ static void tcp_chr_accept(void *opaque)
|
||||
static void tcp_chr_close(CharDriverState *chr)
|
||||
{
|
||||
TCPCharDriver *s = chr->opaque;
|
||||
if (s->fd >= 0)
|
||||
if (s->fd >= 0) {
|
||||
qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
|
||||
closesocket(s->fd);
|
||||
if (s->listen_fd >= 0)
|
||||
}
|
||||
if (s->listen_fd >= 0) {
|
||||
qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
|
||||
closesocket(s->listen_fd);
|
||||
}
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
|
17
savevm.c
17
savevm.c
@@ -306,18 +306,18 @@ typedef struct QEMUFileBdrv
|
||||
int64_t base_offset;
|
||||
} QEMUFileBdrv;
|
||||
|
||||
static int bdrv_put_buffer(void *opaque, const uint8_t *buf,
|
||||
static int block_put_buffer(void *opaque, const uint8_t *buf,
|
||||
int64_t pos, int size)
|
||||
{
|
||||
QEMUFileBdrv *s = opaque;
|
||||
bdrv_pwrite(s->bs, s->base_offset + pos, buf, size);
|
||||
bdrv_put_buffer(s->bs, buf, s->base_offset + pos, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static int bdrv_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
|
||||
static int block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
|
||||
{
|
||||
QEMUFileBdrv *s = opaque;
|
||||
return bdrv_pread(s->bs, s->base_offset + pos, buf, size);
|
||||
return bdrv_get_buffer(s->bs, buf, s->base_offset + pos, size);
|
||||
}
|
||||
|
||||
static int bdrv_fclose(void *opaque)
|
||||
@@ -337,9 +337,9 @@ static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int64_t offset, int is_wr
|
||||
s->base_offset = offset;
|
||||
|
||||
if (is_writable)
|
||||
return qemu_fopen_ops(s, bdrv_put_buffer, NULL, bdrv_fclose, NULL);
|
||||
return qemu_fopen_ops(s, block_put_buffer, NULL, bdrv_fclose, NULL);
|
||||
|
||||
return qemu_fopen_ops(s, NULL, bdrv_get_buffer, bdrv_fclose, NULL);
|
||||
return qemu_fopen_ops(s, NULL, block_get_buffer, bdrv_fclose, NULL);
|
||||
}
|
||||
|
||||
QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
|
||||
@@ -366,6 +366,11 @@ int qemu_file_has_error(QEMUFile *f)
|
||||
return f->has_error;
|
||||
}
|
||||
|
||||
void qemu_file_set_error(QEMUFile *f)
|
||||
{
|
||||
f->has_error = 1;
|
||||
}
|
||||
|
||||
void qemu_fflush(QEMUFile *f)
|
||||
{
|
||||
if (!f->put_buffer)
|
||||
|
4
vl.c
4
vl.c
@@ -3220,10 +3220,10 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque)
|
||||
/* try transferring iterative blocks of memory */
|
||||
|
||||
if (stage == 3) {
|
||||
cpu_physical_memory_set_dirty_tracking(0);
|
||||
|
||||
/* flush all remaining blocks regardless of rate limiting */
|
||||
while (ram_save_block(f) != 0);
|
||||
cpu_physical_memory_set_dirty_tracking(0);
|
||||
}
|
||||
|
||||
qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
|
||||
@@ -4244,9 +4244,7 @@ static const QEMUOption qemu_options[] = {
|
||||
{ "boot", HAS_ARG, QEMU_OPTION_boot },
|
||||
{ "snapshot", 0, QEMU_OPTION_snapshot },
|
||||
{ "m", HAS_ARG, QEMU_OPTION_m },
|
||||
#ifndef _WIN32
|
||||
{ "k", HAS_ARG, QEMU_OPTION_k },
|
||||
#endif
|
||||
#ifdef HAS_AUDIO
|
||||
{ "audio-help", 0, QEMU_OPTION_audio_help },
|
||||
{ "soundhw", HAS_ARG, QEMU_OPTION_soundhw },
|
||||
|
Reference in New Issue
Block a user