Re: [Qemu-devel] [PATCH v3 1/6] RFC: Efficient VM backup for qemu
Dietmar Maurer diet...@proxmox.com writes: * Backup to a single archive file * Backup contain all data to restore VM (full backup) * Do not depend on storage type or image format * Avoid use of temporary storage * store sparse images efficiently It is customary to send a 0/6 cover letter for details like this, rather than slamming it into the first patch (git send-email --cover-letter). But how do I maintain the content of that cover-letter when it is not part of the git tree? Nothing stops you from committing it to your branch. The extra commit isn't sent out, of course. I guess people usually archive it in e-mail instead.
[Qemu-devel] [PATCH 28/38] target-ppc: Compute addition carry with setcond
Cc: Alexander Graf ag...@suse.de Signed-off-by: Richard Henderson r...@twiddle.net --- target-ppc/translate.c | 42 -- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 116cf12..fce261b 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -768,36 +768,26 @@ static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, static inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1, TCGv arg2, int sub) { -int l1 = gen_new_label(); +TCGv t0 = tcg_temp_new(), t1 = arg1, t2 = arg2; #if defined(TARGET_PPC64) if (!(ctx-sf_mode)) { -TCGv t0, t1; -t0 = tcg_temp_new(); -t1 = tcg_temp_new(); - -tcg_gen_ext32u_tl(t0, arg1); -tcg_gen_ext32u_tl(t1, arg2); -if (sub) { -tcg_gen_brcond_tl(TCG_COND_GTU, t0, t1, l1); -} else { -tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1); -} -tcg_gen_movi_tl(cpu_ca, 1); -gen_set_label(l1); -tcg_temp_free(t0); -tcg_temp_free(t1); -} else +t1 = t0; +tcg_gen_ext32u_tl(t1, arg1); +t2 = tcg_temp_new(); +tcg_gen_ext32u_tl(t2, arg2); +} #endif -{ -if (sub) { -tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1); -} else { -tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1); -} -tcg_gen_movi_tl(cpu_ca, 1); -gen_set_label(l1); + +tcg_gen_setcond_tl(sub ? TCG_COND_LEU : TCG_COND_LTU, t0, t1, t2); +tcg_gen_or_tl(cpu_ca, cpu_ca, t0); + +tcg_temp_free(t0); +#if defined(TARGET_PPC64) +if (!(ctx-sf_mode)) { +tcg_temp_free(t2); } +#endif } /* Common add function */ @@ -811,7 +801,7 @@ static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1, (!TCGV_EQUAL(ret,arg1) !TCGV_EQUAL(ret, arg2))) { t0 = ret; } else { -t0 = tcg_temp_local_new(); +t0 = tcg_temp_new(); } if (add_ca) { -- 1.8.1.2
[Qemu-devel] [PATCH 32/38] target-ppc: Compute mullwo without branches
Cc: Alexander Graf ag...@suse.de Signed-off-by: Richard Henderson r...@twiddle.net --- target-ppc/translate.c | 42 ++ 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 439..f886441 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -1036,35 +1036,21 @@ static void gen_mullw(DisasContext *ctx) /* mullwo mullwo. */ static void gen_mullwo(DisasContext *ctx) { -int l1; -TCGv_i64 t0, t1; +TCGv_i32 t0 = tcg_temp_new_i32(); +TCGv_i32 t1 = tcg_temp_new_i32(); -t0 = tcg_temp_new_i64(); -t1 = tcg_temp_new_i64(); -l1 = gen_new_label(); -/* Start with XER OV disabled, the most likely case */ -tcg_gen_movi_tl(cpu_ov, 0); -#if defined(TARGET_PPC64) -tcg_gen_ext32s_i64(t0, cpu_gpr[rA(ctx-opcode)]); -tcg_gen_ext32s_i64(t1, cpu_gpr[rB(ctx-opcode)]); -#else -tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx-opcode)]); -tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx-opcode)]); -#endif -tcg_gen_mul_i64(t0, t0, t1); -#if defined(TARGET_PPC64) -tcg_gen_ext32s_i64(cpu_gpr[rD(ctx-opcode)], t0); -tcg_gen_brcond_i64(TCG_COND_EQ, t0, cpu_gpr[rD(ctx-opcode)], l1); -#else -tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx-opcode)], t0); -tcg_gen_ext32s_i64(t1, t0); -tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1); -#endif -tcg_gen_movi_tl(cpu_ov, 1); -tcg_gen_movi_tl(cpu_so, 1); -gen_set_label(l1); -tcg_temp_free_i64(t0); -tcg_temp_free_i64(t1); +tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx-opcode)]); +tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx-opcode)]); +tcg_gen_muls2_i32(t0, t1, t0, t1); +tcg_gen_ext_i32_tl(cpu_gpr[rD(ctx-opcode)], t0); + +tcg_gen_sari_i32(t0, t0, 31); +tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t1); +tcg_gen_extu_i32_tl(cpu_ov, t0); +tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov); + +tcg_temp_free_i32(t0); +tcg_temp_free_i32(t1); if (unlikely(Rc(ctx-opcode) != 0)) gen_set_Rc0(ctx, cpu_gpr[rD(ctx-opcode)]); } -- 1.8.1.2
Re: [Qemu-devel] [PATCH v12 rebased 2/8] start vm after resetting it
On Thu, Feb 07, 2013 at 11:50:28PM -0200, Marcelo Tosatti wrote: On Wed, Jan 23, 2013 at 03:19:23PM +0800, Hu Tao wrote: From: Wen Congyang we...@cn.fujitsu.com The guest should run after resetting it, but it does not run if its old state is RUN_STATE_INTERNAL_ERROR or RUN_STATE_PAUSED. We don't set runstate to RUN_STATE_PAUSED when resetting the guest, so the runstate will be changed from RUN_STATE_INTERNAL_ERROR or RUN_STATE_PAUSED to RUN_STATE_RUNNING(not RUN_STATE_PAUSED). It appears the last hunk will automatically reset state from RUN_STATE_INTERNAL_ERROR to RUN_STATE_RUNNING ? Yes. I suppose the transition table allows, from RUN_STATE_INTERNAL_ERROR: monitor system_reset monitor cont To resume the machine? True. I think the purpose of this patch is to always reset and _run_ the guest by `system_reset', avoiding an additional `cont' following `system_reset'. Signed-off-by: Wen Congyang we...@cn.fujitsu.com --- include/block/block.h | 2 ++ qmp.c | 2 +- vl.c | 7 --- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/block/block.h b/include/block/block.h index ffd1936..5e82ccb 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -366,6 +366,8 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs); void bdrv_set_in_use(BlockDriverState *bs, int in_use); int bdrv_in_use(BlockDriverState *bs); +void iostatus_bdrv_it(void *opaque, BlockDriverState *bs); + #ifdef CONFIG_LINUX_AIO int raw_get_aio_fd(BlockDriverState *bs); #else diff --git a/qmp.c b/qmp.c index 55b056b..5f1bed1 100644 --- a/qmp.c +++ b/qmp.c @@ -130,7 +130,7 @@ SpiceInfo *qmp_query_spice(Error **errp) }; #endif -static void iostatus_bdrv_it(void *opaque, BlockDriverState *bs) +void iostatus_bdrv_it(void *opaque, BlockDriverState *bs) { bdrv_iostatus_reset(bs); } diff --git a/vl.c b/vl.c index b0bcf1e..1d2edaa 100644 --- a/vl.c +++ b/vl.c @@ -534,7 +534,7 @@ static const RunStateTransition runstate_transitions_def[] = { { RUN_STATE_INMIGRATE, RUN_STATE_RUNNING }, { RUN_STATE_INMIGRATE, RUN_STATE_PAUSED }, -{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED }, +{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_RUNNING }, { RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE }, { RUN_STATE_IO_ERROR, RUN_STATE_RUNNING }, @@ -569,7 +569,7 @@ static const RunStateTransition runstate_transitions_def[] = { { RUN_STATE_SAVE_VM, RUN_STATE_RUNNING }, -{ RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED }, +{ RUN_STATE_SHUTDOWN, RUN_STATE_RUNNING }, { RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE }, { RUN_STATE_DEBUG, RUN_STATE_SUSPENDED }, @@ -1951,7 +1951,8 @@ static bool main_loop_should_exit(void) resume_all_vcpus(); if (runstate_check(RUN_STATE_INTERNAL_ERROR) || runstate_check(RUN_STATE_SHUTDOWN)) { -runstate_set(RUN_STATE_PAUSED); +bdrv_iterate(iostatus_bdrv_it, NULL); +vm_start(); } } if (qemu_wakeup_requested()) { -- 1.8.0.1.240.ge8a1f5a -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- Regards, Hu Tao
Re: [Qemu-devel] [RFC PATCH 03/10] qemu-ga: Add an configure option to specify path to Windows VSS SDK
On 2013/02/19 9:15, mdroth wrote: On Fri, Feb 15, 2013 at 12:55:49PM +0900, Tomoki Sekiyama wrote: On 2013/02/15 9:47, mdroth wrote: [...] Hi Tomoki, Hi, Did you happen to run into this issue compiling the test program? [mdroth@vm qemu-build]$ ls ~/w/vsssdk/inc/win2003/ vdslun.hvsbackup.hvscoordint.idl vsmgmt.idl vsprov.idl vss.idlvsswprv.idl vdslun.idl vscoordint.h vsmgmt.hvsprov.hvss.h vsswprv.h vswriter.h [mdroth@vm qemu-build]$ cat test.c #define __MIDL_user_allocate_free_DEFINED__ #include inc/win2003/vss.h int main(void) { return VSS_CTX_BACKUP; } [mdroth@vm qemu-build]$ gcc -I ~/w/vsssdk/ -o test test.c In file included from test.c:2:0: /home/mdroth/w/vsssdk/inc/win2003/vss.h:25:17: fatal error: rpc.h: No such file or directory compilation terminated. I can't seem to locate any mingw or microsoft package that provides that. It's also not present anywhere on the Wine filesystem I installed the VSS SDK to. Hmm, I haven't seen this yet. I am testing this on Fedora 18 x86_64 host, and it provides package mingw32-headers.noarch or mingw64-headers.noarch which contains the rpc.h (filepath is /usr/x86_64-w64-mingw32/sys-root/mingw/include/rpc.h ) Thanks. I actually did have that header, but I was doing something silly (forgot to use cross-compiler for the test program). The configure issue I was hitting was also an error on my part (options with ~ weren't resolving to my home dir). I did end up missing ntverp.h however in vss-win32.h using Fedora 15. I made some progress trying the build without it however. Can you confirm all the headers in vss-win32.h are needed? Some of headers in vss-win32.h (nterp,h, rpc.h, rpcndr.h, etc) seems needed to build qemu-ga.exe in a native build environment(mingw on Windows). In my Fedora 18 environment, these don't cause errors, but it also succeeded to build even without the headers. I went ahead and put together an FC18 environment, but would be nice if we can get this building for older environments (if possible). I will try this with some of my old VMs and investigate which headers are really needed. Thanks, -- Tomoki Sekiyama
[Qemu-devel] [PATCH 08/38] tcg: Implement multiword addition helpers
Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/tcg-op.h | 82 1 file changed, 82 insertions(+) diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 97e0795..dac3b4e 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -2332,6 +2332,44 @@ static inline void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, #endif } +static inline void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al, +TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh) +{ +if (TCG_TARGET_HAS_add2_i32) { +tcg_gen_op6_i32(INDEX_op_add2_i32, rl, rh, al, ah, bl, bh); +/* Allow the optimizer room to replace add2 with two moves. */ +tcg_gen_op0(INDEX_op_nop); +} else { +TCGv_i64 t0 = tcg_temp_new_i64(); +TCGv_i64 t1 = tcg_temp_new_i64(); +tcg_gen_concat_i32_i64(t0, al, ah); +tcg_gen_concat_i32_i64(t1, bl, bh); +tcg_gen_add_i64(t0, t0, t1); +tcg_gen_extr_i64_i32(rl, rh, t0); +tcg_temp_free_i64(t0); +tcg_temp_free_i64(t1); +} +} + +static inline void tcg_gen_sub2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al, +TCGv_i32 ah, TCGv_i32 bl, TCGv_i32 bh) +{ +if (TCG_TARGET_HAS_sub2_i32) { +tcg_gen_op6_i32(INDEX_op_sub2_i32, rl, rh, al, ah, bl, bh); +/* Allow the optimizer room to replace sub2 with two moves. */ +tcg_gen_op0(INDEX_op_nop); +} else { +TCGv_i64 t0 = tcg_temp_new_i64(); +TCGv_i64 t1 = tcg_temp_new_i64(); +tcg_gen_concat_i32_i64(t0, al, ah); +tcg_gen_concat_i32_i64(t1, bl, bh); +tcg_gen_sub_i64(t0, t0, t1); +tcg_gen_extr_i64_i32(rl, rh, t0); +tcg_temp_free_i64(t0); +tcg_temp_free_i64(t1); +} +} + static inline void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2) { @@ -2370,6 +2408,46 @@ static inline void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, } } +static inline void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al, +TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh) +{ +if (TCG_TARGET_HAS_add2_i64) { +tcg_gen_op6_i64(INDEX_op_add2_i64, rl, rh, al, ah, bl, bh); +/* Allow the optimizer room to replace add2 with two moves. */ +tcg_gen_op0(INDEX_op_nop); +} else { +TCGv_i64 t0 = tcg_temp_new_i64(); +TCGv_i64 t1 = tcg_temp_new_i64(); +tcg_gen_add_i64(t0, al, bl); +tcg_gen_setcond_i64(TCG_COND_LTU, t1, t0, al); +tcg_gen_add_i64(rh, ah, bh); +tcg_gen_add_i64(rh, rh, t1); +tcg_gen_mov_i64(rl, t0); +tcg_temp_free_i64(t0); +tcg_temp_free_i64(t1); +} +} + +static inline void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al, +TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh) +{ +if (TCG_TARGET_HAS_sub2_i64) { +tcg_gen_op6_i64(INDEX_op_sub2_i64, rl, rh, al, ah, bl, bh); +/* Allow the optimizer room to replace sub2 with two moves. */ +tcg_gen_op0(INDEX_op_nop); +} else { +TCGv_i64 t0 = tcg_temp_new_i64(); +TCGv_i64 t1 = tcg_temp_new_i64(); +tcg_gen_sub_i64(t0, al, bl); +tcg_gen_setcond_i64(TCG_COND_LTU, t1, al, bl); +tcg_gen_sub_i64(rh, ah, bh); +tcg_gen_sub_i64(rh, rh, t1); +tcg_gen_mov_i64(rl, t0); +tcg_temp_free_i64(t0); +tcg_temp_free_i64(t1); +} +} + static inline void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) { @@ -2739,6 +2817,8 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) #define tcg_const_tl tcg_const_i64 #define tcg_const_local_tl tcg_const_local_i64 #define tcg_gen_movcond_tl tcg_gen_movcond_i64 +#define tcg_gen_add2_tl tcg_gen_add2_i64 +#define tcg_gen_sub2_tl tcg_gen_sub2_i64 #define tcg_gen_mulu2_tl tcg_gen_mulu2_i64 #define tcg_gen_muls2_tl tcg_gen_muls2_i64 #else @@ -2814,6 +2894,8 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) #define tcg_const_tl tcg_const_i32 #define tcg_const_local_tl tcg_const_local_i32 #define tcg_gen_movcond_tl tcg_gen_movcond_i32 +#define tcg_gen_add2_tl tcg_gen_add2_i32 +#define tcg_gen_sub2_tl tcg_gen_sub2_i32 #define tcg_gen_mulu2_tl tcg_gen_mulu2_i32 #define tcg_gen_muls2_tl tcg_gen_muls2_i32 #endif -- 1.8.1.2
Re: [Qemu-devel] [PATCH] machine: correct macro name for default boot_order
liguang lig.f...@cn.fujitsu.com writes: DEFAULT_MACHINE_OPTIONS is setting default boot_order, while QEMUMachine already has default_machine_opts to encapsulate some default options, so change it to DEFAULT_MACHINE_BOOT_ORDER. Right now, DEFAULT_MACHINE_OPTIONS contains just a .boot_order initializer. But that's not necessarily so; it could contain anything. Avik, Anthony, you wrote or reviewed the patch that added it, what do you think?
Re: [Qemu-devel] [PATCH 1/4] configure: Add --enable-migration-from-qemu-kvm
20.02.2013 02:39, Cole Robinson wrote: This switch will turn on all the migration compat bits needed to perform migration from qemu-kvm to qemu. It's just a stub for now. This compat will break incoming migration from qemu 1.3, but for distros where qemu-kvm was the only shipped package for years it's not a big loss (and I don't know any way to avoid it). Actually I think it is relatively easy to support migration from BOTH qemu and qemu-kvm. By adding a _runtime_ command-line switch (such as --qemu-kvm-compat, which has been already mentioned in other context), which modifies that migration stuff (machine definitions) in a reasonable way. It can be done based on this patchset I guess (when it will be polished and proven to work well). And after that is done, this configure option can go away. How do you guys think? Thanks! /mjt
[Qemu-devel] [PATCH v2] vga: fix byteswapping.
In case host and guest endianness differ the vga code first creates a shared surface (using qemu_create_displaysurface_from), then goes patch the surface format to indicate that the bytes must be swapped. The switch to pixman broke that hack as the format patching isn't propagated into the pixman image, so ui code using the pixman image directly (such as vnc) uses the wrong format. Fix that by adding a byteswap parameter to qemu_create_displaysurface_from, so we'll use the correct format when creating the surface (and the pixman image) and don't have to patch the format afterwards. [ v2: unbreak xen build ] Cc: qemu-sta...@nongnu.org Cc: mark.cave-ayl...@ilande.co.uk Cc: ag...@suse.de Signed-off-by: Gerd Hoffmann kra...@redhat.com --- hw/qxl-render.c |3 ++- hw/vga.c | 18 -- hw/vmware_vga.c |2 +- hw/xenfb.c |3 ++- include/ui/console.h |3 ++- ui/console.c |9 +++-- 6 files changed, 22 insertions(+), 16 deletions(-) diff --git a/hw/qxl-render.c b/hw/qxl-render.c index 88e63f8..455fb91 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -118,7 +118,8 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) qxl-guest_primary.surface.height, qxl-guest_primary.bits_pp, qxl-guest_primary.abs_stride, - qxl-guest_primary.data); + qxl-guest_primary.data, + false); } else { qemu_resize_displaysurface(vga-ds, qxl-guest_primary.surface.width, diff --git a/hw/vga.c b/hw/vga.c index e2ba7f2..1caf23d 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1643,6 +1643,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) uint8_t *d; uint32_t v, addr1, addr; vga_draw_line_func *vga_draw_line; +#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) +static const bool byteswap = false; +#else +static const bool byteswap = true; +#endif full_update |= update_basic_params(s); @@ -1685,18 +1690,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) disp_width != s-last_width || height != s-last_height || s-last_depth != depth) { -#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) -if (depth == 16 || depth == 32) { -#else -if (depth == 32) { -#endif +if (depth == 32 || (depth == 16 !byteswap)) { qemu_free_displaysurface(s-ds); s-ds-surface = qemu_create_displaysurface_from(disp_width, height, depth, s-line_offset, -s-vram_ptr + (s-start_addr * 4)); -#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) -s-ds-surface-pf = qemu_different_endianness_pixelformat(depth); -#endif +s-vram_ptr + (s-start_addr * 4), byteswap); dpy_gfx_resize(s-ds); } else { qemu_console_resize(s-ds, disp_width, height); @@ -1715,7 +1713,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) s-ds-surface = qemu_create_displaysurface_from(disp_width, height, depth, s-line_offset, -s-vram_ptr + (s-start_addr * 4)); +s-vram_ptr + (s-start_addr * 4), byteswap); dpy_gfx_setdata(s-ds); } diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index cd15ee4..8fc201b 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -1074,7 +1074,7 @@ static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch, ds_get_height(s-vga.ds), 32, ds_get_linesize(s-vga.ds), - s-vga.vram_ptr); + s-vga.vram_ptr, false); ppm_save(filename, ds, errp); g_free(ds); } diff --git a/hw/xenfb.c b/hw/xenfb.c index 903efd3..7f1f6b4 100644 --- a/hw/xenfb.c +++ b/hw/xenfb.c @@ -756,7 +756,8 @@ static void xenfb_update(void *opaque) qemu_free_displaysurface(xenfb-c.ds); xenfb-c.ds-surface = qemu_create_displaysurface_from (xenfb-width, xenfb-height, xenfb-depth, - xenfb-row_stride, xenfb-pixels + xenfb-offset); + xenfb-row_stride, xenfb-pixels + xenfb-offset, + false); break; default: /* we must convert stuff */ diff --git a/include/ui/console.h b/include/ui/console.h index fc23baa..18012f1 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -184,7 +184,8 @@ struct DisplayState { void register_displaystate(DisplayState *ds); DisplayState *get_displaystate(void); DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, -int linesize, uint8_t *data); +
Re: [Qemu-devel] using -net dump with tap networking
On Tue, Feb 19, 2013 at 09:16:56PM +0100, Laszlo Ersek wrote: On 02/19/13 18:50, Markus Armbruster wrote: Your example uses -net to connect additional backends to the hubport. If I understand you correctly, you can't use -netdev to do that. Ignorant question: fundamental reason or just not implemented? In order to take a stab at your question at last: - the two (parallel, opposing) links created in (3) connect two backends, - -netdev does not set the peer link in the backend, so you cannot use that, - -device *would* set the links in both directions, but it's for creating frontends. IOW (3) is unique because it links backend to backend. Right. -netdev doesn't allow you to specify a peer, only NICs (-device) do that. This means there is no way to hook up -netdev dump with -netdev hubport, they are both -netdevs :(. This is why I said it's just playing games with syntax. I don't think it buys us anything in the end. Stefan
Re: [Qemu-devel] using -net dump with tap networking
On Tue, Feb 19, 2013 at 06:50:22PM +0100, Markus Armbruster wrote: Stefan Hajnoczi stefa...@gmail.com writes: On Tue, Feb 19, 2013 at 09:53:07AM +0100, Markus Armbruster wrote: Stefan Hajnoczi stefa...@redhat.com writes: On Tue, Feb 19, 2013 at 12:37:28PM +1100, Alexey Kardashevskiy wrote: On 14/02/13 21:26, Stefan Hajnoczi wrote: Now I want to enable network dump. With the old -net syntax I could do that with -net dump but I cannot with the new syntax, tried many variants, none works. What would the correct syntax be for the case above? The question was about new -netdev interface. I would do: qemu-system-ppc64 ... -net tap,ifname=tap0,script=qemu-ifup.sh -net nic,model=virtio -net dump,file=./dump.lan.qemu.virtio The answer is about old -net interface which I know how to use. Does this mean that there is no way to use dump with -netdev tap? It is not possible using just -netdev/-device. The closest you can get is: $ qemu -netdev hubport,hubid=1,id=hubport0 \ -device virtio-net-pci,netdev=hubport0,... \ -net tap,vlan=1,... \ -net dump,vlan=1,... Care to explain briefly how hubport works, and how it's connected to the legacy vlan feature? -netdev hubport instantiates a new port on a hub with vlan number hubid=number. hubport is a -netdev, so it allows you to hook up a NIC to a hub using -netdev/-device syntax. This is just playing games with syntax, we still have a hub in between the virtio-net-pci, tap, and dump devices. I didn't check if the offload features get plumbed through, but I wouldn't count on it. Thanks. Would you mind documenting net backend hubport in qemu-options.hx? Was forgotten in commit f6c874e3. Sure. Stefan
[Qemu-devel] [PATCH 12/38] target-i386: Use add2 to implement the ADX extension
Signed-off-by: Richard Henderson r...@twiddle.net --- target-i386/translate.c | 20 +--- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/target-i386/translate.c b/target-i386/translate.c index 1545e3f..3b92f3b 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -4169,7 +4169,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, if (!(s-cpuid_7_0_ebx_features CPUID_7_0_EBX_ADX)) { goto illegal_op; } else { -TCGv carry_in, carry_out; +TCGv carry_in, carry_out, zero; int end_op; ot = (s-dflag == 2 ? OT_QUAD : OT_LONG); @@ -4229,18 +4229,16 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, #endif default: /* Otherwise compute the carry-out in two steps. */ -tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_regs[reg]); -tcg_gen_setcond_tl(TCG_COND_LTU, cpu_tmp4, - cpu_T[0], cpu_regs[reg]); -tcg_gen_add_tl(cpu_regs[reg], cpu_T[0], carry_in); -tcg_gen_setcond_tl(TCG_COND_LTU, carry_out, - cpu_regs[reg], cpu_T[0]); -tcg_gen_or_tl(carry_out, carry_out, cpu_tmp4); +zero = tcg_const_tl(0); +tcg_gen_add2_tl(cpu_T[0], carry_out, +cpu_T[0], zero, +carry_in, zero); +tcg_gen_add2_tl(cpu_regs[reg], carry_out, +cpu_regs[reg], carry_out, +cpu_T[0], zero); +tcg_temp_free(zero); break; } -/* We began with all flags computed to CC_SRC, and we - have now placed the carry-out in CC_DST. All that - is left is to record the CC_OP. */ set_cc_op(s, end_op); } break; -- 1.8.1.2
[Qemu-devel] [PATCH 33/38] target-sparc: Use official add2/sub2 interfaces for addx/subx
Cc: Blue Swirl blauwir...@gmail.com Signed-off-by: Richard Henderson r...@twiddle.net --- target-sparc/translate.c | 42 -- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index ca75e1a..d3e2acf 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -448,19 +448,16 @@ static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1, case CC_OP_ADD: case CC_OP_TADD: case CC_OP_TADDTV: -#if TCG_TARGET_REG_BITS == 32 TARGET_LONG_BITS == 32 -{ -/* For 32-bit hosts, we can re-use the host's hardware carry - generation by using an ADD2 opcode. We discard the low - part of the output. Ideally we'd combine this operation - with the add that generated the carry in the first place. */ -TCGv dst_low = tcg_temp_new(); -tcg_gen_op6_i32(INDEX_op_add2_i32, dst_low, dst, -cpu_cc_src, src1, cpu_cc_src2, src2); -tcg_temp_free(dst_low); +if (TARGET_LONG_BITS == 32) { +/* We can re-use the host's hardware carry generation by using + an ADD2 opcode. We discard the low part of the output. + Ideally we'd combine this operation with the add that + generated the carry in the first place. */ +carry = tcg_temp_new(); +tcg_gen_add2_tl(carry, dst, cpu_cc_src, src1, cpu_cc_src2, src2); +tcg_temp_free(carry); goto add_done; } -#endif carry_32 = gen_add32_carry32(); break; @@ -492,9 +489,7 @@ static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1, tcg_temp_free(carry); #endif -#if TCG_TARGET_REG_BITS == 32 TARGET_LONG_BITS == 32 add_done: -#endif if (update_cc) { tcg_gen_mov_tl(cpu_cc_src, src1); tcg_gen_mov_tl(cpu_cc_src2, src2); @@ -554,19 +549,16 @@ static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1, case CC_OP_SUB: case CC_OP_TSUB: case CC_OP_TSUBTV: -#if TCG_TARGET_REG_BITS == 32 TARGET_LONG_BITS == 32 -{ -/* For 32-bit hosts, we can re-use the host's hardware carry - generation by using a SUB2 opcode. We discard the low - part of the output. Ideally we'd combine this operation - with the add that generated the carry in the first place. */ -TCGv dst_low = tcg_temp_new(); -tcg_gen_op6_i32(INDEX_op_sub2_i32, dst_low, dst, -cpu_cc_src, src1, cpu_cc_src2, src2); -tcg_temp_free(dst_low); +if (TARGET_LONG_BITS == 32) { +/* We can re-use the host's hardware carry generation by using + a SUB2 opcode. We discard the low part of the output. + Ideally we'd combine this operation with the add that + generated the carry in the first place. */ +carry = tcg_temp_new(); +tcg_gen_sub2_tl(carry, dst, cpu_cc_src, src1, cpu_cc_src2, src2); +tcg_temp_free(carry); goto sub_done; } -#endif carry_32 = gen_sub32_carry32(); break; @@ -592,9 +584,7 @@ static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1, tcg_temp_free(carry); #endif -#if TCG_TARGET_REG_BITS == 32 TARGET_LONG_BITS == 32 sub_done: -#endif if (update_cc) { tcg_gen_mov_tl(cpu_cc_src, src1); tcg_gen_mov_tl(cpu_cc_src2, src2); -- 1.8.1.2
Re: [Qemu-devel] High memory usage by multiqueue
On 02/20/2013 02:59 AM, Edivaldo de Araujo Pereira wrote: Dear Jason, In the last 2 weeks, I noticed a significant increase in the memory usage of qemu. Just to assess the stability of my system, I usually run a kind of stress test, every time I install a new kernel in my host or in a custom VM that I use in my classes, or when I compile a new snapshot of qemu. The test is quite simple, but somewhat brutal: 200 qemu guests (1 cpu, 256MB, no hd) running on a single host (4 core, 8 threads, 8GB). It's obvious that such thing doesn't serve any purpose other than to say it runs... 80% of all memory and 35% of all processing just to make 200 guests little more than idle... But the point is, when everything is ok, it runs very well, and I can even put some 240Mbits of traffic in the virtual net. In my tests, each VM uses ~180MB (thanks to ksm, 200*180MB8GB); but in recent weeks, the memory footprint of the MVs jumped to ~230MB, along whith some change in its behaviour that rends completely broken the magic of ksm (at least in my test); in other words, I can no more run 200 guests in my machine. So I did a git bisect, as Stefan told some time ago, and I found the problem is related to multiqueue support. More precisely, the constant MAX_QUEUE_NUM 1024 in include/net/net.h. As long as I understand, such a high number of queues is at least a little bit out of reality... Wouldn't it imply having possibly that number of threads runing network traffic? Problem is, I can not imagine the total number of logical processors a guest would need to have, just to take advantage of such a number of network traffic thhreads. By the way, that number is many times higher than supported by any physical network adapter I have read about. So I've tampered a little with that number, and found that setting it to 4 or 8 reduces drastically the memory usage, without disrupting any network function (in my test...); yet this is twice the numbers of some examples I've seen in wmware related texts. The good news: my stress test runs smoothly again... well, almost, for I'm not using multiqueue yet... So, I think it would be good to find a better approach; dynamic allocation would be nice, in accordance with command line parameters, wouldn't it? Yes, it's a bug. The dynamic allocation is better(1.5). For 1.4, I think we can simply limit the number to 8. Will post the patch. Thanks Thank you, very much Edivaldo de Araújo Pereira
[Qemu-devel] [PATCH 30/38] target-ppc: Implement neg in terms of subf
Cc: Alexander Graf ag...@suse.de Signed-off-by: Richard Henderson r...@twiddle.net --- target-ppc/translate.c | 63 +++--- 1 file changed, 19 insertions(+), 44 deletions(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index abc75e2..05f93f6 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -1121,50 +1121,6 @@ static void gen_mulldo(DisasContext *ctx) } #endif -/* neg neg. nego nego. */ -static inline void gen_op_arith_neg(DisasContext *ctx, TCGv ret, TCGv arg1, -int ov_check) -{ -int l1 = gen_new_label(); -int l2 = gen_new_label(); -TCGv t0 = tcg_temp_local_new(); -#if defined(TARGET_PPC64) -if (ctx-sf_mode) { -tcg_gen_mov_tl(t0, arg1); -tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT64_MIN, l1); -} else -#endif -{ -tcg_gen_ext32s_tl(t0, arg1); -tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT32_MIN, l1); -} -tcg_gen_neg_tl(ret, arg1); -if (ov_check) { -tcg_gen_movi_tl(cpu_ov, 0); -} -tcg_gen_br(l2); -gen_set_label(l1); -tcg_gen_mov_tl(ret, t0); -if (ov_check) { -tcg_gen_movi_tl(cpu_ov, 1); -tcg_gen_movi_tl(cpu_so, 1); -} -gen_set_label(l2); -tcg_temp_free(t0); -if (unlikely(Rc(ctx-opcode) != 0)) -gen_set_Rc0(ctx, ret); -} - -static void gen_neg(DisasContext *ctx) -{ -gen_op_arith_neg(ctx, cpu_gpr[rD(ctx-opcode)], cpu_gpr[rA(ctx-opcode)], 0); -} - -static void gen_nego(DisasContext *ctx) -{ -gen_op_arith_neg(ctx, cpu_gpr[rD(ctx-opcode)], cpu_gpr[rA(ctx-opcode)], 1); -} - /* Common subf function */ static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2, bool add_ca, bool compute_ca, @@ -1254,6 +1210,25 @@ static void gen_subfic(DisasContext *ctx) tcg_temp_free(c); } +/* neg neg. nego nego. */ +static inline void gen_op_arith_neg(DisasContext *ctx, bool compute_ov) +{ +TCGv zero = tcg_const_tl(0); +gen_op_arith_subf(ctx, cpu_gpr[rD(ctx-opcode)], cpu_gpr[rA(ctx-opcode)], + zero, 0, 0, compute_ov, Rc(ctx-opcode)); +tcg_temp_free(zero); +} + +static void gen_neg(DisasContext *ctx) +{ +gen_op_arith_neg(ctx, 0); +} + +static void gen_nego(DisasContext *ctx) +{ +gen_op_arith_neg(ctx, 1); +} + /***Integer logical***/ #define GEN_LOGICAL2(name, tcg_op, opc, type) \ static void glue(gen_, name)(DisasContext *ctx) \ -- 1.8.1.2
[Qemu-devel] [PATCH 36/38] target-unicore32: Use mul*2 for do_mult
Cc: Guan Xuetao g...@mprc.pku.edu.cn Signed-off-by: Richard Henderson r...@twiddle.net --- target-unicore32/translate.c | 83 ++-- 1 file changed, 11 insertions(+), 72 deletions(-) diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index f4498bc..d5039e2 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -267,37 +267,6 @@ static void gen_exception(int excp) dead_tmp(tmp); } -/* FIXME: Most targets have native widening multiplication. - It would be good to use that instead of a full wide multiply. */ -/* 32x32-64 multiply. Marks inputs as dead. */ -static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b) -{ -TCGv_i64 tmp1 = tcg_temp_new_i64(); -TCGv_i64 tmp2 = tcg_temp_new_i64(); - -tcg_gen_extu_i32_i64(tmp1, a); -dead_tmp(a); -tcg_gen_extu_i32_i64(tmp2, b); -dead_tmp(b); -tcg_gen_mul_i64(tmp1, tmp1, tmp2); -tcg_temp_free_i64(tmp2); -return tmp1; -} - -static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b) -{ -TCGv_i64 tmp1 = tcg_temp_new_i64(); -TCGv_i64 tmp2 = tcg_temp_new_i64(); - -tcg_gen_ext_i32_i64(tmp1, a); -dead_tmp(a); -tcg_gen_ext_i32_i64(tmp2, b); -dead_tmp(b); -tcg_gen_mul_i64(tmp1, tmp1, tmp2); -tcg_temp_free_i64(tmp2); -return tmp1; -} - #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, CF)) /* Set CF to the top bit of var. */ @@ -1219,38 +1188,6 @@ static void disas_coproc_insn(CPUUniCore32State *env, DisasContext *s, } } - -/* Store a 64-bit value to a register pair. Clobbers val. */ -static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val) -{ -TCGv tmp; -tmp = new_tmp(); -tcg_gen_trunc_i64_i32(tmp, val); -store_reg(s, rlow, tmp); -tmp = new_tmp(); -tcg_gen_shri_i64(val, val, 32); -tcg_gen_trunc_i64_i32(tmp, val); -store_reg(s, rhigh, tmp); -} - -/* load and add a 64-bit value from a register pair. */ -static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh) -{ -TCGv_i64 tmp; -TCGv tmpl; -TCGv tmph; - -/* Load 64-bit value rd:rn. */ -tmpl = load_reg(s, rlow); -tmph = load_reg(s, rhigh); -tmp = tcg_temp_new_i64(); -tcg_gen_concat_i32_i64(tmp, tmpl, tmph); -dead_tmp(tmpl); -dead_tmp(tmph); -tcg_gen_add_i64(val, val, tmp); -tcg_temp_free_i64(tmp); -} - /* data processing instructions */ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn) { @@ -1445,24 +1382,26 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn) /* multiply */ static void do_mult(CPUUniCore32State *env, DisasContext *s, uint32_t insn) { -TCGv tmp; -TCGv tmp2; -TCGv_i64 tmp64; +TCGv tmp, tmp2, tmp3, tmp4; if (UCOP_SET(27)) { /* 64 bit mul */ tmp = load_reg(s, UCOP_REG_M); tmp2 = load_reg(s, UCOP_REG_N); if (UCOP_SET(26)) { -tmp64 = gen_muls_i64_i32(tmp, tmp2); +tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2); } else { -tmp64 = gen_mulu_i64_i32(tmp, tmp2); +tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2); } if (UCOP_SET(25)) { /* mult accumulate */ -gen_addq(s, tmp64, UCOP_REG_LO, UCOP_REG_HI); -} -gen_storeq_reg(s, UCOP_REG_LO, UCOP_REG_HI, tmp64); -tcg_temp_free_i64(tmp64); +tmp3 = load_reg(s, UCOP_REG_LO); +tmp4 = load_reg(s, UCOP_REG_HI); +tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, tmp3, tmp4); +dead_tmp(tmp3); +dead_tmp(tmp4); +} +store_reg(s, UCOP_REG_LO, tmp); +store_reg(s, UCOP_REG_HI, tmp2); } else { /* 32 bit mul */ tmp = load_reg(s, UCOP_REG_M); -- 1.8.1.2
Re: [Qemu-devel] [PATCH v3 3/6] add backup related monitor commands
+++ b/qapi-schema.json @@ -425,6 +425,39 @@ { 'type': 'EventInfo', 'data': {'name': 'str'} } ## +# @BackupStatus: +# +# Detailed backup status. +# +# @status: #optional string describing the current backup status. +# This can be 'active', 'done', 'error'. If this field is not +# returned, no backup process has been initiated This should be an enum type, not an open-coded 'str'. @MigrationInfo also use a string for @status. I try to use the same style as existing code. +# +# @errmsg: #optional error message (only returned if status is +'error') # # @total: #optional total amount of bytes involved in the +backup process # # @transferred: #optional amount of bytes already +backed up. +# +# @zero-bytes: #optional amount of 'zero' bytes detected. +# +# @start-time: #optional time (epoch) when backup job started. +# +# @end-time: #optional time (epoch) when backup job finished. Is 1-second resolution good enough, or should we be accounting for sub- second information? IMHO second is good enough. +# +# @backupfile: #optional backup file name # # @uuid: #optional uuid +for this backup job # # Since: 1.5.0 ## { 'type': 'BackupStatus', + 'data': {'*status': 'str', '*errmsg': 'str', '*total': 'int', + '*transferred': 'int', '*zero-bytes': 'int', + '*start-time': 'int', '*end-time': 'int', + '*backupfile': 'str', '*uuid': 'str' } } You can optional set the speed when starting a backup job, but can you later change the job speed on the fly, and if so, with what command? no, you can't change the speed later (currently). Also, shouldn't the current speed be displayed as part of BackupStatus? You can compute the actual speed from those value. + +## # @query-events: # # Return a list of supported QMP events by this server @@ -1824,6 +1857,64 @@ 'data': { 'path': 'str' }, 'returns': [ 'ObjectPropertyInfo' ] } + +## +# @BackupFormat +# +# An enumeration of supported backup formats. +# +# @vma: Proxmox vma backup format +## +{ 'enum': 'BackupFormat', + 'data': [ 'vma' ] } + +## +# @backup: +# +# Starts a VM backup. +# +# @backupfile: the backup file name +# +# @format: format of the backup file +# +# @config-filename: #optional name of a configuration file to include +into # the backup archive. 'backupfile' vs. 'config-filename' feels inconsistent; better might be 'backup- file' and 'config-file'. will change that. +# +# @speed: #optional the maximum speed, in bytes per second # @devlist is missing. +# Returns: the uuid of the backup job # # Since: 1.5.0 ## { +'command': 'backup', 'data': { 'backupfile': 'str', '*format': 'BackupFormat', + '*config-filename': 'str', + '*devlist': 'str', '*speed': 'int' +}, + 'returns': 'str' } + +## +# @query-backup +# +# Returns information about current/last backup task. +# +# Returns: @BackupStatus +# +# Since: 1.5.0 +## +{ 'command': 'query-backup', 'returns': 'BackupStatus' } + +## +# @backup-cancel +# +# Cancel the current executing backup process. +# +# Returns: nothing on success +# +# Notes: This command succeeds even if there is no backup process running. +# +# Since: 1.5.0 +## +{ 'command': 'backup-cancel' } + +++ b/qmp-commands.hx @@ -889,6 +889,18 @@ EQMP }, { +.name = backup, +.args_type = backupfile:s,format:s?,config- filename:F?,speed:o?,devlist:s?, +.mhandler.cmd_new = qmp_marshal_input_backup, +}, + +{ +.name = backup_cancel, This doesn't match the spelling in the .json file. will fix that.
[Qemu-devel] [PATCH 24/38] target-ppc: Use mul*2 in mulh* insns
Cc: Alexander Graf ag...@suse.de Signed-off-by: Richard Henderson r...@twiddle.net --- target-ppc/helper.h | 2 -- target-ppc/int_helper.c | 18 --- target-ppc/translate.c | 82 +++-- 3 files changed, 38 insertions(+), 64 deletions(-) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 18e0394..fcf372a 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -30,8 +30,6 @@ DEF_HELPER_2(icbi, void, env, tl) DEF_HELPER_5(lscbx, tl, env, tl, i32, i32, i32) #if defined(TARGET_PPC64) -DEF_HELPER_FLAGS_2(mulhd, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(mulhdu, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_3(mulldo, i64, env, i64, i64) #endif diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c index 783079d..8653151 100644 --- a/target-ppc/int_helper.c +++ b/target-ppc/int_helper.c @@ -25,24 +25,6 @@ /* Fixed point operations helpers */ #if defined(TARGET_PPC64) -/* multiply high word */ -uint64_t helper_mulhd(uint64_t arg1, uint64_t arg2) -{ -uint64_t tl, th; - -muls64(tl, th, arg1, arg2); -return th; -} - -/* multiply high word unsigned */ -uint64_t helper_mulhdu(uint64_t arg1, uint64_t arg2) -{ -uint64_t tl, th; - -mulu64(tl, th, arg1, arg2); -return th; -} - uint64_t helper_mulldo(CPUPPCState *env, uint64_t arg1, uint64_t arg2) { int64_t th; diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 2ac5794..2673a89 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -1061,24 +1061,15 @@ GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1); /* mulhw mulhw. */ static void gen_mulhw(DisasContext *ctx) { -TCGv_i64 t0, t1; +TCGv_i32 t0 = tcg_temp_new_i32(); +TCGv_i32 t1 = tcg_temp_new_i32(); -t0 = tcg_temp_new_i64(); -t1 = tcg_temp_new_i64(); -#if defined(TARGET_PPC64) -tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx-opcode)]); -tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx-opcode)]); -tcg_gen_mul_i64(t0, t0, t1); -tcg_gen_shri_i64(cpu_gpr[rD(ctx-opcode)], t0, 32); -#else -tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx-opcode)]); -tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx-opcode)]); -tcg_gen_mul_i64(t0, t0, t1); -tcg_gen_shri_i64(t0, t0, 32); -tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx-opcode)], t0); -#endif -tcg_temp_free_i64(t0); -tcg_temp_free_i64(t1); +tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx-opcode)]); +tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx-opcode)]); +tcg_gen_muls2_i32(t0, t1, t0, t1); +tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx-opcode)], t1); +tcg_temp_free_i32(t0); +tcg_temp_free_i32(t1); if (unlikely(Rc(ctx-opcode) != 0)) gen_set_Rc0(ctx, cpu_gpr[rD(ctx-opcode)]); } @@ -1086,24 +1077,15 @@ static void gen_mulhw(DisasContext *ctx) /* mulhwu mulhwu. */ static void gen_mulhwu(DisasContext *ctx) { -TCGv_i64 t0, t1; +TCGv_i32 t0 = tcg_temp_new_i32(); +TCGv_i32 t1 = tcg_temp_new_i32(); -t0 = tcg_temp_new_i64(); -t1 = tcg_temp_new_i64(); -#if defined(TARGET_PPC64) -tcg_gen_ext32u_i64(t0, cpu_gpr[rA(ctx-opcode)]); -tcg_gen_ext32u_i64(t1, cpu_gpr[rB(ctx-opcode)]); -tcg_gen_mul_i64(t0, t0, t1); -tcg_gen_shri_i64(cpu_gpr[rD(ctx-opcode)], t0, 32); -#else -tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx-opcode)]); -tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx-opcode)]); -tcg_gen_mul_i64(t0, t0, t1); -tcg_gen_shri_i64(t0, t0, 32); -tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx-opcode)], t0); -#endif -tcg_temp_free_i64(t0); -tcg_temp_free_i64(t1); +tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx-opcode)]); +tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx-opcode)]); +tcg_gen_mulu2_i32(t0, t1, t0, t1); +tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx-opcode)], t1); +tcg_temp_free_i32(t0); +tcg_temp_free_i32(t1); if (unlikely(Rc(ctx-opcode) != 0)) gen_set_Rc0(ctx, cpu_gpr[rD(ctx-opcode)]); } @@ -1159,19 +1141,31 @@ static void gen_mulli(DisasContext *ctx) tcg_gen_muli_tl(cpu_gpr[rD(ctx-opcode)], cpu_gpr[rA(ctx-opcode)], SIMM(ctx-opcode)); } + #if defined(TARGET_PPC64) -#define GEN_INT_ARITH_MUL_HELPER(name, opc3) \ -static void glue(gen_, name)(DisasContext *ctx) \ -{ \ -gen_helper_##name (cpu_gpr[rD(ctx-opcode)], \ - cpu_gpr[rA(ctx-opcode)], cpu_gpr[rB(ctx-opcode)]); \ -if (unlikely(Rc(ctx-opcode) != 0)) \ -gen_set_Rc0(ctx, cpu_gpr[rD(ctx-opcode)]); \ -} /* mulhd mulhd. */ -GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00); +static void gen_mulhd(DisasContext *ctx) +{ +TCGv lo = tcg_temp_new(); +tcg_gen_muls2_tl(lo, cpu_gpr[rD(ctx-opcode)], + cpu_gpr[rA(ctx-opcode)], cpu_gpr[rB(ctx-opcode)]); +tcg_temp_free(lo); +if
Re: [Qemu-devel] 3 new x86 instructions
Richard Henderson r...@twiddle.net writes: On 2013-02-19 13:52, Torbjorn Granlund wrote: Execute. I believe correct behaviour is to print: 000d 000d 040b 000a The program under your special qemu instead prints: 000e 000d 040b 000a Perhaps I am being silly and the program is behaving correctly. Nope, you found a typo in the comparison. Annoyingly, not in the i686 version, which is what I'd tested by hand before. I've pushed an update to my x86-next branch, and updated the eflags3 branch against which I posted patches for review this afternoon. I cloned a fresh repo, and compiled it exactly like yesterday on the same system (I used bash's history list): [srcpath]/configure make -j8 Now my disk image fails to boot. No bootable device. Retrying in 60 seconds. My boot command is (and was): qemu-system-x86_64 -m 512 -cpu Haswell,+adx \ -net nic,macaddr=52:54:00:f2:81:c7,model=e1000 -net tap \ -cdrom /u/FreeBSD/FreeBSD-9.1-RELEASE-amd64-dvd1.iso -boot c -hda disk.img I went back to the old qemu-system-x86_64 and that still works, so I don't think the disk.img file is corrupt. I then tried something that you might consider more plain: qemu-system-x86_64 -m 512 -cpu Haswell,+adx \ -net nic,macaddr=52:54:00:f2:18:b7,model=e1000 -net tap \ -cdrom /u/GNU/Debian/debian-6.0.6-amd64-netinst.iso -boot d --hda disk.img It fails similarly. (Here disk.img is pristine from a qemu-img create command, but I am attemtping to boot from the iso img.) -- Torbjörn
Re: [Qemu-devel] [PATCH 4/9] target-i386: convert 'hv_relaxed' to static property
On Tue, 19 Feb 2013 15:45:16 -0300 Eduardo Habkost ehabk...@redhat.com wrote: On Mon, Feb 11, 2013 at 05:35:06PM +0100, Igor Mammedov wrote: Signed-off-by: Igor Mammedov imamm...@redhat.com --- target-i386/cpu.c | 35 ++- 1 files changed, 34 insertions(+), 1 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 1f14b65..b804031 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -528,6 +528,38 @@ PropertyInfo qdev_prop_spinlocks = { .defval = _defval \ } +static void x86_get_hv_relaxed(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ +bool value = hyperv_relaxed_timing_enabled(); + +visit_type_bool(v, value, name, errp); +} + +static void x86_set_hv_relaxed(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ +bool value; + +visit_type_bool(v, value, name, errp); +if (error_is_set(errp)) { +return; +} +hyperv_enable_relaxed_timing(value); +} + +PropertyInfo qdev_prop_hv_relaxed = { +.name = boolean, +.get = x86_get_hv_relaxed, +.set = x86_set_hv_relaxed, +}; +#define DEFINE_PROP_HV_RELAXED(_n, _defval) { \ +.name = _n, \ +.info = qdev_prop_hv_relaxed,\ +.qtype = QTYPE_QBOOL, \ +.defval = _defval \ +} + static Property cpu_x86_properties[] = { DEFINE_PROP_FAMILY(family), DEFINE_PROP_MODEL(model), @@ -538,6 +570,7 @@ static Property cpu_x86_properties[] = { DEFINE_PROP_MODEL_ID(model-id), DEFINE_PROP_TSC_FREQ(tsc-frequency), DEFINE_PROP_HV_SPINLOCKS(hv-spinlocks, HYPERV_SPINLOCK_NEVER_RETRY), +DEFINE_PROP_HV_RELAXED(hv-relaxed, false), Why not simply make it a X86CPU struct field, so we don't need a special PropertyInfo? The whole contents of target-i386/hyperv.c are getters/setters for three static variables that should have been X86CPU fields in the first place. I went via less intrusive approach to avoid breaking anything during conversion. Can we proceed with conversion first and than decide whether to move hv_* into CPU or not? DEFINE_PROP_END_OF_LIST(), }; @@ -1468,7 +1501,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp) } else if (!strcmp(featurestr, enforce)) { check_cpuid = enforce_cpuid = 1; } else if (!strcmp(featurestr, hv_relaxed)) { -hyperv_enable_relaxed_timing(true); +object_property_parse(OBJECT(cpu), on, hv-relaxed, errp); } else if (!strcmp(featurestr, hv_vapic)) { hyperv_enable_vapic_recommended(true); } else { -- 1.7.1
[Qemu-devel] [PATCH 20/38] target-arm: Implement adc_cc inline
Use add2 if available, otherwise use 64-bit arithmetic. Cc: Peter Maydell peter.mayd...@linaro.org Signed-off-by: Richard Henderson r...@twiddle.net --- target-arm/helper.h| 1 - target-arm/op_helper.c | 15 --- target-arm/translate.c | 39 ++- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/target-arm/helper.h b/target-arm/helper.h index bca5a5b..507bb9c 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -140,7 +140,6 @@ DEF_HELPER_2(recpe_u32, i32, i32, env) DEF_HELPER_2(rsqrte_u32, i32, i32, env) DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32) -DEF_HELPER_3(adc_cc, i32, env, i32, i32) DEF_HELPER_3(sbc_cc, i32, env, i32, i32) DEF_HELPER_3(shl_cc, i32, env, i32, i32) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 99610d7..49fc036 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -315,21 +315,6 @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip) The only way to do that in TCG is a conditional branch, which clobbers all our temporaries. For now implement these as helper functions. */ -uint32_t HELPER(adc_cc)(CPUARMState *env, uint32_t a, uint32_t b) -{ -uint32_t result; -if (!env-CF) { -result = a + b; -env-CF = result a; -} else { -result = a + b + 1; -env-CF = result = a; -} -env-VF = (a ^ b ^ -1) (a ^ result); -env-NF = env-ZF = result; -return result; -} - uint32_t HELPER(sbc_cc)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t result; diff --git a/target-arm/translate.c b/target-arm/translate.c index ca6f0af..493448a 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -421,6 +421,34 @@ static void gen_add_CC(TCGv dest, TCGv t0, TCGv t1) tcg_gen_mov_i32(dest, cpu_NF); } +/* dest = T0 + T1 + CF. Compute C, N, V and Z flags */ +static void gen_adc_CC(TCGv dest, TCGv t0, TCGv t1) +{ +TCGv tmp = tcg_temp_new_i32(); +if (TCG_TARGET_HAS_add2_i32) { +tcg_gen_movi_i32(tmp, 0); +tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp); +tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, cpu_CF, t1, tmp); +} else { +TCGv_i64 q0 = tcg_temp_new_i64(); +TCGv_i64 q1 = tcg_temp_new_i64(); +tcg_gen_extu_i32_i64(q0, t0); +tcg_gen_extu_i32_i64(q1, t1); +tcg_gen_add_i64(q0, q0, q1); +tcg_gen_extu_i32_i64(q1, cpu_CF); +tcg_gen_add_i64(q0, q0, q1); +tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0); +tcg_temp_free_i64(q0); +tcg_temp_free_i64(q1); +} +tcg_gen_mov_i32(cpu_ZF, cpu_NF); +tcg_gen_xor_i32(cpu_VF, cpu_NF, t0); +tcg_gen_xor_i32(tmp, t0, t1); +tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp); +tcg_temp_free_i32(tmp); +tcg_gen_mov_i32(dest, cpu_NF); +} + /* dest = T0 - T1. Compute C, N, V and Z flags */ static void gen_sub_CC(TCGv dest, TCGv t0, TCGv t1) { @@ -7073,7 +7101,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x05: if (set_cc) { -gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2); +gen_adc_CC(tmp, tmp, tmp2); } else { gen_add_carry(tmp, tmp, tmp2); } @@ -7914,7 +7942,7 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCG break; case 10: /* adc */ if (conds) -gen_helper_adc_cc(t0, cpu_env, t0, t1); +gen_adc_CC(t0, t0, t1); else gen_adc(t0, t1); break; @@ -9232,10 +9260,11 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) } break; case 0x5: /* adc */ -if (s-condexec_mask) +if (s-condexec_mask) { gen_adc(tmp, tmp2); -else -gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2); +} else { +gen_adc_CC(tmp, tmp, tmp2); +} break; case 0x6: /* sbc */ if (s-condexec_mask) -- 1.8.1.2
[Qemu-devel] [PATCH 37/38] target-xtensa: Use mul*2 for mul*hi
Cc: Max Filippov jcmvb...@gmail.com Signed-off-by: Richard Henderson r...@twiddle.net --- target-xtensa/translate.c | 20 ++-- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 7029ac4..b41d12c 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -1652,24 +1652,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) case 11: /*MULSHi*/ HAS_OPTION(XTENSA_OPTION_32_BIT_IMUL_HIGH); { -TCGv_i64 r = tcg_temp_new_i64(); -TCGv_i64 s = tcg_temp_new_i64(); -TCGv_i64 t = tcg_temp_new_i64(); +TCGv lo = tcg_temp_new(); if (OP2 == 10) { -tcg_gen_extu_i32_i64(s, cpu_R[RRR_S]); -tcg_gen_extu_i32_i64(t, cpu_R[RRR_T]); +tcg_gen_mulu2_i32(lo, cpu_R[RRR_R], + cpu_R[RRR_S], cpu_R[RRR_T]); } else { -tcg_gen_ext_i32_i64(s, cpu_R[RRR_S]); -tcg_gen_ext_i32_i64(t, cpu_R[RRR_T]); +tcg_gen_muls2_i32(lo, cpu_R[RRR_R], + cpu_R[RRR_S], cpu_R[RRR_T]); } -tcg_gen_mul_i64(r, s, t); -tcg_gen_shri_i64(r, r, 32); -tcg_gen_trunc_i64_i32(cpu_R[RRR_R], r); - -tcg_temp_free_i64(r); -tcg_temp_free_i64(s); -tcg_temp_free_i64(t); +tcg_temp_free(lo); } break; -- 1.8.1.2
[Qemu-devel] [PATCH 35/38] target-sh4: Use mul*2 for dmul*
Cc: Aurelien Jarno aurel...@aurel32.net Signed-off-by: Richard Henderson r...@twiddle.net --- target-sh4/translate.c | 30 ++ 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/target-sh4/translate.c b/target-sh4/translate.c index c58d79a..d255066 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -833,36 +833,10 @@ static void _decode_opc(DisasContext * ctx) gen_helper_div1(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8)); return; case 0x300d: /* dmuls.l Rm,Rn */ - { - TCGv_i64 tmp1 = tcg_temp_new_i64(); - TCGv_i64 tmp2 = tcg_temp_new_i64(); - - tcg_gen_ext_i32_i64(tmp1, REG(B7_4)); - tcg_gen_ext_i32_i64(tmp2, REG(B11_8)); - tcg_gen_mul_i64(tmp1, tmp1, tmp2); - tcg_gen_trunc_i64_i32(cpu_macl, tmp1); - tcg_gen_shri_i64(tmp1, tmp1, 32); - tcg_gen_trunc_i64_i32(cpu_mach, tmp1); - - tcg_temp_free_i64(tmp2); - tcg_temp_free_i64(tmp1); - } +tcg_gen_muls2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8)); return; case 0x3005: /* dmulu.l Rm,Rn */ - { - TCGv_i64 tmp1 = tcg_temp_new_i64(); - TCGv_i64 tmp2 = tcg_temp_new_i64(); - - tcg_gen_extu_i32_i64(tmp1, REG(B7_4)); - tcg_gen_extu_i32_i64(tmp2, REG(B11_8)); - tcg_gen_mul_i64(tmp1, tmp1, tmp2); - tcg_gen_trunc_i64_i32(cpu_macl, tmp1); - tcg_gen_shri_i64(tmp1, tmp1, 32); - tcg_gen_trunc_i64_i32(cpu_mach, tmp1); - - tcg_temp_free_i64(tmp2); - tcg_temp_free_i64(tmp1); - } +tcg_gen_mulu2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8)); return; case 0x600e: /* exts.b Rm,Rn */ tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4)); -- 1.8.1.2
Re: [Qemu-devel] [PATCH 2/2] coroutine: trim down nesting level in perf_nesting test
On Tue, Feb 19, 2013 at 11:59:10AM +0100, Paolo Bonzini wrote: 2 nested coroutines require 20 GB of virtual address space. Only nest 1000 of them so that the test (only enabled with -m perf on the command line) runs on 32-bit machines too. Cc: qemu-sta...@nongnu.org Signed-off-by: Paolo Bonzini pbonz...@redhat.com --- tests/test-coroutine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Okay, 2 nesting level was unrealistic and QEMU will never approach that in reality. 1000 is fine. Reviewed-by: Stefan Hajnoczi stefa...@redhat.com
Re: [Qemu-devel] [PATCH 1/2] coroutine: move pooling to common code
On Tue, Feb 19, 2013 at 11:59:09AM +0100, Paolo Bonzini wrote: The coroutine pool code is duplicated between the ucontext and sigaltstack backends, and absent from the win32 backend. But the code can be shared easily by moving it to qemu-coroutine.c. Signed-off-by: Paolo Bonzini pbonz...@redhat.com --- coroutine-sigaltstack.c | 43 +-- coroutine-ucontext.c| 43 +-- qemu-coroutine.c| 45 +++-- 3 files changed, 45 insertions(+), 86 deletions(-) Reviewed-by: Stefan Hajnoczi stefa...@redhat.com
[Qemu-devel] [PATCH 31/38] target-ppc: Compute arithmetic shift carry without branches
Cc: Alexander Graf ag...@suse.de Signed-off-by: Richard Henderson r...@twiddle.net --- target-ppc/translate.c | 71 ++ 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 05f93f6..439 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -1773,30 +1773,25 @@ static void gen_sraw(DisasContext *ctx) static void gen_srawi(DisasContext *ctx) { int sh = SH(ctx-opcode); -if (sh != 0) { -int l1, l2; -TCGv t0; -l1 = gen_new_label(); -l2 = gen_new_label(); -t0 = tcg_temp_local_new(); -tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx-opcode)]); -tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1); -tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx-opcode)], (1ULL sh) - 1); -tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); -tcg_gen_movi_tl(cpu_ca, 1); -tcg_gen_br(l2); -gen_set_label(l1); +TCGv dst = cpu_gpr[rA(ctx-opcode)]; +TCGv src = cpu_gpr[rS(ctx-opcode)]; +if (sh == 0) { +tcg_gen_mov_tl(dst, src); tcg_gen_movi_tl(cpu_ca, 0); -gen_set_label(l2); -tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx-opcode)]); -tcg_gen_sari_tl(cpu_gpr[rA(ctx-opcode)], t0, sh); -tcg_temp_free(t0); } else { -tcg_gen_mov_tl(cpu_gpr[rA(ctx-opcode)], cpu_gpr[rS(ctx-opcode)]); -tcg_gen_movi_tl(cpu_ca, 0); +TCGv t0; +tcg_gen_ext32s_tl(dst, src); +tcg_gen_andi_tl(cpu_ca, dst, (1ULL sh) - 1); +t0 = tcg_temp_new(); +tcg_gen_sari_tl(t0, dst, TARGET_LONG_BITS - 1); +tcg_gen_and_tl(cpu_ca, cpu_ca, t0); +tcg_temp_free(t0); +tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0); +tcg_gen_sari_tl(dst, dst, sh); +} +if (unlikely(Rc(ctx-opcode) != 0)) { +gen_set_Rc0(ctx, dst); } -if (unlikely(Rc(ctx-opcode) != 0)) -gen_set_Rc0(ctx, cpu_gpr[rA(ctx-opcode)]); } /* srw srw. */ @@ -1856,28 +1851,24 @@ static void gen_srad(DisasContext *ctx) static inline void gen_sradi(DisasContext *ctx, int n) { int sh = SH(ctx-opcode) + (n 5); -if (sh != 0) { -int l1, l2; -TCGv t0; -l1 = gen_new_label(); -l2 = gen_new_label(); -t0 = tcg_temp_local_new(); -tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx-opcode)], 0, l1); -tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx-opcode)], (1ULL sh) - 1); -tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); -tcg_gen_movi_tl(cpu_ca, 1); -tcg_gen_br(l2); -gen_set_label(l1); +TCGv dst = cpu_gpr[rA(ctx-opcode)]; +TCGv src = cpu_gpr[rS(ctx-opcode)]; +if (sh == 0) { +tcg_gen_mov_tl(dst, src); tcg_gen_movi_tl(cpu_ca, 0); -gen_set_label(l2); -tcg_temp_free(t0); -tcg_gen_sari_tl(cpu_gpr[rA(ctx-opcode)], cpu_gpr[rS(ctx-opcode)], sh); } else { -tcg_gen_mov_tl(cpu_gpr[rA(ctx-opcode)], cpu_gpr[rS(ctx-opcode)]); -tcg_gen_movi_tl(cpu_ca, 0); +TCGv t0; +tcg_gen_andi_tl(cpu_ca, src, (1ULL sh) - 1); +t0 = tcg_temp_new(); +tcg_gen_sari_tl(t0, src, TARGET_LONG_BITS - 1); +tcg_gen_and_tl(cpu_ca, cpu_ca, t0); +tcg_temp_free(t0); +tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0); +tcg_gen_sari_tl(dst, src, sh); +} +if (unlikely(Rc(ctx-opcode) != 0)) { +gen_set_Rc0(ctx, dst); } -if (unlikely(Rc(ctx-opcode) != 0)) -gen_set_Rc0(ctx, cpu_gpr[rA(ctx-opcode)]); } static void gen_sradi0(DisasContext *ctx) -- 1.8.1.2
[Qemu-devel] [PATCH 29/38] target-ppc: Use add2 for carry generation
Cc: Alexander Graf ag...@suse.de Signed-off-by: Richard Henderson r...@twiddle.net --- target-ppc/translate.c | 194 ++--- 1 file changed, 69 insertions(+), 125 deletions(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index fce261b..abc75e2 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -765,73 +765,40 @@ static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov); } -static inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1, - TCGv arg2, int sub) -{ -TCGv t0 = tcg_temp_new(), t1 = arg1, t2 = arg2; - -#if defined(TARGET_PPC64) -if (!(ctx-sf_mode)) { -t1 = t0; -tcg_gen_ext32u_tl(t1, arg1); -t2 = tcg_temp_new(); -tcg_gen_ext32u_tl(t2, arg2); -} -#endif - -tcg_gen_setcond_tl(sub ? TCG_COND_LEU : TCG_COND_LTU, t0, t1, t2); -tcg_gen_or_tl(cpu_ca, cpu_ca, t0); - -tcg_temp_free(t0); -#if defined(TARGET_PPC64) -if (!(ctx-sf_mode)) { -tcg_temp_free(t2); -} -#endif -} - /* Common add function */ static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1, -TCGv arg2, int add_ca, int compute_ca, -int compute_ov) +TCGv arg2, bool add_ca, bool compute_ca, +bool compute_ov, bool compute_rc0) { -TCGv t0, t1; +TCGv t0 = ret; -if ((!compute_ca !compute_ov) || -(!TCGV_EQUAL(ret,arg1) !TCGV_EQUAL(ret, arg2))) { -t0 = ret; -} else { +if (((compute_ca add_ca) || compute_ov) + (TCGV_EQUAL(ret, arg1) || TCGV_EQUAL(ret, arg2))) { t0 = tcg_temp_new(); } -if (add_ca) { -t1 = tcg_temp_local_new(); -tcg_gen_mov_tl(t1, cpu_ca); -} else { -TCGV_UNUSED(t1); -} - if (compute_ca) { -/* Start with XER CA disabled, the most likely case */ -tcg_gen_movi_tl(cpu_ca, 0); +TCGv zero = tcg_const_tl(0); +if (add_ca) { +tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, cpu_ca, zero); +tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, arg2, zero); +} else { +tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, arg2, zero); +} +tcg_temp_free(zero); +} else { +tcg_gen_add_tl(t0, arg1, arg2); +if (add_ca) { +tcg_gen_add_tl(t0, t0, cpu_ca); +} } -tcg_gen_add_tl(t0, arg1, arg2); - -if (compute_ca) { -gen_op_arith_compute_ca(ctx, t0, arg1, 0); -} -if (add_ca) { -tcg_gen_add_tl(t0, t0, t1); -gen_op_arith_compute_ca(ctx, t0, t1, 0); -tcg_temp_free(t1); -} if (compute_ov) { gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0); } - -if (unlikely(Rc(ctx-opcode) != 0)) +if (unlikely(compute_rc0)) { gen_set_Rc0(ctx, t0); +} if (!TCGV_EQUAL(t0, ret)) { tcg_gen_mov_tl(ret, t0); @@ -840,21 +807,21 @@ static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1, } /* Add functions with two operands */ #define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \ -static void glue(gen_, name)(DisasContext *ctx) \ +static void glue(gen_, name)(DisasContext *ctx) \ { \ gen_op_arith_add(ctx, cpu_gpr[rD(ctx-opcode)], \ cpu_gpr[rA(ctx-opcode)], cpu_gpr[rB(ctx-opcode)], \ - add_ca, compute_ca, compute_ov); \ + add_ca, compute_ca, compute_ov, Rc(ctx-opcode));\ } /* Add functions with one operand and one immediate */ #define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,\ add_ca, compute_ca, compute_ov) \ -static void glue(gen_, name)(DisasContext *ctx) \ +static void glue(gen_, name)(DisasContext *ctx) \ { \ -TCGv t0 = tcg_const_local_tl(const_val); \ +TCGv t0 = tcg_const_tl(const_val);\ gen_op_arith_add(ctx, cpu_gpr[rD(ctx-opcode)], \ cpu_gpr[rA(ctx-opcode)], t0,\ - add_ca, compute_ca, compute_ov); \ + add_ca, compute_ca, compute_ov, Rc(ctx-opcode));\ tcg_temp_free(t0);\ } @@ -882,40 +849,27 @@ static void
[Qemu-devel] [PATCH 19/38] target-arm: Use add2 in gen_add_CC
Cc: Peter Maydell peter.mayd...@linaro.org Signed-off-by: Richard Henderson r...@twiddle.net --- target-arm/translate.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/target-arm/translate.c b/target-arm/translate.c index efe76d0..ca6f0af 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -410,12 +410,11 @@ static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1) /* dest = T0 + T1. Compute C, N, V and Z flags */ static void gen_add_CC(TCGv dest, TCGv t0, TCGv t1) { -TCGv tmp; -tcg_gen_add_i32(cpu_NF, t0, t1); +TCGv tmp = tcg_temp_new_i32(); +tcg_gen_movi_i32(tmp, 0); +tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp); tcg_gen_mov_i32(cpu_ZF, cpu_NF); -tcg_gen_setcond_i32(TCG_COND_LTU, cpu_CF, cpu_NF, t0); tcg_gen_xor_i32(cpu_VF, cpu_NF, t0); -tmp = tcg_temp_new_i32(); tcg_gen_xor_i32(tmp, t0, t1); tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp); tcg_temp_free_i32(tmp); -- 1.8.1.2
[Qemu-devel] [PATCH 27/38] target-ppc: Compute addition overflow without branches
Cc: Alexander Graf ag...@suse.de Signed-off-by: Richard Henderson r...@twiddle.net --- target-ppc/translate.c | 46 +- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 7aab6ae..116cf12 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -746,35 +746,23 @@ static void gen_isel(DisasContext *ctx) static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, TCGv arg1, TCGv arg2, int sub) { -int l1; -TCGv t0; +TCGv t0 = tcg_temp_new(); -l1 = gen_new_label(); -/* Start with XER OV disabled, the most likely case */ -tcg_gen_movi_tl(cpu_ov, 0); -t0 = tcg_temp_local_new(); -tcg_gen_xor_tl(t0, arg0, arg1); -#if defined(TARGET_PPC64) -if (!ctx-sf_mode) -tcg_gen_ext32s_tl(t0, t0); -#endif -if (sub) -tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1); -else -tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1); +tcg_gen_xor_tl(cpu_ov, arg0, arg1); tcg_gen_xor_tl(t0, arg1, arg2); +if (sub) { +tcg_gen_and_tl(cpu_ov, cpu_ov, t0); +} else { +tcg_gen_andc_tl(cpu_ov, cpu_ov, t0); +} +tcg_temp_free(t0); #if defined(TARGET_PPC64) -if (!ctx-sf_mode) -tcg_gen_ext32s_tl(t0, t0); +if (!ctx-sf_mode) { +tcg_gen_ext32s_tl(cpu_ov, cpu_ov); +} #endif -if (sub) -tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1); -else -tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1); -tcg_gen_movi_tl(cpu_ov, 1); -tcg_gen_movi_tl(cpu_so, 1); -gen_set_label(l1); -tcg_temp_free(t0); +tcg_gen_shri_tl(cpu_ov, cpu_ov, TARGET_LONG_BITS - 1); +tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov); } static inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1, @@ -837,10 +825,6 @@ static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1, /* Start with XER CA disabled, the most likely case */ tcg_gen_movi_tl(cpu_ca, 0); } -if (compute_ov) { -/* Start with XER OV disabled, the most likely case */ -tcg_gen_movi_tl(cpu_ov, 0); -} tcg_gen_add_tl(t0, arg1, arg2); @@ -1261,10 +1245,6 @@ static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1, /* Start with XER CA disabled, the most likely case */ tcg_gen_movi_tl(cpu_ca, 0); } -if (compute_ov) { -/* Start with XER OV disabled, the most likely case */ -tcg_gen_movi_tl(cpu_ov, 0); -} if (add_ca) { tcg_gen_not_tl(t0, arg1); -- 1.8.1.2
[Qemu-devel] [PATCH] tap: forbid creating multiqueue tap when hub is used
Obviously, hub does not support multiqueue tap. So this patch forbids creating multiple queue tap when hub is used to prevent the crash when command line such as -net tap,queues=2 is used. Signed-off-by: Jason Wang jasow...@redhat.com --- This patch is needed for 1.4 stable also. --- net/tap.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/net/tap.c b/net/tap.c index 48c254e..1e14f59 100644 --- a/net/tap.c +++ b/net/tap.c @@ -693,6 +693,12 @@ int net_init_tap(const NetClientOptions *opts, const char *name, queues = tap-has_queues ? tap-queues : 1; vhostfdname = tap-has_vhostfd ? tap-vhostfd : NULL; +if (peer (tap-has_queues || tap-has_fds || tap-has_vhostfds)) { +error_report(This configuration is not compatiable with multiqueue + tap); +return -1; +} + if (tap-has_fd) { if (tap-has_ifname || tap-has_script || tap-has_downscript || tap-has_vnet_hdr || tap-has_helper || tap-has_queues || -- 1.7.1
Re: [Qemu-devel] [PATCH v9 1/3] iov: Factor out hexdumper
Hi, Done, thanks for the correction. Do you have a lightweight test vector that exercises this? The iovec stuff in my areas is all limited to single iovec element. Interdiff below. hw/usb/dev-network.c (with TRAFFC_DEBUG) calls this on usb packets which could trigger this in theory. Depends on how the guest allocates the usb packet buffers though, so I'm not fully sure whenever that actually triggers in practice. @@ -202,11 +202,16 @@ void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt, FILE *fp, const char *prefix, size_t limit) { int v; -for (v = 0; v iov_cnt limit; v++) { -int size = limit iov[v].iov_len ? limit : iov[v].iov_len; -hexdump(iov[v].iov_base, fp, prefix, size); -limit -= size; +size_t size = 0; +char *buf; + +for (v = 0; v iov_cnt; v++) { +size += iov[v].iov_len; } +size = size limit ? limit : size; +buf = g_malloc(size); +iov_to_buf(iov, iov_cnt, 0, buf, size); You've lost the actual hexdump() call here ;) +g_free(buf); Otherwise it looks fine. cheers, Gerd
Re: [Qemu-devel] [PATCH V4 RESEND 15/22] tap: multiqueue support
On 02/11/2013 06:28 PM, Markus Armbruster wrote: Commit 264986e2 extended NetdevTapOptions without updating the documentation. Hasn't been addressed since. Must fix for 1.4, in my opinion. Will send a patch to fix this. Thanks This is the offending patch: Jason Wang jasow...@redhat.com writes: Recently, linux support multiqueue tap which could let userspace call TUNSETIFF for a signle device many times to create multiple file descriptors as independent queues. User could also enable/disabe a specific queue through TUNSETQUEUE. The patch adds the generic infrastructure to create multiqueue taps. To achieve this a new parameter queues were introduced to specify how many queues were expected to be created for tap by qemu itself. Alternatively, management could also pass multiple pre-created tap file descriptors separated with ':' through a new parameter fds like -netdev tap,id=hn0,fds=X:Y:..:Z. Multiple vhost file descriptors could also be passed in this way. Each TAPState were still associated to a tap fd, which mean multiple TAPStates were created when user needs multiqueue taps. Since each TAPState contains one NetClientState, with the multiqueue nic support, an N peers of NetClientState were built up. A new parameter, mq_required were introduce in tap_open() to create multiqueue tap fds. [...] diff --git a/qapi-schema.json b/qapi-schema.json index 3a4817b..cdd8384 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2533,6 +2533,7 @@ 'data': { '*ifname': 'str', '*fd': 'str', +'*fds':'str', '*script': 'str', '*downscript': 'str', '*helper': 'str', @@ -2540,7 +2541,9 @@ '*vnet_hdr': 'bool', '*vhost': 'bool', '*vhostfd':'str', -'*vhostforce': 'bool' } } +'*vhostfds': 'str', +'*vhostforce': 'bool', +'*queues': 'uint32'} } ## # @NetdevSocketOptions
[Qemu-devel] [PATCH 01/38] tcg: Make 32-bit multiword operations optional for 64-bit hosts
Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/i386/tcg-target.h | 4 tcg/ia64/tcg-target.h | 3 +++ tcg/ppc64/tcg-target.h | 3 +++ tcg/s390/tcg-target.h | 3 +++ tcg/sparc/tcg-target.h | 4 tcg/tcg-opc.h | 6 +++--- tcg/tcg.h | 6 +- tcg/tci/tcg-target.h | 4 8 files changed, 29 insertions(+), 4 deletions(-) diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index e63db9c..43ad2c4 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -114,6 +114,10 @@ typedef enum { #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 1 #define TCG_TARGET_HAS_movcond_i64 1 + +#define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_mulu2_i320 #endif #define TCG_TARGET_deposit_i32_valid(ofs, len) \ diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index 7f3401e..b4ff7c3 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -136,6 +136,9 @@ typedef enum { #define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_deposit_i32 1 #define TCG_TARGET_HAS_deposit_i64 1 +#define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_mulu2_i320 #define TCG_TARGET_deposit_i32_valid(ofs, len) ((len) = 16) #define TCG_TARGET_deposit_i64_valid(ofs, len) ((len) = 16) diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h index 9b8e9a0..ea976ad 100644 --- a/tcg/ppc64/tcg-target.h +++ b/tcg/ppc64/tcg-target.h @@ -85,6 +85,9 @@ typedef enum { #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 0 #define TCG_TARGET_HAS_movcond_i32 0 +#define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_mulu2_i320 #define TCG_TARGET_HAS_div_i64 1 #define TCG_TARGET_HAS_rot_i64 0 diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h index c87b413..7772c35 100644 --- a/tcg/s390/tcg-target.h +++ b/tcg/s390/tcg-target.h @@ -65,6 +65,9 @@ typedef enum TCGReg { #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 0 #define TCG_TARGET_HAS_movcond_i32 0 +#define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_mulu2_i320 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div2_i64 1 diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index 256f973..6c62e45 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -124,6 +124,10 @@ typedef enum { #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 0 #define TCG_TARGET_HAS_movcond_i64 1 + +#define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_mulu2_i320 #endif #define TCG_AREG0 TCG_REG_I0 diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index 9651063..1d9a9a2 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -83,10 +83,10 @@ DEF(deposit_i32, 1, 2, 2, IMPL(TCG_TARGET_HAS_deposit_i32)) DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END) -DEF(add2_i32, 2, 4, 0, IMPL(TCG_TARGET_REG_BITS == 32)) -DEF(sub2_i32, 2, 4, 0, IMPL(TCG_TARGET_REG_BITS == 32)) +DEF(add2_i32, 2, 4, 0, IMPL(TCG_TARGET_HAS_add2_i32)) +DEF(sub2_i32, 2, 4, 0, IMPL(TCG_TARGET_HAS_sub2_i32)) +DEF(mulu2_i32, 2, 2, 0, IMPL(TCG_TARGET_HAS_mulu2_i32)) DEF(brcond2_i32, 0, 4, 2, TCG_OPF_BB_END | IMPL(TCG_TARGET_REG_BITS == 32)) -DEF(mulu2_i32, 2, 2, 0, IMPL(TCG_TARGET_REG_BITS == 32)) DEF(setcond2_i32, 1, 4, 1, IMPL(TCG_TARGET_REG_BITS == 32)) DEF(ext8s_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext8s_i32)) diff --git a/tcg/tcg.h b/tcg/tcg.h index 51c8176..e5c7ce4 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -57,8 +57,8 @@ typedef uint64_t TCGRegSet; #error unsupported #endif -/* Turn some undef macros into false macros. */ #if TCG_TARGET_REG_BITS == 32 +/* Turn some undef macros into false macros. */ #define TCG_TARGET_HAS_div_i64 0 #define TCG_TARGET_HAS_div2_i64 0 #define TCG_TARGET_HAS_rot_i64 0 @@ -80,6 +80,10 @@ typedef uint64_t TCGRegSet; #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 0 #define TCG_TARGET_HAS_movcond_i64 0 +/* Turn some undef macros into true macros. */ +#define TCG_TARGET_HAS_add2_i32 1 +#define TCG_TARGET_HAS_sub2_i32 1 +#define TCG_TARGET_HAS_mulu2_i321 #endif #ifndef TCG_TARGET_deposit_i32_valid diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h index a832f5c..3e235bd 100644 --- a/tcg/tci/tcg-target.h +++ b/tcg/tci/tcg-target.h @@ -100,6 +100,10 @@ #define TCG_TARGET_HAS_orc_i64 0 #define TCG_TARGET_HAS_rot_i64 1 #define TCG_TARGET_HAS_movcond_i64 0 + +#define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_mulu2_i320
[Qemu-devel] [PATCH 22/38] target-mips: Use mul[us]2 in [D]MULT[U] insns
Cc: Aurelien Jarno aurel...@aurel32.net Signed-off-by: Richard Henderson r...@twiddle.net --- target-mips/helper.h| 2 -- target-mips/op_helper.c | 12 target-mips/translate.c | 48 3 files changed, 20 insertions(+), 42 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index cd48738..ed75e2c 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -24,8 +24,6 @@ DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, tl, tl) #ifdef TARGET_MIPS64 DEF_HELPER_FLAGS_1(dclo, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(dclz, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_3(dmult, void, env, tl, tl) -DEF_HELPER_3(dmultu, void, env, tl, tl) #endif DEF_HELPER_3(muls, tl, env, tl, tl) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 526f84f..45cbb2f 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -267,18 +267,6 @@ target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1, (uint64_t)(uint32_t)arg2); } -#ifdef TARGET_MIPS64 -void helper_dmult(CPUMIPSState *env, target_ulong arg1, target_ulong arg2) -{ -muls64((env-active_tc.LO[0]), (env-active_tc.HI[0]), arg1, arg2); -} - -void helper_dmultu(CPUMIPSState *env, target_ulong arg1, target_ulong arg2) -{ -mulu64((env-active_tc.LO[0]), (env-active_tc.HI[0]), arg1, arg2); -} -#endif - #ifndef CONFIG_USER_ONLY static inline hwaddr do_translate_address(CPUMIPSState *env, diff --git a/target-mips/translate.c b/target-mips/translate.c index 4ee9615..f10a533 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -2715,47 +2715,39 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, break; case OPC_MULT: { -TCGv_i64 t2 = tcg_temp_new_i64(); -TCGv_i64 t3 = tcg_temp_new_i64(); +TCGv_i32 t2 = tcg_temp_new_i32(); +TCGv_i32 t3 = tcg_temp_new_i32(); acc = ((ctx-opcode) 11) 0x03; if (acc != 0) { check_dsp(ctx); } -tcg_gen_ext_tl_i64(t2, t0); -tcg_gen_ext_tl_i64(t3, t1); -tcg_gen_mul_i64(t2, t2, t3); -tcg_temp_free_i64(t3); -tcg_gen_trunc_i64_tl(t0, t2); -tcg_gen_shri_i64(t2, t2, 32); -tcg_gen_trunc_i64_tl(t1, t2); -tcg_temp_free_i64(t2); -tcg_gen_ext32s_tl(cpu_LO[acc], t0); -tcg_gen_ext32s_tl(cpu_HI[acc], t1); +tcg_gen_trunc_tl_i32(t2, t0); +tcg_gen_trunc_tl_i32(t3, t1); +tcg_gen_muls2_i32(t2, t3, t2, t3); +tcg_gen_ext_i32_tl(cpu_LO[acc], t2); +tcg_gen_ext_i32_tl(cpu_HI[acc], t3); +tcg_temp_free_i32(t2); +tcg_temp_free_i32(t3); } opn = mult; break; case OPC_MULTU: { -TCGv_i64 t2 = tcg_temp_new_i64(); -TCGv_i64 t3 = tcg_temp_new_i64(); +TCGv_i32 t2 = tcg_temp_new_i32(); +TCGv_i32 t3 = tcg_temp_new_i32(); acc = ((ctx-opcode) 11) 0x03; if (acc != 0) { check_dsp(ctx); } -tcg_gen_ext32u_tl(t0, t0); -tcg_gen_ext32u_tl(t1, t1); -tcg_gen_extu_tl_i64(t2, t0); -tcg_gen_extu_tl_i64(t3, t1); -tcg_gen_mul_i64(t2, t2, t3); -tcg_temp_free_i64(t3); -tcg_gen_trunc_i64_tl(t0, t2); -tcg_gen_shri_i64(t2, t2, 32); -tcg_gen_trunc_i64_tl(t1, t2); -tcg_temp_free_i64(t2); -tcg_gen_ext32s_tl(cpu_LO[acc], t0); -tcg_gen_ext32s_tl(cpu_HI[acc], t1); +tcg_gen_trunc_tl_i32(t2, t0); +tcg_gen_trunc_tl_i32(t3, t1); +tcg_gen_mulu2_i32(t2, t3, t2, t3); +tcg_gen_ext_i32_tl(cpu_LO[acc], t2); +tcg_gen_ext_i32_tl(cpu_HI[acc], t3); +tcg_temp_free_i32(t2); +tcg_temp_free_i32(t3); } opn = multu; break; @@ -2791,11 +2783,11 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, opn = ddivu; break; case OPC_DMULT: -gen_helper_dmult(cpu_env, t0, t1); +tcg_gen_muls2_i64(cpu_LO[0], cpu_HI[0], t0, t1); opn = dmult; break; case OPC_DMULTU: -gen_helper_dmultu(cpu_env, t0, t1); +tcg_gen_mulu2_i64(cpu_LO[0], cpu_HI[0], t0, t1); opn = dmultu; break; #endif -- 1.8.1.2
[Qemu-devel] [PATCH 18/38] target-arm: Use mul[us]2 and add2 in umlal et al
Cc: Peter Maydell peter.mayd...@linaro.org Signed-off-by: Richard Henderson r...@twiddle.net --- target-arm/helper.c| 5 - target-arm/helper.h| 2 -- target-arm/translate.c | 26 ++ 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index e63da57..e97e1a5 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2893,11 +2893,6 @@ uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b) return (a mask) | (b ~mask); } -uint32_t HELPER(logicq_cc)(uint64_t val) -{ -return (val 32) | (val != 0); -} - /* VFP support. We follow the convention used for VFP instructions: Single precision routines have a s suffix, double precision a d suffix. */ diff --git a/target-arm/helper.h b/target-arm/helper.h index 8544f82..bca5a5b 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -46,8 +46,6 @@ DEF_HELPER_3(usat16, i32, env, i32, i32) DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32) -DEF_HELPER_1(logicq_cc, i32, i64) - DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_2(exception, void, env, i32) diff --git a/target-arm/translate.c b/target-arm/translate.c index 129f674..efe76d0 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -6433,13 +6433,11 @@ static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh) tcg_temp_free_i64(tmp); } -/* Set N and Z flags from a 64-bit value. */ -static void gen_logicq_cc(TCGv_i64 val) +/* Set N and Z flags from hi|lo. */ +static void gen_logicq_cc(TCGv lo, TCGv hi) { -TCGv tmp = tcg_temp_new_i32(); -gen_helper_logicq_cc(tmp, val); -gen_logic_CC(tmp); -tcg_temp_free_i32(tmp); +tcg_gen_mov_i32(cpu_NF, hi); +tcg_gen_or_i32(cpu_ZF, lo, hi); } /* Load/Store exclusive instructions are implemented by remembering @@ -7219,18 +7217,22 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) tmp = load_reg(s, rs); tmp2 = load_reg(s, rm); if (insn (1 22)) { -tmp64 = gen_muls_i64_i32(tmp, tmp2); +tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2); } else { -tmp64 = gen_mulu_i64_i32(tmp, tmp2); +tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2); } if (insn (1 21)) { /* mult accumulate */ -gen_addq(s, tmp64, rn, rd); +TCGv al = load_reg(s, rn); +TCGv ah = load_reg(s, rd); +tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah); +tcg_temp_free(al); +tcg_temp_free(ah); } if (insn (1 20)) { -gen_logicq_cc(tmp64); +gen_logicq_cc(tmp, tmp2); } -gen_storeq_reg(s, rn, rd, tmp64); -tcg_temp_free_i64(tmp64); +store_reg(s, rn, tmp); +store_reg(s, rd, tmp2); break; default: goto illegal_op; -- 1.8.1.2
[Qemu-devel] [PATCH 23/38] target-cris: Use mul*2 in mul* insns
Cc: Edgar E. Iglesias edgar.igles...@gmail.com Signed-off-by: Richard Henderson r...@twiddle.net --- target-cris/translate.c | 44 ++-- 1 file changed, 2 insertions(+), 42 deletions(-) diff --git a/target-cris/translate.c b/target-cris/translate.c index 04a5379..df4dbd3 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -340,46 +340,6 @@ static void t_gen_asr(TCGv d, TCGv a, TCGv b) tcg_temp_free(t_31); } -/* 64-bit signed mul, lower result in d and upper in d2. */ -static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b) -{ -TCGv_i64 t0, t1; - -t0 = tcg_temp_new_i64(); -t1 = tcg_temp_new_i64(); - -tcg_gen_ext_i32_i64(t0, a); -tcg_gen_ext_i32_i64(t1, b); -tcg_gen_mul_i64(t0, t0, t1); - -tcg_gen_trunc_i64_i32(d, t0); -tcg_gen_shri_i64(t0, t0, 32); -tcg_gen_trunc_i64_i32(d2, t0); - -tcg_temp_free_i64(t0); -tcg_temp_free_i64(t1); -} - -/* 64-bit unsigned muls, lower result in d and upper in d2. */ -static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b) -{ -TCGv_i64 t0, t1; - -t0 = tcg_temp_new_i64(); -t1 = tcg_temp_new_i64(); - -tcg_gen_extu_i32_i64(t0, a); -tcg_gen_extu_i32_i64(t1, b); -tcg_gen_mul_i64(t0, t0, t1); - -tcg_gen_trunc_i64_i32(d, t0); -tcg_gen_shri_i64(t0, t0, 32); -tcg_gen_trunc_i64_i32(d2, t0); - -tcg_temp_free_i64(t0); -tcg_temp_free_i64(t1); -} - static void t_gen_cris_dstep(TCGv d, TCGv a, TCGv b) { int l1; @@ -832,10 +792,10 @@ static void cris_alu_op_exec(DisasContext *dc, int op, gen_helper_lz(dst, b); break; case CC_OP_MULS: -t_gen_muls(dst, cpu_PR[PR_MOF], a, b); +tcg_gen_muls2_tl(dst, cpu_PR[PR_MOF], a, b); break; case CC_OP_MULU: -t_gen_mulu(dst, cpu_PR[PR_MOF], a, b); +tcg_gen_mulu2_tl(dst, cpu_PR[PR_MOF], a, b); break; case CC_OP_DSTEP: t_gen_cris_dstep(dst, a, b); -- 1.8.1.2
[Qemu-devel] [PATCH 11/38] target-i386: Use mulu2 and muls2
These correspond very closely to the insns that we're emulating. Signed-off-by: Richard Henderson r...@twiddle.net --- target-i386/helper.h | 4 -- target-i386/int_helper.c | 40 target-i386/translate.c | 167 --- 3 files changed, 56 insertions(+), 155 deletions(-) diff --git a/target-i386/helper.h b/target-i386/helper.h index 26a0cc8..d6974df 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -14,12 +14,8 @@ DEF_HELPER_2(idivw_AX, void, env, tl) DEF_HELPER_2(divl_EAX, void, env, tl) DEF_HELPER_2(idivl_EAX, void, env, tl) #ifdef TARGET_X86_64 -DEF_HELPER_2(mulq_EAX_T0, void, env, tl) -DEF_HELPER_2(imulq_EAX_T0, void, env, tl) -DEF_HELPER_3(imulq_T0_T1, tl, env, tl, tl) DEF_HELPER_2(divq_EAX, void, env, tl) DEF_HELPER_2(idivq_EAX, void, env, tl) -DEF_HELPER_FLAGS_2(umulh, TCG_CALL_NO_RWG_SE, tl, tl, tl) #endif DEF_HELPER_2(aam, void, env, int) diff --git a/target-i386/int_helper.c b/target-i386/int_helper.c index 3b56075..74c7c36 100644 --- a/target-i386/int_helper.c +++ b/target-i386/int_helper.c @@ -374,46 +374,6 @@ static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b) return 0; } -void helper_mulq_EAX_T0(CPUX86State *env, target_ulong t0) -{ -uint64_t r0, r1; - -mulu64(r0, r1, EAX, t0); -EAX = r0; -EDX = r1; -CC_DST = r0; -CC_SRC = r1; -} - -target_ulong helper_umulh(target_ulong t0, target_ulong t1) -{ -uint64_t h, l; -mulu64(l, h, t0, t1); -return h; -} - -void helper_imulq_EAX_T0(CPUX86State *env, target_ulong t0) -{ -uint64_t r0, r1; - -muls64(r0, r1, EAX, t0); -EAX = r0; -EDX = r1; -CC_DST = r0; -CC_SRC = ((int64_t)r1 != ((int64_t)r0 63)); -} - -target_ulong helper_imulq_T0_T1(CPUX86State *env, target_ulong t0, -target_ulong t1) -{ -uint64_t r0, r1; - -muls64(r0, r1, t0, t1); -CC_DST = r0; -CC_SRC = ((int64_t)r1 != ((int64_t)r0 63)); -return r0; -} - void helper_divq_EAX(CPUX86State *env, target_ulong t0) { uint64_t r0, r1; diff --git a/target-i386/translate.c b/target-i386/translate.c index 439d19e..1545e3f 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -4111,31 +4111,18 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, ot = s-dflag == 2 ? OT_QUAD : OT_LONG; gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); switch (ot) { -TCGv_i64 t0, t1; default: -t0 = tcg_temp_new_i64(); -t1 = tcg_temp_new_i64(); -#ifdef TARGET_X86_64 -tcg_gen_ext32u_i64(t0, cpu_T[0]); -tcg_gen_ext32u_i64(t1, cpu_regs[R_EDX]); -#else -tcg_gen_extu_i32_i64(t0, cpu_T[0]); -tcg_gen_extu_i32_i64(t0, cpu_regs[R_EDX]); -#endif -tcg_gen_mul_i64(t0, t0, t1); -tcg_gen_trunc_i64_tl(cpu_T[0], t0); -tcg_gen_shri_i64(t0, t0, 32); -tcg_gen_trunc_i64_tl(cpu_T[1], t0); -tcg_temp_free_i64(t0); -tcg_temp_free_i64(t1); -gen_op_mov_reg_T0(OT_LONG, s-vex_v); -gen_op_mov_reg_T1(OT_LONG, reg); +tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); +tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]); +tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32, + cpu_tmp2_i32, cpu_tmp3_i32); +tcg_gen_extu_i32_tl(cpu_regs[s-vex_v], cpu_tmp2_i32); +tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32); break; #ifdef TARGET_X86_64 case OT_QUAD: -tcg_gen_mov_tl(cpu_T[1], cpu_regs[R_EDX]); -tcg_gen_mul_tl(cpu_regs[s-vex_v], cpu_T[0], cpu_T[1]); -gen_helper_umulh(cpu_regs[reg], cpu_T[0], cpu_T[1]); +tcg_gen_mulu2_i64(cpu_regs[s-vex_v], cpu_regs[reg], + cpu_T[0], cpu_regs[R_EDX]); break; #endif } @@ -5034,39 +5021,22 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, break; default: case OT_LONG: -#ifdef TARGET_X86_64 -gen_op_mov_TN_reg(OT_LONG, 1, R_EAX); -tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); -tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); -tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); -gen_op_mov_reg_T0(OT_LONG, R_EAX); -tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); -tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32); -gen_op_mov_reg_T0(OT_LONG, R_EDX); -tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]); -#else -{ -TCGv_i64 t0, t1; -
[Qemu-devel] [PATCH 25/38] target-ppc: Split out SO, OV, CA fields from XER
In preparation for more efficient setting of these fields. Cc: Alexander Graf ag...@suse.de Signed-off-by: Richard Henderson r...@twiddle.net --- target-ppc/cpu.h| 24 +- target-ppc/int_helper.c | 38 - target-ppc/kvm.c| 4 +- target-ppc/machine.c| 8 +- target-ppc/translate.c | 188 +++- target-ppc/translate_init.c | 4 +- 6 files changed, 160 insertions(+), 106 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 8c081db..20f4565 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -941,8 +941,11 @@ struct CPUPPCState { /* CFAR */ target_ulong cfar; #endif -/* XER */ +/* XER (with SO, OV, CA split out) */ target_ulong xer; +target_ulong so; +target_ulong ov; +target_ulong ca; /* Reservation address */ target_ulong reserve_addr; /* Reservation value */ @@ -1268,9 +1271,9 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp) #define XER_CA 29 #define XER_CMP 8 #define XER_BC 0 -#define xer_so ((env-xer XER_SO) 1) -#define xer_ov ((env-xer XER_OV) 1) -#define xer_ca ((env-xer XER_CA) 1) +#define xer_so (env-so) +#define xer_ov (env-ov) +#define xer_ca (env-ca) #define xer_cmp ((env-xer XER_CMP) 0xFF) #define xer_bc ((env-xer XER_BC) 0x7F) @@ -2087,6 +2090,19 @@ enum { /*/ +static inline target_ulong cpu_read_xer(CPUPPCState *env) +{ +return env-xer | (env-so XER_SO) | (env-ov XER_OV) | (env-ca XER_CA); +} + +static inline void cpu_write_xer(CPUPPCState *env, target_ulong xer) +{ +env-so = (xer XER_SO) 1; +env-ov = (xer XER_OV) 1; +env-ca = (xer XER_CA) 1; +env-xer = xer ~((1u XER_SO) | (1u XER_OV) | (1u XER_CA)); +} + static inline void cpu_get_tb_cpu_state(CPUPPCState *env, target_ulong *pc, target_ulong *cs_base, int *flags) { diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c index 8653151..54eca9b 100644 --- a/target-ppc/int_helper.c +++ b/target-ppc/int_helper.c @@ -33,9 +33,9 @@ uint64_t helper_mulldo(CPUPPCState *env, uint64_t arg1, uint64_t arg2) muls64(tl, (uint64_t *)th, arg1, arg2); /* If th != 0 th != -1, then we had an overflow */ if (likely((uint64_t)(th + 1) = 1)) { -env-xer = ~(1 XER_OV); +env-ov = 0; } else { -env-xer |= (1 XER_OV) | (1 XER_SO); +env-so = env-ov = 1; } return (int64_t)tl; } @@ -64,21 +64,17 @@ target_ulong helper_sraw(CPUPPCState *env, target_ulong value, shift = 0x1f; ret = (int32_t)value shift; if (likely(ret = 0 || (value ((1 shift) - 1)) == 0)) { -env-xer = ~(1 XER_CA); +env-ca = 0; } else { -env-xer |= (1 XER_CA); +env-ca = 1; } } else { ret = (int32_t)value; -env-xer = ~(1 XER_CA); +env-ca = 0; } } else { ret = (int32_t)value 31; -if (ret) { -env-xer |= (1 XER_CA); -} else { -env-xer = ~(1 XER_CA); -} +env-ca = (ret != 0); } return (target_long)ret; } @@ -94,21 +90,17 @@ target_ulong helper_srad(CPUPPCState *env, target_ulong value, shift = 0x3f; ret = (int64_t)value shift; if (likely(ret = 0 || (value ((1 shift) - 1)) == 0)) { -env-xer = ~(1 XER_CA); +env-ca = 0; } else { -env-xer |= (1 XER_CA); +env-ca = 1; } } else { ret = (int64_t)value; -env-xer = ~(1 XER_CA); +env-ca = 0; } } else { ret = (int64_t)value 63; -if (ret) { -env-xer |= (1 XER_CA); -} else { -env-xer = ~(1 XER_CA); -} +env-ca = (ret != 0); } return ret; } @@ -188,16 +180,16 @@ target_ulong helper_divo(CPUPPCState *env, target_ulong arg1, if (((int32_t)tmp == INT32_MIN (int32_t)arg2 == (int32_t)-1) || (int32_t)arg2 == 0) { -env-xer |= (1 XER_OV) | (1 XER_SO); +env-so = env-ov = 1; env-spr[SPR_MQ] = 0; return INT32_MIN; } else { env-spr[SPR_MQ] = tmp % arg2; tmp /= (int32_t)arg2; if ((int32_t)tmp != tmp) { -env-xer |= (1 XER_OV) | (1 XER_SO); +env-so = env-ov = 1; } else { -env-xer = ~(1 XER_OV); +env-ov = 0; } return tmp; } @@ -221,11 +213,11 @@ target_ulong helper_divso(CPUPPCState *env, target_ulong arg1, { if (((int32_t)arg1 == INT32_MIN (int32_t)arg2 == (int32_t)-1) || (int32_t)arg2 == 0) { -env-xer |=
[Qemu-devel] [PATCH 17/38] target-arm: Use mul[us]2 in gen_mul[us]_i64_i32
Cc: Peter Maydell peter.mayd...@linaro.org Signed-off-by: Richard Henderson r...@twiddle.net --- target-arm/translate.c | 38 ++ 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/target-arm/translate.c b/target-arm/translate.c index a8893f7..129f674 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -305,35 +305,41 @@ static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b) return a; } -/* FIXME: Most targets have native widening multiplication. - It would be good to use that instead of a full wide multiply. */ /* 32x32-64 multiply. Marks inputs as dead. */ static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b) { -TCGv_i64 tmp1 = tcg_temp_new_i64(); -TCGv_i64 tmp2 = tcg_temp_new_i64(); +TCGv lo = tcg_temp_new_i32(); +TCGv hi = tcg_temp_new_i32(); +TCGv_i64 ret; -tcg_gen_extu_i32_i64(tmp1, a); +tcg_gen_mulu2_i32(lo, hi, a, b); tcg_temp_free_i32(a); -tcg_gen_extu_i32_i64(tmp2, b); tcg_temp_free_i32(b); -tcg_gen_mul_i64(tmp1, tmp1, tmp2); -tcg_temp_free_i64(tmp2); -return tmp1; + +ret = tcg_temp_new_i64(); +tcg_gen_concat_i32_i64(ret, lo, hi); +tcg_temp_free(lo); +tcg_temp_free(hi); + +return ret; } static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b) { -TCGv_i64 tmp1 = tcg_temp_new_i64(); -TCGv_i64 tmp2 = tcg_temp_new_i64(); +TCGv lo = tcg_temp_new_i32(); +TCGv hi = tcg_temp_new_i32(); +TCGv_i64 ret; -tcg_gen_ext_i32_i64(tmp1, a); +tcg_gen_muls2_i32(lo, hi, a, b); tcg_temp_free_i32(a); -tcg_gen_ext_i32_i64(tmp2, b); tcg_temp_free_i32(b); -tcg_gen_mul_i64(tmp1, tmp1, tmp2); -tcg_temp_free_i64(tmp2); -return tmp1; + +ret = tcg_temp_new_i64(); +tcg_gen_concat_i32_i64(ret, lo, hi); +tcg_temp_free(lo); +tcg_temp_free(hi); + +return ret; } /* Swap low and high halfwords. */ -- 1.8.1.2
[Qemu-devel] [PATCH 13/38] tcg: Implement muls2 with mulu2
Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/tcg-op.h | 40 1 file changed, 40 insertions(+) diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index dac3b4e..d70b2eb 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -2396,6 +2396,26 @@ static inline void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2); /* Allow the optimizer room to replace muls2 with two moves. */ tcg_gen_op0(INDEX_op_nop); +} else if (TCG_TARGET_REG_BITS == 32 TCG_TARGET_HAS_mulu2_i32) { +TCGv_i32 t0 = tcg_temp_new_i32(); +TCGv_i32 t1 = tcg_temp_new_i32(); +TCGv_i32 t2 = tcg_temp_new_i32(); +TCGv_i32 t3 = tcg_temp_new_i32(); +tcg_gen_op4_i32(INDEX_op_mulu2_i32, t0, t1, arg1, arg2); +/* Allow the optimizer room to replace mulu2 with two moves. */ +tcg_gen_op0(INDEX_op_nop); +/* Adjust for negative inputs. */ +tcg_gen_sari_i32(t2, arg1, 31); +tcg_gen_sari_i32(t3, arg2, 31); +tcg_gen_and_i32(t2, t2, arg2); +tcg_gen_and_i32(t3, t3, arg1); +tcg_gen_sub_i32(rh, t1, t2); +tcg_gen_sub_i32(rh, rh, t3); +tcg_gen_mov_i32(rl, t0); +tcg_temp_free_i32(t0); +tcg_temp_free_i32(t1); +tcg_temp_free_i32(t2); +tcg_temp_free_i32(t3); } else { TCGv_i64 t0 = tcg_temp_new_i64(); TCGv_i64 t1 = tcg_temp_new_i64(); @@ -2455,6 +2475,26 @@ static inline void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2); /* Allow the optimizer room to replace mulu2 with two moves. */ tcg_gen_op0(INDEX_op_nop); +} else if (TCG_TARGET_HAS_mulu2_i64) { +TCGv_i64 t0 = tcg_temp_new_i64(); +TCGv_i64 t1 = tcg_temp_new_i64(); +TCGv_i64 t2 = tcg_temp_new_i64(); +TCGv_i64 t3 = tcg_temp_new_i64(); +tcg_gen_op4_i64(INDEX_op_mulu2_i64, t0, t1, arg1, arg2); +/* Allow the optimizer room to replace mulu2 with two moves. */ +tcg_gen_op0(INDEX_op_nop); +/* Adjust for negative inputs. */ +tcg_gen_sari_i64(t2, arg1, 63); +tcg_gen_sari_i64(t3, arg2, 63); +tcg_gen_and_i64(t2, t2, arg2); +tcg_gen_and_i64(t3, t3, arg1); +tcg_gen_sub_i64(rh, t1, t2); +tcg_gen_sub_i64(rh, rh, t3); +tcg_gen_mov_i64(rl, t0); +tcg_temp_free_i64(t0); +tcg_temp_free_i64(t1); +tcg_temp_free_i64(t2); +tcg_temp_free_i64(t3); } else { TCGv_i64 t0 = tcg_temp_new_i64(); int sizemask = 0; -- 1.8.1.2
[Qemu-devel] [PATCH v4 2/6] add basic backup support to block driver
Function backup_job_create() creates a block job to backup a block device. The coroutine is started with backup_job_start(). We call backup_do_cow() for each write during backup. That function reads the original data and pass it to backup_dump_cb(). The tracked_request infrastructure is used to serialize access. Currently backup cluster size is hardcoded to 65536 bytes. Signed-off-by: Dietmar Maurer diet...@proxmox.com --- Makefile.objs|1 + backup.c | 338 ++ backup.h | 32 + block.c | 71 +- include/block/block.h|2 + include/block/blockjob.h | 10 ++ 6 files changed, 448 insertions(+), 6 deletions(-) create mode 100644 backup.c create mode 100644 backup.h diff --git a/Makefile.objs b/Makefile.objs index a68cdac..df64f70 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -13,6 +13,7 @@ block-obj-$(CONFIG_POSIX) += aio-posix.o block-obj-$(CONFIG_WIN32) += aio-win32.o block-obj-y += block/ block-obj-y += qapi-types.o qapi-visit.o +block-obj-y += backup.o block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o block-obj-y += qemu-coroutine-sleep.o diff --git a/backup.c b/backup.c new file mode 100644 index 000..c9576d5 --- /dev/null +++ b/backup.c @@ -0,0 +1,338 @@ +/* + * QEMU backup + * + * Copyright (C) 2013 Proxmox Server Solutions + * + * Authors: + * Dietmar Maurer (diet...@proxmox.com) + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include stdio.h +#include errno.h +#include unistd.h + +#include block/block.h +#include block/block_int.h +#include block/blockjob.h +#include qemu/ratelimit.h +#include backup.h + +#define DEBUG_BACKUP 0 + +#define DPRINTF(fmt, ...) \ +do { if (DEBUG_BACKUP) { printf(backup: fmt, ## __VA_ARGS__); } } \ +while (0) + + +#define SLICE_TIME 1ULL /* ns */ + +typedef struct BackupBlockJob { +BlockJob common; +RateLimit limit; +uint64_t sectors_read; +unsigned long *bitmap; +int bitmap_size; +BackupDumpFunc *backup_dump_cb; +BlockDriverCompletionFunc *backup_complete_cb; +void *opaque; +} BackupBlockJob; + +static int backup_get_bitmap(BackupBlockJob *job, int64_t cluster_num) +{ +assert(job); +assert(job-bitmap); + +unsigned long val, idx, bit; + +idx = cluster_num / BITS_PER_LONG; + +assert(job-bitmap_size idx); + +bit = cluster_num % BITS_PER_LONG; +val = job-bitmap[idx]; + +return !!(val (1UL bit)); +} + +static void backup_set_bitmap(BackupBlockJob *job, int64_t cluster_num, + int dirty) +{ +assert(job); +assert(job-bitmap); + +unsigned long val, idx, bit; + +idx = cluster_num / BITS_PER_LONG; + +assert(job-bitmap_size idx); + +bit = cluster_num % BITS_PER_LONG; +val = job-bitmap[idx]; +if (dirty) { +if (!(val (1UL bit))) { +val |= 1UL bit; +} +} else { +if (val (1UL bit)) { +val = ~(1UL bit); +} +} +job-bitmap[idx] = val; +} + +static int backup_in_progress_count; + +static int coroutine_fn backup_do_cow(BlockDriverState *bs, + int64_t sector_num, int nb_sectors) +{ +assert(bs); +BackupBlockJob *job = (BackupBlockJob *)bs-job; +assert(job); + +BlockDriver *drv = bs-drv; +struct iovec iov; +QEMUIOVector bounce_qiov; +void *bounce_buffer = NULL; +int ret = 0; + +backup_in_progress_count++; + +int64_t start, end; + +start = sector_num / BACKUP_BLOCKS_PER_CLUSTER; +end = (sector_num + nb_sectors + BACKUP_BLOCKS_PER_CLUSTER - 1) / +BACKUP_BLOCKS_PER_CLUSTER; + +DPRINTF(brdv_co_backup_cow enter %s C%zd %zd %d\n, +bdrv_get_device_name(bs), start, sector_num, nb_sectors); + +for (; start end; start++) { +if (backup_get_bitmap(job, start)) { +DPRINTF(brdv_co_backup_cow skip C%zd\n, start); +continue; /* already copied */ +} + +/* immediately set bitmap (avoid coroutine race) */ +backup_set_bitmap(job, start, 1); + +DPRINTF(brdv_co_backup_cow C%zd\n, start); + +if (!bounce_buffer) { +iov.iov_len = BACKUP_CLUSTER_SIZE; +iov.iov_base = bounce_buffer = qemu_blockalign(bs, iov.iov_len); +qemu_iovec_init_external(bounce_qiov, iov, 1); +} + +ret = drv-bdrv_co_readv(bs, start * BACKUP_BLOCKS_PER_CLUSTER, + BACKUP_BLOCKS_PER_CLUSTER, + bounce_qiov); + +job-sectors_read += BACKUP_BLOCKS_PER_CLUSTER; + +if (ret 0) { +DPRINTF(brdv_co_backup_cow bdrv_read C%zd failed\n, start); +goto out; +} + +ret = job-backup_dump_cb(job-opaque, bs, start,
[Qemu-devel] [PATCH v4 6/6] add vm state to backups
Signed-off-by: Dietmar Maurer diet...@proxmox.com --- blockdev.c | 196 +- hmp.c|3 +- qapi-schema.json |5 +- 3 files changed, 200 insertions(+), 4 deletions(-) diff --git a/blockdev.c b/blockdev.c index 1cfc780..1b81824 100644 --- a/blockdev.c +++ b/blockdev.c @@ -22,6 +22,8 @@ #include sysemu/arch_init.h #include backup.h #include vma.h +#include migration/qemu-file.h +#include migration/migration.h static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives); @@ -1355,6 +1357,10 @@ static struct GenericBackupState { size_t total; size_t transferred; size_t zero_bytes; +unsigned char buf[BACKUP_CLUSTER_SIZE]; +int buf_index; +size_t buf_cluster_num; +guint8 vmstate_dev_id; } backup_state; typedef struct BackupCB { @@ -1510,10 +1516,170 @@ static void backup_start_jobs(void) backup_run_next_job(); } +static int backup_state_close(void *opaque) +{ +if (!backup_state.buf_index) { +return 0; +} + +size_t zero_bytes = 0; +if (backup_state.buf_index BACKUP_CLUSTER_SIZE) { +memset(backup_state.buf + backup_state.buf_index, 0, + BACKUP_CLUSTER_SIZE - backup_state.buf_index); +} +int bytes = backup_state.driver-dump_cb( +backup_state.writer, backup_state.vmstate_dev_id, +backup_state.buf_cluster_num, +backup_state.buf, zero_bytes); +backup_state.buf_index = 0; + +return bytes 0 ? -1 : 0; +} + +static int backup_state_put_buffer(void *opaque, const uint8_t *buf, + int64_t pos, int size) +{ +assert(backup_state.driver); +assert(backup_state.writer); +assert(backup_state.driver-dump_cb); + +/* Note: our backup driver expects to get whole clusters (64KB) */ + +int ret = size; + +while (size 0) { +int l = BACKUP_CLUSTER_SIZE - backup_state.buf_index; +l = l size ? size : l; +memcpy(backup_state.buf + backup_state.buf_index, buf, l); +backup_state.buf_index += l; +buf += l; +size -= l; +if (backup_state.buf_index == BACKUP_CLUSTER_SIZE) { +size_t zero_bytes = 0; +int bytes = backup_state.driver-dump_cb( +backup_state.writer, backup_state.vmstate_dev_id, +backup_state.buf_cluster_num++, +backup_state.buf, zero_bytes); +backup_state.buf_index = 0; +if (bytes 0) { +return -1; +} +} +} + +return ret; +} + +static const QEMUFileOps backup_file_ops = { +.put_buffer = backup_state_put_buffer, +.close = backup_state_close, +}; + +static void coroutine_fn backup_start_savevm(void *opaque) +{ +assert(backup_state.driver); +assert(backup_state.writer); +int ret; +char *err = NULL; +uint64_t remaining; +int64_t maxlen; +MigrationParams params = { +.blk = 0, +.shared = 0 +}; + +int restart = 0; + +QEMUFile *file = qemu_fopen_ops(NULL, backup_file_ops); + +ret = qemu_savevm_state_begin(file, params); +if (ret 0) { +qemu_fclose(file); +err = g_strdup(qemu_savevm_state_begin failed); +goto abort; +} + +while (1) { +ret = qemu_savevm_state_iterate(file); +remaining = ram_bytes_remaining(); + +if (ret 0) { +qemu_fclose(file); +err = g_strdup_printf(qemu_savevm_state_iterate error %d, ret); +goto abort; +} + +/* stop the VM if we use too much space, + * or if remaining is just a few MB + */ +maxlen = ram_bytes_total(); +size_t cpos = backup_state.buf_cluster_num * BACKUP_CLUSTER_SIZE; +if ((remaining 10) || ((cpos + remaining) = maxlen)) { +if (runstate_is_running()) { +restart = 1; +vm_stop(RUN_STATE_SAVE_VM); + } +} + +if (ret == 1) { /* finished */ +if (runstate_is_running()) { +restart = 1; +vm_stop(RUN_STATE_SAVE_VM); +} + +ret = qemu_savevm_state_complete(file); +if (ret 0) { +qemu_fclose(file); +err = g_strdup(qemu_savevm_state_complete error); +goto abort; + +} else { +if (qemu_fclose(file) 0) { +error_setg(backup_state.error, + backup_start_savevm: qemu_fclose failed); +goto abort; +} +if (backup_state.driver-complete_cb(backup_state.writer, +backup_state.vmstate_dev_id, 0) 0) { +err = g_strdup(backup_start_savevm: complete_cb failed); +goto abort; +} +backup_run_next_job(); +goto
Re: [Qemu-devel] [PATCH 1/2] coroutine: move pooling to common code
On Tue, Feb 19, 2013 at 11:59:09AM +0100, Paolo Bonzini wrote: The coroutine pool code is duplicated between the ucontext and sigaltstack backends, and absent from the win32 backend. But the code can be shared easily by moving it to qemu-coroutine.c. Signed-off-by: Paolo Bonzini pbonz...@redhat.com Thanks, applied both to the block branch. Kevin
Re: [Qemu-devel] [PATCH] tap: forbid creating multiqueue tap when hub is used
Il 20/02/2013 10:18, Jason Wang ha scritto: Obviously, hub does not support multiqueue tap. So this patch forbids creating multiple queue tap when hub is used to prevent the crash when command line such as -net tap,queues=2 is used. Signed-off-by: Jason Wang jasow...@redhat.com --- This patch is needed for 1.4 stable also. Stefan, please add Cc when committing to the net branch. Jason, next time please add the Cc yourself to the body. Paolo --- net/tap.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/net/tap.c b/net/tap.c index 48c254e..1e14f59 100644 --- a/net/tap.c +++ b/net/tap.c @@ -693,6 +693,12 @@ int net_init_tap(const NetClientOptions *opts, const char *name, queues = tap-has_queues ? tap-queues : 1; vhostfdname = tap-has_vhostfd ? tap-vhostfd : NULL; +if (peer (tap-has_queues || tap-has_fds || tap-has_vhostfds)) { +error_report(This configuration is not compatiable with multiqueue + tap); +return -1; +} + if (tap-has_fd) { if (tap-has_ifname || tap-has_script || tap-has_downscript || tap-has_vnet_hdr || tap-has_helper || tap-has_queues ||
Re: [Qemu-devel] Online resize of virtio-blk device does not emit udev event
On Tue, Feb 19, 2013 at 10:15:32PM +0100, Milos Vyletel wrote: I was looking at the virtblk_config_changed_work function in RHEL6.3 kernel's drivers/block/virtio_blk.c which I believe is the function handling blockresize and it does not look like it tries to emit any kobject uevent. Before I jump into patching kernel my question is whether it makes sense to have such uevent? I surely can use a way how to detect capacity change from userspace. I suggest checking how other block drivers (including the device-mapper and scsi layers) handle resize. Perhaps virtio_blk.c can follow an existing approach. Stefan
[Qemu-devel] [PATCH 10/38] tcg-arm: Implement muls2_i32
We even had the encoding of smull already handy... Cc: Andrzej Zaborowski balr...@gmail.com Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/arm/tcg-target.c | 4 tcg/arm/tcg-target.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index d9c33d8..94c6ca4 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -1647,6 +1647,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_mulu2_i32: tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]); break; +case INDEX_op_muls2_i32: +tcg_out_smull32(s, COND_AL, args[0], args[1], args[2], args[3]); +break; /* XXX: Perhaps args[2] 0x1f is wrong */ case INDEX_op_shl_i32: c = const_args[2] ? @@ -1798,6 +1801,7 @@ static const TCGTargetOpDef arm_op_defs[] = { { INDEX_op_sub_i32, { r, r, rI } }, { INDEX_op_mul_i32, { r, r, r } }, { INDEX_op_mulu2_i32, { r, r, r, r } }, +{ INDEX_op_muls2_i32, { r, r, r, r } }, { INDEX_op_and_i32, { r, r, rI } }, { INDEX_op_andc_i32, { r, r, rI } }, { INDEX_op_or_i32, { r, r, rI } }, diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index f9599bd..b6eed1f 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -75,7 +75,7 @@ typedef enum { #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 0 #define TCG_TARGET_HAS_movcond_i32 1 -#define TCG_TARGET_HAS_muls2_i320 +#define TCG_TARGET_HAS_muls2_i321 enum { TCG_AREG0 = TCG_REG_R6, -- 1.8.1.2
[Qemu-devel] [PATCH] doc: document -netdev hubport
Signed-off-by: Stefan Hajnoczi stefa...@redhat.com --- qemu-options.hx | 11 ++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/qemu-options.hx b/qemu-options.hx index 4bc9c85..c77c43e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1404,7 +1404,8 @@ DEF(netdev, HAS_ARG, QEMU_OPTION_netdev, #ifdef CONFIG_VDE vde| #endif -socket],id=str[,option][,option][,...]\n, QEMU_ARCH_ALL) +socket| +hubport],id=str[,option][,option][,...]\n, QEMU_ARCH_ALL) STEXI @item -net nic[,vlan=@var{n}][,macaddr=@var{mac}][,model=@var{type}] [,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}] @findex -net @@ -1726,6 +1727,14 @@ vde_switch -F -sock /tmp/myswitch qemu-system-i386 linux.img -net nic -net vde,sock=/tmp/myswitch @end example +@item -netdev hubport,id=@var{id},hubid=@var{hubid} + +Create a hub port on QEMU vlan @var{hubid}. This syntax is an alterative to +the -net @option{vlan} argument and can be used to connect a NIC specified with +-device to a QEMU vlan. + +Note that only NICs can be connected to a hubport, other -netdevs cannot. + @item -net dump[,vlan=@var{n}][,file=@var{file}][,len=@var{len}] Dump network traffic on VLAN @var{n} to file @var{file} (@file{qemu-vlan0.pcap} by default). At most @var{len} bytes (64k by default) per packet are stored. The file format is -- 1.8.1.2
[Qemu-devel] [PATCH 06/38] tcg: Implement a 64-bit to 32-bit extraction helper
We're going to have use for this shortly in implementing other helpers. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/tcg-op.h | 22 ++ 1 file changed, 22 insertions(+) diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 91c9d80..4ded249 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -2246,6 +2246,26 @@ static inline void tcg_gen_concat32_i64(TCGv_i64 dest, TCGv_i64 low, tcg_gen_deposit_i64(dest, low, high, 32, 32); } +static inline void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg) +{ +#if TCG_TARGET_REG_BITS == 32 +tcg_gen_mov_i32(lo, TCGV_LOW(arg)); +tcg_gen_mov_i32(hi, TCGV_HIGH(arg)); +#else +TCGv_i64 t0 = tcg_temp_new_i64(); +tcg_gen_trunc_i64_i32(lo, arg); +tcg_gen_shri_i64(t0, arg, 32); +tcg_gen_trunc_i64_i32(hi, t0); +tcg_temp_free_i64(t0); +#endif +} + +static inline void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg) +{ +tcg_gen_ext32u_i64(lo, arg); +tcg_gen_shri_i64(hi, arg, 32); +} + static inline void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1, TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2) @@ -2625,6 +2645,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) #define tcg_gen_bswap32_tl tcg_gen_bswap32_i64 #define tcg_gen_bswap64_tl tcg_gen_bswap64_i64 #define tcg_gen_concat_tl_i64 tcg_gen_concat32_i64 +#define tcg_gen_extr_i64_tl tcg_gen_extr32_i64 #define tcg_gen_andc_tl tcg_gen_andc_i64 #define tcg_gen_eqv_tl tcg_gen_eqv_i64 #define tcg_gen_nand_tl tcg_gen_nand_i64 @@ -2697,6 +2718,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) #define tcg_gen_bswap16_tl tcg_gen_bswap16_i32 #define tcg_gen_bswap32_tl tcg_gen_bswap32_i32 #define tcg_gen_concat_tl_i64 tcg_gen_concat_i32_i64 +#define tcg_gen_extr_tl_i64 tcg_gen_extr_i32_i64 #define tcg_gen_andc_tl tcg_gen_andc_i32 #define tcg_gen_eqv_tl tcg_gen_eqv_i32 #define tcg_gen_nand_tl tcg_gen_nand_i32 -- 1.8.1.2
[Qemu-devel] [PATCH 04/38] tcg: Add 64-bit multiword arithmetic operations
Matching the 32-bit multiword arithmetic that we already have. --- tcg/README | 26 ++ tcg/i386/tcg-target.h | 3 +++ tcg/ia64/tcg-target.h | 3 +++ tcg/optimize.c | 4 ++-- tcg/ppc64/tcg-target.h | 3 +++ tcg/s390/tcg-target.h | 3 +++ tcg/sparc/tcg-target.h | 3 +++ tcg/tcg-opc.h | 4 tcg/tcg.h | 3 +++ tcg/tci/tcg-target.h | 3 +++ 10 files changed, 41 insertions(+), 14 deletions(-) diff --git a/tcg/README b/tcg/README index ec1ac79..89f0cdd 100644 --- a/tcg/README +++ b/tcg/README @@ -361,6 +361,20 @@ Write 8, 16, 32 or 64 bits to host memory. All this opcodes assume that the pointed host memory doesn't correspond to a global. In the latter case the behaviour is unpredictable. +* Multiword arithmetic support + +* add2_i32/i64 t0_low, t0_high, t1_low, t1_high, t2_low, t2_high +* sub2_i32/i64 t0_low, t0_high, t1_low, t1_high, t2_low, t2_high + +Similar to add/sub, except that the double-word inputs T1 and T2 are +formed from two single-word arguments, and the double-word output T0 +is returned in two single-word outputs. + +* mulu2_i32/i64 t0_low, t0_high, t1, t2 + +Similar to mul, except two unsigned inputs T1 and T2 yielding the full +double-word product T0. The later is returned in two single-word outputs. + * 64-bit target on 32-bit host support The following opcodes are internal to TCG. Thus they are to be implemented by @@ -372,18 +386,6 @@ They are emitted as needed by inline functions within tcg-op.h. Similar to brcond, except that the 64-bit values T0 and T1 are formed from two 32-bit arguments. -* add2_i32 t0_low, t0_high, t1_low, t1_high, t2_low, t2_high -* sub2_i32 t0_low, t0_high, t1_low, t1_high, t2_low, t2_high - -Similar to add/sub, except that the 64-bit inputs T1 and T2 are -formed from two 32-bit arguments, and the 64-bit output T0 -is returned in two 32-bit outputs. - -* mulu2_i32 t0_low, t0_high, t1, t2 - -Similar to mul, except two 32-bit (unsigned) inputs T1 and T2 yielding -the full 64-bit product T0. The later is returned in two 32-bit outputs. - * setcond2_i32 dest, t1_low, t1_high, t2_low, t2_high, cond Similar to setcond, except that the 64-bit values T1 and T2 are diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index 487dc23..4f00171 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -117,6 +117,9 @@ typedef enum { #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 1 #define TCG_TARGET_HAS_movcond_i64 1 +#define TCG_TARGET_HAS_add2_i64 0 +#define TCG_TARGET_HAS_sub2_i64 0 +#define TCG_TARGET_HAS_mulu2_i640 #endif #define TCG_TARGET_deposit_i32_valid(ofs, len) \ diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index b4ff7c3..40f442e 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -137,8 +137,11 @@ typedef enum { #define TCG_TARGET_HAS_deposit_i32 1 #define TCG_TARGET_HAS_deposit_i64 1 #define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_add2_i64 0 #define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_sub2_i64 0 #define TCG_TARGET_HAS_mulu2_i320 +#define TCG_TARGET_HAS_mulu2_i640 #define TCG_TARGET_deposit_i32_valid(ofs, len) ((len) = 16) #define TCG_TARGET_deposit_i64_valid(ofs, len) ((len) = 16) diff --git a/tcg/optimize.c b/tcg/optimize.c index 973d2d6..027b3a5 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -554,11 +554,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, args[5] = tcg_invert_cond(args[5]); } break; -case INDEX_op_add2_i32: +CASE_OP_32_64(add2): swap_commutative(args[0], args[2], args[4]); swap_commutative(args[1], args[3], args[5]); break; -case INDEX_op_mulu2_i32: +CASE_OP_32_64(mulu2): swap_commutative(args[0], args[2], args[3]); break; case INDEX_op_brcond2_i32: diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h index ea976ad..86929c1 100644 --- a/tcg/ppc64/tcg-target.h +++ b/tcg/ppc64/tcg-target.h @@ -109,6 +109,9 @@ typedef enum { #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 0 #define TCG_TARGET_HAS_movcond_i64 0 +#define TCG_TARGET_HAS_add2_i64 0 +#define TCG_TARGET_HAS_sub2_i64 0 +#define TCG_TARGET_HAS_mulu2_i640 #define TCG_AREG0 TCG_REG_R27 diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h index 7772c35..ee31c37 100644 --- a/tcg/s390/tcg-target.h +++ b/tcg/s390/tcg-target.h @@ -90,6 +90,9 @@ typedef enum TCGReg { #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 0 #define TCG_TARGET_HAS_movcond_i64 0 +#define TCG_TARGET_HAS_add2_i64 0 +#define TCG_TARGET_HAS_sub2_i64 0 +#define TCG_TARGET_HAS_mulu2_i64
Re: [Qemu-devel] [PATCH 3/6] qcow2: flush caches in qcow2_alloc_bytes()
On Tue, Feb 19, 2013 at 04:45:03PM +0100, Stefan Hajnoczi wrote: It is not completely clear to me what is being flushed in qcow2_alloc_bytes() but bdrv_flush(bs-file) is probably wrong. At least the refcount cache should be flushed since this function calls update_cluster_refcount(). To be on the safe side, call the full bdrv_flush(bs). This flushes all caches and the underlying file itself. Signed-off-by: Stefan Hajnoczi stefa...@redhat.com To me it looks as if qcow2_alloc_compressed_cluster_offset() would need a call to qcow2_cache_set_dependency() like there is already for the uncompressed case in qcow2_alloc_cluster_link_l2(). Once we have that, the unconditional flush can be removed. I guess this will be a major performance improvement for converting to compressed qcow2. The bdrv_flush() ended up here only because I pushed the flush from qcow2_alloc_clusters() to its callers so I could remove it from the common fast path. All surviving instances from this still need review. Kevin
Re: [Qemu-devel] [PATCH] tap: forbid creating multiqueue tap when hub is used
On 02/20/2013 05:45 PM, Paolo Bonzini wrote: Il 20/02/2013 10:18, Jason Wang ha scritto: Obviously, hub does not support multiqueue tap. So this patch forbids creating multiple queue tap when hub is used to prevent the crash when command line such as -net tap,queues=2 is used. Signed-off-by: Jason Wang jasow...@redhat.com --- This patch is needed for 1.4 stable also. Stefan, please add Cc when committing to the net branch. Jason, next time please add the Cc yourself to the body. Sure. Paolo --- net/tap.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/net/tap.c b/net/tap.c index 48c254e..1e14f59 100644 --- a/net/tap.c +++ b/net/tap.c @@ -693,6 +693,12 @@ int net_init_tap(const NetClientOptions *opts, const char *name, queues = tap-has_queues ? tap-queues : 1; vhostfdname = tap-has_vhostfd ? tap-vhostfd : NULL; +if (peer (tap-has_queues || tap-has_fds || tap-has_vhostfds)) { +error_report(This configuration is not compatiable with multiqueue + tap); +return -1; +} + if (tap-has_fd) { if (tap-has_ifname || tap-has_script || tap-has_downscript || tap-has_vnet_hdr || tap-has_helper || tap-has_queues ||
Re: [Qemu-devel] [PATCH 0/6] qcow2: cache flush fixes and performance improvements
On Tue, Feb 19, 2013 at 04:45:00PM +0100, Stefan Hajnoczi wrote: Users have reported that qcow2 internal snapshot creation is slow. I filed a bug report at https://bugs.launchpad.net/qemu/+bug/1126369. This patch series reduces the time for qcow2 internal snapshot creation significantly, from more than 3 minutes to under 1 second. In the process of removing unnecessary cache flushes, I also stumbled upon instances of bdrv_flush(bs-file) where we really want to flush metadata updates. Since qcow2 caches metadata this actually does not write out the metadata updates to disk! The fix is either bdrv_flush(bs) or a more specific cache flush (e.g. refcount block cache). This series passes qemu-iotests. Stefan Hajnoczi (6): qcow2: flush refcount cache correctly in alloc_refcount_block() qcow2: flush refcount cache correctly in qcow2_write_snapshots() qcow2: flush caches in qcow2_alloc_bytes() qcow2: flush in qcow2_update_snapshot_refcount() qcow2: drop flush in update_cluster_refcount() qcow2: drop unnecessary flush in qcow2_update_snapshot_refcount() block/qcow2-refcount.c | 12 +++- block/qcow2-snapshot.c | 7 +-- 2 files changed, 4 insertions(+), 15 deletions(-) You touch a few bdrv_flush() callers that don't check the return value. Could you use the opportunity to fix that as well? Kevin
[Qemu-devel] [PATCH RESEND for 1.4-stable] net: reduce memory allocation when multiqueue is not used
Edivaldo reports a problem that the array of NetClientState in NICState is too large - MAX_QUEUE_NUM(1024) which will waste memory even if multiqueue is not used. For 1.4 we can just solve this by reduce the MAX_QUEUE_NUM to 8 which is the same as the current kernel (3.8+) tap queue limit. For 1.5, we will use dynamic allocation instead. Cc: Edivaldo de Araujo Pereira edivaldoapere...@yahoo.com.br Signed-off-by: Jason Wang jasow...@redhat.com --- RESEND since the previous mail misses the list. --- include/net/net.h |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/include/net/net.h b/include/net/net.h index 43a045e..cdffc34 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -9,7 +9,7 @@ #include migration/vmstate.h #include qapi-types.h -#define MAX_QUEUE_NUM 1024 +#define MAX_QUEUE_NUM 8 struct MACAddr { uint8_t a[6]; -- 1.7.1
[Qemu-devel] [PATCH v4 00/10] main-loop: switch to g_poll(3) on POSIX hosts
Amos Kong ak...@redhat.com reported that file descriptors numbered higher than 1024 could crash QEMU. This is due to the fixed size of the fd_set type used for select(2) event polling. This series converts the main-loop.c and aio-posix.c select(2) calls to g_poll(3). This eliminates the fd_set type and allows QEMU to scale to high numbers of file descriptors. The g_poll(3) interface is a portable version of the poll(2) system call. The difference to select(2) is that fine-grained events (G_IO_IN, G_IO_OUT, G_IO_HUP, G_IO_ERR, G_IO_PRI) can be monitored instead of just read/write/exception. Also, there is no limit to the file descriptor numbers that may be used, allowing applications to scale to many file descriptors. See the documentation for details: http://developer.gnome.org/glib/2.28/glib-The-Main-Event-Loop.html#g-poll The QEMU main loop works as follows today: 1. Call out to slirp, iohandlers, and glib sources to fill rfds/wfds/xfds with the file descriptors to select(2). 2. Perform the select(2) call. 3. Call out to slirp, iohandlers, and glib sources to handle events polled in rfds/wfds/xfds. The plan of attack is as follows: 1. Replace select(2) with g_poll(3). Use glue that converts between rfds/wfds/xfds and GPollFD so that the unconverted QEMU components still work. 2. Convert slirp, iohandlers, and glib source fill/poll functions to use GPollFD directly instead of rfds/wfds/xfds. 3. Drop the glue since all components now natively use GPollFD. 4. Convert aio-posix.c to g_poll(3) by reusing GPollFD. I have tested that the series builds and is bisectable on Linux and Windows hosts. But I have not done extensive testing on other host platforms or with long-term guests to check for performance regressions. v4: * Assign revents instead of bitwise OR to make code clearer [Laszlo] * Invoke pollfds_poll() only when select(2) succeeds [Laszlo] * Fix gpollfds_to_select(select_ret || g_poll_ret) call [Laszlo] v3: * Convert slirp/slirp.c to tabs to spaces [Blue Swirl] v2: * Replace custom Poller type with GArray [aliguori] Stefan Hajnoczi (10): main-loop: fix select_ret uninitialized variable warning main-loop: switch to g_poll() on POSIX hosts main-loop: switch POSIX glib integration to GPollFD slirp: slirp/slirp.c coding style cleanup slirp: switch to GPollFD iohandler: switch to GPollFD main-loop: drop rfds/wfds/xfds for good aio: extract aio_dispatch() from aio_poll() aio: convert aio_poll() to g_poll(3) aio: support G_IO_HUP and G_IO_ERR aio-posix.c | 130 - async.c | 2 + include/block/aio.h | 3 + include/qemu/main-loop.h | 4 +- iohandler.c | 40 ++- main-loop.c | 158 ++- slirp/libslirp.h | 6 +- slirp/main.h | 1 - slirp/slirp.c| 673 +-- slirp/socket.c | 9 - slirp/socket.h | 2 + stubs/slirp.c| 6 +- 12 files changed, 547 insertions(+), 487 deletions(-) -- 1.8.1.2
[Qemu-devel] [PATCH v4 01/10] main-loop: fix select_ret uninitialized variable warning
Signed-off-by: Stefan Hajnoczi stefa...@redhat.com --- main-loop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main-loop.c b/main-loop.c index 6f52ac3..d0d8fe4 100644 --- a/main-loop.c +++ b/main-loop.c @@ -330,7 +330,8 @@ void qemu_fd_register(int fd) static int os_host_main_loop_wait(uint32_t timeout) { GMainContext *context = g_main_context_default(); -int select_ret, g_poll_ret, ret, i; +int select_ret = 0; +int g_poll_ret, ret, i; PollingEntry *pe; WaitObjects *w = wait_objects; gint poll_timeout; -- 1.8.1.2
[Qemu-devel] [PATCH v4 08/10] aio: extract aio_dispatch() from aio_poll()
We will need to loop over AioHandlers calling -io_read()/-io_write() when aio_poll() is converted from select(2) to g_poll(2). Luckily the code for this already exists, extract it into the new aio_dispatch() function. Two small changes: * aio_poll() checks !node-deleted to avoid calling handlers that have been deleted. * Fix typo 'then' - 'them' in aio_poll() comment. Signed-off-by: Stefan Hajnoczi stefa...@redhat.com --- aio-posix.c | 57 +++-- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/aio-posix.c b/aio-posix.c index fe4dbb4..35131a3 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -129,30 +129,12 @@ bool aio_pending(AioContext *ctx) return false; } -bool aio_poll(AioContext *ctx, bool blocking) +static bool aio_dispatch(AioContext *ctx) { -static struct timeval tv0; AioHandler *node; -fd_set rdfds, wrfds; -int max_fd = -1; -int ret; -bool busy, progress; - -progress = false; - -/* - * If there are callbacks left that have been queued, we need to call then. - * Do not call select in this case, because it is possible that the caller - * does not need a complete flush (as is the case for qemu_aio_wait loops). - */ -if (aio_bh_poll(ctx)) { -blocking = false; -progress = true; -} +bool progress = false; /* - * Then dispatch any pending callbacks from the GSource. - * * We have to walk very carefully in case qemu_aio_set_fd_handler is * called while we're walking. */ @@ -167,11 +149,15 @@ bool aio_poll(AioContext *ctx, bool blocking) node-pfd.revents = 0; /* See comment in aio_pending. */ -if (revents (G_IO_IN | G_IO_HUP | G_IO_ERR) node-io_read) { +if (!node-deleted +(revents (G_IO_IN | G_IO_HUP | G_IO_ERR)) +node-io_read) { node-io_read(node-opaque); progress = true; } -if (revents (G_IO_OUT | G_IO_ERR) node-io_write) { +if (!node-deleted +(revents (G_IO_OUT | G_IO_ERR)) +node-io_write) { node-io_write(node-opaque); progress = true; } @@ -186,6 +172,33 @@ bool aio_poll(AioContext *ctx, bool blocking) g_free(tmp); } } +return progress; +} + +bool aio_poll(AioContext *ctx, bool blocking) +{ +static struct timeval tv0; +AioHandler *node; +fd_set rdfds, wrfds; +int max_fd = -1; +int ret; +bool busy, progress; + +progress = false; + +/* + * If there are callbacks left that have been queued, we need to call them. + * Do not call select in this case, because it is possible that the caller + * does not need a complete flush (as is the case for qemu_aio_wait loops). + */ +if (aio_bh_poll(ctx)) { +blocking = false; +progress = true; +} + +if (aio_dispatch(ctx)) { +progress = true; +} if (progress !blocking) { return true; -- 1.8.1.2
[Qemu-devel] [PATCH v4 06/10] iohandler: switch to GPollFD
Convert iohandler_select_fill() and iohandler_select_poll() to use GPollFD instead of rfds/wfds/xfds. Signed-off-by: Stefan Hajnoczi stefa...@redhat.com --- include/qemu/main-loop.h | 4 ++-- iohandler.c | 40 ++-- main-loop.c | 4 ++-- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index e8059c3..0995288 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -297,8 +297,8 @@ void qemu_mutex_unlock_iothread(void); /* internal interfaces */ void qemu_fd_register(int fd); -void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds); -void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc); +void qemu_iohandler_fill(GArray *pollfds); +void qemu_iohandler_poll(GArray *pollfds, int rc); QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque); void qemu_bh_schedule_idle(QEMUBH *bh); diff --git a/iohandler.c b/iohandler.c index 2523adc..ae2ef8f 100644 --- a/iohandler.c +++ b/iohandler.c @@ -39,6 +39,7 @@ typedef struct IOHandlerRecord { void *opaque; QLIST_ENTRY(IOHandlerRecord) next; int fd; +int pollfds_idx; bool deleted; } IOHandlerRecord; @@ -78,6 +79,7 @@ int qemu_set_fd_handler2(int fd, ioh-fd_read = fd_read; ioh-fd_write = fd_write; ioh-opaque = opaque; +ioh-pollfds_idx = -1; ioh-deleted = 0; qemu_notify_event(); } @@ -92,38 +94,56 @@ int qemu_set_fd_handler(int fd, return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); } -void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds) +void qemu_iohandler_fill(GArray *pollfds) { IOHandlerRecord *ioh; QLIST_FOREACH(ioh, io_handlers, next) { +int events = 0; + if (ioh-deleted) continue; if (ioh-fd_read (!ioh-fd_read_poll || ioh-fd_read_poll(ioh-opaque) != 0)) { -FD_SET(ioh-fd, readfds); -if (ioh-fd *pnfds) -*pnfds = ioh-fd; +events |= G_IO_IN | G_IO_HUP | G_IO_ERR; } if (ioh-fd_write) { -FD_SET(ioh-fd, writefds); -if (ioh-fd *pnfds) -*pnfds = ioh-fd; +events |= G_IO_OUT | G_IO_ERR; +} +if (events) { +GPollFD pfd = { +.fd = ioh-fd, +.events = events, +}; +ioh-pollfds_idx = pollfds-len; +g_array_append_val(pollfds, pfd); +} else { +ioh-pollfds_idx = -1; } } } -void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int ret) +void qemu_iohandler_poll(GArray *pollfds, int ret) { if (ret 0) { IOHandlerRecord *pioh, *ioh; QLIST_FOREACH_SAFE(ioh, io_handlers, next, pioh) { -if (!ioh-deleted ioh-fd_read FD_ISSET(ioh-fd, readfds)) { +int revents = 0; + +if (!ioh-deleted ioh-pollfds_idx != -1) { +GPollFD *pfd = g_array_index(pollfds, GPollFD, + ioh-pollfds_idx); +revents = pfd-revents; +} + +if (!ioh-deleted ioh-fd_read +(revents (G_IO_IN | G_IO_HUP | G_IO_ERR))) { ioh-fd_read(ioh-opaque); } -if (!ioh-deleted ioh-fd_write FD_ISSET(ioh-fd, writefds)) { +if (!ioh-deleted ioh-fd_write +(revents (G_IO_OUT | G_IO_ERR))) { ioh-fd_write(ioh-opaque); } diff --git a/main-loop.c b/main-loop.c index 839e98f..800868a 100644 --- a/main-loop.c +++ b/main-loop.c @@ -507,9 +507,9 @@ int main_loop_wait(int nonblocking) slirp_update_timeout(timeout); slirp_pollfds_fill(gpollfds); #endif -qemu_iohandler_fill(nfds, rfds, wfds, xfds); +qemu_iohandler_fill(gpollfds); ret = os_host_main_loop_wait(timeout); -qemu_iohandler_poll(rfds, wfds, xfds, ret); +qemu_iohandler_poll(gpollfds, ret); #ifdef CONFIG_SLIRP slirp_pollfds_poll(gpollfds, (ret 0)); #endif -- 1.8.1.2
[Qemu-devel] [PATCH v4 05/10] slirp: switch to GPollFD
Slirp uses rfds/wfds/xfds more extensively than other QEMU components. The rarely-used out-of-band TCP data feature is used. That means we need the full table of select(2) to g_poll(3) events: rfds - G_IO_IN | G_IO_HUP | G_IO_ERR wfds - G_IO_OUT | G_IO_ERR xfds - G_IO_PRI I came up with this table by looking at Linux fs/select.c which maps select(2) to poll(2) internally. Another detail to watch out for are the global variables that reference rfds/wfds/xfds during slirp_select_poll(). sofcantrcvmore() and sofcantsendmore() use these globals to clear fd_set bits. When sofcantrcvmore() is called, the wfds bit is cleared so that the write handler will no longer be run for this iteration of the event loop. This actually seems buggy to me since TCP connections can be half-closed and we'd still want to handle data in half-duplex fashion. I think the real intention is to avoid running the read/write handler when the socket has been fully closed. This is indicated with the SS_NOFDREF state bit so we now check for it before invoking the TCP write handler. Note that UDP/ICMP code paths don't care because they are connectionless. Note that slirp/ has a lot of tabs and sometimes mixed tabs with spaces. I followed the style of the surrounding code. Signed-off-by: Stefan Hajnoczi stefa...@redhat.com --- main-loop.c | 4 +- slirp/libslirp.h | 6 +-- slirp/main.h | 1 - slirp/slirp.c| 133 +-- slirp/socket.c | 9 slirp/socket.h | 2 + stubs/slirp.c| 6 +-- 7 files changed, 87 insertions(+), 74 deletions(-) diff --git a/main-loop.c b/main-loop.c index c2ede99..839e98f 100644 --- a/main-loop.c +++ b/main-loop.c @@ -505,13 +505,13 @@ int main_loop_wait(int nonblocking) #ifdef CONFIG_SLIRP slirp_update_timeout(timeout); -slirp_select_fill(nfds, rfds, wfds, xfds); +slirp_pollfds_fill(gpollfds); #endif qemu_iohandler_fill(nfds, rfds, wfds, xfds); ret = os_host_main_loop_wait(timeout); qemu_iohandler_poll(rfds, wfds, xfds, ret); #ifdef CONFIG_SLIRP -slirp_select_poll(rfds, wfds, xfds, (ret 0)); +slirp_pollfds_poll(gpollfds, (ret 0)); #endif qemu_run_all_timers(); diff --git a/slirp/libslirp.h b/slirp/libslirp.h index 49609c2..ceabff8 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -17,11 +17,9 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, void slirp_cleanup(Slirp *slirp); void slirp_update_timeout(uint32_t *timeout); -void slirp_select_fill(int *pnfds, - fd_set *readfds, fd_set *writefds, fd_set *xfds); +void slirp_pollfds_fill(GArray *pollfds); -void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, - int select_error); +void slirp_pollfds_poll(GArray *pollfds, int select_error); void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len); diff --git a/slirp/main.h b/slirp/main.h index 66e4f92..f2e58cf 100644 --- a/slirp/main.h +++ b/slirp/main.h @@ -31,7 +31,6 @@ extern int ctty_closed; extern char *slirp_tty; extern char *exec_shell; extern u_int curtime; -extern fd_set *global_readfds, *global_writefds, *global_xfds; extern struct in_addr loopback_addr; extern unsigned long loopback_mask; extern char *username; diff --git a/slirp/slirp.c b/slirp/slirp.c index 5d14e7f..bd9b7cb 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -39,9 +39,6 @@ static const uint8_t special_ethaddr[ETH_ALEN] = { static const uint8_t zero_ethaddr[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; -/* XXX: suppress those select globals */ -fd_set *global_readfds, *global_writefds, *global_xfds; - u_int curtime; static u_int time_fasttimo, last_slowtimo; static int do_slowtimo; @@ -261,7 +258,6 @@ void slirp_cleanup(Slirp *slirp) #define CONN_CANFSEND(so) (((so)-so_state (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) #define CONN_CANFRCV(so) (((so)-so_state (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) -#define UPD_NFDS(x) if (nfds (x)) nfds = (x) void slirp_update_timeout(uint32_t *timeout) { @@ -270,23 +266,15 @@ void slirp_update_timeout(uint32_t *timeout) } } -void slirp_select_fill(int *pnfds, - fd_set *readfds, fd_set *writefds, fd_set *xfds) +void slirp_pollfds_fill(GArray *pollfds) { Slirp *slirp; struct socket *so, *so_next; -int nfds; if (QTAILQ_EMPTY(slirp_instances)) { return; } -/* fail safe */ -global_readfds = NULL; -global_writefds = NULL; -global_xfds = NULL; - -nfds = *pnfds; /* * First, TCP sockets */ @@ -302,8 +290,12 @@ void slirp_select_fill(int *pnfds, for (so = slirp-tcb.so_next; so != slirp-tcb; so = so_next) { +int events = 0; + so_next = so-so_next; +so-pollfds_idx = -1; + /* * See if we need a tcp_fasttimo */ @@ -323,8 +315,12 @@
[Qemu-devel] [PATCH v4 07/10] main-loop: drop rfds/wfds/xfds for good
Now that all *_fill() and *_poll() functions use GPollFD we no longer need rfds/wfds/xfds or pollfds_from_select()/pollfds_to_select(). From now on everything uses GPollFD. Signed-off-by: Stefan Hajnoczi stefa...@redhat.com --- main-loop.c | 77 ++--- 1 file changed, 2 insertions(+), 75 deletions(-) diff --git a/main-loop.c b/main-loop.c index 800868a..8c9b58c 100644 --- a/main-loop.c +++ b/main-loop.c @@ -143,66 +143,8 @@ int qemu_init_main_loop(void) return 0; } -static fd_set rfds, wfds, xfds; -static int nfds; static int max_priority; -/* Load rfds/wfds/xfds into gpollfds. Will be removed a few commits later. */ -static void gpollfds_from_select(void) -{ -int fd; -for (fd = 0; fd = nfds; fd++) { -int events = 0; -if (FD_ISSET(fd, rfds)) { -events |= G_IO_IN | G_IO_HUP | G_IO_ERR; -} -if (FD_ISSET(fd, wfds)) { -events |= G_IO_OUT | G_IO_ERR; -} -if (FD_ISSET(fd, xfds)) { -events |= G_IO_PRI; -} -if (events) { -GPollFD pfd = { -.fd = fd, -.events = events, -}; -g_array_append_val(gpollfds, pfd); -} -} -} - -/* Store gpollfds revents into rfds/wfds/xfds. Will be removed a few commits - * later. - */ -static void gpollfds_to_select(int ret) -{ -int i; - -FD_ZERO(rfds); -FD_ZERO(wfds); -FD_ZERO(xfds); - -if (ret = 0) { -return; -} - -for (i = 0; i gpollfds-len; i++) { -int fd = g_array_index(gpollfds, GPollFD, i).fd; -int revents = g_array_index(gpollfds, GPollFD, i).revents; - -if (revents (G_IO_IN | G_IO_HUP | G_IO_ERR)) { -FD_SET(fd, rfds); -} -if (revents (G_IO_OUT | G_IO_ERR)) { -FD_SET(fd, wfds); -} -if (revents G_IO_PRI) { -FD_SET(fd, xfds); -} -} -} - #ifndef _WIN32 static int glib_pollfds_idx; static int glib_n_poll_fds; @@ -251,15 +193,8 @@ static int os_host_main_loop_wait(uint32_t timeout) qemu_mutex_unlock_iothread(); } -/* We'll eventually drop fd_set completely. But for now we still have - * *_fill() and *_poll() functions that use rfds/wfds/xfds. - */ -gpollfds_from_select(); - ret = g_poll((GPollFD *)gpollfds-data, gpollfds-len, timeout); -gpollfds_to_select(ret); - if (timeout 0) { qemu_mutex_lock_iothread(); } @@ -417,6 +352,8 @@ static int os_host_main_loop_wait(uint32_t timeout) WaitObjects *w = wait_objects; gint poll_timeout; static struct timeval tv0; +fd_set rfds, wfds, xfds; +int nfds; /* XXX: need to suppress polling by better using win32 events */ ret = 0; @@ -463,10 +400,6 @@ static int os_host_main_loop_wait(uint32_t timeout) * improve socket latency. */ -/* This back-and-forth between GPollFDs and select(2) is temporary. We'll - * drop it in a couple of patches, I promise :). - */ -gpollfds_from_select(); FD_ZERO(rfds); FD_ZERO(wfds); FD_ZERO(xfds); @@ -480,7 +413,6 @@ static int os_host_main_loop_wait(uint32_t timeout) pollfds_poll(gpollfds, nfds, rfds, wfds, xfds); } } -gpollfds_to_select(select_ret); return select_ret || g_poll_ret; } @@ -498,11 +430,6 @@ int main_loop_wait(int nonblocking) /* poll any events */ g_array_set_size(gpollfds, 0); /* reset for new iteration */ /* XXX: separate device handlers from system ones */ -nfds = -1; -FD_ZERO(rfds); -FD_ZERO(wfds); -FD_ZERO(xfds); - #ifdef CONFIG_SLIRP slirp_update_timeout(timeout); slirp_pollfds_fill(gpollfds); -- 1.8.1.2
[Qemu-devel] [PATCH 14/38] tcg: Apply life analysis to 64-bit multiword arithmetic ops
Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/tcg.c | 28 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index c8a843e..1d8265e 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1217,7 +1217,7 @@ static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps, static void tcg_liveness_analysis(TCGContext *s) { int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops; -TCGOpcode op; +TCGOpcode op, op_new; TCGArg *args; const TCGOpDef *def; uint8_t *dead_temps, *mem_temps; @@ -1324,7 +1324,17 @@ static void tcg_liveness_analysis(TCGContext *s) break; case INDEX_op_add2_i32: +op_new = INDEX_op_add_i32; +goto do_addsub2; case INDEX_op_sub2_i32: +op_new = INDEX_op_sub_i32; +goto do_addsub2; +case INDEX_op_add2_i64: +op_new = INDEX_op_add_i64; +goto do_addsub2; +case INDEX_op_sub2_i64: +op_new = INDEX_op_sub_i64; +do_addsub2: args -= 6; nb_iargs = 4; nb_oargs = 2; @@ -1337,12 +1347,7 @@ static void tcg_liveness_analysis(TCGContext *s) goto do_remove; } /* Create the single operation plus nop. */ -if (op == INDEX_op_add2_i32) { -op = INDEX_op_add_i32; -} else { -op = INDEX_op_sub_i32; -} -s-gen_opc_buf[op_index] = op; +s-gen_opc_buf[op_index] = op = op_new; args[1] = args[2]; args[2] = args[4]; assert(s-gen_opc_buf[op_index + 1] == INDEX_op_nop); @@ -1354,6 +1359,13 @@ static void tcg_liveness_analysis(TCGContext *s) goto do_not_remove; case INDEX_op_mulu2_i32: +case INDEX_op_muls2_i32: +op_new = INDEX_op_mul_i32; +goto do_mul2; +case INDEX_op_mulu2_i64: +case INDEX_op_muls2_i64: +op_new = INDEX_op_mul_i64; +do_mul2: args -= 4; nb_iargs = 2; nb_oargs = 2; @@ -1362,7 +1374,7 @@ static void tcg_liveness_analysis(TCGContext *s) if (dead_temps[args[0]] !mem_temps[args[0]]) { goto do_remove; } -s-gen_opc_buf[op_index] = op = INDEX_op_mul_i32; +s-gen_opc_buf[op_index] = op = op_new; args[1] = args[2]; args[2] = args[3]; assert(s-gen_opc_buf[op_index + 1] == INDEX_op_nop); -- 1.8.1.2
[Qemu-devel] [PATCH 38/38] target-xtensa: Use add2/sub2 for mac
Cc: Max Filippov jcmvb...@gmail.com Signed-off-by: Richard Henderson r...@twiddle.net --- target-xtensa/translate.c | 29 + 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index b41d12c..11e06a3 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -2487,27 +2487,24 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) tcg_gen_sari_i32(cpu_SR[ACCHI], cpu_SR[ACCLO], 31); } } else { -TCGv_i32 res = tcg_temp_new_i32(); -TCGv_i64 res64 = tcg_temp_new_i64(); -TCGv_i64 tmp = tcg_temp_new_i64(); - -tcg_gen_mul_i32(res, m1, m2); -tcg_gen_ext_i32_i64(res64, res); -tcg_gen_concat_i32_i64(tmp, -cpu_SR[ACCLO], cpu_SR[ACCHI]); +TCGv_i32 lo = tcg_temp_new_i32(); +TCGv_i32 hi = tcg_temp_new_i32(); + +tcg_gen_mul_i32(lo, m1, m2); +tcg_gen_sari_i32(hi, lo, 31); if (op == MAC16_MULA) { -tcg_gen_add_i64(tmp, tmp, res64); +tcg_gen_add2_i32(cpu_SR[ACCLO], cpu_SR[ACCHI], + cpu_SR[ACCLO], cpu_SR[ACCHI], + lo, hi); } else { -tcg_gen_sub_i64(tmp, tmp, res64); +tcg_gen_sub2_i32(cpu_SR[ACCLO], cpu_SR[ACCHI], + cpu_SR[ACCLO], cpu_SR[ACCHI], + lo, hi); } -tcg_gen_trunc_i64_i32(cpu_SR[ACCLO], tmp); -tcg_gen_shri_i64(tmp, tmp, 32); -tcg_gen_trunc_i64_i32(cpu_SR[ACCHI], tmp); tcg_gen_ext8s_i32(cpu_SR[ACCHI], cpu_SR[ACCHI]); -tcg_temp_free(res); -tcg_temp_free_i64(res64); -tcg_temp_free_i64(tmp); +tcg_temp_free_i32(lo); +tcg_temp_free_i32(hi); } tcg_temp_free(m1); tcg_temp_free(m2); -- 1.8.1.2
[Qemu-devel] [PATCH v4 1/6] add documenation for new backup framework
Signed-off-by: Dietmar Maurer diet...@proxmox.com --- docs/backup.txt | 116 +++ 1 files changed, 116 insertions(+), 0 deletions(-) create mode 100644 docs/backup.txt diff --git a/docs/backup.txt b/docs/backup.txt new file mode 100644 index 000..927d787 --- /dev/null +++ b/docs/backup.txt @@ -0,0 +1,116 @@ +Efficient VM backup for qemu + +=Requirements= + +* Backup to a single archive file +* Backup needs to contain all data to restore VM (full backup) +* Do not depend on storage type or image format +* Avoid use of temporary storage +* store sparse images efficiently + +=Introduction= + +Most VM backup solutions use some kind of snapshot to get a consistent +VM view at a specific point in time. For example, we previously used +LVM to create a snapshot of all used VM images, which are then copied +into a tar file. + +That basically means that any data written during backup involve +considerable overhead. For LVM we get the following steps: + +1.) read original data (VM write) +2.) write original data into snapshot (VM write) +3.) write new data (VM write) +4.) read data from snapshot (backup) +5.) write data from snapshot into tar file (backup) + +Another approach to backup VM images is to create a new qcow2 image +which use the old image as base. During backup, writes are redirected +to the new image, so the old image represents a 'snapshot'. After +backup, data need to be copied back from new image into the old +one (commit). So a simple write during backup triggers the following +steps: + +1.) write new data to new image (VM write) +2.) read data from old image (backup) +3.) write data from old image into tar file (backup) + +4.) read data from new image (commit) +5.) write data to old image (commit) + +This is in fact the same overhead as before. Other tools like qemu +livebackup produces similar overhead (2 reads, 3 writes). + +Some storage types/formats supports internal snapshots using some kind +of reference counting (rados, sheepdog, dm-thin, qcow2). It would be possible +to use that for backups, but for now we want to be storage-independent. + +=Make it more efficient= + +The be more efficient, we simply need to avoid unnecessary steps. The +following steps are always required: + +1.) read old data before it gets overwritten +2.) write that data into the backup archive +3.) write new data (VM write) + +As you can see, this involves only one read, and two writes. + +To make that work, our backup archive need to be able to store image +data 'out of order'. It is important to notice that this will not work +with traditional archive formats like tar. + +During backup we simply intercept writes, then read existing data and +store that directly into the archive. After that we can continue the +write. + +==Advantages== + +* very good performance (1 read, 2 writes) +* works on any storage type and image format. +* avoid usage of temporary storage +* we can define a new and simple archive format, which is able to + store sparse files efficiently. + +Note: Storing sparse files is a mess with existing archive +formats. For example, tar requires information about holes at the +beginning of the archive. + +==Disadvantages== + +* we need to define a new archive format + +Note: Most existing archive formats are optimized to store small files +including file attributes. We simply do not need that for VM archives. + +* archive contains data 'out of order' + +If you want to access image data in sequential order, you need to +re-order archive data. It would be possible to to that on the fly, +using temporary files. + +Fortunately, a normal restore/extract works perfectly with 'out of +order' data, because the target files are seekable. + +* slow backup storage can slow down VM during backup + +It is important to note that we only do sequential writes to the +backup storage. Furthermore one can compress the backup stream. IMHO, +it is better to slow down the VM a bit. All other solutions creates +large amounts of temporary data during backup. + +=Archive format requirements= + +The basic requirement for such new format is that we can store image +date 'out of order'. It is also very likely that we have less than 256 +drives/images per VM, and we want to be able to store VM configuration +files. + +We have defined a very simply format with those properties, see: + +docs/specs/vma_spec.txt + +Please let us know if you know an existing format which provides the +same functionality. + + -- 1.7.2.5
Re: [Qemu-devel] [PATCH v1 1/6] i2c: support address ranges
Il 20/02/2013 06:29, Peter Crosthwaite ha scritto: @@ -192,12 +197,13 @@ static int i2c_slave_post_load(void *opaque, int version_id) const VMStateDescription vmstate_i2c_slave = { .name = I2CSlave, -.version_id = 1, -.minimum_version_id = 1, -.minimum_version_id_old = 1, +.version_id = 2, +.minimum_version_id = 2, +.minimum_version_id_old = 2, .post_load = i2c_slave_post_load, .fields = (VMStateField []) { VMSTATE_UINT8(address, I2CSlave), +VMSTATE_UINT8(address_range, I2CSlave), VMSTATE_END_OF_LIST() Properties do not need to be serialized. Paolo
[Qemu-devel] Live migration using qcow2
Hi everyone According to http://wiki.qemu.org/Migration/Storage section Image Formats qemu can't do live migration without data corruption when using qcow2 or qed due to the metadata caches. Wasn't that fixed by commit 06d9260 ? Also, Clustered File Systems does not seem to be up-to-date since libvirt considers only OCFS and GFS2 to be safe for migration with cache!=none. Since FUSE supports O_DIRECT officially, adding GlusterFS to this list may be appropriate as well? Thanks in advance, Tiziano [1] http://git.qemu.org/?p=qemu.git;a=commit;h=06d9260ffa9dfa0e96e015501e43480ab66f96f6 -- stepping stone GmbH Neufeldstrasse 9 CH-3012 Bern Telefon: +41 31 332 53 63 www.stepping-stone.ch tiziano.muel...@stepping-stone.ch
Re: [Qemu-devel] [PATCH v3 1/6] RFC: Efficient VM backup for qemu
On Wed, Feb 20, 2013 at 09:01:16AM +0100, Markus Armbruster wrote: Dietmar Maurer diet...@proxmox.com writes: * Backup to a single archive file * Backup contain all data to restore VM (full backup) * Do not depend on storage type or image format * Avoid use of temporary storage * store sparse images efficiently It is customary to send a 0/6 cover letter for details like this, rather than slamming it into the first patch (git send-email --cover-letter). But how do I maintain the content of that cover-letter when it is not part of the git tree? Nothing stops you from committing it to your branch. The extra commit isn't sent out, of course. I guess people usually archive it in e-mail instead. I use separate format-patch and send-email steps, so I'll still have the cover letter file around when I send the next version. Kevin
Re: [Qemu-devel] Live migration using qcow2
On Wed, Feb 20, 2013 at 11:47:56AM +0100, Tiziano Müller wrote: Hi everyone According to http://wiki.qemu.org/Migration/Storage section Image Formats qemu can't do live migration without data corruption when using qcow2 or qed due to the metadata caches. Wasn't that fixed by commit 06d9260 ? Yes, it is fixed. Depending on your backend, you still need cache=none/directsync, of course. Kevin
[Qemu-devel] [PATCH 26/38] target-ppc: Use setcond in gen_op_cmp
Which means that callers need not copy data into local tmps. Cc: Alexander Graf ag...@suse.de Signed-off-by: Richard Henderson r...@twiddle.net --- target-ppc/translate.c | 46 +++--- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 0ac072c..7aab6ae 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -596,33 +596,33 @@ static opc_handler_t invalid_handler = { static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf) { -int l1, l2, l3; +TCGv t0 = tcg_temp_new(); +TCGv_i32 t1 = tcg_temp_new_i32(); tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so); -l1 = gen_new_label(); -l2 = gen_new_label(); -l3 = gen_new_label(); -if (s) { -tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1); -tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2); -} else { -tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1); -tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2); -} -tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 CRF_EQ); -tcg_gen_br(l3); -gen_set_label(l1); -tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 CRF_LT); -tcg_gen_br(l3); -gen_set_label(l2); -tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 CRF_GT); -gen_set_label(l3); +tcg_gen_setcond_tl((s ? TCG_COND_LT: TCG_COND_LTU), t0, arg0, arg1); +tcg_gen_trunc_tl_i32(t1, t0); +tcg_gen_shli_i32(t1, t1, CRF_LT); +tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1); + +tcg_gen_setcond_tl((s ? TCG_COND_GT: TCG_COND_GTU), t0, arg0, arg1); +tcg_gen_trunc_tl_i32(t1, t0); +tcg_gen_shli_i32(t1, t1, CRF_GT); +tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1); + +tcg_gen_setcond_tl(TCG_COND_EQ, t0, arg0, arg1); +tcg_gen_trunc_tl_i32(t1, t0); +tcg_gen_shli_i32(t1, t1, CRF_EQ); +tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1); + +tcg_temp_free(t0); +tcg_temp_free_i32(t1); } static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf) { -TCGv t0 = tcg_const_local_tl(arg1); +TCGv t0 = tcg_const_tl(arg1); gen_op_cmp(arg0, t0, s, crf); tcg_temp_free(t0); } @@ -631,8 +631,8 @@ static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf) static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf) { TCGv t0, t1; -t0 = tcg_temp_local_new(); -t1 = tcg_temp_local_new(); +t0 = tcg_temp_new(); +t1 = tcg_temp_new(); if (s) { tcg_gen_ext32s_tl(t0, arg0); tcg_gen_ext32s_tl(t1, arg1); @@ -647,7 +647,7 @@ static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf) static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf) { -TCGv t0 = tcg_const_local_tl(arg1); +TCGv t0 = tcg_const_tl(arg1); gen_op_cmp32(arg0, t0, s, crf); tcg_temp_free(t0); } -- 1.8.1.2
[Qemu-devel] [PATCH v4 10/10] aio: support G_IO_HUP and G_IO_ERR
aio-posix.c could not take advantage of G_IO_HUP and G_IO_ERR because select(2) does not have equivalent events. Now that g_poll(3) is used we can support G_IO_HUP and G_IO_ERR. Signed-off-by: Stefan Hajnoczi stefa...@redhat.com --- aio-posix.c | 12 ++-- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/aio-posix.c b/aio-posix.c index d755e16..b68eccd 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -88,8 +88,8 @@ void aio_set_fd_handler(AioContext *ctx, node-opaque = opaque; node-pollfds_idx = -1; -node-pfd.events = (io_read ? G_IO_IN | G_IO_HUP : 0); -node-pfd.events |= (io_write ? G_IO_OUT : 0); +node-pfd.events = (io_read ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0); +node-pfd.events |= (io_write ? G_IO_OUT | G_IO_ERR : 0); } aio_notify(ctx); @@ -112,13 +112,6 @@ bool aio_pending(AioContext *ctx) QLIST_FOREACH(node, ctx-aio_handlers, node) { int revents; -/* - * FIXME: right now we cannot get G_IO_HUP and G_IO_ERR because - * main-loop.c is still select based (due to the slirp legacy). - * If main-loop.c ever switches to poll, G_IO_ERR should be - * tested too. Dispatching G_IO_ERR to both handlers should be - * okay, since handlers need to be ready for spurious wakeups. - */ revents = node-pfd.revents node-pfd.events; if (revents (G_IO_IN | G_IO_HUP | G_IO_ERR) node-io_read) { return true; @@ -150,7 +143,6 @@ static bool aio_dispatch(AioContext *ctx) revents = node-pfd.revents node-pfd.events; node-pfd.revents = 0; -/* See comment in aio_pending. */ if (!node-deleted (revents (G_IO_IN | G_IO_HUP | G_IO_ERR)) node-io_read) { -- 1.8.1.2
Re: [Qemu-devel] [PATCH 1/9] build: disable Wstrict-prototypes
On Mon, Feb 18, 2013 at 05:56:57PM -0600, Anthony Liguori wrote: GTK won't build with strict-prototypes due to gtkitemfactory.h: /* We use () here to mean unspecified arguments. This is deprecated * as of C99, but we can't change it without breaking compatibility. * (Note that if we are included from a C++ program () will mean * (void) so an explicit cast will be needed.) */ typedef void(*GtkItemFactoryCallback) (); Signed-off-by: Anthony Liguori aligu...@us.ibm.com --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index bf5970f..74d5878 100755 --- a/configure +++ b/configure @@ -283,7 +283,7 @@ sdl_config=${SDL_CONFIG-${cross_prefix}sdl-config} # default flags for all hosts QEMU_CFLAGS=-fno-strict-aliasing $QEMU_CFLAGS QEMU_CFLAGS=-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS -QEMU_CFLAGS=-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS +QEMU_CFLAGS=-Wredundant-decls $QEMU_CFLAGS QEMU_CFLAGS=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS QEMU_INCLUDES=-I. -I\$(SRC_PATH) -I\$(SRC_PATH)/include if test $debug_info = yes; then Other places wrap the inclusion of problematic headers in '#pragma GCC diagnostic ...' instead of globally disabling warnings. Kevin
[Qemu-devel] [PATCH 16/38] target-s390x: Use mulu2 for mlgr insn
Signed-off-by: Richard Henderson r...@twiddle.net --- target-s390x/helper.h | 1 - target-s390x/int_helper.c | 8 target-s390x/translate.c | 3 +-- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/target-s390x/helper.h b/target-s390x/helper.h index dd90d93..0d80aa0 100644 --- a/target-s390x/helper.h +++ b/target-s390x/helper.h @@ -8,7 +8,6 @@ DEF_HELPER_FLAGS_4(mvc, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(clc, TCG_CALL_NO_WG, i32, env, i32, i64, i64) DEF_HELPER_3(mvcl, i32, env, i32, i32) DEF_HELPER_FLAGS_4(clm, TCG_CALL_NO_WG, i32, env, i32, i32, i64) -DEF_HELPER_FLAGS_3(mul128, TCG_CALL_NO_RWG, i64, env, i64, i64) DEF_HELPER_FLAGS_3(divs32, TCG_CALL_NO_WG, s64, env, s64, s64) DEF_HELPER_FLAGS_3(divu32, TCG_CALL_NO_WG, i64, env, i64, i64) DEF_HELPER_FLAGS_3(divs64, TCG_CALL_NO_WG, s64, env, s64, s64) diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c index 6858301..af16b21 100644 --- a/target-s390x/int_helper.c +++ b/target-s390x/int_helper.c @@ -29,14 +29,6 @@ #define HELPER_LOG(x...) #endif -/* 64/64 - 128 unsigned multiplication */ -uint64_t HELPER(mul128)(CPUS390XState *env, uint64_t v1, uint64_t v2) -{ -uint64_t reth; -mulu64(env-retxl, reth, v1, v2); -return reth; -} - /* 64/32 - 32 signed division */ int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b64) { diff --git a/target-s390x/translate.c b/target-s390x/translate.c index a57296c..bdf69a3 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -2566,8 +2566,7 @@ static ExitStatus op_mul(DisasContext *s, DisasOps *o) static ExitStatus op_mul128(DisasContext *s, DisasOps *o) { -gen_helper_mul128(o-out, cpu_env, o-in1, o-in2); -return_low128(o-out2); +tcg_gen_mulu2_i64(o-out2, o-out, o-in1, o-in2); return NO_EXIT; } -- 1.8.1.2
Re: [Qemu-devel] [PATCH 0/6] qcow2: cache flush fixes and performance improvements
On Wed, Feb 20, 2013 at 11:27:47AM +0100, Kevin Wolf wrote: On Tue, Feb 19, 2013 at 04:45:00PM +0100, Stefan Hajnoczi wrote: Users have reported that qcow2 internal snapshot creation is slow. I filed a bug report at https://bugs.launchpad.net/qemu/+bug/1126369. This patch series reduces the time for qcow2 internal snapshot creation significantly, from more than 3 minutes to under 1 second. In the process of removing unnecessary cache flushes, I also stumbled upon instances of bdrv_flush(bs-file) where we really want to flush metadata updates. Since qcow2 caches metadata this actually does not write out the metadata updates to disk! The fix is either bdrv_flush(bs) or a more specific cache flush (e.g. refcount block cache). This series passes qemu-iotests. Stefan Hajnoczi (6): qcow2: flush refcount cache correctly in alloc_refcount_block() qcow2: flush refcount cache correctly in qcow2_write_snapshots() qcow2: flush caches in qcow2_alloc_bytes() qcow2: flush in qcow2_update_snapshot_refcount() qcow2: drop flush in update_cluster_refcount() qcow2: drop unnecessary flush in qcow2_update_snapshot_refcount() block/qcow2-refcount.c | 12 +++- block/qcow2-snapshot.c | 7 +-- 2 files changed, 4 insertions(+), 15 deletions(-) You touch a few bdrv_flush() callers that don't check the return value. Could you use the opportunity to fix that as well? Sure, will send a v2. Stefan
[Qemu-devel] [PATCH v4 02/10] main-loop: switch to g_poll() on POSIX hosts
Use g_poll(3) instead of select(2). Well, this is kind of a cheat. It's true that we're now using g_poll(3) on POSIX hosts but the *_fill() and *_poll() functions are still using rfds/wfds/xfds. We've set the scene to start converting *_fill() and *_poll() functions step-by-step until no more rfds/wfds/xfds users remain. Then we'll drop the temporary gpollfds_from_select() and gpollfds_to_select() functions and be left with native g_poll(2). On Windows things are a little crazy: convert from rfds/wfds/xfds to GPollFDs, back to rfds/wfds/xfds, call select(2), rfds/wfds/xfds back to GPollFDs, and finally back to rfds/wfds/xfds again. This is only temporary and keeps the Windows build working through the following patches. We'll drop this excessive conversion later and be left with a single GPollFDs - select(2) - GPollFDs sequence that allows Windows to use select(2) while the rest of QEMU only knows about GPollFD. Signed-off-by: Stefan Hajnoczi stefa...@redhat.com --- main-loop.c | 137 1 file changed, 129 insertions(+), 8 deletions(-) diff --git a/main-loop.c b/main-loop.c index d0d8fe4..489b27c 100644 --- a/main-loop.c +++ b/main-loop.c @@ -117,6 +117,8 @@ void qemu_notify_event(void) aio_notify(qemu_aio_context); } +static GArray *gpollfds; + int qemu_init_main_loop(void) { int ret; @@ -133,6 +135,7 @@ int qemu_init_main_loop(void) return ret; } +gpollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD)); qemu_aio_context = aio_context_new(); src = aio_get_g_source(qemu_aio_context); g_source_attach(src, NULL); @@ -146,6 +149,62 @@ static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */ static int n_poll_fds; static int max_priority; +/* Load rfds/wfds/xfds into gpollfds. Will be removed a few commits later. */ +static void gpollfds_from_select(void) +{ +int fd; +for (fd = 0; fd = nfds; fd++) { +int events = 0; +if (FD_ISSET(fd, rfds)) { +events |= G_IO_IN | G_IO_HUP | G_IO_ERR; +} +if (FD_ISSET(fd, wfds)) { +events |= G_IO_OUT | G_IO_ERR; +} +if (FD_ISSET(fd, xfds)) { +events |= G_IO_PRI; +} +if (events) { +GPollFD pfd = { +.fd = fd, +.events = events, +}; +g_array_append_val(gpollfds, pfd); +} +} +} + +/* Store gpollfds revents into rfds/wfds/xfds. Will be removed a few commits + * later. + */ +static void gpollfds_to_select(int ret) +{ +int i; + +FD_ZERO(rfds); +FD_ZERO(wfds); +FD_ZERO(xfds); + +if (ret = 0) { +return; +} + +for (i = 0; i gpollfds-len; i++) { +int fd = g_array_index(gpollfds, GPollFD, i).fd; +int revents = g_array_index(gpollfds, GPollFD, i).revents; + +if (revents (G_IO_IN | G_IO_HUP | G_IO_ERR)) { +FD_SET(fd, rfds); +} +if (revents (G_IO_OUT | G_IO_ERR)) { +FD_SET(fd, wfds); +} +if (revents G_IO_PRI) { +FD_SET(fd, xfds); +} +} +} + #ifndef _WIN32 static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds, fd_set *xfds, uint32_t *cur_timeout) @@ -212,22 +271,22 @@ static void glib_select_poll(fd_set *rfds, fd_set *wfds, fd_set *xfds, static int os_host_main_loop_wait(uint32_t timeout) { -struct timeval tv, *tvarg = NULL; int ret; glib_select_fill(nfds, rfds, wfds, xfds, timeout); -if (timeout UINT32_MAX) { -tvarg = tv; -tv.tv_sec = timeout / 1000; -tv.tv_usec = (timeout % 1000) * 1000; -} - if (timeout 0) { qemu_mutex_unlock_iothread(); } -ret = select(nfds + 1, rfds, wfds, xfds, tvarg); +/* We'll eventually drop fd_set completely. But for now we still have + * *_fill() and *_poll() functions that use rfds/wfds/xfds. + */ +gpollfds_from_select(); + +ret = g_poll((GPollFD *)gpollfds-data, gpollfds-len, timeout); + +gpollfds_to_select(ret); if (timeout 0) { qemu_mutex_lock_iothread(); @@ -327,6 +386,55 @@ void qemu_fd_register(int fd) FD_CONNECT | FD_WRITE | FD_OOB); } +static int pollfds_fill(GArray *pollfds, fd_set *rfds, fd_set *wfds, +fd_set *xfds) +{ +int nfds = -1; +int i; + +for (i = 0; i pollfds-len; i++) { +GPollFD *pfd = g_array_index(pollfds, GPollFD, i); +int fd = pfd-fd; +int events = pfd-events; +if (events (G_IO_IN | G_IO_HUP | G_IO_ERR)) { +FD_SET(fd, rfds); +nfds = MAX(nfds, fd); +} +if (events (G_IO_OUT | G_IO_ERR)) { +FD_SET(fd, wfds); +nfds = MAX(nfds, fd); +} +if (events G_IO_PRI) { +FD_SET(fd, xfds); +nfds = MAX(nfds, fd); +} +} +
Re: [Qemu-devel] how to ues qemu -sd option?
Weng Fan wengfan-f...@cn.fujitsu.com writes: Hi all: I want to use the qemu's -sd option to emulate a sd card, so that I can get more free space. When I use the command qemu-system-ppc -M mpc8544ds -kernel uImage -initrd initrd.img -append root=/dev/ram rdinit=/linuxrc -nographic -sd sd.img to start the kernel image, I can't find any device like mmcblk in the /dev . Any ideas how to get this work? -sd sd.img is shorthand for -drive if=sd,index=0,file=sd.img. Like all -drive (except for if=none), it requests the board to create a suitable device. Boards act on some requests, and ignore others. mpc8544ds ignores if=sd. To add devices beyond what the board code can do, use -device, like this: -drive if=none,id=sd0,file=sd.img -device DEV-MODEL,drive=sd0 with a suitable sd card DEV-MODEL. However, I'm not aware of an sd card device model that can be plugged that way. Perhaps Andreas (cc'ed) knows more. See also docs/qdev-device-use.txt section Block Devices.
[Qemu-devel] [PATCH] help: add docs for multiqueue tap options
Cc: Markus Armbruster arm...@redhat.com Cc: Jason Wang jasow...@redhat.com Signed-off-by: Jason Wang jasow...@redhat.com --- This patch is neede for 1.4 stable also. --- qapi-schema.json |6 ++ qemu-options.hx |4 +++- 2 files changed, 9 insertions(+), 1 deletions(-) diff --git a/qapi-schema.json b/qapi-schema.json index 7275b5d..cd7ea25 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2504,6 +2504,9 @@ # # @fd: #optional file descriptor of an already opened tap # +# @fds: #optional multiple file descriptors of already opened multiqueue capable +# tap +# # @script: #optional script to initialize the interface # # @downscript: #optional script to shut down the interface @@ -2518,6 +2521,9 @@ # # @vhostfd: #optional file descriptor of an already opened vhost net device # +# @vhostfds: #optional file descriptors of multiple already opened vhost net +# devices +# # @vhostforce: #optional vhost on for non-MSIX virtio guests # # Since 1.2 diff --git a/qemu-options.hx b/qemu-options.hx index 4bc9c85..2832d82 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1354,7 +1354,7 @@ DEF(net, HAS_ARG, QEMU_OPTION_net, -net tap[,vlan=n][,name=str],ifname=name\n connect the host TAP network interface to VLAN 'n'\n #else --net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostforce=on|off]\n +-net tap[,vlan=n][,name=str][,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile][,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off]\n connect the host TAP network interface to VLAN 'n'\n use network scripts 'file' (default= DEFAULT_NETWORK_SCRIPT )\n to configure it and 'dfile' (default= DEFAULT_NETWORK_DOWN_SCRIPT )\n @@ -1363,6 +1363,7 @@ DEF(net, HAS_ARG, QEMU_OPTION_net, use network helper 'helper' (default= DEFAULT_BRIDGE_HELPER ) to\n configure it\n use 'fd=h' to connect to an already opened TAP interface\n +use 'fds=x:y:...:z' to connect to already opened multiqueue capable TAP interfaces\n use 'sndbuf=nbytes' to limit the size of the send buffer (the\n default is disabled 'sndbuf=0' to enable flow control set 'sndbuf=1048576')\n use vnet_hdr=off to avoid enabling the IFF_VNET_HDR tap flag\n @@ -1371,6 +1372,7 @@ DEF(net, HAS_ARG, QEMU_OPTION_net, (only has effect for virtio guests which use MSIX)\n use vhostforce=on to force vhost on for non-MSIX virtio guests\n use 'vhostfd=h' to connect to an already opened vhost net device\n +use 'vhostfds=x:y:...:z to connect to multiple already opened vhost net devices\n -net bridge[,vlan=n][,name=str][,br=bridge][,helper=helper]\n connects a host TAP network interface to a host bridge device 'br'\n (default= DEFAULT_BRIDGE_INTERFACE ) using the program 'helper'\n -- 1.7.1
Re: [Qemu-devel] how to ues qemu -sd option?
Hi Weng Fan, On Wed, Feb 20, 2013 at 6:18 PM, Markus Armbruster arm...@redhat.com wrote: Weng Fan wengfan-f...@cn.fujitsu.com writes: Hi all: I want to use the qemu's -sd option to emulate a sd card, so that I can get more free space. When I use the command qemu-system-ppc -M mpc8544ds -kernel uImage -initrd initrd.img -append root=/dev/ram rdinit=/linuxrc -nographic -sd sd.img to start the kernel image, I can't find any device like mmcblk in the /dev . Any ideas how to get this work? -sd sd.img is shorthand for -drive if=sd,index=0,file=sd.img. Like all -drive (except for if=none), it requests the board to create a suitable device. Boards act on some requests, and ignore others. mpc8544ds ignores if=sd. To add devices beyond what the board code can do, use -device, like this: -drive if=none,id=sd0,file=sd.img -device DEV-MODEL,drive=sd0 With minimal effort you may be able to mock something up with SDHCI, at least in its PIO mode.The SDHCI patches are currently doing review cycles on list. Regards, Peter with a suitable sd card DEV-MODEL. However, I'm not aware of an sd card device model that can be plugged that way. Perhaps Andreas (cc'ed) knows more. See also docs/qdev-device-use.txt section Block Devices.
[Qemu-devel] emulate powerpc(mpc8544ds) on x86 architecture
Hi all: I want to emulate powerpc(mpc8544ds) on x86 architecture, is anybody succeed in it? My working step: about qemu: ./configure --cpu=ppc --target-list=ppc-softmmu --enable-fdt --enable-kvm --enable-tcg-interpreter --enable-linux-user --prefix=/home/shir/install/qemu/ make make install but everytime I start my qemu-system-ppc, qemu-system-ppc -M mpc8544ds -kernel uImage -append root=/dev/ram rdinit=/linuxrc -initrd initrd -nographic I get this error : KVM: Couldn't find level irq capability. Expect the VM to stall at times kvm_init_vcpu failed: Cannot allocate memory fedora project reference below( https://fedoraproject.org/wiki/Features/KVM_and_QEMU_merge ): KVM provides kernel support for running guests of *the same architecture* as the host. Guests run directly on the hardware with out any translation needed by the host, allowing much higher levels of performance to be attained. QEMU can now use the KVM kernel support for higher performance virtualization. is that true? -- -- Best regards! -- Shi Rong Nanjing Fujitsu Nanda Software Tech. Co., Ltd.(FNST) No. 6 Wenzhu Road, Nanjing, 210012, China TEL:+86+25-86630566-8222 MOBILE: 15996209501 EMail:shir.f...@cn.fujitsu.com -- This communication is for use by the intended recipient(s) only and may contain information that is privileged, confidential and exempt from disclosure under applicable law. If you are not an intended recipient of this communication, you are hereby notified that any dissemination, distribution or copying hereof is strictly prohibited. If you have received this communication in error, please notify me by reply e-mail, permanently delete this communication from your system, and destroy any hard copies you may have printed.
Re: [Qemu-devel] [PATCH 4/9] target-i386: convert 'hv_relaxed' to static property
On Wed, Feb 20, 2013 at 10:03:37AM +0100, Igor Mammedov wrote: On Tue, 19 Feb 2013 15:45:16 -0300 Eduardo Habkost ehabk...@redhat.com wrote: On Mon, Feb 11, 2013 at 05:35:06PM +0100, Igor Mammedov wrote: Signed-off-by: Igor Mammedov imamm...@redhat.com --- target-i386/cpu.c | 35 ++- 1 files changed, 34 insertions(+), 1 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 1f14b65..b804031 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -528,6 +528,38 @@ PropertyInfo qdev_prop_spinlocks = { .defval = _defval \ } +static void x86_get_hv_relaxed(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ +bool value = hyperv_relaxed_timing_enabled(); + +visit_type_bool(v, value, name, errp); +} + +static void x86_set_hv_relaxed(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ +bool value; + +visit_type_bool(v, value, name, errp); +if (error_is_set(errp)) { +return; +} +hyperv_enable_relaxed_timing(value); +} + +PropertyInfo qdev_prop_hv_relaxed = { +.name = boolean, +.get = x86_get_hv_relaxed, +.set = x86_set_hv_relaxed, +}; +#define DEFINE_PROP_HV_RELAXED(_n, _defval) { \ +.name = _n, \ +.info = qdev_prop_hv_relaxed,\ +.qtype = QTYPE_QBOOL, \ +.defval = _defval \ +} + static Property cpu_x86_properties[] = { DEFINE_PROP_FAMILY(family), DEFINE_PROP_MODEL(model), @@ -538,6 +570,7 @@ static Property cpu_x86_properties[] = { DEFINE_PROP_MODEL_ID(model-id), DEFINE_PROP_TSC_FREQ(tsc-frequency), DEFINE_PROP_HV_SPINLOCKS(hv-spinlocks, HYPERV_SPINLOCK_NEVER_RETRY), +DEFINE_PROP_HV_RELAXED(hv-relaxed, false), Why not simply make it a X86CPU struct field, so we don't need a special PropertyInfo? The whole contents of target-i386/hyperv.c are getters/setters for three static variables that should have been X86CPU fields in the first place. I went via less intrusive approach to avoid breaking anything during conversion. Can we proceed with conversion first and than decide whether to move hv_* into CPU or not? Personally, I find the complex getter+setter+PropertyInfo+DEFINE_PROP_* code above more complex and harder to review (thus harder to make me confident it won't break anything) than simply moving a static variable to a X86CPU field. Also, it doesn't even make sense to have a X86CPU property available for a static variable that is not per-CPU. What do we gain by making it look like a per-X86CPU property if it is not? DEFINE_PROP_END_OF_LIST(), }; @@ -1468,7 +1501,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp) } else if (!strcmp(featurestr, enforce)) { check_cpuid = enforce_cpuid = 1; } else if (!strcmp(featurestr, hv_relaxed)) { -hyperv_enable_relaxed_timing(true); +object_property_parse(OBJECT(cpu), on, hv-relaxed, errp); } else if (!strcmp(featurestr, hv_vapic)) { hyperv_enable_vapic_recommended(true); } else { -- 1.7.1 -- Eduardo
[Qemu-devel] [PATCH v4 3/6] add backup related monitor commands
We use a generic BackupDriver struct to encapsulate all archive format related function. Another option would be to simply dump devid,cluster_num,cluster_data to the output fh (pipe), and an external binary saves the data. That way we could move the whole archive format related code out of qemu. Signed-off-by: Dietmar Maurer diet...@proxmox.com --- backup.h | 12 ++ blockdev.c | 423 ++ hmp-commands.hx | 31 hmp.c| 63 hmp.h|3 + monitor.c|7 + qapi-schema.json | 95 qmp-commands.hx | 27 8 files changed, 661 insertions(+), 0 deletions(-) diff --git a/backup.h b/backup.h index d9395bc..c8ba153 100644 --- a/backup.h +++ b/backup.h @@ -29,4 +29,16 @@ int backup_job_create(BlockDriverState *bs, BackupDumpFunc *backup_dump_cb, BlockDriverCompletionFunc *backup_complete_cb, void *opaque, int64_t speed); +typedef struct BackupDriver { +const char *format; +void *(*open_cb)(const char *filename, uuid_t uuid, Error **errp); +int (*close_cb)(void *opaque, Error **errp); +int (*register_config_cb)(void *opaque, const char *name, gpointer data, + size_t data_len); +int (*register_stream_cb)(void *opaque, const char *devname, size_t size); +int (*dump_cb)(void *opaque, uint8_t dev_id, int64_t cluster_num, + unsigned char *buf, size_t *zero_bytes); +int (*complete_cb)(void *opaque, uint8_t dev_id, int ret); +} BackupDriver; + #endif /* QEMU_BACKUP_H */ diff --git a/blockdev.c b/blockdev.c index 63e6f1e..c340fde 100644 --- a/blockdev.c +++ b/blockdev.c @@ -20,6 +20,7 @@ #include qmp-commands.h #include trace.h #include sysemu/arch_init.h +#include backup.h static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives); @@ -1334,6 +1335,428 @@ void qmp_drive_mirror(const char *device, const char *target, drive_get_ref(drive_get_by_blockdev(bs)); } +/* Backup related function */ + +static void backup_run_next_job(void); + +static struct GenericBackupState { +Error *error; +bool cancel; +uuid_t uuid; +char uuid_str[37]; +int64_t speed; +time_t start_time; +time_t end_time; +char *backup_file; +const BackupDriver *driver; +void *writer; +GList *bcb_list; +size_t total; +size_t transferred; +size_t zero_bytes; +} backup_state; + +typedef struct BackupCB { +BlockDriverState *bs; +uint8_t dev_id; +bool started; +bool completed; +size_t size; +size_t transferred; +size_t zero_bytes; +} BackupCB; + +static int backup_dump_cb(void *opaque, BlockDriverState *bs, + int64_t cluster_num, unsigned char *buf) +{ +BackupCB *bcb = opaque; + +assert(backup_state.driver); +assert(backup_state.writer); +assert(backup_state.driver-dump_cb); + +size_t zero_bytes = 0; +int bytes = backup_state.driver-dump_cb(backup_state.writer, + bcb-dev_id, cluster_num, + buf, zero_bytes); + +if (bytes 0) { +bcb-transferred += bytes; +backup_state.transferred += bytes; +if (zero_bytes) { +bcb-zero_bytes += bytes; +backup_state.zero_bytes += zero_bytes; +} +} + +return bytes; +} + +static void backup_cleanup(void) +{ +if (backup_state.writer backup_state.driver) { +backup_state.end_time = time(NULL); +Error *local_err = NULL; +backup_state.driver-close_cb(backup_state.writer, local_err); +error_propagate(backup_state.error, local_err); +backup_state.writer = NULL; +} + +if (backup_state.bcb_list) { +GList *l = backup_state.bcb_list; +while (l) { +BackupCB *bcb = l-data; +l = g_list_next(l); +drive_put_ref_bh_schedule(drive_get_by_blockdev(bcb-bs)); +g_free(bcb); +} +g_list_free(backup_state.bcb_list); +backup_state.bcb_list = NULL; +} +} + +static void backup_complete_cb(void *opaque, int ret) +{ +BackupCB *bcb = opaque; + +assert(backup_state.driver); +assert(backup_state.writer); +assert(backup_state.driver-complete_cb); +assert(backup_state.driver-close_cb); + +bcb-completed = true; + +backup_state.driver-complete_cb(backup_state.writer, bcb-dev_id, ret); + +if (!backup_state.cancel) { +backup_run_next_job(); +} +} + +static void backup_cancel(void) +{ +backup_state.cancel = true; + +if (!backup_state.error) { +error_setg(backup_state.error, backup cancelled); +} + +/* drain all i/o (awake jobs waiting for aio) */ +bdrv_drain_all(); + +int job_count = 0; +GList *l = backup_state.bcb_list; +while (l) { +BackupCB *bcb = l-data; +
[Qemu-devel] [PATCH v4 5/6] add regression tests for backup
Simple regression tests using vma-reader and vma-writer. Note: the call to g_thread_init() solves problems with g_slice_alloc() - without that call we get arbitrary crashes. Signed-off-by: Dietmar Maurer diet...@proxmox.com --- tests/Makefile | 11 +- tests/backup-test.c | 517 +++ 2 files changed, 526 insertions(+), 2 deletions(-) create mode 100644 tests/backup-test.c diff --git a/tests/Makefile b/tests/Makefile index 567e36e..136be84 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -59,6 +59,8 @@ gcov-files-test-mul64-y = util/host-utils.c check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh +check-backup-y = tests/backup-test$(EXESUF) + # All QTests for now are POSIX-only, but the dependencies are # really in libqtest, not in the testcases themselves. check-qtest-i386-y = tests/fdc-test$(EXESUF) @@ -102,6 +104,7 @@ tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(block-obj-y) libqemuutil tests/test-aio$(EXESUF): tests/test-aio.o $(block-obj-y) libqemuutil.a libqemustub.a tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(block-obj-y) libqemuutil.a libqemustub.a tests/test-iov$(EXESUF): tests/test-iov.o libqemuutil.a +tests/backup-test$(EXESUF): tests/backup-test.o vma-reader.o $(block-obj-y) libqemuutil.a libqemustub.a tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o libqemuutil.a libqemustub.a tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o xbzrle.o page_cache.o libqemuutil.a @@ -213,10 +216,14 @@ check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF) # Consolidated targets -.PHONY: check-qtest check-unit check +.PHONY: check-backup check-qtest check-unit check check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS)) check-unit: $(patsubst %,check-%, $(check-unit-y)) check-block: $(patsubst %,check-%, $(check-block-y)) -check: check-unit check-qtest + +check-backup: tests/backup-test$(EXESUF) + $ + +check: check-unit check-qtest check-backup -include $(wildcard tests/*.d) diff --git a/tests/backup-test.c b/tests/backup-test.c new file mode 100644 index 000..5ff6f1d --- /dev/null +++ b/tests/backup-test.c @@ -0,0 +1,517 @@ +/* + * QEMU backup test suit + * + * Copyright (C) Proxmox Server Solutions + * + * Authors: + * Dietmar Maurer (diet...@proxmox.com) + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Fixme: running 'backup-test -l' trigger a bug in g_slice_alloc() + * Note: 'G_SLICE=always-malloc ./tests/backup-test -l' works + * + */ + +#include sys/time.h +#include sys/types.h +#include stdarg.h +#include stdio.h +#include getopt.h +#include libgen.h + +#include qemu-common.h +#include block/block.h + +#include vma.h + +static int opt_debug; +static int opt_loop; + +#define DPRINTF(fmt, ...) \ +do { if (opt_debug) { printf(fmt, ## __VA_ARGS__); } } while (0) + +#define CLUSTER(x) (x*BACKUP_CLUSTER_SIZE) + +#define RUN_TEST(testfunc, speed) \ +backup_test(#testfunc speed #speed, speed, testfunc); + + +static unsigned char buf_sec_pattern_cd[BDRV_SECTOR_SIZE]; +static unsigned char buf_sec_pattern_32[BDRV_SECTOR_SIZE]; + +#define TEST_IMG_SIZE (6*1024*1024+BDRV_SECTOR_SIZE) +#define TEST_IMG_NAME backuptest.raw +#define TEST_IMG_RESTORE_NAME backuptest.raw.restore +#define TEST_VMA_NAME backuptest.vma + +typedef struct BackupCB { +VmaWriter *vmaw; +uint8_t dev_id; +} BackupCB; + +static int backup_dump_cb(void *opaque, BlockDriverState *bs, + int64_t cluster_num, unsigned char *buf) +{ +BackupCB *bcb = opaque; + +DPRINTF(backup_dump_cb C%zd %d\n, cluster_num, bcb-dev_id); + +size_t zb = 0; +if (vma_writer_write(bcb-vmaw, bcb-dev_id, cluster_num, buf, zb) 0) { +printf(backup_dump_cb vma_writer_write failed\n); +return -1; +} + +return 0; +} + +static void backup_complete_cb(void *opaque, int ret) +{ +BackupCB *bcb = opaque; + +DPRINTF(backup_complete_cb %d %d\n, bcb-dev_id, ret); + +if (ret 0) { +vma_writer_set_error(bcb-vmaw, backup_complete_cb %d, ret); +} + +if (vma_writer_close_stream(bcb-vmaw, bcb-dev_id) = 0) { +Error *err = NULL; +if (vma_writer_close(bcb-vmaw, err) != 0) { +g_error(vma_writer_close failed %s, error_get_pretty(err)); +} +} +DPRINTF(backup_complete_cb finish\n); +} + +static void write_sec_pattern_cd(BlockDriverState *bs, int64_t offset) +{ +int ret; + +DPRINTF(write_sec_pattern_cd %zd\n, offset); + +if (offset 0x1ff) { +g_error(write_sec_pattern_cd offset %zd is not sector aligned\n, +offset); +} + +ret = bdrv_write(bs, offset 9, buf_sec_pattern_cd, 1); +if (ret 0) { +g_error(write_sec_pattern_cd %zd failed, offset); +} + +} + +static void read_sec(BlockDriverState
[Qemu-devel] [PATCH 05/38] tcg: Add signed multiword multiplication operations
Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/README | 4 tcg/arm/tcg-target.h | 1 + tcg/hppa/tcg-target.h | 1 + tcg/i386/tcg-target.h | 2 ++ tcg/ia64/tcg-target.h | 2 ++ tcg/mips/tcg-target.h | 1 + tcg/optimize.c | 1 + tcg/ppc/tcg-target.h | 1 + tcg/ppc64/tcg-target.h | 2 ++ tcg/s390/tcg-target.h | 2 ++ tcg/sparc/tcg-target.h | 2 ++ tcg/tcg-opc.h | 2 ++ tcg/tcg.h | 1 + tcg/tci/tcg-target.h | 2 ++ 14 files changed, 24 insertions(+) diff --git a/tcg/README b/tcg/README index 89f0cdd..934e7af 100644 --- a/tcg/README +++ b/tcg/README @@ -375,6 +375,10 @@ is returned in two single-word outputs. Similar to mul, except two unsigned inputs T1 and T2 yielding the full double-word product T0. The later is returned in two single-word outputs. +* muls2_i32/i64 t0_low, t0_high, t1, t2 + +Similar to mulu2, except the two inputs T1 and T2 are signed. + * 64-bit target on 32-bit host support The following opcodes are internal to TCG. Thus they are to be implemented by diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index 7083f3a..f9599bd 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -75,6 +75,7 @@ typedef enum { #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 0 #define TCG_TARGET_HAS_movcond_i32 1 +#define TCG_TARGET_HAS_muls2_i320 enum { TCG_AREG0 = TCG_REG_R6, diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h index e2754fe..ebd53d9 100644 --- a/tcg/hppa/tcg-target.h +++ b/tcg/hppa/tcg-target.h @@ -98,6 +98,7 @@ typedef enum { #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 #define TCG_TARGET_HAS_movcond_i32 1 +#define TCG_TARGET_HAS_muls2_i320 /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, 0, rs */ diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index 4f00171..2b08ef7 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -95,6 +95,7 @@ typedef enum { #define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_mulu2_i321 +#define TCG_TARGET_HAS_muls2_i320 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div2_i64 1 @@ -120,6 +121,7 @@ typedef enum { #define TCG_TARGET_HAS_add2_i64 0 #define TCG_TARGET_HAS_sub2_i64 0 #define TCG_TARGET_HAS_mulu2_i640 +#define TCG_TARGET_HAS_muls2_i640 #endif #define TCG_TARGET_deposit_i32_valid(ofs, len) \ diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index 40f442e..e3d72ea 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -142,6 +142,8 @@ typedef enum { #define TCG_TARGET_HAS_sub2_i64 0 #define TCG_TARGET_HAS_mulu2_i320 #define TCG_TARGET_HAS_mulu2_i640 +#define TCG_TARGET_HAS_muls2_i320 +#define TCG_TARGET_HAS_muls2_i640 #define TCG_TARGET_deposit_i32_valid(ofs, len) ((len) = 16) #define TCG_TARGET_deposit_i64_valid(ofs, len) ((len) = 16) diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 78af664..0384bd3 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -87,6 +87,7 @@ typedef enum { #define TCG_TARGET_HAS_orc_i32 0 #define TCG_TARGET_HAS_eqv_i32 0 #define TCG_TARGET_HAS_nand_i32 0 +#define TCG_TARGET_HAS_muls2_i320 /* optional instructions only implemented on MIPS4, MIPS32 and Loongson 2 */ #if (defined(__mips_isa_rev) (__mips_isa_rev = 1)) || \ diff --git a/tcg/optimize.c b/tcg/optimize.c index 027b3a5..bc6e5c1 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -559,6 +559,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, swap_commutative(args[1], args[3], args[5]); break; CASE_OP_32_64(mulu2): +CASE_OP_32_64(muls2): swap_commutative(args[0], args[2], args[3]); break; case INDEX_op_brcond2_i32: diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h index 0fdad04..17a6bb3 100644 --- a/tcg/ppc/tcg-target.h +++ b/tcg/ppc/tcg-target.h @@ -94,6 +94,7 @@ typedef enum { #define TCG_TARGET_HAS_nor_i32 1 #define TCG_TARGET_HAS_deposit_i32 1 #define TCG_TARGET_HAS_movcond_i32 1 +#define TCG_TARGET_HAS_muls2_i320 #define TCG_AREG0 TCG_REG_R27 diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h index 86929c1..aa6a0f0 100644 --- a/tcg/ppc64/tcg-target.h +++ b/tcg/ppc64/tcg-target.h @@ -88,6 +88,7 @@ typedef enum { #define TCG_TARGET_HAS_add2_i32 0 #define TCG_TARGET_HAS_sub2_i32 0 #define TCG_TARGET_HAS_mulu2_i320 +#define TCG_TARGET_HAS_muls2_i320 #define TCG_TARGET_HAS_div_i64 1 #define TCG_TARGET_HAS_rot_i64 0 @@ -112,6 +113,7 @@ typedef enum { #define TCG_TARGET_HAS_add2_i64 0
[Qemu-devel] [PATCH v1 3/5] xilinx_spips: Add missing dual-bus snoop commands
From: Nathan Rossi nathan.ro...@xilinx.com Added additional commands to the switch to check for when snooping commands in dual bus mode setups. Cleaned up code to use an enum. Signed-off-by: Nathan Rossi nathan.ro...@xilinx.com Signed-off-by: Peter Crosthwaite peter.crosthwa...@xilinx.com --- hw/xilinx_spips.c | 29 +++-- 1 files changed, 23 insertions(+), 6 deletions(-) diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c index 03797c3..45a1c51 100644 --- a/hw/xilinx_spips.c +++ b/hw/xilinx_spips.c @@ -115,6 +115,19 @@ #define SNOOP_NONE 0xFE #define SNOOP_STRIPING 0 +typedef enum { +READ = 0x3, +FAST_READ = 0xb, +DOR = 0x3b, +QOR = 0x6b, +DIOR = 0xbb, +QIOR = 0xeb, + +PP = 0x2, +DPP = 0xa2, +QPP = 0x32, +} FlashCMD; + typedef struct { SysBusDevice busdev; MemoryRegion iomem; @@ -251,15 +264,19 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s) switch (s-snoop_state) { case (SNOOP_CHECKING): switch (tx) { /* new instruction code */ -case 0x0b: /* dual/quad output read DOR/QOR */ -case 0x6b: -s-snoop_state = 4; +case READ: /* 3 address bytes, no dummy bytes/cycles */ +case PP: +case DPP: +case QPP: +s-snoop_state = 3; break; -/* FIXME: these vary between vendor - set to spansion */ -case 0xbb: /* high performance dual read DIOR */ +case FAST_READ: /* 3 address bytes, 1 dummy byte */ +case DOR: +case QOR: +case DIOR: /* FIXME: these vary between vendor - set to spansion */ s-snoop_state = 4; break; -case 0xeb: /* high performance quad read QIOR */ +case QIOR: /* 3 address bytes, 2 dummy bytes */ s-snoop_state = 6; break; default: -- 1.7.0.4
Re: [Qemu-devel] [PATCH v2] vga: fix byteswapping.
On Wed, 20 Feb 2013, Gerd Hoffmann wrote: In case host and guest endianness differ the vga code first creates a shared surface (using qemu_create_displaysurface_from), then goes patch the surface format to indicate that the bytes must be swapped. The switch to pixman broke that hack as the format patching isn't propagated into the pixman image, so ui code using the pixman image directly (such as vnc) uses the wrong format. Fix that by adding a byteswap parameter to qemu_create_displaysurface_from, so we'll use the correct format when creating the surface (and the pixman image) and don't have to patch the format afterwards. [ v2: unbreak xen build ] Cc: qemu-sta...@nongnu.org Cc: mark.cave-ayl...@ilande.co.uk Cc: ag...@suse.de Signed-off-by: Gerd Hoffmann kra...@redhat.com the patch looks good to me hw/qxl-render.c |3 ++- hw/vga.c | 18 -- hw/vmware_vga.c |2 +- hw/xenfb.c |3 ++- include/ui/console.h |3 ++- ui/console.c |9 +++-- 6 files changed, 22 insertions(+), 16 deletions(-) diff --git a/hw/qxl-render.c b/hw/qxl-render.c index 88e63f8..455fb91 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -118,7 +118,8 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) qxl-guest_primary.surface.height, qxl-guest_primary.bits_pp, qxl-guest_primary.abs_stride, - qxl-guest_primary.data); + qxl-guest_primary.data, + false); } else { qemu_resize_displaysurface(vga-ds, qxl-guest_primary.surface.width, diff --git a/hw/vga.c b/hw/vga.c index e2ba7f2..1caf23d 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1643,6 +1643,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) uint8_t *d; uint32_t v, addr1, addr; vga_draw_line_func *vga_draw_line; +#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) +static const bool byteswap = false; +#else +static const bool byteswap = true; +#endif full_update |= update_basic_params(s); @@ -1685,18 +1690,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) disp_width != s-last_width || height != s-last_height || s-last_depth != depth) { -#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) -if (depth == 16 || depth == 32) { -#else -if (depth == 32) { -#endif +if (depth == 32 || (depth == 16 !byteswap)) { qemu_free_displaysurface(s-ds); s-ds-surface = qemu_create_displaysurface_from(disp_width, height, depth, s-line_offset, -s-vram_ptr + (s-start_addr * 4)); -#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) -s-ds-surface-pf = qemu_different_endianness_pixelformat(depth); -#endif +s-vram_ptr + (s-start_addr * 4), byteswap); dpy_gfx_resize(s-ds); } else { qemu_console_resize(s-ds, disp_width, height); @@ -1715,7 +1713,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) s-ds-surface = qemu_create_displaysurface_from(disp_width, height, depth, s-line_offset, -s-vram_ptr + (s-start_addr * 4)); +s-vram_ptr + (s-start_addr * 4), byteswap); dpy_gfx_setdata(s-ds); } diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index cd15ee4..8fc201b 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -1074,7 +1074,7 @@ static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch, ds_get_height(s-vga.ds), 32, ds_get_linesize(s-vga.ds), - s-vga.vram_ptr); + s-vga.vram_ptr, false); ppm_save(filename, ds, errp); g_free(ds); } diff --git a/hw/xenfb.c b/hw/xenfb.c index 903efd3..7f1f6b4 100644 --- a/hw/xenfb.c +++ b/hw/xenfb.c @@ -756,7 +756,8 @@ static void xenfb_update(void *opaque) qemu_free_displaysurface(xenfb-c.ds); xenfb-c.ds-surface = qemu_create_displaysurface_from (xenfb-width, xenfb-height, xenfb-depth, - xenfb-row_stride, xenfb-pixels + xenfb-offset); + xenfb-row_stride, xenfb-pixels + xenfb-offset, + false); break; default: /* we must convert stuff */ diff --git a/include/ui/console.h b/include/ui/console.h index fc23baa..18012f1 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -184,7 +184,8 @@ struct DisplayState { void register_displaystate(DisplayState *ds); DisplayState
[Qemu-devel] [PATCH 03/38] tcg-sparc: Always implement 32-bit multiword ops
Cc: Blue Swirl blauwir...@gmail.com Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/sparc/tcg-target.c | 6 -- tcg/sparc/tcg-target.h | 7 +++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 03db514..6d489fc 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -1327,6 +1327,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, args[3], const_args[3], args[4], const_args[4]); break; +#endif + case INDEX_op_add2_i32: tcg_out_addsub2(s, args[0], args[1], args[2], args[3], args[4], const_args[4], args[5], const_args[5], @@ -1342,7 +1344,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, ARITH_UMUL); tcg_out_rdy(s, args[1]); break; -#endif case INDEX_op_qemu_ld8u: tcg_out_qemu_ld(s, args, 0); @@ -1511,10 +1512,11 @@ static const TCGTargetOpDef sparc_op_defs[] = { #if TCG_TARGET_REG_BITS == 32 { INDEX_op_brcond2_i32, { rZ, rZ, rJ, rJ } }, { INDEX_op_setcond2_i32, { r, rZ, rZ, rJ, rJ } }, +#endif + { INDEX_op_add2_i32, { r, r, rZ, rZ, rJ, rJ } }, { INDEX_op_sub2_i32, { r, r, rZ, rZ, rJ, rJ } }, { INDEX_op_mulu2_i32, { r, r, rZ, rJ } }, -#endif #if TCG_TARGET_REG_BITS == 64 { INDEX_op_mov_i64, { r, r } }, diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index 6c62e45..8446721 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -102,6 +102,9 @@ typedef enum { #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 0 #define TCG_TARGET_HAS_movcond_i32 1 +#define TCG_TARGET_HAS_add2_i32 1 +#define TCG_TARGET_HAS_sub2_i32 1 +#define TCG_TARGET_HAS_mulu2_i321 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div_i64 1 @@ -124,10 +127,6 @@ typedef enum { #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 0 #define TCG_TARGET_HAS_movcond_i64 1 - -#define TCG_TARGET_HAS_add2_i32 0 -#define TCG_TARGET_HAS_sub2_i32 0 -#define TCG_TARGET_HAS_mulu2_i320 #endif #define TCG_AREG0 TCG_REG_I0 -- 1.8.1.2
[Qemu-devel] [PATCH v4 03/10] main-loop: switch POSIX glib integration to GPollFD
Convert glib file descriptor polling from rfds/wfds/xfds to GPollFD. The Windows code still needs poll_fds[] and n_poll_fds but they can now become local variables. Signed-off-by: Stefan Hajnoczi stefa...@redhat.com --- main-loop.c | 71 +++-- 1 file changed, 22 insertions(+), 49 deletions(-) diff --git a/main-loop.c b/main-loop.c index 489b27c..c2ede99 100644 --- a/main-loop.c +++ b/main-loop.c @@ -145,8 +145,6 @@ int qemu_init_main_loop(void) static fd_set rfds, wfds, xfds; static int nfds; -static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */ -static int n_poll_fds; static int max_priority; /* Load rfds/wfds/xfds into gpollfds. Will be removed a few commits later. */ @@ -206,65 +204,39 @@ static void gpollfds_to_select(int ret) } #ifndef _WIN32 -static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds, - fd_set *xfds, uint32_t *cur_timeout) +static int glib_pollfds_idx; +static int glib_n_poll_fds; + +static void glib_pollfds_fill(uint32_t *cur_timeout) { GMainContext *context = g_main_context_default(); -int i; int timeout = 0; +int n; g_main_context_prepare(context, max_priority); -n_poll_fds = g_main_context_query(context, max_priority, timeout, - poll_fds, ARRAY_SIZE(poll_fds)); -g_assert(n_poll_fds = ARRAY_SIZE(poll_fds)); - -for (i = 0; i n_poll_fds; i++) { -GPollFD *p = poll_fds[i]; - -if ((p-events G_IO_IN)) { -FD_SET(p-fd, rfds); -*max_fd = MAX(*max_fd, p-fd); -} -if ((p-events G_IO_OUT)) { -FD_SET(p-fd, wfds); -*max_fd = MAX(*max_fd, p-fd); -} -if ((p-events G_IO_ERR)) { -FD_SET(p-fd, xfds); -*max_fd = MAX(*max_fd, p-fd); -} -} +glib_pollfds_idx = gpollfds-len; +n = glib_n_poll_fds; +do { +GPollFD *pfds; +glib_n_poll_fds = n; +g_array_set_size(gpollfds, glib_pollfds_idx + glib_n_poll_fds); +pfds = g_array_index(gpollfds, GPollFD, glib_pollfds_idx); +n = g_main_context_query(context, max_priority, timeout, pfds, + glib_n_poll_fds); +} while (n != glib_n_poll_fds); if (timeout = 0 timeout *cur_timeout) { *cur_timeout = timeout; } } -static void glib_select_poll(fd_set *rfds, fd_set *wfds, fd_set *xfds, - bool err) +static void glib_pollfds_poll(void) { GMainContext *context = g_main_context_default(); +GPollFD *pfds = g_array_index(gpollfds, GPollFD, glib_pollfds_idx); -if (!err) { -int i; - -for (i = 0; i n_poll_fds; i++) { -GPollFD *p = poll_fds[i]; - -if ((p-events G_IO_IN) FD_ISSET(p-fd, rfds)) { -p-revents |= G_IO_IN; -} -if ((p-events G_IO_OUT) FD_ISSET(p-fd, wfds)) { -p-revents |= G_IO_OUT; -} -if ((p-events G_IO_ERR) FD_ISSET(p-fd, xfds)) { -p-revents |= G_IO_ERR; -} -} -} - -if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) { +if (g_main_context_check(context, max_priority, pfds, glib_n_poll_fds)) { g_main_context_dispatch(context); } } @@ -273,7 +245,7 @@ static int os_host_main_loop_wait(uint32_t timeout) { int ret; -glib_select_fill(nfds, rfds, wfds, xfds, timeout); +glib_pollfds_fill(timeout); if (timeout 0) { qemu_mutex_unlock_iothread(); @@ -292,7 +264,7 @@ static int os_host_main_loop_wait(uint32_t timeout) qemu_mutex_lock_iothread(); } -glib_select_poll(rfds, wfds, xfds, (ret 0)); +glib_pollfds_poll(); return ret; } #else @@ -438,8 +410,9 @@ static void pollfds_poll(GArray *pollfds, int nfds, fd_set *rfds, static int os_host_main_loop_wait(uint32_t timeout) { GMainContext *context = g_main_context_default(); +GPollFD poll_fds[1024 * 2]; /* this is probably overkill */ int select_ret = 0; -int g_poll_ret, ret, i; +int g_poll_ret, ret, i, n_poll_fds; PollingEntry *pe; WaitObjects *w = wait_objects; gint poll_timeout; -- 1.8.1.2
[Qemu-devel] [PATCH] tcg: Document tcg_qemu_tb_exec() and provide constants for low bit uses
Document tcg_qemu_tb_exec(). In particular, its return value is a combination of a pointer to the next translation block and some extra information in the low two bits. Provide some #defines for the values passed in these bits to improve code clarity. Signed-off-by: Peter Maydell peter.mayd...@linaro.org --- I have a patch cooking which uses the final remaining bottom-two-bits combo to indicate exited TB due to pending interrupt so I thought it would be nice to document what was going on here and get rid of some of the magic numbers in the code. cpu-exec.c|9 + include/exec/gen-icount.h |2 +- tcg/tcg.h | 36 +++- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index 9fcfe9e0..ea63e7d 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -72,7 +72,7 @@ static void cpu_exec_nocache(CPUArchState *env, int max_cycles, next_tb = tcg_qemu_tb_exec(env, tb-tc_ptr); cpu-current_tb = NULL; -if ((next_tb 3) == 2) { +if ((next_tb TB_EXIT_MASK) == TB_EXIT_ICOUNT_EXPIRED) { /* Restore PC. This may happen if async event occurs before the TB starts executing. */ cpu_pc_from_tb(env, tb); @@ -584,7 +584,8 @@ int cpu_exec(CPUArchState *env) spans two pages, we cannot safely do a direct jump. */ if (next_tb != 0 tb-page_addr[1] == -1) { -tb_add_jump((TranslationBlock *)(next_tb ~3), next_tb 3, tb); +tb_add_jump((TranslationBlock *)(next_tb ~TB_EXIT_MASK), +next_tb TB_EXIT_MASK, tb); } spin_unlock(tcg_ctx.tb_ctx.tb_lock); @@ -598,10 +599,10 @@ int cpu_exec(CPUArchState *env) tc_ptr = tb-tc_ptr; /* execute the generated code */ next_tb = tcg_qemu_tb_exec(env, tc_ptr); -if ((next_tb 3) == 2) { +if ((next_tb TB_EXIT_MASK) == TB_EXIT_ICOUNT_EXPIRED) { /* Instruction counter expired. */ int insns_left; -tb = (TranslationBlock *)(next_tb ~3); +tb = (TranslationBlock *)(next_tb ~TB_EXIT_MASK); /* Restore PC. */ cpu_pc_from_tb(env, tb); insns_left = env-icount_decr.u32; diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h index 8043b3b..c858a73 100644 --- a/include/exec/gen-icount.h +++ b/include/exec/gen-icount.h @@ -32,7 +32,7 @@ static void gen_icount_end(TranslationBlock *tb, int num_insns) if (use_icount) { *icount_arg = num_insns; gen_set_label(icount_label); -tcg_gen_exit_tb((tcg_target_long)tb + 2); +tcg_gen_exit_tb((tcg_target_long)tb + TB_EXIT_ICOUNT_EXPIRED); } } diff --git a/tcg/tcg.h b/tcg/tcg.h index 51c8176..7cf4c15 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -669,7 +669,41 @@ TCGv_i64 tcg_const_i64(int64_t val); TCGv_i32 tcg_const_local_i32(int32_t val); TCGv_i64 tcg_const_local_i64(int64_t val); -/* TCG targets may use a different definition of tcg_qemu_tb_exec. */ +/** + * tcg_qemu_tb_exec: + * @env: CPUArchState * for the CPU + * @tb_ptr: address of generated code for the TB to execute + * + * Start executing code from a given translation block. + * Where translation blocks have been linked, execution + * may proceed from the given TB into successive ones. + * Control eventually returns only when some action is needed + * from the top-level loop: either control must pass to a TB + * which has not yet been directly linked, or an asynchronous + * event such as an interrupt needs handling. + * + * The return value is a pointer to the next TB to execute + * (if known; otherwise zero). This pointer is assumed to be + * 4-aligned, and the bottom two bits are used to return further + * information: + * 0, 1: the link between this TB and the next is via the specified + *TB index (0 or 1). That is, we left the TB via (the equivalent + *of) goto_tb index. The main loop uses this to determine + *how to link the TB just executed to the next. + * 2:we are using instruction counting code generation, and we + *stopped executing this TB because the instruction counter + *hit zero. In this case the next-TB pointer returned is the + *TB we were partway through. + * + * Note that TCG targets may use a different definition of tcg_qemu_tb_exec + * to this default (which just calls the prologue code emitted by + * tcg_target_qemu_prologue()). + */ +#define TB_EXIT_MASK 3 +#define TB_EXIT_IDX0 0 +#define TB_EXIT_IDX1 1 +#define TB_EXIT_ICOUNT_EXPIRED 2 + #if !defined(tcg_qemu_tb_exec) # define tcg_qemu_tb_exec(env, tb_ptr) \ ((tcg_target_ulong (*)(void *, void *))tcg_ctx.code_gen_prologue)(env, \ --
Re: [Qemu-devel] [RFC PATCH] Distinguish between reset types
Hi Peter, On Wed, Feb 20, 2013 at 8:50 AM, Peter Maydell peter.mayd...@linaro.org wrote: On 19 February 2013 22:17, Anthony Liguori anth...@codemonkey.ws wrote: David Woodhouse dw...@infradead.org writes: On Tue, 2013-02-19 at 14:29 -0600, Anthony Liguori wrote: So should we even be resetting anything other than the CPU during soft reset? I suspect not. A soft reset triggered by the RCR, keyboard controller, port 92 etc. should all just reset the CPU and nothing else. I suspect what we need to do is convert qemu_system_reset_request() into a qemu_system_cpu_reset() that takes a callback. Once the VCPUs have been reset, the callback can then be used to reset all or some of the device model. If we're just solving a PC problem here and it really is just only reset the CPU, nothing else, why don't we give the x86 CPU a qemu_irq input for reset this CPU core and wire it up to the relevant bit of hardware on the PC board? I don't see the need for a specific 'qemu_system_cpu_reset()' here (and not having one avoids the swamp of trying to define its semantics...) Could we be more general and implement this on the TYPE_DEVICE level (rather than X86_CPU)? I want this GPIO-as-reset feature for all Zynq devices cpus and preihperals alike. The Zynq power controller has software controllable individual reset for every device in the system and my plan-A was to do it as GPIOs. To implement the reset gpio-ins however I was thinking do it in one swift stroke by adding the single GPIO on the TYPE_DEVICE layer that backs onto DeviceClass-.reset. With recent QOM efforts (making CPUs DEVICEs) this catchall will also implment the feature for all CPUs. Power controllers define gpio_outs and then machine model just play connect the dots. RFC! I was planning at some stage to formally RFC this but yet to get around to it. I bring it up because the topic is hot here. How far down this road do we go? Do we end up wiring up the full reset topology and abandoning the special-case qemu_system_reset() altogether? Long term, yes. Short term, whatever we need that's reasonable to get the CSM happy without making things worse. I definitely think we should be modelling reset lines, yes. It would be nice if we could sketch a path for how we get from here to there. Here's a strawman proposal that's probably full of holes: (1) we retain the existing 'reset' Device method as meaning full power-cycle style reset and qemu_system_reset_request() as meaning power cycle entire machine. (Eventually the latter might go away as I doubt much real hardware has a power cycle the world wiring.) (2) we recommend that for new devices etc, where the device has one or more physical reset pins those should be modeled as qdev_gpio input lines, with the behaviour the hardware has when those are asserted. [Q: what do we do about logic-low-is-assert vs logic-high-is-assert hardware?] This reset can obviously share code with the DeviceState::reset in many cases, but it's conceptually separate. (3) when we need to implement a particular effect on a particular board (as here with the PC) we do that by: a. making sure all affected devices implement reset b. wiring up reset on the board model c. having the implementation of the 'reset' register or whatever assert the irq line (4) as and when we have time, convert existing code (ho ho) The TYPE_DEVICE level implementation would give a reset pin to every device that implements DeviceClass-reset which should minimise the pain here. The hard part is devices that dont implement reset at all which are a lost cause WRT this discussion. This obviously works best when the not actually a full power cycle reset you want in (3) is a very limited focus one, like just reset the CPU... It also exposes some not there yet features like the fact we can't have named gpio input lines so you have to have a numbering convention for smooshing all your inputs into a single array. Pins, anybody? :-) Yes my idea requires this so would have to bite the bullet and get this one through. Regards, Peter -- PMM
Re: [Qemu-devel] [RFC PATCH] Distinguish between reset types
On 20 February 2013 12:21, Peter Crosthwaite peter.crosthwa...@xilinx.com wrote: On Wed, Feb 20, 2013 at 8:50 AM, Peter Maydell peter.mayd...@linaro.org wrote: If we're just solving a PC problem here and it really is just only reset the CPU, nothing else, why don't we give the x86 CPU a qemu_irq input for reset this CPU core and wire it up to the relevant bit of hardware on the PC board? I don't see the need for a specific 'qemu_system_cpu_reset()' here (and not having one avoids the swamp of trying to define its semantics...) Could we be more general and implement this on the TYPE_DEVICE level (rather than X86_CPU)? I want this GPIO-as-reset feature for all Zynq devices cpus and preihperals alike. The Zynq power controller has software controllable individual reset for every device in the system and my plan-A was to do it as GPIOs. To implement the reset gpio-ins however I was thinking do it in one swift stroke by adding the single GPIO on the TYPE_DEVICE layer that backs onto DeviceClass-.reset. The trouble is that: * some devices have no reset GPIO line * some devices have more than one (eg a Cortex-A9MPx4 has 18 different reset input lines) * the reset line doesn't always match up with the DeviceClass::reset semantics I guess maybe if there was a way to say 'this device suppresses the default reset input implementation'. (Plus as you note we'd have to actually support named GPIO inputs to have the base class provide an input pin that didn't get tangled up with the device's own inputs.) -- PMM
Re: [Qemu-devel] [PATCH v1 1/6] i2c: support address ranges
On Wed, Feb 20, 2013 at 5:27 PM, Paolo Bonzini pbonz...@redhat.com wrote: Il 20/02/2013 06:29, Peter Crosthwaite ha scritto: @@ -192,12 +197,13 @@ static int i2c_slave_post_load(void *opaque, int version_id) const VMStateDescription vmstate_i2c_slave = { .name = I2CSlave, -.version_id = 1, -.minimum_version_id = 1, -.minimum_version_id_old = 1, +.version_id = 2, +.minimum_version_id = 2, +.minimum_version_id_old = 2, .post_load = i2c_slave_post_load, .fields = (VMStateField []) { VMSTATE_UINT8(address, I2CSlave), +VMSTATE_UINT8(address_range, I2CSlave), VMSTATE_END_OF_LIST() Properties do not need to be serialized. Ok, I do wonder why the address itselt in VMSDs however and my best guess is the intention is that devices can modify their address at runtime (phyiscally very possible and valid with I2C). So what happens if a device changes the value of one of its props at runtime? E.G. in this case what happens if my device decides to change its I2CSlave-address in response to some arbitrary event? Will that play foul with VMSD or can i just save the prop in my VMSD with the rest of my device state to implement restoration of the modified prop? Regards, Peter Paolo
[Qemu-devel] [PATCH v4 04/10] slirp: slirp/slirp.c coding style cleanup
The slirp glue code uses tabs in some places. Since the next patch will modify the file, convert tabs to spaces and fix checkpatch.pl issues. Signed-off-by: Stefan Hajnoczi stefa...@redhat.com --- slirp/slirp.c | 608 ++ 1 file changed, 311 insertions(+), 297 deletions(-) diff --git a/slirp/slirp.c b/slirp/slirp.c index 0e6e232..5d14e7f 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -287,135 +287,139 @@ void slirp_select_fill(int *pnfds, global_xfds = NULL; nfds = *pnfds; - /* -* First, TCP sockets -*/ - do_slowtimo = 0; - - QTAILQ_FOREACH(slirp, slirp_instances, entry) { - /* -* *_slowtimo needs calling if there are IP fragments -* in the fragment queue, or there are TCP connections active -*/ - do_slowtimo |= ((slirp-tcb.so_next != slirp-tcb) || - (slirp-ipq.ip_link != slirp-ipq.ip_link.next)); - - for (so = slirp-tcb.so_next; so != slirp-tcb; -so = so_next) { - so_next = so-so_next; - - /* -* See if we need a tcp_fasttimo -*/ - if (time_fasttimo == 0 so-so_tcpcb-t_flags TF_DELACK) - time_fasttimo = curtime; /* Flag when we want a fasttimo */ - - /* -* NOFDREF can include still connecting to local-host, -* newly socreated() sockets etc. Don't want to select these. -*/ - if (so-so_state SS_NOFDREF || so-s == -1) - continue; - - /* -* Set for reading sockets which are accepting -*/ - if (so-so_state SS_FACCEPTCONN) { -FD_SET(so-s, readfds); - UPD_NFDS(so-s); - continue; - } - - /* -* Set for writing sockets which are connecting -*/ - if (so-so_state SS_ISFCONNECTING) { - FD_SET(so-s, writefds); - UPD_NFDS(so-s); - continue; - } - - /* -* Set for writing if we are connected, can send more, and -* we have something to send -*/ - if (CONN_CANFSEND(so) so-so_rcv.sb_cc) { - FD_SET(so-s, writefds); - UPD_NFDS(so-s); - } - - /* -* Set for reading (and urgent data) if we are connected, can -* receive more, and we have room for it XXX /2 ? -*/ - if (CONN_CANFRCV(so) (so-so_snd.sb_cc (so-so_snd.sb_datalen/2))) { - FD_SET(so-s, readfds); - FD_SET(so-s, xfds); - UPD_NFDS(so-s); - } - } - - /* -* UDP sockets -*/ - for (so = slirp-udb.so_next; so != slirp-udb; -so = so_next) { - so_next = so-so_next; - - /* -* See if it's timed out -*/ - if (so-so_expire) { - if (so-so_expire = curtime) { - udp_detach(so); - continue; - } else - do_slowtimo = 1; /* Let socket expire */ - } - - /* -* When UDP packets are received from over the -* link, they're sendto()'d straight away, so -* no need for setting for writing -* Limit the number of packets queued by this session -* to 4. Note that even though we try and limit this -* to 4 packets, the session could have more queued -* if the packets needed to be fragmented -* (XXX = 4 ?) -*/ - if ((so-so_state SS_ISFCONNECTED) so-so_queued = 4) { - FD_SET(so-s, readfds); - UPD_NFDS(so-s); - } - } +/* + * First, TCP sockets + */ +do_slowtimo = 0; -/* -
Re: [Qemu-devel] [RFC PATCH] Distinguish between reset types
On Wed, Feb 20, 2013 at 10:29 PM, Peter Maydell peter.mayd...@linaro.org wrote: On 20 February 2013 12:21, Peter Crosthwaite peter.crosthwa...@xilinx.com wrote: On Wed, Feb 20, 2013 at 8:50 AM, Peter Maydell peter.mayd...@linaro.org wrote: If we're just solving a PC problem here and it really is just only reset the CPU, nothing else, why don't we give the x86 CPU a qemu_irq input for reset this CPU core and wire it up to the relevant bit of hardware on the PC board? I don't see the need for a specific 'qemu_system_cpu_reset()' here (and not having one avoids the swamp of trying to define its semantics...) Could we be more general and implement this on the TYPE_DEVICE level (rather than X86_CPU)? I want this GPIO-as-reset feature for all Zynq devices cpus and preihperals alike. The Zynq power controller has software controllable individual reset for every device in the system and my plan-A was to do it as GPIOs. To implement the reset gpio-ins however I was thinking do it in one swift stroke by adding the single GPIO on the TYPE_DEVICE layer that backs onto DeviceClass-.reset. The trouble is that: * some devices have no reset GPIO line Is there any harm in just not connecting the default reset GPIO? Or if you are pedantic allow the class definition to opt-out and inhibit generation of the GPIO. * some devices have more than one (eg a Cortex-A9MPx4 has 18 different reset input lines) Yeh you are lost in this case. But my intended semantics for the TYPE_DEVICE reset GPIO is it is a power on reset (PoR) with equivalent function to DeviceClass-reset * the reset line doesn't always match up with the DeviceClass::reset semantics Then its not a PoR equivalent (and thus from QEMUs perspective not a reset at all). Its a device specific GPIO. The same applies to 18 lines of A9MPx4, althought that is a container object so im guessing some of those 18 resets will pass through as PoR equivalents to the subdevices? So working on that case, suppose GIC (a subcomponent of Cortex-A9MPx4) has a PoR equivalent wired directly as one of the 18 resets. The container will have to explicitly define all 18 resets, however, it can pass GICs through to the TYPE_DEVICE reset for the GIC instance, saving on having to hack up GIC to explicitly have a reset GPIO. It just strikes me as a workable solution for the 90% case then we can go you full custom GPIO solution for the harder ones. Regards, Peter I guess maybe if there was a way to say 'this device suppresses the default reset input implementation'. (Plus as you note we'd have to actually support named GPIO inputs to have the base class provide an input pin that didn't get tangled up with the device's own inputs.) -- PMM
[Qemu-devel] [PATCH 02/38] tcg-i386: Always implement 32-bit multiword ops
Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/i386/tcg-target.c | 18 ++ tcg/i386/tcg-target.h | 7 +++ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 7aec304..f645529 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -1922,13 +1922,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_qemu_st(s, args, 3); break; -#if TCG_TARGET_REG_BITS == 32 -case INDEX_op_brcond2_i32: -tcg_out_brcond2(s, args, const_args, 0); -break; -case INDEX_op_setcond2_i32: -tcg_out_setcond2(s, args, const_args); -break; case INDEX_op_mulu2_i32: tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_MUL, args[3]); break; @@ -1956,6 +1949,14 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tgen_arithr(s, ARITH_SBB, args[1], args[5]); } break; + +#if TCG_TARGET_REG_BITS == 32 +case INDEX_op_brcond2_i32: +tcg_out_brcond2(s, args, const_args, 0); +break; +case INDEX_op_setcond2_i32: +tcg_out_setcond2(s, args, const_args); +break; #else /* TCG_TARGET_REG_BITS == 64 */ case INDEX_op_movi_i64: tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]); @@ -2078,10 +2079,11 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_movcond_i32, { r, r, ri, r, 0 } }, #endif -#if TCG_TARGET_REG_BITS == 32 { INDEX_op_mulu2_i32, { a, d, a, r } }, { INDEX_op_add2_i32, { r, r, 0, 1, ri, ri } }, { INDEX_op_sub2_i32, { r, r, 0, 1, ri, ri } }, + +#if TCG_TARGET_REG_BITS == 32 { INDEX_op_brcond2_i32, { r, r, ri, ri } }, { INDEX_op_setcond2_i32, { r, r, r, ri, ri } }, #else diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index 43ad2c4..487dc23 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -92,6 +92,9 @@ typedef enum { #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 #define TCG_TARGET_HAS_movcond_i32 1 +#define TCG_TARGET_HAS_add2_i32 1 +#define TCG_TARGET_HAS_sub2_i32 1 +#define TCG_TARGET_HAS_mulu2_i321 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div2_i64 1 @@ -114,10 +117,6 @@ typedef enum { #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 1 #define TCG_TARGET_HAS_movcond_i64 1 - -#define TCG_TARGET_HAS_add2_i32 0 -#define TCG_TARGET_HAS_sub2_i32 0 -#define TCG_TARGET_HAS_mulu2_i320 #endif #define TCG_TARGET_deposit_i32_valid(ofs, len) \ -- 1.8.1.2
[Qemu-devel] qemu 1.4 : ubuntu 12.10 : ehci + companion + usb-tablet - vmmouse not loaded + usb-tablet not working
Hi List, I'm testing qemu 1.4, without ubuntu desktop 12.10 with graphical installer I found 2 bugs: 1) vmmouse is not loaded if an usb-tablet is plugged on an ehci controller with companion - 4 cases with mixed options: a)ehci +companion +tablet: vmmouse is not loaded qemu command line : -readconfig /usr/share/qemu-server/pve-usb-companion.cfg -device usb-tablet,id=tablet,bus=ehci.0,port=6 # info mice Mouse #0: QEMU PS/2 Mouse * Mouse #1: QEMU HID Tablet (absolute) b)ehci +companion -tablet: vmmouse is loaded qemu command line : -readconfig /usr/share/qemu-server/pve-usb-companion.cfg # info mice Mouse #0: QEMU PS/2 Mouse * Mouse #1: vmmouse (absolute) c)ehci -companion + tablet : vmmouse is loaded qemu command line : -readconfig /usr/share/qemu-server/pve-usb-nocompanion.cfg -device usb-tablet,id=tablet,bus=ehci.0,port=6 # info mice Mouse #1: QEMU HID Tablet (absolute) Mouse #0: QEMU PS/2 Mouse * Mouse #2: vmmouse (absolute) d)ehci -companion -tablet : vmmouse is loaded qemu command line : -readconfig /usr/share/qemu-server/pve-usb-nocompanion.cfg # info mice Mouse #0: QEMU PS/2 Mouse * Mouse #1: vmmouse (absolute) pve-usb-companion.cfg: [device ehci] driver = ich9-usb-ehci1 addr = 1d.7 multifunction = on [device uhci-1] driver = ich9-usb-uhci1 addr = 1d.0 multifunction = on masterbus = ehci.0 firstport = 0 [device uhci-2] driver = ich9-usb-uhci2 addr = 1d.1 multifunction = on masterbus = ehci.0 firstport = 2 [device uhci-3] driver = ich9-usb-uhci3 addr = 1d.2 multifunction = on masterbus = ehci.0 firstport = 4 pve-usb-nocompanion.cfg: [device ehci] driver = ich9-usb-ehci1 addr = 1d.7 multifunction = off 2) -usb-tablet don't work on ehci with ubuntu -- - don't work (mouse not moving) with or without companion - device is correctly displayed with #lsusb,so maybe it's an xorg driver problem. - It's working fine on windows guest. Both bugs result to don't have a working mouse in ubuntu installer. (vmmouse is not available, and usb-tablet is selected but it's not working). Any idea ? Regards, Alexandre Derumier
[Qemu-devel] [PATCH 21/38] target-arm: Implement sbc_cc inline
Use sub2 if available, otherwise use 64-bit arithmetic. Cc: Peter Maydell peter.mayd...@linaro.org Signed-off-by: Richard Henderson r...@twiddle.net --- target-arm/helper.h| 2 -- target-arm/op_helper.c | 15 --- target-arm/translate.c | 47 +++ 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/target-arm/helper.h b/target-arm/helper.h index 507bb9c..63ae13a 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -140,8 +140,6 @@ DEF_HELPER_2(recpe_u32, i32, i32, env) DEF_HELPER_2(rsqrte_u32, i32, i32, env) DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32) -DEF_HELPER_3(sbc_cc, i32, env, i32, i32) - DEF_HELPER_3(shl_cc, i32, env, i32, i32) DEF_HELPER_3(shr_cc, i32, env, i32, i32) DEF_HELPER_3(sar_cc, i32, env, i32, i32) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 49fc036..a522313 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -315,21 +315,6 @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip) The only way to do that in TCG is a conditional branch, which clobbers all our temporaries. For now implement these as helper functions. */ -uint32_t HELPER(sbc_cc)(CPUARMState *env, uint32_t a, uint32_t b) -{ -uint32_t result; -if (!env-CF) { -result = a - b - 1; -env-CF = a b; -} else { -result = a - b; -env-CF = a = b; -} -env-VF = (a ^ b) (a ^ result); -env-NF = env-ZF = result; -return result; -} - /* Similarly for variable shift instructions. */ uint32_t HELPER(shl_cc)(CPUARMState *env, uint32_t x, uint32_t i) diff --git a/target-arm/translate.c b/target-arm/translate.c index 493448a..9993aea 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -464,6 +464,35 @@ static void gen_sub_CC(TCGv dest, TCGv t0, TCGv t1) tcg_gen_mov_i32(dest, cpu_NF); } +/* dest = T0 + ~T1 + CF = T0 - T1 + CF - 1. Compute C, N, V and Z flags */ +static void gen_sbc_CC(TCGv dest, TCGv t0, TCGv t1) +{ +TCGv tmp = tcg_temp_new_i32(); +tcg_gen_subi_i32(cpu_CF, cpu_CF, 1); +if (TCG_TARGET_HAS_add2_i32) { +tcg_gen_movi_i32(tmp, 0); +tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp); +tcg_gen_sub2_i32(cpu_NF, cpu_CF, t0, cpu_CF, t1, tmp); +} else { +TCGv_i64 q0 = tcg_temp_new_i64(); +TCGv_i64 q1 = tcg_temp_new_i64(); +tcg_gen_extu_i32_i64(q0, t0); +tcg_gen_extu_i32_i64(q1, t1); +tcg_gen_sub_i64(q0, q0, q1); +tcg_gen_extu_i32_i64(q1, cpu_CF); +tcg_gen_add_i64(q0, q0, q1); +tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0); +tcg_temp_free_i64(q0); +tcg_temp_free_i64(q1); +} +tcg_gen_mov_i32(cpu_ZF, cpu_NF); +tcg_gen_xor_i32(cpu_VF, cpu_NF, t0); +tcg_gen_xor_i32(tmp, t0, t1); +tcg_gen_and_i32(cpu_VF, cpu_VF, tmp); +tcg_temp_free_i32(tmp); +tcg_gen_mov_i32(dest, cpu_NF); +} + #define GEN_SHIFT(name) \ static void gen_##name(TCGv dest, TCGv t0, TCGv t1) \ { \ @@ -7109,7 +7138,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x06: if (set_cc) { -gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2); +gen_sbc_CC(tmp, tmp, tmp2); } else { gen_sub_carry(tmp, tmp, tmp2); } @@ -7117,7 +7146,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x07: if (set_cc) { -gen_helper_sbc_cc(tmp, cpu_env, tmp2, tmp); +gen_sbc_CC(tmp, tmp2, tmp); } else { gen_sub_carry(tmp, tmp2, tmp); } @@ -7947,10 +7976,11 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCG gen_adc(t0, t1); break; case 11: /* sbc */ -if (conds) -gen_helper_sbc_cc(t0, cpu_env, t0, t1); -else +if (conds) { +gen_sbc_CC(t0, t0, t1); +} else { gen_sub_carry(t0, t0, t1); +} break; case 13: /* sub */ if (conds) @@ -9267,10 +9297,11 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) } break; case 0x6: /* sbc */ -if (s-condexec_mask) +if (s-condexec_mask) { gen_sub_carry(tmp, tmp, tmp2); -else -gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2); +} else { +gen_sbc_CC(tmp, tmp, tmp2); +} break; case 0x7: /* ror */ if (s-condexec_mask) { -- 1.8.1.2
[Qemu-devel] [PATCH 34/38] target-sparc: Use mul*2 for multiply
Cc: Blue Swirl blauwir...@gmail.com Signed-off-by: Richard Henderson r...@twiddle.net --- target-sparc/translate.c | 45 ++--- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index d3e2acf..f99b82a 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -642,39 +642,30 @@ static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) static inline void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext) { -TCGv_i32 r_src1, r_src2; -TCGv_i64 r_temp, r_temp2; - -r_src1 = tcg_temp_new_i32(); -r_src2 = tcg_temp_new_i32(); - -tcg_gen_trunc_tl_i32(r_src1, src1); -tcg_gen_trunc_tl_i32(r_src2, src2); - -r_temp = tcg_temp_new_i64(); -r_temp2 = tcg_temp_new_i64(); - +#if TARGET_LONG_BITS == 32 if (sign_ext) { -tcg_gen_ext_i32_i64(r_temp, r_src2); -tcg_gen_ext_i32_i64(r_temp2, r_src1); +tcg_gen_muls2_tl(dst, cpu_y, src1, src2); } else { -tcg_gen_extu_i32_i64(r_temp, r_src2); -tcg_gen_extu_i32_i64(r_temp2, r_src1); +tcg_gen_mulu2_tl(dst, cpu_y, src1, src2); } +#else +TCGv t0 = tcg_temp_new_i64(); +TCGv t1 = tcg_temp_new_i64(); -tcg_gen_mul_i64(r_temp2, r_temp, r_temp2); - -tcg_gen_shri_i64(r_temp, r_temp2, 32); -tcg_gen_trunc_i64_tl(cpu_y, r_temp); -tcg_temp_free_i64(r_temp); -tcg_gen_andi_tl(cpu_y, cpu_y, 0x); - -tcg_gen_trunc_i64_tl(dst, r_temp2); +if (sign_ext) { +tcg_gen_ext32s_i64(t0, src1); +tcg_gen_ext32s_i64(t1, src2); +} else { +tcg_gen_ext32u_i64(t0, src1); +tcg_gen_ext32u_i64(t1, src2); +} -tcg_temp_free_i64(r_temp2); +tcg_gen_mul_i64(dst, t0, t1); +tcg_temp_free(t0); +tcg_temp_free(t1); -tcg_temp_free_i32(r_src1); -tcg_temp_free_i32(r_src2); +tcg_gen_shri_i64(cpu_y, dst, 32); +#endif } static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2) -- 1.8.1.2
[Qemu-devel] [PATCH 07/38] tcg: Implement multiword multiply helpers
Signed-off-by: Richard Henderson r...@twiddle.net --- tcg-runtime.c | 16 ++- tcg/tcg-op.h | 84 +++ tcg/tcg-runtime.h | 2 ++ 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/tcg-runtime.c b/tcg-runtime.c index abfc364..4b66e51 100644 --- a/tcg-runtime.c +++ b/tcg-runtime.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include stdint.h - +#include qemu/host-utils.h #include tcg/tcg-runtime.h /* 32-bit helpers */ @@ -83,3 +83,17 @@ uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2) { return arg1 % arg2; } + +uint64_t tcg_helper_muluh_i64(uint64_t arg1, uint64_t arg2) +{ +uint64_t l, h; +mulu64(l, h, arg1, arg2); +return h; +} + +int64_t tcg_helper_mulsh_i64(int64_t arg1, int64_t arg2) +{ +uint64_t l, h; +muls64(l, h, arg1, arg2); +return h; +} diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 4ded249..97e0795 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -2332,6 +2332,86 @@ static inline void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, #endif } +static inline void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, + TCGv_i32 arg1, TCGv_i32 arg2) +{ +if (TCG_TARGET_HAS_mulu2_i32) { +tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2); +/* Allow the optimizer room to replace mulu2 with two moves. */ +tcg_gen_op0(INDEX_op_nop); +} else { +TCGv_i64 t0 = tcg_temp_new_i64(); +TCGv_i64 t1 = tcg_temp_new_i64(); +tcg_gen_extu_i32_i64(t0, arg1); +tcg_gen_extu_i32_i64(t1, arg2); +tcg_gen_mul_i64(t0, t0, t1); +tcg_gen_extr_i64_i32(rl, rh, t0); +tcg_temp_free_i64(t0); +tcg_temp_free_i64(t1); +} +} + +static inline void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, + TCGv_i32 arg1, TCGv_i32 arg2) +{ +if (TCG_TARGET_HAS_muls2_i32) { +tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2); +/* Allow the optimizer room to replace muls2 with two moves. */ +tcg_gen_op0(INDEX_op_nop); +} else { +TCGv_i64 t0 = tcg_temp_new_i64(); +TCGv_i64 t1 = tcg_temp_new_i64(); +tcg_gen_ext_i32_i64(t0, arg1); +tcg_gen_ext_i32_i64(t1, arg2); +tcg_gen_mul_i64(t0, t0, t1); +tcg_gen_extr_i64_i32(rl, rh, t0); +tcg_temp_free_i64(t0); +tcg_temp_free_i64(t1); +} +} + +static inline void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, + TCGv_i64 arg1, TCGv_i64 arg2) +{ +if (TCG_TARGET_HAS_mulu2_i64) { +tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2); +/* Allow the optimizer room to replace mulu2 with two moves. */ +tcg_gen_op0(INDEX_op_nop); +} else { +TCGv_i64 t0 = tcg_temp_new_i64(); +int sizemask = 0; +/* Return value and both arguments are 64-bit and unsigned. */ +sizemask |= tcg_gen_sizemask(0, 1, 0); +sizemask |= tcg_gen_sizemask(1, 1, 0); +sizemask |= tcg_gen_sizemask(2, 1, 0); +tcg_gen_mul_i64(t0, arg1, arg2); +tcg_gen_helper64(tcg_helper_muluh_i64, sizemask, rh, arg1, arg2); +tcg_gen_mov_i64(rl, t0); +tcg_temp_free_i64(t0); +} +} + +static inline void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, + TCGv_i64 arg1, TCGv_i64 arg2) +{ +if (TCG_TARGET_HAS_muls2_i64) { +tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2); +/* Allow the optimizer room to replace muls2 with two moves. */ +tcg_gen_op0(INDEX_op_nop); +} else { +TCGv_i64 t0 = tcg_temp_new_i64(); +int sizemask = 0; +/* Return value and both arguments are 64-bit and signed. */ +sizemask |= tcg_gen_sizemask(0, 1, 1); +sizemask |= tcg_gen_sizemask(1, 1, 1); +sizemask |= tcg_gen_sizemask(2, 1, 1); +tcg_gen_mul_i64(t0, arg1, arg2); +tcg_gen_helper64(tcg_helper_mulsh_i64, sizemask, rh, arg1, arg2); +tcg_gen_mov_i64(rl, t0); +tcg_temp_free_i64(t0); +} +} + /***/ /* QEMU specific operations. Their type depend on the QEMU CPU type. */ @@ -2659,6 +2739,8 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) #define tcg_const_tl tcg_const_i64 #define tcg_const_local_tl tcg_const_local_i64 #define tcg_gen_movcond_tl tcg_gen_movcond_i64 +#define tcg_gen_mulu2_tl tcg_gen_mulu2_i64 +#define tcg_gen_muls2_tl tcg_gen_muls2_i64 #else #define tcg_gen_movi_tl tcg_gen_movi_i32 #define tcg_gen_mov_tl tcg_gen_mov_i32 @@ -2732,6 +2814,8 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) #define tcg_const_tl tcg_const_i32 #define tcg_const_local_tl tcg_const_local_i32 #define tcg_gen_movcond_tl tcg_gen_movcond_i32 +#define tcg_gen_mulu2_tl tcg_gen_mulu2_i32 +#define tcg_gen_muls2_tl
Re: [Qemu-devel] [PATCH v1 1/6] i2c: support address ranges
Il 20/02/2013 13:30, Peter Crosthwaite ha scritto: Ok, I do wonder why the address itselt in VMSDs however and my best guess is the intention is that devices can modify their address at runtime (phyiscally very possible and valid with I2C). So what happens if a device changes the value of one of its props at runtime? E.G. in this case what happens if my device decides to change its I2CSlave-address in response to some arbitrary event? Will that play foul with VMSD or can i just save the prop in my VMSD with the rest of my device state to implement restoration of the modified prop? Ok, in this case this would be valid, but the implementation is still a bit weird. What is the behavior on reset? Should it go back to the original value of the address? If so, you need to use a separate variable to store the initial value of the address and the current value. Then the initial value is immutable and thus not serialized; the current value instead is part of the VMState. More importantly, the reset callback can then reset the current address back to the initial value. Paolo
Re: [Qemu-devel] [PATCH] tap: forbid creating multiqueue tap when hub is used
On Wed, Feb 20, 2013 at 05:18:08PM +0800, Jason Wang wrote: diff --git a/net/tap.c b/net/tap.c index 48c254e..1e14f59 100644 --- a/net/tap.c +++ b/net/tap.c @@ -693,6 +693,12 @@ int net_init_tap(const NetClientOptions *opts, const char *name, queues = tap-has_queues ? tap-queues : 1; vhostfdname = tap-has_vhostfd ? tap-vhostfd : NULL; +if (peer (tap-has_queues || tap-has_fds || tap-has_vhostfds)) { +error_report(This configuration is not compatiable with multiqueue + tap); s/compatiable/compatible/ The error message should be specific, for example, multiqueue tap cannot be used with QEMU vlans. A comment would be nice too to remind readers that peer is only set when QEMU vlans are in use. peer is always NULL for -netdev. Stefan
Re: [Qemu-devel] qemu 1.4 : ubuntu 12.10 : ehci + companion + usb-tablet - vmmouse not loaded + usb-tablet not working
Hi Alexandre No solution yet, but I can reproduce bug 2) with Fedora 18 64bit as guest. Regards, Tiziano Am Mittwoch, den 20.02.2013, 13:56 +0100 schrieb Alexandre DERUMIER: Hi List, I'm testing qemu 1.4, without ubuntu desktop 12.10 with graphical installer I found 2 bugs: 1) vmmouse is not loaded if an usb-tablet is plugged on an ehci controller with companion - 4 cases with mixed options: a)ehci +companion +tablet: vmmouse is not loaded qemu command line : -readconfig /usr/share/qemu-server/pve-usb-companion.cfg -device usb-tablet,id=tablet,bus=ehci.0,port=6 # info mice Mouse #0: QEMU PS/2 Mouse * Mouse #1: QEMU HID Tablet (absolute) b)ehci +companion -tablet: vmmouse is loaded qemu command line : -readconfig /usr/share/qemu-server/pve-usb-companion.cfg # info mice Mouse #0: QEMU PS/2 Mouse * Mouse #1: vmmouse (absolute) c)ehci -companion + tablet : vmmouse is loaded qemu command line : -readconfig /usr/share/qemu-server/pve-usb-nocompanion.cfg -device usb-tablet,id=tablet,bus=ehci.0,port=6 # info mice Mouse #1: QEMU HID Tablet (absolute) Mouse #0: QEMU PS/2 Mouse * Mouse #2: vmmouse (absolute) d)ehci -companion -tablet : vmmouse is loaded qemu command line : -readconfig /usr/share/qemu-server/pve-usb-nocompanion.cfg # info mice Mouse #0: QEMU PS/2 Mouse * Mouse #1: vmmouse (absolute) pve-usb-companion.cfg: [device ehci] driver = ich9-usb-ehci1 addr = 1d.7 multifunction = on [device uhci-1] driver = ich9-usb-uhci1 addr = 1d.0 multifunction = on masterbus = ehci.0 firstport = 0 [device uhci-2] driver = ich9-usb-uhci2 addr = 1d.1 multifunction = on masterbus = ehci.0 firstport = 2 [device uhci-3] driver = ich9-usb-uhci3 addr = 1d.2 multifunction = on masterbus = ehci.0 firstport = 4 pve-usb-nocompanion.cfg: [device ehci] driver = ich9-usb-ehci1 addr = 1d.7 multifunction = off 2) -usb-tablet don't work on ehci with ubuntu -- - don't work (mouse not moving) with or without companion - device is correctly displayed with #lsusb,so maybe it's an xorg driver problem. - It's working fine on windows guest. Both bugs result to don't have a working mouse in ubuntu installer. (vmmouse is not available, and usb-tablet is selected but it's not working). Any idea ? Regards, Alexandre Derumier -- stepping stone GmbH Neufeldstrasse 9 CH-3012 Bern Telefon: +41 31 332 53 63 www.stepping-stone.ch tiziano.muel...@stepping-stone.ch
Re: [Qemu-devel] Live migration using qcow2
Am Mittwoch, den 20.02.2013, 12:20 +0100 schrieb Kevin Wolf: On Wed, Feb 20, 2013 at 11:47:56AM +0100, Tiziano Müller wrote: Hi everyone According to http://wiki.qemu.org/Migration/Storage section Image Formats qemu can't do live migration without data corruption when using qcow2 or qed due to the metadata caches. Wasn't that fixed by commit 06d9260 ? Yes, it is fixed. Depending on your backend, you still need cache=none/directsync, of course. Thanks for the fast reply. Can you please elaborate on that (or post a link to an explanation): What exactly does the backend have to provide that for example cache=writeback can be used? Is there a way to test for it? Regards, Tiziano -- stepping stone GmbH Neufeldstrasse 9 CH-3012 Bern Telefon: +41 31 332 53 63 www.stepping-stone.ch tiziano.muel...@stepping-stone.ch
[Qemu-devel] [Bug 1130533] [NEW] Documentation cannot be build since commit c70a01e449536c616c85ab820c6fbad7d7e9cf39
Public bug reported: I tried to build git -based qemu and when documentation is processed I got this error : ./qemu-options.texi:1526: unknown command `list' ./qemu-options.texi:1526: table requires an argument: the formatter for @item ./qemu-options.texi:1526: warning: @table has text but no @item Looks like commit c70a01e449536c616c85ab820c6fbad7d7e9cf39 is guilty ?! Or any modification related to documentation, I think. ** Affects: qemu Importance: Undecided Status: New -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1130533 Title: Documentation cannot be build since commit c70a01e449536c616c85ab820c6fbad7d7e9cf39 Status in QEMU: New Bug description: I tried to build git -based qemu and when documentation is processed I got this error : ./qemu-options.texi:1526: unknown command `list' ./qemu-options.texi:1526: table requires an argument: the formatter for @item ./qemu-options.texi:1526: warning: @table has text but no @item Looks like commit c70a01e449536c616c85ab820c6fbad7d7e9cf39 is guilty ?! Or any modification related to documentation, I think. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1130533/+subscriptions