Compare commits
53 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6173d56bdc | ||
|
f39942d217 | ||
|
5dde87088f | ||
|
3fa017e24b | ||
|
35924dbe8c | ||
|
88aa905668 | ||
|
b93c5c84c8 | ||
|
f203baee5b | ||
|
5e3be62385 | ||
|
b391493bc6 | ||
|
57f9f4c9f5 | ||
|
7ebc79037c | ||
|
ea299062eb | ||
|
e03dd1a6c2 | ||
|
535d2eb34a | ||
|
beb8eab90c | ||
|
8d67694fbf | ||
|
02510b2436 | ||
|
b57a2297f2 | ||
|
43fab08210 | ||
|
915080e6b1 | ||
|
9f59ddcc4f | ||
|
999ceb2c1d | ||
|
307331a42a | ||
|
6728dd464b | ||
|
bb45bcc8de | ||
|
096109c804 | ||
|
7ae1fcc88c | ||
|
299e0bc52a | ||
|
74f0529e24 | ||
|
614971158c | ||
|
afa328b1b2 | ||
|
868dab5dc2 | ||
|
29bb3bf350 | ||
|
dbf45b44b7 | ||
|
d0d888bc6d | ||
|
19abbad0da | ||
|
f48aba6de7 | ||
|
cb2ae96bf6 | ||
|
848f874ca1 | ||
|
a1a86bf902 | ||
|
c727a05459 | ||
|
eb05143e24 | ||
|
0c709e6195 | ||
|
dc88aa49b4 | ||
|
dc2ffbf6d8 | ||
|
d3bf9367f2 | ||
|
c502715a74 | ||
|
b9a61d2154 | ||
|
9525204c5d | ||
|
f79d556b4f | ||
|
41ae9ece21 | ||
|
40480d2bf4 |
52
Changelog
52
Changelog
@@ -1,3 +1,55 @@
|
||||
version 0.12.3
|
||||
- kvm: Fix eflags corruption in kvm mode (Jan Kiszka)
|
||||
- qcow2: Fix access after end of array (Kevin Wolf)
|
||||
- ide save/restore pio/atapi cmd transfer fields and io buffer (Marcelo Tosatti)
|
||||
- net: Monitor command set_link finds only VLAN clients, fix (Markus Armbruster)
|
||||
- net: info network shows only VLAN clients, fix (Markus Armbruster)
|
||||
- net: net_check_clients() checks only VLAN clients, fix (Markus Armbruster)
|
||||
- net: Fix bogus "Warning: vlan 0 with no nics" with -device (Markus Armbruster)
|
||||
- net: net_check_clients() runs too early to see -device, fix (Markus Armbruster)
|
||||
- net: Remove unused net_client_uninit() (Markus Armbruster)
|
||||
- don't dereference NULL after failed strdup (Jim Meyering)
|
||||
- virtio-net: fix network stall under load (Tom Lendacky)
|
||||
- json: fix PRId64 on Win32 (Roy Tam)
|
||||
- fix inet_parse typo (Marcelo Tosatti)
|
||||
- iothread: fix vcpu stop with smp tcg (Marcelo Tosatti)
|
||||
- segfault due to buffer overrun in usb-serial (David S. Ahern)
|
||||
- qcow2: Fix signedness bugs (Kevin Wolf)
|
||||
- Do not ignore error, if open file failed (-serial /dev/tty) (Evgeniy Dushistov)
|
||||
- pc-bios: update to newer version of (stable) seabios (Anthony Liguori)
|
||||
- target-mips: fix ROTR and DROTR by zero (Aurelien Jarno)
|
||||
- target-mips: fix CpU exception for coprocessor 0 (Nathan Froyd)
|
||||
- tcg/mips: fix crash in tcg_out_qemu_ld() (Aurelien Jarno)
|
||||
- target-mips: don't call cpu_loop_exit() from helper.c (Aurelien Jarno)
|
||||
- virtio-blk: Fix error cases which ignored rerror/werror (Kevin Wolf)
|
||||
- virtio-blk: Fix restart after read error (Kevin Wolf)
|
||||
- virtio_blk: Factor virtio_blk_handle_request out (Kevin Wolf)
|
||||
- cirrus: Properly re-register cirrus_linear_io_addr on vram unmap (Jan Kiszka)
|
||||
- qcow2: Don't ignore qcow2_alloc_clusters return value (Kevin Wolf)
|
||||
- qcow2: Don't ignore update_refcount return value (Kevin Wolf)
|
||||
- qcow2: Allow updating no refcounts (Kevin Wolf)
|
||||
- qcow2: Improve error handling in update_refcount (Kevin Wolf)
|
||||
- qcow2: Fix error handling in grow_refcount_table (Kevin Wolf)
|
||||
- block: Return original error codes in bdrv_pread/write (Kevin Wolf)
|
||||
- qcow2: Return 0/-errno in qcow2_alloc_cluster_offset (Kevin Wolf)
|
||||
- qcow2: Return 0/-errno in get_cluster_table (Kevin Wolf)
|
||||
- qcow2: Fix error handling in qcow_save_vmstate (Kevin Wolf)
|
||||
- qcow2: Fix error handling in qcow2_grow_l1_table (Kevin Wolf)
|
||||
- win32/sdl: Fix toggle full screen (Herve Poussineau)
|
||||
- win32: pair qemu_memalign() with qemu_vfree() (Herve Poussineau)
|
||||
- vnc_refresh: calling vnc_update_client might free vs (Stefano Stabellini)
|
||||
- Musicpal: Fix descriptor walk in eth_send (Jan Kiszka)
|
||||
- Musicpal: Fix wm8750 I2C address (Jan Kiszka)
|
||||
- fix savevm command without id or tag (Marcelo Tosatti)
|
||||
- reduce number of reinjects on ACK (Gleb Natapov)
|
||||
- QMP: Fix asynchronous events delivery (Luiz Capitulino)
|
||||
- Documentation: Add missing documentation for qdev related command line options (Stefan Weil)
|
||||
- pc: add driver version compat properties (Gerd Hoffmann)
|
||||
- scsi: device version property (Gerd Hoffmann)
|
||||
- ide: device version property (Gerd Hoffmann)
|
||||
- QMP: Emit asynchronous events on all QMP monitors (Adam Litke)
|
||||
- Fix QEMU_WARN_UNUSED_RESULT (Kevin Wolf)
|
||||
|
||||
version 0.12.2:
|
||||
- Qemu's internal TFTP server breaks lock-step-iness of TFTP (Milan Plzik)
|
||||
- osdep.c: Fix accept4 fallback (Kevin Wolf)
|
||||
|
36
block.c
36
block.c
@@ -691,6 +691,7 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
|
||||
uint8_t tmp_buf[BDRV_SECTOR_SIZE];
|
||||
int len, nb_sectors, count;
|
||||
int64_t sector_num;
|
||||
int ret;
|
||||
|
||||
count = count1;
|
||||
/* first read to align to sector start */
|
||||
@@ -699,8 +700,8 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
|
||||
len = count;
|
||||
sector_num = offset >> BDRV_SECTOR_BITS;
|
||||
if (len > 0) {
|
||||
if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
|
||||
return -EIO;
|
||||
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
|
||||
return ret;
|
||||
memcpy(buf, tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), len);
|
||||
count -= len;
|
||||
if (count == 0)
|
||||
@@ -712,8 +713,8 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
|
||||
/* read the sectors "in place" */
|
||||
nb_sectors = count >> BDRV_SECTOR_BITS;
|
||||
if (nb_sectors > 0) {
|
||||
if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)
|
||||
return -EIO;
|
||||
if ((ret = bdrv_read(bs, sector_num, buf, nb_sectors)) < 0)
|
||||
return ret;
|
||||
sector_num += nb_sectors;
|
||||
len = nb_sectors << BDRV_SECTOR_BITS;
|
||||
buf += len;
|
||||
@@ -722,8 +723,8 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
/* add data from the last sector */
|
||||
if (count > 0) {
|
||||
if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
|
||||
return -EIO;
|
||||
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
|
||||
return ret;
|
||||
memcpy(buf, tmp_buf, count);
|
||||
}
|
||||
return count1;
|
||||
@@ -735,6 +736,7 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
|
||||
uint8_t tmp_buf[BDRV_SECTOR_SIZE];
|
||||
int len, nb_sectors, count;
|
||||
int64_t sector_num;
|
||||
int ret;
|
||||
|
||||
count = count1;
|
||||
/* first write to align to sector start */
|
||||
@@ -743,11 +745,11 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
|
||||
len = count;
|
||||
sector_num = offset >> BDRV_SECTOR_BITS;
|
||||
if (len > 0) {
|
||||
if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
|
||||
return -EIO;
|
||||
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
|
||||
return ret;
|
||||
memcpy(tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), buf, len);
|
||||
if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
|
||||
return -EIO;
|
||||
if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
|
||||
return ret;
|
||||
count -= len;
|
||||
if (count == 0)
|
||||
return count1;
|
||||
@@ -758,8 +760,8 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
|
||||
/* write the sectors "in place" */
|
||||
nb_sectors = count >> BDRV_SECTOR_BITS;
|
||||
if (nb_sectors > 0) {
|
||||
if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)
|
||||
return -EIO;
|
||||
if ((ret = bdrv_write(bs, sector_num, buf, nb_sectors)) < 0)
|
||||
return ret;
|
||||
sector_num += nb_sectors;
|
||||
len = nb_sectors << BDRV_SECTOR_BITS;
|
||||
buf += len;
|
||||
@@ -768,11 +770,11 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
/* add data from the last sector */
|
||||
if (count > 0) {
|
||||
if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
|
||||
return -EIO;
|
||||
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
|
||||
return ret;
|
||||
memcpy(tmp_buf, buf, count);
|
||||
if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
|
||||
return -EIO;
|
||||
if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
|
||||
return ret;
|
||||
}
|
||||
return count1;
|
||||
}
|
||||
@@ -1607,7 +1609,7 @@ static void multiwrite_user_cb(MultiwriteCB *mcb)
|
||||
for (i = 0; i < mcb->num_callbacks; i++) {
|
||||
mcb->callbacks[i].cb(mcb->callbacks[i].opaque, mcb->error);
|
||||
qemu_free(mcb->callbacks[i].free_qiov);
|
||||
qemu_free(mcb->callbacks[i].free_buf);
|
||||
qemu_vfree(mcb->callbacks[i].free_buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -309,7 +309,7 @@ static int curl_open(BlockDriverState *bs, const char *filename, int flags)
|
||||
|
||||
static int inited = 0;
|
||||
|
||||
file = strdup(filename);
|
||||
file = qemu_strdup(filename);
|
||||
s->readahead_size = READ_AHEAD_SIZE;
|
||||
|
||||
/* Parse a trailing ":readahead=#:" param, if present. */
|
||||
|
@@ -33,7 +33,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
int new_l1_size, new_l1_size2, ret, i;
|
||||
uint64_t *new_l1_table;
|
||||
uint64_t new_l1_table_offset;
|
||||
int64_t new_l1_table_offset;
|
||||
uint8_t data[12];
|
||||
|
||||
new_l1_size = s->l1_size;
|
||||
@@ -55,6 +55,10 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
|
||||
|
||||
/* write new table (align to cluster) */
|
||||
new_l1_table_offset = qcow2_alloc_clusters(bs, new_l1_size2);
|
||||
if (new_l1_table_offset < 0) {
|
||||
qemu_free(new_l1_table);
|
||||
return new_l1_table_offset;
|
||||
}
|
||||
|
||||
for(i = 0; i < s->l1_size; i++)
|
||||
new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
|
||||
@@ -67,9 +71,10 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
|
||||
/* set new table */
|
||||
cpu_to_be32w((uint32_t*)data, new_l1_size);
|
||||
cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset);
|
||||
if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,
|
||||
sizeof(data)) != sizeof(data))
|
||||
ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,sizeof(data));
|
||||
if (ret != sizeof(data)) {
|
||||
goto fail;
|
||||
}
|
||||
qemu_free(s->l1_table);
|
||||
qcow2_free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t));
|
||||
s->l1_table_offset = new_l1_table_offset;
|
||||
@@ -77,8 +82,9 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
|
||||
s->l1_size = new_l1_size;
|
||||
return 0;
|
||||
fail:
|
||||
qemu_free(s->l1_table);
|
||||
return -EIO;
|
||||
qemu_free(new_l1_table);
|
||||
qcow2_free_clusters(bs, new_l1_table_offset, new_l1_size2);
|
||||
return ret < 0 ? ret : -EIO;
|
||||
}
|
||||
|
||||
void qcow2_l2_cache_reset(BlockDriverState *bs)
|
||||
@@ -213,13 +219,17 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
int min_index;
|
||||
uint64_t old_l2_offset;
|
||||
uint64_t *l2_table, l2_offset;
|
||||
uint64_t *l2_table;
|
||||
int64_t l2_offset;
|
||||
|
||||
old_l2_offset = s->l1_table[l1_index];
|
||||
|
||||
/* allocate a new l2 entry */
|
||||
|
||||
l2_offset = qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
|
||||
if (l2_offset < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* update the L1 entry */
|
||||
|
||||
@@ -479,8 +489,8 @@ out:
|
||||
* the l2 table offset in the qcow2 file and the cluster index
|
||||
* in the l2 table are given to the caller.
|
||||
*
|
||||
* Returns 0 on success, -errno in failure case
|
||||
*/
|
||||
|
||||
static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
|
||||
uint64_t **new_l2_table,
|
||||
uint64_t *new_l2_offset,
|
||||
@@ -496,8 +506,9 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
|
||||
l1_index = offset >> (s->l2_bits + s->cluster_bits);
|
||||
if (l1_index >= s->l1_size) {
|
||||
ret = qcow2_grow_l1_table(bs, l1_index + 1);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
l2_offset = s->l1_table[l1_index];
|
||||
|
||||
@@ -507,14 +518,16 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
|
||||
/* load the l2 table in memory */
|
||||
l2_offset &= ~QCOW_OFLAG_COPIED;
|
||||
l2_table = l2_load(bs, l2_offset);
|
||||
if (l2_table == NULL)
|
||||
return 0;
|
||||
if (l2_table == NULL) {
|
||||
return -EIO;
|
||||
}
|
||||
} else {
|
||||
if (l2_offset)
|
||||
qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
|
||||
l2_table = l2_allocate(bs, l1_index);
|
||||
if (l2_table == NULL)
|
||||
return 0;
|
||||
if (l2_table == NULL) {
|
||||
return -EIO;
|
||||
}
|
||||
l2_offset = s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED;
|
||||
}
|
||||
|
||||
@@ -526,7 +539,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
|
||||
*new_l2_offset = l2_offset;
|
||||
*new_l2_index = l2_index;
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -548,12 +561,14 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
int l2_index, ret;
|
||||
uint64_t l2_offset, *l2_table, cluster_offset;
|
||||
uint64_t l2_offset, *l2_table;
|
||||
int64_t cluster_offset;
|
||||
int nb_csectors;
|
||||
|
||||
ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
|
||||
if (ret == 0)
|
||||
if (ret < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cluster_offset = be64_to_cpu(l2_table[l2_index]);
|
||||
if (cluster_offset & QCOW_OFLAG_COPIED)
|
||||
@@ -563,6 +578,10 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
|
||||
qcow2_free_any_clusters(bs, cluster_offset, 1);
|
||||
|
||||
cluster_offset = qcow2_alloc_bytes(bs, compressed_size);
|
||||
if (cluster_offset < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) -
|
||||
(cluster_offset >> 9);
|
||||
|
||||
@@ -605,12 +624,12 @@ static int write_l2_entries(BDRVQcowState *s, uint64_t *l2_table,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, uint64_t cluster_offset,
|
||||
QCowL2Meta *m)
|
||||
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
int i, j = 0, l2_index, ret;
|
||||
uint64_t *old_cluster, start_sect, l2_offset, *l2_table;
|
||||
uint64_t cluster_offset = m->cluster_offset;
|
||||
|
||||
if (m->nb_clusters == 0)
|
||||
return 0;
|
||||
@@ -633,10 +652,11 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, uint64_t cluster_offset,
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = -EIO;
|
||||
/* update L2 table */
|
||||
if (!get_cluster_table(bs, m->offset, &l2_table, &l2_offset, &l2_index))
|
||||
ret = get_cluster_table(bs, m->offset, &l2_table, &l2_offset, &l2_index);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < m->nb_clusters; i++) {
|
||||
/* if two concurrent writes happen to the same unallocated cluster
|
||||
@@ -670,30 +690,36 @@ err:
|
||||
/*
|
||||
* alloc_cluster_offset
|
||||
*
|
||||
* For a given offset of the disk image, return cluster offset in
|
||||
* qcow2 file.
|
||||
*
|
||||
* For a given offset of the disk image, return cluster offset in qcow2 file.
|
||||
* If the offset is not found, allocate a new cluster.
|
||||
*
|
||||
* Return the cluster offset if successful,
|
||||
* Return 0, otherwise.
|
||||
* If the cluster was already allocated, m->nb_clusters is set to 0,
|
||||
* m->depends_on is set to NULL and the other fields in m are meaningless.
|
||||
*
|
||||
* If the cluster is newly allocated, m->nb_clusters is set to the number of
|
||||
* contiguous clusters that have been allocated. This may be 0 if the request
|
||||
* conflict with another write request in flight; in this case, m->depends_on
|
||||
* is set and the remaining fields of m are meaningless.
|
||||
*
|
||||
* If m->nb_clusters is non-zero, the other fields of m are valid and contain
|
||||
* information about the first allocated cluster.
|
||||
*
|
||||
* Return 0 on success and -errno in error cases
|
||||
*/
|
||||
|
||||
uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
|
||||
uint64_t offset,
|
||||
int n_start, int n_end,
|
||||
int *num, QCowL2Meta *m)
|
||||
int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
||||
int n_start, int n_end, int *num, QCowL2Meta *m)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
int l2_index, ret;
|
||||
uint64_t l2_offset, *l2_table, cluster_offset;
|
||||
uint64_t l2_offset, *l2_table;
|
||||
int64_t cluster_offset;
|
||||
unsigned int nb_clusters, i = 0;
|
||||
QCowL2Meta *old_alloc;
|
||||
|
||||
ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
nb_clusters = size_to_clusters(s, n_end << 9);
|
||||
|
||||
@@ -709,6 +735,7 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
|
||||
|
||||
cluster_offset &= ~QCOW_OFLAG_COPIED;
|
||||
m->nb_clusters = 0;
|
||||
m->depends_on = NULL;
|
||||
|
||||
goto out;
|
||||
}
|
||||
@@ -723,12 +750,15 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
|
||||
while (i < nb_clusters) {
|
||||
i += count_contiguous_clusters(nb_clusters - i, s->cluster_size,
|
||||
&l2_table[l2_index], i, 0);
|
||||
|
||||
if(be64_to_cpu(l2_table[l2_index + i]))
|
||||
if ((i >= nb_clusters) || be64_to_cpu(l2_table[l2_index + i])) {
|
||||
break;
|
||||
}
|
||||
|
||||
i += count_contiguous_free_clusters(nb_clusters - i,
|
||||
&l2_table[l2_index + i]);
|
||||
if (i >= nb_clusters) {
|
||||
break;
|
||||
}
|
||||
|
||||
cluster_offset = be64_to_cpu(l2_table[l2_index + i]);
|
||||
|
||||
@@ -736,6 +766,7 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
|
||||
(cluster_offset & QCOW_OFLAG_COMPRESSED))
|
||||
break;
|
||||
}
|
||||
assert(i <= nb_clusters);
|
||||
nb_clusters = i;
|
||||
|
||||
/*
|
||||
@@ -779,6 +810,9 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
|
||||
/* allocate a new cluster */
|
||||
|
||||
cluster_offset = qcow2_alloc_clusters(bs, nb_clusters * s->cluster_size);
|
||||
if (cluster_offset < 0) {
|
||||
return cluster_offset;
|
||||
}
|
||||
|
||||
/* save info needed for meta data update */
|
||||
m->offset = offset;
|
||||
@@ -787,10 +821,11 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
|
||||
|
||||
out:
|
||||
m->nb_available = MIN(nb_clusters << (s->cluster_bits - 9), n_end);
|
||||
m->cluster_offset = cluster_offset;
|
||||
|
||||
*num = m->nb_available - n_start;
|
||||
|
||||
return cluster_offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
|
||||
|
@@ -168,9 +168,12 @@ static int grow_refcount_table(BlockDriverState *bs, int min_size)
|
||||
|
||||
cpu_to_be64w((uint64_t*)data, table_offset);
|
||||
cpu_to_be32w((uint32_t*)(data + 8), refcount_table_clusters);
|
||||
if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
|
||||
data, sizeof(data)) != sizeof(data))
|
||||
ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
|
||||
data, sizeof(data));
|
||||
if (ret != sizeof(data)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
qemu_free(s->refcount_table);
|
||||
old_table_offset = s->refcount_table_offset;
|
||||
old_table_size = s->refcount_table_size;
|
||||
@@ -183,7 +186,7 @@ static int grow_refcount_table(BlockDriverState *bs, int min_size)
|
||||
return 0;
|
||||
fail:
|
||||
qemu_free(new_table);
|
||||
return -EIO;
|
||||
return ret < 0 ? ret : -EIO;
|
||||
}
|
||||
|
||||
|
||||
@@ -266,22 +269,26 @@ static int write_refcount_block_entries(BDRVQcowState *s,
|
||||
}
|
||||
|
||||
/* XXX: cache several refcount block clusters ? */
|
||||
static int update_refcount(BlockDriverState *bs,
|
||||
int64_t offset, int64_t length,
|
||||
int addend)
|
||||
static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
|
||||
int64_t offset, int64_t length, int addend)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
int64_t start, last, cluster_offset;
|
||||
int64_t refcount_block_offset = 0;
|
||||
int64_t table_index = -1, old_table_index;
|
||||
int first_index = -1, last_index = -1;
|
||||
int ret;
|
||||
|
||||
#ifdef DEBUG_ALLOC2
|
||||
printf("update_refcount: offset=%" PRId64 " size=%" PRId64 " addend=%d\n",
|
||||
offset, length, addend);
|
||||
#endif
|
||||
if (length <= 0)
|
||||
if (length < 0) {
|
||||
return -EINVAL;
|
||||
} else if (length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
start = offset & ~(s->cluster_size - 1);
|
||||
last = (offset + length - 1) & ~(s->cluster_size - 1);
|
||||
for(cluster_offset = start; cluster_offset <= last;
|
||||
@@ -289,6 +296,7 @@ static int update_refcount(BlockDriverState *bs,
|
||||
{
|
||||
int block_index, refcount;
|
||||
int64_t cluster_index = cluster_offset >> s->cluster_bits;
|
||||
int64_t new_block;
|
||||
|
||||
/* Only write refcount block to disk when we are done with it */
|
||||
old_table_index = table_index;
|
||||
@@ -306,10 +314,12 @@ static int update_refcount(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
/* Load the refcount block and allocate it if needed */
|
||||
refcount_block_offset = alloc_refcount_block(bs, cluster_index);
|
||||
if (refcount_block_offset < 0) {
|
||||
return refcount_block_offset;
|
||||
new_block = alloc_refcount_block(bs, cluster_index);
|
||||
if (new_block < 0) {
|
||||
ret = new_block;
|
||||
goto fail;
|
||||
}
|
||||
refcount_block_offset = new_block;
|
||||
|
||||
/* we can update the count and save it */
|
||||
block_index = cluster_index &
|
||||
@@ -323,24 +333,38 @@ static int update_refcount(BlockDriverState *bs,
|
||||
|
||||
refcount = be16_to_cpu(s->refcount_block_cache[block_index]);
|
||||
refcount += addend;
|
||||
if (refcount < 0 || refcount > 0xffff)
|
||||
return -EINVAL;
|
||||
if (refcount < 0 || refcount > 0xffff) {
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
if (refcount == 0 && cluster_index < s->free_cluster_index) {
|
||||
s->free_cluster_index = cluster_index;
|
||||
}
|
||||
s->refcount_block_cache[block_index] = cpu_to_be16(refcount);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
|
||||
/* Write last changed block to disk */
|
||||
if (refcount_block_offset != 0) {
|
||||
if (write_refcount_block_entries(s, refcount_block_offset,
|
||||
first_index, last_index) < 0)
|
||||
{
|
||||
return -EIO;
|
||||
return ret < 0 ? ret : -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
/*
|
||||
* Try do undo any updates if an error is returned (This may succeed in
|
||||
* some cases like ENOSPC for allocating a new refcount block)
|
||||
*/
|
||||
if (ret < 0) {
|
||||
int dummy;
|
||||
dummy = update_refcount(bs, offset, cluster_offset - offset, -addend);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* addend must be 1 or -1 */
|
||||
@@ -390,9 +414,13 @@ retry:
|
||||
int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
|
||||
{
|
||||
int64_t offset;
|
||||
int ret;
|
||||
|
||||
offset = alloc_clusters_noref(bs, size);
|
||||
update_refcount(bs, offset, size, 1);
|
||||
ret = update_refcount(bs, offset, size, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
@@ -407,6 +435,9 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
|
||||
assert(size > 0 && size <= s->cluster_size);
|
||||
if (s->free_byte_offset == 0) {
|
||||
s->free_byte_offset = qcow2_alloc_clusters(bs, s->cluster_size);
|
||||
if (s->free_byte_offset < 0) {
|
||||
return s->free_byte_offset;
|
||||
}
|
||||
}
|
||||
redo:
|
||||
free_in_cluster = s->cluster_size -
|
||||
@@ -422,6 +453,9 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
|
||||
update_cluster_refcount(bs, offset >> s->cluster_bits, 1);
|
||||
} else {
|
||||
offset = qcow2_alloc_clusters(bs, s->cluster_size);
|
||||
if (offset < 0) {
|
||||
return offset;
|
||||
}
|
||||
cluster_offset = s->free_byte_offset & ~(s->cluster_size - 1);
|
||||
if ((cluster_offset + s->cluster_size) == offset) {
|
||||
/* we are lucky: contiguous data */
|
||||
@@ -439,7 +473,13 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
|
||||
void qcow2_free_clusters(BlockDriverState *bs,
|
||||
int64_t offset, int64_t size)
|
||||
{
|
||||
update_refcount(bs, offset, size, -1);
|
||||
int ret;
|
||||
|
||||
ret = update_refcount(bs, offset, size, -1);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "qcow2_free_clusters failed: %s\n", strerror(-ret));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -549,9 +589,15 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
if (offset & QCOW_OFLAG_COMPRESSED) {
|
||||
nb_csectors = ((offset >> s->csize_shift) &
|
||||
s->csize_mask) + 1;
|
||||
if (addend != 0)
|
||||
update_refcount(bs, (offset & s->cluster_offset_mask) & ~511,
|
||||
nb_csectors * 512, addend);
|
||||
if (addend != 0) {
|
||||
int ret;
|
||||
ret = update_refcount(bs,
|
||||
(offset & s->cluster_offset_mask) & ~511,
|
||||
nb_csectors * 512, addend);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
/* compressed clusters are never modified */
|
||||
refcount = 2;
|
||||
} else {
|
||||
|
@@ -139,6 +139,9 @@ static int qcow_write_snapshots(BlockDriverState *bs)
|
||||
|
||||
snapshots_offset = qcow2_alloc_clusters(bs, snapshots_size);
|
||||
offset = snapshots_offset;
|
||||
if (offset < 0) {
|
||||
return offset;
|
||||
}
|
||||
|
||||
for(i = 0; i < s->nb_snapshots; i++) {
|
||||
sn = s->snapshots + i;
|
||||
@@ -235,6 +238,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
QCowSnapshot *snapshots1, sn1, *sn = &sn1;
|
||||
int i, ret;
|
||||
uint64_t *l1_table = NULL;
|
||||
int64_t l1_table_offset;
|
||||
|
||||
memset(sn, 0, sizeof(*sn));
|
||||
|
||||
@@ -263,7 +267,12 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
goto fail;
|
||||
|
||||
/* create the L1 table of the snapshot */
|
||||
sn->l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t));
|
||||
l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t));
|
||||
if (l1_table_offset < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sn->l1_table_offset = l1_table_offset;
|
||||
sn->l1_size = s->l1_size;
|
||||
|
||||
if (s->l1_size != 0) {
|
||||
|
@@ -561,7 +561,7 @@ static void qcow_aio_write_cb(void *opaque, int ret)
|
||||
acb->hd_aiocb = NULL;
|
||||
|
||||
if (ret >= 0) {
|
||||
ret = qcow2_alloc_cluster_link_l2(bs, acb->cluster_offset, &acb->l2meta);
|
||||
ret = qcow2_alloc_cluster_link_l2(bs, &acb->l2meta);
|
||||
}
|
||||
|
||||
run_dependent_requests(&acb->l2meta);
|
||||
@@ -585,21 +585,23 @@ static void qcow_aio_write_cb(void *opaque, int ret)
|
||||
n_end > QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors)
|
||||
n_end = QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors;
|
||||
|
||||
acb->cluster_offset = qcow2_alloc_cluster_offset(bs, acb->sector_num << 9,
|
||||
index_in_cluster,
|
||||
n_end, &acb->n, &acb->l2meta);
|
||||
ret = qcow2_alloc_cluster_offset(bs, acb->sector_num << 9,
|
||||
index_in_cluster, n_end, &acb->n, &acb->l2meta);
|
||||
if (ret < 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
acb->cluster_offset = acb->l2meta.cluster_offset;
|
||||
|
||||
/* Need to wait for another request? If so, we are done for now. */
|
||||
if (!acb->cluster_offset && acb->l2meta.depends_on != NULL) {
|
||||
if (acb->l2meta.nb_clusters == 0 && acb->l2meta.depends_on != NULL) {
|
||||
QLIST_INSERT_HEAD(&acb->l2meta.depends_on->dependent_requests,
|
||||
acb, next_depend);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!acb->cluster_offset || (acb->cluster_offset & 511) != 0) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
assert((acb->cluster_offset & 511) == 0);
|
||||
|
||||
if (s->crypt_method) {
|
||||
if (!acb->cluster_data) {
|
||||
acb->cluster_data = qemu_mallocz(QCOW_MAX_CRYPT_CLUSTERS *
|
||||
@@ -683,27 +685,27 @@ static int get_bits_from_size(size_t size)
|
||||
static int preallocate(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
uint64_t cluster_offset = 0;
|
||||
uint64_t nb_sectors;
|
||||
uint64_t offset;
|
||||
int num;
|
||||
int ret;
|
||||
QCowL2Meta meta;
|
||||
|
||||
nb_sectors = bdrv_getlength(bs) >> 9;
|
||||
offset = 0;
|
||||
QLIST_INIT(&meta.dependent_requests);
|
||||
meta.cluster_offset = 0;
|
||||
|
||||
while (nb_sectors) {
|
||||
num = MIN(nb_sectors, INT_MAX >> 9);
|
||||
cluster_offset = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num,
|
||||
&meta);
|
||||
ret = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num, &meta);
|
||||
|
||||
if (cluster_offset == 0) {
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (qcow2_alloc_cluster_link_l2(bs, cluster_offset, &meta) < 0) {
|
||||
qcow2_free_any_clusters(bs, cluster_offset, meta.nb_clusters);
|
||||
if (qcow2_alloc_cluster_link_l2(bs, &meta) < 0) {
|
||||
qcow2_free_any_clusters(bs, meta.cluster_offset, meta.nb_clusters);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -722,10 +724,10 @@ static int preallocate(BlockDriverState *bs)
|
||||
* all of the allocated clusters (otherwise we get failing reads after
|
||||
* EOF). Extend the image to the last allocated sector.
|
||||
*/
|
||||
if (cluster_offset != 0) {
|
||||
if (meta.cluster_offset != 0) {
|
||||
uint8_t buf[512];
|
||||
memset(buf, 0, 512);
|
||||
bdrv_write(s->hd, (cluster_offset >> 9) + num - 1, buf, 1);
|
||||
bdrv_write(s->hd, (meta.cluster_offset >> 9) + num - 1, buf, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1056,12 +1058,13 @@ static int qcow_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
int growable = bs->growable;
|
||||
int ret;
|
||||
|
||||
bs->growable = 1;
|
||||
bdrv_pwrite(bs, qcow_vm_state_offset(s) + pos, buf, size);
|
||||
ret = bdrv_pwrite(bs, qcow_vm_state_offset(s) + pos, buf, size);
|
||||
bs->growable = growable;
|
||||
|
||||
return size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcow_load_vmstate(BlockDriverState *bs, uint8_t *buf,
|
||||
|
@@ -135,6 +135,7 @@ struct QCowAIOCB;
|
||||
typedef struct QCowL2Meta
|
||||
{
|
||||
uint64_t offset;
|
||||
uint64_t cluster_offset;
|
||||
int n_start;
|
||||
int nb_available;
|
||||
int nb_clusters;
|
||||
@@ -191,16 +192,13 @@ void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
|
||||
|
||||
uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
||||
int *num);
|
||||
uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
|
||||
uint64_t offset,
|
||||
int n_start, int n_end,
|
||||
int *num, QCowL2Meta *m);
|
||||
int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
||||
int n_start, int n_end, int *num, QCowL2Meta *m);
|
||||
uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
|
||||
uint64_t offset,
|
||||
int compressed_size);
|
||||
|
||||
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, uint64_t cluster_offset,
|
||||
QCowL2Meta *m);
|
||||
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
|
||||
|
||||
/* qcow2-snapshot.c functions */
|
||||
int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
|
||||
|
@@ -595,7 +595,7 @@ static void raw_close(BlockDriverState *bs)
|
||||
close(s->fd);
|
||||
s->fd = -1;
|
||||
if (s->aligned_buf != NULL)
|
||||
qemu_free(s->aligned_buf);
|
||||
qemu_vfree(s->aligned_buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -882,7 +882,7 @@ static int init_directories(BDRVVVFATState* s,
|
||||
mapping->dir_index = 0;
|
||||
mapping->info.dir.parent_mapping_index = -1;
|
||||
mapping->first_mapping_index = -1;
|
||||
mapping->path = strdup(dirname);
|
||||
mapping->path = qemu_strdup(dirname);
|
||||
i = strlen(mapping->path);
|
||||
if (i > 0 && mapping->path[i - 1] == '/')
|
||||
mapping->path[i - 1] = '\0';
|
||||
@@ -1632,10 +1632,10 @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
|
||||
|
||||
/* rename */
|
||||
if (strcmp(basename, basename2))
|
||||
schedule_rename(s, cluster_num, strdup(path));
|
||||
schedule_rename(s, cluster_num, qemu_strdup(path));
|
||||
} else if (is_file(direntry))
|
||||
/* new file */
|
||||
schedule_new_file(s, strdup(path), cluster_num);
|
||||
schedule_new_file(s, qemu_strdup(path), cluster_num);
|
||||
else {
|
||||
assert(0);
|
||||
return 0;
|
||||
@@ -1752,10 +1752,10 @@ static int check_directory_consistency(BDRVVVFATState *s,
|
||||
mapping->mode &= ~MODE_DELETED;
|
||||
|
||||
if (strcmp(basename, basename2))
|
||||
schedule_rename(s, cluster_num, strdup(path));
|
||||
schedule_rename(s, cluster_num, qemu_strdup(path));
|
||||
} else
|
||||
/* new directory */
|
||||
schedule_mkdir(s, cluster_num, strdup(path));
|
||||
schedule_mkdir(s, cluster_num, qemu_strdup(path));
|
||||
|
||||
lfn_init(&lfn);
|
||||
do {
|
||||
|
12
cpu-exec.c
12
cpu-exec.c
@@ -232,11 +232,13 @@ int cpu_exec(CPUState *env1)
|
||||
|
||||
env_to_regs();
|
||||
#if defined(TARGET_I386)
|
||||
/* put eflags in CPU temporary format */
|
||||
CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
|
||||
DF = 1 - (2 * ((env->eflags >> 10) & 1));
|
||||
CC_OP = CC_OP_EFLAGS;
|
||||
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
|
||||
if (!kvm_enabled()) {
|
||||
/* put eflags in CPU temporary format */
|
||||
CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
|
||||
DF = 1 - (2 * ((env->eflags >> 10) & 1));
|
||||
CC_OP = CC_OP_EFLAGS;
|
||||
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
|
||||
}
|
||||
#elif defined(TARGET_SPARC)
|
||||
#elif defined(TARGET_M68K)
|
||||
env->cc_op = CC_OP_FLAGS;
|
||||
|
2
exec.c
2
exec.c
@@ -3307,7 +3307,7 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
|
||||
if (is_write) {
|
||||
cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
|
||||
}
|
||||
qemu_free(bounce.buffer);
|
||||
qemu_vfree(bounce.buffer);
|
||||
bounce.buffer = NULL;
|
||||
cpu_notify_map_clients();
|
||||
}
|
||||
|
@@ -2585,9 +2585,11 @@ static void map_linear_vram(CirrusVGAState *s)
|
||||
|
||||
static void unmap_linear_vram(CirrusVGAState *s)
|
||||
{
|
||||
if (s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end)
|
||||
if (s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
|
||||
s->vga.map_addr = s->vga.map_end = 0;
|
||||
|
||||
cpu_register_physical_memory(s->vga.lfb_addr, s->vga.vram_size,
|
||||
s->cirrus_linear_io_addr);
|
||||
}
|
||||
cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
|
||||
s->vga.vga_io_memory);
|
||||
}
|
||||
|
@@ -115,7 +115,7 @@ static void ide_identify(IDEState *s)
|
||||
put_le16(p + 20, 3); /* XXX: retired, remove ? */
|
||||
put_le16(p + 21, 512); /* cache size in sectors */
|
||||
put_le16(p + 22, 4); /* ecc bytes */
|
||||
padstr((char *)(p + 23), QEMU_VERSION, 8); /* firmware version */
|
||||
padstr((char *)(p + 23), s->version, 8); /* firmware version */
|
||||
padstr((char *)(p + 27), "QEMU HARDDISK", 40); /* model */
|
||||
#if MAX_MULT_SECTORS > 1
|
||||
put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
|
||||
@@ -186,7 +186,7 @@ static void ide_atapi_identify(IDEState *s)
|
||||
put_le16(p + 20, 3); /* buffer type */
|
||||
put_le16(p + 21, 512); /* cache size in sectors */
|
||||
put_le16(p + 22, 4); /* ecc bytes */
|
||||
padstr((char *)(p + 23), QEMU_VERSION, 8); /* firmware version */
|
||||
padstr((char *)(p + 23), s->version, 8); /* firmware version */
|
||||
padstr((char *)(p + 27), "QEMU DVD-ROM", 40); /* model */
|
||||
put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
|
||||
#ifdef USE_DMA_CDROM
|
||||
@@ -238,7 +238,7 @@ static void ide_cfata_identify(IDEState *s)
|
||||
put_le16(p + 8, s->nb_sectors); /* Sectors per card */
|
||||
padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
|
||||
put_le16(p + 22, 0x0004); /* ECC bytes */
|
||||
padstr((char *) (p + 23), QEMU_VERSION, 8); /* Firmware Revision */
|
||||
padstr((char *) (p + 23), s->version, 8); /* Firmware Revision */
|
||||
padstr((char *) (p + 27), "QEMU MICRODRIVE", 40);/* Model number */
|
||||
#if MAX_MULT_SECTORS > 1
|
||||
put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
|
||||
@@ -1591,7 +1591,7 @@ static void ide_atapi_cmd(IDEState *s)
|
||||
buf[7] = 0; /* reserved */
|
||||
padstr8(buf + 8, 8, "QEMU");
|
||||
padstr8(buf + 16, 16, "QEMU DVD-ROM");
|
||||
padstr8(buf + 32, 4, QEMU_VERSION);
|
||||
padstr8(buf + 32, 4, s->version);
|
||||
ide_atapi_cmd_reply(s, 36, max_len);
|
||||
break;
|
||||
case GPCMD_GET_CONFIGURATION:
|
||||
@@ -2590,7 +2590,7 @@ void ide_bus_reset(IDEBus *bus)
|
||||
ide_clear_hob(bus);
|
||||
}
|
||||
|
||||
void ide_init_drive(IDEState *s, DriveInfo *dinfo)
|
||||
void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
|
||||
{
|
||||
int cylinders, heads, secs;
|
||||
uint64_t nb_sectors;
|
||||
@@ -2619,6 +2619,11 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo)
|
||||
if (strlen(s->drive_serial_str) == 0)
|
||||
snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
|
||||
"QM%05d", s->drive_serial);
|
||||
if (version) {
|
||||
pstrcpy(s->version, sizeof(s->version), version);
|
||||
} else {
|
||||
pstrcpy(s->version, sizeof(s->version), QEMU_VERSION);
|
||||
}
|
||||
ide_reset(s);
|
||||
}
|
||||
|
||||
@@ -2635,13 +2640,14 @@ void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
|
||||
s->unit = i;
|
||||
s->drive_serial = drive_serial++;
|
||||
s->io_buffer = qemu_blockalign(s->bs, IDE_DMA_BUF_SECTORS*512 + 4);
|
||||
s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
|
||||
s->smart_selftest_data = qemu_blockalign(s->bs, 512);
|
||||
s->sector_write_timer = qemu_new_timer(vm_clock,
|
||||
ide_sector_write_timer_cb, s);
|
||||
if (i == 0)
|
||||
ide_init_drive(s, hd0);
|
||||
ide_init_drive(s, hd0, NULL);
|
||||
if (i == 1)
|
||||
ide_init_drive(s, hd1);
|
||||
ide_init_drive(s, hd1, NULL);
|
||||
}
|
||||
bus->irq = irq;
|
||||
}
|
||||
@@ -2669,6 +2675,25 @@ static bool is_identify_set(void *opaque, int version_id)
|
||||
return s->identify_set != 0;
|
||||
}
|
||||
|
||||
static EndTransferFunc* transfer_end_table[] = {
|
||||
ide_sector_read,
|
||||
ide_sector_write,
|
||||
ide_transfer_stop,
|
||||
ide_atapi_cmd_reply_end,
|
||||
ide_atapi_cmd,
|
||||
};
|
||||
|
||||
static int transfer_end_table_idx(EndTransferFunc *fn)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(transfer_end_table); i++)
|
||||
if (transfer_end_table[i] == fn)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ide_drive_post_load(void *opaque, int version_id)
|
||||
{
|
||||
IDEState *s = opaque;
|
||||
@@ -2679,14 +2704,42 @@ static int ide_drive_post_load(void *opaque, int version_id)
|
||||
s->cdrom_changed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->cur_io_buffer_len) {
|
||||
s->end_transfer_func = transfer_end_table[s->end_transfer_fn_idx];
|
||||
s->data_ptr = s->io_buffer + s->cur_io_buffer_offset;
|
||||
s->data_end = s->data_ptr + s->cur_io_buffer_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ide_drive_pre_save(void *opaque)
|
||||
{
|
||||
IDEState *s = opaque;
|
||||
|
||||
s->cur_io_buffer_len = 0;
|
||||
|
||||
if (!(s->status & DRQ_STAT))
|
||||
return;
|
||||
|
||||
s->cur_io_buffer_offset = s->data_ptr - s->io_buffer;
|
||||
s->cur_io_buffer_len = s->data_end - s->data_ptr;
|
||||
|
||||
s->end_transfer_fn_idx = transfer_end_table_idx(s->end_transfer_func);
|
||||
if (s->end_transfer_fn_idx == -1) {
|
||||
fprintf(stderr, "%s: invalid end_transfer_func for DRQ_STAT\n",
|
||||
__func__);
|
||||
s->end_transfer_fn_idx = 2;
|
||||
}
|
||||
}
|
||||
|
||||
const VMStateDescription vmstate_ide_drive = {
|
||||
.name = "ide_drive",
|
||||
.version_id = 3,
|
||||
.version_id = 4,
|
||||
.minimum_version_id = 0,
|
||||
.minimum_version_id_old = 0,
|
||||
.pre_save = ide_drive_pre_save,
|
||||
.post_load = ide_drive_post_load,
|
||||
.fields = (VMStateField []) {
|
||||
VMSTATE_INT32(mult_sectors, IDEState),
|
||||
@@ -2709,7 +2762,14 @@ const VMStateDescription vmstate_ide_drive = {
|
||||
VMSTATE_UINT8(sense_key, IDEState),
|
||||
VMSTATE_UINT8(asc, IDEState),
|
||||
VMSTATE_UINT8_V(cdrom_changed, IDEState, 3),
|
||||
/* XXX: if a transfer is pending, we do not save it yet */
|
||||
VMSTATE_INT32_V(req_nb_sectors, IDEState, 4),
|
||||
VMSTATE_VARRAY_INT32(io_buffer, IDEState, io_buffer_total_len, 4,
|
||||
vmstate_info_uint8, uint8_t),
|
||||
VMSTATE_INT32_V(cur_io_buffer_offset, IDEState, 4),
|
||||
VMSTATE_INT32_V(cur_io_buffer_len, IDEState, 4),
|
||||
VMSTATE_UINT8_V(end_transfer_fn_idx, IDEState, 4),
|
||||
VMSTATE_INT32_V(elementary_transfer_size, IDEState, 4),
|
||||
VMSTATE_INT32_V(packet_transfer_size, IDEState, 4),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
@@ -397,6 +397,7 @@ struct IDEState {
|
||||
/* set for lba48 access */
|
||||
uint8_t lba48;
|
||||
BlockDriverState *bs;
|
||||
char version[9];
|
||||
/* ATAPI specific */
|
||||
uint8_t sense_key;
|
||||
uint8_t asc;
|
||||
@@ -416,6 +417,11 @@ struct IDEState {
|
||||
uint8_t *data_ptr;
|
||||
uint8_t *data_end;
|
||||
uint8_t *io_buffer;
|
||||
/* PIO save/restore */
|
||||
int32_t io_buffer_total_len;
|
||||
int cur_io_buffer_offset;
|
||||
int cur_io_buffer_len;
|
||||
uint8_t end_transfer_fn_idx;
|
||||
QEMUTimer *sector_write_timer; /* only used for win2k install hack */
|
||||
uint32_t irq_count; /* counts IRQs when using win2k install hack */
|
||||
/* CF-ATA extended error */
|
||||
@@ -449,6 +455,7 @@ struct IDEDevice {
|
||||
DeviceState qdev;
|
||||
uint32_t unit;
|
||||
DriveInfo *dinfo;
|
||||
char *version;
|
||||
};
|
||||
|
||||
typedef int (*ide_qdev_initfn)(IDEDevice *dev);
|
||||
@@ -548,7 +555,7 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr);
|
||||
void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
|
||||
uint32_t ide_data_readl(void *opaque, uint32_t addr);
|
||||
|
||||
void ide_init_drive(IDEState *s, DriveInfo *dinfo);
|
||||
void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version);
|
||||
void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
|
||||
qemu_irq irq);
|
||||
void ide_init_ioport(IDEBus *bus, int iobase, int iobase2);
|
||||
|
@@ -99,7 +99,7 @@ typedef struct IDEDrive {
|
||||
static int ide_drive_initfn(IDEDevice *dev)
|
||||
{
|
||||
IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
|
||||
ide_init_drive(bus->ifs + dev->unit, dev->dinfo);
|
||||
ide_init_drive(bus->ifs + dev->unit, dev->dinfo, dev->version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -110,6 +110,7 @@ static IDEDeviceInfo ide_drive_info = {
|
||||
.qdev.props = (Property[]) {
|
||||
DEFINE_PROP_UINT32("unit", IDEDrive, dev.unit, -1),
|
||||
DEFINE_PROP_DRIVE("drive", IDEDrive, dev.dinfo),
|
||||
DEFINE_PROP_STRING("ver", IDEDrive, dev.version),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
}
|
||||
};
|
||||
|
@@ -30,7 +30,7 @@
|
||||
|
||||
//#define DEBUG_CMOS
|
||||
|
||||
#define RTC_REINJECT_ON_ACK_COUNT 1000
|
||||
#define RTC_REINJECT_ON_ACK_COUNT 20
|
||||
|
||||
#define RTC_SECONDS 0
|
||||
#define RTC_SECONDS_ALARM 1
|
||||
|
@@ -67,7 +67,7 @@
|
||||
#define MP_AUDIO_IRQ 30
|
||||
|
||||
/* Wolfson 8750 I2C address */
|
||||
#define MP_WM_ADDR 0x34
|
||||
#define MP_WM_ADDR 0x1A
|
||||
|
||||
/* Ethernet register offsets */
|
||||
#define MP_ETH_SMIR 0x010
|
||||
@@ -238,14 +238,13 @@ static void eth_send(mv88w8618_eth_state *s, int queue_index)
|
||||
{
|
||||
uint32_t desc_addr = s->tx_queue[queue_index];
|
||||
mv88w8618_tx_desc desc;
|
||||
uint32_t next_desc;
|
||||
uint8_t buf[2048];
|
||||
int len;
|
||||
|
||||
if (!desc_addr) {
|
||||
return;
|
||||
}
|
||||
do {
|
||||
eth_tx_desc_get(desc_addr, &desc);
|
||||
next_desc = desc.next;
|
||||
if (desc.cmdstat & MP_ETH_TX_OWN) {
|
||||
len = desc.bytes;
|
||||
if (len < 2048) {
|
||||
@@ -256,7 +255,7 @@ static void eth_send(mv88w8618_eth_state *s, int queue_index)
|
||||
s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index);
|
||||
eth_tx_desc_put(desc_addr, &desc);
|
||||
}
|
||||
desc_addr = desc.next;
|
||||
desc_addr = next_desc;
|
||||
} while (desc_addr != s->tx_queue[queue_index]);
|
||||
}
|
||||
|
||||
|
16
hw/pc.c
16
hw/pc.c
@@ -1306,6 +1306,14 @@ static QEMUMachine pc_machine_v0_11 = {
|
||||
.driver = "virtio-blk-pci",
|
||||
.property = "vectors",
|
||||
.value = stringify(0),
|
||||
},{
|
||||
.driver = "ide-drive",
|
||||
.property = "ver",
|
||||
.value = "0.11",
|
||||
},{
|
||||
.driver = "scsi-disk",
|
||||
.property = "ver",
|
||||
.value = "0.11",
|
||||
},{
|
||||
.driver = "PCI",
|
||||
.property = "rombar",
|
||||
@@ -1337,6 +1345,14 @@ static QEMUMachine pc_machine_v0_10 = {
|
||||
.driver = "virtio-blk-pci",
|
||||
.property = "vectors",
|
||||
.value = stringify(0),
|
||||
},{
|
||||
.driver = "ide-drive",
|
||||
.property = "ver",
|
||||
.value = "0.10",
|
||||
},{
|
||||
.driver = "scsi-disk",
|
||||
.property = "ver",
|
||||
.value = "0.10",
|
||||
},{
|
||||
.driver = "PCI",
|
||||
.property = "rombar",
|
||||
|
@@ -65,6 +65,7 @@ struct SCSIDiskState
|
||||
int cluster_size;
|
||||
uint64_t max_lba;
|
||||
QEMUBH *bh;
|
||||
char *version;
|
||||
};
|
||||
|
||||
static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
|
||||
@@ -80,7 +81,7 @@ static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
|
||||
|
||||
static void scsi_remove_request(SCSIDiskReq *r)
|
||||
{
|
||||
qemu_free(r->iov.iov_base);
|
||||
qemu_vfree(r->iov.iov_base);
|
||||
scsi_req_free(&r->req);
|
||||
}
|
||||
|
||||
@@ -315,6 +316,7 @@ static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
|
||||
static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
|
||||
{
|
||||
BlockDriverState *bdrv = req->dev->dinfo->bdrv;
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
|
||||
int buflen = 0;
|
||||
|
||||
if (req->cmd.buf[1] & 0x2) {
|
||||
@@ -432,7 +434,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
|
||||
memcpy(&outbuf[16], "QEMU HARDDISK ", 16);
|
||||
}
|
||||
memcpy(&outbuf[8], "QEMU ", 8);
|
||||
memcpy(&outbuf[32], QEMU_VERSION, 4);
|
||||
memcpy(&outbuf[32], s->version ? s->version : QEMU_VERSION, 4);
|
||||
/* Identify device as SCSI-3 rev 1.
|
||||
Some later commands are also implemented. */
|
||||
outbuf[2] = 3;
|
||||
@@ -1029,6 +1031,7 @@ static SCSIDeviceInfo scsi_disk_info = {
|
||||
.get_buf = scsi_get_buf,
|
||||
.qdev.props = (Property[]) {
|
||||
DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.dinfo),
|
||||
DEFINE_PROP_STRING("ver", SCSIDiskState, version),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
},
|
||||
};
|
||||
|
@@ -1492,7 +1492,7 @@ static USBDevice *usb_net_init(const char *cmdline)
|
||||
|
||||
dev = usb_create(NULL /* FIXME */, "usb-net");
|
||||
qdev_set_nic_properties(&dev->qdev, &nd_table[idx]);
|
||||
qdev_init(&dev->qdev);
|
||||
qdev_init_nofail(&dev->qdev);
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
@@ -497,12 +497,28 @@ static int usb_serial_can_read(void *opaque)
|
||||
static void usb_serial_read(void *opaque, const uint8_t *buf, int size)
|
||||
{
|
||||
USBSerialState *s = opaque;
|
||||
int first_size = RECV_BUF - s->recv_ptr;
|
||||
if (first_size > size)
|
||||
first_size = size;
|
||||
memcpy(s->recv_buf + s->recv_ptr + s->recv_used, buf, first_size);
|
||||
if (size > first_size)
|
||||
memcpy(s->recv_buf, buf + first_size, size - first_size);
|
||||
int first_size, start;
|
||||
|
||||
/* room in the buffer? */
|
||||
if (size > (RECV_BUF - s->recv_used))
|
||||
size = RECV_BUF - s->recv_used;
|
||||
|
||||
start = s->recv_ptr + s->recv_used;
|
||||
if (start < RECV_BUF) {
|
||||
/* copy data to end of buffer */
|
||||
first_size = RECV_BUF - start;
|
||||
if (first_size > size)
|
||||
first_size = size;
|
||||
|
||||
memcpy(s->recv_buf + start, buf, first_size);
|
||||
|
||||
/* wrap around to front if needed */
|
||||
if (size > first_size)
|
||||
memcpy(s->recv_buf, buf + first_size, size - first_size);
|
||||
} else {
|
||||
start -= RECV_BUF;
|
||||
memcpy(s->recv_buf + start, buf, size);
|
||||
}
|
||||
s->recv_used += size;
|
||||
}
|
||||
|
||||
@@ -583,7 +599,7 @@ static USBDevice *usb_serial_init(const char *filename)
|
||||
qdev_prop_set_uint16(&dev->qdev, "vendorid", vendorid);
|
||||
if (productid)
|
||||
qdev_prop_set_uint16(&dev->qdev, "productid", productid);
|
||||
qdev_init(&dev->qdev);
|
||||
qdev_init_nofail(&dev->qdev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
@@ -599,7 +615,7 @@ static USBDevice *usb_braille_init(const char *unused)
|
||||
|
||||
dev = usb_create(NULL /* FIXME */, "usb-braille");
|
||||
qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
|
||||
qdev_init(&dev->qdev);
|
||||
qdev_init_nofail(&dev->qdev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
@@ -272,7 +272,7 @@ static void do_multiwrite(BlockDriverState *bs, BlockRequest *blkreq,
|
||||
if (ret != 0) {
|
||||
for (i = 0; i < num_writes; i++) {
|
||||
if (blkreq[i].error) {
|
||||
virtio_blk_req_complete(blkreq[i].opaque, VIRTIO_BLK_S_IOERR);
|
||||
virtio_blk_rw_complete(blkreq[i].opaque, -EIO);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -316,7 +316,46 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
|
||||
acb = bdrv_aio_readv(req->dev->bs, req->out->sector, &req->qiov,
|
||||
req->qiov.size / 512, virtio_blk_rw_complete, req);
|
||||
if (!acb) {
|
||||
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
|
||||
virtio_blk_rw_complete(req, -EIO);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct MultiReqBuffer {
|
||||
BlockRequest blkreq[32];
|
||||
int num_writes;
|
||||
BlockDriverState *old_bs;
|
||||
} MultiReqBuffer;
|
||||
|
||||
static void virtio_blk_handle_request(VirtIOBlockReq *req,
|
||||
MultiReqBuffer *mrb)
|
||||
{
|
||||
if (req->elem.out_num < 1 || req->elem.in_num < 1) {
|
||||
fprintf(stderr, "virtio-blk missing headers\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (req->elem.out_sg[0].iov_len < sizeof(*req->out) ||
|
||||
req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) {
|
||||
fprintf(stderr, "virtio-blk header not in correct element\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
req->out = (void *)req->elem.out_sg[0].iov_base;
|
||||
req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
|
||||
|
||||
if (req->out->type & VIRTIO_BLK_T_FLUSH) {
|
||||
virtio_blk_handle_flush(req);
|
||||
} else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
|
||||
virtio_blk_handle_scsi(req);
|
||||
} else if (req->out->type & VIRTIO_BLK_T_OUT) {
|
||||
qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
|
||||
req->elem.out_num - 1);
|
||||
virtio_blk_handle_write(mrb->blkreq, &mrb->num_writes,
|
||||
req, &mrb->old_bs);
|
||||
} else {
|
||||
qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
|
||||
req->elem.in_num - 1);
|
||||
virtio_blk_handle_read(req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,42 +363,17 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VirtIOBlock *s = to_virtio_blk(vdev);
|
||||
VirtIOBlockReq *req;
|
||||
BlockRequest blkreq[32];
|
||||
int num_writes = 0;
|
||||
BlockDriverState *old_bs = NULL;
|
||||
MultiReqBuffer mrb = {
|
||||
.num_writes = 0,
|
||||
.old_bs = NULL,
|
||||
};
|
||||
|
||||
while ((req = virtio_blk_get_request(s))) {
|
||||
if (req->elem.out_num < 1 || req->elem.in_num < 1) {
|
||||
fprintf(stderr, "virtio-blk missing headers\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (req->elem.out_sg[0].iov_len < sizeof(*req->out) ||
|
||||
req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) {
|
||||
fprintf(stderr, "virtio-blk header not in correct element\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
req->out = (void *)req->elem.out_sg[0].iov_base;
|
||||
req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
|
||||
|
||||
if (req->out->type & VIRTIO_BLK_T_FLUSH) {
|
||||
virtio_blk_handle_flush(req);
|
||||
} else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
|
||||
virtio_blk_handle_scsi(req);
|
||||
} else if (req->out->type & VIRTIO_BLK_T_OUT) {
|
||||
qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
|
||||
req->elem.out_num - 1);
|
||||
virtio_blk_handle_write(blkreq, &num_writes, req, &old_bs);
|
||||
} else {
|
||||
qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
|
||||
req->elem.in_num - 1);
|
||||
virtio_blk_handle_read(req);
|
||||
}
|
||||
virtio_blk_handle_request(req, &mrb);
|
||||
}
|
||||
|
||||
if (num_writes > 0) {
|
||||
do_multiwrite(old_bs, blkreq, num_writes);
|
||||
if (mrb.num_writes > 0) {
|
||||
do_multiwrite(mrb.old_bs, mrb.blkreq, mrb.num_writes);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -373,6 +387,10 @@ static void virtio_blk_dma_restart_bh(void *opaque)
|
||||
{
|
||||
VirtIOBlock *s = opaque;
|
||||
VirtIOBlockReq *req = s->rq;
|
||||
MultiReqBuffer mrb = {
|
||||
.num_writes = 0,
|
||||
.old_bs = NULL,
|
||||
};
|
||||
|
||||
qemu_bh_delete(s->bh);
|
||||
s->bh = NULL;
|
||||
@@ -380,10 +398,13 @@ static void virtio_blk_dma_restart_bh(void *opaque)
|
||||
s->rq = NULL;
|
||||
|
||||
while (req) {
|
||||
bdrv_aio_writev(req->dev->bs, req->out->sector, &req->qiov,
|
||||
req->qiov.size / 512, virtio_blk_rw_complete, req);
|
||||
virtio_blk_handle_request(req, &mrb);
|
||||
req = req->next;
|
||||
}
|
||||
|
||||
if (mrb.num_writes > 0) {
|
||||
do_multiwrite(mrb.old_bs, mrb.blkreq, mrb.num_writes);
|
||||
}
|
||||
}
|
||||
|
||||
static void virtio_blk_dma_restart_cb(void *opaque, int running, int reason)
|
||||
|
@@ -384,7 +384,15 @@ static int virtio_net_has_buffers(VirtIONet *n, int bufsize)
|
||||
(n->mergeable_rx_bufs &&
|
||||
!virtqueue_avail_bytes(n->rx_vq, bufsize, 0))) {
|
||||
virtio_queue_set_notification(n->rx_vq, 1);
|
||||
return 0;
|
||||
|
||||
/* To avoid a race condition where the guest has made some buffers
|
||||
* available after the above check but before notification was
|
||||
* enabled, check for available buffers again.
|
||||
*/
|
||||
if (virtio_queue_empty(n->rx_vq) ||
|
||||
(n->mergeable_rx_bufs &&
|
||||
!virtqueue_avail_bytes(n->rx_vq, bufsize, 0)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtio_queue_set_notification(n->rx_vq, 0);
|
||||
|
16
json-lexer.c
16
json-lexer.c
@@ -54,6 +54,9 @@ enum json_lexer_state {
|
||||
IN_ESCAPE,
|
||||
IN_ESCAPE_L,
|
||||
IN_ESCAPE_LL,
|
||||
IN_ESCAPE_I,
|
||||
IN_ESCAPE_I6,
|
||||
IN_ESCAPE_I64,
|
||||
IN_ESCAPE_DONE,
|
||||
IN_WHITESPACE,
|
||||
IN_OPERATOR_DONE,
|
||||
@@ -223,6 +226,18 @@ static const uint8_t json_lexer[][256] = {
|
||||
['l'] = IN_ESCAPE_LL,
|
||||
},
|
||||
|
||||
[IN_ESCAPE_I64] = {
|
||||
['d'] = IN_ESCAPE_DONE,
|
||||
},
|
||||
|
||||
[IN_ESCAPE_I6] = {
|
||||
['4'] = IN_ESCAPE_I64,
|
||||
},
|
||||
|
||||
[IN_ESCAPE_I] = {
|
||||
['6'] = IN_ESCAPE_I6,
|
||||
},
|
||||
|
||||
[IN_ESCAPE] = {
|
||||
['d'] = IN_ESCAPE_DONE,
|
||||
['i'] = IN_ESCAPE_DONE,
|
||||
@@ -230,6 +245,7 @@ static const uint8_t json_lexer[][256] = {
|
||||
['s'] = IN_ESCAPE_DONE,
|
||||
['f'] = IN_ESCAPE_DONE,
|
||||
['l'] = IN_ESCAPE_L,
|
||||
['I'] = IN_ESCAPE_I,
|
||||
},
|
||||
|
||||
/* top level rule */
|
||||
|
@@ -476,7 +476,8 @@ static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *a
|
||||
obj = QOBJECT(qint_from_int(va_arg(*ap, int)));
|
||||
} else if (token_is_escape(token, "%ld")) {
|
||||
obj = QOBJECT(qint_from_int(va_arg(*ap, long)));
|
||||
} else if (token_is_escape(token, "%lld")) {
|
||||
} else if (token_is_escape(token, "%lld") ||
|
||||
token_is_escape(token, "%I64d")) {
|
||||
obj = QOBJECT(qint_from_int(va_arg(*ap, long long)));
|
||||
} else if (token_is_escape(token, "%s")) {
|
||||
obj = QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
|
||||
|
11
monitor.c
11
monitor.c
@@ -334,13 +334,10 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
|
||||
{
|
||||
QDict *qmp;
|
||||
const char *event_name;
|
||||
Monitor *mon = cur_mon;
|
||||
Monitor *mon;
|
||||
|
||||
assert(event < QEVENT_MAX);
|
||||
|
||||
if (!monitor_ctrl_mode(mon))
|
||||
return;
|
||||
|
||||
switch (event) {
|
||||
case QEVENT_DEBUG:
|
||||
event_name = "DEBUG";
|
||||
@@ -370,7 +367,11 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
|
||||
qdict_put_obj(qmp, "data", data);
|
||||
}
|
||||
|
||||
monitor_json_emitter(mon, QOBJECT(qmp));
|
||||
QLIST_FOREACH(mon, &mon_list, entry) {
|
||||
if (monitor_ctrl_mode(mon)) {
|
||||
monitor_json_emitter(mon, QOBJECT(qmp));
|
||||
}
|
||||
}
|
||||
QDECREF(qmp);
|
||||
}
|
||||
|
||||
|
64
net.c
64
net.c
@@ -96,7 +96,7 @@ int parse_host_src_port(struct sockaddr_in *haddr,
|
||||
struct sockaddr_in *saddr,
|
||||
const char *input_str)
|
||||
{
|
||||
char *str = strdup(input_str);
|
||||
char *str = qemu_strdup(input_str);
|
||||
char *host_str = str;
|
||||
char *src_str;
|
||||
const char *src_str2;
|
||||
@@ -812,9 +812,6 @@ static int net_init_nic(QemuOpts *opts,
|
||||
}
|
||||
|
||||
nd->used = 1;
|
||||
if (vlan) {
|
||||
nd->vlan->nb_guest_devs++;
|
||||
}
|
||||
nb_nics++;
|
||||
|
||||
return idx;
|
||||
@@ -1128,20 +1125,6 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void net_client_uninit(NICInfo *nd)
|
||||
{
|
||||
if (nd->vlan) {
|
||||
nd->vlan->nb_guest_devs--;
|
||||
}
|
||||
nb_nics--;
|
||||
|
||||
qemu_free(nd->model);
|
||||
qemu_free(nd->name);
|
||||
qemu_free(nd->devaddr);
|
||||
|
||||
nd->used = 0;
|
||||
}
|
||||
|
||||
static int net_host_check_device(const char *device)
|
||||
{
|
||||
int i;
|
||||
@@ -1227,16 +1210,23 @@ void net_set_boot_mask(int net_boot_mask)
|
||||
void do_info_network(Monitor *mon)
|
||||
{
|
||||
VLANState *vlan;
|
||||
VLANClientState *vc;
|
||||
|
||||
QTAILQ_FOREACH(vlan, &vlans, next) {
|
||||
VLANClientState *vc;
|
||||
|
||||
monitor_printf(mon, "VLAN %d devices:\n", vlan->id);
|
||||
|
||||
QTAILQ_FOREACH(vc, &vlan->clients, next) {
|
||||
monitor_printf(mon, " %s: %s\n", vc->name, vc->info_str);
|
||||
}
|
||||
}
|
||||
monitor_printf(mon, "Devices not on any VLAN:\n");
|
||||
QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
|
||||
monitor_printf(mon, " %s: %s", vc->name, vc->info_str);
|
||||
if (vc->peer) {
|
||||
monitor_printf(mon, " peer=%s", vc->peer->name);
|
||||
}
|
||||
monitor_printf(mon, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void do_set_link(Monitor *mon, const QDict *qdict)
|
||||
@@ -1253,6 +1243,7 @@ void do_set_link(Monitor *mon, const QDict *qdict)
|
||||
}
|
||||
}
|
||||
}
|
||||
vc = qemu_find_netdev(name);
|
||||
done:
|
||||
|
||||
if (!vc) {
|
||||
@@ -1289,20 +1280,41 @@ void net_cleanup(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void net_check_clients(void)
|
||||
void net_check_clients(void)
|
||||
{
|
||||
VLANState *vlan;
|
||||
VLANClientState *vc;
|
||||
int has_nic, has_host_dev;
|
||||
|
||||
QTAILQ_FOREACH(vlan, &vlans, next) {
|
||||
if (vlan->nb_guest_devs == 0 && vlan->nb_host_devs == 0)
|
||||
continue;
|
||||
if (vlan->nb_guest_devs == 0)
|
||||
QTAILQ_FOREACH(vc, &vlan->clients, next) {
|
||||
switch (vc->info->type) {
|
||||
case NET_CLIENT_TYPE_NIC:
|
||||
has_nic = 1;
|
||||
break;
|
||||
case NET_CLIENT_TYPE_SLIRP:
|
||||
case NET_CLIENT_TYPE_TAP:
|
||||
case NET_CLIENT_TYPE_SOCKET:
|
||||
case NET_CLIENT_TYPE_VDE:
|
||||
has_host_dev = 1;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
if (has_host_dev && !has_nic)
|
||||
fprintf(stderr, "Warning: vlan %d with no nics\n", vlan->id);
|
||||
if (vlan->nb_host_devs == 0)
|
||||
if (has_nic && !has_host_dev)
|
||||
fprintf(stderr,
|
||||
"Warning: vlan %d is not connected to host network\n",
|
||||
vlan->id);
|
||||
}
|
||||
QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
|
||||
if (!vc->peer) {
|
||||
fprintf(stderr, "Warning: %s %s has no peer\n",
|
||||
vc->info->type == NET_CLIENT_TYPE_NIC ? "nic" : "netdev",
|
||||
vc->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int net_init_client(QemuOpts *opts, void *dummy)
|
||||
@@ -1337,8 +1349,6 @@ int net_init_clients(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
net_check_clients();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
3
net.h
3
net.h
@@ -76,7 +76,6 @@ struct VLANState {
|
||||
int id;
|
||||
QTAILQ_HEAD(, VLANClientState) clients;
|
||||
QTAILQ_ENTRY(VLANState) next;
|
||||
unsigned int nb_guest_devs, nb_host_devs;
|
||||
NetQueue *send_queue;
|
||||
};
|
||||
|
||||
@@ -160,9 +159,9 @@ extern const char *legacy_tftp_prefix;
|
||||
extern const char *legacy_bootp_filename;
|
||||
|
||||
int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev);
|
||||
void net_client_uninit(NICInfo *nd);
|
||||
int net_client_parse(QemuOptsList *opts_list, const char *str);
|
||||
int net_init_clients(void);
|
||||
void net_check_clients(void);
|
||||
void net_cleanup(void);
|
||||
void net_set_boot_mask(int boot_mask);
|
||||
void net_host_device_add(Monitor *mon, const QDict *qdict);
|
||||
|
@@ -728,10 +728,6 @@ int net_init_slirp(QemuOpts *opts,
|
||||
qemu_free(config);
|
||||
}
|
||||
|
||||
if (ret != -1 && vlan) {
|
||||
vlan->nb_host_devs++;
|
||||
}
|
||||
|
||||
qemu_free(vnet);
|
||||
|
||||
return ret;
|
||||
|
@@ -569,9 +569,5 @@ int net_init_socket(QemuOpts *opts,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vlan) {
|
||||
vlan->nb_host_devs++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -714,10 +714,6 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vlan) {
|
||||
vlan->nb_host_devs++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -441,9 +441,5 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
|
||||
}
|
||||
}
|
||||
|
||||
if (vlan) {
|
||||
vlan->nb_host_devs++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -127,9 +127,5 @@ int net_init_vde(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vlan) {
|
||||
vlan->nb_host_devs++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
BIN
pc-bios/bios.bin
BIN
pc-bios/bios.bin
Binary file not shown.
@@ -1180,6 +1180,9 @@ static CharDriverState *qemu_chr_open_tty(QemuOpts *opts)
|
||||
int fd;
|
||||
|
||||
TFR(fd = open(filename, O_RDWR | O_NONBLOCK));
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
tty_serial_init(fd, 115200, 'N', 8, 1);
|
||||
chr = qemu_chr_open_fd(fd, fd);
|
||||
if (!chr) {
|
||||
|
@@ -2,6 +2,8 @@
|
||||
#ifndef QEMU_COMMON_H
|
||||
#define QEMU_COMMON_H
|
||||
|
||||
#include "config-host.h"
|
||||
|
||||
#define QEMU_NORETURN __attribute__ ((__noreturn__))
|
||||
#ifdef CONFIG_GCC_ATTRIBUTE_WARN_UNUSED_RESULT
|
||||
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
@@ -29,7 +31,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
#include "config-host.h"
|
||||
|
||||
#ifndef O_LARGEFILE
|
||||
#define O_LARGEFILE 0
|
||||
|
@@ -467,7 +467,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
} while (persistent || nb_fds > 1);
|
||||
qemu_free(data);
|
||||
qemu_vfree(data);
|
||||
|
||||
close(sharing_fds[0]);
|
||||
bdrv_close(bs);
|
||||
|
@@ -404,6 +404,12 @@ ETEXI
|
||||
|
||||
DEF("device", HAS_ARG, QEMU_OPTION_device,
|
||||
"-device driver[,options] add device\n")
|
||||
STEXI
|
||||
@item -device @var{driver}[,@var{option}[,...]]
|
||||
Add device @var{driver}. Depending on the device type,
|
||||
@var{option} (typically @var{key}=@var{value}) may be useful.
|
||||
ETEXI
|
||||
|
||||
DEF("name", HAS_ARG, QEMU_OPTION_name,
|
||||
"-name string1[,process=string2] set the name of the guest\n"
|
||||
" string1 sets the window title and string2 the process name (on Linux)\n")
|
||||
@@ -1893,6 +1899,8 @@ ETEXI
|
||||
DEF("nodefaults", 0, QEMU_OPTION_nodefaults, \
|
||||
"-nodefaults don't create default devices.\n")
|
||||
STEXI
|
||||
@item -nodefaults
|
||||
Don't create default devices.
|
||||
ETEXI
|
||||
|
||||
#ifndef _WIN32
|
||||
@@ -1915,10 +1923,6 @@ Immediately before starting guest execution, drop root privileges, switching
|
||||
to the specified user.
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
#if defined(TARGET_SPARC) || defined(TARGET_PPC)
|
||||
DEF("prom-env", HAS_ARG, QEMU_OPTION_prom_env,
|
||||
"-prom-env variable=value\n"
|
||||
@@ -1934,6 +1938,19 @@ DEF("old-param", 0, QEMU_OPTION_old_param,
|
||||
#endif
|
||||
DEF("readconfig", HAS_ARG, QEMU_OPTION_readconfig,
|
||||
"-readconfig <file>\n")
|
||||
STEXI
|
||||
@item -readconfig @var{file}
|
||||
Read device configuration from @var{file}.
|
||||
ETEXI
|
||||
DEF("writeconfig", HAS_ARG, QEMU_OPTION_writeconfig,
|
||||
"-writeconfig <file>\n"
|
||||
" read/write config file\n")
|
||||
STEXI
|
||||
@item -writeconfig @var{file}
|
||||
Write device configuration to @var{file}.
|
||||
ETEXI
|
||||
|
||||
HXCOMM This is the last statement. Insert new options before this line!
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
|
@@ -424,7 +424,7 @@ static int inet_parse(QemuOpts *opts, const char *str)
|
||||
__FUNCTION__, str);
|
||||
return -1;
|
||||
}
|
||||
qemu_opt_set(opts, "ipv6", "yes");
|
||||
qemu_opt_set(opts, "ipv6", "on");
|
||||
} else if (qemu_isdigit(str[0])) {
|
||||
/* IPv4 addr */
|
||||
if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) {
|
||||
@@ -432,7 +432,7 @@ static int inet_parse(QemuOpts *opts, const char *str)
|
||||
__FUNCTION__, str);
|
||||
return -1;
|
||||
}
|
||||
qemu_opt_set(opts, "ipv4", "yes");
|
||||
qemu_opt_set(opts, "ipv4", "on");
|
||||
} else {
|
||||
/* hostname */
|
||||
if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) {
|
||||
@@ -450,9 +450,9 @@ static int inet_parse(QemuOpts *opts, const char *str)
|
||||
if (h)
|
||||
qemu_opt_set(opts, "to", h+4);
|
||||
if (strstr(optstr, ",ipv4"))
|
||||
qemu_opt_set(opts, "ipv4", "yes");
|
||||
qemu_opt_set(opts, "ipv4", "on");
|
||||
if (strstr(optstr, ",ipv6"))
|
||||
qemu_opt_set(opts, "ipv6", "yes");
|
||||
qemu_opt_set(opts, "ipv6", "on");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Submodule roms/seabios updated: 5da68339ec...9fb3f4d950
2
savevm.c
2
savevm.c
@@ -1696,7 +1696,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
|
||||
sn->vm_clock_nsec = qemu_get_clock(vm_clock);
|
||||
|
||||
/* Delete old snapshots of the same name */
|
||||
if (del_existing_snapshots(mon, name) < 0) {
|
||||
if (name && del_existing_snapshots(mon, name) < 0) {
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
|
1
sdl.c
1
sdl.c
@@ -525,6 +525,7 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state
|
||||
static void toggle_full_screen(DisplayState *ds)
|
||||
{
|
||||
gui_fullscreen = !gui_fullscreen;
|
||||
do_sdl_resize(real_screen->w, real_screen->h, real_screen->format->BitsPerPixel);
|
||||
if (gui_fullscreen) {
|
||||
scaling_active = 0;
|
||||
gui_saved_grab = gui_grab;
|
||||
|
@@ -179,7 +179,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||
close(s);
|
||||
|
||||
i = 0;
|
||||
bptr = strdup(ex); /* No need to free() this */
|
||||
bptr = qemu_strdup(ex); /* No need to free() this */
|
||||
if (do_pty == 1) {
|
||||
/* Setup "slirp.telnetd -x" */
|
||||
argv[i++] = "slirp.telnetd";
|
||||
|
@@ -590,8 +590,8 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
|
||||
#define cpu_handle_mmu_fault cpu_mips_handle_mmu_fault
|
||||
void do_interrupt (CPUState *env);
|
||||
void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra);
|
||||
target_phys_addr_t do_translate_address (CPUState *env, target_ulong address,
|
||||
int rw);
|
||||
target_phys_addr_t cpu_mips_translate_address (CPUState *env, target_ulong address,
|
||||
int rw);
|
||||
|
||||
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
|
||||
{
|
||||
|
@@ -311,7 +311,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
target_phys_addr_t do_translate_address(CPUState *env, target_ulong address, int rw)
|
||||
target_phys_addr_t cpu_mips_translate_address(CPUState *env, target_ulong address, int rw)
|
||||
{
|
||||
target_phys_addr_t physical;
|
||||
int prot;
|
||||
@@ -326,10 +326,10 @@ target_phys_addr_t do_translate_address(CPUState *env, target_ulong address, int
|
||||
address, rw, access_type);
|
||||
if (ret != TLBRET_MATCH) {
|
||||
raise_mmu_exception(env, address, rw, ret);
|
||||
cpu_loop_exit();
|
||||
return -1LL;
|
||||
} else {
|
||||
return physical;
|
||||
}
|
||||
|
||||
return physical;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -276,10 +276,24 @@ void helper_dmultu (target_ulong arg1, target_ulong arg2)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
static inline target_phys_addr_t do_translate_address(target_ulong address, int rw)
|
||||
{
|
||||
target_phys_addr_t lladdr;
|
||||
|
||||
lladdr = cpu_mips_translate_address(env, address, rw);
|
||||
|
||||
if (lladdr == -1LL) {
|
||||
cpu_loop_exit();
|
||||
} else {
|
||||
return lladdr;
|
||||
}
|
||||
}
|
||||
|
||||
#define HELPER_LD_ATOMIC(name, insn) \
|
||||
target_ulong helper_##name(target_ulong arg, int mem_idx) \
|
||||
{ \
|
||||
env->lladdr = do_translate_address(env, arg, 0); \
|
||||
env->lladdr = do_translate_address(arg, 0); \
|
||||
env->llval = do_##insn(arg, mem_idx); \
|
||||
return env->llval; \
|
||||
}
|
||||
@@ -298,7 +312,7 @@ target_ulong helper_##name(target_ulong arg1, target_ulong arg2, int mem_idx) \
|
||||
env->CP0_BadVAddr = arg2; \
|
||||
helper_raise_exception(EXCP_AdES); \
|
||||
} \
|
||||
if (do_translate_address(env, arg2, 1) == env->lladdr) { \
|
||||
if (do_translate_address(arg2, 1) == env->lladdr) { \
|
||||
tmp = do_##ld_insn(arg2, mem_idx); \
|
||||
if (tmp == env->llval) { \
|
||||
do_##st_insn(arg2, arg1, mem_idx); \
|
||||
|
@@ -821,7 +821,7 @@ static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv
|
||||
static inline void check_cp0_enabled(DisasContext *ctx)
|
||||
{
|
||||
if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
|
||||
generate_exception_err(ctx, EXCP_CpU, 1);
|
||||
generate_exception_err(ctx, EXCP_CpU, 0);
|
||||
}
|
||||
|
||||
static inline void check_cp1_enabled(DisasContext *ctx)
|
||||
@@ -1451,6 +1451,8 @@ static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
|
||||
tcg_gen_rotri_i32(t1, t1, uimm);
|
||||
tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
|
||||
tcg_temp_free_i32(t1);
|
||||
} else {
|
||||
tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
|
||||
}
|
||||
opn = "rotr";
|
||||
} else {
|
||||
@@ -1489,6 +1491,8 @@ static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
|
||||
if (env->insn_flags & ISA_MIPS32R2) {
|
||||
if (uimm != 0) {
|
||||
tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
|
||||
} else {
|
||||
tcg_gen_mov_tl(cpu_gpr[rt], t0);
|
||||
}
|
||||
opn = "drotr";
|
||||
} else {
|
||||
|
@@ -731,9 +731,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
||||
/* label1: fast path */
|
||||
reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
|
||||
|
||||
tcg_out_opc_imm(s, OPC_LW, TCG_REG_V0, TCG_REG_A0,
|
||||
tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
|
||||
offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
|
||||
tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
|
||||
tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
|
||||
|
||||
addr_reg1 = TCG_REG_V0;
|
||||
#endif
|
||||
|
@@ -1036,7 +1036,7 @@ USBDevice *usb_host_device_open(const char *devname)
|
||||
qdev_prop_set_uint32(&dev->qdev, "hostaddr", filter.addr);
|
||||
qdev_prop_set_uint32(&dev->qdev, "vendorid", filter.vendor_id);
|
||||
qdev_prop_set_uint32(&dev->qdev, "productid", filter.product_id);
|
||||
qdev_init(&dev->qdev);
|
||||
qdev_init_nofail(&dev->qdev);
|
||||
return dev;
|
||||
|
||||
fail:
|
||||
|
7
vl.c
7
vl.c
@@ -4042,14 +4042,15 @@ static void tcg_cpu_exec(void)
|
||||
for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
|
||||
CPUState *env = cur_cpu = next_cpu;
|
||||
|
||||
if (!vm_running)
|
||||
break;
|
||||
if (timer_alarm_pending) {
|
||||
timer_alarm_pending = 0;
|
||||
break;
|
||||
}
|
||||
if (cpu_can_run(env))
|
||||
ret = qemu_cpu_exec(env);
|
||||
else if (env->stop)
|
||||
break;
|
||||
|
||||
if (ret == EXCP_DEBUG) {
|
||||
gdb_set_stop_cpu(env);
|
||||
debug_requested = 1;
|
||||
@@ -5968,6 +5969,8 @@ int main(int argc, char **argv, char **envp)
|
||||
if (qemu_opts_foreach(&qemu_device_opts, device_init_func, NULL, 1) != 0)
|
||||
exit(1);
|
||||
|
||||
net_check_clients();
|
||||
|
||||
if (!display_state)
|
||||
dumb_display_init();
|
||||
/* just use the first displaystate for the moment */
|
||||
|
6
vnc.c
6
vnc.c
@@ -2293,7 +2293,7 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
|
||||
static void vnc_refresh(void *opaque)
|
||||
{
|
||||
VncDisplay *vd = opaque;
|
||||
VncState *vs = NULL;
|
||||
VncState *vs = NULL, *vn = NULL;
|
||||
int has_dirty = 0, rects = 0;
|
||||
|
||||
vga_hw_update();
|
||||
@@ -2302,8 +2302,10 @@ static void vnc_refresh(void *opaque)
|
||||
|
||||
vs = vd->clients;
|
||||
while (vs != NULL) {
|
||||
vn = vs->next;
|
||||
rects += vnc_update_client(vs, has_dirty);
|
||||
vs = vs->next;
|
||||
/* vs might be free()ed here */
|
||||
vs = vn;
|
||||
}
|
||||
/* vd->timer could be NULL now if the last client disconnected,
|
||||
* in this case don't update the timer */
|
||||
|
Reference in New Issue
Block a user