A vcpu can be stopped after handling IO in userspace, but before returning to kernel to finish processing. Add ioctls to get/set the PIO state. Signed-off-by: Marcelo Tosatti <mtosatti@xxxxxxxxxx> diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h index f46b79f..c1b2b8c 100644 --- a/arch/x86/include/asm/kvm.h +++ b/arch/x86/include/asm/kvm.h @@ -284,4 +284,18 @@ struct kvm_vcpu_events { __u32 reserved[10]; }; +struct kvm_pio_request { + __u64 guest_gva; + __u32 count; + __u32 cur_count; + __u16 port; + __u8 size; + __u8 in; + __u8 string; + __u8 down; + __u8 rep; + __u8 pad; +}; + + #endif /* _ASM_X86_KVM_H */ diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 1522337..28f31e1 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -222,18 +222,6 @@ struct kvm_pv_mmu_op_buffer { char buf[512] __aligned(sizeof(long)); }; -struct kvm_pio_request { - unsigned long count; - int cur_count; - gva_t guest_gva; - int in; - int port; - int size; - int string; - int down; - int rep; -}; - /* * x86 supports 3 paging modes (4-level 64-bit, 3-level 64-bit, and 2-level * 32-bit). The kvm_mmu structure abstracts the details of the current mmu diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index ac8672f..99d991a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1575,6 +1575,9 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_COALESCED_MMIO: r = KVM_COALESCED_MMIO_PAGE_OFFSET; break; + case KVM_CAP_PIO: + r = KVM_PIO_PAGE_OFFSET; + break; case KVM_CAP_VAPIC: r = !kvm_x86_ops->cpu_has_accelerated_tpr(); break; @@ -2175,6 +2178,26 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu, return 0; } +static void kvm_vcpu_ioctl_x86_get_pio(struct kvm_vcpu *vcpu, + struct kvm_pio_request *pio) +{ + vcpu_load(vcpu); + memcpy(pio, &vcpu->arch.pio, sizeof(struct kvm_pio_request)); + vcpu_put(vcpu); +} + +static int kvm_vcpu_ioctl_x86_set_pio(struct kvm_vcpu *vcpu, + struct kvm_pio_request *pio) +{ + if (!pio->string && pio->size > 4) + return -EINVAL; + + vcpu_load(vcpu); + memcpy(&vcpu->arch.pio, pio, sizeof(struct kvm_pio_request)); + vcpu_put(vcpu); + return 0; +} + long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -2353,6 +2376,27 @@ long kvm_arch_vcpu_ioctl(struct file *filp, r = kvm_vcpu_ioctl_x86_set_vcpu_events(vcpu, &events); break; } + case KVM_SET_VCPU_PIO: { + struct kvm_pio_request pio; + + r = -EFAULT; + if (copy_from_user(&pio, argp, sizeof(struct kvm_pio_request))) + break; + + r = kvm_vcpu_ioctl_x86_set_pio(vcpu, &pio); + break; + } + case KVM_GET_VCPU_PIO: { + struct kvm_pio_request pio; + + kvm_vcpu_ioctl_x86_get_pio(vcpu, &pio); + + r = -EFAULT; + if (copy_to_user(argp, &pio, sizeof(struct kvm_pio_request))) + break; + r = 0; + break; + } default: r = -EINVAL; } diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 4c4937e..0b56d41 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -500,6 +500,7 @@ struct kvm_ioeventfd { #define KVM_CAP_HYPERV 44 #define KVM_CAP_HYPERV_VAPIC 45 #define KVM_CAP_HYPERV_SPIN 46 +#define KVM_CAP_PIO 47 #ifdef KVM_CAP_IRQ_ROUTING @@ -686,6 +687,8 @@ struct kvm_clock_data { /* Available with KVM_CAP_VCPU_EVENTS */ #define KVM_GET_VCPU_EVENTS _IOR(KVMIO, 0x9f, struct kvm_vcpu_events) #define KVM_SET_VCPU_EVENTS _IOW(KVMIO, 0xa0, struct kvm_vcpu_events) +#define KVM_GET_VCPU_PIO _IOR(KVMIO, 0xa1, struct kvm_pio_request) +#define KVM_SET_VCPU_PIO _IOW(KVMIO, 0xa2, struct kvm_pio_request) #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html