diff options
author | Avi Kivity <avi@redhat.com> | 2012-04-09 11:39:59 -0400 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2012-04-16 19:36:15 -0400 |
commit | 1c11b37669a5209bd11fb857a103634afef971e8 (patch) | |
tree | 7919993ec26af1038a0aae32f8682c3f723ba5d6 /arch/x86/kvm/emulate.c | |
parent | ae75954457eee0a608072368c5b477e40f378d7b (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/emulate.c')
-rw-r--r-- | arch/x86/kvm/emulate.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 83756223f8aa..6302e5c74341 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 | */ | ||
571 | static 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 | |||
560 | static int __linearize(struct x86_emulate_ctxt *ctxt, | 586 | static 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; |
626 | bad: | 654 | bad: |
@@ -3415,7 +3443,7 @@ static struct opcode group11[] = { | |||
3415 | }; | 3443 | }; |
3416 | 3444 | ||
3417 | static struct gprefix pfx_0f_6f_0f_7f = { | 3445 | static 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 | ||
3421 | static struct opcode opcode_table[256] = { | 3449 | static struct opcode opcode_table[256] = { |