diff options
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r-- | drivers/kvm/kvm_main.c | 77 |
1 files changed, 44 insertions, 33 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 800ab5028ed3..710483669f34 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -1251,45 +1251,56 @@ struct x86_emulate_ops emulate_ops = { | |||
1251 | int emulate_instruction(struct kvm_vcpu *vcpu, | 1251 | int emulate_instruction(struct kvm_vcpu *vcpu, |
1252 | struct kvm_run *run, | 1252 | struct kvm_run *run, |
1253 | unsigned long cr2, | 1253 | unsigned long cr2, |
1254 | u16 error_code) | 1254 | u16 error_code, |
1255 | int no_decode) | ||
1255 | { | 1256 | { |
1256 | struct x86_emulate_ctxt emulate_ctxt; | 1257 | int r = 0; |
1257 | int r; | ||
1258 | int cs_db, cs_l; | ||
1259 | 1258 | ||
1260 | vcpu->mmio_fault_cr2 = cr2; | 1259 | vcpu->mmio_fault_cr2 = cr2; |
1261 | kvm_x86_ops->cache_regs(vcpu); | 1260 | kvm_x86_ops->cache_regs(vcpu); |
1262 | 1261 | ||
1263 | kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); | ||
1264 | |||
1265 | emulate_ctxt.vcpu = vcpu; | ||
1266 | emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu); | ||
1267 | emulate_ctxt.cr2 = cr2; | ||
1268 | emulate_ctxt.mode = (emulate_ctxt.eflags & X86_EFLAGS_VM) | ||
1269 | ? X86EMUL_MODE_REAL : cs_l | ||
1270 | ? X86EMUL_MODE_PROT64 : cs_db | ||
1271 | ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; | ||
1272 | |||
1273 | if (emulate_ctxt.mode == X86EMUL_MODE_PROT64) { | ||
1274 | emulate_ctxt.cs_base = 0; | ||
1275 | emulate_ctxt.ds_base = 0; | ||
1276 | emulate_ctxt.es_base = 0; | ||
1277 | emulate_ctxt.ss_base = 0; | ||
1278 | } else { | ||
1279 | emulate_ctxt.cs_base = get_segment_base(vcpu, VCPU_SREG_CS); | ||
1280 | emulate_ctxt.ds_base = get_segment_base(vcpu, VCPU_SREG_DS); | ||
1281 | emulate_ctxt.es_base = get_segment_base(vcpu, VCPU_SREG_ES); | ||
1282 | emulate_ctxt.ss_base = get_segment_base(vcpu, VCPU_SREG_SS); | ||
1283 | } | ||
1284 | |||
1285 | emulate_ctxt.gs_base = get_segment_base(vcpu, VCPU_SREG_GS); | ||
1286 | emulate_ctxt.fs_base = get_segment_base(vcpu, VCPU_SREG_FS); | ||
1287 | |||
1288 | vcpu->mmio_is_write = 0; | 1262 | vcpu->mmio_is_write = 0; |
1289 | vcpu->pio.string = 0; | 1263 | vcpu->pio.string = 0; |
1290 | r = x86_decode_insn(&emulate_ctxt, &emulate_ops); | 1264 | |
1265 | if (!no_decode) { | ||
1266 | int cs_db, cs_l; | ||
1267 | kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); | ||
1268 | |||
1269 | vcpu->emulate_ctxt.vcpu = vcpu; | ||
1270 | vcpu->emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu); | ||
1271 | vcpu->emulate_ctxt.cr2 = cr2; | ||
1272 | vcpu->emulate_ctxt.mode = | ||
1273 | (vcpu->emulate_ctxt.eflags & X86_EFLAGS_VM) | ||
1274 | ? X86EMUL_MODE_REAL : cs_l | ||
1275 | ? X86EMUL_MODE_PROT64 : cs_db | ||
1276 | ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; | ||
1277 | |||
1278 | if (vcpu->emulate_ctxt.mode == X86EMUL_MODE_PROT64) { | ||
1279 | vcpu->emulate_ctxt.cs_base = 0; | ||
1280 | vcpu->emulate_ctxt.ds_base = 0; | ||
1281 | vcpu->emulate_ctxt.es_base = 0; | ||
1282 | vcpu->emulate_ctxt.ss_base = 0; | ||
1283 | } else { | ||
1284 | vcpu->emulate_ctxt.cs_base = | ||
1285 | get_segment_base(vcpu, VCPU_SREG_CS); | ||
1286 | vcpu->emulate_ctxt.ds_base = | ||
1287 | get_segment_base(vcpu, VCPU_SREG_DS); | ||
1288 | vcpu->emulate_ctxt.es_base = | ||
1289 | get_segment_base(vcpu, VCPU_SREG_ES); | ||
1290 | vcpu->emulate_ctxt.ss_base = | ||
1291 | get_segment_base(vcpu, VCPU_SREG_SS); | ||
1292 | } | ||
1293 | |||
1294 | vcpu->emulate_ctxt.gs_base = | ||
1295 | get_segment_base(vcpu, VCPU_SREG_GS); | ||
1296 | vcpu->emulate_ctxt.fs_base = | ||
1297 | get_segment_base(vcpu, VCPU_SREG_FS); | ||
1298 | |||
1299 | r = x86_decode_insn(&vcpu->emulate_ctxt, &emulate_ops); | ||
1300 | } | ||
1301 | |||
1291 | if (r == 0) | 1302 | if (r == 0) |
1292 | r = x86_emulate_insn(&emulate_ctxt, &emulate_ops); | 1303 | r = x86_emulate_insn(&vcpu->emulate_ctxt, &emulate_ops); |
1293 | 1304 | ||
1294 | if (vcpu->pio.string) | 1305 | if (vcpu->pio.string) |
1295 | return EMULATE_DO_MMIO; | 1306 | return EMULATE_DO_MMIO; |
@@ -1313,7 +1324,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu, | |||
1313 | } | 1324 | } |
1314 | 1325 | ||
1315 | kvm_x86_ops->decache_regs(vcpu); | 1326 | kvm_x86_ops->decache_regs(vcpu); |
1316 | kvm_x86_ops->set_rflags(vcpu, emulate_ctxt.eflags); | 1327 | kvm_x86_ops->set_rflags(vcpu, vcpu->emulate_ctxt.eflags); |
1317 | 1328 | ||
1318 | if (vcpu->mmio_is_write) { | 1329 | if (vcpu->mmio_is_write) { |
1319 | vcpu->mmio_needed = 0; | 1330 | vcpu->mmio_needed = 0; |
@@ -2055,7 +2066,7 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
2055 | vcpu->mmio_read_completed = 1; | 2066 | vcpu->mmio_read_completed = 1; |
2056 | vcpu->mmio_needed = 0; | 2067 | vcpu->mmio_needed = 0; |
2057 | r = emulate_instruction(vcpu, kvm_run, | 2068 | r = emulate_instruction(vcpu, kvm_run, |
2058 | vcpu->mmio_fault_cr2, 0); | 2069 | vcpu->mmio_fault_cr2, 0, 1); |
2059 | if (r == EMULATE_DO_MMIO) { | 2070 | if (r == EMULATE_DO_MMIO) { |
2060 | /* | 2071 | /* |
2061 | * Read-modify-write. Back to userspace. | 2072 | * Read-modify-write. Back to userspace. |