Skip to content

Commit

Permalink
VMCI: Add support for virtual IOMMU
Browse files Browse the repository at this point in the history
This patch adds support for virtual IOMMU to the vmci module.  We switch
to DMA consistent mappings for guest queuepair and doorbell pages that
are passed to the device.  We still allocate each page individually,
since there's no guarantee that we'll get a contiguous block of physical
for an entire queuepair (especially since we allow up to 128 MiB!).

Also made the split between guest and host in the kernelIf struct much
clearer.  Now it's obvious which fields are which.

Acked-by: George Zhang <georgezhang@vmware.com>
Acked-by: Aditya Sarwade <asarwade@vmware.com>
Signed-off-by: Andy King <acking@vmware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Andy King authored and Greg Kroah-Hartman committed Aug 28, 2013
1 parent 45412be commit 6d6dfb4
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 83 deletions.
2 changes: 1 addition & 1 deletion drivers/misc/vmw_vmci/vmci_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,5 @@ module_exit(vmci_drv_exit);

MODULE_AUTHOR("VMware, Inc.");
MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface.");
MODULE_VERSION("1.0.0.0-k");
MODULE_VERSION("1.1.0.0-k");
MODULE_LICENSE("GPL v2");
7 changes: 7 additions & 0 deletions drivers/misc/vmw_vmci/vmci_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ struct vmci_obj {
enum vmci_obj_type type;
};

/*
* Needed by other components of this module. It's okay to have one global
* instance of this because there can only ever be one VMCI device. Our
* virtual hardware enforces this.
*/
extern struct pci_dev *vmci_pdev;

u32 vmci_get_context_id(void);
int vmci_send_datagram(struct vmci_datagram *dg);

Expand Down
22 changes: 16 additions & 6 deletions drivers/misc/vmw_vmci/vmci_guest.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,11 @@ struct vmci_guest_device {

void *data_buffer;
void *notification_bitmap;
dma_addr_t notification_base;
};

/* vmci_dev singleton device and supporting data*/
struct pci_dev *vmci_pdev;
static struct vmci_guest_device *vmci_dev_g;
static DEFINE_SPINLOCK(vmci_dev_spinlock);

Expand Down Expand Up @@ -528,7 +530,9 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
* well.
*/
if (capabilities & VMCI_CAPS_NOTIFICATIONS) {
vmci_dev->notification_bitmap = vmalloc(PAGE_SIZE);
vmci_dev->notification_bitmap = dma_alloc_coherent(
&pdev->dev, PAGE_SIZE, &vmci_dev->notification_base,
GFP_KERNEL);
if (!vmci_dev->notification_bitmap) {
dev_warn(&pdev->dev,
"Unable to allocate notification bitmap\n");
Expand All @@ -546,16 +550,16 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
/* Set up global device so that we can start sending datagrams */
spin_lock_irq(&vmci_dev_spinlock);
vmci_dev_g = vmci_dev;
vmci_pdev = pdev;
spin_unlock_irq(&vmci_dev_spinlock);

/*
* Register notification bitmap with device if that capability is
* used.
*/
if (capabilities & VMCI_CAPS_NOTIFICATIONS) {
struct page *page =
vmalloc_to_page(vmci_dev->notification_bitmap);
unsigned long bitmap_ppn = page_to_pfn(page);
unsigned long bitmap_ppn =
vmci_dev->notification_base >> PAGE_SHIFT;
if (!vmci_dbell_register_notification_bitmap(bitmap_ppn)) {
dev_warn(&pdev->dev,
"VMCI device unable to register notification bitmap with PPN 0x%x\n",
Expand Down Expand Up @@ -665,11 +669,14 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
if (vmci_dev->notification_bitmap) {
iowrite32(VMCI_CONTROL_RESET,
vmci_dev->iobase + VMCI_CONTROL_ADDR);
vfree(vmci_dev->notification_bitmap);
dma_free_coherent(&pdev->dev, PAGE_SIZE,
vmci_dev->notification_bitmap,
vmci_dev->notification_base);
}

err_remove_vmci_dev_g:
spin_lock_irq(&vmci_dev_spinlock);
vmci_pdev = NULL;
vmci_dev_g = NULL;
spin_unlock_irq(&vmci_dev_spinlock);

Expand Down Expand Up @@ -699,6 +706,7 @@ static void vmci_guest_remove_device(struct pci_dev *pdev)

spin_lock_irq(&vmci_dev_spinlock);
vmci_dev_g = NULL;
vmci_pdev = NULL;
spin_unlock_irq(&vmci_dev_spinlock);

dev_dbg(&pdev->dev, "Resetting vmci device\n");
Expand Down Expand Up @@ -727,7 +735,9 @@ static void vmci_guest_remove_device(struct pci_dev *pdev)
* device, so we can safely free it here.
*/

vfree(vmci_dev->notification_bitmap);
dma_free_coherent(&pdev->dev, PAGE_SIZE,
vmci_dev->notification_bitmap,
vmci_dev->notification_base);
}

vfree(vmci_dev->data_buffer);
Expand Down
Loading

0 comments on commit 6d6dfb4

Please sign in to comment.