diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-08-25 05:47:43 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-10-24 04:51:34 -0400 |
commit | d2ddd1c48364e4161052d6089f06b2cf3c50496b (patch) | |
tree | f8dd6a949e5006e2f39575b567f22d9033b9d1a7 | |
parent | 3e2f65d57a0c1897fcc3287eeb41f117f4d021e5 (diff) |
KVM: x86 emulator: get rid of "restart" in emulation context.
x86_emulate_insn() will return 1 if instruction can be restarted
without re-entering a guest.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | arch/x86/include/asm/kvm_emulate.h | 4 | ||||
-rw-r--r-- | arch/x86/kvm/emulate.c | 43 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 16 |
3 files changed, 30 insertions, 33 deletions
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index 1bbf2b6f2a7e..1bf11400ae99 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h | |||
@@ -224,7 +224,6 @@ struct x86_emulate_ctxt { | |||
224 | /* interruptibility state, as a result of execution of STI or MOV SS */ | 224 | /* interruptibility state, as a result of execution of STI or MOV SS */ |
225 | int interruptibility; | 225 | int interruptibility; |
226 | 226 | ||
227 | bool restart; /* restart string instruction after writeback */ | ||
228 | bool perm_ok; /* do not check permissions if true */ | 227 | bool perm_ok; /* do not check permissions if true */ |
229 | 228 | ||
230 | int exception; /* exception that happens during emulation or -1 */ | 229 | int exception; /* exception that happens during emulation or -1 */ |
@@ -255,6 +254,9 @@ struct x86_emulate_ctxt { | |||
255 | #endif | 254 | #endif |
256 | 255 | ||
257 | int x86_decode_insn(struct x86_emulate_ctxt *ctxt); | 256 | int x86_decode_insn(struct x86_emulate_ctxt *ctxt); |
257 | #define EMULATION_FAILED -1 | ||
258 | #define EMULATION_OK 0 | ||
259 | #define EMULATION_RESTART 1 | ||
258 | int x86_emulate_insn(struct x86_emulate_ctxt *ctxt); | 260 | int x86_emulate_insn(struct x86_emulate_ctxt *ctxt); |
259 | int emulator_task_switch(struct x86_emulate_ctxt *ctxt, | 261 | int emulator_task_switch(struct x86_emulate_ctxt *ctxt, |
260 | u16 tss_selector, int reason, | 262 | u16 tss_selector, int reason, |
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 3dcbc1d0a59d..ec35a71d8b5d 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -437,7 +437,6 @@ static void emulate_exception(struct x86_emulate_ctxt *ctxt, int vec, | |||
437 | ctxt->exception = vec; | 437 | ctxt->exception = vec; |
438 | ctxt->error_code = error; | 438 | ctxt->error_code = error; |
439 | ctxt->error_code_valid = valid; | 439 | ctxt->error_code_valid = valid; |
440 | ctxt->restart = false; | ||
441 | } | 440 | } |
442 | 441 | ||
443 | static void emulate_gp(struct x86_emulate_ctxt *ctxt, int err) | 442 | static void emulate_gp(struct x86_emulate_ctxt *ctxt, int err) |
@@ -2633,9 +2632,6 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt) | |||
2633 | struct opcode opcode, *g_mod012, *g_mod3; | 2632 | struct opcode opcode, *g_mod012, *g_mod3; |
2634 | struct operand memop = { .type = OP_NONE }; | 2633 | struct operand memop = { .type = OP_NONE }; |
2635 | 2634 | ||
2636 | /* we cannot decode insn before we complete previous rep insn */ | ||
2637 | WARN_ON(ctxt->restart); | ||
2638 | |||
2639 | c->eip = ctxt->eip; | 2635 | c->eip = ctxt->eip; |
2640 | c->fetch.start = c->fetch.end = c->eip; | 2636 | c->fetch.start = c->fetch.end = c->eip; |
2641 | ctxt->cs_base = seg_base(ctxt, ops, VCPU_SREG_CS); | 2637 | ctxt->cs_base = seg_base(ctxt, ops, VCPU_SREG_CS); |
@@ -2985,10 +2981,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt) | |||
2985 | } | 2981 | } |
2986 | 2982 | ||
2987 | if (c->rep_prefix && (c->d & String)) { | 2983 | if (c->rep_prefix && (c->d & String)) { |
2988 | ctxt->restart = true; | ||
2989 | /* All REP prefixes have the same first termination condition */ | 2984 | /* All REP prefixes have the same first termination condition */ |
2990 | if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) { | 2985 | if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) { |
2991 | ctxt->restart = false; | ||
2992 | ctxt->eip = c->eip; | 2986 | ctxt->eip = c->eip; |
2993 | goto done; | 2987 | goto done; |
2994 | } | 2988 | } |
@@ -3446,28 +3440,29 @@ writeback: | |||
3446 | struct read_cache *r = &ctxt->decode.io_read; | 3440 | struct read_cache *r = &ctxt->decode.io_read; |
3447 | register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1); | 3441 | register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1); |
3448 | 3442 | ||
3449 | if (string_insn_completed(ctxt)) | 3443 | if (!string_insn_completed(ctxt)) { |
3450 | ctxt->restart = false; | 3444 | /* |
3451 | /* | 3445 | * Re-enter guest when pio read ahead buffer is empty |
3452 | * Re-enter guest when pio read ahead buffer is empty or, | 3446 | * or, if it is not used, after each 1024 iteration. |
3453 | * if it is not used, after each 1024 iteration. | 3447 | */ |
3454 | */ | 3448 | if ((r->end != 0 || c->regs[VCPU_REGS_RCX] & 0x3ff) && |
3455 | else if ((r->end == 0 && !(c->regs[VCPU_REGS_RCX] & 0x3ff)) || | 3449 | (r->end == 0 || r->end != r->pos)) { |
3456 | (r->end != 0 && r->end == r->pos)) { | 3450 | /* |
3457 | ctxt->restart = false; | 3451 | * Reset read cache. Usually happens before |
3458 | c->eip = ctxt->eip; | 3452 | * decode, but since instruction is restarted |
3453 | * we have to do it here. | ||
3454 | */ | ||
3455 | ctxt->decode.mem_read.end = 0; | ||
3456 | return EMULATION_RESTART; | ||
3457 | } | ||
3458 | goto done; /* skip rip writeback */ | ||
3459 | } | 3459 | } |
3460 | } | 3460 | } |
3461 | /* | 3461 | |
3462 | * reset read cache here in case string instruction is restared | 3462 | ctxt->eip = c->eip; |
3463 | * without decoding | ||
3464 | */ | ||
3465 | ctxt->decode.mem_read.end = 0; | ||
3466 | if (!ctxt->restart) | ||
3467 | ctxt->eip = c->eip; | ||
3468 | 3463 | ||
3469 | done: | 3464 | done: |
3470 | return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; | 3465 | return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK; |
3471 | 3466 | ||
3472 | twobyte_insn: | 3467 | twobyte_insn: |
3473 | switch (c->b) { | 3468 | switch (c->b) { |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index d4d33f943d99..bc96ac9ed912 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -4181,18 +4181,17 @@ int emulate_instruction(struct kvm_vcpu *vcpu, | |||
4181 | restart: | 4181 | restart: |
4182 | r = x86_emulate_insn(&vcpu->arch.emulate_ctxt); | 4182 | r = x86_emulate_insn(&vcpu->arch.emulate_ctxt); |
4183 | 4183 | ||
4184 | if (r) { /* emulation failed */ | 4184 | if (r == EMULATION_FAILED) { |
4185 | if (reexecute_instruction(vcpu, cr2)) | 4185 | if (reexecute_instruction(vcpu, cr2)) |
4186 | return EMULATE_DONE; | 4186 | return EMULATE_DONE; |
4187 | 4187 | ||
4188 | return handle_emulation_failure(vcpu); | 4188 | return handle_emulation_failure(vcpu); |
4189 | } | 4189 | } |
4190 | 4190 | ||
4191 | r = EMULATE_DONE; | 4191 | if (vcpu->arch.emulate_ctxt.exception >= 0) { |
4192 | |||
4193 | if (vcpu->arch.emulate_ctxt.exception >= 0) | ||
4194 | inject_emulated_exception(vcpu); | 4192 | inject_emulated_exception(vcpu); |
4195 | else if (vcpu->arch.pio.count) { | 4193 | r = EMULATE_DONE; |
4194 | } else if (vcpu->arch.pio.count) { | ||
4196 | if (!vcpu->arch.pio.in) | 4195 | if (!vcpu->arch.pio.in) |
4197 | vcpu->arch.pio.count = 0; | 4196 | vcpu->arch.pio.count = 0; |
4198 | r = EMULATE_DO_MMIO; | 4197 | r = EMULATE_DO_MMIO; |
@@ -4200,8 +4199,10 @@ restart: | |||
4200 | if (vcpu->mmio_is_write) | 4199 | if (vcpu->mmio_is_write) |
4201 | vcpu->mmio_needed = 0; | 4200 | vcpu->mmio_needed = 0; |
4202 | r = EMULATE_DO_MMIO; | 4201 | r = EMULATE_DO_MMIO; |
4203 | } else if (vcpu->arch.emulate_ctxt.restart) | 4202 | } else if (r == EMULATION_RESTART) |
4204 | goto restart; | 4203 | goto restart; |
4204 | else | ||
4205 | r = EMULATE_DONE; | ||
4205 | 4206 | ||
4206 | toggle_interruptibility(vcpu, vcpu->arch.emulate_ctxt.interruptibility); | 4207 | toggle_interruptibility(vcpu, vcpu->arch.emulate_ctxt.interruptibility); |
4207 | kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags); | 4208 | kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags); |
@@ -5100,8 +5101,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
5100 | if (!irqchip_in_kernel(vcpu->kvm)) | 5101 | if (!irqchip_in_kernel(vcpu->kvm)) |
5101 | kvm_set_cr8(vcpu, kvm_run->cr8); | 5102 | kvm_set_cr8(vcpu, kvm_run->cr8); |
5102 | 5103 | ||
5103 | if (vcpu->arch.pio.count || vcpu->mmio_needed || | 5104 | if (vcpu->arch.pio.count || vcpu->mmio_needed) { |
5104 | vcpu->arch.emulate_ctxt.restart) { | ||
5105 | if (vcpu->mmio_needed) { | 5105 | if (vcpu->mmio_needed) { |
5106 | memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8); | 5106 | memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8); |
5107 | vcpu->mmio_read_completed = 1; | 5107 | vcpu->mmio_read_completed = 1; |