aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c93
1 files changed, 56 insertions, 37 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6f6812ec8419..f91e2c9d7cb1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4544,6 +4544,9 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
4544 return true; 4544 return true;
4545} 4545}
4546 4546
4547static int complete_emulated_mmio(struct kvm_vcpu *vcpu);
4548static int complete_emulated_pio(struct kvm_vcpu *vcpu);
4549
4547int x86_emulate_instruction(struct kvm_vcpu *vcpu, 4550int x86_emulate_instruction(struct kvm_vcpu *vcpu,
4548 unsigned long cr2, 4551 unsigned long cr2,
4549 int emulation_type, 4552 int emulation_type,
@@ -4614,13 +4617,16 @@ restart:
4614 } else if (vcpu->arch.pio.count) { 4617 } else if (vcpu->arch.pio.count) {
4615 if (!vcpu->arch.pio.in) 4618 if (!vcpu->arch.pio.in)
4616 vcpu->arch.pio.count = 0; 4619 vcpu->arch.pio.count = 0;
4617 else 4620 else {
4618 writeback = false; 4621 writeback = false;
4622 vcpu->arch.complete_userspace_io = complete_emulated_pio;
4623 }
4619 r = EMULATE_DO_MMIO; 4624 r = EMULATE_DO_MMIO;
4620 } else if (vcpu->mmio_needed) { 4625 } else if (vcpu->mmio_needed) {
4621 if (!vcpu->mmio_is_write) 4626 if (!vcpu->mmio_is_write)
4622 writeback = false; 4627 writeback = false;
4623 r = EMULATE_DO_MMIO; 4628 r = EMULATE_DO_MMIO;
4629 vcpu->arch.complete_userspace_io = complete_emulated_mmio;
4624 } else if (r == EMULATION_RESTART) 4630 } else if (r == EMULATION_RESTART)
4625 goto restart; 4631 goto restart;
4626 else 4632 else
@@ -5476,6 +5482,24 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
5476 return r; 5482 return r;
5477} 5483}
5478 5484
5485static inline int complete_emulated_io(struct kvm_vcpu *vcpu)
5486{
5487 int r;
5488 vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
5489 r = emulate_instruction(vcpu, EMULTYPE_NO_DECODE);
5490 srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
5491 if (r != EMULATE_DONE)
5492 return 0;
5493 return 1;
5494}
5495
5496static int complete_emulated_pio(struct kvm_vcpu *vcpu)
5497{
5498 BUG_ON(!vcpu->arch.pio.count);
5499
5500 return complete_emulated_io(vcpu);
5501}
5502
5479/* 5503/*
5480 * Implements the following, as a state machine: 5504 * Implements the following, as a state machine:
5481 * 5505 *
@@ -5492,47 +5516,37 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
5492 * copy data 5516 * copy data
5493 * exit 5517 * exit
5494 */ 5518 */
5495static int complete_mmio(struct kvm_vcpu *vcpu) 5519static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
5496{ 5520{
5497 struct kvm_run *run = vcpu->run; 5521 struct kvm_run *run = vcpu->run;
5498 struct kvm_mmio_fragment *frag; 5522 struct kvm_mmio_fragment *frag;
5499 int r;
5500 5523
5501 if (!(vcpu->arch.pio.count || vcpu->mmio_needed)) 5524 BUG_ON(!vcpu->mmio_needed);
5502 return 1;
5503 5525
5504 if (vcpu->mmio_needed) { 5526 /* Complete previous fragment */
5505 /* Complete previous fragment */ 5527 frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++];
5506 frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++]; 5528 if (!vcpu->mmio_is_write)
5507 if (!vcpu->mmio_is_write) 5529 memcpy(frag->data, run->mmio.data, frag->len);
5508 memcpy(frag->data, run->mmio.data, frag->len); 5530 if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {
5509 if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) { 5531 vcpu->mmio_needed = 0;
5510 vcpu->mmio_needed = 0;
5511 if (vcpu->mmio_is_write)
5512 return 1;
5513 vcpu->mmio_read_completed = 1;
5514 goto done;
5515 }
5516 /* Initiate next fragment */
5517 ++frag;
5518 run->exit_reason = KVM_EXIT_MMIO;
5519 run->mmio.phys_addr = frag->gpa;
5520 if (vcpu->mmio_is_write) 5532 if (vcpu->mmio_is_write)
5521 memcpy(run->mmio.data, frag->data, frag->len); 5533 return 1;
5522 run->mmio.len = frag->len; 5534 vcpu->mmio_read_completed = 1;
5523 run->mmio.is_write = vcpu->mmio_is_write; 5535 return complete_emulated_io(vcpu);
5524 return 0; 5536 }
5525 5537 /* Initiate next fragment */
5526 } 5538 ++frag;
5527done: 5539 run->exit_reason = KVM_EXIT_MMIO;
5528 vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); 5540 run->mmio.phys_addr = frag->gpa;
5529 r = emulate_instruction(vcpu, EMULTYPE_NO_DECODE); 5541 if (vcpu->mmio_is_write)
5530 srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); 5542 memcpy(run->mmio.data, frag->data, frag->len);
5531 if (r != EMULATE_DONE) 5543 run->mmio.len = frag->len;
5532 return 0; 5544 run->mmio.is_write = vcpu->mmio_is_write;
5533 return 1; 5545 vcpu->arch.complete_userspace_io = complete_emulated_mmio;
5546 return 0;
5534} 5547}
5535 5548
5549
5536int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 5550int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
5537{ 5551{
5538 int r; 5552 int r;
@@ -5559,9 +5573,14 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
5559 } 5573 }
5560 } 5574 }
5561 5575
5562 r = complete_mmio(vcpu); 5576 if (unlikely(vcpu->arch.complete_userspace_io)) {
5563 if (r <= 0) 5577 int (*cui)(struct kvm_vcpu *) = vcpu->arch.complete_userspace_io;
5564 goto out; 5578 vcpu->arch.complete_userspace_io = NULL;
5579 r = cui(vcpu);
5580 if (r <= 0)
5581 goto out;
5582 } else
5583 WARN_ON(vcpu->arch.pio.count || vcpu->mmio_needed);
5565 5584
5566 r = __vcpu_run(vcpu); 5585 r = __vcpu_run(vcpu);
5567 5586