From: Eran Borovik <borove@xxxxxxxxxx> This patch adds modifications to allow correct balloon operation when a virtual guest uses a direct assigned device. The modifications include a new interface between qemu and kvm to allow mapping and unmapping the pages from the IOMMU as well as pinning and unpinning as needed. Signed-off-by: Eran Borovik <borove@xxxxxxxxxx> --- hw/virtio-balloon.c | 13 ++++++++++--- kvm/include/linux/kvm.h | 2 ++ kvm/libkvm/libkvm.h | 4 ++++ qemu-kvm.c | 10 ++++++++++ qemu-kvm.h | 4 ++++ 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c index 3792012..337f717 100644 --- a/hw/virtio-balloon.c +++ b/hw/virtio-balloon.c @@ -132,6 +132,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) elem.out_sg, elem.out_num) == 4) { ram_addr_t pa; ram_addr_t addr; + bool deflate; pa = (ram_addr_t)ldl_p(&pfn) << VIRTIO_BALLOON_PFN_SHIFT; offset += 4; @@ -139,12 +140,18 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) addr = cpu_get_physical_page_desc(pa); if ((addr & ~TARGET_PAGE_MASK) != IO_MEM_RAM) continue; + deflate = !!(vq == s->dvq); +# ifdef KVM_CAP_DEVICE_ASSIGNMENT + if (deflate) + kvm_map_pfn(NULL, pfn); + else + kvm_unmap_pfn(NULL, pfn); +# endif /* Using qemu_get_ram_ptr is bending the rules a bit, but should be OK because we only want a single page. */ - balloon_page(qemu_get_ram_ptr(addr), !!(vq == s->dvq)); - } - + balloon_page(qemu_get_ram_ptr(addr), deflate); + } virtqueue_push(vq, &elem, offset); virtio_notify(vdev, vq); } diff --git a/kvm/include/linux/kvm.h b/kvm/include/linux/kvm.h index 6485981..90f7723 100644 --- a/kvm/include/linux/kvm.h +++ b/kvm/include/linux/kvm.h @@ -595,6 +595,8 @@ struct kvm_clock_data { struct kvm_userspace_memory_region) #define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47) #define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64) +#define KVM_IOMMU_UNMAP_PAGE _IOW(KVMIO, 0x49, __u64) +#define KVM_IOMMU_MAP_PAGE _IOW(KVMIO, 0x50, __u64) /* Device model IOC */ #define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60) #define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level) diff --git a/kvm/libkvm/libkvm.h b/kvm/libkvm/libkvm.h index 4821a1e..7fa83b5 100644 --- a/kvm/libkvm/libkvm.h +++ b/kvm/libkvm/libkvm.h @@ -714,6 +714,10 @@ int kvm_s390_store_status(kvm_context_t kvm, int slot, unsigned long addr); int kvm_assign_pci_device(kvm_context_t kvm, struct kvm_assigned_pci_dev *assigned_dev); +int kvm_deflate_pfn(kvm_context_t kvm, uint32_t pfn); + +int kvm_inflate_pfn(kvm_context_t kvm, uint32_t pfn); + /*! * \brief Assign IRQ for an assigned device * diff --git a/qemu-kvm.c b/qemu-kvm.c index a305907..a5ca029 100644 --- a/qemu-kvm.c +++ b/qemu-kvm.c @@ -1081,6 +1081,16 @@ static int kvm_old_assign_irq(kvm_context_t kvm, return kvm_vm_ioctl(kvm_state, KVM_ASSIGN_IRQ, assigned_irq); } +int kvm_unmap_pfn(kvm_context_t kvm, uint32_t pfn) +{ + return kvm_vm_ioctl(kvm_state, KVM_IOMMU_UNMAP_PAGE, pfn); +} + +int kvm_map_pfn(kvm_context_t kvm, uint32_t pfn) +{ + return kvm_vm_ioctl(kvm_state, KVM_IOMMU_MAP_PAGE, pfn); +} + #ifdef KVM_CAP_ASSIGN_DEV_IRQ int kvm_assign_irq(kvm_context_t kvm, struct kvm_assigned_irq *assigned_irq) { diff --git a/qemu-kvm.h b/qemu-kvm.h index 6b3e5a1..861c336 100644 --- a/qemu-kvm.h +++ b/qemu-kvm.h @@ -691,6 +691,10 @@ int kvm_s390_store_status(kvm_context_t kvm, int slot, unsigned long addr); int kvm_assign_pci_device(kvm_context_t kvm, struct kvm_assigned_pci_dev *assigned_dev); +int kvm_unmap_pfn(kvm_context_t kvm, uint32_t pfn); + +int kvm_map_pfn(kvm_context_t kvm, uint32_t pfn); + /*! * \brief Assign IRQ for an assigned device * -- 1.6.0.4 -- 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