]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
VMCI: Support upto 64-bit PPNs
authorVishnu DASA <vdasa@vmware.com>
Fri, 15 Feb 2019 16:32:47 +0000 (16:32 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 26 Feb 2019 11:53:55 +0000 (12:53 +0100)
Add support in the VMCI driver to handle upto 64-bit PPNs when the VMCI
device exposes the capability for 64-bit PPNs.

Reviewed-by: Adit Ranadive <aditr@vmware.com>
Reviewed-by: Jorgen Hansen <jhansen@vmware.com>
Signed-off-by: Vishnu Dasa <vdasa@vmware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/vmw_vmci/vmci_doorbell.c
drivers/misc/vmw_vmci/vmci_doorbell.h
drivers/misc/vmw_vmci/vmci_driver.h
drivers/misc/vmw_vmci/vmci_guest.c
drivers/misc/vmw_vmci/vmci_queue_pair.c
drivers/misc/vmw_vmci/vmci_queue_pair.h
include/linux/vmw_vmci_defs.h

index b3fa738ae0050b48ba3f07ef3a02460d72898ea4..7824c7494916e35f31affc8ad8962c0672bb1942 100644 (file)
@@ -330,7 +330,7 @@ int vmci_dbell_host_context_notify(u32 src_cid, struct vmci_handle handle)
 /*
  * Register the notification bitmap with the host.
  */
-bool vmci_dbell_register_notification_bitmap(u32 bitmap_ppn)
+bool vmci_dbell_register_notification_bitmap(u64 bitmap_ppn)
 {
        int result;
        struct vmci_notify_bm_set_msg bitmap_set_msg;
@@ -340,11 +340,14 @@ bool vmci_dbell_register_notification_bitmap(u32 bitmap_ppn)
        bitmap_set_msg.hdr.src = VMCI_ANON_SRC_HANDLE;
        bitmap_set_msg.hdr.payload_size = sizeof(bitmap_set_msg) -
            VMCI_DG_HEADERSIZE;
-       bitmap_set_msg.bitmap_ppn = bitmap_ppn;
+       if (vmci_use_ppn64())
+               bitmap_set_msg.bitmap_ppn64 = bitmap_ppn;
+       else
+               bitmap_set_msg.bitmap_ppn32 = (u32) bitmap_ppn;
 
        result = vmci_send_datagram(&bitmap_set_msg.hdr);
        if (result != VMCI_SUCCESS) {
-               pr_devel("Failed to register (PPN=%u) as notification bitmap (error=%d)\n",
+               pr_devel("Failed to register (PPN=%llu) as notification bitmap (error=%d)\n",
                         bitmap_ppn, result);
                return false;
        }
index e4c0b17486a55c9b41e173944d0ef73ff0886411..410a21f8436f3d146e0440228deb0430349d1d79 100644 (file)
@@ -45,7 +45,7 @@ struct dbell_cpt_state {
 int vmci_dbell_host_context_notify(u32 src_cid, struct vmci_handle handle);
 int vmci_dbell_get_priv_flags(struct vmci_handle handle, u32 *priv_flags);
 
-bool vmci_dbell_register_notification_bitmap(u32 bitmap_ppn);
+bool vmci_dbell_register_notification_bitmap(u64 bitmap_ppn);
 void vmci_dbell_scan_notification_entries(u8 *bitmap);
 
 #endif /* VMCI_DOORBELL_H */
index cee9e977d318429bd84ab6703ab192ed19146488..2fbf4a0ac657953c3b18482acc12edba40b75e2c 100644 (file)
@@ -54,4 +54,6 @@ void vmci_guest_exit(void);
 bool vmci_guest_code_active(void);
 u32 vmci_get_vm_context_id(void);
 
+bool vmci_use_ppn64(void);
+
 #endif /* _VMCI_DRIVER_H_ */
index dad5abee656ef550b0ac041e354e2c7ef89164e3..928708128177d085485817ff71e83facab923c8b 100644 (file)
@@ -64,6 +64,13 @@ struct vmci_guest_device {
        dma_addr_t notification_base;
 };
 
+static bool use_ppn64;
+
+bool vmci_use_ppn64(void)
+{
+       return use_ppn64;
+}
+
 /* vmci_dev singleton device and supporting data*/
 struct pci_dev *vmci_pdev;
 static struct vmci_guest_device *vmci_dev_g;
@@ -432,6 +439,7 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
        struct vmci_guest_device *vmci_dev;
        void __iomem *iobase;
        unsigned int capabilities;
+       unsigned int caps_in_use;
        unsigned long cmd;
        int vmci_err;
        int error;
@@ -496,6 +504,23 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
                error = -ENXIO;
                goto err_free_data_buffer;
        }
+       caps_in_use = VMCI_CAPS_DATAGRAM;
+
+       /*
+        * Use 64-bit PPNs if the device supports.
+        *
+        * There is no check for the return value of dma_set_mask_and_coherent
+        * since this driver can handle the default mask values if
+        * dma_set_mask_and_coherent fails.
+        */
+       if (capabilities & VMCI_CAPS_PPN64) {
+               dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+               use_ppn64 = true;
+               caps_in_use |= VMCI_CAPS_PPN64;
+       } else {
+               dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(44));
+               use_ppn64 = false;
+       }
 
        /*
         * If the hardware supports notifications, we will use that as
@@ -510,14 +535,14 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
                                 "Unable to allocate notification bitmap\n");
                } else {
                        memset(vmci_dev->notification_bitmap, 0, PAGE_SIZE);
-                       capabilities |= VMCI_CAPS_NOTIFICATIONS;
+                       caps_in_use |= VMCI_CAPS_NOTIFICATIONS;
                }
        }
 
-       dev_info(&pdev->dev, "Using capabilities 0x%x\n", capabilities);
+       dev_info(&pdev->dev, "Using capabilities 0x%x\n", caps_in_use);
 
        /* Let the host know which capabilities we intend to use. */
-       iowrite32(capabilities, vmci_dev->iobase + VMCI_CAPS_ADDR);
+       iowrite32(caps_in_use, vmci_dev->iobase + VMCI_CAPS_ADDR);
 
        /* Set up global device so that we can start sending datagrams */
        spin_lock_irq(&vmci_dev_spinlock);
@@ -529,13 +554,13 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
         * Register notification bitmap with device if that capability is
         * used.
         */
-       if (capabilities & VMCI_CAPS_NOTIFICATIONS) {
+       if (caps_in_use & VMCI_CAPS_NOTIFICATIONS) {
                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",
-                                (u32) bitmap_ppn);
+                                "VMCI device unable to register notification bitmap with PPN 0x%lx\n",
+                                bitmap_ppn);
                        error = -ENXIO;
                        goto err_remove_vmci_dev_g;
                }
@@ -611,7 +636,7 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
 
        /* Enable specific interrupt bits. */
        cmd = VMCI_IMR_DATAGRAM;
-       if (capabilities & VMCI_CAPS_NOTIFICATIONS)
+       if (caps_in_use & VMCI_CAPS_NOTIFICATIONS)
                cmd |= VMCI_IMR_NOTIFICATION;
        iowrite32(cmd, vmci_dev->iobase + VMCI_IMR_ADDR);
 
index 264f4ed8eef26e8f839d121d905497c3c75de67c..f5f1aac9d1633189d2e5068dec76bdfc4b0fceb0 100644 (file)
@@ -435,8 +435,8 @@ static int qp_alloc_ppn_set(void *prod_q,
                            void *cons_q,
                            u64 num_consume_pages, struct ppn_set *ppn_set)
 {
-       u32 *produce_ppns;
-       u32 *consume_ppns;
+       u64 *produce_ppns;
+       u64 *consume_ppns;
        struct vmci_queue *produce_q = prod_q;
        struct vmci_queue *consume_q = cons_q;
        u64 i;
@@ -462,31 +462,13 @@ static int qp_alloc_ppn_set(void *prod_q,
                return VMCI_ERROR_NO_MEM;
        }
 
-       for (i = 0; i < num_produce_pages; i++) {
-               unsigned long pfn;
-
+       for (i = 0; i < num_produce_pages; i++)
                produce_ppns[i] =
                        produce_q->kernel_if->u.g.pas[i] >> PAGE_SHIFT;
-               pfn = produce_ppns[i];
-
-               /* Fail allocation if PFN isn't supported by hypervisor. */
-               if (sizeof(pfn) > sizeof(*produce_ppns)
-                   && pfn != produce_ppns[i])
-                       goto ppn_error;
-       }
-
-       for (i = 0; i < num_consume_pages; i++) {
-               unsigned long pfn;
 
+       for (i = 0; i < num_consume_pages; i++)
                consume_ppns[i] =
                        consume_q->kernel_if->u.g.pas[i] >> PAGE_SHIFT;
-               pfn = consume_ppns[i];
-
-               /* Fail allocation if PFN isn't supported by hypervisor. */
-               if (sizeof(pfn) > sizeof(*consume_ppns)
-                   && pfn != consume_ppns[i])
-                       goto ppn_error;
-       }
 
        ppn_set->num_produce_pages = num_produce_pages;
        ppn_set->num_consume_pages = num_consume_pages;
@@ -494,11 +476,6 @@ static int qp_alloc_ppn_set(void *prod_q,
        ppn_set->consume_ppns = consume_ppns;
        ppn_set->initialized = true;
        return VMCI_SUCCESS;
-
- ppn_error:
-       kfree(produce_ppns);
-       kfree(consume_ppns);
-       return VMCI_ERROR_INVALID_ARGS;
 }
 
 /*
@@ -520,12 +497,28 @@ static void qp_free_ppn_set(struct ppn_set *ppn_set)
  */
 static int qp_populate_ppn_set(u8 *call_buf, const struct ppn_set *ppn_set)
 {
-       memcpy(call_buf, ppn_set->produce_ppns,
-              ppn_set->num_produce_pages * sizeof(*ppn_set->produce_ppns));
-       memcpy(call_buf +
-              ppn_set->num_produce_pages * sizeof(*ppn_set->produce_ppns),
-              ppn_set->consume_ppns,
-              ppn_set->num_consume_pages * sizeof(*ppn_set->consume_ppns));
+       if (vmci_use_ppn64()) {
+               memcpy(call_buf, ppn_set->produce_ppns,
+                      ppn_set->num_produce_pages *
+                      sizeof(*ppn_set->produce_ppns));
+               memcpy(call_buf +
+                      ppn_set->num_produce_pages *
+                      sizeof(*ppn_set->produce_ppns),
+                      ppn_set->consume_ppns,
+                      ppn_set->num_consume_pages *
+                      sizeof(*ppn_set->consume_ppns));
+       } else {
+               int i;
+               u32 *ppns = (u32 *) call_buf;
+
+               for (i = 0; i < ppn_set->num_produce_pages; i++)
+                       ppns[i] = (u32) ppn_set->produce_ppns[i];
+
+               ppns = &ppns[ppn_set->num_produce_pages];
+
+               for (i = 0; i < ppn_set->num_consume_pages; i++)
+                       ppns[i] = (u32) ppn_set->consume_ppns[i];
+       }
 
        return VMCI_SUCCESS;
 }
@@ -951,13 +944,15 @@ static int qp_alloc_hypercall(const struct qp_guest_endpoint *entry)
 {
        struct vmci_qp_alloc_msg *alloc_msg;
        size_t msg_size;
+       size_t ppn_size;
        int result;
 
        if (!entry || entry->num_ppns <= 2)
                return VMCI_ERROR_INVALID_ARGS;
 
+       ppn_size = vmci_use_ppn64() ? sizeof(u64) : sizeof(u32);
        msg_size = sizeof(*alloc_msg) +
-           (size_t) entry->num_ppns * sizeof(u32);
+           (size_t) entry->num_ppns * ppn_size;
        alloc_msg = kmalloc(msg_size, GFP_KERNEL);
        if (!alloc_msg)
                return VMCI_ERROR_NO_MEM;
index ed177f04ef2442d50d26005acf6e4d50685f98cf..46c0b6c7bafbfcda3c02723f9a6bfe96442d725f 100644 (file)
@@ -28,8 +28,8 @@ typedef int (*vmci_event_release_cb) (void *client_data);
 struct ppn_set {
        u64 num_produce_pages;
        u64 num_consume_pages;
-       u32 *produce_ppns;
-       u32 *consume_ppns;
+       u64 *produce_ppns;
+       u64 *consume_ppns;
        bool initialized;
 };
 
index b724ef7005de6745bdd8856a8ab50d68bbef06ed..eaa1e762bf060b5b136ff7c219d75a670593b525 100644 (file)
@@ -45,6 +45,7 @@
 #define VMCI_CAPS_GUESTCALL     0x2
 #define VMCI_CAPS_DATAGRAM      0x4
 #define VMCI_CAPS_NOTIFICATIONS 0x8
+#define VMCI_CAPS_PPN64         0x10
 
 /* Interrupt Cause register bits. */
 #define VMCI_ICR_DATAGRAM      0x1
@@ -569,8 +570,10 @@ struct vmci_resource_query_msg {
  */
 struct vmci_notify_bm_set_msg {
        struct vmci_datagram hdr;
-       u32 bitmap_ppn;
-       u32 _pad;
+       union {
+               u32 bitmap_ppn32;
+               u64 bitmap_ppn64;
+       };
 };
 
 /*