aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2012-04-09 11:39:59 -0400
committerMarcelo Tosatti <mtosatti@redhat.com>2012-04-16 19:36:15 -0400
commit1c11b37669a5209bd11fb857a103634afef971e8 (patch)
tree7919993ec26af1038a0aae32f8682c3f723ba5d6 /arch/x86/kvm
parentae75954457eee0a608072368c5b477e40f378d7b (diff)
KVM: x86 emulator: add support for vector alignment
x86 defines three classes of vector instructions: explicitly aligned (#GP(0) if unaligned, explicitly unaligned, and default (which depends on the encoding: AVX is unaligned, SSE is aligned). Add support for marking an instruction as explicitly aligned or unaligned, and mark MOVDQU as unaligned. Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r--arch/x86/kvm/emulate.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 83756223f8a..6302e5c7434 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -142,6 +142,9 @@
142#define Src2FS (OpFS << Src2Shift) 142#define Src2FS (OpFS << Src2Shift)
143#define Src2GS (OpGS << Src2Shift) 143#define Src2GS (OpGS << Src2Shift)
144#define Src2Mask (OpMask << Src2Shift) 144#define Src2Mask (OpMask << Src2Shift)
145#define Aligned ((u64)1 << 41) /* Explicitly aligned (e.g. MOVDQA) */
146#define Unaligned ((u64)1 << 42) /* Explicitly unaligned (e.g. MOVDQU) */
147#define Avx ((u64)1 << 43) /* Advanced Vector Extensions */
145 148
146#define X2(x...) x, x 149#define X2(x...) x, x
147#define X3(x...) X2(x), x 150#define X3(x...) X2(x), x
@@ -557,6 +560,29 @@ static void set_segment_selector(struct x86_emulate_ctxt *ctxt, u16 selector,
557 ctxt->ops->set_segment(ctxt, selector, &desc, base3, seg); 560 ctxt->ops->set_segment(ctxt, selector, &desc, base3, seg);
558} 561}
559 562
563/*
564 * x86 defines three classes of vector instructions: explicitly
565 * aligned, explicitly unaligned, and the rest, which change behaviour
566 * depending on whether they're AVX encoded or not.
567 *
568 * Also included is CMPXCHG16B which is not a vector instruction, yet it is
569 * subject to the same check.
570 */
571static bool insn_aligned(struct x86_emulate_ctxt *ctxt, unsigned size)
572{
573 if (likely(size < 16))
574 return false;
575
576 if (ctxt->d & Aligned)
577 return true;
578 else if (ctxt->d & Unaligned)
579 return false;
580 else if (ctxt->d & Avx)
581 return false;
582 else
583 return true;
584}
585
560static int __linearize(struct x86_emulate_ctxt *ctxt, 586static int __linearize(struct x86_emulate_ctxt *ctxt,
561 struct segmented_address addr, 587 struct segmented_address addr,
562 unsigned size, bool write, bool fetch, 588 unsigned size, bool write, bool fetch,
@@ -621,6 +647,8 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
621 } 647 }
622 if (fetch ? ctxt->mode != X86EMUL_MODE_PROT64 : ctxt->ad_bytes != 8) 648 if (fetch ? ctxt->mode != X86EMUL_MODE_PROT64 : ctxt->ad_bytes != 8)
623 la &= (u32)-1; 649 la &= (u32)-1;
650 if (insn_aligned(ctxt, size) && ((la & (size - 1)) != 0))
651 return emulate_gp(ctxt, 0);
624 *linear = la; 652 *linear = la;
625 return X86EMUL_CONTINUE; 653 return X86EMUL_CONTINUE;
626bad: 654bad:
@@ -3415,7 +3443,7 @@ static struct opcode group11[] = {
3415}; 3443};
3416 3444
3417static struct gprefix pfx_0f_6f_0f_7f = { 3445static struct gprefix pfx_0f_6f_0f_7f = {
3418 N, N, N, I(Sse, em_movdqu), 3446 N, N, N, I(Sse | Unaligned, em_movdqu),
3419}; 3447};
3420 3448
3421static struct opcode opcode_table[256] = { 3449static struct opcode opcode_table[256] = {