Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e48dcf8412 | ||
|
|
2a57f2834c | ||
|
|
51cf4e9846 | ||
|
|
d9457a4fab | ||
|
|
989a328fa5 | ||
|
|
a116d32e0a |
No files matched your search
@@ -150,7 +150,7 @@ test build).
|
||||
When using a downloaded tarball, simply run
|
||||
|
||||
tar -cf vmmon.tar vmmon-only
|
||||
tar -cf vmnet.tar vmnet-only
|
||||
tar -cf vmnet.tar vmmon-only
|
||||
|
||||
to create the tarballs. In this case, there is no protection against
|
||||
unwanted local changes.
|
||||
|
||||
@@ -43,7 +43,6 @@ install: retiredcheck $(MODFILES)
|
||||
if test -z "$(DESTDIR)"; then $(DEPMOD) -a $(VM_UNAME); fi
|
||||
|
||||
clean: $(SUBDIRS)
|
||||
rm -f *.o
|
||||
|
||||
tarballs: $(TARBALLS)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
*-----------------------------------------------------------------------------
|
||||
* Branch player-12.5.6 has been retired on 2017-05-31 and has not been
|
||||
* receiving any updates since. Please switch to latest 12.5.x version
|
||||
* available.
|
||||
*
|
||||
* Latest kernel version this branch is intended to work with is 4.11.
|
||||
*-----------------------------------------------------------------------------
|
||||
+1
-1
@@ -117,7 +117,7 @@ prebuild:: ;
|
||||
postbuild:: ;
|
||||
|
||||
$(DRIVER_KO): prebuild
|
||||
$(MAKE) -C $(BUILD_DIR) M=$$PWD SRCROOT=$$PWD/$(SRCROOT) \
|
||||
$(MAKE) -C $(BUILD_DIR) SUBDIRS=$$PWD SRCROOT=$$PWD/$(SRCROOT) \
|
||||
MODULEBUILDDIR=$(MODULEBUILDDIR) modules
|
||||
$(MAKE) -C $$PWD SRCROOT=$$PWD/$(SRCROOT) \
|
||||
MODULEBUILDDIR=$(MODULEBUILDDIR) postbuild
|
||||
|
||||
@@ -33,7 +33,7 @@ $(DRIVER)-y := $(subst $(SRCROOT)/, , $(patsubst %.c, %.o, \
|
||||
$(wildcard $(SRCROOT)/linux/*.c $(SRCROOT)/common/*.c $(SRCROOT)/vmcore/*.c)))
|
||||
|
||||
clean:
|
||||
rm -rf $(wildcard $(DRIVER).mod.c $(DRIVER).ko .tmp_versions .cache.mk \
|
||||
rm -rf $(wildcard $(DRIVER).mod.c $(DRIVER).ko .tmp_versions \
|
||||
Module.symvers Modules.symvers Module.markers modules.order \
|
||||
$(foreach dir,linux/ common/ vmcore/ \
|
||||
./,$(addprefix $(dir),.*.cmd .*.o.flags *.o)))
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998,2018 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -35,7 +35,6 @@
|
||||
uint32 cpuidFeatures;
|
||||
static CpuidVendor vendor = CPUID_NUM_VENDORS;
|
||||
static uint32 version;
|
||||
static Bool hasSpecCtrl;
|
||||
|
||||
|
||||
/*
|
||||
@@ -98,9 +97,6 @@ CPUID_Init(void)
|
||||
Warning("VMMON CPUID: Unrecognized CPU\n");
|
||||
vendor = CPUID_VENDOR_UNKNOWN;
|
||||
}
|
||||
|
||||
__GET_CPUID2(7, 0, ®s);
|
||||
hasSpecCtrl = vendor == CPUID_VENDOR_INTEL && ((regs.edx >> 26) & 0x3) != 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -211,26 +207,3 @@ CPUID_AddressSizeSupported(void)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* CPUID_HostSupportsSpecCtrl --
|
||||
*
|
||||
* Determine whether the processor supports MSR_SPEC_CTRL.
|
||||
*
|
||||
* Results:
|
||||
* True iff the processor supports the required features.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
CPUID_HostSupportsSpecCtrl(void)
|
||||
{
|
||||
return hasSpecCtrl;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998,2016,2018 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998,2016 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -39,7 +39,6 @@ uint32 CPUID_GetVersion(void);
|
||||
Bool CPUID_SyscallSupported(void);
|
||||
Bool CPUID_LongModeSupported(void);
|
||||
Bool CPUID_AddressSizeSupported(void);
|
||||
Bool CPUID_HostSupportsSpecCtrl(void);
|
||||
|
||||
static INLINE uint32
|
||||
CPUID_GetFeatures(void)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2014 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -122,10 +122,14 @@ EXTERN MPN HostIF_GetNextAnonPage(VMDriver *vm, MPN mpn);
|
||||
EXTERN int HostIF_GetLockedPageList(VMDriver *vm, VA64 uAddr,
|
||||
unsigned int numPages);
|
||||
|
||||
EXTERN int HostIF_ReadPage(VMDriver *vm, MPN mpn, VA64 addr, Bool kernelBuffer);
|
||||
EXTERN int HostIF_WritePage(VMDriver *vm, MPN mpn, VA64 addr,
|
||||
Bool kernelBuffer);
|
||||
EXTERN int HostIF_ReadPage(MPN mpn, VA64 addr, Bool kernelBuffer);
|
||||
EXTERN int HostIF_WritePage(MPN mpn, VA64 addr, Bool kernelBuffer);
|
||||
#ifdef _WIN32
|
||||
/* Add a HostIF_ReadMachinePage() if/when needed */
|
||||
EXTERN int HostIF_WriteMachinePage(MPN mpn, VA64 addr);
|
||||
#else
|
||||
#define HostIF_WriteMachinePage(_a, _b) HostIF_WritePage((_a), (_b), TRUE)
|
||||
#endif
|
||||
#if defined __APPLE__
|
||||
// There is no need for a fast clock lock on Mac OS.
|
||||
#define HostIF_FastClockLock(_callerID) do {} while (0)
|
||||
@@ -141,8 +145,4 @@ EXTERN void HostIF_FreeMachinePage(MPN mpn);
|
||||
|
||||
EXTERN int HostIF_SafeRDMSR(uint32 msr, uint64 *val);
|
||||
|
||||
#if defined __APPLE__
|
||||
EXTERN void HostIF_PageUnitTest(void);
|
||||
#endif
|
||||
|
||||
#endif // ifdef _HOSTIF_H_
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -88,7 +88,6 @@
|
||||
|
||||
#include "vmware.h"
|
||||
#include "hostif.h"
|
||||
#include "vmx86.h"
|
||||
|
||||
#include "memtrack.h"
|
||||
|
||||
@@ -147,11 +146,12 @@ typedef struct MemTrackHT {
|
||||
typedef uint64 MemTrackHTKey;
|
||||
|
||||
typedef struct MemTrack {
|
||||
VMDriver *vm; /* The VM instance. */
|
||||
unsigned numPages; /* Number of pages tracked. */
|
||||
MemTrackDir1 dir1; /* First level directory. */
|
||||
MemTrackHT vpnHashTable; /* VPN to entry hashtable. */
|
||||
#if defined(MEMTRACK_MPN_LOOKUP)
|
||||
MemTrackHT mpnHashTable; /* MPN to entry hashtable. */
|
||||
#endif
|
||||
} MemTrack;
|
||||
|
||||
/*
|
||||
@@ -304,9 +304,11 @@ MemTrackCleanup(MemTrack *mt) // IN
|
||||
if (mt->vpnHashTable.pages[idx] != NULL) {
|
||||
HostIF_FreePage(mt->vpnHashTable.pages[idx]);
|
||||
}
|
||||
#if defined(MEMTRACK_MPN_LOOKUP)
|
||||
if (mt->mpnHashTable.pages[idx] != NULL) {
|
||||
HostIF_FreePage(mt->mpnHashTable.pages[idx]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
HostIF_FreeKernelMem(mt);
|
||||
@@ -330,7 +332,7 @@ MemTrackCleanup(MemTrack *mt) // IN
|
||||
*/
|
||||
|
||||
MemTrack *
|
||||
MemTrack_Init(VMDriver *vm) // IN:
|
||||
MemTrack_Init(void)
|
||||
{
|
||||
MemTrack *mt;
|
||||
unsigned idx;
|
||||
@@ -347,7 +349,6 @@ MemTrack_Init(VMDriver *vm) // IN:
|
||||
goto error;
|
||||
}
|
||||
memset(mt, 0, sizeof *mt);
|
||||
mt->vm = vm;
|
||||
|
||||
for (idx = 0; idx < MEMTRACK_HT_PAGES; idx++) {
|
||||
MemTrackHTPage *htPage = MemTrackAllocPage();
|
||||
@@ -359,6 +360,7 @@ MemTrack_Init(VMDriver *vm) // IN:
|
||||
mt->vpnHashTable.pages[idx] = htPage;
|
||||
}
|
||||
|
||||
#if defined(MEMTRACK_MPN_LOOKUP)
|
||||
for (idx = 0; idx < MEMTRACK_HT_PAGES; idx++) {
|
||||
MemTrackHTPage *htPage = MemTrackAllocPage();
|
||||
|
||||
@@ -368,6 +370,7 @@ MemTrack_Init(VMDriver *vm) // IN:
|
||||
}
|
||||
mt->mpnHashTable.pages[idx] = htPage;
|
||||
}
|
||||
#endif
|
||||
|
||||
return mt;
|
||||
|
||||
@@ -406,8 +409,6 @@ MemTrack_Add(MemTrack *mt, // IN
|
||||
MemTrackDir3 *dir3;
|
||||
MEMTRACK_IDX2DIR(idx, p1, p2, p3);
|
||||
|
||||
ASSERT(HostIF_VMLockIsHeld(mt->vm));
|
||||
|
||||
if (p1 >= MEMTRACK_DIR1_ENTRIES ||
|
||||
p2 >= MEMTRACK_DIR2_ENTRIES ||
|
||||
p3 >= MEMTRACK_DIR3_ENTRIES) {
|
||||
@@ -429,7 +430,9 @@ MemTrack_Add(MemTrack *mt, // IN
|
||||
ent->mpn = mpn;
|
||||
|
||||
MemTrackHTInsert(&mt->vpnHashTable, ent, &ent->vpnChain, ent->vpn);
|
||||
#if defined(MEMTRACK_MPN_LOOKUP)
|
||||
MemTrackHTInsert(&mt->mpnHashTable, ent, &ent->mpnChain, ent->mpn);
|
||||
#endif
|
||||
|
||||
mt->numPages++;
|
||||
|
||||
@@ -458,7 +461,6 @@ MemTrack_LookupVPN(MemTrack *mt, // IN
|
||||
VPN64 vpn) // IN
|
||||
{
|
||||
MemTrackEntry *next = *MemTrackHTLookup(&mt->vpnHashTable, vpn);
|
||||
ASSERT(HostIF_VMLockIsHeld(mt->vm));
|
||||
|
||||
while (next != NULL) {
|
||||
if (next->vpn == vpn) {
|
||||
@@ -471,6 +473,7 @@ MemTrack_LookupVPN(MemTrack *mt, // IN
|
||||
}
|
||||
|
||||
|
||||
#if defined(MEMTRACK_MPN_LOOKUP)
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -490,9 +493,7 @@ MemTrackEntry *
|
||||
MemTrack_LookupMPN(MemTrack *mt, // IN
|
||||
MPN mpn) // IN
|
||||
{
|
||||
MemTrackEntry *next;
|
||||
ASSERT(HostIF_VMLockIsHeld(mt->vm));
|
||||
next = *MemTrackHTLookup(&mt->mpnHashTable, mpn);
|
||||
MemTrackEntry *next = *MemTrackHTLookup(&mt->mpnHashTable, mpn);
|
||||
|
||||
while (next != NULL) {
|
||||
if (next->mpn == mpn) {
|
||||
@@ -503,6 +504,7 @@ MemTrack_LookupMPN(MemTrack *mt, // IN
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -31,22 +31,30 @@
|
||||
#define INCLUDE_ALLOW_VMCORE
|
||||
#include "includeCheck.h"
|
||||
|
||||
#if defined(VMX86_DEBUG)
|
||||
#define MEMTRACK_MPN_LOOKUP
|
||||
#endif
|
||||
|
||||
struct MemTrack;
|
||||
|
||||
typedef struct MemTrackEntry {
|
||||
VPN64 vpn;
|
||||
MPN mpn;
|
||||
struct MemTrackEntry *vpnChain;
|
||||
#if defined(MEMTRACK_MPN_LOOKUP)
|
||||
struct MemTrackEntry *mpnChain;
|
||||
#endif
|
||||
} MemTrackEntry;
|
||||
|
||||
typedef void (MemTrackCleanupCb)(void *cData, MemTrackEntry *entry);
|
||||
|
||||
extern struct MemTrack *MemTrack_Init(VMDriver *vm);
|
||||
extern struct MemTrack *MemTrack_Init(void);
|
||||
extern unsigned MemTrack_Cleanup(struct MemTrack *mt, MemTrackCleanupCb *cb,
|
||||
void *cbData);
|
||||
extern MemTrackEntry *MemTrack_Add(struct MemTrack *mt, VPN64 vpn, MPN mpn);
|
||||
extern MemTrackEntry *MemTrack_LookupVPN(struct MemTrack *mt, VPN64 vpn);
|
||||
#if defined(MEMTRACK_MPN_LOOKUP)
|
||||
extern MemTrackEntry *MemTrack_LookupMPN(struct MemTrack *mt, MPN mpn);
|
||||
#endif
|
||||
|
||||
#endif // _MEMTRACK_H_
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2018 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2016 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -39,9 +39,6 @@
|
||||
# include <linux/string.h> /* memset() in the kernel */
|
||||
|
||||
# define EXPORT_SYMTAB
|
||||
# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
|
||||
# define LINUX_GDT_IS_RO
|
||||
# endif
|
||||
#else
|
||||
# include <string.h>
|
||||
#endif
|
||||
@@ -63,13 +60,6 @@
|
||||
#include "apic.h"
|
||||
#include "x86perfctr.h"
|
||||
|
||||
#ifdef LINUX_GDT_IS_RO
|
||||
# include <asm/desc.h>
|
||||
# define default_rw_gdt get_current_gdt_rw()
|
||||
#else
|
||||
# define default_rw_gdt NULL
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64)
|
||||
# include "x86.h"
|
||||
# include "vmmon-asm-x86-64.h"
|
||||
@@ -79,9 +69,6 @@
|
||||
# define USE_TEMPORARY_GDT 0
|
||||
#endif
|
||||
|
||||
/* Cycle through values of SPEC_CTRL and verify they survive world switch. */
|
||||
#undef CYCLE_SPEC_CTRL
|
||||
|
||||
#define TS_ASSERT(t) do { \
|
||||
DEBUG_ONLY(if (!(t)) TaskAssertFail(__LINE__);) \
|
||||
} while (0)
|
||||
@@ -704,28 +691,11 @@ TaskRestoreHostGDTTRLDT(Descriptor *tempGDTBase,
|
||||
*/
|
||||
|
||||
desc = (Descriptor *)((VA)HOST_KERNEL_LA_2_VA(hostGDT64.offset + tr));
|
||||
#ifdef LINUX_GDT_IS_RO
|
||||
/*
|
||||
* If GDT is read-only, we must always load TR from alternative gdt,
|
||||
* otherwise CPU gets page fault when marking TR busy.
|
||||
*/
|
||||
{
|
||||
DTR64 rwGDT64;
|
||||
|
||||
rwGDT64.offset = (unsigned long)tempGDTBase;
|
||||
rwGDT64.limit = hostGDT64.limit;
|
||||
Desc_SetType((Descriptor *)((unsigned long)tempGDTBase + tr), TASK_DESC);
|
||||
_Set_GDT((DTR *)&rwGDT64);
|
||||
SET_TR(tr);
|
||||
_Set_GDT((DTR *)&hostGDT64);
|
||||
}
|
||||
#else
|
||||
if (Desc_Type(desc) == TASK_DESC_BUSY) {
|
||||
Desc_SetType(desc, TASK_DESC);
|
||||
}
|
||||
_Set_GDT((DTR *)&hostGDT64);
|
||||
SET_TR(tr);
|
||||
#endif
|
||||
SET_LDT(ldt);
|
||||
}
|
||||
}
|
||||
@@ -1597,23 +1567,12 @@ TaskSwitchToMonitor(VMCrossPage *crosspage)
|
||||
{
|
||||
uint64 raxGetsWiped, rcxGetsWiped;
|
||||
|
||||
#ifdef CALL_NOSPEC
|
||||
__asm__ __volatile__(CALL_NOSPEC
|
||||
: "=a" (raxGetsWiped),
|
||||
"=c" (rcxGetsWiped)
|
||||
: "0" (codePtr),
|
||||
"1" (crosspage),
|
||||
THUNK_TARGET(codePtr)
|
||||
: "rdx", "r8", "r9", "r10", "r11", "cc", "memory");
|
||||
#else
|
||||
__asm__ __volatile__("call *%%rax"
|
||||
: "=a" (raxGetsWiped),
|
||||
"=c" (rcxGetsWiped)
|
||||
: "0" (codePtr),
|
||||
"1" (crosspage)
|
||||
: "rdx", "r8", "r9", "r10", "r11", "cc", "memory");
|
||||
#endif
|
||||
|
||||
}
|
||||
#elif defined(_MSC_VER)
|
||||
/*
|
||||
@@ -1778,11 +1737,6 @@ Task_Switch(VMDriver *vm, // IN
|
||||
uint32 pCPU;
|
||||
MPN hvRootMPN;
|
||||
Descriptor *tempGDTBase;
|
||||
#ifdef CYCLE_SPEC_CTRL
|
||||
Bool specCtrlEqual = FALSE;
|
||||
uint64 readSpecCtrlValue = 0;
|
||||
static volatile uint64 currentSpecCtrlValue = 0;
|
||||
#endif
|
||||
|
||||
ASSERT_ON_COMPILE(sizeof(VMCrossPage) == PAGE_SIZE);
|
||||
TaskDisableNMI(&vm->hostAPIC, &lint0NMI, &lint1NMI, &pcNMI, &thermalNMI);
|
||||
@@ -1793,8 +1747,7 @@ Task_Switch(VMDriver *vm, // IN
|
||||
ASSERT(pCPU < ARRAYSIZE(hvRootPage) && pCPU < ARRAYSIZE(tmpGDT));
|
||||
|
||||
hvRootMPN = Atomic_Read64(&hvRootPage[pCPU]);
|
||||
tempGDTBase = USE_TEMPORARY_GDT ? Atomic_ReadPtr(&tmpGDT[pCPU])
|
||||
: default_rw_gdt;
|
||||
tempGDTBase = USE_TEMPORARY_GDT ? Atomic_ReadPtr(&tmpGDT[pCPU]) : NULL;
|
||||
|
||||
/*
|
||||
* We can't allocate memory with interrupts disabled on all hosts
|
||||
@@ -1992,14 +1945,6 @@ Task_Switch(VMDriver *vm, // IN
|
||||
TS_ASSERT(SELECTOR_TABLE(ds) == SELECTOR_GDT);
|
||||
TS_ASSERT(SELECTOR_TABLE(ss) == SELECTOR_GDT);
|
||||
|
||||
if (CPUID_HostSupportsSpecCtrl()) {
|
||||
#ifdef CYCLE_SPEC_CTRL
|
||||
currentSpecCtrlValue = (currentSpecCtrlValue + 1) % 4;
|
||||
__SET_MSR(MSR_SPEC_CTRL, currentSpecCtrlValue);
|
||||
#endif
|
||||
crosspage->crosspageData.specCtrl = __GET_MSR(MSR_SPEC_CTRL);
|
||||
}
|
||||
|
||||
DEBUG_ONLY(crosspage->crosspageData.tinyStack[0] = 0xDEADBEEF;)
|
||||
/* Running in host context prior to TaskSwitchToMonitor() */
|
||||
TaskSwitchToMonitor(crosspage);
|
||||
@@ -2007,16 +1952,6 @@ Task_Switch(VMDriver *vm, // IN
|
||||
|
||||
TS_ASSERT(crosspage->crosspageData.tinyStack[0] == 0xDEADBEEF);
|
||||
|
||||
#ifdef CYCLE_SPEC_CTRL
|
||||
if (CPUID_HostSupportsSpecCtrl()) {
|
||||
readSpecCtrlValue = __GET_MSR(MSR_SPEC_CTRL);
|
||||
specCtrlEqual = readSpecCtrlValue ==
|
||||
crosspage->crosspageData.specCtrl;
|
||||
/* Do not leak cycling SPEC_CTRL value back to host. */
|
||||
__SET_MSR(MSR_SPEC_CTRL, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Temporarily disable single-step stress as VMX/VMCS change code
|
||||
* ASSERTS on RFLAGS content without allowing TF/RF to be set.
|
||||
@@ -2150,12 +2085,6 @@ Task_Switch(VMDriver *vm, // IN
|
||||
if (UNLIKELY(TaskGotException(crosspage, EXC_UD))) {
|
||||
Warning("#UD occurred on switch back to host; dumping core");
|
||||
}
|
||||
#ifdef CYCLE_SPEC_CTRL
|
||||
if (UNLIKELY(!specCtrlEqual)) {
|
||||
Warning("SpecCtrl not equal: expected %"FMT64"x, got %"FMT64"x\n",
|
||||
crosspage->crosspageData.specCtrl, readSpecCtrlValue);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* The NMI/MCE checks above are special cases for interrupts
|
||||
* received during worldswitch. Here is the more generic case
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2016 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -720,35 +720,6 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Vmx86_LookupUserMPN --
|
||||
*
|
||||
* Look up the MPN of a locked user page by user VA under the VM lock.
|
||||
*
|
||||
* Results:
|
||||
* A status code and the MPN on success.
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
Vmx86_LookupUserMPN(VMDriver *vm, // IN: VMDriver
|
||||
VA64 uAddr, // IN: user VA of the page
|
||||
MPN *mpn) // OUT
|
||||
{
|
||||
int ret;
|
||||
HostIF_VMLock(vm, 38);
|
||||
ret = HostIF_LookupUserMPN(vm, uAddr, mpn);
|
||||
HostIF_VMUnlock(vm, 38);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2013,2015-2016 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -106,7 +106,6 @@ extern PseudoTSC pseudoTSC;
|
||||
#define MAX_LOCKED_PAGES (-1)
|
||||
|
||||
extern VMDriver *Vmx86_CreateVM(void);
|
||||
extern int Vmx86_LookupUserMPN(VMDriver *vm, VA64 uAddr, MPN *mpn);
|
||||
extern int Vmx86_ReleaseVM(VMDriver *vm);
|
||||
extern int Vmx86_InitVM(VMDriver *vm, InitBlock *initParams);
|
||||
extern int Vmx86_LateInitVM(VMDriver *vm);
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
#ifndef __COMPAT_MMAP_LOCK_H__
|
||||
#define __COMPAT_MMAP_LOCK_H__
|
||||
|
||||
#include <linux/mm.h>
|
||||
|
||||
/*
|
||||
* In 5.8-rc1, mmap locking was reworked to use wrappers around mmap_sem
|
||||
* (which was also renamed to mmap_lock). All code is now supposed to use
|
||||
* these wrappers as the internal implementation of the lock may change in
|
||||
* the future.
|
||||
*
|
||||
* Check also _LINUX_MMAP_LOCK_H to handle possible backports to distribution
|
||||
* pre-5.8 kernel. This macro is defined in <linux/mmap_lock.h> which is also
|
||||
* included in <linux/mm.h> since the commit introducing the wrappers so that
|
||||
* we should have it defined in any kernel providing the new API.
|
||||
*/
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) || defined(_LINUX_MMAP_LOCK_H)
|
||||
#include <linux/mmap_lock.h>
|
||||
#else
|
||||
|
||||
static inline void mmap_read_lock(struct mm_struct *mm)
|
||||
{
|
||||
down_read(&mm->mmap_sem);
|
||||
}
|
||||
|
||||
static inline void mmap_read_unlock(struct mm_struct *mm)
|
||||
{
|
||||
up_read(&mm->mmap_sem);
|
||||
}
|
||||
|
||||
#endif /* 5.8.0 */
|
||||
|
||||
#endif /* __COMPAT_MMAP_LOCK_H__ */
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2002-2017 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 2002 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -30,32 +30,100 @@
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
|
||||
/* pte_page() API modified in 2.3.23 to return a struct page * --hpreg */
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 23)
|
||||
# define compat_pte_page pte_page
|
||||
#else
|
||||
# include "compat_page.h"
|
||||
|
||||
# define compat_pte_page(_pte) virt_to_page(pte_page(_pte))
|
||||
#endif
|
||||
|
||||
|
||||
/* Appeared in 2.5.5 --hpreg */
|
||||
#ifndef pte_offset_map
|
||||
/* Appeared in SuSE 8.0's 2.4.18 --hpreg */
|
||||
# ifdef pte_offset_atomic
|
||||
# define pte_offset_map pte_offset_atomic
|
||||
# define pte_unmap pte_kunmap
|
||||
# else
|
||||
# define pte_offset_map pte_offset
|
||||
# define pte_unmap(_pte)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Appeared in 2.5.74-mmX --petr */
|
||||
#ifndef pmd_offset_map
|
||||
# define pmd_offset_map(pgd, address) pmd_offset(pgd, address)
|
||||
# define pmd_unmap(pmd)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* p4d level appeared in 4.12.
|
||||
* Appeared in 2.6.10-rc2-mm1. Older kernels did L4 page tables as
|
||||
* part of pgd_offset, or they did not have L4 page tables at all.
|
||||
* In 2.6.11 pml4 -> pgd -> pmd -> pte hierarchy was replaced by
|
||||
* pgd -> pud -> pmd -> pte hierarchy. In 4.12, it was replaced by
|
||||
* pgd -> p4d -> pud -> pmd -> pte hierarchy (5-level page tables).
|
||||
*/
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
|
||||
#ifdef P4D_MASK
|
||||
# define compat_pgd_offset(mm, address) pgd_offset(mm, address)
|
||||
# define compat_pgd_present(pgd) pgd_present(pgd)
|
||||
# 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_pud_offset(p4d, address) pud_offset(p4d, address)
|
||||
# define compat_pud_present(pud) pud_present(pud)
|
||||
typedef pgd_t compat_pgd_t;
|
||||
typedef p4d_t compat_p4d_t;
|
||||
typedef pud_t compat_pud_t;
|
||||
#elif defined(PUD_MASK)
|
||||
# define compat_pgd_offset(mm, address) pgd_offset(mm, address)
|
||||
# define compat_pgd_present(pgd) pgd_present(pgd)
|
||||
# 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;
|
||||
# define compat_pud_offset(p4d, address) pud_offset(p4d, address)
|
||||
# define compat_pud_present(pud) pud_present(pud)
|
||||
typedef pgd_t compat_pgd_t;
|
||||
typedef pgd_t compat_p4d_t;
|
||||
typedef pud_t compat_pud_t;
|
||||
#elif defined(pml4_offset)
|
||||
# define compat_pgd_offset(mm, address) pml4_offset(mm, address)
|
||||
# define compat_pgd_present(pml4) pml4_present(pml4)
|
||||
# define compat_p4d_offset(pml4, address) (pml4)
|
||||
# define compat_p4d_present(pml4) (1)
|
||||
# define compat_pud_offset(pml4, address) pml4_pgd_offset(pml4, address)
|
||||
# define compat_pud_present(pgd) pgd_present(pgd)
|
||||
typedef pml4_t compat_pgd_t;
|
||||
typedef pml4_t compat_p4d_t;
|
||||
typedef pgd_t compat_pud_t;
|
||||
#else
|
||||
# define compat_pgd_offset(mm, address) pgd_offset(mm, address)
|
||||
# define compat_pgd_present(pgd) pgd_present(pgd)
|
||||
# define compat_p4d_offset(pgd, address) (pgd)
|
||||
# define compat_p4d_present(p4d) (1)
|
||||
# define compat_pud_offset(p4d, address) (p4d)
|
||||
# define compat_pud_present(pud) (1)
|
||||
typedef pgd_t compat_pgd_t;
|
||||
typedef pgd_t compat_p4d_t;
|
||||
typedef pgd_t compat_pud_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
|
||||
|
||||
|
||||
#define compat_pgd_offset_k(mm, address) pgd_offset_k(address)
|
||||
|
||||
|
||||
/* 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))
|
||||
#endif
|
||||
/* pud_pfn did not exist before 3.8. */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
|
||||
# define pud_pfn(pud) INVALID_MPN
|
||||
|
||||
|
||||
/* A page_table_lock field is added to struct mm_struct in 2.3.10 --hpreg */
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 10)
|
||||
# define compat_get_page_table_lock(_mm) (&(_mm)->page_table_lock)
|
||||
#else
|
||||
# define compat_get_page_table_lock(_mm) NULL
|
||||
#endif
|
||||
|
||||
|
||||
@@ -80,8 +148,12 @@ typedef pgd_t compat_p4d_t;
|
||||
#define VM_PAGE_KERNEL_EXEC PAGE_KERNEL
|
||||
#endif
|
||||
#else
|
||||
#ifdef PAGE_KERNEL_EXECUTABLE
|
||||
#define VM_PAGE_KERNEL_EXEC PAGE_KERNEL_EXECUTABLE
|
||||
#else
|
||||
#define VM_PAGE_KERNEL_EXEC PAGE_KERNEL_EXEC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __COMPAT_PGTABLE_H__ */
|
||||
@@ -1,30 +0,0 @@
|
||||
#ifndef __COMPAT_POLL_H__
|
||||
#define __COMPAT_POLL_H__
|
||||
|
||||
#include <linux/poll.h>
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0))
|
||||
|
||||
#ifndef __poll_t
|
||||
typedef unsigned int __poll_t;
|
||||
#endif
|
||||
|
||||
static inline __poll_t compat_vfs_poll(struct file *file,
|
||||
struct poll_table_struct *pt)
|
||||
{
|
||||
if (unlikely(!file->f_op->poll))
|
||||
return DEFAULT_POLLMASK;
|
||||
return file->f_op->poll(file, pt);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline __poll_t compat_vfs_poll(struct file *file,
|
||||
struct poll_table_struct *pt)
|
||||
{
|
||||
return vfs_poll(file, pt);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __COMPAT_POLL_H__ */
|
||||
@@ -1,33 +0,0 @@
|
||||
#ifndef __COMPAT_TIMER_H__
|
||||
# define __COMPAT_TIMER_H__
|
||||
|
||||
#include <linux/timer.h>
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) && !defined(timer_setup)
|
||||
|
||||
typedef unsigned long compat_timer_arg_t;
|
||||
|
||||
static inline void compat_timer_setup(struct timer_list *timer,
|
||||
void (*func)(compat_timer_arg_t),
|
||||
unsigned int flags)
|
||||
{
|
||||
init_timer(timer);
|
||||
timer->function = func;
|
||||
timer->data = 0;
|
||||
timer->flags = flags;
|
||||
}
|
||||
|
||||
#else /* new timer interface since 4.15 */
|
||||
|
||||
typedef struct timer_list *compat_timer_arg_t;
|
||||
|
||||
static inline void compat_timer_setup(struct timer_list *timer,
|
||||
void (*func)(compat_timer_arg_t),
|
||||
unsigned int flags)
|
||||
{
|
||||
timer_setup(timer, func, flags);
|
||||
}
|
||||
|
||||
#endif /* new timer interface since 4.15 */
|
||||
|
||||
#endif /* __COMPAT_TIMER_H__ */
|
||||
@@ -251,7 +251,6 @@ static INLINE ub8 hash2(register const ub8 *k, /* the key */
|
||||
{
|
||||
/* c is reserved for the length */
|
||||
case 2: b+=k[1];
|
||||
/* fall through */
|
||||
case 1: a+=k[0];
|
||||
/* case 0: nothing left to add */
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2015,2018 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -133,7 +133,7 @@ PtrToVA64(void const *ptr) // IN
|
||||
*
|
||||
*/
|
||||
|
||||
#define VMMON_VERSION (309 << 16 | 0)
|
||||
#define VMMON_VERSION (308 << 16 | 0)
|
||||
#define VMMON_VERSION_MAJOR(v) ((uint32) (v) >> 16)
|
||||
#define VMMON_VERSION_MINOR(v) ((uint16) (v))
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2015,2018 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -421,7 +421,6 @@ struct VMCrossPageData {
|
||||
*/
|
||||
uint8 switchHostIDT [sizeof(Gate64) * NUM_EXCEPTIONS]; // hostCS:hostVA
|
||||
uint8 switchMon64IDT[sizeof(Gate64) * NUM_EXCEPTIONS]; // 64-bit monCS:monVA
|
||||
uint64 specCtrl; /* host MSR_SPEC_CTRL value before world switch. */
|
||||
}
|
||||
#include "vmware_pack_end.h"
|
||||
VMCrossPageData;
|
||||
@@ -475,7 +474,7 @@ struct VMCrossPage {
|
||||
#include "vmware_pack_end.h"
|
||||
VMCrossPage;
|
||||
|
||||
#define CROSSPAGE_VERSION_BASE 0xbf2 /* increment by 1 */
|
||||
#define CROSSPAGE_VERSION_BASE 0xbf1 /* increment by 1 */
|
||||
#define CROSSPAGE_VERSION ((CROSSPAGE_VERSION_BASE << 1) + WS_INTR_STRESS)
|
||||
|
||||
#if !defined(VMX86_SERVER) && defined(VMM)
|
||||
|
||||
+305
-59
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2002,2014-2017 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 2002,2014 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -26,14 +26,160 @@
|
||||
#include "compat_spinlock.h"
|
||||
#include "compat_page.h"
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* PgtblPte2MPN --
|
||||
*
|
||||
* Returns the page structure associated to a Page Table Entry.
|
||||
*
|
||||
* 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 MPN
|
||||
PgtblPte2MPN(pte_t *pte) // IN
|
||||
{
|
||||
MPN mpn;
|
||||
if (pte_present(*pte) == 0) {
|
||||
return INVALID_MPN;
|
||||
}
|
||||
mpn = pte_pfn(*pte);
|
||||
if (mpn >= INVALID_MPN) {
|
||||
return INVALID_MPN;
|
||||
}
|
||||
return mpn;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* PgtblPte2Page --
|
||||
*
|
||||
* Returns the page structure associated to a Page Table Entry.
|
||||
*
|
||||
* This function is not allowed to schedule() because it can be called while
|
||||
* holding a spinlock --hpreg
|
||||
*
|
||||
* Results:
|
||||
* The page structure if the page table entry points to a physical page
|
||||
* NULL if the page table entry does not point to a physical page
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static INLINE struct page *
|
||||
PgtblPte2Page(pte_t *pte) // IN
|
||||
{
|
||||
if (pte_present(*pte) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return compat_pte_page(*pte);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* PgtblPGD2PTELocked --
|
||||
*
|
||||
* Walks through the hardware page tables to try to find the pte
|
||||
* associated to a virtual address.
|
||||
*
|
||||
* Results:
|
||||
* pte. Caller must call pte_unmap if valid pte returned.
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static INLINE pte_t *
|
||||
PgtblPGD2PTELocked(compat_pgd_t *pgd, // IN: PGD to start with
|
||||
VA addr) // IN: Address in the virtual address
|
||||
// space of that process
|
||||
{
|
||||
compat_p4d_t *p4d;
|
||||
compat_pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
|
||||
if (compat_pgd_present(*pgd) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p4d = compat_p4d_offset(pgd, addr);
|
||||
if (compat_p4d_present(*p4d) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pud = compat_pud_offset(p4d, addr);
|
||||
if (compat_pud_present(*pud) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pmd = pmd_offset_map(pud, addr);
|
||||
if (pmd_present(*pmd) == 0) {
|
||||
pmd_unmap(pmd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pte = pte_offset_map(pmd, addr);
|
||||
pmd_unmap(pmd);
|
||||
return pte;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* PgtblVa2PTELocked --
|
||||
*
|
||||
* Walks through the hardware page tables to try to find the pte
|
||||
* associated to a virtual address.
|
||||
*
|
||||
* Results:
|
||||
* pte. Caller must call pte_unmap if valid pte returned.
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static INLINE pte_t *
|
||||
PgtblVa2PTELocked(struct mm_struct *mm, // IN: Mm structure of a process
|
||||
VA addr) // IN: Address in the virtual address
|
||||
// space of that process
|
||||
{
|
||||
return PgtblPGD2PTELocked(compat_pgd_offset(mm, addr), addr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* PgtblVa2MPNLocked --
|
||||
*
|
||||
* Walks through the hardware page tables to try to find the pte
|
||||
* associated to a virtual address. Then maps PTE to MPN.
|
||||
* 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
|
||||
*
|
||||
* Results:
|
||||
* INVALID_MPN on failure
|
||||
@@ -48,66 +194,91 @@
|
||||
static INLINE 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;
|
||||
MPN mpn;
|
||||
pte_t *pte;
|
||||
|
||||
pgd = pgd_offset(mm, addr);
|
||||
if (pgd_present(*pgd) == 0) {
|
||||
return INVALID_MPN;
|
||||
pte = PgtblVa2PTELocked(mm, addr);
|
||||
if (pte != NULL) {
|
||||
MPN 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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
return INVALID_MPN;
|
||||
}
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* PgtblKVa2MPNLocked --
|
||||
*
|
||||
* Retrieve MPN for a given kernel 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
|
||||
*
|
||||
* Results:
|
||||
* INVALID_MPN on failure
|
||||
* mpn on success
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static INLINE MPN
|
||||
PgtblKVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a caller
|
||||
VA addr) // IN: Address in the virtual address
|
||||
{
|
||||
pte_t *pte;
|
||||
|
||||
pte = PgtblPGD2PTELocked(compat_pgd_offset_k(mm, addr), addr);
|
||||
if (pte != NULL) {
|
||||
MPN mpn = PgtblPte2MPN(pte);
|
||||
pte_unmap(pte);
|
||||
return mpn;
|
||||
}
|
||||
return INVALID_MPN;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* PgtblVa2PageLocked --
|
||||
*
|
||||
* Return the "page" struct for a given va.
|
||||
*
|
||||
* Results:
|
||||
* struct page or NULL. The mm->page_table_lock must be held, so this
|
||||
* function is not allowed to schedule() --hpreg
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static INLINE struct page *
|
||||
PgtblVa2PageLocked(struct mm_struct *mm, // IN: Mm structure of a process
|
||||
VA addr) // IN: Address in the virtual address
|
||||
{
|
||||
pte_t *pte;
|
||||
|
||||
pte = PgtblVa2PTELocked(mm, addr);
|
||||
if (pte != NULL) {
|
||||
struct page *page = PgtblPte2Page(pte);
|
||||
pte_unmap(pte);
|
||||
return page;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
@@ -133,10 +304,85 @@ PgtblVa2MPN(VA addr) // IN
|
||||
|
||||
/* current->mm is NULL for kernel threads, so use active_mm. */
|
||||
mm = current->active_mm;
|
||||
spin_lock(&mm->page_table_lock);
|
||||
if (compat_get_page_table_lock(mm)) {
|
||||
spin_lock(compat_get_page_table_lock(mm));
|
||||
}
|
||||
mpn = PgtblVa2MPNLocked(mm, addr);
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
if (compat_get_page_table_lock(mm)) {
|
||||
spin_unlock(compat_get_page_table_lock(mm));
|
||||
}
|
||||
return mpn;
|
||||
}
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* PgtblKVa2MPN --
|
||||
*
|
||||
* Walks through the hardware page tables of the current process to try to
|
||||
* find the page structure associated to a virtual address.
|
||||
*
|
||||
* Results:
|
||||
* Same as PgtblVa2MPNLocked()
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static INLINE MPN
|
||||
PgtblKVa2MPN(VA addr) // IN
|
||||
{
|
||||
struct mm_struct *mm = current->active_mm;
|
||||
MPN mpn;
|
||||
|
||||
if (compat_get_page_table_lock(mm)) {
|
||||
spin_lock(compat_get_page_table_lock(mm));
|
||||
}
|
||||
mpn = PgtblKVa2MPNLocked(mm, addr);
|
||||
if (compat_get_page_table_lock(mm)) {
|
||||
spin_unlock(compat_get_page_table_lock(mm));
|
||||
}
|
||||
return mpn;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* PgtblVa2Page --
|
||||
*
|
||||
* Walks through the hardware page tables of the current process to try to
|
||||
* find the page structure associated to a virtual address.
|
||||
*
|
||||
* Results:
|
||||
* Same as PgtblVa2PageLocked()
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static INLINE struct page *
|
||||
PgtblVa2Page(VA addr) // IN
|
||||
{
|
||||
struct mm_struct *mm = current->active_mm;
|
||||
struct page *page;
|
||||
|
||||
if (compat_get_page_table_lock(mm)) {
|
||||
spin_lock(compat_get_page_table_lock(mm));
|
||||
}
|
||||
page = PgtblVa2PageLocked(mm, addr);
|
||||
if (compat_get_page_table_lock(mm)) {
|
||||
spin_unlock(compat_get_page_table_lock(mm));
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
|
||||
#endif /* __PGTBL_H__ */
|
||||
@@ -67,7 +67,6 @@ extern "C" {
|
||||
#if defined (VMKPANIC)
|
||||
#include "vmk_assert.h"
|
||||
#else /* !VMKPANIC */
|
||||
#include <linux/kernel.h>
|
||||
#define _ASSERT_PANIC(name) \
|
||||
Panic(_##name##Fmt "\n", __FILE__, __LINE__)
|
||||
#define _ASSERT_PANIC_BUG(bug, name) \
|
||||
@@ -119,7 +118,7 @@ NORETURN void Panic_NoSaveNoReturn(const char *fmt, ...) PRINTF_DECL(1, 2);
|
||||
} while(0)
|
||||
|
||||
#else
|
||||
#define Panic panic
|
||||
NORETURN void Panic(const char *fmt, ...) PRINTF_DECL(1, 2);
|
||||
#endif
|
||||
|
||||
void LogThrottled(uint32 *count, const char *fmt, ...) PRINTF_DECL(2, 3);
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
#define INCLUDE_ALLOW_VMCORE
|
||||
#include "includeCheck.h"
|
||||
|
||||
#include <asm/processor-flags.h>
|
||||
|
||||
#define X86_MAX_INSTR_LEN 15 /* Max byte length of an x86 instruction. */
|
||||
|
||||
#define NUM_IDT_VECTORS 256
|
||||
@@ -64,9 +62,7 @@
|
||||
#define CR3_PDB_MASK 0xfffff000
|
||||
#define CR3_IGNORE 0xFFF
|
||||
#define PAE_CR3_IGNORE 0x1F
|
||||
#ifndef CR3_PCID_MASK
|
||||
#define CR3_PCID_MASK 0xFFF
|
||||
#endif
|
||||
#define CR3_NO_FLUSH (1ULL << 63)
|
||||
|
||||
#define CR4_VME 0x00000001
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2016 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -419,10 +419,6 @@ FIELD( 6, 0, EBX, 0, 4, NUM_INTR_THRESHOLDS, NA, FALSE) \
|
||||
FLAG( 6, 0, ECX, 0, 1, HW_COORD_FEEDBACK, NA, FALSE) \
|
||||
FLAG( 6, 0, ECX, 3, 1, ENERGY_PERF_BIAS, NA, FALSE)
|
||||
|
||||
#define CPUID_7_EDX_26 \
|
||||
FLAG( 7, 0, EDX, 26, 1, LEVEL7EDX_RSVD1, NO, FALSE)
|
||||
#define CPUID_7_EDX_27 \
|
||||
FLAG( 7, 0, EDX, 27, 1, LEVEL7EDX_RSVD2, NO, FALSE)
|
||||
|
||||
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
|
||||
#define CPUID_FIELD_DATA_LEVEL_7 \
|
||||
@@ -444,9 +440,8 @@ FLAG( 7, 0, EBX, 18, 1, RDSEED, YES, TRUE) \
|
||||
FLAG( 7, 0, EBX, 19, 1, ADX, YES, TRUE) \
|
||||
FLAG( 7, 0, EBX, 20, 1, SMAP, YES, FALSE) \
|
||||
FLAG( 7, 0, EBX, 25, 1, PT, NO, FALSE) \
|
||||
FLAG( 7, 0, ECX, 0, 1, PREFETCHWT1, NO, TRUE) \
|
||||
CPUID_7_EDX_26 \
|
||||
CPUID_7_EDX_27
|
||||
FLAG( 7, 0, ECX, 0, 1, PREFETCHWT1, NO, TRUE)
|
||||
|
||||
|
||||
/* LEVEL, SUB-LEVEL, REG, POS, SIZE, NAME, MON SUPP, CPL3 */
|
||||
#define CPUID_FIELD_DATA_LEVEL_A \
|
||||
@@ -713,7 +708,6 @@ FIELD( 84, 0, EBX, 0, 32, LEAF84_BRAND_STRING_EBX, NA, FALSE) \
|
||||
FIELD( 84, 0, ECX, 0, 32, LEAF84_BRAND_STRING_ECX, NA, FALSE) \
|
||||
FIELD( 84, 0, EDX, 0, 32, LEAF84_BRAND_STRING_EDX, NA, FALSE)
|
||||
|
||||
|
||||
#define CPUID_8A_EDX_11 \
|
||||
FLAG( 8A, 0, EDX, 11, 1, SVMEDX_RSVD1, NO, FALSE)
|
||||
#define CPUID_8A_EDX_14_31 \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2003-2015,2018 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 2003-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -63,14 +63,6 @@ extern "C" {
|
||||
*/
|
||||
void __cpuid(int regs[4], int eax);
|
||||
#pragma intrinsic(__cpuid)
|
||||
|
||||
/*
|
||||
* __cpuidex has been supported since VS2008
|
||||
*/
|
||||
#if _MSC_VER >= 1500
|
||||
void __cpuidex(int regs[4], int eax, int ecx);
|
||||
#pragma intrinsic(__cpuidex)
|
||||
#endif /* _MSC_VER >= 1500 */
|
||||
#endif /* VM_X86_64 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -255,20 +247,6 @@ __GET_CPUID(int input, CPUIDRegs *regs)
|
||||
|
||||
#ifdef VM_X86_64
|
||||
|
||||
#if _MSC_VER >= 1500
|
||||
|
||||
/*
|
||||
* __cpuidex has been supported since VS2008
|
||||
*/
|
||||
|
||||
static INLINE void
|
||||
__GET_CPUID2(int inputEax, int inputEcx, CPUIDRegs *regs)
|
||||
{
|
||||
__cpuidex((int *)regs, inputEax, inputEcx);
|
||||
}
|
||||
|
||||
#else // _MSC_VER >= 1500
|
||||
|
||||
/*
|
||||
* No inline assembly in Win64. Implemented in bora/lib/misc in
|
||||
* cpuidMasm64.asm.
|
||||
@@ -276,7 +254,6 @@ __GET_CPUID2(int inputEax, int inputEcx, CPUIDRegs *regs)
|
||||
|
||||
extern void
|
||||
__GET_CPUID2(int inputEax, int inputEcx, CPUIDRegs *regs);
|
||||
#endif // _MSC_VER >= 1500
|
||||
|
||||
#else // VM_X86_64
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2018 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
#ifndef _X86MSR_H_
|
||||
#define _X86MSR_H_
|
||||
#include <asm/msr-index.h>
|
||||
#define INCLUDE_ALLOW_USERLEVEL
|
||||
#define INCLUDE_ALLOW_VMX
|
||||
|
||||
@@ -80,7 +79,6 @@ MSRQuery;
|
||||
#define MSR_SMI_COUNT 0x00000034 // Intel Nehalem Family
|
||||
#define MSR_FEATCTL 0x0000003a
|
||||
#define MSR_TSC_ADJUST 0x0000003b
|
||||
#define MSR_SPEC_CTRL 0x00000048
|
||||
#define MSR_BIOS_UPDT_TRIG 0x00000079
|
||||
#define MSR_BIOS_SIGN_ID 0x0000008b
|
||||
#define MSR_PERFCTR0 0x000000c1
|
||||
@@ -108,7 +106,6 @@ MSRQuery;
|
||||
#define MSR_TSC_AUX 0xc0000103
|
||||
#define MSR_BD_TSC_RATIO 0xc0000104
|
||||
|
||||
|
||||
#ifndef MSR_MISC_FEATURES_ENABLES
|
||||
#define MSR_MISC_FEATURES_ENABLES 0x140
|
||||
#endif
|
||||
@@ -305,9 +302,7 @@ typedef enum {
|
||||
#define MSR_K7_HWCR_SSEDIS 0x00008000ULL // Disable SSE bit
|
||||
#define MSR_K7_HWCR_MONMWAITUSEREN 0x00000400ULL // Enable MONITOR/MWAIT CPL>0
|
||||
#define MSR_K7_HWCR_TLBFFDIS 0x00000040ULL // Disable TLB Flush Filter
|
||||
#ifndef MSR_K7_HWCR_SMMLOCK
|
||||
#define MSR_K7_HWCR_SMMLOCK 0x00000001ULL // Lock SMM environment
|
||||
#endif
|
||||
|
||||
#ifndef MSR_K8_SYSCFG
|
||||
#define MSR_K8_SYSCFG 0xc0010010
|
||||
@@ -349,8 +344,6 @@ typedef enum {
|
||||
#define MSR_VM_CR_SVME_DISABLE 0x0000000000000010ULL
|
||||
#define MSR_VM_CR_RESERVED 0xffffffffffffffe0ULL
|
||||
|
||||
#define MSR_AMD_DE_CFG 0xc0011029 // Decode configuration
|
||||
#define MSR_AMD_DE_CFG_BIT1 (1ULL<<1)
|
||||
|
||||
/* Syscall/Sysret related MSRs (x86_64) */
|
||||
#define MSR_STAR 0xc0000081 // Also present on Athlons.
|
||||
|
||||
+29
-22
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2016 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#define EXPORT_SYMTAB
|
||||
|
||||
#include "compat_timer.h"
|
||||
#include <linux/file.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/poll.h>
|
||||
@@ -81,9 +80,6 @@ static Bool LinuxDriverCheckPadding(void);
|
||||
|
||||
struct VMXLinuxState linuxState;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)
|
||||
typedef int vm_fault_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -109,9 +105,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 vm_fault_t LinuxDriverFault(struct vm_fault *fault);
|
||||
static int LinuxDriverFault(struct vm_fault *fault);
|
||||
#elif defined(VMW_NOPAGE_2624)
|
||||
static vm_fault_t LinuxDriverFault(struct vm_area_struct *vma, struct vm_fault *fault);
|
||||
static int LinuxDriverFault(struct vm_area_struct *vma, struct vm_fault *fault);
|
||||
#else
|
||||
static struct page *LinuxDriverNoPage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
@@ -119,7 +115,7 @@ static struct page *LinuxDriverNoPage(struct vm_area_struct *vma,
|
||||
#endif
|
||||
static int LinuxDriverMmap(struct file *filp, struct vm_area_struct *vma);
|
||||
|
||||
static void LinuxDriverPollTimeout(compat_timer_arg_t unused);
|
||||
static void LinuxDriverPollTimeout(unsigned long clientData);
|
||||
static unsigned int LinuxDriverEstimateTSCkHz(void);
|
||||
|
||||
static struct vm_operations_struct vmuser_mops = {
|
||||
@@ -231,7 +227,7 @@ LinuxDriverEstimateTSCkHz(void)
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static void
|
||||
LinuxDriverEstimateTSCkHzDeferred(compat_timer_arg_t unused)
|
||||
LinuxDriverEstimateTSCkHzDeferred(unsigned long data)
|
||||
{
|
||||
LinuxDriverEstimateTSCkHz();
|
||||
}
|
||||
@@ -269,7 +265,9 @@ LinuxDriverInitTSCkHz(void)
|
||||
}
|
||||
|
||||
Vmx86_ReadTSCAndUptime(&tsckHzStartTime);
|
||||
tscTimer.function = LinuxDriverEstimateTSCkHzDeferred;
|
||||
tscTimer.expires = jiffies + 4 * HZ;
|
||||
tscTimer.data = 0;
|
||||
add_timer(&tscTimer);
|
||||
}
|
||||
|
||||
@@ -311,7 +309,9 @@ init_module(void)
|
||||
*/
|
||||
|
||||
init_waitqueue_head(&linuxState.pollQueue);
|
||||
compat_timer_setup(&linuxState.pollTimer, LinuxDriverPollTimeout, 0);
|
||||
init_timer(&linuxState.pollTimer);
|
||||
linuxState.pollTimer.data = 0;
|
||||
linuxState.pollTimer.function = LinuxDriverPollTimeout;
|
||||
|
||||
linuxState.fastClockThread = NULL;
|
||||
linuxState.fastClockFile = NULL;
|
||||
@@ -360,7 +360,7 @@ init_module(void)
|
||||
linuxState.deviceName, linuxState.major, linuxState.minor);
|
||||
|
||||
HostIF_InitUptime();
|
||||
compat_timer_setup(&tscTimer, LinuxDriverEstimateTSCkHzDeferred, 0);
|
||||
init_timer(&tscTimer);
|
||||
LinuxDriverInitTSCkHz();
|
||||
Vmx86_InitIDList();
|
||||
|
||||
@@ -741,12 +741,14 @@ void
|
||||
LinuxDriverWakeUp(Bool selective) // IN:
|
||||
{
|
||||
if (selective && linuxState.pollList != NULL) {
|
||||
struct timeval tv;
|
||||
VmTimeType now;
|
||||
VMLinux *p;
|
||||
VMLinux *next;
|
||||
|
||||
HostIF_PollListLock(1);
|
||||
now = ktime_get_ns() / NSEC_PER_USEC;
|
||||
do_gettimeofday(&tv);
|
||||
now = tv.tv_sec * 1000000ULL + tv.tv_usec;
|
||||
|
||||
for (p = linuxState.pollList; p != NULL; p = next) {
|
||||
next = p->pollForw;
|
||||
@@ -813,10 +815,12 @@ LinuxDriverPoll(struct file *filp, // IN:
|
||||
}
|
||||
} else {
|
||||
if (linuxState.fastClockThread && vmLinux->pollTimeoutPtr != NULL) {
|
||||
u64 now = ktime_get_ns() / NSEC_PER_USEC;
|
||||
struct timeval tv;
|
||||
|
||||
do_gettimeofday(&tv);
|
||||
poll_wait(filp, &vmLinux->pollQueue, wait);
|
||||
vmLinux->pollTime = *vmLinux->pollTimeoutPtr + now;
|
||||
vmLinux->pollTime = *vmLinux->pollTimeoutPtr +
|
||||
tv.tv_sec * 1000000ULL + tv.tv_usec;
|
||||
if (vmLinux->pollBack == NULL) {
|
||||
HostIF_PollListLock(2);
|
||||
if (vmLinux->pollBack == NULL) {
|
||||
@@ -854,7 +858,7 @@ LinuxDriverPoll(struct file *filp, // IN:
|
||||
*/
|
||||
|
||||
static void
|
||||
LinuxDriverPollTimeout(compat_timer_arg_t unused) // IN:
|
||||
LinuxDriverPollTimeout(unsigned long clientData) // IN:
|
||||
{
|
||||
LinuxDriverWakeUp(FALSE);
|
||||
}
|
||||
@@ -880,11 +884,11 @@ LinuxDriverPollTimeout(compat_timer_arg_t unused) // IN:
|
||||
*/
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
||||
static vm_fault_t
|
||||
static int
|
||||
LinuxDriverFault(struct vm_fault *fault) //IN/OUT
|
||||
#elif defined(VMW_NOPAGE_2624)
|
||||
static vm_fault_t LinuxDriverFault(struct vm_area_struct *vma, //IN
|
||||
struct vm_fault *fault) //IN/OUT
|
||||
static int 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
|
||||
@@ -1283,7 +1287,7 @@ LinuxDriverReadTSC(void *data, // OUT: TSC values
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
__always_inline static Bool
|
||||
__attribute__((always_inline)) static Bool
|
||||
LinuxDriverSyncReadTSCs(uint64 *delta) // OUT: TSC max - TSC min
|
||||
{
|
||||
TSCDelta tscDelta;
|
||||
@@ -1354,6 +1358,7 @@ LinuxDriver_Ioctl(struct file *filp, // IN:
|
||||
case IOCTL_VMX86_CREATE_VM:
|
||||
case IOCTL_VMX86_INIT_CROSSGDT:
|
||||
case IOCTL_VMX86_SET_UID:
|
||||
case IOCTL_VMX86_LOOK_UP_MPN:
|
||||
case IOCTL_VMX86_GET_NUM_VMS:
|
||||
case IOCTL_VMX86_GET_TOTAL_MEM_USAGE:
|
||||
case IOCTL_VMX86_SET_HARD_LIMIT:
|
||||
@@ -1363,6 +1368,8 @@ LinuxDriver_Ioctl(struct file *filp, // IN:
|
||||
case IOCTL_VMX86_GET_KHZ_ESTIMATE:
|
||||
case IOCTL_VMX86_GET_ALL_CPUID:
|
||||
case IOCTL_VMX86_GET_ALL_MSRS:
|
||||
case IOCTL_VMX86_READ_PAGE:
|
||||
case IOCTL_VMX86_WRITE_PAGE:
|
||||
case IOCTL_VMX86_SET_POLL_TIMEOUT_PTR:
|
||||
case IOCTL_VMX86_GET_KERNEL_CLOCK_RATE:
|
||||
case IOCTL_VMX86_GET_REFERENCE_CLOCK_HZ:
|
||||
@@ -1523,7 +1530,7 @@ LinuxDriver_Ioctl(struct file *filp, // IN:
|
||||
if (retval) {
|
||||
break;
|
||||
}
|
||||
args.ret.status = Vmx86_LookupUserMPN(vm, args.uAddr, &args.ret.mpn);
|
||||
args.ret.status = HostIF_LookupUserMPN(vm, args.uAddr, &args.ret.mpn);
|
||||
retval = HostIF_CopyToUser((void *)ioarg, &args, sizeof args);
|
||||
break;
|
||||
}
|
||||
@@ -1842,7 +1849,7 @@ LinuxDriver_Ioctl(struct file *filp, // IN:
|
||||
if (retval) {
|
||||
break;
|
||||
}
|
||||
retval = HostIF_ReadPage(vm, req.mpn, req.uAddr, FALSE);
|
||||
retval = HostIF_ReadPage(req.mpn, req.uAddr, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1853,7 +1860,7 @@ LinuxDriver_Ioctl(struct file *filp, // IN:
|
||||
if (retval) {
|
||||
break;
|
||||
}
|
||||
retval = HostIF_WritePage(vm, req.mpn, req.uAddr, FALSE);
|
||||
retval = HostIF_WritePage(req.mpn, req.uAddr, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+241
-288
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2014 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
/* Must come before vmware.h --hpreg */
|
||||
#include "compat_page.h"
|
||||
#include "compat_timer.h"
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/file.h>
|
||||
@@ -69,10 +68,7 @@
|
||||
#endif
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/irq_vectors.h>
|
||||
#include <linux/mc146818rtc.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/kthread.h>
|
||||
@@ -81,19 +77,18 @@
|
||||
#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"
|
||||
#include "vm_asm.h"
|
||||
#include "modulecall.h"
|
||||
#include "driver.h"
|
||||
#include "memtrack.h"
|
||||
#include "phystrack.h"
|
||||
#include "cpuid.h"
|
||||
#include "cpuid_info.h"
|
||||
#include "hostif.h"
|
||||
#include "hostif_priv.h"
|
||||
#include "driver.h"
|
||||
#include "vmhost.h"
|
||||
#include "x86msr.h"
|
||||
#include "apic.h"
|
||||
@@ -103,41 +98,6 @@
|
||||
#include "pgtbl.h"
|
||||
#include "vmmonInt.h"
|
||||
#include "versioned_atomic.h"
|
||||
#include "compat_poll.h"
|
||||
#include "compat_mmap_lock.h"
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
|
||||
# define global_zone_page_state global_page_state
|
||||
#endif
|
||||
|
||||
static unsigned long get_nr_slab_unreclaimable(void)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
|
||||
return global_node_page_state_pages(NR_SLAB_UNRECLAIMABLE_B);
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
|
||||
return global_node_page_state(NR_SLAB_UNRECLAIMABLE);
|
||||
#else
|
||||
return global_page_state(NR_SLAB_UNRECLAIMABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned long get_nr_unevictable(void)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
|
||||
return global_node_page_state(NR_UNEVICTABLE);
|
||||
#else
|
||||
return global_page_state(NR_UNEVICTABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned long get_nr_anon_mapped(void)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
|
||||
return global_node_page_state(NR_ANON_MAPPED);
|
||||
#else
|
||||
return global_page_state(NR_ANON_PAGES);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if we can use high resolution timers.
|
||||
@@ -182,7 +142,13 @@ static DECLARE_TASKLET(timerTasklet, HostIFWakeupClockThread, 0);
|
||||
*/
|
||||
#define LOCKED_PAGE_SLACK 10000
|
||||
|
||||
u64 uptime_base;
|
||||
static struct {
|
||||
Atomic_uint64 uptimeBase;
|
||||
VersionedAtomic version;
|
||||
uint64 monotimeBase;
|
||||
unsigned long jiffiesBase;
|
||||
struct timer_list timer;
|
||||
} uptimeState;
|
||||
|
||||
/*
|
||||
* First Page Locking strategy
|
||||
@@ -241,21 +207,6 @@ u64 uptime_base;
|
||||
uint8 monitorIPIVector;
|
||||
uint8 hvIPIVector;
|
||||
|
||||
static unsigned long compat_totalram_pages(void)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
|
||||
return totalram_pages;
|
||||
#else
|
||||
return totalram_pages();
|
||||
#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
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
@@ -678,15 +629,6 @@ HostIF_FastClockUnlock(int callerID) // IN
|
||||
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
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
@@ -753,29 +695,7 @@ HostIF_PollListUnlock(int callerID) // IN
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -1089,7 +1009,7 @@ HostIF_FreeLockedPages(VMDriver *vm, // IN: VM instance pointer
|
||||
int
|
||||
HostIF_Init(VMDriver *vm) // IN:
|
||||
{
|
||||
vm->memtracker = MemTrack_Init(vm);
|
||||
vm->memtracker = MemTrack_Init();
|
||||
if (vm->memtracker == NULL) {
|
||||
return -1;
|
||||
}
|
||||
@@ -1244,7 +1164,7 @@ HostIFGetUserPages(void *uvAddr, // IN
|
||||
{
|
||||
int retval;
|
||||
|
||||
mmap_read_lock(current->mm);
|
||||
down_read(¤t->mm->mmap_sem);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
|
||||
retval = get_user_pages((unsigned long)uvAddr, numPages, 0, ppages, NULL);
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
|
||||
@@ -1253,7 +1173,7 @@ HostIFGetUserPages(void *uvAddr, // IN
|
||||
retval = get_user_pages(current, current->mm, (unsigned long)uvAddr,
|
||||
numPages, 0, 0, ppages, NULL);
|
||||
#endif
|
||||
mmap_read_unlock(current->mm);
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
|
||||
return retval != numPages;
|
||||
}
|
||||
@@ -1649,7 +1569,14 @@ unsigned int
|
||||
HostIF_EstimateLockedPageLimit(const VMDriver* vm, // IN
|
||||
unsigned int currentlyLockedPages) // IN
|
||||
{
|
||||
unsigned int totalPhysicalPages = compat_totalram_pages();
|
||||
/*
|
||||
* This variable is available and exported to modules,
|
||||
* since at least 2.6.0.
|
||||
*/
|
||||
|
||||
extern unsigned long totalram_pages;
|
||||
|
||||
unsigned int totalPhysicalPages = totalram_pages;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
|
||||
return MemDefaults_CalcMaxLockedPages(totalPhysicalPages);
|
||||
@@ -1667,11 +1594,16 @@ HostIF_EstimateLockedPageLimit(const VMDriver* vm, // IN
|
||||
unsigned int reservedPages = MEMDEFAULTS_MIN_HOST_PAGES;
|
||||
unsigned int hugePages = (vm == NULL) ? 0 :
|
||||
BYTES_2_PAGES(vm->memInfo.hugePageBytes);
|
||||
unsigned int lockedPages = global_zone_page_state(NR_PAGETABLE) +
|
||||
get_nr_slab_unreclaimable() +
|
||||
get_nr_unevictable() +
|
||||
unsigned int lockedPages = global_page_state(NR_PAGETABLE) +
|
||||
global_page_state(NR_SLAB_UNRECLAIMABLE) +
|
||||
global_page_state(NR_UNEVICTABLE) +
|
||||
hugePages + reservedPages;
|
||||
unsigned int anonPages = get_nr_anon_mapped();
|
||||
unsigned int anonPages =
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
|
||||
global_page_state(NR_ANON_MAPPED);
|
||||
#else
|
||||
global_page_state(NR_ANON_PAGES);
|
||||
#endif
|
||||
unsigned int swapPages = BYTES_2_PAGES(linuxState.swapSize);
|
||||
|
||||
if (anonPages > swapPages) {
|
||||
@@ -1729,6 +1661,146 @@ HostIF_WaitForFreePages(unsigned int timeoutMs) // IN:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* HostIFReadUptimeWork --
|
||||
*
|
||||
* Reads the current uptime. The uptime is based on getimeofday,
|
||||
* which provides the needed high resolution. However, we don't
|
||||
* want uptime to be warped by e.g. calls to settimeofday. So, we
|
||||
* use a jiffies based monotonic clock to sanity check the uptime.
|
||||
* If the uptime is more than one second from the monotonic time,
|
||||
* we assume that the time of day has been set, and recalculate the
|
||||
* uptime base to get uptime back on track with monotonic time. On
|
||||
* the other hand, we do expect jiffies based monotonic time and
|
||||
* timeofday to have small drift (due to NTP rate correction, etc).
|
||||
* We handle this by rebasing the jiffies based monotonic clock
|
||||
* every second (see HostIFUptimeResyncMono).
|
||||
*
|
||||
* Results:
|
||||
* The uptime, in units of UPTIME_FREQ. Also returns the jiffies
|
||||
* value that was used in the monotonic time calculation.
|
||||
*
|
||||
* Side effects:
|
||||
* May reset the uptime base in the case gettimeofday warp was
|
||||
* detected.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/* Assert that HostIF_InitUptime has been called. */
|
||||
ASSERT(uptimeState.timer.function);
|
||||
|
||||
retry:
|
||||
do {
|
||||
version = VersionedAtomic_BeginTryRead(&uptimeState.version);
|
||||
jifs = jiffies;
|
||||
jifBase = uptimeState.jiffiesBase;
|
||||
monoBase = uptimeState.monotimeBase;
|
||||
} while (!VersionedAtomic_EndTryRead(&uptimeState.version, version));
|
||||
|
||||
do_gettimeofday(&tv);
|
||||
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;
|
||||
|
||||
/*
|
||||
* Use the jiffies based monotonic time to sanity check gettimeofday.
|
||||
* If they differ by more than one second, assume the time of day has
|
||||
* been warped, and use the jiffies time to undo (most of) the warp.
|
||||
*/
|
||||
|
||||
diff = uptime - monotime;
|
||||
if (UNLIKELY(diff < -UPTIME_FREQ || diff > UPTIME_FREQ)) {
|
||||
/* Compute a new uptimeBase to get uptime back on track. */
|
||||
uint64 newUpBase = monotime - (uptime - upBase);
|
||||
|
||||
attempts++;
|
||||
if (!Atomic_CMPXCHG64(&uptimeState.uptimeBase, &upBase, &newUpBase) &&
|
||||
attempts < 5) {
|
||||
/* Another thread updated uptimeBase. Recalculate uptime. */
|
||||
goto retry;
|
||||
}
|
||||
uptime = monotime;
|
||||
|
||||
Log("%s: detected settimeofday: fixed uptimeBase old %"FMT64"u "
|
||||
"new %"FMT64"u attempts %u\n", __func__,
|
||||
upBase, newUpBase, attempts);
|
||||
}
|
||||
*j = jifs;
|
||||
|
||||
return uptime;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* HostIFUptimeResyncMono --
|
||||
*
|
||||
* Timer that fires ever second to resynchronize the jiffies based
|
||||
* monotonic time with the uptime.
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side effects:
|
||||
* Resets the monotonic time bases so that jiffies based monotonic
|
||||
* time does not drift from gettimeofday over the long term.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
HostIFUptimeResyncMono(unsigned long data) // IN: ignored
|
||||
{
|
||||
unsigned long jifs;
|
||||
uintptr_t flags;
|
||||
|
||||
/*
|
||||
* Read the uptime and the corresponding jiffies value. This will
|
||||
* also correct the uptime (which is based on time of day) if needed
|
||||
* before we rebase monotonic time (which is based on jiffies).
|
||||
*/
|
||||
|
||||
uint64 uptime = HostIFReadUptimeWork(&jifs);
|
||||
|
||||
/*
|
||||
* Every second, recalculate monoBase and jiffiesBase to squash small
|
||||
* drift between gettimeofday and jiffies. Also, this prevents
|
||||
* (jiffies - jiffiesBase) wrap on 32-bits.
|
||||
*/
|
||||
|
||||
SAVE_FLAGS(flags);
|
||||
CLEAR_INTERRUPTS();
|
||||
VersionedAtomic_BeginWrite(&uptimeState.version);
|
||||
|
||||
uptimeState.monotimeBase = uptime;
|
||||
uptimeState.jiffiesBase = jifs;
|
||||
|
||||
VersionedAtomic_EndWrite(&uptimeState.version);
|
||||
RESTORE_FLAGS(flags);
|
||||
|
||||
/* Reschedule this timer to expire in one second. */
|
||||
mod_timer(&uptimeState.timer, jifs + HZ);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -1740,7 +1812,8 @@ HostIF_WaitForFreePages(unsigned int timeoutMs) // IN:
|
||||
* None
|
||||
*
|
||||
* Side effects:
|
||||
* Sets the initial value for the uptime base.
|
||||
* Sets the initial values for the uptime state, and schedules
|
||||
* the uptime timer.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1748,7 +1821,17 @@ HostIF_WaitForFreePages(unsigned int timeoutMs) // IN:
|
||||
void
|
||||
HostIF_InitUptime(void)
|
||||
{
|
||||
uptime_base = ktime_get_ns();
|
||||
struct timeval tv;
|
||||
|
||||
uptimeState.jiffiesBase = jiffies;
|
||||
do_gettimeofday(&tv);
|
||||
Atomic_Write64(&uptimeState.uptimeBase,
|
||||
-(tv.tv_usec * (UPTIME_FREQ / 1000000) +
|
||||
tv.tv_sec * UPTIME_FREQ));
|
||||
|
||||
init_timer(&uptimeState.timer);
|
||||
uptimeState.timer.function = HostIFUptimeResyncMono;
|
||||
mod_timer(&uptimeState.timer, jiffies + HZ);
|
||||
}
|
||||
|
||||
|
||||
@@ -1757,13 +1840,13 @@ HostIF_InitUptime(void)
|
||||
*
|
||||
* HostIF_CleanupUptime --
|
||||
*
|
||||
* No-op, left for backward compatibility.
|
||||
* Cleanup uptime state, called at module unloading time.
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
* Deschedule the uptime timer.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1771,6 +1854,7 @@ HostIF_InitUptime(void)
|
||||
void
|
||||
HostIF_CleanupUptime(void)
|
||||
{
|
||||
del_timer_sync(&uptimeState.timer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1794,10 +1878,9 @@ HostIF_CleanupUptime(void)
|
||||
uint64
|
||||
HostIF_ReadUptime(void)
|
||||
{
|
||||
u64 tm;
|
||||
unsigned long jifs;
|
||||
|
||||
tm = ktime_get_ns();
|
||||
return (tm - uptime_base) / (NSEC_PER_SEC / UPTIME_FREQ);
|
||||
return HostIFReadUptimeWork(&jifs);
|
||||
}
|
||||
|
||||
|
||||
@@ -1918,15 +2001,15 @@ HostIF_MapCrossPage(VMDriver *vm, // IN
|
||||
return NULL;
|
||||
}
|
||||
vPgAddr = (VA) MapCrossPage(page);
|
||||
HostIF_VMLock(vm, 27);
|
||||
HostIF_GlobalLock(16);
|
||||
if (vm->vmhost->crosspagePagesCount >= MAX_INITBLOCK_CPUS) {
|
||||
HostIF_VMUnlock(vm, 27);
|
||||
HostIF_GlobalUnlock(16);
|
||||
UnmapCrossPage(page, (void*)vPgAddr);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
vm->vmhost->crosspagePages[vm->vmhost->crosspagePagesCount++] = page;
|
||||
HostIF_VMUnlock(vm, 27);
|
||||
HostIF_GlobalUnlock(16);
|
||||
|
||||
ret = vPgAddr | (((VA)p) & (PAGE_SIZE - 1));
|
||||
|
||||
@@ -2144,27 +2227,6 @@ HostIF_VMLockIsHeld(VMDriver *vm) // IN
|
||||
|
||||
#if defined(CONFIG_SMP) || defined(CONFIG_X86_UP_IOAPIC) || \
|
||||
defined(CONFIG_X86_UP_APIC) || defined(CONFIG_X86_LOCAL_APIC)
|
||||
|
||||
#if COMPAT_LINUX_VERSION_CHECK_LT(5, 8, 0)
|
||||
static long compat_copy_from_kernel_nofault(void *dst, VA src, size_t size)
|
||||
{
|
||||
mm_segment_t old_fs;
|
||||
long ret;
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
ret = HostIF_CopyFromUser(dst, (const void *)src, size);
|
||||
set_fs(old_fs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static long compat_copy_from_kernel_nofault(void *dst, VA src, size_t size)
|
||||
{
|
||||
return copy_from_kernel_nofault(dst, (const void *)src, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -2184,11 +2246,15 @@ static long compat_copy_from_kernel_nofault(void *dst, VA src, size_t size)
|
||||
static Bool
|
||||
isVAReadable(VA r) // IN:
|
||||
{
|
||||
mm_segment_t old_fs;
|
||||
uint32 dummy;
|
||||
long ret;
|
||||
|
||||
int ret;
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
r = APICR_TO_ADDR(r, APICR_VERSION);
|
||||
ret = compat_copy_from_kernel_nofault(&dummy, r, sizeof(dummy));
|
||||
ret = HostIF_CopyFromUser(&dummy, (void*)r, sizeof(dummy));
|
||||
set_fs(old_fs);
|
||||
|
||||
return ret == 0;
|
||||
}
|
||||
@@ -2218,7 +2284,7 @@ SetVMAPICAddr(VMDriver *vm, // IN/OUT: driver state
|
||||
volatile void *hostapic;
|
||||
|
||||
ASSERT_ON_COMPILE(APICR_SIZE <= PAGE_SIZE);
|
||||
hostapic = (volatile void *) ioremap(ma, PAGE_SIZE);
|
||||
hostapic = (volatile void *) ioremap_nocache(ma, PAGE_SIZE);
|
||||
if (hostapic) {
|
||||
if ((APIC_VERSIONREG(hostapic) & 0xF0) == 0x10) {
|
||||
vm->hostAPIC.base = (volatile uint32 (*)[4]) hostapic;
|
||||
@@ -2374,41 +2440,44 @@ HostIF_SemaphoreWait(VMDriver *vm, // IN:
|
||||
uint64 *args) // IN:
|
||||
{
|
||||
struct file *file;
|
||||
mm_segment_t old_fs;
|
||||
int res;
|
||||
int waitFD = args[0];
|
||||
int timeoutms = args[2];
|
||||
uint64 value;
|
||||
struct poll_wqueues table;
|
||||
unsigned int mask;
|
||||
|
||||
file = vmware_fget(waitFD);
|
||||
if (file == NULL) {
|
||||
return MX_WAITERROR;
|
||||
}
|
||||
|
||||
poll_initwait(&table);
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
mask = compat_vfs_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;
|
||||
old_fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
|
||||
{
|
||||
struct poll_wqueues table;
|
||||
unsigned int mask;
|
||||
|
||||
poll_initwait(&table);
|
||||
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;
|
||||
poll_freewait(&table);
|
||||
}
|
||||
current->state = TASK_RUNNING;
|
||||
poll_freewait(&table);
|
||||
|
||||
/*
|
||||
* Userland only writes in multiples of sizeof(uint64). This will allow
|
||||
* 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).
|
||||
*
|
||||
* Upstream Linux changed the function parameter types/ordering in 4.14.0.
|
||||
*/
|
||||
#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
|
||||
|
||||
res = file->f_op->read(file, (char *) &value, sizeof value, &file->f_pos);
|
||||
|
||||
if (res == sizeof value) {
|
||||
res = MX_WAITNORMAL;
|
||||
} else {
|
||||
@@ -2417,6 +2486,7 @@ HostIF_SemaphoreWait(VMDriver *vm, // IN:
|
||||
}
|
||||
}
|
||||
|
||||
set_fs(old_fs);
|
||||
fput(file);
|
||||
|
||||
/*
|
||||
@@ -2499,8 +2569,8 @@ HostIF_SemaphoreForceWakeup(VMDriver *vm, // IN:
|
||||
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
|
||||
@@ -2510,34 +2580,22 @@ HostIF_SemaphoreSignal(uint64 *args) // IN:
|
||||
return MX_WAITERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)) {
|
||||
eventfd_signal(eventfd, 1);
|
||||
fput(file);
|
||||
return MX_WAITNORMAL;
|
||||
}
|
||||
old_fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Upstream Linux changed the function parameter types/ordering in 4.14.0.
|
||||
*/
|
||||
#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
|
||||
|
||||
res = file->f_op->write(file, (char *) &value, sizeof value, &file->f_pos);
|
||||
|
||||
if (res == sizeof value) {
|
||||
res = MX_WAITNORMAL;
|
||||
}
|
||||
|
||||
set_fs(old_fs);
|
||||
fput(file);
|
||||
|
||||
/*
|
||||
@@ -2759,75 +2817,13 @@ HostIF_CallOnEachCPU(void (*func)(void*), // IN: function to call
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* HostIFCheckTrackedMPN --
|
||||
*
|
||||
* Check if a given MPN is tracked for the specified VM.
|
||||
*
|
||||
* Result:
|
||||
* TRUE if the MPN is tracked in one of the trackers for the specified VM,
|
||||
* FALSE otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Bool
|
||||
HostIFCheckTrackedMPN(VMDriver *vm, // IN: The VM instance
|
||||
MPN mpn) // IN: The MPN
|
||||
{
|
||||
VMHost * const vmh = vm->vmhost;
|
||||
|
||||
if (vmh == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HostIF_VMLock(vm, 32); // Debug version of PhysTrack wants VM's lock.
|
||||
if (vmh->lockedPages) {
|
||||
if (PhysTrack_Test(vmh->lockedPages, mpn)) {
|
||||
HostIF_VMUnlock(vm, 32);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (vmh->AWEPages) {
|
||||
if (PhysTrack_Test(vmh->AWEPages, mpn)) {
|
||||
HostIF_VMUnlock(vm, 32);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (vm->memtracker) {
|
||||
if (MemTrack_LookupMPN(vm->memtracker, mpn) != NULL) {
|
||||
HostIF_VMUnlock(vm, 32);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
HostIF_VMUnlock(vm, 32);
|
||||
|
||||
if (vmx86_debug) {
|
||||
/*
|
||||
* The monitor may have old KSeg mappings to pages which it no longer
|
||||
* owns. Minimize customer noise by only logging this for developers.
|
||||
*/
|
||||
Log("%s: MPN %" FMT64 "x not owned by this VM\n", __FUNCTION__, mpn);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* HostIF_ReadPage --
|
||||
*
|
||||
* Reads one page of data from a machine page and returns it in the
|
||||
* specified kernel or user buffer. The machine page must be owned by
|
||||
* the specified VM.
|
||||
* puts the content of a machine page into a kernel or user mode
|
||||
* buffer.
|
||||
*
|
||||
* Results:
|
||||
* 0 on success
|
||||
@@ -2840,8 +2836,7 @@ HostIFCheckTrackedMPN(VMDriver *vm, // IN: The VM instance
|
||||
*/
|
||||
|
||||
int
|
||||
HostIF_ReadPage(VMDriver *vm, // IN: The VM instance
|
||||
MPN mpn, // MPN of the page
|
||||
HostIF_ReadPage(MPN mpn, // MPN of the page
|
||||
VA64 addr, // buffer for data
|
||||
Bool kernelBuffer) // is the buffer in kernel space?
|
||||
{
|
||||
@@ -2853,9 +2848,6 @@ HostIF_ReadPage(VMDriver *vm, // IN: The VM instance
|
||||
if (mpn == INVALID_MPN) {
|
||||
return -EFAULT;
|
||||
}
|
||||
if (HostIFCheckTrackedMPN(vm, mpn) == FALSE) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
page = pfn_to_page(mpn);
|
||||
ptr = kmap(page);
|
||||
@@ -2879,8 +2871,8 @@ HostIF_ReadPage(VMDriver *vm, // IN: The VM instance
|
||||
*
|
||||
* HostIF_WritePage --
|
||||
*
|
||||
* Writes one page of data from a kernel or user buffer onto the specified
|
||||
* machine page. The machine page must be owned by the specified VM.
|
||||
* Put the content of a kernel or user mode buffer into a machine
|
||||
* page.
|
||||
*
|
||||
* Results:
|
||||
* 0 on success
|
||||
@@ -2893,9 +2885,9 @@ HostIF_ReadPage(VMDriver *vm, // IN: The VM instance
|
||||
*/
|
||||
|
||||
int
|
||||
HostIFWritePageWork(MPN mpn, // MPN of the page
|
||||
VA64 addr, // data to write to the page
|
||||
Bool kernelBuffer) // is the buffer in kernel space?
|
||||
HostIF_WritePage(MPN mpn, // MPN of the page
|
||||
VA64 addr, // data to write to the page
|
||||
Bool kernelBuffer) // is the buffer in kernel space?
|
||||
{
|
||||
void const *buf = VA64ToPtr(addr);
|
||||
int ret = 0;
|
||||
@@ -2922,45 +2914,6 @@ HostIFWritePageWork(MPN mpn, // MPN of the page
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
HostIF_WritePage(VMDriver *vm, // IN: The VM instance
|
||||
MPN mpn, // MPN of the page
|
||||
VA64 addr, // data to write to the page
|
||||
Bool kernelBuffer) // is the buffer in kernel space?
|
||||
{
|
||||
if (HostIFCheckTrackedMPN(vm, mpn) == FALSE) {
|
||||
return -EFAULT;
|
||||
}
|
||||
return HostIFWritePageWork(mpn, addr, kernelBuffer);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* HostIF_WriteMachinePage --
|
||||
*
|
||||
* Puts the content of a machine page into a kernel or user mode
|
||||
* buffer. This should only be used for host-global pages, not any
|
||||
* VM-owned pages.
|
||||
*
|
||||
* Results:
|
||||
* On success: 0
|
||||
* On failure: a negative error code
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
HostIF_WriteMachinePage(MPN mpn, // IN: MPN of the page
|
||||
VA64 addr) // IN: data to write to the page
|
||||
{
|
||||
return HostIFWritePageWork(mpn, addr, TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -3267,11 +3220,7 @@ HostIFStartTimer(Bool rateChanged, //IN: Did rate change?
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
|
||||
res = kernel_read(filp, pos, (char *)&buf, sizeof(buf));
|
||||
#else
|
||||
res = kernel_read(filp, &buf, sizeof(buf), &pos);
|
||||
#endif
|
||||
res = filp->f_op->read(filp, (void *) &buf, sizeof(buf), &pos);
|
||||
if (res <= 0) {
|
||||
if (res != -ERESTARTSYS) {
|
||||
Log("/dev/rtc read failed: %d\n", res);
|
||||
@@ -3310,9 +3259,12 @@ 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);
|
||||
|
||||
@@ -3346,6 +3298,7 @@ HostIFFastClockThread(void *data) // IN:
|
||||
|
||||
out:
|
||||
LinuxDriverWakeUp(TRUE);
|
||||
set_fs(oldFS);
|
||||
|
||||
/*
|
||||
* Do not exit thread until we are told to do so.
|
||||
@@ -3466,7 +3419,7 @@ HostIF_SetFastClockRate(unsigned int rate) // IN: Frequency in Hz.
|
||||
}
|
||||
} else {
|
||||
if (linuxState.fastClockThread) {
|
||||
send_sig(SIGKILL, linuxState.fastClockThread, 1);
|
||||
force_sig(SIGKILL, linuxState.fastClockThread);
|
||||
kthread_stop(linuxState.fastClockThread);
|
||||
close_rtc(linuxState.fastClockFile, current->files);
|
||||
|
||||
@@ -3514,7 +3467,7 @@ HostIF_MapUserMem(VA addr, // IN: User memory virtual address
|
||||
|
||||
ASSERT(handle);
|
||||
|
||||
if (!write_access_ok(p, size)) {
|
||||
if (!access_ok(VERIFY_WRITE, p, size)) {
|
||||
printk(KERN_ERR "%s: Couldn't verify write to uva 0x%p with size %"
|
||||
FMTSZ"u\n", __func__, p, size);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -205,13 +205,11 @@ skipTaskSwitch:;
|
||||
uint32 nPages = (uint32)crosspage->args[1];
|
||||
VA64 uAddr = (VA64)VPN_2_VA(vpn);
|
||||
ASSERT(nPages <= MODULECALL_NUM_ARGS);
|
||||
HostIF_VMLock(vm, 38);
|
||||
for (i = 0; i < nPages; i++) {
|
||||
MPN mpn;
|
||||
HostIF_LookupUserMPN(vm, uAddr + i * PAGE_SIZE, &mpn);
|
||||
crosspage->args[i] = mpn;
|
||||
}
|
||||
HostIF_VMUnlock(vm, 38);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ prebuild:: ;
|
||||
postbuild:: ;
|
||||
|
||||
$(DRIVER_KO): prebuild
|
||||
$(MAKE) -C $(BUILD_DIR) M=$$PWD SRCROOT=$$PWD/$(SRCROOT) \
|
||||
$(MAKE) -C $(BUILD_DIR) SUBDIRS=$$PWD SRCROOT=$$PWD/$(SRCROOT) \
|
||||
MODULEBUILDDIR=$(MODULEBUILDDIR) modules
|
||||
$(MAKE) -C $$PWD SRCROOT=$$PWD/$(SRCROOT) \
|
||||
MODULEBUILDDIR=$(MODULEBUILDDIR) postbuild
|
||||
|
||||
@@ -35,6 +35,6 @@ $(DRIVER)-y := driver.o hub.o userif.o netif.o bridge.o procfs.o smac_compat.o \
|
||||
####
|
||||
|
||||
clean:
|
||||
rm -rf $(DRIVER).o $(DRIVER).mod.o $(DRIVER).mod.c $(DRIVER).ko .cache.mk \
|
||||
rm -rf $(DRIVER).o $(DRIVER).mod.o $(DRIVER).mod.c $(DRIVER).ko \
|
||||
.tmp_versions Module.symvers Modules.symvers Module.markers \
|
||||
modules.order $($(DRIVER)-y) .*.cmd .*.o.flags
|
||||
+13
-17
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2013, 2017 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2013 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -65,7 +65,7 @@
|
||||
#endif
|
||||
|
||||
#if LOGLEVEL >= 4
|
||||
static u64 vnetTime;
|
||||
static struct timeval vnetTime;
|
||||
#endif
|
||||
|
||||
typedef struct VNetBridge VNetBridge;
|
||||
@@ -636,7 +636,7 @@ VNetBridgeReceiveFromVNet(VNetJack *this, // IN: jack
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
clone = skb_get(clone);
|
||||
atomic_inc(&clone->users);
|
||||
|
||||
clone->dev = dev;
|
||||
clone->protocol = eth_type_trans(clone, dev);
|
||||
@@ -696,7 +696,7 @@ VNetBridgeReceiveFromVNet(VNetJack *this, // IN: jack
|
||||
|
||||
netif_rx_ni(clone);
|
||||
# if LOGLEVEL >= 4
|
||||
vnetTime = ktime_get_ns();
|
||||
do_gettimeofday(&vnetTime);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
@@ -1104,7 +1104,7 @@ VNetBridgeNotifyLogBridgeUpError(int errno, // IN: the error number
|
||||
case -ENODEV:
|
||||
LOG(0, (KERN_WARNING "bridge-%s: interface %s not found or not "
|
||||
"up\n", bridgeName, devName));
|
||||
break;
|
||||
break;
|
||||
case -EINVAL:
|
||||
LOG(0, (KERN_WARNING "bridge-%s: interface %s is not a valid "
|
||||
"Ethernet interface\n", bridgeName, devName));
|
||||
@@ -1143,16 +1143,11 @@ VNetBridgeNotifyLogBridgeUpError(int errno, // IN: the error number
|
||||
static int
|
||||
VNetBridgeNotify(struct notifier_block *this, // IN: callback data (bridge)
|
||||
u_long msg, // IN: type of event
|
||||
void *data) // IN: net_device or notifier info
|
||||
void *data) // IN: device pertaining to event
|
||||
{
|
||||
VNetBridge *bridge = list_entry(this, VNetBridge, notifier);
|
||||
struct net_device *dev;
|
||||
struct net_device *dev = (struct net_device *) data;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
|
||||
dev = netdev_notifier_info_to_dev(data);
|
||||
#else
|
||||
dev = (struct net_device *)data;
|
||||
#endif
|
||||
switch (msg) {
|
||||
case NETDEV_UNREGISTER:
|
||||
LOG(2, (KERN_DEBUG "bridge-%s: interface %s is unregistering\n",
|
||||
@@ -1184,7 +1179,7 @@ VNetBridgeNotify(struct notifier_block *this, // IN: callback data (bridge)
|
||||
|
||||
LOG(1, (KERN_DEBUG "bridge-%s: enabling the bridge on dev up\n",
|
||||
bridge->name));
|
||||
errno = VNetBridgeUp(bridge, FALSE);
|
||||
errno = VNetBridgeUp(bridge, FALSE);
|
||||
if (errno != 0) {
|
||||
VNetBridgeNotifyLogBridgeUpError(errno, bridge->name, dev->name);
|
||||
}
|
||||
@@ -1661,11 +1656,12 @@ VNetBridgeReceiveFromDev(struct sk_buff *skb, // IN: packet to receive
|
||||
|
||||
# if LOGLEVEL >= 4
|
||||
{
|
||||
u64 now;
|
||||
|
||||
now = ktime_get_ns();
|
||||
struct timeval now;
|
||||
do_gettimeofday(&now);
|
||||
LOG(3, (KERN_DEBUG "bridge-%s: time %d\n",
|
||||
bridge->name, (int)((now - vnetTime) / NSEC_PER_USEC)));
|
||||
bridge->name,
|
||||
(int)((now.tv_sec * 1000000 + now.tv_usec)
|
||||
- (vnetTime.tv_sec * 1000000 + vnetTime.tv_usec))));
|
||||
}
|
||||
# endif
|
||||
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
#ifndef __COMPAT_MMAP_LOCK_H__
|
||||
#define __COMPAT_MMAP_LOCK_H__
|
||||
|
||||
#include <linux/mm.h>
|
||||
|
||||
/*
|
||||
* In 5.8-rc1, mmap locking was reworked to use wrappers around mmap_sem
|
||||
* (which was also renamed to mmap_lock). All code is now supposed to use
|
||||
* these wrappers as the internal implementation of the lock may change in
|
||||
* the future.
|
||||
*
|
||||
* Check also _LINUX_MMAP_LOCK_H to handle possible backports to distribution
|
||||
* pre-5.8 kernel. This macro is defined in <linux/mmap_lock.h> which is also
|
||||
* included in <linux/mm.h> since the commit introducing the wrappers so that
|
||||
* we should have it defined in any kernel providing the new API.
|
||||
*/
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) || defined(_LINUX_MMAP_LOCK_H)
|
||||
#include <linux/mmap_lock.h>
|
||||
#else
|
||||
|
||||
static inline void mmap_read_lock(struct mm_struct *mm)
|
||||
{
|
||||
down_read(&mm->mmap_sem);
|
||||
}
|
||||
|
||||
static inline void mmap_read_unlock(struct mm_struct *mm)
|
||||
{
|
||||
up_read(&mm->mmap_sem);
|
||||
}
|
||||
|
||||
#endif /* 5.8.0 */
|
||||
|
||||
#endif /* __COMPAT_MMAP_LOCK_H__ */
|
||||
@@ -337,8 +337,7 @@ typedef netdev_features_t compat_netdev_features_t;
|
||||
typedef u32 compat_netdev_features_t;
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) || \
|
||||
(defined(RHEL_RELEASE_CODE) && RHEL_RELEASE_CODE >= 0x0704)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
|
||||
#define compat_netif_trans_update(d) netif_trans_update(d)
|
||||
#else
|
||||
#define compat_netif_trans_update(d) do { (d)->trans_start = jiffies; } while (0)
|
||||
|
||||
@@ -161,14 +161,6 @@ VNetProcOpen(struct inode *inode, // IN:
|
||||
}
|
||||
|
||||
/* Our procfs callbacks. We only need to specialize open. */
|
||||
#ifdef DEFINE_PROC_SHOW_ATTRIBUTE
|
||||
static const struct proc_ops fops = {
|
||||
.proc_open = VNetProcOpen,
|
||||
.proc_read = seq_read,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
};
|
||||
#else
|
||||
static struct file_operations fops = {
|
||||
.open = VNetProcOpen,
|
||||
.read = seq_read,
|
||||
@@ -176,7 +168,6 @@ static struct file_operations fops = {
|
||||
.release = single_release,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
||||
+21
-63
@@ -47,7 +47,6 @@
|
||||
|
||||
#include "vnetInt.h"
|
||||
#include "compat_skbuff.h"
|
||||
#include "compat_mmap_lock.h"
|
||||
#include "vmnetInt.h"
|
||||
#include "vm_atomic.h"
|
||||
#include "vm_assert.h"
|
||||
@@ -85,55 +84,11 @@ static int VNetUserIfSetUplinkState(VNetPort *port, uint8 linkUp);
|
||||
extern unsigned int vnet_max_qlen;
|
||||
|
||||
#if COMPAT_LINUX_VERSION_CHECK_LT(3, 2, 0)
|
||||
# define compat_kmap_frag(frag) kmap((frag)->page)
|
||||
# define compat_kunmap_frag(page) kunmap((frag)->page)
|
||||
# define compat_kmap(page) kmap(page)
|
||||
# define compat_kunmap(page) kunmap(page)
|
||||
#else
|
||||
# define compat_kmap_frag(frag) kmap(skb_frag_page(frag))
|
||||
# define compat_kunmap_frag(frag) kunmap(skb_frag_page(frag))
|
||||
#endif
|
||||
|
||||
static unsigned int compat_skb_frag_size(const skb_frag_t *frag)
|
||||
{
|
||||
#if COMPAT_LINUX_VERSION_CHECK_LT(3, 2, 0)
|
||||
return frag->size;
|
||||
#else
|
||||
return skb_frag_size(frag);
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned int compat_skb_frag_off(const skb_frag_t *frag)
|
||||
{
|
||||
#if COMPAT_LINUX_VERSION_CHECK_LT(5, 4, 0) && \
|
||||
!(defined(CONFIG_SUSE_VERSION) && CONFIG_SUSE_VERSION == 15 && \
|
||||
defined(CONFIG_SUSE_PATCHLEVEL) && CONFIG_SUSE_PATCHLEVEL >= 2)
|
||||
return frag->page_offset;
|
||||
#else
|
||||
return skb_frag_off(frag);
|
||||
#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
|
||||
|
||||
#if COMPAT_LINUX_VERSION_CHECK_LT(5, 10, 0)
|
||||
static inline
|
||||
__wsum compat_csum_and_copy_to_user(const void *src, void __user *dst, int len)
|
||||
{
|
||||
int err;
|
||||
__wsum ret;
|
||||
|
||||
ret = csum_and_copy_to_user(src, dst, len, 0, &err);
|
||||
return err ? 0 : ret;
|
||||
}
|
||||
#else
|
||||
static inline
|
||||
__wsum compat_csum_and_copy_to_user(const void *src, void __user *dst, int len)
|
||||
{
|
||||
return csum_and_copy_to_user(src, dst, len);
|
||||
}
|
||||
# define compat_kmap(page) kmap((page).p)
|
||||
# define compat_kunmap(page) kunmap((page).p)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -160,7 +115,7 @@ UserifLockPage(VA addr) // IN
|
||||
struct page *page = NULL;
|
||||
int retval;
|
||||
|
||||
mmap_read_lock(current->mm);
|
||||
down_read(¤t->mm->mmap_sem);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
|
||||
retval = get_user_pages(addr, 1, FOLL_WRITE, &page, NULL);
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
|
||||
@@ -169,7 +124,7 @@ UserifLockPage(VA addr) // IN
|
||||
retval = get_user_pages(current, current->mm, addr,
|
||||
1, 1, 0, &page, NULL);
|
||||
#endif
|
||||
mmap_read_unlock(current->mm);
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
|
||||
if (retval != 1) {
|
||||
return NULL;
|
||||
@@ -202,7 +157,7 @@ VNetUserIfMapPtr(VA uAddr, // IN: pointer to user memory
|
||||
struct page **p, // OUT: locked page
|
||||
void **ptr) // OUT: kernel mapped pointer
|
||||
{
|
||||
if (!write_access_ok((void *)uAddr, size) ||
|
||||
if (!access_ok(VERIFY_WRITE, (void *)uAddr, size) ||
|
||||
(((uAddr + size - 1) & ~(PAGE_SIZE - 1)) !=
|
||||
(uAddr & ~(PAGE_SIZE - 1)))) {
|
||||
return -EINVAL;
|
||||
@@ -617,6 +572,7 @@ VNetCsumCopyDatagram(const struct sk_buff *skb, // IN: skb to copy
|
||||
char *buf) // OUT: where to copy data
|
||||
{
|
||||
unsigned int csum;
|
||||
int err = 0;
|
||||
int len = skb_headlen(skb) - offset;
|
||||
char *curr = buf;
|
||||
const skb_frag_t *frag;
|
||||
@@ -629,27 +585,29 @@ VNetCsumCopyDatagram(const struct sk_buff *skb, // IN: skb to copy
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
csum = compat_csum_and_copy_to_user(skb->data + offset, curr, len);
|
||||
if (!csum)
|
||||
return -EFAULT;
|
||||
csum = csum_and_copy_to_user(skb->data + offset, curr, len, 0, &err);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
curr += len;
|
||||
|
||||
for (frag = skb_shinfo(skb)->frags;
|
||||
frag != skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags;
|
||||
frag++) {
|
||||
if (compat_skb_frag_size(frag) > 0) {
|
||||
if (frag->size > 0) {
|
||||
unsigned int tmpCsum;
|
||||
const void *vaddr;
|
||||
|
||||
vaddr = compat_kmap_frag(frag);
|
||||
tmpCsum = compat_csum_and_copy_to_user(vaddr + compat_skb_frag_off(frag),
|
||||
curr, compat_skb_frag_size(frag));
|
||||
compat_kunmap_frag(frag);
|
||||
vaddr = compat_kmap(frag->page);
|
||||
tmpCsum = csum_and_copy_to_user(vaddr + frag->page_offset,
|
||||
curr, frag->size, 0, &err);
|
||||
compat_kunmap(frag->page);
|
||||
|
||||
if (!tmpCsum)
|
||||
return -EFAULT;
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
csum = csum_block_add(csum, tmpCsum, curr - buf);
|
||||
curr += compat_skb_frag_size(frag);
|
||||
curr += frag->size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998, 2017 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -77,7 +77,7 @@
|
||||
|
||||
|
||||
extern struct proto vmnet_proto;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) || defined(sk_net_refcnt)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
|
||||
# define compat_sk_alloc(_bri, _pri) sk_alloc(&init_net, \
|
||||
PF_NETLINK, _pri, &vmnet_proto, 1)
|
||||
#elif defined(VMW_NETDEV_HAS_NET)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2002-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation version 2 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* vmware_pack_begin.h --
|
||||
*
|
||||
* Begin of structure packing. See vmware_pack_init.h for details.
|
||||
*
|
||||
* Note that we do not use the following construct in this include file,
|
||||
* because we want to emit the code every time the file is included --hpreg
|
||||
*
|
||||
* #ifndef foo
|
||||
* # define foo
|
||||
* ...
|
||||
* #endif
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "vmware_pack_init.h"
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma pack(push, 1)
|
||||
#elif __GNUC__
|
||||
#else
|
||||
# error Compiler packing...
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2002-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation version 2 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
/*
|
||||
* vmware_pack_end.h --
|
||||
*
|
||||
* End of structure packing. See vmware_pack_init.h for details.
|
||||
*
|
||||
* Note that we do not use the following construct in this include file,
|
||||
* because we want to emit the code every time the file is included --hpreg
|
||||
*
|
||||
* #ifndef foo
|
||||
* # define foo
|
||||
* ...
|
||||
* #endif
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "vmware_pack_init.h"
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma pack(pop)
|
||||
#elif __GNUC__
|
||||
__attribute__((__packed__))
|
||||
#else
|
||||
# error Compiler packing...
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2002-2015 VMware, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation version 2 and no later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*********************************************************/
|
||||
|
||||
#ifndef __VMWARE_PACK_INIT_H__
|
||||
# define __VMWARE_PACK_INIT_H__
|
||||
|
||||
|
||||
/*
|
||||
* vmware_pack_init.h --
|
||||
*
|
||||
* Platform-independent code to make the compiler pack (i.e. have them
|
||||
* occupy the smallest possible space) structure definitions. The following
|
||||
* constructs are known to work --hpreg
|
||||
*
|
||||
* #include "vmware_pack_begin.h"
|
||||
* struct foo {
|
||||
* ...
|
||||
* }
|
||||
* #include "vmware_pack_end.h"
|
||||
* ;
|
||||
*
|
||||
* typedef
|
||||
* #include "vmware_pack_begin.h"
|
||||
* struct foo {
|
||||
* ...
|
||||
* }
|
||||
* #include "vmware_pack_end.h"
|
||||
* foo;
|
||||
*/
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/*
|
||||
* MSVC 6.0 emits warning 4103 when the pack push and pop pragma pairing is
|
||||
* not balanced within 1 included file. That is annoying because our scheme
|
||||
* is based on the pairing being balanced between 2 included files.
|
||||
*
|
||||
* So we disable this warning, but this is safe because the compiler will also
|
||||
* emit warning 4161 when there is more pops than pushes within 1 main
|
||||
* file --hpreg
|
||||
*/
|
||||
|
||||
# pragma warning(disable:4103)
|
||||
#elif __GNUC__
|
||||
#else
|
||||
# error Compiler packing...
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __VMWARE_PACK_INIT_H__ */
|
||||
Whitespace-only changes.
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user