diff options
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r-- | drivers/kvm/x86_emulate.c | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index 44eb28d31499..d553719fc4cb 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: | |||
1116 | special_insn: | 1120 | special_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; |