diff options
-rw-r--r-- | Changelog | 27 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | block-qcow2.c | 55 | ||||
-rw-r--r-- | block.c | 85 | ||||
-rw-r--r-- | block.h | 10 | ||||
-rw-r--r-- | block_int.h | 1 | ||||
-rw-r--r-- | console.h | 3 | ||||
-rw-r--r-- | cpu-defs.h | 2 | ||||
-rw-r--r-- | cpu-exec.c | 16 | ||||
-rw-r--r-- | exec.c | 12 | ||||
-rw-r--r-- | hw/cirrus_vga.c | 5 | ||||
-rw-r--r-- | hw/e1000.c | 4 | ||||
-rw-r--r-- | hw/lsi53c895a.c | 2 | ||||
-rw-r--r-- | hw/usb-msd.c | 6 | ||||
-rw-r--r-- | hw/usb.h | 5 | ||||
-rw-r--r-- | hw/vga.c | 13 | ||||
-rw-r--r-- | hw/virtio-net.c | 2 | ||||
-rw-r--r-- | hw/virtio.c | 7 | ||||
-rw-r--r-- | kvm-all.c | 6 | ||||
-rw-r--r-- | monitor.c | 47 | ||||
-rw-r--r-- | qemu-char.c | 44 | ||||
-rw-r--r-- | qemu-char.h | 1 | ||||
-rw-r--r-- | qemu-img.c | 8 | ||||
-rw-r--r-- | savevm.c | 4 | ||||
-rw-r--r-- | sdl.c | 2 | ||||
-rw-r--r-- | target-i386/helper.c | 8 | ||||
-rw-r--r-- | target-i386/op_helper.c | 2 | ||||
-rw-r--r-- | vl.c | 76 |
28 files changed, 244 insertions, 211 deletions
@@ -1,3 +1,30 @@ +version 0.10.1: + + - virtio-net: allow masking of notifications on empty queue (Alex Williamson) + - e1000: fix rx descriptor low threshold logic (Alex Willaimson) + - x86 tcg: add NULL checks to lsl instruction (Jan Kiszka) + - kvm vga: fix screen corruption with -std-vga and Windows (Avi Kivity) + - kvm vga: fix screen corruption with Ubuntu installations (Glauber Costa) + - virtio-net: check right return size on sg list (Alex Williamson) + - Make qemu_announce_self handle holes (live migration after hotplug) + (Marcelo Tosatti) + - Revert r6804-r6808 (qcow2 allocation info). This series of changes added + a high cost to startup for large qcow2 images (Anthony Liguori) + - qemu-img: fix help message (Aurelien Jarno) + - Fix build for non-default installs of SDL (Anthony Liguori) + - Fix race condition in env->interrupt_request. When using TCG and a dynticks + host timer, this condition could cause TCG to get stuck in an infinite + loop (Aurelien Jarno) + - Fix reading encrypted hard disk passwords during early startup (Jan Kiszka) + - Fix encrypted disk reporting in 'info block' (Jan Kiszka) + - Fix console size with tiny displays (MusicPal) (Jan Kiszka) + - Improve error handling in bdrv_open2 (Jan Kiszka) + - Avoid leaking data in mux'ed character devices (Jan Kiszka) + - Fix initial character device reset (no banner in monitor) (Jan Kiszka) + - Fix cpuid KVM crash on i386 host (Lubomir Rintel) + - Fix SLES10sp2 installation by adding ISTAT1 register to LSI SCSI emulation + (Ryan Harper) + version 0.10.0: - TCG support (No longer requires GCC 3.x) @@ -1 +1 @@ -0.10.0 +0.10.1 diff --git a/block-qcow2.c b/block-qcow2.c index 465dcd6d42..957e419cae 100644 --- a/block-qcow2.c +++ b/block-qcow2.c @@ -143,10 +143,6 @@ typedef struct BDRVQcowState { uint32_t crypt_method_header; AES_KEY aes_encrypt_key; AES_KEY aes_decrypt_key; - - int64_t highest_alloc; /* highest cluester allocated (in clusters) */ - int64_t nc_free; /* num of free clusters below highest_alloc */ - uint64_t snapshots_offset; int snapshots_size; int nb_snapshots; @@ -174,8 +170,6 @@ static void free_clusters(BlockDriverState *bs, #ifdef DEBUG_ALLOC static void check_refcounts(BlockDriverState *bs); #endif -static void scan_refcount(BlockDriverState *bs, int64_t *high, int64_t *free); - static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename) { @@ -276,8 +270,6 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags) if (refcount_init(bs) < 0) goto fail; - scan_refcount(bs, &s->highest_alloc, &s->nc_free); - /* read the backing file name */ if (header.backing_file_offset != 0) { len = header.backing_file_size; @@ -1646,8 +1638,6 @@ static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) bdi->cluster_size = s->cluster_size; bdi->vm_state_offset = (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits); - bdi->highest_alloc = s->highest_alloc << s->cluster_bits; - bdi->num_free_bytes = s->nc_free << s->cluster_bits; return 0; } @@ -2166,39 +2156,6 @@ static int load_refcount_block(BlockDriverState *bs, return 0; } -static void scan_refcount(BlockDriverState *bs, int64_t *high, int64_t *free) -{ - BDRVQcowState *s = bs->opaque; - int64_t refcnt_index, cluster_index, cluster_end, h = 0, f = 0; - int64_t tail = 0; /* do not count last consecutive free entries */ - - for (refcnt_index=0; refcnt_index < s->refcount_table_size; refcnt_index++){ - if (s->refcount_table[refcnt_index] == 0) { - f += 1 << (s->cluster_bits - REFCOUNT_SHIFT); - tail += 1 << (s->cluster_bits - REFCOUNT_SHIFT); - continue; - } - cluster_index = refcnt_index << (s->cluster_bits - REFCOUNT_SHIFT); - cluster_end = (refcnt_index + 1) << (s->cluster_bits - REFCOUNT_SHIFT); - for ( ; cluster_index < cluster_end; cluster_index++) { - if (get_refcount(bs, cluster_index) == 0) { - f++; - tail++; - } - else { - h = cluster_index; - tail = 0; - } - } - } - - f -= tail; - if (free) - *free = f; - if (high) - *high = (h+1); -} - static int get_refcount(BlockDriverState *bs, int64_t cluster_index) { BDRVQcowState *s = bs->opaque; @@ -2239,12 +2196,6 @@ retry: size, (s->free_cluster_index - nb_clusters) << s->cluster_bits); #endif - - if (s->highest_alloc < s->free_cluster_index) { - s->nc_free += (s->free_cluster_index - s->highest_alloc); - s->highest_alloc = s->free_cluster_index; - } - return (s->free_cluster_index - nb_clusters) << s->cluster_bits; } @@ -2418,12 +2369,6 @@ static int update_cluster_refcount(BlockDriverState *bs, block_index = cluster_index & ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); refcount = be16_to_cpu(s->refcount_block_cache[block_index]); - - if (refcount == 1 && addend == -1) - s->nc_free += 1; - else if (refcount == 0 && addend == 1) - s->nc_free -= 1; - refcount += addend; if (refcount < 0 || refcount > 0xffff) return -EINVAL; @@ -311,8 +311,6 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags) int ret; bs = bdrv_new(""); - if (!bs) - return -ENOMEM; ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL); if (ret < 0) { bdrv_delete(bs); @@ -338,6 +336,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, bs->read_only = 0; bs->is_temporary = 0; bs->encrypted = 0; + bs->valid_key = 0; if (flags & BDRV_O_SNAPSHOT) { BlockDriverState *bs1; @@ -349,12 +348,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, /* if there is a backing file, use it */ bs1 = bdrv_new(""); - if (!bs1) { - return -ENOMEM; - } - if (bdrv_open(bs1, filename, 0) < 0) { + ret = bdrv_open(bs1, filename, 0); + if (ret < 0) { bdrv_delete(bs1); - return -1; + return ret; } total_size = bdrv_getlength(bs1) >> SECTOR_BITS; @@ -372,9 +369,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, else realpath(filename, backing_filename); - if (bdrv_create(&bdrv_qcow2, tmp_filename, - total_size, backing_filename, 0) < 0) { - return -1; + ret = bdrv_create(&bdrv_qcow2, tmp_filename, + total_size, backing_filename, 0); + if (ret < 0) { + return ret; } filename = tmp_filename; bs->is_temporary = 1; @@ -383,14 +381,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, pstrcpy(bs->filename, sizeof(bs->filename), filename); if (flags & BDRV_O_FILE) { drv = find_protocol(filename); - if (!drv) - return -ENOENT; - } else { - if (!drv) { - drv = find_image_format(filename); - if (!drv) - return -1; - } + } else if (!drv) { + drv = find_image_format(filename); + } + if (!drv) { + ret = -ENOENT; + goto unlink_and_fail; } bs->drv = drv; bs->opaque = qemu_mallocz(drv->instance_size); @@ -409,6 +405,9 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, qemu_free(bs->opaque); bs->opaque = NULL; bs->drv = NULL; + unlink_and_fail: + if (bs->is_temporary) + unlink(filename); return ret; } if (drv->bdrv_getlength) { @@ -422,15 +421,13 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, if (bs->backing_file[0] != '\0') { /* if there is a backing file, use it */ bs->backing_hd = bdrv_new(""); - if (!bs->backing_hd) { - fail: - bdrv_close(bs); - return -ENOMEM; - } path_combine(backing_filename, sizeof(backing_filename), filename, bs->backing_file); - if (bdrv_open(bs->backing_hd, backing_filename, open_flags) < 0) - goto fail; + ret = bdrv_open(bs->backing_hd, backing_filename, open_flags); + if (ret < 0) { + bdrv_close(bs); + return ret; + } } /* call the change callback */ @@ -970,6 +967,15 @@ int bdrv_is_encrypted(BlockDriverState *bs) return bs->encrypted; } +int bdrv_key_required(BlockDriverState *bs) +{ + BlockDriverState *backing_hd = bs->backing_hd; + + if (backing_hd && backing_hd->encrypted && !backing_hd->valid_key) + return 1; + return (bs->encrypted && !bs->valid_key); +} + int bdrv_set_key(BlockDriverState *bs, const char *key) { int ret; @@ -982,7 +988,9 @@ int bdrv_set_key(BlockDriverState *bs, const char *key) } if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key) return -1; - return bs->drv->bdrv_set_key(bs, key); + ret = bs->drv->bdrv_set_key(bs, key); + bs->valid_key = (ret == 0); + return ret; } void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size) @@ -1015,12 +1023,12 @@ BlockDriverState *bdrv_find(const char *name) return NULL; } -void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque) +void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque) { BlockDriverState *bs; for (bs = bdrv_first; bs != NULL; bs = bs->next) { - it(opaque, bs->device_name); + it(opaque, bs); } } @@ -1105,8 +1113,7 @@ void bdrv_info(void) } term_printf(" ro=%d", bs->read_only); term_printf(" drv=%s", bs->drv->format_name); - if (bs->encrypted) - term_printf(" encrypted"); + term_printf(" encrypted=%d", bdrv_is_encrypted(bs)); } else { term_printf(" [not inserted]"); } @@ -1118,7 +1125,6 @@ void bdrv_info(void) void bdrv_info_stats (void) { BlockDriverState *bs; - BlockDriverInfo bdi; for (bs = bdrv_first; bs != NULL; bs = bs->next) { term_printf ("%s:" @@ -1126,18 +1132,23 @@ void bdrv_info_stats (void) " wr_bytes=%" PRIu64 " rd_operations=%" PRIu64 " wr_operations=%" PRIu64 - , + "\n", bs->device_name, bs->rd_bytes, bs->wr_bytes, bs->rd_ops, bs->wr_ops); - if (bdrv_get_info(bs, &bdi) == 0) - term_printf(" high=%" PRId64 - " bytes_free=%" PRId64, - bdi.highest_alloc, bdi.num_free_bytes); - term_printf("\n"); } } +const char *bdrv_get_encrypted_filename(BlockDriverState *bs) +{ + if (bs->backing_hd && bs->backing_hd->encrypted) + return bs->backing_file; + else if (bs->encrypted) + return bs->filename; + else + return NULL; +} + void bdrv_get_backing_filename(BlockDriverState *bs, char *filename, int filename_size) { @@ -26,8 +26,6 @@ typedef struct BlockDriverInfo { int cluster_size; /* offset at which the VM state can be saved (0 if not possible) */ int64_t vm_state_offset; - int64_t highest_alloc; /* highest allocated block offset (in bytes) */ - int64_t num_free_bytes; /* below highest_alloc */ } BlockDriverInfo; typedef struct QEMUSnapshotInfo { @@ -103,8 +101,6 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num, BlockDriverCompletionFunc *cb, void *opaque); void bdrv_aio_cancel(BlockDriverAIOCB *acb); -int qemu_key_check(BlockDriverState *bs, const char *name); - /* Ensure contents are flushed to disk. */ void bdrv_flush(BlockDriverState *bs); void bdrv_flush_all(void); @@ -141,9 +137,12 @@ void bdrv_set_change_cb(BlockDriverState *bs, void (*change_cb)(void *opaque), void *opaque); void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size); BlockDriverState *bdrv_find(const char *name); -void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque); +void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), + void *opaque); int bdrv_is_encrypted(BlockDriverState *bs); +int bdrv_key_required(BlockDriverState *bs); int bdrv_set_key(BlockDriverState *bs, const char *key); +int bdrv_query_missing_keys(void); void bdrv_iterate_format(void (*it)(void *opaque, const char *name), void *opaque); const char *bdrv_get_device_name(BlockDriverState *bs); @@ -151,6 +150,7 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors); int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi); +const char *bdrv_get_encrypted_filename(BlockDriverState *bs); void bdrv_get_backing_filename(BlockDriverState *bs, char *filename, int filename_size); int bdrv_snapshot_create(BlockDriverState *bs, diff --git a/block_int.h b/block_int.h index e1943aaa64..44eb280684 100644 --- a/block_int.h +++ b/block_int.h @@ -96,6 +96,7 @@ struct BlockDriverState { int removable; /* if true, the media can be removed */ int locked; /* if true, the media cannot temporarily be ejected */ int encrypted; /* if true, the media is encrypted */ + int valid_key; /* if true, a valid encryption key has been set */ int sg; /* if true, the device is a /dev/sg* */ /* event callback when inserting/removing */ void (*change_cb)(void *opaque); @@ -302,10 +302,9 @@ void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1 void term_print_filename(const char *filename); void term_flush(void); void term_print_help(void); -void monitor_readline(const char *prompt, int is_password, - char *buf, int buf_size); void monitor_suspend(void); void monitor_resume(void); +int monitor_read_bdrv_key(BlockDriverState *bs); /* readline.c */ typedef void ReadLineFunc(void *opaque, const char *str); diff --git a/cpu-defs.h b/cpu-defs.h index 758fa9f2ca..aa46fc3bce 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -27,6 +27,7 @@ #include "config.h" #include <setjmp.h> #include <inttypes.h> +#include <signal.h> #include "osdep.h" #include "sys-queue.h" @@ -170,6 +171,7 @@ typedef struct CPUWatchpoint { memory was accessed */ \ uint32_t halted; /* Nonzero if the CPU is in suspend state */ \ uint32_t interrupt_request; \ + volatile sig_atomic_t exit_request; \ /* The meaning of the MMU modes is defined in the target code. */ \ CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \ target_phys_addr_t iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \ diff --git a/cpu-exec.c b/cpu-exec.c index f7be38df50..7607e240b5 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -311,7 +311,7 @@ int cpu_exec(CPUState *env1) env->exception_index = -1; } #ifdef USE_KQEMU - if (kqemu_is_ok(env) && env->interrupt_request == 0) { + if (kqemu_is_ok(env) && env->interrupt_request == 0 && env->exit_request == 0) { int ret; env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK); ret = kqemu_cpu_exec(env); @@ -326,7 +326,7 @@ int cpu_exec(CPUState *env1) } else if (ret == 2) { /* softmmu execution needed */ } else { - if (env->interrupt_request != 0) { + if (env->interrupt_request != 0 || env->exit_request != 0) { /* hardware interrupt will be executed just after */ } else { /* otherwise, we restart */ @@ -525,11 +525,11 @@ int cpu_exec(CPUState *env1) the program flow was changed */ next_tb = 0; } - if (interrupt_request & CPU_INTERRUPT_EXIT) { - env->interrupt_request &= ~CPU_INTERRUPT_EXIT; - env->exception_index = EXCP_INTERRUPT; - cpu_loop_exit(); - } + } + if (unlikely(env->exit_request)) { + env->exit_request = 0; + env->exception_index = EXCP_INTERRUPT; + cpu_loop_exit(); } #ifdef DEBUG_EXEC if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) { @@ -599,7 +599,7 @@ int cpu_exec(CPUState *env1) TB, but before it is linked into a potentially infinite loop and becomes env->current_tb. Avoid starting execution if there is a pending interrupt. */ - if (unlikely (env->interrupt_request & CPU_INTERRUPT_EXIT)) + if (unlikely (env->exit_request)) env->current_tb = NULL; while (env->current_tb) { @@ -523,6 +523,7 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id) qemu_get_be32s(f, &env->halted); qemu_get_be32s(f, &env->interrupt_request); + env->interrupt_request &= ~CPU_INTERRUPT_EXIT; tlb_flush(env, 1); return 0; @@ -1501,9 +1502,12 @@ void cpu_interrupt(CPUState *env, int mask) #endif int old_mask; + if (mask & CPU_INTERRUPT_EXIT) { + env->exit_request = 1; + mask &= ~CPU_INTERRUPT_EXIT; + } + old_mask = env->interrupt_request; - /* FIXME: This is probably not threadsafe. A different thread could - be in the middle of a read-modify-write operation. */ env->interrupt_request |= mask; #if defined(USE_NPTL) /* FIXME: TB unchaining isn't SMP safe. For now just ignore the @@ -1514,10 +1518,8 @@ void cpu_interrupt(CPUState *env, int mask) if (use_icount) { env->icount_decr.u16.high = 0xffff; #ifndef CONFIG_USER_ONLY - /* CPU_INTERRUPT_EXIT isn't a real interrupt. It just means - an async event happened and we need to process it. */ if (!can_do_io(env) - && (mask & ~(old_mask | CPU_INTERRUPT_EXIT)) != 0) { + && (mask & ~old_mask) != 0) { cpu_abort(env, "Raised interrupt while not in I/O function"); } #endif diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index 8aade84846..2ff80d3316 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -2637,11 +2637,16 @@ static void map_linear_vram(CirrusVGAState *s) s->lfb_vram_mapped = 0; + cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000, + (s->vram_offset + s->cirrus_bank_base[0]) | IO_MEM_UNASSIGNED); + cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000, + (s->vram_offset + s->cirrus_bank_base[1]) | IO_MEM_UNASSIGNED); if (!(s->cirrus_srcptr != s->cirrus_srcptr_end) && !((s->sr[0x07] & 0x01) == 0) && !((s->gr[0x0B] & 0x14) == 0x14) && !(s->gr[0x0B] & 0x02)) { + vga_dirty_log_stop((VGAState *)s); cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000, (s->vram_offset + s->cirrus_bank_base[0]) | IO_MEM_RAM); cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000, diff --git a/hw/e1000.c b/hw/e1000.c index e6155d6a69..1644201d6e 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -666,8 +666,8 @@ e1000_receive(void *opaque, const uint8_t *buf, int size) n = E1000_ICS_RXT0; if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH]) rdt += s->mac_reg[RDLEN] / sizeof(desc); - if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) << s->rxbuf_min_shift >= - s->mac_reg[RDLEN]) + if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) <= s->mac_reg[RDLEN] >> + s->rxbuf_min_shift) n |= E1000_ICS_RXDMT0; set_ics(s, 0, n); diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 36ee28e714..1f4f8b7ef7 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -1369,6 +1369,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) CASE_GET_REG32(dsa, 0x10) case 0x14: /* ISTAT0 */ return s->istat0; + case 0x15: /* ISTAT1 */ + return s->istat1; case 0x16: /* MBOX0 */ return s->mbox0; case 0x17: /* MBOX1 */ diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 342b0e873a..0c8d9cca83 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -11,6 +11,7 @@ #include "usb.h" #include "block.h" #include "scsi-disk.h" +#include "console.h" //#define DEBUG_MSD @@ -513,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev) qemu_free(s); } -USBDevice *usb_msd_init(const char *filename) +USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) { MSDState *s; BlockDriverState *bdrv; @@ -552,9 +553,8 @@ USBDevice *usb_msd_init(const char *filename) bdrv = bdrv_new("usb"); if (bdrv_open2(bdrv, filename, 0, drv) < 0) goto fail; - if (qemu_key_check(bdrv, filename)) - goto fail; s->bs = bdrv; + *pbs = bdrv; s->dev.speed = USB_SPEED_FULL; s->dev.handle_packet = usb_generic_handle_packet; @@ -21,6 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + +#include "block.h" + #define USB_TOKEN_SETUP 0x2d #define USB_TOKEN_IN 0x69 /* device -> host */ #define USB_TOKEN_OUT 0xe1 /* host -> device */ @@ -250,7 +253,7 @@ USBDevice *usb_keyboard_init(void); void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *)); /* usb-msd.c */ -USBDevice *usb_msd_init(const char *filename); +USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs); /* usb-net.c */ USBDevice *usb_net_init(NICInfo *nd); @@ -2482,6 +2482,17 @@ int isa_vga_mm_init(uint8_t *vga_ram_base, return 0; } +static void pci_vga_write_config(PCIDevice *d, + uint32_t address, uint32_t val, int len) +{ + PCIVGAState *pvs = container_of(d, PCIVGAState, dev); + VGAState *s = &pvs->vga_state; + + vga_dirty_log_stop(s); + pci_default_write_config(d, address, val, len); + vga_dirty_log_start(s); +} + int pci_vga_init(PCIBus *bus, uint8_t *vga_ram_base, unsigned long vga_ram_offset, int vga_ram_size, unsigned long vga_bios_offset, int vga_bios_size) @@ -2492,7 +2503,7 @@ int pci_vga_init(PCIBus *bus, uint8_t *vga_ram_base, d = (PCIVGAState *)pci_register_device(bus, "VGA", sizeof(PCIVGAState), - -1, NULL, NULL); + -1, NULL, pci_vga_write_config); if (!d) return -1; s = &d->vga_state; diff --git a/hw/virtio-net.c b/hw/virtio-net.c index e83d1019c1..ad55bb7610 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -228,7 +228,7 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) } if (elem.out_sg[0].iov_len < sizeof(ctrl) || - elem.out_sg[elem.in_num - 1].iov_len < sizeof(status)) { + elem.in_sg[elem.in_num - 1].iov_len < sizeof(status)) { fprintf(stderr, "virtio-net ctrl header not in correct element\n"); exit(1); } diff --git a/hw/virtio.c b/hw/virtio.c index b94ab0f054..08ea16dee5 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -726,9 +726,10 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, void virtio_notify(VirtIODevice *vdev, VirtQueue *vq) { - /* Always notify when queue is empty */ - if ((vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx) && - (vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT)) + /* Always notify when queue is empty (when feature acknowledge) */ + if ((vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT) && + (!(vdev->features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) || + (vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx))) return; vdev->isr |= 0x01; @@ -445,7 +445,7 @@ int kvm_cpu_exec(CPUState *env) do { kvm_arch_pre_run(env, run); - if ((env->interrupt_request & CPU_INTERRUPT_EXIT)) { + if (env->exit_request) { dprintf("interrupt exit requested\n"); ret = 0; break; @@ -512,8 +512,8 @@ int kvm_cpu_exec(CPUState *env) } } while (ret > 0); - if ((env->interrupt_request & CPU_INTERRUPT_EXIT)) { - env->interrupt_request &= ~CPU_INTERRUPT_EXIT; + if (env->exit_request) { + env->exit_request = 0; env->exception_index = EXCP_INTERRUPT; } @@ -76,6 +76,8 @@ static uint8_t term_outbuf[1024]; static int term_outbuf_index; static void monitor_start_input(void); +static void monitor_readline(const char *prompt, int is_password, + char *buf, int buf_size); static CPUState *mon_cpu = NULL; @@ -433,7 +435,7 @@ static void do_change_block(const char *device, const char *filename, const char if (eject_device(bs, 0) < 0) return; bdrv_open2(bs, filename, 0, drv); - qemu_key_check(bs, filename); + monitor_read_bdrv_key(bs); } static void do_change_vnc(const char *target, const char *arg) @@ -494,9 +496,24 @@ static void do_stop(void) vm_stop(EXCP_INTERRUPT); } +static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs) +{ + int *err = opaque; + + if (bdrv_key_required(bs)) + *err = monitor_read_bdrv_key(bs); + else + *err = 0; +} + static void do_cont(void) { - vm_start(); + int err = 0; + + bdrv_iterate(encrypted_bdrv_it, &err); + /* only resume the vm if all keys are set and valid */ + if (!err) + vm_start(); } #ifdef CONFIG_GDBSTUB @@ -2679,8 +2696,9 @@ static void file_completion(const char *input) closedir(ffs); } -static void block_completion_it(void *opaque, const char *name) +static void block_completion_it(void *opaque, BlockDriverState *bs) { + const char *name = bdrv_get_device_name(bs); const char *input = opaque; if (input[0] == '\0' || @@ -2891,8 +2909,8 @@ static void monitor_readline_cb(void *opaque, const char *input) monitor_readline_started = 0; } -void monitor_readline(const char *prompt, int is_password, - char *buf, int buf_size) +static void monitor_readline(const char *prompt, int is_password, + char *buf, int buf_size) { int i; int old_focus[MAX_MON]; @@ -2922,3 +2940,22 @@ void monitor_readline(const char *prompt, int is_password, monitor_hd[i]->focus = old_focus[i]; } } + +int monitor_read_bdrv_key(BlockDriverState *bs) +{ + char password[256]; + int i; + + if (!bdrv_is_encrypted(bs)) + return 0; + + term_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs), + bdrv_get_encrypted_filename(bs)); + for(i = 0; i < 3; i++) { + monitor_readline("Password: ", 1, password, sizeof(password)); + if (bdrv_set_key(bs, password) == 0) + return 0; + term_printf("invalid password\n"); + } + return -EPERM; +} diff --git a/qemu-char.c b/qemu-char.c index 7cdeffd61e..1fd3aefe38 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -101,6 +101,10 @@ /***********************************************************/ /* character device */ +static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs = + TAILQ_HEAD_INITIALIZER(chardevs); +static int initial_reset_issued; + static void qemu_chr_event(CharDriverState *s, int event) { if (!s->chr_event) @@ -118,12 +122,23 @@ static void qemu_chr_reset_bh(void *opaque) void qemu_chr_reset(CharDriverState *s) { - if (s->bh == NULL) { + if (s->bh == NULL && initial_reset_issued) { s->bh = qemu_bh_new(qemu_chr_reset_bh, s); qemu_bh_schedule(s->bh); } } +void qemu_chr_initial_reset(void) +{ + CharDriverState *chr; + + initial_reset_issued = 1; + + TAILQ_FOREACH(chr, &chardevs, next) { + qemu_chr_reset(chr); + } +} + int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len) { return s->chr_write(s, buf, len); @@ -210,12 +225,15 @@ typedef struct { IOEventHandler *chr_event[MAX_MUX]; void *ext_opaque[MAX_MUX]; CharDriverState *drv; - unsigned char buffer[MUX_BUFFER_SIZE]; - int prod; - int cons; int mux_cnt; int term_got_escape; int max_size; + /* Intermediate input buffer allows to catch escape sequences even if the + currently active device is not accepting any input - but only until it + is full as well. */ + unsigned char buffer[MAX_MUX][MUX_BUFFER_SIZE]; + int prod[MAX_MUX]; + int cons[MAX_MUX]; } MuxDriver; @@ -345,11 +363,11 @@ static void mux_chr_accept_input(CharDriverState *chr) int m = chr->focus; MuxDriver *d = chr->opaque; - while (d->prod != d->cons && + while (d->prod[m] != d->cons[m] && d->chr_can_read[m] && d->chr_can_read[m](d->ext_opaque[m])) { d->chr_read[m](d->ext_opaque[m], - &d->buffer[d->cons++ & MUX_BUFFER_MASK], 1); + &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1); } } @@ -357,11 +375,12 @@ static int mux_chr_can_read(void *opaque) { CharDriverState *chr = opaque; MuxDriver *d = chr->opaque; + int m = chr->focus; - if ((d->prod - d->cons) < MUX_BUFFER_SIZE) + if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE) return 1; - if (d->chr_can_read[chr->focus]) - return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]); + if (d->chr_can_read[m]) + return d->chr_can_read[m](d->ext_opaque[m]); return 0; } @@ -376,12 +395,12 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size) for(i = 0; i < size; i++) if (mux_proc_byte(chr, d, buf[i])) { - if (d->prod == d->cons && + if (d->prod[m] == d->cons[m] && d->chr_can_read[m] && d->chr_can_read[m](d->ext_opaque[m])) d->chr_read[m](d->ext_opaque[m], &buf[i], 1); else - d->buffer[d->prod++ & MUX_BUFFER_MASK] = buf[i]; + d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK] = buf[i]; } } @@ -2076,9 +2095,6 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, return NULL; } -static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs -= TAILQ_HEAD_INITIALIZER(chardevs); - CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s)) { const char *p; diff --git a/qemu-char.h b/qemu-char.h index bc0fcf3259..9ff6b99c45 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -74,6 +74,7 @@ void qemu_chr_add_handlers(CharDriverState *s, void *opaque); int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg); void qemu_chr_reset(CharDriverState *s); +void qemu_chr_initial_reset(void); int qemu_chr_can_read(CharDriverState *s); void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); void qemu_chr_accept_input(CharDriverState *s); diff --git a/qemu-img.c b/qemu-img.c index d83ffe3ee9..efbb9b6be8 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -74,8 +74,8 @@ static void help(void) " differ\n" " 'fmt' is the disk image format. It is guessed automatically in most cases\n" " 'size' is the disk image size in kilobytes. Optional suffixes\n" - " 'M' (megabyte, 1024 * 1024) and 'G' (gigabyte, 1024 * 1024 * 1024) are" - " supported any @code{k} or @code{K} is ignored\n" + " 'M' (megabyte, 1024 * 1024) and 'G' (gigabyte, 1024 * 1024 * 1024) are\n" + " supported any 'k' or 'K' is ignored\n" " 'output_filename' is the destination disk image filename\n" " 'output_fmt' is the destination format\n" " '-c' indicates that target image must be compressed (qcow format only)\n" @@ -730,10 +730,6 @@ static int img_info(int argc, char **argv) if (bdrv_get_info(bs, &bdi) >= 0) { if (bdi.cluster_size != 0) printf("cluster_size: %d\n", bdi.cluster_size); - if (bdi.highest_alloc) - printf("highest_alloc: %" PRId64 "\n", bdi.highest_alloc); - if (bdi.num_free_bytes) - printf("num_free_bytes: %" PRId64 "\n", bdi.num_free_bytes); } bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename)); if (backing_filename[0] != '\0') { @@ -118,7 +118,9 @@ void qemu_announce_self(void) VLANClientState *vc; uint8_t buf[256]; - for (i = 0; i < nb_nics; i++) { + for (i = 0; i < MAX_NICS; i++) { + if (!nd_table[i].used) + continue; len = announce_self_create(buf, nd_table[i].macaddr); vlan = nd_table[i].vlan; for(vc = vlan->first_client; vc != NULL; vc = vc->next) { @@ -27,7 +27,7 @@ #include "x_keymap.h" #include <SDL.h> -#include <SDL/SDL_syswm.h> +#include <SDL_syswm.h> #ifndef _WIN32 #include <signal.h> diff --git a/target-i386/helper.c b/target-i386/helper.c index c0fc556c70..82137039d1 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1421,10 +1421,10 @@ static void host_cpuid(uint32_t function, uint32_t count, #else asm volatile("pusha \n\t" "cpuid \n\t" - "mov %%eax, 0(%1) \n\t" - "mov %%ebx, 4(%1) \n\t" - "mov %%ecx, 8(%1) \n\t" - "mov %%edx, 12(%1) \n\t" + "mov %%eax, 0(%2) \n\t" + "mov %%ebx, 4(%2) \n\t" + "mov %%ecx, 8(%2) \n\t" + "mov %%edx, 12(%2) \n\t" "popa" : : "a"(function), "c"(count), "S"(vec) : "memory", "cc"); diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c index 25e079b8fd..be092637a0 100644 --- a/target-i386/op_helper.c +++ b/target-i386/op_helper.c @@ -3241,6 +3241,8 @@ target_ulong helper_lsl(target_ulong selector1) selector = selector1 & 0xffff; eflags = helper_cc_compute_all(CC_OP); + if ((selector & 0xfffc) == 0) + goto fail; if (load_segment(&e1, &e2, selector) != 0) goto fail; rpl = selector & 3; @@ -201,6 +201,7 @@ ram_addr_t ram_size; int nb_nics; NICInfo nd_table[MAX_NICS]; int vm_running; +static int autostart; static int rtc_utc = 1; static int rtc_date_offset = -1; /* -1 means no change */ int cirrus_vga_enabled = 1; @@ -2607,11 +2608,13 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) bdrv_flags |= BDRV_O_CACHE_WB; else if (cache == 3) /* not specified */ bdrv_flags |= BDRV_O_CACHE_DEF; - if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0 || qemu_key_check(bdrv, file)) { + if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0) { fprintf(stderr, "qemu: could not open disk image %s\n", file); return -1; } + if (bdrv_key_required(bdrv)) + autostart = 0; return drives_table_idx; } @@ -2658,7 +2661,7 @@ int usb_device_add_dev(USBDevice *dev) return 0; } -static int usb_device_add(const char *devname) +static int usb_device_add(const char *devname, int is_hotplug) { const char *p; USBDevice *dev; @@ -2675,7 +2678,18 @@ static int usb_device_add(const char *devname) } else if (!strcmp(devname, "keyboard")) { dev = usb_keyboard_init(); } else if (strstart(devname, "disk:", &p)) { - dev = usb_msd_init(p); + BlockDriverState *bs; + + dev = usb_msd_init(p, &bs); + if (!dev) + return -1; + if (bdrv_key_required(bs)) { + autostart = 0; + if (is_hotplug && monitor_read_bdrv_key(bs) < 0) { + dev->handle_destroy(dev); + return -1; + } + } } else if (!strcmp(devname, "wacom-tablet")) { dev = usb_wacom_init(); } else if (strstart(devname, "serial:", &p)) { @@ -2756,7 +2770,7 @@ static int usb_device_del(const char *devname) void do_usb_add(const char *devname) { - usb_device_add(devname); + usb_device_add(devname, 1); } void do_usb_del(const char *devname) @@ -4334,45 +4348,6 @@ static const QEMUOption qemu_options[] = { { NULL }, }; -/* password input */ - -int qemu_key_check(BlockDriverState *bs, const char *name) -{ - char password[256]; - int i; - - if (!bdrv_is_encrypted(bs)) - return 0; - - term_printf("%s is encrypted.\n", name); - for(i = 0; i < 3; i++) { - monitor_readline("Password: ", 1, password, sizeof(password)); - if (bdrv_set_key(bs, password) == 0) - return 0; - term_printf("invalid password\n"); - } - return -EPERM; -} - -static BlockDriverState *get_bdrv(int index) -{ - if (index > nb_drives) - return NULL; - return drives_table[index].bdrv; -} - -static void read_passwords(void) -{ - BlockDriverState *bs; - int i; - - for(i = 0; i < 6; i++) { - bs = get_bdrv(i); - if (bs) - qemu_key_check(bs, bdrv_get_device_name(bs)); - } -} - #ifdef HAS_AUDIO struct soundhw soundhw[] = { #ifdef HAS_AUDIO_CHOICE @@ -4639,7 +4614,6 @@ int main(int argc, char **argv, char **envp) int fds[2]; int tb_size; const char *pid_file = NULL; - int autostart; const char *incoming = NULL; int fd = 0; struct passwd *pwd = NULL; @@ -4696,7 +4670,7 @@ int main(int argc, char **argv, char **envp) kernel_cmdline = ""; cyls = heads = secs = 0; translation = BIOS_ATA_TRANSLATION_AUTO; - monitor_device = "vc"; + monitor_device = "vc:80Cx24C"; serial_devices[0] = "vc:80Cx24C"; for(i = 1; i < MAX_SERIAL_PORTS; i++) @@ -5637,7 +5611,7 @@ int main(int argc, char **argv, char **envp) /* init USB devices */ if (usb_enabled) { for(i = 0; i < usb_devices_index; i++) { - if (usb_device_add(usb_devices[i]) < 0) { + if (usb_device_add(usb_devices[i], 0) < 0) { fprintf(stderr, "Warning: could not add USB device %s\n", usb_devices[i]); } @@ -5693,6 +5667,7 @@ int main(int argc, char **argv, char **envp) } text_consoles_set_display(display_state); + qemu_chr_initial_reset(); if (monitor_device && monitor_hd) monitor_init(monitor_hd, !nographic); @@ -5747,13 +5722,8 @@ int main(int argc, char **argv, char **envp) qemu_start_incoming_migration(incoming); } - { - /* XXX: simplify init */ - read_passwords(); - if (autostart) { - vm_start(); - } - } + if (autostart) + vm_start(); if (daemonize) { uint8_t status = 0; |