Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: x86: Enable support for emulating AVX MOV instructions

Some users of KVM have emulated devices (typically added to private
forks of QEMU) that execute AVX instructions on PCI BARs. Whenever
the guest OS tries to do that, an illegal instruction exception or
emulation failure is triggered.

Add the Avx flag to move instructions:
- (66) 0f 10 - MOVUPS/MOVUPD from memory
- (66) 0f 11 - MOVUPS/MOVUPD to memory
- 66 0f 6f - MOVDQA from memory
- 66 0f 7f - MOVDQA to memory
- f3 0f 6f - MOVDQU from memory
- f3 0f 7f - MOVDQU to memory
- (66) 0f 28 - MOVAPS/MOVAPD from memory
- (66) 0f 29 - MOVAPS/MOVAPD to memory
- (66) 0f 2b - MOVNTPS/MOVNTPD to memory
- 66 0f e7 - MOVNTDQ to memory
- 66 0f 38 2a - MOVNTDQA to memory

Co-developed-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Link: https://lore.kernel.org/kvm/BD108C42-0382-4B17-B601-434A4BD038E7@fb.com/T/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Link: https://patch.msgid.link/20251114003633.60689-11-pbonzini@redhat.com
Signed-off-by: Sean Christopherson <seanjc@google.com>

authored by

Paolo Bonzini and committed by
Sean Christopherson
ebec2543 f0585a71

+7 -7
+7 -7
arch/x86/kvm/emulate.c
··· 4121 4121 } }; 4122 4122 4123 4123 static const struct gprefix pfx_0f_6f_0f_7f = { 4124 - I(Mmx, em_mov), I(Sse | Aligned, em_mov), N, I(Sse | Unaligned, em_mov), 4124 + I(Mmx, em_mov), I(Sse | Avx | Aligned, em_mov), N, I(Sse | Avx | Unaligned, em_mov), 4125 4125 }; 4126 4126 4127 4127 static const struct instr_dual instr_dual_0f_2b = { ··· 4141 4141 }; 4142 4142 4143 4143 static const struct gprefix pfx_0f_e7_0f_38_2a = { 4144 - N, I(Sse, em_mov), N, N, 4144 + N, I(Sse | Avx, em_mov), N, N, 4145 4145 }; 4146 4146 4147 4147 static const struct escape escape_d9 = { { ··· 4354 4354 DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N, 4355 4355 N, D(ImplicitOps | ModRM | SrcMem | NoAccess), N, N, 4356 4356 /* 0x10 - 0x1F */ 4357 - GP(ModRM | DstReg | SrcMem | Mov | Sse, &pfx_0f_10_0f_11), 4358 - GP(ModRM | DstMem | SrcReg | Mov | Sse, &pfx_0f_10_0f_11), 4357 + GP(ModRM | DstReg | SrcMem | Mov | Sse | Avx, &pfx_0f_10_0f_11), 4358 + GP(ModRM | DstMem | SrcReg | Mov | Sse | Avx, &pfx_0f_10_0f_11), 4359 4359 N, N, N, N, N, N, 4360 4360 D(ImplicitOps | ModRM | SrcMem | NoAccess), /* 4 * prefetch + 4 * reserved NOP */ 4361 4361 D(ImplicitOps | ModRM | SrcMem | NoAccess), N, N, ··· 4371 4371 IIP(ModRM | SrcMem | Priv | Op3264 | NoMod, em_dr_write, dr_write, 4372 4372 check_dr_write), 4373 4373 N, N, N, N, 4374 - GP(ModRM | DstReg | SrcMem | Mov | Sse, &pfx_0f_28_0f_29), 4375 - GP(ModRM | DstMem | SrcReg | Mov | Sse, &pfx_0f_28_0f_29), 4376 - N, GP(ModRM | DstMem | SrcReg | Mov | Sse, &pfx_0f_2b), 4374 + GP(ModRM | DstReg | SrcMem | Mov | Sse | Avx, &pfx_0f_28_0f_29), 4375 + GP(ModRM | DstMem | SrcReg | Mov | Sse | Avx, &pfx_0f_28_0f_29), 4376 + N, GP(ModRM | DstMem | SrcReg | Mov | Sse | Avx, &pfx_0f_2b), 4377 4377 N, N, N, N, 4378 4378 /* 0x30 - 0x3F */ 4379 4379 II(ImplicitOps | Priv, em_wrmsr, wrmsr),