diff options
Diffstat (limited to 'vmmon.patch')
-rw-r--r-- | vmmon.patch | 1414 |
1 files changed, 957 insertions, 457 deletions
diff --git a/vmmon.patch b/vmmon.patch index a801be3b146f..9a62baa87f17 100644 --- a/vmmon.patch +++ b/vmmon.patch @@ -1,8 +1,6 @@ -diff --git a/vmmon/Makefile b/vmmon/Makefile -index de8162e..6124a71 100644 --- a/vmmon/Makefile +++ b/vmmon/Makefile -@@ -43,7 +43,11 @@ INCLUDE += -I$(SRCROOT)/shared +@@ -43,7 +43,11 @@ endif @@ -14,11 +12,32 @@ index de8162e..6124a71 100644 # Header directory for the running kernel ifdef LINUXINCLUDE -diff --git a/vmmon/common/hostif.h b/vmmon/common/hostif.h -index 865abc0..2b94ce1 100644 +@@ -100,6 +104,13 @@ auto-build: $(DRIVER_KO) + $(DRIVER): $(DRIVER_KO) + if [ $< -nt $@ ] || [ ! -e $@ ] ; then cp -f $< $@; fi + ++# Use SUBDIRS on 2.x, 3.x, 4.x. Use M on newer kernels. ++ifeq ($(filter-out 2 3 4,$(firstword $(subst ., ,$(VM_UNAME)))),) ++DIRVAR := SUBDIRS ++else ++DIRVAR := M ++endif ++ + # Pass gcc version down the chain, so we can detect if kernel attempts to use unapproved compiler + VM_CCVER := $(VMCCVER) + export VM_CCVER +@@ -117,7 +128,7 @@ prebuild:: ; + postbuild:: ; + + $(DRIVER_KO): prebuild +- $(MAKE) -C $(BUILD_DIR) SUBDIRS=$$PWD SRCROOT=$$PWD/$(SRCROOT) \ ++ $(MAKE) -C $(BUILD_DIR) $(DIRVAR)=$$PWD SRCROOT=$$PWD/$(SRCROOT) \ + MODULEBUILDDIR=$(MODULEBUILDDIR) modules + $(MAKE) -C $$PWD SRCROOT=$$PWD/$(SRCROOT) \ + MODULEBUILDDIR=$(MODULEBUILDDIR) postbuild --- a/vmmon/common/hostif.h +++ b/vmmon/common/hostif.h -@@ -122,14 +122,10 @@ EXTERN MPN64 HostIF_GetNextAnonPage(VMDriver *vm, MPN64 mpn); +@@ -122,14 +122,10 @@ EXTERN MPN64 HostIF_GetNextAnonPage(VMDr EXTERN int HostIF_GetLockedPageList(VMDriver *vm, VA64 uAddr, unsigned int numPages); @@ -36,7 +55,7 @@ index 865abc0..2b94ce1 100644 #if defined __APPLE__ // There is no need for a fast clock lock on Mac OS. #define HostIF_FastClockLock(_callerID) do {} while (0) -@@ -145,4 +141,8 @@ EXTERN void HostIF_FreeMachinePage(MPN64 mpn); +@@ -145,4 +141,8 @@ EXTERN void HostIF_FreeMachinePage(MPN64 EXTERN int HostIF_SafeRDMSR(uint32 msr, uint64 *val); @@ -45,8 +64,6 @@ index 865abc0..2b94ce1 100644 +#endif + #endif // ifdef _HOSTIF_H_ -diff --git a/vmmon/common/memtrack.c b/vmmon/common/memtrack.c -index e53daeb..eec9844 100644 --- a/vmmon/common/memtrack.c +++ b/vmmon/common/memtrack.c @@ -88,6 +88,7 @@ @@ -170,8 +187,6 @@ index e53daeb..eec9844 100644 /* -diff --git a/vmmon/common/memtrack.h b/vmmon/common/memtrack.h -index 977c5af..6d104ad 100644 --- a/vmmon/common/memtrack.h +++ b/vmmon/common/memtrack.h @@ -31,30 +31,22 @@ @@ -206,8 +221,6 @@ index 977c5af..6d104ad 100644 -#endif #endif // _MEMTRACK_H_ -diff --git a/vmmon/common/task.c b/vmmon/common/task.c -index de2429e..228996e 100644 --- a/vmmon/common/task.c +++ b/vmmon/common/task.c @@ -39,6 +39,9 @@ @@ -234,7 +247,7 @@ index de2429e..228996e 100644 #if defined(_WIN64) # include "x86.h" # include "vmmon-asm-x86-64.h" -@@ -708,11 +718,28 @@ TaskRestoreHostGDTTRLDT(Descriptor *tempGDTBase, +@@ -708,11 +718,28 @@ TaskRestoreHostGDTTRLDT(Descriptor *temp */ desc = (Descriptor *)((VA)HOST_KERNEL_LA_2_VA(hostGDT64.offset + tr)); @@ -273,17 +286,12 @@ index de2429e..228996e 100644 /* * We can't allocate memory with interrupts disabled on all hosts -diff --git a/vmmon/common/vmx86.c b/vmmon/common/vmx86.c -index dbe794c..156e94a 100644 --- a/vmmon/common/vmx86.c +++ b/vmmon/common/vmx86.c -@@ -720,6 +720,35 @@ cleanup: - } - - -+/* -+ *---------------------------------------------------------------------- -+ * +@@ -723,6 +723,35 @@ cleanup: + /* + *---------------------------------------------------------------------- + * + * Vmx86_LookupUserMPN -- + * + * Look up the MPN of a locked user page by user VA under the VM lock. @@ -310,11 +318,12 @@ index dbe794c..156e94a 100644 +} + + - /* - *---------------------------------------------------------------------- ++/* ++ *---------------------------------------------------------------------- ++ * + * Vmx86_ReleaseVM -- * -diff --git a/vmmon/common/vmx86.h b/vmmon/common/vmx86.h -index 71ea01b..9e227ca 100644 + * Release a VM (either created here or from a bind). --- a/vmmon/common/vmx86.h +++ b/vmmon/common/vmx86.h @@ -106,6 +106,7 @@ extern PseudoTSC pseudoTSC; @@ -325,7 +334,6 @@ index 71ea01b..9e227ca 100644 extern int Vmx86_ReleaseVM(VMDriver *vm); extern int Vmx86_InitVM(VMDriver *vm, InitBlock *initParams); extern int Vmx86_LateInitVM(VMDriver *vm); -diff --git a/vmmon/include/compat_cred.h b/vmmon/include/compat_cred.h --- a/vmmon/include/compat_cred.h +++ b/vmmon/include/compat_cred.h @@ -24,7 +24,11 @@ @@ -340,8 +348,6 @@ diff --git a/vmmon/include/compat_cred.h b/vmmon/include/compat_cred.h #if !defined(current_fsuid) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) #define current_uid() (current->uid) -diff --git a/vmmon/include/compat_pgtable.h b/vmmon/include/compat_pgtable.h -index dedc25a..4722d4e 100644 --- a/vmmon/include/compat_pgtable.h +++ b/vmmon/include/compat_pgtable.h @@ -30,80 +30,32 @@ @@ -399,27 +405,14 @@ index dedc25a..4722d4e 100644 -# define compat_pud_present(pgd) pgd_present(pgd) -typedef pml4_t compat_pgd_t; -typedef pgd_t compat_pud_t; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) -+# define compat_p4d_offset(pgd, address) p4d_offset(pgd, address) -+# define compat_p4d_present(p4d) p4d_present(p4d) -+# define compat_p4d_large(p4d) p4d_large(p4d) -+# define compat_p4d_pfn(p4d) p4d_pfn(p4d) -+# define COMPAT_P4D_MASK P4D_MASK -+typedef p4d_t compat_p4d_t; - #else +-#else -# define compat_pgd_offset(mm, address) pgd_offset(mm, address) -# define compat_pgd_present(pgd) pgd_present(pgd) -# define compat_pud_offset(pgd, address) (pgd) -# define compat_pud_present(pud) (1) -typedef pgd_t compat_pgd_t; -typedef pgd_t compat_pud_t; -+# define compat_p4d_offset(pgd, address) (pgd) -+# define compat_p4d_present(p4d) (1) -+# define compat_p4d_large(p4d) (0) -+# define compat_p4d_pfn(p4d) INVALID_MPN /* Not used */ -+# define COMPAT_P4D_MASK 0 /* Not used */ -+typedef pgd_t compat_p4d_t; - #endif +-#endif - - -#define compat_pgd_offset_k(mm, address) pgd_offset_k(address) @@ -428,11 +421,7 @@ index dedc25a..4722d4e 100644 -/* Introduced somewhere in 2.6.0, + backported to some 2.4 RedHat kernels */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) && !defined(pte_pfn) -# define pte_pfn(pte) page_to_pfn(compat_pte_page(pte)) -+/* p[gu]d_large did not exist before 2.6.25 */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) -+# define pud_large(pud) 0 -+# define pgd_large(pgd) 0 - #endif +-#endif - - -/* A page_table_lock field is added to struct mm_struct in 2.3.10 --hpreg */ @@ -440,6 +429,26 @@ index dedc25a..4722d4e 100644 -# define compat_get_page_table_lock(_mm) (&(_mm)->page_table_lock) -#else -# define compat_get_page_table_lock(_mm) NULL ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++# define compat_p4d_offset(pgd, address) p4d_offset(pgd, address) ++# define compat_p4d_present(p4d) p4d_present(p4d) ++# define compat_p4d_large(p4d) p4d_large(p4d) ++# define compat_p4d_pfn(p4d) p4d_pfn(p4d) ++# define COMPAT_P4D_MASK P4D_MASK ++typedef p4d_t compat_p4d_t; ++#else ++# define compat_p4d_offset(pgd, address) (pgd) ++# define compat_p4d_present(p4d) (1) ++# define compat_p4d_large(p4d) (0) ++# define compat_p4d_pfn(p4d) INVALID_MPN /* Not used */ ++# define COMPAT_P4D_MASK 0 /* Not used */ ++typedef pgd_t compat_p4d_t; ++#endif ++/* p[gu]d_large did not exist before 2.6.25 */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) ++# define pud_large(pud) 0 ++# define pgd_large(pgd) 0 ++#endif +/* pud_pfn did not exist before 3.8. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) +# define pud_pfn(pud) INVALID_MPN @@ -459,49 +468,57 @@ index dedc25a..4722d4e 100644 #endif /* __COMPAT_PGTABLE_H__ */ -diff --git a/vmmon/include/pgtbl.h b/vmmon/include/pgtbl.h -index 39ef4e1..0935e09 100644 --- a/vmmon/include/pgtbl.h +++ b/vmmon/include/pgtbl.h -@@ -26,154 +26,14 @@ +@@ -26,15 +26,14 @@ #include "compat_spinlock.h" #include "compat_page.h" --/* -- *----------------------------------------------------------------------------- -- * ++ + /* + *----------------------------------------------------------------------------- + * - * PgtblPte2MPN -- - * - * Returns the page structure associated to a Page Table Entry. -- * ++ * PgtblVa2MPNLocked -- + * - * This function is not allowed to schedule() because it can be called while - * holding a spinlock --hpreg -- * -- * Results: -- * INVALID_MPN on failure -- * mpn on success -- * -- * Side effects: -- * None -- * -- *----------------------------------------------------------------------------- -- */ -- --static INLINE MPN64 ++ * Walks through the hardware page tables to try to find the pte ++ * associated to a virtual address. Then maps PTE to MPN. + * + * Results: + * INVALID_MPN on failure +@@ -47,230 +46,70 @@ + */ + + static INLINE MPN64 -PgtblPte2MPN(pte_t *pte) // IN --{ -- MPN64 mpn; ++PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process ++ VA addr) // IN: Address in the virtual address ++ // space of that process + { ++ pgd_t *pgd; ++ compat_p4d_t *p4d; + MPN64 mpn; - if (pte_present(*pte) == 0) { -- return INVALID_MPN; -- } ++ ++ pgd = pgd_offset(mm, addr); ++ if (pgd_present(*pgd) == 0) { + return INVALID_MPN; + } - mpn = pte_pfn(*pte); - if (mpn >= INVALID_MPN) { -- return INVALID_MPN; -- } ++ if (pgd_large(*pgd)) { ++ /* Linux kernel does not support PGD huge pages. */ ++ /* return pgd_pfn(*pgd) + ((addr & PGD_MASK) >> PAGE_SHIFT); */ + return INVALID_MPN; + } - return mpn; -} - -- + -/* - *----------------------------------------------------------------------------- - * @@ -572,8 +589,15 @@ index 39ef4e1..0935e09 100644 - if (pmd_present(*pmd) == 0) { - pmd_unmap(pmd); - return NULL; -- } -- ++ p4d = compat_p4d_offset(pgd, addr); ++ if (compat_p4d_present(*p4d) == 0) { ++ return INVALID_MPN; + } ++ if (compat_p4d_large(*p4d)) { ++ mpn = compat_p4d_pfn(*p4d) + ((addr & ~COMPAT_P4D_MASK) >> PAGE_SHIFT); ++ } else { ++ pud_t *pud; + - pte = pte_offset_map(pmd, addr); - pmd_unmap(pmd); - return pte; @@ -605,40 +629,69 @@ index 39ef4e1..0935e09 100644 - return PgtblPGD2PTELocked(compat_pgd_offset(mm, addr), addr); -} - - - /* - *----------------------------------------------------------------------------- - * - * PgtblVa2MPNLocked -- - * +- +-/* +- *----------------------------------------------------------------------------- +- * +- * PgtblVa2MPNLocked -- +- * - * Retrieve MPN for a given va. - * - * Caller must call pte_unmap if valid pte returned. The mm->page_table_lock - * must be held, so this function is not allowed to schedule() --hpreg -+ * Walks through the hardware page tables to try to find the pte -+ * associated to a virtual address. Then maps PTE to MPN. - * - * Results: - * INVALID_MPN on failure -@@ -188,89 +48,64 @@ PgtblVa2PTELocked(struct mm_struct *mm, // IN: Mm structure of a process - static INLINE MPN64 - PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process - VA addr) // IN: Address in the virtual address -+ // space of that process - { +- * +- * Results: +- * INVALID_MPN on failure +- * mpn on success +- * +- * Side effects: +- * None +- * +- *----------------------------------------------------------------------------- +- */ +- +-static INLINE MPN64 +-PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process +- VA addr) // IN: Address in the virtual address +-{ - pte_t *pte; -+ pgd_t *pgd; -+ compat_p4d_t *p4d; -+ MPN64 mpn; - +- - pte = PgtblVa2PTELocked(mm, addr); - if (pte != NULL) { - MPN64 mpn = PgtblPte2MPN(pte); - pte_unmap(pte); - return mpn; -+ pgd = pgd_offset(mm, addr); -+ if (pgd_present(*pgd) == 0) { -+ return INVALID_MPN; ++ pud = pud_offset(p4d, addr); ++ if (pud_present(*pud) == 0) { ++ return INVALID_MPN; ++ } ++ if (pud_large(*pud)) { ++ mpn = pud_pfn(*pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); ++ } else { ++ pmd_t *pmd; ++ ++ pmd = pmd_offset(pud, addr); ++ if (pmd_present(*pmd) == 0) { ++ return INVALID_MPN; ++ } ++ if (pmd_large(*pmd)) { ++ mpn = pmd_pfn(*pmd) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); ++ } else { ++ pte_t *pte; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,5,0) ++ pte = pte_offset_kernel(pmd, addr); ++#else ++ pte = pte_offset_map(pmd, addr); ++#endif ++ if (pte_present(*pte) == 0) { ++ pte_unmap(pte); ++ return INVALID_MPN; ++ } ++ mpn = pte_pfn(*pte); ++ pte_unmap(pte); ++ } ++ } } - return INVALID_MPN; -} @@ -676,16 +729,15 @@ index 39ef4e1..0935e09 100644 - MPN64 mpn = PgtblPte2MPN(pte); - pte_unmap(pte); - return mpn; -+ if (pgd_large(*pgd)) { -+ /* Linux kernel does not support PGD huge pages. */ -+ /* return pgd_pfn(*pgd) + ((addr & PGD_MASK) >> PAGE_SHIFT); */ -+ return INVALID_MPN; ++ if (mpn >= INVALID_MPN) { ++ mpn = INVALID_MPN; } - return INVALID_MPN; --} ++ return mpn; + } -#endif - - +- -/* - *----------------------------------------------------------------------------- - * @@ -714,50 +766,10 @@ index 39ef4e1..0935e09 100644 - struct page *page = PgtblPte2Page(pte); - pte_unmap(pte); - return page; -+ p4d = compat_p4d_offset(pgd, addr); -+ if (compat_p4d_present(*p4d) == 0) { -+ return INVALID_MPN; -+ } -+ if (compat_p4d_large(*p4d)) { -+ mpn = compat_p4d_pfn(*p4d) + ((addr & ~COMPAT_P4D_MASK) >> PAGE_SHIFT); - } else { +- } else { - return NULL; -+ pud_t *pud; -+ -+ pud = pud_offset(p4d, addr); -+ if (pud_present(*pud) == 0) { -+ return INVALID_MPN; -+ } -+ if (pud_large(*pud)) { -+ mpn = pud_pfn(*pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); -+ } else { -+ pmd_t *pmd; -+ -+ pmd = pmd_offset(pud, addr); -+ if (pmd_present(*pmd) == 0) { -+ return INVALID_MPN; -+ } -+ if (pmd_large(*pmd)) { -+ mpn = pmd_pfn(*pmd) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); -+ } else { -+ pte_t *pte; -+ -+ pte = pte_offset_map(pmd, addr); -+ if (pte_present(*pte) == 0) { -+ pte_unmap(pte); -+ return INVALID_MPN; -+ } -+ mpn = pte_pfn(*pte); -+ pte_unmap(pte); -+ } -+ } -+ } -+ if (mpn >= INVALID_MPN) { -+ mpn = INVALID_MPN; - } +- } -} -+ return mpn; -+} /* @@ -773,10 +785,9 @@ index 39ef4e1..0935e09 100644 - if (compat_get_page_table_lock(mm)) { - spin_unlock(compat_get_page_table_lock(mm)); - } -+ spin_unlock(&mm->page_table_lock); - return mpn; - } - +- return mpn; +-} +- - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) -/* @@ -809,8 +820,9 @@ index 39ef4e1..0935e09 100644 - if (compat_get_page_table_lock(mm)) { - spin_unlock(compat_get_page_table_lock(mm)); - } -- return mpn; --} ++ spin_unlock(&mm->page_table_lock); + return mpn; + } -#endif - - @@ -847,24 +859,31 @@ index 39ef4e1..0935e09 100644 - return page; -} - -- + #endif /* __PGTBL_H__ */ -diff --git a/vmmon/linux/driver.c b/vmmon/linux/driver.c -index 87cf45b..5390a93 100644 --- a/vmmon/linux/driver.c +++ b/vmmon/linux/driver.c -@@ -108,7 +108,9 @@ +@@ -101,14 +101,16 @@ static int LinuxDriver_Open(struct inode + */ + int LinuxDriver_Ioctl(struct inode *inode, struct file *filp, + u_int iocmd, unsigned long ioarg); +-#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL) + static long LinuxDriver_UnlockedIoctl(struct file *filp, + u_int iocmd, unsigned long ioarg); +-#endif static int LinuxDriver_Close(struct inode *inode, struct file *filp); static unsigned int LinuxDriverPoll(struct file *file, poll_table *wait); -#if defined(VMW_NOPAGE_2624) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) ++static vm_fault_t LinuxDriverFault(struct vm_fault *fault); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) +static int LinuxDriverFault(struct vm_fault *fault); +#elif defined(VMW_NOPAGE_2624) static int LinuxDriverFault(struct vm_area_struct *vma, struct vm_fault *fault); #else static struct page *LinuxDriverNoPage(struct vm_area_struct *vma, -@@ -117,7 +117,7 @@ +@@ -117,7 +119,7 @@ static struct page *LinuxDriverNoPage(st #endif static int LinuxDriverMmap(struct file *filp, struct vm_area_struct *vma); @@ -873,7 +892,69 @@ index 87cf45b..5390a93 100644 static struct vm_operations_struct vmuser_mops = { #ifdef VMW_NOPAGE_2624 -@@ -244,7 +259,7 @@ LinuxDriverEstimateTSCkHz(void) +@@ -166,61 +168,15 @@ VMX86_RegisterMonitor(int value) // IN: + return 1291; + } + +-#ifndef HAVE_COMPAT_IOCTL +-static int +-LinuxDriver_Ioctl32_Handler(unsigned int fd, +- unsigned int iocmd, +- unsigned long ioarg, +- struct file *filp) +-{ +- int ret = -ENOTTY; +- +- if (filp && filp->f_op && filp->f_op->ioctl == LinuxDriver_Ioctl) { +- ret = LinuxDriver_Ioctl(filp->f_dentry->d_inode, filp, iocmd, ioarg); +- } +- +- return ret; +-} +-#endif /* !HAVE_COMPAT_IOCTL */ +- + static int + register_ioctl32_handlers(void) + { +-#ifndef HAVE_COMPAT_IOCTL +- { +- int i; +- +- for (i = IOCTL_VMX86_FIRST; i < IOCTL_VMX86_LAST; i++) { +- int retval = register_ioctl32_conversion(i, +- LinuxDriver_Ioctl32_Handler); +- +- if (retval) { +- Warning("Fail to register ioctl32 conversion for cmd %d\n", i); +- +- return retval; +- } +- } +- } +-#endif /* !HAVE_COMPAT_IOCTL */ + return 0; + } + + static void + unregister_ioctl32_handlers(void) + { +-#ifndef HAVE_COMPAT_IOCTL +- { +- int i; +- +- for (i = IOCTL_VMX86_FIRST; i < IOCTL_VMX86_LAST; i++) { +- int retval = unregister_ioctl32_conversion(i); +- +- if (retval) { +- Warning("Fail to unregister ioctl32 conversion for cmd %d\n", i); +- } +- } +- } +-#endif /* !HAVE_COMPAT_IOCTL */ + } + + +@@ -244,7 +200,7 @@ unregister_ioctl32_handlers(void) */ static void @@ -882,7 +963,25 @@ index 87cf45b..5390a93 100644 { Vmx86_GetkHzEstimate(&linuxState.startTime); } -@@ -287,9 +302,13 @@ init_module(void) +@@ -253,7 +209,7 @@ + /* + *---------------------------------------------------------------------- + * +- * init_module -- ++ * LinuxDriverInit -- + * + * linux module entry point. Called by /sbin/insmod command + * +@@ -266,7 +222,7 @@ + */ + + int +-init_module(void) ++LinuxDriverInit(void) + { + int retval; + +@@ -287,9 +243,13 @@ */ init_waitqueue_head(&linuxState.pollQueue); @@ -897,7 +996,22 @@ index 87cf45b..5390a93 100644 linuxState.fastClockThread = NULL; linuxState.fastClockFile = NULL; -@@ -365,9 +363,13 @@ init_module(void) +@@ -310,14 +270,8 @@ + memset(&vmuser_fops, 0, sizeof vmuser_fops); + vmuser_fops.owner = THIS_MODULE; + vmuser_fops.poll = LinuxDriverPoll; +-#ifdef HAVE_UNLOCKED_IOCTL + vmuser_fops.unlocked_ioctl = LinuxDriver_UnlockedIoctl; +-#else +- vmuser_fops.ioctl = LinuxDriver_Ioctl; +-#endif +-#ifdef HAVE_COMPAT_IOCTL + vmuser_fops.compat_ioctl = LinuxDriver_UnlockedIoctl; +-#endif + vmuser_fops.open = LinuxDriver_Open; + vmuser_fops.release = LinuxDriver_Close; + vmuser_fops.mmap = LinuxDriverMmap; +@@ -365,9 +319,13 @@ */ Vmx86_ReadTSCAndUptime(&linuxState.startTime); @@ -912,7 +1026,58 @@ index 87cf45b..5390a93 100644 tscTimer.expires = jiffies + 4 * HZ; add_timer(&tscTimer); -@@ -903,7 +907,7 @@ +@@ -381,7 +339,7 @@ + /* + *---------------------------------------------------------------------- + * +- * cleanup_module -- ++ * LinuxDriverExit -- + * + * Called by /sbin/rmmod + * +@@ -390,7 +348,7 @@ + */ + + void +-cleanup_module(void) ++LinuxDriverExit(void) + { + unregister_ioctl32_handlers(); + +@@ -764,7 +722,6 @@ void + LinuxDriverWakeUp(Bool selective) // IN: + { + if (selective && linuxState.pollList != NULL) { +- struct timeval tv; + VmTimeType now; + VMLinux *p; + VMLinux *next; +@@ -777,8 +734,7 @@ LinuxDriverWakeUp(Bool selective) // IN + #else + HostIF_PollListLock(1); + #endif +- do_gettimeofday(&tv); +- now = tv.tv_sec * 1000000ULL + tv.tv_usec; ++ now = ktime_get_ns() / NSEC_PER_USEC; + + for (p = linuxState.pollList; p != NULL; p = next) { + next = p->pollForw; +@@ -850,12 +806,10 @@ LinuxDriverPoll(struct file *filp, // I + } + } else { + if (linuxState.fastClockThread && vmLinux->pollTimeoutPtr != NULL) { +- struct timeval tv; ++ u64 now = ktime_get_ns() / NSEC_PER_USEC; + +- do_gettimeofday(&tv); + poll_wait(filp, &vmLinux->pollQueue, wait); +- vmLinux->pollTime = *vmLinux->pollTimeoutPtr + +- tv.tv_sec * 1000000ULL + tv.tv_usec; ++ vmLinux->pollTime = *vmLinux->pollTimeoutPtr + now; + if (vmLinux->pollBack == NULL) { + #ifdef POLLSPINLOCK + unsigned long flags; +@@ -903,7 +857,7 @@ LinuxDriverPoll(struct file *filp, // I */ static void @@ -921,19 +1086,24 @@ index 87cf45b..5390a93 100644 { LinuxDriverWakeUp(FALSE); } -@@ -928,7 +934,10 @@ +@@ -928,7 +882,15 @@ LinuxDriverPollTimeout(unsigned long cli *----------------------------------------------------------------------------- */ -#if defined(VMW_NOPAGE_2624) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) -+static int ++static ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) ++vm_fault_t ++#else ++int ++#endif +LinuxDriverFault(struct vm_fault *fault) //IN/OUT +#elif defined(VMW_NOPAGE_2624) static int LinuxDriverFault(struct vm_area_struct *vma, //IN struct vm_fault *fault) //IN/OUT #else -@@ -937,6 +946,9 @@ +@@ -937,6 +899,9 @@ static struct page *LinuxDriverNoPage(st int *type) //OUT: Fault type #endif { @@ -943,7 +1113,19 @@ index 87cf45b..5390a93 100644 VMLinux *vmLinux = (VMLinux *) vma->vm_file->private_data; unsigned long pg; struct page* page; -@@ -1398,7 +1410,6 @@ LinuxDriver_Ioctl(struct file *filp, // IN: +@@ -1106,7 +1071,11 @@ LinuxDriverMmap(struct file *filp, + return err; + } + /* Clear VM_IO, otherwise SuSE's kernels refuse to do get_user_pages */ ++#if COMPAT_LINUX_VERSION_CHECK_LT(6, 3, 0) + vma->vm_flags &= ~VM_IO; ++#else ++ vm_flags_clear(vma, VM_IO); ++#endif + + return 0; + } +@@ -1398,7 +1363,6 @@ LinuxDriver_Ioctl(struct inode *inode, case IOCTL_VMX86_CREATE_VM: case IOCTL_VMX86_INIT_CROSSGDT: case IOCTL_VMX86_SET_UID: @@ -951,7 +1133,7 @@ index 87cf45b..5390a93 100644 #if defined(__linux__) && defined(VMX86_DEVEL) case IOCTL_VMX86_LOOK_UP_LARGE_MPN: #endif -@@ -1411,8 +1423,6 @@ LinuxDriver_Ioctl(struct file *filp, // IN: +@@ -1411,8 +1375,6 @@ LinuxDriver_Ioctl(struct inode *inode, case IOCTL_VMX86_GET_KHZ_ESTIMATE: case IOCTL_VMX86_GET_ALL_CPUID: case IOCTL_VMX86_GET_ALL_MSRS: @@ -960,7 +1142,7 @@ index 87cf45b..5390a93 100644 case IOCTL_VMX86_SET_POLL_TIMEOUT_PTR: case IOCTL_VMX86_GET_KERNEL_CLOCK_RATE: case IOCTL_VMX86_GET_REFERENCE_CLOCK_HZ: -@@ -1579,7 +1589,7 @@ LinuxDriver_Ioctl(struct file *filp, // IN: +@@ -1579,7 +1541,7 @@ LinuxDriver_Ioctl(struct inode *inode, if (retval) { break; } @@ -969,7 +1151,7 @@ index 87cf45b..5390a93 100644 retval = HostIF_CopyToUser((void *)ioarg, &args, sizeof args); break; } -@@ -1912,7 +1922,7 @@ LinuxDriver_Ioctl(struct file *filp, // IN: +@@ -1912,7 +1874,7 @@ LinuxDriver_Ioctl(struct inode *inode, if (retval) { break; } @@ -978,7 +1160,7 @@ index 87cf45b..5390a93 100644 break; } -@@ -1923,7 +1933,7 @@ LinuxDriver_Ioctl(struct file *filp, // IN: +@@ -1923,7 +1885,7 @@ LinuxDriver_Ioctl(struct inode *inode, if (retval) { break; } @@ -987,11 +1169,49 @@ index 87cf45b..5390a93 100644 break; } -diff --git a/vmmon/linux/hostif.c b/vmmon/linux/hostif.c -index fd32013..583d6da 100644 +@@ -2052,7 +2014,6 @@ exit: + } + + +-#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL) + /* + *----------------------------------------------------------------------------- + * +@@ -2075,7 +2036,6 @@ LinuxDriver_UnlockedIoctl(struct file *f + { + return LinuxDriver_Ioctl(NULL, filp, iocmd, ioarg); + } +-#endif + + + /* +@@ -2198,3 +2162,5 @@ + * by default (i.e., neither mkinitrd nor modprobe will accept it). + */ + MODULE_INFO(supported, "external"); ++module_init(LinuxDriverInit); ++module_exit(LinuxDriverExit); --- a/vmmon/linux/hostif.c +++ b/vmmon/linux/hostif.c -@@ -77,19 +77,22 @@ +@@ -44,10 +44,6 @@ + + #include <linux/smp.h> + +-#ifndef HAVE_UNLOCKED_IOCTL +-#include <linux/smp_lock.h> +-#endif +- + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) + # include <asm/asm.h> + #endif +@@ -72,24 +68,30 @@ + #endif + + #include <asm/io.h> ++#include <asm/tlbflush.h> ++#include <asm/irq_vectors.h> + #include <asm/uaccess.h> + #include <linux/mc146818rtc.h> #include <linux/capability.h> #include <linux/kthread.h> #include <linux/wait.h> @@ -1000,6 +1220,7 @@ index fd32013..583d6da 100644 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) +#include <linux/taskstats_kern.h> // For linux/sched/signal.h without version check +#endif ++#include <linux/eventfd.h> #include "vmware.h" #include "x86apic.h" @@ -1016,7 +1237,76 @@ index fd32013..583d6da 100644 #include "vmhost.h" #include "x86msr.h" #include "apic.h" -@@ -1010,7 +1013,7 @@ HostIF_FreeLockedPages(VMDriver *vm, // IN: VM instance pointer +@@ -119,6 +121,13 @@ + # define close_rtc(filp, files) filp_close(filp, files) + #endif + ++/* task's state is read-once rather than volatile from 5.14-rc2. */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) || defined(get_current_state) ++#define get_task_state(task) READ_ONCE((task)->__state) ++#else ++#define get_task_state(task) ((task)->state) ++#endif ++ + #define UPTIME_FREQ CONST64(1000000) + + /* +@@ -478,7 +487,7 @@ + while ((vcpuid = VCPUSet_FindFirst(&req)) != VCPUID_INVALID) { + struct task_struct *t = vm->vmhost->vcpuSemaTask[vcpuid]; + VCPUSet_Remove(&req, vcpuid); +- if (t && (t->state & TASK_INTERRUPTIBLE)) { ++ if (t && (get_task_state(t) & TASK_INTERRUPTIBLE)) { + wake_up_process(t); + } + } +@@ -630,6 +632,15 @@ HostIF_FastClockUnlock(int callerID) // + MutexUnlock(&fastClockMutex, callerID); + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) ++static int crosspage_set_exec(pte_t *pte, unsigned long addr, void *data) ++{ ++ struct page *p = data; ++ ++ set_pte(pte, mk_pte(p, VM_PAGE_KERNEL_EXEC)); ++ return 0; ++} ++#endif + + /* + *----------------------------------------------------------------------------- +@@ -696,7 +707,29 @@ HostIF_PollListUnlock(int callerID) // I + static void * + MapCrossPage(struct page *p) // IN: + { ++#if COMPAT_LINUX_VERSION_CHECK_LT(5, 8, 0) + return vmap(&p, 1, VM_MAP, VM_PAGE_KERNEL_EXEC); ++#else ++ void *addr; ++ ++ addr = vmap(&p, 1, VM_MAP, VM_PAGE_KERNEL_EXEC); ++ if (!addr) ++ return NULL; ++ ++ /* Starting with 5.8, vmap() always sets the NX bit, but the cross ++ * page needs to be executable. */ ++ if (apply_to_page_range(current->mm, (unsigned long)addr, PAGE_SIZE, ++ crosspage_set_exec, p)) { ++ vunmap(addr); ++ return NULL; ++ } ++ ++ preempt_disable(); ++ __flush_tlb_all(); ++ preempt_enable(); ++ ++ return addr; ++#endif + } + + +@@ -1010,7 +1043,7 @@ HostIF_FreeLockedPages(VMDriver *vm, int HostIF_Init(VMDriver *vm) // IN: { @@ -1025,7 +1315,7 @@ index fd32013..583d6da 100644 if (vm->memtracker == NULL) { return -1; } -@@ -1165,10 +1173,7 @@ +@@ -1165,10 +1198,7 @@ HostIFGetUserPages(void *uvAddr, { int retval; @@ -1037,7 +1327,21 @@ index fd32013..583d6da 100644 return retval != numPages; } -@@ -1626,12 +1631,34 @@ HostIF_EstimateLockedPageLimit(const VMDriver* vm, // IN +@@ -1606,9 +1636,13 @@ HostIF_EstimateLockedPageLimit(const VMD + * since at least 2.6.0. + */ + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) + extern unsigned long totalram_pages; + + unsigned int totalPhysicalPages = totalram_pages; ++#else ++ unsigned int totalPhysicalPages = totalram_pages(); ++#endif + + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) + return MemDefaults_CalcMaxLockedPages(totalPhysicalPages); +@@ -1626,13 +1660,37 @@ HostIF_EstimateLockedPageLimit(const VMD unsigned int reservedPages = MEMDEFAULTS_MIN_HOST_PAGES; unsigned int hugePages = (vm == NULL) ? 0 : BYTES_2_PAGES(vm->memInfo.hugePageBytes); @@ -1049,7 +1353,7 @@ index fd32013..583d6da 100644 + unsigned int lockedPages = hugePages + reservedPages; + unsigned int anonPages; unsigned int swapPages = BYTES_2_PAGES(linuxState.swapSize); -+ + + /* global_page_state is global_zone_page_state in 4.14. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) + lockedPages += global_zone_page_state(NR_PAGETABLE); @@ -1057,7 +1361,9 @@ index fd32013..583d6da 100644 + lockedPages += global_page_state(NR_PAGETABLE); +#endif + /* NR_SLAB_* moved from zone to node in 4.13. */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) ++ lockedPages += global_node_page_state_pages(NR_SLAB_UNRECLAIMABLE_B); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) + lockedPages += global_node_page_state(NR_SLAB_UNRECLAIMABLE); +#else + lockedPages += global_page_state(NR_SLAB_UNRECLAIMABLE); @@ -1074,10 +1380,68 @@ index fd32013..583d6da 100644 +#else + anonPages = global_page_state(NR_ANON_PAGES); +#endif - ++ if (anonPages > swapPages) { lockedPages += anonPages - swapPages; -@@ -1726,9 +1753,6 @@ + } +@@ -1691,6 +1749,49 @@ HostIF_WaitForFreePages(unsigned int tim + /* + *---------------------------------------------------------------------- + * ++ * HostIFGetTime -- ++ * ++ * Reads the current time in UPTIME_FREQ units. ++ * ++ * Results: ++ * The uptime, in units of UPTIME_FREQ. ++ * ++ * Side effects: ++ * None. ++ * ++ *---------------------------------------------------------------------- ++ */ ++ ++static uint64 ++HostIFGetTime(void) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) ++ struct timeval tv; ++ ++ do_gettimeofday(&tv); ++ return tv.tv_usec * (UPTIME_FREQ / 1000000) + tv.tv_sec * UPTIME_FREQ; ++#else ++ struct timespec64 now; ++ ++ /* ++ * Use raw time used by Posix timers. This time is not affected by ++ * NTP adjustments, so it may drift from real time and monotonic time, ++ * but it will stay in sync with other timers. ++ */ ++ ktime_get_raw_ts64(&now); ++ /* ++ * UPTIME_FREQ resolution is lower than tv_nsec, ++ * so we have to do division... ++ */ ++ ASSERT_ON_COMPILE(1000000000 % UPTIME_FREQ == 0); ++ return now.tv_nsec / (1000000000 / UPTIME_FREQ) + now.tv_sec * UPTIME_FREQ; ++#endif ++} ++ ++ ++/* ++ *---------------------------------------------------------------------- ++ * + * HostIFReadUptimeWork -- + * + * Reads the current uptime. The uptime is based on getimeofday, +@@ -1719,16 +1820,12 @@ HostIF_WaitForFreePages(unsigned int tim + static uint64 + HostIFReadUptimeWork(unsigned long *j) // OUT: current jiffies + { +- struct timeval tv; + uint64 monotime, uptime, upBase, monoBase; + int64 diff; + uint32 version; unsigned long jifs, jifBase; unsigned int attempts = 0; @@ -1087,7 +1451,22 @@ index fd32013..583d6da 100644 retry: do { version = VersionedAtomic_BeginTryRead(&uptimeState.version); -@@ -1794,7 +1818,7 @@ HostIFReadUptimeWork(unsigned long *j) // OUT: current jiffies +@@ -1737,13 +1834,12 @@ HostIFReadUptimeWork(unsigned long *j) + monoBase = uptimeState.monotimeBase; + } while (!VersionedAtomic_EndTryRead(&uptimeState.version, version)); + +- do_gettimeofday(&tv); ++ uptime = HostIFGetTime(); + upBase = Atomic_Read64(&uptimeState.uptimeBase); + + monotime = (uint64)(jifs - jifBase) * (UPTIME_FREQ / HZ); + monotime += monoBase; + +- uptime = tv.tv_usec * (UPTIME_FREQ / 1000000) + tv.tv_sec * UPTIME_FREQ; + uptime += upBase; + + /* +@@ -1794,7 +1890,7 @@ HostIFReadUptimeWork(unsigned long *j) */ static void @@ -1096,9 +1475,20 @@ index fd32013..583d6da 100644 { unsigned long jifs; uintptr_t flags; -@@ -1856,8 +1880,13 @@ HostIF_InitUptime(void) - -(tv.tv_usec * (UPTIME_FREQ / 1000000) + - tv.tv_sec * UPTIME_FREQ)); +@@ -1848,16 +1944,19 @@ HostIFUptimeResyncMono(unsigned long dat + void + HostIF_InitUptime(void) + { +- struct timeval tv; ++ uint64 tm; + + uptimeState.jiffiesBase = jiffies; +- do_gettimeofday(&tv); +- Atomic_Write64(&uptimeState.uptimeBase, +- -(tv.tv_usec * (UPTIME_FREQ / 1000000) + +- tv.tv_sec * UPTIME_FREQ)); ++ tm = HostIFGetTime(); ++ Atomic_Write64(&uptimeState.uptimeBase, -tm); +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) && !defined(timer_setup) init_timer(&uptimeState.timer); @@ -1111,7 +1501,7 @@ index fd32013..583d6da 100644 mod_timer(&uptimeState.timer, jiffies + HZ); } -@@ -2028,15 +2052,15 @@ HostIF_MapCrossPage(VMDriver *vm, // IN +@@ -2028,15 +2127,15 @@ HostIF_MapCrossPage(VMDriver *vm, // IN return NULL; } vPgAddr = (VA) MapCrossPage(page); @@ -1130,11 +1520,166 @@ index fd32013..583d6da 100644 ret = vPgAddr | (((VA)p) & (PAGE_SIZE - 1)); -@@ -2850,13 +2874,75 @@ HostIF_CallOnEachCPU(void (*func)(void*), // IN: function to call +@@ -2273,16 +2372,26 @@ HostIF_VMLockIsHeld(VMDriver *vm) // IN + static Bool + isVAReadable(VA r) // IN: + { +- mm_segment_t old_fs; + uint32 dummy; + int ret; + ++#if defined(HAVE_GET_KERNEL_NOFAULT) || LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0) ++ /* ++ * Exists from 5.10, first indicated by HAVE_GET_KERNEL_NOFAULT, ++ * and from post-5.17 just existing everywhere. ++ */ ++ ret = get_kernel_nofault(dummy, (void *)r); ++#else ++ { ++ mm_segment_t old_fs; ++ + old_fs = get_fs(); +- set_fs(get_ds()); ++ set_fs(KERNEL_DS); + r = APICR_TO_ADDR(r, APICR_VERSION); + ret = HostIF_CopyFromUser(&dummy, (void*)r, sizeof(dummy)); + set_fs(old_fs); +- ++ } ++#endif + return ret == 0; } +@@ -2311,7 +2416,7 @@ SetVMAPICAddr(VMDriver *vm, // IN/OUT: d + volatile void *hostapic; + + ASSERT_ON_COMPILE(APICR_SIZE <= PAGE_SIZE); +- hostapic = (volatile void *) ioremap_nocache(ma, PAGE_SIZE); ++ hostapic = (volatile void *) ioremap(ma, PAGE_SIZE); + if (hostapic) { + if ((APIC_VERSIONREG(hostapic) & 0xF0) == 0x10) { + vm->hostAPIC.base = (volatile uint32 (*)[4]) hostapic; +@@ -2467,7 +2572,6 @@ HostIF_SemaphoreWait(VMDriver *vm, // + uint64 *args) // IN: + { + struct file *file; +- mm_segment_t old_fs; + int res; + int waitFD = args[0]; + int timeoutms = args[2]; +@@ -2478,22 +2582,19 @@ HostIF_SemaphoreWait(VMDriver *vm, // + return MX_WAITERROR; + } + +- old_fs = get_fs(); +- set_fs(get_ds()); +- + { + struct poll_wqueues table; + unsigned int mask; + + poll_initwait(&table); +- current->state = TASK_INTERRUPTIBLE; ++ __set_current_state(TASK_INTERRUPTIBLE); + mask = file->f_op->poll(file, &table.pt); + if (!(mask & (POLLIN | POLLERR | POLLHUP))) { + vm->vmhost->vcpuSemaTask[vcpuid] = current; + schedule_timeout(timeoutms * HZ / 1000); // convert to Hz + vm->vmhost->vcpuSemaTask[vcpuid] = NULL; + } +- current->state = TASK_RUNNING; ++ __set_current_state(TASK_RUNNING); + poll_freewait(&table); + } -+/* +@@ -2502,9 +2603,11 @@ HostIF_SemaphoreWait(VMDriver *vm, // + * the code to happily deal with a pipe or an eventfd. We only care about + * reading no bytes (EAGAIN - non blocking fd) or sizeof(uint64). + */ +- +- res = file->f_op->read(file, (char *) &value, sizeof value, &file->f_pos); +- ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ res = kernel_read(file, file->f_pos, (char *)&value, sizeof value); ++#else ++ res = kernel_read(file, &value, sizeof value, &file->f_pos); ++#endif + if (res == sizeof value) { + res = MX_WAITNORMAL; + } else { +@@ -2513,7 +2616,6 @@ HostIF_SemaphoreWait(VMDriver *vm, // + } + } + +- set_fs(old_fs); + fput(file); + + /* +@@ -2566,7 +2675,7 @@ + FOR_EACH_VCPU_IN_SET(vcs, vcpuid) { + struct task_struct *t = vm->vmhost->vcpuSemaTask[vcpuid]; + vm->vmhost->vcpuSemaTask[vcpuid] = NULL; +- if (t && (t->state & TASK_INTERRUPTIBLE)) { ++ if (t && (get_task_state(t) & TASK_INTERRUPTIBLE)) { + wake_up_process(t); + } + } ROF_EACH_VCPU_IN_SET(); +@@ -2596,8 +2698,8 @@ HostIF_SemaphoreForceWakeup(VMDriver *vm + int + HostIF_SemaphoreSignal(uint64 *args) // IN: + { ++ struct eventfd_ctx *eventfd; + struct file *file; +- mm_segment_t old_fs; + int res; + int signalFD = args[1]; + uint64 value = 1; // make an eventfd happy should it be there +@@ -2607,22 +2709,36 @@ HostIF_SemaphoreSignal(uint64 *args) // + return MX_WAITERROR; + } + +- old_fs = get_fs(); +- set_fs(get_ds()); ++ /* ++ * If it's eventfd, use specific eventfd interface as kernel writes ++ * to eventfd may not be allowed in kernel 5.10 and later. ++ */ ++ eventfd = eventfd_ctx_fileget(file); ++ if (!IS_ERR(eventfd)) { ++#if COMPAT_LINUX_VERSION_CHECK_LT(6, 8, 0) ++ eventfd_signal(eventfd, 1); ++#else ++ eventfd_signal(eventfd); ++#endif ++ fput(file); ++ return MX_WAITNORMAL; ++ } + + /* + * Always write sizeof(uint64) bytes. This works fine for eventfd and + * pipes. The data written is formatted to make an eventfd happy should + * it be present. + */ +- +- res = file->f_op->write(file, (char *) &value, sizeof value, &file->f_pos); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ res = kernel_write(file, (char *)&value, sizeof value, file->f_pos); ++#else ++ res = kernel_write(file, &value, sizeof value, &file->f_pos); ++#endif + + if (res == sizeof value) { + res = MX_WAITNORMAL; + } + +- set_fs(old_fs); + fput(file); + + /* +@@ -2851,12 +2963,74 @@ HostIF_CallOnEachCPU(void (*func)(void*) + + + /* + *----------------------------------------------------------------------------- + * + * HostIFCheckTrackedMPN -- @@ -1195,7 +1740,7 @@ index fd32013..583d6da 100644 +} + + - /* ++/* *---------------------------------------------------------------------- * * HostIF_ReadPage -- @@ -1208,7 +1753,7 @@ index fd32013..583d6da 100644 * * Results: * 0 on success -@@ -2869,7 +2955,8 @@ HostIF_CallOnEachCPU(void (*func)(void*), // IN: function to call +@@ -2869,7 +3043,8 @@ HostIF_CallOnEachCPU(void (*func)(void*) */ int @@ -1218,7 +1763,7 @@ index fd32013..583d6da 100644 VA64 addr, // buffer for data Bool kernelBuffer) // is the buffer in kernel space? { -@@ -2881,6 +2968,9 @@ HostIF_ReadPage(MPN64 mpn, // MPN of the page +@@ -2881,6 +3056,9 @@ HostIF_ReadPage(MPN64 mpn, // if (mpn == INVALID_MPN) { return -EFAULT; } @@ -1228,7 +1773,7 @@ index fd32013..583d6da 100644 page = pfn_to_page(mpn); ptr = kmap(page); -@@ -2904,8 +2994,8 @@ HostIF_ReadPage(MPN64 mpn, // MPN of the page +@@ -2904,8 +3082,8 @@ HostIF_ReadPage(MPN64 mpn, // * * HostIF_WritePage -- * @@ -1239,7 +1784,7 @@ index fd32013..583d6da 100644 * * Results: * 0 on success -@@ -2918,9 +3008,9 @@ HostIF_ReadPage(MPN64 mpn, // MPN of the page +@@ -2918,9 +3096,9 @@ HostIF_ReadPage(MPN64 mpn, // */ int @@ -1252,7 +1797,7 @@ index fd32013..583d6da 100644 { void const *buf = VA64ToPtr(addr); int ret = 0; -@@ -2947,6 +3037,45 @@ HostIF_WritePage(MPN64 mpn, // MPN of the page +@@ -2947,6 +3125,45 @@ HostIF_WritePage(MPN64 mpn, / return ret; } @@ -1298,8 +1843,72 @@ index fd32013..583d6da 100644 /* *---------------------------------------------------------------------- -diff --git a/vmmon/vmcore/moduleloop.c b/vmmon/vmcore/moduleloop.c -index 94aab9e..a6b2c1a 100644 +@@ -3160,21 +3377,9 @@ HostIFDoIoctl(struct file *filp, + u_int iocmd, + unsigned long ioarg) + { +-#ifdef HAVE_UNLOCKED_IOCTL + if (filp->f_op->unlocked_ioctl) { + return filp->f_op->unlocked_ioctl(filp, iocmd, ioarg); + } +-#else +- if (filp->f_op->ioctl) { +- long err; +- +- lock_kernel(); +- err = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, iocmd, ioarg); +- unlock_kernel(); +- +- return err; +- } +-#endif + return -ENOIOCTLCMD; + } + #endif //VMON_USE_HIGH_RES_TIMERS +@@ -3304,12 +3509,9 @@ HostIFFastClockThread(void *data) // IN + { + struct file *filp = (struct file *) data; + int res; +- mm_segment_t oldFS; + unsigned int rate = 0; + unsigned int prevRate = 0; + +- oldFS = get_fs(); +- set_fs(KERNEL_DS); + allow_signal(SIGKILL); + set_user_nice(current, linuxState.fastClockPriority); + +@@ -3343,8 +3545,6 @@ HostIFFastClockThread(void *data) // IN + + out: + LinuxDriverWakeUp(TRUE); +- set_fs(oldFS); +- + /* + * Do not exit thread until we are told to do so. + */ +@@ -3464,7 +3664,6 @@ HostIF_SetFastClockRate(unsigned int rat + } + } else { + if (linuxState.fastClockThread) { +- force_sig(SIGKILL, linuxState.fastClockThread); + kthread_stop(linuxState.fastClockThread); + close_rtc(linuxState.fastClockFile, current->files); + +@@ -3512,7 +3711,12 @@ HostIF_MapUserMem(VA addr, + + ASSERT(handle); + +- if (!access_ok(VERIFY_WRITE, p, size)) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) ++ if (!access_ok(VERIFY_WRITE, p, size)) ++#else ++ if (!access_ok(p, size)) ++#endif ++ { + printk(KERN_ERR "%s: Couldn't verify write to uva 0x%p with size %" + FMTSZ"u\n", __func__, p, size); + --- a/vmmon/vmcore/moduleloop.c +++ b/vmmon/vmcore/moduleloop.c @@ -205,11 +205,13 @@ skipTaskSwitch:; @@ -1316,294 +1925,185 @@ index 94aab9e..a6b2c1a 100644 break; } -From 8ba37a5023f939ba8d2e0d91b916ff442b1c18dd Mon Sep 17 00:00:00 2001 +From 4c2a103fd2d71f2084f1fe7ceacb816b9832ffa2 Mon Sep 17 00:00:00 2001 From: Michal Kubecek <mkubecek@suse.cz> -Date: Mon, 31 Dec 2018 00:05:42 +0100 -Subject: [PATCH] modules: replace SUBDIRS with M +Date: Sun, 22 Oct 2023 23:24:05 +0200 +Subject: [PATCH] vmmon: use get_user_pages to get page PFN -Since commit 0126be38d988 ("kbuild: announce removal of SUBDIRS if used") -in v5.0-rc1, using SUBDIRS when building out of tree modules produces -a deprecation warning. As M used to work since pretty much ever, use it -unconditionally. ---- - vmmon-only/Makefile | 2 +- - vmnet-only/Makefile | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) +As a side effect of mainline commit 0d940a9b270b ("mm/pgtable: allow +pte_offset_map[_lock]() to fail") in 6.5-rc1, __pte_offset_map(), called by +pte_offset_map(), is no longer exported. WMware developers decided to hack +around this by replacing pte_offset_map() by pte_offset_kernel() which does +not seem to be a good idea and apparently may trigger warn checks in RCU +code on some systems as mentioned in the discussion on issue #223. +Therefore let's use the same solution as we had for 17.0.2 and older +versions as it does not show these problems. -diff --git a/vmmon-only/Makefile b/vmmon-only/Makefile -index ccdd295..b4b71fb 100644 ---- a/vmmon-only/Makefile -+++ b/vmmon-only/Makefile -@@ -121,7 +121,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 -From ca44ce7215b91f82ff500843784b4e86a720fffe Mon Sep 17 00:00:00 2001 -From: Michal Kubecek <mkubecek@suse.cz> -Date: Mon, 31 Dec 2018 00:11:35 +0100 -Subject: [PATCH] vmmon: totalram_pages is a function since 5.0 +Based on an upstream IRC discussion and the hva_to_pfn_*() family of +functions in KVM code, what PgtblVa2MPNLocked() does seems to be an +incomplete and partial open coded logic of get_user_pages() and as it is +only used to get PFN from a virtual address, it can be easily implemented +using get_user_pages() family. -Since commit ca79b0c211af ("mm: convert totalram_pages and totalhigh_pages -variables to atomic") in v5.0-rc1, totalram_pages() is an accessor function -and the actual variable is an atomic. +Without knowledge what exactly are the PFNs used for in VMware, it is hard +to guess the right flags, these seem to work and have been tested by +multiple users over last few weeks. + +We could likely use get_user_pages() also on older kernels and it might be +actually cleaner and more reliable as existing open coded implementation +does not seem to handle some corner cases but without knowledge of VMware +internals, it will be safer to stick to existing code where possible. --- - vmmon-only/linux/hostif.c | 18 ++++++++++-------- - 1 file changed, 10 insertions(+), 8 deletions(-) + vmmon-only/include/pgtbl.h | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) -diff --git a/vmmon-only/linux/hostif.c b/vmmon-only/linux/hostif.c -index af4b1d9..d32653c 100644 ---- a/vmmon-only/linux/hostif.c -+++ b/vmmon-only/linux/hostif.c -@@ -211,6 +211,15 @@ static void UnlockEntry(void *clientData, MemTrackEntry *entryPtr); - uint8 monitorIPIVector; - uint8 hvIPIVector; +diff --git a/vmmon-only/include/pgtbl.h b/vmmon-only/include/pgtbl.h +index 3f43c62..7eaa49a 100644 +--- a/vmmon-only/include/pgtbl.h ++++ b/vmmon-only/include/pgtbl.h +@@ -25,6 +25,7 @@ + #include "compat_pgtable.h" + #include "compat_spinlock.h" + #include "compat_page.h" ++#include "compat_version.h" -+static unsigned long compat_totalram_pages(void) -+{ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) -+ return totalram_pages; -+#else -+ return totalram_pages(); + + /* +@@ -45,6 +46,7 @@ + *----------------------------------------------------------------------------- + */ + ++#if COMPAT_LINUX_VERSION_CHECK_LT(6, 5, 0) // only used by PgtblVa2MPN() below + static INLINE MPN64 + PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process + VA addr) // IN: Address in the virtual address +@@ -110,6 +112,7 @@ PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process + } + return mpn; + } +#endif -+} -+ + + /* +@@ -129,6 +132,8 @@ PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process *----------------------------------------------------------------------------- - * -@@ -1601,14 +1610,7 @@ unsigned int - HostIF_EstimateLockedPageLimit(const VMDriver* vm, // IN - unsigned int currentlyLockedPages) // IN + */ + ++#if COMPAT_LINUX_VERSION_CHECK_LT(6, 5, 0) ++ + static INLINE MPN64 + PgtblVa2MPN(VA addr) // IN { -- /* -- * This variable is available and exported to modules, -- * since at least 2.6.0. -- */ -- -- extern unsigned long totalram_pages; -- -- unsigned int totalPhysicalPages = totalram_pages; -+ unsigned int totalPhysicalPages = compat_totalram_pages(); +@@ -143,4 +148,24 @@ PgtblVa2MPN(VA addr) // IN + return mpn; + } - #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) - return MemDefaults_CalcMaxLockedPages(totalPhysicalPages); -From c3fb5cda191137afddfdbd2f31bb4b15f9aeb3f2 Mon Sep 17 00:00:00 2001 -From: Michal Kubecek <mkubecek@suse.cz> -Date: Mon, 31 Dec 2018 00:15:11 +0100 -Subject: [PATCH] vmmon: bring back the do_gettimeofday() helper - -The do_gettimeofday() helper was removed by commit e4b92b108c6c -("timekeeping: remove obsolete time accessors") in v5.0-rc1. Bring it back -for users in vmmon-only/linux/hostif.c. - -This feels like a quick and clumsy band aid to allow build with post-4.20 -kernels. On a closer look, the whole gymnastics around uptimeState and -HostIFReadUptimeWork() with jiffies and wall time checking and correcting -each other seems to be a workaround for an absence of high resolution -monotonic time. Considering ktime_get_ts64() is available since 3.17 and -before that, ktime_get_ts() since 2.6.17, perhaps the time has come to -clean all this machinery up. But something like this would be beyond the -scope of this repository. ---- - vmmon-only/include/compat_timekeeping32.h | 15 +++++++++++++++ - vmmon-only/linux/driver.c | 1 + - vmmon-only/linux/hostif.c | 1 + - vmnet-only/bridge.c | 11 +++++++++++ - 4 files changed, 28 insertions(+) - create mode 100644 vmmon-only/include/compat_timekeeping32.h - -diff --git a/vmmon-only/include/compat_timekeeping32.h b/vmmon-only/include/compat_timekeeping32.h -new file mode 100644 -index 0000000..5730dcd ---- /dev/null -+++ b/vmmon-only/include/compat_timekeeping32.h -@@ -0,0 +1,15 @@ -+#ifndef __COMPAT_TIMEKEEPING32_H__ -+#define __COMPAT_TIMEKEEPING32_H__ ++#else /* COMPAT_LINUX_VERSION_CHECK_LT(6, 5, 0) */ + -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) -+static inline void do_gettimeofday(struct timeval *tv) ++static INLINE MPN64 ++PgtblVa2MPN(VA addr) // IN +{ -+ struct timespec64 now; ++ struct page *page; ++ int npages; ++ MPN mpn; + -+ ktime_get_real_ts64(&now); -+ tv->tv_sec = now.tv_sec; -+ tv->tv_usec = now.tv_nsec / 1000; ++ npages = get_user_pages_unlocked(addr, 1, &page, FOLL_HWPOISON); ++ if (npages != 1) ++ return INVALID_MPN; ++ mpn = page_to_pfn(page); ++ put_page(page); ++ ++ return mpn; +} -+#endif + -+#endif /* __COMPAT_TIMEKEEPING32_H__ */ -diff --git a/vmmon-only/linux/driver.c b/vmmon-only/linux/driver.c -index ca4b538..cdc7fc1 100644 ---- a/vmmon-only/linux/driver.c -+++ b/vmmon-only/linux/driver.c -@@ -34,6 +34,7 @@ - #include "compat_version.h" - #include "compat_module.h" - #include "compat_page.h" -+#include "compat_timekeeping32.h" - - #include "usercalldefs.h" - -diff --git a/vmmon-only/linux/hostif.c b/vmmon-only/linux/hostif.c -index c985aa0..75f4c8a 100644 ---- a/vmmon-only/linux/hostif.c -+++ b/vmmon-only/linux/hostif.c -@@ -102,6 +102,7 @@ - #include "pgtbl.h" - #include "vmmonInt.h" - #include "versioned_atomic.h" -+#include "compat_timekeeping32.h" - - /* - * Determine if we can use high resolution timers. -From 5db3c8a86f435e21f37a2acf386e2e52a1b42aa6 Mon Sep 17 00:00:00 2001 -From: Michal Kubecek <mkubecek@suse.cz> -Date: Sat, 5 Jan 2019 01:54:57 +0100 -Subject: [PATCH] modules: handle access_ok() with two arguments - -Since commit 96d4f267e40f ("Remove 'type' argument from access_ok() -function") in v5.0-rc1, the type argument of access_ok() was dropped. -The same commit also dropped macros VERIFY_READ and VERIFY_WRITE so check -for their existence on pre-5.0 kernels to allow build against kernels with -this change backported. ---- - vmmon-only/linux/hostif.c | 8 +++++++- - vmnet-only/userif.c | 8 +++++++- - 2 files changed, 14 insertions(+), 2 deletions(-) - -diff --git a/vmmon-only/linux/hostif.c b/vmmon-only/linux/hostif.c -index 75f4c8a..987932b 100644 ---- a/vmmon-only/linux/hostif.c -+++ b/vmmon-only/linux/hostif.c -@@ -221,6 +221,12 @@ static unsigned long compat_totalram_pages(void) - #endif - } - -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) && defined(VERIFY_WRITE) -+ #define write_access_ok(addr, size) access_ok(VERIFY_WRITE, addr, size) -+#else -+ #define write_access_ok(addr, size) access_ok(addr, size) -+#endif ++#endif /* COMPAT_LINUX_VERSION_CHECK_LT(6, 5, 0) */ + - /* - *----------------------------------------------------------------------------- - * -@@ -3644,7 +3650,7 @@ HostIF_MapUserMem(VA addr, // IN: User memory virtual address - - ASSERT(handle); - -- if (!access_ok(VERIFY_WRITE, p, size)) { -+ if (!write_access_ok(p, size)) { - printk(KERN_ERR "%s: Couldn't verify write to uva 0x%p with size %" - FMTSZ"u\n", __func__, p, size); - -From 41413a9b6e660a93600a438944d85b6f51eb680c Mon Sep 17 00:00:00 2001 + #endif /* __PGTBL_H__ */ +From 218fec600d0af1c5e9f4af819b216fb9c69bb838 Mon Sep 17 00:00:00 2001 From: Michal Kubecek <mkubecek@suse.cz> -Date: Tue, 5 Mar 2019 13:21:35 +0100 -Subject: [PATCH] vmmon: use KERNEL_DS rather than get_ds() +Date: Fri, 12 Jan 2024 08:30:33 +0100 +Subject: [PATCH] modules: fix build with -Wmissing-prototypes -Commit 736706bee329 ("get rid of legacy 'get_ds()' function") in v5.1-rc1 -removed get_ds() helper. As this helper always returned KERNEL_DS on x86_64 -since the architecture was introduced (and even on i386, it did so since -v2.1.0), simply use KERNEL_DS regardless of kernel version. ---- - vmmon-only/linux/hostif.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) +Mainline commit 0fcb70851fbf ("Makefile.extrawarn: turn on +missing-prototypes globally") in 6.8-rc1 enables -Wmissing-prototypes +globally, revealing a lot of unclean code and also some actual problems. +This is also the case in vmmon and vmnet modules. -diff --git a/vmmon-only/linux/hostif.c b/vmmon-only/linux/hostif.c -index ef88a22..8ca17de 100644 ---- a/vmmon-only/linux/hostif.c -+++ b/vmmon-only/linux/hostif.c -@@ -2311,7 +2311,7 @@ isVAReadable(VA r) // IN: - int ret; - - old_fs = get_fs(); -- set_fs(get_ds()); -+ set_fs(KERNEL_DS); - r = APICR_TO_ADDR(r, APICR_VERSION); - ret = HostIF_CopyFromUser(&dummy, (void*)r, sizeof(dummy)); - set_fs(old_fs); -@@ -2512,7 +2512,7 @@ HostIF_SemaphoreWait(VMDriver *vm, // IN: - } - - old_fs = get_fs(); -- set_fs(get_ds()); -+ set_fs(KERNEL_DS); - - { - struct poll_wqueues table; -@@ -2641,7 +2641,7 @@ HostIF_SemaphoreSignal(uint64 *args) // IN: - } - - old_fs = get_fs(); -- set_fs(get_ds()); -+ set_fs(KERNEL_DS); - - /* - * Always write sizeof(uint64) bytes. This works fine for eventfd and -From 48812705d760a0dc760420ce495e34ce4d019b92 Mon Sep 17 00:00:00 2001 -From: Michal Kubecek <mkubecek@suse.cz> -Date: Sat, 9 Mar 2019 11:11:29 +0100 -Subject: [PATCH] vmmon: fix return type of vm_operations_struct::fault handler +Most of them are addressed by making functions used only within one file +static. The missing prototype of random_get_entropy_fallback() is handled +by including <linux/timex.h> rather than <asm/timex.h>. -Commit 3d3539018d2c ("mm: create the new vm_fault_t type") in mainline -5.1-rc1 changed the definition of vm_fault_t type to unsigned to catch -vm_operations_struct::fault handlers which still have int as return value. -LinuxDriverFault() in vmmon module is one of those. - -As handler return type was changed by commit 1c8f422059ae ("mm: change -return type to vm_fault_t") in 4.17-rc1, make LinuxDriverFault() always -return vm_fault_t and define vm_fault_t as int when building against -a pre-4.17 kernel. (Except for the branch for really old kernels where -the handler was vm_operations_struct::nopage and returned a pointer to -struct page.) +Finally, there are four functions in vmnet module which are actually used +in multiple files but instead of proper declarations, their prototype is +duplicated in vmnet-only/driver.c, risking that the two copies won't match +(which actually happened in one case). The cleanest solution would be +creating separate header files for them (bridge.h, netif.h, userif.h and +vnetUserListener.h) and including them in the respective source file and +driver.c. As the developers already handle similar cases by simply putting +the declarations into vnetInt.h, let us do the same to keep things simple. --- - vmmon-only/linux/driver.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) + vmmon-only/common/vmx86.c | 2 +- + vmmon-only/linux/driver.c | 4 ++-- + vmmon-only/linux/hostif.c | 6 +++--- + vmnet-only/bridge.c | 2 +- + vmnet-only/driver.c | 16 ++-------------- + vmnet-only/vnetInt.h | 7 +++++++ + 6 files changed, 16 insertions(+), 21 deletions(-) +diff --git a/vmmon-only/common/vmx86.c b/vmmon-only/common/vmx86.c +index 156e94a9..c5ed3e25 100644 +--- a/vmmon-only/common/vmx86.c ++++ b/vmmon-only/common/vmx86.c +@@ -58,7 +58,7 @@ + #include "x86svm.h" + #include "x86cpuid_asm.h" + #if defined(linux) +-#include <asm/timex.h> ++#include <linux/timex.h> + #endif + #include "x86perfctr.h" + diff --git a/vmmon-only/linux/driver.c b/vmmon-only/linux/driver.c -index cdc7fc1..fd9fdac 100644 +index 9c855869..32e9c5ea 100644 --- a/vmmon-only/linux/driver.c +++ b/vmmon-only/linux/driver.c -@@ -81,6 +81,9 @@ static Bool LinuxDriverCheckPadding(void); +@@ -221,7 +221,7 @@ LinuxDriverInitTSCkHz(void) + *---------------------------------------------------------------------- + */ - struct VMXLinuxState linuxState; +-int ++static int + LinuxDriverInit(void) + { + int retval; +@@ -347,7 +347,7 @@ LinuxDriverInit(void) + *---------------------------------------------------------------------- + */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0) -+typedef int vm_fault_t; -+#endif +-void ++static void + LinuxDriverExit(void) + { + unregister_ioctl32_handlers(); +diff --git a/vmmon-only/linux/hostif.c b/vmmon-only/linux/hostif.c +index 3bce32c3..b83e21d3 100644 +--- a/vmmon-only/linux/hostif.c ++++ b/vmmon-only/linux/hostif.c +@@ -3110,7 +3110,7 @@ HostIF_ReadPage(VMDriver *vm, // IN: The VM instance + *---------------------------------------------------------------------- + */ - /* +-int ++static int + HostIFWritePageWork(MPN64 mpn, // MPN of the page + VA64 addr, // data to write to the page + Bool kernelBuffer) // is the buffer in kernel space? +@@ -3416,7 +3416,7 @@ HostIFDoIoctl(struct file *filp, *---------------------------------------------------------------------- -@@ -110,9 +113,9 @@ long LinuxDriver_Ioctl(struct file *filp, u_int iocmd, - static int LinuxDriver_Close(struct inode *inode, struct file *filp); - static unsigned int LinuxDriverPoll(struct file *file, poll_table *wait); - #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) --static int LinuxDriverFault(struct vm_fault *fault); -+static vm_fault_t LinuxDriverFault(struct vm_fault *fault); - #elif defined(VMW_NOPAGE_2624) --static int LinuxDriverFault(struct vm_area_struct *vma, struct vm_fault *fault); -+static vm_fault_t LinuxDriverFault(struct vm_area_struct *vma, struct vm_fault *fault); - #else - static struct page *LinuxDriverNoPage(struct vm_area_struct *vma, - unsigned long address, -@@ -940,11 +943,11 @@ LinuxDriverPollTimeout(compat_timer_arg_t unused) // IN: */ - #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) --static int -+static vm_fault_t - LinuxDriverFault(struct vm_fault *fault) //IN/OUT - #elif defined(VMW_NOPAGE_2624) --static int LinuxDriverFault(struct vm_area_struct *vma, //IN -- struct vm_fault *fault) //IN/OUT -+static vm_fault_t LinuxDriverFault(struct vm_area_struct *vma, //IN -+ struct vm_fault *fault) //IN/OUT - #else - static struct page *LinuxDriverNoPage(struct vm_area_struct *vma, //IN - unsigned long address, //IN +-int ++static int + HostIFStartTimer(Bool rateChanged, //IN: Did rate change? + unsigned int rate, //IN: current clock rate + struct file *filp) //IN: /dev/rtc descriptor |