diff --git a/Makefile b/Makefile index 2c1667b..ba80cb0 100644 --- vmci-only/Makefile +++ vmci-only/Makefile @@ -107,7 +107,7 @@ prebuild:: ; postbuild:: ; $(DRIVER_KO): prebuild - $(MAKE) -C $(BUILD_DIR) SUBDIRS=$$PWD SRCROOT=$$PWD/$(SRCROOT) \ + $(MAKE) -C $(BUILD_DIR) M=$$PWD SRCROOT=$$PWD/$(SRCROOT) \ MODULEBUILDDIR=$(MODULEBUILDDIR) modules $(MAKE) -C $$PWD SRCROOT=$$PWD/$(SRCROOT) \ MODULEBUILDDIR=$(MODULEBUILDDIR) postbuild diff --git a/linux/driver.c b/linux/driver.c index 8ab2064..c0b8328 100644 --- vmci-only/linux/driver.c +++ vmci-only/linux/driver.c @@ -26,6 +26,7 @@ #include #include +#include #include #if defined(__x86_64__) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12) # include @@ -33,6 +34,7 @@ asmlinkage __attribute__((weak)) long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); #endif + #include #include #include @@ -1437,7 +1439,7 @@ static INLINE Bool VMCIUserVAInvalidPointer(VA uva, // IN: size_t size) // IN: { - return !access_ok(VERIFY_WRITE, (void *)uva, size); + return !access_ok((void *)uva, size); } @@ -1467,11 +1469,19 @@ VMCIUserVALockPage(VA addr) // IN: down_read(¤t->mm->mmap_sem); #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) - retval = get_user_pages(addr, 1, 1, 0, &page, NULL); + retval = get_user_pages(addr, #else retval = get_user_pages(current, current->mm, addr, 1, 1, 0, &page, NULL); #endif + 1, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) + 1, 0, +#else + FOLL_WRITE, +#endif + &page, NULL); + up_read(¤t->mm->mmap_sem); if (retval != 1) { @@ -1686,7 +1696,7 @@ vmci_guest_init(void) /* This should be last to make sure we are done initializing. */ retval = pci_register_driver(&vmci_driver); if (retval < 0) { - vfree(data_buffer); + kvfree(data_buffer); data_buffer = NULL; return retval; } @@ -1721,13 +1731,26 @@ vmci_enable_msix(struct pci_dev *pdev) // IN vmci_dev.msix_entries[i].entry = i; vmci_dev.msix_entries[i].vector = i; } - +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) result = pci_enable_msix(pdev, vmci_dev.msix_entries, VMCI_MAX_INTRS); if (!result) { vmci_dev.exclusive_vectors = TRUE; } else if (result > 0) { result = pci_enable_msix(pdev, vmci_dev.msix_entries, 1); } +#else + result = pci_enable_msix_range(pdev, vmci_dev.msix_entries, VMCI_MAX_INTRS, + VMCI_MAX_INTRS); + if (result > 0) { + vmci_dev.exclusive_vectors = TRUE; + } else if (result == -ENOSPC) { + result = pci_enable_msix_range(pdev, vmci_dev.msix_entries, 1, 1); + } + + if (result > 0) + result = 0; +#endif + return result; } @@ -2480,7 +2503,7 @@ vmci_exit(void) if (guestDeviceInit) { pci_unregister_driver(&vmci_driver); - vfree(data_buffer); + kvfree(data_buffer); data_buffer = NULL; guestDeviceInit = FALSE; } @@ -2490,7 +2513,7 @@ vmci_exit(void) VMCI_HostCleanup(); - retval = misc_deregister(&linuxState.misc); + retval = compat_misc_deregister(&linuxState.misc); if (retval) { Warning(LGPFX "Module %s: error unregistering\n", VMCI_MODULE_NAME); } else { diff --git a/linux/vmciKernelIf.c b/linux/vmciKernelIf.c index 2b274a0..5e8a9e9 100644 --- vmci-only/linux/vmciKernelIf.c +++ vmci-only/linux/vmciKernelIf.c @@ -40,6 +40,10 @@ #include /* For memcpy_{to,from}iovec(). */ #include #include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) +#include +#endif #include "compat_highmem.h" #include "compat_interrupt.h" @@ -1196,21 +1200,21 @@ __VMCIMemcpyToQueue(VMCIQueue *queue, // OUT: } else { toCopy = size - bytesCopied; } - + /* Code cloned from kernels drivers/misc/vmw_vmci/vmci_queue_pair.c */ if (isIovec) { - struct iovec *iov = (struct iovec *)src; - int err; - - /* The iovec will track bytesCopied internally. */ - err = memcpy_fromiovec((uint8 *)va + pageOffset, iov, toCopy); - if (err != 0) { - if (kernelIf->host) { - kunmap(kernelIf->u.h.page[pageIndex]); + struct msghdr *msg = (struct msghdr *)src; + int err; + + /* The iovec will track bytes_copied internally. */ + err = memcpy_from_msg((u8 *)va + pageOffset, msg, toCopy); + if (err != 0) { + if (kernelIf->host) + kunmap(kernelIf->u.h.page[pageIndex]); + return VMCI_ERROR_INVALID_ARGS; } - return VMCI_ERROR_INVALID_ARGS; - } - } else { - memcpy((uint8 *)va + pageOffset, (uint8 *)src + bytesCopied, toCopy); + } else { + memcpy((u8 *)va + pageOffset, + (u8 *)src + bytesCopied, toCopy); } bytesCopied += toCopy; @@ -1273,11 +1277,11 @@ __VMCIMemcpyFromQueue(void *dest, // OUT: } if (isIovec) { - struct iovec *iov = (struct iovec *)dest; + struct msghdr *msg = (struct msghdr *)dest; int err; /* The iovec will track bytesCopied internally. */ - err = memcpy_toiovec(iov, (uint8 *)va + pageOffset, toCopy); + err = memcpy_to_msg(msg, (uint8 *)va + pageOffset, toCopy); if (err != 0) { if (kernelIf->host) { kunmap(kernelIf->u.h.page[pageIndex]); @@ -1834,7 +1838,11 @@ VMCIReleasePages(struct page **pages, // IN if (dirty) { set_page_dirty(pages[i]); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 99) + put_page(pages[i]); +#else page_cache_release(pages[i]); +#endif pages[i] = NULL; } } @@ -2050,19 +2058,20 @@ VMCIHost_GetUserMemory(VA64 produceUVA, // IN down_write(¤t->mm->mmap_sem); #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) retval = get_user_pages((VA)produceUVA, - produceQ->kernelIf->numPages, - 1, 0, - produceQ->kernelIf->u.h.headerPage, - NULL); #else retval = get_user_pages(current, current->mm, (VA)produceUVA, +#endif produceQ->kernelIf->numPages, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) 1, 0, +#else + FOLL_WRITE, +#endif produceQ->kernelIf->u.h.headerPage, NULL); -#endif + if (retval < produceQ->kernelIf->numPages) { Log("get_user_pages(produce) failed (retval=%d)\n", retval); VMCIReleasePages(produceQ->kernelIf->u.h.headerPage, retval, FALSE); @@ -2070,13 +2079,22 @@ VMCIHost_GetUserMemory(VA64 produceUVA, // IN goto out; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) + retval = get_user_pages((VA)consumeUVA, +#else retval = get_user_pages(current, current->mm, (VA)consumeUVA, +#endif consumeQ->kernelIf->numPages, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) 1, 0, +#else + FOLL_WRITE, +#endif consumeQ->kernelIf->u.h.headerPage, NULL); + if (retval < consumeQ->kernelIf->numPages) { Log("get_user_pages(consume) failed (retval=%d)\n", retval); VMCIReleasePages(consumeQ->kernelIf->u.h.headerPage, retval, FALSE); diff --git a/shared/compat_module.h b/shared/compat_module.h index 2af7372..de1713d 100644 --- vmci-only/shared/compat_module.h +++ vmci-only/shared/compat_module.h @@ -79,5 +79,12 @@ static const char __module_cat(tag, __LINE__)[] \ #else typedef int compat_mod_param_bool; #endif - +/* + * Linux kernel >= 4.2.99 does not return anything from misc_deregister + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) +#define compat_misc_deregister(misc) misc_deregister(misc) +#else +#define compat_misc_deregister(misc) ({misc_deregister(misc);0;}) +#endif #endif /* __COMPAT_MODULE_H__ */ diff --git a/shared/vm_device_version.h b/shared/vm_device_version.h index ab396bc..f17a892 100644 --- vmci-only/shared/vm_device_version.h +++ vmci-only/shared/vm_device_version.h @@ -53,7 +53,9 @@ * VMware HD Audio codec * VMware HD Audio controller */ +#ifndef PCI_VENDOR_ID_VMWARE #define PCI_VENDOR_ID_VMWARE 0x15AD +#endif #define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405 #define PCI_DEVICE_ID_VMWARE_SVGA 0x0710 #define PCI_DEVICE_ID_VMWARE_VGA 0x0711 @@ -70,7 +72,9 @@ #define PCI_DEVICE_ID_VMWARE_1394 0x0780 #define PCI_DEVICE_ID_VMWARE_BRIDGE 0x0790 #define PCI_DEVICE_ID_VMWARE_ROOTPORT 0x07A0 +#ifndef PCI_DEVICE_ID_VMWARE_VMXNET3 #define PCI_DEVICE_ID_VMWARE_VMXNET3 0x07B0 +#endif #define PCI_DEVICE_ID_VMWARE_PVSCSI 0x07C0 #define PCI_DEVICE_ID_VMWARE_82574 0x07D0 #define PCI_DEVICE_ID_VMWARE_AHCI 0x07E0 diff --git a/shared/vmci_kernel_if.h b/shared/vmci_kernel_if.h index ef9eb82..dbd3f5e 100644 --- vmci-only/shared/vmci_kernel_if.h +++ vmci-only/shared/vmci_kernel_if.h @@ -100,7 +100,7 @@ extern "C" { typedef Semaphore VMCIEvent; typedef Semaphore VMCIMutex; typedef World_ID VMCIHostVmID; - typedef uint32 VMCIHostUser; + typedef uint32_t VMCIHostUser; typedef PPN *VMCIQPGuestMem; #elif defined(__linux__) typedef spinlock_t VMCILock;