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] = { |
