Commit 8370c3d0 authored by Tom Lendacky's avatar Tom Lendacky Committed by Radim Krčmář

kvm: svm: Add kvm_fast_pio_in support

Update the I/O interception support to add the kvm_fast_pio_in function
to speed up the in instruction similar to the out instruction.
Signed-off-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Reviewed-by: default avatarBorislav Petkov <bp@suse.de>
Signed-off-by: default avatarBrijesh Singh <brijesh.singh@amd.com>
Signed-off-by: default avatarRadim Krčmář <rkrcmar@redhat.com>
parent 14727754
...@@ -1133,6 +1133,7 @@ int kvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr); ...@@ -1133,6 +1133,7 @@ int kvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr);
struct x86_emulate_ctxt; struct x86_emulate_ctxt;
int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, unsigned short port); int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, unsigned short port);
int kvm_fast_pio_in(struct kvm_vcpu *vcpu, int size, unsigned short port);
void kvm_emulate_cpuid(struct kvm_vcpu *vcpu); void kvm_emulate_cpuid(struct kvm_vcpu *vcpu);
int kvm_emulate_halt(struct kvm_vcpu *vcpu); int kvm_emulate_halt(struct kvm_vcpu *vcpu);
int kvm_vcpu_halt(struct kvm_vcpu *vcpu); int kvm_vcpu_halt(struct kvm_vcpu *vcpu);
......
...@@ -2270,7 +2270,7 @@ static int io_interception(struct vcpu_svm *svm) ...@@ -2270,7 +2270,7 @@ static int io_interception(struct vcpu_svm *svm)
++svm->vcpu.stat.io_exits; ++svm->vcpu.stat.io_exits;
string = (io_info & SVM_IOIO_STR_MASK) != 0; string = (io_info & SVM_IOIO_STR_MASK) != 0;
in = (io_info & SVM_IOIO_TYPE_MASK) != 0; in = (io_info & SVM_IOIO_TYPE_MASK) != 0;
if (string || in) if (string)
return emulate_instruction(vcpu, 0) == EMULATE_DONE; return emulate_instruction(vcpu, 0) == EMULATE_DONE;
port = io_info >> 16; port = io_info >> 16;
...@@ -2278,7 +2278,8 @@ static int io_interception(struct vcpu_svm *svm) ...@@ -2278,7 +2278,8 @@ static int io_interception(struct vcpu_svm *svm)
svm->next_rip = svm->vmcb->control.exit_info_2; svm->next_rip = svm->vmcb->control.exit_info_2;
skip_emulated_instruction(&svm->vcpu); skip_emulated_instruction(&svm->vcpu);
return kvm_fast_pio_out(vcpu, size, port); return in ? kvm_fast_pio_in(vcpu, size, port)
: kvm_fast_pio_out(vcpu, size, port);
} }
static int nmi_interception(struct vcpu_svm *svm) static int nmi_interception(struct vcpu_svm *svm)
......
...@@ -5615,6 +5615,49 @@ int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, unsigned short port) ...@@ -5615,6 +5615,49 @@ int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, unsigned short port)
} }
EXPORT_SYMBOL_GPL(kvm_fast_pio_out); EXPORT_SYMBOL_GPL(kvm_fast_pio_out);
static int complete_fast_pio_in(struct kvm_vcpu *vcpu)
{
unsigned long val;
/* We should only ever be called with arch.pio.count equal to 1 */
BUG_ON(vcpu->arch.pio.count != 1);
/* For size less than 4 we merge, else we zero extend */
val = (vcpu->arch.pio.size < 4) ? kvm_register_read(vcpu, VCPU_REGS_RAX)
: 0;
/*
* Since vcpu->arch.pio.count == 1 let emulator_pio_in_emulated perform
* the copy and tracing
*/
emulator_pio_in_emulated(&vcpu->arch.emulate_ctxt, vcpu->arch.pio.size,
vcpu->arch.pio.port, &val, 1);
kvm_register_write(vcpu, VCPU_REGS_RAX, val);
return 1;
}
int kvm_fast_pio_in(struct kvm_vcpu *vcpu, int size, unsigned short port)
{
unsigned long val;
int ret;
/* For size less than 4 we merge, else we zero extend */
val = (size < 4) ? kvm_register_read(vcpu, VCPU_REGS_RAX) : 0;
ret = emulator_pio_in_emulated(&vcpu->arch.emulate_ctxt, size, port,
&val, 1);
if (ret) {
kvm_register_write(vcpu, VCPU_REGS_RAX, val);
return ret;
}
vcpu->arch.complete_userspace_io = complete_fast_pio_in;
return 0;
}
EXPORT_SYMBOL_GPL(kvm_fast_pio_in);
static int kvmclock_cpu_down_prep(unsigned int cpu) static int kvmclock_cpu_down_prep(unsigned int cpu)
{ {
__this_cpu_write(cpu_tsc_khz, 0); __this_cpu_write(cpu_tsc_khz, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment