All of lore.kernel.org
 help / color / mirror / Atom feed
* [PULL 00/21] Misc patches for 2022-09-19
@ 2022-09-19 17:34 Paolo Bonzini
  2022-09-19 17:34 ` [PULL 01/21] KVM: use store-release to mark dirty pages as harvested Paolo Bonzini
                   ` (21 more replies)
  0 siblings, 22 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

The following changes since commit d29201ff34a135cdfc197f4413c1c5047e4f58bb:

  Merge tag 'pull-hmp-20220915a' of https://gitlab.com/dagrh/qemu into staging (2022-09-17 10:31:11 -0400)

are available in the Git repository at:

  https://gitlab.com/bonzini/qemu.git tags/for-upstream

for you to fetch changes up to df22fbb751dc72f321218c3fb192730a47ad59a9:

  qboot: update to latest submodule (2022-09-19 15:40:51 +0200)

----------------------------------------------------------------
* add help option for -audio and -audiodev
* another missing memory barrier for dirty pages
* target/i386: Raise #GP on unaligned m128 accesses
* coverity fixes + improvements to components
* add MMX and 3DNow! tests
* SSE4a fixes
* target/i386: TCG translation cleanups
* update qboot submodule

----------------------------------------------------------------
Claudio Fontana (1):
      audio: add help option for -audio and -audiodev

Paolo Bonzini (20):
      KVM: use store-release to mark dirty pages as harvested
      target/i386: Raise #GP on unaligned m128 accesses when required.
      kvm: fix memory leak on failure to read stats descriptors
      spapr_pci: fix leak in spapr_phb_vfio_get_loc_code
      coverity: add new RISC-V component
      coverity: put NUBus under m68k component
      smbios: sanitize type from external type before checking have_fields_bitmap
      tests: unit: simplify test-visitor-serialization list tests
      tests: test-qga: close socket on failure to connect
      tests: unit: add NULL-pointer check
      tests/tcg: i386: fix typos in 3DNow! instructions
      tests/tcg: i386: add MMX and 3DNow! tests
      tests/tcg: refine MMX support in SSE tests
      tests/tcg: remove old SSE tests
      target/i386: correctly mask SSE4a bit indices in register operands
      target/i386: fix INSERTQ implementation
      target/i386: REPZ and REPNZ are mutually exclusive
      target/i386: introduce insn_get_addr
      build: remove extra parentheses causing missing rebuilds
      qboot: update to latest submodule

 Makefile                                |   2 +-
 accel/kvm/kvm-all.c                     |  27 +-
 audio/audio.c                           |  19 ++
 audio/audio.h                           |   1 +
 hw/ppc/spapr_pci.c                      |   1 +
 hw/smbios/smbios.c                      |  14 +-
 qemu-options.hx                         |  10 +-
 roms/qboot                              |   2 +-
 scripts/coverity-scan/COMPONENTS.md     |   5 +-
 softmmu/vl.c                            |   9 +-
 target/i386/ops_sse.h                   |  12 +-
 target/i386/ops_sse_header.h            |   2 +-
 target/i386/tcg/excp_helper.c           |  13 +
 target/i386/tcg/helper-tcg.h            |  28 +-
 target/i386/tcg/sysemu/excp_helper.c    |   8 +
 target/i386/tcg/tcg-cpu.c               |   2 +
 target/i386/tcg/translate.c             |  95 ++++--
 target/i386/tcg/user/excp_helper.c      |   7 +
 tests/tcg/i386/Makefile.target          |  24 +-
 tests/tcg/i386/test-3dnow.c             |   3 +
 tests/tcg/i386/test-avx.py              |  33 +-
 tests/tcg/i386/test-i386.c              | 573 --------------------------------
 tests/tcg/i386/test-mmx.c               | 315 ++++++++++++++++++
 tests/tcg/i386/test-mmx.py              | 244 ++++++++++++++
 tests/tcg/i386/x86.csv                  |   4 +-
 tests/tcg/x86_64/Makefile.target        |   1 -
 tests/unit/check-block-qdict.c          |   2 +-
 tests/unit/test-qga.c                   |   1 +
 tests/unit/test-visitor-serialization.c | 157 ++++-----
 29 files changed, 870 insertions(+), 744 deletions(-)
 create mode 100644 tests/tcg/i386/test-3dnow.c
 create mode 100644 tests/tcg/i386/test-mmx.c
 create mode 100755 tests/tcg/i386/test-mmx.py
-- 
2.37.2



^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PULL 01/21] KVM: use store-release to mark dirty pages as harvested
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 02/21] target/i386: Raise #GP on unaligned m128 accesses when required Paolo Bonzini
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gavin Shan, Peter Xu, Philippe Mathieu-Daudé

The following scenario can happen if QEMU sets more RESET flags while
the KVM_RESET_DIRTY_RINGS ioctl is ongoing on another host CPU:

    CPU0                     CPU1               CPU2
    ------------------------ ------------------ ------------------------
                                                fill gfn0
                                                store-rel flags for gfn0
                                                fill gfn1
                                                store-rel flags for gfn1
    load-acq flags for gfn0
    set RESET for gfn0
    load-acq flags for gfn1
    set RESET for gfn1
    do ioctl! ----------->
                             ioctl(RESET_RINGS)
                                                fill gfn2
                                                store-rel flags for gfn2
    load-acq flags for gfn2
    set RESET for gfn2
                             process gfn0
                             process gfn1
                             process gfn2
    do ioctl!
    etc.

The three load-acquire in CPU0 synchronize with the three store-release
in CPU2, but CPU0 and CPU1 are only synchronized up to gfn1 and CPU1
may miss gfn2's fields other than flags.

The kernel must be able to cope with invalid values of the fields, and
userspace *will* invoke the ioctl once more.  However, once the RESET flag
is cleared on gfn2, it is lost forever, therefore in the above scenario
CPU1 must read the correct value of gfn2's fields.

Therefore RESET must be set with a store-release, that will synchronize
with KVM's load-acquire in CPU1.

Cc: Gavin Shan <gshan@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 accel/kvm/kvm-all.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 136c8eaed3..7c8ce18bdd 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -728,7 +728,23 @@ static bool dirty_gfn_is_dirtied(struct kvm_dirty_gfn *gfn)
 
 static void dirty_gfn_set_collected(struct kvm_dirty_gfn *gfn)
 {
-    gfn->flags = KVM_DIRTY_GFN_F_RESET;
+    /*
+     * Use a store-release so that the CPU that executes KVM_RESET_DIRTY_RINGS
+     * sees the full content of the ring:
+     *
+     * CPU0                     CPU1                         CPU2
+     * ------------------------------------------------------------------------------
+     *                                                       fill gfn0
+     *                                                       store-rel flags for gfn0
+     * load-acq flags for gfn0
+     * store-rel RESET for gfn0
+     *                          ioctl(RESET_RINGS)
+     *                            load-acq flags for gfn0
+     *                            check if flags have RESET
+     *
+     * The synchronization goes from CPU2 to CPU0 to CPU1.
+     */
+    qatomic_store_release(&gfn->flags, KVM_DIRTY_GFN_F_RESET);
 }
 
 /*
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 02/21] target/i386: Raise #GP on unaligned m128 accesses when required.
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
  2022-09-19 17:34 ` [PULL 01/21] KVM: use store-release to mark dirty pages as harvested Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 03/21] kvm: fix memory leak on failure to read stats descriptors Paolo Bonzini
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson, Ricky Zhou

Many instructions which load/store 128-bit values are supposed to
raise #GP when the memory operand isn't 16-byte aligned. This includes:
 - Instructions explicitly requiring memory alignment (Exceptions Type 1
   in the "AVX and SSE Instruction Exception Specification" section of
   the SDM)
 - Legacy SSE instructions that load/store 128-bit values (Exceptions
   Types 2 and 4).

This change sets MO_ALIGN_16 on 128-bit memory accesses that require
16-byte alignment. It adds cpu_record_sigbus and cpu_do_unaligned_access
hooks that simulate a #GP exception in qemu-user and qemu-system,
respectively.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/217
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Ricky Zhou <ricky@rzhou.org>
Message-Id: <20220830034816.57091-2-ricky@rzhou.org>
[Do not bother checking PREFIX_VEX, since AVX is not supported. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/tcg/excp_helper.c        | 13 +++++++++
 target/i386/tcg/helper-tcg.h         | 28 +++++++++++-------
 target/i386/tcg/sysemu/excp_helper.c |  8 ++++++
 target/i386/tcg/tcg-cpu.c            |  2 ++
 target/i386/tcg/translate.c          | 43 ++++++++++++++++------------
 target/i386/tcg/user/excp_helper.c   |  7 +++++
 6 files changed, 72 insertions(+), 29 deletions(-)

diff --git a/target/i386/tcg/excp_helper.c b/target/i386/tcg/excp_helper.c
index c1ffa1c0ef..7c3c8dc7fe 100644
--- a/target/i386/tcg/excp_helper.c
+++ b/target/i386/tcg/excp_helper.c
@@ -140,3 +140,16 @@ G_NORETURN void raise_exception_ra(CPUX86State *env, int exception_index,
 {
     raise_interrupt2(env, exception_index, 0, 0, 0, retaddr);
 }
+
+G_NORETURN void handle_unaligned_access(CPUX86State *env, vaddr vaddr,
+                                        MMUAccessType access_type,
+                                        uintptr_t retaddr)
+{
+    /*
+     * Unaligned accesses are currently only triggered by SSE/AVX
+     * instructions that impose alignment requirements on memory
+     * operands. These instructions raise #GP(0) upon accessing an
+     * unaligned address.
+     */
+    raise_exception_ra(env, EXCP0D_GPF, retaddr);
+}
diff --git a/target/i386/tcg/helper-tcg.h b/target/i386/tcg/helper-tcg.h
index 34167e2e29..cd1723389a 100644
--- a/target/i386/tcg/helper-tcg.h
+++ b/target/i386/tcg/helper-tcg.h
@@ -42,17 +42,6 @@ void x86_cpu_do_interrupt(CPUState *cpu);
 bool x86_cpu_exec_interrupt(CPUState *cpu, int int_req);
 #endif
 
-/* helper.c */
-#ifdef CONFIG_USER_ONLY
-void x86_cpu_record_sigsegv(CPUState *cs, vaddr addr,
-                            MMUAccessType access_type,
-                            bool maperr, uintptr_t ra);
-#else
-bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
-                      MMUAccessType access_type, int mmu_idx,
-                      bool probe, uintptr_t retaddr);
-#endif
-
 void breakpoint_handler(CPUState *cs);
 
 /* n must be a constant to be efficient */
@@ -78,6 +67,23 @@ G_NORETURN void raise_exception_err_ra(CPUX86State *env, int exception_index,
                                        int error_code, uintptr_t retaddr);
 G_NORETURN void raise_interrupt(CPUX86State *nenv, int intno, int is_int,
                                 int error_code, int next_eip_addend);
+G_NORETURN void handle_unaligned_access(CPUX86State *env, vaddr vaddr,
+                                        MMUAccessType access_type,
+                                        uintptr_t retaddr);
+#ifdef CONFIG_USER_ONLY
+void x86_cpu_record_sigsegv(CPUState *cs, vaddr addr,
+                            MMUAccessType access_type,
+                            bool maperr, uintptr_t ra);
+void x86_cpu_record_sigbus(CPUState *cs, vaddr addr,
+                           MMUAccessType access_type, uintptr_t ra);
+#else
+bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+                      MMUAccessType access_type, int mmu_idx,
+                      bool probe, uintptr_t retaddr);
+G_NORETURN void x86_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
+                                            MMUAccessType access_type,
+                                            int mmu_idx, uintptr_t retaddr);
+#endif
 
 /* cc_helper.c */
 extern const uint8_t parity_table[256];
diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c
index 48feba7e75..796dc2a1f3 100644
--- a/target/i386/tcg/sysemu/excp_helper.c
+++ b/target/i386/tcg/sysemu/excp_helper.c
@@ -439,3 +439,11 @@ bool x86_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
     }
     return true;
 }
+
+G_NORETURN void x86_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
+                                            MMUAccessType access_type,
+                                            int mmu_idx, uintptr_t retaddr)
+{
+    X86CPU *cpu = X86_CPU(cs);
+    handle_unaligned_access(&cpu->env, vaddr, access_type, retaddr);
+}
diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
index 6fdfdf9598..d3c2b8fb49 100644
--- a/target/i386/tcg/tcg-cpu.c
+++ b/target/i386/tcg/tcg-cpu.c
@@ -75,10 +75,12 @@ static const struct TCGCPUOps x86_tcg_ops = {
 #ifdef CONFIG_USER_ONLY
     .fake_user_interrupt = x86_cpu_do_interrupt,
     .record_sigsegv = x86_cpu_record_sigsegv,
+    .record_sigbus = x86_cpu_record_sigbus,
 #else
     .tlb_fill = x86_cpu_tlb_fill,
     .do_interrupt = x86_cpu_do_interrupt,
     .cpu_exec_interrupt = x86_cpu_exec_interrupt,
+    .do_unaligned_access = x86_cpu_do_unaligned_access,
     .debug_excp_handler = breakpoint_handler,
     .debug_check_breakpoint = x86_debug_check_breakpoint,
 #endif /* !CONFIG_USER_ONLY */
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index d6420df31d..8ec91d17af 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2738,21 +2738,23 @@ static inline void gen_stq_env_A0(DisasContext *s, int offset)
     tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ);
 }
 
-static inline void gen_ldo_env_A0(DisasContext *s, int offset)
+static inline void gen_ldo_env_A0(DisasContext *s, int offset, bool align)
 {
     int mem_index = s->mem_index;
-    tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEUQ);
+    tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index,
+                        MO_LEUQ | (align ? MO_ALIGN_16 : 0));
     tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
     tcg_gen_addi_tl(s->tmp0, s->A0, 8);
     tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
     tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
 }
 
-static inline void gen_sto_env_A0(DisasContext *s, int offset)
+static inline void gen_sto_env_A0(DisasContext *s, int offset, bool align)
 {
     int mem_index = s->mem_index;
     tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
-    tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index, MO_LEUQ);
+    tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index,
+                        MO_LEUQ | (align ? MO_ALIGN_16 : 0));
     tcg_gen_addi_tl(s->tmp0, s->A0, 8);
     tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
     tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
@@ -3131,7 +3133,7 @@ static const struct SSEOpHelper_table6 sse_op_table6[256] = {
     [0x25] = UNARY_OP(pmovsxdq, SSE41, SSE_OPF_MMX),
     [0x28] = BINARY_OP(pmuldq, SSE41, SSE_OPF_MMX),
     [0x29] = BINARY_OP(pcmpeqq, SSE41, SSE_OPF_MMX),
-    [0x2a] = SPECIAL_OP(SSE41), /* movntqda */
+    [0x2a] = SPECIAL_OP(SSE41), /* movntdqa */
     [0x2b] = BINARY_OP(packusdw, SSE41, SSE_OPF_MMX),
     [0x30] = UNARY_OP(pmovzxbw, SSE41, SSE_OPF_MMX),
     [0x31] = UNARY_OP(pmovzxbd, SSE41, SSE_OPF_MMX),
@@ -3294,17 +3296,17 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x1e7: /* movntdq */
         case 0x02b: /* movntps */
-        case 0x12b: /* movntps */
+        case 0x12b: /* movntpd */
             if (mod == 3)
                 goto illegal_op;
             gen_lea_modrm(env, s, modrm);
-            gen_sto_env_A0(s, ZMM_OFFSET(reg));
+            gen_sto_env_A0(s, ZMM_OFFSET(reg), true);
             break;
         case 0x3f0: /* lddqu */
             if (mod == 3)
                 goto illegal_op;
             gen_lea_modrm(env, s, modrm);
-            gen_ldo_env_A0(s, ZMM_OFFSET(reg));
+            gen_ldo_env_A0(s, ZMM_OFFSET(reg), false);
             break;
         case 0x22b: /* movntss */
         case 0x32b: /* movntsd */
@@ -3373,7 +3375,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x26f: /* movdqu xmm, ea */
             if (mod != 3) {
                 gen_lea_modrm(env, s, modrm);
-                gen_ldo_env_A0(s, ZMM_OFFSET(reg));
+                gen_ldo_env_A0(s, ZMM_OFFSET(reg),
+                               /* movaps, movapd, movdqa */
+                               b == 0x028 || b == 0x128 || b == 0x16f);
             } else {
                 rm = (modrm & 7) | REX_B(s);
                 gen_op_movo(s, ZMM_OFFSET(reg), ZMM_OFFSET(rm));
@@ -3432,7 +3436,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x212: /* movsldup */
             if (mod != 3) {
                 gen_lea_modrm(env, s, modrm);
-                gen_ldo_env_A0(s, ZMM_OFFSET(reg));
+                gen_ldo_env_A0(s, ZMM_OFFSET(reg), true);
             } else {
                 rm = (modrm & 7) | REX_B(s);
                 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)),
@@ -3474,7 +3478,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x216: /* movshdup */
             if (mod != 3) {
                 gen_lea_modrm(env, s, modrm);
-                gen_ldo_env_A0(s, ZMM_OFFSET(reg));
+                gen_ldo_env_A0(s, ZMM_OFFSET(reg), true);
             } else {
                 rm = (modrm & 7) | REX_B(s);
                 gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)),
@@ -3568,7 +3572,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x27f: /* movdqu ea, xmm */
             if (mod != 3) {
                 gen_lea_modrm(env, s, modrm);
-                gen_sto_env_A0(s, ZMM_OFFSET(reg));
+                gen_sto_env_A0(s, ZMM_OFFSET(reg),
+                               /* movaps, movapd, movdqa */
+                               b == 0x029 || b == 0x129 || b == 0x17f);
             } else {
                 rm = (modrm & 7) | REX_B(s);
                 gen_op_movo(s, ZMM_OFFSET(rm), ZMM_OFFSET(reg));
@@ -3724,7 +3730,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             if (mod != 3) {
                 gen_lea_modrm(env, s, modrm);
                 op2_offset = offsetof(CPUX86State,xmm_t0);
-                gen_ldo_env_A0(s, op2_offset);
+                /* FIXME: should be 64-bit access if b1 == 0.  */
+                gen_ldo_env_A0(s, op2_offset, !!b1);
             } else {
                 rm = (modrm & 7) | REX_B(s);
                 op2_offset = ZMM_OFFSET(rm);
@@ -3913,11 +3920,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                         tcg_gen_st16_tl(s->tmp0, cpu_env, op2_offset +
                                         offsetof(ZMMReg, ZMM_W(0)));
                         break;
-                    case 0x2a:            /* movntqda */
-                        gen_ldo_env_A0(s, op1_offset);
+                    case 0x2a:            /* movntdqa */
+                        gen_ldo_env_A0(s, op1_offset, true);
                         return;
                     default:
-                        gen_ldo_env_A0(s, op2_offset);
+                        gen_ldo_env_A0(s, op2_offset, true);
                     }
                 }
                 if (!op6->fn[b1].op1) {
@@ -4499,7 +4506,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             } else {
                 op2_offset = offsetof(CPUX86State, xmm_t0);
                 gen_lea_modrm(env, s, modrm);
-                gen_ldo_env_A0(s, op2_offset);
+                gen_ldo_env_A0(s, op2_offset, true);
             }
 
             val = x86_ldub_code(env, s);
@@ -4606,7 +4613,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     break;
                 default:
                     /* 128 bit access */
-                    gen_ldo_env_A0(s, op2_offset);
+                    gen_ldo_env_A0(s, op2_offset, true);
                     break;
                 }
             } else {
diff --git a/target/i386/tcg/user/excp_helper.c b/target/i386/tcg/user/excp_helper.c
index cd507e2a1b..b3bdb7831a 100644
--- a/target/i386/tcg/user/excp_helper.c
+++ b/target/i386/tcg/user/excp_helper.c
@@ -48,3 +48,10 @@ void x86_cpu_record_sigsegv(CPUState *cs, vaddr addr,
 
     cpu_loop_exit_restore(cs, ra);
 }
+
+void x86_cpu_record_sigbus(CPUState *cs, vaddr addr,
+                           MMUAccessType access_type, uintptr_t ra)
+{
+    X86CPU *cpu = X86_CPU(cs);
+    handle_unaligned_access(&cpu->env, addr, access_type, ra);
+}
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 03/21] kvm: fix memory leak on failure to read stats descriptors
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
  2022-09-19 17:34 ` [PULL 01/21] KVM: use store-release to mark dirty pages as harvested Paolo Bonzini
  2022-09-19 17:34 ` [PULL 02/21] target/i386: Raise #GP on unaligned m128 accesses when required Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 04/21] spapr_pci: fix leak in spapr_phb_vfio_get_loc_code Paolo Bonzini
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson

Reported by Coverity as CID 1490142.  Since the size is constant and the
lifetime is the same as the StatsDescriptors struct, embed the struct
directly instead of using a separate allocation.

Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 accel/kvm/kvm-all.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 7c8ce18bdd..5acab1767f 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -3908,7 +3908,7 @@ exit:
 typedef struct StatsDescriptors {
     const char *ident; /* cache key, currently the StatsTarget */
     struct kvm_stats_desc *kvm_stats_desc;
-    struct kvm_stats_header *kvm_stats_header;
+    struct kvm_stats_header kvm_stats_header;
     QTAILQ_ENTRY(StatsDescriptors) next;
 } StatsDescriptors;
 
@@ -3939,7 +3939,7 @@ static StatsDescriptors *find_stats_descriptors(StatsTarget target, int stats_fd
     descriptors = g_new0(StatsDescriptors, 1);
 
     /* Read stats header */
-    kvm_stats_header = g_malloc(sizeof(*kvm_stats_header));
+    kvm_stats_header = &descriptors->kvm_stats_header;
     ret = read(stats_fd, kvm_stats_header, sizeof(*kvm_stats_header));
     if (ret != sizeof(*kvm_stats_header)) {
         error_setg(errp, "KVM stats: failed to read stats header: "
@@ -3964,7 +3964,6 @@ static StatsDescriptors *find_stats_descriptors(StatsTarget target, int stats_fd
         g_free(kvm_stats_desc);
         return NULL;
     }
-    descriptors->kvm_stats_header = kvm_stats_header;
     descriptors->kvm_stats_desc = kvm_stats_desc;
     descriptors->ident = ident;
     QTAILQ_INSERT_TAIL(&stats_descriptors, descriptors, next);
@@ -3989,7 +3988,7 @@ static void query_stats(StatsResultList **result, StatsTarget target,
         return;
     }
 
-    kvm_stats_header = descriptors->kvm_stats_header;
+    kvm_stats_header = &descriptors->kvm_stats_header;
     kvm_stats_desc = descriptors->kvm_stats_desc;
     size_desc = sizeof(*kvm_stats_desc) + kvm_stats_header->name_size;
 
@@ -4054,7 +4053,7 @@ static void query_stats_schema(StatsSchemaList **result, StatsTarget target,
         return;
     }
 
-    kvm_stats_header = descriptors->kvm_stats_header;
+    kvm_stats_header = &descriptors->kvm_stats_header;
     kvm_stats_desc = descriptors->kvm_stats_desc;
     size_desc = sizeof(*kvm_stats_desc) + kvm_stats_header->name_size;
 
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 04/21] spapr_pci: fix leak in spapr_phb_vfio_get_loc_code
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (2 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 03/21] kvm: fix memory leak on failure to read stats descriptors Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 05/21] coverity: add new RISC-V component Paolo Bonzini
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

Overwriting "path" in the second call to g_strdup_printf() causes a memory leak,
even if the variable itself is g_autofree.

Reported by Coverity as CID 1460454.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/ppc/spapr_pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 67e9d468aa..57c8a4f085 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -800,6 +800,7 @@ static char *spapr_phb_vfio_get_loc_code(SpaprPhbState *sphb,  PCIDevice *pdev)
     }
 
     /* Construct and read from host device tree the loc-code */
+    g_free(path);
     path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", devspec);
     if (!g_file_get_contents(path, &buf, NULL, NULL)) {
         return NULL;
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 05/21] coverity: add new RISC-V component
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (3 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 04/21] spapr_pci: fix leak in spapr_phb_vfio_get_loc_code Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 06/21] coverity: put NUBus under m68k component Paolo Bonzini
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 scripts/coverity-scan/COMPONENTS.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/scripts/coverity-scan/COMPONENTS.md b/scripts/coverity-scan/COMPONENTS.md
index 3aad9cdfaf..fc1608932e 100644
--- a/scripts/coverity-scan/COMPONENTS.md
+++ b/scripts/coverity-scan/COMPONENTS.md
@@ -146,3 +146,6 @@ tests
 
 loongarch
   ~ (/qemu)?((/include)?/hw/(loongarch/.*|.*/loongarch.*)|/target/loongarch/.*)
+
+riscv
+  ~ (/qemu)?((/include)?/hw/riscv/.*|/target/riscv/.*|/hw/.*/(riscv_|ibex_|sifive_).*)
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 06/21] coverity: put NUBus under m68k component
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (4 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 05/21] coverity: add new RISC-V component Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 07/21] smbios: sanitize type from external type before checking have_fields_bitmap Paolo Bonzini
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

It is only used by the Q800 emulation, so put it under that architecture.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 scripts/coverity-scan/COMPONENTS.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/coverity-scan/COMPONENTS.md b/scripts/coverity-scan/COMPONENTS.md
index fc1608932e..0e6ab4936e 100644
--- a/scripts/coverity-scan/COMPONENTS.md
+++ b/scripts/coverity-scan/COMPONENTS.md
@@ -22,7 +22,7 @@ i386
   ~ (/qemu)?((/include)?/hw/i386/.*|/target/i386/.*|/hw/intc/[^/]*apic[^/]*\.c)
 
 m68k
-  ~ (/qemu)?((/include)?/hw/m68k/.*|/target/m68k/.*|(/include)?/hw(/.*)?/mcf.*)
+  ~ (/qemu)?((/include)?/hw/m68k/.*|/target/m68k/.*|(/include)?/hw(/.*)?/mcf.*|(/include)?/hw/nubus/.*)
 
 microblaze
   ~ (/qemu)?((/include)?/hw/microblaze/.*|/target/microblaze/.*)
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 07/21] smbios: sanitize type from external type before checking have_fields_bitmap
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (5 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 06/21] coverity: put NUBus under m68k component Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 08/21] tests: unit: simplify test-visitor-serialization list tests Paolo Bonzini
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

test_bit uses header->type as an offset; if the file incorrectly specifies a
type greater than 127, smbios_entry_add will read and write garbage.

To fix this, just pass the smbios data through, assuming the user knows what
to do.  Reported by Coverity as CID 1487255.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/smbios/smbios.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index 60349ee402..4c9f664830 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -1205,13 +1205,15 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
             return;
         }
 
-        if (test_bit(header->type, have_fields_bitmap)) {
-            error_setg(errp,
-                       "can't load type %d struct, fields already specified!",
-                       header->type);
-            return;
+        if (header->type <= SMBIOS_MAX_TYPE) {
+            if (test_bit(header->type, have_fields_bitmap)) {
+                error_setg(errp,
+                           "can't load type %d struct, fields already specified!",
+                           header->type);
+                return;
+            }
+            set_bit(header->type, have_binfile_bitmap);
         }
-        set_bit(header->type, have_binfile_bitmap);
 
         if (header->type == 4) {
             smbios_type4_count++;
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 08/21] tests: unit: simplify test-visitor-serialization list tests
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (6 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 07/21] smbios: sanitize type from external type before checking have_fields_bitmap Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 09/21] tests: test-qga: close socket on failure to connect Paolo Bonzini
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

test-visitor-serialization list tests is using an "if" to pick either the first
element of the list or the next one.  This was done presumably to mimic the
code that creates the list, which has to fill in either the head pointer
or the next pointer of the last element.  However, the code in the insert
phase is a pretty standard singly-linked list insertion, while the one
in the visit phase looks weird and even looks at the first item twice:
this is confusing because the test puts in 32 items and finishes with
an assertion that i == 33.

So, move the "else" step in a separate switch statement, and change
the do...while loop to a while, because cur_head has already been
initialized beforehand.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 tests/unit/test-visitor-serialization.c | 157 +++++++++++-------------
 1 file changed, 69 insertions(+), 88 deletions(-)

diff --git a/tests/unit/test-visitor-serialization.c b/tests/unit/test-visitor-serialization.c
index 907263d030..667e8fed82 100644
--- a/tests/unit/test-visitor-serialization.c
+++ b/tests/unit/test-visitor-serialization.c
@@ -427,131 +427,117 @@ static void test_primitive_lists(gconstpointer opaque)
     ops->deserialize((void **)&pl_copy_ptr, serialize_data,
                      visit_primitive_list, &error_abort);
 
-    i = 0;
+
+    switch (pl_copy.type) {
+    case PTYPE_STRING:
+        cur_head = pl_copy.value.strings;
+        break;
+    case PTYPE_INTEGER:
+        cur_head = pl_copy.value.integers;
+        break;
+    case PTYPE_S8:
+        cur_head = pl_copy.value.s8_integers;
+        break;
+    case PTYPE_S16:
+        cur_head = pl_copy.value.s16_integers;
+        break;
+    case PTYPE_S32:
+        cur_head = pl_copy.value.s32_integers;
+        break;
+    case PTYPE_S64:
+        cur_head = pl_copy.value.s64_integers;
+        break;
+    case PTYPE_U8:
+        cur_head = pl_copy.value.u8_integers;
+        break;
+    case PTYPE_U16:
+        cur_head = pl_copy.value.u16_integers;
+        break;
+    case PTYPE_U32:
+        cur_head = pl_copy.value.u32_integers;
+        break;
+    case PTYPE_U64:
+        cur_head = pl_copy.value.u64_integers;
+        break;
+    case PTYPE_NUMBER:
+        cur_head = pl_copy.value.numbers;
+        break;
+    case PTYPE_BOOLEAN:
+        cur_head = pl_copy.value.booleans;
+        break;
+    default:
+        g_assert_not_reached();
+    }
 
     /* compare our deserialized list of primitives to the original */
-    do {
+    i = 0;
+    while (cur_head) {
         switch (pl_copy.type) {
         case PTYPE_STRING: {
-            strList *ptr;
-            if (cur_head) {
-                ptr = cur_head;
-                cur_head = ptr->next;
-            } else {
-                cur_head = ptr = pl_copy.value.strings;
-            }
+            strList *ptr = cur_head;
+            cur_head = ptr->next;
             g_assert_cmpstr(pt->value.string, ==, ptr->value);
             break;
         }
         case PTYPE_INTEGER: {
-            intList *ptr;
-            if (cur_head) {
-                ptr = cur_head;
-                cur_head = ptr->next;
-            } else {
-                cur_head = ptr = pl_copy.value.integers;
-            }
+            intList *ptr = cur_head;
+            cur_head = ptr->next;
             g_assert_cmpint(pt->value.integer, ==, ptr->value);
             break;
         }
         case PTYPE_S8: {
-            int8List *ptr;
-            if (cur_head) {
-                ptr = cur_head;
-                cur_head = ptr->next;
-            } else {
-                cur_head = ptr = pl_copy.value.s8_integers;
-            }
+            int8List *ptr = cur_head;
+            cur_head = ptr->next;
             g_assert_cmpint(pt->value.s8, ==, ptr->value);
             break;
         }
         case PTYPE_S16: {
-            int16List *ptr;
-            if (cur_head) {
-                ptr = cur_head;
-                cur_head = ptr->next;
-            } else {
-                cur_head = ptr = pl_copy.value.s16_integers;
-            }
+            int16List *ptr = cur_head;
+            cur_head = ptr->next;
             g_assert_cmpint(pt->value.s16, ==, ptr->value);
             break;
         }
         case PTYPE_S32: {
-            int32List *ptr;
-            if (cur_head) {
-                ptr = cur_head;
-                cur_head = ptr->next;
-            } else {
-                cur_head = ptr = pl_copy.value.s32_integers;
-            }
+            int32List *ptr = cur_head;
+            cur_head = ptr->next;
             g_assert_cmpint(pt->value.s32, ==, ptr->value);
             break;
         }
         case PTYPE_S64: {
-            int64List *ptr;
-            if (cur_head) {
-                ptr = cur_head;
-                cur_head = ptr->next;
-            } else {
-                cur_head = ptr = pl_copy.value.s64_integers;
-            }
+            int64List *ptr = cur_head;
+            cur_head = ptr->next;
             g_assert_cmpint(pt->value.s64, ==, ptr->value);
             break;
         }
         case PTYPE_U8: {
-            uint8List *ptr;
-            if (cur_head) {
-                ptr = cur_head;
-                cur_head = ptr->next;
-            } else {
-                cur_head = ptr = pl_copy.value.u8_integers;
-            }
+            uint8List *ptr = cur_head;
+            cur_head = ptr->next;
             g_assert_cmpint(pt->value.u8, ==, ptr->value);
             break;
         }
         case PTYPE_U16: {
-            uint16List *ptr;
-            if (cur_head) {
-                ptr = cur_head;
-                cur_head = ptr->next;
-            } else {
-                cur_head = ptr = pl_copy.value.u16_integers;
-            }
+            uint16List *ptr = cur_head;
+            cur_head = ptr->next;
             g_assert_cmpint(pt->value.u16, ==, ptr->value);
             break;
         }
         case PTYPE_U32: {
-            uint32List *ptr;
-            if (cur_head) {
-                ptr = cur_head;
-                cur_head = ptr->next;
-            } else {
-                cur_head = ptr = pl_copy.value.u32_integers;
-            }
+            uint32List *ptr = cur_head;
+            cur_head = ptr->next;
             g_assert_cmpint(pt->value.u32, ==, ptr->value);
             break;
         }
         case PTYPE_U64: {
-            uint64List *ptr;
-            if (cur_head) {
-                ptr = cur_head;
-                cur_head = ptr->next;
-            } else {
-                cur_head = ptr = pl_copy.value.u64_integers;
-            }
+            uint64List *ptr = cur_head;
+            cur_head = ptr->next;
             g_assert_cmpint(pt->value.u64, ==, ptr->value);
             break;
         }
         case PTYPE_NUMBER: {
-            numberList *ptr;
             GString *double_expected = g_string_new("");
             GString *double_actual = g_string_new("");
-            if (cur_head) {
-                ptr = cur_head;
-                cur_head = ptr->next;
-            } else {
-                cur_head = ptr = pl_copy.value.numbers;
-            }
+            numberList *ptr = cur_head;
+            cur_head = ptr->next;
             /* we serialize with %f for our reference visitors, so rather than
              * fuzzy floating math to test "equality", just compare the
              * formatted values
@@ -564,13 +550,8 @@ static void test_primitive_lists(gconstpointer opaque)
             break;
         }
         case PTYPE_BOOLEAN: {
-            boolList *ptr;
-            if (cur_head) {
-                ptr = cur_head;
-                cur_head = ptr->next;
-            } else {
-                cur_head = ptr = pl_copy.value.booleans;
-            }
+            boolList *ptr = cur_head;
+            cur_head = ptr->next;
             g_assert_cmpint(!!pt->value.boolean, ==, !!ptr->value);
             break;
         }
@@ -578,9 +559,9 @@ static void test_primitive_lists(gconstpointer opaque)
             g_assert_not_reached();
         }
         i++;
-    } while (cur_head);
+    }
 
-    g_assert_cmpint(i, ==, 33);
+    g_assert_cmpint(i, ==, 32);
 
     ops->cleanup(serialize_data);
     dealloc_helper(&pl, visit_primitive_list, &error_abort);
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 09/21] tests: test-qga: close socket on failure to connect
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (7 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 08/21] tests: unit: simplify test-visitor-serialization list tests Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 10/21] tests: unit: add NULL-pointer check Paolo Bonzini
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

Reported by Coverity as CID 1432543.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 tests/unit/test-qga.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/unit/test-qga.c b/tests/unit/test-qga.c
index a05a4628ed..d27ff94d13 100644
--- a/tests/unit/test-qga.c
+++ b/tests/unit/test-qga.c
@@ -32,6 +32,7 @@ static int connect_qga(char *path)
             g_usleep(G_USEC_PER_SEC);
         }
         if (i++ == 10) {
+            close(s);
             return -1;
         }
     } while (ret == -1);
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 10/21] tests: unit: add NULL-pointer check
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (8 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 09/21] tests: test-qga: close socket on failure to connect Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 11/21] tests/tcg: i386: fix typos in 3DNow! instructions Paolo Bonzini
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

In CID 1432593, Coverity complains that the result of qdict_crumple()
might leak if it is not a dictionary.  This is not a practical concern
since the test would fail immediately with a NULL pointer dereference
in qdict_size().

However, it is not nice to depend on qdict_size() crashing, so add an
explicit assertion that that the crumpled object was indeed a dictionary.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 tests/unit/check-block-qdict.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/unit/check-block-qdict.c b/tests/unit/check-block-qdict.c
index 5a25825093..751c58e737 100644
--- a/tests/unit/check-block-qdict.c
+++ b/tests/unit/check-block-qdict.c
@@ -504,7 +504,7 @@ static void qdict_crumple_test_empty(void)
     src = qdict_new();
 
     dst = qobject_to(QDict, qdict_crumple(src, &error_abort));
-
+    g_assert(dst);
     g_assert_cmpint(qdict_size(dst), ==, 0);
 
     qobject_unref(src);
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 11/21] tests/tcg: i386: fix typos in 3DNow! instructions
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (9 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 10/21] tests: unit: add NULL-pointer check Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 12/21] tests/tcg: i386: add MMX and 3DNow! tests Paolo Bonzini
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 tests/tcg/i386/x86.csv | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/tcg/i386/x86.csv b/tests/tcg/i386/x86.csv
index d5d0c17f1b..c43bf42dd3 100644
--- a/tests/tcg/i386/x86.csv
+++ b/tests/tcg/i386/x86.csv
@@ -1469,16 +1469,16 @@
 "PFCMPEQ mm1, mm2/m64","PFCMPEQ mm2/m64, mm1","pfcmpeq mm2/m64, mm1","0F 0F B0 /r","V","V","3DNOW","amd","rw,r","",""
 "PFCMPGE mm1, mm2/m64","PFCMPGE mm2/m64, mm1","pfcmpge mm2/m64, mm1","0F 0F 90 /r","V","V","3DNOW","amd","rw,r","",""
 "PFCMPGT mm1, mm2/m64","PFCMPGT mm2/m64, mm1","pfcmpgt mm2/m64, mm1","0F 0F A0 /r","V","V","3DNOW","amd","rw,r","",""
-"PFCPIT1 mm1, mm2/m64","PFCPIT1 mm2/m64, mm1","pfcpit1 mm2/m64, mm1","0F 0F A6 /r","V","V","3DNOW","amd","rw,r","",""
 "PFMAX mm1, mm2/m64","PFMAX mm2/m64, mm1","pfmax mm2/m64, mm1","0F 0F A4 /r","V","V","3DNOW","amd","rw,r","",""
 "PFMIN mm1, mm2/m64","PFMIN mm2/m64, mm1","pfmin mm2/m64, mm1","0F 0F 94 /r","V","V","3DNOW","amd","rw,r","",""
 "PFMUL mm1, mm2/m64","PFMUL mm2/m64, mm1","pfmul mm2/m64, mm1","0F 0F B4 /r","V","V","3DNOW","amd","rw,r","",""
 "PFNACC mm1, mm2/m64","PFNACC mm2/m64, mm1","pfnacc mm2/m64, mm1","0F 0F 8A /r","V","V","3DNOW","amd","rw,r","",""
 "PFPNACC mm1, mm2/m64","PFPNACC mm2/m64, mm1","pfpnacc mm2/m64, mm1","0F 0F 8E /r","V","V","3DNOW","amd","rw,r","",""
 "PFRCP mm1, mm2/m64","PFRCP mm2/m64, mm1","pfrcp mm2/m64, mm1","0F 0F 96 /r","V","V","3DNOW","amd","rw,r","",""
+"PFRCPIT1 mm1, mm2/m64","PFRCPIT1 mm2/m64, mm1","pfrcpit1 mm2/m64, mm1","0F 0F A6 /r","V","V","3DNOW","amd","rw,r","",""
 "PFRCPIT2 mm1, mm2/m64","PFRCPIT2 mm2/m64, mm1","pfrcpit2 mm2/m64, mm1","0F 0F B6 /r","V","V","3DNOW","amd","rw,r","",""
 "PFRSQIT1 mm1, mm2/m64","PFRSQIT1 mm2/m64, mm1","pfrsqit1 mm2/m64, mm1","0F 0F A7 /r","V","V","3DNOW","amd","rw,r","",""
-"PFSQRT mm1, mm2/m64","PFSQRT mm2/m64, mm1","pfsqrt mm2/m64, mm1","0F 0F 97 /r","V","V","3DNOW","amd","rw,r","",""
+"PFRSQRT mm1, mm2/m64","PFRSQRT mm2/m64, mm1","pfrsqrt mm2/m64, mm1","0F 0F 97 /r","V","V","3DNOW","amd","rw,r","",""
 "PFSUB mm1, mm2/m64","PFSUB mm2/m64, mm1","pfsub mm2/m64, mm1","0F 0F 9A /r","V","V","3DNOW","amd","rw,r","",""
 "PFSUBR mm1, mm2/m64","PFSUBR mm2/m64, mm1","pfsubr mm2/m64, mm1","0F 0F AA /r","V","V","3DNOW","amd","rw,r","",""
 "PHADDD mm1, mm2/m64","PHADDD mm2/m64, mm1","phaddd mm2/m64, mm1","0F 38 02 /r","V","V","SSSE3","","rw,r","",""
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 12/21] tests/tcg: i386: add MMX and 3DNow! tests
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (10 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 11/21] tests/tcg: i386: fix typos in 3DNow! instructions Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 13/21] tests/tcg: refine MMX support in SSE tests Paolo Bonzini
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

Adjust the test-avx.py generator to produce tests specifically for
MMX and 3DNow.  Using a separate generator introduces some code
duplication, but is a simpler approach because of test-avx's extra
complexity to support 3- and 4-operand AVX instructions.

If needed, a common library can be introduced later.

While at it, for consistency move all the -cpu max rules to the
same place.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 tests/tcg/i386/Makefile.target   |  24 ++-
 tests/tcg/i386/test-3dnow.c      |   3 +
 tests/tcg/i386/test-avx.py       |   1 -
 tests/tcg/i386/test-mmx.c        | 315 +++++++++++++++++++++++++++++++
 tests/tcg/i386/test-mmx.py       | 244 ++++++++++++++++++++++++
 tests/tcg/x86_64/Makefile.target |   1 -
 6 files changed, 583 insertions(+), 5 deletions(-)
 create mode 100644 tests/tcg/i386/test-3dnow.c
 create mode 100644 tests/tcg/i386/test-mmx.c
 create mode 100755 tests/tcg/i386/test-mmx.py

diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target
index be21b81b96..599f192529 100644
--- a/tests/tcg/i386/Makefile.target
+++ b/tests/tcg/i386/Makefile.target
@@ -7,8 +7,8 @@ VPATH 		+= $(I386_SRC)
 
 I386_SRCS=$(notdir $(wildcard $(I386_SRC)/*.c))
 ALL_X86_TESTS=$(I386_SRCS:.c=)
-SKIP_I386_TESTS=test-i386-ssse3 test-avx
-X86_64_TESTS:=$(filter test-i386-bmi2 test-i386-ssse3 test-avx, $(ALL_X86_TESTS))
+SKIP_I386_TESTS=test-i386-ssse3 test-avx test-3dnow test-mmx
+X86_64_TESTS:=$(filter test-i386-bmi2 $(SKIP_I386_TESTS), $(ALL_X86_TESTS))
 
 test-i386-sse-exceptions: CFLAGS += -msse4.1 -mfpmath=sse
 run-test-i386-sse-exceptions: QEMU_OPTS += -cpu max
@@ -82,9 +82,27 @@ run-plugin-sha512-sse-with-%: QEMU_OPTS+=-cpu max
 
 TESTS+=sha512-sse
 
-CLEANFILES += test-avx.h
+CLEANFILES += test-avx.h test-mmx.h test-3dnow.h
+test-3dnow.h: test-mmx.py x86.csv
+	$(PYTHON) $(I386_SRC)/test-mmx.py $(I386_SRC)/x86.csv $@ 3DNOW
+
+test-mmx.h: test-mmx.py x86.csv
+	$(PYTHON) $(I386_SRC)/test-mmx.py $(I386_SRC)/x86.csv $@ MMX SSE SSE2 SSE3 SSSE3
+
 test-avx.h: test-avx.py x86.csv
 	$(PYTHON) $(I386_SRC)/test-avx.py $(I386_SRC)/x86.csv $@
 
+test-3dnow: CFLAGS += -masm=intel -O -I.
+run-test-3dnow: QEMU_OPTS += -cpu max
+run-plugin-test-3dnow: QEMU_OPTS += -cpu max
+test-3dnow: test-3dnow.h
+
+test-mmx: CFLAGS += -masm=intel -O -I.
+run-test-mmx: QEMU_OPTS += -cpu max
+run-plugin-test-mmx: QEMU_OPTS += -cpu max
+test-mmx: test-mmx.h
+
 test-avx: CFLAGS += -masm=intel -O -I.
+run-test-avx: QEMU_OPTS += -cpu max
+run-plugin-test-avx: QEMU_OPTS += -cpu max
 test-avx: test-avx.h
diff --git a/tests/tcg/i386/test-3dnow.c b/tests/tcg/i386/test-3dnow.c
new file mode 100644
index 0000000000..67abc68677
--- /dev/null
+++ b/tests/tcg/i386/test-3dnow.c
@@ -0,0 +1,3 @@
+#define EMMS "femms"
+#define TEST_FILE "test-3dnow.h"
+#include "test-mmx.c"
diff --git a/tests/tcg/i386/test-avx.py b/tests/tcg/i386/test-avx.py
index 6eb455a8b4..2516c66445 100755
--- a/tests/tcg/i386/test-avx.py
+++ b/tests/tcg/i386/test-avx.py
@@ -7,7 +7,6 @@
 from fnmatch import fnmatch
 
 archs = [
-    # TODO: MMX?
     "SSE", "SSE2", "SSE3", "SSSE3", "SSE4_1", "SSE4_2",
 ]
 
diff --git a/tests/tcg/i386/test-mmx.c b/tests/tcg/i386/test-mmx.c
new file mode 100644
index 0000000000..60802067d4
--- /dev/null
+++ b/tests/tcg/i386/test-mmx.c
@@ -0,0 +1,315 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef TEST_FILE
+#define TEST_FILE "test-mmx.h"
+#endif
+#ifndef EMMS
+#define EMMS "emms"
+#endif
+
+typedef void (*testfn)(void);
+
+typedef struct {
+    uint64_t q0, q1;
+} __attribute__((aligned(16))) v2di;
+
+typedef struct {
+    uint64_t mm[8];
+    v2di xmm[8];
+    uint64_t r[16];
+    uint64_t flags;
+    uint32_t ff;
+    uint64_t pad;
+    v2di mem[4];
+    v2di mem0[4];
+} reg_state;
+
+typedef struct {
+    int n;
+    testfn fn;
+    const char *s;
+    reg_state *init;
+} TestDef;
+
+reg_state initI;
+reg_state initF32;
+reg_state initF64;
+
+static void dump_mmx(int n, const uint64_t *r, int ff)
+{
+    if (ff == 32) {
+        float v[2];
+        memcpy(v, r, sizeof(v));
+        printf("MM%d = %016lx %8g %8g\n", n, *r, v[1], v[0]);
+    } else {
+        printf("MM%d = %016lx\n", n, *r);
+    }
+}
+
+static void dump_xmm(const char *name, int n, const v2di *r, int ff)
+{
+    printf("%s%d = %016lx %016lx\n",
+           name, n, r->q1, r->q0);
+    if (ff == 32) {
+        float v[4];
+        memcpy(v, r, sizeof(v));
+        printf(" %8g %8g %8g %8g\n",
+                v[3], v[2], v[1], v[0]);
+    }
+}
+
+static void dump_regs(reg_state *s, int ff)
+{
+    int i;
+
+    for (i = 0; i < 8; i++) {
+        dump_mmx(i, &s->mm[i], ff);
+    }
+    for (i = 0; i < 4; i++) {
+        dump_xmm("mem", i, &s->mem0[i], 0);
+    }
+}
+
+static void compare_state(const reg_state *a, const reg_state *b)
+{
+    int i;
+    for (i = 0; i < 8; i++) {
+        if (a->mm[i] != b->mm[i]) {
+            printf("MM%d = %016lx\n", i, b->mm[i]);
+        }
+    }
+    for (i = 0; i < 16; i++) {
+        if (a->r[i] != b->r[i]) {
+            printf("r%d = %016lx\n", i, b->r[i]);
+        }
+    }
+    for (i = 0; i < 8; i++) {
+        if (memcmp(&a->xmm[i], &b->xmm[i], 8)) {
+            dump_xmm("xmm", i, &b->xmm[i], a->ff);
+        }
+    }
+    for (i = 0; i < 4; i++) {
+        if (memcmp(&a->mem0[i], &a->mem[i], 16)) {
+            dump_xmm("mem", i, &a->mem[i], a->ff);
+        }
+    }
+    if (a->flags != b->flags) {
+        printf("FLAGS = %016lx\n", b->flags);
+    }
+}
+
+#define LOADMM(r, o) "movq " #r ", " #o "[%0]\n\t"
+#define LOADXMM(r, o) "movdqa " #r ", " #o "[%0]\n\t"
+#define STOREMM(r, o) "movq " #o "[%1], " #r "\n\t"
+#define STOREXMM(r, o) "movdqa " #o "[%1], " #r "\n\t"
+#define MMREG(F) \
+    F(mm0, 0x00) \
+    F(mm1, 0x08) \
+    F(mm2, 0x10) \
+    F(mm3, 0x18) \
+    F(mm4, 0x20) \
+    F(mm5, 0x28) \
+    F(mm6, 0x30) \
+    F(mm7, 0x38)
+#define XMMREG(F) \
+    F(xmm0, 0x040) \
+    F(xmm1, 0x050) \
+    F(xmm2, 0x060) \
+    F(xmm3, 0x070) \
+    F(xmm4, 0x080) \
+    F(xmm5, 0x090) \
+    F(xmm6, 0x0a0) \
+    F(xmm7, 0x0b0)
+#define LOADREG(r, o) "mov " #r ", " #o "[rax]\n\t"
+#define STOREREG(r, o) "mov " #o "[rax], " #r "\n\t"
+#define REG(F) \
+    F(rbx, 0xc8) \
+    F(rcx, 0xd0) \
+    F(rdx, 0xd8) \
+    F(rsi, 0xe0) \
+    F(rdi, 0xe8) \
+    F(r8, 0x100) \
+    F(r9, 0x108) \
+    F(r10, 0x110) \
+    F(r11, 0x118) \
+    F(r12, 0x120) \
+    F(r13, 0x128) \
+    F(r14, 0x130) \
+    F(r15, 0x138) \
+
+static void run_test(const TestDef *t)
+{
+    reg_state result;
+    reg_state *init = t->init;
+    memcpy(init->mem, init->mem0, sizeof(init->mem));
+    printf("%5d %s\n", t->n, t->s);
+    asm volatile(
+            MMREG(LOADMM)
+            XMMREG(LOADXMM)
+            "sub rsp, 128\n\t"
+            "push rax\n\t"
+            "push rbx\n\t"
+            "push rcx\n\t"
+            "push rdx\n\t"
+            "push %1\n\t"
+            "push %2\n\t"
+            "mov rax, %0\n\t"
+            "pushf\n\t"
+            "pop rbx\n\t"
+            "shr rbx, 8\n\t"
+            "shl rbx, 8\n\t"
+            "mov rcx, 0x140[rax]\n\t"
+            "and rcx, 0xff\n\t"
+            "or rbx, rcx\n\t"
+            "push rbx\n\t"
+            "popf\n\t"
+            REG(LOADREG)
+            "mov rax, 0xc0[rax]\n\t"
+            "call [rsp]\n\t"
+            "mov [rsp], rax\n\t"
+            "mov rax, 8[rsp]\n\t"
+            REG(STOREREG)
+            "mov rbx, [rsp]\n\t"
+            "mov 0xc0[rax], rbx\n\t"
+            "mov rbx, 0\n\t"
+            "mov 0xf0[rax], rbx\n\t"
+            "mov 0xf8[rax], rbx\n\t"
+            "pushf\n\t"
+            "pop rbx\n\t"
+            "and rbx, 0xff\n\t"
+            "mov 0x140[rax], rbx\n\t"
+            "add rsp, 16\n\t"
+            "pop rdx\n\t"
+            "pop rcx\n\t"
+            "pop rbx\n\t"
+            "pop rax\n\t"
+            "add rsp, 128\n\t"
+            MMREG(STOREMM)
+            EMMS "\n\t"
+            XMMREG(STOREXMM)
+            : : "r"(init), "r"(&result), "r"(t->fn)
+            : "memory", "cc",
+            "rsi", "rdi",
+            "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+            "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
+            "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5",
+            "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11",
+            "xmm12", "xmm13", "xmm14", "xmm15"
+            );
+    compare_state(init, &result);
+}
+
+#define TEST(n, cmd, type) \
+static void __attribute__((naked)) test_##n(void) \
+{ \
+    asm volatile(cmd); \
+    asm volatile("ret"); \
+}
+#include TEST_FILE
+
+
+static const TestDef test_table[] = {
+#define TEST(n, cmd, type) {n, test_##n, cmd, &init##type},
+#include TEST_FILE
+    {-1, NULL, "", NULL}
+};
+
+static void run_all(void)
+{
+    const TestDef *t;
+    for (t = test_table; t->fn; t++) {
+        run_test(t);
+    }
+}
+
+#define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0]))
+
+float val_f32[] = {2.0, -1.0, 4.8, 0.8, 3, -42.0, 5e6, 7.5, 8.3};
+uint64_t val_i64[] = {
+    0x3d6b3b6a9e4118f2lu, 0x355ae76d2774d78clu,
+    0xd851c54a56bf1f29lu, 0x4a84d1d50bf4c4fflu,
+    0x5826475e2c5fd799lu, 0xfd32edc01243f5e9lu,
+};
+
+v2di deadbeef = {0xa5a5a5a5deadbeefull, 0xa5a5a5a5deadbeefull};
+
+void init_f32reg(uint64_t *r)
+{
+    static int n;
+    float v[2];
+    int i;
+    for (i = 0; i < 2; i++) {
+        v[i] = val_f32[n++];
+        if (n == ARRAY_LEN(val_f32)) {
+            n = 0;
+        }
+    }
+    memcpy(r, v, sizeof(*r));
+}
+
+void init_intreg(uint64_t *r)
+{
+    static uint64_t mask;
+    static int n;
+
+    *r = val_i64[n] ^ mask;
+    n++;
+    if (n == ARRAY_LEN(val_i64)) {
+        n = 0;
+        mask *= 0x104C11DB7;
+    }
+}
+
+static void init_all(reg_state *s)
+{
+    int i;
+
+    for (i = 0; i < 16; i++) {
+        init_intreg(&s->r[i]);
+    }
+    s->r[3] = (uint64_t)&s->mem[0]; /* rdx */
+    s->r[5] = (uint64_t)&s->mem[2]; /* rdi */
+    s->r[6] = 0;
+    s->r[7] = 0;
+    s->flags = 2;
+    for (i = 0; i < 8; i++) {
+        s->xmm[i] = deadbeef;
+        memcpy(&s->mm[i], &s->xmm[i], sizeof(s->mm[i]));
+    }
+    for (i = 0; i < 2; i++) {
+        s->mem0[i] = deadbeef;
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    init_all(&initI);
+    init_intreg(&initI.mm[5]);
+    init_intreg(&initI.mm[6]);
+    init_intreg(&initI.mm[7]);
+    init_intreg(&initI.mem0[1].q0);
+    init_intreg(&initI.mem0[1].q1);
+    printf("Int:\n");
+    dump_regs(&initI, 0);
+
+    init_all(&initF32);
+    init_f32reg(&initF32.mm[5]);
+    init_f32reg(&initF32.mm[6]);
+    init_f32reg(&initF32.mm[7]);
+    init_f32reg(&initF32.mem0[1].q0);
+    init_f32reg(&initF32.mem0[1].q1);
+    initF32.ff = 32;
+    printf("F32:\n");
+    dump_regs(&initF32, 32);
+
+    if (argc > 1) {
+        int n = atoi(argv[1]);
+        run_test(&test_table[n]);
+    } else {
+        run_all();
+    }
+    return 0;
+}
diff --git a/tests/tcg/i386/test-mmx.py b/tests/tcg/i386/test-mmx.py
new file mode 100755
index 0000000000..392315e176
--- /dev/null
+++ b/tests/tcg/i386/test-mmx.py
@@ -0,0 +1,244 @@
+#! /usr/bin/env python3
+
+# Generate test-avx.h from x86.csv
+
+import csv
+import sys
+from fnmatch import fnmatch
+
+ignore = set(["EMMS", "FEMMS", "FISTTP",
+    "LDMXCSR", "VLDMXCSR", "STMXCSR", "VSTMXCSR"])
+
+imask = {
+    'PALIGNR': 0x3f,
+    'PEXTRB': 0x0f,
+    'PEXTRW': 0x07,
+    'PEXTRD': 0x03,
+    'PEXTRQ': 0x01,
+    'PINSRB': 0x0f,
+    'PINSRW': 0x07,
+    'PINSRD': 0x03,
+    'PINSRQ': 0x01,
+    'PSHUF[DW]': 0xff,
+    'PSHUF[LH]W': 0xff,
+    'PS[LR][AL][WDQ]': 0x3f,
+}
+
+def strip_comments(x):
+    for l in x:
+        if l != '' and l[0] != '#':
+            yield l
+
+def reg_w(w):
+    if w == 8:
+        return 'al'
+    elif w == 16:
+        return 'ax'
+    elif w == 32:
+        return 'eax'
+    elif w == 64:
+        return 'rax'
+    raise Exception("bad reg_w %d" % w)
+
+def mem_w(w):
+    if w == 8:
+        t = "BYTE"
+    elif w == 16:
+        t = "WORD"
+    elif w == 32:
+        t = "DWORD"
+    elif w == 64:
+        t = "QWORD"
+    else:
+        raise Exception()
+
+    return t + " PTR 32[rdx]"
+
+class MMArg():
+    isxmm = True
+
+    def __init__(self, mw):
+        if mw not in [0, 32, 64]:
+            raise Exception("Bad /m width: %s" % w)
+        self.mw = mw
+        self.ismem = mw != 0
+    def regstr(self, n):
+        if n < 0:
+            return mem_w(self.mw)
+        else:
+            return "mm%d" % (n, )
+
+def match(op, pattern):
+    return fnmatch(op, pattern)
+
+class ArgImm8u():
+    isxmm = False
+    ismem = False
+    def __init__(self, op):
+        for k, v in imask.items():
+            if match(op, k):
+                self.mask = imask[k];
+                return
+        raise Exception("Unknown immediate")
+    def vals(self):
+        mask = self.mask
+        yield 0
+        n = 0
+        while n != mask:
+            n += 1
+            while (n & ~mask) != 0:
+                n += (n & ~mask)
+            yield n
+
+class ArgRM():
+    isxmm = False
+    def __init__(self, rw, mw):
+        if rw not in [8, 16, 32, 64]:
+            raise Exception("Bad r/w width: %s" % w)
+        if mw not in [0, 8, 16, 32, 64]:
+            raise Exception("Bad r/w width: %s" % w)
+        self.rw = rw
+        self.mw = mw
+        self.ismem = mw != 0
+    def regstr(self, n):
+        if n < 0:
+            return mem_w(self.mw)
+        else:
+            return reg_w(self.rw)
+
+class ArgMem():
+    isxmm = False
+    ismem = True
+    def __init__(self, w):
+        if w not in [8, 16, 32, 64, 128, 256]:
+            raise Exception("Bad mem width: %s" % w)
+        self.w = w
+    def regstr(self, n):
+        return mem_w(self.w)
+
+class SkipInstruction(Exception):
+    pass
+
+def ArgGenerator(arg, op):
+    if arg[:2] == 'mm':
+        if "/" in arg:
+            r, m = arg.split('/')
+            if (m[0] != 'm'):
+                raise Exception("Expected /m: %s", arg)
+            return MMArg(int(m[1:]));
+        else:
+            return MMArg(0);
+    elif arg[:4] == 'imm8':
+        return ArgImm8u(op);
+    elif arg[0] == 'r':
+        if '/m' in arg:
+            r, m = arg.split('/')
+            if (m[0] != 'm'):
+                raise Exception("Expected /m: %s", arg)
+            mw = int(m[1:])
+            if r == 'r':
+                rw = mw
+            else:
+                rw = int(r[1:])
+            return ArgRM(rw, mw)
+
+        return ArgRM(int(arg[1:]), 0);
+    elif arg[0] == 'm':
+        return ArgMem(int(arg[1:]))
+    else:
+        raise SkipInstruction
+
+class InsnGenerator:
+    def __init__(self, op, args):
+        self.op = op
+        if op[0:2] == "PF":
+            self.optype = 'F32'
+        else:
+            self.optype = 'I'
+
+        try:
+            self.args = list(ArgGenerator(a, op) for a in args)
+            if len(self.args) > 0 and self.args[-1] is None:
+                self.args = self.args[:-1]
+        except SkipInstruction:
+            raise
+        except Exception as e:
+            raise Exception("Bad arg %s: %s" % (op, e))
+
+    def gen(self):
+        regs = (5, 6, 7)
+        dest = 4
+
+        nreg = len(self.args)
+        if nreg == 0:
+            yield self.op
+            return
+        if isinstance(self.args[-1], ArgImm8u):
+            nreg -= 1
+            immarg = self.args[-1]
+        else:
+            immarg = None
+        memarg = -1
+        for n, arg in enumerate(self.args):
+            if arg.ismem:
+                memarg = n
+
+        if nreg == 1:
+            regset = [(regs[0],)]
+            if memarg == 0:
+                regset += [(-1,)]
+        elif nreg == 2:
+            regset = [
+                (regs[0], regs[1]),
+                (regs[0], regs[0]),
+                ]
+            if memarg == 0:
+                regset += [(-1, regs[0])]
+            elif memarg == 1:
+                regset += [(dest, -1)]
+        else:
+            raise Exception("Too many regs: %s(%d)" % (self.op, nreg))
+
+        for regv in regset:
+            argstr = []
+            for i in range(nreg):
+                arg = self.args[i]
+                argstr.append(arg.regstr(regv[i]))
+            if immarg is None:
+                yield self.op + ' ' + ','.join(argstr)
+            else:
+                for immval in immarg.vals():
+                    yield self.op + ' ' + ','.join(argstr) + ',' + str(immval)
+
+def split0(s):
+    if s == '':
+        return []
+    return s.split(',')
+
+def main():
+    n = 0
+    if len(sys.argv) <= 3:
+        print("Usage: test-mmx.py x86.csv test-mmx.h CPUID...")
+        exit(1)
+    csvfile = open(sys.argv[1], 'r', newline='')
+    archs = sys.argv[3:]
+    with open(sys.argv[2], "w") as outf:
+        outf.write("// Generated by test-mmx.py. Do not edit.\n")
+        for row in csv.reader(strip_comments(csvfile)):
+            insn = row[0].replace(',', '').split()
+            if insn[0] in ignore:
+                continue
+            cpuid = row[6]
+            if cpuid in archs:
+                try:
+                    g = InsnGenerator(insn[0], insn[1:])
+                    for insn in g.gen():
+                        outf.write('TEST(%d, "%s", %s)\n' % (n, insn, g.optype))
+                        n += 1
+                except SkipInstruction:
+                    pass
+        outf.write("#undef TEST\n")
+        csvfile.close()
+
+if __name__ == "__main__":
+    main()
diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target
index 861a0966f4..6895db1c43 100644
--- a/tests/tcg/x86_64/Makefile.target
+++ b/tests/tcg/x86_64/Makefile.target
@@ -17,7 +17,6 @@ TESTS=$(MULTIARCH_TESTS)
 endif
 
 run-test-i386-ssse3: QEMU_OPTS += -cpu max
-run-test-avx: QEMU_OPTS += -cpu max
 run-plugin-test-i386-ssse3-%: QEMU_OPTS += -cpu max
 
 test-x86_64: LDFLAGS+=-lm -lc
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 13/21] tests/tcg: refine MMX support in SSE tests
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (11 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 12/21] tests/tcg: i386: add MMX and 3DNow! tests Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 14/21] tests/tcg: remove old " Paolo Bonzini
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

Extend the support to memory operands, and skip MMX instructions that
were introduced in SSE times, because they are now covered in test-mmx.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 tests/tcg/i386/test-avx.py | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/tests/tcg/i386/test-avx.py b/tests/tcg/i386/test-avx.py
index 2516c66445..e16a3d8bee 100755
--- a/tests/tcg/i386/test-avx.py
+++ b/tests/tcg/i386/test-avx.py
@@ -103,7 +103,11 @@ def regstr(self, n):
 
 class MMArg():
     isxmm = True
-    ismem = False # TODO
+    def __init__(self, mw):
+        if mw not in [0, 32, 64]:
+            raise Exception("Bad mem width: %s" % mw)
+        self.mw = mw
+        self.ismem = mw != 0
     def regstr(self, n):
         return "mm%d" % (n & 7)
 
@@ -169,6 +173,9 @@ def __init__(self, w):
     def regstr(self, n):
         return mem_w(self.w)
 
+class SkipInstruction(Exception):
+    pass
+
 def ArgGenerator(arg, op):
     if arg[:3] == 'xmm' or arg[:3] == "ymm":
         if "/" in arg:
@@ -179,7 +186,13 @@ def ArgGenerator(arg, op):
         else:
             return XMMArg(arg[0], 0);
     elif arg[:2] == 'mm':
-        return MMArg();
+        if "/" in arg:
+            r, m = arg.split('/')
+            if (m[0] != 'm'):
+                raise Exception("Expected /m: %s", arg)
+            return MMArg(int(m[1:]));
+        else:
+            return MMArg(0);
     elif arg[:4] == 'imm8':
         return ArgImm8u(op);
     elif arg == '<XMM0>':
@@ -217,8 +230,12 @@ def __init__(self, op, args):
 
         try:
             self.args = list(ArgGenerator(a, op) for a in args)
+            if not any((x.isxmm for x in self.args)):
+                raise SkipInstruction
             if len(self.args) > 0 and self.args[-1] is None:
                 self.args = self.args[:-1]
+        except SkipInstruction:
+            raise
         except Exception as e:
             raise Exception("Bad arg %s: %s" % (op, e))
 
@@ -339,10 +356,13 @@ def main():
                 continue
             cpuid = row[6]
             if cpuid in archs:
-                g = InsnGenerator(insn[0], insn[1:])
-                for insn in g.gen():
-                    outf.write('TEST(%d, "%s", %s)\n' % (n, insn, g.optype))
-                    n += 1
+                try:
+                    g = InsnGenerator(insn[0], insn[1:])
+                    for insn in g.gen():
+                        outf.write('TEST(%d, "%s", %s)\n' % (n, insn, g.optype))
+                        n += 1
+                except SkipInstruction:
+                    pass
         outf.write("#undef TEST\n")
         csvfile.close()
 
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 14/21] tests/tcg: remove old SSE tests
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (12 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 13/21] tests/tcg: refine MMX support in SSE tests Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 15/21] audio: add help option for -audio and -audiodev Paolo Bonzini
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

The new testsuite is much more comprehensive, so remove the old one;
it is also buggy (the pinsrw test uses incorrect constraints, with =
instead of +, and the golden output for the fxsave tests differs depending
on how the C library uses SSE and AVX instructions).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 tests/tcg/i386/test-i386.c | 573 -------------------------------------
 1 file changed, 573 deletions(-)

diff --git a/tests/tcg/i386/test-i386.c b/tests/tcg/i386/test-i386.c
index e6b308a2c0..864c4e620d 100644
--- a/tests/tcg/i386/test-i386.c
+++ b/tests/tcg/i386/test-i386.c
@@ -34,15 +34,8 @@
 #endif
 //#define LINUX_VM86_IOPL_FIX
 //#define TEST_P4_FLAGS
-#ifdef __SSE__
-#define TEST_SSE
 #define TEST_CMOV  1
 #define TEST_FCOMI 1
-#else
-#undef TEST_SSE
-#define TEST_CMOV  1
-#define TEST_FCOMI 1
-#endif
 
 #if defined(__x86_64__)
 #define FMT64X "%016lx"
@@ -2104,568 +2097,6 @@ static void test_enter(void)
     TEST_ENTER("w", uint16_t, 31);
 }
 
-#ifdef TEST_SSE
-
-typedef int __m64 __attribute__ ((vector_size(8)));
-typedef float __m128 __attribute__ ((vector_size(16)));
-
-typedef union {
-    double d[2];
-    float s[4];
-    uint32_t l[4];
-    uint64_t q[2];
-    __m128 dq;
-} XMMReg;
-
-static uint64_t __attribute__((aligned(16))) test_values[4][2] = {
-    { 0x456723c698694873, 0xdc515cff944a58ec },
-    { 0x1f297ccd58bad7ab, 0x41f21efba9e3e146 },
-    { 0x007c62c2085427f8, 0x231be9e8cde7438d },
-    { 0x0f76255a085427f8, 0xc233e9e8c4c9439a },
-};
-
-#define SSE_OP(op)\
-{\
-    asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           b.q[1], b.q[0],\
-           r.q[1], r.q[0]);\
-}
-
-#define SSE_OP2(op)\
-{\
-    int i;\
-    for(i=0;i<2;i++) {\
-    a.q[0] = test_values[2*i][0];\
-    a.q[1] = test_values[2*i][1];\
-    b.q[0] = test_values[2*i+1][0];\
-    b.q[1] = test_values[2*i+1][1];\
-    SSE_OP(op);\
-    }\
-}
-
-#define MMX_OP2(op)\
-{\
-    int i;\
-    for(i=0;i<2;i++) {\
-    a.q[0] = test_values[2*i][0];\
-    b.q[0] = test_values[2*i+1][0];\
-    asm volatile (#op " %2, %0" : "=y" (r.q[0]) : "0" (a.q[0]), "y" (b.q[0]));\
-    printf("%-9s: a=" FMT64X " b=" FMT64X " r=" FMT64X "\n",\
-           #op,\
-           a.q[0],\
-           b.q[0],\
-           r.q[0]);\
-    }\
-    SSE_OP2(op);\
-}
-
-#define SHUF_OP(op, ib)\
-{\
-    a.q[0] = test_values[0][0];\
-    a.q[1] = test_values[0][1];\
-    b.q[0] = test_values[1][0];\
-    b.q[1] = test_values[1][1];\
-    asm volatile (#op " $" #ib ", %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           b.q[1], b.q[0],\
-           ib,\
-           r.q[1], r.q[0]);\
-}
-
-#define PSHUF_OP(op, ib)\
-{\
-    int i;\
-    for(i=0;i<2;i++) {\
-    a.q[0] = test_values[2*i][0];\
-    a.q[1] = test_values[2*i][1];\
-    asm volatile (#op " $" #ib ", %1, %0" : "=x" (r.dq) : "x" (a.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           ib,\
-           r.q[1], r.q[0]);\
-    }\
-}
-
-#define SHIFT_IM(op, ib)\
-{\
-    int i;\
-    for(i=0;i<2;i++) {\
-    a.q[0] = test_values[2*i][0];\
-    a.q[1] = test_values[2*i][1];\
-    asm volatile (#op " $" #ib ", %0" : "=x" (r.dq) : "0" (a.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           ib,\
-           r.q[1], r.q[0]);\
-    }\
-}
-
-#define SHIFT_OP(op, ib)\
-{\
-    int i;\
-    SHIFT_IM(op, ib);\
-    for(i=0;i<2;i++) {\
-    a.q[0] = test_values[2*i][0];\
-    a.q[1] = test_values[2*i][1];\
-    b.q[0] = ib;\
-    b.q[1] = 0;\
-    asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           b.q[1], b.q[0],\
-           r.q[1], r.q[0]);\
-    }\
-}
-
-#define MOVMSK(op)\
-{\
-    int i, reg;\
-    for(i=0;i<2;i++) {\
-    a.q[0] = test_values[2*i][0];\
-    a.q[1] = test_values[2*i][1];\
-    asm volatile (#op " %1, %0" : "=r" (reg) : "x" (a.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           reg);\
-    }\
-}
-
-#define SSE_OPS(a) \
-SSE_OP(a ## ps);\
-SSE_OP(a ## ss);
-
-#define SSE_OPD(a) \
-SSE_OP(a ## pd);\
-SSE_OP(a ## sd);
-
-#define SSE_COMI(op, field)\
-{\
-    unsigned long eflags;\
-    XMMReg a, b;\
-    a.field[0] = a1;\
-    b.field[0] = b1;\
-    asm volatile (#op " %2, %1\n"\
-        "pushf\n"\
-        "pop %0\n"\
-        : "=rm" (eflags)\
-        : "x" (a.dq), "x" (b.dq));\
-    printf("%-9s: a=%f b=%f cc=%04lx\n",\
-           #op, a1, b1,\
-           eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
-}
-
-void test_sse_comi(double a1, double b1)
-{
-    SSE_COMI(ucomiss, s);
-    SSE_COMI(ucomisd, d);
-    SSE_COMI(comiss, s);
-    SSE_COMI(comisd, d);
-}
-
-#define CVT_OP_XMM(op)\
-{\
-    asm volatile (#op " %1, %0" : "=x" (r.dq) : "x" (a.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           r.q[1], r.q[0]);\
-}
-
-/* Force %xmm0 usage to avoid the case where both register index are 0
-   to test instruction decoding more extensively */
-#define CVT_OP_XMM2MMX(op)\
-{\
-    asm volatile (#op " %1, %0" : "=y" (r.q[0]) : "x" (a.dq) \
-                  : "%xmm0"); \
-    asm volatile("emms\n"); \
-    printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           r.q[0]);\
-}
-
-#define CVT_OP_MMX2XMM(op)\
-{\
-    asm volatile (#op " %1, %0" : "=x" (r.dq) : "y" (a.q[0]));\
-    asm volatile("emms\n"); \
-    printf("%-9s: a=" FMT64X " r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.q[0],\
-           r.q[1], r.q[0]);\
-}
-
-#define CVT_OP_REG2XMM(op)\
-{\
-    asm volatile (#op " %1, %0" : "=x" (r.dq) : "r" (a.l[0]));\
-    printf("%-9s: a=%08x r=" FMT64X "" FMT64X "\n",\
-           #op,\
-           a.l[0],\
-           r.q[1], r.q[0]);\
-}
-
-#define CVT_OP_XMM2REG(op)\
-{\
-    asm volatile (#op " %1, %0" : "=r" (r.l[0]) : "x" (a.dq));\
-    printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
-           #op,\
-           a.q[1], a.q[0],\
-           r.l[0]);\
-}
-
-struct fpxstate {
-    uint16_t fpuc;
-    uint16_t fpus;
-    uint16_t fptag;
-    uint16_t fop;
-    uint32_t fpuip;
-    uint16_t cs_sel;
-    uint16_t dummy0;
-    uint32_t fpudp;
-    uint16_t ds_sel;
-    uint16_t dummy1;
-    uint32_t mxcsr;
-    uint32_t mxcsr_mask;
-    uint8_t fpregs1[8 * 16];
-    uint8_t xmm_regs[8 * 16];
-    uint8_t dummy2[224];
-};
-
-static struct fpxstate fpx_state __attribute__((aligned(16)));
-static struct fpxstate fpx_state2 __attribute__((aligned(16)));
-
-void test_fxsave(void)
-{
-    struct fpxstate *fp = &fpx_state;
-    struct fpxstate *fp2 = &fpx_state2;
-    int i, nb_xmm;
-    XMMReg a, b;
-    a.q[0] = test_values[0][0];
-    a.q[1] = test_values[0][1];
-    b.q[0] = test_values[1][0];
-    b.q[1] = test_values[1][1];
-
-    asm("movdqa %2, %%xmm0\n"
-        "movdqa %3, %%xmm7\n"
-#if defined(__x86_64__)
-        "movdqa %2, %%xmm15\n"
-#endif
-        " fld1\n"
-        " fldpi\n"
-        " fldln2\n"
-        " fxsave %0\n"
-        " fxrstor %0\n"
-        " fxsave %1\n"
-        " fninit\n"
-        : "=m" (*(uint32_t *)fp2), "=m" (*(uint32_t *)fp)
-        : "m" (a), "m" (b));
-    printf("fpuc=%04x\n", fp->fpuc);
-    printf("fpus=%04x\n", fp->fpus);
-    printf("fptag=%04x\n", fp->fptag);
-    for(i = 0; i < 3; i++) {
-        printf("ST%d: " FMT64X " %04x\n",
-               i,
-               *(uint64_t *)&fp->fpregs1[i * 16],
-               *(uint16_t *)&fp->fpregs1[i * 16 + 8]);
-    }
-    printf("mxcsr=%08x\n", fp->mxcsr & 0x1f80);
-#if defined(__x86_64__)
-    nb_xmm = 16;
-#else
-    nb_xmm = 8;
-#endif
-    for(i = 0; i < nb_xmm; i++) {
-        printf("xmm%d: " FMT64X "" FMT64X "\n",
-               i,
-               *(uint64_t *)&fp->xmm_regs[i * 16],
-               *(uint64_t *)&fp->xmm_regs[i * 16 + 8]);
-    }
-}
-
-void test_sse(void)
-{
-    XMMReg r, a, b;
-    int i;
-
-    MMX_OP2(punpcklbw);
-    MMX_OP2(punpcklwd);
-    MMX_OP2(punpckldq);
-    MMX_OP2(packsswb);
-    MMX_OP2(pcmpgtb);
-    MMX_OP2(pcmpgtw);
-    MMX_OP2(pcmpgtd);
-    MMX_OP2(packuswb);
-    MMX_OP2(punpckhbw);
-    MMX_OP2(punpckhwd);
-    MMX_OP2(punpckhdq);
-    MMX_OP2(packssdw);
-    MMX_OP2(pcmpeqb);
-    MMX_OP2(pcmpeqw);
-    MMX_OP2(pcmpeqd);
-
-    MMX_OP2(paddq);
-    MMX_OP2(pmullw);
-    MMX_OP2(psubusb);
-    MMX_OP2(psubusw);
-    MMX_OP2(pminub);
-    MMX_OP2(pand);
-    MMX_OP2(paddusb);
-    MMX_OP2(paddusw);
-    MMX_OP2(pmaxub);
-    MMX_OP2(pandn);
-
-    MMX_OP2(pmulhuw);
-    MMX_OP2(pmulhw);
-
-    MMX_OP2(psubsb);
-    MMX_OP2(psubsw);
-    MMX_OP2(pminsw);
-    MMX_OP2(por);
-    MMX_OP2(paddsb);
-    MMX_OP2(paddsw);
-    MMX_OP2(pmaxsw);
-    MMX_OP2(pxor);
-    MMX_OP2(pmuludq);
-    MMX_OP2(pmaddwd);
-    MMX_OP2(psadbw);
-    MMX_OP2(psubb);
-    MMX_OP2(psubw);
-    MMX_OP2(psubd);
-    MMX_OP2(psubq);
-    MMX_OP2(paddb);
-    MMX_OP2(paddw);
-    MMX_OP2(paddd);
-
-    MMX_OP2(pavgb);
-    MMX_OP2(pavgw);
-
-    asm volatile ("pinsrw $1, %1, %0" : "=y" (r.q[0]) : "r" (0x12345678));
-    printf("%-9s: r=" FMT64X "\n", "pinsrw", r.q[0]);
-
-    asm volatile ("pinsrw $5, %1, %0" : "=x" (r.dq) : "r" (0x12345678));
-    printf("%-9s: r=" FMT64X "" FMT64X "\n", "pinsrw", r.q[1], r.q[0]);
-
-    a.q[0] = test_values[0][0];
-    a.q[1] = test_values[0][1];
-    asm volatile ("pextrw $1, %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
-    printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
-
-    asm volatile ("pextrw $5, %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
-    printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
-
-    asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
-    printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
-
-    asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
-    printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
-
-    {
-        r.q[0] = -1;
-        r.q[1] = -1;
-
-        a.q[0] = test_values[0][0];
-        a.q[1] = test_values[0][1];
-        b.q[0] = test_values[1][0];
-        b.q[1] = test_values[1][1];
-        asm volatile("maskmovq %1, %0" :
-                     : "y" (a.q[0]), "y" (b.q[0]), "D" (&r)
-                     : "memory");
-        printf("%-9s: r=" FMT64X " a=" FMT64X " b=" FMT64X "\n",
-               "maskmov",
-               r.q[0],
-               a.q[0],
-               b.q[0]);
-        asm volatile("maskmovdqu %1, %0" :
-                     : "x" (a.dq), "x" (b.dq), "D" (&r)
-                     : "memory");
-        printf("%-9s: r=" FMT64X "" FMT64X " a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X "\n",
-               "maskmov",
-               r.q[1], r.q[0],
-               a.q[1], a.q[0],
-               b.q[1], b.q[0]);
-    }
-
-    asm volatile ("emms");
-
-    SSE_OP2(punpcklqdq);
-    SSE_OP2(punpckhqdq);
-    SSE_OP2(andps);
-    SSE_OP2(andpd);
-    SSE_OP2(andnps);
-    SSE_OP2(andnpd);
-    SSE_OP2(orps);
-    SSE_OP2(orpd);
-    SSE_OP2(xorps);
-    SSE_OP2(xorpd);
-
-    SSE_OP2(unpcklps);
-    SSE_OP2(unpcklpd);
-    SSE_OP2(unpckhps);
-    SSE_OP2(unpckhpd);
-
-    SHUF_OP(shufps, 0x78);
-    SHUF_OP(shufpd, 0x02);
-
-    PSHUF_OP(pshufd, 0x78);
-    PSHUF_OP(pshuflw, 0x78);
-    PSHUF_OP(pshufhw, 0x78);
-
-    SHIFT_OP(psrlw, 7);
-    SHIFT_OP(psrlw, 16);
-    SHIFT_OP(psraw, 7);
-    SHIFT_OP(psraw, 16);
-    SHIFT_OP(psllw, 7);
-    SHIFT_OP(psllw, 16);
-
-    SHIFT_OP(psrld, 7);
-    SHIFT_OP(psrld, 32);
-    SHIFT_OP(psrad, 7);
-    SHIFT_OP(psrad, 32);
-    SHIFT_OP(pslld, 7);
-    SHIFT_OP(pslld, 32);
-
-    SHIFT_OP(psrlq, 7);
-    SHIFT_OP(psrlq, 32);
-    SHIFT_OP(psllq, 7);
-    SHIFT_OP(psllq, 32);
-
-    SHIFT_IM(psrldq, 16);
-    SHIFT_IM(psrldq, 7);
-    SHIFT_IM(pslldq, 16);
-    SHIFT_IM(pslldq, 7);
-
-    MOVMSK(movmskps);
-    MOVMSK(movmskpd);
-
-    /* FPU specific ops */
-
-    {
-        uint32_t mxcsr;
-        asm volatile("stmxcsr %0" : "=m" (mxcsr));
-        printf("mxcsr=%08x\n", mxcsr & 0x1f80);
-        asm volatile("ldmxcsr %0" : : "m" (mxcsr));
-    }
-
-    test_sse_comi(2, -1);
-    test_sse_comi(2, 2);
-    test_sse_comi(2, 3);
-    test_sse_comi(2, q_nan.d);
-    test_sse_comi(q_nan.d, -1);
-
-    for(i = 0; i < 2; i++) {
-        a.s[0] = 2.7;
-        a.s[1] = 3.4;
-        a.s[2] = 4;
-        a.s[3] = -6.3;
-        b.s[0] = 45.7;
-        b.s[1] = 353.4;
-        b.s[2] = 4;
-        b.s[3] = 56.3;
-        if (i == 1) {
-            a.s[0] = q_nan.d;
-            b.s[3] = q_nan.d;
-        }
-
-        SSE_OPS(add);
-        SSE_OPS(mul);
-        SSE_OPS(sub);
-        SSE_OPS(min);
-        SSE_OPS(div);
-        SSE_OPS(max);
-        SSE_OPS(sqrt);
-        SSE_OPS(cmpeq);
-        SSE_OPS(cmplt);
-        SSE_OPS(cmple);
-        SSE_OPS(cmpunord);
-        SSE_OPS(cmpneq);
-        SSE_OPS(cmpnlt);
-        SSE_OPS(cmpnle);
-        SSE_OPS(cmpord);
-
-
-        a.d[0] = 2.7;
-        a.d[1] = -3.4;
-        b.d[0] = 45.7;
-        b.d[1] = -53.4;
-        if (i == 1) {
-            a.d[0] = q_nan.d;
-            b.d[1] = q_nan.d;
-        }
-        SSE_OPD(add);
-        SSE_OPD(mul);
-        SSE_OPD(sub);
-        SSE_OPD(min);
-        SSE_OPD(div);
-        SSE_OPD(max);
-        SSE_OPD(sqrt);
-        SSE_OPD(cmpeq);
-        SSE_OPD(cmplt);
-        SSE_OPD(cmple);
-        SSE_OPD(cmpunord);
-        SSE_OPD(cmpneq);
-        SSE_OPD(cmpnlt);
-        SSE_OPD(cmpnle);
-        SSE_OPD(cmpord);
-    }
-
-    /* float to float/int */
-    a.s[0] = 2.7;
-    a.s[1] = 3.4;
-    a.s[2] = 4;
-    a.s[3] = -6.3;
-    CVT_OP_XMM(cvtps2pd);
-    CVT_OP_XMM(cvtss2sd);
-    CVT_OP_XMM2MMX(cvtps2pi);
-    CVT_OP_XMM2MMX(cvttps2pi);
-    CVT_OP_XMM2REG(cvtss2si);
-    CVT_OP_XMM2REG(cvttss2si);
-    CVT_OP_XMM(cvtps2dq);
-    CVT_OP_XMM(cvttps2dq);
-
-    a.d[0] = 2.6;
-    a.d[1] = -3.4;
-    CVT_OP_XMM(cvtpd2ps);
-    CVT_OP_XMM(cvtsd2ss);
-    CVT_OP_XMM2MMX(cvtpd2pi);
-    CVT_OP_XMM2MMX(cvttpd2pi);
-    CVT_OP_XMM2REG(cvtsd2si);
-    CVT_OP_XMM2REG(cvttsd2si);
-    CVT_OP_XMM(cvtpd2dq);
-    CVT_OP_XMM(cvttpd2dq);
-
-    /* sse/mmx moves */
-    CVT_OP_XMM2MMX(movdq2q);
-    CVT_OP_MMX2XMM(movq2dq);
-
-    /* int to float */
-    a.l[0] = -6;
-    a.l[1] = 2;
-    a.l[2] = 100;
-    a.l[3] = -60000;
-    CVT_OP_MMX2XMM(cvtpi2ps);
-    CVT_OP_MMX2XMM(cvtpi2pd);
-    CVT_OP_REG2XMM(cvtsi2ss);
-    CVT_OP_REG2XMM(cvtsi2sd);
-    CVT_OP_XMM(cvtdq2ps);
-    CVT_OP_XMM(cvtdq2pd);
-
-    /* XXX: test PNI insns */
-#if 0
-    SSE_OP2(movshdup);
-#endif
-    asm volatile ("emms");
-}
-
-#endif
-
 #define TEST_CONV_RAX(op)\
 {\
     unsigned long a, r;\
@@ -2756,9 +2187,5 @@ int main(int argc, char **argv)
 #endif
     test_enter();
     test_conv();
-#ifdef TEST_SSE
-    test_sse();
-    test_fxsave();
-#endif
     return 0;
 }
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 15/21] audio: add help option for -audio and -audiodev
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (13 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 14/21] tests/tcg: remove old " Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 16/21] target/i386: correctly mask SSE4a bit indices in register operands Paolo Bonzini
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Claudio Fontana

From: Claudio Fontana <cfontana@suse.de>

add a simple help option for -audio and -audiodev
to show the list of available drivers, and document them.

Signed-off-by: Claudio Fontana <cfontana@suse.de>
Message-Id: <20220908081441.7111-1-cfontana@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 audio/audio.c   | 19 +++++++++++++++++++
 audio/audio.h   |  1 +
 qemu-options.hx | 10 ++++++----
 softmmu/vl.c    |  9 +++++++--
 4 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/audio/audio.c b/audio/audio.c
index 76b8735b44..cfa4119c05 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -32,6 +32,7 @@
 #include "qapi/qapi-visit-audio.h"
 #include "qemu/cutils.h"
 #include "qemu/module.h"
+#include "qemu/help_option.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/replay.h"
 #include "sysemu/runstate.h"
@@ -2101,10 +2102,28 @@ static void audio_validate_opts(Audiodev *dev, Error **errp)
     }
 }
 
+void audio_help(void)
+{
+    int i;
+
+    printf("Available audio drivers:\n");
+
+    for (i = 0; i < AUDIODEV_DRIVER__MAX; i++) {
+        audio_driver *driver = audio_driver_lookup(AudiodevDriver_str(i));
+        if (driver) {
+            printf("%s\n", driver->name);
+        }
+    }
+}
+
 void audio_parse_option(const char *opt)
 {
     Audiodev *dev = NULL;
 
+    if (is_help_option(opt)) {
+        audio_help();
+        exit(EXIT_SUCCESS);
+    }
     Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal);
     visit_type_Audiodev(v, NULL, &dev, &error_fatal);
     visit_free(v);
diff --git a/audio/audio.h b/audio/audio.h
index 27e67079a0..01bdc567fb 100644
--- a/audio/audio.h
+++ b/audio/audio.h
@@ -171,6 +171,7 @@ void audio_sample_from_uint64(void *samples, int pos,
 void audio_define(Audiodev *audio);
 void audio_parse_option(const char *opt);
 bool audio_init_audiodevs(void);
+void audio_help(void);
 void audio_legacy_help(void);
 
 AudioState *audio_state_by_name(const char *name);
diff --git a/qemu-options.hx b/qemu-options.hx
index 1bb02363ab..d8b5ce5b43 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -704,10 +704,11 @@ SRST
 ``-audio [driver=]driver,model=value[,prop[=value][,...]]``
     This option is a shortcut for configuring both the guest audio
     hardware and the host audio backend in one go.
-    The host backend options are the same as with the corresponding
-    ``-audiodev`` options below. The guest hardware model can be set with
-    ``model=modelname``. Use ``model=help`` to list the available device
-    types.
+    The driver option is the same as with the corresponding ``-audiodev`` option below.
+    The guest hardware model can be set with ``model=modelname``.
+
+    Use ``driver=help`` to list the available drivers,
+    and ``model=help`` to list the available device types.
 
     The following two example do exactly the same, to show how ``-audio``
     can be used to shorten the command line length:
@@ -721,6 +722,7 @@ ERST
 DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev,
     "-audiodev [driver=]driver,id=id[,prop[=value][,...]]\n"
     "                specifies the audio backend to use\n"
+    "                Use ``-audiodev help`` to list the available drivers\n"
     "                id= identifier of the backend\n"
     "                timer-period= timer period in microseconds\n"
     "                in|out.mixing-engine= use mixing engine to mix streams inside QEMU\n"
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 263f029a8e..e62b9cc35d 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2842,11 +2842,16 @@ void qemu_init(int argc, char **argv, char **envp)
                 audio_parse_option(optarg);
                 break;
             case QEMU_OPTION_audio: {
-                QDict *dict = keyval_parse(optarg, "driver", NULL, &error_fatal);
+                bool help;
                 char *model;
                 Audiodev *dev = NULL;
                 Visitor *v;
-
+                QDict *dict = keyval_parse(optarg, "driver", &help, &error_fatal);
+                if (help || (qdict_haskey(dict, "driver") &&
+                             is_help_option(qdict_get_str(dict, "driver")))) {
+                    audio_help();
+                    exit(EXIT_SUCCESS);
+                }
                 if (!qdict_haskey(dict, "id")) {
                     qdict_put_str(dict, "id", "audiodev0");
                 }
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 16/21] target/i386: correctly mask SSE4a bit indices in register operands
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (14 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 15/21] audio: add help option for -audio and -audiodev Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 17/21] target/i386: fix INSERTQ implementation Paolo Bonzini
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

SSE4a instructions EXTRQ and INSERTQ have two bit index operands, that can be
immediates or taken from an XMM register.  In both cases, the fields are
6-bit wide and the top two bits in the byte are ignored.  translate.c is
doing that correctly for the immediate case, but not for the XMM case, so
fix it.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/ops_sse.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index c0766de18d..3504bca36a 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -926,7 +926,7 @@ static inline uint64_t helper_extrq(uint64_t src, int shift, int len)
 
 void helper_extrq_r(CPUX86State *env, ZMMReg *d, ZMMReg *s)
 {
-    d->ZMM_Q(0) = helper_extrq(d->ZMM_Q(0), s->ZMM_B(1), s->ZMM_B(0));
+    d->ZMM_Q(0) = helper_extrq(d->ZMM_Q(0), s->ZMM_B(1) & 63, s->ZMM_B(0) & 63);
 }
 
 void helper_extrq_i(CPUX86State *env, ZMMReg *d, int index, int length)
@@ -948,7 +948,7 @@ static inline uint64_t helper_insertq(uint64_t src, int shift, int len)
 
 void helper_insertq_r(CPUX86State *env, ZMMReg *d, ZMMReg *s)
 {
-    d->ZMM_Q(0) = helper_insertq(s->ZMM_Q(0), s->ZMM_B(9), s->ZMM_B(8));
+    d->ZMM_Q(0) = helper_insertq(s->ZMM_Q(0), s->ZMM_B(9) & 63, s->ZMM_B(8) & 63);
 }
 
 void helper_insertq_i(CPUX86State *env, ZMMReg *d, int index, int length)
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 17/21] target/i386: fix INSERTQ implementation
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (15 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 16/21] target/i386: correctly mask SSE4a bit indices in register operands Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 18/21] target/i386: REPZ and REPNZ are mutually exclusive Paolo Bonzini
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

INSERTQ is defined to not modify any bits in the lower 64 bits of the
destination, other than the ones being replaced with bits from the
source operand.  QEMU instead is using unshifted bits from the source
for those bits.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/ops_sse.h        | 10 +++++-----
 target/i386/ops_sse_header.h |  2 +-
 target/i386/tcg/translate.c  | 14 ++++++++++++--
 3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index 3504bca36a..7bf8bb967d 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -934,7 +934,7 @@ void helper_extrq_i(CPUX86State *env, ZMMReg *d, int index, int length)
     d->ZMM_Q(0) = helper_extrq(d->ZMM_Q(0), index, length);
 }
 
-static inline uint64_t helper_insertq(uint64_t src, int shift, int len)
+static inline uint64_t helper_insertq(uint64_t dest, uint64_t src, int shift, int len)
 {
     uint64_t mask;
 
@@ -943,17 +943,17 @@ static inline uint64_t helper_insertq(uint64_t src, int shift, int len)
     } else {
         mask = (1ULL << len) - 1;
     }
-    return (src & ~(mask << shift)) | ((src & mask) << shift);
+    return (dest & ~(mask << shift)) | ((src & mask) << shift);
 }
 
 void helper_insertq_r(CPUX86State *env, ZMMReg *d, ZMMReg *s)
 {
-    d->ZMM_Q(0) = helper_insertq(s->ZMM_Q(0), s->ZMM_B(9) & 63, s->ZMM_B(8) & 63);
+    d->ZMM_Q(0) = helper_insertq(d->ZMM_Q(0), s->ZMM_Q(0), s->ZMM_B(9) & 63, s->ZMM_B(8) & 63);
 }
 
-void helper_insertq_i(CPUX86State *env, ZMMReg *d, int index, int length)
+void helper_insertq_i(CPUX86State *env, ZMMReg *d, ZMMReg *s, int index, int length)
 {
-    d->ZMM_Q(0) = helper_insertq(d->ZMM_Q(0), index, length);
+    d->ZMM_Q(0) = helper_insertq(d->ZMM_Q(0), s->ZMM_Q(0), index, length);
 }
 #endif
 
diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h
index d99464afb0..400b24c091 100644
--- a/target/i386/ops_sse_header.h
+++ b/target/i386/ops_sse_header.h
@@ -193,7 +193,7 @@ DEF_HELPER_3(rcpss, void, env, ZMMReg, ZMMReg)
 DEF_HELPER_3(extrq_r, void, env, ZMMReg, ZMMReg)
 DEF_HELPER_4(extrq_i, void, env, ZMMReg, int, int)
 DEF_HELPER_3(insertq_r, void, env, ZMMReg, ZMMReg)
-DEF_HELPER_4(insertq_i, void, env, ZMMReg, int, int)
+DEF_HELPER_5(insertq_i, void, env, ZMMReg, ZMMReg, int, int)
 DEF_HELPER_3(glue(haddps, SUFFIX), void, env, ZMMReg, ZMMReg)
 DEF_HELPER_3(glue(haddpd, SUFFIX), void, env, ZMMReg, ZMMReg)
 DEF_HELPER_3(glue(hsubps, SUFFIX), void, env, ZMMReg, ZMMReg)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 8ec91d17af..5f31a59fb8 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3506,10 +3506,20 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     gen_helper_extrq_i(cpu_env, s->ptr0,
                                        tcg_const_i32(bit_index),
                                        tcg_const_i32(field_length));
-                else
-                    gen_helper_insertq_i(cpu_env, s->ptr0,
+                else {
+                    if (mod != 3) {
+                        gen_lea_modrm(env, s, modrm);
+                        op2_offset = offsetof(CPUX86State, xmm_t0);
+                        gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
+                    } else {
+                        rm = (modrm & 7) | REX_B(s);
+                        op2_offset = ZMM_OFFSET(rm);
+                    }
+                    tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
+                    gen_helper_insertq_i(cpu_env, s->ptr0, s->ptr1,
                                          tcg_const_i32(bit_index),
                                          tcg_const_i32(field_length));
+                }
             }
             break;
         case 0x7e: /* movd ea, mm */
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 18/21] target/i386: REPZ and REPNZ are mutually exclusive
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (16 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 17/21] target/i386: fix INSERTQ implementation Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 19/21] target/i386: introduce insn_get_addr Paolo Bonzini
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson

The later prefix wins if both are present, make it show in s->prefix too.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/tcg/translate.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 5f31a59fb8..eaa56b0f48 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -4733,9 +4733,11 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
     switch (b) {
     case 0xf3:
         prefixes |= PREFIX_REPZ;
+        prefixes &= ~PREFIX_REPNZ;
         goto next_byte;
     case 0xf2:
         prefixes |= PREFIX_REPNZ;
+        prefixes &= ~PREFIX_REPZ;
         goto next_byte;
     case 0xf0:
         prefixes |= PREFIX_LOCK;
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 19/21] target/i386: introduce insn_get_addr
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (17 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 18/21] target/i386: REPZ and REPNZ are mutually exclusive Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 20/21] build: remove extra parentheses causing missing rebuilds Paolo Bonzini
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson

The "O" operand type in the Intel SDM needs to load an 8- to 64-bit
unsigned value, while insn_get is limited to 32 bits.  Extract the code
out of disas_insn and into a separate function.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/tcg/translate.c | 36 ++++++++++++++++++++++++++----------
 1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index eaa56b0f48..44af8c107f 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2289,6 +2289,31 @@ static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
     }
 }
 
+static target_ulong insn_get_addr(CPUX86State *env, DisasContext *s, MemOp ot)
+{
+    target_ulong ret;
+
+    switch (ot) {
+    case MO_8:
+        ret = x86_ldub_code(env, s);
+        break;
+    case MO_16:
+        ret = x86_lduw_code(env, s);
+        break;
+    case MO_32:
+        ret = x86_ldl_code(env, s);
+        break;
+#ifdef TARGET_X86_64
+    case MO_64:
+        ret = x86_ldq_code(env, s);
+        break;
+#endif
+    default:
+        g_assert_not_reached();
+    }
+    return ret;
+}
+
 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, MemOp ot)
 {
     uint32_t ret;
@@ -5851,16 +5876,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
             target_ulong offset_addr;
 
             ot = mo_b_d(b, dflag);
-            switch (s->aflag) {
-#ifdef TARGET_X86_64
-            case MO_64:
-                offset_addr = x86_ldq_code(env, s);
-                break;
-#endif
-            default:
-                offset_addr = insn_get(env, s, s->aflag);
-                break;
-            }
+            offset_addr = insn_get_addr(env, s, s->aflag);
             tcg_gen_movi_tl(s->A0, offset_addr);
             gen_add_A0_ds_seg(s);
             if ((b & 2) == 0) {
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 20/21] build: remove extra parentheses causing missing rebuilds
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (18 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 19/21] target/i386: introduce insn_get_addr Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-19 17:34 ` [PULL 21/21] qboot: update to latest submodule Paolo Bonzini
  2022-09-21 17:33 ` [PULL 00/21] Misc patches for 2022-09-19 Stefan Hajnoczi
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel

Because of two stray parentheses at the end of the definition of
ninja-cmd-goals, the test that is last in the .check-TESTSUITENAME.deps
variable will not be rebuilt.  Fix that.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 13234f2aa4..b576cba5a8 100644
--- a/Makefile
+++ b/Makefile
@@ -145,7 +145,7 @@ NINJAFLAGS = $(if $V,-v) $(if $(MAKE.n), -n) $(if $(MAKE.k), -k0) \
         $(filter-out -j, $(lastword -j1 $(filter -l% -j%, $(MAKEFLAGS)))) \
         -d keepdepfile
 ninja-cmd-goals = $(or $(MAKECMDGOALS), all)
-ninja-cmd-goals += $(foreach g, $(MAKECMDGOALS), $(.ninja-goals.$g))))
+ninja-cmd-goals += $(foreach g, $(MAKECMDGOALS), $(.ninja-goals.$g))
 
 makefile-targets := build.ninja ctags TAGS cscope dist clean uninstall
 # "ninja -t targets" also lists all prerequisites.  If build system
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PULL 21/21] qboot: update to latest submodule
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (19 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 20/21] build: remove extra parentheses causing missing rebuilds Paolo Bonzini
@ 2022-09-19 17:34 ` Paolo Bonzini
  2022-09-21 17:33 ` [PULL 00/21] Misc patches for 2022-09-19 Stefan Hajnoczi
  21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2022-09-19 17:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jason A . Donenfeld

Include patch "Place setup_data at location specified by host"
from Jason A. Donenfeld.

Cc: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 roms/qboot | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/roms/qboot b/roms/qboot
index a5300c4949..8ca302e86d 160000
--- a/roms/qboot
+++ b/roms/qboot
@@ -1 +1 @@
-Subproject commit a5300c4949b8d4de2d34bedfaed66793f48ec948
+Subproject commit 8ca302e86d685fa05b16e2b208888243da319941
-- 
2.37.2



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PULL 00/21] Misc patches for 2022-09-19
  2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
                   ` (20 preceding siblings ...)
  2022-09-19 17:34 ` [PULL 21/21] qboot: update to latest submodule Paolo Bonzini
@ 2022-09-21 17:33 ` Stefan Hajnoczi
  21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hajnoczi @ 2022-09-21 17:33 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 115 bytes --]

Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/7.2 for any user-visible changes.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2022-09-21 17:35 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-19 17:34 [PULL 00/21] Misc patches for 2022-09-19 Paolo Bonzini
2022-09-19 17:34 ` [PULL 01/21] KVM: use store-release to mark dirty pages as harvested Paolo Bonzini
2022-09-19 17:34 ` [PULL 02/21] target/i386: Raise #GP on unaligned m128 accesses when required Paolo Bonzini
2022-09-19 17:34 ` [PULL 03/21] kvm: fix memory leak on failure to read stats descriptors Paolo Bonzini
2022-09-19 17:34 ` [PULL 04/21] spapr_pci: fix leak in spapr_phb_vfio_get_loc_code Paolo Bonzini
2022-09-19 17:34 ` [PULL 05/21] coverity: add new RISC-V component Paolo Bonzini
2022-09-19 17:34 ` [PULL 06/21] coverity: put NUBus under m68k component Paolo Bonzini
2022-09-19 17:34 ` [PULL 07/21] smbios: sanitize type from external type before checking have_fields_bitmap Paolo Bonzini
2022-09-19 17:34 ` [PULL 08/21] tests: unit: simplify test-visitor-serialization list tests Paolo Bonzini
2022-09-19 17:34 ` [PULL 09/21] tests: test-qga: close socket on failure to connect Paolo Bonzini
2022-09-19 17:34 ` [PULL 10/21] tests: unit: add NULL-pointer check Paolo Bonzini
2022-09-19 17:34 ` [PULL 11/21] tests/tcg: i386: fix typos in 3DNow! instructions Paolo Bonzini
2022-09-19 17:34 ` [PULL 12/21] tests/tcg: i386: add MMX and 3DNow! tests Paolo Bonzini
2022-09-19 17:34 ` [PULL 13/21] tests/tcg: refine MMX support in SSE tests Paolo Bonzini
2022-09-19 17:34 ` [PULL 14/21] tests/tcg: remove old " Paolo Bonzini
2022-09-19 17:34 ` [PULL 15/21] audio: add help option for -audio and -audiodev Paolo Bonzini
2022-09-19 17:34 ` [PULL 16/21] target/i386: correctly mask SSE4a bit indices in register operands Paolo Bonzini
2022-09-19 17:34 ` [PULL 17/21] target/i386: fix INSERTQ implementation Paolo Bonzini
2022-09-19 17:34 ` [PULL 18/21] target/i386: REPZ and REPNZ are mutually exclusive Paolo Bonzini
2022-09-19 17:34 ` [PULL 19/21] target/i386: introduce insn_get_addr Paolo Bonzini
2022-09-19 17:34 ` [PULL 20/21] build: remove extra parentheses causing missing rebuilds Paolo Bonzini
2022-09-19 17:34 ` [PULL 21/21] qboot: update to latest submodule Paolo Bonzini
2022-09-21 17:33 ` [PULL 00/21] Misc patches for 2022-09-19 Stefan Hajnoczi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.