Re: [Qemu-devel] [PATCH v3] Add getsockopt for settable SOL_IPV6 options
Patchew URL: https://patchew.org/QEMU/20181214154130.4069-1-tom.des...@gmail.com/ Hi, This series seems to have some coding style problems. See output below for more information: Message-id: 20181214154130.4069-1-tom.des...@gmail.com Type: series Subject: [Qemu-devel] [PATCH v3] Add getsockopt for settable SOL_IPV6 options === TEST SCRIPT BEGIN === #!/bin/bash BASE=base n=1 total=$(git log --oneline $BASE.. | wc -l) failed=0 git config --local diff.renamelimit 0 git config --local diff.renames True git config --local diff.algorithm histogram commits="$(git log --format=%H --reverse $BASE..)" for c in $commits; do echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..." if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then failed=1 echo fi n=$((n+1)) done exit $failed === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test' 3da3146 Add getsockopt for settable SOL_IPV6 options === OUTPUT BEGIN === Checking PATCH 1/1: Add getsockopt for settable SOL_IPV6 options... ERROR: "foo* bar" should be "foo *bar" #38: FILE: linux-user/syscall.c:2368: +void* target_addr; ERROR: braces {} are necessary for all arms of this statement #39: FILE: linux-user/syscall.c:2369: +if (get_user_u32(len, optlen)) [...] ERROR: braces {} are necessary for all arms of this statement #41: FILE: linux-user/syscall.c:2371: +if (len < 0) [...] ERROR: braces {} are necessary for all arms of this statement #45: FILE: linux-user/syscall.c:2375: +if (ret < 0) [...] ERROR: braces {} are necessary for all arms of this statement #47: FILE: linux-user/syscall.c:2377: +if (lv < len) [...] ERROR: braces {} are necessary for all arms of this statement #49: FILE: linux-user/syscall.c:2379: +if (put_user_u32(len, optlen)) [...] ERROR: "(foo*)" should be "(foo *)" #52: FILE: linux-user/syscall.c:2382: +tswap32s((uint32_t*)&val); total: 7 errors, 0 warnings, 42 lines checked Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. === OUTPUT END === Test command exited with code: 1 The full log is available at http://patchew.org/logs/20181214154130.4069-1-tom.des...@gmail.com/testing.checkpatch/?type=message. --- Email generated automatically by Patchew [http://patchew.org/]. Please send your feedback to patchew-de...@redhat.com
Re: [Qemu-devel] [PULL 00/22] misc queue
Patchew URL: https://patchew.org/QEMU/20181214144214.1260-1-peter.mayd...@linaro.org/ Hi, This series seems to have some coding style problems. See output below for more information: Message-id: 20181214144214.1260-1-peter.mayd...@linaro.org Type: series Subject: [Qemu-devel] [PULL 00/22] misc queue === TEST SCRIPT BEGIN === #!/bin/bash BASE=base n=1 total=$(git log --oneline $BASE.. | wc -l) failed=0 git config --local diff.renamelimit 0 git config --local diff.renames True git config --local diff.algorithm histogram commits="$(git log --format=%H --reverse $BASE..)" for c in $commits; do echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..." if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then failed=1 echo fi n=$((n+1)) done exit $failed === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test' a270d9d virt: Fix broken indentation cbd1ee0 target/arm: Create timers in realize, not init dc7dad8 tests/test-arm-mptimer: Don't leak string memory 515636e hw/sd/sdhci: Don't leak memory region in sdhci_sysbus_realize() e774828 hw/arm/mps2-tz.c: Free mscname string in make_dma() 3ddd560 target/arm: Free name string in ARMCPRegInfo hashtable entries 98bd688 include/hw/loader.h: Document load_image_size() 8cc4663 hw/core/loader.c: Remove load_image() 200adc0 device_tree.c: Don't use load_image() a168dfe hw/block/tc58128.c: Don't use load_image() 03e819b hw/i386/multiboot.c: Don't use load_image() 7773750 hw/i386/pc.c: Don't use load_image() deef451 hw/pci/pci.c: Don't use load_image() bc9b210 hw/smbios/smbios.c: Don't use load_image() 8561b4f hw/ppc/ppc405_boards: Don't use load_image() 6fa8785 hw/ppc/mac_newworld, mac_oldworld: Don't use load_image() c2fa852 elf_ops.h: Use address_space_write() to write memory 6b5a590 monitor: Use address_space_read() to read memory 204baf1 disas.c: Use address_space_read() to read memory 5b75a36 Rename cpu_physical_memory_write_rom() to address_space_write_rom() 247aebb exec.c: Rename cpu_physical_memory_write_rom_internal() 9230e2d scripts/checkpatch.pl: Enforce multiline comment syntax === OUTPUT BEGIN === Checking PATCH 1/22: scripts/checkpatch.pl: Enforce multiline comment syntax... WARNING: line over 80 characters #44: FILE: scripts/checkpatch.pl:1576: + $rawline =~ m@^\+.*/\*\*?[ \t]*.+[ \t]*$@) { # /* or /** non-blank ERROR: line over 90 characters #45: FILE: scripts/checkpatch.pl:1577: + WARN("Block comments use a leading /* on a separate line\n" . $herecurr); WARNING: line over 80 characters #54: FILE: scripts/checkpatch.pl:1586: + WARN("Block comments use * on subsequent lines\n" . $hereprev); ERROR: line over 90 characters #62: FILE: scripts/checkpatch.pl:1594: + WARN("Block comments use a trailing */ on a separate line\n" . $herecurr); ERROR: line over 90 characters #84: FILE: scripts/checkpatch.pl:1616: + WARN("Block comments should align the * on each line\n" . $hereprev); total: 3 errors, 2 warnings, 54 lines checked Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. Checking PATCH 2/22: exec.c: Rename cpu_physical_memory_write_rom_internal()... WARNING: line over 80 characters #39: FILE: exec.c:3396: + enum write_rom_type type) total: 0 errors, 1 warnings, 50 lines checked Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. Checking PATCH 3/22: Rename cpu_physical_memory_write_rom() to address_space_write_rom()... WARNING: Block comments use a leading /* on a separate line #190: FILE: include/exec/memory.h:1795: +/** total: 0 errors, 1 warnings, 156 lines checked Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. Checking PATCH 4/22: disas.c: Use address_space_read() to read memory... Checking PATCH 5/22: monitor: Use address_space_read() to read memory... Checking PATCH 6/22: elf_ops.h: Use address_space_write() to write memory... Checking PATCH 7/22: hw/ppc/mac_newworld, mac_oldworld: Don't use load_image()... Checking PATCH 8/22: hw/ppc/ppc405_boards: Don't use load_image()... Checking PATCH 9/22: hw/smbios/smbios.c: Don't use load_image()... Checking PATCH 10/22: hw/pci/pci.c: Don't use load_image()... Checking PATCH 11/22: hw/i386/pc.c: Don't use load_image()... Checking PATCH 12/22: hw/i386/multiboot.c: Don't use load_image()... Checking PATCH 13/22: hw/block/tc58128.c: Don't use load_image()... Checking PATCH 14/22: device_tree.c: Don't use load_image()... Checking PATCH 15/22: hw/core/loader.c: Remove load_image()... Checking PATCH 16/22: includ
[Qemu-devel] [PATCH v4 1/9] target/ppc: fix typo in SIMM5 extraction helper
As the macro name suggests, the argument should be signed and not unsigned. Signed-off-by: Mark Cave-Ayland Reviewed-by: Richard Henderson --- target/ppc/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/internal.h b/target/ppc/internal.h index a9bcadff42..8b35863549 100644 --- a/target/ppc/internal.h +++ b/target/ppc/internal.h @@ -124,7 +124,7 @@ EXTRACT_SHELPER(SIMM, 0, 16); /* 16 bits unsigned immediate value */ EXTRACT_HELPER(UIMM, 0, 16); /* 5 bits signed immediate value */ -EXTRACT_HELPER(SIMM5, 16, 5); +EXTRACT_SHELPER(SIMM5, 16, 5); /* 5 bits signed immediate value */ EXTRACT_HELPER(UIMM5, 16, 5); /* 4 bits unsigned immediate value */ -- 2.11.0
[Qemu-devel] [PATCH v4 4/9] target/ppc: introduce get_avr64() and set_avr64() helpers for VMX register access
These helpers allow us to move AVR register values to/from the specified TCGv_i64 argument. To prevent VMX helpers accessing the cpu_avr{l,h} arrays directly, add extra TCG temporaries as required. Signed-off-by: Mark Cave-Ayland Reviewed-by: Richard Henderson Acked-by: David Gibson --- target/ppc/translate.c | 10 +++ target/ppc/translate/vmx-impl.inc.c | 147 2 files changed, 124 insertions(+), 33 deletions(-) diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 9cecab42f3..3bb24e7310 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -6709,6 +6709,16 @@ static inline void set_fpr(int regno, TCGv_i64 src) tcg_gen_mov_i64(cpu_fpr[regno], src); } +static inline void get_avr64(TCGv_i64 dst, int regno, bool high) +{ +tcg_gen_mov_i64(dst, (high ? cpu_avrh : cpu_avrl)[regno]); +} + +static inline void set_avr64(int regno, TCGv_i64 src, bool high) +{ +tcg_gen_mov_i64((high ? cpu_avrh : cpu_avrl)[regno], src); +} + #include "translate/fp-impl.inc.c" #include "translate/vmx-impl.inc.c" diff --git a/target/ppc/translate/vmx-impl.inc.c b/target/ppc/translate/vmx-impl.inc.c index 3cb6fc2926..5e8327e9a3 100644 --- a/target/ppc/translate/vmx-impl.inc.c +++ b/target/ppc/translate/vmx-impl.inc.c @@ -18,52 +18,66 @@ static inline TCGv_ptr gen_avr_ptr(int reg) static void glue(gen_, name)(DisasContext *ctx) \ { \ TCGv EA; \ +TCGv_i64 avr; \ if (unlikely(!ctx->altivec_enabled)) {\ gen_exception(ctx, POWERPC_EXCP_VPU); \ return; \ } \ gen_set_access_type(ctx, ACCESS_INT); \ +avr = tcg_temp_new_i64(); \ EA = tcg_temp_new(); \ gen_addr_reg_index(ctx, EA); \ tcg_gen_andi_tl(EA, EA, ~0xf);\ /* We only need to swap high and low halves. gen_qemu_ld64_i64 does \ necessary 64-bit byteswap already. */ \ if (ctx->le_mode) { \ -gen_qemu_ld64_i64(ctx, cpu_avrl[rD(ctx->opcode)], EA);\ +gen_qemu_ld64_i64(ctx, avr, EA); \ +set_avr64(rD(ctx->opcode), avr, false); \ tcg_gen_addi_tl(EA, EA, 8); \ -gen_qemu_ld64_i64(ctx, cpu_avrh[rD(ctx->opcode)], EA);\ +gen_qemu_ld64_i64(ctx, avr, EA); \ +set_avr64(rD(ctx->opcode), avr, true);\ } else { \ -gen_qemu_ld64_i64(ctx, cpu_avrh[rD(ctx->opcode)], EA);\ +gen_qemu_ld64_i64(ctx, avr, EA); \ +set_avr64(rD(ctx->opcode), avr, true);\ tcg_gen_addi_tl(EA, EA, 8); \ -gen_qemu_ld64_i64(ctx, cpu_avrl[rD(ctx->opcode)], EA);\ +gen_qemu_ld64_i64(ctx, avr, EA); \ +set_avr64(rD(ctx->opcode), avr, false); \ } \ tcg_temp_free(EA);\ +tcg_temp_free_i64(avr); \ } #define GEN_VR_STX(name, opc2, opc3) \ static void gen_st##name(DisasContext *ctx) \ { \ TCGv EA; \ +TCGv_i64 avr; \ if (unlikely(!ctx->altivec_enabled)) {\ gen_exception(ctx, POWERPC_EXCP_VPU); \ return; \ } \ gen_set_access_type(ctx, ACCESS_INT); \ +avr = tcg_temp_new_i64();
[Qemu-devel] [PATCH v4 2/9] target/ppc: switch EXTRACT_HELPER macros over to use sextract32/extract32
These ensure that we consistently handle signed and unsigned extensions correctly when decoding immediates from instruction opcodes. Signed-off-by: Mark Cave-Ayland Reviewed-by: Richard Henderson --- target/ppc/internal.h | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/ppc/internal.h b/target/ppc/internal.h index 8b35863549..5d460247e2 100644 --- a/target/ppc/internal.h +++ b/target/ppc/internal.h @@ -52,20 +52,20 @@ FUNC_MASK(mask_u64, uint64_t, 64, UINT64_MAX); #define EXTRACT_HELPER(name, shift, nb) \ static inline uint32_t name(uint32_t opcode) \ { \ -return (opcode >> (shift)) & ((1 << (nb)) - 1); \ +return extract32(opcode, shift, nb); \ } #define EXTRACT_SHELPER(name, shift, nb) \ static inline int32_t name(uint32_t opcode) \ { \ -return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));\ +return sextract32(opcode, shift, nb); \ } #define EXTRACT_HELPER_SPLIT(name, shift1, nb1, shift2, nb2) \ static inline uint32_t name(uint32_t opcode) \ { \ -return (((opcode >> (shift1)) & ((1 << (nb1)) - 1)) << nb2) | \ -((opcode >> (shift2)) & ((1 << (nb2)) - 1)); \ +return extract32(opcode, shift1, nb1) << nb2 |\ + extract32(opcode, shift2, nb2);\ } #define EXTRACT_HELPER_SPLIT_3(name, \ -- 2.11.0
[Qemu-devel] [PATCH v4 0/9] target/ppc: prepare for conversion to TCG vector operations
This patchset is an attempt at trying to improve the VMX (Altivec) instruction performance by laying the groundwork for use of the new TCG vector operations. Patches 1 and 2 fix a sign-extension error discovered in EXTRACT_SHELPER and an associated typo in the SIMM5 macro which were discovered whilst testing Richard's follow-on TCG vector improvements patchset. In order to use TCG vector operations, the registers must be accessible from cpu_env whilst currently they are accessed via arrays of static TCG globals. Patches 3-5 are therefore mechanical patches which introduce access helpers for FPR, AVR and VSR registers using the supplied TCGv_i64 parameter. Once this is done, patch 6 enables us to remove the static TCG global arrays and updates the access helpers to read/write to the relevant fields in cpu_env directly. Patches 7 and 8 perform the legwork required to enable VSX instructions to be converted to use TCG vector operations in future by rearranging the FP, VMX and VSX registers into a single aligned VSR register array (the scope of this patchset is VMX only). Patch 9 removes the AVR* macros and replaces them with the corresponding Vsr* macros since they are equivalent. Finally thanks to Richard for taking the time to answer some of my (mostly beginner) questions related to TCG. Signed-off-by: Mark Cave-Ayland v4: - Rebase onto master - Add extra R-B tags from Richard - Leave HI_IDX/LO_IDX in int_helper.c in patch 9 (similarly named macros are also used in other files so let's ensure there is no confusion) - Add cpu_fpr_ptr(), cpu_vsrl_ptr() and cpu_avr_ptr() as suggested by Richard in patch 8 v3: - Rebase onto master, drop RFC prefix, alter subject line - Add A-B tags from David - Add SIMM5/EXTRACT_HELPER macro fix patches to the start of the series - Drop patch 4 from previous patchset (delay AVR register writeback) as it should not be required. - Remove extra get_fpr() accidentally added to GEN_FLOAT macros in patch 3 - Fix temporary leak when VMX/VSX not enabled in patches 4 and 5 - Add patch to remove AVR* macros, replacing them with Vsr* macros - Drop patches converting logical, add and sub instructions to TCG vector ops (let Richard incorporate this into his TCG vector improvements patchset) v2: - Rebase onto master - Add comment explaining rationale for FPR helpers in description for patch 1 - Add R-B tags from Richard - Add patch 3 to delay AVR register writeback as spotted by Richard - Add patches 6 and 7 to merge FPR, VMX and VSX registers into the vsr array to facilitate conversion of VSX instructions to vector operations later - Fix accidental bug whereby the conversion of get_vsr()/set_vsr() to access data from cpu_env was incorrectly squashed into patch 3 - Move set_fpr() further down in gen_fsqrts() and gen_frsqrtes() in patch 1 Mark Cave-Ayland (9): target/ppc: fix typo in SIMM5 extraction helper target/ppc: switch EXTRACT_HELPER macros over to use sextract32/extract32 target/ppc: introduce get_fpr() and set_fpr() helpers for FP register access target/ppc: introduce get_avr64() and set_avr64() helpers for VMX register access target/ppc: introduce get_cpu_vsr{l,h}() and set_cpu_vsr{l,h}() helpers for VSR register access target/ppc: switch FPR, VMX and VSX helpers to access data directly from cpu_env target/ppc: merge ppc_vsr_t and ppc_avr_t union types target/ppc: move FP and VMX registers into aligned vsr register array target/ppc: replace AVR* macros with Vsr* macros linux-user/ppc/signal.c | 28 +- target/ppc/arch_dump.c | 15 +- target/ppc/cpu.h| 42 +- target/ppc/gdbstub.c| 8 +- target/ppc/int_helper.c | 86 ++-- target/ppc/internal.h | 39 +- target/ppc/machine.c| 72 ++- target/ppc/monitor.c| 4 +- target/ppc/translate.c | 73 ++- target/ppc/translate/dfp-impl.inc.c | 2 +- target/ppc/translate/fp-impl.inc.c | 486 +++- target/ppc/translate/vmx-impl.inc.c | 154 +-- target/ppc/translate/vsx-impl.inc.c | 862 ++-- target/ppc/translate_init.inc.c | 26 +- 14 files changed, 1360 insertions(+), 537 deletions(-) -- 2.11.0
[Qemu-devel] [PATCH v4 3/9] target/ppc: introduce get_fpr() and set_fpr() helpers for FP register access
These helpers allow us to move FP register values to/from the specified TCGv_i64 argument in the VSR helpers to be introduced shortly. To prevent FP helpers accessing the cpu_fpr array directly, add extra TCG temporaries as required. Signed-off-by: Mark Cave-Ayland Reviewed-by: Richard Henderson Acked-by: David Gibson --- target/ppc/translate.c | 10 + target/ppc/translate/fp-impl.inc.c | 486 - 2 files changed, 386 insertions(+), 110 deletions(-) diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 96894ab9a8..9cecab42f3 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -6699,6 +6699,16 @@ static inline void gen_##name(DisasContext *ctx) \ GEN_TM_PRIV_NOOP(treclaim); GEN_TM_PRIV_NOOP(trechkpt); +static inline void get_fpr(TCGv_i64 dst, int regno) +{ +tcg_gen_mov_i64(dst, cpu_fpr[regno]); +} + +static inline void set_fpr(int regno, TCGv_i64 src) +{ +tcg_gen_mov_i64(cpu_fpr[regno], src); +} + #include "translate/fp-impl.inc.c" #include "translate/vmx-impl.inc.c" diff --git a/target/ppc/translate/fp-impl.inc.c b/target/ppc/translate/fp-impl.inc.c index 08770ba9f5..0f21a4e477 100644 --- a/target/ppc/translate/fp-impl.inc.c +++ b/target/ppc/translate/fp-impl.inc.c @@ -34,24 +34,37 @@ static void gen_set_cr1_from_fpscr(DisasContext *ctx) #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \ static void gen_f##name(DisasContext *ctx)\ { \ +TCGv_i64 t0; \ +TCGv_i64 t1; \ +TCGv_i64 t2; \ +TCGv_i64 t3; \ if (unlikely(!ctx->fpu_enabled)) {\ gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ +t0 = tcg_temp_new_i64(); \ +t1 = tcg_temp_new_i64(); \ +t2 = tcg_temp_new_i64(); \ +t3 = tcg_temp_new_i64(); \ gen_reset_fpstatus(); \ -gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \ - cpu_fpr[rA(ctx->opcode)],\ - cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \ +get_fpr(t0, rA(ctx->opcode)); \ +get_fpr(t1, rC(ctx->opcode)); \ +get_fpr(t2, rB(ctx->opcode)); \ +gen_helper_f##op(t3, cpu_env, t0, t1, t2);\ if (isfloat) {\ -gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,\ -cpu_fpr[rD(ctx->opcode)]);\ +gen_helper_frsp(t3, cpu_env, t3); \ } \ +set_fpr(rD(ctx->opcode), t3); \ if (set_fprf) { \ -gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]); \ +gen_compute_fprf_float64(t3); \ } \ if (unlikely(Rc(ctx->opcode) != 0)) { \ gen_set_cr1_from_fpscr(ctx); \ } \ +tcg_temp_free_i64(t0);\ +tcg_temp_free_i64(t1);\ +tcg_temp_free_i64(t2);\ +tcg_temp_free_i64(t3);\ } #define GEN_FLOAT_ACB(name, op2, set_fprf, type) \ @@ -61,24 +74,33 @@ _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type); #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \ static void gen_f##name(DisasContext *ctx)\ {
[Qemu-devel] [PATCH v4 7/9] target/ppc: merge ppc_vsr_t and ppc_avr_t union types
Since the VSX registers are actually a superset of the VMX registers then they can be represented by the same type. Merge ppc_avr_t into ppc_vsr_t and change ppc_avr_t to be a simple typedef alias. Note that due to a difference in the naming of the float32 member between ppc_avr_t and ppc_vsr_t, references to the ppc_avr_t f member must be replaced with f32 instead. Signed-off-by: Mark Cave-Ayland Reviewed-by: Richard Henderson Acked-by: David Gibson --- target/ppc/cpu.h| 17 --- target/ppc/int_helper.c | 56 + target/ppc/internal.h | 11 -- 3 files changed, 39 insertions(+), 45 deletions(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index d5f99f1fc7..578641ac20 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -218,7 +218,6 @@ typedef struct opc_handler_t opc_handler_t; /* Types used to describe some PowerPC registers etc. */ typedef struct DisasContext DisasContext; typedef struct ppc_spr_t ppc_spr_t; -typedef union ppc_avr_t ppc_avr_t; typedef union ppc_tlb_t ppc_tlb_t; typedef struct ppc_hash_pte64 ppc_hash_pte64_t; @@ -242,22 +241,26 @@ struct ppc_spr_t { #endif }; -/* Altivec registers (128 bits) */ -union ppc_avr_t { -float32 f[4]; +/* VSX/Altivec registers (128 bits) */ +typedef union _ppc_vsr_t { uint8_t u8[16]; uint16_t u16[8]; uint32_t u32[4]; +uint64_t u64[2]; int8_t s8[16]; int16_t s16[8]; int32_t s32[4]; -uint64_t u64[2]; int64_t s64[2]; +float32 f32[4]; +float64 f64[2]; +float128 f128; #ifdef CONFIG_INT128 __uint128_t u128; #endif -Int128 s128; -}; +Int128 s128; +} ppc_vsr_t; + +typedef ppc_vsr_t ppc_avr_t; #if !defined(CONFIG_USER_ONLY) /* Software TLB cache */ diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index fcac90a4a9..9d715be25c 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -548,8 +548,8 @@ VARITH_DO(muluwm, *, u32) { \ int i; \ \ -for (i = 0; i < ARRAY_SIZE(r->f); i++) {\ -r->f[i] = func(a->f[i], b->f[i], &env->vec_status); \ +for (i = 0; i < ARRAY_SIZE(r->f32); i++) { \ +r->f32[i] = func(a->f32[i], b->f32[i], &env->vec_status); \ } \ } VARITHFP(addfp, float32_add) @@ -563,9 +563,9 @@ VARITHFP(maxfp, float32_max) ppc_avr_t *b, ppc_avr_t *c) \ { \ int i; \ -for (i = 0; i < ARRAY_SIZE(r->f); i++) {\ -r->f[i] = float32_muladd(a->f[i], c->f[i], b->f[i], \ - type, &env->vec_status); \ +for (i = 0; i < ARRAY_SIZE(r->f32); i++) { \ +r->f32[i] = float32_muladd(a->f32[i], c->f32[i], b->f32[i], \ + type, &env->vec_status); \ } \ } VARITHFPFMA(maddfp, 0); @@ -670,9 +670,9 @@ VABSDU(w, u32) { \ int i; \ \ -for (i = 0; i < ARRAY_SIZE(r->f); i++) {\ +for (i = 0; i < ARRAY_SIZE(r->f32); i++) { \ float32 t = cvt(b->element[i], &env->vec_status); \ -r->f[i] = float32_scalbn(t, -uim, &env->vec_status);\ +r->f32[i] = float32_scalbn(t, -uim, &env->vec_status); \ } \ } VCF(ux, uint32_to_float32, u32) @@ -782,9 +782,9 @@ VCMPNE(w, u32, uint32_t, 0) uint32_t none = 0; \ int i; \ \ -for (i = 0; i < ARRAY_SIZE(r->f); i++) {\ +for (i = 0; i < ARRAY_SIZE(r->f32); i++) { \ uint32_t result;\ -int rel = float32_compare_quiet(a->f[i], b->f[i], \ +int rel = float32_compare_quiet(a->f32[i], b->f32[i], \ &env->vec_status); \ if (rel == float_relation_unordered) {
[Qemu-devel] [PATCH v4 5/9] target/ppc: introduce get_cpu_vsr{l, h}() and set_cpu_vsr{l, h}() helpers for VSR register access
These helpers allow us to move VSR register values to/from the specified TCGv_i64 argument. To prevent VSX helpers accessing the cpu_vsr array directly, add extra TCG temporaries as required. Signed-off-by: Mark Cave-Ayland Reviewed-by: Richard Henderson Acked-by: David Gibson --- target/ppc/translate/vsx-impl.inc.c | 862 ++-- 1 file changed, 638 insertions(+), 224 deletions(-) diff --git a/target/ppc/translate/vsx-impl.inc.c b/target/ppc/translate/vsx-impl.inc.c index 85ed135d44..f0665df1a5 100644 --- a/target/ppc/translate/vsx-impl.inc.c +++ b/target/ppc/translate/vsx-impl.inc.c @@ -1,20 +1,48 @@ /*** VSX extension ***/ -static inline TCGv_i64 cpu_vsrh(int n) +static inline void get_vsr(TCGv_i64 dst, int n) +{ +tcg_gen_mov_i64(dst, cpu_vsr[n]); +} + +static inline void set_vsr(int n, TCGv_i64 src) +{ +tcg_gen_mov_i64(cpu_vsr[n], src); +} + +static inline void get_cpu_vsrh(TCGv_i64 dst, int n) +{ +if (n < 32) { +get_fpr(dst, n); +} else { +get_avr64(dst, n - 32, true); +} +} + +static inline void get_cpu_vsrl(TCGv_i64 dst, int n) +{ +if (n < 32) { +get_vsr(dst, n); +} else { +get_avr64(dst, n - 32, false); +} +} + +static inline void set_cpu_vsrh(int n, TCGv_i64 src) { if (n < 32) { -return cpu_fpr[n]; +set_fpr(n, src); } else { -return cpu_avrh[n-32]; +set_avr64(n - 32, src, true); } } -static inline TCGv_i64 cpu_vsrl(int n) +static inline void set_cpu_vsrl(int n, TCGv_i64 src) { if (n < 32) { -return cpu_vsr[n]; +set_vsr(n, src); } else { -return cpu_avrl[n-32]; +set_avr64(n - 32, src, false); } } @@ -22,16 +50,20 @@ static inline TCGv_i64 cpu_vsrl(int n) static void gen_##name(DisasContext *ctx) \ { \ TCGv EA; \ +TCGv_i64 t0; \ if (unlikely(!ctx->vsx_enabled)) {\ gen_exception(ctx, POWERPC_EXCP_VSXU);\ return; \ } \ +t0 = tcg_temp_new_i64(); \ gen_set_access_type(ctx, ACCESS_INT); \ EA = tcg_temp_new(); \ gen_addr_reg_index(ctx, EA); \ -gen_qemu_##operation(ctx, cpu_vsrh(xT(ctx->opcode)), EA); \ +gen_qemu_##operation(ctx, t0, EA);\ +set_cpu_vsrh(xT(ctx->opcode), t0);\ /* NOTE: cpu_vsrl is undefined */ \ tcg_temp_free(EA);\ +tcg_temp_free_i64(t0);\ } VSX_LOAD_SCALAR(lxsdx, ld64_i64) @@ -44,43 +76,60 @@ VSX_LOAD_SCALAR(lxsspx, ld32fs) static void gen_lxvd2x(DisasContext *ctx) { TCGv EA; +TCGv_i64 t0; if (unlikely(!ctx->vsx_enabled)) { gen_exception(ctx, POWERPC_EXCP_VSXU); return; } +t0 = tcg_temp_new_i64(); gen_set_access_type(ctx, ACCESS_INT); EA = tcg_temp_new(); gen_addr_reg_index(ctx, EA); -gen_qemu_ld64_i64(ctx, cpu_vsrh(xT(ctx->opcode)), EA); +gen_qemu_ld64_i64(ctx, t0, EA); +set_cpu_vsrh(xT(ctx->opcode), t0); tcg_gen_addi_tl(EA, EA, 8); -gen_qemu_ld64_i64(ctx, cpu_vsrl(xT(ctx->opcode)), EA); +gen_qemu_ld64_i64(ctx, t0, EA); +set_cpu_vsrl(xT(ctx->opcode), t0); tcg_temp_free(EA); +tcg_temp_free_i64(t0); } static void gen_lxvdsx(DisasContext *ctx) { TCGv EA; +TCGv_i64 t0; +TCGv_i64 t1; if (unlikely(!ctx->vsx_enabled)) { gen_exception(ctx, POWERPC_EXCP_VSXU); return; } +t0 = tcg_temp_new_i64(); +t1 = tcg_temp_new_i64(); gen_set_access_type(ctx, ACCESS_INT); EA = tcg_temp_new(); gen_addr_reg_index(ctx, EA); -gen_qemu_ld64_i64(ctx, cpu_vsrh(xT(ctx->opcode)), EA); -tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xT(ctx->opcode))); +gen_qemu_ld64_i64(ctx, t0, EA); +set_cpu_vsrh(xT(ctx->opcode), t0); +tcg_gen_mov_i64(t1, t0); +set_cpu_vsrl(xT(ctx->opcode), t1); tcg_temp_free(EA); +tcg_temp_free_i64(t0); +tcg_temp_free_i64(t1); } static void gen_lxvw4x(DisasContext *ctx) { TCGv EA; -TCGv_i64 xth = cpu_vsrh(xT(ctx->opcode)); -TCGv_i64 xtl = cpu_vsrl(xT(ctx->opcode)); +TCGv_i64 xth; +TCGv_i64 xtl; if (unlikely(!ctx->vsx_enabled)) { gen_exception(ctx, POWERPC_EXCP_VSXU); return; } +xth = tcg_temp_new_i64(); +xtl = tcg_temp_new_i64(); +get_cpu_vsrh(xth, xT(ctx->opcode)); +get_cpu_vsrl(xtl, xT(ctx->opcode)); gen_set
[Qemu-devel] [PATCH v4 8/9] target/ppc: move FP and VMX registers into aligned vsr register array
The VSX register array is a block of 64 128-bit registers where the first 32 registers consist of the existing 64-bit FP registers extended to 128-bit using new VSR registers, and the last 32 registers are the VMX 128-bit registers as show below: 64-bit 64-bit +++ |FP0 || VSR0 +++ |FP1 || VSR1 +++ |... |... | ... +++ |FP30|| VSR30 +++ |FP31|| VSR31 +++ | VMX0 | VSR32 +-+ | VMX1 | VSR33 +-+ | ...| ... +-+ | VMX30 | VSR62 +-+ | VMX31 | VSR63 +-+ In order to allow for future conversion of VSX instructions to use TCG vector operations, recreate the same layout using an aligned version of the existing vsr register array. Since the old fpr and avr register arrays are removed, the existing callers must also be updated to use the correct offset in the vsr register array. This also includes switching the relevant VMState fields over to using subarrays to make sure that migration is preserved. Signed-off-by: Mark Cave-Ayland Reviewed-by: Richard Henderson Acked-by: David Gibson --- linux-user/ppc/signal.c | 28 --- target/ppc/arch_dump.c | 15 target/ppc/cpu.h| 25 + target/ppc/gdbstub.c| 8 ++--- target/ppc/internal.h | 18 +++--- target/ppc/machine.c| 72 ++--- target/ppc/monitor.c| 4 +-- target/ppc/translate.c | 14 target/ppc/translate/dfp-impl.inc.c | 2 +- target/ppc/translate/vmx-impl.inc.c | 7 +++- target/ppc/translate/vsx-impl.inc.c | 4 +-- target/ppc/translate_init.inc.c | 26 +++--- 12 files changed, 151 insertions(+), 72 deletions(-) diff --git a/linux-user/ppc/signal.c b/linux-user/ppc/signal.c index 2ae120a2bc..619a56950d 100644 --- a/linux-user/ppc/signal.c +++ b/linux-user/ppc/signal.c @@ -258,8 +258,8 @@ static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame) /* Save Altivec registers if necessary. */ if (env->insns_flags & PPC_ALTIVEC) { uint32_t *vrsave; -for (i = 0; i < ARRAY_SIZE(env->avr); i++) { -ppc_avr_t *avr = &env->avr[i]; +for (i = 0; i < 32; i++) { +ppc_avr_t *avr = cpu_avr_ptr(env, i); ppc_avr_t *vreg = (ppc_avr_t *)&frame->mc_vregs.altivec[i]; __put_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]); @@ -281,15 +281,17 @@ static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame) /* Save VSX second halves */ if (env->insns_flags2 & PPC2_VSX) { uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34]; -for (i = 0; i < ARRAY_SIZE(env->vsr); i++) { -__put_user(env->vsr[i], &vsregs[i]); +for (i = 0; i < 32; i++) { +uint64_t *vsrl = cpu_vsrl_ptr(env, i); +__put_user(*vsrl, &vsregs[i]); } } /* Save floating point registers. */ if (env->insns_flags & PPC_FLOAT) { -for (i = 0; i < ARRAY_SIZE(env->fpr); i++) { -__put_user(env->fpr[i], &frame->mc_fregs[i]); +for (i = 0; i < 32; i++) { +uint64_t *fpr = cpu_fpr_ptr(env, i); +__put_user(*fpr, &frame->mc_fregs[i]); } __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]); } @@ -373,8 +375,8 @@ static void restore_user_regs(CPUPPCState *env, #else v_regs = (ppc_avr_t *)frame->mc_vregs.altivec; #endif -for (i = 0; i < ARRAY_SIZE(env->avr); i++) { -ppc_avr_t *avr = &env->avr[i]; +for (i = 0; i < 32; i++) { +ppc_avr_t *avr = cpu_avr_ptr(env, i); ppc_avr_t *vreg = &v_regs[i]; __get_user(avr->u64[PPC_VEC_HI], &vreg->u64[0]); @@ -393,16 +395,18 @@ static void restore_user_regs(CPUPPCState *env, /* Restore VSX second halves */ if (env->insns_flags2 & PPC2_VSX) { uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34]; -for (i = 0; i < ARRAY_SIZE(env->vsr); i++) { -__get_user(env->vsr[i], &vsregs[i]); +for (i = 0; i < 32; i++
[Qemu-devel] [PATCH v4 6/9] target/ppc: switch FPR, VMX and VSX helpers to access data directly from cpu_env
Instead of accessing the FPR, VMX and VSX registers through static arrays of TCGv_i64 globals, remove them and change the helpers to load/store data directly within cpu_env. Signed-off-by: Mark Cave-Ayland Reviewed-by: Richard Henderson Acked-by: David Gibson --- target/ppc/translate.c | 59 ++--- target/ppc/translate/vsx-impl.inc.c | 4 +-- 2 files changed, 18 insertions(+), 45 deletions(-) diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 3bb24e7310..b18ded07b3 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -55,15 +55,9 @@ /* global register indexes */ static char cpu_reg_names[10*3 + 22*4 /* GPR */ + 10*4 + 22*5 /* SPE GPRh */ -+ 10*4 + 22*5 /* FPR */ -+ 2*(10*6 + 22*7) /* AVRh, AVRl */ -+ 10*5 + 22*6 /* VSR */ + 8*5 /* CRF */]; static TCGv cpu_gpr[32]; static TCGv cpu_gprh[32]; -static TCGv_i64 cpu_fpr[32]; -static TCGv_i64 cpu_avrh[32], cpu_avrl[32]; -static TCGv_i64 cpu_vsr[32]; static TCGv_i32 cpu_crf[8]; static TCGv cpu_nip; static TCGv cpu_msr; @@ -108,39 +102,6 @@ void ppc_translate_init(void) offsetof(CPUPPCState, gprh[i]), p); p += (i < 10) ? 4 : 5; cpu_reg_names_size -= (i < 10) ? 4 : 5; - -snprintf(p, cpu_reg_names_size, "fp%d", i); -cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env, -offsetof(CPUPPCState, fpr[i]), p); -p += (i < 10) ? 4 : 5; -cpu_reg_names_size -= (i < 10) ? 4 : 5; - -snprintf(p, cpu_reg_names_size, "avr%dH", i); -#ifdef HOST_WORDS_BIGENDIAN -cpu_avrh[i] = tcg_global_mem_new_i64(cpu_env, - offsetof(CPUPPCState, avr[i].u64[0]), p); -#else -cpu_avrh[i] = tcg_global_mem_new_i64(cpu_env, - offsetof(CPUPPCState, avr[i].u64[1]), p); -#endif -p += (i < 10) ? 6 : 7; -cpu_reg_names_size -= (i < 10) ? 6 : 7; - -snprintf(p, cpu_reg_names_size, "avr%dL", i); -#ifdef HOST_WORDS_BIGENDIAN -cpu_avrl[i] = tcg_global_mem_new_i64(cpu_env, - offsetof(CPUPPCState, avr[i].u64[1]), p); -#else -cpu_avrl[i] = tcg_global_mem_new_i64(cpu_env, - offsetof(CPUPPCState, avr[i].u64[0]), p); -#endif -p += (i < 10) ? 6 : 7; -cpu_reg_names_size -= (i < 10) ? 6 : 7; -snprintf(p, cpu_reg_names_size, "vsr%d", i); -cpu_vsr[i] = tcg_global_mem_new_i64(cpu_env, -offsetof(CPUPPCState, vsr[i]), p); -p += (i < 10) ? 5 : 6; -cpu_reg_names_size -= (i < 10) ? 5 : 6; } cpu_nip = tcg_global_mem_new(cpu_env, @@ -6701,22 +6662,34 @@ GEN_TM_PRIV_NOOP(trechkpt); static inline void get_fpr(TCGv_i64 dst, int regno) { -tcg_gen_mov_i64(dst, cpu_fpr[regno]); +tcg_gen_ld_i64(dst, cpu_env, offsetof(CPUPPCState, fpr[regno])); } static inline void set_fpr(int regno, TCGv_i64 src) { -tcg_gen_mov_i64(cpu_fpr[regno], src); +tcg_gen_st_i64(src, cpu_env, offsetof(CPUPPCState, fpr[regno])); } static inline void get_avr64(TCGv_i64 dst, int regno, bool high) { -tcg_gen_mov_i64(dst, (high ? cpu_avrh : cpu_avrl)[regno]); +#ifdef HOST_WORDS_BIGENDIAN +tcg_gen_ld_i64(dst, cpu_env, offsetof(CPUPPCState, + avr[regno].u64[(high ? 0 : 1)])); +#else +tcg_gen_ld_i64(dst, cpu_env, offsetof(CPUPPCState, + avr[regno].u64[(high ? 1 : 0)])); +#endif } static inline void set_avr64(int regno, TCGv_i64 src, bool high) { -tcg_gen_mov_i64((high ? cpu_avrh : cpu_avrl)[regno], src); +#ifdef HOST_WORDS_BIGENDIAN +tcg_gen_st_i64(src, cpu_env, offsetof(CPUPPCState, + avr[regno].u64[(high ? 0 : 1)])); +#else +tcg_gen_st_i64(src, cpu_env, offsetof(CPUPPCState, + avr[regno].u64[(high ? 1 : 0)])); +#endif } #include "translate/fp-impl.inc.c" diff --git a/target/ppc/translate/vsx-impl.inc.c b/target/ppc/translate/vsx-impl.inc.c index f0665df1a5..7eaa36b4d5 100644 --- a/target/ppc/translate/vsx-impl.inc.c +++ b/target/ppc/translate/vsx-impl.inc.c @@ -2,12 +2,12 @@ static inline void get_vsr(TCGv_i64 dst, int n) { -tcg_gen_mov_i64(dst, cpu_vsr[n]); +tcg_gen_ld_i64(dst, cpu_env, offsetof(CPUPPCState, vsr[n])); } static inline void set_vsr(int n, TCGv_i64 src) { -tcg_gen_mov_i64(cpu_vsr[n], src); +tcg_gen_st_i64(src, cpu_env, offsetof(CPUPPCState, vsr[n])); } static inline void get_cpu_vsrh(TCGv_i64 dst, int n) -- 2.11.0
[Qemu-devel] [PATCH v4 9/9] target/ppc: replace AVR* macros with Vsr* macros
Now that the VMX and VSR register sets have been combined, the same macros can be used to access both AVR and VSR field members. Signed-off-by: Mark Cave-Ayland Reviewed-by: Richard Henderson --- target/ppc/int_helper.c | 30 +- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index 9d715be25c..598731d47a 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -391,13 +391,9 @@ target_ulong helper_602_mfrom(target_ulong arg) #if defined(HOST_WORDS_BIGENDIAN) #define HI_IDX 0 #define LO_IDX 1 -#define AVRB(i) u8[i] -#define AVRW(i) u32[i] #else #define HI_IDX 1 #define LO_IDX 0 -#define AVRB(i) u8[15-(i)] -#define AVRW(i) u32[3-(i)] #endif #if defined(HOST_WORDS_BIGENDIAN) @@ -3277,11 +3273,11 @@ void helper_vcipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) int i; VECTOR_FOR_INORDER_I(i, u32) { -result.AVRW(i) = b->AVRW(i) ^ -(AES_Te0[a->AVRB(AES_shifts[4*i + 0])] ^ - AES_Te1[a->AVRB(AES_shifts[4*i + 1])] ^ - AES_Te2[a->AVRB(AES_shifts[4*i + 2])] ^ - AES_Te3[a->AVRB(AES_shifts[4*i + 3])]); +result.VsrW(i) = b->VsrW(i) ^ +(AES_Te0[a->VsrB(AES_shifts[4 * i + 0])] ^ + AES_Te1[a->VsrB(AES_shifts[4 * i + 1])] ^ + AES_Te2[a->VsrB(AES_shifts[4 * i + 2])] ^ + AES_Te3[a->VsrB(AES_shifts[4 * i + 3])]); } *r = result; } @@ -3292,7 +3288,7 @@ void helper_vcipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) int i; VECTOR_FOR_INORDER_I(i, u8) { -result.AVRB(i) = b->AVRB(i) ^ (AES_sbox[a->AVRB(AES_shifts[i])]); +result.VsrB(i) = b->VsrB(i) ^ (AES_sbox[a->VsrB(AES_shifts[i])]); } *r = result; } @@ -3305,15 +3301,15 @@ void helper_vncipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) ppc_avr_t tmp; VECTOR_FOR_INORDER_I(i, u8) { -tmp.AVRB(i) = b->AVRB(i) ^ AES_isbox[a->AVRB(AES_ishifts[i])]; +tmp.VsrB(i) = b->VsrB(i) ^ AES_isbox[a->VsrB(AES_ishifts[i])]; } VECTOR_FOR_INORDER_I(i, u32) { -r->AVRW(i) = -AES_imc[tmp.AVRB(4*i + 0)][0] ^ -AES_imc[tmp.AVRB(4*i + 1)][1] ^ -AES_imc[tmp.AVRB(4*i + 2)][2] ^ -AES_imc[tmp.AVRB(4*i + 3)][3]; +r->VsrW(i) = +AES_imc[tmp.VsrB(4 * i + 0)][0] ^ +AES_imc[tmp.VsrB(4 * i + 1)][1] ^ +AES_imc[tmp.VsrB(4 * i + 2)][2] ^ +AES_imc[tmp.VsrB(4 * i + 3)][3]; } } @@ -3323,7 +3319,7 @@ void helper_vncipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) int i; VECTOR_FOR_INORDER_I(i, u8) { -result.AVRB(i) = b->AVRB(i) ^ (AES_isbox[a->AVRB(AES_ishifts[i])]); +result.VsrB(i) = b->VsrB(i) ^ (AES_isbox[a->VsrB(AES_ishifts[i])]); } *r = result; } -- 2.11.0
Re: [Qemu-devel] [RFC PATCH 0/5] expose negotiated virtio features in r/o properties
Patchew URL: https://patchew.org/QEMU/20181214165657.749-1-rka...@virtuozzo.com/ Hi, This series seems to have some coding style problems. See output below for more information: Message-id: 20181214165657.749-1-rka...@virtuozzo.com Type: series Subject: [Qemu-devel] [RFC PATCH 0/5] expose negotiated virtio features in r/o properties === TEST SCRIPT BEGIN === #!/bin/bash BASE=base n=1 total=$(git log --oneline $BASE.. | wc -l) failed=0 git config --local diff.renamelimit 0 git config --local diff.renames True git config --local diff.algorithm histogram commits="$(git log --format=%H --reverse $BASE..)" for c in $commits; do echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..." if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then failed=1 echo fi n=$((n+1)) done exit $failed === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test' a786b7b virtio: expose negotiated features in r/o properties 0c6bf38 virtio: drop DEFINE_VIRTIO_COMMON_FEATURES 32e832d qdev-properties: add r/o 64bit bitfield property 86475cf qmp: further consolidate listing of device and object properties 09f1169 qom: preserve get/set presence in aliased properties === OUTPUT BEGIN === Checking PATCH 1/5: qom: preserve get/set presence in aliased properties... Checking PATCH 2/5: qmp: further consolidate listing of device and object properties... Checking PATCH 3/5: qdev-properties: add r/o 64bit bitfield property... Checking PATCH 4/5: virtio: drop DEFINE_VIRTIO_COMMON_FEATURES... Checking PATCH 5/5: virtio: expose negotiated features in r/o properties... ERROR: Macros with complex values should be enclosed in parenthesis #218: FILE: include/hw/virtio/virtio.h:261: +#define DEFINE_VIRTIO_FEATURE_BIT(_name, _state, _field, _bit, _defval) \ +DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval),\ +DEFINE_VIRTIO_FEATURE_BIT_NEGOTIATED(_name, _bit) total: 1 errors, 0 warnings, 165 lines checked Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. === OUTPUT END === Test command exited with code: 1 The full log is available at http://patchew.org/logs/20181214165657.749-1-rka...@virtuozzo.com/testing.checkpatch/?type=message. --- Email generated automatically by Patchew [http://patchew.org/]. Please send your feedback to patchew-de...@redhat.com
[Qemu-devel] [PATCH 0/6] target/ppc: remove various endian hacks from int_helper.c
>From working on the TCG vector operations patchset, it is apparent that there are a large number endian-based hacks in int_helper.c which can be removed by making use of the various Vsr* macros. Patch 1 is simple enough, and implements the complete set of Vsr* macros for both big endian and little endian hosts. Patches 2 and 3 rework the vector merge and multiply algorithms so that they no longer require the endian-dependent HI_IDX and LO_IDX macros. Patches 4 and 5 then completely remove the HI_IDX/LO_IDX and EL_IDX macros by replacing the element accesses with their equivalent Vsr* macro instead. Finally patch 6 is an inspection-based removal of other HOST_WORDS_BIGENDIAN hacks in int_helper.c, again replacing accesses with the relevant Vsr* macro instead. Note that there are still some endian hacks left in int_helper.c after this patchset: in particular the delightfully evil VECTOR_FOR_INORDER_I macro still remains in places where the index variable was used for purposes other than accessing elements within the vector. There were also some parts where additional conversion could be done, but I wasn't confident enough to make the change without access to PPC64 test images or real big-endian host hardware. Signed-off-by: Mark Cave-Ayland Based-on: <20181223111525.581-1-mark.cave-ayl...@ilande.co.uk> "target/ppc: prepare for conversion to TCG vector operations" Mark Cave-Ayland (6): target/ppc: implement complete set of Vsr* macros target/ppc: rework vmrg{l,h}{b,h,w} instructions to use Vsr* macros target/ppc: rework vmul{e,o}{s,u}{b,h,w} instructions to use Vsr* macros target/ppc: eliminate use of HI_IDX and LO_IDX macros from int_helper.c target/ppc: eliminate use of EL_IDX macros from int_helper.c target/ppc: remove various HOST_WORDS_BIGENDIAN hacks in int_helper.c target/ppc/int_helper.c | 551 target/ppc/internal.h | 9 +- 2 files changed, 242 insertions(+), 318 deletions(-) -- 2.11.0
[Qemu-devel] [PATCH 1/6] target/ppc: implement complete set of Vsr* macros
This prepares us for eliminating the use of direct array access within the VMX instruction implementations. Signed-off-by: Mark Cave-Ayland --- target/ppc/internal.h | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/target/ppc/internal.h b/target/ppc/internal.h index c7c0f77dd6..f26a71ffcf 100644 --- a/target/ppc/internal.h +++ b/target/ppc/internal.h @@ -206,16 +206,23 @@ EXTRACT_HELPER_SPLIT_3(DCMX_XV, 5, 16, 0, 1, 2, 5, 1, 6, 6); #if defined(HOST_WORDS_BIGENDIAN) #define VsrB(i) u8[i] +#define VsrSB(i) s8[i] #define VsrH(i) u16[i] +#define VsrSH(i) s16[i] #define VsrW(i) u32[i] +#define VsrSW(i) s32[i] #define VsrD(i) u64[i] +#define VsrSD(i) s64[i] #else #define VsrB(i) u8[15 - (i)] +#define VsrSB(i) s8[15 - (i)] #define VsrH(i) u16[7 - (i)] +#define VsrSH(i) s16[7 - (i)] #define VsrW(i) u32[3 - (i)] +#define VsrSW(i) s32[3 - (i)] #define VsrD(i) u64[1 - (i)] +#define VsrSD(i) s64[1 - (i)] #endif - static inline void getVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env) { vsr->VsrD(0) = env->vsr[n].u64[0]; -- 2.11.0
[Qemu-devel] [PATCH 4/6] target/ppc: eliminate use of HI_IDX and LO_IDX macros from int_helper.c
The original purpose of these macros was to correctly reference the high and low parts of the VSRs regardless of the host endianness. Replace these direct references to high and low parts with the relevant VsrD macro instead, and completely remove the now-unused HI_IDX and LO_IDX macros. Signed-off-by: Mark Cave-Ayland --- target/ppc/int_helper.c | 180 +++- 1 file changed, 85 insertions(+), 95 deletions(-) diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index dc5c9fb8d8..addbe54c21 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -389,14 +389,6 @@ target_ulong helper_602_mfrom(target_ulong arg) /*/ /* Altivec extension helpers */ #if defined(HOST_WORDS_BIGENDIAN) -#define HI_IDX 0 -#define LO_IDX 1 -#else -#define HI_IDX 1 -#define LO_IDX 0 -#endif - -#if defined(HOST_WORDS_BIGENDIAN) #define VECTOR_FOR_INORDER_I(index, element)\ for (index = 0; index < ARRAY_SIZE(r->element); index++) #else @@ -514,8 +506,8 @@ void helper_vprtybq(ppc_avr_t *r, ppc_avr_t *b) res ^= res >> 32; res ^= res >> 16; res ^= res >> 8; -r->u64[LO_IDX] = res & 1; -r->u64[HI_IDX] = 0; +r->VsrD(1) = res & 1; +r->VsrD(0) = 0; } #define VARITH_DO(name, op, element)\ @@ -1243,8 +1235,8 @@ void helper_vbpermq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) } } -r->u64[HI_IDX] = perm; -r->u64[LO_IDX] = 0; +r->VsrD(0) = perm; +r->VsrD(1) = 0; } #undef VBPERMQ_INDEX @@ -1573,25 +1565,25 @@ void helper_vpmsumd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) ppc_avr_t prod[2]; VECTOR_FOR_INORDER_I(i, u64) { -prod[i].u64[LO_IDX] = prod[i].u64[HI_IDX] = 0; +prod[i].VsrD(1) = prod[i].VsrD(0) = 0; for (j = 0; j < 64; j++) { if (a->u64[i] & (1ullu64[i]; } else { -bshift.u64[HI_IDX] = b->u64[i] >> (64-j); -bshift.u64[LO_IDX] = b->u64[i] << j; +bshift.VsrD(0) = b->u64[i] >> (64 - j); +bshift.VsrD(1) = b->u64[i] << j; } -prod[i].u64[LO_IDX] ^= bshift.u64[LO_IDX]; -prod[i].u64[HI_IDX] ^= bshift.u64[HI_IDX]; +prod[i].VsrD(1) ^= bshift.VsrD(1); +prod[i].VsrD(0) ^= bshift.VsrD(0); } } } -r->u64[LO_IDX] = prod[0].u64[LO_IDX] ^ prod[1].u64[LO_IDX]; -r->u64[HI_IDX] = prod[0].u64[HI_IDX] ^ prod[1].u64[HI_IDX]; +r->VsrD(1) = prod[0].VsrD(1) ^ prod[1].VsrD(1); +r->VsrD(0) = prod[0].VsrD(0) ^ prod[1].VsrD(0); #endif } @@ -1809,7 +1801,7 @@ VEXTU_X_DO(vextuwrx, 32, 0) #define VSHIFT(suffix, leftp) \ void helper_vs##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)\ { \ -int shift = b->u8[LO_IDX*15] & 0x7; \ +int shift = b->VsrB(15) & 0x7; \ int doit = 1; \ int i; \ \ @@ -1820,15 +1812,15 @@ VEXTU_X_DO(vextuwrx, 32, 0) if (shift == 0) { \ *r = *a;\ } else if (leftp) { \ -uint64_t carry = a->u64[LO_IDX] >> (64 - shift);\ +uint64_t carry = a->VsrD(1) >> (64 - shift);\ \ -r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry; \ -r->u64[LO_IDX] = a->u64[LO_IDX] << shift; \ +r->VsrD(0) = (a->VsrD(0) << shift) | carry; \ +r->VsrD(1) = a->VsrD(1) << shift; \ } else {\ -uint64_t carry = a->u64[HI_IDX] << (64 - shift);\ +uint64_t carry = a->VsrD(0) << (64 - shift);\ \ -r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry; \ -r->u64[HI_IDX] = a->u64[HI_IDX] >> shift; \ +r->VsrD(1) = (a->VsrD(1) >> shift) | carry; \ +r->VsrD(0) = a->VsrD(0) >> shift; \ } \ }
[Qemu-devel] [PATCH 2/6] target/ppc: rework vmrg{l, h}{b, h, w} instructions to use Vsr* macros
The current implementations make use of the endian-specific macros MRGLO/MRGHI and also reference HI_IDX and LO_IDX directly to calculate array offsets. Rework the implementation to use the Vsr* macros so that these per-endian references can be removed. Signed-off-by: Mark Cave-Ayland --- target/ppc/int_helper.c | 52 - 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index 598731d47a..f084a706ee 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -976,43 +976,41 @@ void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) } } -#define VMRG_DO(name, element, highp) \ +#define VMRG_DOLO(name, element, access)\ void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ { \ ppc_avr_t result; \ int i; \ -size_t n_elems = ARRAY_SIZE(r->element);\ +int m = ARRAY_SIZE(r->element) - 1; \ \ -for (i = 0; i < n_elems / 2; i++) { \ -if (highp) {\ -result.element[i*2+HI_IDX] = a->element[i]; \ -result.element[i*2+LO_IDX] = b->element[i]; \ -} else {\ -result.element[n_elems - i * 2 - (1 + HI_IDX)] =\ -b->element[n_elems - i - 1];\ -result.element[n_elems - i * 2 - (1 + LO_IDX)] =\ -a->element[n_elems - i - 1];\ -} \ +for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ +result.access(m - i) = (i & 1) ? a->access(m - (i >> 1))\ + : b->access(m - (i >> 1)); \ } \ *r = result;\ } -#if defined(HOST_WORDS_BIGENDIAN) -#define MRGHI 0 -#define MRGLO 1 -#else -#define MRGHI 1 -#define MRGLO 0 -#endif -#define VMRG(suffix, element) \ -VMRG_DO(mrgl##suffix, element, MRGHI) \ -VMRG_DO(mrgh##suffix, element, MRGLO) -VMRG(b, u8) -VMRG(h, u16) -VMRG(w, u32) + +#define VMRG_DOHI(name, element, access)\ +void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ +{ \ +ppc_avr_t result; \ +int i; \ +\ +for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ +result.access(i) = (i & 1) ? b->access(i >> 1) \ + : a->access(i >> 1); \ +} \ +*r = result;\ +} + +#define VMRG(suffix, element, access) \ +VMRG_DOLO(mrgl##suffix, element, access) \ +VMRG_DOHI(mrgh##suffix, element, access) +VMRG(b, u8, VsrB) +VMRG(h, u16, VsrH) +VMRG(w, u32, VsrW) #undef VMRG_DO #undef VMRG -#undef MRGHI -#undef MRGLO void helper_vmsummbm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) -- 2.11.0
[Qemu-devel] [PATCH 3/6] target/ppc: rework vmul{e, o}{s, u}{b, h, w} instructions to use Vsr* macros
The current implementations make use of the endian-specific macros HI_IDX and LO_IDX directly to calculate array offsets. Rework the implementation to use the Vsr* macros so that these per-endian references can be removed. Signed-off-by: Mark Cave-Ayland --- target/ppc/int_helper.c | 48 +++- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index f084a706ee..dc5c9fb8d8 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -1118,33 +1118,39 @@ void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, } } -#define VMUL_DO(name, mul_element, prod_element, cast, evenp) \ +#define VMUL_DO_EVN(name, mul_element, mul_access, prod_access, cast) \ void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ { \ int i; \ \ -VECTOR_FOR_INORDER_I(i, prod_element) { \ -if (evenp) {\ -r->prod_element[i] =\ -(cast)a->mul_element[i * 2 + HI_IDX] * \ -(cast)b->mul_element[i * 2 + HI_IDX]; \ -} else {\ -r->prod_element[i] =\ -(cast)a->mul_element[i * 2 + LO_IDX] * \ -(cast)b->mul_element[i * 2 + LO_IDX]; \ -} \ +for (i = 0; i < ARRAY_SIZE(r->mul_element); i += 2) { \ +r->prod_access(i >> 1) = (cast)a->mul_access(i) * \ + (cast)b->mul_access(i);\ +} \ +} + +#define VMUL_DO_ODD(name, mul_element, mul_access, prod_access, cast) \ +void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ +{ \ +int i; \ +\ +for (i = 0; i < ARRAY_SIZE(r->mul_element); i += 2) { \ +r->prod_access(i >> 1) = (cast)a->mul_access(i + 1) * \ + (cast)b->mul_access(i + 1);\ } \ } -#define VMUL(suffix, mul_element, prod_element, cast)\ -VMUL_DO(mule##suffix, mul_element, prod_element, cast, 1)\ -VMUL_DO(mulo##suffix, mul_element, prod_element, cast, 0) -VMUL(sb, s8, s16, int16_t) -VMUL(sh, s16, s32, int32_t) -VMUL(sw, s32, s64, int64_t) -VMUL(ub, u8, u16, uint16_t) -VMUL(uh, u16, u32, uint32_t) -VMUL(uw, u32, u64, uint64_t) -#undef VMUL_DO + +#define VMUL(suffix, mul_element, mul_access, prod_access, cast) \ +VMUL_DO_EVN(mule##suffix, mul_element, mul_access, prod_access, cast) \ +VMUL_DO_ODD(mulo##suffix, mul_element, mul_access, prod_access, cast) +VMUL(sb, s8, VsrSB, VsrSH, int16_t) +VMUL(sh, s16, VsrSH, VsrSW, int32_t) +VMUL(sw, s32, VsrSW, VsrSD, int64_t) +VMUL(ub, u8, VsrB, VsrH, uint16_t) +VMUL(uh, u16, VsrH, VsrW, uint32_t) +VMUL(uw, u32, VsrW, VsrD, uint64_t) +#undef VMUL_DO_EVN +#undef VMUL_DO_ODD #undef VMUL void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, -- 2.11.0
[Qemu-devel] [PATCH 5/6] target/ppc: eliminate use of EL_IDX macros from int_helper.c
These macros can be eliminated by instead using the relavant Vsr* macros in the few locations where they appear. Signed-off-by: Mark Cave-Ayland --- target/ppc/int_helper.c | 66 - 1 file changed, 27 insertions(+), 39 deletions(-) diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index addbe54c21..4cc7fdfd25 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -3320,12 +3320,7 @@ void helper_vncipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) *r = result; } -#define ROTRu32(v, n) (((v) >> (n)) | ((v) << (32-n))) -#if defined(HOST_WORDS_BIGENDIAN) -#define EL_IDX(i) (i) -#else -#define EL_IDX(i) (3 - (i)) -#endif +#define ROTRu32(v, n) (((v) >> (n)) | ((v) << (32 - n))) void helper_vshasigmaw(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six) { @@ -,40 +3328,34 @@ void helper_vshasigmaw(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six) int six = st_six & 0xF; int i; -VECTOR_FOR_INORDER_I(i, u32) { +for (i = 0; i < ARRAY_SIZE(r->u32); i++) { if (st == 0) { if ((six & (0x8 >> i)) == 0) { -r->u32[EL_IDX(i)] = ROTRu32(a->u32[EL_IDX(i)], 7) ^ -ROTRu32(a->u32[EL_IDX(i)], 18) ^ -(a->u32[EL_IDX(i)] >> 3); +r->VsrW(i) = ROTRu32(a->VsrW(i), 7) ^ + ROTRu32(a->VsrW(i), 18) ^ + (a->VsrW(i) >> 3); } else { /* six.bit[i] == 1 */ -r->u32[EL_IDX(i)] = ROTRu32(a->u32[EL_IDX(i)], 17) ^ -ROTRu32(a->u32[EL_IDX(i)], 19) ^ -(a->u32[EL_IDX(i)] >> 10); +r->VsrW(i) = ROTRu32(a->VsrW(i), 17) ^ + ROTRu32(a->VsrW(i), 19) ^ + (a->VsrW(i) >> 10); } } else { /* st == 1 */ if ((six & (0x8 >> i)) == 0) { -r->u32[EL_IDX(i)] = ROTRu32(a->u32[EL_IDX(i)], 2) ^ -ROTRu32(a->u32[EL_IDX(i)], 13) ^ -ROTRu32(a->u32[EL_IDX(i)], 22); +r->VsrW(i) = ROTRu32(a->VsrW(i), 2) ^ + ROTRu32(a->VsrW(i), 13) ^ + ROTRu32(a->VsrW(i), 22); } else { /* six.bit[i] == 1 */ -r->u32[EL_IDX(i)] = ROTRu32(a->u32[EL_IDX(i)], 6) ^ -ROTRu32(a->u32[EL_IDX(i)], 11) ^ -ROTRu32(a->u32[EL_IDX(i)], 25); +r->VsrW(i) = ROTRu32(a->VsrW(i), 6) ^ + ROTRu32(a->VsrW(i), 11) ^ + ROTRu32(a->VsrW(i), 25); } } } } #undef ROTRu32 -#undef EL_IDX #define ROTRu64(v, n) (((v) >> (n)) | ((v) << (64-n))) -#if defined(HOST_WORDS_BIGENDIAN) -#define EL_IDX(i) (i) -#else -#define EL_IDX(i) (1 - (i)) -#endif void helper_vshasigmad(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six) { @@ -3374,33 +3363,32 @@ void helper_vshasigmad(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six) int six = st_six & 0xF; int i; -VECTOR_FOR_INORDER_I(i, u64) { +for (i = 0; i < ARRAY_SIZE(r->u64); i++) { if (st == 0) { if ((six & (0x8 >> (2*i))) == 0) { -r->u64[EL_IDX(i)] = ROTRu64(a->u64[EL_IDX(i)], 1) ^ -ROTRu64(a->u64[EL_IDX(i)], 8) ^ -(a->u64[EL_IDX(i)] >> 7); +r->VsrD(i) = ROTRu64(a->VsrD(i), 1) ^ + ROTRu64(a->VsrD(i), 8) ^ + (a->VsrD(i) >> 7); } else { /* six.bit[2*i] == 1 */ -r->u64[EL_IDX(i)] = ROTRu64(a->u64[EL_IDX(i)], 19) ^ -ROTRu64(a->u64[EL_IDX(i)], 61) ^ -(a->u64[EL_IDX(i)] >> 6); +r->VsrD(i) = ROTRu64(a->VsrD(i), 19) ^ + ROTRu64(a->VsrD(i), 61) ^ + (a->VsrD(i) >> 6); } } else { /* st == 1 */ if ((six & (0x8 >> (2*i))) == 0) { -r->u64[EL_IDX(i)] = ROTRu64(a->u64[EL_IDX(i)], 28) ^ -ROTRu64(a->u64[EL_IDX(i)], 34) ^ -ROTRu64(a->u64[EL_IDX(i)], 39); +r->VsrD(i) = ROTRu64(a->VsrD(i), 28) ^ + ROTRu64(a->VsrD(i), 34) ^ + ROTRu64(a->VsrD(i), 39); } else { /* six.bit[2*i] == 1 */ -r->u64[EL_IDX(i)] = ROTRu64(a->u64[EL_IDX(i)], 14) ^ -ROTRu64(a->u64[EL_IDX(i)], 18) ^ -ROTRu64(a->u64[EL_IDX(i)], 41); +r->VsrD(i) = ROTRu64(a->VsrD(i), 14) ^ + ROTRu64(a->VsrD(i), 18) ^ +
[Qemu-devel] [PATCH 6/6] target/ppc: remove various HOST_WORDS_BIGENDIAN hacks in int_helper.c
Following on from the previous work, there are numerous endian-related hacks in int_helper.c that can now be replaced with Vsr* macros. Signed-off-by: Mark Cave-Ayland --- target/ppc/int_helper.c | 205 +--- 1 file changed, 70 insertions(+), 135 deletions(-) diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index 4cc7fdfd25..0d97eb9383 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -443,8 +443,8 @@ void helper_lvsl(ppc_avr_t *r, target_ulong sh) { int i, j = (sh & 0xf); -VECTOR_FOR_INORDER_I(i, u8) { -r->u8[i] = j++; +for (i = 0; i < ARRAY_SIZE(r->u8); i++) { +r->VsrB(i) = j++; } } @@ -452,18 +452,14 @@ void helper_lvsr(ppc_avr_t *r, target_ulong sh) { int i, j = 0x10 - (sh & 0xf); -VECTOR_FOR_INORDER_I(i, u8) { -r->u8[i] = j++; +for (i = 0; i < ARRAY_SIZE(r->u8); i++) { +r->VsrB(i) = j++; } } void helper_mtvscr(CPUPPCState *env, ppc_avr_t *r) { -#if defined(HOST_WORDS_BIGENDIAN) -env->vscr = r->u32[3]; -#else -env->vscr = r->u32[0]; -#endif +env->vscr = r->VsrW(3); set_flush_to_zero(vscr_nj, &env->vec_status); } @@ -870,8 +866,8 @@ target_ulong helper_vclzlsbb(ppc_avr_t *r) { target_ulong count = 0; int i; -VECTOR_FOR_INORDER_I(i, u8) { -if (r->u8[i] & 0x01) { +for (i = 0; i < ARRAY_SIZE(r->u8); i++) { +if (r->VsrB(i) & 0x01) { break; } count++; @@ -883,12 +879,8 @@ target_ulong helper_vctzlsbb(ppc_avr_t *r) { target_ulong count = 0; int i; -#if defined(HOST_WORDS_BIGENDIAN) for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) { -#else -for (i = 0; i < ARRAY_SIZE(r->u8); i++) { -#endif -if (r->u8[i] & 0x01) { +if (r->VsrB(i) & 0x01) { break; } count++; @@ -1151,18 +1143,14 @@ void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t result; int i; -VECTOR_FOR_INORDER_I(i, u8) { -int s = c->u8[i] & 0x1f; -#if defined(HOST_WORDS_BIGENDIAN) +for (i = 0; i < ARRAY_SIZE(r->u8); i++) { +int s = c->VsrB(i) & 0x1f; int index = s & 0xf; -#else -int index = 15 - (s & 0xf); -#endif if (s & 0x10) { -result.u8[i] = b->u8[index]; +result.VsrB(i) = b->VsrB(index); } else { -result.u8[i] = a->u8[index]; +result.VsrB(i) = a->VsrB(index); } } *r = result; @@ -1174,18 +1162,14 @@ void helper_vpermr(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t result; int i; -VECTOR_FOR_INORDER_I(i, u8) { -int s = c->u8[i] & 0x1f; -#if defined(HOST_WORDS_BIGENDIAN) +for (i = 0; i < ARRAY_SIZE(r->u8); i++) { +int s = c->VsrB(i) & 0x1f; int index = 15 - (s & 0xf); -#else -int index = s & 0xf; -#endif if (s & 0x10) { -result.u8[i] = a->u8[index]; +result.VsrB(i) = a->VsrB(index); } else { -result.u8[i] = b->u8[index]; +result.VsrB(i) = b->VsrB(index); } } *r = result; @@ -1882,25 +1866,14 @@ void helper_vsldoi(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift) int i; ppc_avr_t result; -#if defined(HOST_WORDS_BIGENDIAN) for (i = 0; i < ARRAY_SIZE(r->u8); i++) { int index = sh + i; if (index > 0xf) { -result.u8[i] = b->u8[index - 0x10]; -} else { -result.u8[i] = a->u8[index]; -} -} -#else -for (i = 0; i < ARRAY_SIZE(r->u8); i++) { -int index = (16 - sh) + i; -if (index > 0xf) { -result.u8[i] = a->u8[index - 0x10]; +result.VsrB(i) = b->VsrB(index - 0x10); } else { -result.u8[i] = b->u8[index]; +result.VsrB(i) = a->VsrB(index); } } -#endif *r = result; } @@ -1919,25 +1892,20 @@ void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) /* Experimental testing shows that hardware masks the immediate. */ #define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1)) -#if defined(HOST_WORDS_BIGENDIAN) #define SPLAT_ELEMENT(element) _SPLAT_MASKED(element) -#else -#define SPLAT_ELEMENT(element) \ -(ARRAY_SIZE(r->element) - 1 - _SPLAT_MASKED(element)) -#endif -#define VSPLT(suffix, element) \ +#define VSPLT(suffix, element, access) \ void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \ { \ -uint32_t s = b->element[SPLAT_ELEMENT(element)];\ +uint32_t s = b->access(SPLAT_ELEMENT(element)); \ int i; \
Re: [Qemu-devel] [PATCH v3 0/7] bitmaps: remove x- prefix from QMP api
Patchew URL: https://patchew.org/QEMU/20181214231512.5295-1-js...@redhat.com/ Hi, This series seems to have some coding style problems. See output below for more information: Message-id: 20181214231512.5295-1-js...@redhat.com Type: series Subject: [Qemu-devel] [PATCH v3 0/7] bitmaps: remove x- prefix from QMP api === TEST SCRIPT BEGIN === #!/bin/bash BASE=base n=1 total=$(git log --oneline $BASE.. | wc -l) failed=0 git config --local diff.renamelimit 0 git config --local diff.renames True git config --local diff.algorithm histogram commits="$(git log --format=%H --reverse $BASE..)" for c in $commits; do echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..." if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then failed=1 echo fi n=$((n+1)) done exit $failed === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test' 24334c9 iotests: add iotest 236 for testing bitmap merge 4a6a51f iotests: allow pretty-print for qmp_log 196c922 iotests: add filter_generated_node_ids eae2953 iotests.py: don't abort if IMGKEYSECRET is undefined 6fa block: remove 'x' prefix from experimental bitmap APIs 14c3ee1 blockdev: n-ary bitmap merge 24d5528 blockdev: abort transactions in reverse order === OUTPUT BEGIN === Checking PATCH 1/7: blockdev: abort transactions in reverse order... Checking PATCH 2/7: blockdev: n-ary bitmap merge... ERROR: externs should be avoided in .c files #28: FILE: blockdev.c:2125: +void do_block_dirty_bitmap_merge(const char *node, const char *target, total: 1 errors, 0 warnings, 147 lines checked Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. Checking PATCH 3/7: block: remove 'x' prefix from experimental bitmap APIs... Checking PATCH 4/7: iotests.py: don't abort if IMGKEYSECRET is undefined... Checking PATCH 5/7: iotests: add filter_generated_node_ids... Checking PATCH 6/7: iotests: allow pretty-print for qmp_log... Checking PATCH 7/7: iotests: add iotest 236 for testing bitmap merge... === OUTPUT END === Test command exited with code: 1 The full log is available at http://patchew.org/logs/20181214231512.5295-1-js...@redhat.com/testing.checkpatch/?type=message. --- Email generated automatically by Patchew [http://patchew.org/]. Please send your feedback to patchew-de...@redhat.com
Re: [Qemu-devel] [PATCH for-3.1 2/2] disas/nanomips: Fix format strings
On Tue, Nov 27, 2018 at 1:19 PM Stefan Weil wrote: > > Signed-off-by: Stefan Weil > --- > disas/nanomips.cpp | 18 +++--- > 1 file changed, 11 insertions(+), 7 deletions(-) > Hi, Stefan, My plan is to accept this patch plus (in the same patch) following changes in nanomips.h: This code: typedef unsigned short uint16; typedef unsigned int uint32; typedef long long int64; typedef unsigned long long uint64; namespace img { typedef unsigned long long address; } should become: typedef uint16_t uint16; typedef uint32_t uint32; typedef int64_t int64; typedef uint64_t uint64; namespace img { typedef uint64_t address; } The reason is that I would like to keep custom types. The custom types names "uint32", "int64", etc. are admittedly too generic, but that will change in further development, and it looks do not bother any compiler so far. This means that patch 1/1 will not be applied. There is no need for respin, I will do the corrections while integrating pull request. Please let me know if you object over this. Thanks again for bringing all these issues! Aleksandar > diff --git a/disas/nanomips.cpp b/disas/nanomips.cpp > index 4c3cfceaba..a3f69348b3 100644 > --- a/disas/nanomips.cpp > +++ b/disas/nanomips.cpp > @@ -284,7 +284,8 @@ uint64_t NMD::renumber_registers(uint64_t index, uint64_t > *register_list, > } > > throw std::runtime_error(img::format( > - "Invalid register mapping index %d, size of list = %d", > + "Invalid register mapping index %" PRIu64 > + ", size of list = %zu", > index, register_list_size)); > } > > @@ -501,7 +502,8 @@ std::string NMD::GPR(uint64_t reg) > return gpr_reg[reg]; > } > > -throw std::runtime_error(img::format("Invalid GPR register index %d", > reg)); > +throw std::runtime_error(img::format("Invalid GPR register index %" > PRIu64, > + reg)); > } > > > @@ -518,7 +520,8 @@ std::string NMD::FPR(uint64_t reg) > return fpr_reg[reg]; > } > > -throw std::runtime_error(img::format("Invalid FPR register index %d", > reg)); > +throw std::runtime_error(img::format("Invalid FPR register index %" > PRIu64, > + reg)); > } > > > @@ -532,26 +535,27 @@ std::string NMD::AC(uint64_t reg) > return ac_reg[reg]; > } > > -throw std::runtime_error(img::format("Invalid AC register index %d", > reg)); > +throw std::runtime_error(img::format("Invalid AC register index %" > PRIu64, > + reg)); > } > > > std::string NMD::IMMEDIATE(uint64_t value) > { > -return img::format("0x%x", value); > +return img::format("0x%" PRIx64, value); > } > > > std::string NMD::IMMEDIATE(int64_t value) > { > -return img::format("%d", value); > +return img::format("%" PRId64, value); > } > > > std::string NMD::CPR(uint64_t reg) > { > /* needs more work */ > -return img::format("CP%d", reg); > +return img::format("CP%" PRIu64, reg); > } > > > -- > 2.11.0 > >
Re: [Qemu-devel] [PATCH 5/6] target/mips: MXU: Add handlers for max/min instructions
On Mon, Dec 17, 2018 at 9:11 PM Aleksandar Markovic wrote: > > From: Aleksandar Markovic > > Add translation handlers for max/min MXU instructions. > > Signed-off-by: Aleksandar Markovic > --- > target/mips/translate.c | 356 +--- > 1 file changed, 335 insertions(+), 21 deletions(-) > It would be shorter and cleaner if loops were used for processing bits 2, 1, 0 in Q8MAX and Q8MIN handlers, but, if there is no objection over that, I can do it while applying, without respin of ghe whole series. Thanks, Aleksandar > diff --git a/target/mips/translate.c b/target/mips/translate.c > index c74a831a17..339de8c32b 100644 > --- a/target/mips/translate.c > +++ b/target/mips/translate.c > @@ -24815,6 +24815,338 @@ static void gen_mxu_S32XOR(DisasContext *ctx) > } > > > +/* > + * MXU instruction category max/min > + * > + * > + * S32MAX D16MAX Q8MAX > + * S32MIN D16MIN Q8MIN > + */ > + > +/* > + * S32MAX XRa, XRb, XRc > + *Update XRa with the maximum of signed 32-bit integers contained > + *in XRb and XRc. > + * > + * S32MIN XRa, XRb, XRc > + *Update XRa with the minimum of signed 32-bit integers contained > + *in XRb and XRc. > + * > + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 > + * +---+-+-+---+---+---+---+ > + * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00| > + * +---+-+-+---+---+---+---+ > + */ > +static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx) > +{ > +uint32_t pad, opc, XRc, XRb, XRa; > + > +pad = extract32(ctx->opcode, 21, 5); > +opc = extract32(ctx->opcode, 18, 3); > +XRc = extract32(ctx->opcode, 14, 4); > +XRb = extract32(ctx->opcode, 10, 4); > +XRa = extract32(ctx->opcode, 6, 4); > + > +if (unlikely(pad != 0)) { > +/* opcode padding incorrect -> do nothing */ > +} else if (unlikely(XRa == 0)) { > +/* destination is zero register -> do nothing */ > +} else if (unlikely((XRb == 0) && (XRc == 0))) { > +/* both operands zero registers -> just set destination to zero */ > +tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0); > +} else if (unlikely((XRb == 0) || (XRc == 0))) { > +/* exactly one operand is zero register - find which one is not...*/ > +uint32_t XRx = XRb ? XRb : XRc; > +/* ...and do max/min operation with one operand 0 */ > +if (opc == OPC_MXU_S32MAX) { > +tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0); > +} else { > +tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0); > +} > +} else if (unlikely(XRb == XRc)) { > +/* both operands same -> just set destination to one of them */ > +tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]); > +} else { > +/* the most general case */ > +if (opc == OPC_MXU_S32MAX) { > +tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], > + mxu_gpr[XRc - 1]); > +} else { > +tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], > + mxu_gpr[XRc - 1]); > +} > +} > +} > + > +/* > + * D16MAX > + *Update XRa with the 16-bit-wise maximums of signed integers > + *contained in XRb and XRc. > + * > + * D16MIN > + *Update XRa with the 16-bit-wise minimums of signed integers > + *contained in XRb and XRc. > + * > + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 > + * +---+-+-+---+---+---+---+ > + * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00| > + * +---+-+-+---+---+---+---+ > + */ > +static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx) > +{ > +uint32_t pad, opc, XRc, XRb, XRa; > + > +pad = extract32(ctx->opcode, 21, 5); > +opc = extract32(ctx->opcode, 18, 3); > +XRc = extract32(ctx->opcode, 14, 4); > +XRb = extract32(ctx->opcode, 10, 4); > +XRa = extract32(ctx->opcode, 6, 4); > + > +if (unlikely(pad != 0)) { > +/* opcode padding incorrect -> do nothing */ > +} else if (unlikely(XRc == 0)) { > +/* destination is zero register -> do nothing */ > +} else if (unlikely((XRb == 0) && (XRa == 0))) { > +/* both operands zero registers -> just set destination to zero */ > +tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0); > +} else if (unlikely((XRb == 0) || (XRa == 0))) { > +/* exactly one operand is zero register - find which one is not...*/ > +uint32_t XRx = XRb ? XRb : XRc; > +/* ...and do half-word-wise max/min with one operand 0 */ > +TCGv_i32 t0 = tcg_temp_new(); > +TCGv_i32 t1 = tcg_const_i32(0); > + > +/* the le
[Qemu-devel] [PATCH v2 07/52] alsaaudio: port to -audiodev config
Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c| 314 --- audio/audio_legacy.c | 64 + 2 files changed, 152 insertions(+), 226 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 8302f3e882..6f75644538 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -23,6 +23,7 @@ */ #include "qemu/osdep.h" #include +#include "qapi/opts-visitor.h" #include "qemu-common.h" #include "qemu/main-loop.h" #include "audio.h" @@ -33,28 +34,9 @@ #define AUDIO_CAP "alsa" #include "audio_int.h" -typedef struct ALSAConf { -int size_in_usec_in; -int size_in_usec_out; -const char *pcm_name_in; -const char *pcm_name_out; -unsigned int buffer_size_in; -unsigned int period_size_in; -unsigned int buffer_size_out; -unsigned int period_size_out; -unsigned int threshold; - -int buffer_size_in_overridden; -int period_size_in_overridden; - -int buffer_size_out_overridden; -int period_size_out_overridden; -} ALSAConf; - struct pollhlp { snd_pcm_t *handle; struct pollfd *pfds; -ALSAConf *conf; int count; int mask; }; @@ -66,6 +48,7 @@ typedef struct ALSAVoiceOut { void *pcm_buf; snd_pcm_t *handle; struct pollhlp pollhlp; +Audiodev *dev; } ALSAVoiceOut; typedef struct ALSAVoiceIn { @@ -73,16 +56,13 @@ typedef struct ALSAVoiceIn { snd_pcm_t *handle; void *pcm_buf; struct pollhlp pollhlp; +Audiodev *dev; } ALSAVoiceIn; struct alsa_params_req { int freq; snd_pcm_format_t fmt; int nchannels; -int size_in_usec; -int override_mask; -unsigned int buffer_size; -unsigned int period_size; }; struct alsa_params_obt { @@ -408,7 +388,8 @@ static int alsa_to_audfmt (snd_pcm_format_t alsafmt, AudioFormat *fmt, static void alsa_dump_info (struct alsa_params_req *req, struct alsa_params_obt *obt, -snd_pcm_format_t obtfmt) +snd_pcm_format_t obtfmt, +AudiodevPerDirectionOptions *pdo) { dolog ("parameter | requested value | obtained value\n"); dolog ("format| %10d | %10d\n", req->fmt, obtfmt); @@ -416,8 +397,9 @@ static void alsa_dump_info (struct alsa_params_req *req, req->nchannels, obt->nchannels); dolog ("frequency | %10d | %10d\n", req->freq, obt->freq); dolog ("\n"); -dolog ("requested: buffer size %d period size %d\n", - req->buffer_size, req->period_size); +dolog ("requested: buffer len %" PRId64 " buffer count %" PRId64 "\n", + pdo->has_buffer_len ? pdo->buffer_len : 0, + pdo->has_buffer_count ? pdo->buffer_count : 0); dolog ("obtained: samples %ld\n", obt->samples); } @@ -451,23 +433,25 @@ static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold) } } -static int alsa_open (int in, struct alsa_params_req *req, - struct alsa_params_obt *obt, snd_pcm_t **handlep, - ALSAConf *conf) +static int alsa_open(bool in, struct alsa_params_req *req, + struct alsa_params_obt *obt, snd_pcm_t **handlep, + Audiodev *dev) { +AudiodevPerDirectionOptions *pdo = in ? dev->in : dev->out; +AudiodevAlsaOptions *aopts = &dev->u.alsa; +AudiodevAlsaPerDirectionOptions *apdo = +in ? aopts->alsa_in : aopts->alsa_out; snd_pcm_t *handle; snd_pcm_hw_params_t *hw_params; int err; -int size_in_usec; unsigned int freq, nchannels; -const char *pcm_name = in ? conf->pcm_name_in : conf->pcm_name_out; +const char *pcm_name = apdo->has_dev ? apdo->dev : "default"; snd_pcm_uframes_t obt_buffer_size; const char *typ = in ? "ADC" : "DAC"; snd_pcm_format_t obtfmt; freq = req->freq; nchannels = req->nchannels; -size_in_usec = req->size_in_usec; snd_pcm_hw_params_alloca (&hw_params); @@ -527,79 +511,49 @@ static int alsa_open (int in, struct alsa_params_req *req, goto err; } -if (req->buffer_size) { -unsigned long obt; +if (pdo->buffer_count) { +if (pdo->buffer_len) { +int64_t req = pdo->buffer_len * pdo->buffer_count; -if (size_in_usec) { int dir = 0; -unsigned int btime = req->buffer_size; +unsigned int btime = req; -err = snd_pcm_hw_params_set_buffer_time_near ( -handle, -hw_params, -&btime, -&dir -); -obt = btime; -} -else { -snd_pcm_uframes_t bsize = req->buffer_size; +err = snd_pcm_hw_params_set_buffer_time_near( +handle, hw_params, &btime, &dir); -err = snd_pcm_hw_params_set_buffer_size_near ( -han
[Qemu-devel] [PATCH v2 03/52] qapi: qapi for audio backends
This patch adds structures into qapi to replace the existing configuration structures used by audio backends currently. This qapi will be the base of the -audiodev command line parameter (that replaces the old environment variables based config). This is not a 1:1 translation of the old options, I've tried to make them much more consistent (e.g. almost every backend had an option to specify buffer size, but the name was different for every backend, and some backends required usecs, while some other required frames, samples or bytes). Also tried to reduce the number of abbreviations used by the config keys. Some of the more important changes: * use `in` and `out` instead of `ADC` and `DAC`, as the former is more user friendly imho * moved buffer settings into the global setting area (so it's the same for all backends that support it. Backends that can't change buffer size will simply ignore them). Also using usecs, as it's probably more user friendly than samples or bytes. * try-poll is now an alsa backend specific option (as all other backends currently ignore it) Signed-off-by: Kővágó, Zoltán --- Makefile.objs | 6 +- qapi/audio.json | 253 ++ qapi/qapi-schema.json | 1 + 3 files changed, 257 insertions(+), 3 deletions(-) create mode 100644 qapi/audio.json diff --git a/Makefile.objs b/Makefile.objs index bc5b8a8442..3f833a70c0 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -1,6 +1,6 @@ -QAPI_MODULES = block-core block char common crypto introspect job migration -QAPI_MODULES += misc net rdma rocker run-state sockets tpm trace transaction -QAPI_MODULES += ui +QAPI_MODULES = audio block-core block char common crypto introspect job +QAPI_MODULES += migration misc net rdma rocker run-state sockets tpm trace +QAPI_MODULES += transaction ui ### # Common libraries for tools and emulators diff --git a/qapi/audio.json b/qapi/audio.json new file mode 100644 index 00..56d8ce439f --- /dev/null +++ b/qapi/audio.json @@ -0,0 +1,253 @@ +# -*- mode: python -*- +# +# Copyright (C) 2015 Zoltán Kővágó +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# @AudiodevNoOptions: +# +# The none, coreaudio, sdl and spice audio backend have no options. +# +# Since: 3.2 +## +{ 'struct': 'AudiodevNoOptions', + 'data': { } } + +## +# @AudiodevAlsaPerDirectionOptions: +# +# Options of the alsa backend that are used for both playback and recording. +# +# @dev: #optional the name of the alsa device to use (default 'default') +# +# @try-poll: #optional attempt to use poll mode, falling back to non polling +#access on failure (default on) +# +# Since: 3.2 +## +{ 'struct': 'AudiodevAlsaPerDirectionOptions', + 'data': { +'*dev': 'str', +'*try-poll': 'bool' } } + +## +# @AudiodevAlsaOptions: +# +# Options of the alsa audio backend. +# +# @alsa-in: options of the capture stream +# +# @alsa-out: options of the playback stream +# +# @threshold: #optional set the threshold (in microseconds) when playback starts +# +# Since: 3.2 +## +{ 'struct': 'AudiodevAlsaOptions', + 'data': { +'alsa-in':'AudiodevAlsaPerDirectionOptions', +'alsa-out': 'AudiodevAlsaPerDirectionOptions', +'*threshold': 'int' } } + +## +# @AudiodevDsoundOptions: +# +# Options of the dsound audio backend. +# +# @latency: #optional add extra latency to playback in microseconds (default +# 1) +# +# Since: 3.2 +## +{ 'struct': 'AudiodevDsoundOptions', + 'data': { +'*latency': 'int' } } + +## +# @AudiodevOssPerDirectionOptions: +# +# Options of the oss backend that are used for both playback and recording. +# +# @dev: #optional file name of the oss device (default '/dev/dsp') +# +# @try-poll: #optional attempt to use poll mode, falling back to non polling +#access on failure (default on) +# +# Since: 3.2 +## +{ 'struct': 'AudiodevOssPerDirectionOptions', + 'data': { +'*dev': 'str', +'*try-poll': 'bool' } } + +## +# @AudiodevOssOptions: +# +# Options of the oss audio backend. +# +# @oss-in: options of the capture stream +# +# @oss-out: options of the playback stream +# +# @try-mmap: #optional try using memory mapped access, falling back to non +#memory mapped access on failure (default off) +# +# @exclusive: #optional open device in exclusive mode (vmix won't work) +# (default off) +# +# @dsp-policy: #optional set the timing policy of the device (between 0 and 10, +# where smaller number means smaller latency but higher CPU usage) +# or -1 to use fragment mode (option ignored on some platforms) +# (default 5) +# +# Since: 3.2 +## +{ 'struct': 'AudiodevOssOptions', + 'data': { +'oss-in': 'AudiodevOssPerDirectionOptions', +'oss-out': 'AudiodevOssPerDirectionOptions', +'*try
[Qemu-devel] [PATCH v2 14/52] spiceaudio: port to -audiodev config
Signed-off-by: Kővágó, Zoltán --- audio/spiceaudio.c | 5 - 1 file changed, 5 deletions(-) diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index affc3df17f..4f7873af5a 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -373,10 +373,6 @@ static int line_in_ctl (HWVoiceIn *hw, int cmd, ...) return 0; } -static struct audio_option audio_options[] = { -{ /* end of list */ }, -}; - static struct audio_pcm_ops audio_callbacks = { .init_out = line_out_init, .fini_out = line_out_fini, @@ -394,7 +390,6 @@ static struct audio_pcm_ops audio_callbacks = { static struct audio_driver spice_audio_driver = { .name = "spice", .descr = "spice audio driver", -.options= audio_options, .init = spice_audio_init, .fini = spice_audio_fini, .pcm_ops= &audio_callbacks, -- 2.20.1
[Qemu-devel] [PATCH v2 10/52] noaudio: port to -audiodev config
Signed-off-by: Kővágó, Zoltán --- audio/noaudio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/audio/noaudio.c b/audio/noaudio.c index 2cc274c5e5..f1eb048d80 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -163,7 +163,6 @@ static struct audio_pcm_ops no_pcm_ops = { static struct audio_driver no_audio_driver = { .name = "none", .descr = "Timer based audio emulation", -.options= NULL, .init = no_audio_init, .fini = no_audio_fini, .pcm_ops= &no_pcm_ops, -- 2.20.1
[Qemu-devel] [PATCH v2 08/52] coreaudio: port to -audiodev config
Signed-off-by: Kővágó, Zoltán --- audio/audio_legacy.c | 10 ++ audio/coreaudio.c| 47 ++-- 2 files changed, 20 insertions(+), 37 deletions(-) diff --git a/audio/audio_legacy.c b/audio/audio_legacy.c index f91ce0c3e2..42b55035e3 100644 --- a/audio/audio_legacy.c +++ b/audio/audio_legacy.c @@ -63,6 +63,14 @@ SimpleEnvMap alsa_map[] = { { /* End of list */ } }; +SimpleEnvMap coreaudio_map[] = { +{ "QEMU_COREAUDIO_BUFFER_SIZE", "buffer-len", + ENV_TRANSFORM_FRAMES_TO_USECS_OUT }, +{ "QEMU_COREAUDIO_BUFFER_COUNT", "buffer-count" }, + +{ /* End of list */ } +}; + static unsigned long long toull(const char *str) { unsigned long long ret; @@ -233,6 +241,8 @@ static void legacy_opt(const char *drv) if (strcmp(drv, "alsa") == 0) { handle_env_opts(opts, alsa_map); handle_alsa(opts); +} else if (strcmp(drv, "coreaudio") == 0) { +handle_env_opts(opts, coreaudio_map); } } diff --git a/audio/coreaudio.c b/audio/coreaudio.c index 7d4225dbee..e00b8847d7 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -36,11 +36,6 @@ #define MAC_OS_X_VERSION_10_6 1060 #endif -typedef struct { -int buffer_frames; -int nbuffers; -} CoreaudioConf; - typedef struct coreaudioVoiceOut { HWVoiceOut hw; pthread_mutex_t mutex; @@ -507,7 +502,9 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, int err; const char *typ = "playback"; AudioValueRange frameRange; -CoreaudioConf *conf = drv_opaque; +Audiodev *dev = drv_opaque; +AudiodevPerDirectionOptions *pdo = dev->out; +int frames; /* create mutex */ err = pthread_mutex_init(&core->mutex, NULL); @@ -538,16 +535,17 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, return -1; } -if (frameRange.mMinimum > conf->buffer_frames) { +frames = audio_buffer_frames(pdo, as, 11610); +if (frameRange.mMinimum > frames) { core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum; dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum); } -else if (frameRange.mMaximum < conf->buffer_frames) { +else if (frameRange.mMaximum < frames) { core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum; dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum); } else { -core->audioDevicePropertyBufferFrameSize = conf->buffer_frames; +core->audioDevicePropertyBufferFrameSize = frames; } /* set Buffer Frame Size */ @@ -568,7 +566,8 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, "Could not get device buffer frame size\n"); return -1; } -hw->samples = conf->nbuffers * core->audioDevicePropertyBufferFrameSize; +hw->samples = (pdo->has_buffer_count ? pdo->buffer_count : 4) * +core->audioDevicePropertyBufferFrameSize; /* get StreamFormat */ status = coreaudio_get_streamformat(core->outputDeviceID, @@ -680,40 +679,15 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) return 0; } -static CoreaudioConf glob_conf = { -.buffer_frames = 512, -.nbuffers = 4, -}; - static void *coreaudio_audio_init(Audiodev *dev) { -CoreaudioConf *conf = g_malloc(sizeof(CoreaudioConf)); -*conf = glob_conf; - -return conf; +return dev; } static void coreaudio_audio_fini (void *opaque) { -g_free(opaque); } -static struct audio_option coreaudio_options[] = { -{ -.name = "BUFFER_SIZE", -.tag = AUD_OPT_INT, -.valp = &glob_conf.buffer_frames, -.descr = "Size of the buffer in frames" -}, -{ -.name = "BUFFER_COUNT", -.tag = AUD_OPT_INT, -.valp = &glob_conf.nbuffers, -.descr = "Number of buffers" -}, -{ /* End of list */ } -}; - static struct audio_pcm_ops coreaudio_pcm_ops = { .init_out = coreaudio_init_out, .fini_out = coreaudio_fini_out, @@ -725,7 +699,6 @@ static struct audio_pcm_ops coreaudio_pcm_ops = { static struct audio_driver coreaudio_audio_driver = { .name = "coreaudio", .descr = "CoreAudio http://developer.apple.com/audio/coreaudio.html";, -.options= coreaudio_options, .init = coreaudio_audio_init, .fini = coreaudio_audio_fini, .pcm_ops= &coreaudio_pcm_ops, -- 2.20.1
[Qemu-devel] [PATCH v2 12/52] paaudio: port to -audiodev config
Signed-off-by: Kővágó, Zoltán --- audio/audio_legacy.c | 11 ++ audio/paaudio.c | 80 2 files changed, 40 insertions(+), 51 deletions(-) diff --git a/audio/audio_legacy.c b/audio/audio_legacy.c index f37407586b..1f99d21803 100644 --- a/audio/audio_legacy.c +++ b/audio/audio_legacy.c @@ -96,6 +96,15 @@ SimpleEnvMap oss_map[] = { { /* End of list */ } }; +SimpleEnvMap pa_map[] = { +{ "QEMU_PA_SAMPLES", "buffer", ENV_TRANSFORM_SAMPLES_TO_USECS_OUT }, +{ "QEMU_PA_SERVER", "server" }, +{ "QEMU_PA_SINK", "sink.name" }, +{ "QEMU_PA_SOURCE", "source.name" }, + +{ /* End of list */ } +}; + static unsigned long long toull(const char *str) { unsigned long long ret; @@ -272,6 +281,8 @@ static void legacy_opt(const char *drv) handle_env_opts(opts, dsound_map); } else if (strcmp(drv, "oss") == 0) { handle_env_opts(opts, oss_map); +} else if (strcmp(drv, "pa") == 0) { +handle_env_opts(opts, pa_map); } } diff --git a/audio/paaudio.c b/audio/paaudio.c index 0981f010c9..6de6ed97fc 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -2,6 +2,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "audio.h" +#include "qapi/opts-visitor.h" #include @@ -10,14 +11,7 @@ #include "audio_pt_int.h" typedef struct { -int samples; -char *server; -char *sink; -char *source; -} PAConf; - -typedef struct { -PAConf conf; +Audiodev *dev; pa_threaded_mainloop *mainloop; pa_context *context; } paaudio; @@ -32,6 +26,7 @@ typedef struct { void *pcm_buf; struct audio_pt pt; paaudio *g; +int samples; } PAVoiceOut; typedef struct { @@ -46,6 +41,7 @@ typedef struct { const void *read_data; size_t read_index, read_length; paaudio *g; +int samples; } PAVoiceIn; static void qpa_audio_fini(void *opaque); @@ -227,7 +223,7 @@ static void *qpa_thread_out (void *arg) } } -decr = to_mix = audio_MIN(pa->live, pa->g->conf.samples >> 5); +decr = to_mix = audio_MIN(pa->live, pa->samples >> 5); rpos = pa->rpos; if (audio_pt_unlock(&pa->pt, __func__)) { @@ -319,7 +315,7 @@ static void *qpa_thread_in (void *arg) } } -incr = to_grab = audio_MIN(pa->dead, pa->g->conf.samples >> 5); +incr = to_grab = audio_MIN(pa->dead, pa->samples >> 5); wpos = pa->wpos; if (audio_pt_unlock(&pa->pt, __func__)) { @@ -546,6 +542,8 @@ static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as, struct audsettings obt_as = *as; PAVoiceOut *pa = (PAVoiceOut *) hw; paaudio *g = pa->g = drv_opaque; +AudiodevPaOptions *popts = &g->dev->u.pa; +AudiodevPaPerDirectionOptions *ppdo = popts->sink; ss.format = audfmt_to_pa (as->fmt, as->endianness); ss.channels = as->nchannels; @@ -566,7 +564,7 @@ static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as, g, "qemu", PA_STREAM_PLAYBACK, -g->conf.sink, +ppdo->has_name ? ppdo->name : NULL, &ss, NULL, /* channel map */ &ba,/* buffering attributes */ @@ -578,7 +576,8 @@ static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as, } audio_pcm_init_info (&hw->info, &obt_as); -hw->samples = g->conf.samples; +hw->samples = pa->samples = audio_buffer_samples(g->dev->out, &obt_as, + 46440); pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); pa->rpos = hw->rpos; if (!pa->pcm_buf) { @@ -612,6 +611,8 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) struct audsettings obt_as = *as; PAVoiceIn *pa = (PAVoiceIn *) hw; paaudio *g = pa->g = drv_opaque; +AudiodevPaOptions *popts = &g->dev->u.pa; +AudiodevPaPerDirectionOptions *ppdo = popts->source; ss.format = audfmt_to_pa (as->fmt, as->endianness); ss.channels = as->nchannels; @@ -623,7 +624,7 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) g, "qemu", PA_STREAM_RECORD, -g->conf.source, +ppdo->has_name ? ppdo->name : NULL, &ss, NULL, /* channel map */ NULL, /* buffering attributes */ @@ -635,7 +636,8 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) } audio_pcm_init_info (&hw->info, &obt_as); -hw->samples = g->conf.samples; +hw->samples = pa->samples = audio_buffer_samples(g->dev->in, &obt_as, + 46440); pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); pa->wpos = hw->wpos; if (!pa->pcm_buf) { @@ -808,14 +810,19 @@ static int qpa_ctl_in (HWVoiceIn *hw, int cm
[Qemu-devel] [PATCH v2 16/52] audio: -audiodev command line option: cleanup
Remove no longer needed code. Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 201 +- audio/audio_int.h | 17 2 files changed, 4 insertions(+), 214 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index e7f25ea84b..0c3f0efd46 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -173,113 +173,6 @@ void *audio_calloc (const char *funcname, int nmemb, size_t size) return g_malloc0 (len); } -static const char *audio_audfmt_to_string (AudioFormat fmt) -{ -switch (fmt) { -case AUDIO_FORMAT_U8: -return "U8"; - -case AUDIO_FORMAT_U16: -return "U16"; - -case AUDIO_FORMAT_S8: -return "S8"; - -case AUDIO_FORMAT_S16: -return "S16"; - -case AUDIO_FORMAT_U32: -return "U32"; - -case AUDIO_FORMAT_S32: -return "S32"; - -default: -abort(); -} - -dolog ("Bogus audfmt %d returning S16\n", fmt); -return "S16"; -} - -static AudioFormat audio_string_to_audfmt (const char *s, AudioFormat defval, -int *defaultp) -{ -if (!strcasecmp (s, "u8")) { -*defaultp = 0; -return AUDIO_FORMAT_U8; -} -else if (!strcasecmp (s, "u16")) { -*defaultp = 0; -return AUDIO_FORMAT_U16; -} -else if (!strcasecmp (s, "u32")) { -*defaultp = 0; -return AUDIO_FORMAT_U32; -} -else if (!strcasecmp (s, "s8")) { -*defaultp = 0; -return AUDIO_FORMAT_S8; -} -else if (!strcasecmp (s, "s16")) { -*defaultp = 0; -return AUDIO_FORMAT_S16; -} -else if (!strcasecmp (s, "s32")) { -*defaultp = 0; -return AUDIO_FORMAT_S32; -} -else { -dolog ("Bogus audio format `%s' using %s\n", - s, audio_audfmt_to_string (defval)); -*defaultp = 1; -return defval; -} -} - -static AudioFormat audio_get_conf_fmt (const char *envname, -AudioFormat defval, -int *defaultp) -{ -const char *var = getenv (envname); -if (!var) { -*defaultp = 1; -return defval; -} -return audio_string_to_audfmt (var, defval, defaultp); -} - -static int audio_get_conf_int (const char *key, int defval, int *defaultp) -{ -int val; -char *strval; - -strval = getenv (key); -if (strval && !qemu_strtoi(strval, NULL, 10, &val)) { -*defaultp = 0; -return val; -} -else { -*defaultp = 1; -return defval; -} -} - -static const char *audio_get_conf_str (const char *key, - const char *defval, - int *defaultp) -{ -const char *val = getenv (key); -if (!val) { -*defaultp = 1; -return defval; -} -else { -*defaultp = 0; -return val; -} -} - void AUD_vlog (const char *cap, const char *fmt, va_list ap) { if (cap) { @@ -298,89 +191,6 @@ void AUD_log (const char *cap, const char *fmt, ...) va_end (ap); } -static void audio_process_options (const char *prefix, - struct audio_option *opt) -{ -char *optname; -const char qemu_prefix[] = "QEMU_"; -size_t preflen, optlen; - -if (audio_bug(__func__, !prefix)) { -dolog ("prefix = NULL\n"); -return; -} - -if (audio_bug(__func__, !opt)) { -dolog ("opt = NULL\n"); -return; -} - -preflen = strlen (prefix); - -for (; opt->name; opt++) { -size_t len, i; -int def; - -if (!opt->valp) { -dolog ("Option value pointer for `%s' is not set\n", - opt->name); -continue; -} - -len = strlen (opt->name); -/* len of opt->name + len of prefix + size of qemu_prefix - * (includes trailing zero) + zero + underscore (on behalf of - * sizeof) */ -optlen = len + preflen + sizeof (qemu_prefix) + 1; -optname = g_malloc (optlen); - -pstrcpy (optname, optlen, qemu_prefix); - -/* copy while upper-casing, including trailing zero */ -for (i = 0; i <= preflen; ++i) { -optname[i + sizeof (qemu_prefix) - 1] = qemu_toupper(prefix[i]); -} -pstrcat (optname, optlen, "_"); -pstrcat (optname, optlen, opt->name); - -def = 1; -switch (opt->tag) { -case AUD_OPT_BOOL: -case AUD_OPT_INT: -{ -int *intp = opt->valp; -*intp = audio_get_conf_int (optname, *intp, &def); -} -break; - -case AUD_OPT_FMT: -{ -AudioFormat *fmtp = opt->valp; -*fmtp = audio_get_conf_fmt (optname, *fmtp, &def); -} -break; - -case AUD_OPT_STR: -{ -const char **strp = opt->valp; -
[Qemu-devel] [PATCH v2 02/52] qapi: support nested structs in OptsVisitor
From: Kővágó, Zoltán The current OptsVisitor flattens the whole structure, if there are same named fields under different paths (like `in' and `out' in `Audiodev'), the current visitor can't cope with them (for example setting `frequency=44100' will set the in's frequency to 44100 and leave out's frequency unspecified). This patch fixes it, by always requiring a complete path in case of nested structs. Fields in the path are separated by dots, similar to C structs (without pointers), like `in.frequency' or `out.frequency'. You must provide a full path even in non-ambiguous cases. To keep backward compatibility, this new feature can be disabled when creating a new OptsVisitor, in that case it will work identical to previous versions. Signed-off-by: Kővágó, Zoltán --- hw/acpi/core.c | 2 +- include/qapi/opts-visitor.h | 2 +- net/net.c | 2 +- numa.c | 2 +- qapi/opts-visitor.c | 129 qom/object_interfaces.c | 2 +- tests/qapi-schema/qapi-schema-test.json | 9 +- tests/qapi-schema/qapi-schema-test.out | 4 + tests/test-opts-visitor.c | 43 +++- 9 files changed, 163 insertions(+), 32 deletions(-) diff --git a/hw/acpi/core.c b/hw/acpi/core.c index d6f0709691..654508ac13 100644 --- a/hw/acpi/core.c +++ b/hw/acpi/core.c @@ -243,7 +243,7 @@ void acpi_table_add(const QemuOpts *opts, Error **errp) { Visitor *v; -v = opts_visitor_new(opts); +v = opts_visitor_new(opts, false); visit_type_AcpiTableOptions(v, NULL, &hdrs, &err); visit_free(v); } diff --git a/include/qapi/opts-visitor.h b/include/qapi/opts-visitor.h index ca044e3b33..84edb49f7a 100644 --- a/include/qapi/opts-visitor.h +++ b/include/qapi/opts-visitor.h @@ -33,6 +33,6 @@ typedef struct OptsVisitor OptsVisitor; * (other than integers), null, or arbitrary QTypes. It also requires a * non-null list argument to visit_start_list(). */ -Visitor *opts_visitor_new(const QemuOpts *opts); +Visitor *opts_visitor_new(const QemuOpts *opts, bool nested); #endif diff --git a/net/net.c b/net/net.c index 1f7d626197..f5e7d8a6ef 100644 --- a/net/net.c +++ b/net/net.c @@ -1106,7 +1106,7 @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) void *object = NULL; Error *err = NULL; int ret = -1; -Visitor *v = opts_visitor_new(opts); +Visitor *v = opts_visitor_new(opts, false); const char *type = qemu_opt_get(opts, "type"); diff --git a/numa.c b/numa.c index 50ec016013..31a24f750f 100644 --- a/numa.c +++ b/numa.c @@ -220,7 +220,7 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp) NumaOptions *object = NULL; MachineState *ms = MACHINE(opaque); Error *err = NULL; -Visitor *v = opts_visitor_new(opts); +Visitor *v = opts_visitor_new(opts, false); visit_type_NumaOptions(v, NULL, &object, &err); visit_free(v); diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index 4af6043b75..d8af51b16c 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -72,6 +72,7 @@ struct OptsVisitor * schema, with a single mandatory scalar member. */ ListMode list_mode; GQueue *repeated_opts; +char *repeated_name; /* When parsing a list of repeating options as integers, values of the form * "a-b", representing a closed interval, are allowed. Elements in the @@ -87,6 +88,9 @@ struct OptsVisitor * not survive or escape the OptsVisitor object. */ QemuOpt *fake_id_opt; + +/* List of field names leading to the current structure. */ +GQueue *nested_names; }; @@ -107,6 +111,7 @@ static void opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt) { GQueue *list; +assert(opt); list = g_hash_table_lookup(unprocessed_opts, opt->name); if (list == NULL) { @@ -134,6 +139,11 @@ opts_start_struct(Visitor *v, const char *name, void **obj, if (obj) { *obj = g_malloc0(size); } + +if (ov->nested_names != NULL) { +g_queue_push_tail(ov->nested_names, (gpointer) name); +} + if (ov->depth++ > 0) { return; } @@ -171,6 +181,10 @@ opts_check_struct(Visitor *v, Error **errp) GHashTableIter iter; GQueue *any; +if (ov->nested_names != NULL) { +g_queue_pop_tail(ov->nested_names); +} + if (ov->depth > 1) { return; } @@ -212,15 +226,59 @@ opts_end_alternate(Visitor *v, void **obj) } +static void +sum_strlen(gpointer data, gpointer user_data) +{ +const char *str = data; +size_t *sum_len = user_data; + +if (str) { /* skip NULLs */ +*sum_len += strlen(str) + 1; +} +} + +static void +append_str(gpointer data, gpointer user_data) +{ +const char *str = data; +char *concat_str = user_data; + +if (str) { +strcat(concat_s
Re: [Qemu-devel] [PATCH for-3.1 2/2] disas/nanomips: Fix format strings
On 23.12.18 18:10, Aleksandar Markovic wrote: > Hi, Stefan, > > My plan is to accept this patch plus (in the same patch) following > changes in nanomips.h: > > This code: > > typedef unsigned short uint16; > typedef unsigned int uint32; > typedef long long int64; > typedef unsigned long long uint64; > > namespace img > { > typedef unsigned long long address; > } > > should become: > > typedef uint16_t uint16; > typedef uint32_t uint32; > typedef int64_t int64; > typedef uint64_t uint64; > > namespace img > { > typedef uint64_t address; > } > > The reason is that I would like to keep custom types. The custom types > names "uint32", "int64", etc. are admittedly too generic, but that > will change in further development, and it looks do not bother any > compiler so far. This means that patch 1/1 will not be applied. I must admit that I don't understand the reason for keeping the custom types (many software projects work very well with the POSIX types), but the more important thing is to get the right format strings, and your approach will work for that. It's also good that you address the definition of the "address" data type. Maybe using "typedef uintptr_t address" could also be used (reducing the memory use for 32 bit systems). Stefan > There is no need for respin, I will do the corrections while > integrating pull request. > > Please let me know if you object over this. > > Thanks again for bringing all these issues! > > Aleksandar
[Qemu-devel] [PATCH v2 09/52] dsoundaudio: port to -audiodev config
Signed-off-by: Kővágó, Zoltán --- audio/audio_legacy.c| 12 + audio/dsound_template.h | 6 ++--- audio/dsoundaudio.c | 59 - 3 files changed, 32 insertions(+), 45 deletions(-) diff --git a/audio/audio_legacy.c b/audio/audio_legacy.c index 42b55035e3..48a22c390a 100644 --- a/audio/audio_legacy.c +++ b/audio/audio_legacy.c @@ -71,6 +71,16 @@ SimpleEnvMap coreaudio_map[] = { { /* End of list */ } }; +SimpleEnvMap dsound_map[] = { +{ "QEMU_DSOUND_LATENCY_MILLIS", "latency", ENV_TRANSFORM_MILLIS_TO_USECS }, +{ "QEMU_DSOUND_BUFSIZE_OUT", "out.buffer-len", + ENV_TRANSFORM_BYTES_TO_USECS_OUT }, +{ "QEMU_DSOUND_BUFSIZE_IN", "in.buffer-len", + ENV_TRANSFORM_BYTES_TO_USECS_IN }, + +{ /* End of list */ } +}; + static unsigned long long toull(const char *str) { unsigned long long ret; @@ -243,6 +253,8 @@ static void legacy_opt(const char *drv) handle_alsa(opts); } else if (strcmp(drv, "coreaudio") == 0) { handle_env_opts(opts, coreaudio_map); +} else if (strcmp(drv, "dsound") == 0) { +handle_env_opts(opts, dsound_map); } } diff --git a/audio/dsound_template.h b/audio/dsound_template.h index b439f33f58..96181efb36 100644 --- a/audio/dsound_template.h +++ b/audio/dsound_template.h @@ -167,17 +167,18 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, dsound *s = drv_opaque; WAVEFORMATEX wfx; struct audsettings obt_as; -DSoundConf *conf = &s->conf; #ifdef DSBTYPE_IN const char *typ = "ADC"; DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; DSCBUFFERDESC bd; DSCBCAPS bc; +AudiodevPerDirectionOptions *pdo = s->dev->in; #else const char *typ = "DAC"; DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; DSBUFFERDESC bd; DSBCAPS bc; +AudiodevPerDirectionOptions *pdo = s->dev->out; #endif if (!s->FIELD2) { @@ -193,8 +194,8 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, memset (&bd, 0, sizeof (bd)); bd.dwSize = sizeof (bd); bd.lpwfxFormat = &wfx; +bd.dwBufferBytes = audio_buffer_bytes(pdo, as, 92880); #ifdef DSBTYPE_IN -bd.dwBufferBytes = conf->bufsize_in; hr = IDirectSoundCapture_CreateCaptureBuffer ( s->dsound_capture, &bd, @@ -203,7 +204,6 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, ); #else bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2; -bd.dwBufferBytes = conf->bufsize_out; hr = IDirectSound_CreateSoundBuffer ( s->dsound, &bd, diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index 02fe777cba..a7d04b5033 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -32,6 +32,7 @@ #define AUDIO_CAP "dsound" #include "audio_int.h" +#include "qemu/host-utils.h" #include #include @@ -42,17 +43,11 @@ /* #define DEBUG_DSOUND */ -typedef struct { -int bufsize_in; -int bufsize_out; -int latency_millis; -} DSoundConf; - typedef struct { LPDIRECTSOUND dsound; LPDIRECTSOUNDCAPTURE dsound_capture; struct audsettings settings; -DSoundConf conf; +Audiodev *dev; } dsound; typedef struct { @@ -248,9 +243,9 @@ static void GCC_FMT_ATTR (3, 4) dsound_logerr2 ( dsound_log_hresult (hr); } -static DWORD millis_to_bytes (struct audio_pcm_info *info, DWORD millis) +static uint64_t usecs_to_bytes(struct audio_pcm_info *info, uint32_t usecs) { -return (millis * info->bytes_per_second) / 1000; +return muldiv64(usecs, info->bytes_per_second, 100); } #ifdef DEBUG_DSOUND @@ -478,7 +473,7 @@ static int dsound_run_out (HWVoiceOut *hw, int live) LPVOID p1, p2; int bufsize; dsound *s = ds->s; -DSoundConf *conf = &s->conf; +AudiodevDsoundOptions *dso = &s->dev->u.dsound; if (!dsb) { dolog ("Attempt to run empty with playback buffer\n"); @@ -501,14 +496,14 @@ static int dsound_run_out (HWVoiceOut *hw, int live) len = live << hwshift; if (ds->first_time) { -if (conf->latency_millis) { +if (dso->latency) { DWORD cur_blat; cur_blat = audio_ring_dist (wpos, ppos, bufsize); ds->first_time = 0; old_pos = wpos; old_pos += -millis_to_bytes (&hw->info, conf->latency_millis) - cur_blat; +usecs_to_bytes(&hw->info, dso->latency) - cur_blat; old_pos %= bufsize; old_pos &= ~hw->info.align; } @@ -747,12 +742,6 @@ static int dsound_run_in (HWVoiceIn *hw) return decr; } -static DSoundConf glob_conf = { -.bufsize_in = 16384, -.bufsize_out= 16384, -.latency_millis = 10 -}; - static void dsound_audio_fini (void *opaque) { HRESULT hr; @@ -788,8 +777,17 @@ static void *dsound_audio_init(Audiodev *dev) int err; HRESULT hr; dsound *s = g_malloc0(sizeof(dsound)); +A
[Qemu-devel] [PATCH v2 25/52] paaudio: fix playback glitches
Pulseaudio normally assumes that when the server wants it, the client can generate the audio samples and send it right away. Unfortunately this is not the case with QEMU -- it's up to the emulated system when does it generate the samples. Buffering the samples and sending them from a background thread is just a workaround, that doesn't work too well. Instead enable pa's compatibility support and let pa worry about the details. Signed-off-by: Kővágó, Zoltán --- audio/paaudio.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/audio/paaudio.c b/audio/paaudio.c index 6ed12851c0..9331e630d1 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -511,10 +511,8 @@ static pa_stream *qpa_simple_new ( flags = PA_STREAM_INTERPOLATE_TIMING -#ifdef PA_STREAM_ADJUST_LATENCY -|PA_STREAM_ADJUST_LATENCY -#endif -|PA_STREAM_AUTO_TIMING_UPDATE; +|PA_STREAM_AUTO_TIMING_UPDATE +|PA_STREAM_EARLY_REQUESTS; if (dev) { /* don't move the stream if the user specified a sink/source */ -- 2.20.1
[Qemu-devel] [PATCH v2 18/52] audio: basic support for multi backend audio
Audio functions no longer access glob_audio_state, instead they get an AudioState as a parameter. This is required in order to support multiple backends. glob_audio_state is also gone, and replaced with a tailq so we can store more than one states. Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 105 +++-- audio/audio.h | 12 +++-- audio/audio_int.h | 2 + audio/audio_template.h | 2 +- audio/wavcapture.c | 6 +-- hmp-commands.hx| 11 +++-- monitor.c | 12 - qemu-options.hx| 5 ++ ui/vnc.c | 15 +- ui/vnc.h | 2 + 10 files changed, 133 insertions(+), 39 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 461aea7a01..92fa170b46 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -86,7 +86,8 @@ audio_driver *audio_driver_lookup(const char *name) return NULL; } -static AudioState glob_audio_state; +static QTAILQ_HEAD(AudioStateHead, AudioState) audio_states = +QTAILQ_HEAD_INITIALIZER(audio_states); const struct mixeng_volume nominal_volume = { .mute = 0, @@ -1240,11 +1241,14 @@ static void audio_run_capture (AudioState *s) void audio_run (const char *msg) { -AudioState *s = &glob_audio_state; +AudioState *s; + +QTAILQ_FOREACH(s, &audio_states, list) { +audio_run_out (s); +audio_run_in (s); +audio_run_capture (s); +} -audio_run_out (s); -audio_run_in (s); -audio_run_capture (s); #ifdef DEBUG_POLL { static double prevtime; @@ -1306,13 +1310,11 @@ bool audio_is_cleaning_up(void) return is_cleaning_up; } -void audio_cleanup(void) +static void free_audio_state(AudioState *s) { -AudioState *s = &glob_audio_state; HWVoiceOut *hwo, *hwon; HWVoiceIn *hwi, *hwin; -is_cleaning_up = true; QLIST_FOREACH_SAFE(hwo, &s->hw_head_out, entries, hwon) { SWVoiceCap *sc; @@ -1349,6 +1351,17 @@ void audio_cleanup(void) qapi_free_Audiodev(s->dev); s->dev = NULL; } +g_free(s); +} + +void audio_cleanup(void) +{ +is_cleaning_up = true; +while (!QTAILQ_EMPTY(&audio_states)) { +AudioState *s = QTAILQ_FIRST(&audio_states); +QTAILQ_REMOVE(&audio_states, s, list); +free_audio_state(s); +} } static const VMStateDescription vmstate_audio = { @@ -1361,28 +1374,34 @@ static const VMStateDescription vmstate_audio = { }; static Audiodev *parse_option(QemuOpts *opts, Error **errp); -static int audio_init(Audiodev *dev) + +/* + * if we have dev, this function was called because of an -audiodev argument => + * initialize a new state with it + * if dev == NULL => legacy implicit initialization, return the already created + * state or create a new one + */ +static AudioState *audio_init(Audiodev *dev) { +static bool atexit_registered; size_t i; int done = 0; const char *drvname = NULL; VMChangeStateEntry *e; -AudioState *s = &glob_audio_state; +AudioState *s; struct audio_driver *driver; /* silence gcc warning about uninitialized variable */ QemuOptsList *list = NULL; -if (s->drv) { -if (dev) { -dolog("Cannot create more than one audio backend, sorry\n"); -qapi_free_Audiodev(dev); -} -return -1; -} - if (dev) { /* -audiodev option */ drvname = AudiodevDriver_str(dev->driver); +} else if (!QTAILQ_EMPTY(&audio_states)) { +/* + * todo: check for -audiodev once we have normal audiodev selection + * support + */ +return QTAILQ_FIRST(&audio_states); } else { /* legacy implicit initialization */ audio_handle_legacy_opts(); @@ -1392,12 +1411,18 @@ static int audio_init(Audiodev *dev) exit(1); } } + +s = g_malloc0(sizeof(AudioState)); s->dev = dev; QLIST_INIT (&s->hw_head_out); QLIST_INIT (&s->hw_head_in); QLIST_INIT (&s->cap_head); -atexit(audio_cleanup); +if (!atexit_registered) { +atexit(audio_cleanup); +atexit_registered = true; +} +QTAILQ_INSERT_TAIL(&audio_states, s, list); s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s); @@ -1466,15 +1491,18 @@ static int audio_init(Audiodev *dev) QLIST_INIT (&s->card_head); vmstate_register (NULL, 0, &vmstate_audio, s); -return 0; +return s; } void AUD_register_card (const char *name, QEMUSoundCard *card) { -audio_init(NULL); +if (!card->state) { +card->state = audio_init(NULL); +} + card->name = g_strdup (name); memset (&card->entries, 0, sizeof (card->entries)); -QLIST_INSERT_HEAD (&glob_audio_state.card_head, card, entries); +QLIST_INSERT_HEAD (&card->state->card_head, card, entries); } void AUD_remove_card (QEMUSoundCard *card) @@ -1484,16 +1512,21 @@ void AUD_remove_card (QEMUSoundCard *card
[Qemu-devel] [PATCH v2 17/52] audio: reduce glob_audio_state usage
Remove glob_audio_state from functions, where possible without breaking the API. This means that most static functions in audio.c now take an AudioState pointer instead of implicitly using glob_audio_state. Also included a pointer in SWVoice*, HWVoice* structs, so that functions dealing them can know the audio state without having to pass it around separately. This is required in order to support multiple simultaneous audio backends (added in a later commit). Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 59 +++--- audio/audio_int.h | 7 + audio/audio_template.h | 46 3 files changed, 56 insertions(+), 56 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 0c3f0efd46..461aea7a01 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -398,12 +398,10 @@ static void noop_conv (struct st_sample *dst, const void *src, int samples) (void) samples; } -static CaptureVoiceOut *audio_pcm_capture_find_specific ( -struct audsettings *as -) +static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioState *s, +struct audsettings *as) { CaptureVoiceOut *cap; -AudioState *s = &glob_audio_state; for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) { if (audio_pcm_info_eq (&cap->hw.info, as)) { @@ -480,7 +478,7 @@ static void audio_detach_capture (HWVoiceOut *hw) static int audio_attach_capture (HWVoiceOut *hw) { -AudioState *s = &glob_audio_state; +AudioState *s = hw->s; CaptureVoiceOut *cap; audio_detach_capture (hw); @@ -793,19 +791,15 @@ static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info) /* * Timer */ - -static bool audio_timer_running; -static uint64_t audio_timer_last; - -static int audio_is_timer_needed (void) +static int audio_is_timer_needed(AudioState *s) { HWVoiceIn *hwi = NULL; HWVoiceOut *hwo = NULL; -while ((hwo = audio_pcm_hw_find_any_enabled_out (hwo))) { +while ((hwo = audio_pcm_hw_find_any_enabled_out(s, hwo))) { if (!hwo->poll_mode) return 1; } -while ((hwi = audio_pcm_hw_find_any_enabled_in (hwi))) { +while ((hwi = audio_pcm_hw_find_any_enabled_in(s, hwi))) { if (!hwi->poll_mode) return 1; } return 0; @@ -813,18 +807,18 @@ static int audio_is_timer_needed (void) static void audio_reset_timer (AudioState *s) { -if (audio_is_timer_needed ()) { +if (audio_is_timer_needed(s)) { timer_mod_anticipate_ns(s->ts, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->period_ticks); -if (!audio_timer_running) { -audio_timer_running = true; -audio_timer_last = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +if (!s->timer_running) { +s->timer_running = true; +s->timer_last = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); trace_audio_timer_start(s->period_ticks / SCALE_MS); } } else { timer_del(s->ts); -if (audio_timer_running) { -audio_timer_running = false; +if (s->timer_running) { +s->timer_running = false; trace_audio_timer_stop(); } } @@ -836,11 +830,11 @@ static void audio_timer (void *opaque) AudioState *s = opaque; now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -diff = now - audio_timer_last; +diff = now - s->timer_last; if (diff > s->period_ticks * 3 / 2) { trace_audio_timer_delayed(diff / SCALE_MS); } -audio_timer_last = now; +s->timer_last = now; audio_run("timer"); audio_reset_timer(s); @@ -894,7 +888,7 @@ void AUD_set_active_out (SWVoiceOut *sw, int on) hw = sw->hw; if (sw->active != on) { -AudioState *s = &glob_audio_state; +AudioState *s = sw->s; SWVoiceOut *temp_sw; SWVoiceCap *sc; @@ -941,7 +935,7 @@ void AUD_set_active_in (SWVoiceIn *sw, int on) hw = sw->hw; if (sw->active != on) { -AudioState *s = &glob_audio_state; +AudioState *s = sw->s; SWVoiceIn *temp_sw; if (on) { @@ -1064,7 +1058,7 @@ static void audio_run_out (AudioState *s) HWVoiceOut *hw = NULL; SWVoiceOut *sw; -while ((hw = audio_pcm_hw_find_any_enabled_out (hw))) { +while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) { int played; int live, free, nb_live, cleanup_required, prev_rpos; @@ -1169,7 +1163,7 @@ static void audio_run_in (AudioState *s) { HWVoiceIn *hw = NULL; -while ((hw = audio_pcm_hw_find_any_enabled_in (hw))) { +while ((hw = audio_pcm_hw_find_any_enabled_in(s, hw))) { SWVoiceIn *sw; int captured = 0, min; @@ -1275,8 +1269,8 @@ static int audio_driver_init(AudioState *s, struct audio_driver *drv, s->drv_opaque = drv->init(dev); if (s->drv_opaque) { -audio_init_nb_voices_out
[Qemu-devel] [PATCH v2 34/52] paaudio: port to the new audio backend api
Signed-off-by: Kővágó, Zoltán --- audio/Makefile.objs | 1 - audio/audio_pt_int.c | 174 audio/audio_pt_int.h | 22 --- audio/paaudio.c | 372 ++- configure| 5 - 5 files changed, 45 insertions(+), 529 deletions(-) delete mode 100644 audio/audio_pt_int.c delete mode 100644 audio/audio_pt_int.h diff --git a/audio/Makefile.objs b/audio/Makefile.objs index dca87f6347..d7490a379f 100644 --- a/audio/Makefile.objs +++ b/audio/Makefile.objs @@ -2,7 +2,6 @@ common-obj-y = audio.o audio_legacy.o noaudio.o wavaudio.o mixeng.o common-obj-$(CONFIG_SPICE) += spiceaudio.o common-obj-$(CONFIG_AUDIO_COREAUDIO) += coreaudio.o common-obj-$(CONFIG_AUDIO_DSOUND) += dsoundaudio.o -common-obj-$(CONFIG_AUDIO_PT_INT) += audio_pt_int.o common-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o common-obj-y += wavcapture.o diff --git a/audio/audio_pt_int.c b/audio/audio_pt_int.c deleted file mode 100644 index 3fe56d8514..00 --- a/audio/audio_pt_int.c +++ /dev/null @@ -1,174 +0,0 @@ -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "audio.h" - -#define AUDIO_CAP "audio-pt" - -#include "audio_int.h" -#include "audio_pt_int.h" - -static void GCC_FMT_ATTR(3, 4) logerr (struct audio_pt *pt, int err, - const char *fmt, ...) -{ -va_list ap; - -va_start (ap, fmt); -AUD_vlog (pt->drv, fmt, ap); -va_end (ap); - -AUD_log (NULL, "\n"); -AUD_log (pt->drv, "Reason: %s\n", strerror (err)); -} - -int audio_pt_init (struct audio_pt *p, void *(*func) (void *), - void *opaque, const char *drv, const char *cap) -{ -int err, err2; -const char *efunc; -sigset_t set, old_set; - -p->drv = drv; - -err = sigfillset (&set); -if (err) { -logerr(p, errno, "%s(%s): sigfillset failed", cap, __func__); -return -1; -} - -err = pthread_mutex_init (&p->mutex, NULL); -if (err) { -efunc = "pthread_mutex_init"; -goto err0; -} - -err = pthread_cond_init (&p->cond, NULL); -if (err) { -efunc = "pthread_cond_init"; -goto err1; -} - -err = pthread_sigmask (SIG_BLOCK, &set, &old_set); -if (err) { -efunc = "pthread_sigmask"; -goto err2; -} - -err = pthread_create (&p->thread, NULL, func, opaque); - -err2 = pthread_sigmask (SIG_SETMASK, &old_set, NULL); -if (err2) { -logerr(p, err2, "%s(%s): pthread_sigmask (restore) failed", - cap, __func__); -/* We have failed to restore original signal mask, all bets are off, - so terminate the process */ -exit (EXIT_FAILURE); -} - -if (err) { -efunc = "pthread_create"; -goto err2; -} - -return 0; - - err2: -err2 = pthread_cond_destroy (&p->cond); -if (err2) { -logerr(p, err2, "%s(%s): pthread_cond_destroy failed", cap, __func__); -} - - err1: -err2 = pthread_mutex_destroy (&p->mutex); -if (err2) { -logerr(p, err2, "%s(%s): pthread_mutex_destroy failed", cap, __func__); -} - - err0: -logerr(p, err, "%s(%s): %s failed", cap, __func__, efunc); -return -1; -} - -int audio_pt_fini (struct audio_pt *p, const char *cap) -{ -int err, ret = 0; - -err = pthread_cond_destroy (&p->cond); -if (err) { -logerr(p, err, "%s(%s): pthread_cond_destroy failed", cap, __func__); -ret = -1; -} - -err = pthread_mutex_destroy (&p->mutex); -if (err) { -logerr(p, err, "%s(%s): pthread_mutex_destroy failed", cap, __func__); -ret = -1; -} -return ret; -} - -int audio_pt_lock (struct audio_pt *p, const char *cap) -{ -int err; - -err = pthread_mutex_lock (&p->mutex); -if (err) { -logerr(p, err, "%s(%s): pthread_mutex_lock failed", cap, __func__); -return -1; -} -return 0; -} - -int audio_pt_unlock (struct audio_pt *p, const char *cap) -{ -int err; - -err = pthread_mutex_unlock (&p->mutex); -if (err) { -logerr(p, err, "%s(%s): pthread_mutex_unlock failed", cap, __func__); -return -1; -} -return 0; -} - -int audio_pt_wait (struct audio_pt *p, const char *cap) -{ -int err; - -err = pthread_cond_wait (&p->cond, &p->mutex); -if (err) { -logerr(p, err, "%s(%s): pthread_cond_wait failed", cap, __func__); -return -1; -} -return 0; -} - -int audio_pt_unlock_and_signal (struct audio_pt *p, const char *cap) -{ -int err; - -err = pthread_mutex_unlock (&p->mutex); -if (err) { -logerr(p, err, "%s(%s): pthread_mutex_unlock failed", cap, __func__); -return -1; -} -err = pthread_cond_signal (&p->cond); -if (err) { -logerr(p, err, "%s(%s): pthread_cond_signal failed", cap, __func__); -return -1; -} -return 0; -} - -int audio_pt_join (struct audio_pt *p, void **arg, const char *cap) -{ -int err; -vo
[Qemu-devel] [PATCH v2 31/52] dsoundaudio: port to the new audio backend api
--- audio/dsound_template.h | 45 +++--- audio/dsoundaudio.c | 328 ++-- 2 files changed, 102 insertions(+), 271 deletions(-) diff --git a/audio/dsound_template.h b/audio/dsound_template.h index 96181efb36..ff5a1f85fd 100644 --- a/audio/dsound_template.h +++ b/audio/dsound_template.h @@ -29,6 +29,8 @@ #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER #define FIELD dsound_capture_buffer #define FIELD2 dsound_capture +#define HWVOICE HWVoiceIn +#define DSOUNDVOICE DSoundVoiceIn #else #define NAME "playback buffer" #define NAME2 "DirectSound" @@ -37,6 +39,8 @@ #define BUFPTR LPDIRECTSOUNDBUFFER #define FIELD dsound_buffer #define FIELD2 dsound +#define HWVOICE HWVoiceOut +#define DSOUNDVOICE DSoundVoiceOut #endif static int glue (dsound_unlock_, TYPE) ( @@ -72,8 +76,6 @@ static int glue (dsound_lock_, TYPE) ( ) { HRESULT hr; -LPVOID p1 = NULL, p2 = NULL; -DWORD blen1 = 0, blen2 = 0; DWORD flag; #ifdef DSBTYPE_IN @@ -81,7 +83,7 @@ static int glue (dsound_lock_, TYPE) ( #else flag = entire ? DSBLOCK_ENTIREBUFFER : 0; #endif -hr = glue(IFACE, _Lock)(buf, pos, len, &p1, &blen1, &p2, &blen2, flag); +hr = glue(IFACE, _Lock)(buf, pos, len, p1p, blen1p, p2p, blen2p, flag); if (FAILED (hr)) { #ifndef DSBTYPE_IN @@ -96,34 +98,34 @@ static int glue (dsound_lock_, TYPE) ( goto fail; } -if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) { +if ((p1p && *p1p && (*blen1p & info->align)) || +(p2p && *p2p && (*blen2p & info->align))) { dolog ("DirectSound returned misaligned buffer %ld %ld\n", - blen1, blen2); -glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2); + *blen1p, *blen2p); +glue (dsound_unlock_, TYPE) (buf, *p1p, p2p ? *p2p : NULL, *blen1p, + blen2p ? *blen2p : 0); goto fail; } -if (!p1 && blen1) { -dolog ("warning: !p1 && blen1=%ld\n", blen1); -blen1 = 0; +if (p1p && !*p1p && *blen1p) { +dolog("warning: !p1 && blen1=%ld\n", *blen1p); +*blen1p = 0; } -if (!p2 && blen2) { -dolog ("warning: !p2 && blen2=%ld\n", blen2); -blen2 = 0; +if (p2p && !*p2p && *blen2p) { +dolog("warning: !p2 && blen2=%ld\n", *blen2p); +*blen2p = 0; } -*p1p = p1; -*p2p = p2; -*blen1p = blen1; -*blen2p = blen2; return 0; fail: *p1p = NULL - 1; -*p2p = NULL - 1; *blen1p = -1; -*blen2p = -1; +if (p2p) { +*p2p = NULL - 1; +*blen2p = -1; +} return -1; } @@ -242,7 +244,6 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, goto fail0; } -ds->first_time = 1; obt_as.endianness = 0; audio_pcm_init_info (&hw->info, &obt_as); @@ -252,15 +253,13 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, bc.dwBufferBytes, hw->info.align + 1 ); } +hw->size_emul = bc.dwBufferBytes; hw->samples = bc.dwBufferBytes >> hw->info.shift; ds->s = s; #ifdef DEBUG_DSOUND dolog ("caps %ld, desc %ld\n", bc.dwBufferBytes, bd.dwBufferBytes); - -dolog ("bufsize %d, freq %d, chan %d, fmt %d\n", - hw->bufsize, settings.freq, settings.nchannels, settings.fmt); #endif return 0; @@ -276,3 +275,5 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, #undef BUFPTR #undef FIELD #undef FIELD2 +#undef HWVOICE +#undef DSOUNDVOICE diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index dfcb70c81a..7b3266aaf3 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -53,19 +53,11 @@ typedef struct { typedef struct { HWVoiceOut hw; LPDIRECTSOUNDBUFFER dsound_buffer; -DWORD old_pos; -int first_time; dsound *s; -#ifdef DEBUG_DSOUND -DWORD old_ppos; -DWORD played; -DWORD mixed; -#endif } DSoundVoiceOut; typedef struct { HWVoiceIn hw; -int first_time; LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer; dsound *s; } DSoundVoiceIn; @@ -243,11 +235,6 @@ static void GCC_FMT_ATTR (3, 4) dsound_logerr2 ( dsound_log_hresult (hr); } -static uint64_t usecs_to_bytes(struct audio_pcm_info *info, uint32_t usecs) -{ -return muldiv64(usecs, info->bytes_per_second, 100); -} - #ifdef DEBUG_DSOUND static void print_wave_format (WAVEFORMATEX *wfx) { @@ -312,33 +299,6 @@ static int dsound_get_status_in (LPDIRECTSOUNDCAPTUREBUFFER dscb, return 0; } -static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len) -{ -int src_len1 = dst_len; -int src_len2 = 0; -int pos = hw->rpos + dst_len; -struct st_sample *src1 = hw->mix_buf + hw->rpos; -struct st_sample *src2 = NULL; - -if (pos > hw->samples) { -src_len1 = hw->samples - hw->rpos; -src2 = hw->mix_buf; -src_len2 = dst_len - sr
[Qemu-devel] [PATCH v2 26/52] audio: remove read and write pcm_ops
They just called audio_pcm_sw_read/write anyway, so it makes no sense to have them too. (The noaudio's read is the only exception, but it should work with the generic code too.) Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c | 12 audio/audio.c | 8 audio/audio_int.h | 5 - audio/coreaudio.c | 6 -- audio/dsoundaudio.c | 12 audio/noaudio.c | 19 --- audio/ossaudio.c| 12 audio/paaudio.c | 12 audio/sdlaudio.c| 6 -- audio/spiceaudio.c | 12 audio/wavaudio.c| 6 -- 11 files changed, 4 insertions(+), 106 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index ffc6220d7a..19de7d01cb 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -270,11 +270,6 @@ static int alsa_poll_in (HWVoiceIn *hw) return alsa_poll_helper (alsa->handle, &alsa->pollhlp, POLLIN); } -static int alsa_write (SWVoiceOut *sw, void *buf, int len) -{ -return audio_pcm_sw_write (sw, buf, len); -} - static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness) { switch (fmt) { @@ -996,11 +991,6 @@ static int alsa_run_in (HWVoiceIn *hw) return read_samples; } -static int alsa_read (SWVoiceIn *sw, void *buf, int size) -{ -return audio_pcm_sw_read (sw, buf, size); -} - static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...) { ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; @@ -1070,13 +1060,11 @@ static struct audio_pcm_ops alsa_pcm_ops = { .init_out = alsa_init_out, .fini_out = alsa_fini_out, .run_out = alsa_run_out, -.write= alsa_write, .ctl_out = alsa_ctl_out, .init_in = alsa_init_in, .fini_in = alsa_fini_in, .run_in = alsa_run_in, -.read = alsa_read, .ctl_in = alsa_ctl_in, }; diff --git a/audio/audio.c b/audio/audio.c index 4779061859..1ea80ba6a7 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -598,7 +598,7 @@ static int audio_pcm_sw_get_rpos_in (SWVoiceIn *sw) } } -int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size) +static int audio_pcm_sw_read(SWVoiceIn *sw, void *buf, int size) { HWVoiceIn *hw = sw->hw; int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0; @@ -700,7 +700,7 @@ static int audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live) /* * Soft voice (playback) */ -int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size) +static int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size) { int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck; int ret = 0, pos = 0, total = 0; @@ -858,7 +858,7 @@ int AUD_write (SWVoiceOut *sw, void *buf, int size) return 0; } -return sw->hw->pcm_ops->write(sw, buf, size); +return audio_pcm_sw_write(sw, buf, size); } int AUD_read (SWVoiceIn *sw, void *buf, int size) @@ -873,7 +873,7 @@ int AUD_read (SWVoiceIn *sw, void *buf, int size) return 0; } -return sw->hw->pcm_ops->read(sw, buf, size); +return audio_pcm_sw_read(sw, buf, size); } int AUD_get_buffer_size_out (SWVoiceOut *sw) diff --git a/audio/audio_int.h b/audio/audio_int.h index 9950cea869..d269c38465 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -149,13 +149,11 @@ struct audio_pcm_ops { int (*init_out)(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque); void (*fini_out)(HWVoiceOut *hw); int (*run_out) (HWVoiceOut *hw, int live); -int (*write) (SWVoiceOut *sw, void *buf, int size); int (*ctl_out) (HWVoiceOut *hw, int cmd, ...); int (*init_in) (HWVoiceIn *hw, struct audsettings *as, void *drv_opaque); void (*fini_in) (HWVoiceIn *hw); int (*run_in) (HWVoiceIn *hw); -int (*read)(SWVoiceIn *sw, void *buf, int size); int (*ctl_in) (HWVoiceIn *hw, int cmd, ...); }; @@ -209,11 +207,8 @@ audio_driver *audio_driver_lookup(const char *name); void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as); void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len); -int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int len); int audio_pcm_hw_get_live_in (HWVoiceIn *hw); -int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int len); - int audio_pcm_hw_clip_out (HWVoiceOut *hw, void *pcm_buf, int live, int pending); diff --git a/audio/coreaudio.c b/audio/coreaudio.c index b6935359ee..a45d69 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -489,11 +489,6 @@ static OSStatus audioDeviceIOProc( return 0; } -static int coreaudio_write (SWVoiceOut *sw, void *buf, int len) -{ -return audio_pcm_sw_write (sw, buf, len); -} - static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque) { @@ -692,7 +687,6 @@ static struct audio_pcm_ops coreaudio_pcm_ops = { .init_out = coreaudio_init_out, .fini_out = c
[Qemu-devel] [PATCH v2 40/52] audio: remove hw->samples, buffer_size_in/out pcm_ops
This patch removes the samples member from HWVoiceIn and HWVoiceOut. Backends can specify buffer size via the newly added buffer_size_in and buffer_size_out functions in audio_pcm_ops. They are optional, if not defined qemu will fall back to some built-in constant. Signed-off-by: Kővágó, Zoltán --- Not sure if this is necessary. At first it seemed like a good idea to have a function so that backends can compute the size on demand when needed and things like that, but currently it's just a burden. The only good feature is that it allows a backend to not define a function and let the audio subsystem choose a default value, but the same could be achieved by specifying that hw->samples = 0 means use a default value. So if you guys agree, I'll remove this patch. Maybe add an -audiodev parameter to change it, overriding whatever the backends supplies. --- audio/alsaaudio.c | 20 ++-- audio/audio.c | 2 -- audio/audio_int.h | 5 +++-- audio/audio_template.h | 24 +++- audio/coreaudio.c | 10 +- audio/dsound_template.h | 8 +++- audio/dsoundaudio.c | 4 audio/noaudio.c | 2 -- audio/ossaudio.c| 22 +++--- audio/paaudio.c | 21 + audio/sdlaudio.c| 10 +- audio/spiceaudio.c | 14 -- audio/wavaudio.c| 1 - 13 files changed, 113 insertions(+), 30 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 56271b1174..672803e5c2 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -45,6 +45,7 @@ struct pollhlp { typedef struct ALSAVoiceOut { HWVoiceOut hw; snd_pcm_t *handle; +size_t samples; struct pollhlp pollhlp; Audiodev *dev; } ALSAVoiceOut; @@ -52,6 +53,7 @@ typedef struct ALSAVoiceOut { typedef struct ALSAVoiceIn { HWVoiceIn hw; snd_pcm_t *handle; +size_t samples; struct pollhlp pollhlp; Audiodev *dev; } ALSAVoiceIn; @@ -696,7 +698,7 @@ static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as, obt_as.endianness = obt.endianness; audio_pcm_init_info (&hw->info, &obt_as); -hw->samples = obt.samples; +alsa->samples = obt.samples; alsa->pollhlp.s = hw->s; alsa->handle = handle; @@ -704,6 +706,12 @@ static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as, return 0; } +static size_t alsa_buffer_size_out(HWVoiceOut *hw) +{ +ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; +return alsa->samples; +} + #define VOICE_CTL_PAUSE 0 #define VOICE_CTL_PREPARE 1 #define VOICE_CTL_START 2 @@ -790,7 +798,7 @@ static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) obt_as.endianness = obt.endianness; audio_pcm_init_info (&hw->info, &obt_as); -hw->samples = obt.samples; +alsa->samples = obt.samples; alsa->pollhlp.s = hw->s; alsa->handle = handle; @@ -798,6 +806,12 @@ static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) return 0; } +static size_t alsa_buffer_size_in(HWVoiceIn *hw) +{ +ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; +return alsa->samples; +} + static void alsa_fini_in (HWVoiceIn *hw) { ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; @@ -915,11 +929,13 @@ static void alsa_audio_fini (void *opaque) static struct audio_pcm_ops alsa_pcm_ops = { .init_out = alsa_init_out, .fini_out = alsa_fini_out, +.buffer_size_out = alsa_buffer_size_out, .write= alsa_write, .ctl_out = alsa_ctl_out, .init_in = alsa_init_in, .fini_in = alsa_fini_in, +.buffer_size_in = alsa_buffer_size_in, .read = alsa_read, .ctl_in = alsa_ctl_in, }; diff --git a/audio/audio.c b/audio/audio.c index f195d8eb95..7db183b357 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1742,8 +1742,6 @@ CaptureVoiceOut *AUD_add_capture( QLIST_INIT (&hw->sw_head); QLIST_INIT (&cap->cb_head); -/* XXX find a more elegant way */ -hw->samples = 4096 * 4; audio_pcm_hw_alloc_resources_out(hw); audio_pcm_init_info (&hw->info, as); diff --git a/audio/audio_int.h b/audio/audio_int.h index a5add3c2b8..598038d999 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -70,7 +70,6 @@ typedef struct HWVoiceOut { void *buf_emul; size_t pos_emul, pending_emul, size_emul; -size_t samples; QLIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head; QLIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head; int ctl_caps; @@ -93,7 +92,6 @@ typedef struct HWVoiceIn { void *buf_emul; size_t pos_emul, pending_emul, size_emul; -size_t samples; QLIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head; int ctl_caps; struct audio_pcm_ops *pcm_ops; @@ -155,6 +153,8 @@ struct audio_pcm_ops { int(*init_out)(HWVoiceOut *hw, audsettings *as, void *drv_opaque); void (*fini_out)(HWVoiceOut *hw); size_t (*write)
[Qemu-devel] [PATCH v2 41/52] audio: common rate control code for timer based outputs
This commit removes the ad-hoc rate-limiting code from noaudio and wavaudio, and replaces them with a (slightly modified) code from spiceaudio. This way multiple write calls (for example when the circular buffer wraps around) do not cause problems. Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 30 audio/audio_int.h | 9 + audio/noaudio.c| 49 +- audio/spiceaudio.c | 49 +++--- audio/wavaudio.c | 21 ++-- 5 files changed, 78 insertions(+), 80 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 7db183b357..f89bce3a34 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -2024,3 +2024,33 @@ const char *audio_get_id(QEMUSoundCard *card) return ""; } } + +void audio_rate_start(RateCtl *rate) +{ +memset(rate, 0, sizeof(RateCtl)); +rate->start_ticks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + +size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate, +size_t bytes_avail) +{ +int64_t now; +int64_t ticks; +int64_t bytes; +int64_t samples; +size_t ret; + +now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +ticks = now - rate->start_ticks; +bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND); +samples = (bytes - rate->bytes_sent) >> info->shift; +if (samples < 0 || samples > 65536) { +AUD_log(NULL, "Resetting rate control (%" PRId64 " samples)", samples); +audio_rate_start(rate); +samples = 0; +} + +ret = MIN(samples << info->shift, bytes_avail); +rate->bytes_sent += ret; +return ret; +} diff --git a/audio/audio_int.h b/audio/audio_int.h index 598038d999..0f0ea3e040 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -242,6 +242,15 @@ void *audio_calloc (const char *funcname, int nmemb, size_t size); void audio_run(AudioState *s, const char *msg); +typedef struct RateCtl { +int64_t start_ticks; +int64_t bytes_sent; +} RateCtl; + +void audio_rate_start(RateCtl *rate); +size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate, +size_t bytes_avail); + #define VOICE_ENABLE 1 #define VOICE_DISABLE 2 #define VOICE_VOLUME 3 diff --git a/audio/noaudio.c b/audio/noaudio.c index 9b1dfb551d..85241612cf 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -32,32 +32,26 @@ typedef struct NoVoiceOut { HWVoiceOut hw; -int64_t old_ticks; +RateCtl rate; } NoVoiceOut; typedef struct NoVoiceIn { HWVoiceIn hw; -int64_t old_ticks; +RateCtl rate; } NoVoiceIn; static size_t no_write(HWVoiceOut *hw, void *buf, size_t len) { NoVoiceOut *no = (NoVoiceOut *) hw; -int64_t now; -int64_t ticks; -int64_t bytes; - -now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -ticks = now - no->old_ticks; -bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - -no->old_ticks = now; -return MIN(len, bytes); +return audio_rate_get_bytes(&hw->info, &no->rate, len); } static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque) { +NoVoiceOut *no = (NoVoiceOut *) hw; + audio_pcm_init_info (&hw->info, as); +audio_rate_start(&no->rate); return 0; } @@ -68,14 +62,20 @@ static void no_fini_out (HWVoiceOut *hw) static int no_ctl_out (HWVoiceOut *hw, int cmd, ...) { -(void) hw; -(void) cmd; +NoVoiceOut *no = (NoVoiceOut *) hw; + +if (cmd == VOICE_ENABLE) { +audio_rate_start(&no->rate); +} return 0; } static int no_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) { +NoVoiceIn *no = (NoVoiceIn *) hw; + audio_pcm_init_info (&hw->info, as); +audio_rate_start(&no->rate); return 0; } @@ -86,25 +86,20 @@ static void no_fini_in (HWVoiceIn *hw) static size_t no_read(HWVoiceIn *hw, void *buf, size_t size) { -size_t to_clear; NoVoiceIn *no = (NoVoiceIn *) hw; +int64_t bytes = audio_rate_get_bytes(&hw->info, &no->rate, size); -int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -int64_t ticks = now - no->old_ticks; -int64_t bytes = -muldiv64 (ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - -no->old_ticks = now; -to_clear = MIN(bytes, size); - -audio_pcm_info_clear_buf(&hw->info, buf, to_clear >> hw->info.shift); -return to_clear; +audio_pcm_info_clear_buf(&hw->info, buf, bytes >> hw->info.shift); +return bytes; } static int no_ctl_in (HWVoiceIn *hw, int cmd, ...) { -(void) hw; -(void) cmd; +NoVoiceIn *no = (NoVoiceIn *) hw; + +if (cmd == VOICE_ENABLE) { +audio_rate_start(&no->rate); +} return 0; } diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 709245e453..2495866c82 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -40,15 +40,10 @@ #define L
[Qemu-devel] [PATCH v2 32/52] noaudio: port to the new audio backend api
Signed-off-by: Kővágó, Zoltán --- audio/noaudio.c | 39 +++ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/audio/noaudio.c b/audio/noaudio.c index c49f2df4b3..6a3a1c418b 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -40,10 +40,9 @@ typedef struct NoVoiceIn { int64_t old_ticks; } NoVoiceIn; -static int no_run_out (HWVoiceOut *hw, int live) +static size_t no_write(HWVoiceOut *hw, void *buf, size_t len) { NoVoiceOut *no = (NoVoiceOut *) hw; -int decr, samples; int64_t now; int64_t ticks; int64_t bytes; @@ -51,13 +50,9 @@ static int no_run_out (HWVoiceOut *hw, int live) now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); ticks = now - no->old_ticks; bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); -bytes = MIN(bytes, INT_MAX); -samples = bytes >> hw->info.shift; no->old_ticks = now; -decr = MIN (live, samples); -hw->rpos = (hw->rpos + decr) % hw->samples; -return decr; +return MIN(len, bytes); } static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque) @@ -91,25 +86,21 @@ static void no_fini_in (HWVoiceIn *hw) (void) hw; } -static int no_run_in (HWVoiceIn *hw) +static size_t no_read(HWVoiceIn *hw, void *buf, size_t size) { +size_t to_clear; NoVoiceIn *no = (NoVoiceIn *) hw; -int live = audio_pcm_hw_get_live_in (hw); -int dead = hw->samples - live; -int samples = 0; -if (dead) { -int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -int64_t ticks = now - no->old_ticks; -int64_t bytes = -muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); +int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +int64_t ticks = now - no->old_ticks; +int64_t bytes = +muldiv64 (ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); -no->old_ticks = now; -bytes = MIN (bytes, INT_MAX); -samples = bytes >> hw->info.shift; -samples = MIN (samples, dead); -} -return samples; +no->old_ticks = now; +to_clear = MIN(bytes, size); + +audio_pcm_info_clear_buf(&hw->info, buf, to_clear >> hw->info.shift); +return to_clear; } static int no_ctl_in (HWVoiceIn *hw, int cmd, ...) @@ -132,12 +123,12 @@ static void no_audio_fini (void *opaque) static struct audio_pcm_ops no_pcm_ops = { .init_out = no_init_out, .fini_out = no_fini_out, -.run_out = no_run_out, +.write= no_write, .ctl_out = no_ctl_out, .init_in = no_init_in, .fini_in = no_fini_in, -.run_in = no_run_in, +.read = no_read, .ctl_in = no_ctl_in }; -- 2.20.1
[Qemu-devel] [PATCH v2 42/52] audio: split ctl_* functions into enable_* and volume_*
This way we no longer need vararg functions, improving compile time error detection. Also now it's possible to check actually what commands are supported, without needing to manually update ctl_caps. Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c | 56 +++--- audio/audio.c | 45 +-- audio/audio_int.h | 15 ++--- audio/audio_template.h | 1 - audio/coreaudio.c | 13 ++--- audio/dsoundaudio.c| 50 +++- audio/noaudio.c| 14 ++--- audio/ossaudio.c | 78 ++--- audio/paaudio.c| 126 - audio/sdlaudio.c | 17 +- audio/spiceaudio.c | 101 ++--- audio/wavaudio.c | 7 +-- 12 files changed, 213 insertions(+), 310 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 672803e5c2..bc097b1f31 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -745,34 +745,28 @@ static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int ctl) return 0; } -static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void alsa_enable_out(HWVoiceOut *hw, bool enable) { ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.alsa_out; -switch (cmd) { -case VOICE_ENABLE: -{ -bool poll_mode = !apdo->has_try_poll || apdo->try_poll; +if (enable) { +bool poll_mode = !apdo->has_try_poll || apdo->try_poll; -ldebug ("enabling voice\n"); -if (poll_mode && alsa_poll_out (hw)) { -poll_mode = 0; -} -hw->poll_mode = poll_mode; -return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PREPARE); +ldebug ("enabling voice\n"); +if (poll_mode && alsa_poll_out (hw)) { +poll_mode = 0; } - -case VOICE_DISABLE: +hw->poll_mode = poll_mode; +alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PREPARE); +} else { ldebug ("disabling voice\n"); if (hw->poll_mode) { hw->poll_mode = 0; alsa_fini_poll (&alsa->pollhlp); } -return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PAUSE); +alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PAUSE); } - -return -1; } static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) @@ -861,35 +855,29 @@ static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len) return pos; } -static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...) +static void alsa_enable_in(HWVoiceIn *hw, bool enable) { ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.alsa_in; -switch (cmd) { -case VOICE_ENABLE: -{ -bool poll_mode = !apdo->has_try_poll || apdo->try_poll; +if (enable) { +bool poll_mode = !apdo->has_try_poll || apdo->try_poll; -ldebug ("enabling voice\n"); -if (poll_mode && alsa_poll_in (hw)) { -poll_mode = 0; -} -hw->poll_mode = poll_mode; - -return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_START); +ldebug ("enabling voice\n"); +if (poll_mode && alsa_poll_in (hw)) { +poll_mode = 0; } +hw->poll_mode = poll_mode; -case VOICE_DISABLE: +alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_START); +} else { ldebug ("disabling voice\n"); if (hw->poll_mode) { hw->poll_mode = 0; alsa_fini_poll (&alsa->pollhlp); } -return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_PAUSE); +alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_PAUSE); } - -return -1; } static void *alsa_audio_init(Audiodev *dev) @@ -931,13 +919,13 @@ static struct audio_pcm_ops alsa_pcm_ops = { .fini_out = alsa_fini_out, .buffer_size_out = alsa_buffer_size_out, .write= alsa_write, -.ctl_out = alsa_ctl_out, +.enable_out = alsa_enable_out, .init_in = alsa_init_in, .fini_in = alsa_fini_in, .buffer_size_in = alsa_buffer_size_in, .read = alsa_read, -.ctl_in = alsa_ctl_in, +.enable_in = alsa_enable_in, }; static struct audio_driver alsa_audio_driver = { diff --git a/audio/audio.c b/audio/audio.c index f89bce3a34..7ba939560a 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -638,7 +638,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) total += isamp; } -if (!(hw->ctl_caps & VOICE_VOLUME_CAP)) { +if (!hw->pcm_ops->volume_in) { mixeng_volume (sw->buf, ret, &sw->vol); } @@ -725,7 +725,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size) if (swlim) { sw->conv (sw->buf, buf, swlim); -if (!(sw->h
[Qemu-devel] [PATCH v2 11/52] ossaudio: port to -audiodev config
Signed-off-by: Kővágó, Zoltán --- audio/audio_legacy.c | 17 + audio/ossaudio.c | 153 --- 2 files changed, 59 insertions(+), 111 deletions(-) diff --git a/audio/audio_legacy.c b/audio/audio_legacy.c index 48a22c390a..f37407586b 100644 --- a/audio/audio_legacy.c +++ b/audio/audio_legacy.c @@ -81,6 +81,21 @@ SimpleEnvMap dsound_map[] = { { /* End of list */ } }; +SimpleEnvMap oss_map[] = { +{ "QEMU_AUDIO_DAC_TRY_POLL", "oss-out.try-poll", ENV_TRANSFORM_BOOL }, +{ "QEMU_AUDIO_ADC_TRY_POLL", "oss-in.try-poll", ENV_TRANSFORM_BOOL }, + +{ "QEMU_OSS_FRAGSIZE", "buffer-len", ENV_TRANSFORM_BYTES_TO_USECS_OUT }, +{ "QEMU_OSS_NFRAGS", "buffer-count" }, +{ "QEMU_OSS_MMAP", "try-mmap", ENV_TRANSFORM_BOOL }, +{ "QEMU_OSS_DAC_DEV", "oss-out.dev" }, +{ "QEMU_OSS_ADC_DEV", "oss-in.dev" }, +{ "QEMU_OSS_EXCLUSIVE", "exclusive", ENV_TRANSFORM_BOOL }, +{ "QEMU_OSS_POLICY", "dsp-policy" }, + +{ /* End of list */ } +}; + static unsigned long long toull(const char *str) { unsigned long long ret; @@ -255,6 +270,8 @@ static void legacy_opt(const char *drv) handle_env_opts(opts, coreaudio_map); } else if (strcmp(drv, "dsound") == 0) { handle_env_opts(opts, dsound_map); +} else if (strcmp(drv, "oss") == 0) { +handle_env_opts(opts, oss_map); } } diff --git a/audio/ossaudio.c b/audio/ossaudio.c index e0cadbef29..83ff1d2ebd 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -27,6 +27,7 @@ #include "qemu-common.h" #include "qemu/main-loop.h" #include "qemu/host-utils.h" +#include "qapi/opts-visitor.h" #include "audio.h" #include "trace.h" @@ -37,16 +38,6 @@ #define USE_DSP_POLICY #endif -typedef struct OSSConf { -int try_mmap; -int nfrags; -int fragsize; -const char *devpath_out; -const char *devpath_in; -int exclusive; -int policy; -} OSSConf; - typedef struct OSSVoiceOut { HWVoiceOut hw; void *pcm_buf; @@ -56,7 +47,7 @@ typedef struct OSSVoiceOut { int fragsize; int mmapped; int pending; -OSSConf *conf; +Audiodev *dev; } OSSVoiceOut; typedef struct OSSVoiceIn { @@ -65,12 +56,12 @@ typedef struct OSSVoiceIn { int fd; int nfrags; int fragsize; -OSSConf *conf; +Audiodev *dev; } OSSVoiceIn; struct oss_params { int freq; -AudioFormat fmt; +int fmt; int nchannels; int nfrags; int fragsize; @@ -262,19 +253,26 @@ static int oss_get_version (int fd, int *version, const char *typ) } #endif -static int oss_open (int in, struct oss_params *req, - struct oss_params *obt, int *pfd, OSSConf* conf) +static int oss_open(int in, struct oss_params *req, audsettings *as, +struct oss_params *obt, int *pfd, Audiodev *dev) { +AudiodevOssOptions *oopts = &dev->u.oss; +AudiodevOssPerDirectionOptions *opdo = in ? oopts->oss_in : oopts->oss_out; +AudiodevPerDirectionOptions *pdo = in ? dev->in : dev->out; int fd; -int oflags = conf->exclusive ? O_EXCL : 0; +int oflags = (oopts->has_exclusive && oopts->exclusive) ? O_EXCL : 0; audio_buf_info abinfo; int fmt, freq, nchannels; int setfragment = 1; -const char *dspname = in ? conf->devpath_in : conf->devpath_out; +const char *dspname = opdo->has_dev ? opdo->dev : "/dev/dsp"; const char *typ = in ? "ADC" : "DAC"; +#ifdef USE_DSP_POLICY +int policy = oopts->has_dsp_policy ? oopts->dsp_policy : 5; +#endif /* Kludge needed to have working mmap on Linux */ -oflags |= conf->try_mmap ? O_RDWR : (in ? O_RDONLY : O_WRONLY); +oflags |= (oopts->has_try_mmap && oopts->try_mmap) ? +O_RDWR : (in ? O_RDONLY : O_WRONLY); fd = open (dspname, oflags | O_NONBLOCK); if (-1 == fd) { @@ -285,6 +283,8 @@ static int oss_open (int in, struct oss_params *req, freq = req->freq; nchannels = req->nchannels; fmt = req->fmt; +req->nfrags = pdo->has_buffer_count ? pdo->buffer_count : 4; +req->fragsize = audio_buffer_bytes(pdo, as, 23220); if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) { oss_logerr2 (errno, typ, "Failed to set sample size %d\n", req->fmt); @@ -308,18 +308,18 @@ static int oss_open (int in, struct oss_params *req, } #ifdef USE_DSP_POLICY -if (conf->policy >= 0) { +if (policy >= 0) { int version; if (!oss_get_version (fd, &version, typ)) { trace_oss_version(version); if (version >= 0x04) { -int policy = conf->policy; -if (ioctl (fd, SNDCTL_DSP_POLICY, &policy)) { +int policy2 = policy; +if (ioctl (fd, SNDCTL_DSP_POLICY, &policy2)) { oss_logerr2 (errno, typ, "Failed to set timing policy to %d\n", - conf->policy); + policy);
[Qemu-devel] [PATCH v2 52/52] usbaudio: change playback counters to 64 bit
With stereo playback, they need about 375 minutes of continuous audio playback to overflow, which is usually not a problem (as stopping and later resuming playback resets the counters). But with 7.1 audio, they only need about 95 minutes to overflow. After the overflow, the buf->prod % USBAUDIO_PACKET_SIZE(channels) assertion no longer holds true, which will result in overflowing the buffer. With 64 bit variables, it would take about 762000 years to overflow. Signed-off-by: Kővágó, Zoltán --- hw/usb/dev-audio.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 29475a2b70..45ffc3ebb3 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -577,9 +577,9 @@ static const USBDesc desc_audio_multi = { struct streambuf { uint8_t *data; -uint32_t size; -uint32_t prod; -uint32_t cons; +size_t size; +uint64_t prod; +uint64_t cons; }; static void streambuf_init(struct streambuf *buf, uint32_t size, @@ -600,12 +600,14 @@ static void streambuf_fini(struct streambuf *buf) static int streambuf_put(struct streambuf *buf, USBPacket *p, uint32_t channels) { -uint32_t free = buf->size - (buf->prod - buf->cons); +uint64_t free = buf->size - (buf->prod - buf->cons); if (free < USBAUDIO_PACKET_SIZE(channels)) { return 0; } +/* can happen if prod overflows */ +assert(buf->prod % USBAUDIO_PACKET_SIZE(channels) == 0); usb_packet_copy(p, buf->data + (buf->prod % buf->size), USBAUDIO_PACKET_SIZE(channels)); buf->prod += USBAUDIO_PACKET_SIZE(channels); @@ -614,7 +616,7 @@ static int streambuf_put(struct streambuf *buf, USBPacket *p, uint32_t channels) static uint8_t *streambuf_get(struct streambuf *buf, size_t *len) { -uint32_t used = buf->prod - buf->cons; +uint64_t used = buf->prod - buf->cons; uint8_t *data; if (!used) { -- 2.20.1
[Qemu-devel] [PATCH v2 06/52] audio: -audiodev command line option basic implementation
Audio drivers now get an Audiodev * as config paramters, instead of the global audio_option structs. There is some code in audio/audio_legacy.c that converts the old environment variables to audiodev options (this way backends do not have to worry about legacy options). It also contains a replacement of -audio-help, which prints out the equivalent -audiodev based config of the currently specified environment variables. Note that backends are not updated and still rely on environment variables. Also note that (due to moving try-poll from global to backend specific option) currently ALSA and OSS will always try poll mode, regardless of environment variables or -audiodev options. Signed-off-by: Kővágó, Zoltán --- audio/Makefile.objs| 2 +- audio/alsaaudio.c | 2 +- audio/audio.c | 589 - audio/audio.h | 20 +- audio/audio_int.h | 6 +- audio/audio_legacy.c | 211 +++ audio/audio_template.h | 13 +- audio/coreaudio.c | 2 +- audio/dsoundaudio.c| 2 +- audio/noaudio.c| 2 +- audio/ossaudio.c | 2 +- audio/paaudio.c| 2 +- audio/sdlaudio.c | 2 +- audio/spiceaudio.c | 2 +- audio/wavaudio.c | 2 +- vl.c | 11 +- 16 files changed, 491 insertions(+), 379 deletions(-) create mode 100644 audio/audio_legacy.c diff --git a/audio/Makefile.objs b/audio/Makefile.objs index db4fa7f18f..dca87f6347 100644 --- a/audio/Makefile.objs +++ b/audio/Makefile.objs @@ -1,4 +1,4 @@ -common-obj-y = audio.o noaudio.o wavaudio.o mixeng.o +common-obj-y = audio.o audio_legacy.o noaudio.o wavaudio.o mixeng.o common-obj-$(CONFIG_SPICE) += spiceaudio.o common-obj-$(CONFIG_AUDIO_COREAUDIO) += coreaudio.o common-obj-$(CONFIG_AUDIO_DSOUND) += dsoundaudio.o diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 5bd034267f..8302f3e882 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -1125,7 +1125,7 @@ static ALSAConf glob_conf = { .pcm_name_in = "default", }; -static void *alsa_audio_init (void) +static void *alsa_audio_init(Audiodev *dev) { ALSAConf *conf = g_malloc(sizeof(ALSAConf)); *conf = glob_conf; diff --git a/audio/audio.c b/audio/audio.c index 96cbd57c37..e7f25ea84b 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -25,7 +25,12 @@ #include "hw/hw.h" #include "audio.h" #include "monitor/monitor.h" +#include "qapi/opts-visitor.h" #include "qemu/timer.h" +#include "qemu/option.h" +#include "qemu/config-file.h" +#include "qapi/error.h" +#include "qapi/qapi-visit-audio.h" #include "sysemu/sysemu.h" #include "qemu/cutils.h" #include "sysemu/replay.h" @@ -46,11 +51,12 @@ The 1st one is the one used by default, that is the reason that we generate the list. */ -static const char *audio_prio_list[] = { +const char *audio_prio_list[] = { "spice", CONFIG_AUDIO_DRIVERS "none", "wav", +NULL }; static QLIST_HEAD(, audio_driver) audio_drivers; @@ -80,61 +86,6 @@ audio_driver *audio_driver_lookup(const char *name) return NULL; } -static void audio_module_load_all(void) -{ -int i; - -for (i = 0; i < ARRAY_SIZE(audio_prio_list); i++) { -audio_driver_lookup(audio_prio_list[i]); -} -} - -struct fixed_settings { -int enabled; -int nb_voices; -int greedy; -struct audsettings settings; -}; - -static struct { -struct fixed_settings fixed_out; -struct fixed_settings fixed_in; -union { -int hertz; -int64_t ticks; -} period; -int try_poll_in; -int try_poll_out; -} conf = { -.fixed_out = { /* DAC fixed settings */ -.enabled = 1, -.nb_voices = 1, -.greedy = 1, -.settings = { -.freq = 44100, -.nchannels = 2, -.fmt = AUDIO_FORMAT_S16, -.endianness = AUDIO_HOST_ENDIANNESS, -} -}, - -.fixed_in = { /* ADC fixed settings */ -.enabled = 1, -.nb_voices = 1, -.greedy = 1, -.settings = { -.freq = 44100, -.nchannels = 2, -.fmt = AUDIO_FORMAT_S16, -.endianness = AUDIO_HOST_ENDIANNESS, -} -}, - -.period = { .hertz = 100 }, -.try_poll_in = 1, -.try_poll_out = 1, -}; - static AudioState glob_audio_state; const struct mixeng_volume nominal_volume = { @@ -151,9 +102,6 @@ const struct mixeng_volume nominal_volume = { #ifdef AUDIO_IS_FLAWLESS_AND_NO_CHECKS_ARE_REQURIED #error No its not #else -static void audio_print_options (const char *prefix, - struct audio_option *opt); - int audio_bug (const char *funcname, int cond) { if (cond) { @@ -161,16 +109,9 @@ int audio_bug (const char *funcname, int cond) AUD_log (NULL, "A bug was just triggered in %s\n", funcname); if (!shown) { -struct audio_driver *d; - shown = 1; AUD_log (NULL, "Save all you
[Qemu-devel] [PATCH v2 27/52] audio: use size_t where makes sense
Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c | 8 +- audio/audio.c | 162 audio/audio.h | 4 +- audio/audio_int.h | 22 +++--- audio/audio_template.h | 6 +- audio/mixeng.h | 11 ++- audio/ossaudio.c| 18 ++--- audio/paaudio.c | 8 +- audio/rate_template.h | 2 +- audio/sdlaudio.c| 3 +- audio/wavaudio.c| 4 +- include/sysemu/replay.h | 4 +- replay/replay-audio.c | 16 ++-- 13 files changed, 133 insertions(+), 135 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 19de7d01cb..69e7a3868c 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -747,8 +747,8 @@ static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as, alsa->pcm_buf = audio_calloc(__func__, obt.samples, 1 << hw->info.shift); if (!alsa->pcm_buf) { -dolog ("Could not allocate DAC buffer (%d samples, each %d bytes)\n", - hw->samples, 1 << hw->info.shift); +dolog("Could not allocate DAC buffer (%zu samples, each %d bytes)\n", + hw->samples, 1 << hw->info.shift); alsa_anal_close1 (&handle); return -1; } @@ -849,8 +849,8 @@ static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) alsa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); if (!alsa->pcm_buf) { -dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n", - hw->samples, 1 << hw->info.shift); +dolog("Could not allocate ADC buffer (%zu samples, each %d bytes)\n", + hw->samples, 1 << hw->info.shift); alsa_anal_close1 (&handle); return -1; } diff --git a/audio/audio.c b/audio/audio.c index 1ea80ba6a7..27a8a31a64 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -530,10 +530,10 @@ static int audio_attach_capture (HWVoiceOut *hw) /* * Hard voice (capture) */ -static int audio_pcm_hw_find_min_in (HWVoiceIn *hw) +static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw) { SWVoiceIn *sw; -int m = hw->total_samples_captured; +size_t m = hw->total_samples_captured; for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { if (sw->active) { @@ -543,28 +543,28 @@ static int audio_pcm_hw_find_min_in (HWVoiceIn *hw) return m; } -int audio_pcm_hw_get_live_in (HWVoiceIn *hw) +size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) { -int live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); -if (audio_bug(__func__, live < 0 || live > hw->samples)) { -dolog ("live=%d hw->samples=%d\n", live, hw->samples); +size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); +if (audio_bug(__func__, live > hw->samples)) { +dolog("live=%zu hw->samples=%zu\n", live, hw->samples); return 0; } return live; } -int audio_pcm_hw_clip_out (HWVoiceOut *hw, void *pcm_buf, - int live, int pending) +size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, + size_t live, size_t pending) { -int left = hw->samples - pending; -int len = MIN (left, live); -int clipped = 0; +size_t left = hw->samples - pending; +size_t len = MIN (left, live); +size_t clipped = 0; while (len) { struct st_sample *src = hw->mix_buf + hw->rpos; uint8_t *dst = advance (pcm_buf, hw->rpos << hw->info.shift); -int samples_till_end_of_buf = hw->samples - hw->rpos; -int samples_to_clip = MIN (len, samples_till_end_of_buf); +size_t samples_till_end_of_buf = hw->samples - hw->rpos; +size_t samples_to_clip = MIN (len, samples_till_end_of_buf); hw->clip (dst, src, samples_to_clip); @@ -578,14 +578,14 @@ int audio_pcm_hw_clip_out (HWVoiceOut *hw, void *pcm_buf, /* * Soft voice (capture) */ -static int audio_pcm_sw_get_rpos_in (SWVoiceIn *sw) +static size_t audio_pcm_sw_get_rpos_in(SWVoiceIn *sw) { HWVoiceIn *hw = sw->hw; -int live = hw->total_samples_captured - sw->total_hw_samples_acquired; -int rpos; +ssize_t live = hw->total_samples_captured - sw->total_hw_samples_acquired; +ssize_t rpos; if (audio_bug(__func__, live < 0 || live > hw->samples)) { -dolog ("live=%d hw->samples=%d\n", live, hw->samples); +dolog("live=%zu hw->samples=%zu\n", live, hw->samples); return 0; } @@ -598,17 +598,17 @@ static int audio_pcm_sw_get_rpos_in (SWVoiceIn *sw) } } -static int audio_pcm_sw_read(SWVoiceIn *sw, void *buf, int size) +static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) { HWVoiceIn *hw = sw->hw; -int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0; +size_t samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0; struct st_sample *src, *dst = sw->buf; rpos = audio_pcm_sw_get_rpos_in (sw) %
[Qemu-devel] [PATCH v2 21/52] paaudio: do not move stream when sink/source name is specified
Unless we disable stream moving, pulseaudio can easily move the stream on connect, effectively ignoring the source/sink specified by the user. Signed-off-by: Kővágó, Zoltán --- audio/paaudio.c | 5 + 1 file changed, 5 insertions(+) diff --git a/audio/paaudio.c b/audio/paaudio.c index 24b75ca503..21ffbf7f6e 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -516,6 +516,11 @@ static pa_stream *qpa_simple_new ( #endif |PA_STREAM_AUTO_TIMING_UPDATE; +if (dev) { +/* don't move the stream if the user specified a sink/source */ +flags |= PA_STREAM_DONT_MOVE; +} + if (dir == PA_STREAM_PLAYBACK) { r = pa_stream_connect_playback(stream, dev, attr, flags, NULL, NULL); } else { -- 2.20.1
[Qemu-devel] [PATCH v2 33/52] ossaudio: port to the new audio backend api
Signed-off-by: Kővágó, Zoltán --- audio/ossaudio.c | 287 +-- 1 file changed, 104 insertions(+), 183 deletions(-) diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 05c7d6f85c..f1b57c87b4 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -40,19 +40,15 @@ typedef struct OSSVoiceOut { HWVoiceOut hw; -void *pcm_buf; int fd; -int wpos; int nfrags; int fragsize; int mmapped; -int pending; Audiodev *dev; } OSSVoiceOut; typedef struct OSSVoiceIn { HWVoiceIn hw; -void *pcm_buf; int fd; int nfrags; int fragsize; @@ -371,97 +367,87 @@ static int oss_open(int in, struct oss_params *req, audsettings *as, return -1; } -static void oss_write_pending (OSSVoiceOut *oss) +static size_t oss_get_available_bytes(OSSVoiceOut *oss) { -HWVoiceOut *hw = &oss->hw; +int err; +struct count_info cntinfo; +assert(oss->mmapped); +err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo); +if (err < 0) { +oss_logerr(errno, "SNDCTL_DSP_GETOPTR failed\n"); +return 0; +} + +return audio_ring_dist(cntinfo.ptr, oss->hw.pos_emul, oss->hw.size_emul); +} + +static void *oss_get_buffer_out(HWVoiceOut *hw, size_t *size) +{ +OSSVoiceOut *oss = (OSSVoiceOut *) hw; +if (oss->mmapped) { +*size = MIN(oss_get_available_bytes(oss), hw->size_emul - hw->pos_emul); +return hw->buf_emul + hw->pos_emul; +} else { +return audio_generic_get_buffer_out(hw, size); +} +} + +static size_t oss_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size) +{ +OSSVoiceOut *oss = (OSSVoiceOut *) hw; if (oss->mmapped) { -return; +assert(buf == hw->buf_emul + hw->pos_emul && size < hw->size_emul); + +hw->pos_emul = (hw->pos_emul + size) % hw->size_emul; +return size; +} else { +return audio_generic_put_buffer_out(hw, buf, size); +} +} + +static size_t oss_write(HWVoiceOut *hw, void *buf, size_t len) +{ +OSSVoiceOut *oss = (OSSVoiceOut *) hw; +size_t pos; + +if (oss->mmapped) { +size_t total_len; +len = MIN(len, oss_get_available_bytes(oss)); + +total_len = len; +while (len) { +size_t to_copy = MIN(len, hw->size_emul - hw->pos_emul); +memcpy(hw->buf_emul + hw->pos_emul, buf, to_copy); + +hw->pos_emul = (hw->pos_emul + to_copy) % hw->pos_emul; +buf += to_copy; +len -= to_copy; +} +return total_len; } -while (oss->pending) { -int samples_written; +pos = 0; +while (len) { ssize_t bytes_written; -int samples_till_end = hw->samples - oss->wpos; -int samples_to_write = MIN (oss->pending, samples_till_end); -int bytes_to_write = samples_to_write << hw->info.shift; -void *pcm = advance (oss->pcm_buf, oss->wpos << hw->info.shift); +void *pcm = advance(buf, pos); -bytes_written = write (oss->fd, pcm, bytes_to_write); +bytes_written = write(oss->fd, pcm, len); if (bytes_written < 0) { if (errno != EAGAIN) { -oss_logerr (errno, "failed to write %d bytes\n", -bytes_to_write); +oss_logerr(errno, "failed to write %zu bytes\n", + len); } -break; -} - -if (bytes_written & hw->info.align) { -dolog ("misaligned write asked for %d, but got %zd\n", - bytes_to_write, bytes_written); -return; +return pos; } -samples_written = bytes_written >> hw->info.shift; -oss->pending -= samples_written; -oss->wpos = (oss->wpos + samples_written) % hw->samples; -if (bytes_written - bytes_to_write) { +pos += bytes_written; +if (bytes_written < len) { break; } +len -= bytes_written; } -} - -static int oss_run_out (HWVoiceOut *hw, int live) -{ -OSSVoiceOut *oss = (OSSVoiceOut *) hw; -int err, decr; -struct audio_buf_info abinfo; -struct count_info cntinfo; -int bufsize; - -bufsize = hw->samples << hw->info.shift; - -if (oss->mmapped) { -int bytes, pos; - -err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo); -if (err < 0) { -oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n"); -return 0; -} - -pos = hw->rpos << hw->info.shift; -bytes = audio_ring_dist (cntinfo.ptr, pos, bufsize); -decr = MIN (bytes >> hw->info.shift, live); -} -else { -err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo); -if (err < 0) { -oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n"); -return 0; -} - -if (abinfo.bytes > bufsize) { -trace_oss_invalid_available_size(abinfo.bytes, bufsize); -
[Qemu-devel] [PATCH v2 50/52] usb-audio: do not count on avail bytes actually available
This assumption is no longer true when mixeng is turned off. Signed-off-by: Kővágó, Zoltán --- hw/usb/dev-audio.c | 30 ++ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 589977d96c..510585ad7a 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -318,27 +318,28 @@ static int streambuf_put(struct streambuf *buf, USBPacket *p) { uint32_t free = buf->size - (buf->prod - buf->cons); -if (!free) { +if (free < USBAUDIO_PACKET_SIZE) { return 0; } -assert(free >= USBAUDIO_PACKET_SIZE); + usb_packet_copy(p, buf->data + (buf->prod % buf->size), USBAUDIO_PACKET_SIZE); buf->prod += USBAUDIO_PACKET_SIZE; return USBAUDIO_PACKET_SIZE; } -static uint8_t *streambuf_get(struct streambuf *buf) +static uint8_t *streambuf_get(struct streambuf *buf, size_t *len) { uint32_t used = buf->prod - buf->cons; uint8_t *data; if (!used) { +*len = 0; return NULL; } -assert(used >= USBAUDIO_PACKET_SIZE); data = buf->data + (buf->cons % buf->size); -buf->cons += USBAUDIO_PACKET_SIZE; +*len = MIN(buf->prod - buf->cons, + buf->size - (buf->cons % buf->size)); return data; } @@ -370,16 +371,21 @@ static void output_callback(void *opaque, int avail) USBAudioState *s = opaque; uint8_t *data; -for (;;) { -if (avail < USBAUDIO_PACKET_SIZE) { -return; -} -data = streambuf_get(&s->out.buf); +while (avail) { +size_t written, len; + +data = streambuf_get(&s->out.buf, &len); if (!data) { return; } -AUD_write(s->out.voice, data, USBAUDIO_PACKET_SIZE); -avail -= USBAUDIO_PACKET_SIZE; + +written = AUD_write(s->out.voice, data, len); +avail -= written; +s->out.buf.cons += written; + +if (written < len) { +return; +} } } -- 2.20.1
[Qemu-devel] [PATCH v2 28/52] audio: api for mixeng code free backends
Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 211 - audio/audio_int.h | 45 +++-- audio/audio_template.h | 1 + 3 files changed, 247 insertions(+), 10 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 27a8a31a64..1897e22444 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -575,6 +575,25 @@ size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, return clipped; } +static void audio_pcm_hw_clip_out2(HWVoiceOut *hw, void *pcm_buf, size_t len) +{ +size_t clipped = 0; +size_t pos = hw->rpos; + +while (len) { +st_sample *src = hw->mix_buf + pos; +uint8_t *dst = advance (pcm_buf, clipped << hw->info.shift); +size_t samples_till_end_of_buf = hw->samples - pos; +size_t samples_to_clip = MIN(len, samples_till_end_of_buf); + +hw->clip (dst, src, samples_to_clip); + +pos = (pos + samples_to_clip) % hw->samples; +len -= samples_to_clip; +clipped += samples_to_clip; +} +} + /* * Soft voice (capture) */ @@ -1052,6 +1071,31 @@ static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos, mixeng_clear(hw->mix_buf, samples - n); } +static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) +{ +size_t clipped = 0; + +while (live) { +size_t size, decr, proc; +void *buf = hw->pcm_ops->get_buffer_out(hw, &size); + +decr = MIN(size >> hw->info.shift, live); +audio_pcm_hw_clip_out2(hw, buf, decr); +proc = hw->pcm_ops->put_buffer_out(hw, buf, decr << hw->info.shift) >> +hw->info.shift; + +live -= proc; +clipped += proc; +hw->rpos = (hw->rpos + proc) % hw->samples; + +if (proc == 0 || proc < decr) { +break; +} +} + +return clipped; +} + static void audio_run_out (AudioState *s) { HWVoiceOut *hw = NULL; @@ -1099,7 +1143,11 @@ static void audio_run_out (AudioState *s) } prev_rpos = hw->rpos; -played = hw->pcm_ops->run_out (hw, live); +if (hw->pcm_ops->run_out) { +played = hw->pcm_ops->run_out(hw, live); +} else { +played = audio_pcm_hw_run_out(hw, live); +} replay_audio_out(&played); if (audio_bug(__func__, hw->rpos >= hw->samples)) { dolog("hw->rpos=%zu hw->samples=%zu played=%zu\n", @@ -1158,6 +1206,35 @@ static void audio_run_out (AudioState *s) } } +static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples) +{ +size_t conv = 0; + +while (samples) { +size_t proc; +size_t size = samples << hw->info.shift; +void *buf = hw->pcm_ops->get_buffer_in(hw, &size); + +assert((size & hw->info.align) == 0); +if (size == 0) { +hw->pcm_ops->put_buffer_in(hw, buf, size); +break; +} + +proc = MIN(size >> hw->info.shift, + hw->samples - hw->wpos); + +hw->conv(hw->conv_buf + hw->wpos, buf, proc); +hw->wpos = (hw->wpos + proc) % hw->samples; + +samples -= proc; +conv += proc; +hw->pcm_ops->put_buffer_in(hw, buf, proc << hw->info.shift); +} + +return conv; +} + static void audio_run_in (AudioState *s) { HWVoiceIn *hw = NULL; @@ -1167,7 +1244,12 @@ static void audio_run_in (AudioState *s) size_t captured = 0, min; if (replay_mode != REPLAY_MODE_PLAY) { -captured = hw->pcm_ops->run_in(hw); +if (hw->pcm_ops->run_in) { +captured = hw->pcm_ops->run_in(hw); +} else { +captured = audio_pcm_hw_run_in( +hw, hw->samples - audio_pcm_hw_get_live_in(hw)); +} } replay_audio_in(&captured, hw->conv_buf, &hw->wpos, hw->samples); @@ -1261,12 +1343,137 @@ void audio_run(AudioState *s, const char *msg) #endif } +void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size) +{ +ssize_t start; + +if (unlikely(!hw->buf_emul)) { +size_t calc_size = hw->samples << hw->info.shift; +hw->buf_emul = g_malloc(calc_size); +hw->size_emul = calc_size; +hw->pos_emul = hw->pending_emul = 0; +} + +while (hw->pending_emul < hw->size_emul) { +size_t read_len = MIN(hw->size_emul - hw->pos_emul, + hw->size_emul - hw->pending_emul); +size_t read = hw->pcm_ops->read(hw, hw->buf_emul + hw->pos_emul, +read_len); +hw->pending_emul += read; +if (read < read_len) { +break; +} +} + +start = ((ssize_t) hw->pos_emul) - hw->pending_emul; +if (start < 0) { +start += hw->size_emul; +} +assert(start >= 0 && start < hw->size_emul); + +*size = MIN(hw->pending_emul, hw->size_emul - start); +return hw->buf_emul + start; +} + +void audio_generic_put_buffer_in(HWVoiceI
[Qemu-devel] [PATCH v2 24/52] audio: do not run each backend in audio_run
audio_run is called manually by alsa and oss backends when polling. In this case only the requesting backend should be run, not all of them. Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c | 7 +-- audio/audio.c | 14 +- audio/audio_int.h | 2 +- audio/ossaudio.c | 12 ++-- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index d4bb540cb9..ffc6220d7a 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -39,6 +39,7 @@ struct pollhlp { struct pollfd *pfds; int count; int mask; +AudioState *s; }; typedef struct ALSAVoiceOut { @@ -199,11 +200,11 @@ static void alsa_poll_handler (void *opaque) break; case SND_PCM_STATE_PREPARED: -audio_run ("alsa run (prepared)"); +audio_run(hlp->s, "alsa run (prepared)"); break; case SND_PCM_STATE_RUNNING: -audio_run ("alsa run (running)"); +audio_run (hlp->s, "alsa run (running)"); break; default: @@ -757,6 +758,7 @@ static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as, return -1; } +alsa->pollhlp.s = hw->s; alsa->handle = handle; alsa->dev = dev; return 0; @@ -858,6 +860,7 @@ static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) return -1; } +alsa->pollhlp.s = hw->s; alsa->handle = handle; alsa->dev = dev; return 0; diff --git a/audio/audio.c b/audio/audio.c index a32b86a813..4779061859 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -839,7 +839,7 @@ static void audio_timer (void *opaque) } s->timer_last = now; -audio_run("timer"); +audio_run(s, "timer"); audio_reset_timer(s); } @@ -1241,15 +1241,11 @@ static void audio_run_capture (AudioState *s) } } -void audio_run (const char *msg) +void audio_run(AudioState *s, const char *msg) { -AudioState *s; - -QTAILQ_FOREACH(s, &audio_states, list) { -audio_run_out (s); -audio_run_in (s); -audio_run_capture (s); -} +audio_run_out(s); +audio_run_in(s); +audio_run_capture(s); #ifdef DEBUG_POLL { diff --git a/audio/audio_int.h b/audio/audio_int.h index 9d9db8c270..9950cea869 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -220,7 +220,7 @@ int audio_pcm_hw_clip_out (HWVoiceOut *hw, void *pcm_buf, int audio_bug (const char *funcname, int cond); void *audio_calloc (const char *funcname, int nmemb, size_t size); -void audio_run (const char *msg); +void audio_run(AudioState *s, const char *msg); #define VOICE_ENABLE 1 #define VOICE_DISABLE 2 diff --git a/audio/ossaudio.c b/audio/ossaudio.c index ae06e58d13..fde62c8ce2 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -110,28 +110,28 @@ static void oss_anal_close (int *fdp) static void oss_helper_poll_out (void *opaque) { -(void) opaque; -audio_run ("oss_poll_out"); +AudioState *s = opaque; +audio_run(s, "oss_poll_out"); } static void oss_helper_poll_in (void *opaque) { -(void) opaque; -audio_run ("oss_poll_in"); +AudioState *s = opaque; +audio_run(s, "oss_poll_in"); } static void oss_poll_out (HWVoiceOut *hw) { OSSVoiceOut *oss = (OSSVoiceOut *) hw; -qemu_set_fd_handler (oss->fd, NULL, oss_helper_poll_out, NULL); +qemu_set_fd_handler(oss->fd, NULL, oss_helper_poll_out, hw->s); } static void oss_poll_in (HWVoiceIn *hw) { OSSVoiceIn *oss = (OSSVoiceIn *) hw; -qemu_set_fd_handler (oss->fd, oss_helper_poll_in, NULL, NULL); +qemu_set_fd_handler(oss->fd, oss_helper_poll_in, NULL, hw->s); } static int oss_write (SWVoiceOut *sw, void *buf, int len) -- 2.20.1
[Qemu-devel] [PATCH v2 36/52] spiceaudio: port to the new audio backend api
Signed-off-by: Kővágó, Zoltán --- audio/spiceaudio.c | 112 +++-- 1 file changed, 38 insertions(+), 74 deletions(-) diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index f963853ed8..d1605d3939 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -51,7 +51,7 @@ typedef struct SpiceVoiceOut { SpiceRateCtl rate; int active; uint32_t *frame; -uint32_t *fpos; +uint32_t fpos; uint32_t fsize; } SpiceVoiceOut; @@ -60,7 +60,6 @@ typedef struct SpiceVoiceIn { SpiceRecordInstance sin; SpiceRateCtl rate; int active; -uint32_t samples[LINE_IN_SAMPLES]; } SpiceVoiceIn; static const SpicePlaybackInterface playback_sif = { @@ -152,44 +151,36 @@ static void line_out_fini (HWVoiceOut *hw) spice_server_remove_interface (&out->sin.base); } -static int line_out_run (HWVoiceOut *hw, int live) +static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size) { -SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); -int rpos, decr; -int samples; +SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw); +size_t decr; -if (!live) { -return 0; +if (!out->frame) { +spice_server_playback_get_buffer(&out->sin, &out->frame, &out->fsize); +out->fpos = 0; } -decr = rate_get_samples (&hw->info, &out->rate); -decr = MIN (live, decr); +decr = rate_get_samples(&hw->info, &out->rate); +decr = MIN(out->fsize - out->fpos, decr); -samples = decr; -rpos = hw->rpos; -while (samples) { -int left_till_end_samples = hw->samples - rpos; -int len = MIN (samples, left_till_end_samples); +*size = decr << hw->info.shift; +return out->frame + out->fpos; +} -if (!out->frame) { -spice_server_playback_get_buffer (&out->sin, &out->frame, &out->fsize); -out->fpos = out->frame; -} -if (out->frame) { -len = MIN (len, out->fsize); -hw->clip (out->fpos, hw->mix_buf + rpos, len); -out->fsize -= len; -out->fpos += len; -if (out->fsize == 0) { -spice_server_playback_put_samples (&out->sin, out->frame); -out->frame = out->fpos = NULL; -} -} -rpos = (rpos + len) % hw->samples; -samples -= len; +static size_t line_out_put_buffer(HWVoiceOut *hw, void *buf, size_t size) +{ +SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw); + +out->fpos += size >> 2; +assert(buf == out->frame + out->fpos && out->fpos <= out->fsize); + +if (out->fpos == out->fsize) { /* buffer full */ +spice_server_playback_put_samples(&out->sin, out->frame); +out->frame = NULL; } -hw->rpos = rpos; -return decr; + +return size; } static int line_out_ctl (HWVoiceOut *hw, int cmd, ...) @@ -211,9 +202,9 @@ static int line_out_ctl (HWVoiceOut *hw, int cmd, ...) } out->active = 0; if (out->frame) { -memset (out->fpos, 0, out->fsize << 2); +memset(out->frame + out->fpos, 0, (out->fsize - out->fpos) << 2); spice_server_playback_put_samples (&out->sin, out->frame); -out->frame = out->fpos = NULL; +out->frame = NULL; } spice_server_playback_stop (&out->sin); break; @@ -275,49 +266,20 @@ static void line_in_fini (HWVoiceIn *hw) spice_server_remove_interface (&in->sin.base); } -static int line_in_run (HWVoiceIn *hw) +static size_t line_in_read(HWVoiceIn *hw, void *buf, size_t len) { SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); -int num_samples; -int ready; -int len[2]; -uint64_t delta_samp; -const uint32_t *samples; +uint64_t delta_samp = rate_get_samples(&hw->info, &in->rate); +uint64_t to_read = MIN(len >> 2, delta_samp); +size_t ready = spice_server_record_get_samples(&in->sin, buf, to_read); -if (!(num_samples = hw->samples - audio_pcm_hw_get_live_in (hw))) { -return 0; -} - -delta_samp = rate_get_samples (&hw->info, &in->rate); -num_samples = MIN (num_samples, delta_samp); - -ready = spice_server_record_get_samples (&in->sin, in->samples, num_samples); -samples = in->samples; +/* XXX: do we need this? */ if (ready == 0) { -static const uint32_t silence[LINE_IN_SAMPLES]; -samples = silence; -ready = LINE_IN_SAMPLES; +memset(buf, 0, to_read << 2); +ready = to_read; } -num_samples = MIN (ready, num_samples); - -if (hw->wpos + num_samples > hw->samples) { -len[0] = hw->samples - hw->wpos; -len[1] = num_samples - len[0]; -} else { -len[0] = num_samples; -len[1] = 0; -} - -hw->conv (hw->conv_buf + hw->wpos, samples, len[0]);
[Qemu-devel] [PATCH v2 30/52] coreaudio: port to the new audio backend api
Signed-off-by: Kővágó, Zoltán --- audio/coreaudio.c | 130 -- 1 file changed, 69 insertions(+), 61 deletions(-) diff --git a/audio/coreaudio.c b/audio/coreaudio.c index a45d69..a532e862dd 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -43,9 +43,6 @@ typedef struct coreaudioVoiceOut { UInt32 audioDevicePropertyBufferFrameSize; AudioStreamBasicDescription outputStreamBasicDescription; AudioDeviceIOProcID ioprocid; -int live; -int decr; -int rpos; } coreaudioVoiceOut; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 @@ -397,31 +394,29 @@ static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name) return 0; } -static int coreaudio_run_out (HWVoiceOut *hw, int live) -{ -int decr; -coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; - -if (coreaudio_lock (core, "coreaudio_run_out")) { -return 0; +#define COREAUDIO_WRAPPER_FUNC(name, ret_type, args_decl, args) \ +static ret_type glue(coreaudio_, name)args_decl \ +{ \ +coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; \ +ret_type ret; \ +\ +if (coreaudio_lock(core, "coreaudio_" #name)) { \ +return 0; \ +} \ +\ +ret = glue(audio_generic_, name)args; \ +\ +coreaudio_unlock(core, "coreaudio_" #name); \ +return ret; \ } - -if (core->decr > live) { -ldebug ("core->decr %d live %d core->live %d\n", -core->decr, -live, -core->live); -} - -decr = MIN (core->decr, live); -core->decr -= decr; - -core->live = live - decr; -hw->rpos = core->rpos; - -coreaudio_unlock (core, "coreaudio_run_out"); -return decr; -} +COREAUDIO_WRAPPER_FUNC(get_buffer_out, void *, (HWVocieOut *hw, size_t *size), + (hw, size)) +COREAUDIO_WRAPPER_FUNC(put_buffer_out_nowrite, size_t, + (HWVoiceOut *hw, void *buf, size_t size), + (hw, buf, size)) +COREAUDIO_WRAPPER_FUNC(write, size_t, (HWVoiceOut *hw, void *buf, size_t size), + (hw, buf, size)) +#undef COREAUDIO_WRAPPER_FUNC /* callback to feed audiooutput buffer */ static OSStatus audioDeviceIOProc( @@ -433,19 +428,11 @@ static OSStatus audioDeviceIOProc( const AudioTimeStamp* inOutputTime, void* hwptr) { -UInt32 frame, frameCount; -float *out = outOutputData->mBuffers[0].mData; +UInt32 frameCount, pending_frames; +void *out = outOutputData->mBuffers[0].mData; HWVoiceOut *hw = hwptr; coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr; -int rpos, live; -struct st_sample *src; -#ifndef FLOAT_MIXENG -#ifdef RECIPROCAL -const float scale = 1.f / UINT_MAX; -#else -const float scale = UINT_MAX; -#endif -#endif +size_t len; if (coreaudio_lock (core, "audioDeviceIOProc")) { inInputTime = 0; @@ -453,42 +440,51 @@ static OSStatus audioDeviceIOProc( } frameCount = core->audioDevicePropertyBufferFrameSize; -live = core->live; +pending_frames = hw->pending_emul >> hw->info.shift; /* if there are not enough samples, set signal and return */ -if (live < frameCount) { +if (pending_frames < frameCount) { inInputTime = 0; coreaudio_unlock (core, "audioDeviceIOProc(empty)"); return 0; } -rpos = core->rpos; -src = hw->mix_buf + rpos; +len = frameCount << hw->info.shift; +while (len) { +size_t write_len; +ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul; +if (start < 0) { +start += hw->size_emul; +} +assert(start >= 0 && start < hw->size_emul); -/* fill buffer */ -for (frame = 0; frame < frameCount; frame++) { -#ifdef FLOAT_MIXENG -*out++ = src[frame].l; /* left channel */ -*out++ = src[frame].r; /* right channel */ -#else -#ifdef RECIPROCAL -*out++ = src[frame].l * scale; /* left channel */ -*out++ = src[frame].r * scale; /* right channel */ -#else -*out++ = src[frame].l / scale; /* left channel */ -*out++ = src[frame].r / scale; /* right channel */ -#endif -#endif +write_len = MIN(MIN(hw->pending_emul, len), +hw->size_emul - start); + +memcpy(out, hw->buf_emul + start, write_len); +hw->pending_emul -= write_len; +len -= write_len; +out += write_len;
[Qemu-devel] [PATCH v2 22/52] paaudio: properly disconnect streams in fini_*
Currently this needs a workaround due to bug #74624 in pulseaudio. Reviewed-by: Marc-André Lureau Signed-off-by: Kővágó, Zoltán --- audio/paaudio.c | 25 +++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/audio/paaudio.c b/audio/paaudio.c index 21ffbf7f6e..fa867a8065 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -680,6 +680,27 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) return -1; } +static void qpa_simple_disconnect(PAConnection *c, pa_stream *stream) +{ +int err; + +pa_threaded_mainloop_lock(c->mainloop); +/* + * wait until actually connects. workaround pa bug #74624 + * https://bugs.freedesktop.org/show_bug.cgi?id=74624 + */ +while (pa_stream_get_state(stream) == PA_STREAM_CREATING) { +pa_threaded_mainloop_wait(c->mainloop); +} + +err = pa_stream_disconnect(stream); +if (err != 0) { +dolog("Failed to dissconnect! err=%d\n", err); +} +pa_stream_unref(stream); +pa_threaded_mainloop_unlock(c->mainloop); +} + static void qpa_fini_out (HWVoiceOut *hw) { void *ret; @@ -691,7 +712,7 @@ static void qpa_fini_out (HWVoiceOut *hw) audio_pt_join(&pa->pt, &ret, __func__); if (pa->stream) { -pa_stream_unref (pa->stream); +qpa_simple_disconnect(pa->g->conn, pa->stream); pa->stream = NULL; } @@ -711,7 +732,7 @@ static void qpa_fini_in (HWVoiceIn *hw) audio_pt_join(&pa->pt, &ret, __func__); if (pa->stream) { -pa_stream_unref (pa->stream); +qpa_simple_disconnect(pa->g->conn, pa->stream); pa->stream = NULL; } -- 2.20.1
[Qemu-devel] [PATCH v2 29/52] alsaaudio: port to the new audio backend api
Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c | 306 -- 1 file changed, 81 insertions(+), 225 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 69e7a3868c..56271b1174 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -44,9 +44,6 @@ struct pollhlp { typedef struct ALSAVoiceOut { HWVoiceOut hw; -int wpos; -int pending; -void *pcm_buf; snd_pcm_t *handle; struct pollhlp pollhlp; Audiodev *dev; @@ -55,7 +52,6 @@ typedef struct ALSAVoiceOut { typedef struct ALSAVoiceIn { HWVoiceIn hw; snd_pcm_t *handle; -void *pcm_buf; struct pollhlp pollhlp; Audiodev *dev; } ALSAVoiceIn; @@ -610,102 +606,62 @@ static int alsa_open(bool in, struct alsa_params_req *req, return -1; } -static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle) -{ -snd_pcm_sframes_t avail; - -avail = snd_pcm_avail_update (handle); -if (avail < 0) { -if (avail == -EPIPE) { -if (!alsa_recover (handle)) { -avail = snd_pcm_avail_update (handle); -} -} - -if (avail < 0) { -alsa_logerr (avail, - "Could not obtain number of available frames\n"); -return -1; -} -} - -return avail; -} - -static void alsa_write_pending (ALSAVoiceOut *alsa) -{ -HWVoiceOut *hw = &alsa->hw; - -while (alsa->pending) { -int left_till_end_samples = hw->samples - alsa->wpos; -int len = MIN (alsa->pending, left_till_end_samples); -char *src = advance (alsa->pcm_buf, alsa->wpos << hw->info.shift); - -while (len) { -snd_pcm_sframes_t written; - -written = snd_pcm_writei (alsa->handle, src, len); - -if (written <= 0) { -switch (written) { -case 0: -trace_alsa_wrote_zero(len); -return; - -case -EPIPE: -if (alsa_recover (alsa->handle)) { -alsa_logerr (written, "Failed to write %d frames\n", - len); -return; -} -trace_alsa_xrun_out(); -continue; - -case -ESTRPIPE: -/* stream is suspended and waiting for an - application recovery */ -if (alsa_resume (alsa->handle)) { -alsa_logerr (written, "Failed to write %d frames\n", - len); -return; -} -trace_alsa_resume_out(); -continue; - -case -EAGAIN: -return; - -default: -alsa_logerr (written, "Failed to write %d frames from %p\n", - len, src); -return; -} -} - -alsa->wpos = (alsa->wpos + written) % hw->samples; -alsa->pending -= written; -len -= written; -} -} -} - -static int alsa_run_out (HWVoiceOut *hw, int live) +static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len) { ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; -int decr; -snd_pcm_sframes_t avail; +size_t pos = 0; +size_t len_frames = len >> hw->info.shift; -avail = alsa_get_avail (alsa->handle); -if (avail < 0) { -dolog ("Could not get number of available playback frames\n"); -return 0; +while (len_frames) { +char *src = advance(buf, pos); +snd_pcm_sframes_t written; + +written = snd_pcm_writei(alsa->handle, src, len_frames); + +if (written <= 0) { +switch (written) { +case 0: +trace_alsa_wrote_zero(len_frames); +return pos; + +case -EPIPE: +if (alsa_recover(alsa->handle)) { +alsa_logerr(written, "Failed to write %zu frames\n", +len_frames); +return pos; +} +trace_alsa_xrun_out(); +continue; + +case -ESTRPIPE: +/* stream is suspended and waiting for an + application recovery */ +if (alsa_resume(alsa->handle)) { +alsa_logerr(written, "Failed to write %zu frames\n", +len_frames); +return pos; +} +trace_alsa_resume_out(); +continue; + +case -EAGAIN: +return pos; + +default: +alsa_logerr(written, "Failed to write %zu frames from %p\n", +len, src); +return pos; +} +} + +pos += wri
[Qemu-devel] [PATCH v2 35/52] sdlaudio: port to the new audio backend api
SDL2 is still a big mess, but it's probably not worse than the current version. Signed-off-by: Kővágó, Zoltán --- audio/sdlaudio.c | 136 +-- 1 file changed, 50 insertions(+), 86 deletions(-) diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index 92da4804c6..685cbc83b8 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -42,11 +42,6 @@ typedef struct SDLVoiceOut { HWVoiceOut hw; -int live; -#if USE_SEMAPHORE -int rpos; -#endif -int decr; } SDLVoiceOut; static struct SDLAudioState { @@ -252,17 +247,13 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len) SDLVoiceOut *sdl = opaque; SDLAudioState *s = &glob_sdl; HWVoiceOut *hw = &sdl->hw; -int samples = len >> hw->info.shift; if (s->exit) { return; } -while (samples) { -int to_mix, decr; - -/* dolog ("in callback samples=%d\n", samples); */ #if USE_SEMAPHORE +while (len) { sdl_wait (s, "sdl_callback"); if (s->exit) { return; @@ -271,95 +262,66 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len) if (sdl_lock (s, "sdl_callback")) { return; } - -if (audio_bug(__func__, sdl->live < 0 || sdl->live > hw->samples)) { -dolog("sdl->live=%d hw->samples=%zu\n", sdl->live, hw->samples); -return; -} - -if (!sdl->live) { -goto again; -} -#else -if (s->exit || !sdl->live) { -break; -} #endif -/* dolog ("in callback live=%d\n", live); */ -to_mix = MIN (samples, sdl->live); -decr = to_mix; -while (to_mix) { -int chunk = MIN (to_mix, hw->samples - hw->rpos); -struct st_sample *src = hw->mix_buf + hw->rpos; +while (hw->pending_emul && len) { +size_t write_len; +ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul; +if (start < 0) { +start += hw->size_emul; +} +assert(start >= 0 && start < hw->size_emul); -/* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */ -hw->clip (buf, src, chunk); -#if USE_SEMAPHORE -sdl->rpos = (sdl->rpos + chunk) % hw->samples; -#else -hw->rpos = (hw->rpos + chunk) % hw->samples; -#endif -to_mix -= chunk; -buf += chunk << hw->info.shift; +write_len = MIN(MIN(hw->pending_emul, len), +hw->size_emul - start); + +memcpy(buf, hw->buf_emul + start, write_len); +hw->pending_emul -= write_len; +len -= write_len; +buf += write_len; } -samples -= decr; -sdl->live -= decr; -sdl->decr += decr; #if USE_SEMAPHORE -again: if (sdl_unlock (s, "sdl_callback")) { return; } -#endif } -/* dolog ("done len=%d\n", len); */ - -#if (SDL_MAJOR_VERSION >= 2) -/* SDL2 does not clear the remaining buffer for us, so do it on our own */ -if (samples) { -memset(buf, 0, samples << hw->info.shift); -} -#endif -} - -static int sdl_run_out (HWVoiceOut *hw, int live) -{ -int decr; -SDLVoiceOut *sdl = (SDLVoiceOut *) hw; -SDLAudioState *s = &glob_sdl; - -if (sdl_lock (s, "sdl_run_out")) { -return 0; -} - -if (sdl->decr > live) { -ldebug ("sdl->decr %d live %d sdl->live %d\n", -sdl->decr, -live, -sdl->live); -} - -decr = MIN (sdl->decr, live); -sdl->decr -= decr; - -#if USE_SEMAPHORE -sdl->live = live - decr; -hw->rpos = sdl->rpos; #else -sdl->live = live; +/* clear remaining buffer that we couldn't fill with data */ +if (len) { +memset(buf, 0, len); +} #endif - -if (sdl->live > 0) { -sdl_unlock_and_post (s, "sdl_run_out"); -} -else { -sdl_unlock (s, "sdl_run_out"); -} -return decr; } +#define SDL_WRAPPER_FUNC(name, ret_type, args_decl, args, fail, unlock) \ +static ret_type glue(sdl_, name)args_decl \ +{ \ +SDLAudioState *s = &glob_sdl; \ +ret_type ret; \ +\ +if (sdl_lock(s, "sdl_" #name)) {\ +fail; \ +return 0; /* implicitly casts to NULL */\ +} \ +\ +ret = glue(audio_generic_, name)args; \ +
[Qemu-devel] [PATCH v2 37/52] wavaudio: port to the new audio backend api
Signed-off-by: Kővágó, Zoltán --- audio/wavaudio.c | 54 1 file changed, 9 insertions(+), 45 deletions(-) diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 58300663ff..31db03aadb 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -34,52 +34,28 @@ typedef struct WAVVoiceOut { HWVoiceOut hw; FILE *f; int64_t old_ticks; -void *pcm_buf; int total_samples; } WAVVoiceOut; -static int wav_run_out (HWVoiceOut *hw, int live) +static size_t wav_write_out(HWVoiceOut *hw, void *buf, size_t len) { WAVVoiceOut *wav = (WAVVoiceOut *) hw; -int rpos, decr, samples; -uint8_t *dst; -struct st_sample *src; int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); int64_t ticks = now - wav->old_ticks; int64_t bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); -if (bytes > INT_MAX) { -samples = INT_MAX >> hw->info.shift; -} -else { -samples = bytes >> hw->info.shift; -} - +bytes = MIN(bytes, len); +bytes = bytes >> hw->info.shift << hw->info.shift; wav->old_ticks = now; -decr = MIN (live, samples); -samples = decr; -rpos = hw->rpos; -while (samples) { -int left_till_end_samples = hw->samples - rpos; -int convert_samples = MIN (samples, left_till_end_samples); -src = hw->mix_buf + rpos; -dst = advance (wav->pcm_buf, rpos << hw->info.shift); - -hw->clip (dst, src, convert_samples); -if (fwrite (dst, convert_samples << hw->info.shift, 1, wav->f) != 1) { -dolog ("wav_run_out: fwrite of %d bytes failed\nReaons: %s\n", - convert_samples << hw->info.shift, strerror (errno)); -} - -rpos = (rpos + convert_samples) % hw->samples; -samples -= convert_samples; -wav->total_samples += convert_samples; +if (bytes && fwrite(buf, bytes, 1, wav->f) != 1) { +dolog("wav_write_out: fwrite of %zu bytes failed\nReaons: %s\n", + bytes, strerror(errno)); } -hw->rpos = rpos; -return decr; +wav->total_samples += bytes >> hw->info.shift; +return bytes; } /* VICE code: Store number as little endian. */ @@ -135,13 +111,6 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings *as, audio_pcm_init_info (&hw->info, &wav_as); hw->samples = 1024; -wav->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); -if (!wav->pcm_buf) { -dolog("Could not allocate buffer (%zu bytes)\n", - hw->samples << hw->info.shift); -return -1; -} - le_store (hdr + 22, hw->info.nchannels, 2); le_store (hdr + 24, hw->info.freq, 4); le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4); @@ -151,8 +120,6 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings *as, if (!wav->f) { dolog ("Failed to open wave file `%s'\nReason: %s\n", wav_path, strerror(errno)); -g_free (wav->pcm_buf); -wav->pcm_buf = NULL; return -1; } @@ -206,9 +173,6 @@ static void wav_fini_out (HWVoiceOut *hw) wav->f, strerror (errno)); } wav->f = NULL; - -g_free (wav->pcm_buf); -wav->pcm_buf = NULL; } static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...) @@ -232,7 +196,7 @@ static void wav_audio_fini (void *opaque) static struct audio_pcm_ops wav_pcm_ops = { .init_out = wav_init_out, .fini_out = wav_fini_out, -.run_out = wav_run_out, +.write= wav_write_out, .ctl_out = wav_ctl_out, }; -- 2.20.1
[Qemu-devel] [PATCH v2 19/52] audio: add audiodev properties to frontends
Finally add audiodev= options to audio frontends so users can specify which backend to use when multiple backends exist. Not specifying an audiodev= option currently causes the first audiodev to be used, this is fixed in the next commit. Example usage: -audiodev pa,id=foo -device AC97,audiodev=foo Signed-off-by: Kővágó, Zoltán --- audio/audio.h| 3 ++ hw/audio/ac97.c | 1 + hw/audio/adlib.c | 1 + hw/audio/cs4231a.c | 1 + hw/audio/es1370.c| 7 +++- hw/audio/gus.c | 1 + hw/audio/hda-codec.c | 1 + hw/audio/milkymist-ac97.c| 6 hw/audio/pcspk.c | 1 + hw/audio/pl041.c | 1 + hw/audio/sb16.c | 1 + hw/audio/wm8750.c| 6 hw/core/qdev-properties-system.c | 57 hw/usb/dev-audio.c | 1 + include/hw/qdev-properties.h | 3 ++ 15 files changed, 90 insertions(+), 1 deletion(-) diff --git a/audio/audio.h b/audio/audio.h index 5e0dcdb93e..ccfef9e10a 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -183,4 +183,7 @@ void audio_legacy_help(void); AudioState *audio_state_by_name(const char *name); const char *audio_get_id(QEMUSoundCard *card); +#define DEFINE_AUDIO_PROPERTIES(_s, _f) \ +DEFINE_PROP_AUDIODEV("audiodev", _s, _f) + #endif /* QEMU_AUDIO_H */ diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index 2265622d44..03e3da4f31 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -1408,6 +1408,7 @@ static int ac97_init (PCIBus *bus) } static Property ac97_properties[] = { +DEFINE_AUDIO_PROPERTIES(AC97LinkState, card), DEFINE_PROP_UINT32 ("use_broken_id", AC97LinkState, use_broken_id, 0), DEFINE_PROP_END_OF_LIST (), }; diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index 0957780a3d..0d01cd07c5 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -298,6 +298,7 @@ static void adlib_realizefn (DeviceState *dev, Error **errp) } static Property adlib_properties[] = { +DEFINE_AUDIO_PROPERTIES(AdlibState, card), DEFINE_PROP_UINT32 ("iobase", AdlibState, port, 0x220), DEFINE_PROP_UINT32 ("freq",AdlibState, freq, 44100), DEFINE_PROP_END_OF_LIST (), diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 62da75eefe..d25a120b0f 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -687,6 +687,7 @@ static int cs4231a_init (ISABus *bus) } static Property cs4231a_properties[] = { +DEFINE_AUDIO_PROPERTIES(CSState, card), DEFINE_PROP_UINT32 ("iobase", CSState, port, 0x534), DEFINE_PROP_UINT32 ("irq", CSState, irq, 9), DEFINE_PROP_UINT32 ("dma", CSState, dma, 3), diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index a5314d66fd..8c63912a82 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -886,6 +886,11 @@ static int es1370_init (PCIBus *bus) return 0; } +static Property es1370_properties[] = { +DEFINE_AUDIO_PROPERTIES(ES1370State, card), +DEFINE_PROP_END_OF_LIST(), +}; + static void es1370_class_init (ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS (klass); @@ -902,6 +907,7 @@ static void es1370_class_init (ObjectClass *klass, void *data) dc->desc = "ENSONIQ AudioPCI ES1370"; dc->vmsd = &vmstate_es1370; dc->reset = es1370_on_reset; +dc->props = es1370_properties; } static const TypeInfo es1370_info = { @@ -922,4 +928,3 @@ static void es1370_register_types (void) } type_init (es1370_register_types) - diff --git a/hw/audio/gus.c b/hw/audio/gus.c index b3e2a7fdd5..dfb74cf0d3 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -295,6 +295,7 @@ static int GUS_init (ISABus *bus) } static Property gus_properties[] = { +DEFINE_AUDIO_PROPERTIES(GUSState, card), DEFINE_PROP_UINT32 ("freq",GUSState, freq,44100), DEFINE_PROP_UINT32 ("iobase", GUSState, port,0x240), DEFINE_PROP_UINT32 ("irq", GUSState, emu.gusirq, 7), diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c index c25bfa38b1..e66103aedf 100644 --- a/hw/audio/hda-codec.c +++ b/hw/audio/hda-codec.c @@ -839,6 +839,7 @@ static const VMStateDescription vmstate_hda_audio = { }; static Property hda_audio_properties[] = { +DEFINE_AUDIO_PROPERTIES(HDAAudioState, card), DEFINE_PROP_UINT32("debug", HDAAudioState, debug, 0), DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer, true), DEFINE_PROP_BOOL("use-timer", HDAAudioState, use_timer, true), diff --git a/hw/audio/milkymist-ac97.c b/hw/audio/milkymist-ac97.c index 90cce1e6ed..8739cb376a 100644 --- a/hw/audio/milkymist-ac97.c +++ b/hw/audio/milkymist-ac97.c @@ -328,6 +328,11 @@ static const VMStateDescription vmstate_milkymist_ac97 = { } }; +static Property milkymist_ac97_properties[] = { +DEFINE_AUDIO_PROPERTIES(MilkymistAC97State, card), +DEFINE_PROP_END_OF_LIST(), +}; + static void milkymist_ac97_class_
[Qemu-devel] [PATCH v2 38/52] audio: remove remains of the old backend api
Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 42 ++ audio/audio_int.h | 7 --- 2 files changed, 6 insertions(+), 43 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 1897e22444..4c33e057d7 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -543,7 +543,7 @@ static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw) return m; } -size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) +static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) { size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); if (audio_bug(__func__, live > hw->samples)) { @@ -553,29 +553,7 @@ size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) return live; } -size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, - size_t live, size_t pending) -{ -size_t left = hw->samples - pending; -size_t len = MIN (left, live); -size_t clipped = 0; - -while (len) { -struct st_sample *src = hw->mix_buf + hw->rpos; -uint8_t *dst = advance (pcm_buf, hw->rpos << hw->info.shift); -size_t samples_till_end_of_buf = hw->samples - hw->rpos; -size_t samples_to_clip = MIN (len, samples_till_end_of_buf); - -hw->clip (dst, src, samples_to_clip); - -hw->rpos = (hw->rpos + samples_to_clip) % hw->samples; -len -= samples_to_clip; -clipped += samples_to_clip; -} -return clipped; -} - -static void audio_pcm_hw_clip_out2(HWVoiceOut *hw, void *pcm_buf, size_t len) +static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len) { size_t clipped = 0; size_t pos = hw->rpos; @@ -1080,7 +1058,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) void *buf = hw->pcm_ops->get_buffer_out(hw, &size); decr = MIN(size >> hw->info.shift, live); -audio_pcm_hw_clip_out2(hw, buf, decr); +audio_pcm_hw_clip_out(hw, buf, decr); proc = hw->pcm_ops->put_buffer_out(hw, buf, decr << hw->info.shift) >> hw->info.shift; @@ -1143,11 +1121,7 @@ static void audio_run_out (AudioState *s) } prev_rpos = hw->rpos; -if (hw->pcm_ops->run_out) { -played = hw->pcm_ops->run_out(hw, live); -} else { -played = audio_pcm_hw_run_out(hw, live); -} +played = audio_pcm_hw_run_out(hw, live); replay_audio_out(&played); if (audio_bug(__func__, hw->rpos >= hw->samples)) { dolog("hw->rpos=%zu hw->samples=%zu played=%zu\n", @@ -1244,12 +1218,8 @@ static void audio_run_in (AudioState *s) size_t captured = 0, min; if (replay_mode != REPLAY_MODE_PLAY) { -if (hw->pcm_ops->run_in) { -captured = hw->pcm_ops->run_in(hw); -} else { -captured = audio_pcm_hw_run_in( -hw, hw->samples - audio_pcm_hw_get_live_in(hw)); -} +captured = audio_pcm_hw_run_in( +hw, hw->samples - audio_pcm_hw_get_live_in(hw)); } replay_audio_in(&captured, hw->conv_buf, &hw->wpos, hw->samples); diff --git a/audio/audio_int.h b/audio/audio_int.h index 5c361d9451..cca7efaa05 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -152,7 +152,6 @@ struct audio_driver { struct audio_pcm_ops { int(*init_out)(HWVoiceOut *hw, audsettings *as, void *drv_opaque); void (*fini_out)(HWVoiceOut *hw); -int(*run_out) (HWVoiceOut *hw, int live); size_t (*write) (HWVoiceOut *hw, void *buf, size_t size); /* * get a buffer that after later can be passed to put_buffer_out; optional @@ -170,7 +169,6 @@ struct audio_pcm_ops { int(*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque); void (*fini_in) (HWVoiceIn *hw); -int(*run_in) (HWVoiceIn *hw); size_t (*read)(HWVoiceIn *hw, void *buf, size_t size); void *(*get_buffer_in)(HWVoiceIn *hw, size_t *size); void (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size); @@ -236,11 +234,6 @@ audio_driver *audio_driver_lookup(const char *name); void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as); void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len); -size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw); - -size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, - size_t live, size_t pending); - int audio_bug (const char *funcname, int cond); void *audio_calloc (const char *funcname, int nmemb, size_t size); -- 2.20.1
[Qemu-devel] [PATCH v2 48/52] audio: basic support for multichannel audio
Which currently only means removing some checks. Old code won't require more than two channels, but new code will need it. Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c | 7 --- audio/audio.c | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 418b888a57..063531b743 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -498,13 +498,6 @@ static int alsa_open(bool in, struct alsa_params_req *req, goto err; } -if (nchannels != 1 && nchannels != 2) { -alsa_logerr2 (err, typ, - "Can not handle obtained number of channels %d\n", - nchannels); -goto err; -} - if (pdo->buffer_count) { if (pdo->buffer_len) { int64_t req = pdo->buffer_len * pdo->buffer_count; diff --git a/audio/audio.c b/audio/audio.c index ee508c1f15..782e4ed1c7 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -241,7 +241,7 @@ static int audio_validate_settings (struct audsettings *as) { int invalid; -invalid = as->nchannels != 1 && as->nchannels != 2; +invalid = as->nchannels < 1; invalid |= as->endianness != 0 && as->endianness != 1; switch (as->fmt) { -- 2.20.1
[Qemu-devel] [PATCH v2 23/52] audio: remove audio_MIN, audio_MAX
There's already a MIN and MAX macro in include/qemu/osdep.h, use them instead. Signed-off-by: Kővágó, Zoltán --- Changes from v1: * removed audio_MIN, audio_MAX macros --- audio/alsaaudio.c | 6 +++--- audio/audio.c | 20 ++-- audio/audio.h | 17 - audio/coreaudio.c | 2 +- audio/dsoundaudio.c | 2 +- audio/noaudio.c | 10 +- audio/ossaudio.c | 6 +++--- audio/paaudio.c | 12 ++-- audio/sdlaudio.c | 6 +++--- audio/spiceaudio.c| 10 +- audio/wavaudio.c | 4 ++-- hw/audio/ac97.c | 10 +- hw/audio/adlib.c | 4 ++-- hw/audio/cs4231a.c| 4 ++-- hw/audio/es1370.c | 6 +++--- hw/audio/gus.c| 6 +++--- hw/audio/hda-codec.c | 16 hw/audio/milkymist-ac97.c | 8 hw/audio/pcspk.c | 2 +- hw/audio/sb16.c | 2 +- hw/audio/wm8750.c | 4 ++-- 21 files changed, 70 insertions(+), 87 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 6f75644538..d4bb540cb9 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -642,7 +642,7 @@ static void alsa_write_pending (ALSAVoiceOut *alsa) while (alsa->pending) { int left_till_end_samples = hw->samples - alsa->wpos; -int len = audio_MIN (alsa->pending, left_till_end_samples); +int len = MIN (alsa->pending, left_till_end_samples); char *src = advance (alsa->pcm_buf, alsa->wpos << hw->info.shift); while (len) { @@ -705,7 +705,7 @@ static int alsa_run_out (HWVoiceOut *hw, int live) return 0; } -decr = audio_MIN (live, avail); +decr = MIN (live, avail); decr = audio_pcm_hw_clip_out (hw, alsa->pcm_buf, decr, alsa->pending); alsa->pending += decr; alsa_write_pending (alsa); @@ -923,7 +923,7 @@ static int alsa_run_in (HWVoiceIn *hw) } } -decr = audio_MIN (dead, avail); +decr = MIN (dead, avail); if (!decr) { return 0; } diff --git a/audio/audio.c b/audio/audio.c index a7f79f3929..a32b86a813 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -537,7 +537,7 @@ static int audio_pcm_hw_find_min_in (HWVoiceIn *hw) for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { if (sw->active) { -m = audio_MIN (m, sw->total_hw_samples_acquired); +m = MIN (m, sw->total_hw_samples_acquired); } } return m; @@ -557,14 +557,14 @@ int audio_pcm_hw_clip_out (HWVoiceOut *hw, void *pcm_buf, int live, int pending) { int left = hw->samples - pending; -int len = audio_MIN (left, live); +int len = MIN (left, live); int clipped = 0; while (len) { struct st_sample *src = hw->mix_buf + hw->rpos; uint8_t *dst = advance (pcm_buf, hw->rpos << hw->info.shift); int samples_till_end_of_buf = hw->samples - hw->rpos; -int samples_to_clip = audio_MIN (len, samples_till_end_of_buf); +int samples_to_clip = MIN (len, samples_till_end_of_buf); hw->clip (dst, src, samples_to_clip); @@ -618,7 +618,7 @@ int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size) } swlim = (live * sw->ratio) >> 32; -swlim = audio_MIN (swlim, samples); +swlim = MIN (swlim, samples); while (swlim) { src = hw->conv_buf + rpos; @@ -666,7 +666,7 @@ static int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep) for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { if (sw->active || !sw->empty) { -m = audio_MIN (m, sw->total_hw_samples_mixed); +m = MIN (m, sw->total_hw_samples_mixed); nb_live += 1; } } @@ -729,7 +729,7 @@ int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size) dead = hwsamples - live; swlim = ((int64_t) dead << 32) / sw->ratio; -swlim = audio_MIN (swlim, samples); +swlim = MIN (swlim, samples); if (swlim) { sw->conv (sw->buf, buf, swlim); @@ -741,7 +741,7 @@ int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size) while (swlim) { dead = hwsamples - live; left = hwsamples - wpos; -blck = audio_MIN (dead, left); +blck = MIN (dead, left); if (!blck) { break; } @@ -1033,7 +1033,7 @@ static void audio_capture_mix_and_clear (HWVoiceOut *hw, int rpos, int samples) n = samples; while (n) { int till_end_of_hw = hw->samples - rpos2; -int to_write = audio_MIN (till_end_of_hw, n); +int to_write = MIN (till_end_of_hw, n); int bytes = to_write << hw->info.shift; int written; @@ -1051,7 +1051,7 @@ static void audio_capture_mix_and_clear (HWVoiceOut *hw, int rpos, int samples) } } -n = audio_
[Qemu-devel] [PATCH v2 43/52] audio: add mixeng option (documentation)
This will allow us to disable mixeng when we use a decent backend. Disabling mixeng have a few advantages: * we no longer convert the audio output from one format to another, when the underlying audio system would just convert it to a third format. We no longer convert, only the underlying system, when needed. * the underlying system probably has better resampling and sample format converting methods anyway... * we may support formats that the mixeng currently does not support (S24 or float samples, more than two channels) * when using an audio server (like pulseaudio) different sound card outputs will show up as separate streams, even if we use only one backend Disadvantages: * audio capturing no longer works (wavcapture, and vnc audio extension) * some backends only support a single playback stream or very picky about the audio format. In this case we can't disable mixeng. However mixeng is not removed, only made optional, so this shouldn't be a big concern. Signed-off-by: Kővágó, Zoltán --- qapi/audio.json | 5 + qemu-options.hx | 6 ++ 2 files changed, 11 insertions(+) diff --git a/qapi/audio.json b/qapi/audio.json index 56d8ce439f..180bf207a8 100644 --- a/qapi/audio.json +++ b/qapi/audio.json @@ -184,6 +184,10 @@ # # General audio backend options that are used for both playback and recording. # +# @mixeng: #optional use QEMU's mixing engine to mix all streams inside QEMU. +# When set to off, fixed-settings must be also off. Not every backend +# compatible with the off setting (default on) +# # @fixed-settings: #optional use fixed settings for host input/output. When # off, frequency, channels and format must not be specified # (default on) @@ -207,6 +211,7 @@ ## { 'struct': 'AudiodevPerDirectionOptions', 'data': { +'*mixeng': 'bool', '*fixed-settings': 'bool', '*frequency': 'int', '*channels': 'int', diff --git a/qemu-options.hx b/qemu-options.hx index 687dd23bf2..eb65b511fa 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -432,6 +432,7 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, "specifies the audio backend to use\n" "id= identifier of the backend\n" "timer-period= timer period in microseconds\n" +"in|out.mixeng= use mixeng to mix streams inside QEMU\n" "in|out.fixed-settings= use fixed settings for host audio\n" "in|out.frequency= frequency to use with fixed settings\n" "in|out.channels= number of channels to use with fixed settings\n" @@ -500,6 +501,11 @@ Identifies the audio backend. Sets the timer @var{period} used by the audio subsystem in microseconds. Default is 1 (10 ms). +@item in|out.mixeng=on|off +Use QEMU's mixing engine to mix all streams inside QEMU. When off, +@var{fixed-settings} must be off too. Not every backend is fully +compatible with the off setting. Default is on. + @item in|out.fixed-settings=on|off Use fixed settings for host audio. When off, it will change based on how the guest opens the sound card. In this case you must not specify -- 2.20.1
[Qemu-devel] [PATCH v2 49/52] paaudio: channel-map option
Add an option to change the channel map used by pulseaudio. If not specified, falls back to an OSS compatible channel map. Signed-off-by: Kővágó, Zoltán --- audio/paaudio.c | 18 ++ qapi/audio.json | 5 - qemu-options.hx | 9 + 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/audio/paaudio.c b/audio/paaudio.c index 3b4b29b38f..f472f25e8f 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -337,17 +337,27 @@ static pa_stream *qpa_simple_new ( pa_stream_direction_t dir, const char *dev, const pa_sample_spec *ss, -const pa_channel_map *map, +const char *map, const pa_buffer_attr *attr, int *rerror) { int r; pa_stream *stream; pa_stream_flags_t flags; +pa_channel_map pa_map; pa_threaded_mainloop_lock(c->mainloop); -stream = pa_stream_new(c->context, name, ss, map); +if (map && !pa_channel_map_parse(&pa_map, map)) { +dolog("Invalid channel map specified: '%s'\n", map); +map = NULL; +} +if (!map) { +pa_channel_map_init_extend(&pa_map, ss->channels, + PA_CHANNEL_MAP_OSS); +} + +stream = pa_stream_new(c->context, name, ss, &pa_map); if (!stream) { goto fail; } @@ -424,7 +434,7 @@ static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as, PA_STREAM_PLAYBACK, ppdo->has_name ? ppdo->name : NULL, &ss, -NULL, /* channel map */ +ppdo->has_channel_map ? ppdo->channel_map : NULL, &ba,/* buffering attributes */ &error ); @@ -472,7 +482,7 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) PA_STREAM_RECORD, ppdo->has_name ? ppdo->name : NULL, &ss, -NULL, /* channel map */ +ppdo->has_channel_map ? ppdo->channel_map : NULL, NULL, /* buffering attributes */ &error ); diff --git a/qapi/audio.json b/qapi/audio.json index 180bf207a8..f3efa4620b 100644 --- a/qapi/audio.json +++ b/qapi/audio.json @@ -119,11 +119,14 @@ # # @name: #optional name of the sink/source to use # +# @channel-map: #optional channel map to use (default: OSS compatible map) +# # Since: 3.2 ## { 'struct': 'AudiodevPaPerDirectionOptions', 'data': { -'*name': 'str' } } +'*name':'str', +'*channel-map': 'str' } } ## # @AudiodevPaOptions: diff --git a/qemu-options.hx b/qemu-options.hx index eb65b511fa..d051c52bbb 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -468,6 +468,7 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, "-audiodev pa,id=id[,prop[=value][,...]]\n" "server= PulseAudio server address\n" "sink|source.name= sink/source device name\n" +"sink|source.channel-map= channel map to use\n" #endif #ifdef CONFIG_SDL "-audiodev sdl,id=id[,prop[=value][,...]]\n" @@ -621,6 +622,14 @@ Sets the PulseAudio @var{server} to connect to. @item sink|source.name=@var{sink} Use the specified sink/source for playback/recording. +@item sink|source.channel-map=@var{map} +Use the specified channel map. The default is an OSS compatible +channel map. Do not forget to escape commas inside the map: + +@example +-audiodev pa,id=example,sink.channel-map=front-left,,front-right +@end example + @end table @item -audiodev sdl,id=@var{id}[,@var{prop}[=@var{value}][,...]] -- 2.20.1
[Qemu-devel] [PATCH v2 39/52] audio: unify input and output mixeng buffer management
Usage notes: hw->samples became hw->{mix,conv}_buf->size, except before initialization (audio_pcm_hw_alloc_resources_*), hw->samples gives the initial size of the STSampleBuffer. The next commit tries to fix this inconsistency. Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 130 - audio/audio_int.h | 12 ++-- audio/audio_template.h | 19 +++--- audio/ossaudio.c | 2 +- 4 files changed, 80 insertions(+), 83 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 4c33e057d7..f195d8eb95 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -546,8 +546,8 @@ static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw) static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) { size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); -if (audio_bug(__func__, live > hw->samples)) { -dolog("live=%zu hw->samples=%zu\n", live, hw->samples); +if (audio_bug(__func__, live > hw->conv_buf->size)) { +dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size); return 0; } return live; @@ -556,17 +556,17 @@ static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len) { size_t clipped = 0; -size_t pos = hw->rpos; +size_t pos = hw->mix_buf->pos; while (len) { -st_sample *src = hw->mix_buf + pos; +st_sample *src = hw->mix_buf->samples + pos; uint8_t *dst = advance (pcm_buf, clipped << hw->info.shift); -size_t samples_till_end_of_buf = hw->samples - pos; +size_t samples_till_end_of_buf = hw->mix_buf->size - pos; size_t samples_to_clip = MIN(len, samples_till_end_of_buf); hw->clip (dst, src, samples_to_clip); -pos = (pos + samples_to_clip) % hw->samples; +pos = (pos + samples_to_clip) % hw->mix_buf->size; len -= samples_to_clip; clipped += samples_to_clip; } @@ -581,17 +581,17 @@ static size_t audio_pcm_sw_get_rpos_in(SWVoiceIn *sw) ssize_t live = hw->total_samples_captured - sw->total_hw_samples_acquired; ssize_t rpos; -if (audio_bug(__func__, live < 0 || live > hw->samples)) { -dolog("live=%zu hw->samples=%zu\n", live, hw->samples); +if (audio_bug(__func__, live < 0 || live > hw->conv_buf->size)) { +dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size); return 0; } -rpos = hw->wpos - live; +rpos = hw->conv_buf->pos - live; if (rpos >= 0) { return rpos; } else { -return hw->samples + rpos; +return hw->conv_buf->size + rpos; } } @@ -601,11 +601,11 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) size_t samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0; struct st_sample *src, *dst = sw->buf; -rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples; +rpos = audio_pcm_sw_get_rpos_in(sw) % hw->conv_buf->size; live = hw->total_samples_captured - sw->total_hw_samples_acquired; -if (audio_bug(__func__, live > hw->samples)) { -dolog("live_in=%zu hw->samples=%zu\n", live, hw->samples); +if (audio_bug(__func__, live > hw->conv_buf->size)) { +dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size); return 0; } @@ -618,11 +618,11 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) swlim = MIN (swlim, samples); while (swlim) { -src = hw->conv_buf + rpos; -if (hw->wpos > rpos) { -isamp = hw->wpos - rpos; +src = hw->conv_buf->samples + rpos; +if (hw->conv_buf->pos > rpos) { +isamp = hw->conv_buf->pos - rpos; } else { -isamp = hw->samples - rpos; +isamp = hw->conv_buf->size - rpos; } if (!isamp) { @@ -632,7 +632,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) st_rate_flow (sw->rate, src, dst, &isamp, &osamp); swlim -= osamp; -rpos = (rpos + isamp) % hw->samples; +rpos = (rpos + isamp) % hw->conv_buf->size; dst += osamp; ret += osamp; total += isamp; @@ -680,8 +680,8 @@ static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live) if (nb_live1) { size_t live = smin; -if (audio_bug(__func__, live > hw->samples)) { -dolog("live=%zu hw->samples=%zu\n", live, hw->samples); +if (audio_bug(__func__, live > hw->mix_buf->size)) { +dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size); return 0; } return live; @@ -701,11 +701,11 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size) return size; } -hwsamples = sw->hw->samples; +hwsamples = sw->hw->mix_buf->size; live = sw->total_hw_samples_mixed;
[Qemu-devel] [PATCH v2 44/52] audio: make mixeng optional
Implementation of the previously added mixeng option. Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 70 ++ audio/audio_template.h | 46 --- 2 files changed, 92 insertions(+), 24 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 7ba939560a..26ce25989f 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -840,32 +840,46 @@ static void audio_timer (void *opaque) */ size_t AUD_write(SWVoiceOut *sw, void *buf, size_t size) { +HWVoiceOut *hw; + if (!sw) { /* XXX: Consider options */ return size; } +hw = sw->hw; -if (!sw->hw->enabled) { +if (!hw->enabled) { dolog ("Writing to disabled voice %s\n", SW_NAME (sw)); return 0; } -return audio_pcm_sw_write(sw, buf, size); +if (hw->s->dev->out->mixeng) { +return audio_pcm_sw_write(sw, buf, size); +} else { +return hw->pcm_ops->write(hw, buf, size); +} } size_t AUD_read(SWVoiceIn *sw, void *buf, size_t size) { +HWVoiceIn *hw; + if (!sw) { /* XXX: Consider options */ return size; } +hw = sw->hw; -if (!sw->hw->enabled) { +if (!hw->enabled) { dolog ("Reading from disabled voice %s\n", SW_NAME (sw)); return 0; } -return audio_pcm_sw_read(sw, buf, size); +if (hw->s->dev->in->mixeng) { +return audio_pcm_sw_read(sw, buf, size); +} else { +return hw->pcm_ops->read(hw, buf, size); +} } int AUD_get_buffer_size_out (SWVoiceOut *sw) @@ -1087,6 +1101,26 @@ static void audio_run_out (AudioState *s) HWVoiceOut *hw = NULL; SWVoiceOut *sw; +if (!s->dev->out->mixeng) { +while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) { +/* there is exactly 1 sw for each hw with no mixeng */ +sw = hw->sw_head.lh_first; + +if (hw->pending_disable) { +hw->enabled = 0; +hw->pending_disable = 0; +if (hw->pcm_ops->enable_out) { +hw->pcm_ops->enable_out(hw, false); +} +} + +if (sw->active) { +sw->callback.fn(sw->callback.opaque, INT_MAX); +} +} +return; +} + while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) { size_t played, live, prev_rpos, free; int nb_live, cleanup_required; @@ -1224,6 +1258,17 @@ static void audio_run_in (AudioState *s) { HWVoiceIn *hw = NULL; +if (!s->dev->in->mixeng) { +while ((hw = audio_pcm_hw_find_any_enabled_in(s, hw))) { +/* there is exactly 1 sw for each hw with no mixeng */ +SWVoiceIn *sw = hw->sw_head.lh_first; +if (sw->active) { +sw->callback.fn(sw->callback.opaque, INT_MAX); +} +} +return; +} + while ((hw = audio_pcm_hw_find_any_enabled_in(s, hw))) { SWVoiceIn *sw; size_t captured = 0, min; @@ -1717,6 +1762,11 @@ CaptureVoiceOut *AUD_add_capture( s = audio_init(NULL, NULL); } +if (!s->dev->out->mixeng) { +dolog("Can't capture with mixeng disabled\n"); +goto err0; +} + if (audio_validate_settings (as)) { dolog ("Invalid settings were passed when trying to add capture\n"); audio_print_settings (as); @@ -1875,9 +1925,13 @@ QemuOptsList qemu_audiodev_opts = { static void validate_per_direction_opts(AudiodevPerDirectionOptions *pdo, Error **errp) { +if (!pdo->has_mixeng) { +pdo->has_mixeng = true; +pdo->mixeng = true; +} if (!pdo->has_fixed_settings) { pdo->has_fixed_settings = true; -pdo->fixed_settings = true; +pdo->fixed_settings = pdo->mixeng; } if (!pdo->fixed_settings && (pdo->has_frequency || pdo->has_channels || pdo->has_format)) { @@ -1885,6 +1939,10 @@ static void validate_per_direction_opts(AudiodevPerDirectionOptions *pdo, "You can't use frequency, channels or format with fixed-settings=off"); return; } +if (!pdo->mixeng && pdo->fixed_settings) { +error_setg(errp, "You can't use fixed-settings without mixeng"); +return; +} if (!pdo->has_frequency) { pdo->has_frequency = true; @@ -1896,7 +1954,7 @@ static void validate_per_direction_opts(AudiodevPerDirectionOptions *pdo, } if (!pdo->has_voices) { pdo->has_voices = true; -pdo->voices = 1; +pdo->voices = pdo->mixeng ? 1 : INT_MAX; } if (!pdo->has_format) { pdo->has_format = true; diff --git a/audio/audio_template.h b/audio/audio_template.h index 9ec565fc48..e5a4d6fa40 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -78,26 +78,32 @@ static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw) static void glue(audio_pcm_hw_
[Qemu-devel] [PATCH v2 46/52] audio: support more than two channels in volume setting
Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 28 audio/audio.h | 10 ++ audio/audio_int.h | 4 ++-- audio/paaudio.c| 20 audio/spiceaudio.c | 14 -- 5 files changed, 52 insertions(+), 24 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 26ce25989f..71744fa2c8 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1880,31 +1880,43 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque) } void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol) +{ +Volume vol = { .mute = mute, .channels = 2, .vol = { lvol, rvol } }; +audio_set_volume_out(sw, &vol); +} + +void audio_set_volume_out(SWVoiceOut *sw, Volume *vol) { if (sw) { HWVoiceOut *hw = sw->hw; -sw->vol.mute = mute; -sw->vol.l = nominal_volume.l * lvol / 255; -sw->vol.r = nominal_volume.r * rvol / 255; +sw->vol.mute = vol->mute; +sw->vol.l = nominal_volume.l * vol->vol[0] / 255; +sw->vol.r = nominal_volume.l * vol->vol[vol->channels > 1 ? 1 : 0] / 255; if (hw->pcm_ops->volume_out) { -hw->pcm_ops->volume_out(hw, &sw->vol); +hw->pcm_ops->volume_out(hw, vol); } } } void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol) +{ +Volume vol = { .mute = mute, .channels = 2, .vol = { lvol, rvol } }; +audio_set_volume_in(sw, &vol); +} + +void audio_set_volume_in(SWVoiceIn *sw, Volume *vol) { if (sw) { HWVoiceIn *hw = sw->hw; -sw->vol.mute = mute; -sw->vol.l = nominal_volume.l * lvol / 255; -sw->vol.r = nominal_volume.r * rvol / 255; +sw->vol.mute = vol->mute; +sw->vol.l = nominal_volume.l * vol->vol[0] / 255; +sw->vol.r = nominal_volume.r * vol->vol[vol->channels > 1 ? 1 : 0] / 255; if (hw->pcm_ops->volume_in) { -hw->pcm_ops->volume_in(hw, &sw->vol); +hw->pcm_ops->volume_in(hw, vol); } } } diff --git a/audio/audio.h b/audio/audio.h index bfb12e7531..911365cebd 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -125,6 +125,16 @@ uint64_t AUD_get_elapsed_usec_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts); void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol); void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol); +#define AUDIO_MAX_CHANNELS 16 +typedef struct Volume { +bool mute; +int channels; +uint8_t vol[AUDIO_MAX_CHANNELS]; +} Volume; + +void audio_set_volume_out(SWVoiceOut *sw, Volume *vol); +void audio_set_volume_in(SWVoiceIn *sw, Volume *vol); + SWVoiceIn *AUD_open_in ( QEMUSoundCard *card, SWVoiceIn *sw, diff --git a/audio/audio_int.h b/audio/audio_int.h index a5ead07998..c2f6da5cc2 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -165,7 +165,7 @@ struct audio_pcm_ops { */ size_t (*put_buffer_out)(HWVoiceOut *hw, void *buf, size_t size); void (*enable_out)(HWVoiceOut *hw, bool enable); -void (*volume_out)(HWVoiceOut *hw, struct mixeng_volume *vol); +void (*volume_out)(HWVoiceOut *hw, Volume *vol); int(*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque); void (*fini_in) (HWVoiceIn *hw); @@ -174,7 +174,7 @@ struct audio_pcm_ops { void *(*get_buffer_in)(HWVoiceIn *hw, size_t *size); void (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size); void (*enable_in)(HWVoiceIn *hw, bool enable); -void (*volume_in)(HWVoiceIn *hw, struct mixeng_volume *vol); +void (*volume_in)(HWVoiceIn *hw, Volume *vol); }; void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size); diff --git a/audio/paaudio.c b/audio/paaudio.c index e8556e7a9d..3b4b29b38f 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -537,20 +537,22 @@ static void qpa_fini_in (HWVoiceIn *hw) } } -static void qpa_volume_out(HWVoiceOut *hw, struct mixeng_volume *vol) +static void qpa_volume_out(HWVoiceOut *hw, Volume *vol) { PAVoiceOut *pa = (PAVoiceOut *) hw; pa_operation *op; pa_cvolume v; PAConnection *c = pa->g->conn; +int i; #ifdef PA_CHECK_VERSION/* macro is present in 0.9.16+ */ pa_cvolume_init (&v); /* function is present in 0.9.13+ */ #endif -v.channels = 2; -v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->l) / UINT32_MAX; -v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->r) / UINT32_MAX; +v.channels = vol->channels; +for (i = 0; i < vol->channels; ++i) { +v.values[i] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->vol[i]) / 255; +} pa_threaded_mainloop_lock(c->mainloop); @@ -577,20 +579,22 @@ static void qpa_volume_out(HWVoiceOut *hw, struct mixeng_volume *vol) pa_threaded_mainloop_unlock(c->mainloop); } -static void qpa_volume_in(HWVoiceIn *hw, struct mixeng_volume *vol) +static void qpa_volume_in(HWVoiceIn *hw, Volu
[Qemu-devel] [PATCH v2 04/52] audio: use qapi AudioFormat instead of audfmt_e
I had to include an enum for audio sampling formats into qapi, but that meant duplicating the audfmt_e enum. This patch replaces audfmt_e and associated values with the qapi generated AudioFormat enum. This patch is mostly a search-and-replace, except for switches where the qapi generated AUDIO_FORMAT_MAX caused problems. Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c | 53 +++-- audio/audio.c | 97 +-- audio/audio.h | 12 + audio/audio_win_int.c | 18 audio/ossaudio.c | 30 ++-- audio/paaudio.c | 28 +-- audio/sdlaudio.c | 26 +-- audio/spiceaudio.c| 4 +- audio/wavaudio.c | 17 --- audio/wavcapture.c| 2 +- hw/arm/omap2.c| 2 +- hw/audio/ac97.c | 2 +- hw/audio/adlib.c | 2 +- hw/audio/cs4231a.c| 6 +-- hw/audio/es1370.c | 4 +- hw/audio/gus.c| 2 +- hw/audio/hda-codec.c | 18 hw/audio/lm4549.c | 6 +-- hw/audio/milkymist-ac97.c | 2 +- hw/audio/pcspk.c | 2 +- hw/audio/sb16.c | 14 +++--- hw/audio/wm8750.c | 4 +- hw/display/xlnx_dp.c | 2 +- hw/input/tsc210x.c| 2 +- hw/usb/dev-audio.c| 2 +- ui/vnc.c | 26 +-- 26 files changed, 195 insertions(+), 188 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 635be73bf4..5bd034267f 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -87,7 +87,7 @@ struct alsa_params_req { struct alsa_params_obt { int freq; -audfmt_e fmt; +AudioFormat fmt; int endianness; int nchannels; snd_pcm_uframes_t samples; @@ -294,16 +294,16 @@ static int alsa_write (SWVoiceOut *sw, void *buf, int len) return audio_pcm_sw_write (sw, buf, len); } -static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) +static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness) { switch (fmt) { -case AUD_FMT_S8: +case AUDIO_FORMAT_S8: return SND_PCM_FORMAT_S8; -case AUD_FMT_U8: +case AUDIO_FORMAT_U8: return SND_PCM_FORMAT_U8; -case AUD_FMT_S16: +case AUDIO_FORMAT_S16: if (endianness) { return SND_PCM_FORMAT_S16_BE; } @@ -311,7 +311,7 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) return SND_PCM_FORMAT_S16_LE; } -case AUD_FMT_U16: +case AUDIO_FORMAT_U16: if (endianness) { return SND_PCM_FORMAT_U16_BE; } @@ -319,7 +319,7 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) return SND_PCM_FORMAT_U16_LE; } -case AUD_FMT_S32: +case AUDIO_FORMAT_S32: if (endianness) { return SND_PCM_FORMAT_S32_BE; } @@ -327,7 +327,7 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) return SND_PCM_FORMAT_S32_LE; } -case AUD_FMT_U32: +case AUDIO_FORMAT_U32: if (endianness) { return SND_PCM_FORMAT_U32_BE; } @@ -344,58 +344,58 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) } } -static int alsa_to_audfmt (snd_pcm_format_t alsafmt, audfmt_e *fmt, +static int alsa_to_audfmt (snd_pcm_format_t alsafmt, AudioFormat *fmt, int *endianness) { switch (alsafmt) { case SND_PCM_FORMAT_S8: *endianness = 0; -*fmt = AUD_FMT_S8; +*fmt = AUDIO_FORMAT_S8; break; case SND_PCM_FORMAT_U8: *endianness = 0; -*fmt = AUD_FMT_U8; +*fmt = AUDIO_FORMAT_U8; break; case SND_PCM_FORMAT_S16_LE: *endianness = 0; -*fmt = AUD_FMT_S16; +*fmt = AUDIO_FORMAT_S16; break; case SND_PCM_FORMAT_U16_LE: *endianness = 0; -*fmt = AUD_FMT_U16; +*fmt = AUDIO_FORMAT_U16; break; case SND_PCM_FORMAT_S16_BE: *endianness = 1; -*fmt = AUD_FMT_S16; +*fmt = AUDIO_FORMAT_S16; break; case SND_PCM_FORMAT_U16_BE: *endianness = 1; -*fmt = AUD_FMT_U16; +*fmt = AUDIO_FORMAT_U16; break; case SND_PCM_FORMAT_S32_LE: *endianness = 0; -*fmt = AUD_FMT_S32; +*fmt = AUDIO_FORMAT_S32; break; case SND_PCM_FORMAT_U32_LE: *endianness = 0; -*fmt = AUD_FMT_U32; +*fmt = AUDIO_FORMAT_U32; break; case SND_PCM_FORMAT_S32_BE: *endianness = 1; -*fmt = AUD_FMT_S32; +*fmt = AUDIO_FORMAT_S32; break; case SND_PCM_FORMAT_U32_BE: *endianness = 1; -*fmt = AUD_FMT_U32; +*fmt = AUDIO_FORMAT_U32; break; default: @@ -638,19 +638,22 @@ static int alsa_open (int in, str
[Qemu-devel] [PATCH v2 47/52] audio: replace shift in audio_pcm_info with bytes_per_frame
The bit shifting trick worked because the number of bytes per frame was always a power-of-two (since QEMU only supports mono, stereo and 8, 16 and 32 bit samples). But if we want to add support for surround sound, this no longer holds true. Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c | 10 +++--- audio/audio.c | 76 - audio/audio_int.h | 3 +- audio/coreaudio.c | 4 +-- audio/dsound_template.h | 10 +++--- audio/dsoundaudio.c | 4 +-- audio/noaudio.c | 2 +- audio/ossaudio.c| 14 audio/spiceaudio.c | 5 +-- audio/wavaudio.c| 6 ++-- 10 files changed, 67 insertions(+), 67 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index bc097b1f31..418b888a57 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -612,7 +612,7 @@ static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len) { ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; size_t pos = 0; -size_t len_frames = len >> hw->info.shift; +size_t len_frames = len / hw->info.bytes_per_frame; while (len_frames) { char *src = advance(buf, pos); @@ -656,7 +656,7 @@ static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len) } } -pos += written << hw->info.shift; +pos += written * hw->info.bytes_per_frame; if (written < len_frames) { break; } @@ -822,7 +822,7 @@ static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len) void *dst = advance(buf, pos); snd_pcm_sframes_t nread; -nread = snd_pcm_readi(alsa->handle, dst, len >> hw->info.shift); +nread = snd_pcm_readi(alsa->handle, dst, len / hw->info.bytes_per_frame); if (nread <= 0) { switch (nread) { @@ -848,8 +848,8 @@ static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len) } } -pos += nread << hw->info.shift; -len -= nread << hw->info.shift; +pos += nread * hw->info.bytes_per_frame; +len -= nread * hw->info.bytes_per_frame; } return pos; diff --git a/audio/audio.c b/audio/audio.c index 71744fa2c8..ee508c1f15 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -298,26 +298,27 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, struct audsettings *a void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as) { -int bits = 8, sign = 0, shift = 0; +int bits = 8, sign = 0, mul; switch (as->fmt) { case AUDIO_FORMAT_S8: sign = 1; case AUDIO_FORMAT_U8: +mul = 1; break; case AUDIO_FORMAT_S16: sign = 1; case AUDIO_FORMAT_U16: bits = 16; -shift = 1; +mul = 2; break; case AUDIO_FORMAT_S32: sign = 1; case AUDIO_FORMAT_U32: bits = 32; -shift = 2; +mul = 4; break; default: @@ -328,9 +329,8 @@ void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as) info->bits = bits; info->sign = sign; info->nchannels = as->nchannels; -info->shift = (as->nchannels == 2) + shift; -info->align = (1 << info->shift) - 1; -info->bytes_per_second = info->freq << info->shift; +info->bytes_per_frame = as->nchannels * mul; +info->bytes_per_second = info->freq * info->bytes_per_frame; info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS); } @@ -341,26 +341,25 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len) } if (info->sign) { -memset (buf, 0x00, len << info->shift); +memset (buf, 0x00, len * info->bytes_per_frame); } else { switch (info->bits) { case 8: -memset (buf, 0x80, len << info->shift); +memset (buf, 0x80, len * info->bytes_per_frame); break; case 16: { int i; uint16_t *p = buf; -int shift = info->nchannels - 1; short s = INT16_MAX; if (info->swap_endianness) { s = bswap16 (s); } -for (i = 0; i < len << shift; i++) { +for (i = 0; i < len * info->nchannels; i++) { p[i] = s; } } @@ -370,14 +369,13 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len) { int i; uint32_t *p = buf; -int shift = info->nchannels - 1; int32_t s = INT32_MAX; if (info->swap_endianness) { s = bswap32 (s); } -for (i = 0; i < len << shift; i++) { +for (i = 0; i < len * info->nchannels; i++) { p[i] = s; } } @@ -560,7
[Qemu-devel] [PATCH v2 13/52] sdlaudio: port to -audiodev config
Signed-off-by: Kővágó, Zoltán --- audio/audio_legacy.c | 7 +++ audio/sdlaudio.c | 22 -- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/audio/audio_legacy.c b/audio/audio_legacy.c index 1f99d21803..6d95b761b8 100644 --- a/audio/audio_legacy.c +++ b/audio/audio_legacy.c @@ -105,6 +105,11 @@ SimpleEnvMap pa_map[] = { { /* End of list */ } }; +SimpleEnvMap sdl_map[] = { +{ "QEMU_SDL_SAMPLES", "buffer-len", ENV_TRANSFORM_SAMPLES_TO_USECS_OUT }, +{ /* End of list */ } +}; + static unsigned long long toull(const char *str) { unsigned long long ret; @@ -283,6 +288,8 @@ static void legacy_opt(const char *drv) handle_env_opts(opts, oss_map); } else if (strcmp(drv, "pa") == 0) { handle_env_opts(opts, pa_map); +} else if (strcmp(drv, "sdl") == 0) { +handle_env_opts(opts, sdl_map); } } diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index 097841fde1..cf6ac19927 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -49,12 +49,6 @@ typedef struct SDLVoiceOut { int decr; } SDLVoiceOut; -static struct { -int nb_samples; -} conf = { -.nb_samples = 1024 -}; - static struct SDLAudioState { int exit; #if USE_SEMAPHORE @@ -63,6 +57,7 @@ static struct SDLAudioState { #endif int initialized; bool driver_created; +Audiodev *dev; } glob_sdl; typedef struct SDLAudioState SDLAudioState; @@ -392,7 +387,7 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as, req.freq = as->freq; req.format = aud_to_sdlfmt (as->fmt); req.channels = as->nchannels; -req.samples = conf.nb_samples; +req.samples = audio_buffer_samples(s->dev->out, as, 11610); req.callback = sdl_callback; req.userdata = sdl; @@ -467,6 +462,7 @@ static void *sdl_audio_init(Audiodev *dev) #endif s->driver_created = true; +s->dev = dev; return s; } @@ -480,18 +476,9 @@ static void sdl_audio_fini (void *opaque) #endif SDL_QuitSubSystem (SDL_INIT_AUDIO); s->driver_created = false; +s->dev = NULL; } -static struct audio_option sdl_options[] = { -{ -.name = "SAMPLES", -.tag = AUD_OPT_INT, -.valp = &conf.nb_samples, -.descr = "Size of SDL buffer in samples" -}, -{ /* End of list */ } -}; - static struct audio_pcm_ops sdl_pcm_ops = { .init_out = sdl_init_out, .fini_out = sdl_fini_out, @@ -503,7 +490,6 @@ static struct audio_pcm_ops sdl_pcm_ops = { static struct audio_driver sdl_audio_driver = { .name = "sdl", .descr = "SDL http://www.libsdl.org";, -.options= sdl_options, .init = sdl_audio_init, .fini = sdl_audio_fini, .pcm_ops= &sdl_pcm_ops, -- 2.20.1
[Qemu-devel] [PATCH v2 15/52] wavaudio: port to -audiodev config
Signed-off-by: Kővágó, Zoltán --- audio/audio_legacy.c | 10 audio/wavaudio.c | 58 +++- 2 files changed, 19 insertions(+), 49 deletions(-) diff --git a/audio/audio_legacy.c b/audio/audio_legacy.c index 6d95b761b8..71bbda04e2 100644 --- a/audio/audio_legacy.c +++ b/audio/audio_legacy.c @@ -110,6 +110,14 @@ SimpleEnvMap sdl_map[] = { { /* End of list */ } }; +SimpleEnvMap wav_map[] = { +{ "QEMU_WAV_FREQUENCY", "out.frequency" }, +{ "QEMU_WAV_FORMAT", "out.format", ENV_TRANSFORM_FMT }, +{ "QEMU_WAV_DAC_FIXED_CHANNELS", "out.channels" }, +{ "QEMU_WAV_PATH", "path" }, +{ /* End of list */ } +}; + static unsigned long long toull(const char *str) { unsigned long long ret; @@ -290,6 +298,8 @@ static void legacy_opt(const char *drv) handle_env_opts(opts, pa_map); } else if (strcmp(drv, "sdl") == 0) { handle_env_opts(opts, sdl_map); +} else if (strcmp(drv, "wav") == 0) { +handle_env_opts(opts, wav_map); } } diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 9eff3555b3..214e30ccd9 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu/host-utils.h" #include "qemu/timer.h" +#include "qapi/opts-visitor.h" #include "audio.h" #define AUDIO_CAP "wav" @@ -37,11 +38,6 @@ typedef struct WAVVoiceOut { int total_samples; } WAVVoiceOut; -typedef struct { -struct audsettings settings; -const char *wav_path; -} WAVConf; - static int wav_run_out (HWVoiceOut *hw, int live) { WAVVoiceOut *wav = (WAVVoiceOut *) hw; @@ -112,8 +108,10 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings *as, 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00 }; -WAVConf *conf = drv_opaque; -struct audsettings wav_as = conf->settings; +Audiodev *dev = drv_opaque; +AudiodevWavOptions *wopts = &dev->u.wav; +struct audsettings wav_as = audiodev_to_audsettings(dev->out); +const char *wav_path = wopts->has_path ? wopts->path : "qemu.wav"; stereo = wav_as.nchannels == 2; switch (wav_as.fmt) { @@ -154,10 +152,10 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings *as, le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4); le_store (hdr + 32, 1 << (bits16 + stereo), 2); -wav->f = fopen (conf->wav_path, "wb"); +wav->f = fopen(wav_path, "wb"); if (!wav->f) { dolog ("Failed to open wave file `%s'\nReason: %s\n", - conf->wav_path, strerror (errno)); + wav_path, strerror(errno)); g_free (wav->pcm_buf); wav->pcm_buf = NULL; return -1; @@ -225,54 +223,17 @@ static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...) return 0; } -static WAVConf glob_conf = { -.settings.freq = 44100, -.settings.nchannels = 2, -.settings.fmt = AUDIO_FORMAT_S16, -.wav_path = "qemu.wav" -}; - static void *wav_audio_init(Audiodev *dev) { -WAVConf *conf = g_malloc(sizeof(WAVConf)); -*conf = glob_conf; -return conf; +assert(dev->driver == AUDIODEV_DRIVER_WAV); +return dev; } static void wav_audio_fini (void *opaque) { ldebug ("wav_fini"); -g_free(opaque); } -static struct audio_option wav_options[] = { -{ -.name = "FREQUENCY", -.tag = AUD_OPT_INT, -.valp = &glob_conf.settings.freq, -.descr = "Frequency" -}, -{ -.name = "FORMAT", -.tag = AUD_OPT_FMT, -.valp = &glob_conf.settings.fmt, -.descr = "Format" -}, -{ -.name = "DAC_FIXED_CHANNELS", -.tag = AUD_OPT_INT, -.valp = &glob_conf.settings.nchannels, -.descr = "Number of channels (1 - mono, 2 - stereo)" -}, -{ -.name = "PATH", -.tag = AUD_OPT_STR, -.valp = &glob_conf.wav_path, -.descr = "Path to wave file" -}, -{ /* End of list */ } -}; - static struct audio_pcm_ops wav_pcm_ops = { .init_out = wav_init_out, .fini_out = wav_fini_out, @@ -284,7 +245,6 @@ static struct audio_pcm_ops wav_pcm_ops = { static struct audio_driver wav_audio_driver = { .name = "wav", .descr = "WAV renderer http://wikipedia.org/wiki/WAV";, -.options= wav_options, .init = wav_audio_init, .fini = wav_audio_fini, .pcm_ops= &wav_pcm_ops, -- 2.20.1
[Qemu-devel] [PATCH v2 20/52] audio: audiodev= parameters no longer optional when -audiodev present
This means you should probably stop using -soundhw (as it doesn't allow you to specify any options) and add the device manually with -device. The exception is pcspk, it's currently not possible to manually add it. To use it with audiodev, use something like this: -audiodev id=foo,... -global isa-pcspk.audiodev=foo -soundhw pcspk Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 24 ++-- audio/paaudio.c | 303 +++- 2 files changed, 189 insertions(+), 138 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 92fa170b46..a7f79f3929 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -100,6 +100,8 @@ const struct mixeng_volume nominal_volume = { #endif }; +static bool legacy_config = true; + #ifdef AUDIO_IS_FLAWLESS_AND_NO_CHECKS_ARE_REQURIED #error No its not #else @@ -1381,7 +1383,7 @@ static Audiodev *parse_option(QemuOpts *opts, Error **errp); * if dev == NULL => legacy implicit initialization, return the already created * state or create a new one */ -static AudioState *audio_init(Audiodev *dev) +static AudioState *audio_init(Audiodev *dev, const char *name) { static bool atexit_registered; size_t i; @@ -1395,12 +1397,13 @@ static AudioState *audio_init(Audiodev *dev) if (dev) { /* -audiodev option */ +legacy_config = false; drvname = AudiodevDriver_str(dev->driver); } else if (!QTAILQ_EMPTY(&audio_states)) { -/* - * todo: check for -audiodev once we have normal audiodev selection - * support - */ +if (!legacy_config) { +dolog("You must specify an audiodev= for the device %s\n", name); +exit(1); +} return QTAILQ_FIRST(&audio_states); } else { /* legacy implicit initialization */ @@ -1497,7 +1500,7 @@ static AudioState *audio_init(Audiodev *dev) void AUD_register_card (const char *name, QEMUSoundCard *card) { if (!card->state) { -card->state = audio_init(NULL); +card->state = audio_init(NULL, name); } card->name = g_strdup (name); @@ -1523,8 +1526,11 @@ CaptureVoiceOut *AUD_add_capture( struct capture_callback *cb; if (!s) { -/* todo: remove when we have normal audiodev selection support */ -s = audio_init(NULL); +if (!legacy_config) { +dolog("You must specify audiodev when trying to capture\n"); +goto err0; +} +s = audio_init(NULL, NULL); } if (audio_validate_settings (as)) { @@ -1763,7 +1769,7 @@ static int each_option(void *opaque, QemuOpts *opts, Error **errp) if (!dev) { return -1; } -return audio_init(dev) ? 0 : -1; +return audio_init(dev, NULL) ? 0 : -1; } void audio_set_options(void) diff --git a/audio/paaudio.c b/audio/paaudio.c index 6de6ed97fc..24b75ca503 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -10,10 +10,21 @@ #include "audio_int.h" #include "audio_pt_int.h" -typedef struct { -Audiodev *dev; +typedef struct PAConnection { +char *server; +int refcount; +QTAILQ_ENTRY(PAConnection) list; + pa_threaded_mainloop *mainloop; pa_context *context; +} PAConnection; + +static QTAILQ_HEAD(PAConnectionHead, PAConnection) pa_conns = +QTAILQ_HEAD_INITIALIZER(pa_conns); + +typedef struct { +Audiodev *dev; +PAConnection *conn; } paaudio; typedef struct { @@ -44,7 +55,7 @@ typedef struct { int samples; } PAVoiceIn; -static void qpa_audio_fini(void *opaque); +static void qpa_conn_fini(PAConnection *c); static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...) { @@ -107,11 +118,11 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror) { -paaudio *g = p->g; +PAConnection *c = p->g->conn; -pa_threaded_mainloop_lock (g->mainloop); +pa_threaded_mainloop_lock(c->mainloop); -CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail); +CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail); while (length > 0) { size_t l; @@ -120,11 +131,11 @@ static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror int r; r = pa_stream_peek (p->stream, &p->read_data, &p->read_length); -CHECK_SUCCESS_GOTO (g, rerror, r == 0, unlock_and_fail); +CHECK_SUCCESS_GOTO(c, rerror, r == 0, unlock_and_fail); if (!p->read_data) { -pa_threaded_mainloop_wait (g->mainloop); -CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail); +pa_threaded_mainloop_wait(c->mainloop); +CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail); } else { p->read_index = 0; } @@ -147,53 +158,53 @@ static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror
[Qemu-devel] [PATCH v2 05/52] audio: -audiodev command line option: documentation
This patch adds documentation of an -audiodev command line option, that deprecates the old QEMU_* environment variables for audio backend configuration. It's syntax is similar to existing options (-netdev, -device, etc): -audiodev driver_name,property=value,... Although now it's possible to specify multiple -audiodev options on command line, multiple audio backends are not supported yet. Signed-off-by: Kővágó, Zoltán --- qemu-options.hx | 222 +++- 1 file changed, 219 insertions(+), 3 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index df42116ecc..3ede6a591d 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -416,14 +416,230 @@ The default is @code{en-us}. ETEXI +HXCOMM Deprecated by -audiodev DEF("audio-help", 0, QEMU_OPTION_audio_help, -"-audio-help print list of audio drivers and their options\n", +"-audio-help show -audiodev equivalent of the currently specified audio settings\n", QEMU_ARCH_ALL) STEXI @item -audio-help @findex -audio-help -Will show the audio subsystem help: list of drivers, tunable -parameters. +Will show the -audiodev equivalent of the currently specified +(deprecated) environment variables. +ETEXI + +DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, +"-audiodev [driver=]driver,id=id[,prop[=value][,...]]\n" +"specifies the audio backend to use\n" +"id= identifier of the backend\n" +"timer-period= timer period in microseconds\n" +"in|out.fixed-settings= use fixed settings for host audio\n" +"in|out.frequency= frequency to use with fixed settings\n" +"in|out.channels= number of channels to use with fixed settings\n" +"in|out.format= sample format to use with fixed settings\n" +"valid values: s8, s16, s32, u8, u16, u32\n" +"in|out.voices= number of voices to use\n" +"in|out.buffer-len= size of buffer in microseconds\n" +"in|out.buffer-count= number of buffers\n" +"-audiodev none,id=id,[,prop[=value][,...]]\n" +"dummy driver that discards all output\n" +#ifdef CONFIG_ALSA +"-audiodev alsa,id=id[,prop[=value][,...]]\n" +"alsa-in|alsa-out.dev= name of the audio device to use\n" +"alsa-in|alsa-out.try-poll= attempt to use poll mode\n" +"threshold= threshold (in microseconds) when playback starts\n" +#endif +#ifdef CONFIG_COREAUDIO +"-audiodev coreaudio,id=id[,prop[=value][,...]]\n" +#endif +#ifdef CONFIG_DSOUND +"-audiodev dsound,id=id[,prop[=value][,...]]\n" +"latency= add extra latency to playback in microseconds\n" +#endif +#ifdef CONFIG_OSS +"-audiodev oss,id=id[,prop[=value][,...]]\n" +"oss-in|oss-out.dev= path of the audio device to use\n" +"oss-in|oss-out.try-poll= attempt to use poll mode\n" +"try-mmap= try using memory mapped access\n" +"exclusive= open device in exclusive mode\n" +"dsp-policy= set timing policy (0..10), -1 to use fragment mode\n" +#endif +#ifdef CONFIG_PA +"-audiodev pa,id=id[,prop[=value][,...]]\n" +"server= PulseAudio server address\n" +"sink|source.name= sink/source device name\n" +#endif +#ifdef CONFIG_SDL +"-audiodev sdl,id=id[,prop[=value][,...]]\n" +#endif +#ifdef CONFIG_SPICE +"-audiodev spice,id=id[,prop[=value][,...]]\n" +#endif +"-audiodev wav,id=id[,prop[=value][,...]]\n" +"path= path of wav file to record\n", +QEMU_ARCH_ALL) +STEXI +@item -audiodev [driver=]@var{driver},id=@var{id}[,@var{prop}[=@var{value}][,...]] +@findex -audiodev +Adds a new audio backend @var{driver} identified by @var{id}. There are +global and driver specific properties. Some values can be set +differently for input and output, they're marked with @code{in|out.}. +You can set the input's property with @code{in.@var{prop}} and the +output's property with @code{out.@var{prop}}. For example: +@example +-audiodev alsa,id=example,in.frequency=44110,out.frequency=8000 +-audiodev alsa,id=example,out.channels=1 # leaves in.channels unspecified +@end example + +Valid global options are: + +@table @option +@item id=@var{identifier} +Identifies the audio backend. + +@item timer-period=@var{period} +Sets the timer @var{period} used by the audio subsystem in microseconds. +Default is 1 (10 ms). + +@item in|out.fixed-settings=on|off +Use fixed settings for host audio. When off, it will change based on +how the guest opens the sound card. In this case you must not specify +@var{frequency}, @var{channels} or @var{format}. Default is on. + +@item in|out.frequency=@var{frequency} +Specify the @var{frequency} to use when using @var{fixed-settings}. +Default is 44100Hz. + +@
[Qemu-devel] [PATCH v2 01/52] qapi: support alternates in OptsVisitor
They are required for flat unions (you still have to allocate the structs). Signed-off-by: Kővágó, Zoltán --- include/qapi/opts-visitor.h | 7 +++ qapi/opts-visitor.c | 16 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/include/qapi/opts-visitor.h b/include/qapi/opts-visitor.h index 9b989e7e08..ca044e3b33 100644 --- a/include/qapi/opts-visitor.h +++ b/include/qapi/opts-visitor.h @@ -29,10 +29,9 @@ typedef struct OptsVisitor OptsVisitor; * - values below INT64_MIN or LLONG_MIN are rejected, * - values above INT64_MAX or LLONG_MAX are rejected. * - * The Opts input visitor does not implement support for visiting QAPI - * alternates, numbers (other than integers), null, or arbitrary - * QTypes. It also requires a non-null list argument to - * visit_start_list(). + * The Opts input visitor does not implement support for visiting numbers + * (other than integers), null, or arbitrary QTypes. It also requires a + * non-null list argument to visit_start_list(). */ Visitor *opts_visitor_new(const QemuOpts *opts); diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index 324b197495..4af6043b75 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -156,6 +156,13 @@ opts_start_struct(Visitor *v, const char *name, void **obj, } } +static void +opts_start_alternate(Visitor *v, const char *name, GenericAlternate **obj, + size_t size, Error **errp) +{ +opts_start_struct(v, name, (void **)obj, size, errp); +} + static void opts_check_struct(Visitor *v, Error **errp) @@ -198,6 +205,12 @@ opts_end_struct(Visitor *v, void **obj) ov->fake_id_opt = NULL; } +static void +opts_end_alternate(Visitor *v, void **obj) +{ +opts_end_struct(v, obj); +} + static GQueue * lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp) @@ -547,6 +560,9 @@ opts_visitor_new(const QemuOpts *opts) ov->visitor.check_struct = &opts_check_struct; ov->visitor.end_struct = &opts_end_struct; +ov->visitor.start_alternate = &opts_start_alternate; +ov->visitor.end_alternate = &opts_end_alternate; + ov->visitor.start_list = &opts_start_list; ov->visitor.next_list = &opts_next_list; ov->visitor.check_list = &opts_check_list; -- 2.20.1
[Qemu-devel] [PATCH v2 00/52] Audio 5.1 patches
Hi, I've updated my audio patchset to the current git master. Other than that not much happened since my last update [1], fixed a few small problems that I noticed while rebasing my patches. Please review. [1]: https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg02451.html Kővágó, Zoltán (52): qapi: support alternates in OptsVisitor qapi: support nested structs in OptsVisitor qapi: qapi for audio backends audio: use qapi AudioFormat instead of audfmt_e audio: -audiodev command line option: documentation audio: -audiodev command line option basic implementation alsaaudio: port to -audiodev config coreaudio: port to -audiodev config dsoundaudio: port to -audiodev config noaudio: port to -audiodev config ossaudio: port to -audiodev config paaudio: port to -audiodev config sdlaudio: port to -audiodev config spiceaudio: port to -audiodev config wavaudio: port to -audiodev config audio: -audiodev command line option: cleanup audio: reduce glob_audio_state usage audio: basic support for multi backend audio audio: add audiodev properties to frontends audio: audiodev= parameters no longer optional when -audiodev present paaudio: do not move stream when sink/source name is specified paaudio: properly disconnect streams in fini_* audio: remove audio_MIN, audio_MAX audio: do not run each backend in audio_run paaudio: fix playback glitches audio: remove read and write pcm_ops audio: use size_t where makes sense audio: api for mixeng code free backends alsaaudio: port to the new audio backend api coreaudio: port to the new audio backend api dsoundaudio: port to the new audio backend api noaudio: port to the new audio backend api ossaudio: port to the new audio backend api paaudio: port to the new audio backend api sdlaudio: port to the new audio backend api spiceaudio: port to the new audio backend api wavaudio: port to the new audio backend api audio: remove remains of the old backend api audio: unify input and output mixeng buffer management audio: remove hw->samples, buffer_size_in/out pcm_ops audio: common rate control code for timer based outputs audio: split ctl_* functions into enable_* and volume_* audio: add mixeng option (documentation) audio: make mixeng optional paaudio: get/put_buffer functions audio: support more than two channels in volume setting audio: replace shift in audio_pcm_info with bytes_per_frame audio: basic support for multichannel audio paaudio: channel-map option usb-audio: do not count on avail bytes actually available usb-audio: support more than two channels of audio usbaudio: change playback counters to 64 bit Makefile.objs |6 +- audio/Makefile.objs |3 +- audio/alsaaudio.c | 755 --- audio/audio.c | 1561 --- audio/audio.h | 78 +- audio/audio_int.h | 131 +- audio/audio_legacy.c| 342 + audio/audio_pt_int.c| 174 --- audio/audio_pt_int.h| 22 - audio/audio_template.h | 112 +- audio/audio_win_int.c | 18 +- audio/coreaudio.c | 198 ++- audio/dsound_template.h | 63 +- audio/dsoundaudio.c | 449 ++- audio/mixeng.h | 11 +- audio/noaudio.c | 98 +- audio/ossaudio.c| 594 - audio/paaudio.c | 881 ++--- audio/rate_template.h |2 +- audio/sdlaudio.c| 218 ++-- audio/spiceaudio.c | 286 ++--- audio/wavaudio.c| 158 +-- audio/wavcapture.c |8 +- configure |5 - hmp-commands.hx | 11 +- hw/acpi/core.c |2 +- hw/arm/omap2.c |2 +- hw/audio/ac97.c | 13 +- hw/audio/adlib.c|7 +- hw/audio/cs4231a.c | 11 +- hw/audio/es1370.c | 17 +- hw/audio/gus.c |9 +- hw/audio/hda-codec.c| 35 +- hw/audio/lm4549.c |6 +- hw/audio/milkymist-ac97.c | 16 +- hw/audio/pcspk.c|5 +- hw/audio/pl041.c|1 + hw/audio/sb16.c | 17 +- hw/audio/wm8750.c | 14 +- hw/core/qdev-properties-system.c| 57 + hw/display/xlnx_dp.c|2 +- hw/input/tsc210x.c |2 +- hw/usb/dev-audio.c | 460 ++- include/hw/qdev-properties.h|3 + i
Re: [Qemu-devel] [PATCH v2 23/52] audio: remove audio_MIN, audio_MAX
Hi Zoltán, On 12/23/18 9:51 PM, Kővágó, Zoltán wrote: > There's already a MIN and MAX macro in include/qemu/osdep.h, use them > instead. > > Signed-off-by: Kővágó, Zoltán > > --- > > Changes from v1: > * removed audio_MIN, audio_MAX macros > --- [...]> > diff --git a/audio/audio.h b/audio/audio.h > index ccfef9e10a..bcbe56d639 100644 > --- a/audio/audio.h > +++ b/audio/audio.h > @@ -148,23 +148,6 @@ static inline void *advance (void *p, int incr) > return (d + incr); > } > > -#ifdef __GNUC__ > -#define audio_MIN(a, b) ( __extension__ ({ \ > -__typeof (a) ta = a;\ > -__typeof (b) tb = b;\ > -((ta)>(tb)?(tb):(ta)); \ > -})) > - > -#define audio_MAX(a, b) ( __extension__ ({ \ > -__typeof (a) ta = a;\ > -__typeof (b) tb = b;\ > -((ta)<(tb)?(tb):(ta)); \ > -})) > -#else > -#define audio_MIN(a, b) ((a)>(b)?(b):(a)) > -#define audio_MAX(a, b) ((a)<(b)?(b):(a)) > -#endif > - Those MIN/MAX are smarter than the ones in "qemu/osdep.h", I'd keep them moving them there. Regards, Phil.
Re: [Qemu-devel] [PATCH v2 0/3] vhost-user-test fix
Ping.. Li Qiang 于2018年12月15日周六 下午8:06写道: > Currently, the vhost-user-test is not correct. > When in qtest mode, the accel is qtest, not kvm. > So when the client side of vhost-user-test send > 'VHOST_USER_SET_VRING_CALL' msg, the 'fd' will > no be added in 'fds' in 'vhost_set_vring_file'. > In 'chr_read' of the server side in the > vhost-user-test, it calls 'qemu_chr_fe_get_msgfds' > to get the fd in 'VHOST_USER_SET_VRING_CALL'. Though > there is no fd returned, but as the 'fd' is not initialized > so 'fd' maybe valid, and 'qemu_set_nonblock' will be success. > Even worse, 'qemu_set_nonblock' doesn't check the return value > of fcntl. > > So this cause the interesting bug here: there are three issues, > but they combined and will bypass the qtest. > > This patchset tries to address these issue. > > v2: Change the second patch per Paolo's review > > Li Qiang (3): > tests: vhost-user-test: initialize 'fd' in chr_read > vhost-user: fix ioeventfd_enabled > util: check the return value of fcntl in qemu_set_{block,nonblock} > > hw/virtio/vhost-user.c | 2 +- > tests/vhost-user-test.c | 2 +- > util/oslib-posix.c | 8 ++-- > 3 files changed, 8 insertions(+), 4 deletions(-) > > -- > 2.17.1 > > >
Re: [Qemu-devel] [PATCH for-4.0 v4 2/4] refactor load_image_size
On 12/22/18 00:12, Michael S. Tsirkin wrote: On Thu, Dec 06, 2018 at 10:32:11AM +0800, Li Zhijian wrote: Don't expect read(2) can always read as many as it's told. Signed-off-by: Li Zhijian Reviewed-by: Richard Henderson This is more a theoretical bugfix than a refactoring right? Yes, it does. how about change the title to : "enhance reading on load_image_size()" or such Thanks Zhijian --- V4: add reviewed-by tag --- hw/core/loader.c | 11 +-- 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/hw/core/loader.c b/hw/core/loader.c index fa41842..9cbceab 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -77,21 +77,20 @@ int64_t get_image_size(const char *filename) ssize_t load_image_size(const char *filename, void *addr, size_t size) { int fd; -ssize_t actsize; +ssize_t actsize, l = 0; fd = open(filename, O_RDONLY | O_BINARY); if (fd < 0) { return -1; } -actsize = read(fd, addr, size); -if (actsize < 0) { -close(fd); -return -1; +while ((actsize = read(fd, addr + l, size - l)) > 0) { +l += actsize; } + close(fd); -return actsize; +return actsize < 0 ? -1 : l; } /* read()-like version */ -- 2.7.4 -- Best regards. Li Zhijian (8528)
Re: [Qemu-devel] [PATCH v2 23/52] audio: remove audio_MIN, audio_MAX
Hi Phil, On 2018-12-24 00:49, Philippe Mathieu-Daudé wrote: > Hi Zoltán, > > On 12/23/18 9:51 PM, Kővágó, Zoltán wrote: >> There's already a MIN and MAX macro in include/qemu/osdep.h, use them >> instead. >> >> Signed-off-by: Kővágó, Zoltán >> >> --- >> >> Changes from v1: >> * removed audio_MIN, audio_MAX macros >> --- > [...]> >> diff --git a/audio/audio.h b/audio/audio.h >> index ccfef9e10a..bcbe56d639 100644 >> --- a/audio/audio.h >> +++ b/audio/audio.h >> @@ -148,23 +148,6 @@ static inline void *advance (void *p, int incr) >> return (d + incr); >> } >> >> -#ifdef __GNUC__ >> -#define audio_MIN(a, b) ( __extension__ ({ \ >> -__typeof (a) ta = a;\ >> -__typeof (b) tb = b;\ >> -((ta)>(tb)?(tb):(ta)); \ >> -})) >> - >> -#define audio_MAX(a, b) ( __extension__ ({ \ >> -__typeof (a) ta = a;\ >> -__typeof (b) tb = b;\ >> -((ta)<(tb)?(tb):(ta)); \ >> -})) >> -#else >> -#define audio_MIN(a, b) ((a)>(b)?(b):(a)) >> -#define audio_MAX(a, b) ((a)<(b)?(b):(a)) >> -#endif >> - > > Those MIN/MAX are smarter than the ones in "qemu/osdep.h", I'd keep them > moving them there. Yes, but only when using gcc (or clang when it emulates gcc). Unfortunately, they work differently when one of the expressions has side effects, which is a disaster waiting to happen (when some poor folk finally tries to compile it with a non-gcc compiler). Or do we support any compilers beside gcc and clang? Because if not, sure, do it, just remove the #ifdef and keep only the gcc version. Regards, Zoltan
Re: [Qemu-devel] did the qemu can emulate the whole system with the processor that without support the "virtulization and kvm"?
thank u. >t can either use TCG or a HW based acceleration >like KVM. HW based acceleration is only available on the same machine >type. BTW, if use the HW acceleration like KVM, no TCG translation between target instruction and host instruction happened, right? thanks! At 2018-12-21 22:14:58, "Alex Bennée" wrote: > >tugouxp <13824125...@163.com> writes: > >> thank you. >> >> i just want to confirm one thing, that is whether the qemu can emulate a >> whole operation system just by analysis instructions by instructions >> manually without the support of KVM. >> so from the answer you give to me, it is feasible, right? > >Yes - if you run qemu-system-$(ARCH) you are emulating a full machine >with hardware attached. It can either use TCG or a HW based acceleration >like KVM. HW based acceleration is only available on the same machine >type. > >There is a third type - qemu-$(ARCH) which is often called linux-user >mode. Here the translation engine only translates instruction from guest >to the host and then maps system calls to the host system. This is isn't >emulating a whole system but allows you to run binaries from one >architecture on another. > >> >> >> >> thanks very much! >> >> >> >> >> >> >> >> >> >> At 2018-12-21 17:01:02, "Alex Bennée" wrote: >>> >>>tugouxp <13824125...@163.com> writes: >>> Hi alex: now my host machine did not have the "/dev/kvm" nodes and no chance to make it exists. so i want to know whether the "/dev/kvm" is mandatory for qemu to emulate the whole system. so i can make the emulation without the support of kvm mechanism. >>> >>>QEMU runs in two modes - full system emulation with TCG doesn't require >>>KVM although it is relatively slow. On systems where there guest >>>architecture is the same as the host architecture you can run with KMV >>>(or HAX/WHPX/HVF) accelerators at near native speeds. >>> >>>The reasons for not having a /dev/kvm can vary but you haven't said what >>>your host architecture is and what OS you are running so it's hard to >>>offer advice here. >>> >>>-- >>>Alex Bennée > > >-- >Alex Bennée
Re: [Qemu-devel] [PATCH for-4.0 v8 6/7] qemu_thread_create: propagate the error to callers to handle
On Fri, Dec 21, 2018 at 05:36:57PM +0800, Fei Li wrote: > > On 12/19/2018 08:14 PM, Fei Li wrote: > > > > On 12/19/2018 06:10 PM, Markus Armbruster wrote: > > > Fei Li writes: > > > > > > > On 12/13/2018 03:26 PM, Markus Armbruster wrote: > > > > > There's a question for David Gibson inline. Please search for /ppc/. > > > > > > > > > > Fei Li writes: > > > > > > > > > > > Make qemu_thread_create() return a Boolean to indicate if it > > > > > > succeeds > > > > > > rather than failing with an error. And add an Error parameter to > > > > > > hold > > > > > > the error message and let the callers handle it. > > > > > The "rather than failing with an error" is misleading. Before the > > > > > patch, we report to stderr and abort(). What about: > > > > > > > > > > qemu-thread: Make qemu_thread_create() handle errors properly > > > > > > > > > > qemu_thread_create() abort()s on error. Not nice. Give it a > > > > > return value and an Error ** argument, so it can > > > > > return success / > > > > > failure. > > > > A nice commit-amend! Thanks! > > > > > Still missing from the commit message then: how you update > > > > > the callers. > > > > Yes, agree. I think the-how should also be noted here, like > > > > - propagating the err to callers whose call trace already have the > > > > Error paramater; > > > > - just add an &error_abort for qemu_thread_create() and make it a > > > > "TODO: xxx"; > > > > > Let's see below. > > > > > > > > > > > Cc: Markus Armbruster > > > > > > Cc: Daniel P. Berrangé > > > > > > Cc: Dr. David Alan Gilbert > > > > > > Signed-off-by: Fei Li > > > > > > --- > > > > > > cpus.c | 45 > > > > > > - > > > > > > dump.c | 6 +++-- > > > > > > hw/misc/edu.c | 6 +++-- > > > > > > hw/ppc/spapr_hcall.c | 10 +++-- > > > > > > hw/rdma/rdma_backend.c | 4 +++- > > > > > > hw/usb/ccid-card-emulated.c | 16 ++ > > > > > > include/qemu/thread.h | 4 ++-- > > > > > > io/task.c | 3 ++- > > > > > > iothread.c | 16 +- > > > > > > migration/migration.c | 54 > > > > > > + > > > > > > migration/postcopy-ram.c | 14 ++-- > > > > > > migration/ram.c | 40 > > > > > > - > > > > > > migration/savevm.c | 11 ++--- > > > > > > tests/atomic_add-bench.c | 3 ++- > > > > > > tests/iothread.c | 2 +- > > > > > > tests/qht-bench.c | 3 ++- > > > > > > tests/rcutorture.c | 3 ++- > > > > > > tests/test-aio.c | 2 +- > > > > > > tests/test-rcu-list.c | 3 ++- > > > > > > ui/vnc-jobs.c | 17 +- > > > > > > ui/vnc-jobs.h | 2 +- > > > > > > ui/vnc.c | 4 +++- > > > > > > util/compatfd.c | 12 -- > > > > > > util/oslib-posix.c | 17 ++ > > > > > > util/qemu-thread-posix.c | 24 +--- > > > > > > util/qemu-thread-win32.c | 16 ++ > > > > > > util/rcu.c | 3 ++- > > > > > > util/thread-pool.c | 4 +++- > > > > > > 28 files changed, 243 insertions(+), 101 deletions(-) > > > > > > > ...snip, and only leave the three uncertain small topics... > > > > > > > > > > diff --git a/migration/ram.c b/migration/ram.c > > > > > > index 658dfa88a3..6e0cccf066 100644 > > > > > > --- a/migration/ram.c > > > > > > +++ b/migration/ram.c > > > > > > @@ -473,6 +473,7 @@ static void compress_threads_save_cleanup(void) > > > > > > static int compress_threads_save_setup(void) > > > > > > { > > > > > > int i, thread_count; > > > > > > + Error *local_err = NULL; > > > > > > if (!migrate_use_compression()) { > > > > > > return 0; > > > > > > @@ -502,9 +503,12 @@ static int compress_threads_save_setup(void) > > > > > > comp_param[i].quit = false; > > > > > > qemu_mutex_init(&comp_param[i].mutex); > > > > > > qemu_cond_init(&comp_param[i].cond); > > > > > > - qemu_thread_create(compress_threads + i, "compress", > > > > > > - do_data_compress, comp_param + i, > > > > > > - QEMU_THREAD_JOINABLE); > > > > > > + if (!qemu_thread_create(compress_threads + i, "compress", > > > > > > + do_data_compress, comp_param + i, > > > > > > + QEMU_THREAD_JOINABLE, &local_err)) > > > > > > { > > > > > > + error_reportf_err(local_err, "failed to > > > > > > create do_data_compress: "); > > > > > > + goto exit; [1] > > > > > > + } > > > > > > } > > > > > > return 0; > > > > > Reviewing the migration changes is getting tire
Re: [Qemu-devel] [PATCH] i386: remove the 'INTEL_PT' CPUID bit from named CPU models
On Sat, 2018-12-22 at 10:13 +0100, Paolo Bonzini wrote: > On 22/12/18 02:01, Robert Hoo wrote: > > On Fri, 2018-12-21 at 16:27 +0100, Paolo Bonzini wrote: > > > On 21/12/18 16:22, Philippe Mathieu-Daudé wrote: > > > > Hi Paolo, > > > > > > > > On 12/21/18 7:30 AM, Paolo Bonzini wrote: > > > > > From: Robert Hoo > > > > > > > > > > Processor tracing is not yet implemented for KVM and it will > > > > > be > > > > > an > > > > > opt in feature requiring a special module parameter. > > > > > Disable it, because it is wrong to enable it by default and > > > > > it is impossible that no one has ever used it. > > > > > > > > > > Cc: qemu-sta...@nongnu.org > > > > > > > > Does this patch misses Robert S-o-b? > > > > Signed-off-by: Robert Hoo > > > > Paolo's right. It didn't come from me. > > > > > > No, the author is wrong, it should be me. "git commit -c" > > > apparently > > > copies the author from the original commit. > > > > > > Paolo > > > > Hi Paolo, would you hold on INTEL_PT removal for a moment? I think > > I > > need Luwei's double confirm. > > I'm aware of Luwei's patches, they will be in 4.21. As mentioned in > the > commit message, they will be an opt-in feature, not enabled by > default; > the default is system-wide tracing and no INTEL_PT CPUID bit > available > in the guest. > OK, synced with Luwei, agree with you. > Paolo
Re: [Qemu-devel] [PATCH v1 0/4] de-macrofy softmmu
Patchew URL: https://patchew.org/QEMU/20181217150116.10446-1-alex.ben...@linaro.org/ Hi, This series failed the docker-mingw@fedora build test. Please find the testing commands and their output below. If you have Docker installed, you can probably reproduce it locally. === TEST SCRIPT BEGIN === #!/bin/bash time make docker-test-mingw@fedora SHOW_ENV=1 J=8 === TEST SCRIPT END === CC x86_64-softmmu/target/i386/cpu.o CC x86_64-softmmu/target/i386/gdbstub.o CC aarch64-softmmu/hw/block/virtio-blk.o /tmp/qemu-test/src/accel/tcg/softmmu.c:207:1: error: conflicting types for 'helper_le_ldq_mmu' helper_le_ldq_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, ^ In file included from /tmp/qemu-test/src/include/exec/cpu_ldst.h:127:0, --- /tmp/qemu-test/src/tcg/tcg.h:1307:10: note: previous declaration of 'helper_le_ldq_mmu' was here uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr, ^ /tmp/qemu-test/src/accel/tcg/softmmu.c:214:1: error: conflicting types for 'helper_be_ldq_mmu' helper_be_ldq_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, ^ In file included from /tmp/qemu-test/src/include/exec/cpu_ldst.h:127:0, --- CC aarch64-softmmu/hw/misc/omap_tap.o CC aarch64-softmmu/hw/misc/bcm2835_mbox.o CC aarch64-softmmu/hw/misc/bcm2835_property.o /tmp/qemu-test/src/accel/tcg/softmmu.c:207:1: error: conflicting types for 'helper_le_ldq_mmu' helper_le_ldq_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, ^ In file included from /tmp/qemu-test/src/include/exec/cpu_ldst.h:127:0, --- /tmp/qemu-test/src/tcg/tcg.h:1307:10: note: previous declaration of 'helper_le_ldq_mmu' was here uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr, ^ /tmp/qemu-test/src/accel/tcg/softmmu.c:214:1: error: conflicting types for 'helper_be_ldq_mmu' helper_be_ldq_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, ^ In file included from /tmp/qemu-test/src/include/exec/cpu_ldst.h:127:0, The full log is available at http://patchew.org/logs/20181217150116.10446-1-alex.ben...@linaro.org/testing.docker-mingw@fedora/?type=message. --- Email generated automatically by Patchew [http://patchew.org/]. Please send your feedback to patchew-de...@redhat.com
Re: [Qemu-devel] [PATCH v2 27/52] audio: use size_t where makes sense
> From: Kővágó, Zoltán [mailto:dirty.ice...@gmail.com] > diff --git a/replay/replay-audio.c b/replay/replay-audio.c > index b113836de4..efe1628727 100644 > --- a/replay/replay-audio.c > +++ b/replay/replay-audio.c > @@ -16,18 +16,18 @@ > #include "sysemu/sysemu.h" > #include "audio/audio.h" > > -void replay_audio_out(int *played) > +void replay_audio_out(size_t *played) > { > if (replay_mode == REPLAY_MODE_RECORD) { > g_assert(replay_mutex_locked()); > replay_save_instructions(); > replay_put_event(EVENT_AUDIO_OUT); > -replay_put_dword(*played); > +replay_put_qword(*played); > } else if (replay_mode == REPLAY_MODE_PLAY) { > g_assert(replay_mutex_locked()); > replay_account_executed_instructions(); > if (replay_next_event_is(EVENT_AUDIO_OUT)) { > -*played = replay_get_dword(); > +*played = replay_get_qword(); > replay_finish_event(); > } else { > error_report("Missing audio out event in the replay log"); > @@ -36,7 +36,7 @@ void replay_audio_out(int *played) > } > } > > -void replay_audio_in(int *recorded, void *samples, int *wpos, int size) > +void replay_audio_in(size_t *recorded, void *samples, size_t *wpos, size_t > size) > { > int pos; > uint64_t left, right; > @@ -44,8 +44,8 @@ void replay_audio_in(int *recorded, void *samples, int > *wpos, int size) > g_assert(replay_mutex_locked()); > replay_save_instructions(); > replay_put_event(EVENT_AUDIO_IN); > -replay_put_dword(*recorded); > -replay_put_dword(*wpos); > +replay_put_qword(*recorded); > +replay_put_qword(*wpos); > for (pos = (*wpos - *recorded + size) % size ; pos != *wpos > ; pos = (pos + 1) % size) { > audio_sample_to_uint64(samples, pos, &left, &right); > @@ -56,8 +56,8 @@ void replay_audio_in(int *recorded, void *samples, int > *wpos, int size) > g_assert(replay_mutex_locked()); > replay_account_executed_instructions(); > if (replay_next_event_is(EVENT_AUDIO_IN)) { > -*recorded = replay_get_dword(); > -*wpos = replay_get_dword(); > +*recorded = replay_get_qword(); > +*wpos = replay_get_qword(); > for (pos = (*wpos - *recorded + size) % size ; pos != *wpos > ; pos = (pos + 1) % size) { > left = replay_get_qword(); Please also increment REPLAY_VERSION in replay.c It is required because log format is changed and newer version should not be able reading old logs. Pavel Dovgalyuk
[Qemu-devel] [PATCH 1/1] qdev: rename qdev_create() argument to sync with qdev_try_create()
The second argument used by qdev_create() is typename and 'name' is very confusing. Rename it from 'name' to 'type', which is the same used by qdev_try_create(). Signed-off-by: Dongli Zhang --- hw/core/qdev.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 6b3cc55..1d65e8f 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -113,17 +113,17 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus) /* Create a new device. This only initializes the device state structure and allows properties to be set. The device still needs to be realized. See qdev-core.h. */ -DeviceState *qdev_create(BusState *bus, const char *name) +DeviceState *qdev_create(BusState *bus, const char *type) { DeviceState *dev; -dev = qdev_try_create(bus, name); +dev = qdev_try_create(bus, type); if (!dev) { if (bus) { -error_report("Unknown device '%s' for bus '%s'", name, +error_report("Unknown device '%s' for bus '%s'", type, object_get_typename(OBJECT(bus))); } else { -error_report("Unknown device '%s' for default sysbus", name); +error_report("Unknown device '%s' for default sysbus", type); } abort(); } -- 2.7.4
Re: [Qemu-devel] [PATCH for-4.0 v8 6/7] qemu_thread_create: propagate the error to callers to handle
On 12/24/2018 11:34 AM, Peter Xu wrote: On Fri, Dec 21, 2018 at 05:36:57PM +0800, Fei Li wrote: On 12/19/2018 08:14 PM, Fei Li wrote: On 12/19/2018 06:10 PM, Markus Armbruster wrote: Fei Li writes: On 12/13/2018 03:26 PM, Markus Armbruster wrote: There's a question for David Gibson inline. Please search for /ppc/. Fei Li writes: Make qemu_thread_create() return a Boolean to indicate if it succeeds rather than failing with an error. And add an Error parameter to hold the error message and let the callers handle it. The "rather than failing with an error" is misleading. Before the patch, we report to stderr and abort(). What about: qemu-thread: Make qemu_thread_create() handle errors properly qemu_thread_create() abort()s on error. Not nice. Give it a return value and an Error ** argument, so it can return success / failure. A nice commit-amend! Thanks! Still missing from the commit message then: how you update the callers. Yes, agree. I think the-how should also be noted here, like - propagating the err to callers whose call trace already have the Error paramater; - just add an &error_abort for qemu_thread_create() and make it a "TODO: xxx"; Let's see below. Cc: Markus Armbruster Cc: Daniel P. Berrangé Cc: Dr. David Alan Gilbert Signed-off-by: Fei Li --- cpus.c | 45 - dump.c | 6 +++-- hw/misc/edu.c | 6 +++-- hw/ppc/spapr_hcall.c | 10 +++-- hw/rdma/rdma_backend.c | 4 +++- hw/usb/ccid-card-emulated.c | 16 ++ include/qemu/thread.h | 4 ++-- io/task.c | 3 ++- iothread.c | 16 +- migration/migration.c | 54 + migration/postcopy-ram.c | 14 ++-- migration/ram.c | 40 - migration/savevm.c | 11 ++--- tests/atomic_add-bench.c | 3 ++- tests/iothread.c | 2 +- tests/qht-bench.c | 3 ++- tests/rcutorture.c | 3 ++- tests/test-aio.c | 2 +- tests/test-rcu-list.c | 3 ++- ui/vnc-jobs.c | 17 +- ui/vnc-jobs.h | 2 +- ui/vnc.c | 4 +++- util/compatfd.c | 12 -- util/oslib-posix.c | 17 ++ util/qemu-thread-posix.c | 24 +--- util/qemu-thread-win32.c | 16 ++ util/rcu.c | 3 ++- util/thread-pool.c | 4 +++- 28 files changed, 243 insertions(+), 101 deletions(-) ...snip, and only leave the three uncertain small topics... diff --git a/migration/ram.c b/migration/ram.c index 658dfa88a3..6e0cccf066 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -473,6 +473,7 @@ static void compress_threads_save_cleanup(void) static int compress_threads_save_setup(void) { int i, thread_count; + Error *local_err = NULL; if (!migrate_use_compression()) { return 0; @@ -502,9 +503,12 @@ static int compress_threads_save_setup(void) comp_param[i].quit = false; qemu_mutex_init(&comp_param[i].mutex); qemu_cond_init(&comp_param[i].cond); - qemu_thread_create(compress_threads + i, "compress", - do_data_compress, comp_param + i, - QEMU_THREAD_JOINABLE); + if (!qemu_thread_create(compress_threads + i, "compress", + do_data_compress, comp_param + i, + QEMU_THREAD_JOINABLE, &local_err)) { + error_reportf_err(local_err, "failed to create do_data_compress: "); + goto exit; [1] + } } return 0; Reviewing the migration changes is getting tiresome... Yes, indeed, the migration involves a lot! Thanks so much for helping to review! Is reporting the error appropriate here, and why? I think the qemu monitor should display the obvious and exact failing reason for administrators, esp considering that qemu_thread_create() itself does not print any message thus we have no idea which direct function fails if gdb is not enabled. IOW, I think David's answer to that ppc's error_reportf_err() also apply here: "The error returns are for the guest, the reported errors are for the guest administrator or management layers." There could well be an issue with the "management layers" part. Should this error be sent to the management layer via QMP somehow? Migration maintainers should be able to assist with this question. Kindly ping migration maintainers. :) I think both the maintainers are on holiday so possibly there won't be any reply from them this week... :) Regarding to error reports of migration via QMP layer, please have a look at d59ce6f344 ("migr
[Qemu-devel] live migration
Hello, I have a question I would like to ask. If I add the -incoming parameter when starting the qemu virtual machine, the virtual machine will block all the time, waiting for the migration connection request to arrive. I want to modify the time of this blocking wait, how should I modify the source code?