Re: [Qemu-devel] [PULL 0/4] Net patches
Il 05/09/2013 23:02, Aurelien Jarno ha scritto: It would be nice if you can get the pcnet fix in your tree. For the ne2k patch, as reported it might break the non-PCI version. I have to look at that more in details, probably this week-end. No, that's fine. The non-PCI version is also little endian. Paolo
Re: [Qemu-devel] [PATCH] spapr-rtas: reset top 4 bits in parameters address
Am 06.09.2013 um 07:04 schrieb Alexey Kardashevskiy a...@ozlabs.ru: On 09/06/2013 12:24 AM, Alexey Kardashevskiy wrote: On 09/05/2013 11:08 PM, Alexander Graf wrote: On 05.09.2013, at 14:49, Alexey Kardashevskiy wrote: On 09/05/2013 10:16 PM, Alexander Graf wrote: On 05.09.2013, at 14:04, Alexey Kardashevskiy wrote: On 09/05/2013 08:21 PM, Alexander Graf wrote: On 05.09.2013, at 12:17, Alexey Kardashevskiy wrote: On 09/05/2013 07:27 PM, Alexander Graf wrote: On 05.09.2013, at 09:40, Alexey Kardashevskiy wrote: On 09/05/2013 05:08 PM, Alexander Graf wrote: Am 05.09.2013 um 07:58 schrieb Alexey Kardashevskiy a...@ozlabs.ru: On the real hardware, RTAS is called in real mode and therefore ignores top 4 bits of the address passed in the call. Shouldn't we ignore the upper 4 bits for every memory access in real mode, not just that one parameter? We probably should but I just do not see any easy way of doing this. Yet another Ignore N bits on the top memory region type? No idea. Well, it already works for code that runs inside of guest context, because there the softmmu code for real mode strips the upper 4 bits. I basically see 2 ways of fixing this correctly: 1) Don't access memory through cpu_physical_memory_rw or ldx_phys but instead through real mode wrappers that strip the upper 4 bits, similar to how we handle virtual memory differently from physical memory But there is no a ready wrapper for this, correct? I could not find any. I would rather do this, looks nicer than 2). 2) Create 15 aliases to system_memory at the upper 4 bits of address space. That should at the end of the day give you the same effect Wow. Is not that too much? Ooor since I am normally making bad decisions, I should do this :) The fix as you're proposing it wouldn't work for indirect memory descriptors. Imagine you have an address parameter that gives you a pointer to a struct in memory that again contains a pointer. You still want that pointer be interpreted correctly, no? Yes I do. I just think that having non zero bits at the top is a bug and I would not want the guest to continue sending bad addresses to the host. Or at least I want to know if it still happening. Now we know that the only occasion of this misbehaviour is the stop-self call and others works just fine. If something new comes up (what is pretty unlikely, otherwise we would have noticed this issue a loong time ago AND Paul already madeposted a patch for the host to fix __pa() so it is not going to happen on new kernels either), ok, we will think of fixing this. Doing in QEMU what the hardware does is a good thing but here I would think twice. Well, the idea behind RTAS is that everything RTAS does is usually run in IR=0 DR=0 inside of guest context, so that's the view of the world we should expose. Which makes me think. Couldn't we just set IR=0 DR=0 when getting an RTAS call and use the virtual memory access functions? Those will already strip the upper 4 bits. Ok. We reached the border where my ignorance starts :) Never could understand the concept of the guest virtual memory in QEMU. So we clear IR/DR and call what API? This is not address_space_rw() and company, right? Nono, we basically route things through the same accesses that instructions inside of guest context would call. Something like cpu_ldl_data() for example. IIRC there is also an #ifdef that allows you to just run ldl(). cpu_ldl_data() is defined for CONFIG_USER_ONLY. But ok, it is defined simply as ldl_p(): #define cpu_ldl_data(env, addr) ldl_raw(addr) #define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + GUEST_BASE)) #define laddr(x) g2h(x) #define ldl_raw(p) ldl_p(laddr((p))) static inline int ldl_p(const void *ptr) { int32_t r; memcpy(r, ptr, sizeof(r)); return r; } So it tries accessing memory @ptr (which is the guest physical) and - crashes :) So I need an address converter which is not there. What do I miss? Thanks. It should be defined through a bunch of macros and incomprehensible #include's and glue()'s for softmmu too. Just try and see if it works for you. Hm. I was not clear. I tried. It crashed in ldl_p() and I explained why exactly. I understand what you expected but it should be different set of macros than the one you proposed. Oh. Figured it out, that actually works. I just looked at wrong definition (which does not use CPU state) of cpu_ldl_data() because cscope and grep just could not the correct one. I had to put a breakpoint in ppc_hash64_handle_mmu_fault() to find a cpu_ldl_code, then I tried to define the _data versions of cpu_lXX_code via exec/exec-all.h (this is where the _code versions are defined) but it turned out that they are already defined in exec/softmmu_exec.h :-/ The glue() macro is a pure, refined evil, there should be at least a comment saying
Re: [Qemu-devel] [RFC PATCH 5/6] module: load modules at start
On Thu, 09/05 14:43, Lluís Vilanova wrote: Fam Zheng writes: Add module_load_all to load all DSO modules under: /usr/lib/qemu/block/ /usr/lib/qemu/net/ /usr/lib/qemu/ui/ when starting process. This should probably be based on a define with the prefix set at configure time. Yes, will fix. Adding directories from command-line arguments into that list would also be nice. Of course, but I'd like to keep this series focusing on essential framework and leave it for follow-ups. Thanks, Fam
Re: [Qemu-devel] [PATCH] spapr-rtas: reset top 4 bits in parameters address
On 09/06/2013 04:22 PM, Alexander Graf wrote: Am 06.09.2013 um 07:04 schrieb Alexey Kardashevskiy a...@ozlabs.ru: On 09/06/2013 12:24 AM, Alexey Kardashevskiy wrote: On 09/05/2013 11:08 PM, Alexander Graf wrote: On 05.09.2013, at 14:49, Alexey Kardashevskiy wrote: On 09/05/2013 10:16 PM, Alexander Graf wrote: On 05.09.2013, at 14:04, Alexey Kardashevskiy wrote: On 09/05/2013 08:21 PM, Alexander Graf wrote: On 05.09.2013, at 12:17, Alexey Kardashevskiy wrote: On 09/05/2013 07:27 PM, Alexander Graf wrote: On 05.09.2013, at 09:40, Alexey Kardashevskiy wrote: On 09/05/2013 05:08 PM, Alexander Graf wrote: Am 05.09.2013 um 07:58 schrieb Alexey Kardashevskiy a...@ozlabs.ru: On the real hardware, RTAS is called in real mode and therefore ignores top 4 bits of the address passed in the call. Shouldn't we ignore the upper 4 bits for every memory access in real mode, not just that one parameter? We probably should but I just do not see any easy way of doing this. Yet another Ignore N bits on the top memory region type? No idea. Well, it already works for code that runs inside of guest context, because there the softmmu code for real mode strips the upper 4 bits. I basically see 2 ways of fixing this correctly: 1) Don't access memory through cpu_physical_memory_rw or ldx_phys but instead through real mode wrappers that strip the upper 4 bits, similar to how we handle virtual memory differently from physical memory But there is no a ready wrapper for this, correct? I could not find any. I would rather do this, looks nicer than 2). 2) Create 15 aliases to system_memory at the upper 4 bits of address space. That should at the end of the day give you the same effect Wow. Is not that too much? Ooor since I am normally making bad decisions, I should do this :) The fix as you're proposing it wouldn't work for indirect memory descriptors. Imagine you have an address parameter that gives you a pointer to a struct in memory that again contains a pointer. You still want that pointer be interpreted correctly, no? Yes I do. I just think that having non zero bits at the top is a bug and I would not want the guest to continue sending bad addresses to the host. Or at least I want to know if it still happening. Now we know that the only occasion of this misbehaviour is the stop-self call and others works just fine. If something new comes up (what is pretty unlikely, otherwise we would have noticed this issue a loong time ago AND Paul already madeposted a patch for the host to fix __pa() so it is not going to happen on new kernels either), ok, we will think of fixing this. Doing in QEMU what the hardware does is a good thing but here I would think twice. Well, the idea behind RTAS is that everything RTAS does is usually run in IR=0 DR=0 inside of guest context, so that's the view of the world we should expose. Which makes me think. Couldn't we just set IR=0 DR=0 when getting an RTAS call and use the virtual memory access functions? Those will already strip the upper 4 bits. Ok. We reached the border where my ignorance starts :) Never could understand the concept of the guest virtual memory in QEMU. So we clear IR/DR and call what API? This is not address_space_rw() and company, right? Nono, we basically route things through the same accesses that instructions inside of guest context would call. Something like cpu_ldl_data() for example. IIRC there is also an #ifdef that allows you to just run ldl(). cpu_ldl_data() is defined for CONFIG_USER_ONLY. But ok, it is defined simply as ldl_p(): #define cpu_ldl_data(env, addr) ldl_raw(addr) #define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + GUEST_BASE)) #define laddr(x) g2h(x) #define ldl_raw(p) ldl_p(laddr((p))) static inline int ldl_p(const void *ptr) { int32_t r; memcpy(r, ptr, sizeof(r)); return r; } So it tries accessing memory @ptr (which is the guest physical) and - crashes :) So I need an address converter which is not there. What do I miss? Thanks. It should be defined through a bunch of macros and incomprehensible #include's and glue()'s for softmmu too. Just try and see if it works for you. Hm. I was not clear. I tried. It crashed in ldl_p() and I explained why exactly. I understand what you expected but it should be different set of macros than the one you proposed. Oh. Figured it out, that actually works. I just looked at wrong definition (which does not use CPU state) of cpu_ldl_data() because cscope and grep just could not the correct one. I had to put a breakpoint in ppc_hash64_handle_mmu_fault() to find a cpu_ldl_code, then I tried to define the _data versions of cpu_lXX_code via exec/exec-all.h (this is where the _code versions are defined) but it turned out that they are already defined in exec/softmmu_exec.h :-/ The glue() macro is a pure, refined evil, there should be at least a comment
[Qemu-devel] [PATCH 00/19] tcg-ia64 fixes and improvements
The AREG0 to R32 patch fixes a real bug, and if anyone cared should be applied to stable. Most of the patches are pure cleanup and improvementm rearranging generated code to use fewer stop bits, and therefore reduce execute cycles. Finally, convert to out-of-line ldst handlers. All of this is on top of my current patch sets. Full tree at git://github.com/rth7680/qemu.git tcg-ldst r~ Richard Henderson (19): tcg-ia64: Use TCGMemOp within qemu_ldst routines tcg-ia64: Use shortcuts for nop insns tcg-ia64: Handle constant calls tcg-ia64: Simplify brcond tcg-ia64: Move AREG0 to R32 tcg-ia64: Avoid unnecessary stop bit in tcg_out_alu tcg-ia64: Use ADDS for small addition tcg-ia64: Use SUB_A3 and ADDS_A4 for subtraction tcg-ia64: Use A3 form of logical operations tcg-ia64 Introduce tcg_opc_mov_a tcg-ia64 Introduce tcg_opc_movi_a tcg-ia64 Introduce tcg_opc_ext_i tcg-ia64 Introduce tcg_opc_bswap64_i tcg-ia64: Re-bundle the tlb load tcg-ia64: Move bswap for store into tlb load tcg-ia64: Move tlb addend load into tlb read tcg-i64: Reduce code duplication in tcg_out_qemu_ld tcg-ia64: Convert to new ldst helpers tcg-ia64: Move part of softmmu slow path out of line tcg/ia64/tcg-target.c | 1022 ++--- tcg/ia64/tcg-target.h |6 +- 2 files changed, 555 insertions(+), 473 deletions(-) -- 1.8.3.1
[Qemu-devel] [PATCH 04/19] tcg-ia64: Simplify brcond
There was a misconception that a stop bit is required between a compare and the branch that uses the predicate set by the compare. This lead to the usage of an extra bundle in which to perform the compare. The extra bundle left room for constants to be loaded for use with the compare insn. If we pack the compare and the branch together in the same bundle, then there's no longer any room for non-zero constants. At which point we can eliminate half the function by not handling them. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 42 +- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 6708844..413e00f 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1442,38 +1442,16 @@ static inline uint64_t tcg_opc_cmp_a(int qp, TCGCond cond, TCGArg arg1, } } -static inline void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGArg arg1, - int const_arg1, TCGArg arg2, int const_arg2, - int label_index, int cmp4) +static inline void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, + TCGReg arg2, int label_index, int cmp4) { TCGLabel *l = s-labels[label_index]; -uint64_t opc1, opc2; -if (const_arg1 arg1 != 0) { -opc1 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R2, - arg1, TCG_REG_R0); -arg1 = TCG_REG_R2; -} else { -opc1 = INSN_NOP_M; -} - -if (const_arg2 arg2 != 0) { -opc2 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R3, - arg2, TCG_REG_R0); -arg2 = TCG_REG_R3; -} else { -opc2 = INSN_NOP_I; -} - -tcg_out_bundle(s, mII, - opc1, - opc2, - tcg_opc_cmp_a(TCG_REG_P0, cond, arg1, arg2, cmp4)); -tcg_out_bundle(s, mmB, - INSN_NOP_M, +tcg_out_bundle(s, miB, INSN_NOP_M, - tcg_opc_b1 (TCG_REG_P6, OPC_BR_DPTK_FEW_B1, - get_reloc_pcrel21b(s-code_ptr + 2))); + tcg_opc_cmp_a(TCG_REG_P0, cond, arg1, arg2, cmp4), + tcg_opc_b1(TCG_REG_P6, OPC_BR_DPTK_FEW_B1, + get_reloc_pcrel21b(s-code_ptr + 2))); if (l-has_value) { reloc_pcrel21b((s-code_ptr - 16) + 2, l-u.value); @@ -,12 +2200,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_brcond_i32: -tcg_out_brcond(s, args[2], args[0], const_args[0], - args[1], const_args[1], args[3], 1); +tcg_out_brcond(s, args[2], args[0], args[1], args[3], 1); break; case INDEX_op_brcond_i64: -tcg_out_brcond(s, args[2], args[0], const_args[0], - args[1], const_args[1], args[3], 0); +tcg_out_brcond(s, args[2], args[0], args[1], args[3], 0); break; case INDEX_op_setcond_i32: tcg_out_setcond(s, args[3], args[0], args[1], args[2], 1); @@ -2331,7 +2307,7 @@ static const TCGTargetOpDef ia64_op_defs[] = { { INDEX_op_bswap16_i32, { r, rZ } }, { INDEX_op_bswap32_i32, { r, rZ } }, -{ INDEX_op_brcond_i32, { rI, rI } }, +{ INDEX_op_brcond_i32, { rZ, rZ } }, { INDEX_op_setcond_i32, { r, rZ, rZ } }, { INDEX_op_movcond_i32, { r, rZ, rZ, rI, rI } }, -- 1.8.3.1
[Qemu-devel] [PATCH 01/19] tcg-ia64: Use TCGMemOp within qemu_ldst routines
Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 171 ++ 1 file changed, 90 insertions(+), 81 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index cd4f1ae..dcf4dd3 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1494,7 +1494,7 @@ static inline void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGArg ret, R2 is loaded with the address of the addend TLB entry. R57 is loaded with the address, zero extented on 32-bit targets. */ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg, -int s_bits, uint64_t offset_rw, +TCGMemOp s_bits, uint64_t offset_rw, uint64_t offset_addend) { tcg_out_bundle(s, mII, @@ -1536,23 +1536,24 @@ static const void * const qemu_ld_helpers[4] = { helper_ldq_mmu, }; -static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) +static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, + TCGMemOp opc) { -int addr_reg, data_reg, mem_index, s_bits, bswap; -uint64_t opc_ld_m1[4] = { OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1 }; -uint64_t opc_ext_i29[8] = { OPC_ZXT1_I29, OPC_ZXT2_I29, OPC_ZXT4_I29, 0, -OPC_SXT1_I29, OPC_SXT2_I29, OPC_SXT4_I29, 0 }; +static const uint64_t opc_ld_m1[4] = { +OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1 +}; +static const uint64_t opc_ext_i29[8] = { +OPC_ZXT1_I29, OPC_ZXT2_I29, OPC_ZXT4_I29, 0, +OPC_SXT1_I29, OPC_SXT2_I29, OPC_SXT4_I29, 0 +}; +int addr_reg, data_reg, mem_index; +TCGMemOp s_bits, bswap; data_reg = *args++; addr_reg = *args++; mem_index = *args; -s_bits = opc 3; - -#ifdef TARGET_WORDS_BIGENDIAN -bswap = 1; -#else -bswap = 0; -#endif +s_bits = opc MO_SIZE; +bswap = opc MO_BSWAP; /* Read the TLB entry */ tcg_out_qemu_tlb(s, addr_reg, s_bits, @@ -1573,14 +1574,14 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) TCG_REG_R3, TCG_REG_R57), tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6, TCG_REG_R3, 0)); -if (bswap s_bits == 1) { +if (bswap s_bits == MO_16) { tcg_out_bundle(s, MmI, tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits], TCG_REG_R8, TCG_REG_R3), tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12, TCG_REG_R8, TCG_REG_R8, 15, 15)); -} else if (bswap s_bits == 2) { +} else if (bswap s_bits == MO_32) { tcg_out_bundle(s, MmI, tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits], TCG_REG_R8, TCG_REG_R3), @@ -1594,7 +1595,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0)); } -if (!bswap || s_bits == 0) { +if (!bswap) { tcg_out_bundle(s, miB, tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R58, mem_index, TCG_REG_R0), @@ -1611,7 +1612,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) TCG_REG_B0, TCG_REG_B6)); } -if (opc == 3) { +if (s_bits == MO_64) { tcg_out_bundle(s, miI, tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0), @@ -1621,7 +1622,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) tcg_out_bundle(s, miI, tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0), - tcg_opc_i29(TCG_REG_P0, opc_ext_i29[opc], + tcg_opc_i29(TCG_REG_P0, opc_ext_i29[opc MO_SSIZE], data_reg, TCG_REG_R8)); } } @@ -1635,22 +1636,21 @@ static const void * const qemu_st_helpers[4] = { helper_stq_mmu, }; -static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) +static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, + TCGMemOp opc) { -int addr_reg, data_reg, mem_index, bswap; -uint64_t opc_st_m4[4] = { OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4 }; +static const uint64_t opc_st_m4[4] = { +OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4 +}; +int addr_reg, data_reg, mem_index; +
[Qemu-devel] [PATCH 05/19] tcg-ia64: Move AREG0 to R32
Since the move away from the global areg0, we're no longer globally reserving areg0. Which means our use of R7 clobbers a call-saved register. Shift areg0 into the windowed registers. Indeed, choose the incoming parameter register that it comes to us by. This requires moving the register holding the return address elsewhere. Choose R33 for tidiness. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 13 ++--- tcg/ia64/tcg-target.h | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 413e00f..ad5a6b9 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -107,7 +107,6 @@ enum { }; static const int tcg_target_reg_alloc_order[] = { -TCG_REG_R33, TCG_REG_R35, TCG_REG_R36, TCG_REG_R37, @@ -2402,8 +2401,7 @@ static void tcg_target_qemu_prologue(TCGContext *s) tcg_out_bundle(s, miI, tcg_opc_m34(TCG_REG_P0, OPC_ALLOC_M34, TCG_REG_R34, 32, 24, 0), - tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4, - TCG_AREG0, 0, TCG_REG_R32), + INSN_NOP_I, tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21, TCG_REG_B6, TCG_REG_R33, 0)); @@ -2422,7 +2420,7 @@ static void tcg_target_qemu_prologue(TCGContext *s) tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4, TCG_REG_R12, -frame_size, TCG_REG_R12), tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22, - TCG_REG_R32, TCG_REG_B0), + TCG_REG_R33, TCG_REG_B0), tcg_opc_b4 (TCG_REG_P0, OPC_BR_SPTK_MANY_B4, TCG_REG_B6)); /* epilogue */ @@ -2430,7 +2428,7 @@ static void tcg_target_qemu_prologue(TCGContext *s) tcg_out_bundle(s, miI, INSN_NOP_M, tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21, - TCG_REG_B0, TCG_REG_R32, 0), + TCG_REG_B0, TCG_REG_R33, 0), tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4, TCG_REG_R12, frame_size, TCG_REG_R12)); tcg_out_bundle(s, miB, @@ -2487,16 +2485,17 @@ static void tcg_target_init(TCGContext *s) tcg_regset_set_reg(s-reserved_regs, TCG_REG_R3); /* internal use */ tcg_regset_set_reg(s-reserved_regs, TCG_REG_R12); /* stack pointer */ tcg_regset_set_reg(s-reserved_regs, TCG_REG_R13); /* thread pointer */ -tcg_regset_set_reg(s-reserved_regs, TCG_REG_R32); /* return address */ +tcg_regset_set_reg(s-reserved_regs, TCG_REG_R33); /* return address */ tcg_regset_set_reg(s-reserved_regs, TCG_REG_R34); /* PFS */ -/* The following 3 are not in use, are call-saved, but *not* saved +/* The following 4 are not in use, are call-saved, but *not* saved by the prologue. Therefore we cannot use them without modifying the prologue. There doesn't seem to be any good reason to use these as opposed to the windowed registers. */ tcg_regset_set_reg(s-reserved_regs, TCG_REG_R4); tcg_regset_set_reg(s-reserved_regs, TCG_REG_R5); tcg_regset_set_reg(s-reserved_regs, TCG_REG_R6); +tcg_regset_set_reg(s-reserved_regs, TCG_REG_R7); tcg_add_target_add_op_defs(ia64_op_defs); } diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index 9fe3bf6..65897f2 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -94,6 +94,8 @@ typedef enum { TCG_REG_R61, TCG_REG_R62, TCG_REG_R63, + +TCG_AREG0 = TCG_REG_R32, } TCGReg; #define TCG_CT_CONST_ZERO 0x100 @@ -164,8 +166,6 @@ typedef enum { #define TCG_TARGET_HAS_not_i32 0 /* xor r1, -1, r3 */ #define TCG_TARGET_HAS_not_i64 0 /* xor r1, -1, r3 */ -#define TCG_AREG0 TCG_REG_R7 - static inline void flush_icache_range(uintptr_t start, uintptr_t stop) { start = start ~(32UL - 1UL); -- 1.8.3.1
[Qemu-devel] [PATCH 02/19] tcg-ia64: Use shortcuts for nop insns
There's no need to go through the full opcode-to-insn function call to generate nops. This makes the source a bit more readable. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 251 +- 1 file changed, 127 insertions(+), 124 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index dcf4dd3..1db8745 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -282,6 +282,9 @@ enum { OPC_ZXT1_I29 = 0x0008000ull, OPC_ZXT2_I29 = 0x0008800ull, OPC_ZXT4_I29 = 0x0009000ull, + +INSN_NOP_M= OPC_NOP_M48, /* nop.m 0 */ +INSN_NOP_I= OPC_NOP_I18, /* nop.i 0 */ }; static inline uint64_t tcg_opc_a1(int qp, uint64_t opc, int r1, @@ -853,8 +856,8 @@ static inline void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) { tcg_out_bundle(s, mmI, - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), + INSN_NOP_M, + INSN_NOP_M, tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, ret, 0, arg)); } @@ -862,7 +865,7 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, TCGReg reg, tcg_target_long arg) { tcg_out_bundle(s, mLX, - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), + INSN_NOP_M, tcg_opc_l2 (arg), tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2, reg, arg)); } @@ -875,8 +878,8 @@ static void tcg_out_br(TCGContext *s, int label_index) the existing value and using it again. This ensure that caches and memory are kept coherent during retranslation. */ tcg_out_bundle(s, mmB, - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), + INSN_NOP_M, + INSN_NOP_M, tcg_opc_b1 (TCG_REG_P0, OPC_BR_SPTK_MANY_B1, get_reloc_pcrel21b(s-code_ptr + 2))); @@ -897,7 +900,7 @@ static inline void tcg_out_call(TCGContext *s, TCGArg addr) TCG_REG_B6, TCG_REG_R2, 0)); tcg_out_bundle(s, mmB, tcg_opc_m1 (TCG_REG_P0, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R3), - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), + INSN_NOP_M, tcg_opc_b5 (TCG_REG_P0, OPC_BR_CALL_SPTK_MANY_B5, TCG_REG_B0, TCG_REG_B6)); } @@ -913,7 +916,7 @@ static void tcg_out_exit_tb(TCGContext *s, tcg_target_long arg) imm = (uint64_t)disp 4; tcg_out_bundle(s, mLX, - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), + INSN_NOP_M, tcg_opc_l3 (imm), tcg_opc_x3 (TCG_REG_P0, OPC_BRL_SPTK_MANY_X3, imm)); } @@ -930,12 +933,12 @@ static inline void tcg_out_goto_tb(TCGContext *s, TCGArg arg) tcg_out_bundle(s, MmI, tcg_opc_m1 (TCG_REG_P0, OPC_LD8_M1, TCG_REG_R2, TCG_REG_R2), - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), + INSN_NOP_M, tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21, TCG_REG_B6, TCG_REG_R2, 0)); tcg_out_bundle(s, mmB, - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), + INSN_NOP_M, + INSN_NOP_M, tcg_opc_b4 (TCG_REG_P0, OPC_BR_SPTK_MANY_B4, TCG_REG_B6)); } @@ -945,12 +948,12 @@ static inline void tcg_out_goto_tb(TCGContext *s, TCGArg arg) static inline void tcg_out_jmp(TCGContext *s, TCGArg addr) { tcg_out_bundle(s, mmI, - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), + INSN_NOP_M, + INSN_NOP_M, tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21, TCG_REG_B6, addr, 0)); tcg_out_bundle(s, mmB, - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), + INSN_NOP_M, + INSN_NOP_M, tcg_opc_b4(TCG_REG_P0, OPC_BR_SPTK_MANY_B4, TCG_REG_B6)); } @@ -962,14 +965,14 @@ static inline void tcg_out_ld_rel(TCGContext *s, uint64_t opc_m4, TCGArg arg, tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, TCG_REG_R2, arg2, arg1), tcg_opc_m1 (TCG_REG_P0, opc_m4, arg, TCG_REG_R2), - tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0)); + INSN_NOP_I);
[Qemu-devel] [PATCH 08/19] tcg-ia64: Use SUB_A3 and ADDS_A4 for subtraction
We can subtract from more small constants that just 0 with one insn, and we can add the negative for most small constants. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 25 +++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 1659421..cc8c7a9 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1078,6 +1078,28 @@ static inline void tcg_out_add(TCGContext *s, TCGReg ret, TCGReg arg1, } } +static inline void tcg_out_sub(TCGContext *s, TCGReg ret, TCGArg arg1, + int const_arg1, TCGArg arg2, int const_arg2) +{ +if (const_arg1 arg1 == (int8_t)arg1) { +if (const_arg2) { +tcg_out_movi(s, TCG_TYPE_I64, ret, arg1 - arg2); +return; +} +tcg_out_bundle(s, mmI, + INSN_NOP_M, + INSN_NOP_M, + tcg_opc_a3(TCG_REG_P0, OPC_SUB_A3, ret, arg1, arg2)); +} else if (const_arg2 -arg2 == sextract64(-arg2, 0, 14)) { +tcg_out_bundle(s, mmI, + INSN_NOP_M, + INSN_NOP_M, + tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, ret, -arg2, arg1)); +} else { +tcg_out_alu(s, OPC_SUB_A1, ret, arg1, 0, arg2, 0); +} +} + static inline void tcg_out_eqv(TCGContext *s, TCGArg ret, TCGArg arg1, int const_arg1, TCGArg arg2, int const_arg2) @@ -2083,8 +2105,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_sub_i32: case INDEX_op_sub_i64: -tcg_out_alu(s, OPC_SUB_A1, args[0], args[1], const_args[1], -args[2], const_args[2]); +tcg_out_sub(s, args[0], args[1], const_args[1], args[2], const_args[2]); break; case INDEX_op_and_i32: -- 1.8.3.1
[Qemu-devel] [PATCH 07/19] tcg-ia64: Use ADDS for small addition
Avoids a wasted cycle loading up small constants. Simplify the code assuming the tcg optimizer is going to work and don't expect the first operand of the add to be constant. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 20 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index f0c5e0b..1659421 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1065,6 +1065,19 @@ static void tcg_out_alu(TCGContext *s, uint64_t opc_a1, TCGReg ret, TCGArg arg1, tcg_opc_a1(TCG_REG_P0, opc_a1, ret, arg1, arg2)); } +static inline void tcg_out_add(TCGContext *s, TCGReg ret, TCGReg arg1, + TCGArg arg2, int const_arg2) +{ +if (const_arg2 arg2 == sextract64(arg2, 0, 14)) { +tcg_out_bundle(s, mmI, + INSN_NOP_M, + INSN_NOP_M, + tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, ret, arg2, arg1)); +} else { +tcg_out_alu(s, OPC_ADD_A1, ret, arg1, 0, arg2, const_arg2); +} +} + static inline void tcg_out_eqv(TCGContext *s, TCGArg ret, TCGArg arg1, int const_arg1, TCGArg arg2, int const_arg2) @@ -2066,8 +2079,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_add_i32: case INDEX_op_add_i64: -tcg_out_alu(s, OPC_ADD_A1, args[0], args[1], const_args[1], -args[2], const_args[2]); +tcg_out_add(s, args[0], args[1], args[2], const_args[2]); break; case INDEX_op_sub_i32: case INDEX_op_sub_i64: @@ -2273,7 +2285,7 @@ static const TCGTargetOpDef ia64_op_defs[] = { { INDEX_op_st16_i32, { rZ, r } }, { INDEX_op_st_i32, { rZ, r } }, -{ INDEX_op_add_i32, { r, rI, rI } }, +{ INDEX_op_add_i32, { r, rZ, rI } }, { INDEX_op_sub_i32, { r, rI, rI } }, { INDEX_op_and_i32, { r, rI, rI } }, @@ -2320,7 +2332,7 @@ static const TCGTargetOpDef ia64_op_defs[] = { { INDEX_op_st32_i64, { rZ, r } }, { INDEX_op_st_i64, { rZ, r } }, -{ INDEX_op_add_i64, { r, rI, rI } }, +{ INDEX_op_add_i64, { r, rZ, rI } }, { INDEX_op_sub_i64, { r, rI, rI } }, { INDEX_op_and_i64, { r, rI, rI } }, -- 1.8.3.1
[Qemu-devel] [PATCH 09/19] tcg-ia64: Use A3 form of logical operations
We can and/or/xor/andcm small constants, saving one cycle. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 52 +++ 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index cc8c7a9..de81593 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -261,6 +261,7 @@ enum { OPC_MOV_I_I26 = 0x0015000ull, OPC_MOVL_X2 = 0x0c0ull, OPC_OR_A1 = 0x1007000ull, +OPC_OR_A3 = 0x1017000ull, OPC_SETF_EXP_M18 = 0x0c74800ull, OPC_SETF_SIG_M18 = 0x0c70800ull, OPC_SHL_I7= 0x0f24000ull, @@ -279,6 +280,7 @@ enum { OPC_UNPACK4_L_I2 = 0x0f86000ull, OPC_XMA_L_F2 = 0x1d0ull, OPC_XOR_A1= 0x1007800ull, +OPC_XOR_A3= 0x1017800ull, OPC_ZXT1_I29 = 0x0008000ull, OPC_ZXT2_I29 = 0x0008800ull, OPC_ZXT4_I29 = 0x0009000ull, @@ -1042,27 +1044,34 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, } } -static void tcg_out_alu(TCGContext *s, uint64_t opc_a1, TCGReg ret, TCGArg arg1, -int const_arg1, TCGArg arg2, int const_arg2) +static inline void tcg_out_alu(TCGContext *s, uint64_t opc_a1, uint64_t opc_a3, + TCGReg ret, TCGArg arg1, int const_arg1, + TCGArg arg2, int const_arg2) { -uint64_t opc1 = 0, opc2 = 0; - -if (const_arg1 arg1 != 0) { -opc1 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5, - TCG_REG_R2, arg1, TCG_REG_R0); -arg1 = TCG_REG_R2; -} +uint64_t opc1 = 0, opc2 = 0, opc3 = 0; if (const_arg2 arg2 != 0) { opc2 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R3, arg2, TCG_REG_R0); arg2 = TCG_REG_R3; } +if (const_arg1 arg1 != 0) { +if (opc_a3 arg1 == (int8_t)arg1) { +opc3 = tcg_opc_a3(TCG_REG_P0, opc_a3, ret, arg1, arg2); +} else { +opc1 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5, + TCG_REG_R2, arg1, TCG_REG_R0); +arg1 = TCG_REG_R2; +} +} +if (opc3 == 0) { +opc3 = tcg_opc_a1(TCG_REG_P0, opc_a1, ret, arg1, arg2); +} tcg_out_bundle(s, (opc1 || opc2 ? mII : miI), opc1 ? opc1 : INSN_NOP_M, opc2 ? opc2 : INSN_NOP_I, - tcg_opc_a1(TCG_REG_P0, opc_a1, ret, arg1, arg2)); + opc3); } static inline void tcg_out_add(TCGContext *s, TCGReg ret, TCGReg arg1, @@ -1074,7 +1083,7 @@ static inline void tcg_out_add(TCGContext *s, TCGReg ret, TCGReg arg1, INSN_NOP_M, tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, ret, arg2, arg1)); } else { -tcg_out_alu(s, OPC_ADD_A1, ret, arg1, 0, arg2, const_arg2); +tcg_out_alu(s, OPC_ADD_A1, 0, ret, arg1, 0, arg2, const_arg2); } } @@ -1096,7 +1105,7 @@ static inline void tcg_out_sub(TCGContext *s, TCGReg ret, TCGArg arg1, INSN_NOP_M, tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, ret, -arg2, arg1)); } else { -tcg_out_alu(s, OPC_SUB_A1, ret, arg1, 0, arg2, 0); +tcg_out_alu(s, OPC_SUB_A1, 0, ret, arg1, 0, arg2, 0); } } @@ -2110,13 +2119,14 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_and_i32: case INDEX_op_and_i64: -tcg_out_alu(s, OPC_AND_A1, args[0], args[1], const_args[1], -args[2], const_args[2]); +/* TCG expects arg2 constant; A3 expects arg1 constant. Swap. */ +tcg_out_alu(s, OPC_AND_A1, OPC_AND_A3, args[0], +args[2], const_args[2], args[1], const_args[1]); break; case INDEX_op_andc_i32: case INDEX_op_andc_i64: -tcg_out_alu(s, OPC_ANDCM_A1, args[0], args[1], const_args[1], -args[2], const_args[2]); +tcg_out_alu(s, OPC_ANDCM_A1, OPC_ANDCM_A3, args[0], +args[1], const_args[1], args[2], const_args[2]); break; case INDEX_op_eqv_i32: case INDEX_op_eqv_i64: @@ -2135,8 +2145,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_or_i32: case INDEX_op_or_i64: -tcg_out_alu(s, OPC_OR_A1, args[0], args[1], const_args[1], -args[2], const_args[2]); +/* TCG expects arg2 constant; A3 expects arg1 constant. Swap. */ +tcg_out_alu(s, OPC_OR_A1, OPC_OR_A3, args[0], +args[2], const_args[2], args[1], const_args[1]); break; case INDEX_op_orc_i32: case INDEX_op_orc_i64: @@ -2145,8 +2156,9 @@ static inline void
[Qemu-devel] [PATCH 14/19] tcg-ia64: Re-bundle the tlb load
This sequencing requires 5 stop bits instead of 6, and has room left over to pre-load the tlb addend, and bswap data prior to being stored. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 77 --- 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 3c177c6..2fa6dd5 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1564,38 +1564,69 @@ static inline void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGArg ret, } #if defined(CONFIG_SOFTMMU) +/* We're expecting to use an signed 22-bit immediate add. */ +QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1]) + 0x1f) + /* Load and compare a TLB entry, and return the result in (p6, p7). R2 is loaded with the address of the addend TLB entry. - R57 is loaded with the address, zero extented on 32-bit targets. */ -static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg, -TCGMemOp s_bits, uint64_t offset_rw, -uint64_t offset_addend) -{ -tcg_out_bundle(s, mII, - INSN_NOP_M, - tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, TCG_REG_R2, + R57 is loaded with the address, zero extented on 32-bit targets. + R1, R3 are clobbered. */ +static inline void tcg_out_qemu_tlb(TCGContext *s, TCGReg addr_reg, +TCGMemOp s_bits, int off_rw, int off_add) +{ + /* +.mii +movr2 = off_rw +extr.u r3 = addr_reg, ... # extract tlb page +zxt4 r57 = addr_reg # or mov for 64-bit guest +;; +.mii +addl r2 = r2, areg0 +shlr3 = r3, cteb # via dep.z +depr1 = 0, r57, ...# zero page ofs, keep align +;; +.mmi +addr2 = r2, r3 +;; +ld4r3 = [r2], off_add-off_rw # or ld8 for 64-bit guest +nop +;; +.mmi +nop +cmp.eq p6, p7 = r3, r58 +nop +;; + */ +tcg_out_bundle(s, miI, + tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R2, off_rw), + tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, TCG_REG_R3, addr_reg, TARGET_PAGE_BITS, CPU_TLB_BITS - 1), - tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, TCG_REG_R2, - TCG_REG_R2, 63 - CPU_TLB_ENTRY_BITS, - 63 - CPU_TLB_ENTRY_BITS)); -tcg_out_bundle(s, mII, - tcg_opc_a5 (TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R2, - offset_rw, TCG_REG_R2), tcg_opc_ext_i(TCG_REG_P0, TARGET_LONG_BITS == 32 ? MO_UL : MO_Q, - TCG_REG_R57, addr_reg), + TCG_REG_R57, addr_reg)); +tcg_out_bundle(s, miI, tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2, - TCG_REG_R2, TCG_AREG0)); -tcg_out_bundle(s, mII, + TCG_REG_R2, TCG_AREG0), + tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, TCG_REG_R3, + TCG_REG_R3, 63 - CPU_TLB_ENTRY_BITS, + 63 - CPU_TLB_ENTRY_BITS), + tcg_opc_i14(TCG_REG_P0, OPC_DEP_I14, TCG_REG_R1, 0, + TCG_REG_R57, 63 - s_bits, + TARGET_PAGE_BITS - s_bits - 1)); +tcg_out_bundle(s, MmI, + tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, + TCG_REG_R2, TCG_REG_R2, TCG_REG_R3), tcg_opc_m3 (TCG_REG_P0, (TARGET_LONG_BITS == 32 -? OPC_LD4_M3 : OPC_LD8_M3), TCG_REG_R56, - TCG_REG_R2, offset_addend - offset_rw), - tcg_opc_i14(TCG_REG_P0, OPC_DEP_I14, TCG_REG_R3, 0, - TCG_REG_R57, 63 - s_bits, - TARGET_PAGE_BITS - s_bits - 1), +? OPC_LD4_M3 : OPC_LD8_M3), TCG_REG_R3, + TCG_REG_R2, off_add - off_rw), + INSN_NOP_I); +tcg_out_bundle(s, mmI, + INSN_NOP_M, tcg_opc_a6 (TCG_REG_P0, OPC_CMP_EQ_A6, TCG_REG_P6, - TCG_REG_P7, TCG_REG_R3, TCG_REG_R56)); + TCG_REG_P7, TCG_REG_R1, TCG_REG_R3), + INSN_NOP_I); } /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, -- 1.8.3.1
[Qemu-devel] [PATCH 10/19] tcg-ia64 Introduce tcg_opc_mov_a
Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 35 --- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index de81593..3e96af9 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -865,13 +865,18 @@ static inline void tcg_out_bundle(TCGContext *s, int template, s-code_ptr += 16; } +static inline uint64_t tcg_opc_mov_a(int qp, TCGReg dst, TCGReg src) +{ +return tcg_opc_a4(qp, OPC_ADDS_A4, dst, 0, src); +} + static inline void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) { tcg_out_bundle(s, mmI, INSN_NOP_M, INSN_NOP_M, - tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, ret, 0, arg)); + tcg_opc_mov_a(TCG_REG_P0, ret, arg)); } static inline void tcg_out_movi(TCGContext *s, TCGType type, @@ -1520,14 +1525,14 @@ static inline void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGArg ret, } else if (ret == v1) { opc1 = INSN_NOP_M; } else { -opc1 = tcg_opc_a4(TCG_REG_P6, OPC_ADDS_A4, ret, 0, v1); +opc1 = tcg_opc_mov_a(TCG_REG_P6, ret, v1); } if (const_v2) { opc2 = tcg_opc_a5(TCG_REG_P7, OPC_ADDL_A5, ret, v2, TCG_REG_R0); } else if (ret == v2) { opc2 = INSN_NOP_I; } else { -opc2 = tcg_opc_a4(TCG_REG_P7, OPC_ADDS_A4, ret, 0, v2); +opc2 = tcg_opc_mov_a(TCG_REG_P7, ret, v2); } tcg_out_bundle(s, MmI, @@ -1557,8 +1562,7 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg, #if TARGET_LONG_BITS == 32 tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29, TCG_REG_R57, addr_reg), #else - tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, TCG_REG_R57, - 0, addr_reg), + tcg_opc_mov_a(TCG_REG_P0, TCG_REG_R57, addr_reg), #endif tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2, TCG_REG_R2, TCG_AREG0)); @@ -1609,8 +1613,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, /* P6 is the fast path, and P7 the slow path */ tcg_out_bundle(s, mLX, - tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, - TCG_REG_R56, 0, TCG_AREG0), + tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0), tcg_opc_l2 ((tcg_target_long) qemu_ld_helpers[s_bits]), tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2, (tcg_target_long) qemu_ld_helpers[s_bits])); @@ -1663,8 +1666,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_out_bundle(s, miI, INSN_NOP_M, INSN_NOP_I, - tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4, - data_reg, 0, TCG_REG_R8)); + tcg_opc_mov_a(TCG_REG_P0, data_reg, TCG_REG_R8)); } else { tcg_out_bundle(s, miI, INSN_NOP_M, @@ -1703,8 +1705,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, /* P6 is the fast path, and P7 the slow path */ tcg_out_bundle(s, mLX, - tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, - TCG_REG_R56, 0, TCG_AREG0), + tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0), tcg_opc_l2 ((tcg_target_long) qemu_st_helpers[s_bits]), tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2, (tcg_target_long) qemu_st_helpers[s_bits])); @@ -1724,8 +1725,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, tcg_out_bundle(s, mii, tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), - tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, TCG_REG_R58, - 0, data_reg), + tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg), INSN_NOP_I); break; @@ -1737,8 +1737,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12, TCG_REG_R2, data_reg, 15, 15)); tcg_out_bundle(s, miI, - tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, TCG_REG_R58, - 0, data_reg), + tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg), INSN_NOP_I, tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3, TCG_REG_R2, TCG_REG_R2, 0xb)); @@ -1753,8 +1752,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
[Qemu-devel] [PATCH 12/19] tcg-ia64 Introduce tcg_opc_ext_i
Being able to extend from 64-bits (with a mov) simplifies a few places where the conditional breaks the train of thought. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 54 +++ 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 8057f40..6c95920 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1383,6 +1383,20 @@ static inline void tcg_out_rotr_i64(TCGContext *s, TCGArg ret, TCGArg arg1, } } +static const uint64_t opc_ext_i29[8] = { +OPC_ZXT1_I29, OPC_ZXT2_I29, OPC_ZXT4_I29, 0, +OPC_SXT1_I29, OPC_SXT2_I29, OPC_SXT4_I29, 0 +}; + +static inline uint64_t tcg_opc_ext_i(int qp, TCGMemOp opc, TCGReg d, TCGReg s) +{ +if ((opc MO_SIZE) == MO_64) { +return tcg_opc_mov_a(qp, d, s); +} else { +return tcg_opc_i29(qp, opc_ext_i29[opc MO_SSIZE], d, s); +} +} + static inline void tcg_out_ext(TCGContext *s, uint64_t opc_i29, TCGArg ret, TCGArg arg) { @@ -1562,11 +1576,9 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg, tcg_out_bundle(s, mII, tcg_opc_a5 (TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R2, offset_rw, TCG_REG_R2), -#if TARGET_LONG_BITS == 32 - tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29, TCG_REG_R57, addr_reg), -#else - tcg_opc_mov_a(TCG_REG_P0, TCG_REG_R57, addr_reg), -#endif + tcg_opc_ext_i(TCG_REG_P0, + TARGET_LONG_BITS == 32 ? MO_UL : MO_Q, + TCG_REG_R57, addr_reg), tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2, TCG_REG_R2, TCG_AREG0)); tcg_out_bundle(s, mII, @@ -1596,10 +1608,6 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, static const uint64_t opc_ld_m1[4] = { OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1 }; -static const uint64_t opc_ext_i29[8] = { -OPC_ZXT1_I29, OPC_ZXT2_I29, OPC_ZXT4_I29, 0, -OPC_SXT1_I29, OPC_SXT2_I29, OPC_SXT4_I29, 0 -}; int addr_reg, data_reg, mem_index; TCGMemOp s_bits, bswap; @@ -1663,18 +1671,10 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCG_REG_B0, TCG_REG_B6)); } -if (s_bits == MO_64) { -tcg_out_bundle(s, miI, - INSN_NOP_M, - INSN_NOP_I, - tcg_opc_mov_a(TCG_REG_P0, data_reg, TCG_REG_R8)); -} else { -tcg_out_bundle(s, miI, - INSN_NOP_M, - INSN_NOP_I, - tcg_opc_i29(TCG_REG_P0, opc_ext_i29[opc MO_SSIZE], - data_reg, TCG_REG_R8)); -} +tcg_out_bundle(s, miI, + INSN_NOP_M, + INSN_NOP_I, + tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, TCG_REG_R8)); } /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr, @@ -1790,9 +1790,6 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, static uint64_t const opc_ld_m1[4] = { OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1 }; -static uint64_t const opc_sxt_i29[4] = { -OPC_SXT1_I29, OPC_SXT2_I29, OPC_SXT4_I29, 0 -}; int addr_reg, data_reg; TCGMemOp s_bits, bswap; @@ -1829,8 +1826,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits], data_reg, TCG_REG_R2), INSN_NOP_I, - tcg_opc_i29(TCG_REG_P0, opc_sxt_i29[s_bits], - data_reg, data_reg)); + tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, data_reg)); } } else if (s_bits == MO_64) { tcg_out_bundle(s, mII, @@ -1866,8 +1862,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, INSN_NOP_M, tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, data_reg, data_reg, 0xb), - tcg_opc_i29(TCG_REG_P0, opc_sxt_i29[s_bits], - data_reg, data_reg)); + tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, data_reg)); } } #else @@ -1911,8 +1906,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_out_bundle(s, miI, INSN_NOP_M, INSN_NOP_I, - tcg_opc_i29(TCG_REG_P0, opc_sxt_i29[s_bits], - data_reg, data_reg)); + tcg_opc_ext_i(TCG_REG_P0, opc, data_reg,
Re: [Qemu-devel] [RFC v4 4/5] hw/arm/digic: add UART support
On Thu, 5 Sep 2013 19:17:50 +0100 Peter Maydell peter.mayd...@linaro.org wrote: On 5 September 2013 08:52, Antony Pavlov antonynpav...@gmail.com wrote: +static int uart_can_rx(void *opaque) +{ +DigicUartState *s = opaque; + +return !(s-regs[R_ST] ST_RX_RDY); +} + +static void uart_rx(void *opaque, const uint8_t *buf, int size) +{ +DigicUartState *s = opaque; + +assert(uart_can_rx(opaque)); + +s-regs[R_ST] |= ST_RX_RDY; +s-regs[R_RX] = *buf; Does this UART really not have a FIFO? There is no public documentation on Digic chips. Only Canon's engineers know something about Digic's FIFO (if it exists :). +} diff --git a/hw/char/digic-uart.h b/hw/char/digic-uart.h new file mode 100644 index 000..ca48f4e --- /dev/null +++ b/hw/char/digic-uart.h @@ -0,0 +1,27 @@ Copyright/license header comment at start of all files, please (ditto below). +#ifndef HW_CHAR_DIGIC_UART_H +#define HW_CHAR_DIGIC_UART_H + +#include hw/sysbus.h +#include qemu/typedefs.h + +#define TYPE_DIGIC_UART digic-uart +#define DIGIC_UART(obj) \ +OBJECT_CHECK(DigicUartState, (obj), TYPE_DIGIC_UART) + +enum { +R_TX = 0x00, +R_RX, +R_ST = (0x14 2), +R_MAX +}; + +typedef struct DigicUartState { +SysBusDevice parent_obj; + +MemoryRegion regs_region; +CharDriverState *chr; + +uint32_t regs[R_MAX]; So this thing only has five registers, one of which at least (R_TX) doesn't have state that you'll be storing in this struct anyway, and you're not implementing reads-as-written behaviour for the unknown registers, so I think you should drop the regs[] array and just have individual uint32_t fields for the registers you implement. +} DigicUartState; + +#endif /* HW_CHAR_DIGIC_UART_H */ diff --git a/include/hw/arm/digic.h b/include/hw/arm/digic.h index 48c9f9c..c587ade 100644 --- a/include/hw/arm/digic.h +++ b/include/hw/arm/digic.h @@ -11,10 +11,13 @@ #include cpu-qom.h #include hw/timer/digic-timer.h +#include hw/char/digic-uart.h #define DIGIC4_NB_TIMERS 3 #define DIGIC4_TIMER_BASE(n)(0xc021 + (n) * 0x100) +#define DIGIC_UART_BASE 0xc080 Does this really need to be in the header file? It seems like private implementation information that could go in the source file that needs it. (same is probably true of some of the other macros.) + #define TYPE_DIGIC digic #define DIGIC(obj) OBJECT_CHECK(DigicState, (obj), TYPE_DIGIC) @@ -25,6 +28,7 @@ typedef struct DigicState { ARMCPU cpu; DigicTimerState timer[DIGIC4_NB_TIMERS]; +DigicUartState uart; } DigicState; #endif /* __DIGIC_H__ */ -- 1.8.4.rc3 thanks -- PMM -- -- Best regards, Antony Pavlov
[Qemu-devel] [PATCH 16/19] tcg-ia64: Move tlb addend load into tlb read
Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 24 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 23be46c..819bca3 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1569,7 +1569,7 @@ QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1]) 0x1f) /* Load and compare a TLB entry, and return the result in (p6, p7). - R2 is loaded with the address of the addend TLB entry. + R2 is loaded with the addend TLB entry. R57 is loaded with the address, zero extented on 32-bit targets. R1, R3 are clobbered, leaving R56 free for... BSWAP_1, BSWAP_2 and I-slot insns for swapping data for store. */ @@ -1625,7 +1625,7 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGReg addr_reg, TCG_REG_R2, off_add - off_rw), bswap1); tcg_out_bundle(s, mmI, - INSN_NOP_M, + tcg_opc_m1 (TCG_REG_P0, OPC_LD8_M1, TCG_REG_R2, TCG_REG_R2), tcg_opc_a6 (TCG_REG_P0, OPC_CMP_EQ_A6, TCG_REG_P6, TCG_REG_P7, TCG_REG_R1, TCG_REG_R3), bswap2); @@ -1668,30 +1668,30 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2, (tcg_target_long) qemu_ld_helpers[s_bits])); tcg_out_bundle(s, MmI, - tcg_opc_m3 (TCG_REG_P0, OPC_LD8_M3, TCG_REG_R3, + tcg_opc_m3 (TCG_REG_P7, OPC_LD8_M3, TCG_REG_R3, TCG_REG_R2, 8), - tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R3, - TCG_REG_R3, TCG_REG_R57), + tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2, + TCG_REG_R2, TCG_REG_R57), tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6, TCG_REG_R3, 0)); if (bswap s_bits == MO_16) { tcg_out_bundle(s, MmI, tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits], - TCG_REG_R8, TCG_REG_R3), + TCG_REG_R8, TCG_REG_R2), tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12, TCG_REG_R8, TCG_REG_R8, 15, 15)); } else if (bswap s_bits == MO_32) { tcg_out_bundle(s, MmI, tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits], - TCG_REG_R8, TCG_REG_R3), + TCG_REG_R8, TCG_REG_R2), tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12, TCG_REG_R8, TCG_REG_R8, 31, 31)); } else { tcg_out_bundle(s, mmI, tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits], - TCG_REG_R8, TCG_REG_R3), + TCG_REG_R8, TCG_REG_R2), tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), INSN_NOP_I); } @@ -1763,10 +1763,10 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2, (tcg_target_long) qemu_st_helpers[s_bits])); tcg_out_bundle(s, MmI, - tcg_opc_m3 (TCG_REG_P0, OPC_LD8_M3, TCG_REG_R3, + tcg_opc_m3 (TCG_REG_P7, OPC_LD8_M3, TCG_REG_R3, TCG_REG_R2, 8), - tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R3, - TCG_REG_R3, TCG_REG_R57), + tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2, + TCG_REG_R2, TCG_REG_R57), tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6, TCG_REG_R3, 0)); tcg_out_bundle(s, mii, @@ -1776,7 +1776,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, INSN_NOP_I); tcg_out_bundle(s, miB, tcg_opc_m4 (TCG_REG_P6, opc_st_m4[s_bits], - store_reg, TCG_REG_R3), + store_reg, TCG_REG_R2), tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R59, mem_index), tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, TCG_REG_B0, TCG_REG_B6)); -- 1.8.3.1
[Qemu-devel] [PATCH 15/19] tcg-ia64: Move bswap for store into tlb load
Saving at least two cycles per store, and cleaning up the code. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 96 +-- 1 file changed, 32 insertions(+), 64 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 2fa6dd5..23be46c 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1571,9 +1571,11 @@ QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1]) /* Load and compare a TLB entry, and return the result in (p6, p7). R2 is loaded with the address of the addend TLB entry. R57 is loaded with the address, zero extented on 32-bit targets. - R1, R3 are clobbered. */ + R1, R3 are clobbered, leaving R56 free for... + BSWAP_1, BSWAP_2 and I-slot insns for swapping data for store. */ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGReg addr_reg, -TCGMemOp s_bits, int off_rw, int off_add) +TCGMemOp s_bits, int off_rw, int off_add, +uint64_t bswap1, uint64_t bswap2) { /* .mii @@ -1621,12 +1623,12 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGReg addr_reg, (TARGET_LONG_BITS == 32 ? OPC_LD4_M3 : OPC_LD8_M3), TCG_REG_R3, TCG_REG_R2, off_add - off_rw), - INSN_NOP_I); + bswap1); tcg_out_bundle(s, mmI, INSN_NOP_M, tcg_opc_a6 (TCG_REG_P0, OPC_CMP_EQ_A6, TCG_REG_P6, TCG_REG_P7, TCG_REG_R1, TCG_REG_R3), - INSN_NOP_I); + bswap2); } /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, @@ -1656,7 +1658,8 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, /* Read the TLB entry */ tcg_out_qemu_tlb(s, addr_reg, s_bits, offsetof(CPUArchState, tlb_table[mem_index][0].addr_read), - offsetof(CPUArchState, tlb_table[mem_index][0].addend)); + offsetof(CPUArchState, tlb_table[mem_index][0].addend), + INSN_NOP_I, INSN_NOP_I); /* P6 is the fast path, and P7 the slow path */ tcg_out_bundle(s, mLX, @@ -1727,17 +1730,31 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, static const uint64_t opc_st_m4[4] = { OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4 }; -int addr_reg, data_reg, mem_index; +TCGReg addr_reg, data_reg, store_reg; +int mem_index; +uint64_t bswap1, bswap2; TCGMemOp s_bits; -data_reg = *args++; +store_reg = data_reg = *args++; addr_reg = *args++; mem_index = *args; s_bits = opc MO_SIZE; +bswap1 = bswap2 = INSN_NOP_I; +if (opc MO_BSWAP) { +store_reg = TCG_REG_R56; +bswap1 = tcg_opc_bswap64_i(TCG_REG_P0, store_reg, data_reg); +if (s_bits MO_64) { +int shift = 64 - (8 s_bits); +bswap2 = tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, + store_reg, store_reg, shift, 63 - shift); +} +} + tcg_out_qemu_tlb(s, addr_reg, s_bits, offsetof(CPUArchState, tlb_table[mem_index][0].addr_write), - offsetof(CPUArchState, tlb_table[mem_index][0].addend)); + offsetof(CPUArchState, tlb_table[mem_index][0].addend), + bswap1, bswap2); /* P6 is the fast path, and P7 the slow path */ tcg_out_bundle(s, mLX, @@ -1752,63 +1769,14 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCG_REG_R3, TCG_REG_R57), tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6, TCG_REG_R3, 0)); - -switch (opc) { -case MO_8: -case MO_16: -case MO_32: -case MO_64: -tcg_out_bundle(s, mii, - tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, - TCG_REG_R1, TCG_REG_R2), - tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg), - INSN_NOP_I); -break; - -case MO_16 | MO_BSWAP: -tcg_out_bundle(s, miI, - tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, - TCG_REG_R1, TCG_REG_R2), - INSN_NOP_I, - tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12, - TCG_REG_R2, data_reg, 15, 15)); -tcg_out_bundle(s, miI, - tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg), - INSN_NOP_I, - tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R2, TCG_REG_R2)); -data_reg = TCG_REG_R2; -break; - -case MO_32 | MO_BSWAP: -
[Qemu-devel] [PATCH 11/19] tcg-ia64 Introduce tcg_opc_movi_a
Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 32 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 3e96af9..8057f40 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -879,6 +879,12 @@ static inline void tcg_out_mov(TCGContext *s, TCGType type, tcg_opc_mov_a(TCG_REG_P0, ret, arg)); } +static inline uint64_t tcg_opc_movi_a(int qp, TCGReg dst, int64_t src) +{ +assert(src == sextract64(src, 0, 22)); +return tcg_opc_a5(qp, OPC_ADDL_A5, dst, src, TCG_REG_R0); +} + static inline void tcg_out_movi(TCGContext *s, TCGType type, TCGReg reg, tcg_target_long arg) { @@ -1056,16 +1062,14 @@ static inline void tcg_out_alu(TCGContext *s, uint64_t opc_a1, uint64_t opc_a3, uint64_t opc1 = 0, opc2 = 0, opc3 = 0; if (const_arg2 arg2 != 0) { -opc2 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5, - TCG_REG_R3, arg2, TCG_REG_R0); +opc2 = tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R3, arg2); arg2 = TCG_REG_R3; } if (const_arg1 arg1 != 0) { if (opc_a3 arg1 == (int8_t)arg1) { opc3 = tcg_opc_a3(TCG_REG_P0, opc_a3, ret, arg1, arg2); } else { -opc1 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5, - TCG_REG_R2, arg1, TCG_REG_R0); +opc1 = tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R2, arg1); arg1 = TCG_REG_R2; } } @@ -1429,8 +1433,7 @@ static inline void tcg_out_deposit(TCGContext *s, TCGArg ret, TCGArg a1, } else { /* Otherwise, load any constant into a temporary. Do this into the first I slot to help out with cross-unit delays. */ -i1 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5, -TCG_REG_R2, a2, TCG_REG_R0); +i1 = tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R2, a2); a2 = TCG_REG_R2; } } @@ -1509,8 +1512,8 @@ static inline void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg ret, { tcg_out_bundle(s, MmI, tcg_opc_cmp_a(TCG_REG_P0, cond, arg1, arg2, cmp4), - tcg_opc_a5(TCG_REG_P6, OPC_ADDL_A5, ret, 1, TCG_REG_R0), - tcg_opc_a5(TCG_REG_P7, OPC_ADDL_A5, ret, 0, TCG_REG_R0)); + tcg_opc_movi_a(TCG_REG_P6, ret, 1), + tcg_opc_movi_a(TCG_REG_P7, ret, 0)); } static inline void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGArg ret, @@ -1521,14 +1524,14 @@ static inline void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGArg ret, uint64_t opc1, opc2; if (const_v1) { -opc1 = tcg_opc_a5(TCG_REG_P6, OPC_ADDL_A5, ret, v1, TCG_REG_R0); +opc1 = tcg_opc_movi_a(TCG_REG_P6, ret, v1); } else if (ret == v1) { opc1 = INSN_NOP_M; } else { opc1 = tcg_opc_mov_a(TCG_REG_P6, ret, v1); } if (const_v2) { -opc2 = tcg_opc_a5(TCG_REG_P7, OPC_ADDL_A5, ret, v2, TCG_REG_R0); +opc2 = tcg_opc_movi_a(TCG_REG_P7, ret, v2); } else if (ret == v2) { opc2 = INSN_NOP_I; } else { @@ -1647,15 +1650,13 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, } if (!bswap) { tcg_out_bundle(s, miB, - tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R58, - mem_index, TCG_REG_R0), + tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index), INSN_NOP_I, tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, TCG_REG_B0, TCG_REG_B6)); } else { tcg_out_bundle(s, miB, - tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R58, - mem_index, TCG_REG_R0), + tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index), tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3, TCG_REG_R8, TCG_REG_R8, 0xb), tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, @@ -1776,8 +1777,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, tcg_out_bundle(s, miB, tcg_opc_m4 (TCG_REG_P6, opc_st_m4[opc], data_reg, TCG_REG_R3), - tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R59, - mem_index, TCG_REG_R0), + tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R59, mem_index), tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, TCG_REG_B0, TCG_REG_B6)); } -- 1.8.3.1
[Qemu-devel] [PATCH 19/19] tcg-ia64: Move part of softmmu slow path out of line
Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 156 +++--- tcg/ia64/tcg-target.h | 2 +- 2 files changed, 97 insertions(+), 61 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index ea24e83..9fd176d 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -219,6 +219,7 @@ enum { OPC_ALLOC_M34 = 0x02cull, OPC_BR_DPTK_FEW_B1= 0x084ull, OPC_BR_SPTK_MANY_B1 = 0x0801000ull, +OPC_BR_CALL_SPNT_FEW_B3 = 0x0a2ull, OPC_BR_SPTK_MANY_B4 = 0x0011000ull, OPC_BR_CALL_SPTK_MANY_B5 = 0x0211000ull, OPC_BR_RET_SPTK_MANY_B4 = 0x00108001100ull, @@ -355,6 +356,15 @@ static inline uint64_t tcg_opc_b1(int qp, uint64_t opc, uint64_t imm) | (qp 0x3f); } +static inline uint64_t tcg_opc_b3(int qp, uint64_t opc, int b1, uint64_t imm) +{ +return opc + | ((imm 0x10) 16) /* s */ + | ((imm 0x0f) 13) /* imm20b */ + | ((b1 0x7) 6) + | (qp 0x3f); +} + static inline uint64_t tcg_opc_b4(int qp, uint64_t opc, int b2) { return opc @@ -1633,14 +1643,70 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGReg addr_reg, bswap2); } -/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, - int mmu_idx, uintptr_t retaddr) */ -static const void * const qemu_ld_helpers[4] = { -helper_ret_ldub_mmu, -helper_le_lduw_mmu, -helper_le_ldul_mmu, -helper_le_ldq_mmu, -}; +static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc, +uint8_t *label_ptr) +{ +TCGLabelQemuLdst *l = s-qemu_ldst_labels[s-nb_qemu_ldst_labels++]; + +assert(s-nb_qemu_ldst_labels = TCG_MAX_QEMU_LDST); + +/* We don't need most of the items in the generic structure. */ +memset(l, 0, sizeof(*l)); +l-is_ld = is_ld; +l-opc = opc MO_SIZE; +l-label_ptr[0] = label_ptr; +} + +void tcg_out_tb_finalize(TCGContext *s) +{ +static const void * const helpers[8] = { +helper_ret_stb_mmu, +helper_le_stw_mmu, +helper_le_stl_mmu, +helper_le_stq_mmu, +helper_ret_ldub_mmu, +helper_le_lduw_mmu, +helper_le_ldul_mmu, +helper_le_ldq_mmu, +}; +uintptr_t thunks[8] = { }; +size_t i, n = s-nb_qemu_ldst_labels; + +for (i = 0; i n; i++) { +TCGLabelQemuLdst *l = s-qemu_ldst_labels[i]; +long x = l-is_ld * 4 + l-opc; +uintptr_t dest = thunks[x]; + +/* The out-of-line thunks are all the same; load the return address + from B0, load the GP, and branch to the code. Note that we are + always post-call, so the register window has rolled, so we're + using incomming parameter register numbers, not outgoing. */ +if (dest == 0) { +uintptr_t disp, *desc = (uintptr_t *)helpers[x]; + +thunks[x] = dest = (uintptr_t)s-code_ptr; + +tcg_out_bundle(s, mlx, + INSN_NOP_M, + tcg_opc_l2 (desc[1]), + tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2, + TCG_REG_R1, desc[1])); +tcg_out_bundle(s, mii, + INSN_NOP_M, + INSN_NOP_I, + tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22, + l-is_ld ? TCG_REG_R35 : TCG_REG_R36, + TCG_REG_B0)); +disp = (desc[0] - (uintptr_t)s-code_ptr) 4; +tcg_out_bundle(s, mLX, + INSN_NOP_M, + tcg_opc_l3 (disp), + tcg_opc_x3 (TCG_REG_P0, OPC_BRL_SPTK_MANY_X3, disp)); +} + +reloc_pcrel21b(l-label_ptr[0], dest); +} +} static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGMemOp opc) @@ -1650,7 +1716,8 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, }; int addr_reg, data_reg, mem_index; TCGMemOp s_bits; -uint64_t fin1, fin2, *desc, func, gp, here; +uint64_t fin1, fin2; +uint8_t *label_ptr; data_reg = *args++; addr_reg = *args++; @@ -1677,31 +1744,20 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, fin1 = tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, TCG_REG_R8); } -desc = (uintptr_t *)qemu_ld_helpers[s_bits]; -func = desc[0]; -gp = desc[1]; -here = (uintptr_t)s-code_ptr; - -tcg_out_bundle(s, mlx, +tcg_out_bundle(s, mmI, tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0), - tcg_opc_l2 (here), - tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R59, here)); -tcg_out_bundle(s, mLX,
[Qemu-devel] [PATCH 17/19] tcg-i64: Reduce code duplication in tcg_out_qemu_ld
The only differences were in the bswap insns emitted. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 60 --- 1 file changed, 23 insertions(+), 37 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 819bca3..6355f32 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1647,13 +1647,13 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1 }; int addr_reg, data_reg, mem_index; -TCGMemOp s_bits, bswap; +TCGMemOp s_bits; +uint64_t bswap1, bswap2; data_reg = *args++; addr_reg = *args++; mem_index = *args; s_bits = opc MO_SIZE; -bswap = opc MO_BSWAP; /* Read the TLB entry */ tcg_out_qemu_tlb(s, addr_reg, s_bits, @@ -1662,6 +1662,17 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, INSN_NOP_I, INSN_NOP_I); /* P6 is the fast path, and P7 the slow path */ + +bswap1 = bswap2 = INSN_NOP_I; +if (opc MO_BSWAP) { +bswap1 = tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R8, TCG_REG_R8); +if (s_bits MO_64) { +int shift = 64 - (8 s_bits); +bswap2 = tcg_opc_i11(TCG_REG_P6, OPC_EXTR_U_I11, + TCG_REG_R8, TCG_REG_R8, shift, 63 - shift); +} +} + tcg_out_bundle(s, mLX, tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0), tcg_opc_l2 ((tcg_target_long) qemu_ld_helpers[s_bits]), @@ -1674,41 +1685,16 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCG_REG_R2, TCG_REG_R57), tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6, TCG_REG_R3, 0)); -if (bswap s_bits == MO_16) { -tcg_out_bundle(s, MmI, - tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits], - TCG_REG_R8, TCG_REG_R2), - tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), - tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12, - TCG_REG_R8, TCG_REG_R8, 15, 15)); -} else if (bswap s_bits == MO_32) { -tcg_out_bundle(s, MmI, - tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits], - TCG_REG_R8, TCG_REG_R2), - tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), - tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12, - TCG_REG_R8, TCG_REG_R8, 31, 31)); -} else { -tcg_out_bundle(s, mmI, - tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits], - TCG_REG_R8, TCG_REG_R2), - tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), - INSN_NOP_I); -} -if (!bswap) { -tcg_out_bundle(s, miB, - tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index), - INSN_NOP_I, - tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, - TCG_REG_B0, TCG_REG_B6)); -} else { -tcg_out_bundle(s, miB, - tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index), - tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R8, TCG_REG_R8), - tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, - TCG_REG_B0, TCG_REG_B6)); -} - +tcg_out_bundle(s, MmI, + tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits], + TCG_REG_R8, TCG_REG_R2), + tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), + bswap1); +tcg_out_bundle(s, miB, + tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index), + bswap2, + tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, + TCG_REG_B0, TCG_REG_B6)); tcg_out_bundle(s, miI, INSN_NOP_M, INSN_NOP_I, -- 1.8.3.1
[Qemu-devel] [PATCH 13/19] tcg-ia64 Introduce tcg_opc_bswap64_i
Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 63 +++ 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 6c95920..3c177c6 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1406,12 +1406,17 @@ static inline void tcg_out_ext(TCGContext *s, uint64_t opc_i29, tcg_opc_i29(TCG_REG_P0, opc_i29, ret, arg)); } +static inline uint64_t tcg_opc_bswap64_i(int qp, TCGReg d, TCGReg s) +{ +return tcg_opc_i3(qp, OPC_MUX1_I3, d, s, 0xb); +} + static inline void tcg_out_bswap16(TCGContext *s, TCGArg ret, TCGArg arg) { tcg_out_bundle(s, mII, INSN_NOP_M, tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, ret, arg, 15, 15), - tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, ret, ret, 0xb)); + tcg_opc_bswap64_i(TCG_REG_P0, ret, ret)); } static inline void tcg_out_bswap32(TCGContext *s, TCGArg ret, TCGArg arg) @@ -1419,7 +1424,7 @@ static inline void tcg_out_bswap32(TCGContext *s, TCGArg ret, TCGArg arg) tcg_out_bundle(s, mII, INSN_NOP_M, tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, ret, arg, 31, 31), - tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, ret, ret, 0xb)); + tcg_opc_bswap64_i(TCG_REG_P0, ret, ret)); } static inline void tcg_out_bswap64(TCGContext *s, TCGArg ret, TCGArg arg) @@ -1427,7 +1432,7 @@ static inline void tcg_out_bswap64(TCGContext *s, TCGArg ret, TCGArg arg) tcg_out_bundle(s, miI, INSN_NOP_M, INSN_NOP_I, - tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, ret, arg, 0xb)); + tcg_opc_bswap64_i(TCG_REG_P0, ret, arg)); } static inline void tcg_out_deposit(TCGContext *s, TCGArg ret, TCGArg a1, @@ -1665,8 +1670,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, } else { tcg_out_bundle(s, miB, tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index), - tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3, - TCG_REG_R8, TCG_REG_R8, 0xb), + tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R8, TCG_REG_R8), tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, TCG_REG_B0, TCG_REG_B6)); } @@ -1740,8 +1744,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, tcg_out_bundle(s, miI, tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg), INSN_NOP_I, - tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3, - TCG_REG_R2, TCG_REG_R2, 0xb)); + tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R2, TCG_REG_R2)); data_reg = TCG_REG_R2; break; @@ -1755,8 +1758,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, tcg_out_bundle(s, miI, tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg), INSN_NOP_I, - tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3, - TCG_REG_R2, TCG_REG_R2, 0xb)); + tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R2, TCG_REG_R2)); data_reg = TCG_REG_R2; break; @@ -1765,8 +1767,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg), - tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3, - TCG_REG_R2, data_reg, 0xb)); + tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R2, data_reg)); data_reg = TCG_REG_R2; break; @@ -1833,8 +1834,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits], data_reg, TCG_REG_R2), INSN_NOP_I, - tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, - data_reg, data_reg, 0xb)); + tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg)); } else { if (s_bits == MO_16) { tcg_out_bundle(s, mII, @@ -1855,13 +1855,11 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_out_bundle(s, miI, INSN_NOP_M, INSN_NOP_I, - tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, - data_reg, data_reg, 0xb)); + tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg)); } else
[Qemu-devel] [PATCH 18/19] tcg-ia64: Convert to new ldst helpers
Still inline, but updated to the new routines. Always use the LE helpers, reusing the bswap between the fast and slot paths. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 140 -- 1 file changed, 79 insertions(+), 61 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 6355f32..ea24e83 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -223,6 +223,7 @@ enum { OPC_BR_CALL_SPTK_MANY_B5 = 0x0211000ull, OPC_BR_RET_SPTK_MANY_B4 = 0x00108001100ull, OPC_BRL_SPTK_MANY_X3 = 0x1801000ull, +OPC_BRL_CALL_SPNT_MANY_X4 = 0x1a21000ull, OPC_BRL_CALL_SPTK_MANY_X4 = 0x1a01000ull, OPC_CMP_LT_A6 = 0x180ull, OPC_CMP_LTU_A6= 0x1a0ull, @@ -813,6 +814,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) #if defined(CONFIG_SOFTMMU) tcg_regset_reset_reg(ct-u.regs, TCG_REG_R56); tcg_regset_reset_reg(ct-u.regs, TCG_REG_R57); +tcg_regset_reset_reg(ct-u.regs, TCG_REG_R58); #endif break; case 'Z': @@ -1632,12 +1634,12 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGReg addr_reg, } /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, - int mmu_idx) */ + int mmu_idx, uintptr_t retaddr) */ static const void * const qemu_ld_helpers[4] = { -helper_ldb_mmu, -helper_ldw_mmu, -helper_ldl_mmu, -helper_ldq_mmu, +helper_ret_ldub_mmu, +helper_le_lduw_mmu, +helper_le_ldul_mmu, +helper_le_ldq_mmu, }; static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -1648,7 +1650,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, }; int addr_reg, data_reg, mem_index; TCGMemOp s_bits; -uint64_t bswap1, bswap2; +uint64_t fin1, fin2, *desc, func, gp, here; data_reg = *args++; addr_reg = *args++; @@ -1663,51 +1665,59 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, /* P6 is the fast path, and P7 the slow path */ -bswap1 = bswap2 = INSN_NOP_I; +fin2 = 0; if (opc MO_BSWAP) { -bswap1 = tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R8, TCG_REG_R8); +fin1 = tcg_opc_bswap64_i(TCG_REG_P0, data_reg, TCG_REG_R8); if (s_bits MO_64) { int shift = 64 - (8 s_bits); -bswap2 = tcg_opc_i11(TCG_REG_P6, OPC_EXTR_U_I11, - TCG_REG_R8, TCG_REG_R8, shift, 63 - shift); +fin2 = tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, + data_reg, data_reg, shift, 63 - shift); } +} else { +fin1 = tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, TCG_REG_R8); } -tcg_out_bundle(s, mLX, +desc = (uintptr_t *)qemu_ld_helpers[s_bits]; +func = desc[0]; +gp = desc[1]; +here = (uintptr_t)s-code_ptr; + +tcg_out_bundle(s, mlx, tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0), - tcg_opc_l2 ((tcg_target_long) qemu_ld_helpers[s_bits]), - tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2, - (tcg_target_long) qemu_ld_helpers[s_bits])); -tcg_out_bundle(s, MmI, - tcg_opc_m3 (TCG_REG_P7, OPC_LD8_M3, TCG_REG_R3, - TCG_REG_R2, 8), + tcg_opc_l2 (here), + tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R59, here)); +tcg_out_bundle(s, mLX, tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2, TCG_REG_R2, TCG_REG_R57), - tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6, - TCG_REG_R3, 0)); -tcg_out_bundle(s, MmI, + tcg_opc_l2 (gp), + tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R1, gp)); +tcg_out_bundle(s, mmi, tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits], TCG_REG_R8, TCG_REG_R2), - tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), - bswap1); -tcg_out_bundle(s, miB, tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index), - bswap2, - tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, - TCG_REG_B0, TCG_REG_B6)); -tcg_out_bundle(s, miI, + INSN_NOP_I); +func -= (uintptr_t)s-code_ptr; +tcg_out_bundle(s, mLX, INSN_NOP_M, - INSN_NOP_I, - tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, TCG_REG_R8)); + tcg_opc_l4 (func 4), + tcg_opc_x4 (TCG_REG_P7, OPC_BRL_CALL_SPNT_MANY_X4, + TCG_REG_B0, func 4)); + +/* Note that we always use LE helper functions, so the bswap insns +
Re: [Qemu-devel] [RFC v4 2/5] hw/arm/digic: prepare DIGIC-based boards support
On Thu, 5 Sep 2013 18:54:30 +0100 Peter Maydell peter.mayd...@linaro.org wrote: On 5 September 2013 08:52, Antony Pavlov antonynpav...@gmail.com wrote: Also this patch adds initial support for Canon PowerShot A1100 IS compact camera. Signed-off-by: Antony Pavlov antonynpav...@gmail.com --- hw/arm/Makefile.objs | 2 +- hw/arm/digic_boards.c | 63 +++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 hw/arm/digic_boards.c diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index e140485..f6e9533 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -1,4 +1,4 @@ -obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o +obj-y += boot.o collie.o digic_boards.o exynos4_boards.o gumstix.o highbank.o obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c new file mode 100644 index 000..0b99227 --- /dev/null +++ b/hw/arm/digic_boards.c @@ -0,0 +1,63 @@ Copyright and license summary comment at the top of the file, please. +#include hw/boards.h +#include exec/address-spaces.h +#include hw/arm/digic.h + +typedef struct DigicBoardState { +DigicState *digic; +MemoryRegion ram; +} DigicBoardState; + +typedef struct DigicBoard { +hwaddr ram_size; +hwaddr start_addr; +} DigicBoard; + +static void digic4_board_setup_ram(DigicBoardState *s, hwaddr ram_size) +{ +memory_region_init_ram(s-ram, NULL, ram, ram_size); +memory_region_add_subregion(get_system_memory(), 0, s-ram); +vmstate_register_ram_global(s-ram); +} + +static void digic4_board_init(DigicBoard *board) +{ +Error *err = NULL; + +DigicBoardState *s = g_new(DigicBoardState, 1); + +s-digic = DIGIC(object_new(TYPE_DIGIC)); +object_property_set_bool(OBJECT(s-digic), true, realized, err); +if (err != NULL) { +fprintf(stderr, Couldn't realize DIGIC SoC: %s\n, +error_get_pretty(err)); +exit(1); +} + +digic4_board_setup_ram(s, board-ram_size); + +s-digic-cpu.env.regs[15] = board-start_addr; This is odd. What happens on real hardware? Is the firmware actually at zero? There is no public documentation on Digic chips. Only Canon's engineers know something about real Digic's bootprocess. Nowadays Canon produce two families of photocameras: * relatevely cheap Point-and-Shot cameras (PowerShot series); * more expensive cameras with exchangeable lens (EOS series). The DIGIC chips has two regions for NOR ROM mapping. The PowerShot cameras (as rule) have simple firmware and use only one ROM region. The EOS cameras have more complex firmware and use both ROM regions. So the board-start_addr parameter is used just for selection of ROM region. +} + +static DigicBoard digic4_board_canon_a1100 = { +.ram_size = 64 * 1024 * 1024, +/* CHDK recommends this address for ROM disassembly */ +.start_addr = 0xffc0, +}; + +static void canon_a1100_init(QEMUMachineInitArgs *args) +{ +digic4_board_init(digic4_board_canon_a1100); +} + +static QEMUMachine canon_a1100 = { +.name = canon-a1100, +.desc = Canon PowerShot A1100 IS, +.init = canon_a1100_init, +}; + +static void digic_register_machines(void) +{ +qemu_register_machine(canon_a1100); +} + +machine_init(digic_register_machines) -- 1.8.4.rc3 -- -- Best regards, Antony Pavlov
[Qemu-devel] [PATCH 06/19] tcg-ia64: Avoid unnecessary stop bit in tcg_out_alu
When performing an operation with two input registers, we'd leave the stop bit (and thus an extra cycle) that's only needed when one or the other input is a constant. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 17 ++--- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index ad5a6b9..f0c5e0b 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1042,31 +1042,26 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, } } -static inline void tcg_out_alu(TCGContext *s, uint64_t opc_a1, TCGArg ret, - TCGArg arg1, int const_arg1, - TCGArg arg2, int const_arg2) +static void tcg_out_alu(TCGContext *s, uint64_t opc_a1, TCGReg ret, TCGArg arg1, +int const_arg1, TCGArg arg2, int const_arg2) { -uint64_t opc1, opc2; +uint64_t opc1 = 0, opc2 = 0; if (const_arg1 arg1 != 0) { opc1 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R2, arg1, TCG_REG_R0); arg1 = TCG_REG_R2; -} else { -opc1 = INSN_NOP_M; } if (const_arg2 arg2 != 0) { opc2 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R3, arg2, TCG_REG_R0); arg2 = TCG_REG_R3; -} else { -opc2 = INSN_NOP_I; } -tcg_out_bundle(s, mII, - opc1, - opc2, +tcg_out_bundle(s, (opc1 || opc2 ? mII : miI), + opc1 ? opc1 : INSN_NOP_M, + opc2 ? opc2 : INSN_NOP_I, tcg_opc_a1(TCG_REG_P0, opc_a1, ret, arg1, arg2)); } -- 1.8.3.1
Re: [Qemu-devel] [RFC PATCH 4/6] Makefile: introduce common-obj-m and block-obj-m for DSO
On 09/05/2013 10:53 PM, Fam Zheng wrote: OK. Thanks for pointing out. The problem with ar file is that --whole-archive needs to be done specificly to modules .a, other libs shouldn't be linked with this flag. See also: --whole-archive foo.a --no-whole-archive r~
Re: [Qemu-devel] [RFC v4 4/5] hw/arm/digic: add UART support
On 6 September 2013 07:54, Antony Pavlov antonynpav...@gmail.com wrote: On Thu, 5 Sep 2013 19:17:50 +0100 Peter Maydell peter.mayd...@linaro.org wrote: Does this UART really not have a FIFO? There is no public documentation on Digic chips. Only Canon's engineers know something about Digic's FIFO (if it exists :). You can deduce its existence though -- does the UART let you feed two or three characters to it at faster than whatever the serial line speed is before it sets the stop sending me bits status bit, or does it stop after the first? If the real firmware uses this for anything remotely serious (ie for more than trivial and default-disabled debug info) it probably does have a FIFO. However, let's assume it doesn't for now. -- PMM
Re: [Qemu-devel] [PATCH v2 2/3] hda-codec: make mixemu selectable at runtime
--- a/hw/audio/hda-codec.c +++ b/hw/audio/hda-codec.c @@ -118,7 +118,20 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as) #define QEMU_HDA_AMP_NONE(0) #define QEMU_HDA_AMP_STEPS 0x4a +#ifdef CONFIG_MIXEMU +#define PARAM mixemu +#define HDA_MIXER #include hda-codec-common.h +#else +/* keep the compiler quiet */ +static const desc_codec output_mixemu; +static const desc_codec duplex_mixemu; +static const desc_codec micro_mixemu; Needed? The *_mixemu variants are not referenced without CONFIG_MIXEMU +#endif + +#define PARAM nomixemu #undefine HDA_MIXER +#include hda-codec-common.h + cheers, Gerd
[Qemu-devel] [PATCH 03/19] tcg-ia64: Handle constant calls
Using only indirect calls results in 3 bundles (one to load the descriptor address), and 4 stop bits. By looking through the descriptor to the constants, we can perform the call with 2 bundles and only 1 stop bit. Signed-off-by: Richard Henderson r...@twiddle.net --- tcg/ia64/tcg-target.c | 38 +++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 1db8745..6708844 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -224,6 +224,7 @@ enum { OPC_BR_CALL_SPTK_MANY_B5 = 0x0211000ull, OPC_BR_RET_SPTK_MANY_B4 = 0x00108001100ull, OPC_BRL_SPTK_MANY_X3 = 0x1801000ull, +OPC_BRL_CALL_SPTK_MANY_X4 = 0x1a01000ull, OPC_CMP_LT_A6 = 0x180ull, OPC_CMP_LTU_A6= 0x1a0ull, OPC_CMP_EQ_A6 = 0x1c0ull, @@ -582,6 +583,8 @@ static inline uint64_t tcg_opc_l3(uint64_t imm) return (imm 0x07f0ull) 18; } +#define tcg_opc_l4 tcg_opc_l3 + static inline uint64_t tcg_opc_m1(int qp, uint64_t opc, int r1, int r3) { return opc @@ -666,6 +669,15 @@ static inline uint64_t tcg_opc_x3(int qp, uint64_t opc, uint64_t imm) | (qp 0x3f); } +static inline uint64_t tcg_opc_x4(int qp, uint64_t opc, int b1, uint64_t imm) +{ +return opc + | ((imm 0x0800ull) 23) /* i */ + | ((imm 0x000full) 13) /* imm20b */ + | ((b1 0x7) 6) + | (qp 0x3f); +} + /* * Relocations @@ -891,7 +903,23 @@ static void tcg_out_br(TCGContext *s, int label_index) } } -static inline void tcg_out_call(TCGContext *s, TCGArg addr) +static inline void tcg_out_calli(TCGContext *s, uintptr_t addr) +{ +/* Look through the function descriptor. */ +uintptr_t disp, *desc = (uintptr_t *)addr; +tcg_out_bundle(s, mlx, + INSN_NOP_M, + tcg_opc_l2 (desc[1]), + tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2, TCG_REG_R1, desc[1])); +disp = (desc[0] - (uintptr_t)s-code_ptr) 4; +tcg_out_bundle(s, mLX, + INSN_NOP_M, + tcg_opc_l4 (disp), + tcg_opc_x4 (TCG_REG_P0, OPC_BRL_CALL_SPTK_MANY_X4, + TCG_REG_B0, disp)); +} + +static inline void tcg_out_callr(TCGContext *s, TCGReg addr) { tcg_out_bundle(s, MmI, tcg_opc_m1 (TCG_REG_P0, OPC_LD8_M1, TCG_REG_R2, addr), @@ -2002,7 +2030,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_br(s, args[0]); break; case INDEX_op_call: -tcg_out_call(s, args[0]); +if (likely(const_args[0])) { +tcg_out_calli(s, args[0]); +} else { +tcg_out_callr(s, args[0]); +} break; case INDEX_op_goto_tb: tcg_out_goto_tb(s, args[0]); @@ -2255,7 +2287,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, static const TCGTargetOpDef ia64_op_defs[] = { { INDEX_op_br, { } }, -{ INDEX_op_call, { r } }, +{ INDEX_op_call, { ri } }, { INDEX_op_exit_tb, { } }, { INDEX_op_goto_tb, { } }, -- 1.8.3.1
Re: [Qemu-devel] [RFC PATCH 4/6] Makefile: introduce common-obj-m and block-obj-m for DSO
On Fri, 09/06 00:20, Richard Henderson wrote: On 09/05/2013 10:53 PM, Fam Zheng wrote: OK. Thanks for pointing out. The problem with ar file is that --whole-archive needs to be done specificly to modules .a, other libs shouldn't be linked with this flag. See also: --whole-archive foo.a --no-whole-archive Yes, this is a way to do it, but will complicates the link command, and may be more error prone. I expanded foo.mo to its contained .o for static linking in the next revision that's coming up. Thanks, Fam
Re: [Qemu-devel] [RFC] qcow2 journalling draft
Am 05.09.2013 um 17:26 hat Benoît Canet geschrieben: Le Thursday 05 Sep 2013 à 11:24:40 (+0200), Stefan Hajnoczi a écrit : On Wed, Sep 04, 2013 at 11:55:23AM +0200, Benoît Canet wrote: I'm not sure if multiple journals will work in practice. Doesn't this re-introduce the need to order update steps and flush between them? This is a question for Benoît, who made this requirement. I asked him the same a while ago and apparently his explanation made some sense to me, or I would have remembered that I don't want it. ;-) The reason behind the multiple journal requirement is that if a block get created and deleted in a cyclic way it can generate cyclic insertions/deletions journal entries. The journal could easilly be filled if this pathological corner case happen. When it happen the dedup code repack the journal by writting only the non redundant information into a new journal and then use the new one. It would not be easy to do so if non dedup journal entries are present in the journal hence the multiple journal requirement. The deduplication also need two journals because when the first one is frozen it take some time to write the hash table to disk and anyway new entries must be stored somewhere at the same time. The code cannot block. It might have something to do with the fact that deduplication uses the journal more as a kind of cache for hash values that can be dropped and rebuilt after a crash. For dedupe the journal is more a resume after exit tool. I'm not sure anymore if dedupe needs the same kind of journal as a metadata journal for qcow2. Since you have a dirty flag to discard the journal on crash, the journal is not used for data integrity. That makes me wonder if the metadata journal is the right structure for dedupe? Maybe your original proposal was fine for dedupe and we just misinterpreted it because we thought this needs to be a safe journal. Kevin what do you think of this ? I could strip down the dedupe journal code to specialize it. If you think it turns out easier than using the journalling infrastructure that we're going to implement anyway, then why not. Kevin
[Qemu-devel] [RFC PATCH v2 1/6] make.rule: fix $(obj) to a real relative path
Makefile.target includes rule.mak and unnested common-obj-y, then prefix them with '../', this will ignore object specific QEMU_CFLAGS in subdir Makefile.objs: $(obj)/curl.o: QEMU_CFLAGS += $(CURL_CFLAGS) Because $(obj) here is './block', instead of '../block'. This doesn't hurt compiling because we basically build all .o from top Makefile, before entering Makefile.target, but it will affact arriving per-object libs support. The starting point of $(obj) is fixed in $(obj-base) before including ./Makefile.objs, to get consistency with nested Makefile rules in target rule and variable definition. Signed-off-by: Fam Zheng f...@redhat.com --- Makefile.target | 3 ++- rules.mak | 7 --- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile.target b/Makefile.target index 9a49852..0ab60bd 100644 --- a/Makefile.target +++ b/Makefile.target @@ -144,12 +144,13 @@ endif # CONFIG_SOFTMMU %/translate.o: QEMU_CFLAGS += $(TRANSLATE_OPT_CFLAGS) nested-vars += obj-y +obj-base := .. # This resolves all nested paths, so it must come last include $(SRC_PATH)/Makefile.objs all-obj-y = $(obj-y) -all-obj-y += $(addprefix ../, $(common-obj-y)) +all-obj-y += $(addprefix $(obj)/, $(common-obj-y)) ifndef CONFIG_HAIKU LIBS+=-lm diff --git a/rules.mak b/rules.mak index 4499745..eef1b71 100644 --- a/rules.mak +++ b/rules.mak @@ -103,7 +103,7 @@ clean: clean-timestamp # magic to descend into other directories -obj := . +obj = $(obj-base) old-nested-dirs := define push-var @@ -119,9 +119,10 @@ endef define unnest-dir $(foreach var,$(nested-vars),$(call push-var,$(var),$1/)) -$(eval obj := $(obj)/$1) +$(eval old-obj := $(obj)) +$(eval obj := $(if $(obj),$(obj)/$1,$1)) $(eval include $(SRC_PATH)/$1/Makefile.objs) -$(eval obj := $(patsubst %/$1,%,$(obj))) +$(eval obj := $(old-obj)) $(foreach var,$(nested-vars),$(call pop-var,$(var),$1/)) endef -- 1.8.3.1
[Qemu-devel] [RFC PATCH v2 2/6] rule.mak: allow per object cflags and libs
Adds extract-libs in LINK to expand any per object libs, the syntax to define such a libs options is like: $(obj)/curl.o-libs = $(CURL_LIBS) in block/Makefile.objs. Similarly, $(obj)foo.o-cflags = $(FOO_CFLAGS) is also supported. Signed-off-by: Fam Zheng f...@redhat.com --- rules.mak | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rules.mak b/rules.mak index eef1b71..e581d55 100644 --- a/rules.mak +++ b/rules.mak @@ -17,15 +17,17 @@ QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d # Same as -I$(SRC_PATH) -I., but for the nested source/object directories QEMU_INCLUDES += -I$(D) -I$(@D) +extract-libs = $(strip $(foreach o,$1,$($(obj-base)$o-libs))) + %.o: %.c - $(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $, CC$(TARGET_DIR)$@) + $(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $, CC$(TARGET_DIR)$@) %.o: %.rc $(call quiet-command,$(WINDRES) -I. -o $@ $, RC$(TARGET_DIR)$@) ifeq ($(LIBTOOL),) LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \ $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \ - $(LIBS), LINK $(TARGET_DIR)$@) + $(call extract-libs,$^) $(LIBS), LINK $(TARGET_DIR)$@) else LIBTOOL += $(if $(V),,--quiet) %.lo: %.c @@ -41,7 +43,7 @@ LINK = $(call quiet-command,\ $(sort $(filter %.o, $1)) $(filter-out %.o, $1) \ $(if $(filter %.lo %.la,$^),$(version-lobj-y),$(version-obj-y)) \ $(if $(filter %.lo %.la,$^),$(LIBTOOLFLAGS)) \ - $(LIBS),$(if $(filter %.lo %.la,$^),lt LINK , LINK )$(TARGET_DIR)$@) + $(call extract-libs,$^) $(LIBS),$(if $(filter %.lo %.la,$^),lt LINK , LINK )$(TARGET_DIR)$@) endif %.asm: %.S -- 1.8.3.1
[Qemu-devel] [RFC PATCH v2 0/6] Shared Library Module Support
This series implements feature of shared object building as described in: http://wiki.qemu.org/Features/Modules It's achieved in three steps, with extra bonus to change curl and qed to a shared library module in the end (only to demonstrate the usage, no make install support of .so files yet). v2: inline below 1. Allow per object cflags and libs: [01/06] make.rule: fix $(obj) to a real relative path Slightly changed, added $(obj-base) to work with module dependency variable expansion. [02/06] rule.mak: allow per object cflags and libs 2. Rules for building .so: [03/06] Makefile: introduce common-obj-m and block-obj-m for DSO [Richard] Change some rule generation and don't use ln -r to for intermediate object. 3. Code to load module. All .so files are scanned and loaded when program starts: [04/06] module: implement module loading function [mjt] Don't load all .so unconditionally, subsystem call module_load for specific type. [Lluís] Used configure time prefix as the module base directory. 4. curl and qed adoption: [05/06] curl: build as shared library [06/06] qed: build as shared library Added to demostrate how to write multi-file module. Fam Zheng (6): make.rule: fix $(obj) to a real relative path rule.mak: allow per object cflags and libs Makefile: introduce common-obj-m and block-obj-m for DSO module: implement module loading function curl: build as shared library qed: build as shared library Makefile | 32 --- Makefile.objs | 14 +- Makefile.target | 3 ++- block.c | 1 + block/Makefile.objs | 7 --- bsd-user/main.c | 3 +++ configure | 28 +++ include/qemu/module.h | 9 + linux-user/main.c | 3 +++ qemu-img.c| 1 + rules.mak | 25 +++-- scripts/create_config | 4 ui/console.c | 1 + util/Makefile.objs| 2 ++ util/module.c | 52 +++ vl.c | 2 ++ 16 files changed, 161 insertions(+), 26 deletions(-) -- 1.8.3.1
[Qemu-devel] [RFC PATCH v2 3/6] Makefile: introduce common-obj-m and block-obj-m for DSO
Add necessary rules and flags for shared object generation. $(common-obj-m) will include $(block-obj-m), like $(common-obj-y) does for $(block-obj-y). The new rules introduced here are: 0) For all %.so compiling: QEMU_CFLAGS += -shared -fPIC 1) %.o in $(common-obj-m) is compiled to %.o, with QEMU_CFLAGS += -shared -fPIC. Then linked to %.so. 2) %.mo in $(common-obj-m) is the placeholder for %.so for pattern matching in Makefile. It's linked to -shared with all its dependencies (multiple *.o) as input. Which means the list of depended objects must be ruled out in each sub-Makefile.objs with an variable: $(obj)/foo.mo-obj := $(addprefix $(obj)/,bar.o baz.o qux.o) Notice that $(obj)/ is required for both target and dependency in the rule. DSO suffix (.so) is configure variable (.dll for Windows). Signed-off-by: Fam Zheng f...@redhat.com --- Makefile | 32 +--- Makefile.objs | 14 +- configure | 3 +++ rules.mak | 10 ++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 806946e..cf47ea9 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ Makefile: ; configure: ; .PHONY: all clean cscope distclean dvi html info install install-doc \ - pdf recurse-all speed test dist + pdf recurse-all speed test dist modules $(call set-vpath, $(SRC_PATH)) @@ -121,7 +121,30 @@ ifeq ($(CONFIG_SMARTCARD_NSS),y) include $(SRC_PATH)/libcacard/Makefile endif -all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all +all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules + +mod-obj-m = $(patsubst %.o,%$(DSOSUF),$(filter %.o,$(common-obj-m))) \ +$(patsubst %.mo,%$(DSOSUF),$(filter %.mo,$(common-obj-m))) + +# Generate rules for single file modules (%.so: %.o). +$(foreach o,$(filter %.o,$(common-obj-m)),$(eval \ + $(patsubst %.o,%.so,$o): $o )) + +# For multi file modules, dependencies should be listed explicitly in +# Makefile.objs as +# $(obj)/foo.mo-obj := $(obj)/bar.o $(obj)/biz.o +$(foreach o,$(filter %.mo,$(mod-obj-m)),$(eval \ + $o: $($o-obj))) + +%.mo: + $(if $(BUILD_DYNAMIC), \ + $(call quiet-command,$(CC) $(sort $^) -shared -o $@, LD[M] $(TARGET_DIR)$@), \ + $(call quiet-command,$(AR) rcs $@ $(sort $^), AR $(TARGET_DIR)$@)) + + +modules: $(mod-obj-m) +modules: BUILD_DYNAMIC = 1 +modules: QEMU_CFLAGS += -shared -fPIC config-host.h: config-host.h-timestamp config-host.h-timestamp: config-host.mak @@ -155,7 +178,7 @@ subdir-dtc:dtc/libfdt dtc/tests dtc/%: mkdir -p $@ -$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) +$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) $(common-obj-m) ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS)) romsubdir-%: @@ -235,6 +258,9 @@ clean: rm -f qemu-options.def find . -name '*.[oda]' -type f -exec rm -f {} + find . -name '*.l[oa]' -type f -exec rm -f {} + + find . -name '*'$(DSOSUF) -type f -exec rm -f {} + + find . -name '*.mo' -type f -exec rm -f {} + + rm -f $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ rm -Rf .libs rm -f qemu-img-cmds.h diff --git a/Makefile.objs b/Makefile.objs index f46a4cd..8984a20 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -19,6 +19,8 @@ block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o block-obj-y += qemu-coroutine-sleep.o block-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o +block-obj-m = block/ + ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy) # Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add. # only pull in the actual virtio-9p device if we also enabled virtio. @@ -83,6 +85,9 @@ common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y) common-obj-y += qmp-marshal.o common-obj-y += qmp.o hmp.o + +common-obj-m = $(block-obj-m) + endif ## @@ -121,5 +126,12 @@ nested-vars += \ util-obj-y \ qga-obj-y \ block-obj-y \ - common-obj-y + block-obj-m \ + common-obj-y \ + common-obj-m + dummy := $(call unnest-vars) + +# static linked mods are expanded to .o list +dummy := $(call expand-mod-obj,common-obj-y) +dummy := $(call expand-mod-obj,block-obj-y) diff --git a/configure b/configure index af6b048..75abb87 100755 --- a/configure +++ b/configure @@ -190,6 +190,7 @@ mingw32=no gcov=no gcov_tool=gcov EXESUF= +DSOSUF=.so prefix=/usr/local mandir=\${prefix}/share/man datadir=\${prefix}/share @@ -584,6 +585,7 @@ fi if test $mingw32 = yes ; then EXESUF=.exe + DSOSUF=.dll QEMU_CFLAGS=-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS # enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later) QEMU_CFLAGS=-D__USE_MINGW_ANSI_STDIO=1 $QEMU_CFLAGS @@ -4175,6 +4177,7 @@ echo LIBTOOLFLAGS=$LIBTOOLFLAGS $config_host_mak echo LIBS+=$LIBS $config_host_mak echo
[Qemu-devel] [RFC PATCH v2 4/6] module: implement module loading function
Added three types of modules: typedef enum { MODULE_LOAD_BLOCK = 0, MODULE_LOAD_UI, MODULE_LOAD_NET, MODULE_LOAD_MAX, } module_load_type; and their loading function: void module_load(module_load_type). which loads all .so files in a subdir under ${PREFIX}/qemu/, e.g. /usr/lib/qemu/block. Modules of each type should be loaded before respective subsystem initialization code. Requires gmodule-2.0 from glib. Signed-off-by: Fam Zheng f...@redhat.com --- block.c | 1 + bsd-user/main.c | 3 +++ configure | 20 +++- include/qemu/module.h | 9 + linux-user/main.c | 3 +++ qemu-img.c| 1 + scripts/create_config | 4 ui/console.c | 1 + util/Makefile.objs| 2 ++ util/module.c | 52 +++ vl.c | 2 ++ 11 files changed, 89 insertions(+), 9 deletions(-) diff --git a/block.c b/block.c index a387c1a..49ab0ce 100644 --- a/block.c +++ b/block.c @@ -4009,6 +4009,7 @@ BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs, void bdrv_init(void) { +module_load(MODULE_LOAD_BLOCK); module_call_init(MODULE_INIT_BLOCK); } diff --git a/bsd-user/main.c b/bsd-user/main.c index f9246aa..6cb9e35 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -33,6 +33,7 @@ #include tcg.h #include qemu/timer.h #include qemu/envlist.h +#include qemu/module.h int singlestep; #if defined(CONFIG_USE_GUEST_BASE) @@ -749,6 +750,8 @@ int main(int argc, char **argv) if (argc = 1) usage(); +module_load(MODULE_LOAD_UI); +module_load(MODULE_LOAD_NET); module_call_init(MODULE_INIT_QOM); if ((envlist = envlist_create()) == NULL) { diff --git a/configure b/configure index 75abb87..7fec1c7 100755 --- a/configure +++ b/configure @@ -2249,15 +2249,17 @@ if test $mingw32 = yes; then else glib_req_ver=2.12 fi -if $pkg_config --atleast-version=$glib_req_ver gthread-2.0 /dev/null 21 -then -glib_cflags=`$pkg_config --cflags gthread-2.0 2/dev/null` -glib_libs=`$pkg_config --libs gthread-2.0 2/dev/null` -LIBS=$glib_libs $LIBS -libs_qga=$glib_libs $libs_qga -else -error_exit glib-$glib_req_ver required to compile QEMU -fi +for i in gthread-2.0 gmodule-2.0; do +if $pkg_config --atleast-version=$glib_req_ver $i /dev/null 21 +then +glib_cflags=`$pkg_config --cflags $i 2/dev/null` +glib_libs=`$pkg_config --libs $i 2/dev/null` +LIBS=$glib_libs $LIBS +libs_qga=$glib_libs $libs_qga +else +error_exit glib-$glib_req_ver required to compile QEMU +fi +done ## # pixman support probe diff --git a/include/qemu/module.h b/include/qemu/module.h index c4ccd57..f00bc25 100644 --- a/include/qemu/module.h +++ b/include/qemu/module.h @@ -37,4 +37,13 @@ void register_module_init(void (*fn)(void), module_init_type type); void module_call_init(module_init_type type); +typedef enum { +MODULE_LOAD_BLOCK = 0, +MODULE_LOAD_UI, +MODULE_LOAD_NET, +MODULE_LOAD_MAX, +} module_load_type; + +void module_load(module_load_type type); + #endif diff --git a/linux-user/main.c b/linux-user/main.c index 03859bc..9cbac14 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -34,6 +34,7 @@ #include qemu/timer.h #include qemu/envlist.h #include elf.h +#include qemu/module.h char *exec_path; @@ -3547,6 +3548,8 @@ int main(int argc, char **argv, char **envp) int i; int ret; +module_load(MODULE_LOAD_UI); +module_load(MODULE_LOAD_NET); module_call_init(MODULE_INIT_QOM); qemu_cache_utils_init(envp); diff --git a/qemu-img.c b/qemu-img.c index b9a848d..063e6bf 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -34,6 +34,7 @@ #include getopt.h #include stdio.h #include stdarg.h +#include qemu/module.h #ifdef _WIN32 #include windows.h diff --git a/scripts/create_config b/scripts/create_config index b1adbf5..7a54f2d 100755 --- a/scripts/create_config +++ b/scripts/create_config @@ -25,6 +25,7 @@ case $line in prefix=*) # save for the next definitions prefix=${line#*=} +echo #define CONFIG_PREFIX \$prefix\ ;; CONFIG_AUDIO_DRIVERS=*) drivers=${line#*=} @@ -104,6 +105,9 @@ case $line in value=${line#*=} echo #define $name $value ;; + DSOSUF=*) +echo #define HOST_DSOSUF \${line#*=}\ +;; esac done # read diff --git a/ui/console.c b/ui/console.c index aad4fc9..ad90950 100644 --- a/ui/console.c +++ b/ui/console.c @@ -27,6 +27,7 @@ #include qemu/timer.h #include qmp-commands.h #include sysemu/char.h +#include qemu/module.h //#define DEBUG_CONSOLE #define DEFAULT_BACKSCROLL 512 diff --git a/util/Makefile.objs b/util/Makefile.objs index dc72ab0..33e56b0 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -11,3 +11,5 @@ util-obj-y += iov.o aes.o qemu-config.o qemu-sockets.o uri.o notify.o
[Qemu-devel] [RFC PATCH v2 5/6] curl: build as shared library
Curl block driver is built as shared object module when enabled. We have per object cflags and libs support now, move CURL_CFLAGS and CURL_LIBS from global option variables to a per object basis. make install is not installing it yet, manually copy it to ${prefix}/qemu/block/curl.so to make it loaded. Signed-off-by: Fam Zheng f...@redhat.com --- block/Makefile.objs | 3 ++- configure | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/block/Makefile.objs b/block/Makefile.objs index 4cf9aa4..b1e1520 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -23,4 +23,5 @@ common-obj-y += commit.o common-obj-y += mirror.o common-obj-y += backup.o -$(obj)/curl.o: QEMU_CFLAGS+=$(CURL_CFLAGS) +$(obj)/curl.o-cflags := $(CURL_CFLAGS) +$(obj)/curl.o-libs := $(CURL_LIBS) diff --git a/configure b/configure index 7fec1c7..4adc267 100755 --- a/configure +++ b/configure @@ -2210,8 +2210,6 @@ EOF curl_libs=`$curlconfig --libs 2/dev/null` if compile_prog $curl_cflags $curl_libs ; then curl=yes -libs_tools=$curl_libs $libs_tools -libs_softmmu=$curl_libs $libs_softmmu else if test $curl = yes ; then feature_not_found curl @@ -3889,8 +3887,9 @@ if test $bswap_h = yes ; then echo CONFIG_MACHINE_BSWAP_H=y $config_host_mak fi if test $curl = yes ; then - echo CONFIG_CURL=y $config_host_mak + echo CONFIG_CURL=m $config_host_mak echo CURL_CFLAGS=$curl_cflags $config_host_mak + echo CURL_LIBS=$curl_libs $config_host_mak fi if test $brlapi = yes ; then echo CONFIG_BRLAPI=y $config_host_mak -- 1.8.3.1
[Qemu-devel] [RFC PATCH v2 6/6] qed: build as shared library
Another example of DSO build but with multiple files in a module. Signed-off-by: Fam Zheng f...@redhat.com --- block/Makefile.objs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/Makefile.objs b/block/Makefile.objs index b1e1520..4cb2ab9 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -1,7 +1,6 @@ block-obj-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o -block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o -block-obj-y += qed-check.o +block-obj-m += qed.mo block-obj-y += vhdx.o block-obj-y += parallels.o blkdebug.o blkverify.o block-obj-y += snapshot.o qapi.o @@ -25,3 +24,4 @@ common-obj-y += backup.o $(obj)/curl.o-cflags := $(CURL_CFLAGS) $(obj)/curl.o-libs := $(CURL_LIBS) +$(obj)/qed.mo-obj := $(addprefix $(obj)/,qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o qed-check.o) -- 1.8.3.1
Re: [Qemu-devel] [PATCH v2 3/3] audio: remove CONFIG_MIXEMU configure option and enable mixemu by default
On Do, 2013-09-05 at 18:24 -0400, Bandan Das wrote: Set mixer property to on by default. The by default in the commit message is a bit misleading. There is no default any more once CONFIG_MIXEMU is gone ... Also, always include two versions of devices (with and without mixemu) so that user can select one of them at runtime. That applies to hda audio only, and it's patch #2 actually implementing that (for the CONFIG_MIXEMU=y case). cheers, Gerd
Re: [Qemu-devel] Block Filters
Am 05.09.2013 um 19:29 hat Benoît Canet geschrieben: Le Thursday 05 Sep 2013 à 18:18:45 (+0800), Fam Zheng a écrit : On Thu, 09/05 12:01, Stefan Hajnoczi wrote: On Wed, Sep 04, 2013 at 08:15:36PM +0200, Benoît Canet wrote: Propagate operations like snapshot down the tree. block.c is designed for bs-file/bs-backing_hd kind of BlockDrivers, perhaps it needs to become a bit more generic to support other types of BlockDrivers properly. Shouldn't bs-backing_hd become bs-children[0] and bs-file stay the same ? bs-backing_hd and bs-file exist so that block.c can implement generic functionality shared by a lot of block drivers. They are for code reuse. Many places in the block layer have come to assume that there is only one -file, for example. That's not true for quorum or even vmdk. If we forget about code reuse for a second, and just think of BDS trees, then both -backing_hd and -file should be in -children[]. I think the problem we have is that too much of QEMU uses -file and -backing_hd. It's kind of baked in now to the point where more flexible block drivers like quorum are hard to represent. -backing_hd and -file are mostly image format concepts. Filters and protocols could do without them. After saying all that, I don't have a design that makes everything better :P. Maybe we could start from a generic scheme and add specific operations upon: I propose we let bs-children[] keep all the node connections, including backing_hd and file, then leave the BlockDriver, BlockFilter or BlockProtocol to implement -get_backing_hd(), -get_file_hd(), or even -get_files(), or mark an operation as NULL. These operations give semantics to its children (of course they need some semantics to actually be useful), but it's orthogonal to management of elements in the object tree. So would bs-children[] be manipulated directly by each BlockDriver, BlockFilter BlockProtocol implying the their code have an exact knowledge of the index of each bs in bs-children[] ? I think the driver implementation is the only one who know how to do it. Is creating external snapshots still the only use case for bs-children[] in the generic block layer? Because if so, we could indeed rather move the snapshotting operation into the BlockDrivers. Oh, and why are you talking about BlockDriver, BlockFilter, BlockProtocol? What's the difference between them and why isn't the one BlockDriver struct that we have today enough any more? Kevin
Re: [Qemu-devel] Block Filters
On Fri, 09/06 09:42, Kevin Wolf wrote: Am 05.09.2013 um 19:29 hat Benoît Canet geschrieben: Le Thursday 05 Sep 2013 à 18:18:45 (+0800), Fam Zheng a écrit : On Thu, 09/05 12:01, Stefan Hajnoczi wrote: On Wed, Sep 04, 2013 at 08:15:36PM +0200, Benoît Canet wrote: Propagate operations like snapshot down the tree. block.c is designed for bs-file/bs-backing_hd kind of BlockDrivers, perhaps it needs to become a bit more generic to support other types of BlockDrivers properly. Shouldn't bs-backing_hd become bs-children[0] and bs-file stay the same ? bs-backing_hd and bs-file exist so that block.c can implement generic functionality shared by a lot of block drivers. They are for code reuse. Many places in the block layer have come to assume that there is only one -file, for example. That's not true for quorum or even vmdk. If we forget about code reuse for a second, and just think of BDS trees, then both -backing_hd and -file should be in -children[]. I think the problem we have is that too much of QEMU uses -file and -backing_hd. It's kind of baked in now to the point where more flexible block drivers like quorum are hard to represent. -backing_hd and -file are mostly image format concepts. Filters and protocols could do without them. After saying all that, I don't have a design that makes everything better :P. Maybe we could start from a generic scheme and add specific operations upon: I propose we let bs-children[] keep all the node connections, including backing_hd and file, then leave the BlockDriver, BlockFilter or BlockProtocol to implement -get_backing_hd(), -get_file_hd(), or even -get_files(), or mark an operation as NULL. These operations give semantics to its children (of course they need some semantics to actually be useful), but it's orthogonal to management of elements in the object tree. So would bs-children[] be manipulated directly by each BlockDriver, BlockFilter BlockProtocol implying the their code have an exact knowledge of the index of each bs in bs-children[] ? I think the driver implementation is the only one who know how to do it. Is creating external snapshots still the only use case for bs-children[] in the generic block layer? Because if so, we could indeed rather move the snapshotting operation into the BlockDrivers. Oh, and why are you talking about BlockDriver, BlockFilter, BlockProtocol? What's the difference between them and why isn't the one BlockDriver struct that we have today enough any more? I used the terms with their functional type in mind, didn't mean it's a actual struct in code, they are just block drivers that implement these functions. Fam
Re: [Qemu-devel] Block Filters
On Tue, 09/03 18:24, Benoît Canet wrote: Hello list, I am thinking about QEMU block filters lately. I am not a block.c/blockdev.c expert so tell me what you think of the following. The use cases I see would be: -$user want to have some real cryptography on top of qcow2/qed or another format. snapshots and other block features should continue to work -$user want to use a raid like feature like QUORUM in QEMU. other features should continue to work -$user want to use the future SSD deduplication implementation with metadata on SSD and data on spinning disks. other features should continue to work -$user want to I/O throttle one drive of his vm. -$user want to do Copy On Read -$user want to do a combination of the above -$developer want to make the minimum of required steps to keep changes small -$developer want to keep user interface changes for later Lets take a example case of an user wanting to do I/O throttled encrypted QUORUM on top of QCOW2. Assuming we want to implement throttle and encryption as something remotely being like a block filter this makes a pretty complex BlockDriverState tree. The tree would look like the following: I/O throttling BlockDriverState (bs) | | | | Encryption BlockDriverState (bs) | | | | Quorum BlockDriverState (bs) / | \ /|\ / | \ / | \ QCOW2 bs QCOW2 b s QCOW2 bs | | | | | | | | | | | | RAW bs RAW bs RAW bs An external snapshot should result in a tree like the following. I/O throttling BlockDriverState (bs) | | | | Encryption BlockDriverState (bs) | | | | Quorum BlockDriverState (bs) / | \ /|\ / | \ / | \ QCOW2 bs QCOW2 bs QCOW2 bs | | | | | | | | | | | | QCOW2 bs QCOW2 bs QCOW2 bs | | | | | | | | | | | | RAW bs RAW bs RAW bs In the current state of QEMU we can code some block drivers to implement this tree. However when doing operations like snapshots blockdev.c would have no real idea of what should be snapshotted and how. (The 3 top bs should be kept on top) Moreover it would have no way to manipulate easily this tree of BlockDriverState has each one is encapsulated in it's parent. Also there no generic way to tell the block layer that two or more BlockDriverState are siblings. The current mail is here to propose some additionals structures in order to cope with these problems. The overall strategy of the proposed structures is to push out the BlockDriverStates relationships out of each BlockDriverState. The idea is that it would make it easier for the block layer to manipulate a well known structure instead of being forced to enter into each BlockDriverState specificity. The first structure is the BlockStackNode. The BlockStateNode would be used to represent the relationship between the various BlockDriverStates struct BlockStackNode { BlockDriverState *bs; /* the BlockDriverState holded by this node */ /* this doubly linked list entry points to the child node and the parent * node */ QLIST_ENTRY(BlockStateNode) down; /* This doubly linked list entry point to the siblings of this node */ QLIST_ENTRY(BlockStateNode) siblings; /* a hash or an array of the sibbling of this node for fast access * should be recomputed when updating the tree */ QHASH_ENTRYBlockStateNode, index
[Qemu-devel] [PATCH v2] spapr-rtas: use softmmu for accessing rtas call parameters
On the real hardware, RTAS is called in real mode and therefore ignores top 4 bits of the address passed in the call. This fixes QEMU to use softmmu which can chop top 4 bits if MSR DR is not set. Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru --- Changes: v2: * masking from replaced with the use of cpu_ldl_data which can handle realmode case properly --- hw/ppc/spapr_hcall.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 063bd36..30f90bf 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -4,6 +4,7 @@ #include hw/ppc/spapr.h #include mmu-hash64.h #include cpu-models.h +#include exec/softmmu_exec.h #include libfdt.h @@ -523,10 +524,11 @@ static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr, static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { +CPUPPCState *env = cpu-env; target_ulong rtas_r3 = args[0]; -uint32_t token = ldl_be_phys(rtas_r3); -uint32_t nargs = ldl_be_phys(rtas_r3 + 4); -uint32_t nret = ldl_be_phys(rtas_r3 + 8); +uint32_t token = cpu_ldl_data(env, rtas_r3); +uint32_t nargs = cpu_ldl_data(env, rtas_r3 + 4); +uint32_t nret = cpu_ldl_data(env, rtas_r3 + 8); return spapr_rtas_call(cpu, spapr, token, nargs, rtas_r3 + 12, nret, rtas_r3 + 12 + 4*nargs); -- 1.8.4.rc4
Re: [Qemu-devel] [RFC PATCH 4/6] Makefile: introduce common-obj-m and block-obj-m for DSO
Il 05/09/2013 23:45, Peter Maydell ha scritto: On 5 September 2013 20:41, Paolo Bonzini pbonz...@redhat.com wrote: Libtool used to be really bad, but most performance problems have been solved. How about the it silently creates things in dot-directories, recompiles things at random times when it really shouldn't, and is an enormous insane shell script problems? The positives would have to be really really strong before we let libtool into the codebase... How about we'd break compilation on your favorite OS? :) Darwin ld doesn't support --whole-archive, it needs a different incantation. Relatively recent Solaris now has it, but Apple still holds the bastions. Paolo
Re: [Qemu-devel] Block Filters
Am 06.09.2013 um 09:56 hat Fam Zheng geschrieben: On Tue, 09/03 18:24, Benoît Canet wrote: Hello list, I am thinking about QEMU block filters lately. I am not a block.c/blockdev.c expert so tell me what you think of the following. The use cases I see would be: -$user want to have some real cryptography on top of qcow2/qed or another format. snapshots and other block features should continue to work -$user want to use a raid like feature like QUORUM in QEMU. other features should continue to work -$user want to use the future SSD deduplication implementation with metadata on SSD and data on spinning disks. other features should continue to work -$user want to I/O throttle one drive of his vm. -$user want to do Copy On Read -$user want to do a combination of the above -$developer want to make the minimum of required steps to keep changes small -$developer want to keep user interface changes for later Lets take a example case of an user wanting to do I/O throttled encrypted QUORUM on top of QCOW2. Assuming we want to implement throttle and encryption as something remotely being like a block filter this makes a pretty complex BlockDriverState tree. The tree would look like the following: I/O throttling BlockDriverState (bs) | | | | Encryption BlockDriverState (bs) | | | | Quorum BlockDriverState (bs) / | \ /|\ / | \ / | \ QCOW2 bs QCOW2 b s QCOW2 bs | | | | | | | | | | | | RAW bs RAW bs RAW bs An external snapshot should result in a tree like the following. I/O throttling BlockDriverState (bs) | | | | Encryption BlockDriverState (bs) | | | | Quorum BlockDriverState (bs) / | \ /|\ / | \ / | \ QCOW2 bs QCOW2 bs QCOW2 bs | | | | | | | | | | | | QCOW2 bs QCOW2 bs QCOW2 bs | | | | | | | | | | | | RAW bs RAW bs RAW bs In the current state of QEMU we can code some block drivers to implement this tree. However when doing operations like snapshots blockdev.c would have no real idea of what should be snapshotted and how. (The 3 top bs should be kept on top) Moreover it would have no way to manipulate easily this tree of BlockDriverState has each one is encapsulated in it's parent. Also there no generic way to tell the block layer that two or more BlockDriverState are siblings. The current mail is here to propose some additionals structures in order to cope with these problems. The overall strategy of the proposed structures is to push out the BlockDriverStates relationships out of each BlockDriverState. The idea is that it would make it easier for the block layer to manipulate a well known structure instead of being forced to enter into each BlockDriverState specificity. The first structure is the BlockStackNode. The BlockStateNode would be used to represent the relationship between the various BlockDriverStates struct BlockStackNode { BlockDriverState *bs; /* the BlockDriverState holded by this node */ /* this doubly linked list entry points to the child node and the parent * node */ QLIST_ENTRY(BlockStateNode) down; /* This doubly linked list entry point to the siblings of this node */
Re: [Qemu-devel] [PATCH v2] spapr-rtas: use softmmu for accessing rtas call parameters
On 06.09.2013, at 10:10, Alexey Kardashevskiy wrote: On the real hardware, RTAS is called in real mode and therefore ignores top 4 bits of the address passed in the call. This fixes QEMU to use softmmu which can chop top 4 bits if MSR DR is not set. Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru --- Changes: v2: * masking from replaced with the use of cpu_ldl_data which can handle realmode case properly --- hw/ppc/spapr_hcall.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 063bd36..30f90bf 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -4,6 +4,7 @@ #include hw/ppc/spapr.h #include mmu-hash64.h #include cpu-models.h +#include exec/softmmu_exec.h #include libfdt.h @@ -523,10 +524,11 @@ static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr, static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { +CPUPPCState *env = cpu-env; target_ulong rtas_r3 = args[0]; -uint32_t token = ldl_be_phys(rtas_r3); -uint32_t nargs = ldl_be_phys(rtas_r3 + 4); -uint32_t nret = ldl_be_phys(rtas_r3 + 8); +uint32_t token = cpu_ldl_data(env, rtas_r3); +uint32_t nargs = cpu_ldl_data(env, rtas_r3 + 4); +uint32_t nret = cpu_ldl_data(env, rtas_r3 + 8); Wow - this really aren't that many memory accesses. So looking through rtas calls that come after this dispatch, from what I see they mostly use rtas_ld and rtas_st. They are defined as static inline uint32_t rtas_ld(target_ulong phys, int n) { return ldl_be_phys(phys + 4*n); } static inline void rtas_st(target_ulong phys, int n, uint32_t val) { stl_be_phys(phys + 4*n, val); } which means we need to change them as well to make rtas subcall memory accesses resolve properly. Which brings me to my next question: Why don't we use rtas_ld in the 3 calls above? It looks like a perfect fit really. Also, just changing the call to cpu_ldl_data will potentially break I think. Imagine you do cpu_synchronize_state with DR=1 in a previous call. Now comes an RTAS call. Because you don't do a cpu_synchronize_state() call here, you will still have the DR=1 in MSR, accessing virtual memory at a potentially very low address that may not be mapped in. So before you do the cpu_ldl_data you need to either do cpu_synchronize_state() - which can be slow - or you need to manually change MSR.DR to 0 so that we end up accessing the correct memory location always. If you encapsulate that in rtas_ld and rtas_st it might end up looking quite simple: static inline uint32_t rtas_ld(CPUPPCState *env, target_ulong phys, int n) { uint32_t r; target_ulong msr = env-msr; /* Make sure we access RTAS data in guest real mode */ env-msr ~= MSR_DR; r = ldl_be_phys(phys + 4*n); env-msr = msr; return r; } Or if you think it's too complicated, you can simply make it static inline uint64_t ppc64_phys_to_real(uint64_t addr) { return addr ~0xF000ULL; } static inline uint32_t rtas_ld(target_ulong phys, int n) { return ldl_be_phys(ppc64_phys_to_real(phys) + 4*n); } All things considered, I might even prefer the latter solution as it makes the code flow more obvious. But I'll leave the final call to you. Alex
[Qemu-devel] [PATCH] qemu-xen: vt-d bugfix for pci rom
From 7d93370e8005499d18507b8cd9fa71f4ae794e19 Mon Sep 17 00:00:00 2001 From: Liu Jinsong jinsong@vt-nhm7.tsp.org Date: Fri, 6 Sep 2013 16:34:56 +0800 Subject: [PATCH] qemu-xen: vt-d bugfix for pci rom Remove incorrect memory_region_init_rom_device() from xen_pt_register_regions(), otherwise vt-d device with pci rom cannot pass through to hvm, since it trys to populate from normal ram for pci rom. Signed-off-by: Liu Jinsong jinsong@intel.com --- hw/xen_pt.c |2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/hw/xen_pt.c b/hw/xen_pt.c index 7aae826..b0bffdb 100644 --- a/hw/xen_pt.c +++ b/hw/xen_pt.c @@ -440,8 +440,6 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s) s-bases[PCI_ROM_SLOT].access.maddr = d-rom.base_addr; -memory_region_init_rom_device(s-rom, NULL, NULL, - xen-pci-pt-rom, d-rom.size); pci_register_bar(s-dev, PCI_ROM_SLOT, PCI_BASE_ADDRESS_MEM_PREFETCH, s-rom); -- 1.7.1 0001-qemu-xen-vt-d-bugfix-for-pci-rom.patch Description: 0001-qemu-xen-vt-d-bugfix-for-pci-rom.patch
Re: [Qemu-devel] [PATCH 1/2] qem-xen: add later wakeup logic when qemu wakeup
Stefano Stabellini wrote: On Tue, 3 Sep 2013, Liu, Jinsong wrote: Anthony PERARD wrote: On 01/09/13 10:51, Liu, Jinsong wrote: From 86ad3bb83a984ad7bbc00b81d6a0bfc1abc543ca Mon Sep 17 00:00:00 2001 From: Liu Jinsong jinsong@intel.com Date: Sun, 1 Sep 2013 23:39:14 +0800 Subject: [PATCH 1/2] qemu-xen: add later wakeup logic when qemu wakeup Currently HVM S3 has a bug coming from the difference between qemu-traditioanl and qemu-xen. For qemu-traditional, the way to resume from hvm s3 is via 'xl trigger' command. However, for qemu-xen, the way to resume from hvm s3 inherited from standard qemu, i.e. via QMP, and it doesn't work under Xen. The root cause is, for qemu-xen, 'xl trigger' command didn't reset devices, while QMP didn't unpause hvm domain though they did qemu system reset. We have two qemu-xen patches and one xl patch to fix the HVM S3 bug. This patch is the qemu-xen patch 1. It provides a later wakeup notifier and a register function, and notifies the later wakeup list when qemu wakup by 'xl trigger' command. Signed-off-by: Liu Jinsong jinsong@intel.com --- sysemu.h |1 + vl.c |8 2 files changed, 9 insertions(+), 0 deletions(-) diff --git a/sysemu.h b/sysemu.h index b71f244..4dbcab7 100644 --- a/sysemu.h +++ b/sysemu.h @@ -49,6 +49,7 @@ void qemu_register_suspend_notifier(Notifier *notifier); void qemu_system_wakeup_request(WakeupReason reason); void qemu_system_wakeup_enable(WakeupReason reason, bool enabled); void qemu_register_wakeup_notifier(Notifier *notifier); +void qemu_register_later_wakeup_notifier(Notifier *notifier); void qemu_system_shutdown_request(void); void qemu_system_powerdown_request(void); void qemu_register_powerdown_notifier(Notifier *notifier); diff --git a/vl.c b/vl.c index 5314f55..1c4842d 100644 --- a/vl.c +++ b/vl.c @@ -1478,6 +1478,8 @@ static NotifierList suspend_notifiers = NOTIFIER_LIST_INITIALIZER(suspend_notifiers); static NotifierList wakeup_notifiers = NOTIFIER_LIST_INITIALIZER(wakeup_notifiers); +static NotifierList later_wakeup_notifiers = +NOTIFIER_LIST_INITIALIZER(later_wakeup_notifiers); static uint32_t wakeup_reason_mask = ~0; static RunState vmstop_requested = RUN_STATE_MAX; @@ -1668,6 +1670,11 @@ void qemu_register_wakeup_notifier(Notifier *notifier) notifier_list_add(wakeup_notifiers, notifier); } +void qemu_register_later_wakeup_notifier(Notifier *notifier) +{ +notifier_list_add(later_wakeup_notifiers, notifier); +} + void qemu_system_killed(int signal, pid_t pid) { shutdown_signal = signal; @@ -1744,6 +1751,7 @@ static bool main_loop_should_exit(void) cpu_synchronize_all_states(); qemu_system_reset(VMRESET_SILENT); resume_all_vcpus(); +notifier_list_notify(later_wakeup_notifiers, NULL); monitor_protocol_event(QEVENT_WAKEUP, NULL); } if (qemu_powerdown_requested()) { The patch those not apply properly to QEMU (upstream) but it just because the file sysemu.h have been moved to include/sysemu/sysemu.h Once this is fix: Acked-by: Anthony PERARD anthony.per...@citrix.com Yes. The patches are for qemu-xen tree, to fix xen hvm s3 issue. Where should the 2 patches be checked in? qemu upstream (then backport to qemu-xen tree), or, qemu-xen tree? In general patches should go to qemu upstream first and then be backported to qemu-xen. OK, I will adjust system.h and then send to qemu upstream first. Thanks, Jinsong
Re: [Qemu-devel] [PATCH v3 19/29] tcg-aarch64: Introduce tcg_fmt_Rd_uimm_s
On 05.09.2013 17:41, Richard Henderson wrote: On 09/05/2013 06:32 AM, Claudio Fontana wrote: { -uint32_t half, base, shift, movk = 0; -/* construct halfwords of the immediate with MOVZ/MOVK with LSL */ -/* using MOVZ 0x5280 | extended reg.. */ -base = (value 0x) ? 0xd280 : 0x5280; -/* count trailing zeros in 16 bit steps, mapping 64 to 0. Emit the - first MOVZ with the half-word immediate skipping the zeros, with a shift - (LSL) equal to this number. Then morph all next instructions into MOVKs. - Zero the processed half-word in the value, continue until empty. - We build the final result 16bits at a time with up to 4 instructions, - but do not emit instructions for 16bit zero holes. */ Please do not remove these comments. In my judgement this part of the code profits from some verbose clarification. What is happening might be obvious to you, but not to others trying to step in. Fair enough. In general I'd prefer to keep movi as it was (functionally-wise) for the time being, replacing it with a more efficient version once we can get some numbers (which will be soon) with which to justify (or not) the added code complexity. The most important thing we're not doing at the moment is handling negative numbers efficiently. E.g. we're using 4 insns to load -1. Ok, lets punctually address that then. r~ Claudio
Re: [Qemu-devel] Block Filters
On Fri, 09/06 10:45, Kevin Wolf wrote: Am 06.09.2013 um 09:56 hat Fam Zheng geschrieben: On Tue, 09/03 18:24, Benoît Canet wrote: Hello list, I am thinking about QEMU block filters lately. I am not a block.c/blockdev.c expert so tell me what you think of the following. The use cases I see would be: -$user want to have some real cryptography on top of qcow2/qed or another format. snapshots and other block features should continue to work -$user want to use a raid like feature like QUORUM in QEMU. other features should continue to work -$user want to use the future SSD deduplication implementation with metadata on SSD and data on spinning disks. other features should continue to work -$user want to I/O throttle one drive of his vm. -$user want to do Copy On Read -$user want to do a combination of the above -$developer want to make the minimum of required steps to keep changes small -$developer want to keep user interface changes for later Lets take a example case of an user wanting to do I/O throttled encrypted QUORUM on top of QCOW2. Assuming we want to implement throttle and encryption as something remotely being like a block filter this makes a pretty complex BlockDriverState tree. The tree would look like the following: I/O throttling BlockDriverState (bs) | | | | Encryption BlockDriverState (bs) | | | | Quorum BlockDriverState (bs) / | \ /|\ / | \ / | \ QCOW2 bs QCOW2 b s QCOW2 bs | | | | | | | | | | | | RAW bs RAW bs RAW bs An external snapshot should result in a tree like the following. I/O throttling BlockDriverState (bs) | | | | Encryption BlockDriverState (bs) | | | | Quorum BlockDriverState (bs) / | \ /|\ / | \ / | \ QCOW2 bs QCOW2 bs QCOW2 bs | | | | | | | | | | | | QCOW2 bs QCOW2 bs QCOW2 bs | | | | | | | | | | | | RAW bs RAW bs RAW bs In the current state of QEMU we can code some block drivers to implement this tree. However when doing operations like snapshots blockdev.c would have no real idea of what should be snapshotted and how. (The 3 top bs should be kept on top) Moreover it would have no way to manipulate easily this tree of BlockDriverState has each one is encapsulated in it's parent. Also there no generic way to tell the block layer that two or more BlockDriverState are siblings. The current mail is here to propose some additionals structures in order to cope with these problems. The overall strategy of the proposed structures is to push out the BlockDriverStates relationships out of each BlockDriverState. The idea is that it would make it easier for the block layer to manipulate a well known structure instead of being forced to enter into each BlockDriverState specificity. The first structure is the BlockStackNode. The BlockStateNode would be used to represent the relationship between the various BlockDriverStates struct BlockStackNode { BlockDriverState *bs; /* the BlockDriverState holded by this node */ /* this doubly linked list entry points to the child node and the
Re: [Qemu-devel] [RFC] qcow2 journalling draft
On Wed, 09/04 11:39, Kevin Wolf wrote: First of all, excuse any inconsistencies in the following mail. I wrote it from top to bottom, and there was some thought process involved in almost every paragraph... Am 04.09.2013 um 10:03 hat Stefan Hajnoczi geschrieben: On Tue, Sep 03, 2013 at 03:45:52PM +0200, Kevin Wolf wrote: @@ -103,7 +107,11 @@ in the description of a field. write to an image with unknown auto-clear features if it clears the respective bits from this field first. -Bits 0-63: Reserved (set to 0) +Bit 0: Journal valid bit. This bit indicates that the +image contains a valid main journal starting at +journal_offset. Whether the journal is used can be determined from the journal_offset value (header length must be large enough and journal offset must be valid). Why do we need this autoclear bit? Hm, I introduced this one first and the journal dirty incompatible bit later, perhaps it's unnecessary now. Let's check... The obvious thing we need to protect against is applying stale journal data to an image that has been changed by an older version. As long as the journal is clean, this can't happen, and the journal dirty bit will ensure that the old version can only open the image if it is clean. However, what if we run 'qemu-img check -r leaks' with an old qemu-img version? It will reclaim the clusters used by the journal, and if we continue using the journal we'll corrupt whatever new data is there now. Why can old version qemu-img open the image with dirty journal in the first place? It's incompatible bit. Can we protect against this without using an autoclear bit? +Journals are used to allow safe updates of metadata without impacting +performance by requiring flushes to order updates to different parts of the +metadata. This sentence is hard to parse. Maybe something shorter like this: Journals allow safe metadata updates without the need for carefully ordering and flushing between update steps. Okay, I'll update the text with your proposal. +They consist of transactions, which in turn contain operations that +are effectively executed atomically. A qcow2 image can have a main image +journal that deals with cluster management operations, and additional specific +journals can be used by other features like data deduplication. I'm not sure if multiple journals will work in practice. Doesn't this re-introduce the need to order update steps and flush between them? This is a question for Benoît, who made this requirement. I asked him the same a while ago and apparently his explanation made some sense to me, or I would have remembered that I don't want it. ;-) It might have something to do with the fact that deduplication uses the journal more as a kind of cache for hash values that can be dropped and rebuilt after a crash. +A journal is organised in journal blocks, all of which have a reference count +of exactly 1. It starts with a block containing the following journal header: + +Byte 0 - 7: Magic (qjournal ASCII string) + + 8 - 11: Journal size in bytes, including the header + + 12 - 15: Journal block size order (block size in bytes = 1 order) +The block size must be at least 512 bytes and must not +exceed the cluster size. + + 16 - 19: Journal block index of the descriptor for the last +transaction that has been synced, starting with 1 for the +journal block after the header. 0 is used for empty +journals. + + 20 - 23: Sequence number of the last transaction that has been +synced. 0 is recommended as the initial value. + + 24 - 27: Sequence number of the last transaction that has been +committed. When replaying a journal, all transactions +after the last synced one up to the last commit one must be +synced. Note that this may include a wraparound of sequence +numbers. + + 28 - 31: Checksum (one's complement of the sum of all bytes in the +header journal block except those of the checksum field) + + 32 - 511: Reserved (set to 0) I'm not sure if these fields are necessary. They require updates (and maybe flush) after every commit and sync. The fewer metadata updates, the better, not just for performance but also to reduce the risk of data loss. If any metadata required to access the journal is corrupted, the image will be unavailable. It should be possible to determine
Re: [Qemu-devel] [RFC PATCH 1/6] make.rule: fix $(obj) to a real relative path
Il 05/09/2013 12:20, Fam Zheng ha scritto: Makefile.target includes rule.mak and unnested common-obj-y, then prefix them with '../', this will ignore object specific QEMU_CFLAGS in subdir Makefile.objs: $(obj)/curl.o: QEMU_CFLAGS += $(CURL_CFLAGS) Because $(obj) here is './block', instead of '../block'. This doesn't hurt compiling because we basically build all .o from top Makefile, before entering Makefile.target, but it will affact arriving per-object libs support. The starting point of $(obj) is fixed before including ./Makefile.objs, to get consistency with nested Makefile rules in target rule and variable definition. Signed-off-by: Fam Zheng f...@redhat.com --- Makefile.target | 3 ++- rules.mak | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile.target b/Makefile.target index 9a49852..b35e7c1 100644 --- a/Makefile.target +++ b/Makefile.target @@ -144,12 +144,13 @@ endif # CONFIG_SOFTMMU %/translate.o: QEMU_CFLAGS += $(TRANSLATE_OPT_CFLAGS) nested-vars += obj-y +obj := .. # This resolves all nested paths, so it must come last include $(SRC_PATH)/Makefile.objs all-obj-y = $(obj-y) -all-obj-y += $(addprefix ../, $(common-obj-y)) +all-obj-y += $(addprefix $(obj)/, $(common-obj-y)) The bug is clearly there, but I'm not sure this is correct. obj is the path to the object file. obj-y files are built in the target directory, thus the extra .. should apply only to common-obj-y; $(obj-y) should not be prefixed. So perhaps you need to: 1) move the nested-vars and unnest-vars call from Makefile.objs to Makefile. also move this line: QEMU_CFLAGS+=$(GLIB_CFLAGS) which has no business in Makefile.objs. With this change, Makefile.objs is just a list, like other */Makefile.objs files. 2) remove the additional complication where common-obj-y is including block-obj-y, just add it to all-obj-y manually. 3) in Makefile.target, do this: block-obj-y = ../ common-obj-y = ../ nested-vars = obj-y block-obj-y common-obj-y dummy := $(call unnest-vars) all-obj-y = $(obj-y) $(common-obj-y) $(block-obj-y) (Can all be done in a single patch). ? ifndef CONFIG_HAIKU LIBS+=-lm diff --git a/rules.mak b/rules.mak index 4499745..5758137 100644 --- a/rules.mak +++ b/rules.mak @@ -103,7 +103,6 @@ clean: clean-timestamp # magic to descend into other directories -obj := . old-nested-dirs := define push-var @@ -119,9 +118,10 @@ endef define unnest-dir $(foreach var,$(nested-vars),$(call push-var,$(var),$1/)) -$(eval obj := $(obj)/$1) +$(eval old-obj := $(obj)) +$(eval obj := $(if $(obj),$(obj)/$1,$1)) $(eval include $(SRC_PATH)/$1/Makefile.objs) -$(eval obj := $(patsubst %/$1,%,$(obj))) +$(eval obj := $(old-obj)) $(foreach var,$(nested-vars),$(call pop-var,$(var),$1/)) old-obj doesn't work if you have multiple levels of nesting. But you can call the variable something like obj-parent-$1 instead to solve this problem. However, please clean it up afterwards with $(eval obj-parent-$1 := ). Paolo endef
Re: [Qemu-devel] [PATCH v2] spapr-rtas: use softmmu for accessing rtas call parameters
On 09/06/2013 06:45 PM, Alexander Graf wrote: On 06.09.2013, at 10:10, Alexey Kardashevskiy wrote: On the real hardware, RTAS is called in real mode and therefore ignores top 4 bits of the address passed in the call. This fixes QEMU to use softmmu which can chop top 4 bits if MSR DR is not set. Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru --- Changes: v2: * masking from replaced with the use of cpu_ldl_data which can handle realmode case properly --- hw/ppc/spapr_hcall.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 063bd36..30f90bf 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -4,6 +4,7 @@ #include hw/ppc/spapr.h #include mmu-hash64.h #include cpu-models.h +#include exec/softmmu_exec.h #include libfdt.h @@ -523,10 +524,11 @@ static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr, static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { +CPUPPCState *env = cpu-env; target_ulong rtas_r3 = args[0]; -uint32_t token = ldl_be_phys(rtas_r3); -uint32_t nargs = ldl_be_phys(rtas_r3 + 4); -uint32_t nret = ldl_be_phys(rtas_r3 + 8); +uint32_t token = cpu_ldl_data(env, rtas_r3); +uint32_t nargs = cpu_ldl_data(env, rtas_r3 + 4); +uint32_t nret = cpu_ldl_data(env, rtas_r3 + 8); Wow - this really aren't that many memory accesses. So looking through rtas calls that come after this dispatch, from what I see they mostly use rtas_ld and rtas_st. They are defined as static inline uint32_t rtas_ld(target_ulong phys, int n) { return ldl_be_phys(phys + 4*n); } static inline void rtas_st(target_ulong phys, int n, uint32_t val) { stl_be_phys(phys + 4*n, val); } which means we need to change them as well to make rtas subcall memory accesses resolve properly. Which brings me to my next question: Why don't we use rtas_ld in the 3 calls above? It looks like a perfect fit really. They do not chop top bits too. Also, just changing the call to cpu_ldl_data will potentially break I think. Imagine you do cpu_synchronize_state with DR=1 in a previous call. Now comes an RTAS call. Because you don't do a cpu_synchronize_state() call here, you will still have the DR=1 in MSR, accessing virtual memory at a potentially very low address that may not be mapped in. So before you do the cpu_ldl_data you need to either do cpu_synchronize_state() - which can be slow - or you need to manually change MSR.DR to 0 so that we end up accessing the correct memory location always. If you encapsulate that in rtas_ld and rtas_st it might end up looking quite simple: static inline uint32_t rtas_ld(CPUPPCState *env, target_ulong phys, int n) { uint32_t r; target_ulong msr = env-msr; /* Make sure we access RTAS data in guest real mode */ env-msr ~= MSR_DR; r = ldl_be_phys(phys + 4*n); env-msr = msr; return r; } Or if you think it's too complicated, you can simply make it You added *env - this will result in almost 1000 lines patch - I did it earlier today, I just did not post that pointless patch. static inline uint64_t ppc64_phys_to_real(uint64_t addr) { return addr ~0xF000ULL; } static inline uint32_t rtas_ld(target_ulong phys, int n) { return ldl_be_phys(ppc64_phys_to_real(phys) + 4*n); } All things considered, I might even prefer the latter solution as it makes the code flow more obvious. But I'll leave the final call to you. The latter will do the job, yes, I'll go for it as you are fine with it. Thanks. ps. please review in-kernel xics thing :) -- Alexey
Re: [Qemu-devel] [RFC PATCH v2 4/6] module: implement module loading function
Il 06/09/2013 09:28, Fam Zheng ha scritto: Added three types of modules: typedef enum { MODULE_LOAD_BLOCK = 0, MODULE_LOAD_UI, MODULE_LOAD_NET, MODULE_LOAD_MAX, } module_load_type; and their loading function: void module_load(module_load_type). which loads all .so files in a subdir under ${PREFIX}/qemu/, e.g. /usr/lib/qemu/block. Modules of each type should be loaded before respective subsystem initialization code. Requires gmodule-2.0 from glib. Signed-off-by: Fam Zheng f...@redhat.com --- block.c | 1 + bsd-user/main.c | 3 +++ configure | 20 +++- include/qemu/module.h | 9 + linux-user/main.c | 3 +++ qemu-img.c| 1 + scripts/create_config | 4 ui/console.c | 1 + util/Makefile.objs| 2 ++ util/module.c | 52 +++ vl.c | 2 ++ 11 files changed, 89 insertions(+), 9 deletions(-) diff --git a/block.c b/block.c index a387c1a..49ab0ce 100644 --- a/block.c +++ b/block.c @@ -4009,6 +4009,7 @@ BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs, void bdrv_init(void) { +module_load(MODULE_LOAD_BLOCK); module_call_init(MODULE_INIT_BLOCK); } diff --git a/bsd-user/main.c b/bsd-user/main.c index f9246aa..6cb9e35 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -33,6 +33,7 @@ #include tcg.h #include qemu/timer.h #include qemu/envlist.h +#include qemu/module.h int singlestep; #if defined(CONFIG_USE_GUEST_BASE) @@ -749,6 +750,8 @@ int main(int argc, char **argv) if (argc = 1) usage(); +module_load(MODULE_LOAD_UI); +module_load(MODULE_LOAD_NET); module_call_init(MODULE_INIT_QOM); if ((envlist = envlist_create()) == NULL) { diff --git a/configure b/configure index 75abb87..7fec1c7 100755 --- a/configure +++ b/configure @@ -2249,15 +2249,17 @@ if test $mingw32 = yes; then else glib_req_ver=2.12 fi -if $pkg_config --atleast-version=$glib_req_ver gthread-2.0 /dev/null 21 -then -glib_cflags=`$pkg_config --cflags gthread-2.0 2/dev/null` -glib_libs=`$pkg_config --libs gthread-2.0 2/dev/null` -LIBS=$glib_libs $LIBS -libs_qga=$glib_libs $libs_qga -else -error_exit glib-$glib_req_ver required to compile QEMU -fi +for i in gthread-2.0 gmodule-2.0; do +if $pkg_config --atleast-version=$glib_req_ver $i /dev/null 21 +then +glib_cflags=`$pkg_config --cflags $i 2/dev/null` +glib_libs=`$pkg_config --libs $i 2/dev/null` +LIBS=$glib_libs $LIBS +libs_qga=$glib_libs $libs_qga +else +error_exit glib-$glib_req_ver required to compile QEMU +fi +done ## # pixman support probe diff --git a/include/qemu/module.h b/include/qemu/module.h index c4ccd57..f00bc25 100644 --- a/include/qemu/module.h +++ b/include/qemu/module.h @@ -37,4 +37,13 @@ void register_module_init(void (*fn)(void), module_init_type type); void module_call_init(module_init_type type); +typedef enum { +MODULE_LOAD_BLOCK = 0, +MODULE_LOAD_UI, +MODULE_LOAD_NET, +MODULE_LOAD_MAX, +} module_load_type; + +void module_load(module_load_type type); + #endif diff --git a/linux-user/main.c b/linux-user/main.c index 03859bc..9cbac14 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -34,6 +34,7 @@ #include qemu/timer.h #include qemu/envlist.h #include elf.h +#include qemu/module.h char *exec_path; @@ -3547,6 +3548,8 @@ int main(int argc, char **argv, char **envp) int i; int ret; +module_load(MODULE_LOAD_UI); +module_load(MODULE_LOAD_NET); module_call_init(MODULE_INIT_QOM); qemu_cache_utils_init(envp); diff --git a/qemu-img.c b/qemu-img.c index b9a848d..063e6bf 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -34,6 +34,7 @@ #include getopt.h #include stdio.h #include stdarg.h +#include qemu/module.h #ifdef _WIN32 #include windows.h diff --git a/scripts/create_config b/scripts/create_config index b1adbf5..7a54f2d 100755 --- a/scripts/create_config +++ b/scripts/create_config @@ -25,6 +25,7 @@ case $line in prefix=*) # save for the next definitions prefix=${line#*=} +echo #define CONFIG_PREFIX \$prefix\ ;; CONFIG_AUDIO_DRIVERS=*) drivers=${line#*=} @@ -104,6 +105,9 @@ case $line in value=${line#*=} echo #define $name $value ;; + DSOSUF=*) +echo #define HOST_DSOSUF \${line#*=}\ +;; esac done # read diff --git a/ui/console.c b/ui/console.c index aad4fc9..ad90950 100644 --- a/ui/console.c +++ b/ui/console.c @@ -27,6 +27,7 @@ #include qemu/timer.h #include qmp-commands.h #include sysemu/char.h +#include qemu/module.h Why? //#define DEBUG_CONSOLE #define
[Qemu-devel] [PATCH V2] qemu-xen: vt-d bugfix for pci rom
Liu, Jinsong wrote: From 7d93370e8005499d18507b8cd9fa71f4ae794e19 Mon Sep 17 00:00:00 2001 From: Liu Jinsong jinsong@vt-nhm7.tsp.org Date: Fri, 6 Sep 2013 16:34:56 +0800 Subject: [PATCH] qemu-xen: vt-d bugfix for pci rom Sorry, update 'From: Liu Jinsong jinsong@vt-nhm7.tsp.org' and add some error log. === From 7d93370e8005499d18507b8cd9fa71f4ae794e19 Mon Sep 17 00:00:00 2001 From: Liu Jinsong jinsong@intel.com Date: Fri, 6 Sep 2013 16:34:56 +0800 Subject: [PATCH V2] qemu-xen: vt-d bugfix for pci rom Remove incorrect memory_region_init_rom_device() from xen_pt_register_regions(), otherwise vt-d device with pci rom cannot pass through to hvm, since it trys to populate from normal ram for pci rom. For example, when we pass through Intel 82576 NIC (with 4MB pci rom) to hvm guest, it fails with libxl: error: libxl_qmp.c:454:qmp_next: Socket read error: Connection reset by peer qemu: hardware error: xen: xen_domid = 3, nr_pfn = 400, ram_addr = 2001 (XEN) page_alloc.c:1460:d0 Over-allocation for domain 3: 131329 131328 (XEN) memory.c:132:d0 Could not allocate order=0 extent: id=3 memflags=0 (254 of 1024) Signed-off-by: Liu Jinsong jinsong@intel.com --- hw/xen_pt.c |2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/hw/xen_pt.c b/hw/xen_pt.c index 7aae826..b0bffdb 100644 --- a/hw/xen_pt.c +++ b/hw/xen_pt.c @@ -440,8 +440,6 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s) s-bases[PCI_ROM_SLOT].access.maddr = d-rom.base_addr; -memory_region_init_rom_device(s-rom, NULL, NULL, - xen-pci-pt-rom, d-rom.size); pci_register_bar(s-dev, PCI_ROM_SLOT, PCI_BASE_ADDRESS_MEM_PREFETCH, s-rom); -- 1.7.1
Re: [Qemu-devel] Block Filters
Am 06.09.2013 um 11:18 hat Fam Zheng geschrieben: On Fri, 09/06 10:45, Kevin Wolf wrote: Am 06.09.2013 um 09:56 hat Fam Zheng geschrieben: Since BlockDriver.bdrv_snapshot_create() is an optional operation, blockdev.c can navigate down the tree from top node, until hitting some layer where the op is implemented (the QCow2 bs), so we get rid of this top_node_below_filter pointer. Is it even inherent to a block driver (like a filter), if a snapshot is to be taken at its level? Or is it rather a policy decision that should be made by the user? OK, getting the point that user should have full flexibility and fine operation granularity. It also stands against block_backend-top_node_below_filter. Do we really have the assumption that all the filters are on top of the tree and linear? Shouldn't this be possible? Block Backend | | Quodrum BDS /|\ iot filter | \ / | \ qcow2 qcow2 qcow2 So we throttle only a particular image, not the whole device. But this will make a top_node_below_filter pointer impossible. I was assuming that Benoît's model works for the special case of snapshotting in one predefined way, but this is actually a very good example of why it doesn't. The approach relies on snapshotting siblings together, and in this case the siblings would be iot/qcow2/qcow2, while iot is still a filter. This would mean that either iot needs to be top_node_below_filter and throttling doesn't stay on top, or the left qcow2 is top_node_below_filter and the other Quorum images aren't snapshotted. In our example, the quorum driver, it's not at all clear to me that you want to snapshot all children. In order to roll back to a previous state, one snapshot is enough, you don't need multiple copies of the same one. Perhaps you want two so that we can still compare them for verification. Or all of them because you can afford the disk space and want ultimate safety. I don't think qemu can know which one is true. Only if quorum ever knows about and operates on snapshots, it should be considered specifically, but no. So we need to achieve this in the general design: allow user to take snapshot, or set throttle limits on particular BDSes, as above graph. In the same way, in a typical case you may want to keep I/O throttling for the whole drive, including the new snapshot. But what if the throttling was used in order to not overload the network where the image is stored, and you're now doing a local snapshot, to which you want to stream the image? The I/O throttling should apply only to the backing file, not the new snapshot. Yes, and OTOH, throttling really suits to be a filter only if it can be a non top one, otherwise it's no better than what we have now. Well, it would be a cleaner architecture in any case, but having it in the middle of the stack feels useful indeed, so we should support it. So perhaps what we really need is a more flexible snapshot/BDS tree manipulation command that describes in detail which structure you want to have in the end. Designing the corresponding QMP command is the hard part, I guess. Kevin
Re: [Qemu-devel] [RFC] qcow2 journalling draft
Am 06.09.2013 um 11:20 hat Fam Zheng geschrieben: On Wed, 09/04 11:39, Kevin Wolf wrote: First of all, excuse any inconsistencies in the following mail. I wrote it from top to bottom, and there was some thought process involved in almost every paragraph... Am 04.09.2013 um 10:03 hat Stefan Hajnoczi geschrieben: On Tue, Sep 03, 2013 at 03:45:52PM +0200, Kevin Wolf wrote: @@ -103,7 +107,11 @@ in the description of a field. write to an image with unknown auto-clear features if it clears the respective bits from this field first. -Bits 0-63: Reserved (set to 0) +Bit 0: Journal valid bit. This bit indicates that the +image contains a valid main journal starting at +journal_offset. Whether the journal is used can be determined from the journal_offset value (header length must be large enough and journal offset must be valid). Why do we need this autoclear bit? Hm, I introduced this one first and the journal dirty incompatible bit later, perhaps it's unnecessary now. Let's check... The obvious thing we need to protect against is applying stale journal data to an image that has been changed by an older version. As long as the journal is clean, this can't happen, and the journal dirty bit will ensure that the old version can only open the image if it is clean. However, what if we run 'qemu-img check -r leaks' with an old qemu-img version? It will reclaim the clusters used by the journal, and if we continue using the journal we'll corrupt whatever new data is there now. Why can old version qemu-img open the image with dirty journal in the first place? It's incompatible bit. This is about a clean journal. Kevin
Re: [Qemu-devel] [RFC] qcow2 journalling draft
On Tue, 09/03 15:45, Kevin Wolf wrote: This contains an extension of the qcow2 spec that introduces journalling to the image format, plus some preliminary type definitions and function prototypes in the qcow2 code. Journalling functionality is a crucial feature for the design of data deduplication, and it will improve the core part of qcow2 by avoiding cluster leaks on crashes as well as provide an easier way to get a reliable implementation of performance features like Delayed COW. At this point of the RFC, it would be most important to review the on-disk structure. Once we're confident that it can do everything we want, we can start going into more detail on the qemu side of things. Signed-off-by: Kevin Wolf kw...@redhat.com --- block/Makefile.objs | 2 +- block/qcow2-journal.c | 55 ++ block/qcow2.h | 78 +++ docs/specs/qcow2.txt | 204 +- 4 files changed, 337 insertions(+), 2 deletions(-) create mode 100644 block/qcow2-journal.c diff --git a/block/Makefile.objs b/block/Makefile.objs index 3bb85b5..59be314 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -1,5 +1,5 @@ block-obj-y += raw_bsd.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o -block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o +block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o qcow2-journal.o block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-obj-y += qed-check.o block-obj-y += vhdx.o diff --git a/block/qcow2-journal.c b/block/qcow2-journal.c new file mode 100644 index 000..5b20239 --- /dev/null +++ b/block/qcow2-journal.c @@ -0,0 +1,55 @@ +/* + * qcow2 journalling functions + * + * Copyright (c) 2013 Kevin Wolf kw...@redhat.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the Software), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include qemu-common.h +#include block/block_int.h +#include qcow2.h + +#define QCOW2_JOURNAL_MAGIC 0x716a6f75726e616cULL /* qjournal */ +#define QCOW2_JOURNAL_BLOCK_MAGIC 0x716a626b /* qjbk */ + +typedef struct Qcow2JournalHeader { +uint64_tmagic; +uint32_tjournal_size; +uint32_tblock_size; +uint32_tsynced_index; +uint32_tsynced_seq; +uint32_tcommitted_seq; +uint32_tchecksum; +} QEMU_PACKED Qcow2JournalHeader; + +/* + * One big transaction per journal block. The transaction is committed either + * time based or when a microtransaction (single set of operations that must be + * performed atomically) doesn't fit in the same block any more. + */ +typedef struct Qcow2JournalBlock { +uint32_tmagic; +uint32_tchecksum; +uint32_tseq; +uint32_tdesc_offset; /* Allow block header extensions */ +uint32_tdesc_bytes; +uint32_tnb_data_blocks; +} QEMU_PACKED Qcow2JournalBlock; + diff --git a/block/qcow2.h b/block/qcow2.h index 1000239..2aee1fd 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -157,6 +157,10 @@ typedef struct Qcow2DiscardRegion { QTAILQ_ENTRY(Qcow2DiscardRegion) next; } Qcow2DiscardRegion; +typedef struct Qcow2Journal { + +} Qcow2Journal; + typedef struct BDRVQcowState { int cluster_bits; int cluster_size; @@ -479,4 +483,78 @@ int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, void **table); int qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table); +/* qcow2-journal.c functions */ + +typedef struct Qcow2JournalTransaction Qcow2JournalTransaction; + +enum Qcow2JournalEntryTypeID { +QJ_DESC_NOOP= 0, +QJ_DESC_WRITE = 1, +QJ_DESC_COPY= 2, + +/* required after a cluster is freed and used for other purposes, so that + * new (unjournalled) data won't be overwritten with
Re: [Qemu-devel] [RFC] qcow2 journalling draft
On Fri, 09/06 11:57, Kevin Wolf wrote: Am 06.09.2013 um 11:20 hat Fam Zheng geschrieben: On Wed, 09/04 11:39, Kevin Wolf wrote: First of all, excuse any inconsistencies in the following mail. I wrote it from top to bottom, and there was some thought process involved in almost every paragraph... Am 04.09.2013 um 10:03 hat Stefan Hajnoczi geschrieben: On Tue, Sep 03, 2013 at 03:45:52PM +0200, Kevin Wolf wrote: @@ -103,7 +107,11 @@ in the description of a field. write to an image with unknown auto-clear features if it clears the respective bits from this field first. -Bits 0-63: Reserved (set to 0) +Bit 0: Journal valid bit. This bit indicates that the +image contains a valid main journal starting at +journal_offset. Whether the journal is used can be determined from the journal_offset value (header length must be large enough and journal offset must be valid). Why do we need this autoclear bit? Hm, I introduced this one first and the journal dirty incompatible bit later, perhaps it's unnecessary now. Let's check... The obvious thing we need to protect against is applying stale journal data to an image that has been changed by an older version. As long as the journal is clean, this can't happen, and the journal dirty bit will ensure that the old version can only open the image if it is clean. However, what if we run 'qemu-img check -r leaks' with an old qemu-img version? It will reclaim the clusters used by the journal, and if we continue using the journal we'll corrupt whatever new data is there now. Why can old version qemu-img open the image with dirty journal in the first place? It's incompatible bit. This is about a clean journal. Ah yes, I get it, thanks. Fam
Re: [Qemu-devel] [RFC PATCH v2 3/6] Makefile: introduce common-obj-m and block-obj-m for DSO
Il 06/09/2013 09:28, Fam Zheng ha scritto: Add necessary rules and flags for shared object generation. $(common-obj-m) will include $(block-obj-m), like $(common-obj-y) does for $(block-obj-y). The new rules introduced here are: 0) For all %.so compiling: QEMU_CFLAGS += -shared -fPIC 1) %.o in $(common-obj-m) is compiled to %.o, with QEMU_CFLAGS += -shared -fPIC. Then linked to %.so. 2) %.mo in $(common-obj-m) is the placeholder for %.so for pattern matching in Makefile. It's linked to -shared with all its dependencies (multiple *.o) as input. Which means the list of depended objects must be ruled out in each sub-Makefile.objs with an variable: $(obj)/foo.mo-obj := $(addprefix $(obj)/,bar.o baz.o qux.o) Notice that $(obj)/ is required for both target and dependency in the rule. DSO suffix (.so) is configure variable (.dll for Windows). Some kinks to iron, but this is really well-architected. You took all the best parts of mjt's patches and fixed almost all the ugly ones. Kudos! Signed-off-by: Fam Zheng f...@redhat.com --- Makefile | 32 +--- Makefile.objs | 14 +- configure | 3 +++ rules.mak | 10 ++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 806946e..cf47ea9 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ Makefile: ; configure: ; .PHONY: all clean cscope distclean dvi html info install install-doc \ - pdf recurse-all speed test dist + pdf recurse-all speed test dist modules $(call set-vpath, $(SRC_PATH)) @@ -121,7 +121,30 @@ ifeq ($(CONFIG_SMARTCARD_NSS),y) include $(SRC_PATH)/libcacard/Makefile endif -all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all +all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules + +mod-obj-m = $(patsubst %.o,%$(DSOSUF),$(filter %.o,$(common-obj-m))) \ +$(patsubst %.mo,%$(DSOSUF),$(filter %.mo,$(common-obj-m))) Why common-obj-m only, what about block-obj-m? Perhaps adding to mod-obj-m (better name: modules-m) can be done in unnest-vars? +# Generate rules for single file modules (%.so: %.o). +$(foreach o,$(filter %.o,$(common-obj-m)),$(eval \ + $(patsubst %.o,%.so,$o): $o )) If you subst %.o to %.mo, you can use the same set of rules for both cases. +# For multi file modules, dependencies should be listed explicitly in +# Makefile.objs as +# $(obj)/foo.mo-obj := $(obj)/bar.o $(obj)/biz.o Why not $(obj)/foo.mo: $(obj)/bar.o $(obj)/biz.o ? +$(foreach o,$(filter %.mo,$(mod-obj-m)),$(eval \ + $o: $($o-obj))) + +%.mo: + $(if $(BUILD_DYNAMIC), \ + $(call quiet-command,$(CC) $(sort $^) -shared -o $@, LD[M] $(TARGET_DIR)$@), \ + $(call quiet-command,$(AR) rcs $@ $(sort $^), AR $(TARGET_DIR)$@)) I think we can always build modules dynamically. If the module/no-module configure option decides whether an object moves between *-obj-y and *-obj-m, statically-linked modules will just go on the linker command line with no need for $(AR) or --whole-archive/--no-whole-archive. I'm missing where is the .so built (or I guess it can just be hard-linked?) from the .mo file. IIRC -shared is not portable to Darwin. Darwin has separate file formats for dynamic libraries (.dylib) and loadable modules (.so), so it needs -bundle instad. All this screams just use libtool... + + +modules: $(mod-obj-m) +modules: BUILD_DYNAMIC = 1 +modules: QEMU_CFLAGS += -shared -fPIC -shared is not needed here, only -fPIC. Again, libtool would abstract this nicely. But it's fine if you prefer to have v3 still without libtool and only working on ELF systems. In fact, you probably don't need a special modules target. You can just add $(mod-obj-m) to all. config-host.h: config-host.h-timestamp config-host.h-timestamp: config-host.mak @@ -155,7 +178,7 @@ subdir-dtc:dtc/libfdt dtc/tests dtc/%: mkdir -p $@ -$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) +$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) $(common-obj-m) ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS)) romsubdir-%: @@ -235,6 +258,9 @@ clean: rm -f qemu-options.def find . -name '*.[oda]' -type f -exec rm -f {} + find . -name '*.l[oa]' -type f -exec rm -f {} + + find . -name '*'$(DSOSUF) -type f -exec rm -f {} + + find . -name '*.mo' -type f -exec rm -f {} + + rm -f $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ rm -Rf .libs rm -f qemu-img-cmds.h diff --git a/Makefile.objs b/Makefile.objs index f46a4cd..8984a20 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -19,6 +19,8 @@ block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o block-obj-y += qemu-coroutine-sleep.o block-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o +block-obj-m = block/ + ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy) # Lots of
[Qemu-devel] [PATCH 0/2] qcow2: Discard VM state in active L1 after creating snapshot
This series fixes that 'savevm' becomes much slower after the first snapshot. The reason is unnecessary COW for the VM state, which is now avoided. Kevin Wolf (2): qcow2: Pass discard type to qcow2_discard_clusters() qcow2: Discard VM state in active L1 after creating snapshot block/qcow2-cluster.c | 8 block/qcow2-snapshot.c | 7 +++ block/qcow2.c | 7 +-- block/qcow2.h | 7 ++- 4 files changed, 18 insertions(+), 11 deletions(-) -- 1.8.1.4
[Qemu-devel] [PATCH 1/2] qcow2: Pass discard type to qcow2_discard_clusters()
The function will be used internally instead of only being called for guest discard requests. Signed-off-by: Kevin Wolf kw...@redhat.com --- block/qcow2-cluster.c | 8 block/qcow2.c | 2 +- block/qcow2.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 2d5aa92..b0d688e 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1338,7 +1338,7 @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset) * clusters. */ static int discard_single_l2(BlockDriverState *bs, uint64_t offset, -unsigned int nb_clusters) +unsigned int nb_clusters, enum qcow2_discard_type type) { BDRVQcowState *s = bs-opaque; uint64_t *l2_table; @@ -1367,7 +1367,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset, l2_table[l2_index + i] = cpu_to_be64(0); /* Then decrease the refcount */ -qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST); +qcow2_free_any_clusters(bs, old_offset, 1, type); } ret = qcow2_cache_put(bs, s-l2_table_cache, (void**) l2_table); @@ -1379,7 +1379,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset, } int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset, -int nb_sectors) +int nb_sectors, enum qcow2_discard_type type) { BDRVQcowState *s = bs-opaque; uint64_t end_offset; @@ -1402,7 +1402,7 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset, /* Each L2 table is handled by its own loop iteration */ while (nb_clusters 0) { -ret = discard_single_l2(bs, offset, nb_clusters); +ret = discard_single_l2(bs, offset, nb_clusters, type); if (ret 0) { goto fail; } diff --git a/block/qcow2.c b/block/qcow2.c index 4bc679a..22569e6 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1572,7 +1572,7 @@ static coroutine_fn int qcow2_co_discard(BlockDriverState *bs, qemu_co_mutex_lock(s-lock); ret = qcow2_discard_clusters(bs, sector_num BDRV_SECTOR_BITS, -nb_sectors); +nb_sectors, QCOW2_DISCARD_REQUEST); qemu_co_mutex_unlock(s-lock); return ret; } diff --git a/block/qcow2.h b/block/qcow2.h index 1000239..9c33b98 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -450,7 +450,7 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m); int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset, -int nb_sectors); +int nb_sectors, enum qcow2_discard_type type); int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors); /* qcow2-snapshot.c functions */ -- 1.8.1.4
[Qemu-devel] [PATCH 2/2] qcow2: Discard VM state in active L1 after creating snapshot
During savevm, the VM state is written to the active L1 of the image and then a snapshot is taken. After that, the VM state isn't needed any more in the active L1 and should be discarded. This is implemented by this patch. The impact of not discarding the VM state is that a snapshot can never become smaller than any previous snapshot (because it would be padded with old VM state), and more importantly that future savevm operations cause unnecessary COWs (with associated flushes), which makes subsequent snapshots much slower. Signed-off-by: Kevin Wolf kw...@redhat.com --- block/qcow2-snapshot.c | 7 +++ block/qcow2.c | 5 - block/qcow2.h | 5 + 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index e7e6013..ffead08 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -416,6 +416,13 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) g_free(old_snapshot_list); +/* The VM state isn't needed any more in the active L1 table; in fact, it + * hurts by causing expensive COW for the next snapshot. */ +qcow2_discard_clusters(bs, qcow2_vm_state_offset(s), + align_offset(sn-vm_state_size, s-cluster_size) + BDRV_SECTOR_BITS, + QCOW2_DISCARD_NEVER); + #ifdef DEBUG_ALLOC { BdrvCheckResult result = {0}; diff --git a/block/qcow2.c b/block/qcow2.c index 22569e6..d11ced1 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1747,11 +1747,6 @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs) return 0; } -static int64_t qcow2_vm_state_offset(BDRVQcowState *s) -{ - return (int64_t)s-l1_vm_state_index (s-cluster_bits + s-l2_bits); -} - static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { BDRVQcowState *s = bs-opaque; diff --git a/block/qcow2.h b/block/qcow2.h index 9c33b98..47af5c9 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -361,6 +361,11 @@ static inline int64_t align_offset(int64_t offset, int n) return offset; } +static inline int64_t qcow2_vm_state_offset(BDRVQcowState *s) +{ + return (int64_t)s-l1_vm_state_index (s-cluster_bits + s-l2_bits); +} + static inline int qcow2_get_cluster_type(uint64_t l2_entry) { if (l2_entry QCOW_OFLAG_COMPRESSED) { -- 1.8.1.4
[Qemu-devel] qemu-user-x86_64 segfaults on armv5 (WAS: qemu-user + networking issues / segfaults)
Hello Am Mittwoch, 4. September 2013, 08:35:37 schrieb Richard Henderson: On 08/29/2013 02:27 PM, Christof Schulze wrote: #5 0x6012a100 in tb_gen_code (env=0x612def20, pc=18446744073699066880, cs_base=0, flags=4243635, cflags=0) at /mnt/data/build/qemu-1.6.0-ministatic/translate-all.c:964 In know exactly what this is -- the fallback vsyscall page. I've had a patch set around for the last three years or so to provide a real vdso for x86_64. I repost it every so often, usually to no response. See git://github.com/rth7680/qemu.git elfload-vdso after trying the patch itself and still getting slightly other crashes on irc we decided to try this patch based on the master branch. This allowed for debugging with gdb as it circumvented a bug of the early 1.6rcs of qemu where the g packet was transmitting two many registers. Having set a breakpoint at *0x40816725 (the memory position where the segfault happens) I got the following output. Loaded symbols for /lib64/ld-linux-x86-64.so.2 0x40802650 in _start () from /lib64/ld-linux-x86-64.so.2 (gdb) b *0x40816725 Haltepunkt 1 at 0x40816725: file ../sysdeps/x86_64/dl-trampoline.S, line 46. (gdb) cont Continuing. Breakpoint 1, _dl_runtime_resolve () at ../sysdeps/x86_64/dl-trampoline.S:46 46 ../sysdeps/x86_64/dl-trampoline.S: Datei oder Verzeichnis nicht gefunden. it says dl-trampoline.S: file or directory not found and gives me the gdb shell Breakpoint 1, _dl_runtime_resolve () at ../sysdeps/x86_64/dl-trampoline.S:46 46 in ../sysdeps/x86_64/dl-trampoline.S (gdb) Continuing. Program received signal SIGSEGV, Segmentation fault. 0xff600400 in ?? () RTH mentioned that the runtime resolution of the symbol was into the vsyscall page. Now I am unsure where I should go from this point. Should I collect more data? If so, what exactly is needed? What else could I do to get this resolved? Christof -- () ascii ribbon campaign - against html e-mail /\ www.asciiribbon.org - against proprietary attachments signature.asc Description: This is a digitally signed message part.
Re: [Qemu-devel] savevm too slow
Am 06.09.2013 um 03:31 hat xuanmao_001 geschrieben: Hi, qemuers: I found that the guest disk file cache mode will affect to the time of savevm. the cache 'writeback' too slow. but the cache 'unsafe' is as fast as it can, less than 10 seconds. here is the example I use virsh: @cache with writeback: #the first snapshot real0m21.904s user0m0.006s sys 0m0.008s #the secondary snapshot real2m11.624s user0m0.013s sys 0m0.008s @cache with unsafe: #the first snapshot real0m0.730s user0m0.006s sys 0m0.005s #the secondary snapshot real0m1.296s user0m0.002s sys 0m0.008s I sent patches that should eliminate the difference between the first and second snapshot at least. so, what the difference between them when using different cache. cache=unsafe ignores any flush requests. It's possible that there is potential for optimisation with cache=writeback, i.e. it sends flush requests that aren't necessary in fact. This is something that I haven't checked yet. the other question: when I change the buffer size #define IO_BUF_SIZE 32768 to #define IO_BUF_SIZE (1 * 1024 * 1024), the savevm is more quickly. Is this for cache=unsafe as well? Juan, any specific reason for using 32k? I think it would be better to have a multiple of the qcow2 cluster size, otherwise we get COW for the empty part of newly allocated clusters. If we can't make it dynamic, using at least fixed 64k to match the qcow2 default would probably improve things a bit. Kevin
Re: [Qemu-devel] [RFC PATCH v2 2/6] rule.mak: allow per object cflags and libs
06.09.2013 11:28, Fam Zheng wrote: Adds extract-libs in LINK to expand any per object libs, the syntax to define such a libs options is like: $(obj)/curl.o-libs = $(CURL_LIBS) in block/Makefile.objs. Similarly, $(obj)foo.o-cflags = $(FOO_CFLAGS) is also supported. Please note the UNsimilarity of -libs and -cflags -- one is with slash and another is without. Is it just the patch comment? Thanks, /mjt
Re: [Qemu-devel] Block Filters
On Fri, 09/06 11:55, Kevin Wolf wrote: Am 06.09.2013 um 11:18 hat Fam Zheng geschrieben: On Fri, 09/06 10:45, Kevin Wolf wrote: Am 06.09.2013 um 09:56 hat Fam Zheng geschrieben: Since BlockDriver.bdrv_snapshot_create() is an optional operation, blockdev.c can navigate down the tree from top node, until hitting some layer where the op is implemented (the QCow2 bs), so we get rid of this top_node_below_filter pointer. Is it even inherent to a block driver (like a filter), if a snapshot is to be taken at its level? Or is it rather a policy decision that should be made by the user? OK, getting the point that user should have full flexibility and fine operation granularity. It also stands against block_backend-top_node_below_filter. Do we really have the assumption that all the filters are on top of the tree and linear? Shouldn't this be possible? Block Backend | | Quodrum BDS /|\ iot filter | \ / | \ qcow2 qcow2 qcow2 So we throttle only a particular image, not the whole device. But this will make a top_node_below_filter pointer impossible. I was assuming that Benoît's model works for the special case of snapshotting in one predefined way, but this is actually a very good example of why it doesn't. The approach relies on snapshotting siblings together, and in this case the siblings would be iot/qcow2/qcow2, while iot is still a filter. This would mean that either iot needs to be top_node_below_filter and throttling doesn't stay on top, or the left qcow2 is top_node_below_filter and the other Quorum images aren't snapshotted. I think that user must look at what is there first, rather than do it blindly on the Block Backend, which is only an entry to the tree behind. Because wheather snapshot is supported, depends on what's in the backend. If the tree is merely a single raw image, nothing can be done. So, Block Backend doesn't hide things: I think we split it from BDS for putting device related states in a right place. Users still operates on the BDS for data operations (backup, snapshot, throttle, etc...), much the same as they currently do. The point of this design here is that we are able to assemble them to get flexible and sophisticated configurations. IMO, snapshotting Quodrum childrens, doesn't sound much different from snapshotting guest's rg0-disk0, rg0-disk1, rg0-disk2, it requires the knowledge that they are bound to work together. It's just that the knowledge is from guest raid configuration, or from Quodrum driver. If Quodrum requires all the children's snapshot be taken at the same time, like a transactional snapshot on rg0-disk{0,1,2} must triggered from QMP by user, Quodrum driver must implement its -bdrv_snapshot_create() and ensure it. In our example, the quorum driver, it's not at all clear to me that you want to snapshot all children. In order to roll back to a previous state, one snapshot is enough, you don't need multiple copies of the same one. Perhaps you want two so that we can still compare them for verification. Or all of them because you can afford the disk space and want ultimate safety. I don't think qemu can know which one is true. Only if quorum ever knows about and operates on snapshots, it should be considered specifically, but no. So we need to achieve this in the general design: allow user to take snapshot, or set throttle limits on particular BDSes, as above graph. In the same way, in a typical case you may want to keep I/O throttling for the whole drive, including the new snapshot. But what if the throttling was used in order to not overload the network where the image is stored, and you're now doing a local snapshot, to which you want to stream the image? The I/O throttling should apply only to the backing file, not the new snapshot. Yes, and OTOH, throttling really suits to be a filter only if it can be a non top one, otherwise it's no better than what we have now. Well, it would be a cleaner architecture in any case, but having it in the middle of the stack feels useful indeed, so we should support it. So perhaps what we really need is a more flexible snapshot/BDS tree manipulation command that describes in detail which structure you want to have in the end. Designing the corresponding QMP command is the hard part, I guess. Another concern is that we may do all this with substantial duplication work of QOM. Fam
Re: [Qemu-devel] [RFC PATCH v2 2/6] rule.mak: allow per object cflags and libs
On Fri, 09/06 14:42, Michael Tokarev wrote: 06.09.2013 11:28, Fam Zheng wrote: Adds extract-libs in LINK to expand any per object libs, the syntax to define such a libs options is like: $(obj)/curl.o-libs = $(CURL_LIBS) in block/Makefile.objs. Similarly, $(obj)foo.o-cflags = $(FOO_CFLAGS) is also supported. Please note the UNsimilarity of -libs and -cflags -- one is with slash and another is without. Is it just the patch comment? It's a typo in the commit message. I will fix it. Thanks, Fam
Re: [Qemu-devel] [RFC PATCH v2 3/6] Makefile: introduce common-obj-m and block-obj-m for DSO
On Fri, 09/06 12:09, Paolo Bonzini wrote: Il 06/09/2013 09:28, Fam Zheng ha scritto: Add necessary rules and flags for shared object generation. $(common-obj-m) will include $(block-obj-m), like $(common-obj-y) does for $(block-obj-y). The new rules introduced here are: 0) For all %.so compiling: QEMU_CFLAGS += -shared -fPIC 1) %.o in $(common-obj-m) is compiled to %.o, with QEMU_CFLAGS += -shared -fPIC. Then linked to %.so. 2) %.mo in $(common-obj-m) is the placeholder for %.so for pattern matching in Makefile. It's linked to -shared with all its dependencies (multiple *.o) as input. Which means the list of depended objects must be ruled out in each sub-Makefile.objs with an variable: $(obj)/foo.mo-obj := $(addprefix $(obj)/,bar.o baz.o qux.o) Notice that $(obj)/ is required for both target and dependency in the rule. DSO suffix (.so) is configure variable (.dll for Windows). Some kinks to iron, but this is really well-architected. You took all the best parts of mjt's patches and fixed almost all the ugly ones. Kudos! Signed-off-by: Fam Zheng f...@redhat.com --- Makefile | 32 +--- Makefile.objs | 14 +- configure | 3 +++ rules.mak | 10 ++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 806946e..cf47ea9 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ Makefile: ; configure: ; .PHONY: all clean cscope distclean dvi html info install install-doc \ - pdf recurse-all speed test dist + pdf recurse-all speed test dist modules $(call set-vpath, $(SRC_PATH)) @@ -121,7 +121,30 @@ ifeq ($(CONFIG_SMARTCARD_NSS),y) include $(SRC_PATH)/libcacard/Makefile endif -all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all +all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules + +mod-obj-m = $(patsubst %.o,%$(DSOSUF),$(filter %.o,$(common-obj-m))) \ +$(patsubst %.mo,%$(DSOSUF),$(filter %.mo,$(common-obj-m))) Why common-obj-m only, what about block-obj-m? Because common-obj-m = $(block-obj-m), in Makefile.objs below. Perhaps adding to mod-obj-m (better name: modules-m) can be done in unnest-vars? It looks more straightforward for me to do here, and it's used very locally. +# Generate rules for single file modules (%.so: %.o). +$(foreach o,$(filter %.o,$(common-obj-m)),$(eval \ + $(patsubst %.o,%.so,$o): $o )) If you subst %.o to %.mo, you can use the same set of rules for both cases. +# For multi file modules, dependencies should be listed explicitly in +# Makefile.objs as +# $(obj)/foo.mo-obj := $(obj)/bar.o $(obj)/biz.o Why not $(obj)/foo.mo: $(obj)/bar.o $(obj)/biz.o ? Because I don't know how to expand foo.mo to bar.o and biz.o: I expand foo.mo to bar.o biz.o in the link command line, to skip creating to foo.mo, or libfoo.a, if it's to be linked static: block-obj-y += foo.mo That's for avoiding ar and ln -r. +$(foreach o,$(filter %.mo,$(mod-obj-m)),$(eval \ + $o: $($o-obj))) + +%.mo: + $(if $(BUILD_DYNAMIC), \ + $(call quiet-command,$(CC) $(sort $^) -shared -o $@, LD[M] $(TARGET_DIR)$@), \ + $(call quiet-command,$(AR) rcs $@ $(sort $^), AR $(TARGET_DIR)$@)) I think we can always build modules dynamically. If the module/no-module configure option decides whether an object moves between *-obj-y and *-obj-m, statically-linked modules will just go on the linker command line with no need for $(AR) or --whole-archive/--no-whole-archive. I don't understand, do you mean a cc -shared output can be statically linked into a executable? I'm missing where is the .so built (or I guess it can just be hard-linked?) from the .mo file. IIRC -shared is not portable to Darwin. Darwin has separate file formats for dynamic libraries (.dylib) and loadable modules (.so), so it needs -bundle instad. All this screams just use libtool... + + +modules: $(mod-obj-m) +modules: BUILD_DYNAMIC = 1 +modules: QEMU_CFLAGS += -shared -fPIC -shared is not needed here, only -fPIC. Again, libtool would abstract this nicely. But it's fine if you prefer to have v3 still without libtool and only working on ELF systems. In fact, you probably don't need a special modules target. You can just add $(mod-obj-m) to all. config-host.h: config-host.h-timestamp config-host.h-timestamp: config-host.mak @@ -155,7 +178,7 @@ subdir-dtc:dtc/libfdt dtc/tests dtc/%: mkdir -p $@ -$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) +$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) $(common-obj-m) ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS)) romsubdir-%: @@ -235,6 +258,9 @@ clean: rm -f qemu-options.def find . -name '*.[oda]' -type f -exec rm -f {} + find . -name '*.l[oa]' -type f -exec rm -f {}
Re: [Qemu-devel] [RFC PATCH v2 3/6] Makefile: introduce common-obj-m and block-obj-m for DSO
Il 06/09/2013 13:47, Fam Zheng ha scritto: On Fri, 09/06 12:09, Paolo Bonzini wrote: Il 06/09/2013 09:28, Fam Zheng ha scritto: Add necessary rules and flags for shared object generation. $(common-obj-m) will include $(block-obj-m), like $(common-obj-y) does for $(block-obj-y). The new rules introduced here are: 0) For all %.so compiling: QEMU_CFLAGS += -shared -fPIC 1) %.o in $(common-obj-m) is compiled to %.o, with QEMU_CFLAGS += -shared -fPIC. Then linked to %.so. 2) %.mo in $(common-obj-m) is the placeholder for %.so for pattern matching in Makefile. It's linked to -shared with all its dependencies (multiple *.o) as input. Which means the list of depended objects must be ruled out in each sub-Makefile.objs with an variable: $(obj)/foo.mo-obj := $(addprefix $(obj)/,bar.o baz.o qux.o) Notice that $(obj)/ is required for both target and dependency in the rule. DSO suffix (.so) is configure variable (.dll for Windows). Some kinks to iron, but this is really well-architected. You took all the best parts of mjt's patches and fixed almost all the ugly ones. Kudos! Signed-off-by: Fam Zheng f...@redhat.com --- Makefile | 32 +--- Makefile.objs | 14 +- configure | 3 +++ rules.mak | 10 ++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 806946e..cf47ea9 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ Makefile: ; configure: ; .PHONY: all clean cscope distclean dvi html info install install-doc \ - pdf recurse-all speed test dist + pdf recurse-all speed test dist modules $(call set-vpath, $(SRC_PATH)) @@ -121,7 +121,30 @@ ifeq ($(CONFIG_SMARTCARD_NSS),y) include $(SRC_PATH)/libcacard/Makefile endif -all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all +all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules + +mod-obj-m = $(patsubst %.o,%$(DSOSUF),$(filter %.o,$(common-obj-m))) \ +$(patsubst %.mo,%$(DSOSUF),$(filter %.mo,$(common-obj-m))) Why common-obj-m only, what about block-obj-m? Because common-obj-m = $(block-obj-m), in Makefile.objs below. Perhaps adding to mod-obj-m (better name: modules-m) can be done in unnest-vars? It looks more straightforward for me to do here, and it's used very locally. But it doesn't scale too well, does it? There's no particular reason why all -m variables would be included in common-obj-m. In fact, block- obj-y/block-obj-m are the only remaining case of one variable including another. In another review I even proposed eliminating this exception. +# Generate rules for single file modules (%.so: %.o). +$(foreach o,$(filter %.o,$(common-obj-m)),$(eval \ + $(patsubst %.o,%.so,$o): $o )) If you subst %.o to %.mo, you can use the same set of rules for both cases. +# For multi file modules, dependencies should be listed explicitly in +# Makefile.objs as +# $(obj)/foo.mo-obj := $(obj)/bar.o $(obj)/biz.o Why not $(obj)/foo.mo: $(obj)/bar.o $(obj)/biz.o ? Because I don't know how to expand foo.mo to bar.o and biz.o: I expand foo.mo to bar.o biz.o in the link command line, to skip creating to foo.mo, or libfoo.a, if it's to be linked static: block-obj-y += foo.mo That's for avoiding ar and ln -r. Ah, I see now. See below for an idea (if it works). +$(foreach o,$(filter %.mo,$(mod-obj-m)),$(eval \ + $o: $($o-obj))) + +%.mo: + $(if $(BUILD_DYNAMIC), \ + $(call quiet-command,$(CC) $(sort $^) -shared -o $@, LD[M] $(TARGET_DIR)$@), \ + $(call quiet-command,$(AR) rcs $@ $(sort $^), AR $(TARGET_DIR)$@)) I think we can always build modules dynamically. If the module/no-module configure option decides whether an object moves between *-obj-y and *-obj-m, statically-linked modules will just go on the linker command line with no need for $(AR) or --whole-archive/--no-whole-archive. I don't understand, do you mean a cc -shared output can be statically linked into a executable? So if I understand correctly the .mo file is never used for a statically-linked module? So the ar doesn't matter as things stand Perhaps you could just use .mo file as a placeholder that holds the module's list of dependencies, no matter if it is shared or static: %.mo: $(call quiet-command,echo $(sort $^) $@, GEN$(TARGET_DIR_$@)) In the LINK rule include the list from all .mo files: $(sort $(filter %.o, $1)) \ $(shell cat $(filter %.mo,$^)) \ $(filter-out %.o %.mo,$^)) And the rule for shared objects would be simply: %.$(DSOSUF): QEMU_LDFLAGS += -shared %.$(DSOSUF): %.mo $(call LINK,$^) This would remove the need for the $i-obj variables. Paolo
[Qemu-devel] [PATCH v2 0/2] KVM: s390: add floating irq controller
This series adds a kvm_device that acts as a irq controller for floating interrupts. As a first step it implements functionality to retrieve and inject interrupts for the purpose of migration and for hardening the reset code by allowing user space to explicitly remove all pending floating interrupts. PFAULT patches will also use this device for enabling/disabling pfault, therefore the pfault patch series will be reworked to use this device. * Patch 1/2 adds a new data structure to hold interrupt information. The current one (struct kvm_s390_interrupt) does not allow to inject every kind of interrupt, e.g. some data for program interrupts and machine check interruptions were missing. * Patch 2/2 adds a kvm_device which supports getting/setting currently pending floating interrupts as well as deleting all currently pending interrupts Jens Freimann (2): KVM: s390: add and extend interrupt information data structs KVM: s390: add floating irq controller Documentation/virtual/kvm/devices/s390_flic.txt | 36 +++ arch/s390/include/asm/kvm_host.h| 35 +-- arch/s390/include/uapi/asm/kvm.h| 5 + arch/s390/kvm/interrupt.c | 304 arch/s390/kvm/kvm-s390.c| 1 + include/linux/kvm_host.h| 1 + include/uapi/linux/kvm.h| 65 + virt/kvm/kvm_main.c | 5 + 8 files changed, 368 insertions(+), 84 deletions(-) create mode 100644 Documentation/virtual/kvm/devices/s390_flic.txt -- 1.8.3.4
[Qemu-devel] [PATCH v2 1/2] KVM: s390: add and extend interrupt information data structs
With the currently available struct kvm_s390_interrupt it is not possible to inject every kind of interrupt as defined in the z/Architecture. Add additional interruption parameters to the structures and move it to kvm.h Signed-off-by: Jens Freimann jf...@linux.vnet.ibm.com Reviewed-by: Cornelia Huck cornelia.h...@de.ibm.com --- arch/s390/include/asm/kvm_host.h | 34 +- include/uapi/linux/kvm.h | 63 2 files changed, 64 insertions(+), 33 deletions(-) diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index e87ecaa..adb05c5 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -16,6 +16,7 @@ #include linux/hrtimer.h #include linux/interrupt.h #include linux/kvm_host.h +#include linux/kvm.h #include asm/debug.h #include asm/cpu.h @@ -162,18 +163,6 @@ struct kvm_vcpu_stat { u32 diagnose_9c; }; -struct kvm_s390_io_info { - __u16subchannel_id;/* 0x0b8 */ - __u16subchannel_nr;/* 0x0ba */ - __u32io_int_parm; /* 0x0bc */ - __u32io_int_word; /* 0x0c0 */ -}; - -struct kvm_s390_ext_info { - __u32 ext_params; - __u64 ext_params2; -}; - #define PGM_OPERATION0x01 #define PGM_PRIVILEGED_OP 0x02 #define PGM_EXECUTE 0x03 @@ -182,27 +171,6 @@ struct kvm_s390_ext_info { #define PGM_SPECIFICATION0x06 #define PGM_DATA 0x07 -struct kvm_s390_pgm_info { - __u16 code; -}; - -struct kvm_s390_prefix_info { - __u32 address; -}; - -struct kvm_s390_extcall_info { - __u16 code; -}; - -struct kvm_s390_emerg_info { - __u16 code; -}; - -struct kvm_s390_mchk_info { - __u64 cr14; - __u64 mcic; -}; - struct kvm_s390_interrupt_info { struct list_head list; u64 type; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 99c2533..eeb08a1 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -434,6 +434,69 @@ struct kvm_s390_interrupt { __u64 parm64; }; +struct kvm_s390_io_info { + __u16 subchannel_id; + __u16 subchannel_nr; + __u32 io_int_parm; + __u32 io_int_word; +}; + +struct kvm_s390_ext_info { + __u32 ext_params; + __u32 pad; + __u64 ext_params2; +}; + +struct kvm_s390_pgm_info { + __u64 trans_exc_code; + __u64 mon_code; + __u64 per_address; + __u32 data_exc_code; + __u16 code; + __u16 mon_class_nr; + __u8 per_code; + __u8 per_atmid; + __u8 exc_access_id; + __u8 per_access_id; + __u8 op_access_id; + __u8 pad[3]; +}; + +struct kvm_s390_prefix_info { + __u32 address; +}; + +struct kvm_s390_extcall_info { + __u16 code; +}; + +struct kvm_s390_emerg_info { + __u16 code; +}; + +struct kvm_s390_mchk_info { + __u64 cr14; + __u64 mcic; + __u64 failing_storage_address; + __u32 ext_damage_code; + __u32 pad; + __u8 fixed_logout[16]; +}; + +struct kvm_s390_irq { + __u64 type; + union { + struct kvm_s390_io_info io; + struct kvm_s390_ext_info ext; + struct kvm_s390_pgm_info pgm; + struct kvm_s390_emerg_info emerg; + struct kvm_s390_extcall_info extcall; + struct kvm_s390_prefix_info prefix; + struct kvm_s390_mchk_info mchk; + char reserved[64]; + }; +}; + /* for KVM_SET_GUEST_DEBUG */ #define KVM_GUESTDBG_ENABLE0x0001 -- 1.8.3.4
[Qemu-devel] [PATCH 2/2] s390x/kvm: implement floating-interrupt controller device
This patch implements a floating-interrupt controller device (flic) which interacts with the s390 flic kvm_device. It provides functionality to: * clear all pending floating interrupts in the kernel at device reset * inject/retrieve interrupts into the kernel (used for migration) Signed-off-by: Jens Freimann jf...@linux.vnet.ibm.com Reviewed-by: Thomas Huth th...@linux.vnet.ibm.com --- default-configs/s390x-softmmu.mak | 1 + hw/intc/Makefile.objs | 1 + hw/intc/s390_flic.c | 164 ++ hw/s390x/s390-virtio-ccw.c| 8 +- hw/s390x/s390-virtio.c| 2 + include/hw/s390x/s390_flic.h | 31 +++ 6 files changed, 206 insertions(+), 1 deletion(-) diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak index 81fbc68..d843dc0 100644 --- a/default-configs/s390x-softmmu.mak +++ b/default-configs/s390x-softmmu.mak @@ -1,2 +1,3 @@ CONFIG_VIRTIO=y CONFIG_SCLPCONSOLE=y +CONFIG_S390_FLIC=$(CONFIG_KVM) diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs index 2851eed..b2305aa 100644 --- a/hw/intc/Makefile.objs +++ b/hw/intc/Makefile.objs @@ -23,3 +23,4 @@ obj-$(CONFIG_OMAP) += omap_intc.o obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o obj-$(CONFIG_SH4) += sh_intc.o obj-$(CONFIG_XICS) += xics.o +obj-$(CONFIG_S390_FLIC) += s390_flic.o diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c new file mode 100644 index 000..9dfaafa --- /dev/null +++ b/hw/intc/s390_flic.c @@ -0,0 +1,164 @@ +/* + * QEMU S390x KVM floating interrupt controller (flic) + * + * Copyright 2013 IBM Corp. + * Author(s): Jens Freimann jf...@linux.vnet.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include sys/ioctl.h +#include hw/sysbus.h +#include sysemu/kvm.h +#include migration/qemu-file.h +#include hw/s390x/s390_flic.h + +void s390_flic_init(void) +{ +DeviceState *dev; + +if (kvm_enabled()) { +dev = qdev_create(NULL, s390-flic); +object_property_add_child(qdev_get_machine(), s390-flic, + OBJECT(dev), NULL); +qdev_init_nofail(dev); +} +} + +static int flic_dequeue_irq(QEMUFile *f, struct kvm_s390_irq *s390irq, +KVMS390FLICState *flic) +{ +struct kvm_device_attr attr; +int rc; + +attr.group = KVM_DEV_FLIC_DEQUEUE; +attr.addr = (uint64_t) s390irq; + +rc = ioctl(flic-fd, KVM_GET_DEVICE_ATTR, attr); + +return rc ? -errno : 0; +} + +static int flic_enqueue_irq(QEMUFile *f, struct kvm_s390_irq *s390irq, +KVMS390FLICState *flic) +{ +int rc; +struct kvm_device_attr attr; + +attr.group = KVM_DEV_FLIC_ENQUEUE; +attr.addr = (uint64_t) s390irq; + +rc = ioctl(flic-fd, KVM_SET_DEVICE_ATTR, attr); + +return rc ? -errno : 0; +} + +/* Save pending floating interrupts. */ +static void kvm_floating_interrupt_save(QEMUFile *f, void *opaque) +{ +struct kvm_s390_irq s390irq = {0}; +int r = 0; + +while (!r) { +r = flic_dequeue_irq(f, s390irq, opaque); +if (r == -ENODATA) { +/* At end of list: write special marker */ +memset(s390irq, 0, sizeof(s390irq)); +s390irq.type = 0x; +} +qemu_put_buffer(f, (uint8_t *) s390irq, sizeof(s390irq)); +} +} + +/* Load pending floating interrupts. */ +static int kvm_floating_interrupt_load(QEMUFile *f, void *opaque, int version_id) +{ +int r = 0; +struct kvm_s390_irq s390irq = {0}; + +while (!r) { +qemu_get_buffer(f, (uint8_t *) s390irq, sizeof(s390irq)); +/* Watch for marker indicating end of list */ +if (s390irq.type == 0x) { +return 0; +} +r = flic_enqueue_irq(f, s390irq, (struct KVMS390FLICState *) opaque); +} + +return r; +} + +static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) +{ +KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); +struct kvm_create_device cd = {0}; +int ret; + +flic_state-fd = -1; +if (!kvm_check_extension(kvm_state, KVM_CAP_DEVICE_CTRL)) { +return; +} + +cd.type = KVM_DEV_TYPE_FLIC; +ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, cd); +if (ret 0) { +perror(flic: couldn't create kvm_device); +return; +} +flic_state-fd = cd.fd; + +/* Register savevm handler for floating interrupts */ +register_savevm(NULL, floatingint, 0, 1, kvm_floating_interrupt_save, +kvm_floating_interrupt_load, (void *) flic_state); +} + +static void kvm_s390_flic_unrealize(DeviceState *dev, Error **errp) +{ +KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); + +unregister_savevm(DEVICE(flic_state), floatingint, flic_state); +} + +static void kvm_s390_flic_reset(DeviceState *dev) +{ +KVMS390FLICState *flic
[Qemu-devel] [PATCH 1/2] linux-headers: update for s390 floating interrupt controller
Add symbols required for the s390 floating interrupt controller (flic) Signed-off-by: Jens Freimann jf...@linux.vnet.ibm.com --- linux-headers/asm-s390/kvm.h | 5 linux-headers/linux/kvm.h| 65 2 files changed, 70 insertions(+) diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h index d25da59..33d52b8 100644 --- a/linux-headers/asm-s390/kvm.h +++ b/linux-headers/asm-s390/kvm.h @@ -16,6 +16,11 @@ #define __KVM_S390 +/* Device control API: s390-specific devices */ +#define KVM_DEV_FLIC_DEQUEUE 1 +#define KVM_DEV_FLIC_ENQUEUE 2 +#define KVM_DEV_FLIC_CLEAR_IRQS 3 + /* for KVM_GET_REGS and KVM_SET_REGS */ struct kvm_regs { /* general purpose regs for s390 */ diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index c614070..1f34381 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -434,6 +434,70 @@ struct kvm_s390_interrupt { __u64 parm64; }; +struct kvm_s390_io_info { + __u16 subchannel_id; + __u16 subchannel_nr; + __u32 io_int_parm; + __u32 io_int_word; +}; + +struct kvm_s390_ext_info { + __u32 ext_params; + __u32 pad; + __u64 ext_params2; +}; + +struct kvm_s390_pgm_info { + __u64 trans_exc_code; + __u64 mon_code; + __u64 per_address; + __u32 data_exc_code; + __u16 code; + __u16 mon_class_nr; + __u8 per_code; + __u8 per_atmid; + __u8 exc_access_id; + __u8 per_access_id; + __u8 op_access_id; + __u8 pad[3]; +}; + +struct kvm_s390_prefix_info { + __u32 address; +}; + +struct kvm_s390_extcall_info { + __u16 code; +}; + +struct kvm_s390_emerg_info { + __u16 code; +}; + +struct kvm_s390_mchk_info { + __u64 cr14; + __u64 mcic; + __u64 failing_storage_address; + __u32 ext_damage_code; + __u32 pad; + __u8 fixed_logout[16]; +}; + +struct kvm_s390_irq { + __u64 type; + union { + struct kvm_s390_io_info io; + struct kvm_s390_ext_info ext; + struct kvm_s390_pgm_info pgm; + struct kvm_s390_emerg_info emerg; + struct kvm_s390_extcall_info extcall; + struct kvm_s390_prefix_info prefix; + struct kvm_s390_mchk_info mchk; + char reserved[64]; + }; +}; + + /* for KVM_SET_GUEST_DEBUG */ #define KVM_GUESTDBG_ENABLE0x0001 @@ -839,6 +903,7 @@ struct kvm_device_attr { #define KVM_DEV_TYPE_FSL_MPIC_20 1 #define KVM_DEV_TYPE_FSL_MPIC_42 2 #define KVM_DEV_TYPE_XICS 3 +#define KVM_DEV_TYPE_FLIC 4 /* * ioctls for VM fds -- 1.8.3.4
[Qemu-devel] [PATCH 0/2] s390x/kvm: implement floating interrupt controller
This patchset enables the s390 floating interrupt controller kvm_device. It is used to * clear all pending floating interrupts in the kernel at device reset * inject/retrieve interrupts into the kernel (used for migration) Please note that the linux-headers changes are not yet merged by upstream Jens Freimann (2): linux-headers: update for s390 floating interrupt controller s390x/kvm: implement floating-interrupt controller device default-configs/s390x-softmmu.mak | 1 + hw/intc/Makefile.objs | 1 + hw/intc/s390_flic.c | 164 ++ hw/s390x/s390-virtio-ccw.c| 8 +- hw/s390x/s390-virtio.c| 2 + include/hw/s390x/s390_flic.h | 31 +++ linux-headers/asm-s390/kvm.h | 5 ++ linux-headers/linux/kvm.h | 65 +++ 8 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 hw/intc/s390_flic.c create mode 100644 include/hw/s390x/s390_flic.h -- 1.8.3.4
[Qemu-devel] [PATCH v2 2/2] KVM: s390: add floating irq controller
This patch adds a floating irq controller as a kvm_device. It will be necessary for migration of floating interrupts as well as for hardening the reset code by allowing user space to explicitly remove all pending floating interrupts. Signed-off-by: Jens Freimann jf...@linux.vnet.ibm.com Reviewed-by: Cornelia Huck cornelia.h...@de.ibm.com --- Documentation/virtual/kvm/devices/s390_flic.txt | 36 +++ arch/s390/include/asm/kvm_host.h| 1 + arch/s390/include/uapi/asm/kvm.h| 5 + arch/s390/kvm/interrupt.c | 304 arch/s390/kvm/kvm-s390.c| 1 + include/linux/kvm_host.h| 1 + include/uapi/linux/kvm.h| 2 + virt/kvm/kvm_main.c | 5 + 8 files changed, 304 insertions(+), 51 deletions(-) diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt new file mode 100644 index 000..06aef31 --- /dev/null +++ b/Documentation/virtual/kvm/devices/s390_flic.txt @@ -0,0 +1,36 @@ +FLIC (floating interrupt controller) + + +FLIC handles floating (non per-cpu) interrupts, i.e. I/O, service and some +machine check interruptions. All interrupts are stored in a per-vm list of +pending interrupts. FLIC performs operations on this list. + +Only one FLIC instance may be instantiated. + +FLIC provides support to +- add/delete interrupts (KVM_DEV_FLIC_ENQUEUE and _DEQUEUE) +- purge all pending floating interrupts (KVM_DEV_FLIC_CLEAR_IRQS) + +Groups: + KVM_DEV_FLIC_ENQUEUE +Adds one interrupt to the list of pending floating interrupts. Interrupts +are taken from this list for injection into the guest. attr contains +a struct kvm_s390_irq which contains all data relevant for +interrupt injection. +The format of the data structure kvm_s390_irq as it is copied from userspace +is defined in usr/include/linux/kvm.h. +For historic reasons list members are stored in a different data structure, i.e. +we need to copy the relevant data into a struct kvm_s390_interrupt_info +which can then be added to the list. + + KVM_DEV_FLIC_DEQUEUE +Takes one element off the pending interrupts list and copies it into userspace. +Dequeued interrupts are not injected into the guest. +attr-addr contains the userspace address of a struct kvm_s390_irq. +List elements are stored in the format of struct kvm_s390_interrupt_info +(arch/s390/include/asm/kvm_host.h) and are copied into a struct kvm_s390_irq +(usr/include/linux/kvm.h) + + KVM_DEV_FLIC_CLEAR_IRQS +Simply deletes all elements from the list of currently pending floating interrupts. +No interrupts are injected into the guest. diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index adb05c5..e1cc166 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -238,6 +238,7 @@ struct kvm_arch{ struct sca_block *sca; debug_info_t *dbf; struct kvm_s390_float_interrupt float_int; + struct kvm_device *flic; struct gmap *gmap; int css_support; }; diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h index d25da59..33d52b8 100644 --- a/arch/s390/include/uapi/asm/kvm.h +++ b/arch/s390/include/uapi/asm/kvm.h @@ -16,6 +16,11 @@ #define __KVM_S390 +/* Device control API: s390-specific devices */ +#define KVM_DEV_FLIC_DEQUEUE 1 +#define KVM_DEV_FLIC_ENQUEUE 2 +#define KVM_DEV_FLIC_CLEAR_IRQS 3 + /* for KVM_GET_REGS and KVM_SET_REGS */ struct kvm_regs { /* general purpose regs for s390 */ diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 7f35cb3..d6d5e36 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -656,53 +656,86 @@ struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, return inti; } -int kvm_s390_inject_vm(struct kvm *kvm, - struct kvm_s390_interrupt *s390int) +static void __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti) { struct kvm_s390_local_interrupt *li; struct kvm_s390_float_interrupt *fi; - struct kvm_s390_interrupt_info *inti, *iter; + struct kvm_s390_interrupt_info *iter; int sigcpu; + mutex_lock(kvm-lock); + fi = kvm-arch.float_int; + spin_lock(fi-lock); + if (!is_ioint(inti-type)) { + list_add_tail(inti-list, fi-list); + } else { + u64 isc_bits = int_word_to_isc_bits(inti-io.io_int_word); + + /* Keep I/O interrupts sorted in isc order. */ + list_for_each_entry(iter, fi-list, list) { + if (!is_ioint(iter-type)) + continue; + if (int_word_to_isc_bits(iter-io.io_int_word) +
Re: [Qemu-devel] [PATCH 1/2] linux-headers: update for s390 floating interrupt controller
On 6 September 2013 13:19, Jens Freimann jf...@linux.vnet.ibm.com wrote: Add symbols required for the s390 floating interrupt controller (flic) Updates to linux-headers should be the result of a sync against a specified mainline kernel revision, please (otherwise this should be an RFC patchset). thanks -- PMM
Re: [Qemu-devel] [PATCH 1/2] linux-headers: update for s390 floating interrupt controller
On 6 September 2013 13:19, Jens Freimann jf...@linux.vnet.ibm.com wrote: @@ -839,6 +903,7 @@ struct kvm_device_attr { #define KVM_DEV_TYPE_FSL_MPIC_20 1 #define KVM_DEV_TYPE_FSL_MPIC_42 2 #define KVM_DEV_TYPE_XICS 3 +#define KVM_DEV_TYPE_FLIC 4 Christoffer's patchset switching the ARM VGIC to this list also uses 4 as its enumeration value: https://lists.cs.columbia.edu/pipermail/kvmarm/2013-August/006822.html That patchset isn't in yet, but maybe you should use 5 to avoid conflicts? thanks -- PMM
Re: [Qemu-devel] [PATCH 32/32] PPC: Ignore writes to L2CR
2013/6/30 Alexander Graf ag...@suse.de: The L2CR register contains a number of bits that either impose configuration which we can't deal with or mean something is in progress until the bit is 0 again. Since we don't model the former and we do want to accomodate guests using the latter semantics, let's just ignore writes to L2CR. That way guests always read back 0 and are usually happy with that. Hi, It does not seem to simply ignore writes to L2CR. The kernel we run on qemu no longer works without deleting the write instructions to L2CR. And a simple test of executing a write to L2CR seems to generate an exception instead of ignoring it : $ qemu-system-ppc -cpu e600 -M prep -m 256M -bios prep_bios.elf -d in_asm Trying to write invalid spr 1017 (0x3f9) at fffc Trying to write invalid spr 1017 (0x3f9) at fffc IN: 0xfffc: mtl2cr r0 invalid/unsupported opcode: 00 - 00 - 00 () fff00700 0 IN: 0xfff00700: .long 0x0 Is it really what you wanted ? -- Julio Guerra
[Qemu-devel] [PATCH v2] mips_malta: support up to 2GiB RAM
A Malta board can support up to 2GiB of RAM. Since the unmapped kseg0/1 regions are only 512MiB large the latter 256MiB of those are taken up by the IO region, access to RAM beyond 256MiB must be done through a mapped region. In the case of a Linux guest this means we need to use highmem. The mainline Linux kernel does not support highmem for Malta at this time, however this can be tested using the linux-mti-3.8 kernel branch available from: git://git.linux-mips.org/pub/scm/linux-mti.git You should be able to boot a Linux kernel built from the linux-mti-3.8 branch, with CONFIG_HIGHMEM enabled, using 2GiB RAM by passing -m 2G to QEMU and appending the following kernel parameters: mem=256m@0x0 mem=256m@0x9000 mem=1536m@0x2000 Note that the upper half of the physical address space of a Malta mirrors the lower half (hence the 2GiB limit) except that the IO region (0x1000-0x1fff in the lower half) is not mirrored in the upper half. That is, physical addresses 0x9000-0x9fff access RAM rather than the IO region, resulting in a physical address space resembling the following: 0x - 0x0fff RAM 0x1000 - 0x1fff I/O 0x2000 - 0x7fff RAM 0x8000 - 0x8fff RAM (mirror of 0x - 0x0fff) 0x9000 - 0x9fff RAM 0xa000 - 0x RAM (mirror of 0x2000 - 0x7fff) The second mem parameter provided to the kernel above accesses the second 256MiB of RAM through the upper half of the physical address space, making use of the aliasing described above in order to avoid the IO region and use the whole 2GiB RAM. The memory setup may be seen as 'backwards' in this commit since the 'real' memory is mapped in the upper half of the physical address space and the lower half contains the aliases. On real hardware it would be typical to see the upper half of the physical address space as the alias since the bus addresses generated match the lower half of the physical address space. However since the memory accessible in the upper half of the physical address space is uninterrupted by the IO region it is easiest to map the RAM as a whole there, and functionally it makes no difference to the target code. Due to the requirements of accessing the second 256MiB of RAM through a mapping to the upper half of the physical address space it is usual for the bootloader to indicate a maximum of 256MiB memory to a kernel. This allows kernels which do not support such access to boot on systems with more than 256MiB of RAM. It is also the behaviour assumed by Linux. QEMUs small generated bootloader is modified to provide this behaviour. Signed-off-by: Paul Burton paul.bur...@imgtec.com Signed-off-by: Yongbok Kim yongbok@imgtec.com Reviewed-by: Aurelien Jarno aurel...@aurel32.net --- Changes in v2: - Add a table describing the physical memory space to the commit message, as suggested by Aurelien Jarno. --- hw/mips/mips_malta.c | 36 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index ae0921c..05c8771 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -827,7 +827,8 @@ static int64_t load_kernel (void) } prom_set(prom_buf, prom_index++, memsize); -prom_set(prom_buf, prom_index++, %i, loaderparams.ram_size); +prom_set(prom_buf, prom_index++, %i, + MIN(loaderparams.ram_size, 256 20)); prom_set(prom_buf, prom_index++, modetty0); prom_set(prom_buf, prom_index++, 38400n8r); prom_set(prom_buf, prom_index++, NULL); @@ -884,7 +885,9 @@ void mips_malta_init(QEMUMachineInitArgs *args) char *filename; pflash_t *fl; MemoryRegion *system_memory = get_system_memory(); -MemoryRegion *ram = g_new(MemoryRegion, 1); +MemoryRegion *ram_high = g_new(MemoryRegion, 1); +MemoryRegion *ram_low_preio = g_new(MemoryRegion, 1); +MemoryRegion *ram_low_postio; MemoryRegion *bios, *bios_copy = g_new(MemoryRegion, 1); target_long bios_size = FLASH_SIZE; const size_t smbus_eeprom_size = 8 * 256; @@ -951,15 +954,32 @@ void mips_malta_init(QEMUMachineInitArgs *args) env = cpu-env; /* allocate RAM */ -if (ram_size (256 20)) { +if (ram_size (2048u 20)) { fprintf(stderr, -qemu: Too much memory for this machine: %d MB, maximum 256 MB\n, +qemu: Too much memory for this machine: %d MB, maximum 2048 MB\n, ((unsigned int)ram_size / (1 20))); exit(1); } -memory_region_init_ram(ram, NULL, mips_malta.ram, ram_size); -vmstate_register_ram_global(ram); -memory_region_add_subregion(system_memory, 0, ram); + +/* register RAM at high address where it is undisturbed by IO */ +memory_region_init_ram(ram_high, NULL, mips_malta.ram, ram_size); +vmstate_register_ram_global(ram_high); +memory_region_add_subregion(system_memory, 0x8000, ram_high); + +/*
Re: [Qemu-devel] [RFC v4 4/5] hw/arm/digic: add UART support
On Fri, 6 Sep 2013 08:25:20 +0100 Peter Maydell peter.mayd...@linaro.org wrote: On 6 September 2013 07:54, Antony Pavlov antonynpav...@gmail.com wrote: On Thu, 5 Sep 2013 19:17:50 +0100 Peter Maydell peter.mayd...@linaro.org wrote: Does this UART really not have a FIFO? There is no public documentation on Digic chips. Only Canon's engineers know something about Digic's FIFO (if it exists :). You can deduce its existence though -- does the UART let you feed two or three characters to it at faster than whatever the serial line speed is before it sets the stop sending me bits status bit, or does it stop after the first? No, I can't :) How can I check this mysterious stop sending me bits status bit? Do you mean the UART hardware flow control pin? I can't use hardware flow control as I have only 3-wire UART on the camera. Moreover I have to enable hardware flow control in software, but I have no information how to do it. If the real firmware uses this for anything remotely serious (ie for more than trivial and default-disabled debug info) it probably does have a FIFO. However, let's assume it doesn't for now. -- PMM -- -- Best regards, Antony Pavlov
Re: [Qemu-devel] [PATCH 2/4] kvm: Introduce kvm_arch_irqchip_create
On 23 August 2013 20:41, Christoffer Dall christoffer.d...@linaro.org wrote: Introduce kvm_arch_irqchip_create an arch-specific hook in preparation for architecture-specific use of the device control API to create IRQ chips. Following patches will implement the ARM irqchip create method to prefer the device control API over the older KVM_CREATE_IRQCHIP API. Signed-off-by: Christoffer Dall christoffer.d...@linaro.org --- include/sysemu/kvm.h |4 kvm-all.c| 11 +-- target-arm/kvm.c |5 + target-i386/kvm.c|5 + target-ppc/kvm.c |5 + target-s390x/kvm.c |5 + 6 files changed, 33 insertions(+), 2 deletions(-) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index de74411..1e5847e 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -224,6 +224,10 @@ void kvm_arch_reset_vcpu(CPUState *cpu); int kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr); int kvm_arch_on_sigbus(int code, void *addr); +/* return negative error on error, 0 if irq chip was not created, and positive + * number if it was created */ +int kvm_arch_irqchip_create(KVMState *s); Could you follow the doc-comment coding style for this, please? (The extract/deposit ops in include/qemu/bitops.h are the template I usually crib from.) + void kvm_arch_init_irq_routing(KVMState *s); int kvm_set_irq(KVMState *s, int irq, int level); diff --git a/kvm-all.c b/kvm-all.c index 716860f..fe64f3b 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1295,10 +1295,17 @@ static int kvm_irqchip_create(KVMState *s) return 0; } -ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP); +/* First probe and see if there's a arch-specific hook to create the + * in-kernel irqchip for us */ +ret = kvm_arch_irqchip_create(s); if (ret 0) { -fprintf(stderr, Create kernel irqchip failed\n); return ret; +} else if (ret == 0) { +ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP); +if (ret 0) { +fprintf(stderr, Create kernel irqchip failed\n); +return ret; +} } kvm_kernel_irqchip = true; diff --git a/target-arm/kvm.c b/target-arm/kvm.c index b92e00d..2484d90 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -647,3 +647,8 @@ void kvm_arch_remove_all_hw_breakpoints(void) void kvm_arch_init_irq_routing(KVMState *s) { } + +int kvm_arch_irqchip_create(KVMState *s) +{ +return 0; +} [ditto in s390/ppc/i386] We can avoid all these identical stub versions of this function by using our stubs mechanism: create a file stubs/kvm.c, put the dummy function definition in it, and add a line to stubs/Makefile.obj saying stub-obj-$(CONFIG_KVM) += kvm.o Then only the targets which actually need a real implementation of this function have to provide one; everybody else gets the stub version automatically. In fact you could have the stub version's implementation be to call kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP), which would then simplify the kvm-all.c code a little. (There are probably a few other kvm target functions we could provide stubs for, but that's a later cleanup.) -- PMM
Re: [Qemu-devel] [RFC v2 1/6] bdrv: Use Error for opening images
Am 05.09.2013 um 15:55 hat Max Reitz geschrieben: Add an Error ** parameter to BlockDriver.bdrv_open and BlockDriver.bdrv_file_open to allow more specific error messages. Signed-off-by: Max Reitz mre...@redhat.com diff --git a/block/raw_bsd.c b/block/raw_bsd.c index ab2b0fd..793121a 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -130,12 +130,14 @@ static int raw_has_zero_init(BlockDriverState *bs) return bdrv_has_zero_init(bs-file); } -static int raw_create(const char *filename, QEMUOptionParameter *options) +static int raw_create(const char *filename, QEMUOptionParameter *options, + Error **errp) { return bdrv_create_file(filename, options); } -static int raw_open(BlockDriverState *bs, QDict *options, int flags) +static int raw_open(BlockDriverState *bs, QDict *options, int flags, +Error **errp) { bs-sg = bs-file-sg; return 0; raw_create() shouldn't be converted in this patch, this causes a build failure. Kevin
[Qemu-devel] [PATCH v2 1/6] qapi: Add ImageInfoSpecific type
Add a new type ImageInfoSpecific as a union for image format specific information in ImageInfo. Signed-off-by: Max Reitz mre...@redhat.com --- qapi-schema.json | 18 +- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/qapi-schema.json b/qapi-schema.json index a51f7d2..eebf851 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -210,6 +210,18 @@ 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } } ## +# @ImageInfoSpecific: +# +# A discriminated record of image format specific information structures. +# +# Since: 1.7 +## + +{ 'union': 'ImageInfoSpecific', + 'data': { + } } + +## # @ImageInfo: # # Information about a QEMU image file @@ -238,6 +250,9 @@ # # @backing-image: #optional info of the backing image (since 1.6) # +# @info-string: #optional string supplying additional format-specific +# information (since 1.7) +# # Since: 1.3 # ## @@ -248,7 +263,8 @@ '*cluster-size': 'int', '*encrypted': 'bool', '*backing-filename': 'str', '*full-backing-filename': 'str', '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'], - '*backing-image': 'ImageInfo' } } + '*backing-image': 'ImageInfo', + '*format-specific': 'ImageInfoSpecific' } } ## # @ImageCheck: -- 1.8.3.1
[Qemu-devel] [PATCH v2 2/6] block: Add ImageInfoSpecific to BlockDriverInfo
Add the new ImageInfoSpecific type also to BlockDriverInfo. To prevent memory leaks, this field has to be initialized to NULL every time before calling bdrv_get_info and qapi_free_ImageInfoSpecific has to be called on it when the BlockDriverInfo object is no longer required. Signed-off-by: Max Reitz mre...@redhat.com --- block.c | 3 ++- block/mirror.c| 6 -- block/qapi.c | 6 +- include/block/block.h | 2 ++ qemu-img.c| 3 ++- qemu-io-cmds.c| 6 +- 6 files changed, 20 insertions(+), 6 deletions(-) diff --git a/block.c b/block.c index 26639e8..1a5d2a4 100644 --- a/block.c +++ b/block.c @@ -1921,7 +1921,7 @@ void bdrv_round_to_clusters(BlockDriverState *bs, int64_t *cluster_sector_num, int *cluster_nb_sectors) { -BlockDriverInfo bdi; +BlockDriverInfo bdi = { .format_specific = NULL }; if (bdrv_get_info(bs, bdi) 0 || bdi.cluster_size == 0) { *cluster_sector_num = sector_num; @@ -1932,6 +1932,7 @@ void bdrv_round_to_clusters(BlockDriverState *bs, *cluster_nb_sectors = QEMU_ALIGN_UP(sector_num - *cluster_sector_num + nb_sectors, c); } +qapi_free_ImageInfoSpecific(bdi.format_specific); } static bool tracked_request_overlaps(BdrvTrackedRequest *req, diff --git a/block/mirror.c b/block/mirror.c index 86de458..cfef7e9 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -295,7 +295,7 @@ static void coroutine_fn mirror_run(void *opaque) BlockDriverState *bs = s-common.bs; int64_t sector_num, end, sectors_per_chunk, length; uint64_t last_pause_ns; -BlockDriverInfo bdi; +BlockDriverInfo bdi = { .format_specific = NULL }; char backing_filename[1024]; int ret = 0; int n; @@ -325,6 +325,7 @@ static void coroutine_fn mirror_run(void *opaque) s-buf_size = MAX(s-buf_size, bdi.cluster_size); s-cow_bitmap = bitmap_new(length); } +qapi_free_ImageInfoSpecific(bdi.format_specific); } end = s-common.len BDRV_SECTOR_BITS; @@ -544,13 +545,14 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target, if (granularity == 0) { /* Choose the default granularity based on the target file's cluster * size, clamped between 4k and 64k. */ -BlockDriverInfo bdi; +BlockDriverInfo bdi = { .format_specific = NULL }; if (bdrv_get_info(target, bdi) = 0 bdi.cluster_size != 0) { granularity = MAX(4096, bdi.cluster_size); granularity = MIN(65536, granularity); } else { granularity = 65536; } +qapi_free_ImageInfoSpecific(bdi.format_specific); } assert ((granularity (granularity - 1)) == 0); diff --git a/block/qapi.c b/block/qapi.c index a4bc411..f13fbd5 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -110,7 +110,7 @@ void bdrv_query_image_info(BlockDriverState *bs, uint64_t total_sectors; const char *backing_filename; char backing_filename2[1024]; -BlockDriverInfo bdi; +BlockDriverInfo bdi = { .format_specific = NULL }; int ret; Error *err = NULL; ImageInfo *info = g_new0(ImageInfo, 1); @@ -133,6 +133,10 @@ void bdrv_query_image_info(BlockDriverState *bs, } info-dirty_flag = bdi.is_dirty; info-has_dirty_flag = true; +if (bdi.format_specific) { +info-format_specific = bdi.format_specific; +info-has_format_specific = true; +} } backing_filename = bs-backing_file; if (backing_filename[0] != '\0') { diff --git a/include/block/block.h b/include/block/block.h index e6b391c..85e9703 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -18,6 +18,8 @@ typedef struct BlockDriverInfo { /* offset at which the VM state can be saved (0 if not possible) */ int64_t vm_state_offset; bool is_dirty; +/* additional information; NULL if none */ +ImageInfoSpecific *format_specific; } BlockDriverInfo; typedef struct BlockFragInfo { diff --git a/qemu-img.c b/qemu-img.c index b9a848d..ec1ecca 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1125,7 +1125,7 @@ static int img_convert(int argc, char **argv) uint64_t bs_sectors; uint8_t * buf = NULL; const uint8_t *buf1; -BlockDriverInfo bdi; +BlockDriverInfo bdi = { .format_specific = NULL }; QEMUOptionParameter *param = NULL, *create_options = NULL; QEMUOptionParameter *out_baseimg_param; char *options = NULL; @@ -1369,6 +1369,7 @@ static int img_convert(int argc, char **argv) error_report(could not get block driver info); goto out; } +qapi_free_ImageInfoSpecific(bdi.format_specific); cluster_size = bdi.cluster_size; if (cluster_size = 0 || cluster_size IO_BUF_SIZE) { error_report(invalid cluster size); diff --git
[Qemu-devel] [PATCH v2 3/6] block/qapi: Human-readable ImageInfoSpecific dump
Add a function for generically dumping the ImageInfoSpecific information in a human-readable format to block/qapi.c. Use this function in bdrv_image_info_dump and qemu-io-cmds.c:info_f to allow qemu-img info resp. qemu-io -c info to print that format specific information. Signed-off-by: Max Reitz mre...@redhat.com --- block/qapi.c | 121 +++ include/block/qapi.h | 2 + qemu-io-cmds.c | 3 ++ 3 files changed, 126 insertions(+) diff --git a/block/qapi.c b/block/qapi.c index f13fbd5..4fe45d5 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -25,6 +25,9 @@ #include block/qapi.h #include block/block_int.h #include qmp-commands.h +#include qapi-visit.h +#include qapi/qmp-output-visitor.h +#include qapi/qmp/types.h /* * Returns 0 on success, with *p_list either set to describe snapshot @@ -401,6 +404,119 @@ void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f, } } +static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation, + QDict *dict); +static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation, + QList *list); + +static void dump_qobject(fprintf_function func_fprintf, void *f, + int comp_indent, QObject *obj) +{ +switch (qobject_type(obj)) { +case QTYPE_QINT: { +QInt *value = qobject_to_qint(obj); +func_fprintf(f, % PRId64, qint_get_int(value)); +break; +} +case QTYPE_QSTRING: { +QString *value = qobject_to_qstring(obj); +func_fprintf(f, %s, qstring_get_str(value)); +break; +} +case QTYPE_QDICT: { +QDict *value = qobject_to_qdict(obj); +dump_qdict(func_fprintf, f, comp_indent, value); +break; +} +case QTYPE_QLIST: { +QList *value = qobject_to_qlist(obj); +dump_qlist(func_fprintf, f, comp_indent, value); +break; +} +case QTYPE_QFLOAT: { +QFloat *value = qobject_to_qfloat(obj); +func_fprintf(f, %g, qfloat_get_double(value)); +break; +} +case QTYPE_QBOOL: { +QBool *value = qobject_to_qbool(obj); +func_fprintf(f, %s, qbool_get_int(value) ? true : false); +break; +} +case QTYPE_QERROR: { +QString *value = qerror_human((QError *)obj); +func_fprintf(f, %s, qstring_get_str(value)); +break; +} +case QTYPE_NONE: +break; +case QTYPE_MAX: +default: +abort(); +} +} + +static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation, + QList *list) +{ +const QListEntry *entry; +int i = 0; + +for (entry = qlist_first(list); entry; entry = qlist_next(entry), i++) { +qtype_code type = qobject_type(entry-value); +bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST); +const char *format = composite ? %*s[%i]:\n : %*s[%i]: ; + +func_fprintf(f, format, indentation * 4, , i); +dump_qobject(func_fprintf, f, indentation + 1, entry-value); +if (!composite) { +func_fprintf(f, \n); +} +} +} + +static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation, + QDict *dict) +{ +const QDictEntry *entry; + +for (entry = qdict_first(dict); entry; entry = qdict_next(dict, entry)) { +qtype_code type = qobject_type(entry-value); +bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST); +const char *format = composite ? %*s%s:\n : %*s%s: ; +char key[strlen(entry-key) + 1]; +int i; + +/* replace dashes with spaces in key (variable) names */ +for (i = 0; entry-key[i]; i++) { +key[i] = entry-key[i] == '-' ? ' ' : entry-key[i]; +} +key[i] = 0; + +func_fprintf(f, format, indentation * 4, , key); +dump_qobject(func_fprintf, f, indentation + 1, entry-value); +if (!composite) { +func_fprintf(f, \n); +} +} +} + +void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f, + ImageInfoSpecific *info_spec) +{ +Error *local_err = NULL; +QmpOutputVisitor *ov = qmp_output_visitor_new(); +QObject *obj, *data; + +visit_type_ImageInfoSpecific(qmp_output_get_visitor(ov), info_spec, NULL, + local_err); +obj = qmp_output_get_qobject(ov); +assert(qobject_type(obj) == QTYPE_QDICT); +data = qdict_get(qobject_to_qdict(obj), data); +dump_qobject(func_fprintf, f, 0, data); +qmp_output_visitor_cleanup(ov); +} + void bdrv_image_info_dump(fprintf_function func_fprintf, void *f, ImageInfo *info) { @@ -471,4 +587,9
[Qemu-devel] [PATCH v2 0/6] Provide additional info through qemu-img info
qemu-img info provides only pretty general information about an image. For any image format, there might be specific options which cannot be represented in a universal way; for instance, qcow2 provides the compatibility and lazy_refcount options whose values are certainly interesting but currently cannot be output by qemu-img info. Therefore, this series adds a new ImageInfoSpecific union type to ImageInfo and BlockDriverInfo which may be used by block drivers as a template for new types dedicated to the specific information they can provide. It also adds support to qemu-img info and qemu-io -c info to print the content of these specific structures. v2: - following Eric's recommendation: changed the representation of the format specific information from an uninterpreted blobbed string to a union of format specific types Max Reitz (6): qapi: Add ImageInfoSpecific type block: Add ImageInfoSpecific to BlockDriverInfo block/qapi: Human-readable ImageInfoSpecific dump qcow2: Add support for ImageInfoSpecific qemu-iotests: Discard specific info in _img_info qemu-iotests: Additional info from qemu-img info block.c | 3 +- block/mirror.c | 6 +- block/qapi.c | 127 ++- block/qcow2.c| 12 include/block/block.h| 2 + include/block/qapi.h | 2 + qapi-schema.json | 34 +++- qemu-img.c | 3 +- qemu-io-cmds.c | 9 ++- tests/qemu-iotests/064 | 72 tests/qemu-iotests/064.out | 22 tests/qemu-iotests/common.rc | 19 ++- tests/qemu-iotests/group | 1 + 13 files changed, 304 insertions(+), 8 deletions(-) create mode 100755 tests/qemu-iotests/064 create mode 100644 tests/qemu-iotests/064.out -- 1.8.3.1
[Qemu-devel] [PATCH v2 4/6] qcow2: Add support for ImageInfoSpecific
Add a new ImageInfoSpecificQCow2 type as a subtype of ImageInfoSpecific. This contains the compatibility level as a string and an optional lazy_refcounts boolean (optional means mandatory for compat = 1.1 and not available for compat == 0.10). In qcow2_get_info, fill the BlockDriverInfo.format_specific field with that information. Signed-off-by: Max Reitz mre...@redhat.com --- block/qcow2.c| 12 qapi-schema.json | 16 2 files changed, 28 insertions(+) diff --git a/block/qcow2.c b/block/qcow2.c index 4bc679a..e088c0a 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1755,8 +1755,20 @@ static int64_t qcow2_vm_state_offset(BDRVQcowState *s) static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { BDRVQcowState *s = bs-opaque; + bdi-cluster_size = s-cluster_size; bdi-vm_state_offset = qcow2_vm_state_offset(s); + +bdi-format_specific = g_new0(ImageInfoSpecific, 1); +bdi-format_specific-kind = IMAGE_INFO_SPECIFIC_KIND_QCOW2; +bdi-format_specific-qcow2 = g_new0(ImageInfoSpecificQCow2, 1); +if (s-qcow_version == 2) { +bdi-format_specific-qcow2-compat = g_strdup(0.10); +} else if (s-qcow_version == 3) { +bdi-format_specific-qcow2-compat = g_strdup(1.1); +bdi-format_specific-qcow2-lazy_refcounts = s-use_lazy_refcounts; +bdi-format_specific-qcow2-has_lazy_refcounts = true; +} return 0; } diff --git a/qapi-schema.json b/qapi-schema.json index eebf851..cadf40b 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -210,6 +210,21 @@ 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } } ## +# @ImageInfoSpecificQCow2: +# +# @compat: compatibility level +# +# @lazy-refcounts: #optional on or off; only valid for compat = 1.1 +# +# Since: 1.7 +## +{ 'type': 'ImageInfoSpecificQCow2', + 'data': { + 'compat': 'str', + '*lazy-refcounts': 'bool' + } } + +## # @ImageInfoSpecific: # # A discriminated record of image format specific information structures. @@ -219,6 +234,7 @@ { 'union': 'ImageInfoSpecific', 'data': { + 'qcow2': 'ImageInfoSpecificQCow2' } } ## -- 1.8.3.1
[Qemu-devel] [PATCH v2 5/6] qemu-iotests: Discard specific info in _img_info
In _img_info, filter out additional information specific to the image format provided by qemu-img info, since tests designed for multiple image formats would produce different outputs for every image format else. Signed-off-by: Max Reitz mre...@redhat.com --- tests/qemu-iotests/common.rc | 19 ++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 5e077c3..13f62d8 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -181,12 +181,29 @@ _check_test_img() _img_info() { +discard=0 $QEMU_IMG info $@ $TEST_IMG 21 | \ sed -e s#$IMGPROTO:$TEST_DIR#TEST_DIR#g \ -e s#$TEST_DIR#TEST_DIR#g \ -e s#$IMGFMT#IMGFMT#g \ -e /^disk size:/ D \ --e /actual-size/ D +-e /actual-size/ D | \ +while IFS='' read line; do +if [ $line == Format specific information: ]; then +discard=1 +elif [ `echo $line | sed -e 's/^ *//'` == 'format-specific: {' ]; then +discard=2 +json_indent=`echo $line | sed -e 's/^\( *\).*$/\1/'` +fi +if [ $discard == 0 ]; then +echo $line +elif [ $discard == 1 -a -z $line ]; then +echo +discard=0 +elif [ $discard == 2 -a `echo $line | sed -e 's/ *$//'` == ${json_indent}}, ]; then +discard=0 +fi +done } _get_pids_by_name() -- 1.8.3.1
Re: [Qemu-devel] [PATCH 3/4] kvm: Common device control API functions
On 23 August 2013 20:41, Christoffer Dall christoffer.d...@linaro.org wrote: Introduces two simple functions: int kvm_device_ioctl(int fd, int type, ...); int kvm_create_device(KVMState *s, uint64_t type, bool test); These functions wrap the basic ioctl-based interactions with KVM in a way similar to other KVM ioctl wrappers. Signed-off-by: Christoffer Dall christoffer.d...@linaro.org --- include/sysemu/kvm.h |5 + kvm-all.c| 39 +++ trace-events |1 + 3 files changed, 45 insertions(+) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 1e5847e..84ca5ef 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -190,6 +190,11 @@ int kvm_vm_ioctl(KVMState *s, int type, ...); int kvm_vcpu_ioctl(CPUState *cpu, int type, ...); +int kvm_device_ioctl(int fd, int type, ...); + +int kvm_create_device(KVMState *s, uint64_t type, bool test); Could we have doc comments for these, please? + + /* Arch specific hooks */ extern const KVMCapabilityInfo kvm_arch_required_capabilities[]; diff --git a/kvm-all.c b/kvm-all.c index fe64f3b..957b961 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1770,6 +1770,24 @@ int kvm_vcpu_ioctl(CPUState *cpu, int type, ...) return ret; } +int kvm_device_ioctl(int fd, int type, ...) +{ +int ret; +void *arg; +va_list ap; + +va_start(ap, type); +arg = va_arg(ap, void *); +va_end(ap); + +trace_kvm_device_ioctl(fd, type, arg); +ret = ioctl(fd, type, arg); +if (ret == -1) { +ret = -errno; +} +return ret; +} + int kvm_has_sync_mmu(void) { return kvm_check_extension(kvm_state, KVM_CAP_SYNC_MMU); @@ -2064,3 +2082,24 @@ int kvm_on_sigbus(int code, void *addr) { return kvm_arch_on_sigbus(code, addr); } + +int kvm_create_device(KVMState *s, uint64_t type, bool test) +{ +int ret; +struct kvm_create_device create_dev; + +create_dev.type = type; +create_dev.fd = -1; +create_dev.flags = (test) ? KVM_CREATE_DEVICE_TEST : 0; Why the brackets round 'test' ? + +if (!kvm_check_extension(s, KVM_CAP_DEVICE_CTRL)) { +return -1; We should probably return -$some_errno here, since we pass through a -errno return from kvm_vm_ioctl below. +} + +ret = kvm_vm_ioctl(s, KVM_CREATE_DEVICE, create_dev); +if (ret) { +return ret; +} + +return (test) ? 0 : create_dev.fd; +} thanks -- PMM
[Qemu-devel] [PATCH v2 6/6] qemu-iotests: Additional info from qemu-img info
Add a test for the additional information now provided by qemu-img info when used on qcow2 images. Signed-off-by: Max Reitz mre...@redhat.com --- tests/qemu-iotests/064 | 72 ++ tests/qemu-iotests/064.out | 22 ++ tests/qemu-iotests/group | 1 + 3 files changed, 95 insertions(+) create mode 100755 tests/qemu-iotests/064 create mode 100644 tests/qemu-iotests/064.out diff --git a/tests/qemu-iotests/064 b/tests/qemu-iotests/064 new file mode 100755 index 000..4979db5 --- /dev/null +++ b/tests/qemu-iotests/064 @@ -0,0 +1,72 @@ +#!/bin/bash +# +# Test for additional information emitted by qemu-img info on qcow2 +# images +# +# Copyright (C) 2013 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# + +# creator +owner=mre...@redhat.com + +seq=`basename $0` +echo QA output created by $seq + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap _cleanup; exit \$status 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +# This tests qocw2-specific low-level functionality +_supported_fmt qcow2 +_supported_proto generic +_supported_os Linux + +IMG_SIZE=64M + +echo +echo === Testing qcow2 image with -o compat=0.10 === +echo +IMGOPTS=compat=0.10 _make_test_img $IMG_SIZE +# don't use _img_info, since that function will filter out the +# additional information we're about to test for +$QEMU_IMG info $TEST_IMG | grep Format specific information: -A 42 + +echo +echo === Testing qcow2 image with -o compat=1.1,lazy_refcounts=off === +echo +IMGOPTS=compat=1.1,lazy_refcounts=off _make_test_img $IMG_SIZE +$QEMU_IMG info $TEST_IMG | grep Format specific information: -A 42 + +echo +echo === Testing qcow2 image with -o compat=1.1,lazy_refcounts=on === +echo +IMGOPTS=compat=1.1,lazy_refcounts=on _make_test_img $IMG_SIZE +$QEMU_IMG info $TEST_IMG | grep Format specific information: -A 42 + +# success, all done +echo *** done +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/064.out b/tests/qemu-iotests/064.out new file mode 100644 index 000..6ce5b43 --- /dev/null +++ b/tests/qemu-iotests/064.out @@ -0,0 +1,22 @@ +QA output created by 064 + +=== Testing qcow2 image with -o compat=0.10 === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Format specific information: +compat: 0.10 + +=== Testing qcow2 image with -o compat=1.1,lazy_refcounts=off === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Format specific information: +compat: 1.1 +lazy refcounts: false + +=== Testing qcow2 image with -o compat=1.1,lazy_refcounts=on === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Format specific information: +compat: 1.1 +lazy refcounts: true +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index b696242..740cd84 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -66,3 +66,4 @@ 059 rw auto 060 rw auto 062 rw auto +064 rw auto -- 1.8.3.1
Re: [Qemu-devel] [PATCH 1/2] linux-headers: update for s390 floating interrupt controller
On 06/09/13 14:19, Jens Freimann wrote: Add symbols required for the s390 floating interrupt controller (flic) Signed-off-by: Jens Freimann jf...@linux.vnet.ibm.com As Peter said, this should come via a sync, but you already mentioned that in your cover-letter. I will Ack the kernel patch and let it come via that way.
Re: [Qemu-devel] [PATCH v2 1/2] KVM: s390: add and extend interrupt information data structs
On 06/09/13 14:19, Jens Freimann wrote: With the currently available struct kvm_s390_interrupt it is not possible to inject every kind of interrupt as defined in the z/Architecture. Add additional interruption parameters to the structures and move it to kvm.h Signed-off-by: Jens Freimann jf...@linux.vnet.ibm.com Reviewed-by: Cornelia Huck cornelia.h...@de.ibm.com Acked-by: Christian Borntraeger borntrae...@de.ibm.com --- arch/s390/include/asm/kvm_host.h | 34 +- include/uapi/linux/kvm.h | 63 2 files changed, 64 insertions(+), 33 deletions(-) diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index e87ecaa..adb05c5 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -16,6 +16,7 @@ #include linux/hrtimer.h #include linux/interrupt.h #include linux/kvm_host.h +#include linux/kvm.h #include asm/debug.h #include asm/cpu.h @@ -162,18 +163,6 @@ struct kvm_vcpu_stat { u32 diagnose_9c; }; -struct kvm_s390_io_info { - __u16subchannel_id;/* 0x0b8 */ - __u16subchannel_nr;/* 0x0ba */ - __u32io_int_parm; /* 0x0bc */ - __u32io_int_word; /* 0x0c0 */ -}; - -struct kvm_s390_ext_info { - __u32 ext_params; - __u64 ext_params2; -}; - #define PGM_OPERATION0x01 #define PGM_PRIVILEGED_OP 0x02 #define PGM_EXECUTE 0x03 @@ -182,27 +171,6 @@ struct kvm_s390_ext_info { #define PGM_SPECIFICATION0x06 #define PGM_DATA 0x07 -struct kvm_s390_pgm_info { - __u16 code; -}; - -struct kvm_s390_prefix_info { - __u32 address; -}; - -struct kvm_s390_extcall_info { - __u16 code; -}; - -struct kvm_s390_emerg_info { - __u16 code; -}; - -struct kvm_s390_mchk_info { - __u64 cr14; - __u64 mcic; -}; - struct kvm_s390_interrupt_info { struct list_head list; u64 type; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 99c2533..eeb08a1 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -434,6 +434,69 @@ struct kvm_s390_interrupt { __u64 parm64; }; +struct kvm_s390_io_info { + __u16 subchannel_id; + __u16 subchannel_nr; + __u32 io_int_parm; + __u32 io_int_word; +}; + +struct kvm_s390_ext_info { + __u32 ext_params; + __u32 pad; + __u64 ext_params2; +}; + +struct kvm_s390_pgm_info { + __u64 trans_exc_code; + __u64 mon_code; + __u64 per_address; + __u32 data_exc_code; + __u16 code; + __u16 mon_class_nr; + __u8 per_code; + __u8 per_atmid; + __u8 exc_access_id; + __u8 per_access_id; + __u8 op_access_id; + __u8 pad[3]; +}; + +struct kvm_s390_prefix_info { + __u32 address; +}; + +struct kvm_s390_extcall_info { + __u16 code; +}; + +struct kvm_s390_emerg_info { + __u16 code; +}; + +struct kvm_s390_mchk_info { + __u64 cr14; + __u64 mcic; + __u64 failing_storage_address; + __u32 ext_damage_code; + __u32 pad; + __u8 fixed_logout[16]; +}; + +struct kvm_s390_irq { + __u64 type; + union { + struct kvm_s390_io_info io; + struct kvm_s390_ext_info ext; + struct kvm_s390_pgm_info pgm; + struct kvm_s390_emerg_info emerg; + struct kvm_s390_extcall_info extcall; + struct kvm_s390_prefix_info prefix; + struct kvm_s390_mchk_info mchk; + char reserved[64]; + }; +}; + /* for KVM_SET_GUEST_DEBUG */ #define KVM_GUESTDBG_ENABLE 0x0001
Re: [Qemu-devel] [PATCH v2 2/2] KVM: s390: add floating irq controller
On 06/09/13 14:19, Jens Freimann wrote: This patch adds a floating irq controller as a kvm_device. It will be necessary for migration of floating interrupts as well as for hardening the reset code by allowing user space to explicitly remove all pending floating interrupts. Signed-off-by: Jens Freimann jf...@linux.vnet.ibm.com Reviewed-by: Cornelia Huck cornelia.h...@de.ibm.com Acked-by: Christian Borntraeger borntrae...@de.ibm.com --- Documentation/virtual/kvm/devices/s390_flic.txt | 36 +++ arch/s390/include/asm/kvm_host.h| 1 + arch/s390/include/uapi/asm/kvm.h| 5 + arch/s390/kvm/interrupt.c | 304 arch/s390/kvm/kvm-s390.c| 1 + include/linux/kvm_host.h| 1 + include/uapi/linux/kvm.h| 2 + virt/kvm/kvm_main.c | 5 + 8 files changed, 304 insertions(+), 51 deletions(-) diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt new file mode 100644 index 000..06aef31 --- /dev/null +++ b/Documentation/virtual/kvm/devices/s390_flic.txt @@ -0,0 +1,36 @@ +FLIC (floating interrupt controller) + + +FLIC handles floating (non per-cpu) interrupts, i.e. I/O, service and some +machine check interruptions. All interrupts are stored in a per-vm list of +pending interrupts. FLIC performs operations on this list. + +Only one FLIC instance may be instantiated. + +FLIC provides support to +- add/delete interrupts (KVM_DEV_FLIC_ENQUEUE and _DEQUEUE) +- purge all pending floating interrupts (KVM_DEV_FLIC_CLEAR_IRQS) + +Groups: + KVM_DEV_FLIC_ENQUEUE +Adds one interrupt to the list of pending floating interrupts. Interrupts +are taken from this list for injection into the guest. attr contains +a struct kvm_s390_irq which contains all data relevant for +interrupt injection. +The format of the data structure kvm_s390_irq as it is copied from userspace +is defined in usr/include/linux/kvm.h. +For historic reasons list members are stored in a different data structure, i.e. +we need to copy the relevant data into a struct kvm_s390_interrupt_info +which can then be added to the list. + + KVM_DEV_FLIC_DEQUEUE +Takes one element off the pending interrupts list and copies it into userspace. +Dequeued interrupts are not injected into the guest. +attr-addr contains the userspace address of a struct kvm_s390_irq. +List elements are stored in the format of struct kvm_s390_interrupt_info +(arch/s390/include/asm/kvm_host.h) and are copied into a struct kvm_s390_irq +(usr/include/linux/kvm.h) + + KVM_DEV_FLIC_CLEAR_IRQS +Simply deletes all elements from the list of currently pending floating interrupts. +No interrupts are injected into the guest. diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index adb05c5..e1cc166 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -238,6 +238,7 @@ struct kvm_arch{ struct sca_block *sca; debug_info_t *dbf; struct kvm_s390_float_interrupt float_int; + struct kvm_device *flic; struct gmap *gmap; int css_support; }; diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h index d25da59..33d52b8 100644 --- a/arch/s390/include/uapi/asm/kvm.h +++ b/arch/s390/include/uapi/asm/kvm.h @@ -16,6 +16,11 @@ #define __KVM_S390 +/* Device control API: s390-specific devices */ +#define KVM_DEV_FLIC_DEQUEUE 1 +#define KVM_DEV_FLIC_ENQUEUE 2 +#define KVM_DEV_FLIC_CLEAR_IRQS 3 + /* for KVM_GET_REGS and KVM_SET_REGS */ struct kvm_regs { /* general purpose regs for s390 */ diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 7f35cb3..d6d5e36 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -656,53 +656,86 @@ struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, return inti; } -int kvm_s390_inject_vm(struct kvm *kvm, -struct kvm_s390_interrupt *s390int) +static void __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti) { struct kvm_s390_local_interrupt *li; struct kvm_s390_float_interrupt *fi; - struct kvm_s390_interrupt_info *inti, *iter; + struct kvm_s390_interrupt_info *iter; int sigcpu; + mutex_lock(kvm-lock); + fi = kvm-arch.float_int; + spin_lock(fi-lock); + if (!is_ioint(inti-type)) { + list_add_tail(inti-list, fi-list); + } else { + u64 isc_bits = int_word_to_isc_bits(inti-io.io_int_word); + + /* Keep I/O interrupts sorted in isc order. */ + list_for_each_entry(iter, fi-list, list) { +
Re: [Qemu-devel] [PATCH] vl.c: Implement SIGILL signal handler for triggering SIGSEGV
On 09/06/2013 12:50 AM, Anthony Liguori wrote: On Thu, Sep 5, 2013 at 7:20 AM, Michal Novotny minov...@redhat.com wrote: This is the patch to introduce SIGILL handler to be able to trigger SIGSEGV signal in qemu. This has been written to help debugging state when qemu crashes by SIGSEGV as a simple reproducer to emulate such situation in case of need. Signed-off-by: Michal Novotny minov...@redhat.com --- vl.c | 24 1 file changed, 24 insertions(+) diff --git a/vl.c b/vl.c index 7e04641..3966271 100644 --- a/vl.c +++ b/vl.c @@ -2897,6 +2897,26 @@ static int object_create(QemuOpts *opts, void *opaque) return 0; } +#ifdef CONFIG_POSIX +static void signal_handler(int signal) +{ +int *p = NULL; + +*p = 0xDEADBEEF; I won't repeat the questions from Paolo and Lazlo (I share their confusion) but will simply add that you cannot rely on NULL address accessing causing a SEGV. Even with all the use of volatile in the world, there's no guarantee this is going to crash. Regards, Anthony Liguori The idea was to trigger SIGSEGV (working at least at test conditions) to find out current qemu state. Of course, using gdb is also an option. Please ignore this patch, it was rather one purpose patch used in testing... Thanks, Michal +} + +static void setup_signal_handlers(void) +{ +struct sigaction action; + +memset(action, 0, sizeof(action)); +sigfillset(action.sa_mask); +action.sa_handler = signal_handler; +action.sa_flags = 0; +sigaction(SIGILL, action, NULL); +} +#endif + int main(int argc, char **argv, char **envp) { int i; @@ -2945,6 +2965,10 @@ int main(int argc, char **argv, char **envp) #endif } +#ifdef CONFIG_POSIX +setup_signal_handlers(); +#endif + module_call_init(MODULE_INIT_QOM); qemu_add_opts(qemu_drive_opts); -- 1.7.11.7 -- Michal Novotny minov...@redhat.com, RHCE, Red Hat Virtualization | libvirt-php bindings | php-virt-control.org
Re: [Qemu-devel] [PATCH 2/2] s390x/kvm: implement floating-interrupt controller device
On 06/09/13 14:19, Jens Freimann wrote: This patch implements a floating-interrupt controller device (flic) which interacts with the s390 flic kvm_device. It provides functionality to: * clear all pending floating interrupts in the kernel at device reset * inject/retrieve interrupts into the kernel (used for migration) Signed-off-by: Jens Freimann jf...@linux.vnet.ibm.com Reviewed-by: Thomas Huth th...@linux.vnet.ibm.com Acked-by: Christian Borntraeger borntrae...@de.ibm.com --- default-configs/s390x-softmmu.mak | 1 + hw/intc/Makefile.objs | 1 + hw/intc/s390_flic.c | 164 ++ hw/s390x/s390-virtio-ccw.c| 8 +- hw/s390x/s390-virtio.c| 2 + include/hw/s390x/s390_flic.h | 31 +++ 6 files changed, 206 insertions(+), 1 deletion(-) diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak index 81fbc68..d843dc0 100644 --- a/default-configs/s390x-softmmu.mak +++ b/default-configs/s390x-softmmu.mak @@ -1,2 +1,3 @@ CONFIG_VIRTIO=y CONFIG_SCLPCONSOLE=y +CONFIG_S390_FLIC=$(CONFIG_KVM) diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs index 2851eed..b2305aa 100644 --- a/hw/intc/Makefile.objs +++ b/hw/intc/Makefile.objs @@ -23,3 +23,4 @@ obj-$(CONFIG_OMAP) += omap_intc.o obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o obj-$(CONFIG_SH4) += sh_intc.o obj-$(CONFIG_XICS) += xics.o +obj-$(CONFIG_S390_FLIC) += s390_flic.o diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c new file mode 100644 index 000..9dfaafa --- /dev/null +++ b/hw/intc/s390_flic.c @@ -0,0 +1,164 @@ +/* + * QEMU S390x KVM floating interrupt controller (flic) + * + * Copyright 2013 IBM Corp. + * Author(s): Jens Freimann jf...@linux.vnet.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include sys/ioctl.h +#include hw/sysbus.h +#include sysemu/kvm.h +#include migration/qemu-file.h +#include hw/s390x/s390_flic.h + +void s390_flic_init(void) +{ +DeviceState *dev; + +if (kvm_enabled()) { +dev = qdev_create(NULL, s390-flic); +object_property_add_child(qdev_get_machine(), s390-flic, + OBJECT(dev), NULL); +qdev_init_nofail(dev); +} +} + +static int flic_dequeue_irq(QEMUFile *f, struct kvm_s390_irq *s390irq, +KVMS390FLICState *flic) +{ +struct kvm_device_attr attr; +int rc; + +attr.group = KVM_DEV_FLIC_DEQUEUE; +attr.addr = (uint64_t) s390irq; + +rc = ioctl(flic-fd, KVM_GET_DEVICE_ATTR, attr); + +return rc ? -errno : 0; +} + +static int flic_enqueue_irq(QEMUFile *f, struct kvm_s390_irq *s390irq, +KVMS390FLICState *flic) +{ +int rc; +struct kvm_device_attr attr; + +attr.group = KVM_DEV_FLIC_ENQUEUE; +attr.addr = (uint64_t) s390irq; + +rc = ioctl(flic-fd, KVM_SET_DEVICE_ATTR, attr); + +return rc ? -errno : 0; +} + +/* Save pending floating interrupts. */ +static void kvm_floating_interrupt_save(QEMUFile *f, void *opaque) +{ +struct kvm_s390_irq s390irq = {0}; +int r = 0; + +while (!r) { +r = flic_dequeue_irq(f, s390irq, opaque); +if (r == -ENODATA) { +/* At end of list: write special marker */ +memset(s390irq, 0, sizeof(s390irq)); +s390irq.type = 0x; +} +qemu_put_buffer(f, (uint8_t *) s390irq, sizeof(s390irq)); +} +} + +/* Load pending floating interrupts. */ +static int kvm_floating_interrupt_load(QEMUFile *f, void *opaque, int version_id) +{ +int r = 0; +struct kvm_s390_irq s390irq = {0}; + +while (!r) { +qemu_get_buffer(f, (uint8_t *) s390irq, sizeof(s390irq)); +/* Watch for marker indicating end of list */ +if (s390irq.type == 0x) { +return 0; +} +r = flic_enqueue_irq(f, s390irq, (struct KVMS390FLICState *) opaque); +} + +return r; +} + +static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) +{ +KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); +struct kvm_create_device cd = {0}; +int ret; + +flic_state-fd = -1; +if (!kvm_check_extension(kvm_state, KVM_CAP_DEVICE_CTRL)) { +return; +} + +cd.type = KVM_DEV_TYPE_FLIC; +ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, cd); +if (ret 0) { +perror(flic: couldn't create kvm_device); +return; +} +flic_state-fd = cd.fd; + +/* Register savevm handler for floating interrupts */ +register_savevm(NULL, floatingint, 0, 1, kvm_floating_interrupt_save, +kvm_floating_interrupt_load, (void *) flic_state); +} + +static void
Re: [Qemu-devel] [PATCH v2 0/2] KVM: s390: add floating irq controller
On 06/09/13 14:19, Jens Freimann wrote: This series adds a kvm_device that acts as a irq controller for floating interrupts. As a first step it implements functionality to retrieve and inject interrupts for the purpose of migration and for hardening the reset code by allowing user space to explicitly remove all pending floating interrupts. PFAULT patches will also use this device for enabling/disabling pfault, therefore the pfault patch series will be reworked to use this device. * Patch 1/2 adds a new data structure to hold interrupt information. The current one (struct kvm_s390_interrupt) does not allow to inject every kind of interrupt, e.g. some data for program interrupts and machine check interruptions were missing. * Patch 2/2 adds a kvm_device which supports getting/setting currently pending floating interrupts as well as deleting all currently pending interrupts Jens Freimann (2): KVM: s390: add and extend interrupt information data structs KVM: s390: add floating irq controller Documentation/virtual/kvm/devices/s390_flic.txt | 36 +++ arch/s390/include/asm/kvm_host.h| 35 +-- arch/s390/include/uapi/asm/kvm.h| 5 + arch/s390/kvm/interrupt.c | 304 arch/s390/kvm/kvm-s390.c| 1 + include/linux/kvm_host.h| 1 + include/uapi/linux/kvm.h| 65 + virt/kvm/kvm_main.c | 5 + 8 files changed, 368 insertions(+), 84 deletions(-) create mode 100644 Documentation/virtual/kvm/devices/s390_flic.txt Gleb, Paolo, since the qemu part relies on a kernel header file, it makes sense to not only let the kernel part go via the kvm tree, but also the qemu part. I want Alex to Ack the interface, and if he agrees then I am fine with applying the whole series. If nothing else comes up, feel free to apply the small change request from Peter yourself or ask Jens for a resend. --snip --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -908,7 +908,7 @@ struct kvm_device_attr { #define KVM_DEV_TYPE_FSL_MPIC_20 1 #define KVM_DEV_TYPE_FSL_MPIC_42 2 #define KVM_DEV_TYPE_XICS 3 -#define KVM_DEV_TYPE_FLIC 4 +#define KVM_DEV_TYPE_FLIC 5 /* * ioctls for VM fds --snip
Re: [Qemu-devel] [PATCH 4/4] arm: vgic device control api support
On 23 August 2013 20:41, Christoffer Dall christoffer.d...@linaro.org wrote: Support creating the ARM vgic device through the device control API and setting the base address for the distributor and cpu interfaces in KVM VMs using this API. Because the older KVM_CREATE_IRQCHIP interface needs the irq chip to be created prior to creating the VCPUs, we first test if if can use the if we device control API in kvm_arch_irqchip_create (using the test flag from the device control API). If we cannot, it means we have to fall back to KVM_CREATE_IRQCHIP and use the older ioctl at this point in time. If however, we can use the device control API, we don't do anything and wait until the arm_gic_kvm driver initializes and let that use the device control API. Signed-off-by: Christoffer Dall christoffer.d...@linaro.org --- hw/intc/arm_gic_kvm.c | 23 +-- target-arm/kvm.c | 49 ++--- target-arm/kvm_arm.h | 18 -- 3 files changed, 75 insertions(+), 15 deletions(-) diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c index f713975..9f0a852 100644 --- a/hw/intc/arm_gic_kvm.c +++ b/hw/intc/arm_gic_kvm.c @@ -35,6 +35,7 @@ typedef struct KVMARMGICClass { ARMGICCommonClass parent_class; DeviceRealize parent_realize; void (*parent_reset)(DeviceState *dev); +int dev_fd; } KVMARMGICClass; This looks wrong -- surely we should have a dev_fd per instance of KVMARMGIC, not just one in the class struct? static void kvm_arm_gic_set_irq(void *opaque, int irq, int level) @@ -97,6 +98,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) GICState *s = KVM_ARM_GIC(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s); +int ret; kgc-parent_realize(dev, errp); if (error_is_set(errp)) { @@ -119,13 +121,27 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) for (i = 0; i s-num_cpu; i++) { sysbus_init_irq(sbd, s-parent_irq[i]); } + +/* Try to create the device via the device control API */ +kgc-dev_fd = -1; +ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false); +if (ret = 0) { +kgc-dev_fd = ret; +} else if (ret != -ENODEV) { +fprintf(stderr, Error creating in-kernel VGIC: %d\n, ret); +abort(); We shouldn't abort here, we can just report our failure back to the caller via the Error** it passed us: error_setg_errno(errp, -ret, error creating in-kernel VGIC); return; (there's also an error_setg() if there's no errno involved; both versions use a printf-style format string and can take extra args accordingly.) +} + /* Distributor */ memory_region_init_reservation(s-iomem, OBJECT(s), kvm-gic_dist, 0x1000); sysbus_init_mmio(sbd, s-iomem); kvm_arm_register_device(s-iomem, (KVM_ARM_DEVICE_VGIC_V2 KVM_ARM_DEVICE_ID_SHIFT) -| KVM_VGIC_V2_ADDR_TYPE_DIST); +| KVM_VGIC_V2_ADDR_TYPE_DIST, +KVM_DEV_ARM_VGIC_GRP_ADDR, +KVM_VGIC_V2_ADDR_TYPE_DIST, +kgc-dev_fd); /* CPU interface for current core. Unlike arm_gic, we don't * provide the interface for core #N memory regions, because * cores with a VGIC don't have those. @@ -135,7 +151,10 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) sysbus_init_mmio(sbd, s-cpuiomem[0]); kvm_arm_register_device(s-cpuiomem[0], (KVM_ARM_DEVICE_VGIC_V2 KVM_ARM_DEVICE_ID_SHIFT) -| KVM_VGIC_V2_ADDR_TYPE_CPU); +| KVM_VGIC_V2_ADDR_TYPE_CPU, +KVM_DEV_ARM_VGIC_GRP_ADDR, +KVM_VGIC_V2_ADDR_TYPE_CPU, +kgc-dev_fd); } static void kvm_arm_gic_class_init(ObjectClass *klass, void *data) diff --git a/target-arm/kvm.c b/target-arm/kvm.c index 2484d90..aed3d86 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -184,8 +184,10 @@ out: */ typedef struct KVMDevice { struct kvm_arm_device_addr kda; +struct kvm_device_attr kdattr; MemoryRegion *mr; QSLIST_ENTRY(KVMDevice) entries; +int dev_fd; } KVMDevice; static QSLIST_HEAD(kvm_devices_head, KVMDevice) kvm_devices_head; @@ -219,6 +221,28 @@ static MemoryListener devlistener = { .region_del = kvm_arm_devlistener_del, }; +static void kvm_arm_set_device_addr(KVMDevice *kd) +{ +struct kvm_device_attr *attr = kd-kdattr; +int ret; + +/* If the device control API is available and we have a device fd on the + * KVMDevice struct, let's use the newer API */ putting the closing */ on a line of its
Re: [Qemu-devel] [RFC v2 3/6] block: Error parameter for open functions
Am 05.09.2013 um 15:55 hat Max Reitz geschrieben: Add an Error ** parameter to bdrv_open, bdrv_file_open and associated functions to allow more specific error messages. Signed-off-by: Max Reitz mre...@redhat.com --- block.c | 98 --- block/blkdebug.c | 2 +- block/blkverify.c | 4 +-- block/cow.c | 2 +- block/mirror.c| 5 +-- block/qcow.c | 2 +- block/qcow2.c | 4 +-- block/qed.c | 3 +- block/sheepdog.c | 4 +-- block/vmdk.c | 5 +-- block/vvfat.c | 2 +- blockdev.c| 30 +++- include/block/block.h | 6 ++-- qemu-img.c| 23 +++- qemu-io.c | 14 +--- qemu-nbd.c| 6 ++-- 16 files changed, 125 insertions(+), 85 deletions(-) diff --git a/block.c b/block.c index f485906..8da32b2 100644 --- a/block.c +++ b/block.c @@ -525,7 +525,7 @@ BlockDriver *bdrv_find_protocol(const char *filename, } static int find_image_format(BlockDriverState *bs, const char *filename, - BlockDriver **pdrv) + BlockDriver **pdrv, Error **errp) { int score, score_max; BlockDriver *drv1, *drv; @@ -536,6 +536,7 @@ static int find_image_format(BlockDriverState *bs, const char *filename, if (bs-sg || !bdrv_is_inserted(bs) || bdrv_getlength(bs) == 0) { drv = bdrv_find_format(raw); if (!drv) { +error_setg(errp, Could not find raw image format); ret = -ENOENT; } *pdrv = drv; @@ -544,6 +545,8 @@ static int find_image_format(BlockDriverState *bs, const char *filename, ret = bdrv_pread(bs, 0, buf, sizeof(buf)); if (ret 0) { +error_setg_errno(errp, -ret, Could not read image for determining its + format); *pdrv = NULL; return ret; } @@ -560,6 +563,8 @@ static int find_image_format(BlockDriverState *bs, const char *filename, } } if (!drv) { +error_setg(errp, Could not determine image format: No compatible + driver found); ret = -ENOENT; } *pdrv = drv; @@ -679,10 +684,11 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags) * Removes all processed options from *options. */ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, -QDict *options, int flags, BlockDriver *drv) +QDict *options, int flags, BlockDriver *drv, Error **errp) { int ret, open_flags; const char *filename; +Error *local_err = NULL; assert(drv != NULL); assert(bs-file == NULL); @@ -711,6 +717,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, bs-read_only = !(open_flags BDRV_O_RDWR); if (use_bdrv_whitelist !bdrv_is_whitelisted(drv, bs-read_only)) { +error_setg(errp, Driver '%s' is not whitelisted, drv-format_name); return -ENOTSUP; } @@ -734,25 +741,30 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, if (drv-bdrv_file_open) { assert(file == NULL); assert(drv-bdrv_parse_filename || filename != NULL); -ret = drv-bdrv_file_open(bs, options, open_flags, NULL); +ret = drv-bdrv_file_open(bs, options, open_flags, local_err); } else { if (file == NULL) { -qerror_report(ERROR_CLASS_GENERIC_ERROR, Can't use '%s' as a - block driver for the protocol level, - drv-format_name); +error_setg(errp, Can't use '%s' as a block driver for the + protocol level, drv-format_name); ret = -EINVAL; goto free_and_fail; } bs-file = file; -ret = drv-bdrv_open(bs, options, open_flags, NULL); +ret = drv-bdrv_open(bs, options, open_flags, local_err); } if (ret 0) { +if (error_is_set(local_err)) { +error_propagate(errp, local_err); +} else { +error_setg_errno(errp, -ret, Could not open '%s', filename); filename can be NULL. This happens in cases like: -drive file.driver=nbd,file.host=localhost +} goto free_and_fail; } ret = refresh_total_sectors(bs, bs-total_sectors); if (ret 0) { +error_setg_errno(errp, -ret, Could not refresh total sector count); goto free_and_fail; } diff --git a/qemu-img.c b/qemu-img.c index b9a848d..607981e 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -264,6 +264,7 @@ static BlockDriverState *bdrv_new_open(const char *filename, BlockDriverState *bs; BlockDriver *drv; char password[256]; +Error *local_err = NULL; int ret; bs = bdrv_new(image); @@
Re: [Qemu-devel] [RFC v2 1/6] bdrv: Use Error for opening images
Am 05.09.2013 um 15:55 hat Max Reitz geschrieben: Add an Error ** parameter to BlockDriver.bdrv_open and BlockDriver.bdrv_file_open to allow more specific error messages. Signed-off-by: Max Reitz mre...@redhat.com diff --git a/block/iscsi.c b/block/iscsi.c index 2bbee1f..2464f19 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1046,7 +1046,8 @@ static QemuOptsList runtime_opts = { * We support iscsi url's on the form * iscsi://[username%password@]host[:port]/targetname/lun */ -static int iscsi_open(BlockDriverState *bs, QDict *options, int flags) +static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) { IscsiLun *iscsilun = bs-opaque; struct iscsi_context *iscsi = NULL; block/iscsi.c: In function 'iscsi_create': block/iscsi.c:1265:5: error: too few arguments to function 'iscsi_open' block/iscsi.c:1049:12: note: declared here