Re: [Qemu-devel] [PATCH v3 2/3] qdev: interface for SysBusDevice to change property on requirement
On Fri, Aug 30, 2013 at 4:17 PM, Paolo Bonzini pbonz...@redhat.com wrote: Il 30/08/2013 09:53, Liu Ping Fan ha scritto: qdev's property can not be set after realized, but there is a requirement of adjusting device's behavior on different mother boards. So introducing a callback in sysbus_try_create_simple() to adjust device's property on board's demand. (This patch is needed by the later one which changes hpet's intcap property) I don't think it is useful to add a new mechanism since there is an existing mechanism to set properties for compatibility (which I pointed you to earlier). It is also incorrect because this will have an effect Oh, just aware of this tricky method to set qdev's property. Thanks, will try this way! Regards, Pingfan on all PC boards including pc-q35-1.7 and newer. You need to create a 1.7 machine like commit 45053fd (pc: Create pc-*-1.6 machine-types, 2013-05-27). On top of this: * the 1.6 machines need to have a compatibility property in hw/i386/pc.h. * the pc-i440fx-1.7 machine needs to have a compatibility property for the same thing in hw/i386/pc_piix.c Paolo Signed-off-by: Liu Ping Fan pingf...@linux.vnet.ibm.com --- hw/core/sysbus.c| 5 - hw/i386/pc.c| 2 +- include/hw/sysbus.h | 8 +--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c index 9004d8c..e894bbb 100644 --- a/hw/core/sysbus.c +++ b/hw/core/sysbus.c @@ -172,7 +172,7 @@ DeviceState *sysbus_create_varargs(const char *name, return dev; } -DeviceState *sysbus_try_create_varargs(const char *name, +DeviceState *sysbus_try_create_varargs(const char *name, CompatSet set, hwaddr addr, ...) { DeviceState *dev; @@ -185,6 +185,9 @@ DeviceState *sysbus_try_create_varargs(const char *name, if (!dev) { return NULL; } +if (set) { +set(dev); +} s = SYS_BUS_DEVICE(dev); qdev_init_nofail(dev); if (addr != (hwaddr)-1) { diff --git a/hw/i386/pc.c b/hw/i386/pc.c index e8bc8ce..09c10ac 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1247,7 +1247,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, * when the HPET wants to take over. Thus we have to disable the latter. */ if (!no_hpet (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) { -hpet = sysbus_try_create_simple(hpet, HPET_BASE, NULL); +hpet = sysbus_try_create_simple(hpet, NULL, HPET_BASE, NULL); if (hpet) { for (i = 0; i GSI_NUM_PINS; i++) { diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h index bb50a87..47337f2 100644 --- a/include/hw/sysbus.h +++ b/include/hw/sysbus.h @@ -58,6 +58,8 @@ struct SysBusDevice { pio_addr_t pio[QDEV_MAX_PIO]; }; +typedef void (*CompatSet)(DeviceState *dev); + void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory); MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n); void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p); @@ -77,7 +79,7 @@ MemoryRegion *sysbus_address_space(SysBusDevice *dev); /* Legacy helper function for creating devices. */ DeviceState *sysbus_create_varargs(const char *name, hwaddr addr, ...); -DeviceState *sysbus_try_create_varargs(const char *name, +DeviceState *sysbus_try_create_varargs(const char *name, CompatSet set, hwaddr addr, ...); static inline DeviceState *sysbus_create_simple(const char *name, hwaddr addr, @@ -86,11 +88,11 @@ static inline DeviceState *sysbus_create_simple(const char *name, return sysbus_create_varargs(name, addr, irq, NULL); } -static inline DeviceState *sysbus_try_create_simple(const char *name, +static inline DeviceState *sysbus_try_create_simple(const char *name, CompatSet set, hwaddr addr, qemu_irq irq) { -return sysbus_try_create_varargs(name, addr, irq, NULL); +return sysbus_try_create_varargs(name, set, addr, irq, NULL); } #endif /* !HW_SYSBUS_H */
[Qemu-devel] [Bug 1024248] Re: qemu -M isapc displays blank screen
It looks like this issue is fixed in 1.6.0 version ** Changed in: qemu Status: Confirmed = Fix Released -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1024248 Title: qemu -M isapc displays blank screen Status in QEMU: Fix Released Status in “qemu” package in Debian: Confirmed Bug description: $ qemu-system-x86_64 -M isapc This displays blank SDL window. It has been this way since forever I guess, at least according to http://bugs.debian.org/605525 (a Debian bugreport about it). However, this: $ qemu-system-x86_64 -M isapc -enable-kvm works (at least in current 1.1), and it works fine in qemu-kvm. On the other hand, this: $ qemu-kvm -M isapc -no-kvm also shows blank window. Something is wrong with isapc TCG, and has been for a long time... Thanks, /mjt To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1024248/+subscriptions
Re: [Qemu-devel] [PATCH v3 2/3] qdev: interface for SysBusDevice to change property on requirement
On Fri, Aug 30, 2013 at 8:32 PM, Andreas Färber afaer...@suse.de wrote: Am 30.08.2013 10:17, schrieb Paolo Bonzini: Il 30/08/2013 09:53, Liu Ping Fan ha scritto: qdev's property can not be set after realized, but there is a requirement of adjusting device's behavior on different mother boards. So introducing a callback in sysbus_try_create_simple() to adjust device's property on board's demand. (This patch is needed by the later one which changes hpet's intcap property) I don't think it is useful to add a new mechanism since there is an existing mechanism to set properties for compatibility (which I pointed you to earlier). It is also incorrect because this will have an effect on all PC boards including pc-q35-1.7 and newer. You need to create a 1.7 machine like commit 45053fd (pc: Create pc-*-1.6 machine-types, 2013-05-27). Stefan already has than in his net tree and just needs to (rebase and) flush his queue! Thanks, will do like it. Regards, Pingfan
Re: [Qemu-devel] [Qemu-trivial] [PATCH v3] slirp: Port redirection option behave differently on Linux and Windows
On 2013-09-01 18:13, Stefan Weil wrote: Am 01.09.2013 17:46, schrieb Michael Tokarev: 30.08.2013 15:04, Jan Kiszka wrote: On 2013-08-15 21:25, Taimoor wrote: From: Taimoor Mirza tmi...@codesourcery.com port redirection code uses SO_REUSEADDR socket option before binding to host port. Behavior of SO_REUSEADDR is different on Windows and Linux. Relaunching QEMU with same host and guest port redirection values on Linux throws error but on Windows it does not throw any error. Problem is discussed in http://lists.gnu.org/archive/html/qemu-devel/2013-04/msg03089.html [] Stefan, can you ack this? Then I would pick it up for the slirp queue. I remember having exactly the same issue myself a few years back with the difference of SO_REUSEADDR behavour on windows and *nix, and the suggested change appears to be correct. So you can count on my Reviewed-by: Michael Tokarev m...@tls.msk.ru as well. I applied the v2 of this patch (with a trivial fix) to trivial queue (before seeing this v3), I can remove it if you like. Thanks, /mjt Hi Michael, thanks for your review of this patch. I had no opportunity to test it myself, but I also think that it is fine. (v2 + trivial fix) should be identical to v3, so this looks good, too. Yep, fine with me as well. Thanks, everyone. Jan -- Siemens AG, Corporate Technology, CT RTC ITP SES-DE Corporate Competence Center Embedded Linux
[Qemu-devel] [Bug 1187121] Re: segfault with -vga vmware and -display gtk
This has been fixed in 1.6.0. ** Changed in: qemu Status: Confirmed = Fix Released -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1187121 Title: segfault with -vga vmware and -display gtk Status in QEMU: Fix Released Status in “qemu” package in Debian: Confirmed Bug description: When some guest is run with -vga vmware -display gtk, qemu segfaults after certain guest gui operations. ./x86_64-softmmu/qemu-system-x86_64 -cdrom ubuntu-10.04.4-desktop-i386.iso -vga vmware -enable-kvm (-enable-kvm just to speed things up, it does not depend on kvm). (Ubuntu desktop image is from http://old- releases.ubuntu.com/releases/lucid/ ) This segfaults in a few moments after initial boot. Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0xf5bccb70 (LWP 23460)] 0xf710792c in g_object_unref () from /usr/lib/i386-linux-gnu/libgobject-2.0.so.0 (gdb) bt #0 0xf710792c in g_object_unref () from /usr/lib/i386-linux-gnu/libgobject-2.0.so.0 #1 0x5673b635 in gd_cursor_define (dcl=0x57153d44, c=0x5710e7b8) at ui/gtk.c:380 #2 0x5673895b in dpy_cursor_define (con=0x570c07f8, cursor=cursor@entry=0x5710e7b8) at ui/console.c:1547 #3 0x5665f2a7 in vmsvga_cursor_define (c=0xf5bc6ef0, s=optimized out) at hw/display/vmware_vga.c:492 #4 vmsvga_fifo_run (s=optimized out) at hw/display/vmware_vga.c:628 #5 0x567ce6a8 in memory_region_write_accessor ( opaque=opaque@entry=0x571291d0, addr=1, value=value@entry=0xf5bcc038, size=size@entry=4, shift=0, mask=4294967295) at memory.c:334 #6 0x567ce146 in access_with_adjusted_size (addr=optimized out, value=value@entry=0xf5bcc038, size=size@entry=4, access_size_min=optimized out, access_size_max=optimized out, access=access@entry=0x567ce5e0 memory_region_write_accessor, opaque=opaque@entry=0x571291d0) at memory.c:364 #7 0x567cf28c in memory_region_iorange_write (iorange=0x57243f58, offset=1, width=4, data=1) at memory.c:439 #8 0x567c8b48 in ioport_writel_thunk (opaque=0x57243f58, addr=49233, data=1) at ioport.c:226 #9 0x567c92d3 in ioport_write (data=1, address=49233, index=2) ... (gdb) frame 1 #1 0x5673b635 in gd_cursor_define (dcl=0x57153d44, c=0x5710e7b8) at ui/gtk.c:380 380 g_object_unref(cursor); (gdb) p cursor $1 = (GdkCursor *) 0x570eb1e0 (gdb) p *cursor $2 = {type = GDK_CURSOR_IS_PIXMAP, ref_count = 3} (gdb) frame 2 #2 0x5673895b in dpy_cursor_define (con=0x570c07f8, cursor=cursor@entry=0x5710e7b8) at ui/console.c:1547 1547 dcl-ops-dpy_cursor_define(dcl, cursor); (gdb) p *cursor $3 = {width = 64, height = 64, hot_x = 0, hot_y = 0, refcount = 1, data = 0x5710e7cc} (gdb) p *cursor-data $4 = 0 (gdb) l 1542 QLIST_FOREACH(dcl, s-listeners, next) { 1543 if (con != (dcl-con ? dcl-con : active_console)) { 1544 continue; 1545 } 1546 if (dcl-ops-dpy_cursor_define) { 1547 dcl-ops-dpy_cursor_define(dcl, cursor); 1548 } 1549 } 1550 } 1551 (gdb) To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1187121/+subscriptions
[Qemu-devel] [PATCH v4 0/3] bugs fix for hpet
note: I rebase it onto Stefan's net-next tree, since pc-1.7 has already been defined there. v4: use standard compat property to set hpet's interrupt compatibility v3: change hpet interrupt capablity on board's demand Liu Ping Fan (3): hpet: inverse polarity when pin above ISA_NUM_IRQS hpet: entitle more irq pins for hpet pc-1.6: add compatibility for hpet intcap on pc-*-1.6 hw/timer/hpet.c | 27 +++ include/hw/i386/pc.h | 5 + 2 files changed, 28 insertions(+), 4 deletions(-) -- 1.8.1.4
[Qemu-devel] [PATCH v4 1/3] hpet: inverse polarity when pin above ISA_NUM_IRQS
According to hpet spec, hpet irq is high active. But according to ICH spec, there is inversion before the input of ioapic. So the OS will expect low active on this IRQ line.(And this is observed on bare metal). We fold the emulation of this inversion inside the hpet logic. Signed-off-by: Liu Ping Fan pingf...@linux.vnet.ibm.com --- hw/timer/hpet.c | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index 648b383..1139448 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -198,13 +198,23 @@ static void update_irq(struct HPETTimer *timer, int set) if (!set || !timer_enabled(timer) || !hpet_enabled(timer-state)) { s-isr = ~mask; if (!timer_fsb_route(timer)) { -qemu_irq_lower(s-irqs[route]); +/* fold the ICH PIRQ# pin's internal inversion logic into hpet */ +if (route = ISA_NUM_IRQS) { +qemu_irq_raise(s-irqs[route]); +} else { +qemu_irq_lower(s-irqs[route]); +} } } else if (timer_fsb_route(timer)) { stl_le_phys(timer-fsb 32, timer-fsb 0x); } else if (timer-config HPET_TN_TYPE_LEVEL) { s-isr |= mask; -qemu_irq_raise(s-irqs[route]); +/* fold the ICH PIRQ# pin's internal inversion logic into hpet */ +if (route = ISA_NUM_IRQS) { +qemu_irq_lower(s-irqs[route]); +} else { +qemu_irq_raise(s-irqs[route]); +} } else { s-isr = ~mask; qemu_irq_pulse(s-irqs[route]); -- 1.8.1.4
[Qemu-devel] [PATCH v4 2/3] hpet: entitle more irq pins for hpet
On PC, IRQ2/8 can be reserved for hpet timer 0/1. And pin 16~23 of ioapic can be dynamically assigned to hpet as guest chooses. (Will enable them after introducing pc 1.6 compat) Signed-off-by: Liu Ping Fan pingf...@linux.vnet.ibm.com --- hw/timer/hpet.c | 13 +++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index 1139448..888be66 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -25,6 +25,7 @@ */ #include hw/hw.h +#include hw/boards.h #include hw/i386/pc.h #include ui/console.h #include qemu/timer.h @@ -42,6 +43,12 @@ #define HPET_MSI_SUPPORT0 +/* For bug compat, using only IRQ2. Soon it will be fixed as + * 0xff0104ULL, i.e using IRQ16~23, IRQ8 and IRQ2 after + * introducing pc-1.6 compat. + */ +#define HPET_TN_INT_CAP_DEFAULT 0x4ULL + #define TYPE_HPET hpet #define HPET(obj) OBJECT_CHECK(HPETState, (obj), TYPE_HPET) @@ -73,6 +80,7 @@ typedef struct HPETState { uint8_t rtc_irq_level; qemu_irq pit_enabled; uint8_t num_timers; +uint32_t intcap; HPETTimer timer[HPET_MAX_TIMERS]; /* Memory-mapped, software visible registers */ @@ -663,8 +671,8 @@ static void hpet_reset(DeviceState *d) if (s-flags (1 HPET_MSI_SUPPORT)) { timer-config |= HPET_TN_FSB_CAP; } -/* advertise availability of ioapic inti2 */ -timer-config |= 0x0004ULL 32; +/* advertise availability of ioapic int */ +timer-config |= (uint64_t)s-intcap 32; timer-period = 0ULL; timer-wrap_flag = 0; } @@ -753,6 +761,7 @@ static void hpet_realize(DeviceState *dev, Error **errp) static Property hpet_device_properties[] = { DEFINE_PROP_UINT8(timers, HPETState, num_timers, HPET_MIN_TIMERS), DEFINE_PROP_BIT(msi, HPETState, flags, HPET_MSI_SUPPORT, false), +DEFINE_PROP_UINT32(intcap, HPETState, intcap, HPET_TN_INT_CAP_DEFAULT), DEFINE_PROP_END_OF_LIST(), }; -- 1.8.1.4
[Qemu-devel] [PATCH v4 3/3] pc-1.6: add compatibility for hpet intcap on pc-*-1.6
For guest bug compat, we limit hpet's interrupt compatibility on ioapic's IRQ2 for pc-*-1.6. As to pc-*-1.7 and newer, IRQ2, IRQ8, and IRQ16~23 are allowed. Signed-off-by: Liu Ping Fan pingf...@linux.vnet.ibm.com --- hw/timer/hpet.c | 6 +- include/hw/i386/pc.h | 4 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index 888be66..b6e8c12 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -43,11 +43,7 @@ #define HPET_MSI_SUPPORT0 -/* For bug compat, using only IRQ2. Soon it will be fixed as - * 0xff0104ULL, i.e using IRQ16~23, IRQ8 and IRQ2 after - * introducing pc-1.6 compat. - */ -#define HPET_TN_INT_CAP_DEFAULT 0x4ULL +#define HPET_TN_INT_CAP_DEFAULT 0xff0104ULL #define TYPE_HPET hpet #define HPET(obj) OBJECT_CHECK(HPETState, (obj), TYPE_HPET) diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 894c124..ef481bc 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -219,6 +219,10 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); .driver = e1000,\ .property = mitigation,\ .value= off,\ +},{\ +.driver = hpet,\ +.property = intcap,\ +.value= stringify(4),\ } #define PC_COMPAT_1_5 \ -- 1.8.1.4
Re: [Qemu-devel] [PATCH v3 04/19] block: update bs-total_sectors on writes
On 17.08.2013 08:27, Paolo Bonzini wrote: Il 02/08/2013 09:05, Peter Lieven ha scritto: can you give an update what are to current plans/schedule to merge this series? I have a few patches in the queue that in their current version depend on this series being merged. It should go in soon, perhaps a couple of weeks. That would be good. I would like to make the relevant changes to iscsi soon and as I promised to convert everything in block/iscsi to coroutines this will be a lot. Peter
[Qemu-devel] [PATCH v5 3/8] qcow2: Employ metadata overlap checks
The pre-write overlap check function is now called before most of the qcow2 writes (aborting it on collision or other error). Signed-off-by: Max Reitz mre...@redhat.com --- block/qcow2-cache.c| 17 + block/qcow2-cluster.c | 21 + block/qcow2-snapshot.c | 22 ++ block/qcow2.c | 26 ++ 4 files changed, 86 insertions(+) diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c index 2f3114e..7bcae09 100644 --- a/block/qcow2-cache.c +++ b/block/qcow2-cache.c @@ -115,6 +115,23 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i) } if (c == s-refcount_block_cache) { +ret = qcow2_pre_write_overlap_check(bs, +QCOW2_OL_DEFAULT ~QCOW2_OL_REFCOUNT_BLOCK, +c-entries[i].offset, s-cluster_size); +} else if (c == s-l2_table_cache) { +ret = qcow2_pre_write_overlap_check(bs, +QCOW2_OL_DEFAULT ~QCOW2_OL_ACTIVE_L2, +c-entries[i].offset, s-cluster_size); +} else { +ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, +c-entries[i].offset, s-cluster_size); +} + +if (ret 0) { +return ret; +} + +if (c == s-refcount_block_cache) { BLKDBG_EVENT(bs-file, BLKDBG_REFBLOCK_UPDATE_PART); } else if (c == s-l2_table_cache) { BLKDBG_EVENT(bs-file, BLKDBG_L2_UPDATE); diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index cca76d4..7c248aa 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -80,6 +80,14 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, goto fail; } +/* the L1 position has not yet been updated, so these clusters must + * indeed be completely free */ +ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, +new_l1_table_offset, new_l1_size2); +if (ret 0) { +goto fail; +} + BLKDBG_EVENT(bs-file, BLKDBG_L1_GROW_WRITE_TABLE); for(i = 0; i s-l1_size; i++) new_l1_table[i] = cpu_to_be64(new_l1_table[i]); @@ -149,6 +157,13 @@ static int write_l1_entry(BlockDriverState *bs, int l1_index) buf[i] = cpu_to_be64(s-l1_table[l1_start_index + i]); } +ret = qcow2_pre_write_overlap_check(bs, +QCOW2_OL_DEFAULT ~QCOW2_OL_ACTIVE_L1, +s-l1_table_offset + 8 * l1_start_index, sizeof(buf)); +if (ret 0) { +return ret; +} + BLKDBG_EVENT(bs-file, BLKDBG_L1_UPDATE); ret = bdrv_pwrite_sync(bs-file, s-l1_table_offset + 8 * l1_start_index, buf, sizeof(buf)); @@ -368,6 +383,12 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs, s-aes_encrypt_key); } +ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, +cluster_offset + n_start * BDRV_SECTOR_SIZE, n * BDRV_SECTOR_SIZE); +if (ret 0) { +goto out; +} + BLKDBG_EVENT(bs-file, BLKDBG_COW_WRITE); ret = bdrv_co_writev(bs-file, (cluster_offset 9) + n_start, n, qiov); if (ret 0) { diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 0caac90..e7e6013 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -189,6 +189,15 @@ static int qcow2_write_snapshots(BlockDriverState *bs) return ret; } +/* The snapshot list position has not yet been updated, so these clusters + * must indeed be completely free */ +ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, offset, +s-snapshots_size); +if (ret 0) { +return ret; +} + + /* Write all snapshots to the new list */ for(i = 0; i s-nb_snapshots; i++) { sn = s-snapshots + i; @@ -363,6 +372,12 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) l1_table[i] = cpu_to_be64(s-l1_table[i]); } +ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, +sn-l1_table_offset, s-l1_size * sizeof(uint64_t)); +if (ret 0) { +goto fail; +} + ret = bdrv_pwrite(bs-file, sn-l1_table_offset, l1_table, s-l1_size * sizeof(uint64_t)); if (ret 0) { @@ -475,6 +490,13 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) goto fail; } +ret = qcow2_pre_write_overlap_check(bs, +QCOW2_OL_DEFAULT ~QCOW2_OL_ACTIVE_L1, +s-l1_table_offset, cur_l1_bytes); +if (ret 0) { +goto fail; +} + ret = bdrv_pwrite_sync(bs-file, s-l1_table_offset, sn_l1_table, cur_l1_bytes); if (ret 0) { diff --git a/block/qcow2.c b/block/qcow2.c index 16c9898..3a95ff1 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -624,6 +624,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags) qcow2_free_snapshots(bs);
[Qemu-devel] [PATCH v5 1/8] qcow2: Add corrupt bit
This adds an incompatible bit indicating corruption to qcow2. Any image with this bit set may not be written to unless for repairing (and subsequently clearing the bit if the repair has been successful). Signed-off-by: Max Reitz mre...@redhat.com --- block/qcow2.c | 47 ++ block/qcow2.h | 7 ++- docs/specs/qcow2.txt | 7 ++- tests/qemu-iotests/031.out | 12 ++-- tests/qemu-iotests/036.out | 2 +- 5 files changed, 66 insertions(+), 9 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 78097e5..16c9898 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -272,6 +272,37 @@ static int qcow2_mark_clean(BlockDriverState *bs) return 0; } +/* + * Marks the image as corrupt. + */ +int qcow2_mark_corrupt(BlockDriverState *bs) +{ +BDRVQcowState *s = bs-opaque; + +s-incompatible_features |= QCOW2_INCOMPAT_CORRUPT; +return qcow2_update_header(bs); +} + +/* + * Marks the image as consistent, i.e., unsets the corrupt bit, and flushes + * before if necessary. + */ +int qcow2_mark_consistent(BlockDriverState *bs) +{ +BDRVQcowState *s = bs-opaque; + +if (s-incompatible_features QCOW2_INCOMPAT_CORRUPT) { +int ret = bdrv_flush(bs); +if (ret 0) { +return ret; +} + +s-incompatible_features = ~QCOW2_INCOMPAT_CORRUPT; +return qcow2_update_header(bs); +} +return 0; +} + static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix) { @@ -402,6 +433,17 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags) goto fail; } +if (s-incompatible_features QCOW2_INCOMPAT_CORRUPT) { +/* Corrupt images may not be written to unless they are being repaired + */ +if ((flags BDRV_O_RDWR) !(flags BDRV_O_CHECK)) { +error_report(qcow2: Image is corrupt; cannot be opened +read/write.); +ret = -EACCES; +goto fail; +} +} + /* Check support for various header values */ if (header.refcount_order != 4) { report_unsupported(bs, %d bit reference counts, @@ -1130,6 +1172,11 @@ int qcow2_update_header(BlockDriverState *bs) .name = dirty bit, }, { +.type = QCOW2_FEAT_TYPE_INCOMPATIBLE, +.bit = QCOW2_INCOMPAT_CORRUPT_BITNR, +.name = corrupt bit, +}, +{ .type = QCOW2_FEAT_TYPE_COMPATIBLE, .bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR, .name = lazy refcounts, diff --git a/block/qcow2.h b/block/qcow2.h index dba9771..4297487 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -119,9 +119,12 @@ enum { /* Incompatible feature bits */ enum { QCOW2_INCOMPAT_DIRTY_BITNR = 0, +QCOW2_INCOMPAT_CORRUPT_BITNR = 1, QCOW2_INCOMPAT_DIRTY = 1 QCOW2_INCOMPAT_DIRTY_BITNR, +QCOW2_INCOMPAT_CORRUPT = 1 QCOW2_INCOMPAT_CORRUPT_BITNR, -QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY, +QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY + | QCOW2_INCOMPAT_CORRUPT, }; /* Compatible feature bits */ @@ -361,6 +364,8 @@ int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov, int64_t sector_num, int nb_sectors); int qcow2_mark_dirty(BlockDriverState *bs); +int qcow2_mark_corrupt(BlockDriverState *bs); +int qcow2_mark_consistent(BlockDriverState *bs); int qcow2_update_header(BlockDriverState *bs); /* qcow2-refcount.c functions */ diff --git a/docs/specs/qcow2.txt b/docs/specs/qcow2.txt index 36a559d..33eca36 100644 --- a/docs/specs/qcow2.txt +++ b/docs/specs/qcow2.txt @@ -80,7 +80,12 @@ in the description of a field. tables to repair refcounts before accessing the image. -Bits 1-63: Reserved (set to 0) +Bit 1: Corrupt bit. If this bit is set then any data +structure may be corrupt and the image must not +be written to (unless for regaining +consistency). + +Bits 2-63: Reserved (set to 0) 80 - 87: compatible_features Bitmask of compatible features. An implementation can diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out index 796c993..a943344 100644 --- a/tests/qemu-iotests/031.out +++ b/tests/qemu-iotests/031.out @@ -54,7 +54,7 @@ header_length 72 Header extension: magic 0x6803f857 -length96 +length144 data binary Header extension: @@ -68,7 +68,7 @@ No errors were found on the image. magic 0x514649fb version 2 -backing_file_offset
[Qemu-devel] [PATCH v5 0/8] Add metadata overlap checks
If a qcow2 image file becomes corrupted, any write may inadvertently overwrite important metadata structures such as the L1 table. This series adds functionality for detecting, preventing and (to some extent) repairing such collisions. v5: - fixed patch 6 (forgot to update the event_names array for the new event BLKDBG_REFTABLE_UPDATE); no other changes v4: - fixed handling of preallocated zero clusters in patch 4 - moved OFLAG_COPIED checks into a separate function (this affects patches 4 and 5); functionality remains unchanged - patches 1, 2, 3, 6, 7 and 8 remain unmodified (except for line numbers in block/qcow2-refcount.c) v3: - split PATCH 4/5 into four distinct patches (4/8, 5/8, 6/8 and 7/8, respectively) - directly generate a JSON message when marking the image corrupt - other (minor) fixes according to Kevin's comments v2: - Generally implemented Kevin's comments, especially: - new QMP event QEVENT_BLOCK_IMAGE_CORRUPTED - removed BDRV_O_REPAIR in favor of BDRV_O_CHECK | BDRV_O_RDWR - always check full clusters for overlaps - removed qcow2_check_allocations in favor of some qcow2_check_refcounts extensions that will hopefully include all that functionality Max Reitz (8): qcow2: Add corrupt bit qcow2: Metadata overlap checks qcow2: Employ metadata overlap checks qcow2-refcount: Move OFLAG_COPIED checks qcow2-refcount: Repair OFLAG_COPIED errors qcow2-refcount: Repair shared refcount blocks qcow2_check: Mark image consistent qemu-iotests: Overlapping cluster allocations block/blkdebug.c | 1 + block/qcow2-cache.c| 17 ++ block/qcow2-cluster.c | 25 ++- block/qcow2-refcount.c | 481 + block/qcow2-snapshot.c | 22 +++ block/qcow2.c | 79 +++- block/qcow2.h | 47 - docs/specs/qcow2.txt | 7 +- include/block/block.h | 1 + include/monitor/monitor.h | 1 + monitor.c | 1 + tests/qemu-iotests/031.out | 12 +- tests/qemu-iotests/036.out | 2 +- tests/qemu-iotests/060 | 111 +++ tests/qemu-iotests/060.out | 44 + tests/qemu-iotests/group | 1 + 16 files changed, 805 insertions(+), 47 deletions(-) create mode 100755 tests/qemu-iotests/060 create mode 100644 tests/qemu-iotests/060.out -- 1.8.3.1
[Qemu-devel] [PATCH v5 2/8] qcow2: Metadata overlap checks
Two new functions are added; the first one checks a given range in the image file for overlaps with metadata (main header, L1 tables, L2 tables, refcount table and blocks). The second one should be used immediately before writing to the image file as it calls the first function and, upon collision, marks the image as corrupt and makes the BDS unusable, thereby preventing further access. Both functions take a bitmask argument specifying the structures which should be checked for overlaps, making it possible to also check metadata writes against colliding with other structures. Signed-off-by: Max Reitz mre...@redhat.com --- block/qcow2-refcount.c| 172 ++ block/qcow2.h | 39 +++ include/monitor/monitor.h | 1 + monitor.c | 1 + 4 files changed, 213 insertions(+) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 1244693..310efcc 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -25,6 +25,8 @@ #include qemu-common.h #include block/block_int.h #include block/qcow2.h +#include qemu/range.h +#include qapi/qmp/types.h static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size); static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, @@ -1372,3 +1374,173 @@ fail: return ret; } +#define overlaps_with(ofs, sz) \ +ranges_overlap(offset, size, ofs, sz) + +/* + * Checks if the given offset into the image file is actually free to use by + * looking for overlaps with important metadata sections (L1/L2 tables etc.), + * i.e. a sanity check without relying on the refcount tables. + * + * The chk parameter specifies exactly what checks to perform (being a bitmask + * of QCow2MetadataOverlap values). + * + * Returns: + * - 0 if writing to this offset will not affect the mentioned metadata + * - a positive QCow2MetadataOverlap value indicating one overlapping section + * - a negative value (-errno) indicating an error while performing a check, + * e.g. when bdrv_read failed on QCOW2_OL_INACTIVE_L2 + */ +int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset, + int64_t size) +{ +BDRVQcowState *s = bs-opaque; +int i, j; + +if (!size) { +return 0; +} + +if (chk QCOW2_OL_MAIN_HEADER) { +if (offset s-cluster_size) { +return QCOW2_OL_MAIN_HEADER; +} +} + +/* align range to test to cluster boundaries */ +size = align_offset(offset_into_cluster(s, offset) + size, s-cluster_size); +offset = start_of_cluster(s, offset); + +if ((chk QCOW2_OL_ACTIVE_L1) s-l1_size) { +if (overlaps_with(s-l1_table_offset, s-l1_size * sizeof(uint64_t))) { +return QCOW2_OL_ACTIVE_L1; +} +} + +if ((chk QCOW2_OL_REFCOUNT_TABLE) s-refcount_table_size) { +if (overlaps_with(s-refcount_table_offset, +s-refcount_table_size * sizeof(uint64_t))) { +return QCOW2_OL_REFCOUNT_TABLE; +} +} + +if ((chk QCOW2_OL_SNAPSHOT_TABLE) s-snapshots_size) { +if (overlaps_with(s-snapshots_offset, s-snapshots_size)) { +return QCOW2_OL_SNAPSHOT_TABLE; +} +} + +if ((chk QCOW2_OL_INACTIVE_L1) s-snapshots) { +for (i = 0; i s-nb_snapshots; i++) { +if (s-snapshots[i].l1_size +overlaps_with(s-snapshots[i].l1_table_offset, +s-snapshots[i].l1_size * sizeof(uint64_t))) { +return QCOW2_OL_INACTIVE_L1; +} +} +} + +if ((chk QCOW2_OL_ACTIVE_L2) s-l1_table) { +for (i = 0; i s-l1_size; i++) { +if ((s-l1_table[i] L1E_OFFSET_MASK) +overlaps_with(s-l1_table[i] L1E_OFFSET_MASK, +s-cluster_size)) { +return QCOW2_OL_ACTIVE_L2; +} +} +} + +if ((chk QCOW2_OL_REFCOUNT_BLOCK) s-refcount_table) { +for (i = 0; i s-refcount_table_size; i++) { +if ((s-refcount_table[i] REFT_OFFSET_MASK) +overlaps_with(s-refcount_table[i] REFT_OFFSET_MASK, +s-cluster_size)) { +return QCOW2_OL_REFCOUNT_BLOCK; +} +} +} + +if ((chk QCOW2_OL_INACTIVE_L2) s-snapshots) { +for (i = 0; i s-nb_snapshots; i++) { +uint64_t l1_ofs = s-snapshots[i].l1_table_offset; +uint32_t l1_sz = s-snapshots[i].l1_size; +uint64_t *l1 = g_malloc(l1_sz * sizeof(uint64_t)); +int ret; + +ret = bdrv_read(bs-file, l1_ofs / BDRV_SECTOR_SIZE, (uint8_t *)l1, +l1_sz * sizeof(uint64_t) / BDRV_SECTOR_SIZE); + +if (ret 0) { +g_free(l1); +return ret; +} + +for (j = 0; j l1_sz; j++) { +if ((l1[j] L1E_OFFSET_MASK) +overlaps_with(l1[j]
[Qemu-devel] [PATCH v5 5/8] qcow2-refcount: Repair OFLAG_COPIED errors
Since the OFLAG_COPIED checks are now executed after the refcounts have been repaired (if repairing), it is safe to assume that they are correct but the OFLAG_COPIED flag may be not. Therefore, if its value differs from what it should be (considering the according refcount), that discrepancy can be repaired by correctly setting (or clearing that flag. Signed-off-by: Max Reitz mre...@redhat.com --- block/qcow2-cluster.c | 4 ++-- block/qcow2-refcount.c | 58 -- block/qcow2.h | 1 + 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 7c248aa..2d5aa92 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -145,7 +145,7 @@ static int l2_load(BlockDriverState *bs, uint64_t l2_offset, * and we really don't want bdrv_pread to perform a read-modify-write) */ #define L1_ENTRIES_PER_SECTOR (512 / 8) -static int write_l1_entry(BlockDriverState *bs, int l1_index) +int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index) { BDRVQcowState *s = bs-opaque; uint64_t buf[L1_ENTRIES_PER_SECTOR]; @@ -254,7 +254,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) /* update the L1 entry */ trace_qcow2_l2_allocate_write_l1(bs, l1_index); s-l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED; -ret = write_l1_entry(bs, l1_index); +ret = qcow2_write_l1_entry(bs, l1_index); if (ret 0) { goto fail; } diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index ddc3029..92ecc64 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1207,7 +1207,8 @@ fail: * been already detected and sufficiently signaled by the calling function * (qcow2_check_refcounts) by the time this function is called). */ -static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) +static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res, + BdrvCheckMode fix) { BDRVQcowState *s = bs-opaque; uint64_t *l2_table = qemu_blockalign(bs, s-cluster_size); @@ -1218,6 +1219,7 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) for (i = 0; i s-l1_size; i++) { uint64_t l1_entry = s-l1_table[i]; uint64_t l2_offset = l1_entry L1E_OFFSET_MASK; +bool l2_dirty = false; if (!l2_offset) { continue; @@ -1229,10 +1231,24 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) continue; } if ((refcount == 1) != ((l1_entry QCOW_OFLAG_COPIED) != 0)) { -fprintf(stderr, ERROR OFLAG_COPIED L2 cluster: l1_index=%d +fprintf(stderr, %s OFLAG_COPIED L2 cluster: l1_index=%d l1_entry=% PRIx64 refcount=%d\n, +fix BDRV_FIX_ERRORS ? Repairing : +ERROR, i, l1_entry, refcount); -res-corruptions++; +if (fix BDRV_FIX_ERRORS) { +s-l1_table[i] = refcount == 1 + ? l1_entry | QCOW_OFLAG_COPIED + : l1_entry ~QCOW_OFLAG_COPIED; +ret = qcow2_write_l1_entry(bs, i); +if (ret 0) { +res-check_errors++; +goto fail; +} +res-corruptions_fixed++; +} else { +res-corruptions++; +} } ret = bdrv_pread(bs-file, l2_offset, l2_table, @@ -1257,13 +1273,43 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) continue; } if ((refcount == 1) != ((l2_entry QCOW_OFLAG_COPIED) != 0)) { -fprintf(stderr, ERROR OFLAG_COPIED data cluster: +fprintf(stderr, %s OFLAG_COPIED data cluster: l2_entry=% PRIx64 refcount=%d\n, +fix BDRV_FIX_ERRORS ? Repairing : +ERROR, l2_entry, refcount); -res-corruptions++; +if (fix BDRV_FIX_ERRORS) { +l2_table[j] = cpu_to_be64(refcount == 1 +? l2_entry | QCOW_OFLAG_COPIED +: l2_entry ~QCOW_OFLAG_COPIED); +l2_dirty = true; +res-corruptions_fixed++; +} else { +res-corruptions++; +} } } } + +if (l2_dirty) { +ret = qcow2_pre_write_overlap_check(bs, +QCOW2_OL_DEFAULT ~QCOW2_OL_ACTIVE_L2, l2_offset, +s-cluster_size); +if (ret 0) { +
[Qemu-devel] [PATCH v5 4/8] qcow2-refcount: Move OFLAG_COPIED checks
Move the OFLAG_COPIED checks out of check_refcounts_l1 and check_refcounts_l2 and after the actual refcount checks/fixes (since the refcounts might actually change there). Signed-off-by: Max Reitz mre...@redhat.com --- block/qcow2-refcount.c | 115 +++-- 1 file changed, 82 insertions(+), 33 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 310efcc..ddc3029 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1035,7 +1035,7 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, BDRVQcowState *s = bs-opaque; uint64_t *l2_table, l2_entry; uint64_t next_contiguous_offset = 0; -int i, l2_size, nb_csectors, refcount; +int i, l2_size, nb_csectors; /* Read L2 table from disk */ l2_size = s-l2_size * sizeof(uint64_t); @@ -1087,23 +1087,8 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, case QCOW2_CLUSTER_NORMAL: { -/* QCOW_OFLAG_COPIED must be set iff refcount == 1 */ uint64_t offset = l2_entry L2E_OFFSET_MASK; -if (flags CHECK_OFLAG_COPIED) { -refcount = get_refcount(bs, offset s-cluster_bits); -if (refcount 0) { -fprintf(stderr, Can't get refcount for offset % -PRIx64 : %s\n, l2_entry, strerror(-refcount)); -goto fail; -} -if ((refcount == 1) != ((l2_entry QCOW_OFLAG_COPIED) != 0)) { -fprintf(stderr, ERROR OFLAG_COPIED: offset=% -PRIx64 refcount=%d\n, l2_entry, refcount); -res-corruptions++; -} -} - if (flags CHECK_FRAG_INFO) { res-bfi.allocated_clusters++; if (next_contiguous_offset @@ -1160,7 +1145,7 @@ static int check_refcounts_l1(BlockDriverState *bs, { BDRVQcowState *s = bs-opaque; uint64_t *l1_table, l2_offset, l1_size2; -int i, refcount, ret; +int i, ret; l1_size2 = l1_size * sizeof(uint64_t); @@ -1184,22 +1169,6 @@ static int check_refcounts_l1(BlockDriverState *bs, for(i = 0; i l1_size; i++) { l2_offset = l1_table[i]; if (l2_offset) { -/* QCOW_OFLAG_COPIED must be set iff refcount == 1 */ -if (flags CHECK_OFLAG_COPIED) { -refcount = get_refcount(bs, (l2_offset ~QCOW_OFLAG_COPIED) - s-cluster_bits); -if (refcount 0) { -fprintf(stderr, Can't get refcount for l2_offset % -PRIx64 : %s\n, l2_offset, strerror(-refcount)); -goto fail; -} -if ((refcount == 1) != ((l2_offset QCOW_OFLAG_COPIED) != 0)) { -fprintf(stderr, ERROR OFLAG_COPIED: l2_offset=% PRIx64 - refcount=%d\n, l2_offset, refcount); -res-corruptions++; -} -} - /* Mark L2 table as used */ l2_offset = L1E_OFFSET_MASK; inc_refcounts(bs, res, refcount_table, refcount_table_size, @@ -1231,6 +1200,80 @@ fail: } /* + * Checks the OFLAG_COPIED flag for all L1 and L2 entries. + * + * This function does not print an error message nor does it increment + * check_errors if get_refcount fails (this is because such an error will have + * been already detected and sufficiently signaled by the calling function + * (qcow2_check_refcounts) by the time this function is called). + */ +static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) +{ +BDRVQcowState *s = bs-opaque; +uint64_t *l2_table = qemu_blockalign(bs, s-cluster_size); +int ret; +int refcount; +int i, j; + +for (i = 0; i s-l1_size; i++) { +uint64_t l1_entry = s-l1_table[i]; +uint64_t l2_offset = l1_entry L1E_OFFSET_MASK; + +if (!l2_offset) { +continue; +} + +refcount = get_refcount(bs, l2_offset s-cluster_bits); +if (refcount 0) { +/* don't print message nor increment check_errors */ +continue; +} +if ((refcount == 1) != ((l1_entry QCOW_OFLAG_COPIED) != 0)) { +fprintf(stderr, ERROR OFLAG_COPIED L2 cluster: l1_index=%d +l1_entry=% PRIx64 refcount=%d\n, +i, l1_entry, refcount); +res-corruptions++; +} + +ret = bdrv_pread(bs-file, l2_offset, l2_table, + s-l2_size * sizeof(uint64_t)); +if (ret 0) { +fprintf(stderr, ERROR: Could not read L2 table: %s\n, +strerror(-ret)); +res-check_errors++; +goto fail; +} + +for (j = 0; j s-l2_size; j++) { +uint64_t l2_entry = be64_to_cpu(l2_table[j]); +uint64_t
[Qemu-devel] [PATCH v5 8/8] qemu-iotests: Overlapping cluster allocations
A new test on corrupted images with overlapping cluster allocations. Signed-off-by: Max Reitz mre...@redhat.com --- tests/qemu-iotests/060 | 111 + tests/qemu-iotests/060.out | 44 ++ tests/qemu-iotests/group | 1 + 3 files changed, 156 insertions(+) create mode 100755 tests/qemu-iotests/060 create mode 100644 tests/qemu-iotests/060.out diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 new file mode 100755 index 000..65bb09f --- /dev/null +++ b/tests/qemu-iotests/060 @@ -0,0 +1,111 @@ +#!/bin/bash +# +# Test case for image corruption (overlapping data structures) in qcow2 +# +# Copyright (C) 2013 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# + +# creator +owner=mre...@redhat.com + +seq=`basename $0` +echo QA output created by $seq + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap _cleanup; exit \$status 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +# This tests qocw2-specific low-level functionality +_supported_fmt qcow2 +_supported_proto generic +_supported_os Linux + +rt_offset=65536 # 0x1 (XXX: just an assumption) +rb_offset=131072 # 0x2 (XXX: just an assumption) +l1_offset=196608 # 0x3 (XXX: just an assumption) +l2_offset=262144 # 0x4 (XXX: just an assumption) + +IMGOPTS=compat=1.1 + +echo +echo === Testing L2 reference into L1 === +echo +_make_test_img 64M +# Link first L1 entry (first L2 table) onto itself +# (Note the MSb in the L1 entry is set, ensuring the refcount is one - else any +# later write will result in a COW operation, effectively ruining this attempt +# on image corruption) +poke_file $TEST_IMG $l1_offset \x80\x00\x00\x00\x00\x03\x00\x00 +_check_test_img + +# The corrupt bit should not be set anyway +./qcow2.py $TEST_IMG dump-header | grep incompatible_features + +# Try to write something, thereby forcing the corrupt bit to be set +$QEMU_IO -c write -P 0x2a 0 512 $TEST_IMG | _filter_qemu_io + +# The corrupt bit must now be set +./qcow2.py $TEST_IMG dump-header | grep incompatible_features + +# Try to open the image R/W (which should fail) +$QEMU_IO -c read 0 512 $TEST_IMG 21 | _filter_qemu_io | sed -e s/can't open device .*$/can't open device/ + +# Try to open it RO (which should succeed) +$QEMU_IO -c read 0 512 -r $TEST_IMG | _filter_qemu_io + +# We could now try to fix the image, but this would probably fail (how should an +# L2 table linked onto the L1 table be fixed?) + +echo +echo === Testing cluster data reference into refcount block === +echo +_make_test_img 64M +# Allocate L2 table +truncate -s $(($l2_offset+65536)) $TEST_IMG +poke_file $TEST_IMG $l1_offset \x80\x00\x00\x00\x00\x04\x00\x00 +# Mark cluster as used +poke_file $TEST_IMG $(($rb_offset+8)) \x00\x01 +# Redirect new data cluster onto refcount block +poke_file $TEST_IMG $l2_offset \x80\x00\x00\x00\x00\x02\x00\x00 +_check_test_img +./qcow2.py $TEST_IMG dump-header | grep incompatible_features +$QEMU_IO -c write -P 0x2a 0 512 $TEST_IMG | _filter_qemu_io +./qcow2.py $TEST_IMG dump-header | grep incompatible_features + +# Try to fix it +_check_test_img -r all + +# The corrupt bit should be cleared +./qcow2.py $TEST_IMG dump-header | grep incompatible_features + +# Look if it's really really fixed +$QEMU_IO -c write -P 0x2a 0 512 $TEST_IMG | _filter_qemu_io +./qcow2.py $TEST_IMG dump-header | grep incompatible_features + +# success, all done +echo *** done +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out new file mode 100644 index 000..ca4583a --- /dev/null +++ b/tests/qemu-iotests/060.out @@ -0,0 +1,44 @@ +QA output created by 060 + +=== Testing L2 reference into L1 === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +ERROR cluster 3 refcount=1 reference=3 + +1 errors were found on the image. +Data may be corrupted, or further writes to the image may corrupt it. +incompatible_features 0x0 +qcow2: Preventing invalid write on metadata (overlaps with active L1 table); image marked as corrupt. +write failed: Input/output error +incompatible_features 0x2 +qcow2: Image is corrupt; cannot be opened read/write. +qemu-io: can't open device +no file open, try 'help open' +read 512/512 bytes at offset 0 +512 bytes, X ops;
[Qemu-devel] [PATCH v5 7/8] qcow2_check: Mark image consistent
If no corruptions remain after an image repair (and no errors have been encountered), clear the corrupt flag in qcow2_check. Signed-off-by: Max Reitz mre...@redhat.com --- block/qcow2.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/block/qcow2.c b/block/qcow2.c index 3a95ff1..aeb2ebb 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -312,7 +312,11 @@ static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result, } if (fix result-check_errors == 0 result-corruptions == 0) { -return qcow2_mark_clean(bs); +ret = qcow2_mark_clean(bs); +if (ret 0) { +return ret; +} +return qcow2_mark_consistent(bs); } return ret; } -- 1.8.3.1
[Qemu-devel] [PATCH v5 6/8] qcow2-refcount: Repair shared refcount blocks
If the refcount of a refcount block is greater than one, we can at least try to repair that problem by duplicating the affected block. Signed-off-by: Max Reitz mre...@redhat.com --- block/blkdebug.c | 1 + block/qcow2-refcount.c | 148 - include/block/block.h | 1 + 3 files changed, 148 insertions(+), 2 deletions(-) diff --git a/block/blkdebug.c b/block/blkdebug.c index ccb627a..5d33e03 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -168,6 +168,7 @@ static const char *event_names[BLKDBG_EVENT_MAX] = { [BLKDBG_REFTABLE_LOAD] = reftable_load, [BLKDBG_REFTABLE_GROW] = reftable_grow, +[BLKDBG_REFTABLE_UPDATE]= reftable_update, [BLKDBG_REFBLOCK_LOAD] = refblock_load, [BLKDBG_REFBLOCK_UPDATE]= refblock_update, diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 92ecc64..927bdeb 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1320,6 +1320,121 @@ fail: } /* + * Writes one sector of the refcount table to the disk + */ +#define RT_ENTRIES_PER_SECTOR (512 / sizeof(uint64_t)) +static int write_reftable_entry(BlockDriverState *bs, int rt_index) +{ +BDRVQcowState *s = bs-opaque; +uint64_t buf[RT_ENTRIES_PER_SECTOR]; +int rt_start_index; +int i, ret; + +rt_start_index = rt_index ~(RT_ENTRIES_PER_SECTOR - 1); +for (i = 0; i RT_ENTRIES_PER_SECTOR; i++) { +buf[i] = cpu_to_be64(s-refcount_table[rt_start_index + i]); +} + +ret = qcow2_pre_write_overlap_check(bs, +QCOW2_OL_DEFAULT ~QCOW2_OL_REFCOUNT_TABLE, +s-refcount_table_offset + rt_start_index * sizeof(uint64_t), +sizeof(buf)); +if (ret 0) { +return ret; +} + +BLKDBG_EVENT(bs-file, BLKDBG_REFTABLE_UPDATE); +ret = bdrv_pwrite_sync(bs-file, s-refcount_table_offset + +rt_start_index * sizeof(uint64_t), buf, sizeof(buf)); +if (ret 0) { +return ret; +} + +return 0; +} + +/* + * Allocates a new cluster for the given refcount block (represented by its + * offset in the image file) and copies the current content there. This function + * does _not_ decrement the reference count for the currently occupied cluster. + * + * This function prints an informative message to stderr on error (and returns + * -errno); on success, 0 is returned. + */ +static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index, + uint64_t offset) +{ +BDRVQcowState *s = bs-opaque; +int64_t new_offset = 0; +void *refcount_block = NULL; +int ret; + +/* allocate new refcount block */ +new_offset = qcow2_alloc_clusters(bs, s-cluster_size); +if (new_offset 0) { +fprintf(stderr, Could not allocate new cluster: %s\n, +strerror(-new_offset)); +ret = new_offset; +goto fail; +} + +/* fetch current refcount block content */ +ret = qcow2_cache_get(bs, s-refcount_block_cache, offset, refcount_block); +if (ret 0) { +fprintf(stderr, Could not fetch refcount block: %s\n, strerror(-ret)); +goto fail; +} + +/* new block has not yet been entered into refcount table, therefore it is + * no refcount block yet (regarding this check) */ +ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, new_offset, +s-cluster_size); +if (ret 0) { +fprintf(stderr, Could not write refcount block; metadata overlap +check failed: %s\n, strerror(-ret)); +/* the image will be marked corrupt, so don't even attempt on freeing + * the cluster */ +new_offset = 0; +goto fail; +} + +/* write to new block */ +ret = bdrv_write(bs-file, new_offset / BDRV_SECTOR_SIZE, refcount_block, +s-cluster_sectors); +if (ret 0) { +fprintf(stderr, Could not write refcount block: %s\n, strerror(-ret)); +goto fail; +} + +/* update refcount table */ +assert(!(new_offset (s-cluster_size - 1))); +s-refcount_table[reftable_index] = new_offset; +ret = write_reftable_entry(bs, reftable_index); +if (ret 0) { +fprintf(stderr, Could not update refcount table: %s\n, +strerror(-ret)); +goto fail; +} + +fail: +if (new_offset (ret 0)) { +qcow2_free_clusters(bs, new_offset, s-cluster_size, +QCOW2_DISCARD_ALWAYS); +} +if (refcount_block) { +if (ret 0) { +qcow2_cache_put(bs, s-refcount_block_cache, refcount_block); +} else { +ret = qcow2_cache_put(bs, s-refcount_block_cache, refcount_block); +} +} +if (ret 0) { +return ret; +} +return new_offset; +} + +/* * Checks an image for refcount consistency. * * Returns 0 if no errors are found, the number of errors in case
Re: [Qemu-devel] [PATCH v3 2/3] qcow2: Implement bdrv_amend_options
Am 02.09.2013 05:43, schrieb Fam Zheng: On Fri, 08/30 12:27, Max Reitz wrote: Implement bdrv_amend_options for compat, size, backing_file, backing_fmt and lazy_refcounts. Downgrading images from compat=1.1 to compat=0.10 is achieved through handling all incompatible flags accordingly, clearing all compatible and autoclear flags and expanding all zero clusters. Signed-off-by: Max Reitz mre...@redhat.com --- block/qcow2-cluster.c | 165 ++ block/qcow2.c | 194 +- block/qcow2.h | 3 + 3 files changed, 361 insertions(+), 1 deletion(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index cca76d4..e0ca104 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1476,3 +1476,168 @@ fail: return ret; } + +/* + * Expands all zero clusters in a specific L1 table (or deallocates them, for + * non-backed non-pre-allocated zero clusters). + */ +static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, + int l1_size) +{ +BDRVQcowState *s = bs-opaque; +bool is_active_l1 = (l1_table == s-l1_table); +uint64_t *l2_table; +int ret; +int i, j; + +if (!is_active_l1) { +/* inactive L2 tables require a buffer to be stored in when loading + * them from disk */ +l2_table = qemu_blockalign(bs, s-cluster_size); +} + +for (i = 0; i l1_size; i++) { +uint64_t l2_offset = l1_table[i] L1E_OFFSET_MASK; +bool l2_dirty = false; + +if (!l2_offset) { +/* unallocated */ +continue; +} + +if (is_active_l1) { +/* get active L2 tables from cache */ +ret = qcow2_cache_get(bs, s-l2_table_cache, l2_offset, +(void **)l2_table); +} else { +/* load inactive L2 tables from disk */ +ret = bdrv_read(bs-file, l2_offset / BDRV_SECTOR_SIZE, +(void *)l2_table, s-cluster_sectors); +} +if (ret 0) { +goto fail; +} + +for (j = 0; j s-l2_size; j++) { +uint64_t l2_entry = be64_to_cpu(l2_table[j]); +int64_t offset; + +if (qcow2_get_cluster_type(l2_entry) != QCOW2_CLUSTER_ZERO) { +continue; +} + +offset = l2_entry L2E_OFFSET_MASK; +if (!offset) { +/* not preallocated */ +if (!bs-backing_hd) { +/* not backed; therefore we can simply deallocate the + * cluster */ +l2_table[j] = 0; +l2_dirty = true; +continue; +} + +offset = qcow2_alloc_clusters(bs, s-cluster_size); +if (offset 0) { +ret = offset; +goto fail; +} +} + +ret = bdrv_write_zeroes(bs-file, offset / BDRV_SECTOR_SIZE, +s-cluster_sectors); +if (ret 0) { +qcow2_free_clusters(bs, offset, s-cluster_size, +QCOW2_DISCARD_ALWAYS); +goto fail; +} + +l2_table[j] = cpu_to_be64(offset | QCOW_OFLAG_COPIED); +l2_dirty = true; +} + +if (is_active_l1) { +if (l2_dirty) { +qcow2_cache_entry_mark_dirty(s-l2_table_cache, l2_table); +qcow2_cache_depends_on_flush(s-l2_table_cache); +} +ret = qcow2_cache_put(bs, s-l2_table_cache, (void **)l2_table); +if (ret 0) { +l2_table = NULL; +goto fail; +} +} else { +if (l2_dirty) { +ret = bdrv_write(bs-file, l2_offset / BDRV_SECTOR_SIZE, +(void *)l2_table, s-cluster_sectors); +if (ret 0) { +goto fail; +} +} +} +} + +ret = 0; + +fail: +if (l2_table) { +if (!is_active_l1) { +qemu_vfree(l2_table); +} else { +if (ret 0) { +qcow2_cache_put(bs, s-l2_table_cache, (void **)l2_table); +} else { +ret = qcow2_cache_put(bs, s-l2_table_cache, +(void **)l2_table); +} +} +} +return ret; +} + +/* + * For backed images, expands all zero clusters on the image. For non-backed + * images, deallocates all non-pre-allocated zero clusters (and claims the + * allocation for pre-allocated ones). This is important for downgrading to a + * qcow2 version which doesn't yet support metadata zero clusters. + */ +int qcow2_expand_zero_clusters(BlockDriverState *bs) +{ +BDRVQcowState *s = bs-opaque; +uint64_t *l1_table = NULL; +int ret; +int i, j;
Re: [Qemu-devel] [PATCH v2 2/2] milkymist-uart: use Device::realize instead of SysBusDevice::init
Am 01.09.2013 20:28, schrieb Antony Pavlov: On Sat, 31 Aug 2013 21:09:20 +0200 Andreas Färber afaer...@suse.de wrote: Am 31.08.2013 19:22, schrieb Antony Pavlov: Use of SysBusDevice::init is deprecated. Use Device::realize instead of SysBusDevice::init. Check dma/pl330.c for an example of the pattern. Also introduce TypeInfo::instance_init milkymist_uart_init() as char/pl011.c does. Reported-by: Peter Crosthwaite peter.crosthwa...@xilinx.com Signed-off-by: Antony Pavlov antonynpav...@gmail.com CC: Peter Crosthwaite peter.crosthwa...@xilinx.com CC: Michael Walle mich...@walle.cc CC: Andreas Färber afaer...@suse.de --- hw/char/milkymist-uart.c | 24 ++-- 1 file changed, 14 insertions(+), 10 deletions(-) Thanks, applied to qom-next (with shortened commit message): https://github.com/afaerber/qemu-cpu/commits/qom-next That's about the patch number 1 ( milkymist-uart: use qemu_chr_fe_write_all() instead of qemu_chr_fe_write()) ? No, it's about patch 2, which I replied to. Patch 1 is not a QOM conversion but an unrelated bug fix - it can be handled either by the lm32 maintainer or by whomever takes care of the char layer these days (Anthony/Gerd). Regards, Andreas -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
Re: [Qemu-devel] [PATCH v3 2/3] qcow2: Implement bdrv_amend_options
Am 02.09.2013 um 05:43 hat Fam Zheng geschrieben: On Fri, 08/30 12:27, Max Reitz wrote: Implement bdrv_amend_options for compat, size, backing_file, backing_fmt and lazy_refcounts. Downgrading images from compat=1.1 to compat=0.10 is achieved through handling all incompatible flags accordingly, clearing all compatible and autoclear flags and expanding all zero clusters. Signed-off-by: Max Reitz mre...@redhat.com --- block/qcow2-cluster.c | 165 ++ block/qcow2.c | 194 +- block/qcow2.h | 3 + 3 files changed, 361 insertions(+), 1 deletion(-) +static int qcow2_amend_options(BlockDriverState *bs, + QEMUOptionParameter *options) +{ +BDRVQcowState *s = bs-opaque; +int old_version = s-qcow_version, new_version = old_version; +uint64_t new_size = 0; +const char *backing_file = NULL, *backing_format = NULL; +bool lazy_refcounts = s-use_lazy_refcounts; +int ret; +int i; + +for (i = 0; options[i].name; i++) +{ +if (!strcmp(options[i].name, compat)) { +if (!options[i].value.s) { +/* preserve default */ +} else if (!strcmp(options[i].value.s, 0.10)) { +new_version = 2; +} else if (!strcmp(options[i].value.s, 1.1)) { +new_version = 3; +} else { +fprintf(stderr, Unknown compatibility level %s.\n, +options[i].value.s); +return -EINVAL; +} +} else if (!strcmp(options[i].name, preallocation)) { +if (options[i].assigned) { For encryption flag and cluster_size, you checked the original value and only error out on actual change, should check the original preallocation value here as well? +fprintf(stderr, Cannot change preallocation mode.\n); +return -ENOTSUP; +} +} else if (!strcmp(options[i].name, size)) { +new_size = options[i].value.n; +} else if (!strcmp(options[i].name, backing_file)) { +backing_file = options[i].value.s; +} else if (!strcmp(options[i].name, backing_fmt)) { +backing_format = options[i].value.s; +} else if (!strcmp(options[i].name, encryption)) { +if (options[i].assigned +(options[i].value.n != !!s-crypt_method)) { +fprintf(stderr, Changing the encryption flag is not +supported.\n); +return -ENOTSUP; +} +} else if (!strcmp(options[i].name, cluster_size)) { +if (options[i].assigned (options[i].value.n != s-cluster_size)) +{ +fprintf(stderr, Changing the cluster size is not +supported.\n); +return -ENOTSUP; +} +} else if (!strcmp(options[i].name, lazy_refcounts)) { +if (options[i].assigned) { +lazy_refcounts = options[i].value.n; +} +} else { +/* if this assertion fails, this probably means a new option was + * added without having it covered here */ +assert(false); A unknown option reported as -ENOTSUP with a proper message is good enough, it's not that critical for an assert. assert() has nothing to do with being critical. This is not code for handling a user error, but for catching programming errors. If the else branch is reached, this is a bug, and you want it to be detected as quickly as possible (and without having to debug a lot in order to find out where a bogus -ENOTSUP comes from) Kevin
Re: [Qemu-devel] [PATCH] target-ppc: Fix include for qemu_notify_event
Am 01.09.2013 18:00, schrieb Richard Henderson: Signed-off-by: Richard Henderson r...@twiddle.net --- target-ppc/kvm_ppc.c | 1 + 1 file changed, 1 insertion(+) The PowerPC target has been broken for more than a week. Déjà vu, Alex already sent a fix on ~Friday. Andreas r~ diff --git a/target-ppc/kvm_ppc.c b/target-ppc/kvm_ppc.c index 9b83655..47e54a6 100644 --- a/target-ppc/kvm_ppc.c +++ b/target-ppc/kvm_ppc.c @@ -12,6 +12,7 @@ */ #include qemu-common.h +#include qemu/main-loop.h #include qemu/timer.h #include kvm_ppc.h #include sysemu/device_tree.h -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
[Qemu-devel] [PULL 1/6] pci: Introduce helper to retrieve a PCI device's DMA address space
From: Alexey Kardashevskiy a...@ozlabs.ru A PCI device's DMA address space (possibly an IOMMU) is returned by a method on the PCIBus. At the moment that only has one caller, so the method is simply open coded. We'll need another caller for VFIO, so this patch introduces a helper/wrapper function. If IOMMU is not set, the pci_device_iommu_address_space() function returns the parent's IOMMU skipping the bus master address space as otherwise proper emulation would require more effort for no benefit. Signed-off-by: David Gibson da...@gibson.dropbear.id.au [aik: added inheritance from parent if iommu is not set for the current bus] Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru Signed-off-by: Michael S. Tsirkin m...@redhat.com --- include/hw/pci/pci.h | 1 + hw/pci/pci.c | 24 ++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index ccec2ba..2374aa9 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -405,6 +405,7 @@ void pci_device_deassert_intx(PCIDevice *dev); typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int); +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev); void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque); static inline void diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 4c004f5..8c33352 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -812,12 +812,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, } pci_dev-bus = bus; -if (bus-iommu_fn) { -dma_as = bus-iommu_fn(bus, bus-iommu_opaque, devfn); -} else { -/* FIXME: inherit memory region from bus creator */ -dma_as = address_space_memory; -} +dma_as = pci_device_iommu_address_space(pci_dev); memory_region_init_alias(pci_dev-bus_master_enable_region, OBJECT(pci_dev), bus master, @@ -2239,6 +2234,23 @@ static void pci_device_class_init(ObjectClass *klass, void *data) k-props = pci_props; } +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) +{ +PCIBus *bus = PCI_BUS(dev-bus); + +if (bus-iommu_fn) { +return bus-iommu_fn(bus, bus-iommu_opaque, dev-devfn); +} + +if (bus-parent_dev) { +/** We are ignoring the bus master DMA bit of the bridge + * as it would complicate things such as VFIO for no good reason */ +return pci_device_iommu_address_space(bus-parent_dev); +} + +return address_space_memory; +} + void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque) { bus-iommu_fn = fn; -- MST
[Qemu-devel] [PULL 2/6] pc: fix regression for 64 bit PCI memory
commit 398489018183d613306ab022653552247d93919f pc: limit 64 bit hole to 2G by default introduced a way for management to control the window allocated to the 64 bit PCI hole. This is useful, but existing management tools do not know how to set this property. As a result, e.g. specifying a large ivshmem device with size 4G is broken by default. For example this configuration no longer works: -device ivshmem,size=4294967296,chardev=cfoo -chardev socket,path=/tmp/sock,id=cfoo,server,nowait Fix this by detecting that hole size was not specified and defaulting to the backwards-compatible value of 1 62. Cc: qemu-sta...@nongnu.org Cc: Igor Mammedov imamm...@redhat.com Signed-off-by: Michael S. Tsirkin m...@redhat.com --- include/hw/i386/pc.h | 11 ++- hw/pci-host/piix.c | 9 ++--- hw/pci-host/q35.c| 8 +--- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index f79d478..475ba9e 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -106,7 +106,16 @@ PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, #define PCI_HOST_PROP_PCI_HOLE64_START pci-hole64-start #define PCI_HOST_PROP_PCI_HOLE64_END pci-hole64-end #define PCI_HOST_PROP_PCI_HOLE64_SIZE pci-hole64-size -#define DEFAULT_PCI_HOLE64_SIZE (1ULL 31) +#define DEFAULT_PCI_HOLE64_SIZE (~0x0ULL) + +static inline uint64_t pci_host_get_hole64_size(uint64_t pci_hole64_size) +{ +if (pci_hole64_size == DEFAULT_PCI_HOLE64_SIZE) { +return 1ULL 62; +} else { +return pci_hole64_size; +} +} void pc_init_pci64_hole(PcPciInfo *pci_info, uint64_t pci_hole64_start, uint64_t pci_hole64_size); diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index dc1718f..221d82b 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -320,6 +320,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, PCII440FXState *f; unsigned i; I440FXState *i440fx; +uint64_t pci_hole64_size; dev = qdev_create(NULL, TYPE_I440FX_PCI_HOST_BRIDGE); s = PCI_HOST_BRIDGE(dev); @@ -351,13 +352,15 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, pci_hole_start, pci_hole_size); memory_region_add_subregion(f-system_memory, pci_hole_start, f-pci_hole); +pci_hole64_size = pci_host_get_hole64_size(i440fx-pci_hole64_size); + pc_init_pci64_hole(i440fx-pci_info, 0x1ULL + above_4g_mem_size, - i440fx-pci_hole64_size); + pci_hole64_size); memory_region_init_alias(f-pci_hole_64bit, OBJECT(d), pci-hole64, f-pci_address_space, i440fx-pci_info.w64.begin, - i440fx-pci_hole64_size); -if (i440fx-pci_hole64_size) { + pci_hole64_size); +if (pci_hole64_size) { memory_region_add_subregion(f-system_memory, i440fx-pci_info.w64.begin, f-pci_hole_64bit); diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 12314d8..4febd24 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -320,6 +320,7 @@ static int mch_init(PCIDevice *d) { int i; MCHPCIState *mch = MCH_PCI_DEVICE(d); +uint64_t pci_hole64_size; /* setup pci memory regions */ memory_region_init_alias(mch-pci_hole, OBJECT(mch), pci-hole, @@ -329,13 +330,14 @@ static int mch_init(PCIDevice *d) memory_region_add_subregion(mch-system_memory, mch-below_4g_mem_size, mch-pci_hole); +pci_hole64_size = pci_host_get_hole64_size(mch-pci_hole64_size); pc_init_pci64_hole(mch-pci_info, 0x1ULL + mch-above_4g_mem_size, - mch-pci_hole64_size); + pci_hole64_size); memory_region_init_alias(mch-pci_hole_64bit, OBJECT(mch), pci-hole64, mch-pci_address_space, mch-pci_info.w64.begin, - mch-pci_hole64_size); -if (mch-pci_hole64_size) { + pci_hole64_size); +if (pci_hole64_size) { memory_region_add_subregion(mch-system_memory, mch-pci_info.w64.begin, mch-pci_hole_64bit); -- MST
[Qemu-devel] [PULL 5/6] pc: reduce duplication, fix PIIX descriptions
We have a lot of code duplication between machine types, this increases with each new machine type and each new field. This has already introduced a minor bug: description for pc-1.3 says Standard PC while description for pc-1.4 is Standard PC (i440FX + PIIX, 1996) which makes you think 1.3 is somehow more standard, or newer, while in fact it's a revision of the same PC. This patch addresses this issue by using macros, along the lines used by PC_COMPAT_X_X - only for non-property options. The approach can extend to non-PC machine types. Cc: Paolo Bonzini pbonz...@redhat.com Signed-off-by: Michael S. Tsirkin m...@redhat.com --- include/hw/i386/pc.h | 8 + hw/i386/pc_piix.c| 86 +--- hw/i386/pc_q35.c | 25 --- 3 files changed, 56 insertions(+), 63 deletions(-) diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 475ba9e..7fb04d8 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -325,4 +325,12 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); .value= stringify(0),\ } +#define PC_COMMON_MACHINE_OPTIONS \ +.default_boot_order = cad + +#define PC_DEFAULT_MACHINE_OPTIONS \ +PC_COMMON_MACHINE_OPTIONS, \ +.hot_add_cpu = pc_hot_add_cpu, \ +.max_cpus = 255 + #endif diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index aa0a39a..275e395 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -334,36 +334,39 @@ static void pc_xen_hvm_init(QEMUMachineInitArgs *args) } #endif +#define PC_I440FX_MACHINE_OPTIONS \ +PC_DEFAULT_MACHINE_OPTIONS, \ +.desc = Standard PC (i440FX + PIIX, 1996), \ +.hot_add_cpu = pc_hot_add_cpu + +#define PC_I440FX_1_6_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS + static QEMUMachine pc_i440fx_machine_v1_6 = { +PC_I440FX_1_6_MACHINE_OPTIONS, .name = pc-i440fx-1.6, .alias = pc, -.desc = Standard PC (i440FX + PIIX, 1996), .init = pc_init_pci_1_6, -.hot_add_cpu = pc_hot_add_cpu, -.max_cpus = 255, .is_default = 1, -.default_boot_order = cad, }; static QEMUMachine pc_i440fx_machine_v1_5 = { +PC_I440FX_1_6_MACHINE_OPTIONS, .name = pc-i440fx-1.5, -.desc = Standard PC (i440FX + PIIX, 1996), .init = pc_init_pci_1_5, -.hot_add_cpu = pc_hot_add_cpu, -.max_cpus = 255, .compat_props = (GlobalProperty[]) { PC_COMPAT_1_5, { /* end of list */ } }, -.default_boot_order = cad, }; +#define PC_I440FX_1_4_MACHINE_OPTIONS \ +PC_I440FX_1_6_MACHINE_OPTIONS, \ +.hot_add_cpu = NULL + static QEMUMachine pc_i440fx_machine_v1_4 = { +PC_I440FX_1_4_MACHINE_OPTIONS, .name = pc-i440fx-1.4, -.desc = Standard PC (i440FX + PIIX, 1996), .init = pc_init_pci_1_4, -.max_cpus = 255, -.default_boot_order = cad, .compat_props = (GlobalProperty[]) { PC_COMPAT_1_4, { /* end of list */ } @@ -391,11 +394,9 @@ static QEMUMachine pc_i440fx_machine_v1_4 = { } static QEMUMachine pc_machine_v1_3 = { +PC_I440FX_1_4_MACHINE_OPTIONS, .name = pc-1.3, -.desc = Standard PC, .init = pc_init_pci_1_3, -.max_cpus = 255, -.default_boot_order = cad, .compat_props = (GlobalProperty[]) { PC_COMPAT_1_3, { /* end of list */ } @@ -430,12 +431,13 @@ static QEMUMachine pc_machine_v1_3 = { .value= off,\ } +#define PC_I440FX_1_2_MACHINE_OPTIONS \ +PC_I440FX_1_4_MACHINE_OPTIONS, \ +.init = pc_init_pci_1_2 + static QEMUMachine pc_machine_v1_2 = { +PC_I440FX_1_2_MACHINE_OPTIONS, .name = pc-1.2, -.desc = Standard PC, -.init = pc_init_pci_1_2, -.max_cpus = 255, -.default_boot_order = cad, .compat_props = (GlobalProperty[]) { PC_COMPAT_1_2, { /* end of list */ } @@ -475,11 +477,8 @@ static QEMUMachine pc_machine_v1_2 = { } static QEMUMachine pc_machine_v1_1 = { +PC_I440FX_1_2_MACHINE_OPTIONS, .name = pc-1.1, -.desc = Standard PC, -.init = pc_init_pci_1_2, -.max_cpus = 255, -.default_boot_order = cad, .compat_props = (GlobalProperty[]) { PC_COMPAT_1_1, { /* end of list */ } @@ -507,11 +506,8 @@ static QEMUMachine pc_machine_v1_1 = { } static QEMUMachine pc_machine_v1_0 = { +PC_I440FX_1_2_MACHINE_OPTIONS, .name = pc-1.0, -.desc = Standard PC, -.init = pc_init_pci_1_2, -.max_cpus = 255, -.default_boot_order = cad, .compat_props = (GlobalProperty[]) { PC_COMPAT_1_0, { /* end of list */ } @@ -523,11 +519,8 @@ static QEMUMachine pc_machine_v1_0 = { PC_COMPAT_1_0 static QEMUMachine pc_machine_v0_15 = { +PC_I440FX_1_2_MACHINE_OPTIONS, .name = pc-0.15, -.desc = Standard PC, -.init = pc_init_pci_1_2, -.max_cpus = 255, -.default_boot_order = cad, .compat_props = (GlobalProperty[]) { PC_COMPAT_0_15, { /* end of list */ } @@ -556,11 +549,8
[Qemu-devel] [PULL 0/6] pc,pci,virtio fixes and cleanups
The following changes since commit 1ae2757c6c4525c9b42f408c86818f843bad7418: virtio: virtqueue_get_avail_bytes: fix desc_pa when loop over the indirect descriptor table (2013-08-25 12:52:33 +0300) are available in the git repository at: git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_anthony for you to fetch changes up to 23fe2b3f9e7df8da53ac1bc32c6875254911d7f4: virtio_pci: fix level interrupts with irqfd (2013-09-01 11:15:03 +0300) pc,pci,virtio fixes and cleanups This includes pc and pci cleanups and enhancements, and a virtio bugfix for level interrupts. Signed-off-by: Michael S. Tsirkin m...@redhat.com Alexey Kardashevskiy (2): pci: Introduce helper to retrieve a PCI device's DMA address space pci: add config space access traces Markus Armbruster (1): hw: Clean up bogus default boot order Michael S. Tsirkin (3): pc: fix regression for 64 bit PCI memory pc: reduce duplication, fix PIIX descriptions virtio_pci: fix level interrupts with irqfd include/hw/boards.h | 7 +-- include/hw/i386/pc.h | 19 ++- include/hw/pci/pci.h | 1 + hw/alpha/dp264.c | 1 - hw/arm/collie.c | 1 - hw/arm/exynos4_boards.c | 2 - hw/arm/gumstix.c | 2 - hw/arm/highbank.c| 2 - hw/arm/integratorcp.c| 1 - hw/arm/kzm.c | 1 - hw/arm/mainstone.c | 1 - hw/arm/musicpal.c| 1 - hw/arm/nseries.c | 6 +-- hw/arm/omap_sx1.c| 2 - hw/arm/palm.c| 1 - hw/arm/realview.c| 4 -- hw/arm/spitz.c | 4 -- hw/arm/stellaris.c | 2 - hw/arm/tosa.c| 1 - hw/arm/versatilepb.c | 2 - hw/arm/vexpress.c| 2 - hw/arm/xilinx_zynq.c | 1 - hw/arm/z2.c | 1 - hw/core/null-machine.c | 1 - hw/cris/axis_dev88.c | 1 - hw/i386/pc_piix.c| 88 +--- hw/i386/pc_q35.c | 27 +- hw/i386/xen_machine_pv.c | 1 - hw/lm32/lm32_boards.c| 2 - hw/lm32/milkymist.c | 1 - hw/m68k/an5206.c | 1 - hw/m68k/dummy_m68k.c | 1 - hw/m68k/mcf5208.c| 1 - hw/microblaze/petalogix_ml605_mmu.c | 1 - hw/microblaze/petalogix_s3adsp1800_mmu.c | 1 - hw/mips/mips_fulong2e.c | 1 - hw/mips/mips_jazz.c | 2 - hw/mips/mips_malta.c | 1 - hw/mips/mips_mipssim.c | 1 - hw/mips/mips_r4k.c | 1 - hw/openrisc/openrisc_sim.c | 1 - hw/pci-host/piix.c | 9 ++-- hw/pci-host/q35.c| 8 +-- hw/pci/pci.c | 24 ++--- hw/pci/pci_host.c| 11 +++- hw/ppc/e500plat.c| 1 - hw/ppc/mac_newworld.c| 4 +- hw/ppc/mac_oldworld.c| 4 +- hw/ppc/mpc8544ds.c | 1 - hw/ppc/ppc405_boards.c | 2 - hw/ppc/ppc440_bamboo.c | 1 - hw/ppc/prep.c| 4 +- hw/ppc/spapr.c | 4 +- hw/ppc/virtex_ml507.c| 1 - hw/s390x/s390-virtio-ccw.c | 1 - hw/s390x/s390-virtio.c | 1 - hw/sh4/r2d.c | 1 - hw/sh4/shix.c| 1 - hw/sparc/leon3.c | 1 - hw/sparc/sun4m.c | 22 hw/sparc64/sun4u.c | 10 ++-- hw/unicore32/puv3.c | 1 - hw/virtio/virtio-pci.c | 3 +- hw/xtensa/xtensa_lx60.c | 2 - hw/xtensa/xtensa_sim.c | 1 - vl.c | 4 +- trace-events | 4 ++ 67 files changed, 144 insertions(+), 180 deletions(-)
[Qemu-devel] [PULL 4/6] hw: Clean up bogus default boot order
From: Markus Armbruster arm...@redhat.com We set default boot order cad in every single machine definition except pseries and moxiesim, even though very few boards actually care for boot order, and cad makes sense for even fewer. Machines that care: * pc and its variants Accept up to three letters 'a', 'b' (undocumented alias for 'a'), 'c', 'd' and 'n'. Reject all others (fatal with -boot). * nseries (n800, n810) Check whether order starts with 'n'. Silently ignored otherwise. * prep, g3beige, mac99 Extract the first character the machine understands (subset of 'a'..'f'). Silently ignored otherwise. * spapr Accept an arbitrary string (vl.c restricts it to contain only 'a'..'p', no duplicates). * sun4[mdc] Use the first character. Silently ignored otherwise. Strip characters these machines ignore from their default boot order. For all other machines, remove the unused default boot order alltogether. Note that my rename of QEMUMachine member boot_order to default_boot_order and QEMUMachineInitArgs member boot_device to boot_order has a welcome side effect: it makes every use of boot orders visible in this patch, for easy review. Signed-off-by: Markus Armbruster arm...@redhat.com Reviewed-by: Laszlo Ersek ler...@redhat.com Signed-off-by: Michael S. Tsirkin m...@redhat.com --- include/hw/boards.h | 7 ++- hw/alpha/dp264.c | 1 - hw/arm/collie.c | 1 - hw/arm/exynos4_boards.c | 2 -- hw/arm/gumstix.c | 2 -- hw/arm/highbank.c| 2 -- hw/arm/integratorcp.c| 1 - hw/arm/kzm.c | 1 - hw/arm/mainstone.c | 1 - hw/arm/musicpal.c| 1 - hw/arm/nseries.c | 6 +++--- hw/arm/omap_sx1.c| 2 -- hw/arm/palm.c| 1 - hw/arm/realview.c| 4 hw/arm/spitz.c | 4 hw/arm/stellaris.c | 2 -- hw/arm/tosa.c| 1 - hw/arm/versatilepb.c | 2 -- hw/arm/vexpress.c| 2 -- hw/arm/xilinx_zynq.c | 1 - hw/arm/z2.c | 1 - hw/core/null-machine.c | 1 - hw/cris/axis_dev88.c | 1 - hw/i386/pc_piix.c| 32 hw/i386/pc_q35.c | 8 hw/i386/xen_machine_pv.c | 1 - hw/lm32/lm32_boards.c| 2 -- hw/lm32/milkymist.c | 1 - hw/m68k/an5206.c | 1 - hw/m68k/dummy_m68k.c | 1 - hw/m68k/mcf5208.c| 1 - hw/microblaze/petalogix_ml605_mmu.c | 1 - hw/microblaze/petalogix_s3adsp1800_mmu.c | 1 - hw/mips/mips_fulong2e.c | 1 - hw/mips/mips_jazz.c | 2 -- hw/mips/mips_malta.c | 1 - hw/mips/mips_mipssim.c | 1 - hw/mips/mips_r4k.c | 1 - hw/openrisc/openrisc_sim.c | 1 - hw/ppc/e500plat.c| 1 - hw/ppc/mac_newworld.c| 4 ++-- hw/ppc/mac_oldworld.c| 4 ++-- hw/ppc/mpc8544ds.c | 1 - hw/ppc/ppc405_boards.c | 2 -- hw/ppc/ppc440_bamboo.c | 1 - hw/ppc/prep.c| 4 ++-- hw/ppc/spapr.c | 4 ++-- hw/ppc/virtex_ml507.c| 1 - hw/s390x/s390-virtio-ccw.c | 1 - hw/s390x/s390-virtio.c | 1 - hw/sh4/r2d.c | 1 - hw/sh4/shix.c| 1 - hw/sparc/leon3.c | 1 - hw/sparc/sun4m.c | 22 +++--- hw/sparc64/sun4u.c | 10 +- hw/unicore32/puv3.c | 1 - hw/xtensa/xtensa_lx60.c | 2 -- hw/xtensa/xtensa_sim.c | 1 - vl.c | 4 ++-- 59 files changed, 51 insertions(+), 119 deletions(-) diff --git a/include/hw/boards.h b/include/hw/boards.h index fb7c6f1..5a7ae9f 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -6,12 +6,9 @@ #include sysemu/blockdev.h #include hw/qdev.h -#define DEFAULT_MACHINE_OPTIONS \ -.boot_order = cad - typedef struct QEMUMachineInitArgs { ram_addr_t ram_size; -const char *boot_device; +const char *boot_order; const char *kernel_filename; const char *kernel_cmdline; const char *initrd_filename; @@ -42,7 +39,7 @@ typedef struct QEMUMachine { no_sdcard:1; int is_default; const char
[Qemu-devel] [PULL 3/6] pci: add config space access traces
From: Alexey Kardashevskiy a...@ozlabs.ru This adds pci_cfg_read and pci_cfg_write traces for config spaces accesses. Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru Signed-off-by: Michael S. Tsirkin m...@redhat.com --- hw/pci/pci_host.c | 11 ++- trace-events | 4 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index 7dd9b25..77c7d1f 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -20,6 +20,7 @@ #include hw/pci/pci.h #include hw/pci/pci_host.h +#include trace.h /* debug PCI */ //#define DEBUG_PCI @@ -51,14 +52,22 @@ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr, uint32_t limit, uint32_t val, uint32_t len) { assert(len = 4); +trace_pci_cfg_write(pci_dev-name, PCI_SLOT(pci_dev-devfn), +PCI_FUNC(pci_dev-devfn), addr, val); pci_dev-config_write(pci_dev, addr, val, MIN(len, limit - addr)); } uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr, uint32_t limit, uint32_t len) { +uint32_t ret; + assert(len = 4); -return pci_dev-config_read(pci_dev, addr, MIN(len, limit - addr)); +ret = pci_dev-config_read(pci_dev, addr, MIN(len, limit - addr)); +trace_pci_cfg_read(pci_dev-name, PCI_SLOT(pci_dev-devfn), + PCI_FUNC(pci_dev-devfn), addr, ret); + +return ret; } void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len) diff --git a/trace-events b/trace-events index 3856b5c..9d1d1df 100644 --- a/trace-events +++ b/trace-events @@ -1176,3 +1176,7 @@ object_class_dynamic_cast_assert(const char *type, const char *target, const cha # hw/xen/xen_pvdevice.c xen_pv_mmio_read(uint64_t addr) WARNING: read from Xen PV Device MMIO space (address %PRIx64) xen_pv_mmio_write(uint64_t addr) WARNING: write to Xen PV Device MMIO space (address %PRIx64) + +# hw/pci/pci_host.c +pci_cfg_read(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) %s %02u:%u @0x%x - 0x%x +pci_cfg_write(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) %s %02u:%u @0x%x - 0x%x -- MST
[Qemu-devel] [PULL 6/6] virtio_pci: fix level interrupts with irqfd
commit 62c96360ae7f2c7a8b029277fbb7cb082fdef7fd virtio-pci: fix level interrupts only helps systems without irqfd: on systems with irqfd support we passed in flag requesting irqfd even when msix is disabled. As a result, for level interrupts we didn't install an fd handler so unmasking an fd had no effect. Fix this up. Cc: qemu-sta...@nongnu.org Signed-off-by: Michael S. Tsirkin m...@redhat.com --- hw/virtio/virtio-pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index d37037e..41b96ce 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -799,8 +799,7 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) break; } -r = virtio_pci_set_guest_notifier(d, n, assign, - kvm_msi_via_irqfd_enabled()); +r = virtio_pci_set_guest_notifier(d, n, assign, with_irqfd); if (r 0) { goto assign_error; } -- MST
Re: [Qemu-devel] [PATCH] target-ppc: Fix include for qemu_notify_event
On 02.09.2013, at 09:56, Andreas Färber wrote: Am 01.09.2013 18:00, schrieb Richard Henderson: Signed-off-by: Richard Henderson r...@twiddle.net --- target-ppc/kvm_ppc.c | 1 + 1 file changed, 1 insertion(+) The PowerPC target has been broken for more than a week. Déjà vu, Alex already sent a fix on ~Friday. Sending out pull request :). I just wanted to do another autotest run last night. Alex
[Qemu-devel] [PULL 10/18] target-ppc: fix bit extraction for FPBF and FPL
From: Aurelien Jarno aurel...@aurel32.net Bit extraction for the FP BF and L field of the MTFSFI and MTFSF instructions is wrong and doesn't match the reference manual (which explain the bit number in big endian format). It has been broken in commit 7d08d85645def18eac2a9d672c1868a35e0bcf79. This patch fixes this, which in turn fixes the problem reported by Khem Raj about the floor() function of libm. Reported-by: Khem Raj raj.k...@gmail.com Signed-off-by: Aurelien Jarno aurel...@aurel32.net CC: qemu-sta...@nongnu.org (1.6) Signed-off-by: Alexander Graf ag...@suse.de --- target-ppc/translate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index f07d70d..41f4048 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -428,9 +428,9 @@ EXTRACT_HELPER(CRM, 12, 8); EXTRACT_HELPER(SR, 16, 4); /* mtfsf/mtfsfi */ -EXTRACT_HELPER(FPBF, 19, 3); +EXTRACT_HELPER(FPBF, 23, 3); EXTRACT_HELPER(FPIMM, 12, 4); -EXTRACT_HELPER(FPL, 21, 1); +EXTRACT_HELPER(FPL, 25, 1); EXTRACT_HELPER(FPFLM, 17, 8); EXTRACT_HELPER(FPW, 16, 1); -- 1.8.1.4
[Qemu-devel] [PULL 16/18] PPC: KVM: Compile fix for qemu_notify_event
The function qemu_notify_event is defined by a header that we don't include in the PPC KVM code. Include it to get the code building again. target-ppc/kvm_ppc.c: In function 'kvmppc_timer_hack': target-ppc/kvm_ppc.c:26:5: error: implicit declaration of function 'qemu_notify_event' [-Werror=implicit-function-declaration] target-ppc/kvm_ppc.c:26:5: error: nested extern declaration of 'qemu_notify_event' [-Werror=nested-externs] Signed-off-by: Alexander Graf ag...@suse.de --- target-ppc/kvm_ppc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target-ppc/kvm_ppc.c b/target-ppc/kvm_ppc.c index 9b83655..f769acd 100644 --- a/target-ppc/kvm_ppc.c +++ b/target-ppc/kvm_ppc.c @@ -15,6 +15,7 @@ #include qemu/timer.h #include kvm_ppc.h #include sysemu/device_tree.h +#include qemu/main-loop.h #define PROC_DEVTREE_PATH /proc/device-tree -- 1.8.1.4
[Qemu-devel] [PULL 00/18] ppc patch queue 2013-09-02
Hi Blue / Aurelien / Anthony, This is my current patch queue for ppc. Please pull. Alex The following changes since commit 4ff78e0dbcd5c795962567fdc1b31e9e03c55b07: Merge remote-tracking branch 'luiz/queue/qmp' into staging (2013-08-30 12:26:04 -0500) are available in the git repository at: git://github.com/agraf/qemu.git ppc-for-upstream for you to fetch changes up to 7e472264e9e2727bc7d08fe6f012db76e1c1a193: PPC: spapr: iommu: rework traces (2013-09-02 10:06:43 +0200) Alexander Graf (2): PPC: E500: Generate device tree on reset PPC: KVM: Compile fix for qemu_notify_event Alexey Kardashevskiy (5): spapr-pci: fix config space access to support bridges spapr-pci: rework MSI/MSIX xics: move registration of global state to realize() spapr: add stop-self RTAS call required to support hot CPU unplug PPC: spapr: iommu: rework traces Andreas Färber (3): ppc405_boards: Disable debug output ppc405_uc: Disable debug output ppc405_boards: Don't enforce presence of firmware for qtest Aneesh Kumar K.V (1): target-ppc: Use #define instead of opencoding SLB valid bit Anton Blanchard (5): pseries: Fix stalls on hypervisor virtual console target-ppc: USE LPCR_ILE to control exception endian on POWER7 target-ppc: POWER7 supports the MSR_LE bit disas/ppc.c: Fix little endian disassembly pseries: Add H_SET_MODE hcall to change guest exception endianness Aurelien Jarno (1): target-ppc: fix bit extraction for FPBF and FPL Efimov Vasily (1): ppc: virtex_ml507: QEMU_OPTION_dtb support for this machine. disas/ppc.c | 3 +- hw/char/spapr_vty.c | 2 ++ hw/intc/xics.c | 21 ++--- hw/ppc/e500.c | 52 ++-- hw/ppc/ppc405_boards.c | 39 +--- hw/ppc/ppc405_uc.c | 16 +- hw/ppc/spapr.c | 31 +++ hw/ppc/spapr_hcall.c| 50 +++ hw/ppc/spapr_iommu.c| 71 +++ hw/ppc/spapr_pci.c | 73 ++--- hw/ppc/spapr_rtas.c | 23 ++ hw/ppc/virtex_ml507.c | 29 +++--- include/hw/pci-host/spapr.h | 8 +++-- include/hw/ppc/spapr.h | 21 +++-- target-ppc/cpu.h| 2 ++ target-ppc/excp_helper.c| 10 +++ target-ppc/kvm_ppc.c| 1 + target-ppc/mmu_helper.c | 2 +- target-ppc/translate.c | 4 +-- target-ppc/translate_init.c | 2 +- trace-events| 5 21 files changed, 305 insertions(+), 160 deletions(-)
[Qemu-devel] [PULL 05/18] disas/ppc.c: Fix little endian disassembly
From: Anton Blanchard an...@samba.org Use info-endian to select the endian of the instruction to be disassembled. Signed-off-by: Anton Blanchard an...@samba.org Reviewed-by: Anthony Liguori aligu...@us.ibm.com Signed-off-by: Alexander Graf ag...@suse.de --- disas/ppc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/disas/ppc.c b/disas/ppc.c index c149506..99c4cbc 100644 --- a/disas/ppc.c +++ b/disas/ppc.c @@ -5157,7 +5157,8 @@ int print_insn_ppc (bfd_vma memaddr, struct disassemble_info *info) { int dialect = (char *) info-private_data - (char *) 0; - return print_insn_powerpc (memaddr, info, 1, dialect); + return print_insn_powerpc (memaddr, info, info-endian == BFD_ENDIAN_BIG, + dialect); } /* Print a big endian PowerPC instruction. */ -- 1.8.1.4
[Qemu-devel] [PULL 08/18] ppc405_uc: Disable debug output
From: Andreas Färber afaer...@suse.de Signed-off-by: Andreas Färber afaer...@suse.de Signed-off-by: Alexander Graf ag...@suse.de --- hw/ppc/ppc405_uc.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 0ef5254..6d6a7f1 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -30,15 +30,15 @@ #include qemu/log.h #include exec/address-spaces.h -#define DEBUG_OPBA -#define DEBUG_SDRAM -#define DEBUG_GPIO -#define DEBUG_SERIAL -#define DEBUG_OCM +//#define DEBUG_OPBA +//#define DEBUG_SDRAM +//#define DEBUG_GPIO +//#define DEBUG_SERIAL +//#define DEBUG_OCM //#define DEBUG_I2C -#define DEBUG_GPT -#define DEBUG_MAL -#define DEBUG_CLOCKS +//#define DEBUG_GPT +//#define DEBUG_MAL +//#define DEBUG_CLOCKS //#define DEBUG_CLOCKS_LL ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd, -- 1.8.1.4
[Qemu-devel] [PULL 06/18] ppc: virtex_ml507: QEMU_OPTION_dtb support for this machine.
From: Efimov Vasily r...@ispras.ru QEMU has 'dtb' option for specifing the device tree file for the kernel. The patch adds support for this option to the 'virtex_ml507' machine implementation. Signed-off-by: Efimov Vasily r...@ispras.ru Signed-off-by: Alexander Graf ag...@suse.de --- hw/ppc/virtex_ml507.c | 29 +++-- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index 08e77fb..e9468b1 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -141,22 +141,31 @@ static int xilinx_load_device_tree(hwaddr addr, { char *path; int fdt_size; -void *fdt; +void *fdt = NULL; int r; +const char *dtb_filename; -/* Try the local ppc.dtb override. */ -fdt = load_device_tree(ppc.dtb, fdt_size); -if (!fdt) { -path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); -if (path) { -fdt = load_device_tree(path, fdt_size); -g_free(path); +dtb_filename = qemu_opt_get(qemu_get_machine_opts(), dtb); +if (dtb_filename) { +fdt = load_device_tree(dtb_filename, fdt_size); +if (!fdt) { +error_report(Error while loading device tree file '%s', +dtb_filename); } +} else { +/* Try the local ppc.dtb override. */ +fdt = load_device_tree(ppc.dtb, fdt_size); if (!fdt) { -return 0; +path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); +if (path) { +fdt = load_device_tree(path, fdt_size); +g_free(path); +} } } - +if (!fdt) { +return 0; +} r = qemu_devtree_setprop_string(fdt, /chosen, bootargs, kernel_cmdline); if (r 0) fprintf(stderr, couldn't set /chosen/bootargs\n); -- 1.8.1.4
[Qemu-devel] [PULL 07/18] ppc405_boards: Disable debug output
From: Andreas Färber afaer...@suse.de Also move one stray debug output into an #ifdef. Signed-off-by: Andreas Färber afaer...@suse.de Signed-off-by: Alexander Graf ag...@suse.de --- hw/ppc/ppc405_boards.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index f74e5e5..807ada0 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -42,7 +42,7 @@ #define USE_FLASH_BIOS -#define DEBUG_BOARD_INIT +//#define DEBUG_BOARD_INIT /*/ /* PPC405EP reference board (IBM) */ @@ -353,9 +353,9 @@ static void ref405ep_init(QEMUMachineInitArgs *args) bdloc = 0; } #ifdef DEBUG_BOARD_INIT +printf(bdloc RAM_ADDR_FMT \n, bdloc); printf(%s: Done\n, __func__); #endif -printf(bdloc RAM_ADDR_FMT \n, bdloc); } static QEMUMachine ref405ep_machine = { -- 1.8.1.4
[Qemu-devel] [PULL 12/18] target-ppc: Use #define instead of opencoding SLB valid bit
From: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com Use SLB_ESID_V instead of (1 27) in the code Reviewed-by: Andreas Färber afaer...@suse.de Signed-off-by: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com Signed-off-by: Alexander Graf ag...@suse.de --- target-ppc/mmu_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c index 5dd4e05..9c9132e 100644 --- a/target-ppc/mmu_helper.c +++ b/target-ppc/mmu_helper.c @@ -2061,7 +2061,7 @@ void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value) /* ESID = srnum */ rb |= ((uint32_t)srnum 0xf) 28; /* Set the valid bit */ -rb |= 1 27; +rb |= SLB_ESID_V; /* Index = ESID */ rb |= (uint32_t)srnum; -- 1.8.1.4
[Qemu-devel] [PULL 01/18] PPC: E500: Generate device tree on reset
Today we generate the device tree once on machine initialization and then store the finalized blob in memory to reload it on reset. This is bad for 2 reasons. First we potentially waste a bunch of RAM for no good reason, as we have all information required to regenerate the device tree available anyways. The second reason is even more important. On machine init when we generate the device tree for the first time, we don't have all of the devices fully initialized yet. But the device tree needs to potentially walk devices to put information about them into the device tree. Move the generation into a reset function. That way we just generate it new every time we reset, solving both of the above issues. Signed-off-by: Alexander Graf ag...@suse.de --- hw/ppc/e500.c | 52 +++- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index e79612b..9059ff9 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -123,13 +123,14 @@ static void dt_serial_create(void *fdt, unsigned long long offset, } } -static int ppce500_load_device_tree(CPUPPCState *env, -QEMUMachineInitArgs *args, +static int ppce500_load_device_tree(QEMUMachineInitArgs *args, PPCE500Params *params, hwaddr addr, hwaddr initrd_base, -hwaddr initrd_size) +hwaddr initrd_size, +bool dry_run) { +CPUPPCState *env = first_cpu-env_ptr; int ret = -1; uint64_t mem_reg_property[] = { 0, cpu_to_be64(args-ram_size) }; int fdt_size; @@ -369,12 +370,10 @@ static int ppce500_load_device_tree(CPUPPCState *env, } done: -qemu_devtree_dumpdtb(fdt, fdt_size); -ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); -if (ret 0) { -goto out; +if (!dry_run) { +qemu_devtree_dumpdtb(fdt, fdt_size); +cpu_physical_memory_write(addr, fdt, fdt_size); } -g_free(fdt); ret = fdt_size; out: @@ -383,6 +382,41 @@ out: return ret; } +typedef struct DeviceTreeParams { +QEMUMachineInitArgs args; +PPCE500Params params; +hwaddr addr; +hwaddr initrd_base; +hwaddr initrd_size; +} DeviceTreeParams; + +static void ppce500_reset_device_tree(void *opaque) +{ +DeviceTreeParams *p = opaque; +ppce500_load_device_tree(p-args, p-params, p-addr, p-initrd_base, + p-initrd_size, false); +} + +static int ppce500_prep_device_tree(QEMUMachineInitArgs *args, +PPCE500Params *params, +hwaddr addr, +hwaddr initrd_base, +hwaddr initrd_size) +{ +DeviceTreeParams *p = g_new(DeviceTreeParams, 1); +p-args = *args; +p-params = *params; +p-addr = addr; +p-initrd_base = initrd_base; +p-initrd_size = initrd_size; + +qemu_register_reset(ppce500_reset_device_tree, p); + +/* Issue the device tree loader once, so that we get the size of the blob */ +return ppce500_load_device_tree(args, params, addr, initrd_base, +initrd_size, true); +} + /* Create -kernel TLB entries for BookE. */ static inline hwaddr booke206_page_size_to_tlb(uint64_t size) { @@ -746,7 +780,7 @@ void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params) struct boot_info *boot_info; int dt_size; -dt_size = ppce500_load_device_tree(env, args, params, dt_base, +dt_size = ppce500_prep_device_tree(args, params, dt_base, initrd_base, initrd_size); if (dt_size 0) { fprintf(stderr, couldn't load device tree\n); -- 1.8.1.4
[Qemu-devel] [PULL 04/18] target-ppc: POWER7 supports the MSR_LE bit
From: Anton Blanchard an...@samba.org Add MSR_LE to the msr_mask for POWER7. Signed-off-by: Anton Blanchard an...@samba.org Reviewed-by: Anthony Liguori aligu...@us.ibm.com Signed-off-by: Alexander Graf ag...@suse.de --- target-ppc/translate_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 609f797..d2645ba 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -7227,7 +7227,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data) PPC_SEGMENT_64B | PPC_SLBI | PPC_POPCNTB | PPC_POPCNTWD; pcc-insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX | PPC2_ISA205; -pcc-msr_mask = 0x8204FF36ULL; +pcc-msr_mask = 0x8204FF37ULL; pcc-mmu_model = POWERPC_MMU_2_06; #if defined(CONFIG_SOFTMMU) pcc-handle_mmu_fault = ppc_hash64_handle_mmu_fault; -- 1.8.1.4
[Qemu-devel] [PULL 02/18] pseries: Fix stalls on hypervisor virtual console
From: Anton Blanchard an...@samba.org A number of users are reporting stalls when using the pseries hypervisor virtual console. A simple test case is to paste 15 or 17 characters at a time into the console. Pasting 15 characters at a time works fine but pasting 17 characters hangs for a random amount of time. Other activity (network, qemu monitor etc) unblocks it. If qemu-char tries to send more than 16 characters at once, vty_can_receive returns false. At this point we have to wait for the guest to consume that output. Everything is good so far. The problem occurs when the the guest does consume the output. We need to signal back to the qemu-char layer that we are ready for more input. Without this we block until something else kicks us (eg network activity). Signed-off-by: Anton Blanchard an...@samba.org Signed-off-by: Alexander Graf ag...@suse.de --- hw/char/spapr_vty.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c index a799721..9c2aef8 100644 --- a/hw/char/spapr_vty.c +++ b/hw/char/spapr_vty.c @@ -47,6 +47,8 @@ static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max) buf[n++] = dev-buf[dev-out++ % VTERM_BUFSIZE]; } +qemu_chr_accept_input(dev-chardev); + return n; } -- 1.8.1.4
[Qemu-devel] [PULL 13/18] spapr-pci: rework MSI/MSIX
From: Alexey Kardashevskiy a...@ozlabs.ru On the sPAPR platform a guest allocates MSI/MSIX vectors via RTAS hypercalls which return global IRQ numbers to a guest so it only operates with those and never touches MSIMessage. Therefore MSIMessage handling is completely hidden in QEMU. Previously every sPAPR PCI host bridge implemented its own MSI window to catch msi_notify()/msix_notify() calls from QEMU devices (virtio-pci or vfio) and route them to the guest via qemu_pulse_irq(). MSIMessage used to be encoded as: .addr - address within the PHB MSI window; .data - the device index on PHB plus vector number. The MSI MR write function translated this MSIMessage to a global IRQ number and called qemu_pulse_irq(). However the total number of IRQs is not really big (at the moment it is 1024 IRQs starting from 4096) and even 16bit data field of MSIMessage seems to be enough to store an IRQ number there. This simplifies MSI handling in sPAPR PHB. Specifically, this does: 1. remove a MSI window from a PHB; 2. add a single memory region for all MSIs to sPAPREnvironment and spapr_pci_msi_init() to initialize it; 3. encode MSIMessage as: * .addr - a fixed address of SPAPR_PCI_MSI_WINDOW==0x400ULL; * .data as an IRQ number. 4. change IRQ allocator to align first IRQ number in a block for MSI. MSI uses lower bits to specify the vector number so the first IRQ has to be aligned. MSIX does not need any special allocator though. Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru Reviewed-by: Anthony Liguori aligu...@us.ibm.com Acked-by: Michael S. Tsirkin m...@redhat.com Signed-off-by: Alexander Graf ag...@suse.de --- hw/ppc/spapr.c | 29 ++--- hw/ppc/spapr_pci.c | 61 - include/hw/pci-host/spapr.h | 8 +++--- include/hw/ppc/spapr.h | 4 ++- 4 files changed, 60 insertions(+), 42 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 4b566aa..1ce9b0b 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -88,6 +88,9 @@ int spapr_allocate_irq(int hint, bool lsi) if (hint) { irq = hint; +if (hint = spapr-next_irq) { +spapr-next_irq = hint + 1; +} /* FIXME: we should probably check for collisions somehow */ } else { irq = spapr-next_irq++; @@ -103,22 +106,39 @@ int spapr_allocate_irq(int hint, bool lsi) return irq; } -/* Allocate block of consequtive IRQs, returns a number of the first */ -int spapr_allocate_irq_block(int num, bool lsi) +/* + * Allocate block of consequtive IRQs, returns a number of the first. + * If msi==true, aligns the first IRQ number to num. + */ +int spapr_allocate_irq_block(int num, bool lsi, bool msi) { int first = -1; -int i; +int i, hint = 0; + +/* + * MSIMesage::data is used for storing VIRQ so + * it has to be aligned to num to support multiple + * MSI vectors. MSI-X is not affected by this. + * The hint is used for the first IRQ, the rest should + * be allocated continously. + */ +if (msi) { +assert((num == 1) || (num == 2) || (num == 4) || + (num == 8) || (num == 16) || (num == 32)); +hint = (spapr-next_irq + num - 1) ~(num - 1); +} for (i = 0; i num; ++i) { int irq; -irq = spapr_allocate_irq(0, lsi); +irq = spapr_allocate_irq(hint, lsi); if (!irq) { return -1; } if (0 == i) { first = irq; +hint = 0; } /* If the above doesn't create a consecutive block then that's @@ -1214,6 +1234,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) spapr_create_nvram(spapr); /* Set up PCI */ +spapr_pci_msi_init(spapr, SPAPR_PCI_MSI_WINDOW); spapr_pci_rtas_init(); phb = spapr_create_phb(spapr, 0); diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 65be265..9b6ee32 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -250,11 +250,11 @@ static int spapr_msicfg_find(sPAPRPHBState *phb, uint32_t config_addr, * This is required for msi_notify()/msix_notify() which * will write at the addresses via spapr_msi_write(). */ -static void spapr_msi_setmsg(PCIDevice *pdev, hwaddr addr, - bool msix, unsigned req_num) +static void spapr_msi_setmsg(PCIDevice *pdev, hwaddr addr, bool msix, + unsigned first_irq, unsigned req_num) { unsigned i; -MSIMessage msg = { .address = addr, .data = 0 }; +MSIMessage msg = { .address = addr, .data = first_irq }; if (!msix) { msi_set_message(pdev, msg); @@ -262,8 +262,7 @@ static void spapr_msi_setmsg(PCIDevice *pdev, hwaddr addr, return; } -for (i = 0; i req_num; ++i) { -msg.address = addr | (i 2); +for (i = 0; i req_num; ++i, ++msg.data) { msix_set_message(pdev, i, msg);
[Qemu-devel] [PULL 15/18] pseries: Add H_SET_MODE hcall to change guest exception endianness
From: Anton Blanchard an...@samba.org H_SET_MODE is used for controlling various partition settings. One of these settings is the endianness a guest takes its exceptions in. Signed-off-by: Anton Blanchard an...@samba.org [agraf: fix whitespace] Signed-off-by: Alexander Graf ag...@suse.de --- hw/ppc/spapr.c | 2 +- hw/ppc/spapr_hcall.c | 50 ++ include/hw/ppc/spapr.h | 17 - 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 1ce9b0b..04f0ee3 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -282,7 +282,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model, uint32_t start_prop = cpu_to_be32(initrd_base); uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size); char hypertas_prop[] = hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt -\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk; +\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk\0hcall-set-mode; char qemu_hypertas_prop[] = hcall-memop1; uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)}; uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)}; diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 67d6cd9..89e6a00 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -657,6 +657,54 @@ static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr, return H_SUCCESS; } +static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPREnvironment *spapr, + target_ulong opcode, target_ulong *args) +{ +CPUState *cs; +target_ulong mflags = args[0]; +target_ulong resource = args[1]; +target_ulong value1 = args[2]; +target_ulong value2 = args[3]; +target_ulong ret = H_P2; + +if (resource == H_SET_MODE_ENDIAN) { +if (value1) { +ret = H_P3; +goto out; +} +if (value2) { +ret = H_P4; +goto out; +} + +switch (mflags) { +case H_SET_MODE_ENDIAN_BIG: +for (cs = first_cpu; cs != NULL; cs = cs-next_cpu) { +PowerPCCPU *cp = POWERPC_CPU(cs); +CPUPPCState *env = cp-env; +env-spr[SPR_LPCR] = ~LPCR_ILE; +} +ret = H_SUCCESS; +break; + +case H_SET_MODE_ENDIAN_LITTLE: +for (cs = first_cpu; cs != NULL; cs = cs-next_cpu) { +PowerPCCPU *cp = POWERPC_CPU(cs); +CPUPPCState *env = cp-env; +env-spr[SPR_LPCR] |= LPCR_ILE; +} +ret = H_SUCCESS; +break; + +default: +ret = H_UNSUPPORTED_FLAG; +} +} + +out: +return ret; +} + static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1]; static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1]; @@ -734,6 +782,8 @@ static void hypercall_register_types(void) /* qemu/KVM-PPC specific hcalls */ spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas); + +spapr_register_hypercall(H_SET_MODE, h_set_mode); } type_init(hypercall_register_types) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 41b0466..e37b419 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -111,6 +111,15 @@ typedef struct sPAPREnvironment { #define H_NOT_ENOUGH_RESOURCES -44 #define H_R_STATE -45 #define H_RESCINDEND -46 +#define H_P2 -55 +#define H_P3 -56 +#define H_P4 -57 +#define H_P5 -58 +#define H_P6 -59 +#define H_P7 -60 +#define H_P8 -61 +#define H_P9 -62 +#define H_UNSUPPORTED_FLAG -256 #define H_MULTI_THREADS_ACTIVE -9005 @@ -145,6 +154,11 @@ typedef struct sPAPREnvironment { #define H_PP1 (1ULL(63-62)) #define H_PP2 (1ULL(63-63)) +/* H_SET_MODE flags */ +#define H_SET_MODE_ENDIAN4 +#define H_SET_MODE_ENDIAN_BIG0 +#define H_SET_MODE_ENDIAN_LITTLE 1 + /* VASI States */ #define H_VASI_INVALID0 #define H_VASI_ENABLED1 @@ -269,7 +283,8 @@ typedef struct sPAPREnvironment { #define H_GET_EM_PARMS 0x2B8 #define H_SET_MPP 0x2D0 #define H_GET_MPP 0x2D4 -#define MAX_HCALL_OPCODEH_GET_MPP +#define H_SET_MODE 0x31C +#define MAX_HCALL_OPCODEH_SET_MODE /* The hcalls above are standardized in PAPR and implemented by pHyp * as well. -- 1.8.1.4
[Qemu-devel] [PULL 17/18] spapr: add stop-self RTAS call required to support hot CPU unplug
From: Alexey Kardashevskiy a...@ozlabs.ru PAPR+ requires two RTAS calls to be supported by the hypervisor in order to allow hotplugging VCPUs from the guest. The start-cpu RTAS call was already there but stop-self was not. This adds the stop-self RTAS call. Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru Signed-off-by: Alexander Graf ag...@suse.de --- hw/ppc/spapr_rtas.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 394ce05..eb542f2 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -202,6 +202,28 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPREnvironment *spapr, rtas_st(rets, 0, -3); } +static void rtas_stop_self(PowerPCCPU *cpu, sPAPREnvironment *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, + uint32_t nret, target_ulong rets) +{ +CPUState *cs = CPU(cpu); +CPUPPCState *env = cpu-env; + +cs-halted = 1; +cpu_exit(cs); +/* + * While stopping a CPU, the guest calls H_CPPR which + * effectively disables interrupts on XICS level. + * However decrementer interrupts in TCG can still + * wake the CPU up so here we disable interrupts in MSR + * as well. + * As rtas_start_cpu() resets the whole MSR anyway, there is + * no need to bother with specific bits, we just clear it. + */ +env-msr = 0; +} + static struct rtas_call { const char *name; spapr_rtas_fn fn; @@ -322,6 +344,7 @@ static void core_rtas_register_types(void) spapr_rtas_register(query-cpu-stopped-state, rtas_query_cpu_stopped_state); spapr_rtas_register(start-cpu, rtas_start_cpu); +spapr_rtas_register(stop-self, rtas_stop_self); } type_init(core_rtas_register_types) -- 1.8.1.4
[Qemu-devel] [PULL 03/18] target-ppc: USE LPCR_ILE to control exception endian on POWER7
From: Anton Blanchard an...@samba.org On POWER7, LPCR_ILE is used to control what endian guests take their exceptions in so use it instead of MSR_ILE. Signed-off-by: Anton Blanchard an...@samba.org Reviewed-by: Anthony Liguori aligu...@us.ibm.com Signed-off-by: Alexander Graf ag...@suse.de --- target-ppc/cpu.h | 2 ++ target-ppc/excp_helper.c | 10 ++ 2 files changed, 12 insertions(+) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 711db08..422a6bb 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -453,6 +453,8 @@ struct ppc_slb_t { #define MSR_RI 1 /* Recoverable interrupt1*/ #define MSR_LE 0 /* Little-endian mode 1 hflags */ +#define LPCR_ILE (1 (63-38)) + #define msr_sf ((env-msr MSR_SF)1) #define msr_isf ((env-msr MSR_ISF) 1) #define msr_shv ((env-msr MSR_SHV) 1) diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c index e9fcad8..e957761 100644 --- a/target-ppc/excp_helper.c +++ b/target-ppc/excp_helper.c @@ -611,9 +611,19 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) tlb_flush(env, 1); } +#ifdef TARGET_PPC64 +if (excp_model == POWERPC_EXCP_POWER7) { +if (env-spr[SPR_LPCR] LPCR_ILE) { +new_msr |= (target_ulong)1 MSR_LE; +} +} else if (msr_ile) { +new_msr |= (target_ulong)1 MSR_LE; +} +#else if (msr_ile) { new_msr |= (target_ulong)1 MSR_LE; } +#endif /* Jump to handler */ vector = env-excp_vectors[excp]; -- 1.8.1.4
[Qemu-devel] [PULL 09/18] ppc405_boards: Don't enforce presence of firmware for qtest
From: Andreas Färber afaer...@suse.de Adopt error_report() while at it. Signed-off-by: Andreas Färber afaer...@suse.de Signed-off-by: Alexander Graf ag...@suse.de --- hw/ppc/ppc405_boards.c | 35 --- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index 807ada0..75b2177 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -27,9 +27,11 @@ #include hw/timer/m48t59.h #include hw/block/flash.h #include sysemu/sysemu.h +#include sysemu/qtest.h #include block/block.h #include hw/boards.h #include qemu/log.h +#include qemu/error-report.h #include hw/loader.h #include sysemu/blockdev.h #include exec/address-spaces.h @@ -252,17 +254,20 @@ static void ref405ep_init(QEMUMachineInitArgs *args) if (filename) { bios_size = load_image(filename, memory_region_get_ram_ptr(bios)); g_free(filename); +if (bios_size 0 || bios_size BIOS_SIZE) { +error_report(Could not load PowerPC BIOS '%s', bios_name); +exit(1); +} +bios_size = (bios_size + 0xfff) ~0xfff; +memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); +} else if (!qtest_enabled() || kernel_filename != NULL) { +error_report(Could not load PowerPC BIOS '%s', bios_name); +exit(1); } else { +/* Avoid an uninitialized variable warning */ bios_size = -1; } -if (bios_size 0 || bios_size BIOS_SIZE) { -fprintf(stderr, qemu: could not load PowerPC bios '%s'\n, -bios_name); -exit(1); -} -bios_size = (bios_size + 0xfff) ~0xfff; memory_region_set_readonly(bios, true); -memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); } /* Register FPGA */ #ifdef DEBUG_BOARD_INIT @@ -569,17 +574,17 @@ static void taihu_405ep_init(QEMUMachineInitArgs *args) if (filename) { bios_size = load_image(filename, memory_region_get_ram_ptr(bios)); g_free(filename); -} else { -bios_size = -1; -} -if (bios_size 0 || bios_size BIOS_SIZE) { -fprintf(stderr, qemu: could not load PowerPC bios '%s'\n, -bios_name); +if (bios_size 0 || bios_size BIOS_SIZE) { +error_report(Could not load PowerPC BIOS '%s', bios_name); +exit(1); +} +bios_size = (bios_size + 0xfff) ~0xfff; +memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); +} else if (!qtest_enabled()) { +error_report(Could not load PowerPC BIOS '%s', bios_name); exit(1); } -bios_size = (bios_size + 0xfff) ~0xfff; memory_region_set_readonly(bios, true); -memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); } /* Register Linux flash */ dinfo = drive_get(IF_PFLASH, 0, fl_idx); -- 1.8.1.4
[Qemu-devel] [PULL 14/18] xics: move registration of global state to realize()
From: Alexey Kardashevskiy a...@ozlabs.ru Registration of global state belongs into realize so move it there. Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru Reviewed-by: Andreas Färber afaer...@suse.de Signed-off-by: Alexander Graf ag...@suse.de --- hw/intc/xics.c | 21 +++-- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/hw/intc/xics.c b/hw/intc/xics.c index 6b3c071..31868c4 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -642,6 +642,17 @@ static void xics_realize(DeviceState *dev, Error **errp) ICSState *ics = icp-ics; int i; +/* Registration of global state belongs into realize */ +spapr_rtas_register(ibm,set-xive, rtas_set_xive); +spapr_rtas_register(ibm,get-xive, rtas_get_xive); +spapr_rtas_register(ibm,int-off, rtas_int_off); +spapr_rtas_register(ibm,int-on, rtas_int_on); + +spapr_register_hypercall(H_CPPR, h_cppr); +spapr_register_hypercall(H_IPI, h_ipi); +spapr_register_hypercall(H_XIRR, h_xirr); +spapr_register_hypercall(H_EOI, h_eoi); + ics-nr_irqs = icp-nr_irqs; ics-offset = XICS_IRQ_BASE; ics-icp = icp; @@ -678,16 +689,6 @@ static void xics_class_init(ObjectClass *oc, void *data) dc-realize = xics_realize; dc-props = xics_properties; dc-reset = xics_reset; - -spapr_rtas_register(ibm,set-xive, rtas_set_xive); -spapr_rtas_register(ibm,get-xive, rtas_get_xive); -spapr_rtas_register(ibm,int-off, rtas_int_off); -spapr_rtas_register(ibm,int-on, rtas_int_on); - -spapr_register_hypercall(H_CPPR, h_cppr); -spapr_register_hypercall(H_IPI, h_ipi); -spapr_register_hypercall(H_XIRR, h_xirr); -spapr_register_hypercall(H_EOI, h_eoi); } static const TypeInfo xics_info = { -- 1.8.1.4
[Qemu-devel] [PULL 11/18] spapr-pci: fix config space access to support bridges
From: Alexey Kardashevskiy a...@ozlabs.ru spapr-pci config space accessors use find_dev() to find a PCI device. However find_dev() only searched on a primary bus and did not do recursive search through secondary buses so config space access was not possible for devices other that on a primary bus. This fixed find_dev() by using the PCI API pci_find_device() function. This effectively enabled pci bridges on spapr. Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru Acked-by: Michael S. Tsirkin m...@redhat.com Signed-off-by: Alexander Graf ag...@suse.de --- hw/ppc/spapr_pci.c | 12 ++-- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 1ca35a0..65be265 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -65,22 +65,14 @@ static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid, { sPAPRPHBState *sphb = find_phb(spapr, buid); PCIHostState *phb = PCI_HOST_BRIDGE(sphb); -BusState *bus = BUS(phb-bus); -BusChild *kid; +int bus_num = (config_addr 16) 0xFF; int devfn = (config_addr 8) 0xFF; if (!phb) { return NULL; } -QTAILQ_FOREACH(kid, bus-children, sibling) { -PCIDevice *dev = (PCIDevice *)kid-child; -if (dev-devfn == devfn) { -return dev; -} -} - -return NULL; +return pci_find_device(phb-bus, bus_num, devfn); } static uint32_t rtas_pci_cfgaddr(uint32_t arg) -- 1.8.1.4
[Qemu-devel] [PULL 18/18] PPC: spapr: iommu: rework traces
From: Alexey Kardashevskiy a...@ozlabs.ru This converts old style fprintf to traces. Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru [agraf: change patch subject] Signed-off-by: Alexander Graf ag...@suse.de --- hw/ppc/spapr_iommu.c | 71 ++-- trace-events | 5 2 files changed, 29 insertions(+), 47 deletions(-) diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 3d4a1fc..ef45f4f 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -22,13 +22,12 @@ #include kvm_ppc.h #include sysemu/dma.h #include exec/address-spaces.h +#include trace.h #include hw/ppc/spapr.h #include libfdt.h -/* #define DEBUG_TCE */ - enum sPAPRTCEAccess { SPAPR_TCE_FAULT = 0, SPAPR_TCE_RO = 1, @@ -61,44 +60,28 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr) { sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu); uint64_t tce; - -#ifdef DEBUG_TCE -fprintf(stderr, spapr_tce_translate liobn=0x% PRIx32 addr=0x -DMA_ADDR_FMT \n, tcet-liobn, addr); -#endif +IOMMUTLBEntry ret = { +.target_as = address_space_memory, +.iova = 0, +.translated_addr = 0, +.addr_mask = ~(hwaddr)0, +.perm = IOMMU_NONE, +}; if (tcet-bypass) { -return (IOMMUTLBEntry) { -.target_as = address_space_memory, -.iova = 0, -.translated_addr = 0, -.addr_mask = ~(hwaddr)0, -.perm = IOMMU_RW, -}; -} - -/* Check if we are in bound */ -if (addr = tcet-window_size) { -#ifdef DEBUG_TCE -fprintf(stderr, spapr_tce_translate out of bounds\n); -#endif -return (IOMMUTLBEntry) { .perm = IOMMU_NONE }; +ret.perm = IOMMU_RW; +} else if (addr tcet-window_size) { +/* Check if we are in bound */ +tce = tcet-table[addr SPAPR_TCE_PAGE_SHIFT]; +ret.iova = addr ~SPAPR_TCE_PAGE_MASK; +ret.translated_addr = tce ~SPAPR_TCE_PAGE_MASK; +ret.addr_mask = SPAPR_TCE_PAGE_MASK; +ret.perm = tce; } +trace_spapr_iommu_xlate(tcet-liobn, addr, ret.iova, ret.perm, +ret.addr_mask); -tce = tcet-table[addr SPAPR_TCE_PAGE_SHIFT]; - -#ifdef DEBUG_TCE -fprintf(stderr, - *paddr=0x%llx, *len=0x%llx\n, -(tce ~SPAPR_TCE_PAGE_MASK), SPAPR_TCE_PAGE_MASK + 1); -#endif - -return (IOMMUTLBEntry) { -.target_as = address_space_memory, -.iova = addr ~SPAPR_TCE_PAGE_MASK, -.translated_addr = tce ~SPAPR_TCE_PAGE_MASK, -.addr_mask = SPAPR_TCE_PAGE_MASK, -.perm = tce, -}; +return ret; } static int spapr_tce_table_pre_load(void *opaque) @@ -150,10 +133,7 @@ static int spapr_tce_table_realize(DeviceState *dev) } tcet-nb_table = tcet-window_size SPAPR_TCE_PAGE_SHIFT; -#ifdef DEBUG_TCE -fprintf(stderr, spapr_iommu: New TCE table @ %p, liobn=0x%x, -table @ %p, fd=%d\n, tcet, liobn, tcet-table, tcet-fd); -#endif +trace_spapr_iommu_new_table(tcet-liobn, tcet, tcet-table, tcet-fd); memory_region_init_iommu(tcet-iommu, OBJECT(dev), spapr_iommu_ops, iommu-spapr, UINT64_MAX); @@ -250,20 +230,17 @@ static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong liobn = args[0]; target_ulong ioba = args[1]; target_ulong tce = args[2]; +target_ulong ret = H_PARAMETER; sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn); ioba = ~(SPAPR_TCE_PAGE_SIZE - 1); if (tcet) { -return put_tce_emu(tcet, ioba, tce); +ret = put_tce_emu(tcet, ioba, tce); } -#ifdef DEBUG_TCE -fprintf(stderr, %s on liobn= TARGET_FMT_lx /*%s*/ - ioba 0x TARGET_FMT_lx TCE 0x TARGET_FMT_lx \n, -__func__, liobn, /*dev-qdev.id, */ioba, tce); -#endif +trace_spapr_iommu_put(liobn, ioba, tce, ret); -return H_PARAMETER; +return ret; } int spapr_dma_dt(void *fdt, int node_off, const char *propname, diff --git a/trace-events b/trace-events index 3856b5c..aaad356 100644 --- a/trace-events +++ b/trace-events @@ -1133,6 +1133,11 @@ xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) ics_write_ xics_ics_reject(int nr, int srcno) reject irq %#x [src %d] xics_ics_eoi(int nr) ics_eoi: irq %#x +# hw/ppc/spapr_iommu.c +spapr_iommu_put(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t ret) liobn=%PRIx64 ioba=0x%PRIx64 tce=0x%PRIx64 ret=%PRId64 +spapr_iommu_xlate(uint64_t liobn, uint64_t ioba, uint64_t tce, unsigned perm, unsigned pgsize) liobn=%PRIx64 0x%PRIx64 - 0x%PRIx64 perm=%u mask=%x +spapr_iommu_new_table(uint64_t liobn, void *tcet, void *table, int fd) liobn=%PRIx64 tcet=%p table=%p fd=%d + # util/hbitmap.c hbitmap_iter_skip_words(const void *hb, void *hbi, uint64_t pos, unsigned long cur) hb %p hbi %p pos %PRId64 cur 0x%lx hbitmap_reset(void
Re: [Qemu-devel] [PULL 00/26] Block patches
Am 30.08.2013 um 19:14 hat Anthony Liguori geschrieben: This pull request breaks make check, qemu-system-i386 segvs when running qtest. bisect blames the following commit. I confirmed this commit introduces the breakage too. commit 19abade25242079f4b5582de17b2302fe185be2b Author: Max Reitz mre...@redhat.com Date: Fri Aug 30 14:34:29 2013 +0200 qcow2-refcount: Repair shared refcount blocks If the refcount of a refcount block is greater than one, we can at least try to repair that problem by duplicating the affected block. Signed-off-by: Max Reitz mre...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com Sorry, seems I messed up here. The shell history shows that I did run 'make check', but somehow the failure must have escaped my attention (it's not an assertion failure and we do have some noise in successful runs, maybe that's why) The other test case that could have caught it (qemu-iotests 026) has been broken for ages, and we need to finally fix it. Thanks for catching this, Anthony. I'll send a v2. Kevin
Re: [Qemu-devel] [PATCH] target-i386: Only provide CMOV and friends if feature bit set
Ping^3! thanks -- PMM On 20 August 2013 13:59, Peter Maydell peter.mayd...@linaro.org wrote: Ping^2! This has been reviewed and I've checked that the patch still applies to master. thanks -- PMM On 25 July 2013 17:54, Peter Maydell peter.mayd...@linaro.org wrote: Ping! (patchwork url: http://patchwork.ozlabs.org/patch/259148/) thanks -- PMM On 15 July 2013 18:21, Peter Maydell peter.mayd...@linaro.org wrote: The instructions CMOVcc, FCMOVcc and F[U]COMI[P] should only be present if the CMOV feature bit is set. Add missing feature bit checks so we correctly fault if emulating a 486 or 586. This fixes bug LP:1201446. Signed-off-by: Peter Maydell peter.mayd...@linaro.org --- target-i386/translate.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/target-i386/translate.c b/target-i386/translate.c index 6550c27..f75e3b1 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -6434,12 +6434,18 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, } break; case 0x1d: /* fucomi */ +if (!(s-cpuid_features CPUID_CMOV)) { +goto illegal_op; +} gen_update_cc_op(s); gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); gen_helper_fucomi_ST0_FT0(cpu_env); set_cc_op(s, CC_OP_EFLAGS); break; case 0x1e: /* fcomi */ +if (!(s-cpuid_features CPUID_CMOV)) { +goto illegal_op; +} gen_update_cc_op(s); gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); gen_helper_fcomi_ST0_FT0(cpu_env); @@ -6495,6 +6501,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, } break; case 0x3d: /* fucomip */ +if (!(s-cpuid_features CPUID_CMOV)) { +goto illegal_op; +} gen_update_cc_op(s); gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); gen_helper_fucomi_ST0_FT0(cpu_env); @@ -6502,6 +6511,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, set_cc_op(s, CC_OP_EFLAGS); break; case 0x3e: /* fcomip */ +if (!(s-cpuid_features CPUID_CMOV)) { +goto illegal_op; +} gen_update_cc_op(s); gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); gen_helper_fcomi_ST0_FT0(cpu_env); @@ -6518,6 +6530,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, (JCC_BE 1), (JCC_P 1), }; + +if (!(s-cpuid_features CPUID_CMOV)) { +goto illegal_op; +} op1 = fcmov_cc[op 3] | (((op 3) 1) ^ 1); l1 = gen_new_label(); gen_jcc1_noeob(s, op1, l1); @@ -6889,6 +6905,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_ldst_modrm(env, s, modrm, OT_BYTE, OR_TMP0, 1); break; case 0x140 ... 0x14f: /* cmov Gv, Ev */ +if (!(s-cpuid_features CPUID_CMOV)) { +goto illegal_op; +} ot = dflag + OT_WORD; modrm = cpu_ldub_code(env, s-pc++); reg = ((modrm 3) 7) | rex_r; -- 1.7.9.5 -- 12345678901234567890123456789012345678901234567890123456789012345678901234567890 1 2 3 4 5 6 7 8
Re: [Qemu-devel] [PATCH v2] pseries: Update SLOF firmware image
On 28.08.2013, at 09:42, Alexey Kardashevskiy wrote: On 08/27/2013 06:33 PM, Alexander Graf wrote: On 27.08.2013, at 05:42, Alexey Kardashevskiy wrote: This has reworked USB OHCI and adds support of USB EHCI, VIRTIO-SCSI and various fixes (IBM VSCSI, VGA and more). The full list of fixes is: * usb-ohci: Convert td-phys every time to td-virt * usb-storage: Fix cbwflags field * Add -fno-strict-aliasing in global CFLAGS * usb: fix various issues found with js2x * Move hex64-{decode,encode}-unit to node.fs * usb: Use separate in-memory endian swap * usb-ohci: collect TDs from done list * js2x: more fixes * js2x: Fix build of takeover image * js2x: use new usb stack * usb-ohci: Use proper memory barriers always * usb: Fix a couple of warnings * Fix $cat-instance-unit * Cache phandle of /chosen * Use root.fs on qemu as well * usb-ehci: Add ehci handshake * usb: add mb for write accessors * usb-ohci: add missing memory barriers * usb-ohci: suspend the controller in exit code path * usb-ohci: Add a reset when closing the OHCI * usb: Use proper accessors for MMIO and separate in-memory endian swap * Use a global definition of sync() and mb() * net-snk: Remove exception handling * usb: unmap buffers * slof: call quiesce on closing of stdin * usb-kbd: accept s to drop to OF prompt * USB storage driver * usb-ohci: add Bulk transfer support * usb-ehci: Add bulk support * usb-core: add usb bulk support * USB generic hub device driver * usb-ehci: setup new device * usb-ehci: Check ehci ports * usb-ehci: initialize controller * USB keyboard driver * usb-core: setup new device * usb-core: create dev pool allocation * usb-ohci: implement ohci send control * usb-core: usb send control * usb-core: implement usb_{get,put}_pipe routines * usb-ohci: allocate pipe pool * usb-ohci: reset, init and check-ports * Add standard header stdbool.h * usb-slof: forth support routines for C * usb-ehci: Add USB EHCI skeleton * usb-core: Add register accessor functions * Use __builtin_bswap routines for endianness swapping * usb-core: hcd registration and query routines * usb-core: adding generic dev-hci.fs * usb-core: registration and makefiles * Add new USB code * Remove old usb code * vga: fix hcall-invert-screen and hcall-blink-screen * Enumerate disk/cdrom aliases for multiple disks or cdroms * scsi: unify scsi probing code * vscsi: generalizing probe code * virtio-scsi: iterate through targets * scsi: unify and use make-disk-alias * nvram: remove unnecessary prints * Add hack to client interface finddevice of /memory * scsi: Fix cdrom boot crash when no medium present * Look for /memory@0, not just /memory * Fix instanceqname crashing when displaying instance arguments * Fix js2x build * scsi-disk: Bound check read-blocks * Fix off by one error in scsi-disk get-capacity * scsi: fix report-luns handling * SLOF: virtio-scsi block driver code * scsi: Move bits of vio-vscsi.fs to a common helpers file * scsi: Move scsi-disk.fs to a generic place * SLOF: virtio-scsi helper routines * SLOF: virtio-scsi - add pci device file * iso9660: Don't constantly reallocate the read buffer * vscsi: Sanitize interface between scsi-disk.fs and vio-vscsi.fs * vio-vscsi: Rework vio-vscsi support * virtio: Add a virtio-set-qaddr helper * disk-label: Allocate 4096 bytes for 4k block devices * disk-label: Increase the max size of the PReP boot partition * Make load-base a real environment variable * vio-vscsi: Switch to using a wildcard disk node and make scsi-disk generic * Fix disk-label package to use proper instance path * Increase size of catpad * Fix instancepath to contain unit address for wildcard nodes * Fix handling of wildcard nodes in open-dev * vio-vscsi: Get CRQ on open and release on close Cc: Benjamin Herrenschmidt b...@kernel.crashing.org Cc: Nikunj A Dadhania nik...@linux.vnet.ibm.com Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru --- Changes: v2: * added 2 patches on top --- pc-bios/README | 2 +- pc-bios/slof.bin | Bin 909720 - 875424 bytes roms/SLOF| 2 +- For this to work we also need to update the SLOF copy at git.qemu.org. Anthony, could you please do that? Checked - it is there. What is the next step to get it in upstream? Pinging me :). Thanks, applied to ppc-next. Alex
[Qemu-devel] [PULL v2 00/26] Block patches
The following changes since commit b5d54bd42158b90b239bb6ce9c13072eb3a53fd2: Merge remote-tracking branch 'qemu-kvm/uq/master' into stable-1.5 (2013-08-29 17:21:51 -0500) are available in the git repository at: git://repo.or.cz/qemu/kevin.git for-anthony for you to fetch changes up to ca0eca91b65c34d6e5f5c77d5c18ed3de5b26139: qemu-iotests: Overlapping cluster allocations (2013-09-02 10:15:15 +0200) Bharata B Rao (1): gluster: Abort on AIO completion failure Kevin Wolf (6): qcow2: Change default for new images to compat=1.1 block: Remove redundant assertion qapi-types.py: Split off generate_struct_fields() Revert block: Disable driver-specific options for 1.6 qemu-iotests: Update reference output for 051 block: Remove old raw driver Laszlo Ersek (7): add skeleton for BSD licensed raw BlockDriver raw_bsd: emit debug events in bdrv_co_readv() and bdrv_co_writev() raw_bsd: add raw_create() raw_bsd: introduce special members raw_bsd: add raw_create_options raw_bsd: register bdrv_raw switch raw block driver from raw.o to raw_bsd.o Max Reitz (11): option: Add assigned flag to QEMUOptionParameter qcow2-refcount: Snapshot update for zero clusters qemu-iotests: Snapshotting zero clusters qcow2: Add corrupt bit qcow2: Metadata overlap checks qcow2: Employ metadata overlap checks qcow2-refcount: Move OFLAG_COPIED checks qcow2-refcount: Repair OFLAG_COPIED errors qcow2-refcount: Repair shared refcount blocks qcow2_check: Mark image consistent qemu-iotests: Overlapping cluster allocations Peter Maydell (1): block/qcow2.h: Avoid 1LL 63 (shifts into sign bit) block.c| 1 - block/Makefile.objs| 2 +- block/blkdebug.c | 1 + block/gluster.c| 15 +- block/qcow2-cache.c| 17 ++ block/qcow2-cluster.c | 25 ++- block/qcow2-refcount.c | 533 - block/qcow2-snapshot.c | 22 ++ block/qcow2.c | 83 ++- block/qcow2.h | 53 - block/{raw.c = raw_bsd.c} | 170 +++ blockdev.c | 143 docs/specs/qcow2.txt | 7 +- include/block/block.h | 1 + include/monitor/monitor.h | 1 + include/qemu/option.h | 1 + monitor.c | 1 + scripts/qapi-types.py | 19 +- tests/qemu-iotests/031.out | 12 +- tests/qemu-iotests/036.out | 2 +- tests/qemu-iotests/051.out | 1 - tests/qemu-iotests/060 | 111 ++ tests/qemu-iotests/060.out | 44 tests/qemu-iotests/062 | 64 ++ tests/qemu-iotests/062.out | 9 + tests/qemu-iotests/group | 4 +- util/qemu-option.c | 9 + 27 files changed, 1029 insertions(+), 322 deletions(-) rename block/{raw.c = raw_bsd.c} (57%) create mode 100755 tests/qemu-iotests/060 create mode 100644 tests/qemu-iotests/060.out create mode 100755 tests/qemu-iotests/062 create mode 100644 tests/qemu-iotests/062.out
[Qemu-devel] [PULL v2 01/26] qcow2: Change default for new images to compat=1.1
By the time that qemu 1.7 will be released, enough time will have passed since qemu 1.1, which is the first version to understand version 3 images, that changing the default shouldn't hurt many people any more and the benefits of using the new format outweigh the pain. qemu-iotests already runs with compat=1.1 by default. Signed-off-by: Kevin Wolf kw...@redhat.com Reviewed-by: Eric Blake ebl...@redhat.com --- block/qcow2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/block/qcow2.c b/block/qcow2.c index 78097e5..5e5f413 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1429,7 +1429,9 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options) return -EINVAL; } } else if (!strcmp(options-name, BLOCK_OPT_COMPAT_LEVEL)) { -if (!options-value.s || !strcmp(options-value.s, 0.10)) { +if (!options-value.s) { +/* keep the default */ +} else if (!strcmp(options-value.s, 0.10)) { version = 2; } else if (!strcmp(options-value.s, 1.1)) { version = 3; -- 1.8.1.4
[Qemu-devel] [PULL v2 02/26] block: Remove redundant assertion
The failing condition is checked immediately before the assertion, so keeping the assertion is kind of redundant. Signed-off-by: Kevin Wolf kw...@redhat.com --- block.c | 1 - 1 file changed, 1 deletion(-) diff --git a/block.c b/block.c index a387c1a..26639e8 100644 --- a/block.c +++ b/block.c @@ -743,7 +743,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, ret = -EINVAL; goto free_and_fail; } -assert(file != NULL); bs-file = file; ret = drv-bdrv_open(bs, options, open_flags); } -- 1.8.1.4
[Qemu-devel] [PULL v2 11/26] raw_bsd: add raw_create_options
From: Laszlo Ersek ler...@redhat.com On 08/05/13 15:03, Paolo Bonzini wrote: [...] 4) There is another member, .create_options, which is an array of QEMUOptionParameter structs, terminated by an all-zero item. The only option you need is for the virtual disk size. You will find something to copy from in other block drivers, for example block/qcow2.c. Code taken and adapted from block/qcow2.c, as suggested. The code being copied/modified is blamed on commit 20d97356c9df6d68fbd37d6334fdb7063f24eab6 Author: Blue Swirl blauwir...@gmail.com Date: Fri Apr 23 20:19:47 2010 + Fix OpenBSD build and commit 7c80ab3f21f0b1342f23057d4345ae266c7348d9 Author: Jes Sorensen jes.soren...@redhat.com Date: Fri Dec 17 16:02:39 2010 +0100 block/qcow2.c: rename qcow_ functions to qcow2_ Signed-off-by: Laszlo Ersek ler...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/raw_bsd.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/block/raw_bsd.c b/block/raw_bsd.c index b1d7209..b70245d 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -1,6 +1,7 @@ /* BlockDriver implementation for raw * - * Copyright (C) 2013, Red Hat, Inc. + * Copyright (C) 2010, 2013, Red Hat, Inc. + * Copyright (C) 2010, Blue Swirl blauwir...@gmail.com * * Author: * Laszlo Ersek ler...@redhat.com @@ -25,6 +26,16 @@ */ #include block/block_int.h +#include qemu/option.h + +static const QEMUOptionParameter raw_create_options[] = { +{ +.name = BLOCK_OPT_SIZE, +.type = OPT_SIZE, +.help = Virtual disk size +}, +{ 0 } +}; static TYPE raw_reopen_prepare(BlockDriverState *bs) { -- 1.8.1.4
[Qemu-devel] [PULL v2 07/26] add skeleton for BSD licensed raw BlockDriver
From: Laszlo Ersek ler...@redhat.com On 08/05/13 15:03, Paolo Bonzini wrote: - Original Message - From: Laszlo Ersek ler...@redhat.com To: Paolo Bonzini pbonz...@redhat.com Sent: Monday, August 5, 2013 2:43:46 PM Subject: Re: [PATCH 1/2] raw: add license header On 08/02/13 00:27, Paolo Bonzini wrote: On 08/01/2013 10:13 AM, Christoph Hellwig wrote: On Wed, Jul 31, 2013 at 08:19:51AM +0200, Paolo Bonzini wrote: Most of the block layer is under the BSD license, thus it is reasonable to license block/raw.c the same way. CCed people should ACK by replying with a Signed-off-by line. The coded was intended to be GPLv2. Laszlo, would you be willing to do clean-room reverse engineering? (No rants, please. :)) What's the scope exactly? It's quite small, it's a file full of forwarders like static void raw_foo(BlockDriverState *bs) { return bdrv_foo(bs-file); } It's 170 lines of code, all as boring as this. I only picked you because I'm quite certain you have never seen the file (and the answer confirmed it). Basically: 1) BlockDriver is a struct in which these function members are interesting: .bdrv_reopen_prepare .bdrv_co_readv .bdrv_co_writev .bdrv_co_is_allocated .bdrv_co_write_zeroes .bdrv_co_discard .bdrv_getlength .bdrv_get_info .bdrv_truncate .bdrv_is_inserted .bdrv_media_changed .bdrv_eject .bdrv_lock_medium .bdrv_ioctl .bdrv_aio_ioctl .bdrv_has_zero_init They should be implemented as simple forwarders (see above). There are 16 functions listed here, you can easily see how this already accounts for 100+ SLOC roughly... The implementations of bdrv_co_readv and bdrv_co_writev should also call BLKDBG_EVENT on bs-file too, before forwarding to bs-file. The events to be generated are BLKDBG_READ_AIO and BLKDBG_WRITE_AIO. 2) This is also a simple forwarder function: .bdrv_create but there is no BlockDriverState argument so the forwarded-to function does not have a bs-file argument either. The forwarded-to function is bdrv_create_file. 3) These members are special .format_name is the string raw .bdrv_open raw_open should set bs-sg to bs-file-sg and return 0 .bdrv_closeraw_close should do nothing .bdrv_proberaw_probe should just return 1. 4) There is another member, .create_options, which is an array of QEMUOptionParameter structs, terminated by an all-zero item. The only option you need is for the virtual disk size. You will find something to copy from in other block drivers, for example block/qcow2.c. 5) Formats are registered with bdrv_register (takes a BlockDriver*). You also need to pass the caller of bdrv_register to block_init. 6) I'm not sure how to organize the patch series, so I'll leave this to your creativity. I guess in this case move/copy detection of git should be disabled. I would definitely include this spec in the commit message as a proof of clean-room reverse engineering. 7) Remember a BSD header like the one in block.c. Paolo This patch implements the email up to the paragraph ending with 100+ SLOC roughly. The skeleton is generated from the list there, with a simple shell loop using sed and the raw_foo() template. The BSD license block is copied (and reflowed) from util/qemu-progress.c. Signed-off-by: Laszlo Ersek ler...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/raw_bsd.c | 108 1 file changed, 108 insertions(+) create mode 100644 block/raw_bsd.c diff --git a/block/raw_bsd.c b/block/raw_bsd.c new file mode 100644 index 000..5c17d53 --- /dev/null +++ b/block/raw_bsd.c @@ -0,0 +1,108 @@ +/* BlockDriver implementation for raw + * + * Copyright (C) 2013, Red Hat, Inc. + * + * Author: + * Laszlo Ersek ler...@redhat.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the Software), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +
[Qemu-devel] [PULL v2 06/26] block/qcow2.h: Avoid 1LL 63 (shifts into sign bit)
From: Peter Maydell peter.mayd...@linaro.org The expression 1LL 63 tries to shift the 1 into the sign bit of a 'long long', which provokes a clang sanitizer warning: runtime error: left shift of 1 by 63 places cannot be represented in type 'long long' Use 1ULL 63 as the definition of QCOW_OFLAG_COPIED instead to avoid this. For consistency, we also update the other QCOW_OFLAG definitions to use the ULL suffix rather than LL, though only the shift by 63 is undefined behaviour. Signed-off-by: Peter Maydell peter.mayd...@linaro.org Reviewed-by: Eric Blake ebl...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/qcow2.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/block/qcow2.h b/block/qcow2.h index dba9771..365a17e 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -40,11 +40,11 @@ #define QCOW_MAX_CRYPT_CLUSTERS 32 /* indicate that the refcount of the referenced cluster is exactly one. */ -#define QCOW_OFLAG_COPIED (1LL 63) +#define QCOW_OFLAG_COPIED (1ULL 63) /* indicate that the cluster is compressed (they never have the copied flag) */ -#define QCOW_OFLAG_COMPRESSED (1LL 62) +#define QCOW_OFLAG_COMPRESSED (1ULL 62) /* The cluster reads as all zeros */ -#define QCOW_OFLAG_ZERO (1LL 0) +#define QCOW_OFLAG_ZERO (1ULL 0) #define REFCOUNT_SHIFT 1 /* refcount size is 2 bytes */ -- 1.8.1.4
[Qemu-devel] [PULL v2 03/26] qapi-types.py: Split off generate_struct_fields()
Signed-off-by: Kevin Wolf kw...@redhat.com Reviewed-by: Eric Blake ebl...@redhat.com --- scripts/qapi-types.py | 19 +-- 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 5ee46ea..86de980 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -57,12 +57,8 @@ typedef struct %(name)sList ''', name=name) -def generate_struct(structname, fieldname, members): -ret = mcgen(''' -struct %(name)s -{ -''', - name=structname) +def generate_struct_fields(members): +ret = '' for argname, argentry, optional, structured in parse_args(members): if optional: @@ -80,6 +76,17 @@ struct %(name)s ''', c_type=c_type(argentry), c_name=c_var(argname)) +return ret + +def generate_struct(structname, fieldname, members): +ret = mcgen(''' +struct %(name)s +{ +''', + name=structname) + +ret += generate_struct_fields(members) + if len(fieldname): fieldname = + fieldname ret += mcgen(''' -- 1.8.1.4
[Qemu-devel] [PULL v2 13/26] switch raw block driver from raw.o to raw_bsd.o
From: Laszlo Ersek ler...@redhat.com Incoming function prototypes and outgoing function calls must match reality. Implemented using the struct BlockDriver definition in include/block/block_int.h, and gcc errors warnings. v1-v2: On 08/20/13 09:51, Kevin Wolf wrote: Am 18.08.2013 um 16:29 hat Paolo Bonzini geschrieben: Il 16/08/2013 16:15, Laszlo Ersek ha scritto: +static int raw_reopen_prepare(BDRVReopenState *reopen_state, + BlockReopenQueue *queue, Error **errp) { -return bdrv_reopen_prepare(bs-file); +BDRVReopenState tmp = *reopen_state; + +tmp.bs = tmp.bs-file; +return bdrv_reopen_prepare(tmp, queue, errp); } This should just return zero, my fault. Which is because bdrv_reopen_queue() already queues bs-file for reopen. The simple return 0; implementation is shared by all other format drivers that support reopening images. Signed-off-by: Laszlo Ersek ler...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/Makefile.objs | 2 +- block/raw_bsd.c | 78 ++--- 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/block/Makefile.objs b/block/Makefile.objs index 4cf9aa4..3bb85b5 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -1,4 +1,4 @@ -block-obj-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o +block-obj-y += raw_bsd.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-obj-y += qed-check.o diff --git a/block/raw_bsd.c b/block/raw_bsd.c index 2dc1921..ab2b0fd 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -29,7 +29,7 @@ #include block/block_int.h #include qemu/option.h -static const QEMUOptionParameter raw_create_options[] = { +static QEMUOptionParameter raw_create_options[] = { { .name = BLOCK_OPT_SIZE, .type = OPT_SIZE, @@ -38,104 +38,114 @@ static const QEMUOptionParameter raw_create_options[] = { { 0 } }; -static TYPE raw_reopen_prepare(BlockDriverState *bs) +static int raw_reopen_prepare(BDRVReopenState *reopen_state, + BlockReopenQueue *queue, Error **errp) { -return bdrv_reopen_prepare(bs-file); +return 0; } -static TYPE raw_co_readv(BlockDriverState *bs) +static int coroutine_fn raw_co_readv(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, QEMUIOVector *qiov) { BLKDBG_EVENT(bs-file, BLKDBG_READ_AIO); -return bdrv_co_readv(bs-file); +return bdrv_co_readv(bs-file, sector_num, nb_sectors, qiov); } -static TYPE raw_co_writev(BlockDriverState *bs) +static int coroutine_fn raw_co_writev(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, QEMUIOVector *qiov) { BLKDBG_EVENT(bs-file, BLKDBG_WRITE_AIO); -return bdrv_co_writev(bs-file); +return bdrv_co_writev(bs-file, sector_num, nb_sectors, qiov); } -static TYPE raw_co_is_allocated(BlockDriverState *bs) +static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs, +int64_t sector_num, int nb_sectors, +int *pnum) { -return bdrv_co_is_allocated(bs-file); +return bdrv_co_is_allocated(bs-file, sector_num, nb_sectors, pnum); } -static TYPE raw_co_write_zeroes(BlockDriverState *bs) +static int coroutine_fn raw_co_write_zeroes(BlockDriverState *bs, +int64_t sector_num, int nb_sectors) { -return bdrv_co_write_zeroes(bs-file); +return bdrv_co_write_zeroes(bs-file, sector_num, nb_sectors); } -static TYPE raw_co_discard(BlockDriverState *bs) +static int coroutine_fn raw_co_discard(BlockDriverState *bs, + int64_t sector_num, int nb_sectors) { -return bdrv_co_discard(bs-file); +return bdrv_co_discard(bs-file, sector_num, nb_sectors); } -static TYPE raw_getlength(BlockDriverState *bs) +static int64_t raw_getlength(BlockDriverState *bs) { return bdrv_getlength(bs-file); } -static TYPE raw_get_info(BlockDriverState *bs) +static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { -return bdrv_get_info(bs-file); +return bdrv_get_info(bs-file, bdi); } -static TYPE raw_truncate(BlockDriverState *bs) +static int raw_truncate(BlockDriverState *bs, int64_t offset) { -return bdrv_truncate(bs-file); +return bdrv_truncate(bs-file, offset); } -static TYPE raw_is_inserted(BlockDriverState *bs) +static int raw_is_inserted(BlockDriverState *bs) { return bdrv_is_inserted(bs-file); } -static TYPE raw_media_changed(BlockDriverState *bs) +static int raw_media_changed(BlockDriverState *bs) { return bdrv_media_changed(bs-file); } -static TYPE
[Qemu-devel] [PULL v2 09/26] raw_bsd: add raw_create()
From: Laszlo Ersek ler...@redhat.com On 08/05/13 15:03, Paolo Bonzini wrote: [...] 2) This is also a simple forwarder function: .bdrv_create but there is no BlockDriverState argument so the forwarded-to function does not have a bs-file argument either. The forwarded-to function is bdrv_create_file. Signed-off-by: Laszlo Ersek ler...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/raw_bsd.c | 4 1 file changed, 4 insertions(+) diff --git a/block/raw_bsd.c b/block/raw_bsd.c index 19091a3..5bcbe71 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -108,3 +108,7 @@ static TYPE raw_has_zero_init(BlockDriverState *bs) return bdrv_has_zero_init(bs-file); } +static TYPE raw_create(void) +{ +return bdrv_create_file(); +} -- 1.8.1.4
[Qemu-devel] [PULL v2 05/26] qemu-iotests: Update reference output for 051
Signed-off-by: Kevin Wolf kw...@redhat.com --- tests/qemu-iotests/051.out | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index 5582ed3..86e989c 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -85,7 +85,6 @@ QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized Testing: -drive if=scsi QEMU X.Y.Z monitor - type 'help' for more information (qemu) QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty -QEMU_PROG: -drive if=scsi: Device initialization failed. QEMU_PROG: Device initialization failed. QEMU_PROG: Initialization of device lsi53c895a failed -- 1.8.1.4
[Qemu-devel] [PULL v2 19/26] qcow2: Add corrupt bit
From: Max Reitz mre...@redhat.com This adds an incompatible bit indicating corruption to qcow2. Any image with this bit set may not be written to unless for repairing (and subsequently clearing the bit if the repair has been successful). Signed-off-by: Max Reitz mre...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/qcow2.c | 47 ++ block/qcow2.h | 7 ++- docs/specs/qcow2.txt | 7 ++- tests/qemu-iotests/031.out | 12 ++-- tests/qemu-iotests/036.out | 2 +- 5 files changed, 66 insertions(+), 9 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 5e5f413..fe91568 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -272,6 +272,37 @@ static int qcow2_mark_clean(BlockDriverState *bs) return 0; } +/* + * Marks the image as corrupt. + */ +int qcow2_mark_corrupt(BlockDriverState *bs) +{ +BDRVQcowState *s = bs-opaque; + +s-incompatible_features |= QCOW2_INCOMPAT_CORRUPT; +return qcow2_update_header(bs); +} + +/* + * Marks the image as consistent, i.e., unsets the corrupt bit, and flushes + * before if necessary. + */ +int qcow2_mark_consistent(BlockDriverState *bs) +{ +BDRVQcowState *s = bs-opaque; + +if (s-incompatible_features QCOW2_INCOMPAT_CORRUPT) { +int ret = bdrv_flush(bs); +if (ret 0) { +return ret; +} + +s-incompatible_features = ~QCOW2_INCOMPAT_CORRUPT; +return qcow2_update_header(bs); +} +return 0; +} + static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix) { @@ -402,6 +433,17 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags) goto fail; } +if (s-incompatible_features QCOW2_INCOMPAT_CORRUPT) { +/* Corrupt images may not be written to unless they are being repaired + */ +if ((flags BDRV_O_RDWR) !(flags BDRV_O_CHECK)) { +error_report(qcow2: Image is corrupt; cannot be opened +read/write.); +ret = -EACCES; +goto fail; +} +} + /* Check support for various header values */ if (header.refcount_order != 4) { report_unsupported(bs, %d bit reference counts, @@ -1130,6 +1172,11 @@ int qcow2_update_header(BlockDriverState *bs) .name = dirty bit, }, { +.type = QCOW2_FEAT_TYPE_INCOMPATIBLE, +.bit = QCOW2_INCOMPAT_CORRUPT_BITNR, +.name = corrupt bit, +}, +{ .type = QCOW2_FEAT_TYPE_COMPATIBLE, .bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR, .name = lazy refcounts, diff --git a/block/qcow2.h b/block/qcow2.h index 365a17e..32ecb33 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -119,9 +119,12 @@ enum { /* Incompatible feature bits */ enum { QCOW2_INCOMPAT_DIRTY_BITNR = 0, +QCOW2_INCOMPAT_CORRUPT_BITNR = 1, QCOW2_INCOMPAT_DIRTY = 1 QCOW2_INCOMPAT_DIRTY_BITNR, +QCOW2_INCOMPAT_CORRUPT = 1 QCOW2_INCOMPAT_CORRUPT_BITNR, -QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY, +QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY + | QCOW2_INCOMPAT_CORRUPT, }; /* Compatible feature bits */ @@ -361,6 +364,8 @@ int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov, int64_t sector_num, int nb_sectors); int qcow2_mark_dirty(BlockDriverState *bs); +int qcow2_mark_corrupt(BlockDriverState *bs); +int qcow2_mark_consistent(BlockDriverState *bs); int qcow2_update_header(BlockDriverState *bs); /* qcow2-refcount.c functions */ diff --git a/docs/specs/qcow2.txt b/docs/specs/qcow2.txt index 36a559d..33eca36 100644 --- a/docs/specs/qcow2.txt +++ b/docs/specs/qcow2.txt @@ -80,7 +80,12 @@ in the description of a field. tables to repair refcounts before accessing the image. -Bits 1-63: Reserved (set to 0) +Bit 1: Corrupt bit. If this bit is set then any data +structure may be corrupt and the image must not +be written to (unless for regaining +consistency). + +Bits 2-63: Reserved (set to 0) 80 - 87: compatible_features Bitmask of compatible features. An implementation can diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out index 796c993..a943344 100644 --- a/tests/qemu-iotests/031.out +++ b/tests/qemu-iotests/031.out @@ -54,7 +54,7 @@ header_length 72 Header extension: magic 0x6803f857 -length96 +length144 data binary Header extension: @@ -68,7 +68,7 @@ No errors were found on the image. magic
[Qemu-devel] [PULL v2 04/26] Revert block: Disable driver-specific options for 1.6
This reverts commit 8afaefb8919dc8746a57c450a758717c516c7b0a. Signed-off-by: Kevin Wolf kw...@redhat.com --- blockdev.c | 143 --- tests/qemu-iotests/group | 2 +- 2 files changed, 1 insertion(+), 144 deletions(-) diff --git a/blockdev.c b/blockdev.c index 121520e..e70e16e 100644 --- a/blockdev.c +++ b/blockdev.c @@ -46,7 +46,6 @@ static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives); extern QemuOptsList qemu_common_drive_opts; -extern QemuOptsList qemu_old_drive_opts; static const char *const if_name[IF_COUNT] = { [IF_NONE] = none, @@ -755,26 +754,6 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) { const char *value; -/* - * Check that only old options are used by copying into a QemuOpts with - * stricter checks. Going through a QDict seems to be the easiest way to - * achieve this... - */ -QemuOpts* check_opts; -QDict *qdict; -Error *local_err = NULL; - -qdict = qemu_opts_to_qdict(all_opts, NULL); -check_opts = qemu_opts_from_qdict(qemu_old_drive_opts, qdict, local_err); -QDECREF(qdict); - -if (error_is_set(local_err)) { -qerror_report_err(local_err); -error_free(local_err); -return NULL; -} -qemu_opts_del(check_opts); - /* Change legacy command line options into QMP ones */ qemu_opt_rename(all_opts, iops, throttling.iops-total); qemu_opt_rename(all_opts, iops_rd, throttling.iops-read); @@ -2001,128 +1980,6 @@ QemuOptsList qemu_common_drive_opts = { }, }; -QemuOptsList qemu_old_drive_opts = { -.name = drive, -.head = QTAILQ_HEAD_INITIALIZER(qemu_old_drive_opts.head), -.desc = { -{ -.name = bus, -.type = QEMU_OPT_NUMBER, -.help = bus number, -},{ -.name = unit, -.type = QEMU_OPT_NUMBER, -.help = unit number (i.e. lun for scsi), -},{ -.name = if, -.type = QEMU_OPT_STRING, -.help = interface (ide, scsi, sd, mtd, floppy, pflash, virtio), -},{ -.name = index, -.type = QEMU_OPT_NUMBER, -.help = index number, -},{ -.name = cyls, -.type = QEMU_OPT_NUMBER, -.help = number of cylinders (ide disk geometry), -},{ -.name = heads, -.type = QEMU_OPT_NUMBER, -.help = number of heads (ide disk geometry), -},{ -.name = secs, -.type = QEMU_OPT_NUMBER, -.help = number of sectors (ide disk geometry), -},{ -.name = trans, -.type = QEMU_OPT_STRING, -.help = chs translation (auto, lba. none), -},{ -.name = media, -.type = QEMU_OPT_STRING, -.help = media type (disk, cdrom), -},{ -.name = snapshot, -.type = QEMU_OPT_BOOL, -.help = enable/disable snapshot mode, -},{ -.name = file, -.type = QEMU_OPT_STRING, -.help = disk image, -},{ -.name = discard, -.type = QEMU_OPT_STRING, -.help = discard operation (ignore/off, unmap/on), -},{ -.name = cache, -.type = QEMU_OPT_STRING, -.help = host cache usage (none, writeback, writethrough, -directsync, unsafe), -},{ -.name = aio, -.type = QEMU_OPT_STRING, -.help = host AIO implementation (threads, native), -},{ -.name = format, -.type = QEMU_OPT_STRING, -.help = disk format (raw, qcow2, ...), -},{ -.name = serial, -.type = QEMU_OPT_STRING, -.help = disk serial number, -},{ -.name = rerror, -.type = QEMU_OPT_STRING, -.help = read error action, -},{ -.name = werror, -.type = QEMU_OPT_STRING, -.help = write error action, -},{ -.name = addr, -.type = QEMU_OPT_STRING, -.help = pci address (virtio only), -},{ -.name = readonly, -.type = QEMU_OPT_BOOL, -.help = open drive file as read-only, -},{ -.name = iops, -.type = QEMU_OPT_NUMBER, -.help = limit total I/O operations per second, -},{ -.name = iops_rd, -.type = QEMU_OPT_NUMBER, -.help = limit read operations per second, -},{ -.name = iops_wr, -.type = QEMU_OPT_NUMBER, -.help = limit write operations per second, -},{ -.name = bps, -.type = QEMU_OPT_NUMBER, -.help = limit total bytes per second, -},{ -.name =
[Qemu-devel] [PULL v2 08/26] raw_bsd: emit debug events in bdrv_co_readv() and bdrv_co_writev()
From: Laszlo Ersek ler...@redhat.com On 08/05/13 15:03, Paolo Bonzini wrote: [...] 1) BlockDriver is a struct in which these function members are interesting: .bdrv_reopen_prepare .bdrv_co_readv .bdrv_co_writev .bdrv_co_is_allocated .bdrv_co_write_zeroes .bdrv_co_discard .bdrv_getlength .bdrv_get_info .bdrv_truncate .bdrv_is_inserted .bdrv_media_changed .bdrv_eject .bdrv_lock_medium .bdrv_ioctl .bdrv_aio_ioctl .bdrv_has_zero_init They should be implemented as simple forwarders (see above). There are 16 functions listed here, you can easily see how this already accounts for 100+ SLOC roughly... The implementations of bdrv_co_readv and bdrv_co_writev should also call BLKDBG_EVENT on bs-file too, before forwarding to bs-file. The events to be generated are BLKDBG_READ_AIO and BLKDBG_WRITE_AIO. Signed-off-by: Laszlo Ersek ler...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/raw_bsd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/block/raw_bsd.c b/block/raw_bsd.c index 5c17d53..19091a3 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -33,11 +33,13 @@ static TYPE raw_reopen_prepare(BlockDriverState *bs) static TYPE raw_co_readv(BlockDriverState *bs) { +BLKDBG_EVENT(bs-file, BLKDBG_READ_AIO); return bdrv_co_readv(bs-file); } static TYPE raw_co_writev(BlockDriverState *bs) { +BLKDBG_EVENT(bs-file, BLKDBG_WRITE_AIO); return bdrv_co_writev(bs-file); } -- 1.8.1.4
[Qemu-devel] [PULL v2 10/26] raw_bsd: introduce special members
From: Laszlo Ersek ler...@redhat.com On 08/05/13 15:03, Paolo Bonzini wrote: [...] 3) These members are special .format_name is the string raw .bdrv_open raw_open should set bs-sg to bs-file-sg and return 0 .bdrv_closeraw_close should do nothing .bdrv_proberaw_probe should just return 1. v1-v2: On 08/20/13 10:11, Kevin Wolf wrote: Am 16.08.2013 um 16:15 hat Laszlo Ersek geschrieben: +static int raw_probe(void) +{ +return 1; +} Maybe add a comment here like smallest possible positive score so that raw is used if and only if no other block driver works. Signed-off-by: Laszlo Ersek ler...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/raw_bsd.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/block/raw_bsd.c b/block/raw_bsd.c index 5bcbe71..b1d7209 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -112,3 +112,26 @@ static TYPE raw_create(void) { return bdrv_create_file(); } + +static const char *raw_format_name(void) +{ +return raw; +} + +static int raw_open(BlockDriverState *bs) +{ +bs-sg = bs-file-sg; +return 0; +} + +static void raw_close(void) +{ +} + +static int raw_probe(void) +{ +/* smallest possible positive score so that raw is used if and only if no + * other block driver works + */ +return 1; +} -- 1.8.1.4
[Qemu-devel] [PULL v2 24/26] qcow2-refcount: Repair shared refcount blocks
From: Max Reitz mre...@redhat.com If the refcount of a refcount block is greater than one, we can at least try to repair that problem by duplicating the affected block. Signed-off-by: Max Reitz mre...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/blkdebug.c | 1 + block/qcow2-refcount.c | 148 - include/block/block.h | 1 + 3 files changed, 148 insertions(+), 2 deletions(-) diff --git a/block/blkdebug.c b/block/blkdebug.c index ccb627a..5d33e03 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -168,6 +168,7 @@ static const char *event_names[BLKDBG_EVENT_MAX] = { [BLKDBG_REFTABLE_LOAD] = reftable_load, [BLKDBG_REFTABLE_GROW] = reftable_grow, +[BLKDBG_REFTABLE_UPDATE]= reftable_update, [BLKDBG_REFBLOCK_LOAD] = refblock_load, [BLKDBG_REFBLOCK_UPDATE]= refblock_update, diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 2276b6f..ba129de 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1338,6 +1338,121 @@ fail: } /* + * Writes one sector of the refcount table to the disk + */ +#define RT_ENTRIES_PER_SECTOR (512 / sizeof(uint64_t)) +static int write_reftable_entry(BlockDriverState *bs, int rt_index) +{ +BDRVQcowState *s = bs-opaque; +uint64_t buf[RT_ENTRIES_PER_SECTOR]; +int rt_start_index; +int i, ret; + +rt_start_index = rt_index ~(RT_ENTRIES_PER_SECTOR - 1); +for (i = 0; i RT_ENTRIES_PER_SECTOR; i++) { +buf[i] = cpu_to_be64(s-refcount_table[rt_start_index + i]); +} + +ret = qcow2_pre_write_overlap_check(bs, +QCOW2_OL_DEFAULT ~QCOW2_OL_REFCOUNT_TABLE, +s-refcount_table_offset + rt_start_index * sizeof(uint64_t), +sizeof(buf)); +if (ret 0) { +return ret; +} + +BLKDBG_EVENT(bs-file, BLKDBG_REFTABLE_UPDATE); +ret = bdrv_pwrite_sync(bs-file, s-refcount_table_offset + +rt_start_index * sizeof(uint64_t), buf, sizeof(buf)); +if (ret 0) { +return ret; +} + +return 0; +} + +/* + * Allocates a new cluster for the given refcount block (represented by its + * offset in the image file) and copies the current content there. This function + * does _not_ decrement the reference count for the currently occupied cluster. + * + * This function prints an informative message to stderr on error (and returns + * -errno); on success, 0 is returned. + */ +static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index, + uint64_t offset) +{ +BDRVQcowState *s = bs-opaque; +int64_t new_offset = 0; +void *refcount_block = NULL; +int ret; + +/* allocate new refcount block */ +new_offset = qcow2_alloc_clusters(bs, s-cluster_size); +if (new_offset 0) { +fprintf(stderr, Could not allocate new cluster: %s\n, +strerror(-new_offset)); +ret = new_offset; +goto fail; +} + +/* fetch current refcount block content */ +ret = qcow2_cache_get(bs, s-refcount_block_cache, offset, refcount_block); +if (ret 0) { +fprintf(stderr, Could not fetch refcount block: %s\n, strerror(-ret)); +goto fail; +} + +/* new block has not yet been entered into refcount table, therefore it is + * no refcount block yet (regarding this check) */ +ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, new_offset, +s-cluster_size); +if (ret 0) { +fprintf(stderr, Could not write refcount block; metadata overlap +check failed: %s\n, strerror(-ret)); +/* the image will be marked corrupt, so don't even attempt on freeing + * the cluster */ +new_offset = 0; +goto fail; +} + +/* write to new block */ +ret = bdrv_write(bs-file, new_offset / BDRV_SECTOR_SIZE, refcount_block, +s-cluster_sectors); +if (ret 0) { +fprintf(stderr, Could not write refcount block: %s\n, strerror(-ret)); +goto fail; +} + +/* update refcount table */ +assert(!(new_offset (s-cluster_size - 1))); +s-refcount_table[reftable_index] = new_offset; +ret = write_reftable_entry(bs, reftable_index); +if (ret 0) { +fprintf(stderr, Could not update refcount table: %s\n, +strerror(-ret)); +goto fail; +} + +fail: +if (new_offset (ret 0)) { +qcow2_free_clusters(bs, new_offset, s-cluster_size, +QCOW2_DISCARD_ALWAYS); +} +if (refcount_block) { +if (ret 0) { +qcow2_cache_put(bs, s-refcount_block_cache, refcount_block); +} else { +ret = qcow2_cache_put(bs, s-refcount_block_cache, refcount_block); +} +} +if (ret 0) { +return ret; +} +return new_offset; +} + +/* * Checks an image for refcount
[Qemu-devel] [PULL v2 14/26] block: Remove old raw driver
This is unused code now. Signed-off-by: Kevin Wolf kw...@redhat.com --- block/raw.c | 192 1 file changed, 192 deletions(-) delete mode 100644 block/raw.c diff --git a/block/raw.c b/block/raw.c deleted file mode 100644 index 4751825..000 --- a/block/raw.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Block driver for RAW format - * - * Copyright (c) 2006 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the Software), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include qemu-common.h -#include block/block_int.h -#include qemu/module.h - -static int raw_open(BlockDriverState *bs, QDict *options, int flags) -{ -bs-sg = bs-file-sg; -return 0; -} - -/* We have nothing to do for raw reopen, stubs just return - * success */ -static int raw_reopen_prepare(BDRVReopenState *state, - BlockReopenQueue *queue, Error **errp) -{ -return 0; -} - -static int coroutine_fn raw_co_readv(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov) -{ -BLKDBG_EVENT(bs-file, BLKDBG_READ_AIO); -return bdrv_co_readv(bs-file, sector_num, nb_sectors, qiov); -} - -static int coroutine_fn raw_co_writev(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov) -{ -BLKDBG_EVENT(bs-file, BLKDBG_WRITE_AIO); -return bdrv_co_writev(bs-file, sector_num, nb_sectors, qiov); -} - -static void raw_close(BlockDriverState *bs) -{ -} - -static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs, -int64_t sector_num, -int nb_sectors, int *pnum) -{ -return bdrv_co_is_allocated(bs-file, sector_num, nb_sectors, pnum); -} - -static int coroutine_fn raw_co_write_zeroes(BlockDriverState *bs, -int64_t sector_num, -int nb_sectors) -{ -return bdrv_co_write_zeroes(bs-file, sector_num, nb_sectors); -} - -static int64_t raw_getlength(BlockDriverState *bs) -{ -return bdrv_getlength(bs-file); -} - -static int raw_truncate(BlockDriverState *bs, int64_t offset) -{ -return bdrv_truncate(bs-file, offset); -} - -static int raw_probe(const uint8_t *buf, int buf_size, const char *filename) -{ - return 1; /* everything can be opened as raw image */ -} - -static int coroutine_fn raw_co_discard(BlockDriverState *bs, - int64_t sector_num, int nb_sectors) -{ -return bdrv_co_discard(bs-file, sector_num, nb_sectors); -} - -static int raw_is_inserted(BlockDriverState *bs) -{ -return bdrv_is_inserted(bs-file); -} - -static int raw_media_changed(BlockDriverState *bs) -{ -return bdrv_media_changed(bs-file); -} - -static void raw_eject(BlockDriverState *bs, bool eject_flag) -{ -bdrv_eject(bs-file, eject_flag); -} - -static void raw_lock_medium(BlockDriverState *bs, bool locked) -{ -bdrv_lock_medium(bs-file, locked); -} - -static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) -{ - return bdrv_ioctl(bs-file, req, buf); -} - -static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, -unsigned long int req, void *buf, -BlockDriverCompletionFunc *cb, void *opaque) -{ - return bdrv_aio_ioctl(bs-file, req, buf, cb, opaque); -} - -static int raw_create(const char *filename, QEMUOptionParameter *options) -{ -return bdrv_create_file(filename, options); -} - -static QEMUOptionParameter raw_create_options[] = { -{ -.name = BLOCK_OPT_SIZE, -.type = OPT_SIZE, -.help = Virtual disk size -}, -{ NULL } -}; - -static int raw_has_zero_init(BlockDriverState *bs) -{ -return bdrv_has_zero_init(bs-file); -} - -static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) -{ -return bdrv_get_info(bs-file, bdi); -} - -static BlockDriver
[Qemu-devel] [PULL v2 12/26] raw_bsd: register bdrv_raw
From: Laszlo Ersek ler...@redhat.com On 08/05/13 15:03, Paolo Bonzini wrote: [...] 5) Formats are registered with bdrv_register (takes a BlockDriver*). You also need to pass the caller of bdrv_register to block_init. Fill in the BlockDriver structure with the raw_*() functions that have been added to block/raw_bsd.c, in the order the fields are defined in include/block/block_int.h. I needed more explanation / naming examples for registering the driver than what Paolo gave me, so I copied / adapted from block/qcow2.c. The parts I took as basis for modification are blamed on commit 5efa9d5a8b18841c9c62208a494d7f519238979a Author: Anthony Liguori aligu...@us.ibm.com Date: Sat May 9 17:03:42 2009 -0500 Convert block infrastructure to use new module init functionality commit 20d97356c9df6d68fbd37d6334fdb7063f24eab6 Author: Blue Swirl blauwir...@gmail.com Date: Fri Apr 23 20:19:47 2010 + Fix OpenBSD build Signed-off-by: Laszlo Ersek ler...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/raw_bsd.c | 38 +- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/block/raw_bsd.c b/block/raw_bsd.c index b70245d..2dc1921 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -2,6 +2,7 @@ * * Copyright (C) 2010, 2013, Red Hat, Inc. * Copyright (C) 2010, Blue Swirl blauwir...@gmail.com + * Copyright (C) 2009, Anthony Liguori aligu...@us.ibm.com * * Author: * Laszlo Ersek ler...@redhat.com @@ -124,11 +125,6 @@ static TYPE raw_create(void) return bdrv_create_file(); } -static const char *raw_format_name(void) -{ -return raw; -} - static int raw_open(BlockDriverState *bs) { bs-sg = bs-file-sg; @@ -146,3 +142,35 @@ static int raw_probe(void) */ return 1; } + +static BlockDriver bdrv_raw = { +.format_name = raw, +.bdrv_probe = raw_probe, +.bdrv_reopen_prepare = raw_reopen_prepare, +.bdrv_open= raw_open, +.bdrv_close = raw_close, +.bdrv_create = raw_create, +.bdrv_co_readv= raw_co_readv, +.bdrv_co_writev = raw_co_writev, +.bdrv_co_write_zeroes = raw_co_write_zeroes, +.bdrv_co_discard = raw_co_discard, +.bdrv_co_is_allocated = raw_co_is_allocated, +.bdrv_truncate= raw_truncate, +.bdrv_getlength = raw_getlength, +.bdrv_get_info= raw_get_info, +.bdrv_is_inserted = raw_is_inserted, +.bdrv_media_changed = raw_media_changed, +.bdrv_eject = raw_eject, +.bdrv_lock_medium = raw_lock_medium, +.bdrv_ioctl = raw_ioctl, +.bdrv_aio_ioctl = raw_aio_ioctl, +.create_options = raw_create_options[0], +.bdrv_has_zero_init = raw_has_zero_init +}; + +static void bdrv_raw_init(void) +{ +bdrv_register(bdrv_raw); +} + +block_init(bdrv_raw_init); -- 1.8.1.4
[Qemu-devel] [PULL v2 18/26] qemu-iotests: Snapshotting zero clusters
From: Max Reitz mre...@redhat.com This test creates an image with unallocated zero clusters, then creates a snapshot. Afterwards, there should be neither any errors nor leaks. Signed-off-by: Max Reitz mre...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- tests/qemu-iotests/062 | 64 ++ tests/qemu-iotests/062.out | 9 +++ tests/qemu-iotests/group | 1 + 3 files changed, 74 insertions(+) create mode 100755 tests/qemu-iotests/062 create mode 100644 tests/qemu-iotests/062.out diff --git a/tests/qemu-iotests/062 b/tests/qemu-iotests/062 new file mode 100755 index 000..0511246 --- /dev/null +++ b/tests/qemu-iotests/062 @@ -0,0 +1,64 @@ +#!/bin/bash +# +# Test case for snapshotting images with unallocated zero clusters in +# qcow2 +# +# Copyright (C) 2013 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# + +# creator +owner=mre...@redhat.com + +seq=`basename $0` +echo QA output created by $seq + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap _cleanup; exit \$status 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +# This tests qocw2-specific low-level functionality +_supported_fmt qcow2 +_supported_proto generic +_supported_os Linux + +IMGOPTS=compat=1.1 +IMG_SIZE=64M + +echo +echo === Testing snapshotting an image with zero clusters === +echo +_make_test_img $IMG_SIZE +# Write some zero clusters +$QEMU_IO -c write -z 0 256k $TEST_IMG | _filter_qemu_io +# Create a snapshot +$QEMU_IMG snapshot -c foo $TEST_IMG +# Check the image (there shouldn't be any errors or leaks) +_check_test_img + +# success, all done +echo *** done +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/062.out b/tests/qemu-iotests/062.out new file mode 100644 index 000..442d761 --- /dev/null +++ b/tests/qemu-iotests/062.out @@ -0,0 +1,9 @@ +QA output created by 062 + +=== Testing snapshotting an image with zero clusters === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +wrote 262144/262144 bytes at offset 0 +256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +No errors were found on the image. +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 93ace2e..fb13792 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -64,3 +64,4 @@ 055 rw auto 056 rw auto backing 059 rw auto +062 rw auto -- 1.8.1.4
[Qemu-devel] [PULL v2 16/26] option: Add assigned flag to QEMUOptionParameter
From: Max Reitz mre...@redhat.com Adds an assigned flag to QEMUOptionParameter which is cleared at the beginning of parse_option_parameters and set on (successful) set_option_parameter and set_option_parameter_int. Signed-off-by: Max Reitz mre...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- include/qemu/option.h | 1 + util/qemu-option.c| 9 + 2 files changed, 10 insertions(+) diff --git a/include/qemu/option.h b/include/qemu/option.h index 7a58e47..63db4cc 100644 --- a/include/qemu/option.h +++ b/include/qemu/option.h @@ -46,6 +46,7 @@ typedef struct QEMUOptionParameter { char* s; } value; const char *help; +bool assigned; } QEMUOptionParameter; diff --git a/util/qemu-option.c b/util/qemu-option.c index 4ebdc4c..e0844a9 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -275,6 +275,8 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name, return -1; } +list-assigned = true; + return 0; } @@ -306,6 +308,8 @@ int set_option_parameter_int(QEMUOptionParameter *list, const char *name, return -1; } +list-assigned = true; + return 0; } @@ -397,6 +401,7 @@ QEMUOptionParameter *parse_option_parameters(const char *param, char value[256]; char *param_delim, *value_delim; char next_delim; +int i; if (list == NULL) { return NULL; @@ -406,6 +411,10 @@ QEMUOptionParameter *parse_option_parameters(const char *param, dest = allocated = append_option_parameters(NULL, list); } +for (i = 0; dest[i].name; i++) { +dest[i].assigned = false; +} + while (*param) { // Find parameter name and value in the string -- 1.8.1.4
[Qemu-devel] [PULL v2 21/26] qcow2: Employ metadata overlap checks
From: Max Reitz mre...@redhat.com The pre-write overlap check function is now called before most of the qcow2 writes (aborting it on collision or other error). Signed-off-by: Max Reitz mre...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/qcow2-cache.c| 17 + block/qcow2-cluster.c | 21 + block/qcow2-snapshot.c | 22 ++ block/qcow2.c | 26 ++ 4 files changed, 86 insertions(+) diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c index 2f3114e..7bcae09 100644 --- a/block/qcow2-cache.c +++ b/block/qcow2-cache.c @@ -115,6 +115,23 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i) } if (c == s-refcount_block_cache) { +ret = qcow2_pre_write_overlap_check(bs, +QCOW2_OL_DEFAULT ~QCOW2_OL_REFCOUNT_BLOCK, +c-entries[i].offset, s-cluster_size); +} else if (c == s-l2_table_cache) { +ret = qcow2_pre_write_overlap_check(bs, +QCOW2_OL_DEFAULT ~QCOW2_OL_ACTIVE_L2, +c-entries[i].offset, s-cluster_size); +} else { +ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, +c-entries[i].offset, s-cluster_size); +} + +if (ret 0) { +return ret; +} + +if (c == s-refcount_block_cache) { BLKDBG_EVENT(bs-file, BLKDBG_REFBLOCK_UPDATE_PART); } else if (c == s-l2_table_cache) { BLKDBG_EVENT(bs-file, BLKDBG_L2_UPDATE); diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index cca76d4..7c248aa 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -80,6 +80,14 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, goto fail; } +/* the L1 position has not yet been updated, so these clusters must + * indeed be completely free */ +ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, +new_l1_table_offset, new_l1_size2); +if (ret 0) { +goto fail; +} + BLKDBG_EVENT(bs-file, BLKDBG_L1_GROW_WRITE_TABLE); for(i = 0; i s-l1_size; i++) new_l1_table[i] = cpu_to_be64(new_l1_table[i]); @@ -149,6 +157,13 @@ static int write_l1_entry(BlockDriverState *bs, int l1_index) buf[i] = cpu_to_be64(s-l1_table[l1_start_index + i]); } +ret = qcow2_pre_write_overlap_check(bs, +QCOW2_OL_DEFAULT ~QCOW2_OL_ACTIVE_L1, +s-l1_table_offset + 8 * l1_start_index, sizeof(buf)); +if (ret 0) { +return ret; +} + BLKDBG_EVENT(bs-file, BLKDBG_L1_UPDATE); ret = bdrv_pwrite_sync(bs-file, s-l1_table_offset + 8 * l1_start_index, buf, sizeof(buf)); @@ -368,6 +383,12 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs, s-aes_encrypt_key); } +ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, +cluster_offset + n_start * BDRV_SECTOR_SIZE, n * BDRV_SECTOR_SIZE); +if (ret 0) { +goto out; +} + BLKDBG_EVENT(bs-file, BLKDBG_COW_WRITE); ret = bdrv_co_writev(bs-file, (cluster_offset 9) + n_start, n, qiov); if (ret 0) { diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 0caac90..e7e6013 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -189,6 +189,15 @@ static int qcow2_write_snapshots(BlockDriverState *bs) return ret; } +/* The snapshot list position has not yet been updated, so these clusters + * must indeed be completely free */ +ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, offset, +s-snapshots_size); +if (ret 0) { +return ret; +} + + /* Write all snapshots to the new list */ for(i = 0; i s-nb_snapshots; i++) { sn = s-snapshots + i; @@ -363,6 +372,12 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) l1_table[i] = cpu_to_be64(s-l1_table[i]); } +ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, +sn-l1_table_offset, s-l1_size * sizeof(uint64_t)); +if (ret 0) { +goto fail; +} + ret = bdrv_pwrite(bs-file, sn-l1_table_offset, l1_table, s-l1_size * sizeof(uint64_t)); if (ret 0) { @@ -475,6 +490,13 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) goto fail; } +ret = qcow2_pre_write_overlap_check(bs, +QCOW2_OL_DEFAULT ~QCOW2_OL_ACTIVE_L1, +s-l1_table_offset, cur_l1_bytes); +if (ret 0) { +goto fail; +} + ret = bdrv_pwrite_sync(bs-file, s-l1_table_offset, sn_l1_table, cur_l1_bytes); if (ret 0) { diff --git a/block/qcow2.c b/block/qcow2.c index fe91568..05e002d 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -624,6 +624,8 @@ static int qcow2_open(BlockDriverState *bs, QDict
[Qemu-devel] [PULL v2 22/26] qcow2-refcount: Move OFLAG_COPIED checks
From: Max Reitz mre...@redhat.com Move the OFLAG_COPIED checks out of check_refcounts_l1 and check_refcounts_l2 and after the actual refcount checks/fixes (since the refcounts might actually change there). Signed-off-by: Max Reitz mre...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/qcow2-refcount.c | 115 +++-- 1 file changed, 82 insertions(+), 33 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 8ee2f13..aa4b98d 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1053,7 +1053,7 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, BDRVQcowState *s = bs-opaque; uint64_t *l2_table, l2_entry; uint64_t next_contiguous_offset = 0; -int i, l2_size, nb_csectors, refcount; +int i, l2_size, nb_csectors; /* Read L2 table from disk */ l2_size = s-l2_size * sizeof(uint64_t); @@ -1105,23 +1105,8 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, case QCOW2_CLUSTER_NORMAL: { -/* QCOW_OFLAG_COPIED must be set iff refcount == 1 */ uint64_t offset = l2_entry L2E_OFFSET_MASK; -if (flags CHECK_OFLAG_COPIED) { -refcount = get_refcount(bs, offset s-cluster_bits); -if (refcount 0) { -fprintf(stderr, Can't get refcount for offset % -PRIx64 : %s\n, l2_entry, strerror(-refcount)); -goto fail; -} -if ((refcount == 1) != ((l2_entry QCOW_OFLAG_COPIED) != 0)) { -fprintf(stderr, ERROR OFLAG_COPIED: offset=% -PRIx64 refcount=%d\n, l2_entry, refcount); -res-corruptions++; -} -} - if (flags CHECK_FRAG_INFO) { res-bfi.allocated_clusters++; if (next_contiguous_offset @@ -1178,7 +1163,7 @@ static int check_refcounts_l1(BlockDriverState *bs, { BDRVQcowState *s = bs-opaque; uint64_t *l1_table, l2_offset, l1_size2; -int i, refcount, ret; +int i, ret; l1_size2 = l1_size * sizeof(uint64_t); @@ -1202,22 +1187,6 @@ static int check_refcounts_l1(BlockDriverState *bs, for(i = 0; i l1_size; i++) { l2_offset = l1_table[i]; if (l2_offset) { -/* QCOW_OFLAG_COPIED must be set iff refcount == 1 */ -if (flags CHECK_OFLAG_COPIED) { -refcount = get_refcount(bs, (l2_offset ~QCOW_OFLAG_COPIED) - s-cluster_bits); -if (refcount 0) { -fprintf(stderr, Can't get refcount for l2_offset % -PRIx64 : %s\n, l2_offset, strerror(-refcount)); -goto fail; -} -if ((refcount == 1) != ((l2_offset QCOW_OFLAG_COPIED) != 0)) { -fprintf(stderr, ERROR OFLAG_COPIED: l2_offset=% PRIx64 - refcount=%d\n, l2_offset, refcount); -res-corruptions++; -} -} - /* Mark L2 table as used */ l2_offset = L1E_OFFSET_MASK; inc_refcounts(bs, res, refcount_table, refcount_table_size, @@ -1249,6 +1218,80 @@ fail: } /* + * Checks the OFLAG_COPIED flag for all L1 and L2 entries. + * + * This function does not print an error message nor does it increment + * check_errors if get_refcount fails (this is because such an error will have + * been already detected and sufficiently signaled by the calling function + * (qcow2_check_refcounts) by the time this function is called). + */ +static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) +{ +BDRVQcowState *s = bs-opaque; +uint64_t *l2_table = qemu_blockalign(bs, s-cluster_size); +int ret; +int refcount; +int i, j; + +for (i = 0; i s-l1_size; i++) { +uint64_t l1_entry = s-l1_table[i]; +uint64_t l2_offset = l1_entry L1E_OFFSET_MASK; + +if (!l2_offset) { +continue; +} + +refcount = get_refcount(bs, l2_offset s-cluster_bits); +if (refcount 0) { +/* don't print message nor increment check_errors */ +continue; +} +if ((refcount == 1) != ((l1_entry QCOW_OFLAG_COPIED) != 0)) { +fprintf(stderr, ERROR OFLAG_COPIED L2 cluster: l1_index=%d +l1_entry=% PRIx64 refcount=%d\n, +i, l1_entry, refcount); +res-corruptions++; +} + +ret = bdrv_pread(bs-file, l2_offset, l2_table, + s-l2_size * sizeof(uint64_t)); +if (ret 0) { +fprintf(stderr, ERROR: Could not read L2 table: %s\n, +strerror(-ret)); +res-check_errors++; +goto fail; +} + +for (j = 0; j s-l2_size; j++) { +
[Qemu-devel] [PULL v2 26/26] qemu-iotests: Overlapping cluster allocations
From: Max Reitz mre...@redhat.com A new test on corrupted images with overlapping cluster allocations. Signed-off-by: Max Reitz mre...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- tests/qemu-iotests/060 | 111 + tests/qemu-iotests/060.out | 44 ++ tests/qemu-iotests/group | 1 + 3 files changed, 156 insertions(+) create mode 100755 tests/qemu-iotests/060 create mode 100644 tests/qemu-iotests/060.out diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 new file mode 100755 index 000..65bb09f --- /dev/null +++ b/tests/qemu-iotests/060 @@ -0,0 +1,111 @@ +#!/bin/bash +# +# Test case for image corruption (overlapping data structures) in qcow2 +# +# Copyright (C) 2013 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# + +# creator +owner=mre...@redhat.com + +seq=`basename $0` +echo QA output created by $seq + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap _cleanup; exit \$status 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +# This tests qocw2-specific low-level functionality +_supported_fmt qcow2 +_supported_proto generic +_supported_os Linux + +rt_offset=65536 # 0x1 (XXX: just an assumption) +rb_offset=131072 # 0x2 (XXX: just an assumption) +l1_offset=196608 # 0x3 (XXX: just an assumption) +l2_offset=262144 # 0x4 (XXX: just an assumption) + +IMGOPTS=compat=1.1 + +echo +echo === Testing L2 reference into L1 === +echo +_make_test_img 64M +# Link first L1 entry (first L2 table) onto itself +# (Note the MSb in the L1 entry is set, ensuring the refcount is one - else any +# later write will result in a COW operation, effectively ruining this attempt +# on image corruption) +poke_file $TEST_IMG $l1_offset \x80\x00\x00\x00\x00\x03\x00\x00 +_check_test_img + +# The corrupt bit should not be set anyway +./qcow2.py $TEST_IMG dump-header | grep incompatible_features + +# Try to write something, thereby forcing the corrupt bit to be set +$QEMU_IO -c write -P 0x2a 0 512 $TEST_IMG | _filter_qemu_io + +# The corrupt bit must now be set +./qcow2.py $TEST_IMG dump-header | grep incompatible_features + +# Try to open the image R/W (which should fail) +$QEMU_IO -c read 0 512 $TEST_IMG 21 | _filter_qemu_io | sed -e s/can't open device .*$/can't open device/ + +# Try to open it RO (which should succeed) +$QEMU_IO -c read 0 512 -r $TEST_IMG | _filter_qemu_io + +# We could now try to fix the image, but this would probably fail (how should an +# L2 table linked onto the L1 table be fixed?) + +echo +echo === Testing cluster data reference into refcount block === +echo +_make_test_img 64M +# Allocate L2 table +truncate -s $(($l2_offset+65536)) $TEST_IMG +poke_file $TEST_IMG $l1_offset \x80\x00\x00\x00\x00\x04\x00\x00 +# Mark cluster as used +poke_file $TEST_IMG $(($rb_offset+8)) \x00\x01 +# Redirect new data cluster onto refcount block +poke_file $TEST_IMG $l2_offset \x80\x00\x00\x00\x00\x02\x00\x00 +_check_test_img +./qcow2.py $TEST_IMG dump-header | grep incompatible_features +$QEMU_IO -c write -P 0x2a 0 512 $TEST_IMG | _filter_qemu_io +./qcow2.py $TEST_IMG dump-header | grep incompatible_features + +# Try to fix it +_check_test_img -r all + +# The corrupt bit should be cleared +./qcow2.py $TEST_IMG dump-header | grep incompatible_features + +# Look if it's really really fixed +$QEMU_IO -c write -P 0x2a 0 512 $TEST_IMG | _filter_qemu_io +./qcow2.py $TEST_IMG dump-header | grep incompatible_features + +# success, all done +echo *** done +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out new file mode 100644 index 000..ca4583a --- /dev/null +++ b/tests/qemu-iotests/060.out @@ -0,0 +1,44 @@ +QA output created by 060 + +=== Testing L2 reference into L1 === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +ERROR cluster 3 refcount=1 reference=3 + +1 errors were found on the image. +Data may be corrupted, or further writes to the image may corrupt it. +incompatible_features 0x0 +qcow2: Preventing invalid write on metadata (overlaps with active L1 table); image marked as corrupt. +write failed: Input/output error +incompatible_features 0x2 +qcow2: Image is corrupt; cannot be opened read/write. +qemu-io: can't open device +no file
[Qemu-devel] [PULL v2 23/26] qcow2-refcount: Repair OFLAG_COPIED errors
From: Max Reitz mre...@redhat.com Since the OFLAG_COPIED checks are now executed after the refcounts have been repaired (if repairing), it is safe to assume that they are correct but the OFLAG_COPIED flag may be not. Therefore, if its value differs from what it should be (considering the according refcount), that discrepancy can be repaired by correctly setting (or clearing that flag. Signed-off-by: Max Reitz mre...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/qcow2-cluster.c | 4 ++-- block/qcow2-refcount.c | 58 -- block/qcow2.h | 1 + 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 7c248aa..2d5aa92 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -145,7 +145,7 @@ static int l2_load(BlockDriverState *bs, uint64_t l2_offset, * and we really don't want bdrv_pread to perform a read-modify-write) */ #define L1_ENTRIES_PER_SECTOR (512 / 8) -static int write_l1_entry(BlockDriverState *bs, int l1_index) +int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index) { BDRVQcowState *s = bs-opaque; uint64_t buf[L1_ENTRIES_PER_SECTOR]; @@ -254,7 +254,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) /* update the L1 entry */ trace_qcow2_l2_allocate_write_l1(bs, l1_index); s-l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED; -ret = write_l1_entry(bs, l1_index); +ret = qcow2_write_l1_entry(bs, l1_index); if (ret 0) { goto fail; } diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index aa4b98d..2276b6f 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1225,7 +1225,8 @@ fail: * been already detected and sufficiently signaled by the calling function * (qcow2_check_refcounts) by the time this function is called). */ -static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) +static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res, + BdrvCheckMode fix) { BDRVQcowState *s = bs-opaque; uint64_t *l2_table = qemu_blockalign(bs, s-cluster_size); @@ -1236,6 +1237,7 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) for (i = 0; i s-l1_size; i++) { uint64_t l1_entry = s-l1_table[i]; uint64_t l2_offset = l1_entry L1E_OFFSET_MASK; +bool l2_dirty = false; if (!l2_offset) { continue; @@ -1247,10 +1249,24 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) continue; } if ((refcount == 1) != ((l1_entry QCOW_OFLAG_COPIED) != 0)) { -fprintf(stderr, ERROR OFLAG_COPIED L2 cluster: l1_index=%d +fprintf(stderr, %s OFLAG_COPIED L2 cluster: l1_index=%d l1_entry=% PRIx64 refcount=%d\n, +fix BDRV_FIX_ERRORS ? Repairing : +ERROR, i, l1_entry, refcount); -res-corruptions++; +if (fix BDRV_FIX_ERRORS) { +s-l1_table[i] = refcount == 1 + ? l1_entry | QCOW_OFLAG_COPIED + : l1_entry ~QCOW_OFLAG_COPIED; +ret = qcow2_write_l1_entry(bs, i); +if (ret 0) { +res-check_errors++; +goto fail; +} +res-corruptions_fixed++; +} else { +res-corruptions++; +} } ret = bdrv_pread(bs-file, l2_offset, l2_table, @@ -1275,13 +1291,43 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) continue; } if ((refcount == 1) != ((l2_entry QCOW_OFLAG_COPIED) != 0)) { -fprintf(stderr, ERROR OFLAG_COPIED data cluster: +fprintf(stderr, %s OFLAG_COPIED data cluster: l2_entry=% PRIx64 refcount=%d\n, +fix BDRV_FIX_ERRORS ? Repairing : +ERROR, l2_entry, refcount); -res-corruptions++; +if (fix BDRV_FIX_ERRORS) { +l2_table[j] = cpu_to_be64(refcount == 1 +? l2_entry | QCOW_OFLAG_COPIED +: l2_entry ~QCOW_OFLAG_COPIED); +l2_dirty = true; +res-corruptions_fixed++; +} else { +res-corruptions++; +} } } } + +if (l2_dirty) { +ret = qcow2_pre_write_overlap_check(bs, +QCOW2_OL_DEFAULT ~QCOW2_OL_ACTIVE_L2, l2_offset, +
[Qemu-devel] [PULL v2 15/26] gluster: Abort on AIO completion failure
From: Bharata B Rao bhar...@linux.vnet.ibm.com Currently if gluster AIO callback thread fails to notify the QEMU thread about AIO completion, we try graceful recovery by marking the disk drive as inaccessible. This error recovery code is race-prone as found by Asias and Stefan. However as found out by Paolo, this kind of error is impossible and hence simplify the code that handles this error recovery. Signed-off-by: Bharata B Rao bhar...@linux.vnet.ibm.com Reviewed-by: Stefan Hajnoczi stefa...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/gluster.c | 15 ++- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/block/gluster.c b/block/gluster.c index 46f36f8..dbb03f4 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -427,20 +427,9 @@ static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg) /* * Gluster AIO callback thread failed to notify the waiting * QEMU thread about IO completion. - * - * Complete this IO request and make the disk inaccessible for - * subsequent reads and writes. */ -error_report(Gluster failed to notify QEMU about IO completion); - -qemu_mutex_lock_iothread(); /* We are in gluster thread context */ -acb-common.cb(acb-common.opaque, -EIO); -qemu_aio_release(acb); -close(s-fds[GLUSTER_FD_READ]); -close(s-fds[GLUSTER_FD_WRITE]); -qemu_aio_set_fd_handler(s-fds[GLUSTER_FD_READ], NULL, NULL, NULL); -bs-drv = NULL; /* Make the disk inaccessible */ -qemu_mutex_unlock_iothread(); +error_report(Gluster AIO completion failed: %s, strerror(errno)); +abort(); } } -- 1.8.1.4
[Qemu-devel] [PULL v2 17/26] qcow2-refcount: Snapshot update for zero clusters
From: Max Reitz mre...@redhat.com Account for all cluster types in qcow2_update_snapshot_refcounts; this prevents this function from updating the refcount of unallocated zero clusters which effectively led to wrong adjustments of the refcount of cluster 0 (the main qcow2 header). This in turn resulted in images with (unallocated) zero clusters having a cluster 0 refcount greater than one after creating a snapshot. Signed-off-by: Max Reitz mre...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/qcow2-refcount.c | 52 +- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 1244693..a61224a 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -861,11 +861,14 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, } for(j = 0; j s-l2_size; j++) { +uint64_t cluster_index; + offset = be64_to_cpu(l2_table[j]); -if (offset != 0) { -old_offset = offset; -offset = ~QCOW_OFLAG_COPIED; -if (offset QCOW_OFLAG_COMPRESSED) { +old_offset = offset; +offset = ~QCOW_OFLAG_COPIED; + +switch (qcow2_get_cluster_type(offset)) { +case QCOW2_CLUSTER_COMPRESSED: nb_csectors = ((offset s-csize_shift) s-csize_mask) + 1; if (addend != 0) { @@ -880,8 +883,16 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, } /* compressed clusters are never modified */ refcount = 2; -} else { -uint64_t cluster_index = (offset L2E_OFFSET_MASK) s-cluster_bits; +break; + +case QCOW2_CLUSTER_NORMAL: +case QCOW2_CLUSTER_ZERO: +cluster_index = (offset L2E_OFFSET_MASK) s-cluster_bits; +if (!cluster_index) { +/* unallocated */ +refcount = 0; +break; +} if (addend != 0) { refcount = update_cluster_refcount(bs, cluster_index, addend, QCOW2_DISCARD_SNAPSHOT); @@ -893,19 +904,26 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, ret = refcount; goto fail; } -} +break; -if (refcount == 1) { -offset |= QCOW_OFLAG_COPIED; -} -if (offset != old_offset) { -if (addend 0) { -qcow2_cache_set_dependency(bs, s-l2_table_cache, -s-refcount_block_cache); -} -l2_table[j] = cpu_to_be64(offset); -qcow2_cache_entry_mark_dirty(s-l2_table_cache, l2_table); +case QCOW2_CLUSTER_UNALLOCATED: +refcount = 0; +break; + +default: +abort(); +} + +if (refcount == 1) { +offset |= QCOW_OFLAG_COPIED; +} +if (offset != old_offset) { +if (addend 0) { +qcow2_cache_set_dependency(bs, s-l2_table_cache, +s-refcount_block_cache); } +l2_table[j] = cpu_to_be64(offset); +qcow2_cache_entry_mark_dirty(s-l2_table_cache, l2_table); } } -- 1.8.1.4
[Qemu-devel] [PULL v2 20/26] qcow2: Metadata overlap checks
From: Max Reitz mre...@redhat.com Two new functions are added; the first one checks a given range in the image file for overlaps with metadata (main header, L1 tables, L2 tables, refcount table and blocks). The second one should be used immediately before writing to the image file as it calls the first function and, upon collision, marks the image as corrupt and makes the BDS unusable, thereby preventing further access. Both functions take a bitmask argument specifying the structures which should be checked for overlaps, making it possible to also check metadata writes against colliding with other structures. Signed-off-by: Max Reitz mre...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/qcow2-refcount.c| 172 ++ block/qcow2.h | 39 +++ include/monitor/monitor.h | 1 + monitor.c | 1 + 4 files changed, 213 insertions(+) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index a61224a..8ee2f13 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -25,6 +25,8 @@ #include qemu-common.h #include block/block_int.h #include block/qcow2.h +#include qemu/range.h +#include qapi/qmp/types.h static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size); static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, @@ -1390,3 +1392,173 @@ fail: return ret; } +#define overlaps_with(ofs, sz) \ +ranges_overlap(offset, size, ofs, sz) + +/* + * Checks if the given offset into the image file is actually free to use by + * looking for overlaps with important metadata sections (L1/L2 tables etc.), + * i.e. a sanity check without relying on the refcount tables. + * + * The chk parameter specifies exactly what checks to perform (being a bitmask + * of QCow2MetadataOverlap values). + * + * Returns: + * - 0 if writing to this offset will not affect the mentioned metadata + * - a positive QCow2MetadataOverlap value indicating one overlapping section + * - a negative value (-errno) indicating an error while performing a check, + * e.g. when bdrv_read failed on QCOW2_OL_INACTIVE_L2 + */ +int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset, + int64_t size) +{ +BDRVQcowState *s = bs-opaque; +int i, j; + +if (!size) { +return 0; +} + +if (chk QCOW2_OL_MAIN_HEADER) { +if (offset s-cluster_size) { +return QCOW2_OL_MAIN_HEADER; +} +} + +/* align range to test to cluster boundaries */ +size = align_offset(offset_into_cluster(s, offset) + size, s-cluster_size); +offset = start_of_cluster(s, offset); + +if ((chk QCOW2_OL_ACTIVE_L1) s-l1_size) { +if (overlaps_with(s-l1_table_offset, s-l1_size * sizeof(uint64_t))) { +return QCOW2_OL_ACTIVE_L1; +} +} + +if ((chk QCOW2_OL_REFCOUNT_TABLE) s-refcount_table_size) { +if (overlaps_with(s-refcount_table_offset, +s-refcount_table_size * sizeof(uint64_t))) { +return QCOW2_OL_REFCOUNT_TABLE; +} +} + +if ((chk QCOW2_OL_SNAPSHOT_TABLE) s-snapshots_size) { +if (overlaps_with(s-snapshots_offset, s-snapshots_size)) { +return QCOW2_OL_SNAPSHOT_TABLE; +} +} + +if ((chk QCOW2_OL_INACTIVE_L1) s-snapshots) { +for (i = 0; i s-nb_snapshots; i++) { +if (s-snapshots[i].l1_size +overlaps_with(s-snapshots[i].l1_table_offset, +s-snapshots[i].l1_size * sizeof(uint64_t))) { +return QCOW2_OL_INACTIVE_L1; +} +} +} + +if ((chk QCOW2_OL_ACTIVE_L2) s-l1_table) { +for (i = 0; i s-l1_size; i++) { +if ((s-l1_table[i] L1E_OFFSET_MASK) +overlaps_with(s-l1_table[i] L1E_OFFSET_MASK, +s-cluster_size)) { +return QCOW2_OL_ACTIVE_L2; +} +} +} + +if ((chk QCOW2_OL_REFCOUNT_BLOCK) s-refcount_table) { +for (i = 0; i s-refcount_table_size; i++) { +if ((s-refcount_table[i] REFT_OFFSET_MASK) +overlaps_with(s-refcount_table[i] REFT_OFFSET_MASK, +s-cluster_size)) { +return QCOW2_OL_REFCOUNT_BLOCK; +} +} +} + +if ((chk QCOW2_OL_INACTIVE_L2) s-snapshots) { +for (i = 0; i s-nb_snapshots; i++) { +uint64_t l1_ofs = s-snapshots[i].l1_table_offset; +uint32_t l1_sz = s-snapshots[i].l1_size; +uint64_t *l1 = g_malloc(l1_sz * sizeof(uint64_t)); +int ret; + +ret = bdrv_read(bs-file, l1_ofs / BDRV_SECTOR_SIZE, (uint8_t *)l1, +l1_sz * sizeof(uint64_t) / BDRV_SECTOR_SIZE); + +if (ret 0) { +g_free(l1); +return ret; +} + +for (j = 0; j l1_sz; j++) { +
[Qemu-devel] [PATCH 1/4] monitor: introduce monitor_read_console
This patch introduces monitor_read_console(), which will drop into interactive mode with chardev ringbuf backend, and install a readline handler. When the handler is invoked, the given data will be written to ringbuf backend. Signed-off-by: Lei Li li...@linux.vnet.ibm.com --- include/monitor/monitor.h |3 +++ monitor.c | 14 ++ 2 files changed, 17 insertions(+), 0 deletions(-) diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index 1942cc4..e6a6f47 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -89,6 +89,9 @@ ReadLineState *monitor_get_rs(Monitor *mon); int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, void *opaque); +int monitor_read_console(Monitor *mon, const char *device, + ReadLineFunc *readline_func, void *opaque); + int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret); int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret); diff --git a/monitor.c b/monitor.c index 0aeaf6c..531095e 100644 --- a/monitor.c +++ b/monitor.c @@ -263,6 +263,20 @@ int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, } } +int monitor_read_console(Monitor *mon, const char *device, + ReadLineFunc *readline_func, void *opaque) +{ +char prompt[60]; + +if (!mon-rs) { +return -1; +} + +snprintf(prompt, sizeof(prompt), %s: , device); +readline_start(mon-rs, prompt, 0, readline_func, opaque); +return 0; +} + static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond, void *opaque) { -- 1.7.7.6
[Qemu-devel] [PATCH 0/4 RFC] Introduce console for ringbuf backend
This patch series aims at adding HMP console feature for ringbuf backend. It behaves like a serial console, which drops user into an interactive mode with ringbuf backend and takes user back to the monitor by the 'ctrl-]' escape sequence. It would suspend the monitor, output the data that backed in the ringbuf backend to console first, and install a new readline handler to get input from console back into the ringbuf backend. Once escape sequence is detected, it will resume the monitor. This implementation is reworked based on Anthony's suggestions on the previous version: http://lists.gnu.org/archive/html/qemu-devel/2013-01/msg03888.html Suggestions and comments are very welcome! Lei Li (4): monitor: introduce monitor_read_console hmp: factor out ringbuf_print_help() qemu-char: export ringbuf_count hmp: add console support for ringbuf backend hmp-commands.hx | 21 +++ hmp.c | 141 + hmp.h |1 + include/monitor/monitor.h |3 + include/sysemu/char.h |2 + monitor.c | 14 + qemu-char.c |2 +- 7 files changed, 171 insertions(+), 13 deletions(-)
[Qemu-devel] [PULL v2 25/26] qcow2_check: Mark image consistent
From: Max Reitz mre...@redhat.com If no corruptions remain after an image repair (and no errors have been encountered), clear the corrupt flag in qcow2_check. Signed-off-by: Max Reitz mre...@redhat.com Signed-off-by: Kevin Wolf kw...@redhat.com --- block/qcow2.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/block/qcow2.c b/block/qcow2.c index 05e002d..4bc679a 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -312,7 +312,11 @@ static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result, } if (fix result-check_errors == 0 result-corruptions == 0) { -return qcow2_mark_clean(bs); +ret = qcow2_mark_clean(bs); +if (ret 0) { +return ret; +} +return qcow2_mark_consistent(bs); } return ret; } -- 1.8.1.4
[Qemu-devel] [PATCH 3/4] qemu-char: export ringbuf_count
Signed-off-by: Lei Li li...@linux.vnet.ibm.com --- include/sysemu/char.h |2 ++ qemu-char.c |2 +- 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/include/sysemu/char.h b/include/sysemu/char.h index 8053130..ed20fe3 100644 --- a/include/sysemu/char.h +++ b/include/sysemu/char.h @@ -288,6 +288,8 @@ void register_char_driver_qapi(const char *name, ChardevBackendKind kind, /* add an eventfd to the qemu devices that are polled */ CharDriverState *qemu_chr_open_eventfd(int eventfd); +size_t ringbuf_count(const CharDriverState *chr); + extern int term_escape_char; CharDriverState *qemu_char_get_next_serial(void); diff --git a/qemu-char.c b/qemu-char.c index 6259496..0d74fae 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2781,7 +2781,7 @@ typedef struct { uint8_t *cbuf; } RingBufCharDriver; -static size_t ringbuf_count(const CharDriverState *chr) +size_t ringbuf_count(const CharDriverState *chr) { const RingBufCharDriver *d = chr-opaque; -- 1.7.7.6
[Qemu-devel] [PATCH 2/4] hmp: factor out ringbuf_print_help()
Factor out ringbuf_print_help(), which will be called in hmp_read_ringbuf_cb() reading data that can be written with monitor_printf() to the console from ringbuf backend. Signed-off-by: Lei Li li...@linux.vnet.ibm.com --- hmp.c | 31 +++ 1 files changed, 19 insertions(+), 12 deletions(-) diff --git a/hmp.c b/hmp.c index fcca6ae..624ed6f 100644 --- a/hmp.c +++ b/hmp.c @@ -752,6 +752,24 @@ void hmp_pmemsave(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, errp); } +static void ringbuf_print_help(Monitor *mon, const char *data) +{ +int i; + +for (i = 0; data[i]; i++) { +unsigned char ch = data[i]; + +if (ch == '\\') { +monitor_printf(mon, ); +} else if ((ch 0x20 ch != '\n' ch != '\t') || ch == 0x7F) { +monitor_printf(mon, \\u%04X, ch); +} else { +monitor_printf(mon, %c, ch); +} + +} +} + void hmp_ringbuf_write(Monitor *mon, const QDict *qdict) { const char *chardev = qdict_get_str(qdict, device); @@ -769,7 +787,6 @@ void hmp_ringbuf_read(Monitor *mon, const QDict *qdict) const char *chardev = qdict_get_str(qdict, device); char *data; Error *errp = NULL; -int i; data = qmp_ringbuf_read(chardev, size, false, 0, errp); if (errp) { @@ -778,18 +795,8 @@ void hmp_ringbuf_read(Monitor *mon, const QDict *qdict) return; } -for (i = 0; data[i]; i++) { -unsigned char ch = data[i]; - -if (ch == '\\') { -monitor_printf(mon, ); -} else if ((ch 0x20 ch != '\n' ch != '\t') || ch == 0x7F) { -monitor_printf(mon, \\u%04X, ch); -} else { -monitor_printf(mon, %c, ch); -} +ringbuf_print_help(mon, data); -} monitor_printf(mon, \n); g_free(data); } -- 1.7.7.6
[Qemu-devel] [PATCH 4/4] hmp: add console support for ringbuf backend
This patch add console command which would suspend the monitor, output the data that backed in the ringbuf backend to console first, and install a new readline handler to get input back to the ringbuf backend. Take back to the monitor once escape sequence 'Ctrl-]' is detected. Signed-off-by: Lei Li li...@linux.vnet.ibm.com --- hmp-commands.hx | 21 ++ hmp.c | 110 +++ hmp.h |1 + 3 files changed, 132 insertions(+), 0 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 65b7f60..286d48d 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -876,6 +876,27 @@ stops because the size limit is reached. ETEXI { +.name = console, +.args_type = chardev:s, +.params = chardev, +.mhandler.cmd = hmp_console, +}, + +STEXI +@item console @var{device} +@findex console +Connect to the serial console from within the monitor, allow to read and +write data from/to ringbuf device @var{chardev}. Exit from the console and +return back to monitor by 'ctrl-]'. + +@example +(qemu) console foo +foo: data string... +@end example + +ETEXI + +{ .name = migrate, .args_type = detach:-d,blk:-b,inc:-i,uri:s, .params = [-d] [-b] [-i] uri, diff --git a/hmp.c b/hmp.c index 624ed6f..87613cc 100644 --- a/hmp.c +++ b/hmp.c @@ -1521,3 +1521,113 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, err); } + +typedef struct ConsoleStatus +{ +QEMUTimer *timer; +Monitor *mon; +CharDriverState *chr; +} ConsoleStatus; + +enum escape_char +{ +ESCAPE_CHAR_CTRL_GS = 0x1d /* ctrl-] is used for escape */ +}; + +static void hmp_read_ringbuf_cb(void *opaque) +{ +ConsoleStatus *status = opaque; +char *data; +int len; +Error *err = NULL; + +len = ringbuf_count(status-chr); +if (len) { +data = qmp_ringbuf_read(status-chr-label, len, 0, 0, err); +if (err) { +monitor_printf(status-mon, %s\n, error_get_pretty(err)); +error_free(err); +return; +} +ringbuf_print_help(status-mon, data); +monitor_flush(status-mon); +g_free(data); +timer_mod(status-timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000); +} else { +timer_del(status-timer); +} + +monitor_resume(status-mon); +g_free(status); +} + +static void hmp_write_console(Monitor *mon, void *opaque) +{ +CharDriverState *chr = opaque; +ConsoleStatus *status; + +status = g_malloc0(sizeof(*status)); +status-mon = mon; +status-chr = chr; +status-timer = timer_new_ms(QEMU_CLOCK_REALTIME, hmp_read_ringbuf_cb, + status); +timer_mod(status-timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME)); +} + +static void hmp_read_console(Monitor *mon, const char *data, + void *opaque) +{ +CharDriverState *chr = opaque; +enum escape_char console_escape = ESCAPE_CHAR_CTRL_GS; +int len = strlen(data) + 1; +char *tmp_buf = g_malloc0(len); +int i; +Error *err = NULL; + +for (i = 0; data[i]; i++) { +if (data[i] == console_escape) { +monitor_read_command(mon, 1); +goto out; +} +tmp_buf[i] = data[i]; +} + +qmp_ringbuf_write(chr-label, tmp_buf, 0, 0, err); +if (err) { +monitor_printf(mon, %s\n, error_get_pretty(err)); +monitor_read_command(mon, 1); +error_free(err); +goto out; +} + +out: +g_free(tmp_buf); +return; +} + +void hmp_console(Monitor *mon, const QDict *qdict) +{ +const char *device = qdict_get_str(qdict, chardev); +CharDriverState *chr; +Error *err = NULL; + +chr = qemu_chr_find(device); +if (!chr) { +error_set(err, QERR_DEVICE_NOT_FOUND, device); +goto out; +} + +if (monitor_suspend(mon)) { +monitor_printf(mon, Failed to suspend console\n); +return; +} + +hmp_write_console(mon, chr); + +if (monitor_read_console(mon, device, hmp_read_console, chr) 0) { +monitor_printf(mon, Connect to console %s failed\n, device); +} + +out: +hmp_handle_error(mon, err); +} diff --git a/hmp.h b/hmp.h index 6c3bdcd..d7fb52d 100644 --- a/hmp.h +++ b/hmp.h @@ -87,5 +87,6 @@ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict); void hmp_chardev_add(Monitor *mon, const QDict *qdict); void hmp_chardev_remove(Monitor *mon, const QDict *qdict); void hmp_qemu_io(Monitor *mon, const QDict *qdict); +void hmp_console(Monitor *mon, const QDict *qdict); #endif -- 1.7.7.6
Re: [Qemu-devel] [PATCH] seccomp: adding a second whitelist
On Fri, Aug 30, 2013 at 11:42:34AM -0400, Paul Moore wrote: On Friday, August 30, 2013 05:23:45 PM Stefan Hajnoczi wrote: On Fri, Aug 30, 2013 at 4:21 PM, Eduardo Otubo ot...@linux.vnet.ibm.com wrote: On 08/29/2013 05:34 AM, Stefan Hajnoczi wrote: On Wed, Aug 28, 2013 at 10:04:32PM -0300, Eduardo Otubo wrote: Now there's a second whitelist, right before the vcpu starts. The second whitelist is the same as the first one, except for exec() and select(). -netdev tap,downscript=/path/to/script requires exec() in the QEMU shutdown code path. Will this work with seccomp? I actually don't know, but I'll test that as well. Can you run a test with this patch and -netdev? I mean, if you're pointing that out you might have a scenario already setup, right? I'm not having much luck running qemu.git/master with CONFIG_SECCOMP on Fedora 19. The GTK UI opens but I don't see the guest's display. $ x86_64-softmmu/qemu-system-x86_64 [...GTK UI opens but QEMU is hung...] strace shows the process is hung somehow and ps says it's defunct although it never exited. $ sudo cat /proc/5912/stack [81061fda] do_exit+0x6ca/0xa20 [810ef090] __secure_computing+0xe0/0x240 [8101d722] syscall_trace_enter+0x172/0x230 [816478c8] tracesys+0x7e/0xe2 [] 0x Okay, so seccomp killed the process. $ sudo cat /proc/5912/syscall 29 0x0 0x1000 0x380 0x7fffbeb49380 0x0 0x0 0x7fffbeb495b8 0x7f6b72402657 $ git grep '\29\' arch/x86/include/generated/uapi/asm/unistd_64.h #define __NR_shmget 29 Now it needs syscall 30. I guess the whitelist is only designed for a specific invocation that you are testing? For future reference, it doesn't need to be that hard to identify when seccomp has killed a process. If you're running audit go ahead and check the audit log: # ausearch -m SECCOMP time-Fri Aug 30 11:37:46 2013 type=SECCOMP msg=audit(1377877066.414:64): auid=0 uid=0 gid=0 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 pid=3787 comm=20-live-basic_d sig=31 syscall=2 compat=0 ip=0x3a27ae6570 code=0x0 ... and notice the 'syscall' field which in this case happens to be '2'. If you have the 'scmp_sys_resolver' tool installed on your system (libseccomp- devel = 2.1.0 on Fedora) you can then resolve the syscall number: # scmp_sys_resolver 2 open It is also worth mentioning that while scmp_sys_resolver resolves syscalls for the native architecture by default, it can resolve for any of the architectures that libseccomp supports, see the manpage for details (currently: x86, x86_64, x32, and arm). Useful tips, thanks. Stefan
Re: [Qemu-devel] About coroutine inside qemu
On Fri, Aug 30, 2013 at 08:59:37PM +, Yaodong Yang wrote: When a new work thread, which is not inside coroutine, enter a coroutine(named as A), what happened to the work thread? Is it true that the work thread also become a coroutine, or it just stop? Later if the coroutine A call yield. what happened to the work thread? qemu_coroutine_enter() returns when the coroutine yields or terminates. Therefore the thread gives its control to the coroutine until it yields or terminates. Stefan
Re: [Qemu-devel] Capture SIGSEGV to track pc.ram page access
On Sun, Sep 01, 2013 at 11:38:34AM +0200, Thomas Knauth wrote: My question is where do I have to touch qemu to call my code for handling SIGSEGVs? Is this possible at all? Can anyone suggest alternative ways of tracking which pages of pc.ram are accessed? Maybe you can use the dirty page tracking infrastructure? memory_global_dirty_log_start() Stefan
[Qemu-devel] [PATCH V3 0/3] qemu-iotests: add test for fd passing via SCM rights
This series add test case for fd passing with unix socket at runtime. Since getfd and closefd interface will interact with monitor's data, so it will help to do regression test for monitor patches. Since python2 do not support sendmsg(), so a C helper program is added to do the job. v2: 1: add missing $ in the makefile rule. v3: Address Eric's comments: 1: typo fix, remove . in the end of error message, strick check argc as !=, use EXIT_SUCCESS and EXIT_FAILURE as exit values, strict error check for strtol() call. Address Luiz's comments: 1: change the helper program parameter as bin socket-fd file-path , the program open the file itself now, data parameter is removed and blank is always used as iov data, better usage tip message, folder the string parsing code into a function. 2: related change for helper program parameter change. 3: related change for helper program parameter change. Other: 1: remove LINK rule in makefile, remove fd checking code inside send_fd() since it is already checked before calling, add '' around %s for path and number string in error message. 2: renamed fd_bin to bin in send_fd_scm() to tip better, add '' around %s for path in error message. Wenchao Xia (3): 1 qemu-iotests: add unix socket help program 2 qemu-iotests: add infrastructure of fd passing via SCM 3 qemu-iotests: add tests for runtime fd passing via SCM rights QMP/qmp.py |6 ++ configure |2 +- tests/Makefile |3 +- tests/qemu-iotests/045 | 36 - tests/qemu-iotests/045.out |4 +- tests/qemu-iotests/check |1 + tests/qemu-iotests/iotests.py | 23 ++ tests/qemu-iotests/socket_scm_helper.c | 135 8 files changed, 205 insertions(+), 5 deletions(-) create mode 100644 tests/qemu-iotests/socket_scm_helper.c
[Qemu-devel] [PATCH V3 1/3] qemu-iotests: add unix socket help program
This program can do a sendmsg call to transfer fd with unix socket, which is not supported in python2. The built binary will not be deleted in clean, but it is a existing issue in ./tests, which should be solved in another patch. Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com --- configure |2 +- tests/Makefile |3 +- tests/qemu-iotests/socket_scm_helper.c | 135 3 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 tests/qemu-iotests/socket_scm_helper.c diff --git a/configure b/configure index 0a55c20..5080c38 100755 --- a/configure +++ b/configure @@ -4544,7 +4544,7 @@ if [ $dtc_internal = yes ]; then fi # build tree in object directory in case the source is not in the current directory -DIRS=tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-schema tests/tcg/xtensa +DIRS=tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-schema tests/tcg/xtensa tests/qemu-iotests DIRS=$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw DIRS=$DIRS roms/seabios roms/vgabios DIRS=$DIRS qapi-generated diff --git a/tests/Makefile b/tests/Makefile index baba9e9..c285805 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -172,6 +172,7 @@ tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y) tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y) tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y) +tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o # QTest rules @@ -250,7 +251,7 @@ check-report.html: check-report.xml # Other tests .PHONY: check-tests/qemu-iotests-quick.sh -check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF) qemu-io$(EXESUF) +check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF) qemu-io$(EXESUF) tests/qemu-iotests/socket_scm_helper$(EXESUF) $ .PHONY: check-tests/test-qapi.py diff --git a/tests/qemu-iotests/socket_scm_helper.c b/tests/qemu-iotests/socket_scm_helper.c new file mode 100644 index 000..0e2b285 --- /dev/null +++ b/tests/qemu-iotests/socket_scm_helper.c @@ -0,0 +1,135 @@ +/* + * SCM_RIGHTS with unix socket help program for test + * + * Copyright IBM, Inc. 2013 + * + * Authors: + * Wenchao Xiaxiaw...@linux.vnet.ibm.com + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + */ + +#include stdio.h +#include errno.h +#include sys/socket.h +#include sys/un.h +#include stdlib.h +#include sys/types.h +#include sys/stat.h +#include fcntl.h +#include unistd.h + +/* #define SOCKET_SCM_DEBUG */ + +/* + * @fd and @fd_to_send will not be checked for validation in this function, + * a blank will be sent as iov data to notify qemu. + */ +static int send_fd(int fd, int fd_to_send) +{ +struct msghdr msg; +struct iovec iov[1]; +int ret; +char control[CMSG_SPACE(sizeof(int))]; +struct cmsghdr *cmsg; + +memset(msg, 0, sizeof(msg)); +memset(control, 0, sizeof(control)); + +/* Send a blank to notify qemu */ +iov[0].iov_base = (void *) ; +iov[0].iov_len = 1; + +msg.msg_iov = iov; +msg.msg_iovlen = 1; + +msg.msg_control = control; +msg.msg_controllen = sizeof(control); + +cmsg = CMSG_FIRSTHDR(msg); + +cmsg-cmsg_len = CMSG_LEN(sizeof(int)); +cmsg-cmsg_level = SOL_SOCKET; +cmsg-cmsg_type = SCM_RIGHTS; +memcpy(CMSG_DATA(cmsg), fd, sizeof(int)); + +do { +ret = sendmsg(fd, msg, 0); +} while (ret 0 errno == EINTR); + +if (ret 0) { +fprintf(stderr, Failed to send msg, reason: %s\n, strerror(errno)); +} + +return ret; +} + +/* Convert string to fd number. */ +static int get_fd_num(const char *fd_str) +{ +int sock; +char *err; + +errno = 0; +sock = strtol(fd_str, err, 10); +if (errno) { +fprintf(stderr, Failed in strtol for socket fd, reason: %s\n, +strerror(errno)); +return -1; +} +if (!*fd_str || *err || sock 0) { +fprintf(stderr, bad numerical value for socket fd '%s'\n, fd_str); +return -1; +} + +return sock; +} + +/* + * To make things simple, the caller needs to specify: + * 1. socket fd. + * 2. path of the file to be sent. + */ +int main(int argc, char **argv, char **envp) +{ +int sock, fd, ret; + +#ifdef SOCKET_SCM_DEBUG +int i; +for (i = 0; i argc; i++) { +fprintf(stderr, Parameter %d: %s\n, i, argv[i]); +} +#endif + +if (argc != 3) { +fprintf(stderr, +Usage: %s socket-fd file-path \n, +argv[0]); +return EXIT_FAILURE; +} + + +sock = get_fd_num(argv[1]); +if (sock 0) { +return EXIT_FAILURE; +} + +/* Now only open a file in
[Qemu-devel] [PATCH V3 2/3] qemu-iotests: add infrastructure of fd passing via SCM
This patch make use of the compiled scm helper program to transfer fd via unix socket at runtime. Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com --- QMP/qmp.py|6 ++ tests/qemu-iotests/check |1 + tests/qemu-iotests/iotests.py | 23 +++ 3 files changed, 30 insertions(+), 0 deletions(-) diff --git a/QMP/qmp.py b/QMP/qmp.py index c551df1..074f09a 100644 --- a/QMP/qmp.py +++ b/QMP/qmp.py @@ -188,3 +188,9 @@ class QEMUMonitorProtocol: def settimeout(self, timeout): self.__sock.settimeout(timeout) + +def get_sock_fd(self): +return self.__sock.fileno() + +def is_scm_available(self): +return self.__sock.family == socket.AF_UNIX diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check index 74628ae..2f7f78e 100755 --- a/tests/qemu-iotests/check +++ b/tests/qemu-iotests/check @@ -164,6 +164,7 @@ QEMU_IO -- $QEMU_IO IMGFMT-- $FULL_IMGFMT_DETAILS IMGPROTO -- $FULL_IMGPROTO_DETAILS PLATFORM -- $FULL_HOST_DETAILS +SOCKET_SCM_HELPER -- $SOCKET_SCM_HELPER EOF #MKFS_OPTIONS -- $FULL_MKFS_OPTIONS diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 33ad0ec..d79cc56 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -38,6 +38,8 @@ imgfmt = os.environ.get('IMGFMT', 'raw') imgproto = os.environ.get('IMGPROTO', 'file') test_dir = os.environ.get('TEST_DIR', '/var/tmp') +socket_scm_helper = os.environ.get('SOCKET_SCM_HELPER', 'socket_scm_helper') + def qemu_img(*args): '''Run qemu-img and return the exit code''' devnull = open('/dev/null', 'r+') @@ -80,6 +82,12 @@ class VM(object): '-display', 'none', '-vga', 'none'] self._num_drives = 0 +#This can be used to add unused monitor +def add_monitor_telnet(self, ip, port): +args = 'tcp:%s:%d,server,nowait,telnet' % (ip, port) +self._args.append('-monitor') +self._args.append(args) + def add_drive(self, path, opts=''): '''Add a virtio-blk drive to the VM''' options = ['if=virtio', @@ -112,6 +120,21 @@ class VM(object): self._args.append(','.join(options)) return self +def send_fd_scm(self, fd_file_path): +#In iotest.py, the qmp should always use unix socket. +assert self._qmp.is_scm_available() +bin = socket_scm_helper +if os.path.exists(bin) == False: +print Scm help program does not present, path '%s'. % bin +return -1 +fd_param = [%s % bin, +%d % self._qmp.get_sock_fd(), +%s % fd_file_path] +devnull = open('/dev/null', 'rb') +p = subprocess.Popen(fd_param, stdin=devnull, stdout=sys.stdout, + stderr=sys.stderr) +return p.wait() + def launch(self): '''Launch the VM and establish a QMP connection''' devnull = open('/dev/null', 'rb') -- 1.7.1
[Qemu-devel] [PATCH V3 3/3] qemu-iotests: add tests for runtime fd passing via SCM rights
This case will test whether the monitor can receive fd at runtime. To verify better, additional monitor is created to see if qemu can handler two monitor instances correctly. Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com --- tests/qemu-iotests/045 | 36 +++- tests/qemu-iotests/045.out |4 ++-- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/tests/qemu-iotests/045 b/tests/qemu-iotests/045 index 2b6f1af..4381d8a 100755 --- a/tests/qemu-iotests/045 +++ b/tests/qemu-iotests/045 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Tests for fdsets. +# Tests for fdsets and getfd. # # Copyright (C) 2012 IBM Corp. # @@ -125,5 +125,39 @@ class TestFdSets(iotests.QMPTestCase): 'No file descriptor supplied via SCM_RIGHTS') self.vm.shutdown() +#Add fd at runtime, there are two ways: monitor related or fdset related +class TestSCMFd(iotests.QMPTestCase): +def setUp(self): +self.vm = iotests.VM() +qemu_img('create', '-f', iotests.imgfmt, image0, '128K') +#Add a unused monitor, to verify it works fine when two minitor present +self.vm.add_monitor_telnet(0,4445) +self.vm.launch() + +def tearDown(self): +self.vm.shutdown() +os.remove(image0) + +def _send_fd_by_SCM(self): +ret = self.vm.send_fd_scm(image0) +self.assertEqual(ret, 0, 'Failed to send fd with UNIX SCM') + +def test_add_fd(self): +self._send_fd_by_SCM() +result = self.vm.qmp('add-fd', fdset_id=2, opaque='image0:r') +self.assert_qmp(result, 'return/fdset-id', 2) + +def test_getfd(self): +self._send_fd_by_SCM() +result = self.vm.qmp('getfd', fdname='image0:r') +self.assert_qmp(result, 'return', {}) + +def test_closefd(self): +self._send_fd_by_SCM() +result = self.vm.qmp('getfd', fdname='image0:r') +self.assert_qmp(result, 'return', {}) +result = self.vm.qmp('closefd', fdname='image0:r') +self.assert_qmp(result, 'return', {}) + if __name__ == '__main__': iotests.main(supported_fmts=['raw']) diff --git a/tests/qemu-iotests/045.out b/tests/qemu-iotests/045.out index 3f8a935..dae404e 100644 --- a/tests/qemu-iotests/045.out +++ b/tests/qemu-iotests/045.out @@ -1,5 +1,5 @@ -.. +. -- -Ran 6 tests +Ran 9 tests OK -- 1.7.1
Re: [Qemu-devel] [PATCH 0/6][RFC] AArch64 support for Versatile Express using KVM
Alex, Am 28.06.2013 15:04, schrieb Andreas Färber: Am 28.06.2013 14:44, schrieb Peter Maydell: On 28 June 2013 13:20, Mian M. Hamayun m.hama...@virtualopensystems.com wrote: This patch series implements KVM support in QEMU for the ARMv8 Cortex A57 CPU. It depends on the previously submitted AArch64 Preparation Patchset V4, and uses as a base, the existing Versatile Express machine model and the already available KVM in-kernel GIC support. This rather overlaps with a bunch of work John Rigby has already done (though not yet published to the mailing lists): https://git.linaro.org/gitweb?p=people/pmaydell/qemu-aarch64.git;a=shortlog;h=refs/heads/kvm-aarch64-wip so now we need to reconcile the two trees. If you'd let us know you were doing this a bit earlier we could probably have coordinated something... I had been looking into that tree myself, and apart from John's Linux'ish ARM: prefixes rather than our usual target-arm: (part of which you forgot to fix before sending a PULL), I am really opposed to copying A15MPCore_priv for A57. I plan to post a cleanup for the A9 version the weekend, now that we have a more elaborate hw/ directory structure for headers. Also I would really prefer to have the is_aarch64() helper operate on ARMCPU rather than CPUARMState. QOM cast removal is underway to make that more efficient. Is there a 32-bit aarch64 register in ARMv8 to be accessed by TCG? If not, the field should be in ARMCPU and a bool rather than uint32_t. Care to comment on the latter? Regards, Andreas -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
[Qemu-devel] [PATCH] spice-core: Use g_strdup_printf instead of snprintf
Several places in spice-core.c were using either g_malloc+snprintf or snprintf+g_strdup to achieve the same result as g_strdup_printf. Signed-off-by: Christophe Fergeau cferg...@redhat.com --- ui/spice-core.c | 22 -- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/ui/spice-core.c b/ui/spice-core.c index bd7a248..01b9906 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -511,7 +511,6 @@ SpiceInfo *qmp_query_spice(Error **errp) int port, tls_port; const char *addr; SpiceInfo *info; -char version_string[20]; /* 12 = |255.255.255\0| is the max */ info = g_malloc0(sizeof(*info)); @@ -534,11 +533,10 @@ SpiceInfo *qmp_query_spice(Error **errp) info-host = g_strdup(addr ? addr : 0.0.0.0); info-has_compiled_version = true; -snprintf(version_string, sizeof(version_string), %d.%d.%d, - (SPICE_SERVER_VERSION 0xff) 16, - (SPICE_SERVER_VERSION 0xff00) 8, - SPICE_SERVER_VERSION 0xff); -info-compiled_version = g_strdup(version_string); +info-compiled_version = g_strdup_printf(%d.%d.%d, + (SPICE_SERVER_VERSION 0xff) 16, + (SPICE_SERVER_VERSION 0xff00) 8, + SPICE_SERVER_VERSION 0xff); if (port) { info-has_port = true; @@ -640,7 +638,7 @@ void qemu_spice_init(void) char *x509_key_file = NULL, *x509_cert_file = NULL, *x509_cacert_file = NULL; -int port, tls_port, len, addr_flags; +int port, tls_port, addr_flags; spice_image_compression_t compression; spice_wan_compression_t wan_compr; bool seamless_migration; @@ -671,30 +669,26 @@ void qemu_spice_init(void) if (NULL == x509_dir) { x509_dir = .; } -len = strlen(x509_dir) + 32; str = qemu_opt_get(opts, x509-key-file); if (str) { x509_key_file = g_strdup(str); } else { -x509_key_file = g_malloc(len); -snprintf(x509_key_file, len, %s/%s, x509_dir, X509_SERVER_KEY_FILE); +x509_key_file = g_strdup_printf(%s/%s, x509_dir, X509_SERVER_KEY_FILE); } str = qemu_opt_get(opts, x509-cert-file); if (str) { x509_cert_file = g_strdup(str); } else { -x509_cert_file = g_malloc(len); -snprintf(x509_cert_file, len, %s/%s, x509_dir, X509_SERVER_CERT_FILE); +x509_cert_file = g_strdup_printf(%s/%s, x509_dir, X509_SERVER_CERT_FILE); } str = qemu_opt_get(opts, x509-cacert-file); if (str) { x509_cacert_file = g_strdup(str); } else { -x509_cacert_file = g_malloc(len); -snprintf(x509_cacert_file, len, %s/%s, x509_dir, X509_CA_CERT_FILE); +x509_cacert_file = g_strdup_printf(%s/%s, x509_dir, X509_CA_CERT_FILE); } x509_key_password = qemu_opt_get(opts, x509-key-password); -- 1.8.3.1
Re: [Qemu-devel] [PATCH 0/6][RFC] AArch64 support for Versatile Express using KVM
On 2 September 2013 10:46, Andreas Färber afaer...@suse.de wrote: Am 28.06.2013 15:04, schrieb Andreas Färber: Is there a 32-bit aarch64 register in ARMv8 to be accessed by TCG? If not, the field should be in ARMCPU and a bool rather than uint32_t. Care to comment on the latter? I don't suppose the usermode emulation touches it, but the architectural state corresponding to that 'aarch64' field is the PSTATE nRW bit. I don't think this bit is directly accessible via a register access though (other PSTATE bits may be). thanks -- PMM
[Qemu-devel] [PATCH v4 1/5] block: Image file option amendment
This patch adds the amend option to qemu-img which allows changing image options on existing image files. It also adds the generic bdrv implementation which is basically just a wrapper for the image format specific function. Signed-off-by: Max Reitz mre...@redhat.com --- block.c | 8 + include/block/block.h | 2 ++ include/block/block_int.h | 3 ++ qemu-img-cmds.hx | 6 qemu-img.c| 84 +++ qemu-img.texi | 5 +++ 6 files changed, 108 insertions(+) diff --git a/block.c b/block.c index a387c1a..9c40a15 100644 --- a/block.c +++ b/block.c @@ -4674,3 +4674,11 @@ void bdrv_add_before_write_notifier(BlockDriverState *bs, { notifier_with_return_list_add(bs-before_write_notifiers, notifier); } + +int bdrv_amend_options(BlockDriverState *bs, QEMUOptionParameter *options) +{ +if (bs-drv-bdrv_amend_options == NULL) { +return -ENOTSUP; +} +return bs-drv-bdrv_amend_options(bs, options); +} diff --git a/include/block/block.h b/include/block/block.h index e6b391c..c284b4a 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -223,6 +223,8 @@ typedef enum { int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix); +int bdrv_amend_options(BlockDriverState *bs_new, QEMUOptionParameter *options); + /* async block I/O */ typedef void BlockDriverDirtyHandler(BlockDriverState *bs, int64_t sector, int sector_num); diff --git a/include/block/block_int.h b/include/block/block_int.h index 8012e25..3c93766 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -205,6 +205,9 @@ struct BlockDriver { int (*bdrv_check)(BlockDriverState* bs, BdrvCheckResult *result, BdrvCheckMode fix); +int (*bdrv_amend_options)(BlockDriverState *bs, +QEMUOptionParameter *options); + void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event); /* TODO Better pass a option string/QDict/QemuOpts to add any rule? */ diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx index 4ca7e95..5a066b5 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -61,5 +61,11 @@ DEF(resize, img_resize, resize [-q] filename [+ | -]size) STEXI @item resize [-q] @var{filename} [+ | -]@var{size} +ETEXI + +DEF(amend, img_amend, +amend [-q] [-f fmt] -o options filename) +STEXI +@item amend [-q] [-f @var{fmt}] -o @var{options} @var{filename} @end table ETEXI diff --git a/qemu-img.c b/qemu-img.c index b9a848d..7a8f064 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -2308,6 +2308,90 @@ out: return 0; } +static int img_amend(int argc, char **argv) +{ +int c, ret = 0; +char *options = NULL; +QEMUOptionParameter *create_options = NULL, *options_param = NULL; +const char *fmt = NULL, *filename; +bool quiet = false; +BlockDriverState *bs = NULL; + +for (;;) { +c = getopt(argc, argv, hqf:o:); +if (c == -1) { +break; +} + +switch (c) { +case 'h': +case '?': +help(); +break; +case 'o': +options = optarg; +break; +case 'f': +fmt = optarg; +break; +case 'q': +quiet = true; +break; +} +} + +if (optind != argc - 1) { +help(); +} + +if (!options) { +help(); +} + +filename = argv[argc - 1]; + +bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet); +if (!bs) { +error_report(Could not open image '%s', filename); +ret = -1; +goto out; +} + +fmt = bs-drv-format_name; + +if (is_help_option(options)) { +ret = print_block_option_help(filename, fmt); +goto out; +} + +create_options = append_option_parameters(create_options, +bs-drv-create_options); +options_param = parse_option_parameters(options, create_options, +options_param); +if (options_param == NULL) { +error_report(Invalid options for file format '%s', fmt); +ret = -1; +goto out; +} + +ret = bdrv_amend_options(bs, options_param); +if (ret 0) { +error_report(Error while amending options: %s, strerror(-ret)); +goto out; +} + +out: +if (bs) { +bdrv_delete(bs); +} +free_option_parameters(create_options); +free_option_parameters(options_param); +if (ret) { +return 1; +} +return 0; +} + static const img_cmd_t img_cmds[] = { #define DEF(option, callback, arg_string)\ { option, callback }, diff --git a/qemu-img.texi b/qemu-img.texi index 69f1bda..8697f23 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -282,6 +282,11 @@ sizes accordingly. Failure to do so will result in data loss! After using this command to grow a
[Qemu-devel] [PATCH v4 2/5] qcow2-cluster: Expand zero clusters
Add functionality for expanding zero clusters. This is necessary for downgrading the image version to one without zero cluster support. For non-backed images, this function may also just discard zero clusters instead of truly expanding them. Signed-off-by: Max Reitz mre...@redhat.com --- block/qcow2-cluster.c | 228 + block/qcow2-refcount.c | 29 --- block/qcow2.h | 5 ++ 3 files changed, 248 insertions(+), 14 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 2d5aa92..c90fb51 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1497,3 +1497,231 @@ fail: return ret; } + +/* + * Expands all zero clusters in a specific L1 table (or deallocates them, for + * non-backed non-pre-allocated zero clusters). + * + * expanded_clusters is a bitmap where every bit corresponds to one cluster in + * the image file; a bit gets set if the corresponding cluster has been used for + * zero expansion (i.e., has been filled with zeroes and is referenced from an + * L2 table). nb_clusters contains the total cluster count of the image file, + * i.e., the number of bits in expanded_clusters. + */ +static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, + int l1_size, uint8_t *expanded_clusters, + uint64_t nb_clusters) +{ +BDRVQcowState *s = bs-opaque; +bool is_active_l1 = (l1_table == s-l1_table); +uint64_t *l2_table = NULL; +int ret; +int i, j; + +if (!is_active_l1) { +/* inactive L2 tables require a buffer to be stored in when loading + * them from disk */ +l2_table = qemu_blockalign(bs, s-cluster_size); +} + +for (i = 0; i l1_size; i++) { +uint64_t l2_offset = l1_table[i] L1E_OFFSET_MASK; +bool l2_dirty = false; + +if (!l2_offset) { +/* unallocated */ +continue; +} + +if (is_active_l1) { +/* get active L2 tables from cache */ +ret = qcow2_cache_get(bs, s-l2_table_cache, l2_offset, +(void **)l2_table); +} else { +/* load inactive L2 tables from disk */ +ret = bdrv_read(bs-file, l2_offset / BDRV_SECTOR_SIZE, +(void *)l2_table, s-cluster_sectors); +} +if (ret 0) { +goto fail; +} + +for (j = 0; j s-l2_size; j++) { +uint64_t l2_entry = be64_to_cpu(l2_table[j]); +int64_t offset = l2_entry L2E_OFFSET_MASK, cluster_index; +int cluster_type = qcow2_get_cluster_type(l2_entry); + +if (cluster_type == QCOW2_CLUSTER_NORMAL) { +cluster_index = offset s-cluster_bits; +assert((cluster_index = 0) (cluster_index nb_clusters)); +if (expanded_clusters[cluster_index / 8] +(1 (cluster_index % 8))) { +/* Probably a shared L2 table; this cluster was a zero + * cluster which has been expanded, its refcount + * therefore most likely requires an update. */ +ret = qcow2_update_cluster_refcount(bs, cluster_index, 1, +QCOW2_DISCARD_NEVER); +if (ret 0) { +goto fail; +} +/* Since we just increased the refcount, the COPIED flag may + * no longer be set. */ +l2_table[j] = cpu_to_be64(l2_entry ~QCOW_OFLAG_COPIED); +l2_dirty = true; +} +continue; +} +else if (qcow2_get_cluster_type(l2_entry) != QCOW2_CLUSTER_ZERO) { +continue; +} + +if (!offset) { +/* not preallocated */ +if (!bs-backing_hd) { +/* not backed; therefore we can simply deallocate the + * cluster */ +l2_table[j] = 0; +l2_dirty = true; +continue; +} + +offset = qcow2_alloc_clusters(bs, s-cluster_size); +if (offset 0) { +ret = offset; +goto fail; +} +} + +ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, +offset, s-cluster_size); +if (ret 0) { +qcow2_free_clusters(bs, offset, s-cluster_size, +QCOW2_DISCARD_ALWAYS); +goto fail; +} + +ret = bdrv_write_zeroes(bs-file, offset / BDRV_SECTOR_SIZE, +s-cluster_sectors); +if (ret 0) { +qcow2_free_clusters(bs, offset,
[Qemu-devel] [PATCH v4 0/5] block/qcow2: Image file option amendment
This series adds support to qemu-img, block and qcow2 for amending image options on existing image files. Depends on: - option: Add assigned flag to QEMUOptionParameter - qcow2-refcount: Snapshot update for zero clusters (series, v3) - Add metadata overlap checks (series, v5) v4: - rebased on the metadata overlap check series (and fit to it) - split patch 2 into three distinct patches (2, 3 and 4) - extended test for zero expansion on backed and inactive backed clusters (and fixed according to the metadata overlap check series (i.e., adjusted header length)) - fixed zero expansion with shared L2 tables v3: - deallocate non-preallocated zero clusters on non-backed images instead of zero expanding them - qcow2 version downgrade: error out on refcount_order != 4 - implemented Eric's comments regarding the qemu-img amend and img_amend itself v2: - Generally implemented Kevin's comments, especially: - Zero cluster expansion for inactive L2 tables - Correct handling of preallocated zero clusters - More test cases Max Reitz (5): block: Image file option amendment qcow2-cluster: Expand zero clusters qcow2: Save refcount order in BDRVQcowState qcow2: Implement bdrv_amend_options qemu-iotest: qcow2 image option amendment block.c| 8 ++ block/qcow2-cluster.c | 228 + block/qcow2-refcount.c | 29 ++-- block/qcow2.c | 198 - block/qcow2.h | 6 + include/block/block.h | 2 + include/block/block_int.h | 3 + qemu-img-cmds.hx | 6 + qemu-img.c | 84 +++ qemu-img.texi | 5 + tests/qemu-iotests/061 | 178 +++ tests/qemu-iotests/061.out | 349 + tests/qemu-iotests/group | 1 + 13 files changed, 1082 insertions(+), 15 deletions(-) create mode 100755 tests/qemu-iotests/061 create mode 100644 tests/qemu-iotests/061.out -- 1.8.3.1
[Qemu-devel] [PATCH v4 3/5] qcow2: Save refcount order in BDRVQcowState
Save the image refcount order in BDRVQcowState. This will be relevant for future code supporting different refcount orders than four and also for code that needs to verify a certain refcount order for an opened image. Signed-off-by: Max Reitz mre...@redhat.com --- block/qcow2.c | 3 ++- block/qcow2.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/block/qcow2.c b/block/qcow2.c index aeb2ebb..28b104e 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -455,6 +455,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags) ret = -ENOTSUP; goto fail; } +s-refcount_order = header.refcount_order; if (header.cluster_bits MIN_CLUSTER_BITS || header.cluster_bits MAX_CLUSTER_BITS) { @@ -1133,7 +1134,7 @@ int qcow2_update_header(BlockDriverState *bs) .incompatible_features = cpu_to_be64(s-incompatible_features), .compatible_features= cpu_to_be64(s-compatible_features), .autoclear_features = cpu_to_be64(s-autoclear_features), -.refcount_order = cpu_to_be32(3 + REFCOUNT_SHIFT), +.refcount_order = cpu_to_be32(s-refcount_order), .header_length = cpu_to_be32(header_length), }; diff --git a/block/qcow2.h b/block/qcow2.h index 25176ac..b070709 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -199,6 +199,7 @@ typedef struct BDRVQcowState { int flags; int qcow_version; bool use_lazy_refcounts; +int refcount_order; bool discard_passthrough[QCOW2_DISCARD_MAX]; -- 1.8.3.1
[Qemu-devel] [PATCH v4 5/5] qemu-iotest: qcow2 image option amendment
Add tests for qemu-img amend on qcow2 image files. Signed-off-by: Max Reitz mre...@redhat.com --- tests/qemu-iotests/061 | 178 +++ tests/qemu-iotests/061.out | 349 + tests/qemu-iotests/group | 1 + 3 files changed, 528 insertions(+) create mode 100755 tests/qemu-iotests/061 create mode 100644 tests/qemu-iotests/061.out diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061 new file mode 100755 index 000..86404e6 --- /dev/null +++ b/tests/qemu-iotests/061 @@ -0,0 +1,178 @@ +#!/bin/bash +# +# Test case for image option amendment in qcow2. +# +# Copyright (C) 2013 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# + +# creator +owner=mre...@redhat.com + +seq=`basename $0` +echo QA output created by $seq + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap _cleanup; exit \$status 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +# This tests qocw2-specific low-level functionality +_supported_fmt qcow2 +_supported_proto generic +_supported_os Linux + +echo +echo === Testing version downgrade with zero expansion === +echo +IMGOPTS=compat=1.1,lazy_refcounts=on _make_test_img 64M +$QEMU_IO -c write -z 0 128k $TEST_IMG | _filter_qemu_io +./qcow2.py $TEST_IMG dump-header +$QEMU_IMG amend -o compat=0.10 $TEST_IMG +./qcow2.py $TEST_IMG dump-header +$QEMU_IO -c read -P 0 0 128k $TEST_IMG | _filter_qemu_io +_check_test_img + +echo +echo === Testing dirty version downgrade === +echo +IMGOPTS=compat=1.1,lazy_refcounts=on _make_test_img 64M +$QEMU_IO -c write -P 0x2a 0 128k -c flush -c abort $TEST_IMG | _filter_qemu_io +./qcow2.py $TEST_IMG dump-header +$QEMU_IMG amend -o compat=0.10 $TEST_IMG +./qcow2.py $TEST_IMG dump-header +$QEMU_IO -c read -P 0x2a 0 128k $TEST_IMG | _filter_qemu_io +_check_test_img + +echo +echo === Testing version downgrade with unknown compat/autoclear flags === +echo +IMGOPTS=compat=1.1 _make_test_img 64M +./qcow2.py $TEST_IMG set-feature-bit compatible 42 +./qcow2.py $TEST_IMG set-feature-bit autoclear 42 +./qcow2.py $TEST_IMG dump-header +$QEMU_IMG amend -o compat=0.10 $TEST_IMG +./qcow2.py $TEST_IMG dump-header +_check_test_img + +echo +echo === Testing version upgrade and resize === +echo +IMGOPTS=compat=0.10 _make_test_img 64M +$QEMU_IO -c write -P 0x2a 42M 64k $TEST_IMG | _filter_qemu_io +./qcow2.py $TEST_IMG dump-header +$QEMU_IMG amend -o compat=1.1,lazy_refcounts=on,size=128M $TEST_IMG +./qcow2.py $TEST_IMG dump-header +$QEMU_IO -c read -P 0x2a 42M 64k $TEST_IMG | _filter_qemu_io +_check_test_img + +echo +echo === Testing dirty lazy_refcounts=off === +echo +IMGOPTS=compat=1.1,lazy_refcounts=on _make_test_img 64M +$QEMU_IO -c write -P 0x2a 0 128k -c flush -c abort $TEST_IMG | _filter_qemu_io +./qcow2.py $TEST_IMG dump-header +$QEMU_IMG amend -o lazy_refcounts=off $TEST_IMG +./qcow2.py $TEST_IMG dump-header +$QEMU_IO -c read -P 0x2a 0 128k $TEST_IMG | _filter_qemu_io +_check_test_img + +echo +echo === Testing backing file === +echo +IMGOPTS=compat=1.1 _make_test_img 64M +IMGOPTS=compat=1.1 TEST_IMG=$TEST_IMG.base _make_test_img 64M +$QEMU_IO -c write -P 0x2a 0 128k $TEST_IMG.base | _filter_qemu_io +$QEMU_IO -c read -P 0 0 128k $TEST_IMG | _filter_qemu_io +$QEMU_IMG amend -o backing_file=$TEST_IMG.base,backing_fmt=qcow2 $TEST_IMG +$QEMU_IO -c read -P 0x2a 0 128k $TEST_IMG | _filter_qemu_io +_check_test_img + +echo +echo === Testing invalid configurations === +echo +IMGOPTS=compat=0.10 _make_test_img 64M +$QEMU_IMG amend -o lazy_refcounts=on $TEST_IMG +$QEMU_IMG amend -o compat=1.1 $TEST_IMG # actually valid +$QEMU_IMG amend -o compat=0.10,lazy_refcounts=on $TEST_IMG +$QEMU_IMG amend -o compat=0.42 $TEST_IMG +$QEMU_IMG amend -o foo=bar $TEST_IMG +$QEMU_IMG amend -o cluster_size=1k $TEST_IMG +$QEMU_IMG amend -o encryption=on $TEST_IMG +$QEMU_IMG amend -o preallocation=on $TEST_IMG + +echo +echo === Testing correct handling of unset value === +echo +IMGOPTS=compat=1.1,cluster_size=1k _make_test_img 64M +echo Should work: +$QEMU_IMG amend -o lazy_refcounts=on $TEST_IMG +echo Should not work: # Just to know which of these tests actually fails +$QEMU_IMG amend -o cluster_size=64k $TEST_IMG + +echo +echo === Testing zero expansion on inactive clusters === +echo +IMGOPTS=compat=1.1