* [PATCH 00/10] KVM: emulate: enable AVX moves
@ 2025-11-14 0:36 Paolo Bonzini
2025-11-14 0:36 ` [PATCH 01/10] KVM: emulate: add MOVNTDQA Paolo Bonzini
` (12 more replies)
0 siblings, 13 replies; 22+ messages in thread
From: Paolo Bonzini @ 2025-11-14 0:36 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: kbusch, chang.seok.bae
Over a year ago, Keith Busch posted an RFC patch to enable VMOVDQA
and VMOVDQU instructions in the KVM emulator. The reason to do so
is that people are using QEMU to emulate fancy devices whose drivers
use those instructions with BARs that, on real hardware, would
presumably support write combining. These same people obviously
would appreciate being able to use KVM instead of emulation, hence
the request.
The original patch was not bad at all, but missed a few details:
- checking in XCR0 if AVX is enabled (which also protects against
*hosts* with AVX disabled)
- 32-bit support
- clearing the high bytes of AVX registers if VEX.L=0
- checking some invalid prefix combinations
The ugly parts are in patch 7, which has to juggle the fact that the
same instruction can decode to SSE and AVX, and we only know which are
valid after all the groups are handled.
While at it I also included a small refactoring taken out of the
APX series, by Chang S. Bae, some cleanups, and an extra MOVNTDQ
instruction.
Paolo
Chang S. Bae (1):
KVM: x86: Refactor REX prefix handling in instruction emulation
Paolo Bonzini (9):
KVM: emulate: add MOVNTDQA
KVM: emulate: move Src2Shift up one bit
KVM: emulate: improve formatting of flags table
KVM: emulate: move op_prefix to struct x86_emulate_ctxt
KVM: emulate: share common register decoding code
KVM: emulate: add get_xcr callback
KVM: emulate: add AVX support to register fetch and writeback
KVM: emulate: decode VEX prefix
KVM: emulate: enable AVX moves
arch/x86/kvm/emulate.c | 320 ++++++++++++++++++++++++++-----------
arch/x86/kvm/fpu.h | 62 +++++++
arch/x86/kvm/kvm_emulate.h | 20 ++-
arch/x86/kvm/x86.c | 9 ++
4 files changed, 311 insertions(+), 100 deletions(-)
--
2.43.5
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 01/10] KVM: emulate: add MOVNTDQA
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
@ 2025-11-14 0:36 ` Paolo Bonzini
2025-11-14 0:36 ` [PATCH 02/10] KVM: emulate: move Src2Shift up one bit Paolo Bonzini
` (11 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Paolo Bonzini @ 2025-11-14 0:36 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: kbusch, chang.seok.bae
MOVNTDQA is a simple MOV instruction, in fact it has the same
characteristics as 0F E7 (MOVNTDQ) other than the aligned-address
requirement.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/emulate.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 4e3da5b497b8..43ae4fcb2137 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -4133,7 +4133,7 @@ static const struct gprefix pfx_0f_28_0f_29 = {
I(Aligned, em_mov), I(Aligned, em_mov), N, N,
};
-static const struct gprefix pfx_0f_e7 = {
+static const struct gprefix pfx_0f_e7_0f_38_2a = {
N, I(Sse, em_mov), N, N,
};
@@ -4431,7 +4431,7 @@ static const struct opcode twobyte_table[256] = {
/* 0xD0 - 0xDF */
N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
/* 0xE0 - 0xEF */
- N, N, N, N, N, N, N, GP(SrcReg | DstMem | ModRM | Mov, &pfx_0f_e7),
+ N, N, N, N, N, N, N, GP(SrcReg | DstMem | ModRM | Mov, &pfx_0f_e7_0f_38_2a),
N, N, N, N, N, N, N, N,
/* 0xF0 - 0xFF */
N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N
@@ -4458,8 +4458,13 @@ static const struct gprefix three_byte_0f_38_f1 = {
* byte.
*/
static const struct opcode opcode_map_0f_38[256] = {
- /* 0x00 - 0x7f */
- X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N),
+ /* 0x00 - 0x1f */
+ X16(N), X16(N),
+ /* 0x20 - 0x2f */
+ X8(N),
+ X2(N), GP(SrcReg | DstMem | ModRM | Mov | Aligned, &pfx_0f_e7_0f_38_2a), N, N, N, N, N,
+ /* 0x30 - 0x7f */
+ X16(N), X16(N), X16(N), X16(N), X16(N),
/* 0x80 - 0xef */
X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N),
/* 0xf0 - 0xf1 */
--
2.43.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 02/10] KVM: emulate: move Src2Shift up one bit
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
2025-11-14 0:36 ` [PATCH 01/10] KVM: emulate: add MOVNTDQA Paolo Bonzini
@ 2025-11-14 0:36 ` Paolo Bonzini
2025-11-17 19:51 ` Chang S. Bae
2025-11-14 0:36 ` [PATCH 03/10] KVM: emulate: improve formatting of flags table Paolo Bonzini
` (10 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: Paolo Bonzini @ 2025-11-14 0:36 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: kbusch, chang.seok.bae
An irresistible microoptimization (changing accesses to Src2 to just an
AND :)) that also frees a bit for AVX in the low flags word. This makes
it closer to SSE since both of them can access XMM registers, pointlessly
shaving another clock cycle or two (maybe).
No functional change intended.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/emulate.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 43ae4fcb2137..57799b5d9da2 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -147,7 +147,7 @@
#define PageTable (1 << 29) /* instruction used to write page table */
#define NotImpl (1 << 30) /* instruction is not implemented */
/* Source 2 operand type */
-#define Src2Shift (31)
+#define Src2Shift (32) /* bits 32-36 */
#define Src2None (OpNone << Src2Shift)
#define Src2Mem (OpMem << Src2Shift)
#define Src2CL (OpCL << Src2Shift)
@@ -161,6 +161,7 @@
#define Src2FS (OpFS << Src2Shift)
#define Src2GS (OpGS << Src2Shift)
#define Src2Mask (OpMask << Src2Shift)
+/* free: 37-39 */
#define Mmx ((u64)1 << 40) /* MMX Vector instruction */
#define AlignMask ((u64)7 << 41)
#define Aligned ((u64)1 << 41) /* Explicitly aligned (e.g. MOVDQA) */
--
2.43.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 03/10] KVM: emulate: improve formatting of flags table
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
2025-11-14 0:36 ` [PATCH 01/10] KVM: emulate: add MOVNTDQA Paolo Bonzini
2025-11-14 0:36 ` [PATCH 02/10] KVM: emulate: move Src2Shift up one bit Paolo Bonzini
@ 2025-11-14 0:36 ` Paolo Bonzini
2025-11-17 19:53 ` Chang S. Bae
2025-11-14 0:36 ` [PATCH 04/10] KVM: emulate: move op_prefix to struct x86_emulate_ctxt Paolo Bonzini
` (9 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: Paolo Bonzini @ 2025-11-14 0:36 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: kbusch, chang.seok.bae
Align a little better the comments on the right side and list
explicitly the bits used by multi-bit fields.
No functional change intended.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/emulate.c | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 57799b5d9da2..28f81346878e 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -81,9 +81,8 @@
*/
/* Operand sizes: 8-bit operands or specified/overridden size. */
-#define ByteOp (1<<0) /* 8-bit operands. */
-/* Destination operand type. */
-#define DstShift 1
+#define ByteOp (1<<0) /* 8-bit operands. */
+#define DstShift 1 /* Destination operand type at bits 1-5 */
#define ImplicitOps (OpImplicit << DstShift)
#define DstReg (OpReg << DstShift)
#define DstMem (OpMem << DstShift)
@@ -95,8 +94,7 @@
#define DstDX (OpDX << DstShift)
#define DstAccLo (OpAccLo << DstShift)
#define DstMask (OpMask << DstShift)
-/* Source operand type. */
-#define SrcShift 6
+#define SrcShift 6 /* Source operand type at bits 6-10 */
#define SrcNone (OpNone << SrcShift)
#define SrcReg (OpReg << SrcShift)
#define SrcMem (OpMem << SrcShift)
@@ -119,10 +117,10 @@
#define SrcAccHi (OpAccHi << SrcShift)
#define SrcMask (OpMask << SrcShift)
#define BitOp (1<<11)
-#define MemAbs (1<<12) /* Memory operand is absolute displacement */
+#define MemAbs (1<<12) /* Memory operand is absolute displacement */
#define String (1<<13) /* String instruction (rep capable) */
#define Stack (1<<14) /* Stack instruction (push/pop) */
-#define GroupMask (7<<15) /* Opcode uses one of the group mechanisms */
+#define GroupMask (7<<15) /* Group mechanisms, at bits 15-17 */
#define Group (1<<15) /* Bits 3:5 of modrm byte extend opcode */
#define GroupDual (2<<15) /* Alternate decoding of mod == 3 */
#define Prefix (3<<15) /* Instruction varies with 66/f2/f3 prefix */
@@ -131,11 +129,8 @@
#define InstrDual (6<<15) /* Alternate instruction decoding of mod == 3 */
#define ModeDual (7<<15) /* Different instruction for 32/64 bit */
#define Sse (1<<18) /* SSE Vector instruction */
-/* Generic ModRM decode. */
-#define ModRM (1<<19)
-/* Destination is only written; never read. */
-#define Mov (1<<20)
-/* Misc flags */
+#define ModRM (1<<19) /* Generic ModRM decode. */
+#define Mov (1<<20) /* Destination is only written; never read. */
#define Prot (1<<21) /* instruction generates #UD if not in prot-mode */
#define EmulateOnUD (1<<22) /* Emulate if unsupported by the host */
#define NoAccess (1<<23) /* Don't access memory (lea/invlpg/verr etc) */
@@ -143,11 +138,10 @@
#define Undefined (1<<25) /* No Such Instruction */
#define Lock (1<<26) /* lock prefix is allowed for the instruction */
#define Priv (1<<27) /* instruction generates #GP if current CPL != 0 */
-#define No64 (1<<28)
+#define No64 (1<<28) /* Instruction generates #UD in 64-bit mode */
#define PageTable (1 << 29) /* instruction used to write page table */
#define NotImpl (1 << 30) /* instruction is not implemented */
-/* Source 2 operand type */
-#define Src2Shift (32) /* bits 32-36 */
+#define Src2Shift (32) /* Source 2 operand type at bits 32-36 */
#define Src2None (OpNone << Src2Shift)
#define Src2Mem (OpMem << Src2Shift)
#define Src2CL (OpCL << Src2Shift)
@@ -163,11 +157,12 @@
#define Src2Mask (OpMask << Src2Shift)
/* free: 37-39 */
#define Mmx ((u64)1 << 40) /* MMX Vector instruction */
-#define AlignMask ((u64)7 << 41)
+#define AlignMask ((u64)7 << 41) /* Memory alignment requirement at bits 41-43 */
#define Aligned ((u64)1 << 41) /* Explicitly aligned (e.g. MOVDQA) */
#define Unaligned ((u64)2 << 41) /* Explicitly unaligned (e.g. MOVDQU) */
#define Avx ((u64)3 << 41) /* Advanced Vector Extensions */
#define Aligned16 ((u64)4 << 41) /* Aligned to 16 byte boundary (e.g. FXSAVE) */
+/* free: 44 */
#define NoWrite ((u64)1 << 45) /* No writeback */
#define SrcWrite ((u64)1 << 46) /* Write back src operand */
#define NoMod ((u64)1 << 47) /* Mod field is ignored */
--
2.43.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 04/10] KVM: emulate: move op_prefix to struct x86_emulate_ctxt
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
` (2 preceding siblings ...)
2025-11-14 0:36 ` [PATCH 03/10] KVM: emulate: improve formatting of flags table Paolo Bonzini
@ 2025-11-14 0:36 ` Paolo Bonzini
2025-11-17 19:54 ` Chang S. Bae
2025-11-14 0:36 ` [PATCH 05/10] KVM: emulate: share common register decoding code Paolo Bonzini
` (8 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: Paolo Bonzini @ 2025-11-14 0:36 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: kbusch, chang.seok.bae
VEX decode will need to set it based on the "pp" bits, so make it
a field in the struct rather than a local variable.
No functional change intended.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/emulate.c | 8 ++++----
arch/x86/kvm/kvm_emulate.h | 1 +
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 28f81346878e..7ef791407dbc 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -4761,7 +4761,6 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
int rc = X86EMUL_CONTINUE;
int mode = ctxt->mode;
int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
- bool op_prefix = false;
bool has_seg_override = false;
struct opcode opcode;
u16 dummy;
@@ -4813,7 +4812,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
for (;;) {
switch (ctxt->b = insn_fetch(u8, ctxt)) {
case 0x66: /* operand-size override */
- op_prefix = true;
+ ctxt->op_prefix = true;
/* switch between 2/4 bytes */
ctxt->op_bytes = def_op_bytes ^ 6;
break;
@@ -4920,9 +4919,9 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
opcode = opcode.u.group[goffset];
break;
case Prefix:
- if (ctxt->rep_prefix && op_prefix)
+ if (ctxt->rep_prefix && ctxt->op_prefix)
return EMULATION_FAILED;
- simd_prefix = op_prefix ? 0x66 : ctxt->rep_prefix;
+ simd_prefix = ctxt->op_prefix ? 0x66 : ctxt->rep_prefix;
switch (simd_prefix) {
case 0x00: opcode = opcode.u.gprefix->pfx_no; break;
case 0x66: opcode = opcode.u.gprefix->pfx_66; break;
@@ -5140,6 +5139,7 @@ void init_decode_cache(struct x86_emulate_ctxt *ctxt)
ctxt->rip_relative = false;
ctxt->rex_prefix = 0;
ctxt->lock_prefix = 0;
+ ctxt->op_prefix = false;
ctxt->rep_prefix = 0;
ctxt->regs_valid = 0;
ctxt->regs_dirty = 0;
diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h
index 7b5ddb787a25..83af019620e3 100644
--- a/arch/x86/kvm/kvm_emulate.h
+++ b/arch/x86/kvm/kvm_emulate.h
@@ -348,6 +348,7 @@ struct x86_emulate_ctxt {
u8 opcode_len;
u8 b;
u8 intercept;
+ bool op_prefix;
u8 op_bytes;
u8 ad_bytes;
union {
--
2.43.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 05/10] KVM: emulate: share common register decoding code
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
` (3 preceding siblings ...)
2025-11-14 0:36 ` [PATCH 04/10] KVM: emulate: move op_prefix to struct x86_emulate_ctxt Paolo Bonzini
@ 2025-11-14 0:36 ` Paolo Bonzini
2025-11-17 19:55 ` Chang S. Bae
2025-11-14 0:36 ` [PATCH 06/10] KVM: emulate: add get_xcr callback Paolo Bonzini
` (7 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: Paolo Bonzini @ 2025-11-14 0:36 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: kbusch, chang.seok.bae
Remove all duplicate handling of register operands, including picking
the right register class and fetching it, by extracting a new function
that can be used for both REG and MODRM operands.
Centralize setting op->orig_val = op->val in fetch_register_operand()
as well.
No functional change intended.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/emulate.c | 49 +++++++++++++++---------------------------
1 file changed, 17 insertions(+), 32 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 7ef791407dbc..6c8d3f786e74 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1026,6 +1026,7 @@ static void fetch_register_operand(struct operand *op)
op->val = *(u64 *)op->addr.reg;
break;
}
+ op->orig_val = op->val;
}
static int em_fninit(struct x86_emulate_ctxt *ctxt)
@@ -1071,16 +1072,9 @@ static int em_fnstsw(struct x86_emulate_ctxt *ctxt)
return X86EMUL_CONTINUE;
}
-static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
- struct operand *op)
+static void __decode_register_operand(struct x86_emulate_ctxt *ctxt,
+ struct operand *op, int reg)
{
- unsigned int reg;
-
- if (ctxt->d & ModRM)
- reg = ctxt->modrm_reg;
- else
- reg = (ctxt->b & 7) | ((ctxt->rex_prefix & 1) << 3);
-
if (ctxt->d & Sse) {
op->type = OP_XMM;
op->bytes = 16;
@@ -1099,9 +1093,20 @@ static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
op->type = OP_REG;
op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
op->addr.reg = decode_register(ctxt, reg, ctxt->d & ByteOp);
-
fetch_register_operand(op);
- op->orig_val = op->val;
+}
+
+static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
+ struct operand *op)
+{
+ unsigned int reg;
+
+ if (ctxt->d & ModRM)
+ reg = ctxt->modrm_reg;
+ else
+ reg = (ctxt->b & 7) | ((ctxt->rex_prefix & 1) << 3);
+
+ __decode_register_operand(ctxt, op, reg);
}
static void adjust_modrm_seg(struct x86_emulate_ctxt *ctxt, int base_reg)
@@ -1128,24 +1133,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
ctxt->modrm_seg = VCPU_SREG_DS;
if (ctxt->modrm_mod == 3 || (ctxt->d & NoMod)) {
- op->type = OP_REG;
- op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
- op->addr.reg = decode_register(ctxt, ctxt->modrm_rm,
- ctxt->d & ByteOp);
- if (ctxt->d & Sse) {
- op->type = OP_XMM;
- op->bytes = 16;
- op->addr.xmm = ctxt->modrm_rm;
- kvm_read_sse_reg(ctxt->modrm_rm, &op->vec_val);
- return rc;
- }
- if (ctxt->d & Mmx) {
- op->type = OP_MM;
- op->bytes = 8;
- op->addr.mm = ctxt->modrm_rm & 7;
- return rc;
- }
- fetch_register_operand(op);
+ __decode_register_operand(ctxt, op, ctxt->modrm_rm);
return rc;
}
@@ -4619,14 +4607,12 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
op->addr.reg = reg_rmw(ctxt, VCPU_REGS_RAX);
fetch_register_operand(op);
- op->orig_val = op->val;
break;
case OpAccLo:
op->type = OP_REG;
op->bytes = (ctxt->d & ByteOp) ? 2 : ctxt->op_bytes;
op->addr.reg = reg_rmw(ctxt, VCPU_REGS_RAX);
fetch_register_operand(op);
- op->orig_val = op->val;
break;
case OpAccHi:
if (ctxt->d & ByteOp) {
@@ -4637,7 +4623,6 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
op->bytes = ctxt->op_bytes;
op->addr.reg = reg_rmw(ctxt, VCPU_REGS_RDX);
fetch_register_operand(op);
- op->orig_val = op->val;
break;
case OpDI:
op->type = OP_MEM;
--
2.43.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 06/10] KVM: emulate: add get_xcr callback
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
` (4 preceding siblings ...)
2025-11-14 0:36 ` [PATCH 05/10] KVM: emulate: share common register decoding code Paolo Bonzini
@ 2025-11-14 0:36 ` Paolo Bonzini
2025-11-17 19:56 ` Chang S. Bae
2025-11-14 0:36 ` [PATCH 07/10] KVM: emulate: add AVX support to register fetch and writeback Paolo Bonzini
` (6 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: Paolo Bonzini @ 2025-11-14 0:36 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: kbusch, chang.seok.bae
This will be necessary in order to check whether AVX is enabled.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/kvm_emulate.h | 1 +
arch/x86/kvm/x86.c | 9 +++++++++
2 files changed, 10 insertions(+)
diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h
index 83af019620e3..5f9d69c64cd5 100644
--- a/arch/x86/kvm/kvm_emulate.h
+++ b/arch/x86/kvm/kvm_emulate.h
@@ -237,6 +237,7 @@ struct x86_emulate_ops {
bool (*is_smm)(struct x86_emulate_ctxt *ctxt);
int (*leave_smm)(struct x86_emulate_ctxt *ctxt);
void (*triple_fault)(struct x86_emulate_ctxt *ctxt);
+ int (*get_xcr)(struct x86_emulate_ctxt *ctxt, u32 index, u64 *xcr);
int (*set_xcr)(struct x86_emulate_ctxt *ctxt, u32 index, u64 xcr);
gva_t (*get_untagged_addr)(struct x86_emulate_ctxt *ctxt, gva_t addr,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c9c2aa6f4705..cfce7c120215 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -8842,6 +8842,14 @@ static void emulator_triple_fault(struct x86_emulate_ctxt *ctxt)
kvm_make_request(KVM_REQ_TRIPLE_FAULT, emul_to_vcpu(ctxt));
}
+static int emulator_get_xcr(struct x86_emulate_ctxt *ctxt, u32 index, u64 *xcr)
+{
+ if (index != XCR_XFEATURE_ENABLED_MASK)
+ return 1;
+ *xcr = emul_to_vcpu(ctxt)->arch.xcr0;
+ return 0;
+}
+
static int emulator_set_xcr(struct x86_emulate_ctxt *ctxt, u32 index, u64 xcr)
{
return __kvm_set_xcr(emul_to_vcpu(ctxt), index, xcr);
@@ -8914,6 +8922,7 @@ static const struct x86_emulate_ops emulate_ops = {
.is_smm = emulator_is_smm,
.leave_smm = emulator_leave_smm,
.triple_fault = emulator_triple_fault,
+ .get_xcr = emulator_get_xcr,
.set_xcr = emulator_set_xcr,
.get_untagged_addr = emulator_get_untagged_addr,
.is_canonical_addr = emulator_is_canonical_addr,
--
2.43.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 07/10] KVM: emulate: add AVX support to register fetch and writeback
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
` (5 preceding siblings ...)
2025-11-14 0:36 ` [PATCH 06/10] KVM: emulate: add get_xcr callback Paolo Bonzini
@ 2025-11-14 0:36 ` Paolo Bonzini
2025-11-14 17:06 ` kernel test robot
2025-11-14 20:10 ` kernel test robot
2025-11-14 0:36 ` [PATCH 08/10] KVM: x86: Refactor REX prefix handling in instruction emulation Paolo Bonzini
` (5 subsequent siblings)
12 siblings, 2 replies; 22+ messages in thread
From: Paolo Bonzini @ 2025-11-14 0:36 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: kbusch, chang.seok.bae
Prepare struct operand for hosting AVX registers. Remove the
existing, incomplete code that placed the Avx flag in the operand
alignment field, and repurpose the name for a separate bit that
indicates:
- after decode, whether an instruction supports the VEX prefix;
- before writeback, that the instruction did have the VEX prefix and
therefore 1) it can have op_bytes == 32; 2) t should clear high
bytes of XMM registers.
Right now the bit will never be set and the patch has no intended
functional change. However, this is actually more vexing than the
decoder changes itself, and therefore worth separating.
Co-developed-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/emulate.c | 58 ++++++++++++++++++++++++++---------
arch/x86/kvm/fpu.h | 62 ++++++++++++++++++++++++++++++++++++++
arch/x86/kvm/kvm_emulate.h | 7 +++--
3 files changed, 110 insertions(+), 17 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 6c8d3f786e74..94dc8a61965b 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -141,6 +141,7 @@
#define No64 (1<<28) /* Instruction generates #UD in 64-bit mode */
#define PageTable (1 << 29) /* instruction used to write page table */
#define NotImpl (1 << 30) /* instruction is not implemented */
+#define Avx ((u64)1 << 31) /* Instruction uses VEX prefix */
#define Src2Shift (32) /* Source 2 operand type at bits 32-36 */
#define Src2None (OpNone << Src2Shift)
#define Src2Mem (OpMem << Src2Shift)
@@ -157,12 +158,11 @@
#define Src2Mask (OpMask << Src2Shift)
/* free: 37-39 */
#define Mmx ((u64)1 << 40) /* MMX Vector instruction */
-#define AlignMask ((u64)7 << 41) /* Memory alignment requirement at bits 41-43 */
+#define AlignMask ((u64)3 << 41) /* Memory alignment requirement at bits 41-42 */
#define Aligned ((u64)1 << 41) /* Explicitly aligned (e.g. MOVDQA) */
#define Unaligned ((u64)2 << 41) /* Explicitly unaligned (e.g. MOVDQU) */
-#define Avx ((u64)3 << 41) /* Advanced Vector Extensions */
-#define Aligned16 ((u64)4 << 41) /* Aligned to 16 byte boundary (e.g. FXSAVE) */
-/* free: 44 */
+#define Aligned16 ((u64)3 << 41) /* Aligned to 16 byte boundary (e.g. FXSAVE) */
+/* free: 43-44 */
#define NoWrite ((u64)1 << 45) /* No writeback */
#define SrcWrite ((u64)1 << 46) /* Write back src operand */
#define NoMod ((u64)1 << 47) /* Mod field is ignored */
@@ -618,7 +618,6 @@ static unsigned insn_alignment(struct x86_emulate_ctxt *ctxt, unsigned size)
switch (alignment) {
case Unaligned:
- case Avx:
return 1;
case Aligned16:
return 16;
@@ -1075,7 +1074,14 @@ static int em_fnstsw(struct x86_emulate_ctxt *ctxt)
static void __decode_register_operand(struct x86_emulate_ctxt *ctxt,
struct operand *op, int reg)
{
- if (ctxt->d & Sse) {
+ if ((ctxt->d & Avx) && ctxt->op_bytes == 32) {
+ op->type = OP_YMM;
+ op->bytes = 32;
+ op->addr.xmm = reg;
+ kvm_read_avx_reg(reg, &op->vec_val2);
+ return;
+ }
+ if (ctxt->d & (Avx|Sse)) {
op->type = OP_XMM;
op->bytes = 16;
op->addr.xmm = reg;
@@ -1767,7 +1773,15 @@ static int writeback(struct x86_emulate_ctxt *ctxt, struct operand *op)
op->data,
op->bytes * op->count);
case OP_XMM:
- kvm_write_sse_reg(op->addr.xmm, &op->vec_val);
+ if (!(ctxt->d & Avx)) {
+ kvm_write_sse_reg(op->addr.xmm, &op->vec_val);
+ break;
+ }
+ /* full YMM write but with high bytes cleared */
+ memset(op->valptr + 16, 0, 16);
+ fallthrough;
+ case OP_YMM:
+ kvm_write_avx_reg(op->addr.xmm, &op->vec_val2);
break;
case OP_MM:
kvm_write_mmx_reg(op->addr.mm, &op->mm_val);
@@ -4861,9 +4875,8 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
ctxt->op_bytes = 8; /* REX.W */
/* Opcode byte(s). */
- opcode = opcode_table[ctxt->b];
- /* Two-byte opcode? */
if (ctxt->b == 0x0f) {
+ /* Two- or three-byte opcode */
ctxt->opcode_len = 2;
ctxt->b = insn_fetch(u8, ctxt);
opcode = twobyte_table[ctxt->b];
@@ -4874,6 +4887,9 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
ctxt->b = insn_fetch(u8, ctxt);
opcode = opcode_map_0f_38[ctxt->b];
}
+ } else {
+ /* Opcode byte(s). */
+ opcode = opcode_table[ctxt->b];
}
ctxt->d = opcode.flags;
@@ -5022,7 +5038,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
ctxt->op_bytes = 4;
if (ctxt->d & Sse)
- ctxt->op_bytes = 16;
+ ctxt->op_bytes = 16, ctxt->d &= ~Avx;
else if (ctxt->d & Mmx)
ctxt->op_bytes = 8;
}
@@ -5154,20 +5170,34 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt, bool check_intercepts)
}
if (unlikely(ctxt->d &
- (No64|Undefined|Sse|Mmx|Intercept|CheckPerm|Priv|Prot|String))) {
+ (No64|Undefined|Avx|Sse|Mmx|Intercept|CheckPerm|Priv|Prot|String))) {
if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) ||
(ctxt->d & Undefined)) {
rc = emulate_ud(ctxt);
goto done;
}
- if (((ctxt->d & (Sse|Mmx)) && ((ops->get_cr(ctxt, 0) & X86_CR0_EM)))
- || ((ctxt->d & Sse) && !(ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR))) {
+ if ((ctxt->d & (Avx|Sse|Mmx)) && ((ops->get_cr(ctxt, 0) & X86_CR0_EM))) {
rc = emulate_ud(ctxt);
goto done;
}
- if ((ctxt->d & (Sse|Mmx)) && (ops->get_cr(ctxt, 0) & X86_CR0_TS)) {
+ if (ctxt->d & Avx) {
+ u64 xcr = 0;
+ if (!(ops->get_cr(ctxt, 4) & X86_CR4_OSXSAVE)
+ || ops->get_xcr(ctxt, 0, &xcr)
+ || !(xcr & XFEATURE_MASK_YMM)) {
+ rc = emulate_ud(ctxt);
+ goto done;
+ }
+ } else if (ctxt->d & Sse) {
+ if (!(ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR)) {
+ rc = emulate_ud(ctxt);
+ goto done;
+ }
+ }
+
+ if ((ctxt->d & (Avx|Sse|Mmx)) && (ops->get_cr(ctxt, 0) & X86_CR0_TS)) {
rc = emulate_nm(ctxt);
goto done;
}
diff --git a/arch/x86/kvm/fpu.h b/arch/x86/kvm/fpu.h
index 3ba12888bf66..9bc08c3c53f5 100644
--- a/arch/x86/kvm/fpu.h
+++ b/arch/x86/kvm/fpu.h
@@ -15,6 +15,54 @@ typedef u32 __attribute__((vector_size(16))) sse128_t;
#define sse128_l3(x) ({ __sse128_u t; t.vec = x; t.as_u32[3]; })
#define sse128(lo, hi) ({ __sse128_u t; t.as_u64[0] = lo; t.as_u64[1] = hi; t.vec; })
+typedef u32 __attribute__((vector_size(32))) avx256_t;
+
+static inline void _kvm_read_avx_reg(int reg, avx256_t *data)
+{
+ switch (reg) {
+ case 0: asm("vmovdqa %%ymm0, %0" : "=m"(*data)); break;
+ case 1: asm("vmovdqa %%ymm1, %0" : "=m"(*data)); break;
+ case 2: asm("vmovdqa %%ymm2, %0" : "=m"(*data)); break;
+ case 3: asm("vmovdqa %%ymm3, %0" : "=m"(*data)); break;
+ case 4: asm("vmovdqa %%ymm4, %0" : "=m"(*data)); break;
+ case 5: asm("vmovdqa %%ymm5, %0" : "=m"(*data)); break;
+ case 6: asm("vmovdqa %%ymm6, %0" : "=m"(*data)); break;
+ case 7: asm("vmovdqa %%ymm7, %0" : "=m"(*data)); break;
+ case 8: asm("vmovdqa %%ymm8, %0" : "=m"(*data)); break;
+ case 9: asm("vmovdqa %%ymm9, %0" : "=m"(*data)); break;
+ case 10: asm("vmovdqa %%ymm10, %0" : "=m"(*data)); break;
+ case 11: asm("vmovdqa %%ymm11, %0" : "=m"(*data)); break;
+ case 12: asm("vmovdqa %%ymm12, %0" : "=m"(*data)); break;
+ case 13: asm("vmovdqa %%ymm13, %0" : "=m"(*data)); break;
+ case 14: asm("vmovdqa %%ymm14, %0" : "=m"(*data)); break;
+ case 15: asm("vmovdqa %%ymm15, %0" : "=m"(*data)); break;
+ default: BUG();
+ }
+}
+
+static inline void _kvm_write_avx_reg(int reg, const avx256_t *data)
+{
+ switch (reg) {
+ case 0: asm("vmovdqa %0, %%ymm0" : : "m"(*data)); break;
+ case 1: asm("vmovdqa %0, %%ymm1" : : "m"(*data)); break;
+ case 2: asm("vmovdqa %0, %%ymm2" : : "m"(*data)); break;
+ case 3: asm("vmovdqa %0, %%ymm3" : : "m"(*data)); break;
+ case 4: asm("vmovdqa %0, %%ymm4" : : "m"(*data)); break;
+ case 5: asm("vmovdqa %0, %%ymm5" : : "m"(*data)); break;
+ case 6: asm("vmovdqa %0, %%ymm6" : : "m"(*data)); break;
+ case 7: asm("vmovdqa %0, %%ymm7" : : "m"(*data)); break;
+ case 8: asm("vmovdqa %0, %%ymm8" : : "m"(*data)); break;
+ case 9: asm("vmovdqa %0, %%ymm9" : : "m"(*data)); break;
+ case 10: asm("vmovdqa %0, %%ymm10" : : "m"(*data)); break;
+ case 11: asm("vmovdqa %0, %%ymm11" : : "m"(*data)); break;
+ case 12: asm("vmovdqa %0, %%ymm12" : : "m"(*data)); break;
+ case 13: asm("vmovdqa %0, %%ymm13" : : "m"(*data)); break;
+ case 14: asm("vmovdqa %0, %%ymm14" : : "m"(*data)); break;
+ case 15: asm("vmovdqa %0, %%ymm15" : : "m"(*data)); break;
+ default: BUG();
+ }
+}
+
static inline void _kvm_read_sse_reg(int reg, sse128_t *data)
{
switch (reg) {
@@ -109,6 +157,20 @@ static inline void kvm_fpu_put(void)
fpregs_unlock();
}
+static inline void kvm_read_avx_reg(int reg, avx256_t *data)
+{
+ kvm_fpu_get();
+ _kvm_read_avx_reg(reg, data);
+ kvm_fpu_put();
+}
+
+static inline void kvm_write_avx_reg(int reg, const avx256_t *data)
+{
+ kvm_fpu_get();
+ _kvm_write_avx_reg(reg, data);
+ kvm_fpu_put();
+}
+
static inline void kvm_read_sse_reg(int reg, sse128_t *data)
{
kvm_fpu_get();
diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h
index 5f9d69c64cd5..c526f46f5595 100644
--- a/arch/x86/kvm/kvm_emulate.h
+++ b/arch/x86/kvm/kvm_emulate.h
@@ -249,7 +249,7 @@ struct x86_emulate_ops {
/* Type, address-of, and value of an instruction's operand. */
struct operand {
- enum { OP_REG, OP_MEM, OP_MEM_STR, OP_IMM, OP_XMM, OP_MM, OP_NONE } type;
+ enum { OP_REG, OP_MEM, OP_MEM_STR, OP_IMM, OP_XMM, OP_YMM, OP_MM, OP_NONE } type;
unsigned int bytes;
unsigned int count;
union {
@@ -268,11 +268,12 @@ struct operand {
union {
unsigned long val;
u64 val64;
- char valptr[sizeof(sse128_t)];
+ char valptr[sizeof(avx256_t)];
sse128_t vec_val;
+ avx256_t vec_val2;
u64 mm_val;
void *data;
- };
+ } __aligned(32);
};
#define X86_MAX_INSTRUCTION_LENGTH 15
--
2.43.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 08/10] KVM: x86: Refactor REX prefix handling in instruction emulation
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
` (6 preceding siblings ...)
2025-11-14 0:36 ` [PATCH 07/10] KVM: emulate: add AVX support to register fetch and writeback Paolo Bonzini
@ 2025-11-14 0:36 ` Paolo Bonzini
2025-11-17 19:56 ` Chang S. Bae
2025-11-14 0:36 ` [PATCH 09/10] KVM: emulate: decode VEX prefix Paolo Bonzini
` (4 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: Paolo Bonzini @ 2025-11-14 0:36 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: kbusch, chang.seok.bae
From: "Chang S. Bae" <chang.seok.bae@intel.com>
Restructure how to represent and interpret REX fields, preparing
for handling of both REX2 and VEX.
REX uses the upper four bits of a single byte as a fixed identifier,
and the lower four bits containing the data. VEX and REX2 extends this so
that the first byte identifies the prefix and the rest encode additional
bits; and while VEX only has the same four data bits as REX, eight zero
bits are a valid value for the data bits of REX2. So, stop storing the
REX byte as-is. Instead, store only the low bits of the REX prefix and
track separately whether a REX-like prefix was used.
No functional changes intended.
Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
Message-ID: <20251110180131.28264-11-chang.seok.bae@intel.com>
[Extracted from APX series; removed bitfields and REX2-specific default. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/emulate.c | 33 +++++++++++++++++++++------------
arch/x86/kvm/kvm_emulate.h | 11 ++++++++++-
2 files changed, 31 insertions(+), 13 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 94dc8a61965b..643f0ebadf9c 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -239,6 +239,13 @@ enum x86_transfer_type {
X86_TRANSFER_TASK_SWITCH,
};
+enum {
+ REX_B = 1,
+ REX_X = 2,
+ REX_R = 4,
+ REX_W = 8,
+};
+
static void writeback_registers(struct x86_emulate_ctxt *ctxt)
{
unsigned long dirty = ctxt->regs_dirty;
@@ -919,7 +926,7 @@ static void *decode_register(struct x86_emulate_ctxt *ctxt, u8 modrm_reg,
int byteop)
{
void *p;
- int highbyte_regs = (ctxt->rex_prefix == 0) && byteop;
+ int highbyte_regs = (ctxt->rex_prefix == REX_NONE) && byteop;
if (highbyte_regs && modrm_reg >= 4 && modrm_reg < 8)
p = (unsigned char *)reg_rmw(ctxt, modrm_reg & 3) + 1;
@@ -1110,7 +1117,7 @@ static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
if (ctxt->d & ModRM)
reg = ctxt->modrm_reg;
else
- reg = (ctxt->b & 7) | ((ctxt->rex_prefix & 1) << 3);
+ reg = (ctxt->b & 7) | (ctxt->rex_bits & REX_B ? 8 : 0);
__decode_register_operand(ctxt, op, reg);
}
@@ -1129,9 +1136,9 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
int rc = X86EMUL_CONTINUE;
ulong modrm_ea = 0;
- ctxt->modrm_reg = ((ctxt->rex_prefix << 1) & 8); /* REX.R */
- index_reg = (ctxt->rex_prefix << 2) & 8; /* REX.X */
- base_reg = (ctxt->rex_prefix << 3) & 8; /* REX.B */
+ ctxt->modrm_reg = (ctxt->rex_bits & REX_R ? 8 : 0);
+ index_reg = (ctxt->rex_bits & REX_X ? 8 : 0);
+ base_reg = (ctxt->rex_bits & REX_B ? 8 : 0);
ctxt->modrm_mod = (ctxt->modrm & 0xc0) >> 6;
ctxt->modrm_reg |= (ctxt->modrm & 0x38) >> 3;
@@ -2464,7 +2471,7 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
setup_syscalls_segments(&cs, &ss);
- if ((ctxt->rex_prefix & 0x8) != 0x0)
+ if (ctxt->rex_bits & REX_W)
usermode = X86EMUL_MODE_PROT64;
else
usermode = X86EMUL_MODE_PROT32;
@@ -4850,7 +4857,8 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
case 0x40 ... 0x4f: /* REX */
if (mode != X86EMUL_MODE_PROT64)
goto done_prefixes;
- ctxt->rex_prefix = ctxt->b;
+ ctxt->rex_prefix = REX_PREFIX;
+ ctxt->rex_bits = ctxt->b & 0xf;
continue;
case 0xf0: /* LOCK */
ctxt->lock_prefix = 1;
@@ -4864,15 +4872,15 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
}
/* Any legacy prefix after a REX prefix nullifies its effect. */
-
- ctxt->rex_prefix = 0;
+ ctxt->rex_prefix = REX_NONE;
+ ctxt->rex_bits = 0;
}
done_prefixes:
/* REX prefix. */
- if (ctxt->rex_prefix & 8)
- ctxt->op_bytes = 8; /* REX.W */
+ if (ctxt->rex_bits & REX_W)
+ ctxt->op_bytes = 8;
/* Opcode byte(s). */
if (ctxt->b == 0x0f) {
@@ -5138,7 +5146,8 @@ void init_decode_cache(struct x86_emulate_ctxt *ctxt)
{
/* Clear fields that are set conditionally but read without a guard. */
ctxt->rip_relative = false;
- ctxt->rex_prefix = 0;
+ ctxt->rex_prefix = REX_NONE;
+ ctxt->rex_bits = 0;
ctxt->lock_prefix = 0;
ctxt->op_prefix = false;
ctxt->rep_prefix = 0;
diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h
index c526f46f5595..fb3dab4b5a53 100644
--- a/arch/x86/kvm/kvm_emulate.h
+++ b/arch/x86/kvm/kvm_emulate.h
@@ -319,6 +319,14 @@ typedef void (*fastop_t)(struct fastop *);
#define NR_EMULATOR_GPRS 8
#endif
+/*
+ * Distinguish between no prefix, REX, or in the future REX2.
+ */
+enum rex_type {
+ REX_NONE,
+ REX_PREFIX,
+};
+
struct x86_emulate_ctxt {
void *vcpu;
const struct x86_emulate_ops *ops;
@@ -360,7 +368,8 @@ struct x86_emulate_ctxt {
int (*check_perm)(struct x86_emulate_ctxt *ctxt);
bool rip_relative;
- u8 rex_prefix;
+ enum rex_type rex_prefix;
+ u8 rex_bits;
u8 lock_prefix;
u8 rep_prefix;
/* bitmaps of registers in _regs[] that can be read */
--
2.43.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 09/10] KVM: emulate: decode VEX prefix
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
` (7 preceding siblings ...)
2025-11-14 0:36 ` [PATCH 08/10] KVM: x86: Refactor REX prefix handling in instruction emulation Paolo Bonzini
@ 2025-11-14 0:36 ` Paolo Bonzini
2025-11-14 0:36 ` [PATCH 10/10] KVM: emulate: enable AVX moves Paolo Bonzini
` (3 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Paolo Bonzini @ 2025-11-14 0:36 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: kbusch, chang.seok.bae
After all the changes done in the previous patches, the only thing
left to support AVX moves is to expand the VEX prefix into the appropriate
REX, 66/F3/F2 and map prefixes. Three-operand instructions are not
supported.
The Avx bit in this case is not cleared, in fact it is used as the
sign that the instruction does support VEX encoding. Until it is
added to any instruction, however, the only functional change is
to change some not-implemented instructions to #UD if they correspond
to a VEX prefix with an invalid map.
Co-developed-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/emulate.c | 123 +++++++++++++++++++++++++++++++++++++----
1 file changed, 113 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 643f0ebadf9c..1e17043a6304 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3963,6 +3963,8 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
I2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock, _e), \
I2bv(((_f) & ~Lock) | DstAcc | SrcImm, _e)
+static const struct opcode ud = I(SrcNone, emulate_ud);
+
static const struct opcode group7_rm0[] = {
N,
I(SrcNone | Priv | EmulateOnUD, em_hypercall),
@@ -4762,11 +4765,87 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
return rc;
}
+static int x86_decode_avx(struct x86_emulate_ctxt *ctxt,
+ u8 vex_1st, u8 vex_2nd, struct opcode *opcode)
+{
+ u8 vex_3rd, map, pp, l, v;
+ int rc = X86EMUL_CONTINUE;
+
+ if (ctxt->rep_prefix || ctxt->op_prefix || ctxt->rex_prefix)
+ goto ud;
+
+ if (vex_1st == 0xc5) {
+ /* Expand RVVVVlpp to VEX3 format */
+ vex_3rd = vex_2nd & ~0x80; /* VVVVlpp from VEX2, w=0 */
+ vex_2nd = (vex_2nd & 0x80) | 0x61; /* R from VEX2, X=1 B=1 mmmmm=00001 */
+ } else {
+ vex_3rd = insn_fetch(u8, ctxt);
+ }
+
+ /* vex_2nd = RXBmmmmm, vex_3rd = wVVVVlpp. Fix polarity */
+ vex_2nd ^= 0xE0; /* binary 11100000 */
+ vex_3rd ^= 0x78; /* binary 01111000 */
+
+ ctxt->rex_prefix = REX_PREFIX;
+ ctxt->rex_bits = (vex_2nd & 0xE0) >> 5; /* RXB */
+ ctxt->rex_bits |= (vex_3rd & 0x80) >> 4; /* w */
+ if (ctxt->rex_bits && ctxt->mode != X86EMUL_MODE_PROT64)
+ goto ud;
+
+ map = vex_2nd & 0x1f;
+ v = (vex_3rd >> 3) & 0xf;
+ l = vex_3rd & 0x4;
+ pp = vex_3rd & 0x3;
+
+ ctxt->b = insn_fetch(u8, ctxt);
+ switch (map) {
+ case 1:
+ ctxt->opcode_len = 2;
+ *opcode = twobyte_table[ctxt->b];
+ break;
+ case 2:
+ ctxt->opcode_len = 3;
+ *opcode = opcode_map_0f_38[ctxt->b];
+ break;
+ case 3:
+ /* no 0f 3a instructions are supported yet */
+ return X86EMUL_UNHANDLEABLE;
+ default:
+ goto ud;
+ }
+
+ /*
+ * No three operand instructions are supported yet; those that
+ * *are* marked with the Avx flag reserve the VVVV flag.
+ */
+ if (v)
+ goto ud;
+
+ if (l)
+ ctxt->op_bytes = 32;
+ else
+ ctxt->op_bytes = 16;
+
+ switch (pp) {
+ case 0: break;
+ case 1: ctxt->op_prefix = true; break;
+ case 2: ctxt->rep_prefix = 0xf3; break;
+ case 3: ctxt->rep_prefix = 0xf2; break;
+ }
+
+done:
+ return rc;
+ud:
+ *opcode = ud;
+ return rc;
+}
+
int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int emulation_type)
{
int rc = X86EMUL_CONTINUE;
int mode = ctxt->mode;
int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
+ bool vex_prefix = false;
bool has_seg_override = false;
struct opcode opcode;
u16 dummy;
@@ -4883,7 +4962,21 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
ctxt->op_bytes = 8;
/* Opcode byte(s). */
- if (ctxt->b == 0x0f) {
+ if (ctxt->b == 0xc4 || ctxt->b == 0xc5) {
+ /* VEX or LDS/LES */
+ u8 vex_2nd = insn_fetch(u8, ctxt);
+ if (mode != X86EMUL_MODE_PROT64 && (vex_2nd & 0xc0) != 0xc0) {
+ opcode = opcode_table[ctxt->b];
+ ctxt->modrm = vex_2nd;
+ /* the Mod/RM byte has been fetched already! */
+ goto done_modrm;
+ }
+
+ vex_prefix = true;
+ rc = x86_decode_avx(ctxt, ctxt->b, vex_2nd, &opcode);
+ if (rc != X86EMUL_CONTINUE)
+ goto done;
+ } else if (ctxt->b == 0x0f) {
/* Two- or three-byte opcode */
ctxt->opcode_len = 2;
ctxt->b = insn_fetch(u8, ctxt);
@@ -4899,17 +4992,12 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
/* Opcode byte(s). */
opcode = opcode_table[ctxt->b];
}
- ctxt->d = opcode.flags;
- if (ctxt->d & ModRM)
+ if (opcode.flags & ModRM)
ctxt->modrm = insn_fetch(u8, ctxt);
- /* vex-prefix instructions are not implemented */
- if (ctxt->opcode_len == 1 && (ctxt->b == 0xc5 || ctxt->b == 0xc4) &&
- (mode == X86EMUL_MODE_PROT64 || (ctxt->modrm & 0xc0) == 0xc0)) {
- ctxt->d = NotImpl;
- }
-
+done_modrm:
+ ctxt->d = opcode.flags;
while (ctxt->d & GroupMask) {
switch (ctxt->d & GroupMask) {
case Group:
@@ -4975,6 +5063,19 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
if (ctxt->d == 0)
return EMULATION_FAILED;
+ if (unlikely(vex_prefix)) {
+ /*
+ * Only specifically marked instructions support VEX. Since many
+ * instructions support it but are not annotated, return not implemented
+ * rather than #UD.
+ */
+ if (!(ctxt->d & Avx))
+ return EMULATION_FAILED;
+
+ if (!(ctxt->d & AlignMask))
+ ctxt->d |= Unaligned;
+ }
+
ctxt->execute = opcode.u.execute;
/*
@@ -5045,7 +5146,9 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
if ((ctxt->d & No16) && ctxt->op_bytes == 2)
ctxt->op_bytes = 4;
- if (ctxt->d & Sse)
+ if (vex_prefix)
+ ;
+ else if (ctxt->d & Sse)
ctxt->op_bytes = 16, ctxt->d &= ~Avx;
else if (ctxt->d & Mmx)
ctxt->op_bytes = 8;
--
2.43.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 10/10] KVM: emulate: enable AVX moves
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
` (8 preceding siblings ...)
2025-11-14 0:36 ` [PATCH 09/10] KVM: emulate: decode VEX prefix Paolo Bonzini
@ 2025-11-14 0:36 ` Paolo Bonzini
2025-11-14 0:51 ` [PATCH 00/10] " Keith Busch
` (2 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Paolo Bonzini @ 2025-11-14 0:36 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: kbusch, chang.seok.bae
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>
---
arch/x86/kvm/emulate.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 1e17043a6304..75619bdc600f 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -4122,7 +4122,7 @@ static const struct group_dual group15 = { {
} };
static const struct gprefix pfx_0f_6f_0f_7f = {
- I(Mmx, em_mov), I(Sse | Aligned, em_mov), N, I(Sse | Unaligned, em_mov),
+ I(Mmx, em_mov), I(Sse | Avx | Aligned, em_mov), N, I(Sse | Avx | Unaligned, em_mov),
};
static const struct instr_dual instr_dual_0f_2b = {
@@ -4142,7 +4142,7 @@ static const struct gprefix pfx_0f_28_0f_29 = {
};
static const struct gprefix pfx_0f_e7_0f_38_2a = {
- N, I(Sse, em_mov), N, N,
+ N, I(Sse | Avx, em_mov), N, N,
};
static const struct escape escape_d9 = { {
@@ -4355,8 +4355,8 @@ static const struct opcode twobyte_table[256] = {
DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N,
N, D(ImplicitOps | ModRM | SrcMem | NoAccess), N, N,
/* 0x10 - 0x1F */
- GP(ModRM | DstReg | SrcMem | Mov | Sse, &pfx_0f_10_0f_11),
- GP(ModRM | DstMem | SrcReg | Mov | Sse, &pfx_0f_10_0f_11),
+ GP(ModRM | DstReg | SrcMem | Mov | Sse | Avx, &pfx_0f_10_0f_11),
+ GP(ModRM | DstMem | SrcReg | Mov | Sse | Avx, &pfx_0f_10_0f_11),
N, N, N, N, N, N,
D(ImplicitOps | ModRM | SrcMem | NoAccess), /* 4 * prefetch + 4 * reserved NOP */
D(ImplicitOps | ModRM | SrcMem | NoAccess), N, N,
@@ -4372,9 +4372,9 @@ static const struct opcode twobyte_table[256] = {
IIP(ModRM | SrcMem | Priv | Op3264 | NoMod, em_dr_write, dr_write,
check_dr_write),
N, N, N, N,
- GP(ModRM | DstReg | SrcMem | Mov | Sse, &pfx_0f_28_0f_29),
- GP(ModRM | DstMem | SrcReg | Mov | Sse, &pfx_0f_28_0f_29),
- N, GP(ModRM | DstMem | SrcReg | Mov | Sse, &pfx_0f_2b),
+ GP(ModRM | DstReg | SrcMem | Mov | Sse | Avx, &pfx_0f_28_0f_29),
+ GP(ModRM | DstMem | SrcReg | Mov | Sse | Avx, &pfx_0f_28_0f_29),
+ N, GP(ModRM | DstMem | SrcReg | Mov | Sse | Avx, &pfx_0f_2b),
N, N, N, N,
/* 0x30 - 0x3F */
II(ImplicitOps | Priv, em_wrmsr, wrmsr),
--
2.43.5
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH 00/10] KVM: emulate: enable AVX moves
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
` (9 preceding siblings ...)
2025-11-14 0:36 ` [PATCH 10/10] KVM: emulate: enable AVX moves Paolo Bonzini
@ 2025-11-14 0:51 ` Keith Busch
2025-11-17 19:57 ` Chang S. Bae
2025-11-21 18:55 ` Sean Christopherson
12 siblings, 0 replies; 22+ messages in thread
From: Keith Busch @ 2025-11-14 0:51 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: linux-kernel, kvm, chang.seok.bae
On Thu, Nov 13, 2025 at 07:36:23PM -0500, Paolo Bonzini wrote:
> Over a year ago, Keith Busch posted an RFC patch to enable VMOVDQA
> and VMOVDQU instructions in the KVM emulator. The reason to do so
> is that people are using QEMU to emulate fancy devices whose drivers
> use those instructions with BARs that, on real hardware, would
> presumably support write combining. These same people obviously
> would appreciate being able to use KVM instead of emulation, hence
> the request.
Thanks so much! We do still use this, so I'm happy to see this moving. I
know it's been some time in the making, but I can appreciate this is
pretty gnarly and the details are important. I will be happy to give
this a run through the emulation devices, though it may be another week
or so before I can give it a spin.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 07/10] KVM: emulate: add AVX support to register fetch and writeback
2025-11-14 0:36 ` [PATCH 07/10] KVM: emulate: add AVX support to register fetch and writeback Paolo Bonzini
@ 2025-11-14 17:06 ` kernel test robot
2025-11-14 20:10 ` kernel test robot
1 sibling, 0 replies; 22+ messages in thread
From: kernel test robot @ 2025-11-14 17:06 UTC (permalink / raw)
To: Paolo Bonzini, linux-kernel, kvm
Cc: llvm, oe-kbuild-all, kbusch, chang.seok.bae
Hi Paolo,
kernel test robot noticed the following build errors:
[auto build test ERROR on v6.18-rc5]
[also build test ERROR on linus/master next-20251114]
[cannot apply to kvm/queue kvm/next mst-vhost/linux-next kvm/linux-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Paolo-Bonzini/KVM-emulate-add-MOVNTDQA/20251114-084216
base: v6.18-rc5
patch link: https://lore.kernel.org/r/20251114003633.60689-8-pbonzini%40redhat.com
patch subject: [PATCH 07/10] KVM: emulate: add AVX support to register fetch and writeback
config: i386-buildonly-randconfig-002-20251114 (https://download.01.org/0day-ci/archive/20251115/202511150016.KszKz14N-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251115/202511150016.KszKz14N-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511150016.KszKz14N-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
>> arch/x86/kvm/fpu.h:60:15: error: register %ymm14 is only available in 64-bit mode
60 | case 14: asm("vmovdqa %0, %%ymm14" : : "m"(*data)); break;
| ^
<inline asm>:1:20: note: instantiated into assembly here
1 | vmovdqa 32(%esi), %ymm14
| ^~~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
>> arch/x86/kvm/fpu.h:57:15: error: register %ymm11 is only available in 64-bit mode
57 | case 11: asm("vmovdqa %0, %%ymm11" : : "m"(*data)); break;
| ^
<inline asm>:1:20: note: instantiated into assembly here
1 | vmovdqa 32(%esi), %ymm11
| ^~~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
>> arch/x86/kvm/fpu.h:58:15: error: register %ymm12 is only available in 64-bit mode
58 | case 12: asm("vmovdqa %0, %%ymm12" : : "m"(*data)); break;
| ^
<inline asm>:1:20: note: instantiated into assembly here
1 | vmovdqa 32(%esi), %ymm12
| ^~~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
>> arch/x86/kvm/fpu.h:55:15: error: register %ymm9 is only available in 64-bit mode
55 | case 9: asm("vmovdqa %0, %%ymm9" : : "m"(*data)); break;
| ^
<inline asm>:1:20: note: instantiated into assembly here
1 | vmovdqa 32(%esi), %ymm9
| ^~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
>> arch/x86/kvm/fpu.h:61:15: error: register %ymm15 is only available in 64-bit mode
61 | case 15: asm("vmovdqa %0, %%ymm15" : : "m"(*data)); break;
| ^
<inline asm>:1:20: note: instantiated into assembly here
1 | vmovdqa 32(%esi), %ymm15
| ^~~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
>> arch/x86/kvm/fpu.h:59:15: error: register %ymm13 is only available in 64-bit mode
59 | case 13: asm("vmovdqa %0, %%ymm13" : : "m"(*data)); break;
| ^
<inline asm>:1:20: note: instantiated into assembly here
1 | vmovdqa 32(%esi), %ymm13
| ^~~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
>> arch/x86/kvm/fpu.h:56:15: error: register %ymm10 is only available in 64-bit mode
56 | case 10: asm("vmovdqa %0, %%ymm10" : : "m"(*data)); break;
| ^
<inline asm>:1:20: note: instantiated into assembly here
1 | vmovdqa 32(%esi), %ymm10
| ^~~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
>> arch/x86/kvm/fpu.h:54:15: error: register %ymm8 is only available in 64-bit mode
54 | case 8: asm("vmovdqa %0, %%ymm8" : : "m"(*data)); break;
| ^
<inline asm>:1:20: note: instantiated into assembly here
1 | vmovdqa 32(%esi), %ymm8
| ^~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
arch/x86/kvm/fpu.h:37:15: error: register %ymm14 is only available in 64-bit mode
37 | case 14: asm("vmovdqa %%ymm14, %0" : "=m"(*data)); break;
| ^
<inline asm>:1:10: note: instantiated into assembly here
1 | vmovdqa %ymm14, 32(%esi)
| ^~~~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
arch/x86/kvm/fpu.h:34:15: error: register %ymm11 is only available in 64-bit mode
34 | case 11: asm("vmovdqa %%ymm11, %0" : "=m"(*data)); break;
| ^
<inline asm>:1:10: note: instantiated into assembly here
1 | vmovdqa %ymm11, 32(%esi)
| ^~~~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
arch/x86/kvm/fpu.h:35:15: error: register %ymm12 is only available in 64-bit mode
35 | case 12: asm("vmovdqa %%ymm12, %0" : "=m"(*data)); break;
| ^
<inline asm>:1:10: note: instantiated into assembly here
1 | vmovdqa %ymm12, 32(%esi)
| ^~~~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
arch/x86/kvm/fpu.h:32:15: error: register %ymm9 is only available in 64-bit mode
32 | case 9: asm("vmovdqa %%ymm9, %0" : "=m"(*data)); break;
| ^
<inline asm>:1:10: note: instantiated into assembly here
1 | vmovdqa %ymm9, 32(%esi)
| ^~~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
arch/x86/kvm/fpu.h:38:15: error: register %ymm15 is only available in 64-bit mode
38 | case 15: asm("vmovdqa %%ymm15, %0" : "=m"(*data)); break;
| ^
<inline asm>:1:10: note: instantiated into assembly here
1 | vmovdqa %ymm15, 32(%esi)
| ^~~~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
arch/x86/kvm/fpu.h:36:15: error: register %ymm13 is only available in 64-bit mode
36 | case 13: asm("vmovdqa %%ymm13, %0" : "=m"(*data)); break;
| ^
<inline asm>:1:10: note: instantiated into assembly here
1 | vmovdqa %ymm13, 32(%esi)
| ^~~~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
arch/x86/kvm/fpu.h:33:15: error: register %ymm10 is only available in 64-bit mode
33 | case 10: asm("vmovdqa %%ymm10, %0" : "=m"(*data)); break;
| ^
<inline asm>:1:10: note: instantiated into assembly here
1 | vmovdqa %ymm10, 32(%esi)
| ^~~~~~~
In file included from arch/x86/kvm/emulate.c:24:
In file included from arch/x86/kvm/kvm_emulate.h:16:
arch/x86/kvm/fpu.h:31:15: error: register %ymm8 is only available in 64-bit mode
31 | case 8: asm("vmovdqa %%ymm8, %0" : "=m"(*data)); break;
| ^
<inline asm>:1:10: note: instantiated into assembly here
1 | vmovdqa %ymm8, 32(%esi)
| ^~~~~~
16 errors generated.
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for I2C_K1
Depends on [n]: I2C [=y] && HAS_IOMEM [=y] && (ARCH_SPACEMIT || COMPILE_TEST [=y]) && OF [=n]
Selected by [m]:
- MFD_SPACEMIT_P1 [=m] && HAS_IOMEM [=y] && (ARCH_SPACEMIT || COMPILE_TEST [=y]) && I2C [=y]
vim +60 arch/x86/kvm/fpu.h
42
43 static inline void _kvm_write_avx_reg(int reg, const avx256_t *data)
44 {
45 switch (reg) {
46 case 0: asm("vmovdqa %0, %%ymm0" : : "m"(*data)); break;
47 case 1: asm("vmovdqa %0, %%ymm1" : : "m"(*data)); break;
48 case 2: asm("vmovdqa %0, %%ymm2" : : "m"(*data)); break;
49 case 3: asm("vmovdqa %0, %%ymm3" : : "m"(*data)); break;
50 case 4: asm("vmovdqa %0, %%ymm4" : : "m"(*data)); break;
51 case 5: asm("vmovdqa %0, %%ymm5" : : "m"(*data)); break;
52 case 6: asm("vmovdqa %0, %%ymm6" : : "m"(*data)); break;
53 case 7: asm("vmovdqa %0, %%ymm7" : : "m"(*data)); break;
> 54 case 8: asm("vmovdqa %0, %%ymm8" : : "m"(*data)); break;
> 55 case 9: asm("vmovdqa %0, %%ymm9" : : "m"(*data)); break;
> 56 case 10: asm("vmovdqa %0, %%ymm10" : : "m"(*data)); break;
> 57 case 11: asm("vmovdqa %0, %%ymm11" : : "m"(*data)); break;
> 58 case 12: asm("vmovdqa %0, %%ymm12" : : "m"(*data)); break;
> 59 case 13: asm("vmovdqa %0, %%ymm13" : : "m"(*data)); break;
> 60 case 14: asm("vmovdqa %0, %%ymm14" : : "m"(*data)); break;
> 61 case 15: asm("vmovdqa %0, %%ymm15" : : "m"(*data)); break;
62 default: BUG();
63 }
64 }
65
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 07/10] KVM: emulate: add AVX support to register fetch and writeback
2025-11-14 0:36 ` [PATCH 07/10] KVM: emulate: add AVX support to register fetch and writeback Paolo Bonzini
2025-11-14 17:06 ` kernel test robot
@ 2025-11-14 20:10 ` kernel test robot
1 sibling, 0 replies; 22+ messages in thread
From: kernel test robot @ 2025-11-14 20:10 UTC (permalink / raw)
To: Paolo Bonzini, linux-kernel, kvm; +Cc: oe-kbuild-all, kbusch, chang.seok.bae
Hi Paolo,
kernel test robot noticed the following build errors:
[auto build test ERROR on v6.18-rc5]
[also build test ERROR on linus/master next-20251114]
[cannot apply to kvm/queue kvm/next mst-vhost/linux-next kvm/linux-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Paolo-Bonzini/KVM-emulate-add-MOVNTDQA/20251114-084216
base: v6.18-rc5
patch link: https://lore.kernel.org/r/20251114003633.60689-8-pbonzini%40redhat.com
patch subject: [PATCH 07/10] KVM: emulate: add AVX support to register fetch and writeback
config: i386-buildonly-randconfig-006-20251114 (https://download.01.org/0day-ci/archive/20251115/202511150213.HaLLVfkt-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251115/202511150213.HaLLVfkt-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511150213.HaLLVfkt-lkp@intel.com/
All errors (new ones prefixed by >>):
arch/x86/kvm/fpu.h: Assembler messages:
>> arch/x86/kvm/fpu.h:37: Error: bad register name `%ymm14'
>> arch/x86/kvm/fpu.h:36: Error: bad register name `%ymm13'
>> arch/x86/kvm/fpu.h:38: Error: bad register name `%ymm15'
>> arch/x86/kvm/fpu.h:35: Error: bad register name `%ymm12'
>> arch/x86/kvm/fpu.h:34: Error: bad register name `%ymm11'
>> arch/x86/kvm/fpu.h:33: Error: bad register name `%ymm10'
>> arch/x86/kvm/fpu.h:32: Error: bad register name `%ymm9'
>> arch/x86/kvm/fpu.h:31: Error: bad register name `%ymm8'
arch/x86/kvm/fpu.h:58: Error: bad register name `%ymm12'
arch/x86/kvm/fpu.h:59: Error: bad register name `%ymm13'
arch/x86/kvm/fpu.h:54: Error: bad register name `%ymm8'
arch/x86/kvm/fpu.h:55: Error: bad register name `%ymm9'
arch/x86/kvm/fpu.h:56: Error: bad register name `%ymm10'
arch/x86/kvm/fpu.h:57: Error: bad register name `%ymm11'
arch/x86/kvm/fpu.h:61: Error: bad register name `%ymm15'
arch/x86/kvm/fpu.h:60: Error: bad register name `%ymm14'
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for I2C_K1
Depends on [n]: I2C [=y] && HAS_IOMEM [=y] && (ARCH_SPACEMIT || COMPILE_TEST [=y]) && OF [=n]
Selected by [y]:
- MFD_SPACEMIT_P1 [=y] && HAS_IOMEM [=y] && (ARCH_SPACEMIT || COMPILE_TEST [=y]) && I2C [=y]
vim +37 arch/x86/kvm/fpu.h
19
20 static inline void _kvm_read_avx_reg(int reg, avx256_t *data)
21 {
22 switch (reg) {
23 case 0: asm("vmovdqa %%ymm0, %0" : "=m"(*data)); break;
24 case 1: asm("vmovdqa %%ymm1, %0" : "=m"(*data)); break;
25 case 2: asm("vmovdqa %%ymm2, %0" : "=m"(*data)); break;
26 case 3: asm("vmovdqa %%ymm3, %0" : "=m"(*data)); break;
27 case 4: asm("vmovdqa %%ymm4, %0" : "=m"(*data)); break;
28 case 5: asm("vmovdqa %%ymm5, %0" : "=m"(*data)); break;
29 case 6: asm("vmovdqa %%ymm6, %0" : "=m"(*data)); break;
30 case 7: asm("vmovdqa %%ymm7, %0" : "=m"(*data)); break;
> 31 case 8: asm("vmovdqa %%ymm8, %0" : "=m"(*data)); break;
> 32 case 9: asm("vmovdqa %%ymm9, %0" : "=m"(*data)); break;
> 33 case 10: asm("vmovdqa %%ymm10, %0" : "=m"(*data)); break;
> 34 case 11: asm("vmovdqa %%ymm11, %0" : "=m"(*data)); break;
> 35 case 12: asm("vmovdqa %%ymm12, %0" : "=m"(*data)); break;
> 36 case 13: asm("vmovdqa %%ymm13, %0" : "=m"(*data)); break;
> 37 case 14: asm("vmovdqa %%ymm14, %0" : "=m"(*data)); break;
> 38 case 15: asm("vmovdqa %%ymm15, %0" : "=m"(*data)); break;
39 default: BUG();
40 }
41 }
42
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 02/10] KVM: emulate: move Src2Shift up one bit
2025-11-14 0:36 ` [PATCH 02/10] KVM: emulate: move Src2Shift up one bit Paolo Bonzini
@ 2025-11-17 19:51 ` Chang S. Bae
0 siblings, 0 replies; 22+ messages in thread
From: Chang S. Bae @ 2025-11-17 19:51 UTC (permalink / raw)
To: Paolo Bonzini, linux-kernel, kvm; +Cc: kbusch
On 11/13/2025 4:36 PM, Paolo Bonzini wrote:
> An irresistible microoptimization (changing accesses to Src2 to just an
> AND :)) that also frees a bit for AVX in the low flags word. This makes
> it closer to SSE since both of them can access XMM registers, pointlessly
> shaving another clock cycle or two (maybe).
>
> No functional change intended.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Yes, this looks sane to me as well:
Reviewed-by: Chang S. Bae <chang.seok.bae@intel.com
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 03/10] KVM: emulate: improve formatting of flags table
2025-11-14 0:36 ` [PATCH 03/10] KVM: emulate: improve formatting of flags table Paolo Bonzini
@ 2025-11-17 19:53 ` Chang S. Bae
0 siblings, 0 replies; 22+ messages in thread
From: Chang S. Bae @ 2025-11-17 19:53 UTC (permalink / raw)
To: Paolo Bonzini, linux-kernel, kvm; +Cc: kbusch
On 11/13/2025 4:36 PM, Paolo Bonzini wrote:
> Align a little better the comments on the right side and list
> explicitly the bits used by multi-bit fields.
>
> No functional change intended.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Thanks for aligning those comments and clarifying reserved bits. This
will definitely help folks who are considering adding new flags.
Reviewed-by: Chang S. Bae <chang.seok.bae@intel.com>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 04/10] KVM: emulate: move op_prefix to struct x86_emulate_ctxt
2025-11-14 0:36 ` [PATCH 04/10] KVM: emulate: move op_prefix to struct x86_emulate_ctxt Paolo Bonzini
@ 2025-11-17 19:54 ` Chang S. Bae
0 siblings, 0 replies; 22+ messages in thread
From: Chang S. Bae @ 2025-11-17 19:54 UTC (permalink / raw)
To: Paolo Bonzini, linux-kernel, kvm; +Cc: kbusch
On 11/13/2025 4:36 PM, Paolo Bonzini wrote:
> VEX decode will need to set it based on the "pp" bits, so make it
> a field in the struct rather than a local variable.
>
> No functional change intended.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Chang S. Bae <chang.seok.bae@intel.com>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 05/10] KVM: emulate: share common register decoding code
2025-11-14 0:36 ` [PATCH 05/10] KVM: emulate: share common register decoding code Paolo Bonzini
@ 2025-11-17 19:55 ` Chang S. Bae
0 siblings, 0 replies; 22+ messages in thread
From: Chang S. Bae @ 2025-11-17 19:55 UTC (permalink / raw)
To: Paolo Bonzini, linux-kernel, kvm; +Cc: kbusch
On 11/13/2025 4:36 PM, Paolo Bonzini wrote:
> Remove all duplicate handling of register operands, including picking
> the right register class and fetching it, by extracting a new function
> that can be used for both REG and MODRM operands.
>
> Centralize setting op->orig_val = op->val in fetch_register_operand()
> as well.
>
> No functional change intended.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Looks like a very nice refactoring to me:
Reviewed-by: Chang S. Bae <chang.seok.bae@intel.com>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 06/10] KVM: emulate: add get_xcr callback
2025-11-14 0:36 ` [PATCH 06/10] KVM: emulate: add get_xcr callback Paolo Bonzini
@ 2025-11-17 19:56 ` Chang S. Bae
0 siblings, 0 replies; 22+ messages in thread
From: Chang S. Bae @ 2025-11-17 19:56 UTC (permalink / raw)
To: Paolo Bonzini, linux-kernel, kvm; +Cc: kbusch
On 11/13/2025 4:36 PM, Paolo Bonzini wrote:
> This will be necessary in order to check whether AVX is enabled.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Indeed, REX2 emulation support also needs this to check APX. Thanks!
Reviewed-by: Chang S. Bae <chang.seok.bae@intel.com>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 08/10] KVM: x86: Refactor REX prefix handling in instruction emulation
2025-11-14 0:36 ` [PATCH 08/10] KVM: x86: Refactor REX prefix handling in instruction emulation Paolo Bonzini
@ 2025-11-17 19:56 ` Chang S. Bae
0 siblings, 0 replies; 22+ messages in thread
From: Chang S. Bae @ 2025-11-17 19:56 UTC (permalink / raw)
To: Paolo Bonzini, linux-kernel, kvm; +Cc: kbusch
On 11/13/2025 4:36 PM, Paolo Bonzini wrote:
> From: "Chang S. Bae" <chang.seok.bae@intel.com>
>
> Restructure how to represent and interpret REX fields, preparing
> for handling of both REX2 and VEX.
>
> REX uses the upper four bits of a single byte as a fixed identifier,
> and the lower four bits containing the data. VEX and REX2 extends this so
> that the first byte identifies the prefix and the rest encode additional
> bits; and while VEX only has the same four data bits as REX, eight zero
> bits are a valid value for the data bits of REX2. So, stop storing the
> REX byte as-is. Instead, store only the low bits of the REX prefix and
> track separately whether a REX-like prefix was used.
>
> No functional changes intended.
>
> Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
> Message-ID: <20251110180131.28264-11-chang.seok.bae@intel.com>
> [Extracted from APX series; removed bitfields and REX2-specific default. - Paolo]
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Thanks for the incorporation!
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 00/10] KVM: emulate: enable AVX moves
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
` (10 preceding siblings ...)
2025-11-14 0:51 ` [PATCH 00/10] " Keith Busch
@ 2025-11-17 19:57 ` Chang S. Bae
2025-11-21 18:55 ` Sean Christopherson
12 siblings, 0 replies; 22+ messages in thread
From: Chang S. Bae @ 2025-11-17 19:57 UTC (permalink / raw)
To: Paolo Bonzini, linux-kernel, kvm; +Cc: kbusch
On 11/13/2025 4:36 PM, Paolo Bonzini wrote:
>
> While at it I also included a small refactoring taken out of the
> APX series, by Chang S. Bae, some cleanups, and an extra MOVNTDQ
> instruction.
As I'm preparing REX2 support, appreciate this effort! I’ve added my
review tag for the obvious and nice cleanups.
I can also look further at the VEX pieces and other related bits, and
would like to follow up with test tags unless anything else comes up.
Thanks,
Chang
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 00/10] KVM: emulate: enable AVX moves
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
` (11 preceding siblings ...)
2025-11-17 19:57 ` Chang S. Bae
@ 2025-11-21 18:55 ` Sean Christopherson
12 siblings, 0 replies; 22+ messages in thread
From: Sean Christopherson @ 2025-11-21 18:55 UTC (permalink / raw)
To: Sean Christopherson, linux-kernel, kvm, Paolo Bonzini
Cc: kbusch, chang.seok.bae
On Thu, 13 Nov 2025 19:36:23 -0500, Paolo Bonzini wrote:
> Over a year ago, Keith Busch posted an RFC patch to enable VMOVDQA
> and VMOVDQU instructions in the KVM emulator. The reason to do so
> is that people are using QEMU to emulate fancy devices whose drivers
> use those instructions with BARs that, on real hardware, would
> presumably support write combining. These same people obviously
> would appreciate being able to use KVM instead of emulation, hence
> the request.
>
> [...]
Applied to kvm-x86 misc, with massaged shortlogs to make it obvious these are
x86 changes.
[1/10] KVM: x86: Add support for emulating MOVNTDQA
https://github.com/kvm-x86/linux/commit/c57d9bafbd0b
[2/10] KVM: x86: Move Src2Shift up one bit (use bits 36:32 for Src2 in the emulator)
https://github.com/kvm-x86/linux/commit/3f3fc58df502
[3/10] KVM: x86: Improve formatting of the emulator's flags table
https://github.com/kvm-x86/linux/commit/3d8834a0d1c9
[4/10] KVM: x86: Move op_prefix to struct x86_emulate_ctxt (from x86_decode_insn())
https://github.com/kvm-x86/linux/commit/1a84b07acaa4
[5/10] KVM: x86: Share emulator's common register decoding code
https://github.com/kvm-x86/linux/commit/7e11eec989c8
[6/10] KVM: x86: Add x86_emulate_ops.get_xcr() callback
https://github.com/kvm-x86/linux/commit/f106797f81d6
[7/10] KVM: x86: Add AVX support to the emulator's register fetch and writeback
https://github.com/kvm-x86/linux/commit/4cb21be4c3b0
[8/10] KVM: x86: Refactor REX prefix handling in instruction emulation
https://github.com/kvm-x86/linux/commit/825f0aece084
[9/10] KVM: x86: Add emulator support for decoding VEX prefixes
https://github.com/kvm-x86/linux/commit/f0585a714a75
[10/10] KVM: x86: Enable support for emulating AVX MOV instructions
https://github.com/kvm-x86/linux/commit/ebec25438f3d
--
https://github.com/kvm-x86/linux/tree/next
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2025-11-21 18:56 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-14 0:36 [PATCH 00/10] KVM: emulate: enable AVX moves Paolo Bonzini
2025-11-14 0:36 ` [PATCH 01/10] KVM: emulate: add MOVNTDQA Paolo Bonzini
2025-11-14 0:36 ` [PATCH 02/10] KVM: emulate: move Src2Shift up one bit Paolo Bonzini
2025-11-17 19:51 ` Chang S. Bae
2025-11-14 0:36 ` [PATCH 03/10] KVM: emulate: improve formatting of flags table Paolo Bonzini
2025-11-17 19:53 ` Chang S. Bae
2025-11-14 0:36 ` [PATCH 04/10] KVM: emulate: move op_prefix to struct x86_emulate_ctxt Paolo Bonzini
2025-11-17 19:54 ` Chang S. Bae
2025-11-14 0:36 ` [PATCH 05/10] KVM: emulate: share common register decoding code Paolo Bonzini
2025-11-17 19:55 ` Chang S. Bae
2025-11-14 0:36 ` [PATCH 06/10] KVM: emulate: add get_xcr callback Paolo Bonzini
2025-11-17 19:56 ` Chang S. Bae
2025-11-14 0:36 ` [PATCH 07/10] KVM: emulate: add AVX support to register fetch and writeback Paolo Bonzini
2025-11-14 17:06 ` kernel test robot
2025-11-14 20:10 ` kernel test robot
2025-11-14 0:36 ` [PATCH 08/10] KVM: x86: Refactor REX prefix handling in instruction emulation Paolo Bonzini
2025-11-17 19:56 ` Chang S. Bae
2025-11-14 0:36 ` [PATCH 09/10] KVM: emulate: decode VEX prefix Paolo Bonzini
2025-11-14 0:36 ` [PATCH 10/10] KVM: emulate: enable AVX moves Paolo Bonzini
2025-11-14 0:51 ` [PATCH 00/10] " Keith Busch
2025-11-17 19:57 ` Chang S. Bae
2025-11-21 18:55 ` Sean Christopherson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox