From c2d8d311c18b13c5282ab7d7b2ae57e3dd1e7f7d Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Mon, 14 Nov 2011 15:07:01 +0000 Subject: xen: do not initialize the interval timer and PCSPK emulator PIT and PCSPK are emulated by the hypervisor so we don't need to emulate them in Qemu: this patch prevents Qemu from waking up needlessly at PIT_FREQ on Xen. Signed-off-by: Stefano Stabellini --- hw/pc.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index 4d34a335e..a752a6b2f 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -47,6 +47,7 @@ #include "ui/qemu-spice.h" #include "memory.h" #include "exec-memory.h" +#include "arch_init.h" /* output Bochs bios info messages */ //#define DEBUG_BIOS @@ -1097,7 +1098,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, qemu_irq pit_alt_irq = NULL; qemu_irq rtc_irq = NULL; qemu_irq *a20_line; - ISADevice *i8042, *port92, *vmmouse, *pit; + ISADevice *i8042, *port92, *vmmouse, *pit = NULL; qemu_irq *cpu_exit_irq; register_ioport_write(0x80, 1, 1, ioport80_write, NULL); @@ -1126,16 +1127,18 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, qemu_register_boot_set(pc_boot_set, *rtc_state); - if (kvm_irqchip_in_kernel()) { - pit = kvm_pit_init(isa_bus, 0x40); - } else { - pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq); - } - if (hpet) { - /* connect PIT to output control line of the HPET */ - qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0)); + if (!xen_enabled()) { + if (kvm_irqchip_in_kernel()) { + pit = kvm_pit_init(isa_bus, 0x40); + } else { + pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq); + } + if (hpet) { + /* connect PIT to output control line of the HPET */ + qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0)); + } + pcspk_init(isa_bus, pit); } - pcspk_init(isa_bus, pit); for(i = 0; i < MAX_SERIAL_PORTS; i++) { if (serial_hds[i]) { -- cgit v1.2.3 From 95d5d75ede92c7ae7b47e8de2694db969b7fc06f Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Mon, 21 Nov 2011 11:10:21 +0000 Subject: xen: disable rtc_clock rtc_clock is only used by the RTC emulator (mc146818rtc.c), however Xen has its own RTC emulator in the hypervisor so we can disable it. Signed-off-by: Stefano Stabellini --- xen-all.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xen-all.c b/xen-all.c index bdf9c0fc7..b88ad5dda 100644 --- a/xen-all.c +++ b/xen-all.c @@ -603,6 +603,10 @@ void xen_vcpu_init(void) qemu_register_reset(xen_reset_vcpu, first_cpu); xen_reset_vcpu(first_cpu); } + /* if rtc_clock is left to default (host_clock), disable it */ + if (rtc_clock == host_clock) { + qemu_clock_enable(rtc_clock, false); + } } /* get the ioreq packets from share mem */ -- cgit v1.2.3 From ba1dffed6342f900595b97435c05646f559b5ea7 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Fri, 13 Apr 2012 16:44:54 +0000 Subject: xen_disk: remove syncwrite option This patch removes a dead option. The same can be achieved removing BDRV_O_NOCACHE and BDRV_O_CACHE_WB from the flags passed to bdrv_open. Signed-off-by: Stefano Stabellini --- hw/xen_disk.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/hw/xen_disk.c b/hw/xen_disk.c index 22dbd1030..49e53b7e7 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -48,7 +48,6 @@ /* ------------------------------------------------------------- */ -static int syncwrite = 0; static int batch_maps = 0; static int max_requests = 32; @@ -189,15 +188,10 @@ static int ioreq_parse(struct ioreq *ioreq) ioreq->presync = 1; return 0; } - if (!syncwrite) { - ioreq->presync = ioreq->postsync = 1; - } + ioreq->presync = ioreq->postsync = 1; /* fall through */ case BLKIF_OP_WRITE: ioreq->prot = PROT_READ; /* from memory */ - if (syncwrite) { - ioreq->postsync = 1; - } break; default: xen_be_printf(&blkdev->xendev, 0, "error: unknown operation (%d)\n", -- cgit v1.2.3 From c6961b7d38317fd48a8e86a8c2be4b9aeeb71ac0 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Thu, 26 Apr 2012 16:35:53 +0000 Subject: xen_disk: use bdrv_aio_flush instead of bdrv_flush Use bdrv_aio_flush instead of bdrv_flush. Make sure to call bdrv_aio_writev/readv after the presync bdrv_aio_flush is fully completed and make sure to call the postsync bdrv_aio_flush after bdrv_aio_writev/readv is fully completed. Signed-off-by: Stefano Stabellini --- hw/xen_disk.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/hw/xen_disk.c b/hw/xen_disk.c index 49e53b7e7..cf0624383 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -66,6 +66,7 @@ struct ioreq { QEMUIOVector v; int presync; int postsync; + uint8_t mapped; /* grant mapping */ uint32_t domids[BLKIF_MAX_SEGMENTS_PER_REQUEST]; @@ -242,7 +243,7 @@ static void ioreq_unmap(struct ioreq *ioreq) XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev; int i; - if (ioreq->v.niov == 0) { + if (ioreq->v.niov == 0 || ioreq->mapped == 0) { return; } if (batch_maps) { @@ -268,6 +269,7 @@ static void ioreq_unmap(struct ioreq *ioreq) ioreq->page[i] = NULL; } } + ioreq->mapped = 0; } static int ioreq_map(struct ioreq *ioreq) @@ -275,7 +277,7 @@ static int ioreq_map(struct ioreq *ioreq) XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev; int i; - if (ioreq->v.niov == 0) { + if (ioreq->v.niov == 0 || ioreq->mapped == 1) { return 0; } if (batch_maps) { @@ -307,9 +309,12 @@ static int ioreq_map(struct ioreq *ioreq) ioreq->blkdev->cnt_map++; } } + ioreq->mapped = 1; return 0; } +static int ioreq_runio_qemu_aio(struct ioreq *ioreq); + static void qemu_aio_complete(void *opaque, int ret) { struct ioreq *ioreq = opaque; @@ -321,11 +326,19 @@ static void qemu_aio_complete(void *opaque, int ret) } ioreq->aio_inflight--; + if (ioreq->presync) { + ioreq->presync = 0; + ioreq_runio_qemu_aio(ioreq); + return; + } if (ioreq->aio_inflight > 0) { return; } if (ioreq->postsync) { - bdrv_flush(ioreq->blkdev->bs); + ioreq->postsync = 0; + ioreq->aio_inflight++; + bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq); + return; } ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY; @@ -345,7 +358,8 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) ioreq->aio_inflight++; if (ioreq->presync) { - bdrv_flush(blkdev->bs); /* FIXME: aio_flush() ??? */ + bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq); + return 0; } switch (ioreq->req.operation) { -- cgit v1.2.3 From ed5477664369c1e9de23b0e7e8f16a418573bd2a Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 14 May 2012 16:46:33 +0000 Subject: xen_disk: properly update stats in ioreq_release() While for the "normal" case (called from blk_send_response_all()) decrementing requests_finished is correct, doing so in the parse error case is wrong; requests_inflight needs to be decremented instead. Signed-off-by: Jan Beulich Signed-off-by: Stefano Stabellini Reviewed-by: Kevin Wolf --- hw/xen_disk.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/xen_disk.c b/hw/xen_disk.c index cf0624383..07594bc0c 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -154,7 +154,7 @@ static void ioreq_finish(struct ioreq *ioreq) blkdev->requests_finished++; } -static void ioreq_release(struct ioreq *ioreq) +static void ioreq_release(struct ioreq *ioreq, bool finish) { struct XenBlkDev *blkdev = ioreq->blkdev; @@ -162,7 +162,11 @@ static void ioreq_release(struct ioreq *ioreq) memset(ioreq, 0, sizeof(*ioreq)); ioreq->blkdev = blkdev; QLIST_INSERT_HEAD(&blkdev->freelist, ioreq, list); - blkdev->requests_finished--; + if (finish) { + blkdev->requests_finished--; + } else { + blkdev->requests_inflight--; + } } /* @@ -457,7 +461,7 @@ static void blk_send_response_all(struct XenBlkDev *blkdev) while (!QLIST_EMPTY(&blkdev->finished)) { ioreq = QLIST_FIRST(&blkdev->finished); send_notify += blk_send_response_one(ioreq); - ioreq_release(ioreq); + ioreq_release(ioreq, true); } if (send_notify) { xen_be_send_notify(&blkdev->xendev); @@ -513,7 +517,7 @@ static void blk_handle_requests(struct XenBlkDev *blkdev) if (blk_send_response_one(ioreq)) { xen_be_send_notify(&blkdev->xendev); } - ioreq_release(ioreq); + ioreq_release(ioreq, false); continue; } -- cgit v1.2.3 From a4f1a7589ad0926fc8db1a6c56d1c3e015be565c Mon Sep 17 00:00:00 2001 From: Anthony PERARD Date: Thu, 17 May 2012 10:31:20 +0000 Subject: xen: Fix PV-on-HVM In the context of PV-on-HVM under Xen, the emulated nics are supposed to be unplug before the guest drivers are initialized, when the guest write to a specific IO port. Without this patch, the guest end up with two nics with the same MAC, the emulated nic and the PV nic. Signed-off-by: Anthony PERARD Signed-off-by: Stefano Stabellini Acked-by: Paolo Bonzini --- hw/xen_platform.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/xen_platform.c b/hw/xen_platform.c index a9c52a6e3..0214f370b 100644 --- a/hw/xen_platform.c +++ b/hw/xen_platform.c @@ -87,7 +87,10 @@ static void unplug_nic(PCIBus *b, PCIDevice *d) { if (pci_get_word(d->config + PCI_CLASS_DEVICE) == PCI_CLASS_NETWORK_ETHERNET) { - qdev_unplug(&(d->qdev), NULL); + /* Until qdev_free includes a call to object_unparent, we call it here + */ + object_unparent(&d->qdev.parent_obj); + qdev_free(&d->qdev); } } -- cgit v1.2.3 From 180640ea071c98739b6cc55b8d03367bcb442b94 Mon Sep 17 00:00:00 2001 From: "John V. Baboval" Date: Thu, 17 May 2012 10:33:09 +0000 Subject: Call xc_domain_shutdown with the reboot flag when the guest requests a reboot. Signed-off-by: John V. Baboval Signed-off-by: Tom Goetz Signed-off-by: Anthony PERARD Signed-off-by: Stefano Stabellini --- hw/xen_common.h | 2 +- xen-all.c | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/hw/xen_common.h b/hw/xen_common.h index 7043c14ca..fe7f227f9 100644 --- a/hw/xen_common.h +++ b/hw/xen_common.h @@ -148,6 +148,6 @@ static inline int xen_xc_hvm_inject_msi(XenXC xen_xc, domid_t dom, } #endif -void destroy_hvm_domain(void); +void destroy_hvm_domain(bool reboot); #endif /* QEMU_HW_XEN_COMMON_H */ diff --git a/xen-all.c b/xen-all.c index b88ad5dda..b5220cc6a 100644 --- a/xen-all.c +++ b/xen-all.c @@ -860,7 +860,7 @@ static void cpu_handle_ioreq(void *opaque) "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n", req->state, req->data_is_ptr, req->addr, req->data, req->count, req->size); - destroy_hvm_domain(); + destroy_hvm_domain(false); return; } @@ -874,10 +874,11 @@ static void cpu_handle_ioreq(void *opaque) */ if (runstate_is_running()) { if (qemu_shutdown_requested_get()) { - destroy_hvm_domain(); + destroy_hvm_domain(false); } if (qemu_reset_requested_get()) { qemu_system_reset(VMRESET_REPORT); + destroy_hvm_domain(true); } } @@ -1163,7 +1164,7 @@ int xen_hvm_init(void) return 0; } -void destroy_hvm_domain(void) +void destroy_hvm_domain(bool reboot) { XenXC xc_handle; int sts; @@ -1172,12 +1173,15 @@ void destroy_hvm_domain(void) if (xc_handle == XC_HANDLER_INITIAL_VALUE) { fprintf(stderr, "Cannot acquire xenctrl handle\n"); } else { - sts = xc_domain_shutdown(xc_handle, xen_domid, SHUTDOWN_poweroff); + sts = xc_domain_shutdown(xc_handle, xen_domid, + reboot ? SHUTDOWN_reboot : SHUTDOWN_poweroff); if (sts != 0) { - fprintf(stderr, "? xc_domain_shutdown failed to issue poweroff, " - "sts %d, %s\n", sts, strerror(errno)); + fprintf(stderr, "xc_domain_shutdown failed to issue %s, " + "sts %d, %s\n", reboot ? "reboot" : "poweroff", + sts, strerror(errno)); } else { - fprintf(stderr, "Issued domain %d poweroff\n", xen_domid); + fprintf(stderr, "Issued domain %d %s\n", xen_domid, + reboot ? "reboot" : "poweroff"); } xc_interface_close(xc_handle); } -- cgit v1.2.3 From f8687bab919672ccdfe29e366e60b5dd1b6ae71b Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 23 May 2012 23:26:41 +0200 Subject: es1370: Fix debug code When DEBUG_ES1370 is defined, the compiler shows these warnings: hw/es1370.c: In function ?es1370_update_voices?: hw/es1370.c:414: warning: format ?%d? expects type ?int?, but argument 3 has type ?size_t? hw/es1370.c: In function ?es1370_writel?: hw/es1370.c:582: warning: format ?%d? expects type ?int?, but argument 3 has type ?long int? hw/es1370.c:592: warning: format ?%d? expects type ?int?, but argument 3 has type ?long int? hw/es1370.c:609: warning: format ?%d? expects type ?int?, but argument 3 has type ?long int? hw/es1370.c: In function ?es1370_readl?: hw/es1370.c:751: warning: suggest braces around empty body in an ?if? statement Fix the format strings and add the missing braces. Signed-off-by: Stefan Weil Signed-off-by: malc --- hw/es1370.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hw/es1370.c b/hw/es1370.c index f19cef31a..573f74736 100644 --- a/hw/es1370.c +++ b/hw/es1370.c @@ -410,7 +410,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl) if ((old_fmt != new_fmt) || (old_freq != new_freq)) { d->shift = (new_fmt & 1) + (new_fmt >> 1); - ldebug ("channel %d, freq = %d, nchannels %d, fmt %d, shift %d\n", + ldebug ("channel %zu, freq = %d, nchannels %d, fmt %d, shift %d\n", i, new_freq, 1 << (new_fmt & 1), @@ -578,7 +578,7 @@ IO_WRITE_PROTO (es1370_writel) d++; case ES1370_REG_DAC1_SCOUNT: d->scount = (val & 0xffff) | (d->scount & ~0xffff); - ldebug ("chan %d CURR_SAMP_CT %d, SAMP_CT %d\n", + ldebug ("chan %td CURR_SAMP_CT %d, SAMP_CT %d\n", d - &s->chan[0], val >> 16, (val & 0xffff)); break; @@ -588,7 +588,7 @@ IO_WRITE_PROTO (es1370_writel) d++; case ES1370_REG_DAC1_FRAMEADR: d->frame_addr = val; - ldebug ("chan %d frame address %#x\n", d - &s->chan[0], val); + ldebug ("chan %td frame address %#x\n", d - &s->chan[0], val); break; case ES1370_REG_PHANTOM_FRAMECNT: @@ -605,7 +605,7 @@ IO_WRITE_PROTO (es1370_writel) case ES1370_REG_DAC1_FRAMECNT: d->frame_cnt = val; d->leftover = 0; - ldebug ("chan %d frame count %d, buffer size %d\n", + ldebug ("chan %td frame count %d, buffer size %d\n", d - &s->chan[0], val >> 16, val & 0xffff); break; @@ -745,9 +745,10 @@ IO_READ_PROTO (es1370_readl) { uint32_t size = ((d->frame_cnt & 0xffff) + 1) << 2; uint32_t curr = ((d->frame_cnt >> 16) + 1) << 2; - if (curr > size) + if (curr > size) { dolog ("read framecnt curr %d, size %d %d\n", curr, size, curr > size); + } } #endif break; -- cgit v1.2.3 From aeb29b6459cb9496b38c820f3faff64cf2369d0d Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 24 May 2012 12:05:15 -0300 Subject: audio: Always call fini on exit Not only clean up enabled voices but any registered one. Backends like pulsaudio rely on unconditional fini handler invocations. This fixes "Memory pool destroyed but not all memory blocks freed!" warnings on VM shutdowns when pa is used and lockups of QEMU on shutdown as it got stuck on some pa-internal synchronization point. Signed-off-by: Jan Kiszka Signed-off-by: malc --- audio/audio.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index bd9237e9d..583ee51ea 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1775,10 +1775,12 @@ static void audio_atexit (void) HWVoiceOut *hwo = NULL; HWVoiceIn *hwi = NULL; - while ((hwo = audio_pcm_hw_find_any_enabled_out (hwo))) { + while ((hwo = audio_pcm_hw_find_any_out (hwo))) { SWVoiceCap *sc; - hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE); + if (hwo->enabled) { + hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE); + } hwo->pcm_ops->fini_out (hwo); for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) { @@ -1791,8 +1793,10 @@ static void audio_atexit (void) } } - while ((hwi = audio_pcm_hw_find_any_enabled_in (hwi))) { - hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE); + while ((hwi = audio_pcm_hw_find_any_in (hwi))) { + if (hwi->enabled) { + hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE); + } hwi->pcm_ops->fini_in (hwi); } -- cgit v1.2.3 From 8ab1bf120d7fcf84f199679ad0d25acbc354c69c Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 23 May 2012 15:48:04 -0300 Subject: configure: check if environ is declared Some systems may declare environ automatically, others don't. Check for it. Signed-off-by: Luiz Capitulino Signed-off-by: Michael Roth --- configure | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/configure b/configure index b55a792de..1f338f8dc 100755 --- a/configure +++ b/configure @@ -2831,6 +2831,21 @@ if compile_prog "" "" ; then linux_magic_h=yes fi +######################################## +# check if environ is declared + +has_environ=no +cat > $TMPC << EOF +#include +int main(void) { + environ = environ; + return 0; +} +EOF +if compile_prog "" "" ; then + has_environ=yes +fi + ########################################## # End of CC checks # After here, no more $cc or $ld runs @@ -3342,6 +3357,10 @@ if test "$linux_magic_h" = "yes" ; then echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak fi +if test "$has_environ" = "yes" ; then + echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak +fi + # USB host support case "$usb" in linux) -- cgit v1.2.3 From 2c02cbf6e929c20545b46feb5ecde9c86877198a Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 23 May 2012 15:48:05 -0300 Subject: qemu-ga: Fix missing environ declaration Commit 3674838cd05268954bb6473239cd7f700a79bf0f uses the environ global variable, but is relying on environ to be declared somewhere else. This worked for me because on F16 environ is declared in , but that doesn't happen in OpenBSD for example, causing a build failure. This commit fixes the build error by declaring environ if it hasn't being declared yet. Also fixes a build warning due to a missing include. Signed-off-by: Luiz Capitulino Signed-off-by: Michael Roth --- qga/commands-posix.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 7664be10a..dab3bf9c9 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -14,12 +14,17 @@ #include #include #include +#include #include "qga/guest-agent-core.h" #include "qga-qmp-commands.h" #include "qerror.h" #include "qemu-queue.h" #include "host-utils.h" +#ifndef CONFIG_HAS_ENVIRON +extern char **environ; +#endif + #if defined(__linux__) #include #include @@ -27,7 +32,6 @@ #include #include #include -#include #if defined(__linux__) && defined(FIFREEZE) #define CONFIG_FSFREEZE -- cgit v1.2.3 From 12badfc2385ae6822cbcbcc8d1c0ed71c9e0ff09 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Mon, 21 May 2012 12:03:10 +0200 Subject: scsi: declare vmstate_info_scsi_requests to be static Signed-off-by: Jim Meyering --- hw/scsi-bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 8ab9bcda8..f10f3ec25 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -1561,7 +1561,7 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size) return 0; } -const VMStateInfo vmstate_info_scsi_requests = { +static const VMStateInfo vmstate_info_scsi_requests = { .name = "scsi-requests", .get = get_scsi_requests, .put = put_scsi_requests, -- cgit v1.2.3 From b6c147622d31272f9728da9ec16d146bf8c45a74 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Mon, 21 May 2012 13:06:54 +0200 Subject: qcow2: don't leak buffer for unexpected qcow_version in header Signed-off-by: Jim Meyering Signed-off-by: Kevin Wolf --- block/qcow2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/block/qcow2.c b/block/qcow2.c index 655799c6a..c2e49cded 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -919,7 +919,8 @@ int qcow2_update_header(BlockDriverState *bs) ret = sizeof(*header); break; default: - return -EINVAL; + ret = -EINVAL; + goto fail; } buf += ret; -- cgit v1.2.3 From 9fda6ab1d9f33c04f35438bce101427dd557fef6 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 21 May 2012 14:58:05 +0100 Subject: qemu-img: Explain how rebase operation can be used to perform a 'diff' operation. Signed-off-by: Richard W.M. Jones Signed-off-by: Kevin Wolf --- qemu-img.texi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/qemu-img.texi b/qemu-img.texi index b2ca3a542..6fc3c28e0 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -159,6 +159,24 @@ It can be used without an accessible old backing file, i.e. you can use it to fix an image whose backing file has already been moved/renamed. @end table +You can use @code{rebase} to perform a ``diff'' operation on two +disk images. This can be useful when you have copied or cloned +a guest, and you want to get back to a thin image on top of a +template or base image. + +Say that @code{base.img} has been cloned as @code{modified.img} by +copying it, and that the @code{modified.img} guest has run so there +are now some changes compared to @code{base.img}. To construct a thin +image called @code{diff.qcow2} that contains just the differences, do: + +@example +qemu-img create -f qcow2 -b modified.img diff.qcow2 +qemu-img rebase -b base.img diff.qcow2 +@end example + +At this point, @code{modified.img} can be discarded, since +@code{base.img + diff.qcow2} contains the same information. + @item resize @var{filename} [+ | -]@var{size} Change the disk image as if it had been created with @var{size}. -- cgit v1.2.3 From 622b6057beb3d8ce8035aaedab2137108bd6bfe4 Mon Sep 17 00:00:00 2001 From: MORITA Kazutaka Date: Thu, 17 May 2012 03:15:31 +0900 Subject: sheepdog: mark image as snapshot when tag is specified When a snapshot tag is specified in the filename, the opened image is a snapshot. Signed-off-by: MORITA Kazutaka Signed-off-by: Kevin Wolf --- block/sheepdog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index e01d37168..776a1cc96 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1103,7 +1103,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags) } } - if (snapid) { + if (snapid || tag[0] != '\0') { dprintf("%" PRIx32 " snapshot inode was open.\n", vid); s->is_snapshot = 1; } -- cgit v1.2.3 From cb595887cc4ddd7c732b711164756eb0b1b31077 Mon Sep 17 00:00:00 2001 From: MORITA Kazutaka Date: Thu, 17 May 2012 03:15:33 +0900 Subject: sheepdog: return -errno on error On error, BlockDriver APIs should return -errno instead of -1. Signed-off-by: MORITA Kazutaka Signed-off-by: Kevin Wolf --- block/sheepdog.c | 78 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index 776a1cc96..991133e08 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -468,7 +468,7 @@ static int connect_to_sdog(const char *addr, const char *port) if (ret) { error_report("unable to get address info %s, %s", addr, strerror(errno)); - return -1; + return -errno; } for (res = res0; res; res = res->ai_next) { @@ -495,7 +495,7 @@ static int connect_to_sdog(const char *addr, const char *port) dprintf("connected to %s:%s\n", addr, port); goto success; } - fd = -1; + fd = -errno; error_report("failed connect to %s:%s", addr, port); success: freeaddrinfo(res0); @@ -510,12 +510,13 @@ static int send_req(int sockfd, SheepdogReq *hdr, void *data, ret = qemu_send_full(sockfd, hdr, sizeof(*hdr), 0); if (ret < sizeof(*hdr)) { error_report("failed to send a req, %s", strerror(errno)); - return ret; + return -errno; } ret = qemu_send_full(sockfd, data, *wlen, 0); if (ret < *wlen) { error_report("failed to send a req, %s", strerror(errno)); + ret = -errno; } return ret; @@ -553,6 +554,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data, ret = qemu_recv_full(sockfd, hdr, sizeof(*hdr), 0); if (ret < sizeof(*hdr)) { error_report("failed to get a rsp, %s", strerror(errno)); + ret = -errno; goto out; } @@ -564,6 +566,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data, ret = qemu_recv_full(sockfd, data, *rlen, 0); if (ret < *rlen) { error_report("failed to get the data, %s", strerror(errno)); + ret = -errno; goto out; } } @@ -587,6 +590,7 @@ static int do_co_req(int sockfd, SheepdogReq *hdr, void *data, ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr)); if (ret < sizeof(*hdr)) { error_report("failed to get a rsp, %s", strerror(errno)); + ret = -errno; goto out; } @@ -598,6 +602,7 @@ static int do_co_req(int sockfd, SheepdogReq *hdr, void *data, ret = qemu_co_recv(sockfd, data, *rlen); if (ret < *rlen) { error_report("failed to get the data, %s", strerror(errno)); + ret = -errno; goto out; } } @@ -787,7 +792,7 @@ static int get_sheep_fd(BDRVSheepdogState *s) fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { error_report("%s", strerror(errno)); - return -1; + return fd; } socket_set_nonblock(fd); @@ -796,7 +801,7 @@ static int get_sheep_fd(BDRVSheepdogState *s) if (ret) { error_report("%s", strerror(errno)); closesocket(fd); - return -1; + return -errno; } qemu_aio_set_fd_handler(fd, co_read_response, NULL, aio_flush_request, s); @@ -883,7 +888,7 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid, fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { - return -1; + return fd; } memset(buf, 0, sizeof(buf)); @@ -904,14 +909,17 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid, ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen); if (ret) { - ret = -1; goto out; } if (rsp->result != SD_RES_SUCCESS) { error_report("cannot get vdi info, %s, %s %d %s", sd_strerror(rsp->result), filename, snapid, tag); - ret = -1; + if (rsp->result == SD_RES_NO_VDI) { + ret = -ENOENT; + } else { + ret = -EIO; + } goto out; } *vid = rsp->vdi_id; @@ -980,7 +988,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, if (ret < 0) { qemu_co_mutex_unlock(&s->lock); error_report("failed to send a req, %s", strerror(errno)); - return -EIO; + return -errno; } if (wlen) { @@ -988,7 +996,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, if (ret < 0) { qemu_co_mutex_unlock(&s->lock); error_report("failed to send a data, %s", strerror(errno)); - return -EIO; + return -errno; } } @@ -1038,7 +1046,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies, ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen); if (ret) { error_report("failed to send a request to the sheep"); - return -1; + return ret; } switch (rsp->result) { @@ -1046,7 +1054,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies, return 0; default: error_report("%s", sd_strerror(rsp->result)); - return -1; + return -EIO; } } @@ -1082,10 +1090,12 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags) memset(vdi, 0, sizeof(vdi)); memset(tag, 0, sizeof(tag)); if (parse_vdiname(s, filename, vdi, &snapid, tag) < 0) { + ret = -EINVAL; goto out; } s->fd = get_sheep_fd(s); if (s->fd < 0) { + ret = s->fd; goto out; } @@ -1099,6 +1109,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags) s->flush_fd = connect_to_sdog(s->addr, s->port); if (s->flush_fd < 0) { error_report("failed to connect"); + ret = s->flush_fd; goto out; } } @@ -1111,6 +1122,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags) fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { error_report("failed to connect"); + ret = fd; goto out; } @@ -1139,7 +1151,7 @@ out: closesocket(s->fd); } g_free(buf); - return -1; + return ret; } static int do_sd_create(char *filename, int64_t vdi_size, @@ -1154,7 +1166,7 @@ static int do_sd_create(char *filename, int64_t vdi_size, fd = connect_to_sdog(addr, port); if (fd < 0) { - return -EIO; + return fd; } memset(buf, 0, sizeof(buf)); @@ -1177,7 +1189,7 @@ static int do_sd_create(char *filename, int64_t vdi_size, closesocket(fd); if (ret) { - return -EIO; + return ret; } if (rsp->result != SD_RES_SUCCESS) { @@ -1294,8 +1306,9 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) } ret = bdrv_file_open(&bs, backing_file, 0); - if (ret < 0) - return -EIO; + if (ret < 0) { + return ret; + } s = bs->opaque; @@ -1379,7 +1392,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset) fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { - return -EIO; + return fd; } /* we don't need to update entire object */ @@ -1391,10 +1404,9 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset) if (ret < 0) { error_report("failed to update an inode."); - return -EIO; } - return 0; + return ret; } /* @@ -1464,6 +1476,7 @@ static int sd_create_branch(BDRVSheepdogState *s) fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { error_report("failed to connect"); + ret = fd; goto out; } @@ -1606,8 +1619,9 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num, if (bs->growable && sector_num + nb_sectors > bs->total_sectors) { /* TODO: shouldn't block here */ - if (sd_truncate(bs, (sector_num + nb_sectors) * SECTOR_SIZE) < 0) { - return -EIO; + ret = sd_truncate(bs, (sector_num + nb_sectors) * SECTOR_SIZE); + if (ret < 0) { + return ret; } bs->total_sectors = sector_num + nb_sectors; } @@ -1724,7 +1738,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) /* refresh inode. */ fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { - ret = -EIO; + ret = fd; goto cleanup; } @@ -1732,7 +1746,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) s->inode.nr_copies, datalen, 0, 0, s->cache_enabled); if (ret < 0) { error_report("failed to write snapshot's inode."); - ret = -EIO; goto cleanup; } @@ -1741,7 +1754,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) if (ret < 0) { error_report("failed to create inode for snapshot. %s", strerror(errno)); - ret = -EIO; goto cleanup; } @@ -1752,7 +1764,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) if (ret < 0) { error_report("failed to read new inode info. %s", strerror(errno)); - ret = -EIO; goto cleanup; } @@ -1773,7 +1784,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) char *buf = NULL; uint32_t vid; uint32_t snapid = 0; - int ret = -ENOENT, fd; + int ret = 0, fd; old_s = g_malloc(sizeof(BDRVSheepdogState)); @@ -1791,13 +1802,13 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) ret = find_vdi_name(s, vdi, snapid, tag, &vid, 1); if (ret) { error_report("Failed to find_vdi_name"); - ret = -ENOENT; goto out; } fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { error_report("failed to connect"); + ret = fd; goto out; } @@ -1808,7 +1819,6 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) closesocket(fd); if (ret) { - ret = -ENOENT; goto out; } @@ -1861,6 +1871,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { + ret = fd; goto out; } @@ -1888,6 +1899,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { error_report("failed to connect"); + ret = fd; goto out; } @@ -1925,6 +1937,10 @@ out: g_free(vdi_inuse); + if (ret < 0) { + return ret; + } + return found; } @@ -1940,8 +1956,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, fd = connect_to_sdog(s->addr, s->port); if (fd < 0) { - ret = -EIO; - goto cleanup; + return fd; } while (size) { @@ -1965,7 +1980,6 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, if (ret < 0) { error_report("failed to save vmstate %s", strerror(errno)); - ret = -EIO; goto cleanup; } -- cgit v1.2.3 From b6fc8245e96dea6b7198a46e883d107403ddb90c Mon Sep 17 00:00:00 2001 From: MORITA Kazutaka Date: Thu, 17 May 2012 03:15:34 +0900 Subject: sheepdog: use heap instead of stack for BDRVSheepdogState bdrv_create() is called in coroutine context now, so we cannot use more stack than 1 MB in the function if we use ucontext coroutine. This patch allocates BDRVSheepdogState, whose size is 4 MB, on the heap in sd_create(). Signed-off-by: MORITA Kazutaka Signed-off-by: Kevin Wolf --- block/sheepdog.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index 991133e08..6d52277a8 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1249,24 +1249,26 @@ out: static int sd_create(const char *filename, QEMUOptionParameter *options) { - int ret; + int ret = 0; uint32_t vid = 0, base_vid = 0; int64_t vdi_size = 0; char *backing_file = NULL; - BDRVSheepdogState s; + BDRVSheepdogState *s; char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN]; uint32_t snapid; int prealloc = 0; const char *vdiname; + s = g_malloc0(sizeof(BDRVSheepdogState)); + strstart(filename, "sheepdog:", &vdiname); - memset(&s, 0, sizeof(s)); memset(vdi, 0, sizeof(vdi)); memset(tag, 0, sizeof(tag)); - if (parse_vdiname(&s, vdiname, vdi, &snapid, tag) < 0) { + if (parse_vdiname(s, vdiname, vdi, &snapid, tag) < 0) { error_report("invalid filename"); - return -EINVAL; + ret = -EINVAL; + goto out; } while (options && options->name) { @@ -1282,7 +1284,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) } else { error_report("Invalid preallocation mode: '%s'", options->value.s); - return -EINVAL; + ret = -EINVAL; + goto out; } } options++; @@ -1290,7 +1293,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) if (vdi_size > SD_MAX_VDI_SIZE) { error_report("too big image size"); - return -EINVAL; + ret = -EINVAL; + goto out; } if (backing_file) { @@ -1302,12 +1306,13 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) drv = bdrv_find_protocol(backing_file); if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) { error_report("backing_file must be a sheepdog image"); - return -EINVAL; + ret = -EINVAL; + goto out; } ret = bdrv_file_open(&bs, backing_file, 0); if (ret < 0) { - return ret; + goto out; } s = bs->opaque; @@ -1315,19 +1320,23 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) if (!is_snapshot(&s->inode)) { error_report("cannot clone from a non snapshot vdi"); bdrv_delete(bs); - return -EINVAL; + ret = -EINVAL; + goto out; } base_vid = s->inode.vdi_id; bdrv_delete(bs); } - ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port); + ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s->addr, s->port); if (!prealloc || ret) { - return ret; + goto out; } - return sd_prealloc(filename); + ret = sd_prealloc(filename); +out: + g_free(s); + return ret; } static void sd_close(BlockDriverState *bs) -- cgit v1.2.3 From df021791897cb7a171710dadf66648b4379de627 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 24 May 2012 12:56:32 +0200 Subject: qcow2: Check qcow2_alloc_clusters_at() return value When using qcow2_alloc_clusters_at(), the cluster allocation code checked the wrong variable for an error code. Signed-off-by: Kevin Wolf --- block/qcow2-cluster.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 10c22fe12..4b3345b11 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -762,7 +762,6 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset, uint64_t *host_offset, unsigned int *nb_clusters) { BDRVQcowState *s = bs->opaque; - int64_t cluster_offset; QCowL2Meta *old_alloc; trace_qcow2_do_alloc_clusters_offset(qemu_coroutine_self(), guest_offset, @@ -808,17 +807,21 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset, /* Allocate new clusters */ trace_qcow2_cluster_alloc_phys(qemu_coroutine_self()); if (*host_offset == 0) { - cluster_offset = qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size); + int64_t cluster_offset = + qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size); + if (cluster_offset < 0) { + return cluster_offset; + } + *host_offset = cluster_offset; + return 0; } else { - cluster_offset = *host_offset; - *nb_clusters = qcow2_alloc_clusters_at(bs, cluster_offset, *nb_clusters); - } - - if (cluster_offset < 0) { - return cluster_offset; + int ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters); + if (ret < 0) { + return ret; + } + *nb_clusters = ret; + return 0; } - *host_offset = cluster_offset; - return 0; } /* -- cgit v1.2.3 From b84762e2456e15c091c25aff052afb8766394acd Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 24 May 2012 16:26:51 +0100 Subject: qemu-iotests: mark 035 qcow2-only The 035 parallel aio write test relies on knowledge of qcow2 metadata layout to stress parallel L2 table accesses. This only works for qcow2 unless we add additional calculations for qed or other formats. Mark this test as qcow2-only. Note that the test is strictly speaking non-deterministic although the output produced is reliable with qcow2. This is because the aio_write command returns before the aio write request has completed. Completions can occur at any time afterwards and cause a message to be printed. Therefore the exact output of this test is not deterministic but we seem to get away with it for qcow2 (maybe due to coroutine and main loop scheduling). Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- tests/qemu-iotests/035 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qemu-iotests/035 b/tests/qemu-iotests/035 index 56616a1b7..9d2d3472e 100755 --- a/tests/qemu-iotests/035 +++ b/tests/qemu-iotests/035 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.rc . ./common.filter -_supported_fmt generic +_supported_fmt qcow2 _supported_proto generic _supported_os Linux -- cgit v1.2.3 From 9ecd394753919b7395e620dffb8a5e23c45b5e07 Mon Sep 17 00:00:00 2001 From: Pavel Hrdina Date: Thu, 24 May 2012 11:02:28 +0200 Subject: fdc: floppy drive should be visible after start without media If you start guest with floppy drive but without media inserted, guest still should see floppy drive pressent. Signed-off-by: Pavel Hrdina Signed-off-by: Kevin Wolf --- hw/pc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/pc.c b/hw/pc.c index 4d34a335e..967c17a3f 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -382,7 +382,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, if (floppy) { fdc_get_bs(fd, floppy); for (i = 0; i < 2; i++) { - if (fd[i] && bdrv_is_inserted(fd[i])) { + if (fd[i]) { bdrv_get_floppy_geometry_hint(fd[i], &nb_heads, &max_track, &last_sect, FDRIVE_DRV_NONE, &fd_type[i], &rate); -- cgit v1.2.3 From cfb08fbafcd946341bdf14103293887763802697 Mon Sep 17 00:00:00 2001 From: Pavel Hrdina Date: Thu, 24 May 2012 11:02:29 +0200 Subject: fdc: fix media detection We have to set up 'media_changed' after guest start so floppy driver could detect that there is no media in drive. For this purpose we call 'fdctrl_change_cb' instead of 'fd_revalidate' in 'fdctrl_connect_drives'. 'fd_revalidate' is called inside 'fdctrl_change_cb'. We still have to set default drive geometry in 'fd_revalidate' even if there is no media in drive. When you try to open (windows) or mount (linux) floppy the driver tries to seek on track 1. Linux guest stuck in loop then kernel crashes and windows guest prints error message. Signed-off-by: Pavel Hrdina Signed-off-by: Kevin Wolf --- hw/fdc.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/hw/fdc.c b/hw/fdc.c index cb4cd25c1..30d34e3f1 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -179,12 +179,14 @@ static void fd_revalidate(FDrive *drv) FDriveRate rate; FLOPPY_DPRINTF("revalidate\n"); - if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) { + if (drv->bs != NULL) { ro = bdrv_is_read_only(drv->bs); bdrv_get_floppy_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect, drv->drive, &drive, &rate); - if (nb_heads != 0 && max_track != 0 && last_sect != 0) { - FLOPPY_DPRINTF("User defined disk (%d %d %d)", + if (!bdrv_is_inserted(drv->bs)) { + FLOPPY_DPRINTF("No disk in drive\n"); + } else if (nb_heads != 0 && max_track != 0 && last_sect != 0) { + FLOPPY_DPRINTF("User defined disk (%d %d %d)\n", nb_heads - 1, max_track, last_sect); } else { FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads, @@ -201,7 +203,7 @@ static void fd_revalidate(FDrive *drv) drv->drive = drive; drv->media_rate = rate; } else { - FLOPPY_DPRINTF("No disk in drive\n"); + FLOPPY_DPRINTF("No drive connected\n"); drv->last_sect = 0; drv->max_track = 0; drv->flags &= ~FDISK_DBL_SIDES; @@ -709,7 +711,7 @@ static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0) FDrive *cur_drv; /* A seek clears the disk change line (if a disk is inserted) */ cur_drv = get_cur_drv(fdctrl); - if (cur_drv->max_track) { + if (cur_drv->bs != NULL && bdrv_is_inserted(cur_drv->bs)) { cur_drv->media_changed = 0; } } @@ -1878,7 +1880,7 @@ static int fdctrl_connect_drives(FDCtrl *fdctrl) } fd_init(drive); - fd_revalidate(drive); + fdctrl_change_cb(drive, 0); if (drive->bs) { bdrv_set_dev_ops(drive->bs, &fdctrl_block_ops, drive); } -- cgit v1.2.3 From 7cd331617a48785faaf2aafe36db5c06285bfed8 Mon Sep 17 00:00:00 2001 From: Pavel Hrdina Date: Thu, 24 May 2012 11:02:30 +0200 Subject: fdc-test: introduced qtest no_media_on_start and cmos qtest for floppy As default a guest has always one floppy drive so 0x10 byte in CMOS has to have 0x40 value. Higher 4 bits means that the first floppy drive is 1.44 Mb 3"5 drive and lower 4 bits means the second drive is not present. After the guest starts DSKCHG bit in DIR register should be set. If there is no media in drive, this bit should be set all the time. Because we start the guest without media in drive, we have to swap 'eject' and 'change' in 'test_media_change'. Signed-off-by: Pavel Hrdina Signed-off-by: Kevin Wolf --- tests/fdc-test.c | 65 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/tests/fdc-test.c b/tests/fdc-test.c index 5b5dd7481..22d24ac7d 100644 --- a/tests/fdc-test.c +++ b/tests/fdc-test.c @@ -63,6 +63,12 @@ char test_image[] = "/tmp/qtest.XXXXXX"; #define assert_bit_set(data, mask) g_assert_cmphex((data) & (mask), ==, (mask)) #define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0) +static uint8_t base = 0x70; + +enum { + CMOS_FLOPPY = 0x10, +}; + static void floppy_send(uint8_t byte) { uint8_t msr; @@ -108,34 +114,43 @@ static void send_step_pulse(void) cyl = (cyl + 1) % 4; } -static void test_media_change(void) +static uint8_t cmos_read(uint8_t reg) { - uint8_t dir; + outb(base + 0, reg); + return inb(base + 1); +} - /* Media changed bit must be up-to-date after step pulse. Do two SEEKs - * because we may already happen to be on the right cylinder initially. */ - send_step_pulse(); - send_step_pulse(); - dir = inb(FLOPPY_BASE + reg_dir); - assert_bit_clear(dir, DSKCHG); +static void test_cmos(void) +{ + uint8_t cmos; - /* Eject the floppy and check that DSKCHG is set. Reading it out doesn't - * reset the bit. */ - qmp("{'execute':'eject', 'arguments':{ 'device':'floppy0' }}"); - qmp(""); /* ignore event */ + cmos = cmos_read(CMOS_FLOPPY); + g_assert(cmos == 0x40); +} +static void test_no_media_on_start(void) +{ + uint8_t dir; + + /* Media changed bit must be set all time after start if there is + * no media in drive. */ dir = inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG); dir = inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG); - + send_step_pulse(); send_step_pulse(); dir = inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG); dir = inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG); +} + +static void test_media_change(void) +{ + uint8_t dir; - /* And then insert it again. DSKCHK should not be reset until a step pulse + /* Insert media in drive. DSKCHK should not be reset until a step pulse * is sent. */ qmp("{'execute':'change', 'arguments':{ 'device':'floppy0', " "'target': '%s' }}", test_image); @@ -152,6 +167,22 @@ static void test_media_change(void) assert_bit_clear(dir, DSKCHG); dir = inb(FLOPPY_BASE + reg_dir); assert_bit_clear(dir, DSKCHG); + + /* Eject the floppy and check that DSKCHG is set. Reading it out doesn't + * reset the bit. */ + qmp("{'execute':'eject', 'arguments':{ 'device':'floppy0' }}"); + qmp(""); /* ignore event */ + + dir = inb(FLOPPY_BASE + reg_dir); + assert_bit_set(dir, DSKCHG); + dir = inb(FLOPPY_BASE + reg_dir); + assert_bit_set(dir, DSKCHG); + + send_step_pulse(); + dir = inb(FLOPPY_BASE + reg_dir); + assert_bit_set(dir, DSKCHG); + dir = inb(FLOPPY_BASE + reg_dir); + assert_bit_set(dir, DSKCHG); } int main(int argc, char **argv) @@ -177,12 +208,12 @@ int main(int argc, char **argv) /* Run the tests */ g_test_init(&argc, &argv, NULL); - cmdline = g_strdup_printf("-vnc none " - "-drive file=%s,if=floppy,cache=writeback ", - test_image); + cmdline = g_strdup_printf("-vnc none "); qtest_start(cmdline); qtest_irq_intercept_in(global_qtest, "ioapic"); + qtest_add_func("/fdc/cmos", test_cmos); + qtest_add_func("/fdc/no_media_on_start", test_no_media_on_start); qtest_add_func("/fdc/media_change", test_media_change); ret = g_test_run(); -- cgit v1.2.3 From 24f50d7ea5896a30b0e78f68884586bb8b40ff97 Mon Sep 17 00:00:00 2001 From: Andreas Färber Date: Sun, 27 May 2012 19:50:47 +0200 Subject: tcg/ppc: Handle _CALL_DARWIN being undefined on Darwin powerpc-apple-darwin9-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5577) does not define _CALL_DARWIN, leading to unexpected behavior w.r.t. register clobbering and stack frame layout. Since _CALL_DARWIN is a reserved identifier, define a custom TCG_TARGET_CALL_DARWIN based on either _CALL_DARWIN or __APPLE__. Signed-off-by: Andreas F?rber Signed-off-by: malc --- tcg/ppc/tcg-target.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 4cde48d2f..d26569715 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -24,7 +24,11 @@ static uint8_t *tb_ret_addr; -#ifdef _CALL_DARWIN +#if defined _CALL_DARWIN || defined __APPLE__ +#define TCG_TARGET_CALL_DARWIN +#endif + +#ifdef TCG_TARGET_CALL_DARWIN #define LINKAGE_AREA_SIZE 24 #define LR_OFFSET 8 #elif defined _CALL_AIX @@ -99,7 +103,7 @@ static const int tcg_target_reg_alloc_order[] = { TCG_REG_R29, TCG_REG_R30, TCG_REG_R31, -#ifdef _CALL_DARWIN +#ifdef TCG_TARGET_CALL_DARWIN TCG_REG_R2, #endif TCG_REG_R3, @@ -110,7 +114,7 @@ static const int tcg_target_reg_alloc_order[] = { TCG_REG_R8, TCG_REG_R9, TCG_REG_R10, -#ifndef _CALL_DARWIN +#ifndef TCG_TARGET_CALL_DARWIN TCG_REG_R11, #endif TCG_REG_R12, @@ -140,7 +144,7 @@ static const int tcg_target_call_oarg_regs[2] = { }; static const int tcg_target_callee_save_regs[] = { -#ifdef _CALL_DARWIN +#ifdef TCG_TARGET_CALL_DARWIN TCG_REG_R11, TCG_REG_R13, #endif @@ -1965,7 +1969,7 @@ static void tcg_target_init(TCGContext *s) tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff); tcg_regset_set32(tcg_target_call_clobber_regs, 0, (1 << TCG_REG_R0) | -#ifdef _CALL_DARWIN +#ifdef TCG_TARGET_CALL_DARWIN (1 << TCG_REG_R2) | #endif (1 << TCG_REG_R3) | @@ -1983,7 +1987,7 @@ static void tcg_target_init(TCGContext *s) tcg_regset_clear(s->reserved_regs); tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1); -#ifndef _CALL_DARWIN +#ifndef TCG_TARGET_CALL_DARWIN tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2); #endif #ifdef _CALL_SYSV -- cgit v1.2.3 From e20e48a8020a3b95eea28c89310d2ff14ad4aca2 Mon Sep 17 00:00:00 2001 From: Andreas Färber Date: Sat, 28 Apr 2012 00:29:05 +0200 Subject: slirp: Untangle TCPOLEN_* from TCPOPT_* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b72210568ef0c0fb141a01cffb71a09c4efa0364 (slirp: clean up conflicts with system headers) enclosed TCPOLEN_MAXSEG with an #ifdef TCPOPT_EOL. This broke the build on illumos, which has TCPOPT_* but not TCPOLEN_*. Move them to their own #ifdef TCPOLEN_MAXSEG section to remedy this. Cc: Paolo Bonzini Signed-off-by: Andreas Färber Signed-off-by: Jan Kiszka --- slirp/tcp.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/slirp/tcp.h b/slirp/tcp.h index 82996031e..2e2b4033a 100644 --- a/slirp/tcp.h +++ b/slirp/tcp.h @@ -79,20 +79,23 @@ struct tcphdr { #define TCPOPT_EOL 0 #define TCPOPT_NOP 1 #define TCPOPT_MAXSEG 2 -#define TCPOLEN_MAXSEG 4 #define TCPOPT_WINDOW 3 -#define TCPOLEN_WINDOW 3 #define TCPOPT_SACK_PERMITTED 4 /* Experimental */ -#define TCPOLEN_SACK_PERMITTED 2 #define TCPOPT_SACK 5 /* Experimental */ #define TCPOPT_TIMESTAMP 8 -#define TCPOLEN_TIMESTAMP 10 -#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ #define TCPOPT_TSTAMP_HDR \ (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP) #endif +#ifndef TCPOLEN_MAXSEG +#define TCPOLEN_MAXSEG 4 +#define TCPOLEN_WINDOW 3 +#define TCPOLEN_SACK_PERMITTED 2 +#define TCPOLEN_TIMESTAMP 10 +#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ +#endif + /* * Default maximum segment size for TCP. * With an IP MSS of 576, this is 536, -- cgit v1.2.3 From c9b9f6824fd82058f6918b64d8fd9b1578fac353 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Tue, 22 May 2012 19:56:36 +1000 Subject: ISCSI: redo how we set up the events Call qemu_notify_event() after updating events. Otherwise, If we add an event for -is-writeable but the socket is already writeable there may be a delay before the event callback is actually triggered. Those delays would in particular hurt performance during BIOS boot and when the GRUB bootloader reads the kernel and initrd. But first call out to the socket write functions directly, and only set up the write event if the socket is full. This will happen very rarely and this improves performance. Signed-off-by: Ronnie Sahlberg --- block/iscsi.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/block/iscsi.c b/block/iscsi.c index d37c4ee17..db41bb758 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -39,6 +39,7 @@ typedef struct IscsiLun { int lun; int block_size; unsigned long num_blocks; + int events; } IscsiLun; typedef struct IscsiAIOCB { @@ -104,11 +105,27 @@ static void iscsi_set_events(IscsiLun *iscsilun) { struct iscsi_context *iscsi = iscsilun->iscsi; + int ev; - qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), iscsi_process_read, - (iscsi_which_events(iscsi) & POLLOUT) - ? iscsi_process_write : NULL, - iscsi_process_flush, iscsilun); + /* We always register a read handler. */ + ev = POLLIN; + ev |= iscsi_which_events(iscsi); + if (ev != iscsilun->events) { + qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), + iscsi_process_read, + (ev & POLLOUT) ? iscsi_process_write : NULL, + iscsi_process_flush, + iscsilun); + + } + + /* If we just added an event, the callback might be delayed + * unless we call qemu_notify_event(). + */ + if (ev & ~iscsilun->events) { + qemu_notify_event(); + } + iscsilun->events = ev; } static void -- cgit v1.2.3 From c7b4a95202032bf1a9e13dd9695389c0ed246eec Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 26 May 2012 09:41:13 +0200 Subject: ISCSI: change num_blocks to 64-bit Signed-off-by: Paolo Bonzini --- block/iscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/iscsi.c b/block/iscsi.c index db41bb758..9cd258ff6 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -38,7 +38,7 @@ typedef struct IscsiLun { struct iscsi_context *iscsi; int lun; int block_size; - unsigned long num_blocks; + uint64_t num_blocks; int events; } IscsiLun; -- cgit v1.2.3 From dbfff6d776670cca751b904063c9173a23ae8c75 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Fri, 25 May 2012 21:59:01 +1000 Subject: ISCSI: get device type at connection time This is needed to avoid READ CAPACITY(16) for MMC devices. Signed-off-by: Ronnie Sahlberg Signed-off-by: Paolo Bonzini --- block/iscsi.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/block/iscsi.c b/block/iscsi.c index 9cd258ff6..91cca83c5 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -29,6 +29,7 @@ #include "qemu-error.h" #include "block_int.h" #include "trace.h" +#include "hw/scsi-defs.h" #include #include @@ -37,6 +38,7 @@ typedef struct IscsiLun { struct iscsi_context *iscsi; int lun; + enum scsi_inquiry_peripheral_device_type type; int block_size; uint64_t num_blocks; int events; @@ -508,18 +510,33 @@ iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status, } static void -iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data, +iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data, void *opaque) { struct IscsiTask *itask = opaque; - struct scsi_task *task; + struct scsi_task *task = command_data; + struct scsi_inquiry_standard *inq; if (status != 0) { itask->status = 1; itask->complete = 1; + scsi_free_scsi_task(task); return; } + inq = scsi_datain_unmarshall(task); + if (inq == NULL) { + error_report("iSCSI: Failed to unmarshall inquiry data."); + itask->status = 1; + itask->complete = 1; + scsi_free_scsi_task(task); + return; + } + + itask->iscsilun->type = inq->periperal_device_type; + + scsi_free_scsi_task(task); + task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun, iscsi_readcapacity16_cb, opaque); if (task == NULL) { @@ -530,6 +547,30 @@ iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data, } } +static void +iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data, + void *opaque) +{ + struct IscsiTask *itask = opaque; + struct scsi_task *task; + + if (status != 0) { + itask->status = 1; + itask->complete = 1; + return; + } + + task = iscsi_inquiry_task(iscsi, itask->iscsilun->lun, + 0, 0, 36, + iscsi_inquiry_cb, opaque); + if (task == NULL) { + error_report("iSCSI: failed to send inquiry command."); + itask->status = 1; + itask->complete = 1; + return; + } +} + static int parse_chap(struct iscsi_context *iscsi, const char *target) { QemuOptsList *list; -- cgit v1.2.3 From 6bcd1346bbfb051820e1c55bd4f04766f556bcdf Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Sat, 26 May 2012 14:56:38 +1000 Subject: ISCSI: Only call READCAPACITY16 for SBC devices, use READCAPACITY10 for MMC Signed-off-by: Ronnie Sahlberg --- block/iscsi.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/block/iscsi.c b/block/iscsi.c index 91cca83c5..472c8539c 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -509,6 +509,42 @@ iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status, scsi_free_scsi_task(task); } +static void +iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status, + void *command_data, void *opaque) +{ + struct IscsiTask *itask = opaque; + struct scsi_readcapacity10 *rc10; + struct scsi_task *task = command_data; + + if (status != 0) { + error_report("iSCSI: Failed to read capacity of iSCSI lun. %s", + iscsi_get_error(iscsi)); + itask->status = 1; + itask->complete = 1; + scsi_free_scsi_task(task); + return; + } + + rc10 = scsi_datain_unmarshall(task); + if (rc10 == NULL) { + error_report("iSCSI: Failed to unmarshall readcapacity10 data."); + itask->status = 1; + itask->complete = 1; + scsi_free_scsi_task(task); + return; + } + + itask->iscsilun->block_size = rc10->block_size; + itask->iscsilun->num_blocks = rc10->lba + 1; + itask->bs->total_sectors = itask->iscsilun->num_blocks * + itask->iscsilun->block_size / BDRV_SECTOR_SIZE ; + + itask->status = 0; + itask->complete = 1; + scsi_free_scsi_task(task); +} + static void iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data, void *opaque) @@ -537,13 +573,31 @@ iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data, scsi_free_scsi_task(task); - task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun, + switch (itask->iscsilun->type) { + case TYPE_DISK: + task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun, iscsi_readcapacity16_cb, opaque); - if (task == NULL) { - error_report("iSCSI: failed to send readcapacity16 command."); - itask->status = 1; + if (task == NULL) { + error_report("iSCSI: failed to send readcapacity16 command."); + itask->status = 1; + itask->complete = 1; + return; + } + break; + case TYPE_ROM: + task = iscsi_readcapacity10_task(iscsi, itask->iscsilun->lun, + 0, 0, + iscsi_readcapacity10_cb, opaque); + if (task == NULL) { + error_report("iSCSI: failed to send readcapacity16 command."); + itask->status = 1; + itask->complete = 1; + return; + } + break; + default: + itask->status = 0; itask->complete = 1; - return; } } -- cgit v1.2.3 From f4dfa67f04037c1b1a8f4e4ddc944c5ab308f35b Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Tue, 22 May 2012 20:10:05 +1000 Subject: ISCSI: Switch to using READ16/WRITE16 for I/O to the LUN This allows using LUNs bigger than 2TB. Keep using READ10 for other device types such as MMC. Signed-off-by: Ronnie Sahlberg --- block/iscsi.c | 112 +++++++++++++++++++++++++++++++++++++++++++--------------- trace-events | 4 +-- 2 files changed, 85 insertions(+), 31 deletions(-) diff --git a/block/iscsi.c b/block/iscsi.c index 472c8539c..22888a084 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -25,6 +25,7 @@ #include "config-host.h" #include +#include #include "qemu-common.h" #include "qemu-error.h" #include "block_int.h" @@ -180,12 +181,12 @@ iscsi_readv_writev_bh_cb(void *p) static void -iscsi_aio_write10_cb(struct iscsi_context *iscsi, int status, +iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, void *command_data, void *opaque) { IscsiAIOCB *acb = opaque; - trace_iscsi_aio_write10_cb(iscsi, status, acb, acb->canceled); + trace_iscsi_aio_write16_cb(iscsi, status, acb, acb->canceled); g_free(acb->buf); @@ -198,7 +199,7 @@ iscsi_aio_write10_cb(struct iscsi_context *iscsi, int status, acb->status = 0; if (status < 0) { - error_report("Failed to write10 data to iSCSI lun. %s", + error_report("Failed to write16 data to iSCSI lun. %s", iscsi_get_error(iscsi)); acb->status = -EIO; } @@ -223,12 +224,9 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, struct iscsi_context *iscsi = iscsilun->iscsi; IscsiAIOCB *acb; size_t size; - int fua = 0; - - /* set FUA on writes when cache mode is write through */ - if (!(bs->open_flags & BDRV_O_CACHE_WB)) { - fua = 1; - } + uint32_t num_sectors; + uint64_t lba; + struct iscsi_data data; acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque); trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb); @@ -238,18 +236,44 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, acb->canceled = 0; - /* XXX we should pass the iovec to write10 to avoid the extra copy */ + /* XXX we should pass the iovec to write16 to avoid the extra copy */ /* this will allow us to get rid of 'buf' completely */ size = nb_sectors * BDRV_SECTOR_SIZE; acb->buf = g_malloc(size); qemu_iovec_to_buffer(acb->qiov, acb->buf); - acb->task = iscsi_write10_task(iscsi, iscsilun->lun, acb->buf, size, - sector_qemu2lun(sector_num, iscsilun), - fua, 0, iscsilun->block_size, - iscsi_aio_write10_cb, acb); + + + acb->task = malloc(sizeof(struct scsi_task)); if (acb->task == NULL) { - error_report("iSCSI: Failed to send write10 command. %s", - iscsi_get_error(iscsi)); + error_report("iSCSI: Failed to allocate task for scsi WRITE16 " + "command. %s", iscsi_get_error(iscsi)); + qemu_aio_release(acb); + return NULL; + } + memset(acb->task, 0, sizeof(struct scsi_task)); + + acb->task->xfer_dir = SCSI_XFER_WRITE; + acb->task->cdb_size = 16; + acb->task->cdb[0] = 0x8a; + if (!(bs->open_flags & BDRV_O_CACHE_WB)) { + /* set FUA on writes when cache mode is write through */ + acb->task->cdb[1] |= 0x04; + } + lba = sector_qemu2lun(sector_num, iscsilun); + *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32); + *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff); + num_sectors = size / iscsilun->block_size; + *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors); + acb->task->expxferlen = size; + + data.data = acb->buf; + data.size = size; + + if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task, + iscsi_aio_write16_cb, + &data, + acb) != 0) { + scsi_free_scsi_task(acb->task); g_free(acb->buf); qemu_aio_release(acb); return NULL; @@ -261,12 +285,12 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, } static void -iscsi_aio_read10_cb(struct iscsi_context *iscsi, int status, +iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status, void *command_data, void *opaque) { IscsiAIOCB *acb = opaque; - trace_iscsi_aio_read10_cb(iscsi, status, acb, acb->canceled); + trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled); if (acb->canceled != 0) { qemu_aio_release(acb); @@ -277,7 +301,7 @@ iscsi_aio_read10_cb(struct iscsi_context *iscsi, int status, acb->status = 0; if (status != 0) { - error_report("Failed to read10 data from iSCSI lun. %s", + error_report("Failed to read16 data from iSCSI lun. %s", iscsi_get_error(iscsi)); acb->status = -EIO; } @@ -296,8 +320,10 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num, IscsiLun *iscsilun = bs->opaque; struct iscsi_context *iscsi = iscsilun->iscsi; IscsiAIOCB *acb; - size_t qemu_read_size, lun_read_size; + size_t qemu_read_size; int i; + uint64_t lba; + uint32_t num_sectors; qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors; @@ -322,16 +348,44 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num, acb->read_offset = bdrv_offset % iscsilun->block_size; } - lun_read_size = (qemu_read_size + iscsilun->block_size - + acb->read_offset - 1) - / iscsilun->block_size * iscsilun->block_size; - acb->task = iscsi_read10_task(iscsi, iscsilun->lun, - sector_qemu2lun(sector_num, iscsilun), - lun_read_size, iscsilun->block_size, - iscsi_aio_read10_cb, acb); + num_sectors = (qemu_read_size + iscsilun->block_size + + acb->read_offset - 1) + / iscsilun->block_size; + + acb->task = malloc(sizeof(struct scsi_task)); if (acb->task == NULL) { - error_report("iSCSI: Failed to send read10 command. %s", - iscsi_get_error(iscsi)); + error_report("iSCSI: Failed to allocate task for scsi READ16 " + "command. %s", iscsi_get_error(iscsi)); + qemu_aio_release(acb); + return NULL; + } + memset(acb->task, 0, sizeof(struct scsi_task)); + + acb->task->xfer_dir = SCSI_XFER_READ; + lba = sector_qemu2lun(sector_num, iscsilun); + acb->task->expxferlen = qemu_read_size; + + switch (iscsilun->type) { + case TYPE_DISK: + acb->task->cdb_size = 16; + acb->task->cdb[0] = 0x88; + *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32); + *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff); + *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors); + break; + default: + acb->task->cdb_size = 10; + acb->task->cdb[0] = 0x28; + *(uint32_t *)&acb->task->cdb[2] = htonl(lba); + *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors); + break; + } + + if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task, + iscsi_aio_read16_cb, + NULL, + acb) != 0) { + scsi_free_scsi_task(acb->task); qemu_aio_release(acb); return NULL; } diff --git a/trace-events b/trace-events index 87cb96cab..45c6bc127 100644 --- a/trace-events +++ b/trace-events @@ -602,9 +602,9 @@ escc_kbd_command(int val) "Command %d" escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x" # block/iscsi.c -iscsi_aio_write10_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d" +iscsi_aio_write16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d" iscsi_aio_writev(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p" -iscsi_aio_read10_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d" +iscsi_aio_read16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d" iscsi_aio_readv(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p" # hw/esp.c -- cgit v1.2.3 From 9b24d8e987d1249836cd4bccebf7c3a33025b293 Mon Sep 17 00:00:00 2001 From: Andreas Färber Date: Mon, 28 May 2012 19:34:20 +0200 Subject: slirp: Avoid statements without effect on Big Endian host MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Darwin has HTON*/NTOH* macros that on BE simply return the argument. This is incompatible with SLIRP's use of these macros as a statement. Undefine the macros in the HOST_WORDS_BIGENDIAN code path to redefine these macros as no-op, as already done when they were undefined. Suggested-by: Peter Maydell Signed-off-by: Andreas Färber Signed-off-by: Jan Kiszka --- slirp/ip.h | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/slirp/ip.h b/slirp/ip.h index 88c903fcc..e2ee5e304 100644 --- a/slirp/ip.h +++ b/slirp/ip.h @@ -34,18 +34,14 @@ #define _IP_H_ #ifdef HOST_WORDS_BIGENDIAN -# ifndef NTOHL -# define NTOHL(d) -# endif -# ifndef NTOHS -# define NTOHS(d) -# endif -# ifndef HTONL -# define HTONL(d) -# endif -# ifndef HTONS -# define HTONS(d) -# endif +# undef NTOHL +# undef NTOHS +# undef HTONL +# undef HTONS +# define NTOHL(d) +# define NTOHS(d) +# define HTONL(d) +# define HTONS(d) #else # ifndef NTOHL # define NTOHL(d) ((d) = ntohl((d))) -- cgit v1.2.3 From 917cfc1f266b554ea9ab4d958fa048bd27bce58f Mon Sep 17 00:00:00 2001 From: Andreas Färber Date: Mon, 28 May 2012 19:52:35 +0200 Subject: slirp: Avoid redefining MAX_TCPOPTLEN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MAX_TCPOPTLEN is being defined as 32. Darwin already has it as 40, causing a warning. The value is only used to declare an array, into which currently 4 bytes are written at most. Therefore always override MAX_TCPOPTLEN for now. Suggested-by: Jan Kiszka Reviewed-by: Stefan Weil Signed-off-by: Andreas Färber Signed-off-by: Jan Kiszka --- slirp/tcp_output.c | 1 + 1 file changed, 1 insertion(+) diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c index 779314bf9..8aa3d9047 100644 --- a/slirp/tcp_output.c +++ b/slirp/tcp_output.c @@ -47,6 +47,7 @@ static const u_char tcp_outflags[TCP_NSTATES] = { }; +#undef MAX_TCPOPTLEN #define MAX_TCPOPTLEN 32 /* max # bytes that go in options */ /* -- cgit v1.2.3 From f283edc4827f6bfa82240e36433d7184ab106b0f Mon Sep 17 00:00:00 2001 From: Andreas Färber Date: Sun, 27 May 2012 16:21:02 +0200 Subject: arch_init: Fix AltiVec build on Darwin/ppc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit f29a56147b66845914d0a645bf9b4c5bb9a6af57 (implement -no-user-config command-line option (v3)) introduced uses of bool in arch_init.c. Shortly before that usage is support code for AltiVec (conditional to __ALTIVEC__). GCC's altivec.h may in a !__APPLE_ALTIVEC__ code path redefine bool, leading to type mismatches. altivec.h recommends to #undef for C++ compatibility, but doing so in C leads to bool remaining undefined. Fix by redefining bool to _Bool as mandated for stdbool.h by POSIX. Signed-off-by: Andreas Färber Reviewed-by: Paolo Bonzini --- arch_init.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch_init.c b/arch_init.c index 988adcae0..a9e8b7442 100644 --- a/arch_init.c +++ b/arch_init.c @@ -100,6 +100,10 @@ const uint32_t arch_type = QEMU_ARCH; #define VECTYPE vector unsigned char #define SPLAT(p) vec_splat(vec_ld(0, p), 0) #define ALL_EQ(v1, v2) vec_all_eq(v1, v2) +/* altivec.h may redefine the bool macro as vector type. + * Reset it to POSIX semantics. */ +#undef bool +#define bool _Bool #elif defined __SSE2__ #include #define VECTYPE __m128i -- cgit v1.2.3 From 60b46aa2f3d40457d6f722cc79e3dbacd04b492f Mon Sep 17 00:00:00 2001 From: Andreas Färber Date: Mon, 28 May 2012 03:18:31 +0200 Subject: cocoa: Suppress Cocoa frontend for -qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- ui/cocoa.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index e7d6e898e..2383646dc 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -879,7 +879,8 @@ int main (int argc, const char * argv[]) { !strcmp(opt, "-vnc") || !strcmp(opt, "-nographic") || !strcmp(opt, "-version") || - !strcmp(opt, "-curses")) { + !strcmp(opt, "-curses") || + !strcmp(opt, "-qtest")) { return qemu_main(gArgc, gArgv, *_NSGetEnviron()); } } -- cgit v1.2.3 From 8294a64d7f9ecc428cd58ba36ad0b913084a8824 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 9 May 2012 18:23:06 +0300 Subject: vga: fix vram double-mapping with -vga std and -M pc-0.12 With pc-0.12, we map the video RAM both through the PCI BAR (the guest does this) and through a fixed mapping at 0xe0000000. The memory API doesn't allow this double map, and aborts. Fix by using an alias. Reported-by: Michael Tokarev Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- hw/vga.c | 7 ++++++- hw/vga_int.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/vga.c b/hw/vga.c index 5824f85d0..d784df7df 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -2357,10 +2357,15 @@ void vga_init(VGACommonState *s, MemoryRegion *address_space, void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory) { #ifdef CONFIG_BOCHS_VBE + /* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region, + * so use an alias to avoid double-mapping the same region. + */ + memory_region_init_alias(&s->vram_vbe, "vram.vbe", + &s->vram, 0, memory_region_size(&s->vram)); /* XXX: use optimized standard vga accesses */ memory_region_add_subregion(system_memory, VBE_DISPI_LFB_PHYSICAL_ADDRESS, - &s->vram); + &s->vram_vbe); s->vbe_mapped = 1; #endif } diff --git a/hw/vga_int.h b/hw/vga_int.h index 7685b2b16..d244d8ff9 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -105,6 +105,7 @@ typedef struct VGACommonState { MemoryRegion *legacy_address_space; uint8_t *vram_ptr; MemoryRegion vram; + MemoryRegion vram_vbe; uint32_t vram_size; uint32_t latch; MemoryRegion *chain4_alias; -- cgit v1.2.3 From 9c3a596a03cc10c2d9097f057b9ccb9d557a4d5f Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Mon, 26 Mar 2012 15:27:00 -0400 Subject: fix multiboot loading if load_end_addr == 0 The previous multiboot load code did not treat the case where load_end_addr was 0 specially. The multiboot specification says the following: * load_end_addr Contains the physical address of the end of the data segment. (load_end_addr - load_addr) specifies how much data to load. This implies that the text and data segments must be consecutive in the OS image; this is true for existing a.out executable formats. If this field is zero, the boot loader assumes that the text and data segments occupy the whole OS image file. Signed-off-by: Scott Moser Signed-off-by: Anthony Liguori --- hw/multiboot.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/hw/multiboot.c b/hw/multiboot.c index b4484a326..b1e04c571 100644 --- a/hw/multiboot.c +++ b/hw/multiboot.c @@ -202,10 +202,16 @@ int load_multiboot(void *fw_cfg, uint32_t mh_bss_end_addr = ldl_p(header+i+24); mh_load_addr = ldl_p(header+i+16); uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr); - uint32_t mb_load_size = mh_load_end_addr - mh_load_addr; - + uint32_t mb_load_size = 0; mh_entry_addr = ldl_p(header+i+28); - mb_kernel_size = mh_bss_end_addr - mh_load_addr; + + if (mh_load_end_addr) { + mb_kernel_size = mh_bss_end_addr - mh_load_addr; + mb_load_size = mh_load_end_addr - mh_load_addr; + } else { + mb_kernel_size = kernel_file_size - mb_kernel_text_offset; + mb_load_size = mb_kernel_size; + } /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE. uint32_t mh_mode_type = ldl_p(header+i+32); -- cgit v1.2.3 From a6de8ed80e1cf47d0f372e0856e6eeb6de9bbf0e Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Sun, 20 May 2012 17:57:45 +0800 Subject: pci: call object_unparent() before free_qdev() Start VM with 8 multiple-function block devs, hot-removing those block devs by 'device_del ...' would cause qemu abort. | (qemu) device_del virti0-0-0 | (qemu) ** |ERROR:qom/object.c:389:object_delete: assertion failed: (obj->ref == 0) It's a regression introduced by commit 57c9fafe The whole PCI slot should be removed once. Currently only one func is cleaned in pci_unplug_device(), if you try to remove a single func by monitor cmd. free_qdev() are called for all functions in slot, but unparent_delete() is only called for one function. Signed-off-by: XXXX Signed-off-by: Anthony Liguori --- hw/acpi_piix4.c | 1 + hw/pci.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 585da4e3e..0345490ee 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -299,6 +299,7 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots) if (pc->no_hotplug) { slot_free = false; } else { + object_unparent(OBJECT(dev)); qdev_free(qdev); } } diff --git a/hw/pci.c b/hw/pci.c index b706e6980..c1ebdde91 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1527,7 +1527,6 @@ static int pci_unplug_device(DeviceState *qdev) qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev))); return -1; } - object_unparent(OBJECT(dev)); return dev->bus->hotplug(dev->bus->hotplug_qdev, dev, PCI_HOTPLUG_DISABLED); } -- cgit v1.2.3 From eecae14724b64d43f9a44b9b4e69143961c201a3 Mon Sep 17 00:00:00 2001 From: Andreas Färber Date: Sun, 27 May 2012 17:02:20 +0200 Subject: qemu-ga: Fix use of environ on Darwin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use _NSGetEnviron() helper to access the environment. Signed-off-by: Andreas Färber Cc: Charlie Somerville Signed-off-by: Michael Roth --- qga/commands-posix.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index dab3bf9c9..4a71c27c4 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -22,8 +22,13 @@ #include "host-utils.h" #ifndef CONFIG_HAS_ENVIRON +#ifdef __APPLE__ +#include +#define environ (*_NSGetEnviron()) +#else extern char **environ; #endif +#endif #if defined(__linux__) #include -- cgit v1.2.3 From 9e2fa418fbe71dd472fe5a9cd89ca26d5b594920 Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Tue, 29 May 2012 10:08:50 -0500 Subject: qemu-ga: avoid blocking on atime update when reading /etc/mtab Currently we re-read/re-process /etc/mtab to get an updated list of mounts when guest-fsfreeze-thaw is called. This can cause an atime update on /etc/mtab, which will block if we're in a frozen state. Instead, use /proc's version of mtab, which may not be up-to-date with options passed via -o remount, but is compatible for our use cases since we only care about the filesystem type. Reported-by: Matsuda, Daiki Signed-off-by: Michael Roth --- qga/commands-posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 4a71c27c4..00d035da9 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -345,7 +345,7 @@ static int guest_fsfreeze_build_mount_list(GuestFsfreezeMountList *mounts) { struct mntent *ment; GuestFsfreezeMount *mount; - char const *mtab = MOUNTED; + char const *mtab = "/proc/self/mounts"; FILE *fp; fp = setmntent(mtab, "r"); -- cgit v1.2.3 From 1352672860399b40965b5093dd026688979e60a5 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Mon, 21 May 2012 11:27:02 -0300 Subject: Expose CPUID leaf 7 only for -cpu host Changes v2 -> v3; - Check for kvm_enabled() before setting cpuid_7_0_ebx_features Changes v1 -> v2: - Use kvm_arch_get_supported_cpuid() instead of host_cpuid() on cpu_x86_fill_host(). We should use GET_SUPPORTED_CPUID for all bits on "-cpu host" eventually, but I am not changing all the other CPUID leaves because we may not be able to test such an intrusive change in time for 1.1. Description of the bug: Since QEMU 0.15, the CPUID information on CPUID[EAX=7,ECX=0] is being returned unfiltered to the guest, directly from the GET_SUPPORTED_CPUID return value. The problem is that this makes the resulting CPU feature flags unpredictable and dependent on the host CPU and kernel version. This breaks live-migration badly if migrating from a host CPU that supports some features on that CPUID leaf (running a recent kernel) to a kernel or host CPU that doesn't support it. Migration also is incorrect (the virtual CPU changes under the guest's feet) if you migrate in the opposite direction (from an old CPU/kernel to a new CPU/kernel), but with less serious consequences (guests normally query CPUID information only once on boot). Fortunately, the bug affects only users using cpudefs with level >= 7. The right behavior should be to explicitly enable those features on [cpudef] config sections or on the "-cpu" command-line arguments. Right now there is no predefined CPU model on QEMU that has those features: the latest Intel model we have is Sandy Bridge. I would like to get this fixed on 1.1, so I am submitting this patch, that enables those features only if "-cpu host" is being used (as we don't have any pre-defined CPU model that actually have those features). After 1.1 is released, we can make those features properly configurable on [cpudef] and -cpu configuration. One problem is: with this patch, users with the following setup: - Running QEMU 1.0; - Using a cpudef having level >= 7; - Running a kernel that supports the features on CPUID leaf 7; and - Running on a CPU that supports some features on CPUID leaf 7 won't be able to live-migrate to QEMU 1.1. But for these users live-migration is already broken (they can't live-migrate to hosts with older CPUs or older kernels, already), I don't see how to avoid this problem. Signed-off-by: Eduardo Habkost Signed-off-by: Anthony Liguori --- target-i386/cpu.c | 22 +++++++++++++++------- target-i386/cpu.h | 2 ++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 89b4ac7ec..388bc5c52 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -238,6 +238,8 @@ typedef struct x86_def_t { /* Store the results of Centaur's CPUID instructions */ uint32_t ext4_features; uint32_t xlevel2; + /* The feature bits on CPUID[EAX=7,ECX=0].EBX */ + uint32_t cpuid_7_0_ebx_features; } x86_def_t; #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE) @@ -521,6 +523,12 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def->ext_features = ecx; x86_cpu_def->features = edx; + if (kvm_enabled() && x86_cpu_def->level >= 7) { + x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX); + } else { + x86_cpu_def->cpuid_7_0_ebx_features = 0; + } + host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx); x86_cpu_def->xlevel = eax; @@ -1185,6 +1193,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_kvm_features = def->kvm_features; env->cpuid_svm_features = def->svm_features; env->cpuid_ext4_features = def->ext4_features; + env->cpuid_7_0_ebx = def->cpuid_7_0_ebx_features; env->cpuid_xlevel2 = def->xlevel2; object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000, "tsc-frequency", &error); @@ -1451,13 +1460,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *edx = 0; break; case 7: - if (kvm_enabled()) { - KVMState *s = env->kvm_state; - - *eax = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EAX); - *ebx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EBX); - *ecx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_ECX); - *edx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EDX); + /* Structured Extended Feature Flags Enumeration Leaf */ + if (count == 0) { + *eax = 0; /* Maximum ECX value for sub-leaves */ + *ebx = env->cpuid_7_0_ebx; /* Feature flags */ + *ecx = 0; /* Reserved */ + *edx = 0; /* Reserved */ } else { *eax = 0; *ebx = 0; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index b5b9a5069..2460f6348 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -741,6 +741,8 @@ typedef struct CPUX86State { /* Store the results of Centaur's CPUID instructions */ uint32_t cpuid_xlevel2; uint32_t cpuid_ext4_features; + /* Flags from CPUID[EAX=7,ECX=0].EBX */ + uint32_t cpuid_7_0_ebx; /* MTRRs */ uint64_t mtrr_fixed[11]; -- cgit v1.2.3 From 1643f2b232628905e8f32965ff36a87bd53b93c5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 24 May 2012 10:55:01 +0200 Subject: vnc: fix segfault in vnc_display_pw_expire() NULL pointer dereference in case no vnc server is configured. Catch this and return -EINVAL like vnc_display_password() does. Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- ui/vnc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/vnc.c b/ui/vnc.c index be384a531..54bc5adab 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -2849,6 +2849,10 @@ int vnc_display_pw_expire(DisplayState *ds, time_t expires) { VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + if (!vs) { + return -EINVAL; + } + vs->expires = expires; return 0; } -- cgit v1.2.3 From e78bd5ab07d65fec77fcae468b2836c79a836d49 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 29 May 2012 11:20:31 +0200 Subject: xhci: add usage info to docs Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- docs/usb2.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/usb2.txt b/docs/usb2.txt index 228aa33ce..d17e3c004 100644 --- a/docs/usb2.txt +++ b/docs/usb2.txt @@ -55,6 +55,21 @@ try ... ... then use "bus=ehci.0" to assign your usb devices to that bus. +xhci controller support +----------------------- + +There also is xhci host controller support available. It got alot +less testing than ehci and there are a bunch of known limitations, so +ehci may work better for you. On the other hand the xhci hardware +design is much more virtualization-friendly, thus xhci emulation uses +less ressources (especially cpu). If you wanna give xhci a try +use this to add the host controller ... + + qemu -device nec-usb-xhci,id=xhci + +... then use "bus=xhci.0" when assigning usb devices. + + More USB tips & tricks ====================== -- cgit v1.2.3 From eba25057b9a5e19d10ace2bc7716667a31297169 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Mon, 28 May 2012 09:27:54 +0200 Subject: block: prevent snapshot mode $TMPDIR symlink attack In snapshot mode, bdrv_open creates an empty temporary file without checking for mkstemp or close failure, and ignoring the possibility of a buffer overrun given a surprisingly long $TMPDIR. Change the get_tmp_filename function to return int (not void), so that it can inform its two callers of those failures. Also avoid the risk of buffer overrun and do not ignore mkstemp or close failure. Update both callers (in block.c and vvfat.c) to propagate temp-file-creation failure to their callers. get_tmp_filename creates and closes an empty file, while its callers later open that presumed-existing file with O_CREAT. The problem was that a malicious user could provoke mkstemp failure and race to create a symlink with the selected temporary file name, thus causing the qemu process (usually root owned) to open through the symlink, overwriting an attacker-chosen file. This addresses CVE-2012-2652. http://bugzilla.redhat.com/CVE-2012-2652 Reviewed-by: Stefan Hajnoczi Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- block.c | 37 ++++++++++++++++++++++++------------- block/vvfat.c | 7 ++++++- block_int.h | 2 +- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/block.c b/block.c index af2ab4f3e..7547051ec 100644 --- a/block.c +++ b/block.c @@ -409,28 +409,36 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options) return bdrv_create(drv, filename, options); } -#ifdef _WIN32 -void get_tmp_filename(char *filename, int size) +/* + * Create a uniquely-named empty temporary file. + * Return 0 upon success, otherwise a negative errno value. + */ +int get_tmp_filename(char *filename, int size) { +#ifdef _WIN32 char temp_dir[MAX_PATH]; - - GetTempPath(MAX_PATH, temp_dir); - GetTempFileName(temp_dir, "qem", 0, filename); -} + /* GetTempFileName requires that its output buffer (4th param) + have length MAX_PATH or greater. */ + assert(size >= MAX_PATH); + return (GetTempPath(MAX_PATH, temp_dir) + && GetTempFileName(temp_dir, "qem", 0, filename) + ? 0 : -GetLastError()); #else -void get_tmp_filename(char *filename, int size) -{ int fd; const char *tmpdir; - /* XXX: race condition possible */ tmpdir = getenv("TMPDIR"); if (!tmpdir) tmpdir = "/tmp"; - snprintf(filename, size, "%s/vl.XXXXXX", tmpdir); + if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) { + return -EOVERFLOW; + } fd = mkstemp(filename); - close(fd); -} + if (fd < 0 || close(fd)) { + return -errno; + } + return 0; #endif +} /* * Detect host devices. By convention, /dev/cdrom[N] is always @@ -753,7 +761,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, bdrv_delete(bs1); - get_tmp_filename(tmp_filename, sizeof(tmp_filename)); + ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename)); + if (ret < 0) { + return ret; + } /* Real path is meaningless for protocols */ if (is_protocol) diff --git a/block/vvfat.c b/block/vvfat.c index 2dc9d5088..0fd3367d8 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -2808,7 +2808,12 @@ static int enable_write_target(BDRVVVFATState *s) array_init(&(s->commits), sizeof(commit_t)); s->qcow_filename = g_malloc(1024); - get_tmp_filename(s->qcow_filename, 1024); + ret = get_tmp_filename(s->qcow_filename, 1024); + if (ret < 0) { + g_free(s->qcow_filename); + s->qcow_filename = NULL; + return ret; + } bdrv_qcow = bdrv_find_format("qcow"); options = parse_option_parameters("", bdrv_qcow->create_options, NULL); diff --git a/block_int.h b/block_int.h index b80e66db6..3d4abc657 100644 --- a/block_int.h +++ b/block_int.h @@ -335,7 +335,7 @@ struct BlockDriverState { BlockJob *job; }; -void get_tmp_filename(char *filename, int size); +int get_tmp_filename(char *filename, int size); void bdrv_set_io_limits(BlockDriverState *bs, BlockIOLimit *io_limits); -- cgit v1.2.3 From 6f12926142bd3ab5bea700decdeb59a16b9cd8ae Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Wed, 30 May 2012 17:04:41 +0000 Subject: pc-bios: Update OpenBIOS images Update OpenBIOS images to r1060 built from submodule. Signed-off-by: Blue Swirl --- pc-bios/README | 2 +- pc-bios/openbios-ppc | Bin 729876 -> 729876 bytes pc-bios/openbios-sparc32 | Bin 381764 -> 381764 bytes pc-bios/openbios-sparc64 | Bin 1598648 -> 1598648 bytes roms/openbios | 2 +- 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pc-bios/README b/pc-bios/README index 6b64d6868..e56e9e5f0 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -12,7 +12,7 @@ 1275-1994 (referred to as Open Firmware) compliant firmware. The included images for PowerPC (for 32 and 64 bit PPC CPUs), Sparc32 and Sparc64 are built from OpenBIOS SVN revision - 1056. + 1060. - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc index d4656db8b..aeae26588 100644 Binary files a/pc-bios/openbios-ppc and b/pc-bios/openbios-ppc differ diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32 index 4312c690a..d90c4e59a 100644 Binary files a/pc-bios/openbios-sparc32 and b/pc-bios/openbios-sparc32 differ diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64 index b18610508..457d26422 100644 Binary files a/pc-bios/openbios-sparc64 and b/pc-bios/openbios-sparc64 differ diff --git a/roms/openbios b/roms/openbios index ff61d973e..d1d2787f8 160000 --- a/roms/openbios +++ b/roms/openbios @@ -1 +1 @@ -Subproject commit ff61d973e5a4a68b29e485b3f88e6a2d1d96cf45 +Subproject commit d1d2787f87167edf487a60e61b9168514d5a7434 -- cgit v1.2.3 From b3dbb9546ade0108156a04b4983cd3057fd77563 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Thu, 31 May 2012 08:53:39 +0800 Subject: Update version for 1.1.0-rc4 release Signed-off-by: Anthony Liguori --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 87903b67d..00572cea3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.93 +1.0.94 -- cgit v1.2.3