VMCI: Support upto 64-bit PPNs
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>
This commit is contained in:
parent
bede03a579
commit
f2db7361cb
@ -330,7 +330,7 @@ int vmci_dbell_host_context_notify(u32 src_cid, struct vmci_handle handle)
|
|||||||
/*
|
/*
|
||||||
* Register the notification bitmap with the host.
|
* 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;
|
int result;
|
||||||
struct vmci_notify_bm_set_msg bitmap_set_msg;
|
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.src = VMCI_ANON_SRC_HANDLE;
|
||||||
bitmap_set_msg.hdr.payload_size = sizeof(bitmap_set_msg) -
|
bitmap_set_msg.hdr.payload_size = sizeof(bitmap_set_msg) -
|
||||||
VMCI_DG_HEADERSIZE;
|
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);
|
result = vmci_send_datagram(&bitmap_set_msg.hdr);
|
||||||
if (result != VMCI_SUCCESS) {
|
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);
|
bitmap_ppn, result);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ struct dbell_cpt_state {
|
|||||||
int vmci_dbell_host_context_notify(u32 src_cid, struct vmci_handle handle);
|
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);
|
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);
|
void vmci_dbell_scan_notification_entries(u8 *bitmap);
|
||||||
|
|
||||||
#endif /* VMCI_DOORBELL_H */
|
#endif /* VMCI_DOORBELL_H */
|
||||||
|
@ -54,4 +54,6 @@ void vmci_guest_exit(void);
|
|||||||
bool vmci_guest_code_active(void);
|
bool vmci_guest_code_active(void);
|
||||||
u32 vmci_get_vm_context_id(void);
|
u32 vmci_get_vm_context_id(void);
|
||||||
|
|
||||||
|
bool vmci_use_ppn64(void);
|
||||||
|
|
||||||
#endif /* _VMCI_DRIVER_H_ */
|
#endif /* _VMCI_DRIVER_H_ */
|
||||||
|
@ -64,6 +64,13 @@ struct vmci_guest_device {
|
|||||||
dma_addr_t notification_base;
|
dma_addr_t notification_base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool use_ppn64;
|
||||||
|
|
||||||
|
bool vmci_use_ppn64(void)
|
||||||
|
{
|
||||||
|
return use_ppn64;
|
||||||
|
}
|
||||||
|
|
||||||
/* vmci_dev singleton device and supporting data*/
|
/* vmci_dev singleton device and supporting data*/
|
||||||
struct pci_dev *vmci_pdev;
|
struct pci_dev *vmci_pdev;
|
||||||
static struct vmci_guest_device *vmci_dev_g;
|
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;
|
struct vmci_guest_device *vmci_dev;
|
||||||
void __iomem *iobase;
|
void __iomem *iobase;
|
||||||
unsigned int capabilities;
|
unsigned int capabilities;
|
||||||
|
unsigned int caps_in_use;
|
||||||
unsigned long cmd;
|
unsigned long cmd;
|
||||||
int vmci_err;
|
int vmci_err;
|
||||||
int error;
|
int error;
|
||||||
@ -496,6 +504,23 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
|
|||||||
error = -ENXIO;
|
error = -ENXIO;
|
||||||
goto err_free_data_buffer;
|
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
|
* 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");
|
"Unable to allocate notification bitmap\n");
|
||||||
} else {
|
} else {
|
||||||
memset(vmci_dev->notification_bitmap, 0, PAGE_SIZE);
|
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. */
|
/* 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 */
|
/* Set up global device so that we can start sending datagrams */
|
||||||
spin_lock_irq(&vmci_dev_spinlock);
|
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
|
* Register notification bitmap with device if that capability is
|
||||||
* used.
|
* used.
|
||||||
*/
|
*/
|
||||||
if (capabilities & VMCI_CAPS_NOTIFICATIONS) {
|
if (caps_in_use & VMCI_CAPS_NOTIFICATIONS) {
|
||||||
unsigned long bitmap_ppn =
|
unsigned long bitmap_ppn =
|
||||||
vmci_dev->notification_base >> PAGE_SHIFT;
|
vmci_dev->notification_base >> PAGE_SHIFT;
|
||||||
if (!vmci_dbell_register_notification_bitmap(bitmap_ppn)) {
|
if (!vmci_dbell_register_notification_bitmap(bitmap_ppn)) {
|
||||||
dev_warn(&pdev->dev,
|
dev_warn(&pdev->dev,
|
||||||
"VMCI device unable to register notification bitmap with PPN 0x%x\n",
|
"VMCI device unable to register notification bitmap with PPN 0x%lx\n",
|
||||||
(u32) bitmap_ppn);
|
bitmap_ppn);
|
||||||
error = -ENXIO;
|
error = -ENXIO;
|
||||||
goto err_remove_vmci_dev_g;
|
goto err_remove_vmci_dev_g;
|
||||||
}
|
}
|
||||||
@ -611,7 +636,7 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
|
|||||||
|
|
||||||
/* Enable specific interrupt bits. */
|
/* Enable specific interrupt bits. */
|
||||||
cmd = VMCI_IMR_DATAGRAM;
|
cmd = VMCI_IMR_DATAGRAM;
|
||||||
if (capabilities & VMCI_CAPS_NOTIFICATIONS)
|
if (caps_in_use & VMCI_CAPS_NOTIFICATIONS)
|
||||||
cmd |= VMCI_IMR_NOTIFICATION;
|
cmd |= VMCI_IMR_NOTIFICATION;
|
||||||
iowrite32(cmd, vmci_dev->iobase + VMCI_IMR_ADDR);
|
iowrite32(cmd, vmci_dev->iobase + VMCI_IMR_ADDR);
|
||||||
|
|
||||||
|
@ -435,8 +435,8 @@ static int qp_alloc_ppn_set(void *prod_q,
|
|||||||
void *cons_q,
|
void *cons_q,
|
||||||
u64 num_consume_pages, struct ppn_set *ppn_set)
|
u64 num_consume_pages, struct ppn_set *ppn_set)
|
||||||
{
|
{
|
||||||
u32 *produce_ppns;
|
u64 *produce_ppns;
|
||||||
u32 *consume_ppns;
|
u64 *consume_ppns;
|
||||||
struct vmci_queue *produce_q = prod_q;
|
struct vmci_queue *produce_q = prod_q;
|
||||||
struct vmci_queue *consume_q = cons_q;
|
struct vmci_queue *consume_q = cons_q;
|
||||||
u64 i;
|
u64 i;
|
||||||
@ -462,31 +462,13 @@ static int qp_alloc_ppn_set(void *prod_q,
|
|||||||
return VMCI_ERROR_NO_MEM;
|
return VMCI_ERROR_NO_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_produce_pages; i++) {
|
for (i = 0; i < num_produce_pages; i++)
|
||||||
unsigned long pfn;
|
|
||||||
|
|
||||||
produce_ppns[i] =
|
produce_ppns[i] =
|
||||||
produce_q->kernel_if->u.g.pas[i] >> PAGE_SHIFT;
|
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_ppns[i] =
|
||||||
consume_q->kernel_if->u.g.pas[i] >> PAGE_SHIFT;
|
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_produce_pages = num_produce_pages;
|
||||||
ppn_set->num_consume_pages = num_consume_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->consume_ppns = consume_ppns;
|
||||||
ppn_set->initialized = true;
|
ppn_set->initialized = true;
|
||||||
return VMCI_SUCCESS;
|
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)
|
static int qp_populate_ppn_set(u8 *call_buf, const struct ppn_set *ppn_set)
|
||||||
{
|
{
|
||||||
memcpy(call_buf, ppn_set->produce_ppns,
|
if (vmci_use_ppn64()) {
|
||||||
ppn_set->num_produce_pages * sizeof(*ppn_set->produce_ppns));
|
memcpy(call_buf, ppn_set->produce_ppns,
|
||||||
memcpy(call_buf +
|
ppn_set->num_produce_pages *
|
||||||
ppn_set->num_produce_pages * sizeof(*ppn_set->produce_ppns),
|
sizeof(*ppn_set->produce_ppns));
|
||||||
ppn_set->consume_ppns,
|
memcpy(call_buf +
|
||||||
ppn_set->num_consume_pages * sizeof(*ppn_set->consume_ppns));
|
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;
|
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;
|
struct vmci_qp_alloc_msg *alloc_msg;
|
||||||
size_t msg_size;
|
size_t msg_size;
|
||||||
|
size_t ppn_size;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (!entry || entry->num_ppns <= 2)
|
if (!entry || entry->num_ppns <= 2)
|
||||||
return VMCI_ERROR_INVALID_ARGS;
|
return VMCI_ERROR_INVALID_ARGS;
|
||||||
|
|
||||||
|
ppn_size = vmci_use_ppn64() ? sizeof(u64) : sizeof(u32);
|
||||||
msg_size = sizeof(*alloc_msg) +
|
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);
|
alloc_msg = kmalloc(msg_size, GFP_KERNEL);
|
||||||
if (!alloc_msg)
|
if (!alloc_msg)
|
||||||
return VMCI_ERROR_NO_MEM;
|
return VMCI_ERROR_NO_MEM;
|
||||||
|
@ -28,8 +28,8 @@ typedef int (*vmci_event_release_cb) (void *client_data);
|
|||||||
struct ppn_set {
|
struct ppn_set {
|
||||||
u64 num_produce_pages;
|
u64 num_produce_pages;
|
||||||
u64 num_consume_pages;
|
u64 num_consume_pages;
|
||||||
u32 *produce_ppns;
|
u64 *produce_ppns;
|
||||||
u32 *consume_ppns;
|
u64 *consume_ppns;
|
||||||
bool initialized;
|
bool initialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#define VMCI_CAPS_GUESTCALL 0x2
|
#define VMCI_CAPS_GUESTCALL 0x2
|
||||||
#define VMCI_CAPS_DATAGRAM 0x4
|
#define VMCI_CAPS_DATAGRAM 0x4
|
||||||
#define VMCI_CAPS_NOTIFICATIONS 0x8
|
#define VMCI_CAPS_NOTIFICATIONS 0x8
|
||||||
|
#define VMCI_CAPS_PPN64 0x10
|
||||||
|
|
||||||
/* Interrupt Cause register bits. */
|
/* Interrupt Cause register bits. */
|
||||||
#define VMCI_ICR_DATAGRAM 0x1
|
#define VMCI_ICR_DATAGRAM 0x1
|
||||||
@ -569,8 +570,10 @@ struct vmci_resource_query_msg {
|
|||||||
*/
|
*/
|
||||||
struct vmci_notify_bm_set_msg {
|
struct vmci_notify_bm_set_msg {
|
||||||
struct vmci_datagram hdr;
|
struct vmci_datagram hdr;
|
||||||
u32 bitmap_ppn;
|
union {
|
||||||
u32 _pad;
|
u32 bitmap_ppn32;
|
||||||
|
u64 bitmap_ppn64;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user