|
@@ -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);
|
|
|
|
|
|
+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)
|
|
|
{
|
|
|
__this_cpu_write(cpu_tsc_khz, 0);
|