diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2010-02-25 23:30:36 -0300 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2010-02-25 23:30:36 -0300 |
commit | 352de743974a48e282a5d37f053aa664404e311b (patch) | |
tree | 13a30a888ad68d5fb63746ad921bf1afc75c82d2 | |
parent | Merge commit '299e0bc52a5d56ff89ad8d7d09c82233cd8ccb6a' into stable-0.12-merge (diff) | |
parent | Merge remote branch 'qemu-kvm/uq/stable-0.12' into stable-0.12 (diff) | |
download | qemu-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-- | Changelog | 52 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | block/curl.c | 2 | ||||
-rw-r--r-- | block/qcow2-cluster.c | 20 | ||||
-rw-r--r-- | block/qcow2.h | 6 | ||||
-rw-r--r-- | block/vvfat.c | 10 | ||||
-rw-r--r-- | cpu-exec.c | 12 | ||||
-rw-r--r-- | hw/ide/core.c | 59 | ||||
-rw-r--r-- | hw/ide/internal.h | 5 | ||||
-rw-r--r-- | hw/usb-serial.c | 28 | ||||
-rw-r--r-- | hw/virtio-blk.c | 93 | ||||
-rw-r--r-- | hw/virtio-net.c | 10 | ||||
-rw-r--r-- | json-lexer.c | 16 | ||||
-rw-r--r-- | json-parser.c | 3 | ||||
-rw-r--r-- | net.c | 64 | ||||
-rw-r--r-- | net.h | 3 | ||||
-rw-r--r-- | net/slirp.c | 4 | ||||
-rw-r--r-- | net/socket.c | 4 | ||||
-rw-r--r-- | net/tap-win32.c | 4 | ||||
-rw-r--r-- | net/tap.c | 4 | ||||
-rw-r--r-- | net/vde.c | 4 | ||||
-rw-r--r-- | pc-bios/bios.bin | bin | 131072 -> 131072 bytes | |||
-rw-r--r-- | qemu-char.c | 3 | ||||
-rw-r--r-- | qemu-sockets.c | 8 | ||||
m--------- | roms/seabios | 0 | ||||
-rw-r--r-- | slirp/misc.c | 2 | ||||
-rw-r--r-- | target-mips/cpu.h | 4 | ||||
-rw-r--r-- | target-mips/helper.c | 8 | ||||
-rw-r--r-- | target-mips/op_helper.c | 18 | ||||
-rw-r--r-- | target-mips/translate.c | 6 | ||||
-rw-r--r-- | tcg/mips/tcg-target.c | 4 | ||||
-rw-r--r-- | vl.c | 7 |
32 files changed, 328 insertions, 137 deletions
@@ -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) @@ -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 *))); @@ -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; } @@ -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; } @@ -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; } diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin Binary files differindex 1741eeced..855f46834 100644 --- a/pc-bios/bios.bin +++ b/pc-bios/bios.bin 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 @@ -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 */ |