aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/x86_emulate.c
diff options
context:
space:
mode:
authorLaurent Vivier <Laurent.Vivier@bull.net>2007-08-05 03:36:40 -0400
committerAvi Kivity <avi@qumranet.com>2007-10-13 04:18:23 -0400
commite70669abd4e60dfea3ac1639848e20e2b8dd1255 (patch)
tree4625f787efdf5f586514cd6306e045a97edb490e /drivers/kvm/x86_emulate.c
parent9fdaaac38e8c8a63c6383b807b91fea2d51da95d (diff)
KVM: Cleanup string I/O instruction emulation
Both vmx and svm decode the I/O instructions, and both botch the job, requiring the instruction prefixes to be fetched in order to completely decode the instruction. So, if we see a string I/O instruction, use the x86 emulator to decode it, as it already has all the prefix decoding machinery. This patch defines ins/outs opcodes in x86_emulate.c and calls emulate_instruction() from io_interception() (svm.c) and from handle_io() (vmx.c). It removes all vmx/svm prefix instruction decoders (get_addr_size(), io_get_override(), io_address(), get_io_count()) Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r--drivers/kvm/x86_emulate.c49
1 files changed, 44 insertions, 5 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 44eb28d3149..d553719fc4c 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -103,9 +103,12 @@ static u8 opcode_table[256] = {
103 /* 0x58 - 0x5F */ 103 /* 0x58 - 0x5F */
104 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, 104 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
105 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, 105 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
106 /* 0x60 - 0x6F */ 106 /* 0x60 - 0x6B */
107 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ , 107 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ ,
108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108 0, 0, 0, 0, 0, 0, 0, 0,
109 /* 0x6C - 0x6F */
110 SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, /* insb, insw/insd */
111 SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, /* outsb, outsw/outsd */
109 /* 0x70 - 0x7F */ 112 /* 0x70 - 0x7F */
110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111 /* 0x80 - 0x87 */ 114 /* 0x80 - 0x87 */
@@ -428,10 +431,11 @@ struct operand {
428}) 431})
429 432
430/* Access/update address held in a register, based on addressing mode. */ 433/* Access/update address held in a register, based on addressing mode. */
434#define address_mask(reg) \
435 ((ad_bytes == sizeof(unsigned long)) ? \
436 (reg) : ((reg) & ((1UL << (ad_bytes << 3)) - 1)))
431#define register_address(base, reg) \ 437#define register_address(base, reg) \
432 ((base) + ((ad_bytes == sizeof(unsigned long)) ? (reg) : \ 438 ((base) + address_mask(reg))
433 ((reg) & ((1UL << (ad_bytes << 3)) - 1))))
434
435#define register_address_increment(reg, inc) \ 439#define register_address_increment(reg, inc) \
436 do { \ 440 do { \
437 /* signed type ensures sign extension to long */ \ 441 /* signed type ensures sign extension to long */ \
@@ -1116,6 +1120,41 @@ done:
1116special_insn: 1120special_insn:
1117 if (twobyte) 1121 if (twobyte)
1118 goto twobyte_special_insn; 1122 goto twobyte_special_insn;
1123 switch(b) {
1124 case 0x6c: /* insb */
1125 case 0x6d: /* insw/insd */
1126 if (kvm_setup_pio(ctxt->vcpu, NULL,
1127 1, /* in */
1128 (d & ByteOp) ? 1 : op_bytes, /* size */
1129 rep_prefix ?
1130 address_mask(_regs[VCPU_REGS_RCX]) : 1, /* count */
1131 1, /* strings */
1132 (_eflags & EFLG_DF), /* down */
1133 register_address(ctxt->es_base,
1134 _regs[VCPU_REGS_RDI]), /* address */
1135 rep_prefix,
1136 _regs[VCPU_REGS_RDX] /* port */
1137 ) == 0)
1138 return -1;
1139 return 0;
1140 case 0x6e: /* outsb */
1141 case 0x6f: /* outsw/outsd */
1142 if (kvm_setup_pio(ctxt->vcpu, NULL,
1143 0, /* in */
1144 (d & ByteOp) ? 1 : op_bytes, /* size */
1145 rep_prefix ?
1146 address_mask(_regs[VCPU_REGS_RCX]) : 1, /* count */
1147 1, /* strings */
1148 (_eflags & EFLG_DF), /* down */
1149 register_address(override_base ?
1150 *override_base : ctxt->ds_base,
1151 _regs[VCPU_REGS_RSI]), /* address */
1152 rep_prefix,
1153 _regs[VCPU_REGS_RDX] /* port */
1154 ) == 0)
1155 return -1;
1156 return 0;
1157 }
1119 if (rep_prefix) { 1158 if (rep_prefix) {
1120 if (_regs[VCPU_REGS_RCX] == 0) { 1159 if (_regs[VCPU_REGS_RCX] == 0) {
1121 ctxt->vcpu->rip = _eip; 1160 ctxt->vcpu->rip = _eip;