diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2011-04-04 06:39:35 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-05-11 07:57:03 -0400 |
commit | f6511935f424b9a25059ae18e91ad11dd24980e6 (patch) | |
tree | 8f3b8108255f943b2e3f355a9cdd12d31c92c16e /arch/x86/kvm/emulate.c | |
parent | bf608f88faef1245ff87e731512517fc676ffe02 (diff) |
KVM: SVM: Add checks for IO instructions
This patch adds code to check for IOIO intercepts on
instructions decoded by the KVM instruction emulator.
[avi: fix build error due to missing #define D2bvIP]
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r-- | arch/x86/kvm/emulate.c | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index cc32e72fe175..d88dcfd66a8f 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -2623,6 +2623,28 @@ static int check_rdpmc(struct x86_emulate_ctxt *ctxt) | |||
2623 | return X86EMUL_CONTINUE; | 2623 | return X86EMUL_CONTINUE; |
2624 | } | 2624 | } |
2625 | 2625 | ||
2626 | static int check_perm_in(struct x86_emulate_ctxt *ctxt) | ||
2627 | { | ||
2628 | struct decode_cache *c = &ctxt->decode; | ||
2629 | |||
2630 | c->dst.bytes = min(c->dst.bytes, 4u); | ||
2631 | if (!emulator_io_permited(ctxt, ctxt->ops, c->src.val, c->dst.bytes)) | ||
2632 | return emulate_gp(ctxt, 0); | ||
2633 | |||
2634 | return X86EMUL_CONTINUE; | ||
2635 | } | ||
2636 | |||
2637 | static int check_perm_out(struct x86_emulate_ctxt *ctxt) | ||
2638 | { | ||
2639 | struct decode_cache *c = &ctxt->decode; | ||
2640 | |||
2641 | c->src.bytes = min(c->src.bytes, 4u); | ||
2642 | if (!emulator_io_permited(ctxt, ctxt->ops, c->dst.val, c->src.bytes)) | ||
2643 | return emulate_gp(ctxt, 0); | ||
2644 | |||
2645 | return X86EMUL_CONTINUE; | ||
2646 | } | ||
2647 | |||
2626 | #define D(_y) { .flags = (_y) } | 2648 | #define D(_y) { .flags = (_y) } |
2627 | #define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i } | 2649 | #define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i } |
2628 | #define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \ | 2650 | #define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \ |
@@ -2640,6 +2662,7 @@ static int check_rdpmc(struct x86_emulate_ctxt *ctxt) | |||
2640 | #define GP(_f, _g) { .flags = ((_f) | Prefix), .u.gprefix = (_g) } | 2662 | #define GP(_f, _g) { .flags = ((_f) | Prefix), .u.gprefix = (_g) } |
2641 | 2663 | ||
2642 | #define D2bv(_f) D((_f) | ByteOp), D(_f) | 2664 | #define D2bv(_f) D((_f) | ByteOp), D(_f) |
2665 | #define D2bvIP(_f, _i, _p) DIP((_f) | ByteOp, _i, _p), DIP(_f, _i, _p) | ||
2643 | #define I2bv(_f, _e) I((_f) | ByteOp, _e), I(_f, _e) | 2666 | #define I2bv(_f, _e) I((_f) | ByteOp, _e), I(_f, _e) |
2644 | 2667 | ||
2645 | #define D6ALU(_f) D2bv((_f) | DstMem | SrcReg | ModRM), \ | 2668 | #define D6ALU(_f) D2bv((_f) | DstMem | SrcReg | ModRM), \ |
@@ -2773,8 +2796,8 @@ static struct opcode opcode_table[256] = { | |||
2773 | I(DstReg | SrcMem | ModRM | Src2Imm, em_imul_3op), | 2796 | I(DstReg | SrcMem | ModRM | Src2Imm, em_imul_3op), |
2774 | I(SrcImmByte | Mov | Stack, em_push), | 2797 | I(SrcImmByte | Mov | Stack, em_push), |
2775 | I(DstReg | SrcMem | ModRM | Src2ImmByte, em_imul_3op), | 2798 | I(DstReg | SrcMem | ModRM | Src2ImmByte, em_imul_3op), |
2776 | D2bv(DstDI | Mov | String), /* insb, insw/insd */ | 2799 | D2bvIP(DstDI | Mov | String, ins, check_perm_in), /* insb, insw/insd */ |
2777 | D2bv(SrcSI | ImplicitOps | String), /* outsb, outsw/outsd */ | 2800 | D2bvIP(SrcSI | ImplicitOps | String, outs, check_perm_out), /* outsb, outsw/outsd */ |
2778 | /* 0x70 - 0x7F */ | 2801 | /* 0x70 - 0x7F */ |
2779 | X16(D(SrcImmByte)), | 2802 | X16(D(SrcImmByte)), |
2780 | /* 0x80 - 0x87 */ | 2803 | /* 0x80 - 0x87 */ |
@@ -2825,11 +2848,13 @@ static struct opcode opcode_table[256] = { | |||
2825 | N, N, N, N, N, N, N, N, | 2848 | N, N, N, N, N, N, N, N, |
2826 | /* 0xE0 - 0xE7 */ | 2849 | /* 0xE0 - 0xE7 */ |
2827 | X4(D(SrcImmByte)), | 2850 | X4(D(SrcImmByte)), |
2828 | D2bv(SrcImmUByte | DstAcc), D2bv(SrcAcc | DstImmUByte), | 2851 | D2bvIP(SrcImmUByte | DstAcc, in, check_perm_in), |
2852 | D2bvIP(SrcAcc | DstImmUByte, out, check_perm_out), | ||
2829 | /* 0xE8 - 0xEF */ | 2853 | /* 0xE8 - 0xEF */ |
2830 | D(SrcImm | Stack), D(SrcImm | ImplicitOps), | 2854 | D(SrcImm | Stack), D(SrcImm | ImplicitOps), |
2831 | D(SrcImmFAddr | No64), D(SrcImmByte | ImplicitOps), | 2855 | D(SrcImmFAddr | No64), D(SrcImmByte | ImplicitOps), |
2832 | D2bv(SrcNone | DstAcc), D2bv(SrcAcc | ImplicitOps), | 2856 | D2bvIP(SrcNone | DstAcc, in, check_perm_in), |
2857 | D2bvIP(SrcAcc | ImplicitOps, out, check_perm_out), | ||
2833 | /* 0xF0 - 0xF7 */ | 2858 | /* 0xF0 - 0xF7 */ |
2834 | N, DI(ImplicitOps, icebp), N, N, | 2859 | N, DI(ImplicitOps, icebp), N, N, |
2835 | DI(ImplicitOps | Priv, hlt), D(ImplicitOps), | 2860 | DI(ImplicitOps | Priv, hlt), D(ImplicitOps), |
@@ -2923,6 +2948,7 @@ static struct opcode twobyte_table[256] = { | |||
2923 | #undef EXT | 2948 | #undef EXT |
2924 | 2949 | ||
2925 | #undef D2bv | 2950 | #undef D2bv |
2951 | #undef D2bvIP | ||
2926 | #undef I2bv | 2952 | #undef I2bv |
2927 | #undef D6ALU | 2953 | #undef D6ALU |
2928 | 2954 | ||
@@ -3731,11 +3757,6 @@ special_insn: | |||
3731 | case 0xed: /* in (e/r)ax,dx */ | 3757 | case 0xed: /* in (e/r)ax,dx */ |
3732 | c->src.val = c->regs[VCPU_REGS_RDX]; | 3758 | c->src.val = c->regs[VCPU_REGS_RDX]; |
3733 | do_io_in: | 3759 | do_io_in: |
3734 | c->dst.bytes = min(c->dst.bytes, 4u); | ||
3735 | if (!emulator_io_permited(ctxt, ops, c->src.val, c->dst.bytes)) { | ||
3736 | rc = emulate_gp(ctxt, 0); | ||
3737 | goto done; | ||
3738 | } | ||
3739 | if (!pio_in_emulated(ctxt, ops, c->dst.bytes, c->src.val, | 3760 | if (!pio_in_emulated(ctxt, ops, c->dst.bytes, c->src.val, |
3740 | &c->dst.val)) | 3761 | &c->dst.val)) |
3741 | goto done; /* IO is needed */ | 3762 | goto done; /* IO is needed */ |
@@ -3744,12 +3765,6 @@ special_insn: | |||
3744 | case 0xef: /* out dx,(e/r)ax */ | 3765 | case 0xef: /* out dx,(e/r)ax */ |
3745 | c->dst.val = c->regs[VCPU_REGS_RDX]; | 3766 | c->dst.val = c->regs[VCPU_REGS_RDX]; |
3746 | do_io_out: | 3767 | do_io_out: |
3747 | c->src.bytes = min(c->src.bytes, 4u); | ||
3748 | if (!emulator_io_permited(ctxt, ops, c->dst.val, | ||
3749 | c->src.bytes)) { | ||
3750 | rc = emulate_gp(ctxt, 0); | ||
3751 | goto done; | ||
3752 | } | ||
3753 | ops->pio_out_emulated(c->src.bytes, c->dst.val, | 3768 | ops->pio_out_emulated(c->src.bytes, c->dst.val, |
3754 | &c->src.val, 1, ctxt->vcpu); | 3769 | &c->src.val, 1, ctxt->vcpu); |
3755 | c->dst.type = OP_NONE; /* Disable writeback. */ | 3770 | c->dst.type = OP_NONE; /* Disable writeback. */ |