aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2010-02-25 23:30:36 -0300
committerMarcelo Tosatti <mtosatti@redhat.com>2010-02-25 23:30:36 -0300
commit352de743974a48e282a5d37f053aa664404e311b (patch)
tree13a30a888ad68d5fb63746ad921bf1afc75c82d2
parentMerge commit '299e0bc52a5d56ff89ad8d7d09c82233cd8ccb6a' into stable-0.12-merge (diff)
parentMerge remote branch 'qemu-kvm/uq/stable-0.12' into stable-0.12 (diff)
downloadqemu-kvm-352de743974a48e282a5d37f053aa664404e311b.tar.gz
qemu-kvm-352de743974a48e282a5d37f053aa664404e311b.tar.bz2
qemu-kvm-352de743974a48e282a5d37f053aa664404e311b.zip
Merge commit '6173d56bdcb53389c54e803873e6bf8f87836a4f' into stable-0.12-merge
* commit '6173d56bdcb53389c54e803873e6bf8f87836a4f': (27 commits) Update version and change for 0.12.3 release qcow2: Fix access after end of array ide save/restore pio/atapi cmd transfer fields and io buffer net: Monitor command set_link finds only VLAN clients, fix net: info network shows only VLAN clients, fix net: net_check_clients() checks only VLAN clients, fix net: Fix bogus "Warning: vlan 0 with no nics" with -device net: net_check_clients() runs too early to see -device, fix net: Remove unused net_client_uninit() don't dereference NULL after failed strdup virtio-net: fix network stall under load json: fix PRId64 on Win32 fix inet_parse typo iothread: fix vcpu stop with smp tcg segfault due to buffer overrun in usb-serial qcow2: Fix signedness bugs Do not ignore error, if open file failed (-serial /dev/tty) pc-bios: update to newer version of (stable) seabios kvm: Fix eflags corruption in kvm mode target-mips: fix ROTR and DROTR by zero ... Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> modified: net/slirp.c
-rw-r--r--Changelog52
-rw-r--r--VERSION2
-rw-r--r--block/curl.c2
-rw-r--r--block/qcow2-cluster.c20
-rw-r--r--block/qcow2.h6
-rw-r--r--block/vvfat.c10
-rw-r--r--cpu-exec.c12
-rw-r--r--hw/ide/core.c59
-rw-r--r--hw/ide/internal.h5
-rw-r--r--hw/usb-serial.c28
-rw-r--r--hw/virtio-blk.c93
-rw-r--r--hw/virtio-net.c10
-rw-r--r--json-lexer.c16
-rw-r--r--json-parser.c3
-rw-r--r--net.c64
-rw-r--r--net.h3
-rw-r--r--net/slirp.c4
-rw-r--r--net/socket.c4
-rw-r--r--net/tap-win32.c4
-rw-r--r--net/tap.c4
-rw-r--r--net/vde.c4
-rw-r--r--pc-bios/bios.binbin131072 -> 131072 bytes
-rw-r--r--qemu-char.c3
-rw-r--r--qemu-sockets.c8
m---------roms/seabios0
-rw-r--r--slirp/misc.c2
-rw-r--r--target-mips/cpu.h4
-rw-r--r--target-mips/helper.c8
-rw-r--r--target-mips/op_helper.c18
-rw-r--r--target-mips/translate.c6
-rw-r--r--tcg/mips/tcg-target.c4
-rw-r--r--vl.c7
32 files changed, 328 insertions, 137 deletions
diff --git a/Changelog b/Changelog
index dede703d3..67d0efd3a 100644
--- a/Changelog
+++ b/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)
diff --git a/VERSION b/VERSION
index 26acbf080..aa22d3ce3 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.12.2
+0.12.3
diff --git a/block/curl.c b/block/curl.c
index 5223ce879..c9c457486 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -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. */
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 4e30d161a..b13b6935f 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -219,7 +219,8 @@ 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];
@@ -560,7 +561,8 @@ 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);
@@ -704,10 +706,8 @@ err:
*
* 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;
@@ -750,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]);
@@ -763,6 +766,7 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
(cluster_offset & QCOW_OFLAG_COMPRESSED))
break;
}
+ assert(i <= nb_clusters);
nb_clusters = i;
/*
diff --git a/block/qcow2.h b/block/qcow2.h
index d9ea6abc5..de9397a3d 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -192,10 +192,8 @@ 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);
diff --git a/block/vvfat.c b/block/vvfat.c
index 063f7318c..c1acb3586 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -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 {
diff --git a/cpu-exec.c b/cpu-exec.c
index 0f085eab3..040d4741b 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -236,11 +236,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;
diff --git a/hw/ide/core.c b/hw/ide/core.c
index b6643e826..64aebc276 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2640,6 +2640,7 @@ 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);
@@ -2674,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;
@@ -2684,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),
@@ -2714,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()
}
};
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index f9a34b8a5..8869a0834 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -417,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 */
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 37293ea41..c3f340137 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -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;
}
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index a2f063974..2fd9b3fba 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -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)
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 2f201ffc7..d8a1629dc 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -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);
diff --git a/json-lexer.c b/json-lexer.c
index 53697c5ff..9d649205a 100644
--- a/json-lexer.c
+++ b/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 */
diff --git a/json-parser.c b/json-parser.c
index 7624c0f9b..2ab6f6c11 100644
--- a/json-parser.c
+++ b/json-parser.c
@@ -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 *)));
diff --git a/net.c b/net.c
index 6ef93e615..029b0d79b 100644
--- a/net.c
+++ b/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;
}
diff --git a/net.h b/net.h
index 4971fcbbb..673b3554d 100644
--- a/net.h
+++ b/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);
diff --git a/net/slirp.c b/net/slirp.c
index 3f91c4bb3..50ac0b9bb 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -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;
diff --git a/net/socket.c b/net/socket.c
index 5533737e4..442a9c790 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -569,9 +569,5 @@ int net_init_socket(QemuOpts *opts,
return -1;
}
- if (vlan) {
- vlan->nb_host_devs++;
- }
-
return 0;
}
diff --git a/net/tap-win32.c b/net/tap-win32.c
index b717c1724..8370c803b 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -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;
}
diff --git a/net/tap.c b/net/tap.c
index 0d8b42412..adbc97992 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -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;
}
diff --git a/net/vde.c b/net/vde.c
index 42b463350..0b46fa640 100644
--- a/net/vde.c
+++ b/net/vde.c
@@ -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;
}
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index 1741eeced..855f46834 100644
--- a/pc-bios/bios.bin
+++ b/pc-bios/bios.bin
Binary files differ
diff --git a/qemu-char.c b/qemu-char.c
index b13f8d4cf..5a1b535bd 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -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) {
diff --git a/qemu-sockets.c b/qemu-sockets.c
index 8850516f2..a88b2a77f 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -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;
}
diff --git a/roms/seabios b/roms/seabios
-Subproject 5da68339ecf44677b8f4f115cdf3cb1da46a9f6
+Subproject 9fb3f4d950744e97cc655b7d7b523d8bf101e4a
diff --git a/slirp/misc.c b/slirp/misc.c
index c76ad8fef..b68af6d7a 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -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";
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 97e106f47..89c28f1bf 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -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)
{
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 1e7e01608..ec8711498 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -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
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index be75af5e6..dda9e825e 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -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); \
diff --git a/target-mips/translate.c b/target-mips/translate.c
index f756ab9db..f811f50c7 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -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 {
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 8fcb5c99c..807b8fdfa 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -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
diff --git a/vl.c b/vl.c
index c9d46de0c..59f8084fa 100644
--- a/vl.c
+++ b/vl.c
@@ -4094,14 +4094,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;
@@ -6081,6 +6082,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 */