aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/kvm_host.h1
-rw-r--r--arch/x86/kvm/x86.c36
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
352struct kvm_pio_request { 352struct 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}
6536EXPORT_SYMBOL_GPL(kvm_emulate_instruction_from_buffer); 6536EXPORT_SYMBOL_GPL(kvm_emulate_instruction_from_buffer);
6537 6537
6538static 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
6538static int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, 6548static 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
6571static int kvm_fast_pio_in(struct kvm_vcpu *vcpu, int size, 6589static 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
6592int kvm_fast_pio(struct kvm_vcpu *vcpu, int size, unsigned short port, int in) 6611int 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}
6605EXPORT_SYMBOL_GPL(kvm_fast_pio); 6621EXPORT_SYMBOL_GPL(kvm_fast_pio);
6606 6622