diff options
| -rw-r--r-- | arch/x86/include/asm/kvm_host.h | 1 | ||||
| -rw-r--r-- | arch/x86/kvm/x86.c | 36 |
2 files changed, 27 insertions, 10 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 264814f26ce0..159b5988292f 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
| @@ -350,6 +350,7 @@ struct kvm_mmu_page { | |||
| 350 | }; | 350 | }; |
| 351 | 351 | ||
| 352 | struct kvm_pio_request { | 352 | struct kvm_pio_request { |
| 353 | unsigned long linear_rip; | ||
| 353 | unsigned long count; | 354 | unsigned long count; |
| 354 | int in; | 355 | int in; |
| 355 | int port; | 356 | int port; |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 9f279bb145e5..099b851dabaf 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
| @@ -6535,14 +6535,27 @@ int kvm_emulate_instruction_from_buffer(struct kvm_vcpu *vcpu, | |||
| 6535 | } | 6535 | } |
| 6536 | EXPORT_SYMBOL_GPL(kvm_emulate_instruction_from_buffer); | 6536 | EXPORT_SYMBOL_GPL(kvm_emulate_instruction_from_buffer); |
| 6537 | 6537 | ||
| 6538 | static int complete_fast_pio_out(struct kvm_vcpu *vcpu) | ||
| 6539 | { | ||
| 6540 | vcpu->arch.pio.count = 0; | ||
| 6541 | |||
| 6542 | if (unlikely(!kvm_is_linear_rip(vcpu, vcpu->arch.pio.linear_rip))) | ||
| 6543 | return 1; | ||
| 6544 | |||
| 6545 | return kvm_skip_emulated_instruction(vcpu); | ||
| 6546 | } | ||
| 6547 | |||
| 6538 | static int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, | 6548 | static int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, |
| 6539 | unsigned short port) | 6549 | unsigned short port) |
| 6540 | { | 6550 | { |
| 6541 | unsigned long val = kvm_register_read(vcpu, VCPU_REGS_RAX); | 6551 | unsigned long val = kvm_register_read(vcpu, VCPU_REGS_RAX); |
| 6542 | int ret = emulator_pio_out_emulated(&vcpu->arch.emulate_ctxt, | 6552 | int ret = emulator_pio_out_emulated(&vcpu->arch.emulate_ctxt, |
| 6543 | size, port, &val, 1); | 6553 | size, port, &val, 1); |
| 6544 | /* do not return to emulator after return from userspace */ | 6554 | |
| 6545 | vcpu->arch.pio.count = 0; | 6555 | if (!ret) { |
| 6556 | vcpu->arch.pio.linear_rip = kvm_get_linear_rip(vcpu); | ||
| 6557 | vcpu->arch.complete_userspace_io = complete_fast_pio_out; | ||
| 6558 | } | ||
| 6546 | return ret; | 6559 | return ret; |
| 6547 | } | 6560 | } |
| 6548 | 6561 | ||
| @@ -6553,6 +6566,11 @@ static int complete_fast_pio_in(struct kvm_vcpu *vcpu) | |||
| 6553 | /* We should only ever be called with arch.pio.count equal to 1 */ | 6566 | /* We should only ever be called with arch.pio.count equal to 1 */ |
| 6554 | BUG_ON(vcpu->arch.pio.count != 1); | 6567 | BUG_ON(vcpu->arch.pio.count != 1); |
| 6555 | 6568 | ||
| 6569 | if (unlikely(!kvm_is_linear_rip(vcpu, vcpu->arch.pio.linear_rip))) { | ||
| 6570 | vcpu->arch.pio.count = 0; | ||
| 6571 | return 1; | ||
| 6572 | } | ||
| 6573 | |||
| 6556 | /* For size less than 4 we merge, else we zero extend */ | 6574 | /* For size less than 4 we merge, else we zero extend */ |
| 6557 | val = (vcpu->arch.pio.size < 4) ? kvm_register_read(vcpu, VCPU_REGS_RAX) | 6575 | val = (vcpu->arch.pio.size < 4) ? kvm_register_read(vcpu, VCPU_REGS_RAX) |
| 6558 | : 0; | 6576 | : 0; |
| @@ -6565,7 +6583,7 @@ static int complete_fast_pio_in(struct kvm_vcpu *vcpu) | |||
| 6565 | vcpu->arch.pio.port, &val, 1); | 6583 | vcpu->arch.pio.port, &val, 1); |
| 6566 | kvm_register_write(vcpu, VCPU_REGS_RAX, val); | 6584 | kvm_register_write(vcpu, VCPU_REGS_RAX, val); |
| 6567 | 6585 | ||
| 6568 | return 1; | 6586 | return kvm_skip_emulated_instruction(vcpu); |
| 6569 | } | 6587 | } |
| 6570 | 6588 | ||
| 6571 | static int kvm_fast_pio_in(struct kvm_vcpu *vcpu, int size, | 6589 | static int kvm_fast_pio_in(struct kvm_vcpu *vcpu, int size, |
| @@ -6584,6 +6602,7 @@ static int kvm_fast_pio_in(struct kvm_vcpu *vcpu, int size, | |||
| 6584 | return ret; | 6602 | return ret; |
| 6585 | } | 6603 | } |
| 6586 | 6604 | ||
| 6605 | vcpu->arch.pio.linear_rip = kvm_get_linear_rip(vcpu); | ||
| 6587 | vcpu->arch.complete_userspace_io = complete_fast_pio_in; | 6606 | vcpu->arch.complete_userspace_io = complete_fast_pio_in; |
| 6588 | 6607 | ||
| 6589 | return 0; | 6608 | return 0; |
| @@ -6591,16 +6610,13 @@ static int kvm_fast_pio_in(struct kvm_vcpu *vcpu, int size, | |||
| 6591 | 6610 | ||
| 6592 | int kvm_fast_pio(struct kvm_vcpu *vcpu, int size, unsigned short port, int in) | 6611 | int kvm_fast_pio(struct kvm_vcpu *vcpu, int size, unsigned short port, int in) |
| 6593 | { | 6612 | { |
| 6594 | int ret = kvm_skip_emulated_instruction(vcpu); | 6613 | int ret; |
| 6595 | 6614 | ||
| 6596 | /* | ||
| 6597 | * TODO: we might be squashing a KVM_GUESTDBG_SINGLESTEP-triggered | ||
| 6598 | * KVM_EXIT_DEBUG here. | ||
| 6599 | */ | ||
| 6600 | if (in) | 6615 | if (in) |
| 6601 | return kvm_fast_pio_in(vcpu, size, port) && ret; | 6616 | ret = kvm_fast_pio_in(vcpu, size, port); |
| 6602 | else | 6617 | else |
| 6603 | return kvm_fast_pio_out(vcpu, size, port) && ret; | 6618 | ret = kvm_fast_pio_out(vcpu, size, port); |
| 6619 | return ret && kvm_skip_emulated_instruction(vcpu); | ||
| 6604 | } | 6620 | } |
| 6605 | EXPORT_SYMBOL_GPL(kvm_fast_pio); | 6621 | EXPORT_SYMBOL_GPL(kvm_fast_pio); |
| 6606 | 6622 | ||
