diff options
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 93 |
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 | ||
4547 | static int complete_emulated_mmio(struct kvm_vcpu *vcpu); | ||
4548 | static int complete_emulated_pio(struct kvm_vcpu *vcpu); | ||
4549 | |||
4547 | int x86_emulate_instruction(struct kvm_vcpu *vcpu, | 4550 | int 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 | ||
5485 | static 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 | |||
5496 | static 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 | */ |
5495 | static int complete_mmio(struct kvm_vcpu *vcpu) | 5519 | static 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; |
5527 | done: | 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 | |||
5536 | int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 5550 | int 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 | ||