Compare commits
18
Commits
p12.5.6
...
player-12.5.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c1d3aad26 | ||
|
|
0c0c10b9f5 | ||
|
|
77a6966b97 | ||
|
|
625084e96a | ||
|
|
1d91cc5b6a | ||
|
|
6fd497d954 | ||
|
|
3fc524fd27 | ||
|
|
9706dac631 | ||
|
|
111554af22 | ||
|
|
28a59964b8 | ||
|
|
ae3ab449f2 | ||
|
|
0fd5d6d023 | ||
|
|
e3a11e99a1 | ||
|
|
185466f7db | ||
|
|
1e10360246 | ||
|
|
1ee356aa18 | ||
|
|
84f16afb1f | ||
|
|
027dd56418 |
No files matched your search
@@ -3,6 +3,8 @@
|
||||
*.ko
|
||||
*.ko.cmd
|
||||
*.mod.c
|
||||
*.tar
|
||||
.tmp_versions
|
||||
.cache.mk
|
||||
Module.symvers
|
||||
modules.order
|
||||
@@ -0,0 +1,197 @@
|
||||
This document explains how to use the repository to retrieve the module
|
||||
source, build modules and install them. There are two basic methods: we can
|
||||
either build the modules from source and install them ourselves or replace
|
||||
VMware provided source tarballs with patched ones and let it use its own
|
||||
vmware-modconfig tool.
|
||||
|
||||
|
||||
0. Quick guide for impatient
|
||||
----------------------------
|
||||
|
||||
First method (build and install):
|
||||
|
||||
wget https://github.com/mkubecek/vmware-host-modules/archive/workstation-14.1.1.tar.gz
|
||||
tar -xzf workstation-14.1.1.tar.gz
|
||||
cd vmware-host-modules-workstation-14.1.1
|
||||
make
|
||||
make install
|
||||
|
||||
Last command must be executed with root privileges (first four shouldn't).
|
||||
Based on your VMware product, replace "14.1.1" with your installed version
|
||||
and/or "workstation" with "player".
|
||||
|
||||
Second method (replace original tarballs):
|
||||
|
||||
wget https://github.com/mkubecek/vmware-host-modules/archive/workstation-14.1.1.tar.gz
|
||||
tar -xzf workstation-14.1.1.tar.gz
|
||||
cd vmware-host-modules-workstation-14.1.1
|
||||
tar -cf vmmon.tar vmmon-only
|
||||
tar -cf vmnet.tar vmnet-only
|
||||
cp -v vmmon.tar vmnet.tar /usr/lib/vmware/modules/source/
|
||||
vmware-modconfig --console --install-all
|
||||
|
||||
In this case, last two commands require root privileges.
|
||||
|
||||
|
||||
1a. Retrieve the source - with git
|
||||
----------------------------------
|
||||
|
||||
Using git is preferrable as it allows an easy switch to sources for
|
||||
different product/version or update for newer kernel version. Without git,
|
||||
you can only download one particular source snapshot.
|
||||
|
||||
First, clone the repository from GitHub either using HTTPS
|
||||
|
||||
git clone https://github.com/mkubecek/vmware-host-modules.git
|
||||
|
||||
or using SSH
|
||||
|
||||
git clone git@github.com:mkubecek/vmware-host-modules.git
|
||||
|
||||
Using SSH is preferrable if you already have an account on GitHub, use
|
||||
HTTPS if you don't.
|
||||
|
||||
Branch "master" cannot be used to build modules, it contains only common
|
||||
files so that changes in them can be merged into all other branches easily.
|
||||
To get actual sources, checkout a "real" branch, e.g.
|
||||
|
||||
git checkout workstation-14.1.1
|
||||
|
||||
Branch name consists of "workstation" (for Workstation) or "player" (for
|
||||
Player), a dash and version number ("14.1.1" here). Always use correct
|
||||
product and version, the modules check if internal source version matches
|
||||
installed product and refuse to load otherwise. Actually, in all recent
|
||||
versions, "workstation" and "player" sources have been identical but there
|
||||
is no guarantee it will always be the case.
|
||||
|
||||
To pull out updated branch (if there are new commits), run "git pull", to
|
||||
switch to a new branch run "git fetch" and "git checkout ...".
|
||||
|
||||
|
||||
1b. Retrieve the source - without git
|
||||
-------------------------------------
|
||||
|
||||
GitHub allows to download a particular snapshot (branch or tag) directly
|
||||
without git:
|
||||
|
||||
wget https://github.com/mkubecek/vmware-host-modules/archive/workstation-14.1.1.tar.gz
|
||||
|
||||
where "workstation" and "14.1.1" have the same meaning as in section 1a.
|
||||
Any other tool can be used to retrieve the URL, of course. It's also
|
||||
possible to download directly from the web interface, switch to the branch
|
||||
you are interested in, click the "Clone or download" button and then
|
||||
"Download ZIP".
|
||||
|
||||
Unpack the downloaded archive
|
||||
|
||||
tar -xzf workstation-14.1.1.tar.gz
|
||||
|
||||
or
|
||||
|
||||
unzip vmware-host-modules-workstation-14.1.1.zip
|
||||
|
||||
depending on archive type. Then change to the resulting directory.
|
||||
|
||||
|
||||
2a. Build and install modules - directly
|
||||
----------------------------------------
|
||||
|
||||
To build modules against currently running kernel, just run "make" in top
|
||||
level directory. It creates two module files vmmon-only/vmmon.ko and
|
||||
vmnet-only/vmnet.ko (unstripped). To build against a different kernel, set
|
||||
variable VM_UNAME, e.g.
|
||||
|
||||
make VM_UNAME='4.14.15-5-default'
|
||||
|
||||
As name suggests, this variable should be set to what "uname -r" would show
|
||||
when that kernel is booted (it's the same as name of the subdirectory under
|
||||
/lib/modules with modules of that kernel).
|
||||
|
||||
To install built modules for currently running kernel, run "make install".
|
||||
This command needs to be run as user with permissions to write into the
|
||||
directory with kernel modules (under normal circumstances, this should be
|
||||
only root). The VM_UNAME variable can be used to install for a different
|
||||
kernel. Unless you know well what are you doing and why, the same value
|
||||
should be always used for "make" and "make install". That's why makefile
|
||||
checks if vermagic tag of the moudules match VM_UNAME (or current kernel if
|
||||
VM_UNAME isn't set).
|
||||
|
||||
If DESTDIR is not set (or is empty), "make install" also runs depmod to
|
||||
update module dependency cache.
|
||||
|
||||
Note that "make install" replaces existing module files but it does not
|
||||
replace modules in running kernel if they are already loaded. Reloading the
|
||||
modules can be enforced e.g. by
|
||||
|
||||
/etc/init.d/vmware restart
|
||||
|
||||
All running VMs should be turned off before this.
|
||||
|
||||
|
||||
2b. Build and install modules - replacing the original source tarballs
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Manual build and installation of host modules may be natural for developers
|
||||
and power users but those who prefer to "just use" would appreciate if they
|
||||
could rely on standard VMware tools. To this goal, we need to replace the
|
||||
module source tarballs with patched versions.
|
||||
|
||||
In local checked out repository, the replacement tarballs can be created
|
||||
with
|
||||
|
||||
make tarballs
|
||||
|
||||
This command creates files vmmon.tar and vmnet.tar which can be used to
|
||||
replace the original tarballs provided with the VMware product. Note that
|
||||
this command creates the tarball from current HEAD (in git language), i.e.
|
||||
they do not contain any uncommited local changes (e.g. files created by
|
||||
test build).
|
||||
|
||||
When using a downloaded tarball, simply run
|
||||
|
||||
tar -cf vmmon.tar vmmon-only
|
||||
tar -cf vmnet.tar vmmon-only
|
||||
|
||||
to create the tarballs. In this case, there is no protection against
|
||||
unwanted local changes.
|
||||
|
||||
Whatever way you used to create the tarballs, replace the original ones
|
||||
provided by VMware
|
||||
|
||||
/usr/lib/vmware/modules/source/vmmon.tar
|
||||
/usr/lib/vmware/modules/source/vmnet.tar
|
||||
|
||||
by patched versions. It is highly recommended to backup the original
|
||||
tarballs before replacing them.
|
||||
|
||||
Once patched tarballs are installed, you can rebuild the modules as usual:
|
||||
|
||||
vmware-modconfig --console --install-all
|
||||
|
||||
or let the GUI run the command for you.
|
||||
|
||||
Replacing the original tarballs prevents having to rebuild and install the
|
||||
modules manually with every new kernel version. However, once the VMware
|
||||
product is upgraded or reinstalled, tarballs are replaced so that if the
|
||||
new VMware version doesn't build/work with a recent kernel, you still need
|
||||
to repeat the process. The same also holds if there is a new kernel which
|
||||
requires updated version of the patches.
|
||||
|
||||
|
||||
3. Final notes
|
||||
--------------
|
||||
|
||||
Always make sure that you are using a branch matching the Workstation or
|
||||
Player version you are running. VMware software may refuse to start if
|
||||
module intended for different version is loaded. And unless you have
|
||||
a reason not to, use current head of that branch; even if the module
|
||||
builds, there may still be later fixes which may be important.
|
||||
|
||||
In some web forums, one can comments suggesting to rip out one patched file
|
||||
and use it as replacement for the corresponding file with VMware tarballs.
|
||||
Please don't do this - and if you do, don't complain if something doesn't
|
||||
work. A commit fixing some problem is meant to be used as a whole; picking
|
||||
just changes in one file can lead to rather unpredictable results. While
|
||||
picking just one commit (or some of the commits) in a branch is perfectly
|
||||
fine (you should still know what are you doing and why), picking just one
|
||||
patched file rarely makes sense.
|
||||
@@ -0,0 +1,48 @@
|
||||
MODULES = vmmon vmnet
|
||||
SUBDIRS = $(MODULES:%=%-only)
|
||||
TARBALLS = $(MODULES:%=%.tar)
|
||||
MODFILES = $(foreach mod,$(MODULES),$(mod)-only/$(mod).ko)
|
||||
VM_UNAME = $(shell uname -r)
|
||||
MODDIR = /lib/modules/$(VM_UNAME)/misc
|
||||
|
||||
MODINFO = /sbin/modinfo
|
||||
DEPMOD = /sbin/depmod
|
||||
|
||||
%.tar: FORCE gitcleancheck
|
||||
git archive -o $@ --format=tar HEAD $(@:.tar=-only)
|
||||
|
||||
.PHONY: FORCE subdirs $(SUBDIRS) clean tarballs
|
||||
|
||||
subdirs: retiredcheck $(SUBDIRS)
|
||||
|
||||
FORCE:
|
||||
|
||||
$(SUBDIRS):
|
||||
$(MAKE) -C $@ $(MAKECMDGOALS)
|
||||
|
||||
gitcheck:
|
||||
@git status >/dev/null 2>&1 \
|
||||
|| ( echo "This only works in a git repository."; exit 1 )
|
||||
|
||||
gitcleancheck: gitcheck
|
||||
@git diff --exit-code HEAD >/dev/null 2>&1 \
|
||||
|| echo "Warning: tarballs will reflect current HEAD (no uncommited changes)"
|
||||
|
||||
retiredcheck:
|
||||
@test -f RETIRED && cat RETIRED || true
|
||||
|
||||
install: retiredcheck $(MODFILES)
|
||||
@for f in $(MODFILES); do \
|
||||
mver=$$($(MODINFO) -F vermagic $$f);\
|
||||
mver=$${mver%% *};\
|
||||
test "$${mver}" = "$(VM_UNAME)" \
|
||||
|| ( echo "Version mismatch: module $$f $${mver}, kernel $(VM_UNAME)" ; exit 1 );\
|
||||
done
|
||||
install -D -t $(DESTDIR)$(MODDIR) $(MODFILES)
|
||||
strip --strip-debug $(MODULES:%=$(DESTDIR)$(MODDIR)/%.ko)
|
||||
if test -z "$(DESTDIR)"; then $(DEPMOD) -a $(VM_UNAME); fi
|
||||
|
||||
clean: $(SUBDIRS)
|
||||
|
||||
tarballs: $(TARBALLS)
|
||||
|
||||
@@ -12,12 +12,17 @@ a particular version of Player or Workstation.
|
||||
|
||||
From these tags, branches "player-${version}" and "workstation-${version}"
|
||||
are forked. These branches track changes needed to build these modules
|
||||
against recent kernel versions. Tag "p${ver}-k${ver}" marks the set of
|
||||
changes needed to build modules from Player ${ver} against kernel ${ver},
|
||||
against recent kernel versions. Tag "p${ver}-k${kver}" marks the set of
|
||||
changes needed to build modules from Player ${ver} against kernel ${kver},
|
||||
e.g. p12.5.5-k4.11 is for Player 12.5.5 and kernel 4.11; similar naming
|
||||
scheme "w${ver}-k${kver}" is used for Workstation modules. In general,
|
||||
later points in the branch should also work with older kernels (e.g.
|
||||
p12.5.5-k4.11 with kernel 4.10) but it's not completely reliable.
|
||||
p12.5.5-k4.11 with kernel 4.10) but it's not guaranteed; it may happen that
|
||||
a fix for new kernel version may be too complicated to make also work with
|
||||
older versions.
|
||||
|
||||
At the moment, changes are tested to build against all (vanilla) kernel
|
||||
releases starting with 4.9.
|
||||
|
||||
This repository is provided "as is" with no guarantees. Use the contents on
|
||||
your own risk.
|
||||
@@ -0,0 +1,7 @@
|
||||
*-----------------------------------------------------------------------------
|
||||
* Branch player-12.5.8 has been retired on 2018-01-18 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.14.
|
||||
*-----------------------------------------------------------------------------
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2014 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2017 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,14 +122,10 @@ EXTERN MPN HostIF_GetNextAnonPage(VMDriver *vm, MPN mpn);
|
||||
EXTERN int HostIF_GetLockedPageList(VMDriver *vm, VA64 uAddr,
|
||||
unsigned int numPages);
|
||||
|
||||
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_ReadPage(VMDriver *vm, MPN mpn, VA64 addr, Bool kernelBuffer);
|
||||
EXTERN int HostIF_WritePage(VMDriver *vm, MPN mpn, VA64 addr,
|
||||
Bool kernelBuffer);
|
||||
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)
|
||||
@@ -145,4 +141,8 @@ 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 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2017 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,6 +88,7 @@
|
||||
|
||||
#include "vmware.h"
|
||||
#include "hostif.h"
|
||||
#include "vmx86.h"
|
||||
|
||||
#include "memtrack.h"
|
||||
|
||||
@@ -146,12 +147,11 @@ 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,11 +304,9 @@ 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);
|
||||
@@ -332,7 +330,7 @@ MemTrackCleanup(MemTrack *mt) // IN
|
||||
*/
|
||||
|
||||
MemTrack *
|
||||
MemTrack_Init(void)
|
||||
MemTrack_Init(VMDriver *vm) // IN:
|
||||
{
|
||||
MemTrack *mt;
|
||||
unsigned idx;
|
||||
@@ -349,6 +347,7 @@ MemTrack_Init(void)
|
||||
goto error;
|
||||
}
|
||||
memset(mt, 0, sizeof *mt);
|
||||
mt->vm = vm;
|
||||
|
||||
for (idx = 0; idx < MEMTRACK_HT_PAGES; idx++) {
|
||||
MemTrackHTPage *htPage = MemTrackAllocPage();
|
||||
@@ -360,7 +359,6 @@ MemTrack_Init(void)
|
||||
mt->vpnHashTable.pages[idx] = htPage;
|
||||
}
|
||||
|
||||
#if defined(MEMTRACK_MPN_LOOKUP)
|
||||
for (idx = 0; idx < MEMTRACK_HT_PAGES; idx++) {
|
||||
MemTrackHTPage *htPage = MemTrackAllocPage();
|
||||
|
||||
@@ -370,7 +368,6 @@ MemTrack_Init(void)
|
||||
}
|
||||
mt->mpnHashTable.pages[idx] = htPage;
|
||||
}
|
||||
#endif
|
||||
|
||||
return mt;
|
||||
|
||||
@@ -409,6 +406,8 @@ 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) {
|
||||
@@ -430,9 +429,7 @@ 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++;
|
||||
|
||||
@@ -461,6 +458,7 @@ 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) {
|
||||
@@ -473,7 +471,6 @@ MemTrack_LookupVPN(MemTrack *mt, // IN
|
||||
}
|
||||
|
||||
|
||||
#if defined(MEMTRACK_MPN_LOOKUP)
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -493,7 +490,9 @@ MemTrackEntry *
|
||||
MemTrack_LookupMPN(MemTrack *mt, // IN
|
||||
MPN mpn) // IN
|
||||
{
|
||||
MemTrackEntry *next = *MemTrackHTLookup(&mt->mpnHashTable, mpn);
|
||||
MemTrackEntry *next;
|
||||
ASSERT(HostIF_VMLockIsHeld(mt->vm));
|
||||
next = *MemTrackHTLookup(&mt->mpnHashTable, mpn);
|
||||
|
||||
while (next != NULL) {
|
||||
if (next->mpn == mpn) {
|
||||
@@ -504,7 +503,6 @@ MemTrack_LookupMPN(MemTrack *mt, // IN
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2017 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,30 +31,22 @@
|
||||
#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(void);
|
||||
extern struct MemTrack *MemTrack_Init(VMDriver *vm);
|
||||
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-2016 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2017 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,6 +39,9 @@
|
||||
# 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
|
||||
@@ -60,6 +63,13 @@
|
||||
#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"
|
||||
@@ -691,11 +701,28 @@ 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);
|
||||
}
|
||||
}
|
||||
@@ -1747,7 +1774,8 @@ 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]) : NULL;
|
||||
tempGDTBase = USE_TEMPORARY_GDT ? Atomic_ReadPtr(&tmpGDT[pCPU])
|
||||
: default_rw_gdt;
|
||||
|
||||
/*
|
||||
* We can't allocate memory with interrupts disabled on all hosts
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2016 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2017 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,6 +720,35 @@ 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-2013,2015-2016 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2017 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,6 +106,7 @@ 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,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2002 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 2002-2017 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,80 +30,32 @@
|
||||
#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
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* p4d level appeared in 4.12.
|
||||
*/
|
||||
#ifdef PUD_MASK
|
||||
# define compat_pgd_offset(mm, address) pgd_offset(mm, address)
|
||||
# define compat_pgd_present(pgd) pgd_present(pgd)
|
||||
# define compat_pud_offset(pgd, address) pud_offset(pgd, address)
|
||||
# define compat_pud_present(pud) pud_present(pud)
|
||||
typedef pgd_t compat_pgd_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_pud_offset(pml4, address) pml4_pgd_offset(pml4, address)
|
||||
# define compat_pud_present(pgd) pgd_present(pgd)
|
||||
typedef pml4_t compat_pgd_t;
|
||||
typedef pgd_t compat_pud_t;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
|
||||
# define compat_p4d_offset(pgd, address) p4d_offset(pgd, address)
|
||||
# define compat_p4d_present(p4d) p4d_present(p4d)
|
||||
# define compat_p4d_large(p4d) p4d_large(p4d)
|
||||
# define compat_p4d_pfn(p4d) p4d_pfn(p4d)
|
||||
# define COMPAT_P4D_MASK P4D_MASK
|
||||
typedef p4d_t compat_p4d_t;
|
||||
#else
|
||||
# define compat_pgd_offset(mm, address) pgd_offset(mm, address)
|
||||
# define compat_pgd_present(pgd) pgd_present(pgd)
|
||||
# define compat_pud_offset(pgd, address) (pgd)
|
||||
# define compat_pud_present(pud) (1)
|
||||
typedef pgd_t compat_pgd_t;
|
||||
typedef pgd_t compat_pud_t;
|
||||
# define compat_p4d_offset(pgd, address) (pgd)
|
||||
# define compat_p4d_present(p4d) (1)
|
||||
# define compat_p4d_large(p4d) (0)
|
||||
# define compat_p4d_pfn(p4d) INVALID_MPN /* Not used */
|
||||
# define COMPAT_P4D_MASK 0 /* Not used */
|
||||
typedef pgd_t compat_p4d_t;
|
||||
#endif
|
||||
|
||||
|
||||
#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))
|
||||
/* p[gu]d_large did not exist before 2.6.25 */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
|
||||
# define pud_large(pud) 0
|
||||
# define pgd_large(pgd) 0
|
||||
#endif
|
||||
|
||||
|
||||
/* 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
|
||||
/* pud_pfn did not exist before 3.8. */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
|
||||
# define pud_pfn(pud) INVALID_MPN
|
||||
#endif
|
||||
|
||||
|
||||
@@ -128,12 +80,8 @@ typedef pgd_t compat_pud_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__ */
|
||||
@@ -0,0 +1,33 @@
|
||||
#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__ */
|
||||
+56
-296
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 2002,2014 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 2002,2014-2017 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,154 +26,14 @@
|
||||
#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_pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
|
||||
if (compat_pgd_present(*pgd) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pud = compat_pud_offset(pgd, 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 --
|
||||
*
|
||||
* Retrieve MPN for a given va.
|
||||
*
|
||||
* Caller must call pte_unmap if valid pte returned. The mm->page_table_lock
|
||||
* must be held, so this function is not allowed to schedule() --hpreg
|
||||
* Walks through the hardware page tables to try to find the pte
|
||||
* associated to a virtual address. Then maps PTE to MPN.
|
||||
*
|
||||
* Results:
|
||||
* INVALID_MPN on failure
|
||||
@@ -188,89 +48,64 @@ PgtblVa2PTELocked(struct mm_struct *mm, // IN: Mm structure of a process
|
||||
static INLINE MPN
|
||||
PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process
|
||||
VA addr) // IN: Address in the virtual address
|
||||
// space of that process
|
||||
{
|
||||
pte_t *pte;
|
||||
pgd_t *pgd;
|
||||
compat_p4d_t *p4d;
|
||||
MPN mpn;
|
||||
|
||||
pte = PgtblVa2PTELocked(mm, addr);
|
||||
if (pte != NULL) {
|
||||
MPN mpn = PgtblPte2MPN(pte);
|
||||
pte_unmap(pte);
|
||||
return mpn;
|
||||
pgd = pgd_offset(mm, addr);
|
||||
if (pgd_present(*pgd) == 0) {
|
||||
return INVALID_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;
|
||||
if (pgd_large(*pgd)) {
|
||||
/* Linux kernel does not support PGD huge pages. */
|
||||
/* return pgd_pfn(*pgd) + ((addr & PGD_MASK) >> PAGE_SHIFT); */
|
||||
return INVALID_MPN;
|
||||
}
|
||||
return 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;
|
||||
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 {
|
||||
return NULL;
|
||||
pud_t *pud;
|
||||
|
||||
pud = pud_offset(p4d, addr);
|
||||
if (pud_present(*pud) == 0) {
|
||||
return INVALID_MPN;
|
||||
}
|
||||
if (pud_large(*pud)) {
|
||||
mpn = pud_pfn(*pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT);
|
||||
} else {
|
||||
pmd_t *pmd;
|
||||
|
||||
pmd = pmd_offset(pud, addr);
|
||||
if (pmd_present(*pmd) == 0) {
|
||||
return INVALID_MPN;
|
||||
}
|
||||
if (pmd_large(*pmd)) {
|
||||
mpn = pmd_pfn(*pmd) + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
|
||||
} else {
|
||||
pte_t *pte;
|
||||
|
||||
pte = pte_offset_map(pmd, addr);
|
||||
if (pte_present(*pte) == 0) {
|
||||
pte_unmap(pte);
|
||||
return INVALID_MPN;
|
||||
}
|
||||
mpn = pte_pfn(*pte);
|
||||
pte_unmap(pte);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mpn >= INVALID_MPN) {
|
||||
mpn = INVALID_MPN;
|
||||
}
|
||||
return mpn;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -298,85 +133,10 @@ PgtblVa2MPN(VA addr) // IN
|
||||
|
||||
/* current->mm is NULL for kernel threads, so use active_mm. */
|
||||
mm = current->active_mm;
|
||||
if (compat_get_page_table_lock(mm)) {
|
||||
spin_lock(compat_get_page_table_lock(mm));
|
||||
}
|
||||
spin_lock(&mm->page_table_lock);
|
||||
mpn = PgtblVa2MPNLocked(mm, addr);
|
||||
if (compat_get_page_table_lock(mm)) {
|
||||
spin_unlock(compat_get_page_table_lock(mm));
|
||||
}
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
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,6 +67,7 @@ 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) \
|
||||
@@ -118,7 +119,7 @@ NORETURN void Panic_NoSaveNoReturn(const char *fmt, ...) PRINTF_DECL(1, 2);
|
||||
} while(0)
|
||||
|
||||
#else
|
||||
NORETURN void Panic(const char *fmt, ...) PRINTF_DECL(1, 2);
|
||||
#define Panic panic
|
||||
#endif
|
||||
|
||||
void LogThrottled(uint32 *count, const char *fmt, ...) PRINTF_DECL(2, 3);
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#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
|
||||
@@ -62,7 +64,9 @@
|
||||
#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
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#ifndef _X86MSR_H_
|
||||
#define _X86MSR_H_
|
||||
#include <asm/msr-index.h>
|
||||
#define INCLUDE_ALLOW_USERLEVEL
|
||||
#define INCLUDE_ALLOW_VMX
|
||||
|
||||
@@ -106,7 +107,9 @@ MSRQuery;
|
||||
#define MSR_TSC_AUX 0xc0000103
|
||||
#define MSR_BD_TSC_RATIO 0xc0000104
|
||||
|
||||
#ifndef MSR_MISC_FEATURES_ENABLES
|
||||
#define MSR_MISC_FEATURES_ENABLES 0x140
|
||||
#endif
|
||||
|
||||
/* Intel Core Architecture and later: use only architected counters. */
|
||||
#define IA32_MSR_PERF_CAPABILITIES 0x345
|
||||
@@ -475,7 +478,11 @@ typedef enum {
|
||||
/*
|
||||
* MISC_FEATURES_ENABLES bits
|
||||
*/
|
||||
#ifdef MSR_MISC_FEATURES_ENABLES_CPUID_FAULT
|
||||
#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULTING MSR_MISC_FEATURES_ENABLES_CPUID_FAULT
|
||||
#else
|
||||
#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULTING 1
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
+10
-16
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2016 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2017 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,6 +21,7 @@
|
||||
|
||||
#define EXPORT_SYMTAB
|
||||
|
||||
#include "compat_timer.h"
|
||||
#include <linux/file.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/poll.h>
|
||||
@@ -115,7 +116,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(unsigned long clientData);
|
||||
static void LinuxDriverPollTimeout(compat_timer_arg_t unused);
|
||||
static unsigned int LinuxDriverEstimateTSCkHz(void);
|
||||
|
||||
static struct vm_operations_struct vmuser_mops = {
|
||||
@@ -227,7 +228,7 @@ LinuxDriverEstimateTSCkHz(void)
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static void
|
||||
LinuxDriverEstimateTSCkHzDeferred(unsigned long data)
|
||||
LinuxDriverEstimateTSCkHzDeferred(compat_timer_arg_t unused)
|
||||
{
|
||||
LinuxDriverEstimateTSCkHz();
|
||||
}
|
||||
@@ -265,9 +266,7 @@ LinuxDriverInitTSCkHz(void)
|
||||
}
|
||||
|
||||
Vmx86_ReadTSCAndUptime(&tsckHzStartTime);
|
||||
tscTimer.function = LinuxDriverEstimateTSCkHzDeferred;
|
||||
tscTimer.expires = jiffies + 4 * HZ;
|
||||
tscTimer.data = 0;
|
||||
add_timer(&tscTimer);
|
||||
}
|
||||
|
||||
@@ -309,9 +308,7 @@ init_module(void)
|
||||
*/
|
||||
|
||||
init_waitqueue_head(&linuxState.pollQueue);
|
||||
init_timer(&linuxState.pollTimer);
|
||||
linuxState.pollTimer.data = 0;
|
||||
linuxState.pollTimer.function = LinuxDriverPollTimeout;
|
||||
compat_timer_setup(&linuxState.pollTimer, LinuxDriverPollTimeout, 0);
|
||||
|
||||
linuxState.fastClockThread = NULL;
|
||||
linuxState.fastClockFile = NULL;
|
||||
@@ -360,7 +357,7 @@ init_module(void)
|
||||
linuxState.deviceName, linuxState.major, linuxState.minor);
|
||||
|
||||
HostIF_InitUptime();
|
||||
init_timer(&tscTimer);
|
||||
compat_timer_setup(&tscTimer, LinuxDriverEstimateTSCkHzDeferred, 0);
|
||||
LinuxDriverInitTSCkHz();
|
||||
Vmx86_InitIDList();
|
||||
|
||||
@@ -858,7 +855,7 @@ LinuxDriverPoll(struct file *filp, // IN:
|
||||
*/
|
||||
|
||||
static void
|
||||
LinuxDriverPollTimeout(unsigned long clientData) // IN:
|
||||
LinuxDriverPollTimeout(compat_timer_arg_t unused) // IN:
|
||||
{
|
||||
LinuxDriverWakeUp(FALSE);
|
||||
}
|
||||
@@ -1358,7 +1355,6 @@ 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:
|
||||
@@ -1368,8 +1364,6 @@ 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:
|
||||
@@ -1530,7 +1524,7 @@ LinuxDriver_Ioctl(struct file *filp, // IN:
|
||||
if (retval) {
|
||||
break;
|
||||
}
|
||||
args.ret.status = HostIF_LookupUserMPN(vm, args.uAddr, &args.ret.mpn);
|
||||
args.ret.status = Vmx86_LookupUserMPN(vm, args.uAddr, &args.ret.mpn);
|
||||
retval = HostIF_CopyToUser((void *)ioarg, &args, sizeof args);
|
||||
break;
|
||||
}
|
||||
@@ -1849,7 +1843,7 @@ LinuxDriver_Ioctl(struct file *filp, // IN:
|
||||
if (retval) {
|
||||
break;
|
||||
}
|
||||
retval = HostIF_ReadPage(req.mpn, req.uAddr, FALSE);
|
||||
retval = HostIF_ReadPage(vm, req.mpn, req.uAddr, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1860,7 +1854,7 @@ LinuxDriver_Ioctl(struct file *filp, // IN:
|
||||
if (retval) {
|
||||
break;
|
||||
}
|
||||
retval = HostIF_WritePage(req.mpn, req.uAddr, FALSE);
|
||||
retval = HostIF_WritePage(vm, req.mpn, req.uAddr, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+157
-26
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2014 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2017 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,6 +30,7 @@
|
||||
|
||||
/* 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>
|
||||
@@ -82,13 +83,13 @@
|
||||
#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"
|
||||
@@ -99,6 +100,37 @@
|
||||
#include "vmmonInt.h"
|
||||
#include "versioned_atomic.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(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.
|
||||
*/
|
||||
@@ -1009,7 +1041,7 @@ HostIF_FreeLockedPages(VMDriver *vm, // IN: VM instance pointer
|
||||
int
|
||||
HostIF_Init(VMDriver *vm) // IN:
|
||||
{
|
||||
vm->memtracker = MemTrack_Init();
|
||||
vm->memtracker = MemTrack_Init(vm);
|
||||
if (vm->memtracker == NULL) {
|
||||
return -1;
|
||||
}
|
||||
@@ -1594,16 +1626,11 @@ 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_page_state(NR_PAGETABLE) +
|
||||
global_page_state(NR_SLAB_UNRECLAIMABLE) +
|
||||
global_page_state(NR_UNEVICTABLE) +
|
||||
unsigned int lockedPages = global_zone_page_state(NR_PAGETABLE) +
|
||||
get_nr_slab_unreclaimable() +
|
||||
get_nr_unevictable() +
|
||||
hugePages + reservedPages;
|
||||
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 anonPages = get_nr_anon_mapped();
|
||||
unsigned int swapPages = BYTES_2_PAGES(linuxState.swapSize);
|
||||
|
||||
if (anonPages > swapPages) {
|
||||
@@ -1767,7 +1794,7 @@ HostIFReadUptimeWork(unsigned long *j) // OUT: current jiffies
|
||||
*/
|
||||
|
||||
static void
|
||||
HostIFUptimeResyncMono(unsigned long data) // IN: ignored
|
||||
HostIFUptimeResyncMono(compat_timer_arg_t unused) // IN: ignored
|
||||
{
|
||||
unsigned long jifs;
|
||||
uintptr_t flags;
|
||||
@@ -1829,8 +1856,7 @@ HostIF_InitUptime(void)
|
||||
-(tv.tv_usec * (UPTIME_FREQ / 1000000) +
|
||||
tv.tv_sec * UPTIME_FREQ));
|
||||
|
||||
init_timer(&uptimeState.timer);
|
||||
uptimeState.timer.function = HostIFUptimeResyncMono;
|
||||
compat_timer_setup(&uptimeState.timer, HostIFUptimeResyncMono, 0);
|
||||
mod_timer(&uptimeState.timer, jiffies + HZ);
|
||||
}
|
||||
|
||||
@@ -2001,15 +2027,15 @@ HostIF_MapCrossPage(VMDriver *vm, // IN
|
||||
return NULL;
|
||||
}
|
||||
vPgAddr = (VA) MapCrossPage(page);
|
||||
HostIF_GlobalLock(16);
|
||||
HostIF_VMLock(vm, 27);
|
||||
if (vm->vmhost->crosspagePagesCount >= MAX_INITBLOCK_CPUS) {
|
||||
HostIF_GlobalUnlock(16);
|
||||
HostIF_VMUnlock(vm, 27);
|
||||
UnmapCrossPage(page, (void*)vPgAddr);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
vm->vmhost->crosspagePages[vm->vmhost->crosspagePagesCount++] = page;
|
||||
HostIF_GlobalUnlock(16);
|
||||
HostIF_VMUnlock(vm, 27);
|
||||
|
||||
ret = vPgAddr | (((VA)p) & (PAGE_SIZE - 1));
|
||||
|
||||
@@ -2817,13 +2843,75 @@ 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 --
|
||||
*
|
||||
* puts the content of a machine page into a kernel or user mode
|
||||
* buffer.
|
||||
* 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.
|
||||
*
|
||||
* Results:
|
||||
* 0 on success
|
||||
@@ -2836,7 +2924,8 @@ HostIF_CallOnEachCPU(void (*func)(void*), // IN: function to call
|
||||
*/
|
||||
|
||||
int
|
||||
HostIF_ReadPage(MPN mpn, // MPN of the page
|
||||
HostIF_ReadPage(VMDriver *vm, // IN: The VM instance
|
||||
MPN mpn, // MPN of the page
|
||||
VA64 addr, // buffer for data
|
||||
Bool kernelBuffer) // is the buffer in kernel space?
|
||||
{
|
||||
@@ -2848,6 +2937,9 @@ HostIF_ReadPage(MPN mpn, // MPN of the page
|
||||
if (mpn == INVALID_MPN) {
|
||||
return -EFAULT;
|
||||
}
|
||||
if (HostIFCheckTrackedMPN(vm, mpn) == FALSE) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
page = pfn_to_page(mpn);
|
||||
ptr = kmap(page);
|
||||
@@ -2871,8 +2963,8 @@ HostIF_ReadPage(MPN mpn, // MPN of the page
|
||||
*
|
||||
* HostIF_WritePage --
|
||||
*
|
||||
* Put the content of a kernel or user mode buffer into a machine
|
||||
* page.
|
||||
* 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.
|
||||
*
|
||||
* Results:
|
||||
* 0 on success
|
||||
@@ -2885,9 +2977,9 @@ HostIF_ReadPage(MPN mpn, // MPN of the page
|
||||
*/
|
||||
|
||||
int
|
||||
HostIF_WritePage(MPN mpn, // MPN of the page
|
||||
VA64 addr, // data to write to the page
|
||||
Bool kernelBuffer) // is the buffer in kernel space?
|
||||
HostIFWritePageWork(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;
|
||||
@@ -2914,6 +3006,45 @@ HostIF_WritePage(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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2017 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,11 +205,13 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
+11
-6
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998-2013 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998-2013, 2017 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
|
||||
@@ -636,7 +636,7 @@ VNetBridgeReceiveFromVNet(VNetJack *this, // IN: jack
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
atomic_inc(&clone->users);
|
||||
clone = skb_get(clone);
|
||||
|
||||
clone->dev = dev;
|
||||
clone->protocol = eth_type_trans(clone, dev);
|
||||
@@ -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,11 +1143,16 @@ 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: device pertaining to event
|
||||
void *data) // IN: net_device or notifier info
|
||||
{
|
||||
VNetBridge *bridge = list_entry(this, VNetBridge, notifier);
|
||||
struct net_device *dev = (struct net_device *) data;
|
||||
struct net_device *dev;
|
||||
|
||||
#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",
|
||||
@@ -1179,7 +1184,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);
|
||||
}
|
||||
|
||||
@@ -337,7 +337,8 @@ typedef netdev_features_t compat_netdev_features_t;
|
||||
typedef u32 compat_netdev_features_t;
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) || \
|
||||
(defined(RHEL_RELEASE_CODE) && RHEL_RELEASE_CODE >= 0x0704)
|
||||
#define compat_netif_trans_update(d) netif_trans_update(d)
|
||||
#else
|
||||
#define compat_netif_trans_update(d) do { (d)->trans_start = jiffies; } while (0)
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <linux/pci_ids.h>
|
||||
|
||||
/* LSILogic 53C1030 Parallel SCSI controller
|
||||
* LSILogic SAS1068 SAS controller
|
||||
*/
|
||||
@@ -53,7 +55,10 @@
|
||||
* VMware HD Audio codec
|
||||
* VMware HD Audio controller
|
||||
*/
|
||||
#ifndef PCI_VENDOR_ID_VMWARE
|
||||
#define PCI_VENDOR_ID_VMWARE 0x15AD
|
||||
#endif
|
||||
|
||||
#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405
|
||||
#define PCI_DEVICE_ID_VMWARE_SVGA 0x0710
|
||||
#define PCI_DEVICE_ID_VMWARE_VGA 0x0711
|
||||
@@ -70,7 +75,11 @@
|
||||
#define PCI_DEVICE_ID_VMWARE_1394 0x0780
|
||||
#define PCI_DEVICE_ID_VMWARE_BRIDGE 0x0790
|
||||
#define PCI_DEVICE_ID_VMWARE_ROOTPORT 0x07A0
|
||||
|
||||
#ifndef PCI_DEVICE_ID_VMWARE_VMXNET3
|
||||
#define PCI_DEVICE_ID_VMWARE_VMXNET3 0x07B0
|
||||
#endif
|
||||
|
||||
#define PCI_DEVICE_ID_VMWARE_PVSCSI 0x07C0
|
||||
#define PCI_DEVICE_ID_VMWARE_82574 0x07D0
|
||||
#define PCI_DEVICE_ID_VMWARE_AHCI 0x07E0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************
|
||||
* Copyright (C) 1998 VMware, Inc. All rights reserved.
|
||||
* Copyright (C) 1998, 2017 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)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) || defined(sk_net_refcnt)
|
||||
# define compat_sk_alloc(_bri, _pri) sk_alloc(&init_net, \
|
||||
PF_NETLINK, _pri, &vmnet_proto, 1)
|
||||
#elif defined(VMW_NETDEV_HAS_NET)
|
||||
|
||||
Reference in new issue
Block a user