Compare commits

..
10 Commits
Author SHA1 Message Date
Michal Kubecek 63ff06f34c Merge branch 'master' into player-12.5.5 2018-04-02 15:37:20 +02:00
Michal Kubecek 5027ee962c mark branch player-12.5.5 as retired 2018-04-02 15:33:40 +02:00
Michal Kubecek 1e192ab478 vmmon: adapt to 5-level page table hierarchy
Since commit  f2a6a7050109 ("x86: Convert the rest of the code to support
p4d_t") in v4.12-rc1 we need to handle the 5-level page table hierarchy
(pgd -> p4d -> pud -> pmd -> pte).
2017-05-31 09:26:39 +02:00
Michal Kubecek 21d7ca2ad5 vmmon: use standard definition of MSR_MISC_FEATURES_ENABLES if available
The MSR_MISC_FEATURES_ENABLES macro is defined in mainline since commit
ab6d9468631a ("x86/msr: Rename MISC_FEATURE_ENABLES to
MISC_FEATURES_ENABLES") in v4.12-rc1.

The MSR_MISC_FEATURES_ENABLES_CPUID_FAULT macro is defined in mainline
since commit e9ea1e7f53b8 ("x86/arch_prctl: Add ARCH_[GET|SET]_CPUID") in
v4.12-rc1.
2017-05-31 09:26:39 +02:00
Michal Kubecek 1678e8dfec all: add explicit includes for signal headers
Since commit c3edc4010e9d ("sched/headers: Move task_struct::signal and
task_struct::sighand types and accessors into <linux/sched/signal.h>") in
v4.11-rc1, force_sig() and signal_pending() are in <linux/sched/signal.h>

Since commit  192c9414516e ("sched/headers: Remove <linux/signal.h> from
<linux/sched.h>") in v4.11-rc1, <linux/signal.h> needs to be included
explicitely, it's no longer included via <linux/sched.h>
2017-05-31 09:26:39 +02:00
Michal Kubecek c1ee74ac5e vmmon: drop vma parameter of vm_operations_struct::fault
Since commit 11bac8000449 ("mm, fs: reduce fault, page_mkwrite, and
pfn_mkwrite to take only vmf") in v4.11-rc1, fault() callback in struct
vm_operations_struct takes only one argument.
2017-05-31 09:26:39 +02:00
Michal Kubecek b7d3ea5042 vmnet: use standard definition of PCI_VENDOR_ID_VMWARE_VMXNET3 if available
The PCI_DEVICE_ID_VMWARE_VMXNET3 macro is defined in mainline pci_ids.h
since commit b1226c7db1d9 ("vmxnet3: Move PCI Id to pci_ids.h") in
v4.10-rc1.
2017-05-31 09:26:27 +02:00
Michal Kubecek 15cfc0391c vmnet: use standard definition of PCI_VENDOR_ID_VMWARE if available
The PCI_VENDOR_ID_VMWARE macro is defined in mainline pci_ids.h since
commit 94e57fea6202 ("PCI: Move PCI_VENDOR_ID_VMWARE to pci_ids.h")
in v3.18-rc1.
2017-05-31 09:24:53 +02:00
Michal Kubecek c62c78e908 import Player 12.5.5 module sources 2017-05-31 09:20:00 +02:00
Michal Kubecek 4f648692e4 import Player 12.5.2 module sources 2017-05-31 09:19:26 +02:00
175 changed files with 68450 additions and 2 deletions

No files matched your search

+1 -1
View File
@@ -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.
-1
View File
@@ -43,7 +43,6 @@ install: retiredcheck $(MODFILES)
if test -z "$(DESTDIR)"; then $(DEPMOD) -a $(VM_UNAME); fi
clean: $(SUBDIRS)
rm -f *.o
tarballs: $(TARBALLS)
+7
View File
@@ -0,0 +1,7 @@
*-----------------------------------------------------------------------------
* Branch player-12.5.5 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.
*-----------------------------------------------------------------------------
+339
View File
@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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; either version 2 of the License, or
(at your option) any 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
+150
View File
@@ -0,0 +1,150 @@
#!/usr/bin/make -f
##########################################################
# 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
# 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 kernel module Makefile to be distributed externally
####
####
#### SRCROOT _must_ be a relative path.
####
SRCROOT = .
#
# open-vm-tools doesn't replicate shared source files for different modules;
# instead, files are kept in shared locations. So define a few useful macros
# to be able to handle both cases cleanly.
#
INCLUDE :=
ifdef OVT_SOURCE_DIR
AUTOCONF_DIR := $(OVT_SOURCE_DIR)/modules/linux/shared/autoconf
VMLIB_PATH = $(OVT_SOURCE_DIR)/lib/$(1)
INCLUDE += -I$(OVT_SOURCE_DIR)/modules/linux/shared
INCLUDE += -I$(OVT_SOURCE_DIR)/lib/include
else
AUTOCONF_DIR := $(SRCROOT)/shared/autoconf
INCLUDE += -I$(SRCROOT)/shared
endif
VM_UNAME = $(shell uname -r)
# Header directory for the running kernel
ifdef LINUXINCLUDE
HEADER_DIR = $(LINUXINCLUDE)
else
HEADER_DIR = /lib/modules/$(VM_UNAME)/build/include
endif
BUILD_DIR = $(HEADER_DIR)/..
DRIVER := vmmon
PRODUCT := @@PRODUCT@@
# Grep program
GREP = /bin/grep
vm_check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \
> /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
vm_check_file = $(shell if test -f $(1); then echo "yes"; else echo "no"; fi)
ifndef VM_KBUILD
VM_KBUILD := no
ifeq ($(call vm_check_file,$(BUILD_DIR)/Makefile), yes)
VM_KBUILD := yes
endif
export VM_KBUILD
endif
ifndef VM_KBUILD_SHOWN
ifeq ($(VM_KBUILD), no)
VM_DUMMY := $(shell echo >&2 "Using standalone build system.")
else
VM_DUMMY := $(shell echo >&2 "Using kernel build system.")
endif
VM_KBUILD_SHOWN := yes
export VM_KBUILD_SHOWN
endif
ifneq ($(VM_KBUILD), no)
VMCCVER := $(shell $(CC) -dumpversion)
# If there is no version defined, we are in toplevel pass, not yet in kernel makefiles...
ifeq ($(VERSION),)
DRIVER_KO := $(DRIVER).ko
.PHONY: $(DRIVER_KO)
auto-build: $(DRIVER_KO)
cp -f $< $(SRCROOT)/../$(DRIVER).o
# $(DRIVER_KO) is a phony target, so compare file times explicitly
$(DRIVER): $(DRIVER_KO)
if [ $< -nt $@ ] || [ ! -e $@ ] ; then cp -f $< $@; fi
# Pass gcc version down the chain, so we can detect if kernel attempts to use unapproved compiler
VM_CCVER := $(VMCCVER)
export VM_CCVER
VM_CC := $(CC)
export VM_CC
MAKEOVERRIDES := $(filter-out CC=%,$(MAKEOVERRIDES))
#
# Define a setup target that gets built before the actual driver.
# This target may not be used at all, but if it is then it will be defined
# in Makefile.kernel
#
prebuild:: ;
postbuild:: ;
$(DRIVER_KO): prebuild
$(MAKE) -C $(BUILD_DIR) SUBDIRS=$$PWD SRCROOT=$$PWD/$(SRCROOT) \
MODULEBUILDDIR=$(MODULEBUILDDIR) modules
$(MAKE) -C $$PWD SRCROOT=$$PWD/$(SRCROOT) \
MODULEBUILDDIR=$(MODULEBUILDDIR) postbuild
endif
vm_check_build = $(shell if $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) \
$(CPPFLAGS) $(CFLAGS) $(CFLAGS_KERNEL) $(LINUXINCLUDE) \
$(EXTRA_CFLAGS) -Iinclude2/asm/mach-default \
-DKBUILD_BASENAME=\"$(DRIVER)\" \
-Werror -S -o /dev/null -xc $(1) \
> /dev/null 2>&1; then echo "$(2)"; else echo "$(3)"; fi)
CC_WARNINGS := -Wall -Wstrict-prototypes
CC_OPTS := $(GLOBAL_DEFS) $(CC_WARNINGS) -DVMW_USING_KBUILD
ifdef VMX86_DEVEL
CC_OPTS += -DVMX86_DEVEL
endif
ifdef VMX86_DEBUG
CC_OPTS += -DVMX86_DEBUG
endif
include $(SRCROOT)/Makefile.kernel
else
include $(SRCROOT)/Makefile.normal
endif
#.SILENT:
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/make -f
##########################################################
# 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
# 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
#
##########################################################
CC_OPTS += -DVMMON -DVMCORE
INCLUDE := -I$(SRCROOT)/include -I$(SRCROOT)/common -I$(SRCROOT)/linux \
-I$(SRCROOT)/vmcore
EXTRA_CFLAGS := $(CC_OPTS) $(INCLUDE)
EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/autoconf/smpcall.c, -DVMW_HAVE_SMP_CALL_3ARG, )
EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/autoconf/tsc_khz.c, -DVMW_HAVE_TSC_KHZ, )
obj-m += $(DRIVER).o
$(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 \
Module.symvers Modules.symvers Module.markers modules.order \
$(foreach dir,linux/ common/ vmcore/ \
./,$(addprefix $(dir),.*.cmd .*.o.flags *.o)))
+143
View File
@@ -0,0 +1,143 @@
#!/usr/bin/make -f
##########################################################
# 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
# 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
#
##########################################################
vm_check_build = $(shell if $(CC) $(CC_OPTS) $(INCLUDE) -Werror -S -o /dev/null -xc $(1) \
> /dev/null 2>&1; then echo "$(2)"; else echo "$(3)"; fi)
####
#### DESTDIR is where the module, object files, and dependencies are built
####
DESTDIR := driver-$(VM_UNAME)
####
#### DRIVERNAME should be untouched unless you have a good reason to change
#### it. The form below is how the scripts expect it.
####
DRIVERNAME := $(DRIVER)-xxx-$(VM_UNAME)
ifneq (,$(filter x86_64%, $(shell $(CC) -dumpmachine)))
MACHINE := x86_64
else
MACHINE := x386
endif
ifdef QUIET
ECHO := @true
else
ECHO := @echo
endif
####
#### You must compile with at least -O level of optimization
#### or the module won't load.
#### If desparate, I think that bringing in <linux/bitops.h> might
#### suffice.
####
CC_WARNINGS := -Wall -Wstrict-prototypes
# Don't use -pipe or egcs-2.91.66 (shipped with RedHat) will die
CC_KFLAGS := -D__KERNEL__ -fno-strength-reduce -fno-omit-frame-pointer \
-fno-common -DKBUILD_MODNAME=$(DRIVER)
CC_KFLAGS += $(call vm_check_gcc,-falign-loops=2 -falign-jumps=2 -falign-functions=2, \
-malign-loops=2 -malign-jumps=2 -malign-functions=2)
CC_KFLAGS += $(call vm_check_gcc,-fno-strict-aliasing,)
ifeq ($(MACHINE),x86_64)
CC_KFLAGS += -mno-red-zone -mcmodel=kernel
else
# Gcc 3.0 deprecates -m486 --hpreg
CC_KFLAGS += -DCPU=586 $(call check_gcc,-march=i586,-m486)
endif
CC_OPTS := -O2 -DMODULE -DVMMON -DVMCORE $(GLOBAL_DEFS) $(CC_KFLAGS) $(CC_WARNINGS)
INCLUDE := -I$(SRCROOT)/include -I$(SRCROOT)/common -I$(SRCROOT)/linux \
-I$(SRCROOT)/vmcore -I$(HEADER_DIR)
INCLUDE += $(shell $(CC) $(INCLUDE) -E $(SRCROOT)/autoconf/geninclude.c \
| sed -n -e 's!^APATH!-I$(HEADER_DIR)/asm!p')
CC_OPTS += $(call vm_check_build, $(SRCROOT)/autoconf/smpcall.c, -DVMW_HAVE_SMP_CALL_3ARG, )
CC_OPTS += $(call vm_check_build, $(SRCROOT)/autoconf/tsc_khz.c, -DVMW_HAVE_TSC_KHZ, )
C_TARGETS_LINUX := driver.o hostif.o driverLog.o
C_TARGETS_COMMON := vmx86.o memtrack.o phystrack.o cpuid.o task.o hashFunc.o
C_TARGETS_VMCORE := moduleloop.o
C_TARGETS_LINUX_D := ${C_TARGETS_LINUX:.o=.d}
C_TARGETS_COMMON_D := ${C_TARGETS_COMMON:.o=.d}
C_TARGETS_VMCORE_D := ${C_TARGETS_VMCORE:.o=.d}
C_TARGETS := $(C_TARGETS_LINUX) $(C_TARGETS_COMMON) $(C_TARGETS_VMCORE)
####
#### Make Targets are beneath here.
####
driver: setup deps
$(MAKE) -C $(DESTDIR) -f ../Makefile SRCROOT=../$(SRCROOT) $(DRIVER).o \
INCLUDE_DEPS=1
setup:
@if [ -d $(DESTDIR) ] ; then true ; else mkdir $(DESTDIR); chmod 755 $(DESTDIR) ; fi
$(DRIVER) $(DRIVER).o: $(DRIVERNAME)
cp -f $< $@
$(DRIVERNAME): $(C_TARGETS)
$(ECHO) "Building $(DRIVERNAME)"
ld -r -o $(DRIVERNAME) $(C_TARGETS)
auto-build:
$(MAKE) driver QUIET=1
cp -f $(DESTDIR)/$(DRIVERNAME) $(SRCROOT)/../$(DRIVER).o
$(C_TARGETS_LINUX): %.o: $(SRCROOT)/linux/%.c
$(ECHO) "Compiling linux/$(<F)"
$(CC) $(CC_OPTS) $(INCLUDE) -c $<
$(C_TARGETS_COMMON): %.o: $(SRCROOT)/common/%.c
$(ECHO) "Compiling common/$(<F)"
$(CC) $(CC_OPTS) $(INCLUDE) -c $<
$(C_TARGETS_VMCORE): %.o: $(SRCROOT)/vmcore/%.c
$(ECHO) "Compiling vmcore/$(<F)"
$(CC) $(CC_OPTS) $(INCLUDE) -c $<
clean:
rm -rf $(DESTDIR)/
$(C_TARGETS_COMMON_D): %.d: $(SRCROOT)/common/%.c
$(ECHO) "Dependencies for $(<F)"
$(CC) -MM $(CC_OPTS) $(INCLUDE) $< > $@
$(C_TARGETS_LINUX_D): %.d: $(SRCROOT)/linux/%.c
$(ECHO) "Dependencies for $(<F)"
$(CC) -MM $(CC_OPTS) $(INCLUDE) $< > $@
$(C_TARGETS_VMCORE_D): %.d: $(SRCROOT)/vmcore/%.c
$(ECHO) "Dependencies for $(<F)"
$(CC) -MM $(CC_OPTS) $(INCLUDE) $< > $@
deps: setup
$(MAKE) -C $(DESTDIR) -f ../Makefile SRCROOT=../$(SRCROOT) driver_deps
driver_deps: ${C_TARGETS:.o=.d}
ifdef INCLUDE_DEPS
include ${C_TARGETS:.o=.d}
endif
.SILENT:
+14
View File
@@ -0,0 +1,14 @@
This files in this directory and its subdirectories are the kernel module
portion of the VMware Virtual Machine Monitor. In order to build, make
certain the Makefile is correct, especially in whether or not your system
is multi-processor and then just type
make
from this directory. A copy of the module will be left in
driver-<kernel version>/vmmon.o
(e.g. driver-up-2.0.32/vmmon.o).
If you have any problems or questions, send mail to support@vmware.com
+41
View File
@@ -0,0 +1,41 @@
/*********************************************************
* Copyright (C) 2003 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
*
*********************************************************/
#include "compat_version.h"
#include "compat_autoconf.h"
#ifdef CONFIG_X86_VOYAGER
APATH/mach-voyager
#endif
#ifdef CONFIG_X86_VISWS
APATH/mach-visws
#endif
#ifdef CONFIG_X86_NUMAQ
APATH/mach-numaq
#endif
#ifdef CONFIG_X86_BIGSMP
APATH/mach-bigsmp
#endif
#ifdef CONFIG_X86_SUMMIT
APATH/mach-summit
#endif
#ifdef CONFIG_X86_GENERICARCH
APATH/mach-generic
#endif
APATH/mach-default
+37
View File
@@ -0,0 +1,37 @@
/*********************************************************
* Copyright (C) 2008 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
*
*********************************************************/
/*
* Detect whether smp_call_function has 4 or 3 arguments.
* Change happened between 2.6.26 and 2.6.27-rc1.
*/
#include "compat_version.h"
#include "compat_autoconf.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
# error This compile test intentionally fails.
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
# include <linux/smp.h>
int
vmware_smp_call_function(void (*func)(void *info), void *info, int wait)
{
return smp_call_function(func, info, wait);
}
#endif
+32
View File
@@ -0,0 +1,32 @@
/*********************************************************
* Copyright (C) 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
*
*********************************************************/
/*
* Detect if tsc_khz is available.
*/
#include "compat_version.h"
#include "compat_autoconf.h"
#include <linux/cpu.h>
int
vmw_tsc_khz(void)
{
return tsc_khz;
}
+279
View File
@@ -0,0 +1,279 @@
/*********************************************************
* Copyright (C) 2011 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
*
*********************************************************/
#include "vmware.h"
#include "hostif.h"
#include "x86cpuid_asm.h"
#include "vm_asm.h"
#include "cpuid.h"
#include "apic.h"
/*
*----------------------------------------------------------------------
*
* APIC_GetMA --
*
* Return the MA of the host's APIC by reading the APIC_BASE
* MSR and applying any necessary masking.
*
* Side effects:
* None
*
* Return value:
* MA of host APIC if successful (guaranteed to be page-aligned),
* or the sentinel (MA)-1 if unsucessful or if X2 APIC mode is enabled
* since this disables the MMIO interface.
*
*----------------------------------------------------------------------
*/
MA
APIC_GetMA(void)
{
uint64 result;
CpuidVendor cpuVendor = CPUID_GetVendor();
uint32 features = CPUID_GetFeatures();
if (!CPUID_ISSET(1, EDX, MSR, features) ||
!CPUID_ISSET(1, EDX, APIC, features)) {
return (MA)-1;
}
if (cpuVendor != CPUID_VENDOR_INTEL &&
cpuVendor != CPUID_VENDOR_AMD &&
cpuVendor != CPUID_VENDOR_VIA) {
return (MA)-1;
}
/*
* Check if X2 APIC mode is enabled.
*/
if ((__GET_MSR(MSR_APIC_BASE) & APIC_MSR_X2APIC_ENABLED) != 0) {
return (MA)-1;
}
/*
* APIC is present and enabled. The CPUID[0x1].edx[APIC] bit,
* already checked, mirrors the APIC base MSR's enable bit.
*/
// Mask out goo in the low 12 bits, which is unrelated to the address.
result = __GET_MSR(MSR_APIC_BASE) & ~MASK64(PAGE_SHIFT);
/*
* On Intel, the high bits are reserved so we mask.
* On AMD, high bits are explicitly MBZ, so no need.
* Via doesn't specify, so we'll assume reserved.
*/
if (cpuVendor == CPUID_VENDOR_INTEL || cpuVendor == CPUID_VENDOR_VIA) {
/*
* Intel suggests using CPUID 0x80000008.eax[7-0] (physical
* address size), with 36 (24 bit MPNs) as a fallback.
* Via has that cpuid leaf as well.
*/
unsigned numPhysicalBits = 36;
if (CPUID_AddressSizeSupported()) {
numPhysicalBits = __GET_EAX_FROM_CPUID(0x80000008) & 0xff;
}
result &= MASK64(numPhysicalBits);
}
ASSERT_ON_COMPILE(sizeof(result) == sizeof(MA));
return result;
}
/*
*----------------------------------------------------------------------
*
* APIC_Read --
*
* Reads the given APIC register using the proper interface. Does not
* check to see if the register number is valid.
*
* Side effects:
* Yes.
*
* Return value:
* Value of the register.
*
*----------------------------------------------------------------------
*/
uint32
APIC_Read(const APICDescriptor *desc, // IN
int regNum) // IN
{
if (desc->isX2) {
return (uint32 )__GET_MSR(MSR_X2APIC_BASE + regNum);
} else {
return desc->base[regNum][0];
}
}
/*
*----------------------------------------------------------------------
*
* APIC_ReadID --
*
* Reads the APIC ID using the proper interface. The semantics of the
* ID are different in X2APIC mode so APIC_Read() should not be used.
*
* Side effects:
* None.
*
* Return value:
* APIC ID.
*
*----------------------------------------------------------------------
*/
uint32
APIC_ReadID(const APICDescriptor *desc) // IN
{
uint32 reg = APIC_Read(desc, APICR_ID);
if (desc->isX2) {
return reg;
} else {
return (reg & XAPIC_ID_MASK) >> APIC_ID_SHIFT;
}
}
/*
*----------------------------------------------------------------------
*
* APIC_Write --
*
* Writes the given value to the given APIC register using the proper
* interface. Does not check to see if the register number is valid.
*
* Side effects:
* Yes.
*
* Return value:
* None.
*
*----------------------------------------------------------------------
*/
void
APIC_Write(const APICDescriptor *desc, // IN
int regNum, // IN
uint32 val) // IN
{
if (desc->isX2) {
__SET_MSR(MSR_X2APIC_BASE + regNum, val);
} else {
desc->base[regNum][0] = val;
}
}
/*
*----------------------------------------------------------------------
*
* APIC_ReadICR --
*
* Reads the APIC ICR using the proper interface. The semantics of the
* ICR are different in X2APIC mode so APIC_Read() should not be used.
*
* Side effects:
* Yes.
*
* Return value:
* The full 64-bit value of the ICR.
*
*----------------------------------------------------------------------
*/
uint64
APIC_ReadICR(const APICDescriptor *desc) // IN
{
if (desc->isX2) {
return __GET_MSR(MSR_X2APIC_BASE + APICR_ICRLO);
} else {
uint32 icrHi = desc->base[APICR_ICRHI][0];
uint32 icrLo = desc->base[APICR_ICRLO][0];
return (uint64) icrHi << 32 | icrLo;
}
}
/*
*----------------------------------------------------------------------
*
* APIC_WriteICR --
*
* Writes the given value to the APIC ICR using the proper interface.
* The semantics of the ICR are different in X2APIC mode so APIC_Write()
* should not be used.
*
* Side effects:
* Yes.
*
* Return value:
* None.
*
*----------------------------------------------------------------------
*/
void
APIC_WriteICR(const APICDescriptor *desc, // IN
uint32 id, // IN
uint32 icrLo) // IN
{
if (desc->isX2) {
uint64 icr = (uint64) id << 32 | icrLo;
__SET_MSR(MSR_X2APIC_BASE + APICR_ICRLO, icr);
} else {
ASSERT(!(id & ~(APIC_ICRHI_DEST_MASK >> APIC_ICRHI_DEST_OFFSET)));
desc->base[APICR_ICRHI][0] = id << APIC_ICRHI_DEST_OFFSET;
desc->base[APICR_ICRLO][0] = icrLo;
}
}
/*
*----------------------------------------------------------------------
*
* APIC_MaxLvt --
*
* Reads the maximum number of LVT entries from the APIC version register.
*
* Side effects:
* No.
*
* Return value:
* The maximum number of LVT entries.
*
*----------------------------------------------------------------------
*/
uint32
APIC_MaxLVT(const APICDescriptor *desc) // IN
{
uint32 ver = APIC_Read(desc, APICR_VERSION);
return (ver >> APIC_MAX_LVT_SHIFT) & APIC_MAX_LVT_MASK;
}
+47
View File
@@ -0,0 +1,47 @@
/*********************************************************
* Copyright (C) 2011 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
*
*********************************************************/
/*
* apic.h --
*
* Some host APIC helper functions
*/
#ifndef APIC_H
#define APIC_H
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "vm_basic_types.h"
typedef struct {
Bool isX2;
volatile uint32 (*base)[4];
} APICDescriptor;
MA APIC_GetMA(void);
uint32 APIC_Read(const APICDescriptor *desc, int regNum);
void APIC_Write(const APICDescriptor *desc, int regNum, uint32 val);
void APIC_WriteICR(const APICDescriptor *desc, uint32 id, uint32 icrLo);
uint64 APIC_ReadICR(const APICDescriptor *desc);
uint32 APIC_ReadID(const APICDescriptor *desc);
uint32 APIC_MaxLVT(const APICDescriptor *desc);
#endif
+203
View File
@@ -0,0 +1,203 @@
/*********************************************************
* Copyright (C) 2006,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
* 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
*
*********************************************************/
/*
* comport.c --
*
* Simple COM1 port routines for debugging code that can't do any real
* host IO, such as the worldswitch and related.
*
* They all wait for the last character to complete transmission so if the
* system crashes immediately on return, the last character will be seen
* by the remote end.
*
* These routines do not have any external dependencies so can be called
* by any code that has privilege to access IO ports.
*
* Under Windows, they can be made to forward output to DbgPrint for
* printing via the debugger. Just have USE_DBGPRINT set to 1. If you
* let USE_DBGPRINT be 0 with Windows, make sure the comport hardware is
* powered-up by leaving Hyperterm running with the comport open, else
* Windows will power the chip down.
*/
#include "comport.h"
#include "vm_basic_asm.h" // for INB, OUTB
#if 000 // defined(_MSC_VER)
#define USE_DBGPRINT 1
#define USE_MACPORT80 0
#else
#define USE_DBGPRINT 0
#ifdef __APPLE__
#define USE_MACPORT80 1
#else
#define USE_MACPORT80 0
#endif
#endif
#if USE_DBGPRINT
void DbgPrint(char const *format, ...);
#elif !USE_MACPORT80
#define IOBASE 0x3F8 // COM1 base IO port number
#define BAUD 115200 // baud rate
#define THR 0 // transmitter holding register
#define LSR 5 // line status register
#define LSR_TE 0x20 // - transmit fifo completely empty
#define LSR_TI 0x40 // - transmitter idle
#endif
void
CP_Init(void)
{
#if !USE_DBGPRINT && !USE_MACPORT80
OUTB(IOBASE+3, 0x83); // LCR=select DLL/DLH, wordlen=8 bits
OUTB(IOBASE+0, (115200/BAUD)&255); // DLL=lo order baud rate
OUTB(IOBASE+1, (115200/BAUD)/256); // DLH=hi order baud rate
OUTB(IOBASE+3, 0x03); // LCR=select RBR/THR/IER
OUTB(IOBASE+4, 0x07); // MCR=dtr, rts, port-enable
OUTB(IOBASE+2, 0x07); // FCR=reset rcv fifo, reset xmt fifo
OUTB(IOBASE+1, 0); // IER=disable all interrupts
#endif
}
void
CP_PutChr(uint8 ch) // IN
{
#if USE_DBGPRINT
DbgPrint("%c", ch);
#elif USE_MACPORT80
int bit;
OUTB(0x80, (ch & 1) | 0x10);
for (bit = 1; bit < 64; bit ++) {
OUTB(0x80, (ch >> (bit & 7)) & 1);
}
#else
if (ch == '\n') CP_PutChr('\r');
while ((INB(IOBASE+LSR) & LSR_TE) == 0) { }
OUTB(IOBASE+THR, ch);
while ((INB(IOBASE+LSR) & LSR_TI) == 0) { }
#endif
}
void
CP_PutDec(uint32 value) // IN
{
#if USE_DBGPRINT
DbgPrint("%u", value);
#else
char s[12];
int i;
i = 0;
do {
s[i++] = (value % 10) + '0';
value /= 10;
} while (value > 0);
while (--i >= 0) CP_PutChr(s[i]);
#endif
}
void
CP_PutHexPtr(void *value) // IN
{
if (sizeof value == 8) {
CP_PutHex64((uint64)(VA)value);
}
if (sizeof value == 4) {
CP_PutHex32((uint32)(VA)value);
}
}
void
CP_PutHex64(uint64 value) // IN
{
CP_PutHex32((uint32)(value >> 32));
CP_PutHex32((uint32)value);
}
void
CP_PutHex32(uint32 value) // IN
{
#if USE_DBGPRINT
DbgPrint("%8.8X", value);
#else
CP_PutHex16((uint16)(value >> 16));
CP_PutHex16((uint16)value);
#endif
}
void
CP_PutHex16(uint16 value) // IN
{
#if USE_DBGPRINT
DbgPrint("%4.4X", value);
#else
CP_PutHex8((uint8)(value >> 8));
CP_PutHex8((uint8)value);
#endif
}
void
CP_PutHex8(uint8 value) // IN
{
#if USE_DBGPRINT
DbgPrint("%2.2X", value);
#else
CP_PutChr("0123456789ABCDEF"[(value>>4)&15]);
CP_PutChr("0123456789ABCDEF"[value&15]);
#endif
}
void
CP_PutSp(void)
{
CP_PutChr(' ');
}
void
CP_PutCrLf(void)
{
CP_PutChr('\n');
}
void
CP_PutStr(char const *s) // IN
{
#if USE_DBGPRINT
DbgPrint("%s", s);
#else
char c;
while ((c = *(s ++)) != 0) {
CP_PutChr(c);
}
#endif
}
+41
View File
@@ -0,0 +1,41 @@
/*********************************************************
* Copyright (C) 2006 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 _COMPORT_H
#define _COMPORT_H
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMX
#include "includeCheck.h"
#include "vm_basic_types.h" // for uint8, et al
void CP_Init(void);
void CP_PutChr(uint8 ch);
void CP_PutDec(uint32 value);
void CP_PutHexPtr(void *value);
void CP_PutHex64(uint64 value);
void CP_PutHex32(uint32 value);
void CP_PutHex16(uint16 value);
void CP_PutHex8(uint8 value);
void CP_PutSp(void);
void CP_PutCrLf(void);
void CP_PutStr(char const *s);
#endif
+209
View File
@@ -0,0 +1,209 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
#ifdef linux
/* Must come before any kernel header file --hpreg */
# include "driver-config.h"
# include <linux/string.h>
#endif
#ifdef __APPLE__
# include <string.h> // For strcmp().
#endif
#include "vmware.h"
#include "vm_assert.h"
#include "hostif.h"
#include "cpuid.h"
#include "x86cpuid_asm.h"
uint32 cpuidFeatures;
static CpuidVendor vendor = CPUID_NUM_VENDORS;
static uint32 version;
/*
*-----------------------------------------------------------------------------
*
* CPUIDExtendedSupported --
*
* Determine whether processor supports extended CPUID (0x8000xxxx)
* and how many of them.
*
* Results:
* 0 if extended CPUID is not supported
* otherwise maximum extended CPUID supported (bit 31 set)
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
static uint32
CPUIDExtendedSupported(void)
{
uint32 eax;
eax = __GET_EAX_FROM_CPUID(0x80000000);
if ((eax & 0x80000000) != 0x80000000) {
return 0;
}
return eax;
}
void
CPUID_Init(void)
{
CPUIDRegs regs;
uint32 *ptr;
char name[16];
__GET_CPUID(1, &regs);
version = regs.eax;
cpuidFeatures = regs.edx;
__GET_CPUID(0, &regs);
ptr = (uint32 *)name;
ptr[0] = regs.ebx;
ptr[1] = regs.edx;
ptr[2] = regs.ecx;
ptr[3] = 0;
if (strcmp(name, CPUID_INTEL_VENDOR_STRING_FIXED) == 0) {
vendor = CPUID_VENDOR_INTEL;
} else if (strcmp(name, CPUID_AMD_VENDOR_STRING_FIXED) == 0) {
vendor = CPUID_VENDOR_AMD;
} else if (strcmp(name, CPUID_CYRIX_VENDOR_STRING_FIXED) == 0) {
vendor = CPUID_VENDOR_CYRIX;
} else {
Warning("VMMON CPUID: Unrecognized CPU\n");
vendor = CPUID_VENDOR_UNKNOWN;
}
}
CpuidVendor
CPUID_GetVendor(void)
{
ASSERT(vendor != CPUID_NUM_VENDORS);
return vendor;
}
uint32
CPUID_GetVersion(void)
{
ASSERT(vendor != CPUID_NUM_VENDORS);
return version;
}
/*
*-----------------------------------------------------------------------------
*
* CPUID_SyscallSupported --
*
* Determine whether processor supports syscall opcode and MSRs.
*
* Results:
* FALSE if processor does not support syscall
* TRUE if processor supports syscall
*
* Side effects:
* It determines value only on first call, caching it for future.
*
*-----------------------------------------------------------------------------
*/
Bool
CPUID_SyscallSupported(void)
{
/*
* It is OK to use local static variables here as 'result' does not depend
* on any work done in CPUID_Init(). It purely depends on the CPU.
*/
static Bool initialized = FALSE;
static Bool result;
if (UNLIKELY(!initialized)) {
result = CPUIDExtendedSupported() >= 0x80000001
&& (__GET_EDX_FROM_CPUID(0x80000001) & (1 << 11));
initialized = TRUE;
}
return result;
}
Bool
CPUID_LongModeSupported(void)
{
/*
* It is OK to use local static variables here as 'result' does not depend
* on any work done in CPUID_Init(). It purely depends on the CPU.
*/
static Bool initialized = FALSE;
static Bool result;
if (UNLIKELY(!initialized)) {
result = CPUIDExtendedSupported() >= 0x80000001
&& (__GET_EDX_FROM_CPUID(0x80000001) & (1 << 29));
initialized = TRUE;
}
return result;
}
/*
*-----------------------------------------------------------------------------
*
* CPUID_AddressSizeSupported --
*
* Determine whether processor supports the address size cpuid
* extended leaf.
*
* Results:
* True iff the processor supports CPUID 0x80000008.
*
* Side effects:
* It determines value only on first call, caching it for future.
*
*-----------------------------------------------------------------------------
*/
Bool
CPUID_AddressSizeSupported(void)
{
/*
* It is OK to use local static variables here as 'result' does not depend
* on any work done in CPUID_Init(). It purely depends on the CPU.
*/
static Bool initialized = FALSE;
static Bool result;
if (UNLIKELY(!initialized)) {
result = CPUIDExtendedSupported() >= 0x80000008;
initialized = TRUE;
}
return result;
}
+56
View File
@@ -0,0 +1,56 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* cpuid.h --
*
* wrap CPUID instruction
*/
#ifndef CPUID_H
#define CPUID_H
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "x86cpuid.h"
extern uint32 cpuidFeatures;
void CPUID_Init(void);
CpuidVendor CPUID_GetVendor(void);
uint32 CPUID_GetVersion(void);
Bool CPUID_SyscallSupported(void);
Bool CPUID_LongModeSupported(void);
Bool CPUID_AddressSizeSupported(void);
static INLINE uint32
CPUID_GetFeatures(void)
{
return cpuidFeatures;
}
static INLINE Bool
CPUID_SSE2Supported(void)
{
return CPUID_ISSET(1, EDX, SSE2, CPUID_GetFeatures());
}
#endif
+41
View File
@@ -0,0 +1,41 @@
/*********************************************************
* Copyright (C) 2001 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
*
*********************************************************/
/*
* hashFunc.c --
*
* The core implementation lives in lib/shared/hashFunc.h because it
* is shared by the vmkernel and vmmon.
*/
#include "hashFunc.h"
/*
* Wrappers
*/
// arbitrary constant
#define HASH_INIT_VALUE (42)
// 64-bit hash for one 4K page
uint64
HashFunc_HashPage(const void *addr)
{
return hash2((uint64 *)addr, PAGE_SIZE / sizeof (uint64), HASH_INIT_VALUE);
}
+83
View File
@@ -0,0 +1,83 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* hostKernel.h --
*
* Definition of HOST_KERNEL_* --hpreg
*/
#ifndef __HOST_KERNEL_H__
# define __HOST_KERNEL_H__
# ifdef linux
/*
* In some cases, this files needs to include Linux kernel header file
* asm/page.h.
*
* However, asm/page.h defines PAGE_SHIFT, PAGE_SIZE, PAGE_MASK, PAGE_OFFSET
* and VMware header file vm_basic_types.h defines PAGE_SHIFT, PAGE_SIZE,
* PAGE_MASK, PAGE_OFFSET. PAGE_MASK and PAGE_OFFSET are defined differently
* (XXX we should really prefix the VMware version with VM_ to prevent any
* further confusion), but fortunately the driver does not use them.
*
* So in this file, we must solve the definition conflict for files that
* include both this file and vm_basic_types.h. 2 cases can occur:
*
* 1) this file is included before vm_basic_types.h is included. This is fine,
* because vm_basic_types.h only defines PAGE_* if they don't exist yet.
*
* 2) vm_basic_types.h is included before this file is included.
* We must undefine
* PAGE_* in between. But this only works if asm/page.h is not included
* before this file is included.
*
* In summary: if you make sure you do not include asm/page.h before you
* include this file, then we guarantee that:
* . This file and vm_basic_types.h can be included in any order
* . asm/page.h will be included
* . The PAGE_* definitions will come from asm/page.h
*
* --hpreg
*/
/* Must come before any kernel header file --hpreg */
# include "driver-config.h"
# undef PAGE_SHIFT
# undef PAGE_SIZE
# undef PAGE_MASK
# undef PAGE_OFFSET
/* For __PAGE_OFFSET --hpreg */
# include <asm/page.h>
# define HOST_KERNEL_VA_2_LA(_x) (_x)
# define HOST_KERNEL_LA_2_VA(_x) (_x)
# else
/* For VA and LA --hpreg */
# include "vm_basic_types.h"
# define HOST_KERNEL_VA_2_LA(_addr) ((LA)(_addr))
# define HOST_KERNEL_LA_2_VA(_addr) ((VA)(_addr))
# endif
#endif /* __HOST_KERNEL_H__ */
+148
View File
@@ -0,0 +1,148 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* hostif.h - Platform dependent interface for supporting
* the vmx86 device driver.
*/
#ifndef _HOSTIF_H_
#define _HOSTIF_H_
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "vmx86.h"
#include "vcpuset.h"
#include "hostifMem.h"
#include "hostifGlobalLock.h"
/*
* Host-specific definitions.
*/
#if !__linux__ && !defined(WINNT_DDK) && !defined __APPLE__
#error "Only Linux or NT or Mac OS defined for now."
#endif
/*
* The default monitor spin time for crosscalls is 50 usec
* in vmcore/vmx/main/monitor_init.c. This value is used
* in vmx86_YieldToSet to decide whether to block and wait
* for another vCPU to process our crosscall, or just wake
* up the other vCPUs and go back to monitor.
*/
#define CROSSCALL_SPIN_SHORT_US 50
/*
* Sleep timeout in usec, see above comment for CROSSCALL_SPIN_SHORT_US
*/
#define CROSSCALL_SLEEP_US 1000
/* Return value for HostIF_IPI. */
typedef enum {
IPI_NONE, // No IPI was sent.
IPI_UNICAST, // Unicast IPIs were sent.
IPI_BROADCAST // A broadcast IPI was sent to all PCPUs.
} HostIFIPIMode;
EXTERN int HostIF_Init(VMDriver *vm);
EXTERN int HostIF_LookupUserMPN(VMDriver *vm, VA64 uAddr, MPN *mpn);
EXTERN void *HostIF_MapCrossPage(VMDriver *vm, VA64 uAddr);
EXTERN void HostIF_InitFP(VMDriver *vm);
EXTERN void *HostIF_AllocPage(void);
EXTERN void HostIF_FreePage(void *ptr);
EXTERN int HostIF_LockPage(VMDriver *vm, VA64 uAddr,
Bool allowMultipleMPNsPerVA, MPN *mpn);
EXTERN int HostIF_UnlockPage(VMDriver *vm, VA64 uAddr);
EXTERN int HostIF_UnlockPageByMPN(VMDriver *vm, MPN mpn, VA64 uAddr);
EXTERN Bool HostIF_IsLockedByMPN(VMDriver *vm, MPN mpn);
EXTERN void HostIF_FreeAllResources(VMDriver *vm);
EXTERN uint64 HostIF_ReadUptime(void);
EXTERN uint64 HostIF_UptimeFrequency(void);
EXTERN unsigned int HostIF_EstimateLockedPageLimit(const VMDriver *vm,
unsigned int lockedPages);
EXTERN void HostIF_Wait(unsigned int timeoutMs);
EXTERN void HostIF_WaitForFreePages(unsigned int timeoutMs);
EXTERN void *HostIF_AllocCrossGDT(uint32 numPages, MPN maxValidFirst,
MPN *crossGDTMPNs);
EXTERN void HostIF_FreeCrossGDT(uint32 numPages, void *crossGDT);
EXTERN void HostIF_VMLock(VMDriver *vm, int callerID);
EXTERN void HostIF_VMUnlock(VMDriver *vm, int callerID);
#ifdef VMX86_DEBUG
EXTERN Bool HostIF_VMLockIsHeld(VMDriver *vm);
#endif
EXTERN Bool HostIF_APICInit(VMDriver *vm, Bool setVMPtr, Bool probe);
EXTERN int HostIF_SemaphoreWait(VMDriver *vm,
Vcpuid vcpuid,
uint64 *args);
EXTERN int HostIF_SemaphoreSignal(uint64 *args);
EXTERN void HostIF_SemaphoreForceWakeup(VMDriver *vm, const VCPUSet *vcs);
EXTERN HostIFIPIMode HostIF_IPI(VMDriver *vm, const VCPUSet *vcs);
EXTERN uint32 HostIF_GetCurrentPCPU(void);
EXTERN void HostIF_CallOnEachCPU(void (*func)(void *), void *data);
EXTERN Bool HostIF_PrepareWaitForThreads(VMDriver *vm, Vcpuid currVcpu);
EXTERN void HostIF_WaitForThreads(VMDriver *vm, Vcpuid currVcpu);
EXTERN void HostIF_CancelWaitForThreads(VMDriver *vm, Vcpuid currVcpu);
EXTERN void HostIF_WakeUpYielders(VMDriver *vm, Vcpuid currVcpu);
EXTERN int HostIF_AllocLockedPages(VMDriver *vm, VA64 addr,
unsigned int numPages, Bool kernelMPNBuffer);
EXTERN int HostIF_FreeLockedPages(VMDriver *vm, VA64 addr,
unsigned int numPages, Bool kernelMPNBuffer);
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_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)
#define HostIF_FastClockUnlock(_callerID) do {} while (0)
#else
EXTERN void HostIF_FastClockLock(int callerID);
EXTERN void HostIF_FastClockUnlock(int callerID);
#endif
EXTERN int HostIF_SetFastClockRate(unsigned rate);
EXTERN MPN HostIF_AllocMachinePage(void);
EXTERN void HostIF_FreeMachinePage(MPN mpn);
EXTERN int HostIF_SafeRDMSR(uint32 msr, uint64 *val);
#endif // ifdef _HOSTIF_H_
+45
View File
@@ -0,0 +1,45 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* hostifGlobalLock.h - Platform dependent interface. This module
* defines functions for manipulating/checking
* the Global lock used by some drivers.
*/
#ifndef _HOSTIFGLOBALLOCK_H_
#define _HOSTIFGLOBALLOCK_H_
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#ifdef __APPLE__
Bool HostIFGlobalLock_Start(void);
void HostIFGlobalLock_Stop(void);
#endif
void HostIF_GlobalLock(int callerID);
void HostIF_GlobalUnlock(int callerID);
#ifdef VMX86_DEBUG
Bool HostIF_GlobalLockIsHeld(void);
#endif
#endif // ifdef _HOSTIFGLOBALLOCK_H_
+37
View File
@@ -0,0 +1,37 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* hostifMem.h - Platform dependent interface. This module defines
* functions for allocating and releasing memory
* from the kernel.
*/
#ifndef _HOSTIFMEM_H_
#define _HOSTIFMEM_H_
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
void *HostIF_AllocKernelMem(size_t size, int nonPageable);
void HostIF_FreeKernelMem(void *ptr);
#endif // ifdef _HOSTIFMEM_H_
+551
View File
@@ -0,0 +1,551 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* memtrack.c --
*
* Utility module for tracking pinned memory, which allows later
* lookup by VPN.
*
* --
*
* Track memory using a 3-level directory, to keep allocations to one
* page in size. The first level is inlined with the MemTrack struct
* and a new page is allocated for each directory in the second level,
* as needed. The third level packs in as many MemTrackEntry structs
* on a single page as possible.
*
* Optionally use a 2-level directory on systems that prefer larger
* contiguous allocations. In this case we allow the first level
* allocation to be larger than 1 page (its size will depend on the
* maximum number of tracked pages, currently set to 4GB).
*
* MemTrack MemTrackDir1 MemTrackDir2 MemTrackDir3
* (Handle) (Optional)
*
* ---->/----------\
* | | Dir[0] |----->/----------\
* | | Dir[1] | | Entry[0] |
* | | ... | | Entry[1] |
* | | Dir[N] | | ... |
* /----------\ MEMTRACK_DIR2_ENTRIES \----------/ | Entry[N] |
* | ... | | \----------/
* | dir1 |----/----------\ | ->/----------\
* | ... |\ | Dir[0] |---- | | Dir[N+1] |
* | | \ | Dir[1] |------- | Dir[N+2] |
* \----------/ \ | ... | | ... |
* \| Dir[N] |----- | Dir[N+N] | .
* \----------/ | \----------/ .
* MEMTRACK_DIR1_ENTRIES | .
* --->/----------\
* | ... |
* | |
* | |
* | Dir[M] |----->/----------\
* \----------/ | ... |
* | |
* | |
* | Entry[M] |
* \----------/
*
* We also keep a simple chaining hash table of entries hashed on
* the VPN, for quick lookup. A separate hash table hashed on the MPN
* exists as well, but this is only used in debug builds.
*
* This tracker does not allow pages to be removed. If, in the future,
* we have a use case for removing MPNs from the tracker, a simple
* MemTrackEntry recycle scheme can be implemented at the cost of an
* additional pointer per MemTrackEntry instance.
*/
#if defined(__linux__)
/* Must come before any kernel header file. */
# include "driver-config.h"
# include <linux/string.h> /* memset() in the kernel */
#elif defined(WINNT_DDK)
# undef PAGE_SIZE /* Redefined in ntddk.h, and we use that defn. */
# undef PAGE_SHIFT
# include <ntddk.h>
#else
# include <string.h>
#endif
#include "vmware.h"
#include "hostif.h"
#include "memtrack.h"
/*
* Modify this value to increase the maximum number of tracked pages
* per MemTrack instance.
*/
#define MEMTRACK_MAX_TRACKED MBYTES_2_PAGES(4096)
/*
* Linux uses a 3-level directory, because we want to keep allocations
* to a single page.
*/
#if defined(__linux__)
#define MEMTRACK_3LEVEL (1)
#endif
#define MEMTRACK_DIR3_ENTRIES (PAGE_SIZE / sizeof (MemTrackEntry))
#if defined(MEMTRACK_3LEVEL)
#define MEMTRACK_DIR2_ENTRIES (PAGE_SIZE / sizeof (void *))
#else
#define MEMTRACK_DIR2_ENTRIES (1)
#endif
#define MEMTRACK_DIR1_ENTRIES CEILING(MEMTRACK_MAX_TRACKED, \
(MEMTRACK_DIR2_ENTRIES * \
MEMTRACK_DIR3_ENTRIES))
#define MEMTRACK_HT_SIZE (16384)
#define MEMTRACK_HT_ENTRIES (PAGE_SIZE / sizeof (void *))
#define MEMTRACK_HT_PAGES (MEMTRACK_HT_SIZE / MEMTRACK_HT_ENTRIES)
typedef struct MemTrackDir3 {
MemTrackEntry entries[MEMTRACK_DIR3_ENTRIES];
} MemTrackDir3;
#if defined(MEMTRACK_3LEVEL)
typedef struct MemTrackDir2 {
MemTrackDir3 *dir[MEMTRACK_DIR2_ENTRIES];
} MemTrackDir2;
#else
typedef struct MemTrackDir3 MemTrackDir2;
#endif
typedef struct MemTrackDir1 {
MemTrackDir2 *dir[MEMTRACK_DIR1_ENTRIES];
} MemTrackDir1;
typedef struct MemTrackHTPage {
MemTrackEntry *entries[MEMTRACK_HT_ENTRIES];
} MemTrackHTPage;
typedef struct MemTrackHT {
MemTrackHTPage *pages[MEMTRACK_HT_PAGES];
} MemTrackHT;
typedef uint64 MemTrackHTKey;
typedef struct MemTrack {
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;
/*
* The following functions and macros help allocate and access the
* directory structure. This is convenient because the second level
* directory is optional.
*/
#define MEMTRACK_IDX2DIR(_idx, _p1, _p2, _p3) \
do { \
_p1 = _idx / (MEMTRACK_DIR2_ENTRIES * MEMTRACK_DIR3_ENTRIES); \
_p2 = (_idx / MEMTRACK_DIR3_ENTRIES) % MEMTRACK_DIR2_ENTRIES; \
_p3 = _idx % MEMTRACK_DIR3_ENTRIES; \
} while (0)
#define MEMTRACK_GETDIR2(_dir1, _p1) (_dir1->dir[_p1])
#define MEMTRACK_ALLOCDIR2(_dir1, _p1) MemTrackAllocDir2(_dir1, _p1)
#define MEMTRACK_FREEDIR2(_dir1) HostIF_FreePage(_dir1)
#if defined(MEMTRACK_3LEVEL)
#define MEMTRACK_GETENTRY(_dir1, _p1, _p2, _p3) \
(&((_dir1->dir[_p1])->dir[_p2])->entries[_p3])
#define MEMTRACK_GETDIR3(_dir2, _p2) (_dir2->dir[_p2])
#define MEMTRACK_ALLOCDIR3(_dir2, _p2) MemTrackAllocDir3(_dir2, _p2)
#define MEMTRACK_FREEDIR3(_dir2) HostIF_FreePage(_dir2)
#else
#define MEMTRACK_GETENTRY(_dir1, _p1, _p2, _p3) \
(&(_dir1->dir[_p1])->entries[_p3])
#define MEMTRACK_GETDIR3(_dir2, _p2) (_dir2)
#define MEMTRACK_ALLOCDIR3(_dir2, _p2) (_dir2)
#define MEMTRACK_FREEDIR3(_dir2)
#endif
static INLINE void *
MemTrackAllocPage(void)
{
void *ptr = HostIF_AllocPage();
if (ptr != NULL) {
memset(ptr, 0, PAGE_SIZE);
}
return ptr;
}
#define MEMTRACK_ALLOCDFN(_name, _itype, _otype) \
static INLINE _otype * \
_name(_itype *arg, unsigned pos) \
{ \
if (arg->dir[pos] == NULL) { \
arg->dir[pos] = MemTrackAllocPage(); \
} \
return arg->dir[pos]; \
}
#if defined(MEMTRACK_3LEVEL)
MEMTRACK_ALLOCDFN(MemTrackAllocDir3, MemTrackDir2, MemTrackDir3)
#endif
MEMTRACK_ALLOCDFN(MemTrackAllocDir2, MemTrackDir1, MemTrackDir2)
/*
*----------------------------------------------------------------------
*
* MemTrackHTLookup --
* MemTrackHTInsert --
*
* Helper functions to insert or lookup entries in the VPN or
* MPN hash tables. Hash tables are always allocated in page
* size chunks.
*
*----------------------------------------------------------------------
*/
#define MEMTRACK_HASHKEY(_key, _hash, _page, _pos) \
do { \
_hash = _key % MEMTRACK_HT_SIZE; \
_page = _hash / MEMTRACK_HT_ENTRIES; \
_pos = _hash % MEMTRACK_HT_ENTRIES; \
} while(0)
static INLINE MemTrackEntry **
MemTrackHTLookup(MemTrackHT *ht, // IN
MemTrackHTKey key) // IN
{
uint64 hash, page, pos;
MEMTRACK_HASHKEY(key, hash, page, pos);
return &ht->pages[page]->entries[pos];
}
static INLINE void
MemTrackHTInsert(MemTrackHT *ht, // IN
MemTrackEntry *ent, // IN
MemTrackEntry **chain, // OUT
MemTrackHTKey key) // IN
{
MemTrackEntry **head = MemTrackHTLookup(ht, key);
*chain = *head;
*head = ent;
}
/*
*----------------------------------------------------------------------
*
* MemTrackCleanup --
*
* Deallocate all memory associated with the specified tracker.
*
* Results:
* None.
*
* Side effects:
* Memory deallocation.
*
*----------------------------------------------------------------------
*/
static void
MemTrackCleanup(MemTrack *mt) // IN
{
unsigned idx;
unsigned p1;
MemTrackDir1 *dir1;
if (mt == NULL) {
return;
}
dir1 = &mt->dir1;
for (p1 = 0; p1 < MEMTRACK_DIR1_ENTRIES; p1++) {
unsigned p2;
MemTrackDir2 *dir2 = MEMTRACK_GETDIR2(dir1, p1);
if (dir2 == NULL) {
break;
}
for (p2 = 0; p2 < MEMTRACK_DIR2_ENTRIES; p2++) {
MemTrackDir3 *dir3 = MEMTRACK_GETDIR3(dir2, p2);
if (dir3 == NULL) {
break;
}
MEMTRACK_FREEDIR3(dir3);
}
MEMTRACK_FREEDIR2(dir2);
}
for (idx = 0; idx < MEMTRACK_HT_PAGES; idx++) {
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);
}
/*
*----------------------------------------------------------------------
*
* MemTrack_Init --
*
* Allocate and initialize the tracker.
*
* Results:
* Handle used to access the tracker.
*
* Side effects:
* Memory allocation.
*
*----------------------------------------------------------------------
*/
MemTrack *
MemTrack_Init(void)
{
MemTrack *mt;
unsigned idx;
#if defined(MEMTRACK_3LEVEL)
ASSERT_ON_COMPILE(sizeof *mt <= PAGE_SIZE);
ASSERT_ON_COMPILE(sizeof (MemTrackDir2) == PAGE_SIZE);
#endif
ASSERT_ON_COMPILE(sizeof (MemTrackDir3) <= PAGE_SIZE);
mt = HostIF_AllocKernelMem(sizeof *mt, FALSE);
if (mt == NULL) {
Warning("MemTrack failed to allocate handle.\n");
goto error;
}
memset(mt, 0, sizeof *mt);
for (idx = 0; idx < MEMTRACK_HT_PAGES; idx++) {
MemTrackHTPage *htPage = MemTrackAllocPage();
if (htPage == NULL) {
Warning("MemTrack failed to allocate VPN hash table (%d).\n", idx);
goto error;
}
mt->vpnHashTable.pages[idx] = htPage;
}
#if defined(MEMTRACK_MPN_LOOKUP)
for (idx = 0; idx < MEMTRACK_HT_PAGES; idx++) {
MemTrackHTPage *htPage = MemTrackAllocPage();
if (htPage == NULL) {
Warning("MemTrack failed to allocate MPN hash table (%d).\n", idx);
goto error;
}
mt->mpnHashTable.pages[idx] = htPage;
}
#endif
return mt;
error:
MemTrackCleanup(mt);
return NULL;
}
/*
*----------------------------------------------------------------------
*
* MemTrack_Add --
*
* Add the specified VPN:MPN pair to the memory tracker.
*
* Results:
* A pointer to the element, or NULL on error.
*
* Side effects:
* Memory allocation.
*
*----------------------------------------------------------------------
*/
MemTrackEntry *
MemTrack_Add(MemTrack *mt, // IN
VPN64 vpn, // IN
MPN mpn) // IN
{
unsigned idx = mt->numPages;
unsigned p1, p2, p3;
MemTrackEntry *ent;
MemTrackDir1 *dir1 = &mt->dir1;
MemTrackDir2 *dir2;
MemTrackDir3 *dir3;
MEMTRACK_IDX2DIR(idx, p1, p2, p3);
if (p1 >= MEMTRACK_DIR1_ENTRIES ||
p2 >= MEMTRACK_DIR2_ENTRIES ||
p3 >= MEMTRACK_DIR3_ENTRIES) {
return NULL;
}
dir2 = MEMTRACK_ALLOCDIR2(dir1, p1);
if (dir2 == NULL) {
return NULL;
}
dir3 = MEMTRACK_ALLOCDIR3(dir2, p2);
if (dir3 == NULL) {
return NULL;
}
ent = MEMTRACK_GETENTRY(dir1, p1, p2, p3);
ent->vpn = vpn;
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++;
return ent;
}
/*
*----------------------------------------------------------------------
*
* MemTrack_LookupVPN --
*
* Lookup the specified VPN address in the memory tracker.
*
* Results:
* A pointer to the element, or NULL if not there.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
MemTrackEntry *
MemTrack_LookupVPN(MemTrack *mt, // IN
VPN64 vpn) // IN
{
MemTrackEntry *next = *MemTrackHTLookup(&mt->vpnHashTable, vpn);
while (next != NULL) {
if (next->vpn == vpn) {
return next;
}
next = next->vpnChain;
}
return NULL;
}
#if defined(MEMTRACK_MPN_LOOKUP)
/*
*----------------------------------------------------------------------
*
* MemTrack_LookupMPN --
*
* Lookup the specified MPN address in the memory tracker.
*
* Results:
* A pointer to the element, or NULL if not there.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
MemTrackEntry *
MemTrack_LookupMPN(MemTrack *mt, // IN
MPN mpn) // IN
{
MemTrackEntry *next = *MemTrackHTLookup(&mt->mpnHashTable, mpn);
while (next != NULL) {
if (next->mpn == mpn) {
return next;
}
next = next->mpnChain;
}
return NULL;
}
#endif
/*
*----------------------------------------------------------------------
*
* MemTrack_Cleanup --
*
* Cleanup all resources allocated for the tracker. For
* all pages in the tracker call the user provided clean up
* function.
*
* Results:
* Number of pages in the tracker.
*
* Side effects:
* Memory deallocation.
*
*----------------------------------------------------------------------
*/
unsigned
MemTrack_Cleanup(MemTrack *mt, // IN
MemTrackCleanupCb *cb, // IN
void *cData) // IN
{
unsigned idx;
unsigned count = 0;
for (idx = 0; idx < mt->numPages; idx++) {
unsigned p1, p2, p3;
MemTrackEntry *ent;
MemTrackDir1 *dir1 = &mt->dir1;
MEMTRACK_IDX2DIR(idx, p1, p2, p3);
ent = MEMTRACK_GETENTRY(dir1, p1, p2, p3);
cb(cData, ent);
count++;
}
MemTrackCleanup(mt);
return count;
}
+60
View File
@@ -0,0 +1,60 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* memtrack.h --
*
* Utility module for tracking pinned memory, which allows later
* lookup by VPN.
*/
#ifndef _MEMTRACK_H_
#define _MEMTRACK_H_
#define INCLUDE_ALLOW_VMMON
#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 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_
+495
View File
@@ -0,0 +1,495 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* phystrack.c --
*
* track down the utilization of the physical pages.
*
* Depending on configuration phystracker provides either 2-level or
* 3-level structure to track whether page (specified by its MPN) is
* locked or no. Linux uses 3-level structures with top limit of
* 1TB (32bit) or 16TB (64bit). Windows use 2-level structures
* ready to hold 128GB (32bit) or 2TB (64bit) of memory. On Mac
* limit is 2-level 128GB.
*
* 2-level phystracker is built on top of 3-level one by collapsing
* middle level.
*/
#ifdef linux
/* Must come before any kernel header file --hpreg */
# include "driver-config.h"
# include <linux/string.h> /* memset() in the kernel */
#else
# include <string.h>
#endif
#include "vmware.h"
#include "vmx86.h"
#include "phystrack.h"
#include "hostif.h"
#define BYTES_PER_ENTRY (PAGE_SIZE)
#define PHYSTRACK_L3_ENTRIES (8 * BYTES_PER_ENTRY) /* 128MB */
#if defined(WINNT_DDK)
#define PHYSTRACK_L1_ENTRIES (PHYSTRACK_MAX_SUPPORTED_GB * 8)
#elif defined(__linux__)
#define PHYSTRACK_L2_ENTRIES (BYTES_PER_ENTRY / sizeof(void *)) /* 64GB or 128GB */
/*
* Currently MPN is 32 bits. 15 bits are in L3, 9 bits are in L2,
* leaving 8 bits for L1...
*/
#define PHYSTRACK_L1_ENTRIES (256) /* 16TB. */
#else
#define PHYSTRACK_L1_ENTRIES ((128 + 4) * 8) /* 128 GB */
#endif
#ifndef PHYSTRACK_L2_ENTRIES
#define PHYSTRACK_L2_ENTRIES (1)
#else
#define PHYSTRACK_3LEVEL (1)
#endif
typedef struct PhysTrackerL3 {
uint8 bits[BYTES_PER_ENTRY];
} PhysTrackerL3;
#ifdef PHYSTRACK_3LEVEL
typedef struct PhysTrackerL2 {
PhysTrackerL3 *dir[PHYSTRACK_L2_ENTRIES];
} PhysTrackerL2;
#else
typedef struct PhysTrackerL3 PhysTrackerL2;
#endif
typedef struct PhysTracker {
VMDriver *vm; /* Used only for debugging and asserts. */
PhysTrackerL2 *dir[PHYSTRACK_L1_ENTRIES];
} PhysTracker;
/*
* Convert MPN to p1, p2, and p3 indices. p1/p2/p3 must be l-values.
* Currently we support a 64 bit container for an MPN
* in hosted but not an actual 64 bit value as no hosted OS
* supports this yet. Hence in PhysMem tracker we are deliberately using
* a 32-bit container to save memory. Also the tracker is allocating pages
* considering the MPN to be a 32 bit value. This will change once we get
* systems supporting 64 bit memory/addressing space.
* Until then let us assert if a value greater than 32 bit is being passed.
*/
#define PHYSTRACK_MPN2IDX(mpn, p1, p2, p3) \
do { \
ASSERT((mpn >> 32) == 0); \
p2 = (unsigned)(mpn) / PHYSTRACK_L3_ENTRIES; \
p1 = p2 / PHYSTRACK_L2_ENTRIES; \
p2 = p2 % PHYSTRACK_L2_ENTRIES; \
p3 = (unsigned)(mpn) % PHYSTRACK_L3_ENTRIES; \
} while (0)
/*
* Convert L3 index to offset and bitmask. offs/bitmask must be l-values.
*/
#define PHYSTRACK_GETL3POS(p3, offs, bitmask) \
do { \
offs = (p3) / 8; \
bitmask = 1 << ((p3) % 8); \
} while (0)
/*
* Helpers hiding middle level.
*/
#ifdef PHYSTRACK_3LEVEL
#define PHYSTRACK_GETL3(dir2, p2) (dir2)->dir[(p2)]
#define PHYSTRACK_ALLOCL3(dir2, p2) PhysTrackAllocL3((dir2), (p2))
#define PHYSTRACK_FREEL3(dir2, p2) PhysTrackFreeL3((dir2), (p2))
#else
#define PHYSTRACK_GETL3(dir2, p2) (dir2)
#define PHYSTRACK_ALLOCL3(dir2, p2) (dir2)
#define PHYSTRACK_FREEL3(dir2, p2) do { } while (0)
#endif
#ifdef PHYSTRACK_3LEVEL
/*
*----------------------------------------------------------------------
*
* PhysTrackAllocL3 --
*
* Allocate and hook L3 table to the L2 directory if does not exist.
* Or get existing one if it exists.
*
* Results:
* L3 table.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE_SINGLE_CALLER PhysTrackerL3 *
PhysTrackAllocL3(PhysTrackerL2 *dir2,
unsigned int p2)
{
PhysTrackerL3 *dir3;
dir3 = dir2->dir[p2];
if (!dir3) {
ASSERT_ON_COMPILE(sizeof *dir3 == PAGE_SIZE);
dir3 = HostIF_AllocPage();
if (!dir3) {
PANIC();
}
memset(dir3, 0, sizeof *dir3);
dir2->dir[p2] = dir3;
}
return dir3;
}
/*
*----------------------------------------------------------------------
*
* PhysTrackFreeL3 --
*
* Unhook L3 table from L2 directory, and free it.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE_SINGLE_CALLER void
PhysTrackFreeL3(PhysTrackerL2 *dir2,
unsigned int p2)
{
HostIF_FreePage(dir2->dir[p2]);
dir2->dir[p2] = NULL;
}
#endif
/*
*----------------------------------------------------------------------
*
* PhysTrack_Alloc --
*
* Create new PhysTracker.
*
* Results:
* Creates new PhysTracker.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
PhysTracker *
PhysTrack_Alloc(VMDriver *vm)
{
PhysTracker *tracker;
ASSERT(vm != NULL);
/* allocate a new phystracker */
tracker = HostIF_AllocKernelMem(sizeof *tracker, FALSE);
if (tracker) {
memset(tracker, 0, sizeof *tracker);
tracker->vm = vm;
} else {
Warning("%s failed\n", __FUNCTION__);
}
return tracker;
}
/*
*----------------------------------------------------------------------
*
* PhysTrack_Free --
*
* module deallocation
*
* Results:
* reallocates all structures, including 'tracker'
*
* Side effects:
* tracker deallocated
*
*----------------------------------------------------------------------
*/
void
PhysTrack_Free(PhysTracker *tracker)
{
unsigned int p1;
ASSERT(tracker);
for (p1 = 0; p1 < PHYSTRACK_L1_ENTRIES; p1++) {
PhysTrackerL2 *dir2 = tracker->dir[p1];
if (dir2) {
unsigned int p2;
for (p2 = 0; p2 < PHYSTRACK_L2_ENTRIES; p2++) {
PhysTrackerL3 *dir3 = PHYSTRACK_GETL3(dir2, p2);
if (dir3) {
unsigned int pos;
for (pos = 0; pos < BYTES_PER_ENTRY; pos++) {
if (dir3->bits[pos]) {
Warning("%s: pfns still locked\n", __FUNCTION__);
PANIC();
}
}
PHYSTRACK_FREEL3(dir2, p2);
}
}
HostIF_FreePage(dir2);
tracker->dir[p1] = NULL;
}
}
HostIF_FreeKernelMem(tracker);
}
/*
*----------------------------------------------------------------------
*
* PhysTrack_Add --
*
* add a page to the core map tracking.
*
* Results:
* void
*
* Side effects:
* Fatal if the page is already tracked.
*
*----------------------------------------------------------------------
*/
void
PhysTrack_Add(PhysTracker *tracker, // IN/OUT
MPN mpn) // IN: MPN of page to be added
{
unsigned int p1;
unsigned int p2;
unsigned int p3;
unsigned int pos;
unsigned int bit;
PhysTrackerL2 *dir2;
PhysTrackerL3 *dir3;
ASSERT(tracker);
ASSERT(HostIF_VMLockIsHeld(tracker->vm));
PHYSTRACK_MPN2IDX(mpn, p1, p2, p3);
ASSERT(p1 < PHYSTRACK_L1_ENTRIES);
dir2 = tracker->dir[p1];
if (!dir2) {
// more efficient with page alloc
ASSERT_ON_COMPILE(sizeof *dir2 == PAGE_SIZE);
dir2 = HostIF_AllocPage();
if (!dir2) {
PANIC();
}
memset(dir2, 0, sizeof *dir2);
tracker->dir[p1] = dir2;
}
dir3 = PHYSTRACK_ALLOCL3(dir2, p2);
PHYSTRACK_GETL3POS(p3, pos, bit);
if (dir3->bits[pos] & bit) {
PANIC();
}
dir3->bits[pos] |= bit;
}
/*
*----------------------------------------------------------------------
*
* PhysTrack_Remove --
*
* remove a page from the core map tracking
*
* Results:
* void
*
* Side effects:
* Fatal if the page is not tracked
*
*----------------------------------------------------------------------
*/
void
PhysTrack_Remove(PhysTracker *tracker, // IN/OUT
MPN mpn) // IN: MPN of page to be removed.
{
unsigned int p1;
unsigned int p2;
unsigned int p3;
unsigned int pos;
unsigned int bit;
PhysTrackerL2 *dir2;
PhysTrackerL3 *dir3;
ASSERT(tracker);
ASSERT(HostIF_VMLockIsHeld(tracker->vm));
PHYSTRACK_MPN2IDX(mpn, p1, p2, p3);
ASSERT(p1 < PHYSTRACK_L1_ENTRIES);
dir2 = tracker->dir[p1];
if (!dir2) {
PANIC();
}
dir3 = PHYSTRACK_GETL3(dir2, p2);
if (!dir3) {
PANIC();
}
PHYSTRACK_GETL3POS(p3, pos, bit);
if (!(dir3->bits[pos] & bit)) {
PANIC();
}
dir3->bits[pos] &= ~bit;
}
/*
*----------------------------------------------------------------------
*
* PhysTrack_Test --
*
* tests whether a page is being tracked
*
* Results:
* TRUE if the page is tracked
* FALSE otherwise
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Bool
PhysTrack_Test(const PhysTracker *tracker, // IN
MPN mpn) // IN: MPN of page to be tested.
{
unsigned int p1;
unsigned int p2;
unsigned int p3;
unsigned int pos;
unsigned int bit;
PhysTrackerL2 *dir2;
PhysTrackerL3 *dir3;
ASSERT(tracker);
ASSERT(HostIF_VMLockIsHeld(tracker->vm));
PHYSTRACK_MPN2IDX(mpn, p1, p2, p3);
if (p1 >= PHYSTRACK_L1_ENTRIES) {
return FALSE;
}
dir2 = tracker->dir[p1];
if (!dir2) {
return FALSE;
}
dir3 = PHYSTRACK_GETL3(dir2, p2);
if (!dir3) {
return FALSE;
}
PHYSTRACK_GETL3POS(p3, pos, bit);
return (dir3->bits[pos] & bit) != 0;
}
/*
*----------------------------------------------------------------------
*
* PhysTrack_GetNext --
*
* Return next tracked page
*
* Results:
* MPN when some tracked page was found
* INVALID_MPN otherwise.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
MPN
PhysTrack_GetNext(const PhysTracker *tracker, // IN
MPN mpn) // IN: MPN of page to be tracked.
{
unsigned int p1;
unsigned int p2;
unsigned int p3;
if (mpn == INVALID_MPN) {
mpn = 0; /* First iteration. */
} else {
mpn++; /* We want the next MPN. */
}
PHYSTRACK_MPN2IDX(mpn, p1, p2, p3);
ASSERT(tracker);
ASSERT(HostIF_VMLockIsHeld(tracker->vm));
for (; p1 < PHYSTRACK_L1_ENTRIES; p1++) {
PhysTrackerL2 *dir2;
dir2 = tracker->dir[p1];
if (dir2) {
for (; p2 < PHYSTRACK_L2_ENTRIES; p2++) {
PhysTrackerL3 *dir3;
dir3 = PHYSTRACK_GETL3(dir2, p2);
if (dir3) {
for (; p3 < PHYSTRACK_L3_ENTRIES; p3++) {
unsigned int pos;
unsigned int bit;
PHYSTRACK_GETL3POS(p3, pos, bit);
if (dir3->bits[pos] & bit) {
return (p1 * PHYSTRACK_L2_ENTRIES + p2) * PHYSTRACK_L3_ENTRIES + p3;
}
}
}
p3 = 0;
}
}
p2 = 0; p3 = 0;
}
return INVALID_MPN;
}
+54
View File
@@ -0,0 +1,54 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* phystrack.h --
*
* track down the utilization of the physical pages
*/
#ifndef PHYSTRACK_H
#define PHYSTRACK_H
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#if defined(WINNT_DDK)
/* XXX: can be more efficient based on server vs. desktop and version of Windows */
#define PHYSTRACK_MAX_SUPPORTED_GB (2048 + 4) /* 2 TB 64-bit W2k8 + 4 GB PCI */
#endif
struct PhysTracker;
struct VMDriver;
EXTERN struct PhysTracker *PhysTrack_Alloc(struct VMDriver *vm);
EXTERN void PhysTrack_Free(struct PhysTracker *);
EXTERN void PhysTrack_Add(struct PhysTracker *, MPN);
EXTERN void PhysTrack_Remove(struct PhysTracker *, MPN);
EXTERN Bool PhysTrack_Test(const struct PhysTracker *, MPN);
EXTERN MPN PhysTrack_GetNext(const struct PhysTracker *, MPN);
#endif
File diff suppressed because it is too large. Load diff
+43
View File
@@ -0,0 +1,43 @@
/*********************************************************
* 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
* 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 TASK_H
#define TASK_H
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
struct InitBlock;
struct InitCrossGDT;
extern Bool Task_AllocCrossGDT(struct InitBlock *initBlock);
extern int Task_InitCrosspage(VMDriver *vm, struct InitBlock *params);
extern int Task_InitCrossGDT(struct InitCrossGDT *initCrossGDT);
extern void Task_Switch(VMDriver *vm, Vcpuid vcpuid);
extern Bool Task_Initialize(void);
extern void Task_Terminate(void);
extern MPN Task_GetHVRootPageForPCPU(uint32 pCPU);
extern Descriptor *Task_GetTmpGDT(uint32 pCPU);
#endif
File diff suppressed because it is too large. Load diff
+201
View File
@@ -0,0 +1,201 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* vmx86.h - Platform independent data and interface for supporting
* the vmx86 device driver.
*/
#ifndef VMX86_H
#define VMX86_H
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "x86apic.h"
#include "x86msr.h"
#include "modulecall.h"
#include "vcpuid.h"
#include "initblock.h"
#include "iocontrols.h"
#include "numa_defs.h"
#include "rateconv.h"
#include "vmmem_shared.h"
#include "apic.h"
typedef struct PseudoTSCOffsetInfo {
uint32 inVMMCnt; /* Number of vcpus executing in the VMM. */
uint32 vcpuid; /* Index into VMDriver.ptscOffsets. */
} PseudoTSCOffsetInfo;
typedef struct TSCDelta {
Atomic_uint64 min;
Atomic_uint64 max;
} TSCDelta;
/*
* VMDriver - the main data structure for the driver side of a
* virtual machine.
*/
typedef struct VMDriver {
/* Unique (in the driver), strictly positive, VM ID used by userland. */
int userID;
struct VMDriver *nextDriver; /* Next on list of all VMDrivers */
Vcpuid numVCPUs; /* Number of vcpus in VM. */
struct VMHost *vmhost; /* Host-specific fields. */
/* Pointers to the crossover pages shared with the monitor. */
struct VMCrossPage *crosspage[MAX_INITBLOCK_CPUS];
volatile uint32 currentHostCpu[MAX_INITBLOCK_CPUS];
VCPUSet crosscallWaitSet[MAX_INITBLOCK_CPUS];
APICDescriptor hostAPIC;
struct MemTrack *memtracker; /* Memory tracker pointer */
Bool checkFuncFailed;
struct PerfCounter *perfCounter;
VMMemMgmtInfo memInfo;
unsigned fastClockRate;/* Protected by FastClockLock. */
int fastSuspResFlag;
volatile PseudoTSCOffsetInfo ptscOffsetInfo; /* Volatile per PR 699101#29. */
Atomic_uint64 ptscLatest;
int64 ptscOffsets[MAX_INITBLOCK_CPUS];
} VMDriver;
typedef struct VmTimeStart {
uint64 count;
uint64 time;
} VmTimeStart;
typedef struct RefClockParams {
RateConv_Ratio ratio;
Atomic_uint64 add;
} RefClockParams;
typedef struct PseudoTSC {
RefClockParams refClockToPTSC;
int64 tscOffset;
uint64 hz;
volatile Bool useRefClock;
Bool neverSwitchToRefClock;
Bool hwTSCsSynced;
volatile Bool initialized;
} PseudoTSC;
extern PseudoTSC pseudoTSC;
#define MAX_LOCKED_PAGES (-1)
extern VMDriver *Vmx86_CreateVM(void);
extern int Vmx86_ReleaseVM(VMDriver *vm);
extern int Vmx86_InitVM(VMDriver *vm, InitBlock *initParams);
extern int Vmx86_LateInitVM(VMDriver *vm);
extern int Vmx86_RunVM(VMDriver *vm, Vcpuid vcpuid);
extern void Vmx86_YieldToSet(VMDriver *vm, Vcpuid currVcpu, const VCPUSet *req,
uint32 usecs, Bool skew);
extern void Vmx86_ReadTSCAndUptime(VmTimeStart *st);
extern uint32 Vmx86_ComputekHz(uint64 cycles, uint64 uptime);
extern uint32 Vmx86_GetkHzEstimate(VmTimeStart *st);
extern int Vmx86_SetHostClockRate(VMDriver *vm, unsigned rate);
extern int Vmx86_LockPage(VMDriver *vm,
VA64 uAddr,
Bool allowMultipleMPNsPerVA,
MPN *mpn);
extern int Vmx86_UnlockPage(VMDriver *vm, VA64 uAddr);
extern int Vmx86_UnlockPageByMPN(VMDriver *vm, MPN mpn, VA64 uAddr);
extern MPN Vmx86_GetRecycledPage(VMDriver *vm);
extern int Vmx86_ReleaseAnonPage(VMDriver *vm, MPN mpn);
extern int Vmx86_AllocLockedPages(VMDriver *vm, VA64 addr,
unsigned numPages, Bool kernelMPNBuffer,
Bool ignoreLimits);
extern int Vmx86_FreeLockedPages(VMDriver *vm, VA64 addr,
unsigned numPages, Bool kernelMPNBuffer);
extern MPN Vmx86_GetNextAnonPage(VMDriver *vm, MPN mpn);
extern int Vmx86_GetLockedPageList(VMDriver *vm, VA64 uAddr,
unsigned int numPages);
extern int32 Vmx86_GetNumVMs(void);
extern int32 Vmx86_GetTotalMemUsage(void);
extern Bool Vmx86_SetConfiguredLockedPagesLimit(unsigned limit);
extern void Vmx86_SetDynamicLockedPagesLimit(unsigned limit);
extern Bool Vmx86_GetMemInfo(VMDriver *curVM,
Bool curVMOnly,
VMMemInfoArgs *args,
int outArgsLength);
extern void Vmx86_Admit(VMDriver *curVM, VMMemInfoArgs *args);
extern Bool Vmx86_Readmit(VMDriver *curVM, OvhdMem_Deltas *delta);
extern void Vmx86_UpdateMemInfo(VMDriver *curVM,
const VMMemMgmtInfoPatch *patch);
extern void Vmx86_Add2MonPageTable(VMDriver *vm, VPN vpn, MPN mpn,
Bool readOnly);
extern Bool Vmx86_PAEEnabled(void);
extern Bool Vmx86_VMXEnabled(void);
extern Bool Vmx86_GetAllMSRs(MSRQuery *query);
extern void Vmx86_MonTimerIPI(void);
extern void Vmx86_InitIDList(void);
extern VMDriver *Vmx86_LookupVMByUserID(int userID);
extern Bool Vmx86_FastSuspResSetOtherFlag(VMDriver *vm, int otherVmUserId);
extern int Vmx86_FastSuspResGetMyFlag(VMDriver *vm, Bool blockWait);
extern void Vmx86_Open(void);
extern void Vmx86_Close(void);
static INLINE Bool
Vmx86_HwTSCsSynced(void)
{
return pseudoTSC.hwTSCsSynced;
}
static INLINE Bool
Vmx86_PseudoTSCUsesRefClock(void)
{
return pseudoTSC.useRefClock;
}
static INLINE Bool
Vmx86_SetPseudoTSCUseRefClock(void)
{
if (!pseudoTSC.useRefClock && !pseudoTSC.neverSwitchToRefClock) {
pseudoTSC.useRefClock = TRUE;
return TRUE;
}
return FALSE;
}
static INLINE uint64
Vmx86_GetPseudoTSCHz(void)
{
return pseudoTSC.hz;
}
static INLINE uint64
Vmx86_GetPseudoTSCOffset(void)
{
return pseudoTSC.tscOffset;
}
extern void Vmx86_InitPseudoTSC(PTSCInitParams *params);
extern Bool Vmx86_CheckPseudoTSC(uint64 *lastTSC, uint64 *lastRC);
extern uint64 Vmx86_GetPseudoTSC(void);
extern uint64 Vmx86_GetUnavailablePerfCtrs(void);
#endif
+95
View File
@@ -0,0 +1,95 @@
/*********************************************************
* Copyright (C) 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
* 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
*
*********************************************************/
/*
* address_defs.h --
*
* Macros for virtual/physical/machine address/page conversions, page types.
*/
#ifndef _ADDRESS_DEFS_H_
#define _ADDRESS_DEFS_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#include "includeCheck.h"
#include "vm_basic_defs.h" // For PAGE_SHIFT
/*
* Virtual, physical, machine address and page conversion macros
*/
#define VA_2_VPN(_va) ((_va) >> PAGE_SHIFT)
#define PTR_2_VPN(_ptr) VA_2_VPN((VA)(_ptr))
#define VPN_2_VA(_vpn) ((_vpn) << PAGE_SHIFT)
#define VPN_2_PTR(_vpn) ((void *)VPN_2_VA(_vpn))
/*
* Notice that we don't cast PA_2_PPN's argument to an unsigned type, because
* we would lose compile-time checks for pointer operands and byte-sized
* operands. If you use a signed quantity for _pa, ones may be shifted into the
* high bits of your ppn.
*/
#define PA_2_PPN(_pa) ((_pa) >> PAGE_SHIFT)
#define PPN_2_PA(_ppn) ((PA)(_ppn) << PAGE_SHIFT)
static INLINE MA MPN_2_MA(MPN mpn) { return (MA)mpn << PAGE_SHIFT; }
static INLINE MPN MA_2_MPN(MA ma) { return (MPN)(ma >> PAGE_SHIFT); }
static INLINE IOA IOPN_2_IOA(IOPN iopn) { return (IOA)(iopn << PAGE_SHIFT); }
static INLINE IOPN IOA_2_IOPN(IOA ioa) { return (IOPN)(ioa >> PAGE_SHIFT); }
typedef char PageArray[PAGE_SIZE];
/*
*----------------------------------------------------------------------
*
* IsGoodMPN --
*
* Is the given MPN valid?
*
* Results:
* Return TRUE if "mpn" looks plausible. We could make this stricter on
* a per-architecture basis.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE Bool
IsGoodMPN(MPN mpn)
{
return mpn <= MAX_MPN;
}
static INLINE Bool
IsGoodMPNOrMemref(MPN mpn)
{
return IsGoodMPN(mpn) || mpn == MEMREF_MPN;
}
#endif
+60
View File
@@ -0,0 +1,60 @@
/*********************************************************
* Copyright (C) 2006 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
*
*********************************************************/
/*
* basic_initblock.h --
*
* VM initialization block.
*/
#ifndef _BASIC_INITBLOCK_H_
#define _BASIC_INITBLOCK_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "vcpuid.h"
#define MAX_INITBLOCK_CPUS 128
typedef
#include "vmware_pack_begin.h"
struct InitBlock {
uint32 magicNumber; /* Magic number (INIT_BLOCK_MAGIC) */
Vcpuid numVCPUs;
VA64 crosspage[MAX_INITBLOCK_CPUS];
uint32 vmInitFailurePeriod;
LA64 crossGDTHKLA;
MPN crossGDTMPNs[5]; // CROSSGDT_NUMPAGES
}
#include "vmware_pack_end.h"
InitBlock;
#endif // _BASIC_INITBLOCK_H_
+428
View File
@@ -0,0 +1,428 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* circList.h --
*
* macros, prototypes and struct definitions for double-linked
* circular lists.
*/
#ifndef _CIRCLIST_H_
#define _CIRCLIST_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#include "includeCheck.h"
#include "vmware.h"
typedef struct ListItem {
struct ListItem *prev;
struct ListItem *next;
} ListItem;
/* A list with no elements is a null pointer. */
#define LIST_ITEM_DEF(name) \
ListItem * name = NULL
#define LIST_EMPTY(l) ((l) == NULL)
/* initialize list item */
#define INIT_LIST_ITEM(p) \
do { \
(p)->prev = (p)->next = (p); \
} while (0)
/* check if initialized */
#define IS_LIST_ITEM_INITIALIZED(li) \
(((li) == (li)->prev) && ((li) == (li)->next))
/* return first element in the list */
#define LIST_FIRST(l) (l)
#define LIST_FIRST_CHK(l) (l)
/* return last element in the list */
#define LIST_LAST(l) ((l)->prev)
#define LIST_LAST_CHK(l) (LIST_EMPTY(l) ? NULL : LIST_LAST(l))
/*
* LIST_CONTAINER - get the struct for this entry (like list_entry)
* @ptr: the &struct ListItem pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list struct within the struct.
*/
#define LIST_CONTAINER(ptr, type, member) \
VMW_CONTAINER_OF(ptr, type, member)
/*
* delete item from the list
*/
#define LIST_DEL DelListItem
/*
* link two lists together
*/
#define LIST_SPLICE SpliceLists
/*
* Split a list into two lists
*/
#define LIST_SPLIT SplitLists
/*
* Add item to front of stack. List pointer points to new head.
*/
#define LIST_PUSH PushListItem
/*
* Add item at back of queue. List pointer only changes if list was empty.
*/
#define LIST_QUEUE QueueListItem
/*
* Get the list size.
*/
#define LIST_SIZE GetListSize
/*
* LIST_SCAN_FROM scans the list from "from" up until "until".
* The loop variable p should not be destroyed in the process.
* "from" is an element in the list where to start scanning.
* "until" is the element where search should stop.
* member is the field to use for the search - either "next" or "prev".
*/
#define LIST_SCAN_FROM(p, from, until, member) \
for (p = (from); (p) != NULL; \
(p) = (((p)->member == (until)) ? NULL : (p)->member))
/* scan the entire list (non-destructively) */
#define LIST_SCAN(p, l) \
LIST_SCAN_FROM(p, LIST_FIRST(l), LIST_FIRST(l), next)
/* scan a list backward from last element to first (non-destructively) */
#define LIST_SCAN_BACK(p, l) \
LIST_SCAN_FROM(p, LIST_LAST_CHK(l), LIST_LAST(l), prev)
/* scan the entire list where loop element may be destroyed */
#define LIST_SCAN_SAFE(p, pn, l) \
if (!LIST_EMPTY(l)) \
for (p = (l), (pn) = NextListItem(p, l); (p) != NULL; \
(p) = (pn), (pn) = NextListItem(p, l))
/* scan the entire list backwards where loop element may be destroyed */
#define LIST_SCAN_BACK_SAFE(p, pn, l) \
if (!LIST_EMPTY(l)) \
for (p = LIST_LAST(l), (pn) = PrevListItem(p, l); (p) != NULL; \
(p) = (pn), (pn) = PrevListItem(p, l))
/* function definitions */
/*
*----------------------------------------------------------------------
*
* NextListItem --
*
* Returns the next member of a doubly linked list, or NULL if last.
* Assumes: p is member of the list headed by head.
*
* Result:
* If head or p is NULL, return NULL. Otherwise,
* next list member (or null if last).
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE ListItem *
NextListItem(ListItem *p, // IN
ListItem *head) // IN
{
if (head == NULL || p == NULL) {
return NULL;
}
/* both p and head are non-null */
p = p->next;
return p == head ? NULL : p;
}
/*
*----------------------------------------------------------------------
*
* PrevListItem --
*
* Returns the prev member of a doubly linked list, or NULL if first.
* Assumes: p is member of the list headed by head.
*
* Result:
* If head or prev is NULL, return NULL. Otherwise,
* prev list member (or null if first).
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE ListItem *
PrevListItem(ListItem *p, // IN
ListItem *head) // IN
{
if (head == NULL || p == NULL) {
return NULL;
}
/* both p and head are non-null */
return p == head ? NULL : p->prev;
}
/*
*----------------------------------------------------------------------
*
* DelListItem --
*
* Deletes a member of a doubly linked list, possibly modifies the
* list header itself.
* Assumes neither p nor headp is null and p is a member of *headp.
*
* Result:
* None
*
* Side effects:
* Modifies *headp.
*
*----------------------------------------------------------------------
*/
static INLINE void
DelListItem(ListItem *p, // IN
ListItem **headp) // IN/OUT
{
ListItem *next;
ASSERT(p);
ASSERT(headp);
next = p->next;
if (p == next) {
*headp = NULL;
} else {
next->prev = p->prev;
p->prev->next = next;
if (*headp == p) {
*headp = next;
}
}
}
/*
*----------------------------------------------------------------------
*
* QueueListItem --
*
* Adds a new member to the back of a doubly linked list (queue)
* Assumes neither p nor headp is null and p is not a member of *headp.
*
* Result:
* None
*
* Side effects:
* Modifies *headp.
*
*----------------------------------------------------------------------
*/
static INLINE void
QueueListItem(ListItem *p, // IN
ListItem **headp) // IN/OUT
{
ListItem *head;
head = *headp;
if (LIST_EMPTY(head)) {
INIT_LIST_ITEM(p);
*headp = p;
} else {
p->prev = head->prev;
p->next = head;
p->prev->next = p;
head->prev = p;
}
}
/*
*----------------------------------------------------------------------
*
* PushListItem --
*
* Adds a new member to the front of a doubly linked list (stack)
* Assumes neither p nor headp is null and p is not a member of *headp.
*
* Result:
* None
*
* Side effects:
* Modifies *headp.
*
*----------------------------------------------------------------------
*/
static INLINE void
PushListItem(ListItem *p, // IN
ListItem **headp) // IN/OUT
{
QueueListItem(p, headp);
*headp = p;
}
/*
*----------------------------------------------------------------------
*
* SpliceLists --
*
* Make a single list {l1 l2} from {l1} and {l2} and return it.
* It is okay for one or both lists to be NULL.
* No checking is done. It is assumed that l1 and l2 are two
* distinct lists.
*
* Result:
* A list { l1 l2 }.
*
* Side effects:
* Modifies l1 and l2 list pointers.
*
*----------------------------------------------------------------------
*/
static INLINE ListItem *
SpliceLists(ListItem *l1, // IN
ListItem *l2) // IN
{
ListItem *l1Last, *l2Last;
if (LIST_EMPTY(l1)) {
return l2;
}
if (LIST_EMPTY(l2)) {
return l1;
}
l1Last = l1->prev; /* last elem of l1 */
l2Last = l2->prev; /* last elem of l2 */
/*
* l1 -> ... -> l1Last l2 -> ... l2Last
*/
l1Last->next = l2;
l2->prev = l1Last;
l1->prev = l2Last;
l2Last->next = l1;
return l1;
}
/*
*----------------------------------------------------------------------
*
* SplitLists --
*
* Make a list l = {l1 l2} into two separate lists {l1} and {l2}, where:
* l = { ... x -> p -> ... } split into:
* l1 = { ... -> x }
* l2 = { p -> ... }
* Assumes neither p nor l is null and p is a member of l.
* If p is the first element of l, then l1 will be NULL.
*
* Result:
* None.
*
* Side effects:
* Sets *l1p and *l2p to the resulting two lists.
* Modifies l's pointers.
*
*----------------------------------------------------------------------
*/
static INLINE void
SplitLists(ListItem *p, // IN
ListItem *l, // IN
ListItem **l1p, // OUT
ListItem **l2p) // OUT
{
ListItem *last;
if (p == LIST_FIRST(l)) { /* first element */
*l1p = NULL;
*l2p = l;
return;
}
last = l->prev;
*l1p = l;
p->prev->next = l;
l->prev = p->prev;
*l2p = p;
p->prev = last;
last->next = p;
}
/*
*----------------------------------------------------------------------
*
* GetListSize --
*
* Return the number of items in the list.
*
* Result:
* The number of items in the list.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE int
GetListSize(ListItem *head) // IN
{
ListItem *li;
int ret = 0;
LIST_SCAN(li, head) {
ret++;
}
return ret;
}
#endif /* _CIRCLIST_H_ */
+67
View File
@@ -0,0 +1,67 @@
/*********************************************************
* Copyright (C) 2009-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
*
*********************************************************/
/*
* community_source.h --
*
* Macros for excluding source code from community.
*/
#ifndef _COMMUNITY_SOURCE_H_
#define _COMMUNITY_SOURCE_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMKDRIVERS
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
/*
* Convenience macro for COMMUNITY_SOURCE
*/
#undef EXCLUDE_COMMUNITY_SOURCE
#ifdef COMMUNITY_SOURCE
#define EXCLUDE_COMMUNITY_SOURCE(x)
#else
#define EXCLUDE_COMMUNITY_SOURCE(x) x
#endif
#undef COMMUNITY_SOURCE_AMD_SECRET
#if !defined(COMMUNITY_SOURCE) || defined(AMD_SOURCE)
/*
* It's ok to include AMD_SECRET source code for non-Community Source,
* or for drops directed at AMD.
*/
#define COMMUNITY_SOURCE_AMD_SECRET
#endif
#undef COMMUNITY_SOURCE_INTEL_SECRET
#if !defined(COMMUNITY_SOURCE) || defined(INTEL_SOURCE)
/*
* It's ok to include INTEL_SECRET source code for non-Community Source,
* or for drops directed at Intel.
*/
#define COMMUNITY_SOURCE_INTEL_SECRET
#endif
#endif
+41
View File
@@ -0,0 +1,41 @@
/*********************************************************
* Copyright (C) 2009 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 __COMPAT_AUTOCONF_H__
# define __COMPAT_AUTOCONF_H__
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMKDRIVERS
#include "includeCheck.h"
#ifndef LINUX_VERSION_CODE
# error "Include compat_version.h before compat_autoconf.h"
#endif
/* autoconf.h moved from linux/autoconf.h to generated/autoconf.h in 2.6.33-rc1. */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
# include <linux/autoconf.h>
#else
# include <generated/autoconf.h>
#endif
#endif /* __COMPAT_AUTOCONF_H__ */
+47
View File
@@ -0,0 +1,47 @@
/*********************************************************
* 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
* 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 __COMPAT_CRED_H__
# define __COMPAT_CRED_H__
/*
* Include linux/cred.h via linux/sched.h - it is not nice, but
* as cpp does not have #ifexist...
*/
#include <linux/sched.h>
#if !defined(current_fsuid) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
#define current_uid() (current->uid)
#define current_euid() (current->euid)
#define current_fsuid() (current->fsuid)
#define current_gid() (current->gid)
#define current_egid() (current->egid)
#define current_fsgid() (current->fsgid)
#endif
#if !defined(cap_set_full)
/* cap_set_full was removed in kernel version 3.0-rc4. */
#define cap_set_full(_c) do { (_c) = CAP_FULL_SET; } while (0)
#endif
#if !defined(GLOBAL_ROOT_UID)
#define GLOBAL_ROOT_UID (0)
#endif
#endif /* __COMPAT_CRED_H__ */
+32
View File
@@ -0,0 +1,32 @@
/*********************************************************
* Copyright (C) 2012 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 __COMPAT_HIGHMEM_H__
# define __COMPAT_HIGHMEM_H__
#include <linux/highmem.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
# define compat_kmap_atomic(_page) kmap_atomic(_page)
# define compat_kunmap_atomic(_page) kunmap_atomic(_page)
#else
# define compat_kmap_atomic(_page) kmap_atomic((_page), KM_USER0)
# define compat_kunmap_atomic(_page) kunmap_atomic((_page), KM_USER0)
#endif
#endif /* __COMPAT_HIGHMEM_H__ */
+55
View File
@@ -0,0 +1,55 @@
/*********************************************************
* Copyright (C) 2003 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 __COMPAT_INTERRUPT_H__
# define __COMPAT_INTERRUPT_H__
#include <linux/interrupt.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 69)
/*
* We cannot just define irqreturn_t, as some 2.4.x kernels have
* typedef void irqreturn_t; for "increasing" backward compatibility.
*/
typedef void compat_irqreturn_t;
#define COMPAT_IRQ_NONE
#define COMPAT_IRQ_HANDLED
#define COMPAT_IRQ_RETVAL(x)
#else
typedef irqreturn_t compat_irqreturn_t;
#define COMPAT_IRQ_NONE IRQ_NONE
#define COMPAT_IRQ_HANDLED IRQ_HANDLED
#define COMPAT_IRQ_RETVAL(x) IRQ_RETVAL(x)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
#define COMPAT_IRQF_DISABLED SA_INTERRUPT
#define COMPAT_IRQF_SHARED SA_SHIRQ
#else
#define COMPAT_IRQF_DISABLED IRQF_DISABLED
#define COMPAT_IRQF_SHARED IRQF_SHARED
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
#define COMPAT_IRQ_HANDLER_ARGS(irq, devp) (int irq, void *devp, struct pt_regs *regs)
#else
#define COMPAT_IRQ_HANDLER_ARGS(irq, devp) (int irq, void *devp)
#endif
#endif /* __COMPAT_INTERRUPT_H__ */
+63
View File
@@ -0,0 +1,63 @@
/*********************************************************
* Copyright (C) 2003 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 __COMPAT_IOPORT_H__
# define __COMPAT_IOPORT_H__
#include <linux/ioport.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
static inline void *
compat_request_region(unsigned long start, unsigned long len, const char *name)
{
if (check_region(start, len)) {
return NULL;
}
request_region(start, len, name);
return (void*)1;
}
#else
#define compat_request_region(start, len, name) request_region(start, len, name)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 7)
/* mmap io support starts from 2.3.7, fail the call for kernel prior to that */
static inline void *
compat_request_mem_region(unsigned long start, unsigned long len, const char *name)
{
return NULL;
}
static inline void
compat_release_mem_region(unsigned long start, unsigned long len)
{
return;
}
#else
#define compat_request_mem_region(start, len, name) request_mem_region(start, len, name)
#define compat_release_mem_region(start, len) release_mem_region(start, len)
#endif
/* these two macro defs are needed by compat_pci_request_region */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 15)
# define IORESOURCE_IO 0x00000100
# define IORESOURCE_MEM 0x00000200
#endif
#endif /* __COMPAT_IOPORT_H__ */
+42
View File
@@ -0,0 +1,42 @@
/*********************************************************
* Copyright (C) 2004 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 __COMPAT_KERNEL_H__
# define __COMPAT_KERNEL_H__
#include <asm/unistd.h>
#include <linux/kernel.h>
/*
* container_of was introduced in 2.5.28 but it's easier to check like this.
*/
#ifndef container_of
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#endif
/*
* vsnprintf became available in 2.4.10. For older kernels, just fall back on
* vsprintf.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 10)
#define vsnprintf(str, size, fmt, args) vsprintf(str, fmt, args)
#endif
#endif /* __COMPAT_KERNEL_H__ */
+83
View File
@@ -0,0 +1,83 @@
/*********************************************************
* Copyright (C) 2007 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
*
*********************************************************/
/*
* compat_module.h --
*/
#ifndef __COMPAT_MODULE_H__
# define __COMPAT_MODULE_H__
#include <linux/module.h>
/*
* Modules wishing to use the GPL license are required to include a
* MODULE_LICENSE definition in their module source as of 2.4.10.
*/
#ifndef MODULE_LICENSE
#define MODULE_LICENSE(license)
#endif
/*
* To make use of our own home-brewed MODULE_INFO, we need macros to
* concatenate two expressions to "__mod_", and and to convert an
* expression into a string. I'm sure we've got these in our codebase,
* but I'd rather not introduce such a dependency in a compat header.
*/
#ifndef __module_cat
#define __module_cat_1(a, b) __mod_ ## a ## b
#define __module_cat(a, b) __module_cat_1(a, b)
#endif
#ifndef __stringify
#define __stringify_1(x) #x
#define __stringify(x) __stringify_1(x)
#endif
/*
* MODULE_INFO was born in 2.5.69.
*/
#ifndef MODULE_INFO
#define MODULE_INFO(tag, info) \
static const char __module_cat(tag, __LINE__)[] \
__attribute__((section(".modinfo"), unused)) = __stringify(tag) "=" info
#endif
/*
* MODULE_VERSION was born in 2.6.4. The earlier form appends a long "\0xxx"
* string to the module's version, but that was removed in 2.6.10, so we'll
* ignore it in our wrapper.
*/
#ifndef MODULE_VERSION
#define MODULE_VERSION(_version) MODULE_INFO(version, _version)
#endif
/*
* Linux kernel < 2.6.31 takes 'int' for 'bool' module parameters.
* Linux kernel >= 3.3.0 takes 'bool' for 'bool' module parameters.
* Kernels between the two take either. So flip switch at 3.0.0.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
typedef bool compat_mod_param_bool;
#else
typedef int compat_mod_param_bool;
#endif
#endif /* __COMPAT_MODULE_H__ */
+75
View File
@@ -0,0 +1,75 @@
/*********************************************************
* 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
* 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 __COMPAT_PAGE_H__
# define __COMPAT_PAGE_H__
#include <linux/mm.h>
#include <asm/page.h>
/* The pfn_to_page() API appeared in 2.5.14 and changed to function during 2.6.x */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) && !defined(pfn_to_page)
# define pfn_to_page(_pfn) (mem_map + (_pfn))
# define page_to_pfn(_page) ((_page) - mem_map)
#endif
/* The virt_to_page() API appeared in 2.4.0 --hpreg */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) && !defined(virt_to_page)
# define virt_to_page(_kvAddr) pfn_to_page(MAP_NR(_kvAddr))
#endif
/*
* The get_order() API appeared at some point in 2.3.x, and was then backported
* in 2.2.17-21mdk and in the stock 2.2.18. Because we can only detect its
* definition through makefile tricks, we provide our own for now --hpreg
*/
static inline int
compat_get_order(unsigned long size) // IN
{
int order;
size = (size - 1) >> (PAGE_SHIFT - 1);
order = -1;
do {
size >>= 1;
order++;
} while (size);
return order;
}
/*
* BUG() was added to <asm/page.h> in 2.2.18, and was moved to <asm/bug.h>
* in 2.5.58.
*
* XXX: Technically, this belongs in some sort of "compat_asm_page.h" file, but
* since our compatibility wrappers don't distinguish between <asm/xxx.h> and
* <linux/xxx.h>, putting it here is reasonable.
*/
#ifndef BUG
#define BUG() do { \
printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
__asm__ __volatile__(".byte 0x0f,0x0b"); \
} while (0)
#endif
#endif /* __COMPAT_PAGE_H__ */
+72
View File
@@ -0,0 +1,72 @@
/*********************************************************
* Copyright (C) 1999 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
*
*********************************************************/
/*
* compat_pci.h: PCI compatibility wrappers.
*/
#ifndef __COMPAT_PCI_H__
#define __COMPAT_PCI_H__
#include "compat_ioport.h"
#include <linux/pci.h>
#ifndef DMA_BIT_MASK
# define DMA_BIT_MASK(n) DMA_##n##BIT_MASK
#endif
/*
* Power Management related compat wrappers.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
# define compat_pci_save_state(pdev) pci_save_state((pdev), NULL)
# define compat_pci_restore_state(pdev) pci_restore_state((pdev), NULL)
#else
# define compat_pci_save_state(pdev) pci_save_state((pdev))
# define compat_pci_restore_state(pdev) pci_restore_state((pdev))
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
# define pm_message_t u32
# define compat_pci_choose_state(pdev, state) (state)
# define PCI_D0 0
# define PCI_D3hot 3
#else
# define compat_pci_choose_state(pdev, state) pci_choose_state((pdev), (state))
#endif
/* 2.6.14 changed the PCI shutdown callback */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
# define COMPAT_PCI_SHUTDOWN(func) .driver = { .shutdown = (func), }
# define COMPAT_PCI_DECLARE_SHUTDOWN(func, var) (func)(struct device *(var))
# define COMPAT_PCI_TO_DEV(dev) (to_pci_dev(dev))
#else
# define COMPAT_PCI_SHUTDOWN(func) .shutdown = (func)
# define COMPAT_PCI_DECLARE_SHUTDOWN(func, var) (func)(struct pci_dev *(var))
# define COMPAT_PCI_TO_DEV(dev) (dev)
#endif
/* 2.6.26 introduced the device_set_wakeup_enable() function */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
# define compat_device_set_wakeup_enable(dev, val) do {} while(0)
#else
# define compat_device_set_wakeup_enable(dev, val) \
device_set_wakeup_enable(dev, val)
#endif
#endif /* __COMPAT_PCI_H__ */
+159
View File
@@ -0,0 +1,159 @@
/*********************************************************
* 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
* 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 __COMPAT_PGTABLE_H__
# define __COMPAT_PGTABLE_H__
#if defined(CONFIG_PARAVIRT) && defined(CONFIG_HIGHPTE)
# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21)
# include <asm/paravirt.h>
# undef paravirt_map_pt_hook
# define paravirt_map_pt_hook(type, va, pfn) do {} while (0)
# endif
#endif
#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. In 4.12, it was replaced by
* pgd -> p4d -> pud -> pmd -> pte hierarchy (5-level page tables).
*/
#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_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_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
#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
/* 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
/*
* Define VM_PAGE_KERNEL_EXEC for vmapping executable pages.
*
* On ia32 PAGE_KERNEL_EXEC was introduced in 2.6.8.1. Unfortunately it accesses
* __PAGE_KERNEL_EXEC which is not exported for modules. So we use
* __PAGE_KERNEL and just cut _PAGE_NX bit from it.
*
* For ia32 kernels before 2.6.8.1 we use PAGE_KERNEL directly, these kernels
* do not have noexec support.
*
* On x86-64 situation is a bit better: they always supported noexec, but
* before 2.6.8.1 flag was named PAGE_KERNEL_EXECUTABLE, and it was renamed
* to PAGE_KERNEL_EXEC when ia32 got noexec too (see above).
*/
#ifdef CONFIG_X86
#ifdef _PAGE_NX
#define VM_PAGE_KERNEL_EXEC __pgprot(__PAGE_KERNEL & ~_PAGE_NX)
#else
#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__ */
+293
View File
@@ -0,0 +1,293 @@
/*********************************************************
* 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
* 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 __COMPAT_SCHED_H__
# define __COMPAT_SCHED_H__
#include <linux/sched.h>
/* CLONE_KERNEL available in 2.5.35 and higher. */
#ifndef CLONE_KERNEL
#define CLONE_KERNEL CLONE_FILES | CLONE_FS | CLONE_SIGHAND
#endif
/* TASK_COMM_LEN become available in 2.6.11. */
#ifndef TASK_COMM_LEN
#define TASK_COMM_LEN 16
#endif
/* The capable() API appeared in 2.1.92 --hpreg */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 1, 92)
# define capable(_capability) suser()
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 0)
# define need_resched() need_resched
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 3)
# define need_resched() (current->need_resched)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 3)
# define cond_resched() (need_resched() ? schedule() : (void) 0)
#endif
/* Oh well. We need yield... Happy us! */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 20)
# ifdef __x86_64__
# define compat_yield() there_is_nothing_like_yield()
# else
# include <linux/unistd.h>
# include <linux/kernel.h>
/*
* Used by _syscallX macros. Note that this is global variable, so
* do not rely on its contents too much. As exit() is only function
* we use, and we never check return value from exit(), we have
* no problem...
*/
extern int errno;
/*
* compat_exit() provides an access to the exit() function. It must
* be named compat_exit(), as exit() (with different signature) is
* provided by x86-64, arm and other (but not by i386).
*/
# define __NR_compat_yield __NR_sched_yield
static inline _syscall0(int, compat_yield);
# endif
#else
# define compat_yield() yield()
#endif
/*
* Since 2.5.34 there are two methods to enumerate tasks:
* for_each_process(p) { ... } which enumerates only tasks and
* do_each_thread(g,t) { ... } while_each_thread(g,t) which enumerates
* also threads even if they share same pid.
*/
#ifndef for_each_process
# define for_each_process(p) for_each_task(p)
#endif
#ifndef do_each_thread
# define do_each_thread(g, t) for_each_task(g) { t = g; do
# define while_each_thread(g, t) while (0) }
#endif
/*
* Lock for signal mask is moving target...
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 40) && defined(CLONE_PID)
/* 2.4.x without NPTL patches or early 2.5.x */
#define compat_sigmask_lock sigmask_lock
#define compat_dequeue_signal_current(siginfo_ptr) \
dequeue_signal(&current->blocked, (siginfo_ptr))
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 60) && !defined(INIT_SIGHAND)
/* RedHat's 2.4.x with first version of NPTL support, or 2.5.40 to 2.5.59 */
#define compat_sigmask_lock sig->siglock
#define compat_dequeue_signal_current(siginfo_ptr) \
dequeue_signal(&current->blocked, (siginfo_ptr))
#else
/* RedHat's 2.4.x with second version of NPTL support, or 2.5.60+. */
#define compat_sigmask_lock sighand->siglock
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
#define compat_dequeue_signal_current(siginfo_ptr) \
dequeue_signal(&current->blocked, (siginfo_ptr))
#else
#define compat_dequeue_signal_current(siginfo_ptr) \
dequeue_signal(current, &current->blocked, (siginfo_ptr))
#endif
#endif
/*
* recalc_sigpending() had task argument in the past
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 29) && defined(CLONE_PID)
/* 2.4.x without NPTL patches or early 2.5.x */
#define compat_recalc_sigpending() recalc_sigpending(current)
#else
/* RedHat's 2.4.x with NPTL support, or 2.5.29+ */
#define compat_recalc_sigpending() recalc_sigpending()
#endif
/*
* reparent_to_init() was introduced in 2.4.8. In 2.5.38 (or possibly
* earlier, but later than 2.5.31) a call to it was added into
* daemonize(), so compat_daemonize no longer needs to call it.
*
* In 2.4.x kernels reparent_to_init() forgets to do correct refcounting
* on current->user. It is better to count one too many than one too few...
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 8) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 38)
#define compat_reparent_to_init() do { \
reparent_to_init(); \
atomic_inc(&current->user->__count); \
} while (0)
#else
#define compat_reparent_to_init() do {} while (0)
#endif
/*
* daemonize appeared in 2.2.18. Except 2.2.17-4-RH7.0, which has it too.
* Fortunately 2.2.17-4-RH7.0 uses versioned symbols, so we can check
* its existence with defined().
*/
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)) && !defined(daemonize)
static inline void daemonize(void) {
struct fs_struct *fs;
exit_mm(current);
current->session = 1;
current->pgrp = 1;
exit_fs(current);
fs = init_task.fs;
current->fs = fs;
atomic_inc(&fs->count);
}
#endif
/*
* flush_signals acquires sighand->siglock since 2.5.61... Verify RH's kernels!
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 61)
#define compat_flush_signals(task) do { \
spin_lock_irq(&task->compat_sigmask_lock); \
flush_signals(task); \
spin_unlock_irq(&task->compat_sigmask_lock); \
} while (0)
#else
#define compat_flush_signals(task) flush_signals(task)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 61)
#define compat_allow_signal(signr) do { \
spin_lock_irq(&current->compat_sigmask_lock); \
sigdelset(&current->blocked, signr); \
compat_recalc_sigpending(); \
spin_unlock_irq(&current->compat_sigmask_lock); \
} while (0)
#else
#define compat_allow_signal(signr) allow_signal(signr)
#endif
/*
* daemonize can set process name since 2.5.61. Prior to 2.5.61, daemonize
* didn't block signals on our behalf.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 61)
#define compat_daemonize(x...) \
({ \
/* Beware! No snprintf here, so verify arguments! */ \
sprintf(current->comm, x); \
\
/* Block all signals. */ \
spin_lock_irq(&current->compat_sigmask_lock); \
sigfillset(&current->blocked); \
compat_recalc_sigpending(); \
spin_unlock_irq(&current->compat_sigmask_lock); \
compat_flush_signals(current); \
\
daemonize(); \
compat_reparent_to_init(); \
})
#else
#define compat_daemonize(x...) daemonize(x)
#endif
/*
* try to freeze a process. For kernels 2.6.11 or newer, we know how to choose
* the interface. The problem is that the oldest interface, introduced in
* 2.5.18, was backported to 2.4.x kernels. So if we're older than 2.6.11,
* we'll decide what to do based on whether or not swsusp was configured
* for the kernel. For kernels 2.6.20 and newer, we'll also need to include
* freezer.h since the try_to_freeze definition was pulled out of sched.h.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
#include <linux/freezer.h>
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) || defined(VMW_TL10S64_WORKAROUND)
#define compat_try_to_freeze() try_to_freeze()
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
#define compat_try_to_freeze() try_to_freeze(PF_FREEZE)
#elif defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_SOFTWARE_SUSPEND2)
#include "compat_mm.h"
#include <linux/errno.h>
#include <linux/suspend.h>
static inline int compat_try_to_freeze(void) {
if (current->flags & PF_FREEZE) {
refrigerator(PF_FREEZE);
return 1;
} else {
return 0;
}
}
#else
static inline int compat_try_to_freeze(void) { return 0; }
#endif
/*
* As of 2.6.23-rc1, kernel threads are no longer freezable by
* default. Instead, kernel threads that need to be frozen must opt-in
* by calling set_freezable() as soon as the thread is created.
*/
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
#define compat_set_freezable() do { set_freezable(); } while (0)
#else
#define compat_set_freezable() do {} while (0)
#endif
/*
* Around 2.6.27 kernel stopped sending signals to kernel
* threads being frozen, instead threads have to check
* freezing() or use wait_event_freezable(). Unfortunately
* wait_event_freezable() completely hides the fact that
* thread was frozen from calling code and sometimes we do
* want to know that.
*/
#ifdef PF_FREEZER_NOSIG
#define compat_wait_check_freezing() freezing(current)
#else
#define compat_wait_check_freezing() (0)
#endif
/*
* Since 2.6.27-rc2 kill_proc() is gone... Replacement (GPL-only!)
* API is available since 2.6.19. Use them from 2.6.27-rc1 up.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
typedef int compat_pid;
#define compat_find_get_pid(pid) (pid)
#define compat_put_pid(pid) do { } while (0)
#define compat_kill_pid(pid, sig, flag) kill_proc(pid, sig, flag)
#else
typedef struct pid * compat_pid;
#define compat_find_get_pid(pid) find_get_pid(pid)
#define compat_put_pid(pid) put_pid(pid)
#define compat_kill_pid(pid, sig, flag) kill_pid(pid, sig, flag)
#endif
#endif /* __COMPAT_SCHED_H__ */
+49
View File
@@ -0,0 +1,49 @@
/*********************************************************
* 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
* 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 __COMPAT_SEMAPHORE_H__
# define __COMPAT_SEMAPHORE_H__
/* <= 2.6.25 have asm only, 2.6.26 has both, and 2.6.27-rc2+ has linux only. */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
# include <asm/semaphore.h>
#else
# include <linux/semaphore.h>
#endif
/*
* The init_MUTEX_LOCKED() API appeared in 2.2.18, and is also in
* 2.2.17-21mdk --hpreg
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)
#ifndef init_MUTEX_LOCKED
#define init_MUTEX_LOCKED(_sem) *(_sem) = MUTEX_LOCKED
#endif
#ifndef DECLARE_MUTEX
#define DECLARE_MUTEX(name) struct semaphore name = MUTEX
#endif
#ifndef DECLARE_MUTEX_LOCKED
#define DECLARE_MUTEX_LOCKED(name) struct semaphore name = MUTEX_LOCKED
#endif
#endif
#endif /* __COMPAT_SEMAPHORE_H__ */
+48
View File
@@ -0,0 +1,48 @@
/*********************************************************
* Copyright (C) 2005 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 __COMPAT_SPINLOCK_H__
# define __COMPAT_SPINLOCK_H__
#include <linux/spinlock.h>
/*
* Preempt support was added during 2.5.x development cycle, and later
* it was backported to 2.4.x. In 2.4.x backport these definitions
* live in linux/spinlock.h, that's why we put them here (in 2.6.x they
* are defined in linux/preempt.h which is included by linux/spinlock.h).
*/
#ifdef CONFIG_PREEMPT
#define compat_preempt_disable() preempt_disable()
#define compat_preempt_enable() preempt_enable()
#else
#define compat_preempt_disable() do { } while (0)
#define compat_preempt_enable() do { } while (0)
#endif
/* Some older kernels - 2.6.10 and earlier - lack DEFINE_SPINLOCK */
#ifndef DEFINE_SPINLOCK
#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
#endif
/* Same goes for DEFINE_RWLOCK */
#ifndef DEFINE_RWLOCK
#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED
#endif
#endif /* __COMPAT_SPINLOCK_H__ */
+131
View File
@@ -0,0 +1,131 @@
/*********************************************************
* 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
* 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 __COMPAT_VERSION_H__
# define __COMPAT_VERSION_H__
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMKDRIVERS
#include "includeCheck.h"
#ifndef __linux__
# error "linux-version.h"
#endif
#include <linux/version.h>
#ifndef KERNEL_VERSION
# error KERNEL_VERSION macro is not defined, environment is busted
#endif
/*
* Distinguish relevant classes of Linux kernels.
*
* The convention is that version X defines all
* the KERNEL_Y symbols where Y <= X.
*
* XXX Do not add more definitions here. This way of doing things does not
* scale, and we are going to phase it out soon --hpreg
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 1, 0)
# define KERNEL_2_1
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 2, 0)
# define KERNEL_2_2
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 1)
# define KERNEL_2_3_1
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 15)
/* new networking */
# define KERNEL_2_3_15
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 25)
/* new procfs */
# define KERNEL_2_3_25
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 29)
/* even newer procfs */
# define KERNEL_2_3_29
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 43)
/* softnet changes */
# define KERNEL_2_3_43
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 47)
/* more softnet changes */
# define KERNEL_2_3_47
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 99)
/* name in netdevice struct is array and not pointer */
# define KERNEL_2_3_99
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
/* New 'owner' member at the beginning of struct file_operations */
# define KERNEL_2_4_0
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 8)
/* New netif_rx_ni() --hpreg */
# define KERNEL_2_4_8
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 2)
/* New kdev_t, major()/minor() API --hpreg */
# define KERNEL_2_5_2
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 5)
/* New sk_alloc(), pte_offset_map()/pte_unmap() --hpreg */
# define KERNEL_2_5_5
#endif
/* Linux kernel 3.0 can be called 2.6.40, and 3.1 can be 2.6.41...
* Use COMPAT_LINUX_VERSION_CHECK_LT iff you need to compare running kernel to
* versions 3.0 and above.
*
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
/* Straight forward comparison if kernel version is 3.0.0 and beyond */
# define COMPAT_LINUX_VERSION_CHECK_LT(a, b, c) LINUX_VERSION_CODE < KERNEL_VERSION (a, b, c)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 40)
/* Use b of the check to calculate corresponding c of kernel
* version to compare */
# define COMPAT_LINUX_VERSION_CHECK_LT(a, b, c) LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, (b + 40))
#else
/* This is anyways lesser than any 3.x versions */
# define COMPAT_LINUX_VERSION_CHECK_LT(a, b, c) 1
#endif
#endif /* __COMPAT_VERSION_H__ */
+78
View File
@@ -0,0 +1,78 @@
/*********************************************************
* Copyright (C) 2005-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
* 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
*
*********************************************************/
/*
* contextinfo.h
*
* Context structures shared across all products
*/
#ifndef _CONTEXTINFO_H
#define _CONTEXTINFO_H
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMMON
#include "includeCheck.h"
#include "x86desc.h"
#pragma pack(push, 1)
typedef struct Context64 {
uint64 cr3;
uint64 rax;
uint64 rcx;
uint64 rdx;
uint64 rbx;
uint64 rsi;
uint64 rdi;
uint64 rbp;
uint64 rsp;
uint64 r8;
uint64 r9;
uint64 r10;
uint64 r11;
uint64 r12;
uint64 r13;
uint64 r14;
uint64 r15;
uint32 cs;
uint32 ds;
uint32 ss;
uint32 es;
uint32 fs;
uint32 gs;
uint64 rip;
uint64 eflags;
uint16 ldt;
uint16 _pad[3];
} Context64;
#pragma pack(pop)
#pragma pack(push, 1)
typedef struct ContextInfo64 {
DTRWords64 gdtr;
DTRWords64 idtr;
Context64 context;
uint16 tr;
uint16 _pad0;
} ContextInfo64;
#pragma pack(pop)
#endif
+49
View File
@@ -0,0 +1,49 @@
/*********************************************************
* Copyright (C) 2009 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
*
*********************************************************/
/*
* cpu_defs.h --
*
* CPU-related definitions shared between vmkernel and user-space.
*/
#ifndef CPU_DEFS_H
#define CPU_DEFS_H
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMKDRIVERS
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMX
#include "includeCheck.h"
#include "vm_basic_types.h"
typedef uint32 PCPU;
#define INVALID_PCPU ((PCPU) -1)
#define MAX_PCPUS 576
#define MAX_PCPUS_BITS 10 // MAX_PCPUS <= (1 << MAX_PCPUS_BITS)
#define MAX_PCPUS_MASK ((1 << MAX_PCPUS_BITS) - 1)
#endif
+95
View File
@@ -0,0 +1,95 @@
/*********************************************************
* 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
* 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 _CPUID_INFO_H
#define _CPUID_INFO_H
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMKERNEL
#include "includeCheck.h"
#include "vm_basic_asm.h"
#include "x86cpuid_asm.h"
typedef struct CPUID0 {
int numEntries;
char name[16]; // 4 extra bytes to null terminate
} CPUID0;
typedef struct CPUID1 {
uint32 version;
uint32 ebx;
uint32 ecxFeatures;
uint32 edxFeatures;
} CPUID1;
typedef struct CPUID80 {
uint32 numEntries;
uint32 ebx;
uint32 ecx;
uint32 edx;
} CPUID80;
typedef struct CPUID81 {
uint32 eax;
uint32 ebx;
uint32 ecxFeatures;
uint32 edxFeatures;
} CPUID81;
typedef struct CPUIDSummary {
CPUID0 id0;
CPUID1 id1;
CPUIDRegs ida;
CPUID80 id80;
CPUID81 id81;
CPUIDRegs id88, id8a;
} CPUIDSummary;
/*
*----------------------------------------------------------------------
*
* CPUIDSummary_RegsFromCpuid0 --
*
* Fills in the given CPUIDRegs struct with the values from the CPUID0 struct.
*
* Results:
* Returns the CPUIDRegs pointer passed in.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE CPUIDRegs*
CPUIDSummary_RegsFromCpuid0(CPUID0* id0In,
CPUIDRegs* id0Out)
{
id0Out->eax = id0In->numEntries;
id0Out->ebx = *(uint32 *) (id0In->name + 0);
id0Out->edx = *(uint32 *) (id0In->name + 4);
id0Out->ecx = *(uint32 *) (id0In->name + 8);
return id0Out;
}
#endif
+79
View File
@@ -0,0 +1,79 @@
/*********************************************************
* Copyright (C) 2006-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
* 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
*
*********************************************************/
/*
* crossgdt.h --
*
* This GDT is used for switching between monitor and host context.
* It contains the host and monitor basic segment descriptors.
* There is only one in the whole host system, shared by all VMs.
* It is allocated when the first VCPU is started and freed when the
* driver is unloaded.
*/
#ifndef _CROSSGDT_H_
#define _CROSSGDT_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "vm_basic_defs.h" // PAGE_SIZE
#include "x86types.h" // Descriptor
typedef struct CrossGDT {
Descriptor gdtes[0x5000 / sizeof (Descriptor)]; // 0x5000 > GDT_LIMIT
} CrossGDT;
#define CROSSGDT_NUMPAGES ((sizeof (CrossGDT) + PAGE_SIZE - 1) / PAGE_SIZE)
/*
* Out of the 5 pages, only the first and last are really used.
*
* All we need to map are the first and last pages. This mask tells
* the setup code which pages it can put stuff in and it tells the
* mapping and invalidation code which pages are mapped and unmapped.
*/
#define CROSSGDT_PAGEMASK 0x11
/*
* These segments are placed in the first crossGDT page. We assume
* they do not overlap any host segments (checked by
* Task_InitCrossGDT). The only real requirement is that they (and
* the host CS/SS) be physically contiguous with the start of the
* crossGDT so they will remain valid when paging is turned off.
*
* As of this writing (Nov 2006), host GDT limits:
* Linux 64 bit: 80 (yes 80, not 7F)
* 32 bit: FF
* MacOS 64 bit: 8F
* 32 bit: 8F
* Windows 64 bit: 6F
* 32 bit: 3FF
*/
#define CROSSGDT_LOWSEG (0x0FD0 / 8) // all host segs must be below this
#define CROSSGDT_64BITCS (0x0FD0 / 8) // 64-bit code segment
#define CROSSGDT_64BITSS (0x0FD8 / 8) // 64-bit data segment
#define CROSSGDT_FLAT32CS (0x0FE0 / 8) // 32-bit flat code seg
#define CROSSGDT_FLAT32SS (0x0FE8 / 8) // 32-bit flat data seg
#define CROSSGDT_MON32CS (0x0FF0 / 8) // 32-bit FFC00000 base code seg
#define CROSSGDT_MON32SS (0x0FF8 / 8) // 32-bit FFC00000 base data seg
#endif
+79
View File
@@ -0,0 +1,79 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* Sets the proper defines from the Linux header files
*
* This file must be included before the inclusion of any kernel header file,
* with the exception of linux/autoconf.h and linux/version.h --hpreg
*/
#ifndef __VMX_CONFIG_H__
#define __VMX_CONFIG_H__
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMKDRIVERS
#include "includeCheck.h"
#include "compat_version.h"
#include "compat_autoconf.h"
/*
* We rely on Kernel Module support. Check here.
*/
#ifndef CONFIG_MODULES
# error "No Module support in this kernel. Please configure with CONFIG_MODULES"
#endif
/*
* 2.2 kernels still use __SMP__ (derived from CONFIG_SMP
* in the main Makefile), so we do it here.
*/
#ifdef CONFIG_SMP
# define __SMP__ 1
#endif
#if defined(CONFIG_MODVERSIONS) && defined(KERNEL_2_1)
# if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60)
/*
* MODVERSIONS might be already defined when using kernel's Makefiles.
*/
# ifndef MODVERSIONS
# define MODVERSIONS
# endif
# include <linux/modversions.h>
# endif
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
/*
* Force the uintptr_t definition to come from linux/types.h instead of vm_basic_types.h.
*/
# include <linux/types.h>
# define _STDINT_H 1
#endif
#ifndef __KERNEL__
# define __KERNEL__
#endif
#endif
+345
View File
@@ -0,0 +1,345 @@
/*********************************************************
* Copyright (C) 2001,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
* 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 _HASH_FUNC_H
#define _HASH_FUNC_H
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMKERNEL
#include "includeCheck.h"
/*
* hashFunc.h --
*
* Hash functions defined as simple wrappers around code placed
* in the public domain by Bob Jenkins. His original code can
* be used freely for any purpose, including commercial (see the
* original comments in the enclosed code).
*/
#include "vm_basic_types.h"
#include "vm_basic_defs.h"
#include "vm_assert.h"
/*
* operations
*/
extern uint64 HashFunc_HashBytes(const uint8 *key, uint32 nBytes);
extern uint64 HashFunc_HashMoreBytes(const uint8 *key, uint32 nBytes,
uint64 initialValue);
extern uint64 HashFunc_HashBytesSlow(const uint8 *key, uint32 nBytes);
extern uint64 HashFunc_HashQuads(const uint64 *key, uint32 nQuads);
extern uint64 HashFunc_HashPage(const void *addr);
/*
--------------------------------------------------------------------
Hashes 32-bit key and returns a value that can fit into numBits bits.
--------------------------------------------------------------------
*/
static INLINE uint32
HashFunc_TruncHash32(uint32 key, unsigned numBits)
{
const uint32 hashConst = 0x9e3779b9; /* the golden ratio */
ASSERT(numBits > 0 && numBits <= 32);
return (key * hashConst) >> (32 - numBits);
}
/*
--------------------------------------------------------------------
Hashes 64-bit key and returns a value that can fit into numBits bits.
--------------------------------------------------------------------
*/
static INLINE uint32
HashFunc_TruncHash64(uint64 key, unsigned numBits)
{
return HashFunc_TruncHash32((uint32)(key ^ (key >> 32)), numBits);
}
/*
* Original Bob Jenkins public-domain code with minor modifications
* (static functions, 32-bit length args, disabled self-test code).
*/
typedef uint64 ub8; /* unsigned 8-byte quantities */
typedef uint32 ub4; /* unsigned 4-byte quantities */
typedef uint8 ub1;
#define hashsize(n) ((ub8)1<<(n))
#define hashmask(n) (hashsize(n)-1)
/*
--------------------------------------------------------------------
mix -- mix 3 64-bit values reversibly.
mix() takes 48 machine instructions, but only 24 cycles on a superscalar
machine (like Intel's new MMX architecture). It requires 4 64-bit
registers for 4::2 parallelism.
All 1-bit deltas, all 2-bit deltas, all deltas composed of top bits of
(a,b,c), and all deltas of bottom bits were tested. All deltas were
tested both on random keys and on keys that were nearly all zero.
These deltas all cause every bit of c to change between 1/3 and 2/3
of the time (well, only 113/400 to 287/400 of the time for some
2-bit delta). These deltas all cause at least 80 bits to change
among (a,b,c) when the mix is run either forward or backward (yes it
is reversible).
This implies that a hash using mix64 has no funnels. There may be
characteristics with 3-bit deltas or bigger, I didn't test for
those.
--------------------------------------------------------------------
*/
#define mix64(a,b,c) \
{ \
a -= b; a -= c; a ^= (c>>43); \
b -= c; b -= a; b ^= (a<<9); \
c -= a; c -= b; c ^= (b>>8); \
a -= b; a -= c; a ^= (c>>38); \
b -= c; b -= a; b ^= (a<<23); \
c -= a; c -= b; c ^= (b>>5); \
a -= b; a -= c; a ^= (c>>35); \
b -= c; b -= a; b ^= (a<<49); \
c -= a; c -= b; c ^= (b>>11); \
a -= b; a -= c; a ^= (c>>12); \
b -= c; b -= a; b ^= (a<<18); \
c -= a; c -= b; c ^= (b>>22); \
}
/*
--------------------------------------------------------------------
hash() -- hash a variable-length key into a 64-bit value
k : the key (the unaligned variable-length array of bytes)
len : the length of the key, counting by bytes
level : can be any 8-byte value
Returns a 64-bit value. Every bit of the key affects every bit of
the return value. No funnels. Every 1-bit and 2-bit delta achieves
avalanche. About 41+5len instructions.
The best hash table sizes are powers of 2. There is no need to do
mod a prime (mod is sooo slow!). If you need less than 64 bits,
use a bitmask. For example, if you need only 10 bits, do
h = (h & hashmask(10));
In which case, the hash table should have hashsize(10) elements.
If you are hashing n strings (ub1 **)k, do it like this:
for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
By Bob Jenkins, Jan 4 1997. bob_jenkins@burtleburtle.net. You may
use this code any way you wish, private, educational, or commercial,
as long as this whole comment accompanies it.
See http://burtleburtle.net/bob/hash/evahash.html
Use for hash table lookup, or anything where one collision in 2^^64
is acceptable. Do NOT use for cryptographic purposes.
--------------------------------------------------------------------
*/
static INLINE ub8 hash(register const ub1 *k, /* the key */
register ub4 length, /* the length of the key */
register ub8 level) /* the previous hash, or an arbitrary value */
{
register ub8 a,b,c;
ub4 len;
/* Set up the internal state */
len = length;
a = b = level; /* the previous hash value */
c = CONST64U(0x9e3779b97f4a7c13); /* the golden ratio; an arbitrary value */
/*---------------------------------------- handle most of the key */
while (len >= 24)
{
a += (k[0] +((ub8)k[ 1]<< 8)+((ub8)k[ 2]<<16)+((ub8)k[ 3]<<24)
+((ub8)k[4 ]<<32)+((ub8)k[ 5]<<40)+((ub8)k[ 6]<<48)+((ub8)k[ 7]<<56));
b += (k[8] +((ub8)k[ 9]<< 8)+((ub8)k[10]<<16)+((ub8)k[11]<<24)
+((ub8)k[12]<<32)+((ub8)k[13]<<40)+((ub8)k[14]<<48)+((ub8)k[15]<<56));
c += (k[16] +((ub8)k[17]<< 8)+((ub8)k[18]<<16)+((ub8)k[19]<<24)
+((ub8)k[20]<<32)+((ub8)k[21]<<40)+((ub8)k[22]<<48)+((ub8)k[23]<<56));
mix64(a,b,c);
k += 24; len -= 24;
}
/*------------------------------------- handle the last 23 bytes */
c += length;
switch(len) /* all the case statements fall through */
{
case 23: c+=((ub8)k[22]<<56);
case 22: c+=((ub8)k[21]<<48);
case 21: c+=((ub8)k[20]<<40);
case 20: c+=((ub8)k[19]<<32);
case 19: c+=((ub8)k[18]<<24);
case 18: c+=((ub8)k[17]<<16);
case 17: c+=((ub8)k[16]<<8);
/* the first byte of c is reserved for the length */
case 16: b+=((ub8)k[15]<<56);
case 15: b+=((ub8)k[14]<<48);
case 14: b+=((ub8)k[13]<<40);
case 13: b+=((ub8)k[12]<<32);
case 12: b+=((ub8)k[11]<<24);
case 11: b+=((ub8)k[10]<<16);
case 10: b+=((ub8)k[ 9]<<8);
case 9: b+=((ub8)k[ 8]);
case 8: a+=((ub8)k[ 7]<<56);
case 7: a+=((ub8)k[ 6]<<48);
case 6: a+=((ub8)k[ 5]<<40);
case 5: a+=((ub8)k[ 4]<<32);
case 4: a+=((ub8)k[ 3]<<24);
case 3: a+=((ub8)k[ 2]<<16);
case 2: a+=((ub8)k[ 1]<<8);
case 1: a+=((ub8)k[ 0]);
/* case 0: nothing left to add */
}
mix64(a,b,c);
/*-------------------------------------------- report the result */
return c;
}
/*
--------------------------------------------------------------------
This works on all machines, is identical to hash() on little-endian
machines, and it is much faster than hash(), but it requires
-- that the key be an array of ub8's, and
-- that all your machines have the same endianness, and
-- that the length be the number of ub8's in the key
--------------------------------------------------------------------
*/
static INLINE ub8 hash2(register const ub8 *k, /* the key */
register ub4 length, /* the length of the key */
register ub8 level) /* the previous hash, or an arbitrary value */
{
register ub8 a,b,c;
ub4 len;
/* Set up the internal state */
len = length;
a = b = level; /* the previous hash value */
c = CONST64U(0x9e3779b97f4a7c13); /* the golden ratio; an arbitrary value */
/*---------------------------------------- handle most of the key */
while (len >= 3)
{
a += k[0];
b += k[1];
c += k[2];
mix64(a,b,c);
k += 3; len -= 3;
}
/*-------------------------------------- handle the last 2 ub8's */
c += length;
switch(len) /* all the case statements fall through */
{
/* c is reserved for the length */
case 2: b+=k[1];
case 1: a+=k[0];
/* case 0: nothing left to add */
}
mix64(a,b,c);
/*-------------------------------------------- report the result */
return c;
}
/*
--------------------------------------------------------------------
This is identical to hash() on little-endian machines, and it is much
faster than hash(), but a little slower than hash2(), and it requires
-- that all your machines be little-endian, for example all Intel x86
chips or all VAXen. It gives wrong results on big-endian machines.
--------------------------------------------------------------------
*/
static INLINE ub8 hash3(register const ub1 *k, /* the key */
register ub4 length, /* the length of the key */
register ub8 level) /* the previous hash, or an arbitrary value */
{
register ub8 a,b,c;
ub4 len;
/* Set up the internal state */
len = length;
a = b = level; /* the previous hash value */
c = CONST64U(0x9e3779b97f4a7c13); /* the golden ratio; an arbitrary value */
/*---------------------------------------- handle most of the key */
if (((size_t)k)&7)
{
while (len >= 24)
{
a += (k[0] +((ub8)k[ 1]<< 8)+((ub8)k[ 2]<<16)+((ub8)k[ 3]<<24)
+((ub8)k[4 ]<<32)+((ub8)k[ 5]<<40)+((ub8)k[ 6]<<48)+((ub8)k[ 7]<<56));
b += (k[8] +((ub8)k[ 9]<< 8)+((ub8)k[10]<<16)+((ub8)k[11]<<24)
+((ub8)k[12]<<32)+((ub8)k[13]<<40)+((ub8)k[14]<<48)+((ub8)k[15]<<56));
c += (k[16] +((ub8)k[17]<< 8)+((ub8)k[18]<<16)+((ub8)k[19]<<24)
+((ub8)k[20]<<32)+((ub8)k[21]<<40)+((ub8)k[22]<<48)+((ub8)k[23]<<56));
mix64(a,b,c);
k += 24; len -= 24;
}
}
else
{
while (len >= 24) /* aligned */
{
a += *(ub8 *)(k+0);
b += *(ub8 *)(k+8);
c += *(ub8 *)(k+16);
mix64(a,b,c);
k += 24; len -= 24;
}
}
/*------------------------------------- handle the last 23 bytes */
c += length;
switch(len) /* all the case statements fall through */
{
case 23: c+=((ub8)k[22]<<56);
case 22: c+=((ub8)k[21]<<48);
case 21: c+=((ub8)k[20]<<40);
case 20: c+=((ub8)k[19]<<32);
case 19: c+=((ub8)k[18]<<24);
case 18: c+=((ub8)k[17]<<16);
case 17: c+=((ub8)k[16]<<8);
/* the first byte of c is reserved for the length */
case 16: b+=((ub8)k[15]<<56);
case 15: b+=((ub8)k[14]<<48);
case 14: b+=((ub8)k[13]<<40);
case 13: b+=((ub8)k[12]<<32);
case 12: b+=((ub8)k[11]<<24);
case 11: b+=((ub8)k[10]<<16);
case 10: b+=((ub8)k[ 9]<<8);
case 9: b+=((ub8)k[ 8]);
case 8: a+=((ub8)k[ 7]<<56);
case 7: a+=((ub8)k[ 6]<<48);
case 6: a+=((ub8)k[ 5]<<40);
case 5: a+=((ub8)k[ 4]<<32);
case 4: a+=((ub8)k[ 3]<<24);
case 3: a+=((ub8)k[ 2]<<16);
case 2: a+=((ub8)k[ 1]<<8);
case 1: a+=((ub8)k[ 0]);
/* case 0: nothing left to add */
}
mix64(a,b,c);
/*-------------------------------------------- report the result */
return c;
}
#endif //_HASH_FUNC_H
+17
View File
@@ -0,0 +1,17 @@
/*********************************************************
* Copyright (C) 2008 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
*
*********************************************************/
+43
View File
@@ -0,0 +1,43 @@
/*********************************************************
* 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
* 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 _INITBLOCK_H
#define _INITBLOCK_H
#define INCLUDE_ALLOW_VMX
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#include "includeCheck.h"
#include "basic_initblock.h"
#define MAX_LOGFILE_NAME_LENGTH 256
#define MAX_MONITOR_REGIONS 8
#define INIT_BLOCK_MAGIC (0x1789+14)
/*
* Option flags
*/
/* None yet */
#endif
+623
View File
@@ -0,0 +1,623 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* iocontrols.h
*
* The driver io controls.
*/
#ifndef _IOCONTROLS_H_
#define _IOCONTROLS_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_MODULE
#include "includeCheck.h"
#ifdef VMX86_SERVER
#error iocontrols.h is for hosted vmmon, do not use on visor
#endif
#include "basic_initblock.h"
#include "x86segdescrs.h"
#include "rateconv.h"
#include "overheadmem_types.h"
#include "pageLock_defs.h"
#include "numa_defs.h"
/*
*-----------------------------------------------------------------------------
*
* VA64ToPtr --
*
* Convert a VA64 to a pointer.
*
* Usage of this function is strictly limited to these 2 cases:
*
* 1) In a VMX function which does an ioctl to vmmon, and receives a VMX
* pointer as a result.
*
* 2) In the vmmon code, for the functions which have a VA64 and need
* to call kernel APIs which take pointers.
*
* Results:
* Virtual address.
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static INLINE void *
VA64ToPtr(VA64 va64) // IN
{
#ifdef VM_64BIT
ASSERT_ON_COMPILE(sizeof (void *) == 8);
#else
ASSERT_ON_COMPILE(sizeof (void *) == 4);
// Check that nothing of value will be lost.
ASSERT(!(va64 >> 32));
#endif
return (void *)(uintptr_t)va64;
}
/*
*-----------------------------------------------------------------------------
*
* PtrToVA64 --
*
* Convert a pointer to a VA64.
*
* Usage of this function is strictly limited to these 2 cases:
*
* 1) In a VMX function which does an ioctl to vmmon, and passes in a VMX
* pointer.
*
* 2) In the vmmon code, for the functions which need to pass in a kernel
* pointer to functions which can take either a user or a kernel
* pointer in the same parameter.
*
* Results:
* Virtual address.
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static INLINE VA64
PtrToVA64(void const *ptr) // IN
{
ASSERT_ON_COMPILE(sizeof ptr <= sizeof (VA64));
return (VA64)(uintptr_t)ptr;
}
/*
* Driver version.
*
* Increment major version when you make an incompatible change.
* Compatibility goes both ways (old driver with new executable
* as well as new driver with old executable).
*
* Note: Vmcore compatibility is different from driver versioning.
* For vmcore puposes, the bora tree is conceptually split in two:
* vmcore, and rest-of-bora. The vmmon driver is largely outside
* vmcore and vmcore imports functionality from vmmon. Addition,
* deletion or modification of an iocontrol used only by rest-of-bora
* does not break vmcore compatibility.
*
* See bora/doc/vmcore details.
*
*/
#define VMMON_VERSION (308 << 16 | 0)
#define VMMON_VERSION_MAJOR(v) ((uint32) (v) >> 16)
#define VMMON_VERSION_MINOR(v) ((uint16) (v))
/*
* ENOMEM returned after MAX_VMS virtual machines created
*/
#ifdef VMX86_SERVER
#define MAX_VMS 128
#else
#define MAX_VMS 64
#endif
/*
* MsgWaitForMultipleObjects doesn't scale well enough on Win32.
* Allocate with MAX_VMS so static buffers are large, but do
* admissions control with this value on Win32 until we check
* scalability (probably in authd).
*/
#ifdef _WIN32
#define MAX_VMS_WIN32 64
#endif
#if !__linux__
/*
* On platforms other than Linux, IOCTLCMD_foo values are just numbers, and
* we build the IOCTL_VMX86_foo values around these using platform-specific
* format for encoding arguments and sizes.
*/
# define IOCTLCMD(_cmd) IOCTLCMD_ ## _cmd
#else // if __linux__
/*
* Linux defines _IO* macros, but the core kernel code ignore the encoded
* ioctl value. It is up to individual drivers to decode the value (for
* example to look at the size of a structure to determine which version
* of a specific command should be used) or not (which is what we
* currently do, so right now the ioctl value for a given command is the
* command itself).
*
* Hence, we just define the IOCTL_VMX86_foo values directly, with no
* intermediate IOCTLCMD_ representation.
*/
# define IOCTLCMD(_cmd) IOCTL_VMX86_ ## _cmd
#endif
enum IOCTLCmd {
/*
* We need to bracket the range of values used for ioctls, because x86_64
* Linux forces us to explicitly register ioctl handlers by value for
* handling 32 bit ioctl syscalls. Hence FIRST and LAST. FIRST must be
* 2001 so that VERSION is 2001 for backwards compatibility.
*/
#if defined __linux__ || defined _WIN32
/* Start at 2001 because legacy code did. */
IOCTLCMD(FIRST) = 2001,
#else
/* Start at 0. */
IOCTLCMD(FIRST),
#endif
IOCTLCMD(VERSION) = IOCTLCMD(FIRST),
IOCTLCMD(CREATE_VM),
IOCTLCMD(RELEASE_VM),
IOCTLCMD(GET_NUM_VMS),
IOCTLCMD(ALLOC_CROSSGDT),
IOCTLCMD(INIT_VM),
IOCTLCMD(INIT_CROSSGDT),
IOCTLCMD(RUN_VM),
IOCTLCMD(LOOK_UP_MPN),
IOCTLCMD(LOCK_PAGE),
IOCTLCMD(UNLOCK_PAGE),
IOCTLCMD(APIC_INIT),
IOCTLCMD(SET_HARD_LIMIT),
IOCTLCMD(GET_MEM_INFO),
IOCTLCMD(ADMIT),
IOCTLCMD(UPDATE_MEM_INFO),
IOCTLCMD(READMIT),
IOCTLCMD(PAE_ENABLED),
IOCTLCMD(GET_TOTAL_MEM_USAGE),
IOCTLCMD(GET_KHZ_ESTIMATE),
IOCTLCMD(SET_HOST_CLOCK_RATE),
IOCTLCMD(READ_PAGE),
IOCTLCMD(WRITE_PAGE),
IOCTLCMD(LOCK_PAGE_NEW),
IOCTLCMD(UNLOCK_PAGE_BY_MPN),
/* AWE calls */
IOCTLCMD(ALLOC_LOCKED_PAGES),
IOCTLCMD(FREE_LOCKED_PAGES),
IOCTLCMD(GET_NEXT_ANON_PAGE),
IOCTLCMD(GET_LOCKED_PAGES_LIST),
IOCTLCMD(GET_ALL_MSRS),
IOCTLCMD(COUNT_PRESENT_PAGES),
IOCTLCMD(GET_REFERENCE_CLOCK_HZ),
IOCTLCMD(INIT_PSEUDO_TSC),
IOCTLCMD(CHECK_PSEUDO_TSC),
IOCTLCMD(GET_PSEUDO_TSC),
IOCTLCMD(SYNC_GET_TSCS),
IOCTLCMD(GET_IPI_VECTORS),
IOCTLCMD(SEND_IPI),
/*
* Keep host-specific calls at the end so they can be undefined
* without renumbering the common calls.
*/
#if defined __linux__
IOCTLCMD(SET_UID), // VMX86_DEVEL only
#endif
#if defined __linux__ || defined __APPLE__
IOCTLCMD(GET_ALL_CPUID),
IOCTLCMD(GET_KERNEL_CLOCK_RATE),
#endif
#if defined _WIN32 || defined __APPLE__
IOCTLCMD(ALLOC_CONTIG_PAGES),
#endif
#if defined _WIN32
IOCTLCMD(FREE_CONTIG_PAGES),
IOCTLCMD(HARD_LIMIT_MONITOR_STATUS), // Windows 2000 only
IOCTLCMD(BLUE_SCREEN), // USE_BLUE_SCREEN only
IOCTLCMD(CHANGE_HARD_LIMIT),
IOCTLCMD(GET_KERNEL_PROC_ADDRESS),
IOCTLCMD(READ_VA64),
IOCTLCMD(SET_MEMORY_PARAMS),
IOCTLCMD(REMEMBER_KHZ_ESTIMATE),
IOCTLCMD(REMAP_SCATTER_LIST),
IOCTLCMD(UNMAP_SCATTER_LIST),
#endif
#if defined __APPLE__
IOCTLCMD(ALLOC_LOW_PAGES),
IOCTLCMD(INIT_DRIVER),
IOCTLCMD(BLUEPILL),
#endif
IOCTLCMD(SET_POLL_TIMEOUT_PTR),
IOCTLCMD(FAST_SUSP_RES_SET_OTHER_FLAG),
IOCTLCMD(FAST_SUSP_RES_GET_MY_FLAG),
#if defined __linux__
IOCTLCMD(SET_HOST_CLOCK_PRIORITY),
IOCTLCMD(VMX_ENABLED),
IOCTLCMD(SET_HOST_SWAP_SIZE),
#endif
IOCTLCMD(GET_UNAVAIL_PERF_CTRS),
// Must be last.
IOCTLCMD(LAST)
};
#if defined _WIN32
/*
* Windows ioctl definitions.
*
* We use the IRP Information field for the return value
* of IOCTLCMD_RUN_VM, to be faster since it is used a lot.
*/
#define FILE_DEVICE_VMX86 0x8101
#define VMX86_IOCTL_BASE_INDEX 0x801
#define VMIOCTL_BUFFERED(name) \
CTL_CODE(FILE_DEVICE_VMX86, \
VMX86_IOCTL_BASE_INDEX + IOCTLCMD_ ## name, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define VMIOCTL_NEITHER(name) \
CTL_CODE(FILE_DEVICE_VMX86, \
VMX86_IOCTL_BASE_INDEX + IOCTLCMD_ ## name, \
METHOD_NEITHER, \
FILE_ANY_ACCESS)
#define IOCTL_VMX86_VERSION VMIOCTL_BUFFERED(VERSION)
#define IOCTL_VMX86_CREATE_VM VMIOCTL_BUFFERED(CREATE_VM)
#define IOCTL_VMX86_RELEASE_VM VMIOCTL_BUFFERED(RELEASE_VM)
#define IOCTL_VMX86_GET_NUM_VMS VMIOCTL_BUFFERED(GET_NUM_VMS)
#define IOCTL_VMX86_ALLOC_CROSSGDT VMIOCTL_BUFFERED(ALLOC_CROSSGDT)
#define IOCTL_VMX86_INIT_VM VMIOCTL_BUFFERED(INIT_VM)
#define IOCTL_VMX86_INIT_CROSSGDT VMIOCTL_BUFFERED(INIT_CROSSGDT)
#define IOCTL_VMX86_RUN_VM VMIOCTL_NEITHER(RUN_VM)
#define IOCTL_VMX86_SEND_IPI VMIOCTL_NEITHER(SEND_IPI)
#define IOCTL_VMX86_GET_IPI_VECTORS VMIOCTL_BUFFERED(GET_IPI_VECTORS)
#define IOCTL_VMX86_LOOK_UP_MPN VMIOCTL_BUFFERED(LOOK_UP_MPN)
#define IOCTL_VMX86_LOCK_PAGE VMIOCTL_BUFFERED(LOCK_PAGE)
#define IOCTL_VMX86_UNLOCK_PAGE VMIOCTL_BUFFERED(UNLOCK_PAGE)
#define IOCTL_VMX86_APIC_INIT VMIOCTL_BUFFERED(APIC_INIT)
#define IOCTL_VMX86_SET_HARD_LIMIT VMIOCTL_BUFFERED(SET_HARD_LIMIT)
#define IOCTL_VMX86_GET_MEM_INFO VMIOCTL_BUFFERED(GET_MEM_INFO)
#define IOCTL_VMX86_ADMIT VMIOCTL_BUFFERED(ADMIT)
#define IOCTL_VMX86_READMIT VMIOCTL_BUFFERED(READMIT)
#define IOCTL_VMX86_UPDATE_MEM_INFO VMIOCTL_BUFFERED(UPDATE_MEM_INFO)
#define IOCTL_VMX86_PAE_ENABLED VMIOCTL_BUFFERED(PAE_ENABLED)
#define IOCTL_VMX86_BEEP VMIOCTL_BUFFERED(BEEP)
#define IOCTL_VMX86_HARD_LIMIT_MONITOR_STATUS VMIOCTL_BUFFERED(HARD_LIMIT_MONITOR_STATUS)
#define IOCTL_VMX86_CHANGE_HARD_LIMIT VMIOCTL_BUFFERED(CHANGE_HARD_LIMIT)
#define IOCTL_VMX86_ALLOC_CONTIG_PAGES VMIOCTL_BUFFERED(ALLOC_CONTIG_PAGES)
#define IOCTL_VMX86_FREE_CONTIG_PAGES VMIOCTL_BUFFERED(FREE_CONTIG_PAGES)
#define IOCTL_VMX86_GET_TOTAL_MEM_USAGE VMIOCTL_BUFFERED(GET_TOTAL_MEM_USAGE)
#define IOCTL_VMX86_GET_KHZ_ESTIMATE VMIOCTL_BUFFERED(GET_KHZ_ESTIMATE)
#define IOCTL_VMX86_SET_HOST_CLOCK_RATE VMIOCTL_BUFFERED(SET_HOST_CLOCK_RATE)
#define IOCTL_VMX86_SYNC_GET_TSCS VMIOCTL_BUFFERED(SYNC_GET_TSCS)
#define IOCTL_VMX86_READ_PAGE VMIOCTL_BUFFERED(READ_PAGE)
#define IOCTL_VMX86_WRITE_PAGE VMIOCTL_BUFFERED(WRITE_PAGE)
#define IOCTL_VMX86_LOCK_PAGE_NEW VMIOCTL_BUFFERED(LOCK_PAGE_NEW)
#define IOCTL_VMX86_UNLOCK_PAGE_BY_MPN VMIOCTL_BUFFERED(UNLOCK_PAGE_BY_MPN)
#define IOCTL_VMX86_ALLOC_LOCKED_PAGES VMIOCTL_BUFFERED(ALLOC_LOCKED_PAGES)
#define IOCTL_VMX86_FREE_LOCKED_PAGES VMIOCTL_BUFFERED(FREE_LOCKED_PAGES)
#define IOCTL_VMX86_GET_NEXT_ANON_PAGE VMIOCTL_BUFFERED(GET_NEXT_ANON_PAGE)
#define IOCTL_VMX86_GET_LOCKED_PAGES_LIST VMIOCTL_BUFFERED(GET_LOCKED_PAGES_LIST)
#define IOCTL_VMX86_GET_KERNEL_PROC_ADDRESS VMIOCTL_BUFFERED(GET_KERNEL_PROC_ADDRESS)
#define IOCTL_VMX86_READ_VA64 VMIOCTL_BUFFERED(READ_VA64)
#define IOCTL_VMX86_SET_MEMORY_PARAMS VMIOCTL_BUFFERED(SET_MEMORY_PARAMS)
#define IOCTL_VMX86_REMEMBER_KHZ_ESTIMATE VMIOCTL_BUFFERED(REMEMBER_KHZ_ESTIMATE)
#define IOCTL_VMX86_GET_ALL_MSRS VMIOCTL_BUFFERED(GET_ALL_MSRS)
#define IOCTL_VMX86_COUNT_PRESENT_PAGES VMIOCTL_BUFFERED(COUNT_PRESENT_PAGES)
#define IOCTL_VMX86_FAST_SUSP_RES_SET_OTHER_FLAG VMIOCTL_BUFFERED(FAST_SUSP_RES_SET_OTHER_FLAG)
#define IOCTL_VMX86_FAST_SUSP_RES_GET_MY_FLAG VMIOCTL_BUFFERED(FAST_SUSP_RES_GET_MY_FLAG)
#define IOCTL_VMX86_GET_REFERENCE_CLOCK_HZ VMIOCTL_BUFFERED(GET_REFERENCE_CLOCK_HZ)
#define IOCTL_VMX86_INIT_PSEUDO_TSC VMIOCTL_BUFFERED(INIT_PSEUDO_TSC)
#define IOCTL_VMX86_CHECK_PSEUDO_TSC VMIOCTL_BUFFERED(CHECK_PSEUDO_TSC)
#define IOCTL_VMX86_GET_PSEUDO_TSC VMIOCTL_NEITHER(GET_PSEUDO_TSC)
#define IOCTL_VMX86_SET_HOST_CLOCK_PRIORITY VMIOCTL_BUFFERED(SET_HOST_CLOCK_PRIORITY)
#define IOCTL_VMX86_GET_UNAVAIL_PERF_CTRS VMIOCTL_NEITHER(GET_UNAVAIL_PERF_CTRS)
#define IOCTL_VMX86_REMAP_SCATTER_LIST VMIOCTL_BUFFERED(REMAP_SCATTER_LIST)
#define IOCTL_VMX86_UNMAP_SCATTER_LIST VMIOCTL_BUFFERED(UNMAP_SCATTER_LIST)
#endif
/*
* Flags sent into APICBASE ioctl
*/
#define APIC_FLAG_DISABLE_NMI 0x00000001
#define APIC_FLAG_PROBE 0x00000002
#define APIC_FLAG_FORCE_ENABLE 0x00000004
typedef
#include "vmware_pack_begin.h"
struct VMLockPageRet {
MPN mpn; // OUT: MPN
int32 status; // OUT: PAGE_* status code
}
#include "vmware_pack_end.h"
VMLockPageRet;
typedef
#include "vmware_pack_begin.h"
union {
VA64 uAddr; // IN: user address
VMLockPageRet ret; // OUT: status code and MPN
}
#include "vmware_pack_end.h"
VMLockPage;
typedef struct VMAPICInfo {
uint32 flags;
} VMAPICInfo;
#define VMX86_DRIVER_VCPUID_OFFSET 1000
/*
* We keep track of 3 different limits on the number of pages we can lock.
* The host limit is determined at driver load time (in windows only) to
* make sure we do not starve the host by locking too many pages.
* The static limit is user defined in the UI and the dynamic limit is
* set by authd's hardLimitMonitor code (windows only), which queries
* host load and adjusts the limit accordingly. We lock the minimum of
* all these values at any given time.
*/
typedef struct LockedPageLimit {
uint32 host; // driver calculated maximum for this host
uint32 configured; // user defined maximum pages to lock
uint32 dynamic; // authd hardLimitMonitor pages to lock
} LockedPageLimit;
/*
* Sentinel VA for IOCTL_VMX86_SET_MEMORY_PARAMS, indicates
* NtQuerySystemInformation should be used to determine the host
* LockedPageLimit.
*/
#define MEMORY_PARAM_USE_SYSINFO_FOR_LOCKED_PAGE_LIMIT ((VA64)(int64)-1)
/*
* Data structures for the GET_MEM_INFO and ADMIT ioctls.
*
* Be careful adding structs and fields to VMMemInfoArgs and its
* substructures. These are compiled into both the 32-bit and 64-bit
* vmmon drivers and the 32-bit and 64-bit vmx's and need to have
* the same size and layout in all four combinations. Note the
* use of padding below to ensure that this happens.
*/
typedef struct VMMemMgmtInfo {
uint32 minAllocation; // minimum pages for vm
uint32 maxAllocation; // maximum pages the vm could lock
uint32 shares; // proportional sharing weight
uint32 nonpaged; // overhead memory (guest, mmap)
uint32 paged; // vmx memory (malloc, statics)
uint32 anonymous; // vmm memory
uint32 mainMemSize; // guest main memory size
uint32 locked; // number of pages locked by this vm
uint32 perVMOverhead; // memory for vmx/vmmon overheads
Percent touchedPct; // % of guest memory being touched
Percent dirtiedPct; // % of guest memory being dirtied
Bool admitted; // admission control
uint8 _pad; // for alignment of 64-bit fields
uint64 hugePageBytes; // number of bytes occupied by huge pages
uint64 timestamp; // most recent poll of get mem info time
} VMMemMgmtInfo;
typedef struct VMMemMgmtInfoPatch {
Percent touchedPct; // % of guest memory being touched
Percent dirtiedPct; // % of guest memory being dirtied
uint8 _pad[6];
uint64 hugePageBytes;
} VMMemMgmtInfoPatch;
/*
* See comment on padding and size/layout constraints above when
* when modifying VMMemInfoArgs or its components.
*/
typedef struct VMMemInfoArgs {
uint64 currentTime; // Host time in secs of the call.
uint32 minVmMemPct; // % of vm that must fit in memory
uint32 globalMinAllocation;// pages that must fit in maxLockedPages
uint32 numLockedPages; // total locked pages by all vms
LockedPageLimit lockedPageLimit; // set of locked page limits
uint32 maxLockedPages; // effective limit on locked pages
uint32 callerIndex; // this vm's index memInfo array
uint32 numVMs; // number of running VMs
uint8 _pad[4];
VMMemMgmtInfo memInfo[1];
} VMMemInfoArgs;
#define VM_GET_MEM_INFO_SIZE(numVMs) \
(sizeof(VMMemInfoArgs) - sizeof(VMMemMgmtInfo) + (numVMs) * sizeof(VMMemMgmtInfo))
typedef struct VMMPNNext {
MPN inMPN; // IN
MPN outMPN; // OUT
} VMMPNNext;
typedef struct VMMPNList {
uint32 mpnCount; // IN (and OUT on Mac OS)
Bool ignoreLimits;
uint8 _pad[3];
VA64 mpnList; // IN: User VA of an array of 64-bit MPNs.
} VMMPNList;
typedef struct VARange {
VA64 addr;
VA64 bv;
unsigned len;
uint32 pad;
} VARange;
typedef struct VMMUnlockPageByMPN {
MPN mpn;
VA64 uAddr; /* IN: User VA of the page (optional). */
} VMMUnlockPageByMPN;
typedef struct VMMReadWritePage {
MPN mpn; // IN
VA64 uAddr; // IN: User VA of a PAGE_SIZE-large buffer.
} VMMReadWritePage;
struct passthrough_iorange {
unsigned short ioBase; /* Base of range to pass through. */
unsigned short numPorts; /* Length of range. */
};
/*
* Data structure for the INIT_PSEUDO_TSC and CHECK_PSEUDO_TSC.
*/
typedef struct PTSCInitParams {
RateConv_Params refClockToPTSC;
uint64 tscHz;
uint64 initialPTSC;
int64 tscOffset;
Bool forceRefClock;
Bool forceTSC;
Bool hwTSCsSynced;
uint8 _pad[5];
} PTSCInitParams;
typedef struct PTSCCheckParams {
uint64 lastTSC;
uint64 lastRC;
Bool usingRefClock;
uint8 _pad[7];
} PTSCCheckParams;
#ifndef VMX86_SERVER
typedef struct IPIVectors {
/*
* Vector(s) the host uses for its own IPIs; we use this as a performance
* hint.
*/
uint8 hostIPIVectors[2];
/*
* Vectors we have allocated or stolen for the monitor interrupts.
*/
uint8 monitorIPIVector;
uint8 hvIPIVector;
} IPIVectors;
#endif
/*
* This struct is passed to IOCTL_VMX86_INIT_CROSSGDT to fill in a crossGDT
* entry.
*/
typedef struct InitCrossGDT {
uint32 index; // index in crossGDT to update (offset / 8)
Descriptor value; // value to set the crossGDT entry to
} InitCrossGDT;
#if defined __linux__
/*
* Linux uses mmap(2) to allocate contiguous locked pages, and uses these
* macros to marshall real arguments to mmap's made-up 'offset' argument.
*/
#define VMMON_MAP_MT_LOW4GB 0
#define VMMON_MAP_MT_LOW16MB 1
#define VMMON_MAP_MT_ANY 2
#define VMMON_MAP_OFFSET_SHIFT 0
#define VMMON_MAP_OFFSET_MASK 0x00000FFF
#define VMMON_MAP_ORDER_SHIFT 12
#define VMMON_MAP_ORDER_MASK 0xF
#define VMMON_MAP_MT_SHIFT 16
#define VMMON_MAP_MT_MASK 0x7
#define VMMON_MAP_RSVD_SHIFT 19
#define VMMON_MAP_RSVD(base) \
((base) >> VMMON_MAP_RSVD_SHIFT)
#define VMMON_MAP_MT(base) \
(((base) >> VMMON_MAP_MT_SHIFT) & VMMON_MAP_MT_MASK)
#define VMMON_MAP_ORDER(base) \
(((base) >> VMMON_MAP_ORDER_SHIFT) & VMMON_MAP_ORDER_MASK)
#define VMMON_MAP_OFFSET(base) \
(((base) >> VMMON_MAP_OFFSET_SHIFT) & VMMON_MAP_OFFSET_MASK)
#define VMMON_MAP_BASE(mt, order) (((mt) << VMMON_MAP_MT_SHIFT) | \
((order) << VMMON_MAP_ORDER_SHIFT))
#elif defined _WIN32
/*
* Windows uses an ioctl to allocate contiguous locked pages.
*/
typedef struct VMAllocContiguousMem {
VA64 mpnList; // IN: User VA of an array of 64-bit MPNs.
uint32 mpnCount; // IN
uint32 order; // IN
MPN maxMPN; // IN
} VMAllocContiguousMem;
#elif defined __APPLE__
# include "iocontrolsMacos.h"
#endif
/* Clean up helper macros */
#undef IOCTLCMD
#endif // ifndef _IOCONTROLS_H_
+154
View File
@@ -0,0 +1,154 @@
/*********************************************************
* Copyright (C) 1998-2012 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 _MEMDEFAULTS_H_
#define _MEMDEFAULTS_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_MODULE
#include "includeCheck.h"
#include "vm_basic_math.h"
#include "vm_basic_defs.h"
#define MEMDEFAULTS_MIN_HOST_PAGES MBYTES_2_PAGES(128)
/*
*-----------------------------------------------------------------------------
*
* MemDefaults_CalcMaxLockedPages --
*
* Calculate the rough estimate of the maximum amount of memory
* that can be locked (total for the kernel, all VMs, and other apps),
* based on the size of host memory as supplied in pages.
*
* Results:
* The estimated maximum memory that can be locked in pages.
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static INLINE unsigned
MemDefaults_CalcMaxLockedPages(unsigned hostPages) // IN:
{
unsigned reservedPages;
#if defined(__APPLE__)
/*
* Reserve (25% of the host memory + 512 MB) or 4 GB, whichever is lower.
* 4 GB hosts perform poorly with less than 1.5 GB reserved, and large
* memory hosts (>= 16 GB) may want to use more than 75% for VMs.
*/
reservedPages = MIN((hostPages / 4) + MBYTES_2_PAGES(512),
GBYTES_2_PAGES(4));
#elif defined(_WIN32)
{
unsigned int hostGig = PAGES_2_GBYTES(hostPages);
if (hostGig <= 4) {
reservedPages = hostPages / 4;
} else if (hostGig >= 16) {
reservedPages = hostPages / 8;
} else {
/*
* Increment by 1/32 for each 4GB of host mem between 4 and 16.
* See PR779556.
*/
reservedPages = hostPages / 32 * (8 - hostGig / 4);
}
}
#else // Linux
reservedPages = hostPages / 8;
#endif
reservedPages = MAX(reservedPages, MEMDEFAULTS_MIN_HOST_PAGES);
return hostPages > reservedPages ? hostPages - reservedPages : 0;
}
/*
*-----------------------------------------------------------------------------
*
* MemDefaults_CalcMaxLockedMBs --
*
* Calculate the rough estimate of the maximum amount of memory
* that can be locked based on the size of host memory as supplied
* in MBytes.
*
* Results:
* The estimated maximum memory that can be locked in MBytes.
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static INLINE uint32
MemDefaults_CalcMaxLockedMBs(uint32 hostMem) // IN:
{
return PAGES_2_MBYTES(
MemDefaults_CalcMaxLockedPages(MBYTES_2_PAGES(hostMem)));
}
/*
*-----------------------------------------------------------------------------
*
* MemDefaults_CalcMinReservedMBs --
*
* Provide a lower bound on the user as to the minimum amount
* of memory to lock based on the size of host memory. This
* threshold might be crossed as a result of the user limiting
* the amount of memory consumed by all VMs.
*
* Results:
* The minimum locked memory requirement in MBytes.
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static INLINE uint32
MemDefaults_CalcMinReservedMBs(uint32 hostMem) // IN:
{
if (hostMem < 512) {
return 32;
} else if (hostMem < 1024) {
return 64;
} else {
return 128;
}
}
void MemDefaults_GetReservedMemory(uint32 *host, uint32 *min,
uint32 *max, uint32 *recommended);
#endif
+495
View File
@@ -0,0 +1,495 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* modulecall.h
*
* Monitor <--> Module (kernel driver) interface
*/
#ifndef _MODULECALL_H
#define _MODULECALL_H
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#include "includeCheck.h"
#include "x86types.h"
#include "x86desc.h"
#include "ptsc.h"
#include "vcpuid.h"
#include "vcpuset.h"
#include "vmm_constants.h"
#include "contextinfo.h"
#include "rateconv.h"
#include "modulecallstructs.h"
#include "mon_assert.h"
#define NUM_EXCEPTIONS 20 /* EXC_DE ... EXC_XF. */
#define MODULECALL_TABLE \
MC(INTR) \
MC(SEMAWAIT) \
MC(SEMASIGNAL) \
MC(SEMAFORCEWAKEUP) \
MC(IPI) /* Hit thread with IPI. */ \
MC(USERRETURN) /* Return codes for user calls. */ \
MC(GET_RECYCLED_PAGES) \
MC(RELEASE_ANON_PAGES) \
MC(LOOKUP_MPN) \
MC(COSCHED) \
MC(ALLOC_VMX_PAGE) \
MC(ALLOC_TMP_GDT) \
MC(PIN_MPN)
/*
*----------------------------------------------------------------------
*
* ModuleCallType --
*
* Enumeration of support calls done by the module.
*
* If anything changes in the enum, please update kstatModuleCallPtrs
* for stats purposes.
*
*----------------------------------------------------------------------
*/
typedef enum ModuleCallType {
MODULECALL_NONE = 100,
#define MC(_modulecall) MODULECALL_##_modulecall,
MODULECALL_TABLE
#undef MC
MODULECALL_LAST // Number of entries. Must be the last one
} ModuleCallType;
#define MODULECALL_USERCALL_NONE 300
/*
* Define VMX86_UCCOST in the makefiles (Local.mk,
* typically) if you want a special build whose only purpose
* is to measure the overhead of a user call and its
* breakdown.
*
* WINDOWS NOTE: I don't know how to pass VMX86_UCCOST to
* the driver build on Windows. It must be defined by hand.
*
* ESX Note: we don't have a crosspage in which to store these
* timestamps. Such a feature would perhaps be nice (if we
* ever tire of the argument that esx does so few usercalls
* that speed doesn't matter).
*/
#if defined(VMX86_UCCOST) && !defined(VMX86_SERVER)
#define UCTIMESTAMP(cp, stamp) \
do { (cp)->ucTimeStamps[UCCOST_ ## stamp] = RDTSC(); } while (0)
#else
#define UCTIMESTAMP(cp, stamp)
#endif
#ifdef VMX86_SERVER
typedef struct UCCostResults {
uint32 vmksti;
uint32 vmkcli;
uint32 ucnop;
} UCCostResults;
#else
typedef struct UCCostResults {
uint32 htom;
uint32 mtoh;
uint32 ucnop;
} UCCostResults;
typedef enum UCCostStamp {
#define UC(x) UCCOST_ ## x,
#include "uccostTable.h"
UCCOST_MAX
} UCCostStamp;
#endif // VMX86_SERVER
/*
* Header for the wsBody64.S worldswitch code file.
*/
typedef struct WSModule {
uint32 vmmonVersion; // VMMON_VERSION when assembled as part of monitor
uint16 moduleSize; // size of whole wsBody64 module
uint16 hostToVmm; // offset from beginning of header to hostToVmm
uint16 vmm64ToHost;
uint16 _pad[3];
uint8 code[1024]; // big enough for MAX('.wsBody64', 'wsBody64Log')
} WSModule;
typedef
#include "vmware_pack_begin.h"
struct SwitchNMIOffsets {
uint16 db; // offset to start of #DB handler
uint16 nmi; // offset to start of #NMI handler
uint16 df; // offset to start of #DF handler
uint16 ud; // offset to start of #UD handler
uint16 gp; // offset to start of #GP handler
uint16 pf; // offset to start of #PF handler
uint16 mce; // offset to start of #MCE handler
}
#include "vmware_pack_end.h"
SwitchNMIOffsets;
/*
* This is a header for the switchNMI.S module. It contains code for
* exceptions occurring during worldswitch. The code gets copied to
* the crosspage by initialization.
*/
typedef
#include "vmware_pack_begin.h"
struct SwitchNMI { // see switchNMI.S
uint16 switchNMISize;
SwitchNMIOffsets host; // offsets to handlers
volatile Bool wsException[NUM_EXCEPTIONS]; // EXC_DE ... EXC_XF
// TRUE -> fault occurred in
// worldswitch
uint64 wsUD2; // IP of ud2 instruction
// 0ULL == unset
// other == worldswitch IP
uint8 codeBlock[768]; // Enough for
// max('.switchNMI',
// '.switchNMILog').
}
#include "vmware_pack_end.h"
SwitchNMI;
#define SHADOW_DR(cpData, n) (cpData)->shadowDR[n].ureg64
/*----------------------------------------------------------------------
*
* MAX_SWITCH_PT_PATCHES
*
* This is the maximum number of patches that must be placed into
* the monitor page tables so that two pages of the host GDT and the
* crosspage can be accessed during worldswitch.
*
*----------------------------------------------------------------------
*/
#define MAX_SWITCH_PT_PATCHES 3
/*----------------------------------------------------------------------
*
* WS_INTR_STRESS
*
* When set to non-zero, world switch code will enable single-step
* debugging across much of the switch path in both directions. The
* #DB handler detects single-stepping and induces a simulated NMI per
* instruction. This verifies that interrupts and exceptions are safe
* across the switch path, even if an NMI were raised during handling
* of another exception.
*
* When set to zero, normal worldswitch operation occurs.
*
* See the worldswitch assembly code for details.
*
*----------------------------------------------------------------------
*/
#define WS_INTR_STRESS 0
/*----------------------------------------------------------------------
*
* VMM64PageTablePatch
*
* Describes an entry in the monitor page table which needs to be
* patched during the back-to-host worldswitch.
*
* o A patch can appear at any place in the page table, and so four
* items are required to uniquely describe the patch:
*
* o level
*
* This is the level in the page table to which the patch must
* be applied: L4, L3, L2, L1. This information is used to
* determine the base of the region of memory which must be
* patched. The level value corresponds to the following
* regions in monitor memory:
*
* MMU_ROOT_64
* MMU_L3_64
* MMU_L2_64
* MON_PAGE_TABLE_64
*
* The value zero is reserved to indicate an empty spot in the
* array of patches.
*
* o level offset
*
* The monitor memory regions corresponding to the page table
* levels may be more than one page in length, so a 'page
* offset' is required to know the starting address of the page
* table page which must be patched in 'level'.
*
* o page index
*
* The 'index' value specifies the element in the page which
* should be patched.
*
* o pte
*
* This is the PTE value which will be patched into the monitor
* page table.
*
*----------------------------------------------------------------------
*/
typedef
#include "vmware_pack_begin.h"
struct VMM64PageTablePatch {
#define PTP_EMPTY (0U) /* Unused array entry. (must be 0) */
#define PTP_LEVEL_L1 (1U) /* leaf level */
#define PTP_LEVEL_L2 (2U)
#define PTP_LEVEL_L3 (3U)
#define PTP_LEVEL_L4 (4U) /* root level */
uint16 level; /* [0, 4] (maximal size: 3 bits) */
uint16 page; /* Index of 'page' in 'level'. */
uint32 index; /* Index of 'pte' in 'page'. */
VM_PDPTE pte; /* PTE. */
}
#include "vmware_pack_end.h"
VMM64PageTablePatch;
#define MODULECALL_NUM_ARGS 4
/*
*----------------------------------------------------------------------
*
* VMCrossPageData --
*
* Data which is stored on the VMCrossPage.
*
*----------------------------------------------------------------------
*/
typedef
#include "vmware_pack_begin.h"
struct VMCrossPageData {
/*
* A tiny stack upon which interrupt and exception handlers in the switch
* path temporarily run. Keep the end 16-byte aligned. This stack must
* be large enough for the sum of:
*
* - 1 #DB exception frame (5 * uint64)
* - 1 #NMI exception frame (5 * uint64)
* - 1 #MCE exception frame (5 * uint64)
* - the largest stack use instantaneously possible by #MCE handling code
* - the largest stack use instantaneously possible by #NMI handling code
* - the largest stack use instantaneously possible by #DB handling code
* - one high-water uint32 used to detect stack overflows when debugging
* - remaining pad bytes to align to 16 bytes
*
* 184 bytes is slightly more than enough as of 2015/03/17 -- fjacobs.
*/
uint32 tinyStack[46];
uint64 hostCR3;
uint32 crosspageMA;
uint8 hostDRSaved; // Host DR spilled to hostDR[x].
uint8 hostDRInHW; // 0 -> shadowDR in h/w, 1 -> hostDR in h/w.
// contains host-sized DB,NMI,MCE entries
uint16 hostSS;
uint64 hostRSP;
uint64 hostDR[8];
uint64 hostRBX;
uint64 hostRSI;
uint64 hostRDI;
uint64 hostRBP;
uint64 hostR12;
uint64 hostR13;
uint64 hostR14;
uint64 hostR15;
LA64 hostCrossPageLA; // where host has crosspage mapped
uint16 hostInitial64CS;
uint16 _pad0[3];
uint64 wsCR0;
uint64 wsCR4;
DTR64 crossGDTHKLADesc; // always uses host kernel linear address
uint16 _pad1[3];
DTR64 mon64GDTR;
uint16 mon64ES;
uint16 mon64SS;
uint16 mon64DS;
uint64 mon64CR3;
uint64 mon64RBX;
uint64 mon64RSP;
uint64 mon64RBP;
uint64 mon64RSI;
uint64 mon64RDI;
uint64 mon64R12;
uint64 mon64R13;
uint64 mon64R14;
uint64 mon64R15;
uint64 mon64RIP;
Task64 monTask64; /* vmm64's task */
VMM64PageTablePatch vmm64PTP[MAX_SWITCH_PT_PATCHES]; /* page table patch */
LA64 vmm64CrossPageLA;
LA64 vmm64CrossGDTLA; // where crossGDT mapped by PT patch
// 64-bit host: host kernel linear
// address
/*
* The monitor may requests up to two actions when returning to the
* host. The moduleCallType field and args encode a request for
* some action in the driver. The userCallType field (together
* with the RPC block) encodes a user call request. The two
* requests are independent. The user call is executed first, with
* the exception of MODULECALL_INTR which has a special effect.
*/
ModuleCallType moduleCallType;
uint32 retval;
uint64 args[MODULECALL_NUM_ARGS];
int userCallType;
uint32 pcpuNum; /* Used as extra module call arg within vmmon. */
VCPUSet yieldVCPUs;
#if !defined(VMX86_SERVER)
uint64 ucTimeStamps[UCCOST_MAX];
#endif
/*
* The values in the shadow debug registers must match those in the
* hardware debug register immediately after a task switch in
* either direction. They are used to minimize moves to and from
* the debug registers.
*/
SharedUReg64 shadowDR[8];
uint8 shadowDRInHW; // bit n set iff %DRn == shadowDR[n]
SwitchedMSRState switchedMSRState;
uint8 _pad2[7];
/*
* Adjustment for machines where the hardware TSC does not run
* constantly (laptops) or is out of sync between different PCPUs.
* Updated as needed by vmmon. See VMK_SharedData for the ESX
* analog, which is updated by the vmkernel.
*/
RateConv_ParamsVolatile pseudoTSCConv;
VmAbsoluteTS worldSwitchPTSC; // PTSC value immediately before
// last worldswitch.
VmAbsoluteTS timerIntrTS; // PTSC of timer interrupt while in the vmm
VmAbsoluteTS hstTimerExpiry; // PTSC of host timer interrupt
VmAbsoluteTS monTimerExpiry; // PTSC of next MonTimer callback
Bool activateVMX; // TRUE -> activate Intel VMX extensions
Bool activateSVM; // TRUE -> activate AMD SVM extensions
Bool retryWorldSwitch; // TRUE -> return to host on host->vmm switch
/*
* TRUE if moduleCall was interrupted by signal. Only
* vmmon uses this field to remember that it should
* restart RunVM call, nobody else should look at it.
*/
Bool moduleCallInterrupted;
uint8 _pad3[4];
DTR64 switchHostIDTR; // baseLA = switchHostIDT's host knl LA
uint16 _pad4[3];
DTR64 switchMon64IDTR; // has baseLA = switchMon64IDT's monitor LA
// contains 64-bit DB,NMI,MCE entries
uint16 _pad5[3];
/*
* Descriptors and interrupt tables for switchNMI handlers. Each
* IDT has only enough space for the hardware exceptions; they are
* sized to accommodate 64-bit descriptors.
*/
uint8 switchHostIDT [sizeof(Gate64) * NUM_EXCEPTIONS]; // hostCS:hostVA
uint8 switchMon64IDT[sizeof(Gate64) * NUM_EXCEPTIONS]; // 64-bit monCS:monVA
}
#include "vmware_pack_end.h"
VMCrossPageData;
/*
*----------------------------------------------------------------------
*
* VMCrossPageCode --
*
* Code which is stored on the VMCrossPage.
*
*----------------------------------------------------------------------
*/
typedef
#include "vmware_pack_begin.h"
struct VMCrossPageCode {
WSModule worldswitch;
SwitchNMI faultHandler;
}
#include "vmware_pack_end.h"
VMCrossPageCode;
/*
*----------------------------------------------------------------------
*
* VMCrossPage --
*
* Data structure shared between the monitor and the module
* that is used for crossing between the two.
* Accessible as vm->cross (kernel module) and CROSS_PAGE
* (monitor)
*
* Exactly one page long
*
*----------------------------------------------------------------------
*/
typedef
#include "vmware_pack_begin.h"
struct VMCrossPage {
uint32 version; /* 4 bytes. Must be at offset zero. */
uint32 crosspage_size; /* 4 bytes. Must be at offset 4. */
VMCrossPageData crosspageData;
uint8 _pad[PAGE_SIZE - (sizeof(uint32) /* version */ +
sizeof(uint32) /* crosspage_size */ +
sizeof(VMCrossPageData) +
sizeof(VMCrossPageCode))];
VMCrossPageCode crosspageCode;
}
#include "vmware_pack_end.h"
VMCrossPage;
#define CROSSPAGE_VERSION_BASE 0xbf1 /* increment by 1 */
#define CROSSPAGE_VERSION ((CROSSPAGE_VERSION_BASE << 1) + WS_INTR_STRESS)
#if !defined(VMX86_SERVER) && defined(VMM)
#define CROSS_PAGE ((VMCrossPage * const) VPN_2_VA(CROSS_PAGE_START))
#define VMM_SWITCH_SHARED_DATA ((VMCrossPageData *)&CROSS_PAGE->crosspageData)
#endif
#define NULLPAGE_LINEAR_START (MONITOR_LINEAR_START + \
PAGE_SIZE * CPL0_GUARD_PAGE_START)
#define MX_WAITINTERRUPTED 3
#define MX_WAITTIMEDOUT 2
#define MX_WAITNORMAL 1 // Must equal one; see linux module code.
#define MX_WAITERROR 0 // Use MX_ISWAITERROR() to test for error.
// Any zero or negative value denotes error.
#define MX_ISWAITERROR(e) ((e) <= MX_WAITERROR)
#endif
+99
View File
@@ -0,0 +1,99 @@
/*********************************************************
* Copyright (C) 2006,2009-2011,2013-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
* 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
*
*********************************************************/
/*
* modulecallstructs.h --
*
*
* Data structures that need to be included in modulecall.h
* as well as the vmkernel.
*
*/
#ifndef _MODULECALLSTRUCTS_H_
#define _MODULECALLSTRUCTS_H_
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "vm_basic_types.h"
/*
* Flags indicating switched MSR status.
*
* UNUSED - Not used by the monitor (yet). [This is a value, not a flag.]
* USED - Hardware MSR is used by the monitor.
* RESTORED - Monitor value is restored on world switch into the VMM.
* SHADOWED - Live monitor value is always shadowed in the SwitchedMSRState.
*
*/
#define SWITCHED_MSR_FLAG_UNUSED 0
#define SWITCHED_MSR_FLAG_USED 1
#define SWITCHED_MSR_FLAG_RESTORED 2
#define SWITCHED_MSR_FLAG_SHADOWED 4
/*
* Note: If you add an msr to this list, please also ensure that
* hardware support for the msr is properly indicated in
* both the monitor (MonMSRIsSupported) and in the vmkernel
* (world switch msrSupported array).
*/
#define SWITCHED_MSRS \
SWMSR(MSR_SYSENTER_CS) \
SWMSR(MSR_SYSENTER_EIP) \
SWMSR(MSR_SYSENTER_ESP) \
SWMSR(MSR_STAR) \
SWMSR(MSR_LSTAR) \
SWMSR(MSR_CSTAR) \
SWMSR(MSR_SFMASK) \
SWMSR(MSR_TSC_AUX) \
SWMSR(MSR_BD_TSC_RATIO)
/*
* Data structures for dealing with the context-switched MSRs that need
* to be specially handled. While the MSR definitions themselves
* are part of the x86 architecture, our handling of them (and hence
* these data structures) is an implementation detail.
*/
typedef enum SwitchedMSR {
#define SWMSR(msr) SWITCHED_##msr,
SWITCHED_MSRS
#undef SWMSR
NUM_SWITCHED_MSRS
} SwitchedMSR;
/*
* Switched MSR values for each [vp]CPU.
*/
typedef struct SwitchedMSRValues {
uint64 a[NUM_SWITCHED_MSRS];
} SwitchedMSRValues;
typedef struct SwitchedMSRState {
SwitchedMSRValues smv;
uint8 flags[NUM_SWITCHED_MSRS];
uint32 _pad;
} SwitchedMSRState;
#endif
+207
View File
@@ -0,0 +1,207 @@
/*********************************************************
* Copyright (C) 2007-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
* 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 _MON_ASSERT_H_
#define _MON_ASSERT_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "vm_assert.h"
#include "vm_basic_asm.h"
/*
* Monitor Source Location
*
* The monitor encodes source locations -- file name & line number --
* in just 32 bits; the process is arcane enough that it deserves a
* little discussion.
*
* o The ASSERT family of macros are expanded in the monitor to take
* an 'Assert_MonSrcLoc' rather than the standard '<file>,
* <line-number>' couplet.
*
* o The '<file>, <line-number>' couplet is encoded into
* Assert_MonSrcLoc, which is an unsigned 32-bit integer.
*
* o The upper 16-bits of Assert_MonSrcLoc are the line number.
*
* Source lines above 65535 will be silently masked to 16-bits.
*
* o The lower 16-bits of Assert_MonSrcLoc are the offset to the file
* name from the start of the file name table.
*
* This, of course, implies that the size of the table containing
* the file names cannot exceed 64K.
*
* o If we use '__FILE__' directly, gcc will coalesce all equivalent
* strings into a single occurrence (in '.rodata').
*
* Using the full pathname for __FILE__ is undesirable because
* different source trees frequently have different path name
* lengths, and this causes the 'monitor-modular-size' script to
* report differences in '.rodata'.
*
* o To avoid differences in '.rodata', each __FILE__ is put into
* its own section. The monitor's linker (not ld) will use the
* name of the section to recover the name of the source file.
*
* o At run time, prior to loading, when our linker is creating an
* executable image of the monitor and extensions, all the file
* names are extracted from these sections, the '${VMTREE}' prefix
* is removed, and the resulting table of shortened file names is
* added to '.rodata'.
*
* Further, during linkage, each relocation to the original
* section containing the path name is modified so that the low
* 16-bits contain an offset from '__vmm_pathnames_start' rather
* than the base of the original containing section.
*
* Only three types of relocations to the assertion strings are
* supported (32-bit PC-relative and 32-bit/64-bit absolute) because that
* is all the compiler has been seen to generate.
*/
#define ALL_ASSERT_TYPES \
ADEF(AssertType_AssertPanic, _AssertPanicFmt), \
ADEF(AssertType_AssertAssert, _AssertAssertFmt), \
ADEF(AssertType_AssertVerify, _AssertVerifyFmt), \
ADEF(AssertType_AssertNotImplemented, _AssertNotImplementedFmt), \
ADEF(AssertType_AssertNotReached, _AssertNotReachedFmt), \
ADEF(AssertType_AssertPanicBug, _AssertPanicFmt " bugNr=%d"), \
ADEF(AssertType_AssertAssertBug, _AssertAssertFmt " bugNr=%d"), \
ADEF(AssertType_AssertVerifyBug, _AssertVerifyFmt " bugNr=%d"), \
ADEF(AssertType_AssertNotImplementedBug, \
_AssertNotImplementedFmt " bugNr=%d"), \
ADEF(AssertType_AssertNotReachedBug, _AssertNotReachedFmt " bugNr=%d"),\
ADEF(AssertType_AssertNotTested, _AssertNotTestedFmt)
typedef uint32 Assert_MonSrcLoc;
#define ADEF(type, fmt) type
typedef enum Assert_Type {
ALL_ASSERT_TYPES
} Assert_Type;
#undef ADEF
typedef struct Assert_Info {
VA faultAddr;
struct {
Assert_Type type:4;
int bugNr:28;
} misc;
Assert_MonSrcLoc loc;
} Assert_Info;
/*
* The portion of the __attribute__ line after __FILE__ is there so that
* the .assert_pathname_* sections are not marked as ALLOC, since we only
* need them in the vmx and do not need them loaded.
*/
#define __VMM__FILE__SECTION \
__attribute__((section (".assert_pathname_" __FILE__ ",\"\"#")))
#define __VMM__FILE__ ({ \
static __VMM__FILE__SECTION const char file[] = ""; \
file; \
})
#define ASSERT_MONSRCFILEOFFSET(loc) LOWORD(loc)
#define ASSERT_MONSRCLINE(loc) HIWORD(loc)
#define ASSERT_NULL_MONSRCLOC 0 // there is never line 0
#ifdef VMM // {
#ifdef MONITOR_APP // {
#define ASSERT_MONSRCLOC() ASSERT_NULL_MONSRCLOC
#else // } {
#define ASSERT_MONSRCLOC() ({ \
const uintptr_t offset = ((__LINE__ << 16) + \
(uintptr_t)__VMM__FILE__); \
const Assert_MonSrcLoc loc = offset; \
loc; \
})
extern const char __vmm_pathnames_start;
#define ASSERT_MONSRCFILE(loc) \
(&__vmm_pathnames_start + ASSERT_MONSRCFILEOFFSET(loc))
/*
* Assertion information is collected in a non-loadable section
* named .assert_info. Each record in this section contains
* a VMM address, an assertion type, an optional bug number, and
* the MonSrcLoc described previously. The VMM address is a key
* used by the VMX to look up the information associated with
* a particular assertion failure.
*
* Assertion failures are fired by executing a ud2 instruction.
*
* For assertions which always result in a terminal user RPC, we use
* __builtin_trap to generate the ud2, so that gcc knows that the
* subsequent code is unreachable. For assertions which are
* recoverable (e.g any assertion triggered on the BackToHost path),
* we generate the ud2 manually, so that gcc will treat the subsequent
* code as reachable.
*
* The memory barriers work around a gcc bug that results from having
* to continue past an assertion. Without these barriers, gcc has been
* seen to hoist code into the failing arm of the assertion, where it
* can then tell that, because of the assertion failure, the code ends
* up accessing an array out of bounds.
*/
#define ASSERT_RECORDINFO(assembly, assertType, bugNr) \
__asm__ __volatile__(".pushsection .assert_info;" \
".quad 0f;" \
".long %c[type] + (%c[bug] << 4);" \
".long (%c[line] << 16) + %c[file];" \
".popsection;" \
"0: " assembly : : \
[line] "i" (__LINE__), \
[file] "i" (__VMM__FILE__), \
[type] "i" (assertType), \
[bug] "i" (bugNr))
#define _ASSERT_PANIC(name) \
({COMPILER_MEM_BARRIER(); \
ASSERT_RECORDINFO("ud2", AssertType_##name, 0);})
#define _ASSERT_PANIC_NORETURN(name) \
({COMPILER_MEM_BARRIER(); \
ASSERT_RECORDINFO("", AssertType_##name, 0); \
__builtin_trap();})
#define _ASSERT_PANIC_BUG(bug, name) \
({COMPILER_MEM_BARRIER(); \
ASSERT_RECORDINFO("ud2", AssertType_##name##Bug, bug);})
#define _ASSERT_PANIC_BUG_NORETURN(bug, name) \
({COMPILER_MEM_BARRIER(); \
ASSERT_RECORDINFO("", AssertType_##name##Bug, bug); \
__builtin_trap();})
#endif // MONITOR_APP }
#endif // VMM }
#endif
+156
View File
@@ -0,0 +1,156 @@
/*********************************************************
* Copyright (C) 2010-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
* 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 _MONITORACTION_EXPORTED_H_
#define _MONITORACTION_EXPORTED_H_
#define INCLUDE_ALLOW_VMX
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_DISTRIBUTE
#include "includeCheck.h"
#include "vm_assert.h"
#include "vm_atomic.h"
#include "vm_basic_types.h"
/*
* Please bump the version number if your change will break the
* compatability to the drivers.
*/
#define ACTION_EXPORTED_VERSION 2
#define ACTION_WORD_SIZE (sizeof(uint64) * 8)
#define ACTION_NUM_WORDS (2)
#define ACTION_NUM_IDS (ACTION_NUM_WORDS * ACTION_WORD_SIZE)
#define MONACTION_INVALID MAX_UINT32
typedef uint32 MonitorIdemAction;
/*
* Representation of a set of actions.
*/
typedef struct MonitorActionSet {
volatile uint64 word[ACTION_NUM_WORDS];
} MonitorActionSet;
#ifndef __cplusplus
typedef enum MonitorActionSetName MonitorActionSetName;
#endif
/*
* Summary of action and interrupt states.
*/
typedef struct MonitorActionIntr {
MonitorActionSet pendingSet;
volatile Bool action;
Bool intr;
Bool nmi;
Bool db;
uint32 _pad;
} MonitorActionIntr;
/*
*------------------------------------------------------------------------
* MonitorActionSet_AtomicInclude --
*
* This function atomically adds an action to an action set.
*
* Results:
* TRUE if the action being added did not exist in the action set.
* FALSE otherwise.
*
* Side effects:
* The given action set will be updated.
*------------------------------------------------------------------------
*/
static INLINE Bool
MonitorActionSet_AtomicInclude(MonitorActionSet *set, const uint32 actionID)
{
Atomic_uint64 *atomicSet =
Atomic_VolatileToAtomic64(&set->word[actionID / ACTION_WORD_SIZE]);
uint64 mask = (uint64)1 << (actionID % ACTION_WORD_SIZE);
uint64 oldWord;
uint64 newWord;
ASSERT_ON_COMPILE((ACTION_WORD_SIZE & (ACTION_WORD_SIZE - 1)) == 0);
#ifdef VMX86_DEBUG
/* If ASSERT is not desirable, do explicit check. Please see PR 567811. */
#ifdef MODULE
if (UNLIKELY(actionID / ACTION_WORD_SIZE >= ACTION_NUM_WORDS)) {
return FALSE;
}
#else
ASSERT(actionID / ACTION_WORD_SIZE < ACTION_NUM_WORDS);
#endif // MODULE
#endif // VMX86_DEBUG
do {
oldWord = Atomic_Read64(atomicSet);
newWord = oldWord | mask;
} while (!Atomic_CMPXCHG64(atomicSet, &oldWord, &newWord));
return (oldWord & mask) == 0;
}
/*
*----------------------------------------------------------------------------
* MonitorAction_SetBits --
*
* The core logic for posting an action. Update the set of pending
* actions of the target VCPU in the shared area to mark the action
* as present. Make sure the bit is set in the pendingSet first to
* avoid a race with the drain loop.
*
* It's the responsibility of the callers to ensure that the change
* to actionIntr->action is globally visible before any IPI is sent
* (the change to pendingSet is pushed out by the cmpxchg in
* MonitorActionSet_AtomicInclude).
*
* Results:
* TRUE if the action being posted was not pending before.
* FALSE otherwise (other threads could have posted the same action).
*
* Side effects:
* None.
*----------------------------------------------------------------------------
*/
static INLINE Bool
MonitorAction_SetBits(MonitorActionIntr *actionIntr, MonitorIdemAction actionID)
{
/* Careful if optimizing this: see PR70016. */
Bool newAction =
MonitorActionSet_AtomicInclude(&actionIntr->pendingSet, actionID);
actionIntr->action = TRUE;
return newAction;
}
/*
* C1 states entered by monitor while waiting for an action
*/
typedef enum {
VMM_C1_STATE_INVALID = 0,
VMM_C1_STATE_HLT,
VMM_C1_STATE_MWAIT,
VMM_C1_STATE_PAUSE
} vmmC1StateType;
#endif // _MONITORACTION_EXPORTED_H_
+72
View File
@@ -0,0 +1,72 @@
/*********************************************************
* Copyright (C) 2006 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
*
*********************************************************/
/*
* numa_defs.h --
* This is the internal header file for the NUMA module.
*/
#ifndef _NUMA_DEFS_H
#define _NUMA_DEFS_H
#define INCLUDE_ALLOW_VMX
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#include "includeCheck.h"
#include "vm_basic_types.h"
#include "vm_basic_defs.h"
#include "cpu_defs.h"
/* Machine NUMA nodes */
typedef uint32 NUMA_Node;
typedef uint32 NUMA_NodeMask;
typedef uint8 NUMA_MemRangeID;
/*
* Constants
*/
#define NUMA_MAX_NODES 32
#define NUMA_MAX_CPUS_PER_NODE (vmx86_server ? MAX_PCPUS : 32)
#define NUMA_MAX_MEM_RANGES 64
#define INVALID_NUMANODE ((NUMA_Node)-1)
#define NUMA_NODE_MASK_ANY ((NUMA_NodeMask)-1)
#define NUMA_NODE_MASK_NONE ((NUMA_NodeMask)0)
/*
* Structures
*/
typedef struct {
MPN startMPN;
MPN endMPN;
NUMA_Node id;
Bool isReliable;
Bool isVolatile;
} NUMA_MemRange;
typedef struct NUMA_MemRangesList {
uint64 numMemRanges;
NUMA_MemRange memRange[NUMA_MAX_MEM_RANGES];
} NUMA_MemRangesList;
#endif // _NUMA_DEFS_H
+131
View File
@@ -0,0 +1,131 @@
/*********************************************************
* Copyright (C) 2001-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
* 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
*
*********************************************************/
/*
* overheadmem_types.h
*
* Types for tracking memory overheads.
*/
#ifndef _OVERHEADMEM_TYPES_H
#define _OVERHEADMEM_TYPES_H
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_MODULE
#include "includeCheck.h"
#include "vm_basic_types.h"
/*
* There are 4 types of memory we lock on the host. Memory can be Mem_Mapped in
* the vmx, anonymous memory for use by monitor is not mapped permanently in any
* address space, guest memory regions other than main memory (can be
* locked/unlocked on hosted but not on ESX), and main memory which can be
* locked/unlocked in hosted and esx.
*
* In addition, the vmx may malloc memory or declare (large) static structures.
* Neither of these is locked on hosted platforms and the hostOS may swap it.
* Therefore, on hosted platforms we do not track this memory and instead
* include a working set component (sched.mem.hosted.perVMOverheadMBs).
* On ESX, this memory must be accounted for so we account it to user
* (nonpaged) overhead. At present, the accounting is extremely coarse,
* and only aggregate sizes are hard-coded (see PR363997).
*/
typedef enum OvhdMemType {
OvhdMem_memmap,
OvhdMem_anon,
OvhdMem_guest,
OvhdMem_mainmem,
OvhdMem_malloc,
OvhdMem_static,
OvhdMem_text,
NumOvhdMemTypes
} OvhdMemType;
#define OvhdMemMask(type) (1 << type)
#define OVHDMEM_NONE 0x0
#define OVHDMEM_MEMMAP 0x1 // OvhdMemMask(OvhdMem_memmap)
#define OVHDMEM_ANON 0x2 // OvhdMemMask(OvhdMem_anon)
#define OVHDMEM_GUEST 0x4 // OvhdMemMask(OvhdMem_guest)
#define OVHDMEM_MAINMEM 0x8 // OvhdMemMask(OvhdMem_mainmem)
#define OVHDMEM_MALLOC 0x10 // OvhdMemMask(OvhdMem_malloc)
#define OVHDMEM_STATIC 0x20 // OvhdMemMask(OvhdMem_static)
#define OVHDMEM_TEXT 0x40 // OvhdMemMask(OvhdMem_text)
#define OVHDMEM_ALL_USER (OVHDMEM_MEMMAP | OVHDMEM_GUEST | OVHDMEM_MAINMEM | \
OVHDMEM_MALLOC | OVHDMEM_STATIC | OVHDMEM_TEXT)
#define OVHDMEM_ALL (OVHDMEM_ALL_USER | OVHDMEM_ANON)
/* ... and four categories of memory sources. */
typedef enum OvhdMemCategory {
OvhdMemCat_paged,
OvhdMemCat_nonpaged,
OvhdMemCat_excluded,
OvhdMemCat_anonymous,
NumOvhdMemCategories
} OvhdMemCategory;
#define OVHDMEM_PAGED (OVHDMEM_MALLOC | OVHDMEM_STATIC)
#define OVHDMEM_NONPAGED (OVHDMEM_GUEST | OVHDMEM_MEMMAP)
#define OVHDMEM_EXCLUDED (OVHDMEM_MAINMEM | OVHDMEM_TEXT)
#if ((OVHDMEM_PAGED & OVHDMEM_NONPAGED) != 0) || \
((OVHDMEM_NONPAGED & OVHDMEM_EXCLUDED) != 0) || \
((OVHDMEM_PAGED & OVHDMEM_EXCLUDED) != 0) || \
((OVHDMEM_PAGED | OVHDMEM_NONPAGED | OVHDMEM_EXCLUDED | OVHDMEM_ANON) != \
OVHDMEM_ALL)
#error Overheadmem categories do not form a partition of the overheads
#endif
/* Categories of overhead for 32-bit and 64-bit mode. */
typedef struct OvhdMem_Overheads {
uint32 paged;
uint32 nonpaged;
uint32 anonymous;
uint32 text;
} OvhdMem_Overheads;
typedef struct OvhdMem_Deltas {
int32 paged;
int32 nonpaged;
int32 anonymous;
} OvhdMem_Deltas;
/* Types for tracking vmx (user) overheads. */
#define OVHDMEM_MAX_NAME_LEN 36
/* Types for tracking vmm overheads. */
typedef struct OvhdMemUsage {
uint32 reserved; // pages
uint32 used; // pages
} OvhdMemUsage;
typedef struct OvhdMemNode {
OvhdMemUsage usage; // allocated and rsvd bytes for source
OvhdMemUsage maxUsage; // max allocated and rsvd bytes for source
char name[OVHDMEM_MAX_NAME_LEN]; // name of overhead source
OvhdMemType type; // how/where memory for source is managed
} OvhdMemNode;
#endif
+105
View File
@@ -0,0 +1,105 @@
/*********************************************************
* Copyright (C) 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
*
*********************************************************/
/*
* pageLock_defs.h
*
* Page lock status codes, used by vmmon.
*/
#ifndef _PAGELOCK_DEFS_H_
#define _PAGELOCK_DEFS_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_MODULE
#include "includeCheck.h"
/*
* Return codes from page locking, unlocking, and MPN lookup.
* They share an error code space because they call one another
* internally.
*
* PAGE_LOCK_FAILED The host refused to lock a page.
* PAGE_LOCK_LIMIT_EXCEEDED We have reached the limit of locked
* pages for all VMs
* PAGE_LOCK_TOUCH_FAILED Failed to touch page after lock.
* PAGE_LOCK_IN_TRANSITION The page is locked but marked by Windows
* as nonpresent in CPU PTE and in transition
* in Windows PFN.
*
* PAGE_LOCK_SYS_ERROR System call error.
* PAGE_LOCK_ALREADY_LOCKED Page already locked.
* PAGE_LOCK_MEMTRACKER_ERROR MemTracker fails.
* PAGE_LOCK_PHYSTRACKER_ERROR PhysTracker fails.
* PAGE_LOCK_MDL_ERROR Mdl error on Windows.
*
* PAGE_UNLOCK_NO_ERROR Unlock successful (must be 0).
* PAGE_UNLOCK_NOT_TRACKED Not in memtracker.
* PAGE_UNLOCK_NO_MPN Tracked but no MPN.
* PAGE_UNLOCK_NOT_LOCKED Not locked.
* PAGE_UNLOCK_TOUCH_FAILED Failed to touch page.
* PAGE_UNLOCK_MISMATCHED_TYPE Tracked but was locked by different API
*
* PAGE_LOOKUP_INVALID_ADDR Consistency checking.
* PAGE_LOOKUP_BAD_HIGH_ADDR Consistency checking.
* PAGE_LOOKUP_ZERO_ADDR Consistency checking.
* PAGE_LOOKUP_SMALL_ADDR Consistency checking.
*
* All error values must be negative values less than -4096 to avoid
* conflicts with errno values on Linux.
*
* -- edward
*/
#define PAGE_LOCK_SUCCESS 0
#define PAGE_LOCK_FAILED (-10001)
#define PAGE_LOCK_LIMIT_EXCEEDED (-10002)
#define PAGE_LOCK_TOUCH_FAILED (-10003)
#define PAGE_LOCK_IN_TRANSITION (-10004)
#define PAGE_LOCK_SYS_ERROR (-10010)
#define PAGE_LOCK_ALREADY_LOCKED (-10011)
#define PAGE_LOCK_MEMTRACKER_ERROR (-10012)
#define PAGE_LOCK_PHYSTRACKER_ERROR (-10013)
#define PAGE_LOCK_MDL_ERROR (-10014)
#define PAGE_UNLOCK_SUCCESS 0
#define PAGE_UNLOCK_NOT_TRACKED (-10100)
#define PAGE_UNLOCK_NO_MPN (-10101)
#define PAGE_UNLOCK_NOT_LOCKED (-10102)
#define PAGE_UNLOCK_TOUCH_FAILED (-10103)
#define PAGE_UNLOCK_MISMATCHED_TYPE (-10104)
#define PAGE_LOOKUP_SUCCESS 0
#define PAGE_LOOKUP_INVALID_ADDR (-10200)
#define PAGE_LOOKUP_BAD_HIGH_ADDR (-10201)
#define PAGE_LOOKUP_ZERO_ADDR (-10202)
#define PAGE_LOOKUP_SMALL_ADDR (-10203)
#define PAGE_LOOKUP_SYS_ERROR (-10204)
#define PAGE_LOOKUP_NOT_TRACKED (-10) // added to another code
#define PAGE_LOOKUP_NO_MPN (-20) // added to another code
#define PAGE_LOOKUP_NOT_LOCKED (-30) // added to another code
#define PAGE_LOOKUP_NO_VM (-40) // added to another code
#define PAGE_LOCK_SOFT_FAILURE(status) (status <= PAGE_LOCK_FAILED && \
status > PAGE_LOCK_SYS_ERROR)
#endif // ifndef _PAGELOCK_DEFS_H_
+101
View File
@@ -0,0 +1,101 @@
/*********************************************************
* Copyright (C) 2010-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
* 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
*
*********************************************************/
/*
* pagelist.h --
*
* Definitions of operations on BPNs used in communicating page info
* between VMKernel/VMX and VMM.
*/
#ifndef _PAGELIST_H
#define _PAGELIST_H
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_MODULE
#include "includeCheck.h"
#include "vm_assert.h"
#include "vmcore_types.h"
/*
* Sets of pages are passed between the monitor and the platform to be
* shared, invalidated, remapped, or swapped.
*
* A set is sized so that it fits in a 4KB page.
*/
#pragma pack(push, 1)
typedef struct PageListEntry {
CompressedBPN cbpn;
Bool voided;
uint8 _pad[2];
} PageListEntry;
#pragma pack(pop)
#define PAGELIST_MAX (PAGE_SIZE / sizeof(PageListEntry))
static INLINE PageListEntry
PageList_CreateEntry(BPN bpn)
{
PageListEntry ple;
CompressedBPN_Write(&ple.cbpn, bpn);
ple.voided = FALSE;
return ple;
}
static INLINE BPN
PageList_BPN(const PageListEntry *ple)
{
return CompressedBPN_Read(&ple->cbpn);
}
static INLINE Bool
PageList_IsVoid(const PageListEntry *ple)
{
ASSERT(ple->voided == TRUE || ple->voided == FALSE);
return ple->voided;
}
static INLINE void
PageList_VoidEntry(PageListEntry *ple)
{
ple->voided = TRUE;
}
/*
* This function inspects the set of BPN between entry [0,i) in the page list
* and returns TRUE if any of them matches the provided BPN.
*/
static INLINE Bool
PageList_IsBPNDup(const PageListEntry *pageList, unsigned i, BPN bpn)
{
unsigned k;
for (k = 0; k < i; k++) {
if (PageList_BPN(&pageList[k]) == bpn) {
return TRUE;
}
}
return FALSE;
}
#endif
+122
View File
@@ -0,0 +1,122 @@
/*********************************************************
* Copyright (C) 2009-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
* 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
*
*********************************************************/
/*
* pcip_defs.h --
*
* PCI passthru definitions shared by the vmx, monitor, vmkernel, and
* vmmon. Not all PCI passthru definitions are found here: the shared
* bits mainly pertain to interrupt proxying.
*/
#ifndef _PCIP_DEFS_H
#define _PCIP_DEFS_H
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMMON
#include "includeCheck.h"
#include "monitorAction_exported.h"
#include "bitvector.h"
#define MAX_INTERRUPTS 256 // max interrupts a device could use
#define PCIP_MAX_MSIX_VECTORS 128
#define PCIP_MAX_VECTORS (PCIP_MAX_MSIX_VECTORS + 2)
typedef struct PCIPVecBV {
BitVector bv;
uint32 reserved[PCIP_MAX_VECTORS / sizeof (uint32) - 1];
} PCIPVecBV;
typedef enum PCIPassthruVectorIndex {
PCIP_INDEX_IOAPIC,
PCIP_INDEX_MSI,
PCIP_INDEX_MSIXOFF,
PCIP_INDEX_INVALID = PCIP_INDEX_MSIXOFF + PCIP_MAX_MSIX_VECTORS,
} PCIPassthruVectorIndex;
typedef enum PCIPassthru_IntrType {
PCIPASSTHRU_INTR_NONE = 0x00,
PCIPASSTHRU_INTR_IOAPIC = 0x01,
PCIPASSTHRU_INTR_MSI = 0x02,
PCIPASSTHRU_INTR_MSIX = 0x04,
} PCIPassthru_IntrType;
typedef struct FPTIntrProxyInfo {
uint32 adapterIndex;
uint32 vectorIndex;
MonitorIdemAction actionID;
uint32 _pad0;
/*
* These addresses are only needed for hosted platforms, where our kernel
* modules lack a SharedArea API.
*/
#ifndef VMX86_SERVER
VA64 notifyUVA;
VA64 vectorIndexUVA;
#endif
} FPTIntrProxyInfo;
typedef struct UPTIntrProxyInfo {
uint32 adapterIndex;
MonitorIdemAction actionID;
} UPTIntrProxyInfo;
typedef union PCIPassthru_IntrProxyInfo {
FPTIntrProxyInfo fpt;
UPTIntrProxyInfo upt;
} PCIPassthru_IntrProxyInfo;
typedef enum PCIPassthru_ErrorType {
PCIPASSTHRU_ERROR_NONE = 0x00,
PCIPASSTHRU_ERROR_AER = 0x01,
PCIPASSTHRU_ERROR_PAGE_FAULT = 0x02,
} PCIPassthru_ErrorType;
typedef struct PCIPassthru_PageFaultInfo {
uint64 ioAddr;
uint64 machAddr;
uint8 faultReason;
uint8 unused[7];
} PCIPassthru_PageFaultInfo;
typedef struct PCIPassthru_AERInfo {
uint64 count;
} PCIPassthru_AERInfo;
typedef union PCIPassthru_ErrorInfo {
PCIPassthru_PageFaultInfo pageFaultInfo;
PCIPassthru_AERInfo aerInfo;
} PCIPassthru_ErrorInfo;
typedef
#include "vmware_pack_begin.h"
struct PCIPassthru_ErrorMsg {
uint32 sbdf;
PCIPassthru_ErrorType errorType;
PCIPassthru_ErrorInfo errorInfo;
}
#include "vmware_pack_end.h"
PCIPassthru_ErrorMsg;
#endif // _PCIP_DEFS_H
+72
View File
@@ -0,0 +1,72 @@
/*********************************************************
* Copyright (C) 1998-2012,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
* 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
*
*********************************************************/
/*
* perfctr_generic.h --
*
*/
#ifndef _PERFCTR_GENERIC_H_
#define _PERFCTR_GENERIC_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#include "includeCheck.h"
#include "vm_basic_types.h"
/*
* nmiNo -- vmm peer is not attempting to do nmi profiling this run
* nmiYes -- vmm peer is doing nmi profiling and nmis are currently enabled
* nmiStopped -- vmm peer is doing nmi profiling, but nmis are temporarily
* disabled for safety reasons.
*/
typedef enum {nmiNo = 0, nmiYes, nmiStopped} NMIStatus;
typedef struct NMIShared { /* shared with vmx and vmkernel */
NMIStatus vmmStatus;
int32 nmiErrorCode;
int64 nmiErrorData;
} NMIShared;
/*
* CrossProf: structures for unified profiling of vmm, vmx, and
* vmkernel. Per-vcpu.
*/
#define CALLSTACK_CROSSPROF_PAGES 1
typedef struct {
/*
* This structure is per-vcpu. The raw data is a packed vector
* of MonitorCallStackSample, a variable-length structure.
*/
/* raw data - packed vec of MonitorCallStackSample, variable length */
uint8 crossProfSampleBuffer[PAGES_2_BYTES(CALLSTACK_CROSSPROF_PAGES)];
uint32 crossProfSampleBytes;
uint32 crossProfNumDroppedSamples; /* For when buffer fills up */
Bool enabled; /* Can be false in stats build if monitor.callstack=FALSE */
uint8 _pad[3];
} CrossProfShared;
#endif // ifndef _PERFCTR_GENERIC_H_
+388
View File
@@ -0,0 +1,388 @@
/*********************************************************
* 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
* 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 __PGTBL_H__
# define __PGTBL_H__
#include <linux/highmem.h>
#include "compat_pgtable.h"
#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 --
*
* 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
* mpn on success
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static INLINE MPN
PgtblVa2MPNLocked(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) {
MPN mpn = PgtblPte2MPN(pte);
pte_unmap(pte);
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;
}
}
/*
*-----------------------------------------------------------------------------
*
* PgtblVa2MPN --
*
* 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
PgtblVa2MPN(VA addr) // IN
{
struct mm_struct *mm;
MPN mpn;
/* 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));
}
mpn = PgtblVa2MPNLocked(mm, addr);
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__ */
+64
View File
@@ -0,0 +1,64 @@
/*********************************************************
* Copyright (C) 2001,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
* 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
*
*********************************************************/
/*
* pshare_ext.h --
*
* VMKernel/VMMon <-> VMM transparent page sharing info.
*/
#ifndef _PSHARE_EXT_H
#define _PSHARE_EXT_H
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_MODULE
#include "includeCheck.h"
#include "pagelist.h"
#include "vm_basic_types.h"
#include "vm_assert.h"
/*
* constants
*/
#define PSHARE_PAGELIST_MAX (PAGELIST_MAX)
#define PSHARE_P2M_BUFFER_MPNS_MAX (16)
#define PSHARE_P2M_BUFFER_MPNS_DEFAULT (4)
#define PSHARE_P2M_BUFFER_SLOTS_PER_MPN (PAGE_SIZE / sizeof(PShare_P2MUpdate))
#define PSHARE_POISON_MARKER (CONST64U(0xAAAAAAAAAAAAAAAA))
#define PSHARE_SALT_UNSET 0
#define PSHARE_SALT_DEFAULT 1
MY_ASSERTS(PSHARE_EXT,
ASSERT_ON_COMPILE(PSHARE_PAGELIST_MAX <= PAGELIST_MAX);)
/*
* types
*/
typedef struct PShare_P2MUpdate {
BPN bpn;
MPN mpn;
} PShare_P2MUpdate;
#endif
+263
View File
@@ -0,0 +1,263 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* ptsc.h --
*
* Pseudo TSC
*/
#ifndef _PTSC_H_
#define _PTSC_H_
#define INCLUDE_ALLOW_VMX
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#include "includeCheck.h"
#include "rateconv.h"
/*
* RDTSC and PTSC_Get.
*
* RDTSC reads the hardware timestamp counter on the current physical
* CPU. In general, the TSC is *not* a globally consistent timer that
* runs at a constant rate. Any code that still assumes it is should
* be corrected; see PR 20499.
*
* PTSC_Get returns a pseudo-TSC that runs at approximately the
* maximum speed of physical CPU 0's TSC and is approximately globally
* consistent. It is available both at userlevel and in the monitor,
* with different implementations. In the vmkernel, Timer_PseudoTSC
* provides similar functionality.
*
*/
/* TS stands for "timestamp", which is in units of "cycles" */
typedef uint64 VmAbsoluteTS; // a particular point in time (in cycles)
typedef int64 VmRelativeTS; // a signed delta in cycles
typedef uint64 VmIntervalTS; // an unsigned delta in cycles
typedef uint64 VmAbsoluteUS; // a particular point in time (in us)
typedef int64 VmRelativeUS; // a signed delta in us
typedef uint64 VmIntervalUS; // an unsigned delta in us
/*
* Compare two VmAbsoluteTS's using comparison operator op, allowing
* for wrap. The assumption is that differences should not be more
* than 2**63, so a larger difference is taken as negative.
*/
#define COMPARE_TS(ts1, op, ts2) (((int64) ((ts1) - (ts2))) op 0)
#define MAX_ABSOLUTE_TS \
((VmAbsoluteTS) CONST64U(0xffffffffffffffff))
/*
* Largest possible unambiguous difference between two VmAbsoluteTS's
* according to COMPARE_TS's method of comparison.
*/
#define MAX_RELATIVE_TS \
((VmRelativeTS) CONST64(0x7fffffffffffffff))
#define MAX_ABSOLUTE_US \
((VmAbsoluteUS) CONST64U(0xffffffffffffffff))
typedef struct PTSCInfo {
Bool hwTSCsSynced;
Bool hwTSCsAdjusted;
uint8 _pad[6];
int64 hz;
uint32 kHz;
uint32 mHz;
RateConv_Ratio usToCycles;
RateConv_Ratio cyclesToUs;
RateConv_Ratio msToCycles;
RateConv_Ratio cyclesToNs;
} PTSCInfo;
extern PTSCInfo ptscInfo;
Bool PTSC_Init(uint64 tscHz);
VmAbsoluteTS PTSC_InitialCount(const char *module,
const char *option,
VmIntervalTS freq,
VmAbsoluteTS defaultCnt);
Bool PTSC_HasPerfectlySynchronizedTSCs(void);
static INLINE int64
PTSC_Hz(void)
{
ASSERT(ptscInfo.hz);
return ptscInfo.hz;
}
static INLINE uint32
PTSC_KHz(void)
{
ASSERT(ptscInfo.kHz);
return ptscInfo.kHz;
}
static INLINE uint32
PTSC_MHz(void)
{
ASSERT(ptscInfo.mHz);
return ptscInfo.mHz;
}
#if defined(VM_X86_64) || defined(VM_ARM_64)
/*
* Conversions to/from cycles. Note that the conversions operate on
* signed values, so be careful when taking the difference of two
* VmAbsoluteTS (which is unsigned) that that value is not out of range
* of the signed type.
*/
static INLINE VmRelativeTS
PTSC_USToCycles(int64 us)
{
return Muls64x32s64(us, ptscInfo.usToCycles.mult, ptscInfo.usToCycles.shift);
}
static INLINE VmRelativeTS
PTSC_MSToCycles(int64 ms)
{
return Muls64x32s64(ms, ptscInfo.msToCycles.mult, ptscInfo.msToCycles.shift);
}
static INLINE int64
PTSC_CyclesToNS(VmRelativeTS ts)
{
return Muls64x32s64(ts, ptscInfo.cyclesToNs.mult, ptscInfo.cyclesToNs.shift);
}
static INLINE int64
PTSC_CyclesToUS(VmRelativeTS ts)
{
return Muls64x32s64(ts, ptscInfo.cyclesToUs.mult, ptscInfo.cyclesToUs.shift);
}
#else
/* 32-bit Muls64x32s64 too big to justify inlining. */
VmRelativeTS PTSC_USToCycles(int64 us);
VmRelativeTS PTSC_MSToCycles(int64 ms);
int64 PTSC_CyclesToNS(VmRelativeTS ts);
int64 PTSC_CyclesToUS(VmRelativeTS ts);
#endif
#if defined(VMX86_SERVER) && defined(VMX86_VMX)
/*
* ESX with userworld VMX
*/
#include "x86types.h"
#include "user_layout.h"
#ifdef VM_ARM_64
static INLINE VmAbsoluteTS
PTSC_Get(void)
{
extern __thread User_ThreadData vmkUserTdata;
register RateConv_Params params;
register uint64 pseudoTSC;
/*
* On ARM64 the generic timer guarantees that the counters are synchronous
* and independent of CPU frequency.
*/
params = vmkUserTdata.pseudoTSCConv;
pseudoTSC = RDTSC();
/*
* assert that conversion rate is `identity'.
* we'll have to revisit that when/if this assumption changes
* on some platform
*/
ASSERT((params.mult == 1 && params.shift == 0) ||
(params.mult == 0x80000000 && params.shift == 31));
pseudoTSC += params.add;
return pseudoTSC;
}
#else
static INLINE VmAbsoluteTS
PTSC_Get(void)
{
extern __thread User_ThreadData vmkUserTdata;
VmAbsoluteTS ptsc;
if (vmkUserTdata.magic != USER_THREADDATA_MAGIC) {
return 0;
}
ptsc = vmkUserTdata.u.pseudoTSCGet(&vmkUserTdata);
ASSERT((int64)ptsc >= 0);
return ptsc;
}
#endif
#else
/*
* Monitor and hosted VMX
*/
VmAbsoluteTS PTSC_Get(void);
#endif
/*
*-----------------------------------------------------------------------------
*
* PTSC_HasSynchronizedTSCs --
*
* Returns TRUE iff the platform TSCs are known to be synchronized.
*
*-----------------------------------------------------------------------------
*/
static INLINE Bool
PTSC_HasSynchronizedTSCs(void)
{
return ptscInfo.hwTSCsSynced;
}
/*
*-----------------------------------------------------------------------------
*
* PTSC_HostAdjustedTSCs --
*
* Returns TRUE if the platform may have adjusted TSCs in an attempt
* to sync them up.
*
*-----------------------------------------------------------------------------
*/
static INLINE Bool
PTSC_HostAdjustedTSCs(void)
{
return ptscInfo.hwTSCsAdjusted;
}
#endif /* ifndef _PTSC_H_ */
+118
View File
@@ -0,0 +1,118 @@
/*********************************************************
* Copyright (C) 2003 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
*
*********************************************************/
/*
*
* rateconv.h --
*
* Parameters and functions for linear rate conversion of 64 bit
* counters:
*
* y = ((x * mult) >> shift) + add.
*
*/
#ifndef _VM_RATECONV_H_
#define _VM_RATECONV_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#include "includeCheck.h"
#include "vm_basic_types.h"
#include "vm_basic_asm.h"
#include "vm_assert.h"
#include "vm_atomic.h"
/* RateConv_Params is part of vmx<->vmmon interface (INIT_PSEUDO_TSC ioctl) */
typedef struct RateConv_Params {
uint32 mult; /* mult == 1 implies shift == 0. */
uint32 shift;
int64 add;
} RateConv_Params;
typedef struct RateConv_ParamsVolatile {
RateConv_Params p;
Bool changed;
uint8 pad[7];
} RateConv_ParamsVolatile;
typedef struct RateConv_Ratio {
uint32 mult;
uint32 shift;
} RateConv_Ratio;
#define RATE_CONV_IDENTITY { 1, 0, 0 } /* Out = in. */
Bool RateConv_ComputeParams(uint64 inHz, uint64 inBase,
uint64 outHz, uint64 outBase,
RateConv_Params *conv);
void RateConv_LogParams(const char *prefix,
uint64 inHz, uint64 inBase,
uint64 outHz, uint64 outBase,
const RateConv_Params *conv);
Bool RateConv_ComputeRatio(uint64 inHz, uint64 outHz,
RateConv_Ratio *ratio);
void RateConv_LogRatio(const char *prefix,
uint64 inHz, uint64 outHz,
const RateConv_Ratio *ratio);
/*
*----------------------------------------------------------------------
*
* RateConv_Unsigned --
*
* Apply rate conversion to an unsigned argument:
* y = ((x * mult) >> shift) + add.
*
*----------------------------------------------------------------------
*/
static INLINE uint64
RateConv_Unsigned(const RateConv_Params *conv, uint64 x)
{
return Mul64x3264(x, conv->mult, conv->shift) + conv->add;
}
/*
*----------------------------------------------------------------------
*
* RateConv_Signed --
*
* Apply rate conversion to a signed argument:
* y = ((x * mult) >> shift) + add.
*
*----------------------------------------------------------------------
*/
static INLINE int64
RateConv_Signed(const RateConv_Params *conv, int64 x)
{
return Muls64x32s64(x, conv->mult, conv->shift) + conv->add;
}
#endif // _VM_RATECONV_H_
+34
View File
@@ -0,0 +1,34 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#include "includeCheck.h"
UC(CALL_START)
UC(BEGIN_BACK_TO_HOST)
UC(SWITCHED_TO_MODULE)
UC(VMX_SELECT_RETURN)
UC(VMX_HANDLER_START)
UC(VMX_SIGNAL)
UC(MODULE_SIGNAL)
UC(SWITCHING_TO_MONITOR)
UC(DONE_BACK_TO_HOST)
UC(CALL_END)
#undef UC
+35
View File
@@ -0,0 +1,35 @@
/*********************************************************
* Copyright (C) 2008 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 USERCALLDEFS_H
#define USERCALLDEFS_H
#ifdef linux
#include <linux/errno.h>
#define USERCALL_RESTART (-ERESTARTNOINTR)
#else
#include <usercall.h>
#define USERCALL_RESTART (USERCALL_NOP)
#endif
/*
* -1 to -4096 are reserved for syscall errors on Linux. -1 is reserved for
* failing DeviceIoControl on Windows.
*/
#define USERCALL_VMX86ALLOCERR (-8192)
#endif
+65
View File
@@ -0,0 +1,65 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
*
* vcpuid.h --
*
* Monitor's VCPU ID.
*/
#ifndef _VCPUID_H_
#define _VCPUID_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "vm_basic_types.h"
typedef uint32 Vcpuid; // VCPU number
#define VCPUID_INVALID (~0U)
#define BOOT_VCPU_ID 0
#define IS_BOOT_VCPUID(vcpuid) ((vcpuid) == BOOT_VCPU_ID)
#define MAX_VCPUS 128
#define MAX_CORES_PER_SOCKET 64
#ifdef VMM
#include "vcpuset.h"
/* In VMM, CurVcpuid() is available everywhere. */
extern const Vcpuid curVcpuid;
extern const VCPUSet curVcpuidSet;
#define CurVcpuid() (curVcpuid)
#define CurVcpuidSet() (&curVcpuidSet)
#define IS_BOOT_VCPU() IS_BOOT_VCPUID(CurVcpuid())
#endif /* VMM */
#endif // ifndef _VCPUID_H_
+808
View File
@@ -0,0 +1,808 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* vcpuset.h --
*
* ADT for a set of VCPUs. Implemented as an array of bitmasks.
*
*/
#ifndef _VCPUSET_H_
#define _VCPUSET_H_
#define INCLUDE_ALLOW_VMX
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "vm_basic_asm.h"
#include "vm_atomic.h"
#include "vcpuid.h"
#include "vcpuset_types.h"
#if defined VMX86_VMX
# include "str.h" /* Str_Snprintf */
# define VCS_SNPRINTF Str_Snprintf
#elif defined MONITOR_APP
# include <stdio.h> /* libc snprintf */
# if defined WIN32
# define VCS_SNPRINTF _snprintf
# else
# define VCS_SNPRINTF snprintf
# endif
#elif defined VMM || defined VMKERNEL
# include "vm_libc.h" /* vmcore snprintf */
# define VCS_SNPRINTF snprintf
#endif
#ifdef VMX86_VMX
#include "vmx.h"
#endif
/*
* A buffer for logging a VCPUSet must fit a maximally-populated set. To
* balance brevity and readability, sets are formatted for printing like long
* hexadecimal numbers, with a '.' at every 64-VCPU subset boundary. The
* highest-numbered VCPU in the set is printed first, followed by all slots
* for lower-numbered VCPUs, populated or not. Leading zeroes are not printed.
*
* Examples, assuming a VCS_SUBSET_COUNT of 2:
* An empty set: "0x0\0"
* A full set: "0xffffffffffffffff.ffffffffffffffff\0"
* A set with only VCPU 50: "0x4000000000000\0"
* A set with only VCPU 80: "0x10000.0000000000000000\0"
*/
#define VCS_BUF_SIZE (2 + /* "0x" */ \
(VCS_SUBSET_COUNT * VCS_SUBSET_WIDTH / 4) + /* (hex) */ \
(VCS_SUBSET_COUNT - 1) + /* '.' */ \
1) /* NULL */
extern VCPUSet vcpuSetFull;
#define FOR_EACH_VCPU_IN_SET(_vcpuSet, _v) \
do { \
Vcpuid _v; \
VCPUSet __vcs; \
VCPUSet_Copy(&__vcs, _vcpuSet); \
while ((_v = VCPUSet_FindFirst(&__vcs)) != VCPUID_INVALID) { \
VCPUSet_Remove(&__vcs, _v);
#define ROF_EACH_VCPU_IN_SET() \
} \
} while (0)
#define FOR_EACH_SUBSET_IN_SET(_setIndex) \
do { \
int _setIndex; \
for (_setIndex = 0; _setIndex < VCS_SUBSET_COUNT; _setIndex++) {
#define ROF_EACH_SUBSET_IN_SET() \
} \
} while (0)
#define FOR_EACH_SUBSET_IN_SET_COUNTDOWN(_setIndex) \
do { \
int _setIndex; \
for (_setIndex = VCS_SUBSET_COUNT - 1; _setIndex >= 0; _setIndex--) {
#define ROF_EACH_SUBSET_IN_SET_COUNTDOWN() \
} \
} while (0)
#define FOR_EACH_POPULATED_SUBSET_IN_SET(_setIndex) \
do { \
int _setIndex; \
int _maxSubsets = VCS_VCPUID_SUBSET_IDX(NumVCPUs() - 1); \
for (_setIndex = 0; _setIndex <= _maxSubsets; _setIndex++) {
#define ROF_EACH_POPULATED_SUBSET_IN_SET() \
} \
} while (0)
/*
*----------------------------------------------------------------------
*
* VCPUSet_Empty --
*
* Clear all bits in a VCPUSet.
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_Empty(VCPUSet *vcs)
{
FOR_EACH_SUBSET_IN_SET(idx) {
vcs->subset[idx] = 0;
} ROF_EACH_SUBSET_IN_SET();
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_IsEmpty --
*
* Return TRUE iff a VCPUSet has no bits set.
*
*----------------------------------------------------------------------
*/
static INLINE Bool
VCPUSet_IsEmpty(const VCPUSet *vcs)
{
FOR_EACH_SUBSET_IN_SET(idx) {
if (vcs->subset[idx] != 0) {
return FALSE;
}
} ROF_EACH_SUBSET_IN_SET();
return TRUE;
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_Full --
*
* Returns a pointer to a VCPUSet containing all valid VCPUs.
*
*----------------------------------------------------------------------
*/
static INLINE const VCPUSet *
VCPUSet_Full(void)
{
/*
* Read too early, we may get the wrong notion of how many
* vcpus the VM has. Cf. pr286243 and pr289186.
*/
#if defined (VMX86_VMX)
ASSERT(NumVCPUs() != 0 && !VCPUSet_IsEmpty(&vcpuSetFull));
#endif
return &vcpuSetFull;
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_Copy --
*
* Copy one VCPUSet's contents to another.
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_Copy(VCPUSet *dest, const VCPUSet *src)
{
FOR_EACH_SUBSET_IN_SET(idx) {
dest->subset[idx] = src->subset[idx];
} ROF_EACH_SUBSET_IN_SET();
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_Equals --
*
* Compare two VCPUSets, return TRUE iff their contents match.
*
*----------------------------------------------------------------------
*/
static INLINE Bool
VCPUSet_Equals(const VCPUSet *vcs1, const VCPUSet *vcs2)
{
FOR_EACH_SUBSET_IN_SET(idx) {
if (vcs1->subset[idx] != vcs2->subset[idx]) {
return FALSE;
}
} ROF_EACH_SUBSET_IN_SET();
return TRUE;
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_IsMember --
*
* Return TRUE iff the given Vcpuid is present in a VCPUSet.
*
*----------------------------------------------------------------------
*/
static INLINE Bool
VCPUSet_IsMember(const VCPUSet *vcs, Vcpuid v)
{
ASSERT(v < MAX_VCPUS);
return (vcs->subset[VCS_VCPUID_SUBSET_IDX(v)] &
VCS_VCPUID_SUBSET_BIT(v)) != 0;
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_AtomicIsMember --
*
* Return TRUE iff the given Vcpuid is present in a VCPUSet.
*
*----------------------------------------------------------------------
*/
static INLINE Bool
VCPUSet_AtomicIsMember(VCPUSet *vcs, Vcpuid v)
{
volatile uint64 *subset = &vcs->subset[VCS_VCPUID_SUBSET_IDX(v)];
ASSERT(v < MAX_VCPUS);
return (Atomic_Read64(Atomic_VolatileToAtomic64(subset)) &
VCS_VCPUID_SUBSET_BIT(v)) != 0;
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_FindFirst --
* VCPUSet_FindLast --
*
* Find the first (lowest-numbered) or last (highest-numbered)
* Vcpuid in a VCPUSet.
*
* Results:
* Vcpuid if at least one is present in a set.
* VCPUID_INVALID if the set is empty.
*
*----------------------------------------------------------------------
*/
static INLINE Vcpuid
VCPUSet_FindFirst(const VCPUSet *vcs)
{
FOR_EACH_SUBSET_IN_SET(idx) {
uint64 subset = vcs->subset[idx];
if (subset != 0) {
return lssb64_0(subset) + (idx << VCS_SUBSET_SHIFT);
}
} ROF_EACH_SUBSET_IN_SET();
return VCPUID_INVALID;
}
static INLINE Vcpuid
VCPUSet_FindLast(const VCPUSet *vcs)
{
FOR_EACH_SUBSET_IN_SET_COUNTDOWN(idx) {
uint64 subset = vcs->subset[idx];
if (subset != 0) {
return mssb64_0(subset) + (idx << VCS_SUBSET_SHIFT);
}
} ROF_EACH_SUBSET_IN_SET_COUNTDOWN();
return VCPUID_INVALID;
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_Remove --
* VCPUSet_AtomicRemove --
*
* Remove or atomically remove a single Vcpuid from a VCPUSet.
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_Remove(VCPUSet *vcs, Vcpuid v)
{
ASSERT(v < MAX_VCPUS);
vcs->subset[VCS_VCPUID_SUBSET_IDX(v)] &= ~VCS_VCPUID_SUBSET_BIT(v);
}
static INLINE void
VCPUSet_AtomicRemove(VCPUSet *vcs, Vcpuid v)
{
volatile uint64 *subset = &vcs->subset[VCS_VCPUID_SUBSET_IDX(v)];
ASSERT(v < MAX_VCPUS);
Atomic_And64(Atomic_VolatileToAtomic64(subset), ~VCS_VCPUID_SUBSET_BIT(v));
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_IncludeSet --
* VCPUSet_RemoveSet --
*
* Add/remove all vcpus present in the set 'src' to/from the set 'dest'.
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_IncludeSet(VCPUSet *dest, const VCPUSet *src)
{
FOR_EACH_SUBSET_IN_SET(idx) {
dest->subset[idx] |= src->subset[idx];
} ROF_EACH_SUBSET_IN_SET();
}
static INLINE void
VCPUSet_RemoveSet(VCPUSet *dest, const VCPUSet *src)
{
FOR_EACH_SUBSET_IN_SET(idx) {
dest->subset[idx] &= ~src->subset[idx];
} ROF_EACH_SUBSET_IN_SET();
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_Include --
* VCPUSet_AtomicInclude --
*
* Add or atomically add a single Vcpuid to a VCPUSet.
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_Include(VCPUSet *vcs, Vcpuid v)
{
ASSERT(v < MAX_VCPUS);
vcs->subset[VCS_VCPUID_SUBSET_IDX(v)] |= VCS_VCPUID_SUBSET_BIT(v);
}
static INLINE void
VCPUSet_AtomicInclude(VCPUSet *vcs, Vcpuid v)
{
volatile uint64 *subset = &vcs->subset[VCS_VCPUID_SUBSET_IDX(v)];
ASSERT(v < MAX_VCPUS);
Atomic_Or64(Atomic_VolatileToAtomic64(subset), VCS_VCPUID_SUBSET_BIT(v));
}
#if defined(VMM) && !defined(MONITOR_APP)
/*
*----------------------------------------------------------------------
*
* VCPUSet_PackCareful --
*
* Pack a VCPUSet into the bytes at "ptr".
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_PackCareful(unsigned numVCPUs, const VCPUSet *vcs, void *ptr)
{
memcpy(ptr, vcs->subset, (numVCPUs + 7) / 8);
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_UnpackCareful --
*
* Unpack a VCPUSet from the bytes at "src".
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_UnpackCareful(unsigned numVCPUs, VCPUSet *vcs, void *ptr)
{
memcpy(vcs->subset, ptr, (numVCPUs + 7) / 8);
}
#endif /* VMM && !MONITOR_APP */
/*
*----------------------------------------------------------------------
*
* VCPUSet_PopulateRange --
*
* Populates the given set with 'numVCPUs' VCPUs starting at 'firstVCPU'.
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_PopulateRange(VCPUSet *vcs, unsigned firstVCPU,
unsigned numVCPUs)
{
unsigned sub;
unsigned lastVCPU = firstVCPU + numVCPUs - 1;
unsigned firstSubset = firstVCPU / VCS_SUBSET_WIDTH;
unsigned lastSubset = lastVCPU / VCS_SUBSET_WIDTH;
unsigned lowMaskShift = firstVCPU % VCS_SUBSET_WIDTH;
unsigned highMaskShift = VCS_SUBSET_WIDTH - 1 - lastVCPU % VCS_SUBSET_WIDTH;
ASSERT(firstSubset <= lastSubset && lastSubset < VCS_SUBSET_COUNT);
VCPUSet_Empty(vcs);
for (sub = firstSubset; sub <= lastSubset; sub++) {
vcs->subset[sub] = CONST64U(-1);
}
vcs->subset[firstSubset] &= (CONST64U(-1) << lowMaskShift);
vcs->subset[lastSubset] &= (CONST64U(-1) >> highMaskShift);
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_Populate --
*
* Populates the given set with the VCPUs in [0, numVCPUs).
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_Populate(VCPUSet *vcs, unsigned numVCPUs)
{
VCPUSet_PopulateRange(vcs, 0, numVCPUs);
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_Subset --
*
* Return the specified subset of a VCPUSet.
*
*----------------------------------------------------------------------
*/
static INLINE uint64
VCPUSet_Subset(const VCPUSet *vcs,
unsigned subset)
{
ASSERT(subset < VCS_SUBSET_COUNT);
return vcs->subset[subset];
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_SubsetPtr --
*
* Return a pointer to the specified subset of a VCPUSet.
*
*----------------------------------------------------------------------
*/
static INLINE uint64 *
VCPUSet_SubsetPtr(VCPUSet *vcs, unsigned subset)
{
ASSERT(subset < VCS_SUBSET_COUNT);
return &vcs->subset[subset];
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_IsSupersetOrEqual --
*
* Return TRUE iff vcs1 contains a superset of the VCPUs in vcs2
* or vcs1 and vcs2 contain exactly the same VCPUs.
*
*----------------------------------------------------------------------
*/
static INLINE Bool
VCPUSet_IsSupersetOrEqual(const VCPUSet *vcs1, const VCPUSet *vcs2)
{
FOR_EACH_SUBSET_IN_SET(idx) {
if (vcs2->subset[idx] & ~vcs1->subset[idx]) {
return FALSE;
}
} ROF_EACH_SUBSET_IN_SET();
return TRUE;
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_IsSubsetOrEqual --
*
* Return TRUE iff vcs1 contains a subset of the VCPUs in vcs2
* or vcs1 and vcs2 contain exactly the same VCPUs.
*
*----------------------------------------------------------------------
*/
static INLINE Bool
VCPUSet_IsSubsetOrEqual(const VCPUSet *vcs1, const VCPUSet *vcs2)
{
return VCPUSet_IsSupersetOrEqual(vcs2, vcs1);
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_MakeSingleton --
*
* Add a single Vcpuid to a VCPUSet and remove all others.
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_MakeSingleton(VCPUSet *vcs, Vcpuid v)
{
VCPUSet_Empty(vcs);
VCPUSet_Include(vcs, v);
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_IsSingleton --
*
* Return TRUE iff vcs contains exactly one VCPU.
*
*----------------------------------------------------------------------
*/
static INLINE Bool
VCPUSet_IsSingleton(const VCPUSet *vcs)
{
Bool foundOnce = FALSE;
FOR_EACH_SUBSET_IN_SET(idx) {
uint64 sub = vcs->subset[idx];
if (sub != 0) {
if (foundOnce || (sub & (sub - 1)) != 0) {
return FALSE;
}
foundOnce = TRUE;
}
} ROF_EACH_SUBSET_IN_SET();
return foundOnce;
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_IsFull --
*
* Returns true iff vcs contains the set of all vcpus.
*
*----------------------------------------------------------------------
*/
static INLINE Bool
VCPUSet_IsFull(const VCPUSet *vcs)
{
return VCPUSet_Equals(vcs, VCPUSet_Full());
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_AtomicReadWriteSubset --
*
* For the nth aligned 64-VCPU subset of a VCPU set, atomically
* read then write. Return the contents read. Set 0 is VCPUs
* 0-63 and set 1 is VCPUs 64-127.
*
*----------------------------------------------------------------------
*/
static INLINE uint64
VCPUSet_AtomicReadWriteSubset(VCPUSet *vcs, uint64 vcpus,
unsigned n)
{
ASSERT(n < VCS_SUBSET_COUNT);
return Atomic_ReadWrite64(Atomic_VolatileToAtomic64(&vcs->subset[n]),
vcpus);
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_Size --
*
* Return the number of VCPUs in this set.
*
*----------------------------------------------------------------------
*/
static INLINE int
VCPUSet_Size(const VCPUSet *vcs)
{
int n = 0;
FOR_EACH_SUBSET_IN_SET(idx) {
uint64 bits = vcs->subset[idx];
while (bits != 0) {
bits = bits & (bits - 1);
n++;
}
} ROF_EACH_SUBSET_IN_SET();
return n;
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_UnionSubset --
*
* Given an 64-bit value and a subset number, add the VCPUs
* represented to the set.
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_UnionSubset(VCPUSet *vcs, uint64 vcpus, unsigned n)
{
ASSERT(n < VCS_SUBSET_COUNT);
vcs->subset[n] |= vcpus;
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_SubtractSubset --
*
* Given an 64-bit value and a subset number, remove the VCPUs
* represented in the subset from the set.
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_SubtractSubset(VCPUSet *vcs, uint64 vcpus, unsigned n)
{
ASSERT(n < VCS_SUBSET_COUNT);
vcs->subset[n] &= ~vcpus;
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_AtomicUnionSubset --
*
* Given a 64-bit value and a subset number, atomically add
* the VCPUs represented to the set.
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_AtomicUnionSubset(VCPUSet *vcs, uint64 vcpus, unsigned n)
{
uint64 *subsetPtr = &vcs->subset[n];
ASSERT(n < VCS_SUBSET_COUNT);
Atomic_Or64(Atomic_VolatileToAtomic64(subsetPtr), vcpus);
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_Invert --
*
* Makes all non-present valid VCPUs in a set present and all
* VCPUs present non-present.
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_Invert(VCPUSet *vcs)
{
VCPUSet temp;
VCPUSet_Copy(&temp, VCPUSet_Full());
VCPUSet_RemoveSet(&temp, vcs);
VCPUSet_Copy(vcs, &temp);
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_Intersection
*
* Given two VCPUSets, populate the destination set with only the
* VCPUs common to both.
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_Intersection(VCPUSet *dest, const VCPUSet *src)
{
FOR_EACH_SUBSET_IN_SET(idx) {
dest->subset[idx] &= src->subset[idx];
} ROF_EACH_SUBSET_IN_SET();
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_LogFormat --
*
* Given a buffer of at least VCS_BUF_SIZE to fill, write into it a
* string suitable for use in Log() or LOG().
* Returns the buffer which was passed as an argument, after
* writing the string.
*
*----------------------------------------------------------------------
*/
#ifdef VCS_SNPRINTF
static INLINE char *
VCPUSet_LogFormat(char *buf, const int size, const VCPUSet *vcs)
{
int offset = 0;
Vcpuid highest = VCPUSet_FindLast(vcs);
int idx = (highest == VCPUID_INVALID) ? 0 : highest / 8;
ASSERT(size >= VCS_BUF_SIZE);
#define VCS_LOGF(...) \
{ \
int ret = VCS_SNPRINTF(buf + offset, size - offset, __VA_ARGS__); \
ASSERT(0 <= ret && ret < size - offset); \
offset += ret; \
}
/* Print the leading value with no zero-extension. */
VCS_LOGF("%#x", ((unsigned char *)vcs)[idx--]);
while (idx >= 0) {
if ((idx + 1) % (VCS_SUBSET_WIDTH / 8) == 0) {
VCS_LOGF(".");
}
VCS_LOGF("%02x", ((unsigned char *)vcs)[idx]);
idx--;
}
return buf;
}
#undef VCS_LOGF
#endif
#endif /* _VCPUSET_H_ */
+58
View File
@@ -0,0 +1,58 @@
/*********************************************************
* Copyright (C) 2002-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
* 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
*
*********************************************************/
/*
* vcpuset_types.h --
*
* ADT for a set of VCPUs. Implemented as an array of bitmasks.
*
*/
#ifndef _VCPUSET_TYPES_H_
#define _VCPUSET_TYPES_H_
#define INCLUDE_ALLOW_VMX
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "vm_basic_asm.h"
#include "vm_atomic.h"
#include "vcpuid.h"
#define VCS_SUBSET_WIDTH 64
#define VCS_SUBSET_SHIFT 6
#define VCS_SUBSET_MASK ((CONST64U(1) << VCS_SUBSET_SHIFT) - 1)
#define VCS_SUBSET_COUNT 2
#define VCS_VCPUID_SUBSET_IDX(v) ((v) >> VCS_SUBSET_SHIFT)
#define VCS_VCPUID_SUBSET_BIT(v) (CONST64U(1) << ((v) & VCS_SUBSET_MASK))
/*
* If you update this type, you also need to update the SEND_IPI line in
* bora/public/iocontrolsMacosTable.h.
*/
typedef struct VCPUSet {
uint64 subset[VCS_SUBSET_COUNT];
} VCPUSet;
#endif
+170
View File
@@ -0,0 +1,170 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* Versioned atomic synchronization:
*
* These synchronization macros allow single-writer/many-reader
* access to data, based on Leslie Lamport's paper "Concurrent
* Reading and Writing", Communications of the ACM, November 1977.
*
* many-writer/many-reader can be implemented on top of versioned
* atomics by using an additional spin lock to synchronize
* writers. This is preferable for cases where readers are expected to
* greatly outnumber writers.
*
* Multiple concurrent writers to the version variables are not
* allowed. Even if writers are working on lock-free or disjoint
* data, the version counters are not interlocked for read-modify-write.
*
* Recursive use of versioned atomics in writers is currently not supported.
*/
#ifndef _VERSIONED_ATOMIC_H
#define _VERSIONED_ATOMIC_H
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#include "includeCheck.h"
#include "vm_basic_asm.h"
#include "vm_assert.h"
/*
* Users with attribute(packed) structs must ensure any
* VersionedAtomic members are marked as ALIGNED(4). Unfortunately
* the compiler cannot be trusted to align our substruct correctly
* (PR515329). If the enclosing struct is packed, the VersionedAtomic
* alignment requested below will be ignored!
*/
typedef struct {
volatile uint32 v0;
volatile uint32 v1;
} ALIGNED(4) VersionedAtomic;
/*
*-----------------------------------------------------------------------------
*
* VersionedAtomic_BeginWrite --
* Called by a writer to indicate that the data protected by
* a given atomic version is about to change. Effectively locks out
* all readers until EndWrite is called.
*
* Results:
* .
*
* Side effects:
*
*
*-----------------------------------------------------------------------------
*/
static INLINE void
VersionedAtomic_BeginWrite(VersionedAtomic *versions)
{
/*
* As long as the variable is on natural boundary it is guaranteed
* to be atomic, so we don't need to write from left to right as in
* Lamport's original algorithm.
*/
ASSERT(((size_t)(&versions->v0) & (sizeof(versions->v0) - 1)) == 0);
/* If recursive use is needed demand for support in PR514764 */
ASSERT(versions->v1 == versions->v0);
versions->v0++;
COMPILER_MEM_BARRIER();
}
/*
*-----------------------------------------------------------------------------
*
* VersionedAtomic_EndWrite --
* Called by a writer after it is done updating shared data. Lets
* pending and new readers proceed on shared data.
*
* Results:
* .
*
* Side effects:
*
*
*-----------------------------------------------------------------------------
*/
static INLINE void
VersionedAtomic_EndWrite(VersionedAtomic *versions)
{
ASSERT(((size_t)(&versions->v1) & (sizeof(versions->v1) - 1)) == 0);
ASSERT(versions->v1 + 1 == versions->v0);
COMPILER_MEM_BARRIER();
versions->v1 = versions->v0;
}
/*
*-----------------------------------------------------------------------------
*
* VersionedAtomic_BeginTryRead --
* Called by a reader before it tried to read shared data.
*
* Results:
* Returns a version number to the reader. This version number
* is required to confirm validity of the read operation when reader
* calls EndTryRead.
*
* Side effects:
*
*
*-----------------------------------------------------------------------------
*/
static INLINE uint32
VersionedAtomic_BeginTryRead(const VersionedAtomic *versions)
{
uint32 readVersion;
readVersion = versions->v1;
COMPILER_MEM_BARRIER();
return readVersion;
}
/*
*-----------------------------------------------------------------------------
*
* VersionedAtomic_EndTryRead --
* Called by a reader after it finishes reading shared data, to confirm
* validity of the data that was just read (IOW, to make sure that a
* writer did not intervene while the read was in progress).
*
* Results:
* TRUE if the data read between BeginTryRead() and this call is
* valid. FALSE otherwise.
*
* Side effects:
*
*
*-----------------------------------------------------------------------------
*/
static INLINE Bool
VersionedAtomic_EndTryRead(const VersionedAtomic *versions,
uint32 readVersion)
{
COMPILER_MEM_BARRIER();
return LIKELY(versions->v0 == readVersion);
}
#endif //_VERSIONED_ATOMIC_H
+93
View File
@@ -0,0 +1,93 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* vm_asm.h
*
* asm macros
*/
#ifndef _VM_ASM_H_
#define _VM_ASM_H_
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_USERLEVEL
#include "includeCheck.h"
#ifdef VM_ARM_64
#include "vm_asm_arm64.h"
#else
#include "vm_basic_asm.h"
#include "x86msr.h"
#ifdef VM_X86_64
#include "vm_asm_x86_64.h"
#else
#include "vm_asm_x86.h"
#endif
static INLINE void
SET_FS64(uint64 fs64)
{
__SET_MSR(MSR_FSBASE, fs64);
}
static INLINE void
SET_GS64(uint64 gs64)
{
__SET_MSR(MSR_GSBASE, gs64);
}
static INLINE void
SET_KernelGS64(uint64 kgs64)
{
__SET_MSR(MSR_KERNELGSBASE, kgs64);
}
static INLINE uint64
GET_FS64(void)
{
return __GET_MSR(MSR_FSBASE);
}
static INLINE uint64
GET_GS64(void)
{
return __GET_MSR(MSR_GSBASE);
}
static INLINE uint64
GET_KernelGS64(void)
{
return __GET_MSR(MSR_KERNELGSBASE);
}
#endif // VM_ARM_64
#endif
+998
View File
@@ -0,0 +1,998 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* vm_asm_x86.h
*
* IA32 asm macros
*/
#ifndef _VM_ASM_X86_H_
#define _VM_ASM_X86_H_
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_USERLEVEL
#include "includeCheck.h"
#include "x86types.h"
#include "x86desc.h"
#include "x86sel.h"
#include "x86_basic_defs.h"
#include "x86msr.h"
#ifdef VM_X86_64
#define _GETSET_DTR_TYPE DTR64
#else
#define _GETSET_DTR_TYPE DTR32
#endif
#ifdef __GNUC__
#if defined __APPLE__
/* PR 352418: GCC produces error if the non-Apple version is used */
#define ASSERT_ON_COMPILE_SELECTOR_SIZE(expr)
#else
/* ASSERT_ON_COMPILE_SELECTOR_SIZE:
*
* - Selector must be 16-bits.
* - If a constant is used, it better be only 16-bits.
* - If it's not a constant, it must be Selector-sized. or less.
*
* Although aesthetically the following looks nicer, gcc is unable
* to produce a constant expression for it:
*
* ASSERT_ON_COMPILE(sizeof(Selector) == 2 && \
* ((__builtin_constant_p(expr) ? ((expr) >> 16) == 0) \
* : sizeof(expr) <= 2)
*/
#if (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
#define ASSERT_ON_COMPILE_SELECTOR_SIZE(expr) \
ASSERT_ON_COMPILE(sizeof(Selector) == 2 && \
((__builtin_constant_p(expr) && ((expr) >> 16) == 0) || \
sizeof(expr) <= 2))
#else
/* gcc 3.3.3 is not able to produce a constant expression (PR 356383) */
#define ASSERT_ON_COMPILE_SELECTOR_SIZE(expr)
#endif
#endif
/*
* [GS]ET_[GI]DT() are defined as macros wrapping a function
* so we can pass the argument implicitly by reference (requires
* a macro) and get type checking too (requires a function).
*/
#define SET_GDT(var) _Set_GDT(&(var))
/* Checked against the Intel manual and GCC --hpreg */
static INLINE void
_Set_GDT(_GETSET_DTR_TYPE *dtr)
{
__asm__(
"lgdt %0"
:
: "m" (*dtr)
);
}
#define SET_IDT(var) _Set_IDT(&(var))
/* Checked against the Intel manual and GCC --hpreg */
static INLINE void
_Set_IDT(_GETSET_DTR_TYPE *dtr)
{
__asm__(
"lidt %0"
:
: "m" (*dtr)
);
}
#define GET_GDT(var) _Get_GDT(&(var))
/*
* Checked against the Intel manual and GCC --hpreg
* volatile because there's a hidden input (the [IG]DTR) that can change
* without the compiler knowing it.
*/
static INLINE void
_Get_GDT(_GETSET_DTR_TYPE *dtr)
{
__asm__ __volatile__(
"sgdt %0"
: "=m" (*dtr)
);
}
#define GET_IDT(var) _Get_IDT(&(var))
/*
* Checked against the Intel manual and GCC --hpreg
* volatile because the [IG]DT can change without the compiler knowing it
* (when we use l[ig]dt).
*/
static INLINE void
_Get_IDT(_GETSET_DTR_TYPE *dtr)
{
__asm__ __volatile__(
"sidt %0"
: "=m" (*dtr)
);
}
#define SET_LDT(expr) \
do { \
const Selector _set_ldt_sel = (Selector)(expr); \
ASSERT_ON_COMPILE_SELECTOR_SIZE(expr); \
/* lldt reads from the GDT; don't sink any writes. */ \
COMPILER_MEM_BARRIER(); \
/* Checked against the Intel manual and GCC --hpreg */ \
__asm__("lldt %0" \
: \
: "rm" (_set_ldt_sel)); \
} while (0)
/* Checked against the Intel manual and GCC --hpreg
*
* volatile because the LDT can change without the compiler knowing it
* (when we use lldt).
*/
static INLINE void
_GET_LDT(Selector * const result)
{
__asm__ __volatile__("sldt %0"
: "=rm" (*result));
}
#define GET_LDT(var) \
do { \
_GET_LDT(&(var)); \
} while (0)
/* Checked against the Intel manual and GCC --thutt */
#define _BUILD_SET_R(func, reg) \
static INLINE void \
func(uintptr_t r) \
{ \
__asm__("mov %0, %%" #reg \
: /* no outputs */ \
: "r" (r) \
: "memory"); \
}
/* Not yet checked against the Intel manual and GCC --slava
*
* 'volatile' because CRs and DRs can change without the compiler
* knowing it (when there is a page fault, when a breakpoint occurs,
* and moreover it seems there is no way to teach gcc that smsw
* clobbers cr0 for example).
*
* The parameter is a 'uintptr_t *' so that the size of the actual
* parameter must exactly match the size of the hardware register.
* This prevents the use of 32-bit variables when building 64-bit
* code.
*/
#define _BUILD_GET_R(func, reg) \
static INLINE void \
func(uintptr_t *result) \
{ \
__asm__ __volatile__("mov %%" #reg ", %0" \
: "=r" (*result)); \
}
_BUILD_SET_R(_SET_CR0, cr0)
_BUILD_SET_R(_SET_CR2, cr2)
_BUILD_SET_R(_SET_CR3, cr3)
_BUILD_SET_R(_SET_CR4, cr4)
_BUILD_SET_R(_SET_CR8, cr8)
_BUILD_GET_R(_GET_CR0, cr0)
_BUILD_GET_R(_GET_CR2, cr2)
_BUILD_GET_R(_GET_CR3, cr3)
_BUILD_GET_R(_GET_CR4, cr4)
_BUILD_GET_R(_GET_CR8, cr8)
#if defined __APPLE__
/* Mac OS gcc 4 uses DBx instead of DRx register names. */
_BUILD_SET_R(_SET_DR0, db0)
_BUILD_SET_R(_SET_DR1, db1)
_BUILD_SET_R(_SET_DR2, db2)
_BUILD_SET_R(_SET_DR3, db3)
_BUILD_SET_R(_SET_DR6, db6)
_BUILD_SET_R(_SET_DR7, db7)
_BUILD_GET_R(_GET_DR0, db0)
_BUILD_GET_R(_GET_DR1, db1)
_BUILD_GET_R(_GET_DR2, db2)
_BUILD_GET_R(_GET_DR3, db3)
_BUILD_GET_R(_GET_DR6, db6)
_BUILD_GET_R(_GET_DR7, db7)
#else
_BUILD_SET_R(_SET_DR0, dr0)
_BUILD_SET_R(_SET_DR1, dr1)
_BUILD_SET_R(_SET_DR2, dr2)
_BUILD_SET_R(_SET_DR3, dr3)
_BUILD_SET_R(_SET_DR6, dr6)
_BUILD_SET_R(_SET_DR7, dr7)
_BUILD_GET_R(_GET_DR0, dr0)
_BUILD_GET_R(_GET_DR1, dr1)
_BUILD_GET_R(_GET_DR2, dr2)
_BUILD_GET_R(_GET_DR3, dr3)
_BUILD_GET_R(_GET_DR6, dr6)
_BUILD_GET_R(_GET_DR7, dr7)
#endif
#define SET_CR_DR(regType, regNum, expr) \
do { \
/* Ensure no implicit truncation of 'expr' */ \
ASSERT_ON_COMPILE(sizeof(expr) <= sizeof(uintptr_t)); \
_SET_##regType##regNum(expr); \
} while (0)
#define GET_CR_DR(regType, regNum, var) \
do { \
_GET_##regType##regNum(&(var)); \
} while (0)
#define SET_CR0(expr) SET_CR_DR(CR, 0, expr)
#define SET_CR2(expr) SET_CR_DR(CR, 2, expr)
#define SET_CR3(expr) SET_CR_DR(CR, 3, expr)
#define SET_CR4(expr) SET_CR_DR(CR, 4, expr)
#define SET_CR8(expr) SET_CR_DR(CR, 8, expr)
/* Undefine GET_CR0; it is defined in mach_asm.h for SLES cross-compile */
#undef GET_CR0
#define GET_CR0(var) GET_CR_DR(CR, 0, var)
#define GET_CR2(var) GET_CR_DR(CR, 2, var)
#define GET_CR3(var) GET_CR_DR(CR, 3, var)
#define GET_CR4(var) GET_CR_DR(CR, 4, var)
#define GET_CR8(var) GET_CR_DR(CR, 8, var)
#define SET_DR0(expr) SET_CR_DR(DR, 0, expr)
#define SET_DR1(expr) SET_CR_DR(DR, 1, expr)
#define SET_DR2(expr) SET_CR_DR(DR, 2, expr)
#define SET_DR3(expr) SET_CR_DR(DR, 3, expr)
#define SET_DR6(expr) SET_CR_DR(DR, 6, expr)
#define SET_DR7(expr) SET_CR_DR(DR, 7, expr)
#define GET_DR0(var) GET_CR_DR(DR, 0, var)
#define GET_DR1(var) GET_CR_DR(DR, 1, var)
#define GET_DR2(var) GET_CR_DR(DR, 2, var)
#define GET_DR3(var) GET_CR_DR(DR, 3, var)
#define GET_DR6(var) GET_CR_DR(DR, 6, var)
#define GET_DR7(var) GET_CR_DR(DR, 7, var)
#define SET_SEGREG(reg, expr) \
do { \
const Selector _set_segreg_sel = (Selector)(expr); \
ASSERT_ON_COMPILE_SELECTOR_SIZE(expr); \
/* mov to Sreg reads from the [GL]DT; don't sink any writes. */ \
COMPILER_MEM_BARRIER(); \
/* Checked against the Intel manual and GCC --hpreg */ \
__asm__("movw %0, %%" #reg \
: \
: "rm" (_set_segreg_sel)); \
} while (0)
#define SET_DS(expr) SET_SEGREG(ds, expr)
#define SET_ES(expr) SET_SEGREG(es, expr)
#define SET_FS(expr) SET_SEGREG(fs, expr)
#define SET_GS(expr) SET_SEGREG(gs, expr)
#define SET_SS(expr) SET_SEGREG(ss, expr)
/* Checked against the Intel manual and GCC --hpreg
*
* volatile because the content of CS can change without the compiler
* knowing it (when we use call gates).
*
* XXX: The segment register getter functions have not been updated to
* have stricter type checking like many other functions in this
* file because they return a value, rather than taking an
* argument. Perhaps sometime in the future, a willing soul will
* change these accessors to take an argument and at the same
* time install better type checking.
*/
#define _BUILD_GET_SEG(func, reg) \
static INLINE Selector \
func(void) \
{ \
Selector result; \
__asm__ __volatile__("movw %%" #reg ", %0" \
: "=rm" (result)); \
return result; \
}
_BUILD_GET_SEG(GET_CS, cs)
_BUILD_GET_SEG(GET_DS, ds)
_BUILD_GET_SEG(GET_ES, es)
_BUILD_GET_SEG(GET_FS, fs)
_BUILD_GET_SEG(GET_GS, gs)
_BUILD_GET_SEG(GET_SS, ss)
#define SET_TR(expr) \
do { \
const Selector _set_tr_sel = (Selector)(expr); \
ASSERT_ON_COMPILE_SELECTOR_SIZE(expr); \
/* ltr reads from the GDT; don't sink any writes. */ \
COMPILER_MEM_BARRIER(); \
/* Checked against the Intel manual and GCC --hpreg */ \
__asm__ __volatile__("ltr %0" \
: \
: "rm" (_set_tr_sel) : "memory"); \
} while (0)
/* Checked against the Intel manual and GCC --hpreg
volatile because the content of TR can change without the compiler knowing
it (when we use task gates). */
static INLINE void
_GET_TR(Selector * const result)
{
__asm__ __volatile__("str %0"
: "=rm" (*result));
}
#define GET_TR(var) \
do { \
_GET_TR(&(var)); \
} while (0)
/* Checked against the Intel manual and GCC --hpreg
We use this to restore interrupts, so this cannot be reordered around
by gcc */
static INLINE void
_Set_flags(uintptr_t f)
{
__asm__ __volatile__(
"push %0" "\n\t"
"popf"
:
: "g" (f)
: "memory", "cc"
);
}
/* Checked against the Intel manual and GCC --hpreg
volatile because gcc 2.7.2.3 doesn't know when eflags are modified (it
seems to ignore the "cc" clobber). gcc 2.95.2 is ok: it optimize 2
successive calls only if there is no instructions in between. */
static INLINE uintptr_t
_Get_flags(void)
{
uintptr_t result;
__asm__ __volatile__(
"pushf" "\n\t"
"pop %0"
: "=rm" (result)
:
: "memory"
);
return result;
}
#define SAVE_FLAGS(var) do { \
var = _Get_flags(); \
} while (0)
static INLINE Bool
HwInterruptsEnabled(uint32 eflags)
{
return (eflags & EFLAGS_IF) != 0;
}
/* Checked against the Intel manual and GCC --hpreg */
static INLINE void
CLTS(void)
{
__asm__ __volatile__ ("clts");
}
/* Beginning of the section whose correctness has NOT been checked */
#define FNCLEX() __asm__("fnclex" ::);
/* TLB_INVALIDATE_xxx are not checked yet */
#define TLB_INVALIDATE_PAGE(_addr) do { \
__asm__ __volatile__("invlpg %0": :"m" (*(char *) (_addr)):"memory"); \
} while (0)
#define TLB_INVALIDATE_PAGE_OFF_FS(_addr) do { \
__asm__ __volatile__("fs; invlpg %0": :"m" (*(char *) (_addr)):"memory"); \
} while (0)
#if ! defined(VMKBOOT)
#define RESTORE_FLAGS _Set_flags
#define ENABLE_INTERRUPTS() __asm__ __volatile__ ("sti": : :"memory")
#define CLEAR_INTERRUPTS() __asm__ __volatile__ ("cli": : :"memory")
#endif
#define RAISE_INTERRUPT(_x) __asm__ __volatile__("int %0" :: "g" (_x))
#define RETURN_FROM_INT() __asm__ __volatile__("iret" :: )
#if ! defined(VMKERNEL) && ! defined(VMKBOOT)
#define NO_INTERRUPTS_BEGIN() do { \
uintptr_t _flags; \
SAVE_FLAGS(_flags); \
CLEAR_INTERRUPTS();
#define NO_INTERRUPTS_END() RESTORE_FLAGS(_flags); \
} while(0)
#endif
/* End of the section whose correctness has NOT been checked */
#elif defined _MSC_VER /* !__GNUC__ */
#define SET_IDT(_idt) _Set_IDT(&(_idt))
#define SET_GDT(_gdt) _Set_GDT(&(_gdt))
#define SET_TR(_tr) _Set_TR(_tr)
#define SET_LDT(_tr) _Set_LDT(_tr)
#define GET_IDT(_idt) _Get_IDT(&(_idt))
#define GET_GDT(_gdt) _Get_GDT(&(_gdt))
#define GET_TR(_tr) do { _tr = _Get_TR(); } while (0)
#define GET_LDT(_tr) do { _tr = _Get_LDT(); } while (0)
#define GET_CR0(_reg) __asm mov eax, cr0 __asm mov _reg, eax
#define SET_CR0(_reg) __asm mov eax, _reg __asm mov cr0, eax
#define GET_CR2(_reg) __asm mov eax, cr2 __asm mov _reg, eax
#define SET_CR2(_reg) __asm mov eax, _reg __asm mov cr2, eax
#define GET_CR3(_reg) __asm mov eax, cr3 __asm mov _reg, eax
#define SET_CR3(_reg) __asm mov eax, _reg __asm mov cr3, eax
/*
* MSC doesn't seem to like CR4 in __asm statements. We emit
* the opcode for MOV EAX,CR4 = 0xf020e0 and MOV CR4,EAX = 0xf022e0
*/
#define GET_CR4(_reg) { \
__asm _emit 0x0f __asm _emit 0x20 __asm _emit 0xe0 \
__asm mov _reg, eax \
}
#define SET_CR4(_reg) { \
__asm mov eax, _reg \
__asm _emit 0x0f __asm _emit 0x22 __asm _emit 0xe0 \
}
#define GET_DR0(_reg) do { __asm mov eax,dr0 __asm mov _reg,eax } while (0)
#define SET_DR0(_reg) do { __asm mov eax,_reg __asm mov dr0,eax } while (0)
#define GET_DR1(_reg) do { __asm mov eax,dr1 __asm mov _reg,eax } while (0)
#define SET_DR1(_reg) do { __asm mov eax,_reg __asm mov dr1,eax } while (0)
#define GET_DR2(_reg) do { __asm mov eax,dr2 __asm mov _reg,eax } while (0)
#define SET_DR2(_reg) do { __asm mov eax,_reg __asm mov dr2,eax } while (0)
#define GET_DR3(_reg) do { __asm mov eax,dr3 __asm mov _reg,eax } while (0)
#define SET_DR3(_reg) do { __asm mov eax,_reg __asm mov dr3,eax } while (0)
#define GET_DR6(_reg) do { __asm mov eax,dr6 __asm mov _reg,eax } while (0)
#define SET_DR6(_reg) do { __asm mov eax,_reg __asm mov dr6,eax } while (0)
#define GET_DR7(_reg) do { __asm mov eax,dr7 __asm mov _reg,eax } while (0)
#define SET_DR7(_reg) do { __asm mov eax,_reg __asm mov dr7,eax } while (0)
#define CLTS() __asm clts
#define FNCLEX() __asm fnclex
#define TLB_INVALIDATE_PAGE(_addr) { \
void *_a = (_addr); \
__asm mov eax, _a __asm invlpg [eax] \
}
#define TLB_INVALIDATE_PAGE_OFF_FS(_addr) { \
uint32 __a = (uint32) (_addr); \
__asm mov eax, __a _asm invlpg fs:[eax] \
}
#define ENABLE_INTERRUPTS() { __asm sti }
#define CLEAR_INTERRUPTS() { __asm cli }
#define RAISE_INTERRUPT(_x) {__asm int _x }
#define RETURN_FROM_INT() {__asm iretd }
#define SAVE_FLAGS(x) { \
__asm pushfd __asm pop eax __asm mov x, eax \
}
#define RESTORE_FLAGS(x) { \
__asm push x __asm popfd\
}
static INLINE void SET_DS(Selector val)
{
__asm mov ax, val
__asm mov ds, ax
}
static INLINE void SET_ES(Selector val)
{
__asm mov ax, val
__asm mov es, ax
}
static INLINE void SET_FS(Selector val)
{
__asm mov ax, val
__asm mov fs, ax
}
static INLINE void SET_GS(Selector val)
{
__asm mov ax, val
__asm mov gs, ax
}
static INLINE void SET_SS(Selector val)
{
__asm mov ax, val
__asm mov ss, ax
}
static INLINE Selector GET_FS(void)
{
Selector _v;
__asm mov _v,fs
return _v;
}
static INLINE Selector GET_GS(void)
{
Selector _v;
__asm mov _v,gs
return _v;
}
static INLINE Selector GET_DS(void)
{
Selector _v;
__asm mov _v,ds
return _v;
}
static INLINE Selector GET_ES(void)
{
Selector _v;
__asm mov _v,es
return _v;
}
static INLINE Selector GET_SS(void)
{
Selector _v;
__asm mov _v,ss
return _v;
}
static INLINE Selector GET_CS(void)
{
Selector _v;
__asm mov _v,cs
return _v;
}
#pragma warning( disable : 4035)
static INLINE uint32 GET_WORD_FROM_FS(uint32 *_addr) {
__asm mov eax, _addr
__asm mov eax, fs:[eax]
}
static INLINE uint16 GET_SHORT_FROM_FS(uint16 *_addr) {
__asm mov eax, _addr
__asm mov ax, fs:[eax]
}
static INLINE uint8 GET_BYTE_FROM_FS(uint8 *_addr) {
__asm mov eax, _addr
__asm mov al, fs:[eax]
}
#pragma warning (default: 4035)
static INLINE void SET_WORD_FS(uint32 *_addr, uint32 _val) {
__asm mov eax, _addr
__asm mov ebx, _val
__asm mov fs:[eax], ebx
}
static INLINE void SET_SHORT_FS(uint32 *_addr, uint16 _val) {
__asm mov eax, _addr
__asm mov bx, _val
__asm mov fs:[eax], bx
}
static INLINE void SET_BYTE_FS(uint32 *_addr, uint8 _val) {
__asm mov eax, _addr
__asm mov bl, _val
__asm mov fs:[eax], bl
}
static INLINE void _Set_GDT(_GETSET_DTR_TYPE *dtr) {
__asm mov eax, dtr
__asm lgdt [eax]
}
static INLINE void _Set_IDT(_GETSET_DTR_TYPE *dtr) {
__asm mov eax, dtr
__asm lidt [eax]
}
static INLINE void _Set_LDT(Selector val)
{
__asm lldt val
}
static INLINE void _Set_TR(Selector val)
{
__asm ltr val
}
static INLINE void _Get_GDT(_GETSET_DTR_TYPE *dtr) {
__asm mov eax, dtr
__asm sgdt [eax]
}
static INLINE void _Get_IDT(_GETSET_DTR_TYPE *dtr) {
__asm mov eax, dtr
__asm sidt [eax]
}
static INLINE Selector _Get_LDT(void) {
Selector sel;
__asm sldt sel
return sel;
}
static INLINE Selector _Get_TR(void) {
Selector sel;
__asm str sel
return sel;
}
static INLINE void
MEMCOPY_TO_FS(VA to,
char * from,
unsigned long n)
{
unsigned long i =0;
while (i+4 <=n) {
uint32 x = *(uint32*) (from + i);
uint32 _faddr = (uint32) (to+i);
__asm mov eax, _faddr
__asm mov ebx, x
__asm mov fs:[eax], ebx
i +=4;
}
while (i<n) {
uint8 x = from[i];
uint32 _faddr = (uint32) (to+i);
__asm mov eax, _faddr
__asm mov bl, x
__asm mov fs:[eax], bl
i++;
}
}
static INLINE void
MEMCOPY_FROM_FS(char * to,
VA from,
unsigned long n)
{
unsigned long i =0;
while (i+4 <=n) {
uint32 x;
uint32 _faddr = (uint32)(from+i);
__asm mov eax, _faddr
__asm mov ebx, fs:[eax]
__asm mov x,ebx
*(uint32*)(to+i)=x;
i +=4;
}
while (i<n) {
uint8 x;
uint32 _faddr = (uint32) (from+i);
__asm mov eax, _faddr;
__asm mov bl, fs:[eax]
__asm mov x, bl
*(uint8*)(to+i)=x;
i++;
}
}
#else
#error No compiler defined for get/set
#endif /* !__GNUC__ && !_MSC_VER */
#ifdef __GNUC__
static INLINE unsigned CURRENT_CPL(void)
{
return SELECTOR_RPL(GET_CS());
}
#elif defined _MSC_VER
static INLINE unsigned CURRENT_CPL(void) {
volatile Selector _v;
__asm mov ax, cs _asm mov _v, ax
return SELECTOR_RPL(_v);
}
#else
#error No compiler defined for CURRENT_CPL
#endif
#ifdef __GNUC__
/* Checked against the Intel manual and GCC --hpreg
volatile because the msr can change without the compiler knowing it
(when we use wrmsr). */
static INLINE uint64 __GET_MSR(int cx)
{
uint64 msr;
#ifdef VM_X86_64
__asm__ __volatile__(
"rdmsr; shlq $32, %%rdx; orq %%rdx, %%rax"
: "=a" (msr)
: "c" (cx)
: "%rdx"
);
#else
__asm__ __volatile__(
"rdmsr"
: "=A" (msr)
: "c" (cx)
);
#endif
return msr;
}
#elif defined _MSC_VER
#pragma warning( disable : 4035)
static INLINE uint64 __GET_MSR(int input)
{
__asm push ecx
__asm mov ecx, input
__asm _emit 0x0f __asm _emit 0x32
__asm pop ecx
}
static INLINE void __SET_MSR(int input, uint64 val)
{
uint32 hival = (uint32)(val >> 32);
uint32 loval = (uint32)val;
__asm push edx
__asm push ecx
__asm push eax
__asm mov eax, loval
__asm mov edx, hival
__asm mov ecx, input
__asm _emit 0x0f __asm _emit 0x30
__asm pop eax
__asm pop ecx
__asm pop edx
}
#pragma warning (default: 4035)
#else
#error
#endif
#ifdef __GNUC__
static INLINE void __SET_MSR(int cx, uint64 val)
{
#ifdef VM_X86_64
__asm__ __volatile__(
"wrmsr"
: /* no outputs */
: "a" ((uint32) val), "d" ((uint32)(val >> 32)), "c" (cx)
);
#else
__asm__ __volatile__(
"wrmsr"
: /* no outputs */
: "A" (val),
"c" (cx)
);
#endif
}
#endif
/*
* RDMSR/WRMSR access the 64bit MSRs as two
* 32 bit quantities, whereas GET_MSR/SET_MSR
* above access the MSRs as one 64bit quantity.
*/
#ifdef __GNUC__
#undef RDMSR
#undef WRMSR
#define RDMSR(msrNum, low, high) do { \
__asm__ __volatile__( \
"rdmsr" \
: "=a" (low), "=d" (high) \
: "c" (msrNum) \
); \
} while (0)
#define WRMSR(msrNum, low, high) do { \
__asm__ __volatile__( \
"wrmsr" \
: /* no outputs */ \
: "c" (msrNum), \
"a" (low), \
"d" (high) \
); \
} while (0)
static INLINE uint64 RDPMC(int cx)
{
#ifdef VM_X86_64
uint64 pmcLow;
uint64 pmcHigh;
__asm__ __volatile__(
"rdpmc"
: "=a" (pmcLow), "=d" (pmcHigh)
: "c" (cx)
);
return pmcHigh << 32 | pmcLow;
#else
uint64 pmc;
__asm__ __volatile__(
"rdpmc"
: "=A" (pmc)
: "c" (cx)
);
return pmc;
#endif
}
#elif defined _MSC_VER
#ifndef VM_X86_64 // XXX Switch to intrinsics with the new 32 and 64-bit compilers.
static INLINE uint64 RDPMC(int counter)
{
__asm mov ecx, counter
__asm rdpmc
}
static INLINE void WRMSR(uint32 msrNum, uint32 lo, uint32 hi)
{
__asm mov ecx, msrNum
__asm mov eax, lo
__asm mov edx, hi
__asm wrmsr
}
#endif
#endif
#if defined(__GNUC__) && (defined(VMM) || defined(VMKERNEL) || defined(FROBOS))
static INLINE uint64 __XGETBV(int cx)
{
#ifdef VM_X86_64
uint64 lowval, hival;
__asm__ __volatile__(
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
".byte 0x0f, 0x01, 0xd0"
#else
"xgetbv"
#endif
: "=a" (lowval), "=d" (hival)
: "c" (cx)
);
return hival << 32 | lowval;
#else
uint64 val;
__asm__ __volatile__(
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
".byte 0x0f, 0x01, 0xd0"
#else
"xgetbv"
#endif
: "=A" (val)
: "c" (cx)
);
return val;
#endif
}
static INLINE void __XSETBV(int cx, uint64 val)
{
__asm__ __volatile__(
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
".byte 0x0f, 0x01, 0xd1"
#else
"xsetbv"
#endif
: /* no outputs */
: "a" ((uint32)val), "d" ((uint32)(val >> 32)), "c" (cx)
);
}
static INLINE uint64 GET_XCR0(void)
{
return __XGETBV(0);
}
#define SET_XCR0(val) __XSETBV(0, val)
static INLINE void SET_XCR0_IF_NEEDED(uint64 newVal, uint64 oldVal)
{
ASSERT(oldVal == GET_XCR0());
if (newVal != oldVal) {
SET_XCR0(newVal);
}
}
#endif
#define START_TRACING() { \
uintptr_t flags; \
SAVE_FLAGS(flags); \
flags |= EFLAGS_TF; \
RESTORE_FLAGS(flags); \
}
#define STOP_TRACING() { \
uintptr_t flags; \
SAVE_FLAGS(flags); \
flags &= ~EFLAGS_TF; \
RESTORE_FLAGS(flags); \
}
static INLINE Bool
INTERRUPTS_ENABLED(void)
{
uintptr_t flags;
SAVE_FLAGS(flags);
return ((flags & EFLAGS_IF) != 0);
}
static INLINE void
SET_KERNEL_PER_CORE(uint64 val)
{
__SET_MSR(MSR_GSBASE, val);
}
#endif
+136
View File
@@ -0,0 +1,136 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* vm_asm_x86_64.h
*
* x86-64 asm macros
*/
#ifndef _VM_ASM_X86_64_H_
#define _VM_ASM_X86_64_H_
#define INCLUDE_ALLOW_VMX
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_DISTRIBUTE
#include "includeCheck.h"
#ifdef __GNUC__
#include "vm_asm_x86.h"
#endif
/*
* This file contains inline assembly routines used by x86_64 code.
*/
#ifdef __GNUC__
/* nop; prevents #error for no compiler definition from firing */
#elif defined _MSC_VER /* !__GNUC__ */
/*
* x86-64 windows doesn't support inline asm so we have to use these
* intrinsic functions defined in the compiler. Not all of these are well
* documented. There is an array in the compiler dll (c1.dll) which has
* an array of the names of all the intrinsics minus the leading
* underscore. Searching around in the ntddk.h file can also be helpful.
*
* The declarations for the intrinsic functions were taken from the DDK.
* Our declarations must match the ddk's otherwise the 64-bit c++ compiler
* will complain about second linkage of the intrinsic functions.
* We define the intrinsic using the basic types corresponding to the
* Windows typedefs. This avoids having to include windows header files
* to get to the windows types.
*/
#ifdef _WIN64
#ifdef __cplusplus
extern "C" {
#endif
unsigned __int64 __readmsr(unsigned long);
void __writemsr(unsigned long, unsigned __int64);
#pragma intrinsic(__readmsr, __writemsr)
#ifdef __cplusplus
}
#endif
static INLINE uint64
RDPMC(int counter)
{
return __readpmc(counter);
}
static INLINE void
WRMSR(uint32 msrNum, uint32 lo, uint32 hi)
{
uint64 value = QWORD(hi, lo);
__writemsr(msrNum, value);
}
static INLINE uint64
__GET_MSR(int input)
{
return __readmsr((unsigned long)input);
}
static INLINE void
__SET_MSR(int cx, uint64 val)
{
__writemsr((unsigned long)cx, (unsigned __int64)val);
}
#endif
#else
#error No compiler defined for get/set
#endif /* !__GNUC__ && !_MSC_VER */
#ifdef __GNUC__
static INLINE void
SWAPGS(void)
{
__asm__ __volatile__("swapgs");
}
static INLINE uint64
RDTSCP_AuxOnly(void)
{
uint64 tscLow, tscHigh, tscAux;
__asm__ __volatile__(
"rdtscp"
: "=a" (tscLow), "=d" (tscHigh), "=c" (tscAux)
);
return tscAux;
}
#endif
#endif
+336
View File
@@ -0,0 +1,336 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* vm_assert.h --
*
* The basic assertion facility for all VMware code.
*
* For proper use, see bora/doc/assert and
* http://vmweb.vmware.com/~mts/WebSite/guide/programming/asserts.html.
*/
#ifndef _VM_ASSERT_H_
#define _VM_ASSERT_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMKDRIVERS
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
// XXX not necessary except some places include vm_assert.h improperly
#include "vm_basic_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Some bits of vmcore are used in VMKernel code and cannot have
* the VMKERNEL define due to other header dependencies.
*/
#if defined(VMKERNEL) && !defined(VMKPANIC)
#define VMKPANIC 1
#endif
/*
* Internal macros, functions, and strings
*
* The monitor wants to save space at call sites, so it has specialized
* functions for each situation. User level wants to save on implementation
* so it uses generic functions.
*/
#if !defined VMM || defined MONITOR_APP // {
#if defined (VMKPANIC)
#include "vmk_assert.h"
#else /* !VMKPANIC */
#define _ASSERT_PANIC(name) \
Panic(_##name##Fmt "\n", __FILE__, __LINE__)
#define _ASSERT_PANIC_BUG(bug, name) \
Panic(_##name##Fmt " bugNr=%d\n", __FILE__, __LINE__, bug)
#define _ASSERT_PANIC_NORETURN(name) \
Panic(_##name##Fmt "\n", __FILE__, __LINE__)
#define _ASSERT_PANIC_BUG_NORETURN(bug, name) \
Panic(_##name##Fmt " bugNr=%d\n", __FILE__, __LINE__, bug)
#endif /* VMKPANIC */
#endif // }
// These strings don't have newline so that a bug can be tacked on.
#define _AssertPanicFmt "PANIC %s:%d"
#define _AssertAssertFmt "ASSERT %s:%d"
#define _AssertVerifyFmt "VERIFY %s:%d"
#define _AssertNotImplementedFmt "NOT_IMPLEMENTED %s:%d"
#define _AssertNotReachedFmt "NOT_REACHED %s:%d"
#define _AssertMemAllocFmt "MEM_ALLOC %s:%d"
#define _AssertNotTestedFmt "NOT_TESTED %s:%d"
/*
* Panic and log functions
*/
void Log(const char *fmt, ...) PRINTF_DECL(1, 2);
void Warning(const char *fmt, ...) PRINTF_DECL(1, 2);
#if defined VMKPANIC
void Panic_SaveRegs(void);
#ifdef VMX86_DEBUG
void Panic_NoSave(const char *fmt, ...) PRINTF_DECL(1, 2);
#else
NORETURN void Panic_NoSave(const char *fmt, ...) PRINTF_DECL(1, 2);
#endif
NORETURN void Panic_NoSaveNoReturn(const char *fmt, ...) PRINTF_DECL(1, 2);
#define Panic(fmt...) do { \
Panic_SaveRegs(); \
Panic_NoSave(fmt); \
} while(0)
#define Panic_NoReturn(fmt...) do { \
Panic_SaveRegs(); \
Panic_NoSaveNoReturn(fmt); \
} while(0)
#else
NORETURN void Panic(const char *fmt, ...) PRINTF_DECL(1, 2);
#endif
void LogThrottled(uint32 *count, const char *fmt, ...) PRINTF_DECL(2, 3);
void WarningThrottled(uint32 *count, const char *fmt, ...) PRINTF_DECL(2, 3);
#ifndef ASSERT_IFNOT
/*
* PR 271512: When compiling with gcc, catch assignments inside an ASSERT.
*
* 'UNLIKELY' is defined with __builtin_expect, which does not warn when
* passed an assignment (gcc bug 36050). To get around this, we put 'cond'
* in an 'if' statement and make sure it never gets executed by putting
* that inside of 'if (0)'. We use gcc's statement expression syntax to
* make ASSERT an expression because some code uses it that way.
*
* Since statement expression syntax is a gcc extension and since it's
* not clear if this is a problem with other compilers, the ASSERT
* definition was not changed for them. Using a bare 'cond' with the
* ternary operator may provide a solution.
*/
#ifdef __GNUC__
#define ASSERT_IFNOT(cond, panic) \
({if (UNLIKELY(!(cond))) { panic; if (0) { if (cond) {;}}} (void)0;})
#else
#define ASSERT_IFNOT(cond, panic) \
(UNLIKELY(!(cond)) ? (panic) : (void)0)
#endif
#endif
/*
* Assert, panic, and log macros
*
* Some of these are redefined below undef !VMX86_DEBUG.
* ASSERT() is special cased because of interaction with Windows DDK.
*/
#if defined VMX86_DEBUG
#undef ASSERT
#define ASSERT(cond) ASSERT_IFNOT(cond, _ASSERT_PANIC(AssertAssert))
#define ASSERT_BUG(bug, cond) \
ASSERT_IFNOT(cond, _ASSERT_PANIC_BUG(bug, AssertAssert))
#endif
#undef VERIFY
#define VERIFY(cond) \
ASSERT_IFNOT(cond, _ASSERT_PANIC_NORETURN(AssertVerify))
#define VERIFY_BUG(bug, cond) \
ASSERT_IFNOT(cond, _ASSERT_PANIC_BUG_NORETURN(bug, AssertVerify))
#define PANIC() _ASSERT_PANIC(AssertPanic)
#define PANIC_BUG(bug) _ASSERT_PANIC_BUG(bug, AssertPanic)
#define ASSERT_NOT_IMPLEMENTED(cond) \
ASSERT_IFNOT(cond, NOT_IMPLEMENTED())
#define ASSERT_NOT_IMPLEMENTED_BUG(bug, cond) \
ASSERT_IFNOT(cond, NOT_IMPLEMENTED_BUG(bug))
#if defined VMKPANIC || defined VMM
#define NOT_IMPLEMENTED() _ASSERT_PANIC_NORETURN(AssertNotImplemented)
#else
#define NOT_IMPLEMENTED() _ASSERT_PANIC(AssertNotImplemented)
#endif
#if defined VMM
#define NOT_IMPLEMENTED_BUG(bug) \
_ASSERT_PANIC_BUG_NORETURN(bug, AssertNotImplemented)
#else
#define NOT_IMPLEMENTED_BUG(bug) _ASSERT_PANIC_BUG(bug, AssertNotImplemented)
#endif
#if defined VMKPANIC || defined VMM
#define NOT_REACHED() _ASSERT_PANIC_NORETURN(AssertNotReached)
#else
#define NOT_REACHED() _ASSERT_PANIC(AssertNotReached)
#endif
#define ASSERT_MEM_ALLOC(cond) \
ASSERT_IFNOT(cond, _ASSERT_PANIC(AssertMemAlloc))
#ifdef VMX86_DEVEL
#define ASSERT_DEVEL(cond) ASSERT(cond)
#define NOT_TESTED() Warning(_AssertNotTestedFmt "\n", __FILE__, __LINE__)
#else
#define ASSERT_DEVEL(cond) ((void)0)
#define NOT_TESTED() Log(_AssertNotTestedFmt "\n", __FILE__, __LINE__)
#endif
#define ASSERT_NO_INTERRUPTS() ASSERT(!INTERRUPTS_ENABLED())
#define ASSERT_HAS_INTERRUPTS() ASSERT(INTERRUPTS_ENABLED())
#define ASSERT_NOT_TESTED(cond) (UNLIKELY(!(cond)) ? NOT_TESTED() : (void)0)
#define NOT_TESTED_ONCE() DO_ONCE(NOT_TESTED())
#define NOT_TESTED_1024() \
do { \
static uint16 count = 0; \
if (UNLIKELY(count == 0)) { NOT_TESTED(); } \
count = (count + 1) & 1023; \
} while (0)
#define LOG_ONCE(_s) DO_ONCE(Log _s)
/*
* Redefine macros that are only in debug versions
*/
#if !defined VMX86_DEBUG // {
#undef ASSERT
#define ASSERT(cond) ((void)0)
#define ASSERT_BUG(bug, cond) ((void)0)
/*
* Expand NOT_REACHED() as appropriate for each situation.
*
* Mainly, we want the compiler to infer the same control-flow
* information as it would from Panic(). Otherwise, different
* compilation options will lead to different control-flow-derived
* errors, causing some make targets to fail while others succeed.
*
* VC++ has the __assume() built-in function which we don't trust
* (see bug 43485); gcc has no such construct; we just panic in
* userlevel code. The monitor doesn't want to pay the size penalty
* (measured at 212 bytes for the release vmm for a minimal infinite
* loop; panic would cost even more) so it does without and lives
* with the inconsistency.
*/
#if defined VMKPANIC || defined VMM
#undef NOT_REACHED
#if defined __GNUC__ && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 5)
#define NOT_REACHED() (__builtin_unreachable())
#else
#define NOT_REACHED() ((void)0)
#endif
#else
// keep debug definition
#endif
#undef LOG_UNEXPECTED
#define LOG_UNEXPECTED(bug) ((void)0)
#undef ASSERT_NOT_TESTED
#define ASSERT_NOT_TESTED(cond) ((void)0)
#undef NOT_TESTED
#define NOT_TESTED() ((void)0)
#undef NOT_TESTED_ONCE
#define NOT_TESTED_ONCE() ((void)0)
#undef NOT_TESTED_1024
#define NOT_TESTED_1024() ((void)0)
#endif // !VMX86_DEBUG }
/*
* Compile-time assertions.
*
* ASSERT_ON_COMPILE does not use the common
* switch (0) { case 0: case (e): ; } trick because some compilers (e.g. MSVC)
* generate code for it.
*
* The implementation uses both enum and typedef because the typedef alone is
* insufficient; gcc allows arrays to be declared with non-constant expressions
* (even in typedefs, where it makes no sense).
*
* NOTE: if GCC ever changes so that it ignores unused types altogether, this
* assert might not fire! We explicitly mark it as unused because GCC 4.8+
* uses -Wunused-local-typedefs as part of -Wall, which means the typedef will
* generate a warning.
*/
#if defined(_Static_assert) || defined(__cplusplus) || \
!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
#define ASSERT_ON_COMPILE(e) \
do { \
enum { AssertOnCompileMisused = ((e) ? 1 : -1) }; \
UNUSED_TYPE(typedef char AssertOnCompileFailed[AssertOnCompileMisused]); \
} while (0)
#else
#define ASSERT_ON_COMPILE(e) \
do { \
_Static_assert(e, #e); \
} while (0);
#endif
/*
* To put an ASSERT_ON_COMPILE() outside a function, wrap it
* in MY_ASSERTS(). The first parameter must be unique in
* each .c file where it appears. For example,
*
* MY_ASSERTS(FS3_INT,
* ASSERT_ON_COMPILE(sizeof(FS3_DiskLock) == 128);
* ASSERT_ON_COMPILE(sizeof(FS3_DiskLockReserved) == DISK_BLOCK_SIZE);
* ASSERT_ON_COMPILE(sizeof(FS3_DiskBlock) == DISK_BLOCK_SIZE);
* ASSERT_ON_COMPILE(sizeof(Hardware_DMIUUID) == 16);
* )
*
* Caution: ASSERT() within MY_ASSERTS() is silently ignored.
* The same goes for anything else not evaluated at compile time.
*/
#define MY_ASSERTS(name, assertions) \
static INLINE void name(void) { \
assertions \
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* ifndef _VM_ASSERT_H_ */
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+548
View File
@@ -0,0 +1,548 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* vm_basic_asm_x86.h
*
* Basic IA32 asm macros
*/
#ifndef _VM_BASIC_ASM_X86_H_
#define _VM_BASIC_ASM_X86_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#ifdef VM_X86_64
/*
* The gcc inline asm uses the "A" constraint which differs in 32 & 64
* bit mode. 32 bit means eax and edx, 64 means rax or rdx.
*/
#error "x86-64 not supported"
#endif
/*
* XTEST
* Return TRUE if processor is in transaction region.
*
*/
#if defined(__GNUC__) && (defined(VMM) || defined(VMKERNEL) || defined(FROBOS))
static INLINE Bool
xtest(void)
{
uint8 al;
__asm__ __volatile__(".byte 0x0f, 0x01, 0xd6 # xtest \n"
"setnz %%al\n"
: "=a"(al) : : "cc");
return al;
}
#endif /* __GNUC__ */
/*
* FXSAVE/FXRSTOR
* save/restore SIMD/MMX fpu state
*
* The pointer passed in must be 16-byte aligned.
*
* Intel and AMD processors behave differently w.r.t. fxsave/fxrstor. Intel
* processors unconditionally save the exception pointer state (instruction
* ptr., data ptr., and error instruction opcode). FXSAVE_ES1 and FXRSTOR_ES1
* work correctly for Intel processors.
*
* AMD processors only save the exception pointer state if ES=1. This leads to a
* security hole whereby one process/VM can inspect the state of another process
* VM. The AMD recommended workaround involves clobbering the exception pointer
* state unconditionally, and this is implemented in FXRSTOR_AMD_ES0. Note that
* FXSAVE_ES1 will only save the exception pointer state for AMD processors if
* ES=1.
*
* The workaround (FXRSTOR_AMD_ES0) only costs 1 cycle more than just doing an
* fxrstor, on both AMD Opteron and Intel Core CPUs.
*/
#if defined(__GNUC__)
static INLINE void
FXSAVE_ES1(void *save)
{
__asm__ __volatile__ ("fxsave %0\n" : "=m" (*(uint8 *)save) : : "memory");
}
static INLINE void
FXRSTOR_ES1(const void *load)
{
__asm__ __volatile__ ("fxrstor %0\n"
: : "m" (*(const uint8 *)load) : "memory");
}
static INLINE void
FXRSTOR_AMD_ES0(const void *load)
{
uint64 dummy = 0;
__asm__ __volatile__
("fnstsw %%ax \n" // Grab x87 ES bit
"bt $7,%%ax \n" // Test ES bit
"jnc 1f \n" // Jump if ES=0
"fnclex \n" // ES=1. Clear it so fild doesn't trap
"1: \n"
"ffree %%st(7) \n" // Clear tag bit - avoid poss. stack overflow
"fildl %0 \n" // Dummy Load from "safe address" changes all
// x87 exception pointers.
"fxrstor %1 \n"
:
: "m" (dummy), "m" (*(const uint8 *)load)
: "ax", "memory");
}
#endif /* __GNUC__ */
/*
* XSAVE/XRSTOR
* save/restore GSSE/SIMD/MMX fpu state
*
* The pointer passed in must be 64-byte aligned.
* See above comment for more information.
*/
#if defined(__GNUC__) && (defined(VMM) || defined(VMKERNEL) || defined(FROBOS))
static INLINE void
XSAVE_ES1(void *save, uint64 mask)
{
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
__asm__ __volatile__ (
".byte 0x0f, 0xae, 0x21 \n"
:
: "c" ((uint8 *)save), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#else
__asm__ __volatile__ (
"xsave %0 \n"
: "=m" (*(uint8 *)save)
: "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#endif
}
static INLINE void
XSAVEOPT_ES1(void *save, uint64 mask)
{
__asm__ __volatile__ (
".byte 0x0f, 0xae, 0x31 \n"
:
: "c" ((uint8 *)save), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
}
static INLINE void
XRSTOR_ES1(const void *load, uint64 mask)
{
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
__asm__ __volatile__ (
".byte 0x0f, 0xae, 0x29 \n"
:
: "c" ((const uint8 *)load),
"a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#else
__asm__ __volatile__ (
"xrstor %0 \n"
:
: "m" (*(const uint8 *)load),
"a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#endif
}
static INLINE void
XRSTOR_AMD_ES0(const void *load, uint64 mask)
{
uint64 dummy = 0;
__asm__ __volatile__
("fnstsw %%ax \n" // Grab x87 ES bit
"bt $7,%%ax \n" // Test ES bit
"jnc 1f \n" // Jump if ES=0
"fnclex \n" // ES=1. Clear it so fild doesn't trap
"1: \n"
"ffree %%st(7) \n" // Clear tag bit - avoid poss. stack overflow
"fildl %0 \n" // Dummy Load from "safe address" changes all
// x87 exception pointers.
"mov %%ebx, %%eax \n"
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
".byte 0x0f, 0xae, 0x29 \n"
:
: "m" (dummy), "c" ((const uint8 *)load),
"b" ((uint32)mask), "d" ((uint32)(mask >> 32))
#else
"xrstor %1 \n"
:
: "m" (dummy), "m" (*(const uint8 *)load),
"b" ((uint32)mask), "d" ((uint32)(mask >> 32))
#endif
: "eax", "memory");
}
#endif /* __GNUC__ */
/*
*-----------------------------------------------------------------------------
*
* Div643232 --
*
* Unsigned integer division:
* The dividend is 64-bit wide
* The divisor is 32-bit wide
* The quotient is 32-bit wide
*
* Use this function if you are certain that:
* o Either the quotient will fit in 32 bits,
* o Or your code is ready to handle a #DE exception indicating overflow.
* If that is not the case, then use Div643264().
*
* Results:
* Quotient and remainder
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__)
static INLINE void
Div643232(uint64 dividend, // IN
uint32 divisor, // IN
uint32 *quotient, // OUT
uint32 *remainder) // OUT
{
__asm__(
"divl %4"
: "=a" (*quotient),
"=d" (*remainder)
: "0" ((uint32)dividend),
"1" ((uint32)(dividend >> 32)),
"rm" (divisor)
: "cc"
);
}
#elif defined _MSC_VER
static INLINE void
Div643232(uint64 dividend, // IN
uint32 divisor, // IN
uint32 *quotient, // OUT
uint32 *remainder) // OUT
{
__asm {
mov eax, DWORD PTR [dividend]
mov edx, DWORD PTR [dividend+4]
div DWORD PTR [divisor]
mov edi, DWORD PTR [quotient]
mov [edi], eax
mov edi, DWORD PTR [remainder]
mov [edi], edx
}
}
#else
#error No compiler defined for Div643232
#endif
#if defined(__GNUC__)
/*
*-----------------------------------------------------------------------------
*
* Div643264 --
*
* Unsigned integer division:
* The dividend is 64-bit wide
* The divisor is 32-bit wide
* The quotient is 64-bit wide
*
* Results:
* Quotient and remainder
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static INLINE void
Div643264(uint64 dividend, // IN
uint32 divisor, // IN
uint64 *quotient, // OUT
uint32 *remainder) // OUT
{
uint32 hQuotient;
uint32 lQuotient;
__asm__(
"divl %5" "\n\t"
"movl %%eax, %0" "\n\t"
"movl %4, %%eax" "\n\t"
"divl %5"
: "=&rm" (hQuotient),
"=a" (lQuotient),
"=d" (*remainder)
: "1" ((uint32)(dividend >> 32)),
"g" ((uint32)dividend),
"rm" (divisor),
"2" (0)
: "cc"
);
*quotient = (uint64)hQuotient << 32 | lQuotient;
}
#endif
/*
*-----------------------------------------------------------------------------
*
* Mul64x3264 --
*
* Unsigned integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Unsigned 64-bit integer multiplicand.
* Unsigned 32-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Unsigned 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) && \
!defined(MUL64_NO_ASM)
static INLINE uint64
Mul64x3264(uint64 multiplicand, uint32 multiplier, uint32 shift)
{
uint64 result;
uint32 tmp1, tmp2;
// ASSERT(shift >= 0 && shift < 64);
__asm__("mov %%eax, %2\n\t" // Save lo(multiplicand)
"mov %%edx, %%eax\n\t" // Get hi(multiplicand)
"mull %4\n\t" // p2 = hi(multiplicand) * multiplier
"xchg %%eax, %2\n\t" // Save lo(p2), get lo(multiplicand)
"mov %%edx, %1\n\t" // Save hi(p2)
"mull %4\n\t" // p1 = lo(multiplicand) * multiplier
"addl %2, %%edx\n\t" // hi(p1) += lo(p2)
"adcl $0, %1\n\t" // hi(p2) += carry from previous step
"cmpl $32, %%ecx\n\t" // shift < 32?
"jl 2f\n\t" // Go if so
"shll $1, %%eax\n\t" // Save lo(p1) bit 31 in CF in case shift=32
"mov %%edx, %%eax\n\t" // result = hi(p2):hi(p1) >> (shift & 31)
"mov %1, %%edx\n\t"
"shrdl %%edx, %%eax\n\t"
"mov $0, %2\n\t"
"adcl $0, %2\n\t" // Get highest order bit shifted out, from CF
"shrl %%cl, %%edx\n\t"
"jmp 3f\n"
"2:\n\t"
"xor %2, %2\n\t"
"shrdl %%edx, %%eax\n\t" // result = hi(p2):hi(p1):lo(p1) >> shift
"adcl $0, %2\n\t" // Get highest order bit shifted out, from CF
"shrdl %1, %%edx\n"
"3:\n\t"
"addl %2, %%eax\n\t" // result += highest order bit shifted out
"adcl $0, %%edx"
: "=A" (result), "=&r" (tmp1), "=&r" (tmp2)
: "0" (multiplicand), "rm" (multiplier), "c" (shift)
: "cc");
return result;
}
#elif defined _MSC_VER
#pragma warning(disable: 4035)
static INLINE uint64
Mul64x3264(uint64 multiplicand, uint32 multiplier, uint32 shift)
{
// ASSERT(shift >= 0 && shift < 64);
__asm {
mov eax, DWORD PTR [multiplicand+4] // Get hi(multiplicand)
mul DWORD PTR [multiplier] // p2 = hi(multiplicand) * multiplier
mov ecx, eax // Save lo(p2)
mov ebx, edx // Save hi(p2)
mov eax, DWORD PTR [multiplicand] // Get lo(multiplicand)
mul DWORD PTR [multiplier+0] // p1 = lo(multiplicand) * multiplier
add edx, ecx // hi(p1) += lo(p2)
adc ebx, 0 // hi(p2) += carry from previous step
mov ecx, DWORD PTR [shift] // Get shift
cmp ecx, 32 // shift < 32?
jl SHORT l2 // Go if so
shl eax, 1 // Save lo(p1) bit 31 in CF in case shift=32
mov eax, edx // result = hi(p2):hi(p1) >> (shift & 31)
mov edx, ebx
shrd eax, edx, cl
mov esi, 0
adc esi, 0 // Get highest order bit shifted out, from CF
shr edx, cl
jmp SHORT l3
l2:
xor esi, esi
shrd eax, edx, cl // result = hi(p2):hi(p1):lo(p1) >> shift
adc esi, 0 // Get highest order bit shifted out, from CF
shrd edx, ebx, cl
l3:
add eax, esi // result += highest order bit shifted out
adc edx, 0
}
// return with result in edx:eax
}
#pragma warning(default: 4035)
#else
#define MUL64_NO_ASM 1
#include "mul64.h"
#endif
/*
*-----------------------------------------------------------------------------
*
* Muls64x32s64 --
*
* Signed integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Signed 64-bit integer multiplicand.
* Unsigned 32-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Signed 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) && \
!defined(MUL64_NO_ASM)
static INLINE int64
Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
{
int64 result;
uint32 tmp1, tmp2;
// ASSERT(shift >= 0 && shift < 64);
__asm__("mov %%eax, %2\n\t" // Save lo(multiplicand)
"mov %%edx, %%eax\n\t" // Get hi(multiplicand)
"test %%eax, %%eax\n\t" // Check sign of multiplicand
"jl 0f\n\t" // Go if negative
"mull %4\n\t" // p2 = hi(multiplicand) * multiplier
"jmp 1f\n"
"0:\n\t"
"mull %4\n\t" // p2 = hi(multiplicand) * multiplier
"sub %4, %%edx\n" // hi(p2) += -1 * multiplier
"1:\n\t"
"xchg %%eax, %2\n\t" // Save lo(p2), get lo(multiplicand)
"mov %%edx, %1\n\t" // Save hi(p2)
"mull %4\n\t" // p1 = lo(multiplicand) * multiplier
"addl %2, %%edx\n\t" // hi(p1) += lo(p2)
"adcl $0, %1\n\t" // hi(p2) += carry from previous step
"cmpl $32, %%ecx\n\t" // shift < 32?
"jl 2f\n\t" // Go if so
"shll $1, %%eax\n\t" // Save lo(p1) bit 31 in CF in case shift=32
"mov %%edx, %%eax\n\t" // result = hi(p2):hi(p1) >> (shift & 31)
"mov %1, %%edx\n\t"
"shrdl %%edx, %%eax\n\t"
"mov $0, %2\n\t"
"adcl $0, %2\n\t" // Get highest order bit shifted out from CF
"sarl %%cl, %%edx\n\t"
"jmp 3f\n"
"2:\n\t"
"xor %2, %2\n\t"
"shrdl %%edx, %%eax\n\t" // result = hi(p2):hi(p1):lo(p1) >> shift
"adcl $0, %2\n\t" // Get highest order bit shifted out from CF
"shrdl %1, %%edx\n"
"3:\n\t"
"addl %2, %%eax\n\t" // result += highest order bit shifted out
"adcl $0, %%edx"
: "=A" (result), "=&r" (tmp1), "=&rm" (tmp2)
: "0" (multiplicand), "rm" (multiplier), "c" (shift)
: "cc");
return result;
}
#elif defined(_MSC_VER)
#pragma warning(disable: 4035)
static INLINE int64
Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
{
//ASSERT(shift >= 0 && shift < 64);
__asm {
mov eax, DWORD PTR [multiplicand+4] // Get hi(multiplicand)
test eax, eax // Check sign of multiplicand
jl SHORT l0 // Go if negative
mul DWORD PTR [multiplier] // p2 = hi(multiplicand) * multiplier
jmp SHORT l1
l0:
mul DWORD PTR [multiplier] // p2 = hi(multiplicand) * multiplier
sub edx, DWORD PTR [multiplier] // hi(p2) += -1 * multiplier
l1:
mov ecx, eax // Save lo(p2)
mov ebx, edx // Save hi(p2)
mov eax, DWORD PTR [multiplicand] // Get lo(multiplicand)
mul DWORD PTR [multiplier] // p1 = lo(multiplicand) * multiplier
add edx, ecx // hi(p1) += lo(p2)
adc ebx, 0 // hi(p2) += carry from previous step
mov ecx, DWORD PTR [shift] // Get shift
cmp ecx, 32 // shift < 32?
jl SHORT l2 // Go if so
shl eax, 1 // Save lo(p1) bit 31 in CF in case shift=32
mov eax, edx // result = hi(p2):hi(p1) >> (shift & 31)
mov edx, ebx
shrd eax, edx, cl
mov esi, 0
adc esi, 0 // Get highest order bit shifted out, from CF
sar edx, cl
jmp SHORT l3
l2:
xor esi, esi
shrd eax, edx, cl // result = hi(p2):hi(p1):lo(p1) << shift
adc esi, 0 // Get highest order bit shifted out, from CF
shrd edx, ebx, cl
l3:
add eax, esi // result += highest order bit shifted out
adc edx, 0
}
// return with result in edx:eax
}
#pragma warning(default: 4035)
#endif
#endif
+615
View File
@@ -0,0 +1,615 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* vm_basic_asm_x86_64.h
*
* Basic x86_64 asm macros.
*/
#ifndef _VM_BASIC_ASM_X86_64_H_
#define _VM_BASIC_ASM_X86_64_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#ifndef VM_X86_64
#error "This file is x86-64 only!"
#endif
#if defined(_MSC_VER) && !defined(BORA_NO_WIN32_INTRINS)
#ifdef __cplusplus
extern "C" {
#endif
uint64 _umul128(uint64 multiplier, uint64 multiplicand,
uint64 *highProduct);
int64 _mul128(int64 multiplier, int64 multiplicand,
int64 *highProduct);
uint64 __shiftright128(uint64 lowPart, uint64 highPart, uint8 shift);
#ifdef __cplusplus
}
#endif
#pragma intrinsic(_umul128, _mul128, __shiftright128)
#endif // _MSC_VER
#if defined(__GNUC__)
/*
* GET_CURRENT_RIP
*
* Returns the current instruction pointer. In the example below:
*
* foo.c
* L123: Foo(GET_CURRENT_RIP())
*
* the return value from GET_CURRENT_RIP will point a debugger to L123.
*/
#define GET_CURRENT_RIP() ({ \
void *__rip; \
asm("lea 0(%%rip), %0;\n\t" \
: "=r" (__rip)); \
__rip; \
})
#define GET_CURRENT_PC() GET_CURRENT_RIP()
/*
* GET_CURRENT_LOCATION
*
* Updates the arguments with the values of the %rip, %rbp, and %rsp
* registers at the current code location where the macro is invoked,
* and the return address.
*/
#define GET_CURRENT_LOCATION(rip, rbp, rsp, retAddr) do { \
asm("lea 0(%%rip), %0\n" \
"mov %%rbp, %1\n" \
"mov %%rsp, %2\n" \
: "=r" (rip), "=r" (rbp), "=r" (rsp)); \
retAddr = (uint64) GetReturnAddress(); \
} while (0)
#endif
/*
* FXSAVE/FXRSTOR
* save/restore SIMD/MMX fpu state
*
* The pointer passed in must be 16-byte aligned.
*
* Intel and AMD processors behave differently w.r.t. fxsave/fxrstor. Intel
* processors unconditionally save the exception pointer state (instruction
* ptr., data ptr., and error instruction opcode). FXSAVE_ES1 and FXRSTOR_ES1
* work correctly for Intel processors.
*
* AMD processors only save the exception pointer state if ES=1. This leads to a
* security hole whereby one process/VM can inspect the state of another process
* VM. The AMD recommended workaround involves clobbering the exception pointer
* state unconditionally, and this is implemented in FXRSTOR_AMD_ES0. Note that
* FXSAVE_ES1 will only save the exception pointer state for AMD processors if
* ES=1.
*
* The workaround (FXRSTOR_AMD_ES0) only costs 1 cycle more than just doing an
* fxrstor, on both AMD Opteron and Intel Core CPUs.
*/
#if defined(__GNUC__)
static INLINE void
FXSAVE_ES1(void *save)
{
__asm__ __volatile__ ("fxsaveq %0 \n" : "=m" (*(uint8 *)save) : : "memory");
}
static INLINE void
FXSAVE_COMPAT_ES1(void *save)
{
__asm__ __volatile__ ("fxsave %0 \n" : "=m" (*(uint8 *)save) : : "memory");
}
static INLINE void
FXRSTOR_ES1(const void *load)
{
__asm__ __volatile__ ("fxrstorq %0 \n"
: : "m" (*(const uint8 *)load) : "memory");
}
static INLINE void
FXRSTOR_COMPAT_ES1(const void *load)
{
__asm__ __volatile__ ("fxrstor %0 \n"
: : "m" (*(const uint8 *)load) : "memory");
}
static INLINE void
FXRSTOR_AMD_ES0(const void *load)
{
uint64 dummy = 0;
__asm__ __volatile__
("fnstsw %%ax \n" // Grab x87 ES bit
"bt $7,%%ax \n" // Test ES bit
"jnc 1f \n" // Jump if ES=0
"fnclex \n" // ES=1. Clear it so fild doesn't trap
"1: \n"
"ffree %%st(7) \n" // Clear tag bit - avoid poss. stack overflow
"fildl %0 \n" // Dummy Load from "safe address" changes all
// x87 exception pointers.
"fxrstorq %1 \n"
:
: "m" (dummy), "m" (*(const uint8 *)load)
: "ax", "memory");
}
#endif /* __GNUC__ */
/*
* XSAVE/XRSTOR
* save/restore GSSE/SIMD/MMX fpu state
*
* The pointer passed in must be 64-byte aligned.
* See above comment for more information.
*/
#if defined(__GNUC__) && (defined(VMM) || defined(VMKERNEL) || defined(FROBOS))
static INLINE void
XSAVE_ES1(void *save, uint64 mask)
{
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
__asm__ __volatile__ (
".byte 0x48, 0x0f, 0xae, 0x21 \n"
:
: "c" ((uint8 *)save), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#else
__asm__ __volatile__ (
"xsaveq %0 \n"
: "=m" (*(uint8 *)save)
: "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#endif
}
static INLINE void
XSAVE_COMPAT_ES1(void *save, uint64 mask)
{
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
__asm__ __volatile__ (
".byte 0x0f, 0xae, 0x21 \n"
:
: "c" ((uint8 *)save), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#else
__asm__ __volatile__ (
"xsave %0 \n"
: "=m" (*(uint8 *)save)
: "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#endif
}
static INLINE void
XSAVEOPT_ES1(void *save, uint64 mask)
{
__asm__ __volatile__ (
".byte 0x48, 0x0f, 0xae, 0x31 \n"
:
: "c" ((uint8 *)save), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
}
static INLINE void
XRSTOR_ES1(const void *load, uint64 mask)
{
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
__asm__ __volatile__ (
".byte 0x48, 0x0f, 0xae, 0x29 \n"
:
: "c" ((const uint8 *)load),
"a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#else
__asm__ __volatile__ (
"xrstorq %0 \n"
:
: "m" (*(const uint8 *)load),
"a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#endif
}
static INLINE void
XRSTOR_COMPAT_ES1(const void *load, uint64 mask)
{
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
__asm__ __volatile__ (
".byte 0x0f, 0xae, 0x29 \n"
:
: "c" ((const uint8 *)load),
"a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#else
__asm__ __volatile__ (
"xrstor %0 \n"
:
: "m" (*(const uint8 *)load),
"a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#endif
}
static INLINE void
XRSTOR_AMD_ES0(const void *load, uint64 mask)
{
uint64 dummy = 0;
__asm__ __volatile__
("fnstsw %%ax \n" // Grab x87 ES bit
"bt $7,%%ax \n" // Test ES bit
"jnc 1f \n" // Jump if ES=0
"fnclex \n" // ES=1. Clear it so fild doesn't trap
"1: \n"
"ffree %%st(7) \n" // Clear tag bit - avoid poss. stack overflow
"fildl %0 \n" // Dummy Load from "safe address" changes all
// x87 exception pointers.
"mov %%ebx, %%eax \n"
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
".byte 0x48, 0x0f, 0xae, 0x29 \n"
:
: "m" (dummy), "c" ((const uint8 *)load),
"b" ((uint32)mask), "d" ((uint32)(mask >> 32))
#else
"xrstorq %1 \n"
:
: "m" (dummy), "m" (*(const uint8 *)load),
"b" ((uint32)mask), "d" ((uint32)(mask >> 32))
#endif
: "eax", "memory");
}
#endif /* __GNUC__ */
/*
* XTEST
* Return TRUE if processor is in transaction region.
*
*/
#if defined(__GNUC__) && (defined(VMM) || defined(VMKERNEL) || defined(FROBOS))
static INLINE Bool
xtest(void)
{
uint8 al;
__asm__ __volatile__(".byte 0x0f, 0x01, 0xd6 # xtest \n"
"setnz %%al\n"
: "=a"(al) : : "cc");
return al;
}
#endif /* __GNUC__ */
/*
*-----------------------------------------------------------------------------
*
* Mul64x6464 --
*
* Unsigned integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Unsigned 64-bit integer multiplicand.
* Unsigned 64-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Unsigned 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__) && !defined(MUL64_NO_ASM)
static INLINE uint64
Mul64x6464(uint64 multiplicand,
uint64 multiplier,
uint32 shift)
{
/*
* Implementation:
* Multiply 64x64 bits to yield a full 128-bit product.
* Clear the carry bit (needed for the shift == 0 case).
* Shift result in RDX:RAX right by "shift".
* Add the carry bit. (If shift > 0, this is the highest order bit
* that was discarded by the shift; else it is 0.)
* Return the low-order 64 bits of the above.
*
*/
uint64 result, dummy;
__asm__("mulq %3 \n\t"
"clc \n\t"
"shrdq %b4, %1, %0 \n\t"
"adc $0, %0 \n\t"
: "=a" (result),
"=d" (dummy)
: "0" (multiplier),
"rm" (multiplicand),
"c" (shift)
: "cc");
return result;
}
#elif defined(_MSC_VER) && !defined(MUL64_NO_ASM)
static INLINE uint64
Mul64x6464(uint64 multiplicand,
uint64 multiplier,
uint32 shift)
{
/*
* Unfortunately, MSVC intrinsics don't give us access to the carry
* flag after a 128-bit shift, so the implementation is more
* awkward:
* Multiply 64x64 bits to yield a full 128-bit product.
* Shift result right by "shift".
* If shift != 0, extract and add in highest order bit that was
* discarded by the shift.
* Return the low-order 64 bits of the above.
*/
uint64 tmplo, tmphi;
tmplo = _umul128(multiplicand, multiplier, &tmphi);
if (shift == 0) {
return tmplo;
} else {
return __shiftright128(tmplo, tmphi, (uint8) shift) +
((tmplo >> (shift - 1)) & 1);
}
}
#else
#define MUL64_NO_ASM 1
#include "mul64.h"
#endif
/*
*-----------------------------------------------------------------------------
*
* Muls64x64s64 --
*
* Signed integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Signed 64-bit integer multiplicand.
* Unsigned 64-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Signed 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__) && !defined(MUL64_NO_ASM)
static inline int64
Muls64x64s64(int64 multiplicand,
int64 multiplier,
uint32 shift)
{
int64 result, dummy;
/* Implementation:
* Multiply 64x64 bits to yield a full 128-bit product.
* Clear the carry bit (needed for the shift == 0 case).
* Shift result in RDX:RAX right by "shift".
* Add the carry bit. (If shift > 0, this is the highest order bit
* that was discarded by the shift; else it is 0.)
* Return the low-order 64 bits of the above.
*
* Note: using the unsigned shrd instruction is correct because
* shift < 64 and we return only the low 64 bits of the shifted
* result.
*/
__asm__("imulq %3 \n\t"
"clc \n\t"
"shrdq %b4, %1, %0 \n\t"
"adc $0, %0 \n\t"
: "=a" (result),
"=d" (dummy)
: "0" (multiplier),
"rm" (multiplicand),
"c" (shift)
: "cc");
return result;
}
#elif defined(_MSC_VER) && !defined(MUL64_NO_ASM)
static INLINE int64
Muls64x64s64(int64 multiplicand,
int64 multiplier,
uint32 shift)
{
/*
* Unfortunately, MSVC intrinsics don't give us access to the carry
* flag after a 128-bit shift, so the implementation is more
* awkward:
* Multiply 64x64 bits to yield a full 128-bit product.
* Shift result right by "shift".
* If shift != 0, extract and add in highest order bit that was
* discarded by the shift.
* Return the low-order 64 bits of the above.
*
* Note: using an unsigned shift is correct because shift < 64 and
* we return only the low 64 bits of the shifted result.
*/
int64 tmplo, tmphi;
tmplo = _mul128(multiplicand, multiplier, &tmphi);
if (shift == 0) {
return tmplo;
} else {
return __shiftright128(tmplo, tmphi, (uint8) shift) +
((tmplo >> (shift - 1)) & 1);
}
}
#endif
#ifndef MUL64_NO_ASM
/*
*-----------------------------------------------------------------------------
*
* Mul64x3264 --
*
* Unsigned integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Unsigned 64-bit integer multiplicand.
* Unsigned 32-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Unsigned 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
static INLINE uint64
Mul64x3264(uint64 multiplicand, uint32 multiplier, uint32 shift)
{
return Mul64x6464(multiplicand, multiplier, shift);
}
/*
*-----------------------------------------------------------------------------
*
* Muls64x32s64 --
*
* Signed integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Signed 64-bit integer multiplicand.
* Unsigned 32-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Signed 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
static INLINE int64
Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
{
return Muls64x64s64(multiplicand, multiplier, shift);
}
#endif
#if defined(__GNUC__)
static INLINE void *
uint64set(void *dst, uint64 val, uint64 count)
{
int dummy0;
int dummy1;
__asm__ __volatile__("\t"
"cld" "\n\t"
"rep ; stosq" "\n"
: "=c" (dummy0), "=D" (dummy1)
: "0" (count), "1" (dst), "a" (val)
: "memory", "cc");
return dst;
}
#endif
/*
*-----------------------------------------------------------------------------
*
* Div643232 --
*
* Unsigned integer division:
* The dividend is 64-bit wide
* The divisor is 32-bit wide
* The quotient is 32-bit wide
*
* Use this function if you are certain that the quotient will fit in 32 bits,
* If that is not the case, a #DE exception was generated in 32-bit version,
* but not in this 64-bit version. So please be careful.
*
* Results:
* Quotient and remainder
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__) || defined(_MSC_VER)
static INLINE void
Div643232(uint64 dividend, // IN
uint32 divisor, // IN
uint32 *quotient, // OUT
uint32 *remainder) // OUT
{
*quotient = (uint32)(dividend / divisor);
*remainder = (uint32)(dividend % divisor);
}
#endif
/*
*-----------------------------------------------------------------------------
*
* Div643264 --
*
* Unsigned integer division:
* The dividend is 64-bit wide
* The divisor is 32-bit wide
* The quotient is 64-bit wide
*
* Results:
* Quotient and remainder
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__)
static INLINE void
Div643264(uint64 dividend, // IN
uint32 divisor, // IN
uint64 *quotient, // OUT
uint32 *remainder) // OUT
{
*quotient = dividend / divisor;
*remainder = dividend % divisor;
}
#endif
#endif // _VM_BASIC_ASM_X86_64_H_
@@ -0,0 +1,313 @@
/*********************************************************
* Copyright (C) 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
* 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
*
*********************************************************/
/*
* vm_basic_asm_x86_common.h --
*
* Basic assembler macros common to 32-bit and 64-bit x86 ISA.
*/
#ifndef _VM_BASIC_ASM_X86_COMMON_H_
#define _VM_BASIC_ASM_X86_COMMON_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#ifndef VM_X86_ANY
#error "Should be included only in x86 builds"
#endif
/*
* x86-64 windows doesn't support inline asm so we have to use these
* intrinsic functions defined in the compiler. Not all of these are well
* documented. There is an array in the compiler dll (c1.dll) which has
* an array of the names of all the intrinsics minus the leading
* underscore. Searching around in the ntddk.h file can also be helpful.
*
* The declarations for the intrinsic functions were taken from the DDK.
* Our declarations must match the ddk's otherwise the 64-bit c++ compiler
* will complain about second linkage of the intrinsic functions.
* We define the intrinsic using the basic types corresponding to the
* Windows typedefs. This avoids having to include windows header files
* to get to the windows types.
*/
#if defined(_MSC_VER) && !defined(BORA_NO_WIN32_INTRINS)
#ifdef __cplusplus
extern "C" {
#endif
/*
* It seems x86 & x86-64 windows still implements these intrinsic
* functions. The documentation for the x86-64 suggest the
* __inbyte/__outbyte intrinsics even though the _in/_out work fine and
* __inbyte/__outbyte aren't supported on x86.
*/
int _inp(unsigned short);
unsigned short _inpw(unsigned short);
unsigned long _inpd(unsigned short);
int _outp(unsigned short, int);
unsigned short _outpw(unsigned short, unsigned short);
unsigned long _outpd(uint16, unsigned long);
#pragma intrinsic(_inp, _inpw, _inpd, _outp, _outpw, _outpw, _outpd)
/*
* Prevents compiler from re-ordering reads, writes and reads&writes.
* These functions do not add any instructions thus only affect
* the compiler ordering.
*
* See:
* `Lockless Programming Considerations for Xbox 360 and Microsoft Windows'
* http://msdn.microsoft.com/en-us/library/bb310595(VS.85).aspx
*/
void _ReadBarrier(void);
void _WriteBarrier(void);
void _ReadWriteBarrier(void);
#pragma intrinsic(_ReadBarrier, _WriteBarrier, _ReadWriteBarrier)
void _mm_mfence(void);
void _mm_lfence(void);
#pragma intrinsic(_mm_mfence, _mm_lfence)
unsigned int __getcallerseflags(void);
#pragma intrinsic(__getcallerseflags)
#ifdef VM_X86_64
/*
* intrinsic functions only supported by x86-64 windows as of 2k3sp1
*/
unsigned __int64 __rdtsc(void);
void __stosw(unsigned short *, unsigned short, size_t);
void __stosd(unsigned long *, unsigned long, size_t);
void _mm_pause(void);
#pragma intrinsic(__rdtsc, __stosw, __stosd, _mm_pause)
unsigned char _BitScanForward64(unsigned long *, unsigned __int64);
unsigned char _BitScanReverse64(unsigned long *, unsigned __int64);
#pragma intrinsic(_BitScanForward64, _BitScanReverse64)
#endif /* VM_X86_64 */
unsigned char _BitScanForward(unsigned long *, unsigned long);
unsigned char _BitScanReverse(unsigned long *, unsigned long);
#pragma intrinsic(_BitScanForward, _BitScanReverse)
unsigned char _bittest(const long *, long);
unsigned char _bittestandset(long *, long);
unsigned char _bittestandreset(long *, long);
unsigned char _bittestandcomplement(long *, long);
#pragma intrinsic(_bittest, _bittestandset, _bittestandreset, _bittestandcomplement)
#ifdef VM_X86_64
unsigned char _bittestandset64(__int64 *, __int64);
unsigned char _bittestandreset64(__int64 *, __int64);
#pragma intrinsic(_bittestandset64, _bittestandreset64)
#endif // VM_X86_64
#ifdef __cplusplus
}
#endif
#endif // _MSC_VER
#ifdef __GNUC__
/*
* Checked against the Intel manual and GCC --hpreg
*
* volatile because reading from port can modify the state of the underlying
* hardware.
*
* Note: The undocumented %z construct doesn't work (internal compiler error)
* with gcc-2.95.1
*/
#define __GCC_IN(s, type, name) \
static INLINE type \
name(uint16 port) \
{ \
type val; \
\
__asm__ __volatile__( \
"in" #s " %w1, %0" \
: "=a" (val) \
: "Nd" (port) \
); \
\
return val; \
}
__GCC_IN(b, uint8, INB)
__GCC_IN(w, uint16, INW)
__GCC_IN(l, uint32, IN32)
/*
* Checked against the Intel manual and GCC --hpreg
*
* Note: The undocumented %z construct doesn't work (internal compiler error)
* with gcc-2.95.1
*/
#define __GCC_OUT(s, s2, port, val) do { \
__asm__( \
"out" #s " %" #s2 "1, %w0" \
: \
: "Nd" (port), "a" (val) \
); \
} while (0)
#define OUTB(port, val) __GCC_OUT(b, b, port, val)
#define OUTW(port, val) __GCC_OUT(w, w, port, val)
#define OUT32(port, val) __GCC_OUT(l, , port, val)
#define GET_CURRENT_EIP(_eip) \
__asm__ __volatile("call 0\n\tpopl %0" : "=r" (_eip): );
static INLINE unsigned int
GetCallerEFlags(void)
{
unsigned long flags;
asm volatile("pushf; pop %0" : "=r"(flags));
return flags;
}
#elif defined(_MSC_VER)
static INLINE uint8
INB(uint16 port)
{
return (uint8)_inp(port);
}
static INLINE void
OUTB(uint16 port, uint8 value)
{
_outp(port, value);
}
static INLINE uint16
INW(uint16 port)
{
return _inpw(port);
}
static INLINE void
OUTW(uint16 port, uint16 value)
{
_outpw(port, value);
}
static INLINE uint32
IN32(uint16 port)
{
return _inpd(port);
}
static INLINE void
OUT32(uint16 port, uint32 value)
{
_outpd(port, value);
}
#ifndef VM_X86_64
#ifdef NEAR
#undef NEAR
#endif
#define GET_CURRENT_EIP(_eip) do { \
__asm call NEAR PTR $+5 \
__asm pop eax \
__asm mov _eip, eax \
} while (0)
#endif // VM_X86_64
static INLINE unsigned int
GetCallerEFlags(void)
{
return __getcallerseflags();
}
#endif // __GNUC__
/* Sequence recommended by Intel for the Pentium 4. */
#define INTEL_MICROCODE_VERSION() ( \
__SET_MSR(MSR_BIOS_SIGN_ID, 0), \
__GET_EAX_FROM_CPUID(1), \
__GET_MSR(MSR_BIOS_SIGN_ID))
/*
*-----------------------------------------------------------------------------
*
* RDTSC_BARRIER --
*
* Implements an RDTSC fence. Instructions executed prior to the
* fence will have completed before the fence and all stores to
* memory are flushed from the store buffer.
*
* On AMD, MFENCE is sufficient. On Intel, only LFENCE is
* documented to fence RDTSC, but LFENCE won't drain the store
* buffer. So, use MFENCE;LFENCE, which will work on both AMD and
* Intel.
*
* It is the callers' responsibility to check for SSE2 before
* calling this function.
*
* Results:
* None.
*
* Side effects:
* Cause loads and stores prior to this to be globally visible, and
* RDTSC will not pass.
*
*-----------------------------------------------------------------------------
*/
static INLINE void
RDTSC_BARRIER(void)
{
#ifdef __GNUC__
__asm__ __volatile__(
"mfence \n\t"
"lfence \n\t"
::: "memory"
);
#elif defined _MSC_VER
/* Prevent compiler from moving code across mfence/lfence. */
_ReadWriteBarrier();
_mm_mfence();
_mm_lfence();
_ReadWriteBarrier();
#else
#error No compiler defined for RDTSC_BARRIER
#endif
}
/*
* Compiler/CPU barriers. These take the form of <mem access type>_<mem access
* type>_MEM_BARRIER, where <mem access type> is either LD (load), ST (store) or
* LDST (any). On x86 we only need to care specifically about store-load
* reordering on normal memory types and mfence, otherwise only a compiler
* barrier is needed.
*/
#define LD_LD_MEM_BARRIER() COMPILER_MEM_BARRIER()
#define LD_ST_MEM_BARRIER() COMPILER_MEM_BARRIER()
#define LD_LDST_MEM_BARRIER() COMPILER_MEM_BARRIER()
#define ST_LD_MEM_BARRIER() asm volatile ("mfence" ::: "memory")
#define ST_ST_MEM_BARRIER() COMPILER_MEM_BARRIER()
#define ST_LDST_MEM_BARRIER() ST_LD_MEM_BARRIER()
#define LDST_LD_MEM_BARRIER() ST_LD_MEM_BARRIER()
#define LDST_ST_MEM_BARRIER() COMPILER_MEM_BARRIER()
#define LDST_LDST_MEM_BARRIER() ST_LD_MEM_BARRIER()
#endif // _VM_BASIC_ASM_X86_COMMON_H_
+786
View File
@@ -0,0 +1,786 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* vm_basic_defs.h --
*
* Standard macros for VMware source code.
*/
#ifndef _VM_BASIC_DEFS_H_
#define _VM_BASIC_DEFS_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMKDRIVERS
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "vm_basic_types.h" // For INLINE.
/* Checks for FreeBSD, filtering out VMKERNEL. */
#define __IS_FREEBSD__ (!defined(VMKERNEL) && defined(__FreeBSD__))
#define __IS_FREEBSD_VER__(ver) (__IS_FREEBSD__ && __FreeBSD_version >= (ver))
#if defined _WIN32 && defined USERLEVEL
#include <stddef.h> /*
* We redefine offsetof macro from stddef; make
* sure that it's already defined before we do that.
*/
#include <windows.h> // for Sleep() and LOWORD() etc.
#undef GetFreeSpace // Unpollute preprocessor namespace.
#endif
/*
* Simple macros
*/
#ifndef vmw_offsetof
#define vmw_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#if (defined __APPLE__ || defined __FreeBSD__) && \
(!defined KERNEL && !defined _KERNEL && !defined VMKERNEL && !defined __KERNEL__)
# include <stddef.h>
#else
#ifndef offsetof
#define VMW_DEFINED_OFFSETOF
/*
* XXX While the _WIN32 implementation appears to be identical to vmw_offsetof
* in terms of behavior, they need to be separate to match verbatim the
* definition used by the respective compilers, to avoid a redefinition warning.
*
* This is necessary until we eliminate the inclusion of <windows.h> above.
*/
#ifdef _WIN32
#define offsetof(s,m) (size_t)&(((s *)0)->m)
/*
* We use the builtin offset for gcc/clang, except when we're running under the
* vmkernel's GDB macro preprocessor, since gdb doesn't understand
* __builtin_offsetof.
*/
#elif defined __GNUC__ && !defined VMKERNEL_GDB_MACRO_BUILDER
#define offsetof __builtin_offsetof
#else
#define offsetof vmw_offsetof
#endif
#endif // offsetof
#endif // __APPLE__
#define VMW_CONTAINER_OF(ptr, type, member) \
((type *)((char *)(ptr) - vmw_offsetof(type, member)))
#ifndef ARRAYSIZE
#define ARRAYSIZE(a) (sizeof (a) / sizeof *(a))
#endif
#ifndef MIN
#define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b))
#endif
/* The Solaris 9 cross-compiler complains about these not being used */
#ifndef sun
static INLINE int
Min(int a, int b)
{
return a < b ? a : b;
}
#endif
#ifndef MAX
#define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b))
#endif
#ifndef sun
static INLINE int
Max(int a, int b)
{
return a > b ? a : b;
}
#endif
#define VMW_CLAMP(x, min, max) \
((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
#define ROUNDUP(x,y) (((x) + (y) - 1) / (y) * (y))
#define ROUNDDOWN(x,y) ((x) / (y) * (y))
#define ROUNDUPBITS(x, bits) (((uintptr_t) (x) + MASK(bits)) & ~MASK(bits))
#define ROUNDDOWNBITS(x, bits) ((uintptr_t) (x) & ~MASK(bits))
#define CEILING(x, y) (((x) + (y) - 1) / (y))
#if defined __APPLE__
#include <machine/param.h>
#undef MASK
#endif
/*
* The MASK macro behaves badly when given negative numbers or numbers larger
* than the highest order bit number (e.g. 32 on a 32-bit machine) as an
* argument. The range 0..31 is safe.
*/
#define MASK(n) ((1 << (n)) - 1) /* make an n-bit mask */
#define MASK64(n) ((CONST64U(1) << (n)) - 1) /* make an n-bit mask */
/*
* MASKRANGE64 makes a bit vector starting at bit lo and ending at bit hi. No
* checking for lo < hi is done.
*/
#define MASKRANGE64(hi, lo) (MASK64((hi) - (lo) + 1) << (lo))
/* SIGNEXT64 sign extends a n-bit value to 64-bits. */
#define SIGNEXT64(val, n) (((int64)(val) << (64 - (n))) >> (64 - (n)))
#define DWORD_ALIGN(x) ((((x) + 3) >> 2) << 2)
#define QWORD_ALIGN(x) ((((x) + 7) >> 3) << 3)
#define IMPLIES(a,b) (!(a) || (b))
/*
* Not everybody (e.g., the monitor) has NULL
*/
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
/*
* Token concatenation
*
* The C preprocessor doesn't prescan arguments when they are
* concatenated or stringified. So we need extra levels of
* indirection to convince the preprocessor to expand its
* arguments.
*/
#define CONC(x, y) x##y
#define XCONC(x, y) CONC(x, y)
#define XXCONC(x, y) XCONC(x, y)
#define MAKESTR(x) #x
#define XSTR(x) MAKESTR(x)
/*
* Wide versions of string constants.
*/
#ifndef WSTR
#define WSTR_(X) L ## X
#define WSTR(X) WSTR_(X)
#endif
/*
* Page operations
*
* It has been suggested that these definitions belong elsewhere
* (like x86types.h). However, I deem them common enough
* (since even regular user-level programs may want to do
* page-based memory manipulation) to be here.
* -- edward
*/
#ifndef PAGE_SHIFT // {
#if defined VM_I386
#define PAGE_SHIFT 12
#elif defined __APPLE__
#define PAGE_SHIFT 12
#elif defined VM_ARM_64
#define PAGE_SHIFT 12
#elif defined __arm__
#define PAGE_SHIFT 12
#else
#error
#endif
#endif // }
#ifndef PAGE_SIZE
#define PAGE_SIZE (1 << PAGE_SHIFT)
#endif
#ifndef PAGE_MASK
#define PAGE_MASK (PAGE_SIZE - 1)
#endif
#ifndef PAGE_OFFSET
#define PAGE_OFFSET(_addr) ((uintptr_t)(_addr) & (PAGE_SIZE - 1))
#endif
#ifndef PAGE_NUMBER
#define PAGE_NUMBER(_addr) ((uintptr_t)(_addr) / PAGE_SIZE)
#endif
#ifndef VM_PAGE_BASE
#define VM_PAGE_BASE(_addr) ((_addr) & ~(PAGE_SIZE - 1))
#endif
#ifndef VM_PAGES_SPANNED
#define VM_PAGES_SPANNED(_addr, _size) \
((((_addr) & (PAGE_SIZE - 1)) + (_size) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
#endif
#ifndef BYTES_2_PAGES
#define BYTES_2_PAGES(_nbytes) ((_nbytes) >> PAGE_SHIFT)
#endif
#ifndef PAGES_2_BYTES
#define PAGES_2_BYTES(_npages) (((uint64)(_npages)) << PAGE_SHIFT)
#endif
#ifndef MBYTES_2_PAGES
#define MBYTES_2_PAGES(_nbytes) ((_nbytes) << (20 - PAGE_SHIFT))
#endif
#ifndef PAGES_2_MBYTES
#define PAGES_2_MBYTES(_npages) ((_npages) >> (20 - PAGE_SHIFT))
#endif
#ifndef GBYTES_2_PAGES
#define GBYTES_2_PAGES(_nbytes) ((_nbytes) << (30 - PAGE_SHIFT))
#endif
#ifndef PAGES_2_GBYTES
#define PAGES_2_GBYTES(_npages) ((_npages) >> (30 - PAGE_SHIFT))
#endif
#ifndef BYTES_2_MBYTES
#define BYTES_2_MBYTES(_nbytes) ((_nbytes) >> 20)
#endif
#ifndef MBYTES_2_BYTES
#define MBYTES_2_BYTES(_nbytes) ((uint64)(_nbytes) << 20)
#endif
#ifndef BYTES_2_GBYTES
#define BYTES_2_GBYTES(_nbytes) ((_nbytes) >> 30)
#endif
#ifndef GBYTES_2_BYTES
#define GBYTES_2_BYTES(_nbytes) ((uint64)(_nbytes) << 30)
#endif
#ifndef VM_PAE_LARGE_PAGE_SHIFT
#define VM_PAE_LARGE_PAGE_SHIFT 21
#endif
#ifndef VM_PAE_LARGE_PAGE_SIZE
#define VM_PAE_LARGE_PAGE_SIZE (1 << VM_PAE_LARGE_PAGE_SHIFT)
#endif
#ifndef VM_PAE_LARGE_PAGE_MASK
#define VM_PAE_LARGE_PAGE_MASK (VM_PAE_LARGE_PAGE_SIZE - 1)
#endif
#ifndef VM_PAE_LARGE_2_SMALL_PAGES
#define VM_PAE_LARGE_2_SMALL_PAGES (BYTES_2_PAGES(VM_PAE_LARGE_PAGE_SIZE))
#endif
/*
* Word operations
*/
#ifndef LOWORD
#define LOWORD(_dw) ((_dw) & 0xffff)
#endif
#ifndef HIWORD
#define HIWORD(_dw) (((_dw) >> 16) & 0xffff)
#endif
#ifndef LOBYTE
#define LOBYTE(_w) ((_w) & 0xff)
#endif
#ifndef HIBYTE
#define HIBYTE(_w) (((_w) >> 8) & 0xff)
#endif
#ifndef HIDWORD
#define HIDWORD(_qw) ((uint32)((_qw) >> 32))
#endif
#ifndef LODWORD
#define LODWORD(_qw) ((uint32)(_qw))
#endif
#define QWORD(_hi, _lo) ((((uint64)(_hi)) << 32) | ((uint32)(_lo)))
/*
* Deposit a field _src at _pos bits from the right,
* with a length of _len, into the integer _target.
*/
#define DEPOSIT_BITS(_src,_pos,_len,_target) { \
unsigned mask = ((1 << _len) - 1); \
unsigned shiftedmask = ((1 << _len) - 1) << _pos; \
_target = (_target & ~shiftedmask) | ((_src & mask) << _pos); \
}
/*
* Get return address.
*/
#ifdef _MSC_VER
#ifdef __cplusplus
extern "C"
#endif
void *_ReturnAddress(void);
#pragma intrinsic(_ReturnAddress)
#define GetReturnAddress() _ReturnAddress()
#elif __GNUC__
#define GetReturnAddress() __builtin_return_address(0)
#endif
#ifdef __GNUC__
#ifndef sun
/*
* A bug in __builtin_frame_address was discovered in gcc 4.1.1, and
* fixed in 4.2.0; assume it originated in 4.0. PR 147638 and 554369.
*/
#if !(__GNUC__ == 4 && (__GNUC_MINOR__ == 0 || __GNUC_MINOR__ == 1))
#define GetFrameAddr() __builtin_frame_address(0)
#endif
#endif // sun
#endif // __GNUC__
/*
* Data prefetch was added in gcc 3.1.1
* http://www.gnu.org/software/gcc/gcc-3.1/changes.html
*/
#ifdef __GNUC__
# if ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 1) || \
(__GNUC__ == 3 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ >= 1))
# define PREFETCH_R(var) __builtin_prefetch((var), 0 /* read */, \
3 /* high temporal locality */)
# define PREFETCH_W(var) __builtin_prefetch((var), 1 /* write */, \
3 /* high temporal locality */)
# else
# define PREFETCH_R(var) ((void)(var))
# define PREFETCH_W(var) ((void)(var))
# endif
#endif /* __GNUC__ */
#ifdef USERLEVEL // {
/*
* Note this might be a problem on NT b/c while sched_yield guarantees it
* moves you to the end of your priority list, Sleep(0) offers no such
* guarantee. Bummer. --Jeremy.
*/
#if defined(N_PLAT_NLM)
/* We do not have YIELD() as we do not need it yet... */
#elif defined(_WIN32)
# define YIELD() Sleep(0)
#elif defined(VMKERNEL)
/* We don't have a YIELD macro in the vmkernel */
#else
# include <sched.h> // For sched_yield. Don't ask. --Jeremy.
# define YIELD() sched_yield()
#endif
/*
* Standardize some Posix names on Windows.
*/
#ifdef _WIN32 // {
#define snprintf _snprintf
#define strtok_r strtok_s
#if (_MSC_VER < 1500)
#define vsnprintf _vsnprintf
#endif
typedef int uid_t;
typedef int gid_t;
static INLINE void
sleep(unsigned int sec)
{
Sleep(sec * 1000);
}
static INLINE int
usleep(unsigned long usec)
{
Sleep(CEILING(usec, 1000));
return 0;
}
typedef int pid_t;
#define F_OK 0
#define X_OK 1
#define W_OK 2
#define R_OK 4
#endif // }
/*
* Macro for username comparison.
*/
#ifdef _WIN32 // {
#define USERCMP(x,y) Str_Strcasecmp(x,y)
#else
#define USERCMP(x,y) strcmp(x,y)
#endif // }
#endif // }
#ifndef va_copy
#ifdef _WIN32
/*
* Windows needs va_copy. This works for both 32 and 64-bit Windows
* based on inspection of how varags.h from the Visual C CRTL is
* implemented. (Future versions of the RTL may break this).
*/
#define va_copy(dest, src) ((dest) = (src))
#elif defined(__APPLE__) && defined(KERNEL)
#include "availabilityMacOS.h"
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
// The Mac OS 10.5 kernel SDK defines va_copy in stdarg.h.
#include <stdarg.h>
#else
/*
* The Mac OS 10.4 kernel SDK needs va_copy. Based on inspection of
* stdarg.h from the MacOSX10.4u.sdk kernel framework, this should
* work.
*/
#define va_copy(dest, src) ((dest) = (src))
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
#elif defined(__GNUC__) && (__GNUC__ < 3)
/*
* Old versions of gcc recognize __va_copy, but not va_copy.
*/
#define va_copy(dest, src) __va_copy(dest, src)
#endif // _WIN32
#endif // va_copy
/*
* This one is outside USERLEVEL because it's used by
* files compiled into the Windows hgfs driver or the display
* driver.
*/
#ifdef _WIN32
#define PATH_MAX 256
#ifndef strcasecmp
#define strcasecmp(_s1,_s2) _stricmp((_s1),(_s2))
#endif
#ifndef strncasecmp
#define strncasecmp(_s1,_s2,_n) _strnicmp((_s1),(_s2),(_n))
#endif
#endif
#if defined __linux__ && !defined __KERNEL__ && !defined MODULE && \
!defined VMM && !defined FROBOS && !defined __ANDROID__
#include <features.h>
#if __GLIBC_PREREQ(2, 1) && !defined GLIBC_VERSION_21
#define GLIBC_VERSION_21
#endif
#if __GLIBC_PREREQ(2, 2) && !defined GLIBC_VERSION_22
#define GLIBC_VERSION_22
#endif
#if __GLIBC_PREREQ(2, 3) && !defined GLIBC_VERSION_23
#define GLIBC_VERSION_23
#endif
#if __GLIBC_PREREQ(2, 4) && !defined GLIBC_VERSION_24
#define GLIBC_VERSION_24
#endif
#if __GLIBC_PREREQ(2, 5) && !defined GLIBC_VERSION_25
#define GLIBC_VERSION_25
#endif
#if __GLIBC_PREREQ(2, 12) && !defined GLIBC_VERSION_212
#define GLIBC_VERSION_212
#endif
#endif
/*
* Convenience definitions of unicode characters.
*/
#ifndef UTF8_ELLIPSIS
#define UTF8_ELLIPSIS "\xe2\x80\xa6"
#endif
/*
* Convenience macros and definitions. Can often be used instead of #ifdef.
*/
#undef ARM64_ONLY
#ifdef VM_ARM_64
#define ARM64_ONLY(x) x
#else
#define ARM64_ONLY(x)
#endif
#undef X86_ONLY
#ifdef VM_X86_ANY
#define X86_ONLY(x) x
#else
#define X86_ONLY(x)
#endif
#undef DEBUG_ONLY
#ifdef VMX86_DEBUG
#define vmx86_debug 1
#define DEBUG_ONLY(x) x
#else
#define vmx86_debug 0
#define DEBUG_ONLY(x)
#endif
#ifdef VMX86_STATS
#define vmx86_stats 1
#define STATS_ONLY(x) x
#else
#define vmx86_stats 0
#define STATS_ONLY(x)
#endif
#ifdef VMX86_DEVEL
#define vmx86_devel 1
#define DEVEL_ONLY(x) x
#else
#define vmx86_devel 0
#define DEVEL_ONLY(x)
#endif
#ifdef VMX86_LOG
#define vmx86_log 1
#define LOG_ONLY(x) x
#else
#define vmx86_log 0
#define LOG_ONLY(x)
#endif
#ifdef VMX86_BETA
#define vmx86_beta 1
#define BETA_ONLY(x) x
#else
#define vmx86_beta 0
#define BETA_ONLY(x)
#endif
#ifdef VMX86_RELEASE
#define vmx86_release 1
#define RELEASE_ONLY(x) x
#else
#define vmx86_release 0
#define RELEASE_ONLY(x)
#endif
#ifdef VMX86_SERVER
#define vmx86_server 1
#define SERVER_ONLY(x) x
#define HOSTED_ONLY(x)
#else
#define vmx86_server 0
#define SERVER_ONLY(x)
#define HOSTED_ONLY(x) x
#endif
#ifdef VMKERNEL
#define vmkernel 1
#define VMKERNEL_ONLY(x) x
#else
#define vmkernel 0
#define VMKERNEL_ONLY(x)
#endif
#ifdef _WIN32
#define WIN32_ONLY(x) x
#define POSIX_ONLY(x)
#define vmx86_win32 1
#else
#define WIN32_ONLY(x)
#define POSIX_ONLY(x) x
#define vmx86_win32 0
#endif
#ifdef __linux__
#define vmx86_linux 1
#define LINUX_ONLY(x) x
#else
#define vmx86_linux 0
#define LINUX_ONLY(x)
#endif
#ifdef __APPLE__
#define vmx86_apple 1
#define APPLE_ONLY(x) x
#else
#define vmx86_apple 0
#define APPLE_ONLY(x)
#endif
#ifdef VMM
#define VMM_ONLY(x) x
#define USER_ONLY(x)
#else
#define VMM_ONLY(x)
#define USER_ONLY(x) x
#endif
/* VMVISOR ifdef only allowed in the vmkernel */
#ifdef VMKERNEL
#ifdef VMVISOR
#define vmvisor 1
#define VMVISOR_ONLY(x) x
#else
#define vmvisor 0
#define VMVISOR_ONLY(x)
#endif
#endif
#ifdef _WIN32
#define VMW_INVALID_HANDLE INVALID_HANDLE_VALUE
#else
#define VMW_INVALID_HANDLE (-1LL)
#endif
#ifdef _WIN32
#define fsync(fd) _commit(fd)
#define fileno(f) _fileno(f)
#else
#endif
/*
* Debug output macros for Windows drivers (the Eng variant is for
* display/printer drivers only.
*/
#ifdef _WIN32
#ifndef USES_OLD_WINDDK
#if defined(VMX86_LOG)
#ifdef _WIN64
#define WinDrvPrint(arg, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, (ULONG)~0, arg, __VA_ARGS__)
#else
#define WinDrvPrint(arg, ...) DbgPrint(arg, __VA_ARGS__)
#endif
#define WinDrvEngPrint(arg, ...) EngDbgPrint(arg, __VA_ARGS__)
#else
#define WinDrvPrint(arg, ...)
#define WinDrvEngPrint(arg, ...)
#endif
#endif
#endif // _WIN32
#ifdef HOSTED_LG_PG
#define hosted_lg_pg 1
#else
#define hosted_lg_pg 0
#endif
/*
* Use to initialize cbSize for this structure to preserve < Vista
* compatibility.
*/
#define NONCLIENTMETRICSINFO_V1_SIZE CCSIZEOF_STRUCT(NONCLIENTMETRICS, \
lfMessageFont)
/* This is not intended to be thread-safe. */
#define DO_ONCE(code) \
do { \
static Bool _doOnceDone = FALSE; \
if (UNLIKELY(!_doOnceDone)) { \
_doOnceDone = TRUE; \
code; \
} \
} while (0)
/*
* Bug 827422 and 838523.
*/
#if defined __GNUC__ && __GNUC__ >= 4
#define VISIBILITY_HIDDEN __attribute__((visibility("hidden")))
#else
#define VISIBILITY_HIDDEN /* nothing */
#endif
/*
* Bitfield extraction.
*/
#define EXTRACT_BITSLICE32(_val , _lsb, _msb) \
(((uint32)(_val) << (31 - (_msb))) >> ((31 - (_msb)) + (_lsb)))
#define EXTRACT_BITFIELD32(_val, _pos, _len) \
EXTRACT_BITSLICE32((_val), (_pos), ((_pos) + (_len) - 1))
#define EXTRACT_BITSLICE64(_val, _lsb, _msb) \
(((uint64)(_val) << (63 - (_msb))) >> ((63 - (_msb)) + (_lsb)))
#define EXTRACT_BITFIELD64(_val, _pos, _len) \
EXTRACT_BITSLICE64((_val), (_pos), ((_pos) + (_len) - 1))
/*
* Typical cache line size. Use this for aligning structures to cache
* lines for performance, but do not rely on it for correctness.
*
* On x86, all current processors newer than P4 have 64-byte lines,
* but P4 had 128.
*
* On ARM, the line size can vary between cores. 64-byte lines are
* common, but either larger or smaller powers of two are possible.
*/
#define CACHELINE_SIZE 64
#define CACHELINE_SHIFT 6
#define CACHELINE_ALIGNMENT_MASK (CACHELINE_SIZE - 1)
/*
* Bits to bytes sizes.
*/
#define SIZE_8BIT 1
#define SIZE_16BIT 2
#define SIZE_24BIT 3
#define SIZE_32BIT 4
#define SIZE_48BIT 6
#define SIZE_64BIT 8
#define SIZE_80BIT 10
#define SIZE_128BIT 16
#define SIZE_256BIT 32
#endif // ifndef _VM_BASIC_DEFS_H_
+166
View File
@@ -0,0 +1,166 @@
/*********************************************************
* Copyright (C) 2008-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
*
*********************************************************/
/*
* vm_basic_math.h --
*
* Standard mathematical macros for VMware source code.
*/
#ifndef _VM_BASIC_MATH_H_
#define _VM_BASIC_MATH_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMKDRIVERS
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "vm_basic_types.h" // For INLINE.
#include "vm_basic_asm.h" // For Div64...
static INLINE uint32
RatioOf(uint32 numer1, uint32 numer2, uint32 denom)
{
uint64 numer = (uint64)numer1 * numer2;
/* Calculate "(numer1 * numer2) / denom" avoiding round-off errors. */
#if defined(VMM) || !(defined(__i386__) || defined(__x86_64__))
return numer / denom;
#else
uint32 ratio;
uint32 unused;
Div643232(numer, denom, &ratio, &unused);
return ratio;
#endif
}
static INLINE uint32
ExponentialAvg(uint32 avg, uint32 value, uint32 gainNumer, uint32 gainDenom)
{
uint32 term1 = gainNumer * avg;
uint32 term2 = (gainDenom - gainNumer) * value;
return (term1 + term2) / gainDenom;
}
static INLINE Bool
IsPowerOfTwo(uint32 x)
{
/* Does not check for zero. Callers depend on this. */
return !(x & (x - 1));
}
static INLINE uint32
GetPowerOfTwo(uint32 x)
{
/* Returns next-greatest power-of-two. */
uint32 power2 = 1;
while (x > power2) {
power2 = power2 << 1;
}
return power2;
}
#if !defined(_WIN32) && !defined(_WIN64)
/*
*-----------------------------------------------------------------------------
*
* RotateLeft32 --
*
* Results:
* Value rotated to the left by 'shift' bits.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
static INLINE uint32
RotateLeft32(uint32 value, uint8 shift)
{
return ((value << shift) | (value >> (32 - shift)));
}
/*
*-----------------------------------------------------------------------------
*
* RotateRight32 --
*
* Results:
* Value rotated to the right by 'shift' bits.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
static INLINE uint32
RotateRight32(uint32 value, uint8 shift)
{
return ((value >> shift) | (value << (32 - shift)));
}
/*
*-----------------------------------------------------------------------------
*
* RotateLeft64 --
*
* Results:
* Value rotated to the left by 'shift' bits.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
static INLINE uint64
RotateLeft64(uint64 value, uint8 shift)
{
return ((value << shift) | (value >> (64 - shift)));
}
/*
*-----------------------------------------------------------------------------
*
* RotateRight64 --
*
* Results:
* Value rotated to the right by 'shift' bits.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
static INLINE uint64
RotateRight64(uint64 value, uint8 shift)
{
return ((value >> shift) | (value << (64 - shift)));
}
#endif // if !defined(_WIN32) && !defined(_WIN64)
#endif // ifndef _VM_BASIC_MATH_H_
File diff suppressed because it is too large. Load diff
+55
View File
@@ -0,0 +1,55 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/*
* vm_time.h --
*
* Time management functions.
* Part of driver-only distribution
*
* see comment in poll.c
*/
#ifndef VM_TIME_H
#define VM_TIME_H
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
struct VmTimeVirtualRealClock;
typedef struct VmTimeVirtualRealClock VmTimeVirtualRealClock;
#ifdef USERLEVEL
VmTimeType VmTime_ReadVirtualTime(void);
VmTimeVirtualRealClock *VmTime_NewVirtualRealClock(void);
void VmTime_StartVirtualRealClock(VmTimeVirtualRealClock *, double);
void VmTime_ResetVirtualRealClock(VmTimeVirtualRealClock *);
VmTimeType VmTime_ReadVirtualRealTime(VmTimeVirtualRealClock *);
VmTimeType VmTime_RemainingVirtualRealTime(VmTimeVirtualRealClock *,
VmTimeType realTime);
void VmTime_UpdateVirtualRealTime(VmTimeVirtualRealClock *clock,
VmTimeType realTime,
VmTimeType virtualTime);
#endif
#endif /* VM_TIME_H */
+48
View File
@@ -0,0 +1,48 @@
/*********************************************************
* 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
* 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
*
*********************************************************/
/* Do not include inline functions, typedefs or other such
* nonsense here. This file is for _constants_.
*/
#ifndef _VMM_CONSTANTS_H_
#define _VMM_CONSTANTS_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#include "includeCheck.h"
#define INTERRUPT_REDIRECTION_BITMAP_SIZE 32
#define IO_PERMISSION_BITMAP_SIZE 0
#define VMM_PANIC_NONE 0
#define VMM_PANIC_MSG_COPYING 1
#define VMM_PANIC_MSG_COPIED 2
#define VMM_PANIC_COREDUMPING 3
#define VMM_PANIC_VCPU 4
#define VMM_PANIC_MSG_SIZE 256
#define VMM_CPL0_STACK 1
#define VMM_CPL1_STACK 2
#endif
+108
View File
@@ -0,0 +1,108 @@
/*********************************************************
* Copyright (C) 2000-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
*
*********************************************************/
/*
* vmmem_shared.h --
*
* This is the header file for machine memory manager.
*/
#ifndef _VMMEM_SHARED_H
#define _VMMEM_SHARED_H
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMX
#include "includeCheck.h"
/*
* Page remapping definitions.
*/
#define VMMEM_FLAG_BIT(x) (1 << (x))
#define VMMEM_ANON_LOW_MEM VMMEM_FLAG_BIT(0)
#define VMMEM_ANON_LARGE_PAGE VMMEM_FLAG_BIT(1)
#define VMMEM_ANON_CAN_FAIL VMMEM_FLAG_BIT(2)
#define VMMEM_ANON_USE_PREALLOC VMMEM_FLAG_BIT(3)
#define VMMEM_ANON_IOABLE_PAGE VMMEM_FLAG_BIT(4)
#define VMMEM_ANON_ALL_FLAGS MASK(5)
#define VMMEM_GUEST_WRITEABLE VMMEM_FLAG_BIT(0)
#define VMMEM_GUEST_BREAKCOW VMMEM_FLAG_BIT(1)
#define VMMEM_GUEST_LARGE_PAGE VMMEM_FLAG_BIT(2)
#define VMMEM_GUEST_CAN_FAIL VMMEM_FLAG_BIT(3)
#define VMMEM_GUEST_TEST_ZEROCOW VMMEM_FLAG_BIT(4)
#define VMMEM_GUEST_TRY_ZEROCOW VMMEM_FLAG_BIT(5)
#define VMMEM_GUEST_TRY_POISONCOW VMMEM_FLAG_BIT(6)
#define VMMEM_GUEST_PREALLOC VMMEM_FLAG_BIT(7)
#define VMMEM_GUEST_ALL_FLAGS MASK(8)
#define VMMEM_GUEST_TRY_COW (VMMEM_GUEST_TEST_ZEROCOW | \
VMMEM_GUEST_TRY_ZEROCOW | \
VMMEM_GUEST_TRY_POISONCOW)
#define VMMEM_PLATFORM_CHECK_OK VMMEM_FLAG_BIT(0)
#define VMMEM_PLATFORM_KEY_OK VMMEM_FLAG_BIT(1)
#define VMMEM_PLATFORM_COW VMMEM_FLAG_BIT(2)
#define VMMEM_PLATFORM_EXPOSED_TO_VMM VMMEM_FLAG_BIT(3)
#define VMMEM_PLATFORM_P2M_UPDATE_PENDING VMMEM_FLAG_BIT(4)
#define VMMEM_PLATFORM_TRY_COW_SUCCESS VMMEM_FLAG_BIT(5)
#define VMMEM_PLATFORM_DIRTY VMMEM_FLAG_BIT(6)
#define VMMEM_PLATFORM_BACKED_LARGE VMMEM_FLAG_BIT(7)
#define VMMEM_PLATFORM_LARGE_RETRY VMMEM_FLAG_BIT(8)
#define MAX_PLATFORM_PAGE_INFO_PAGES 240
/*
* Structure used to query platform about the page state.
*/
typedef struct PlatformPageInfoList {
uint32 numPages;
uint32 _pad;
BPN bpn[MAX_PLATFORM_PAGE_INFO_PAGES]; // bpns to check
MPN mpn[MAX_PLATFORM_PAGE_INFO_PAGES]; // filled in by host
uint8 flags[MAX_PLATFORM_PAGE_INFO_PAGES]; // filled in by host
} PlatformPageInfoList;
#define VMMEM_SERVICES_TYPE_2_MASK(type) \
(1 << type)
#define VMMEM_SERVICES_IN_MASK(typeMask, type) \
(VMMEM_SERVICES_TYPE_2_MASK(type) & typeMask)
#define VMMEM_SERVICES_CLEAR_MASK(typeMask, type) \
(typeMask & ~VMMEM_SERVICES_TYPE_2_MASK(type))
#define VMMEM_SERVICES_DEFS \
MDEF(VMMEM_SERVICES_TYPE_P2M, P2MUpdate_FilterPages) \
MDEF(VMMEM_SERVICES_TYPE_SWAP, BusMemSwap_FilterPages)
#define MDEF(_type, _cb) _type,
typedef enum VmMemServices_Type {
VMMEM_SERVICES_DEFS
#undef MDEF
VMMEM_SERVICES_TYPE_MAX
} VmMemServices_Type;
#define VMMEM_SERVICES_TYPE_INVALID (VMMEM_SERVICES_TYPE_MAX)
void VmMem_DisableLargePageAllocations(void);
void VmMem_EnableLargePageAllocations(void);
#endif
+57
View File
@@ -0,0 +1,57 @@
/*********************************************************
* 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
* 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.h --
*
* Standard include file for VMware source code.
*/
#ifndef _VMWARE_H_
#define _VMWARE_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#include "includeCheck.h"
#include "vm_basic_types.h"
#include "vm_basic_defs.h"
#include "vm_assert.h"
/*
* Global error codes. Currently used internally, but may be exported
* to customers one day, like VM_E_XXX in vmcontrol_constants.h
*/
typedef enum VMwareStatus {
VMWARE_STATUS_SUCCESS, /* success */
VMWARE_STATUS_ERROR, /* generic error */
VMWARE_STATUS_NOMEM, /* generic memory allocation error */
VMWARE_STATUS_INSUFFICIENT_RESOURCES, /* internal or system resource limit exceeded */
VMWARE_STATUS_INVALID_ARGS /* invalid arguments */
} VMwareStatus;
#define VMWARE_SUCCESS(s) ((s) == VMWARE_STATUS_SUCCESS)
#endif // ifndef _VMWARE_H_
+43
View File
@@ -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
+44
View File
@@ -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
+65
View File
@@ -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__ */
+242
View File
@@ -0,0 +1,242 @@
/*********************************************************
* Copyright (C) 2006-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
* 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
*
*********************************************************/
/*
* x86_basic_defs.h --
*
* Basic macros describing the x86 architecture.
*/
#ifndef _X86_BASIC_DEFS_H_
#define _X86_BASIC_DEFS_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#define X86_MAX_INSTR_LEN 15 /* Max byte length of an x86 instruction. */
#define NUM_IDT_VECTORS 256
/*
* control registers
*/
#define CR0_PE 0x00000001
#define CR0_MP 0x00000002
#define CR0_EM 0x00000004
#define CR0_TS 0x00000008
#define CR0_ET 0x00000010
#define CR0_NE 0x00000020
#define CR0_WP 0x00010000
#define CR0_AM 0x00040000
#define CR0_NW 0x20000000
#define CR0_CD 0x40000000
#define CR0_PG 0x80000000
#define CR0_RESERVED CONST64U(0xffffffff1ffaffc0)
#define CR3_PWT 0x00000008
#define CR3_PCD 0x00000010
#define CR3_PDB_SHIFT 12
#define CR3_PDB_MASK 0xfffff000
#define CR3_IGNORE 0xFFF
#define PAE_CR3_IGNORE 0x1F
#define CR3_PCID_MASK 0xFFF
#define CR3_NO_FLUSH (1ULL << 63)
#define CR4_VME 0x00000001
#define CR4_PVI 0x00000002
#define CR4_TSD 0x00000004
#define CR4_DE 0x00000008
#define CR4_PSE 0x00000010
#define CR4_PAE 0x00000020
#define CR4_MCE 0x00000040
#define CR4_PGE 0x00000080
#define CR4_PCE 0x00000100
#define CR4_OSFXSR 0x00000200 // CPU/OS supports SIMD insts
#define CR4_OSXMMEXCPT 0x00000400 // #XF exception enable PIII only
#define CR4_VMXE 0x00002000
#define CR4_SMXE 0x00004000
#define CR4_FSGSBASE 0x00010000
#define CR4_PCIDE 0x00020000
#define CR4_OSXSAVE 0x00040000
#define CR4_SMEP 0x00100000
#define CR4_SMAP 0x00200000
/* Removing a bit from CR4_RESERVED causes Task_Switch to leave the bit set. */
#define CR4_RESERVED CONST64U(0xffffffffffc89800)
#define CR8_RESERVED CONST64U(0xfffffffffffffff0)
/*
* Debug registers.
*/
#define DR_COUNT 4
#define DR6_B0 0x00000001
#define DR6_B1 0x00000002
#define DR6_B2 0x00000004
#define DR6_B3 0x00000008
#define DR6_B0123 (DR6_B0 | DR6_B1 | DR6_B2 | DR6_B3)
#define DR6_B(_n) (1 << (_n))
#define DR6_BD 0x00002000
#define DR6_BS 0x00004000
#define DR6_BT 0x00008000
#define DR6_RTM 0x00010000
#define DR6_ONES 0xfffe0ff0
#define DR6_DEFAULT (DR6_ONES | DR6_RTM)
#define DR6_RESERVED_MASK 0xfffe1ff0
#define DR7_L_MASK(_n) (1 << ((_n) * 2))
#define DR7_G_MASK(_n) (1 << ((_n) * 2 + 1))
#define DR7_LG_MASK(_n) (3 << ((_n) * 2))
#define DR7_RW_MASK(_n) (3 << (16 + (_n) * 4))
#define DR7_LEN_MASK(_n) (3 << (18 + (_n) * 4))
#define DR7_BP_MASK(_n) (DR7_L_MASK(_n) |\
DR7_G_MASK(_n) |\
DR7_RW_MASK(_n) |\
DR7_LEN_MASK(_n))
#define DR7_L0 DR7_L_MASK(0)
#define DR7_G0 DR7_G_MASK(0)
#define DR7_L1 DR7_L_MASK(1)
#define DR7_G1 DR7_G_MASK(1)
#define DR7_L2 DR7_L_MASK(2)
#define DR7_G2 DR7_G_MASK(2)
#define DR7_L3 DR7_L_MASK(3)
#define DR7_G3 DR7_G_MASK(3)
#define DR7_ENABLED 0x000000ff
#define DR7_LE 0x00000100 // Deprecated in modern hardware
#define DR7_GE 0x00000200 // Deprecated in modern hardware
#define DR7_GD 0x00002000
#define DR7_ONES 0x00000400
#define DR7_RTM 0x00000800
#define DR7_RESERVED CONST64U(0xffffffff0000d400)
#define DR7_DEFUNCT (DR7_LE | DR7_GE)
#define DR7_DEFAULT DR7_ONES
#define DR7_LX_MASK (DR7_L0 | DR7_L1 | DR7_L2 | DR7_L3 | DR7_LE)
#define DR7_GX_MASK (DR7_G0 | DR7_G1 | DR7_G2 | DR7_G3 | DR7_GE)
#define DR7_LGX_MASK (DR7_LX_MASK | DR7_GX_MASK)
#define DR7_RW(_r,_n) (((_r) >> (16+(_n)*4)) & 0x3)
#define DR7_L(_r,_n) (((_r) >> ((_n)*2)) & 1)
#define DR7_G(_r,_n) (((_r) >> (1 + (_n)*2)) & 1)
#define DR7_LEN(_r,_n) (((_r) >> (18+(_n)*4)) & 0x3)
#define DR7_RW_BITS(_n,_rw) ((_rw) << (16 + (_n) * 4))
#define DR7_LEN_BITS(_n,_len) ((_len) << (18 + (_n) * 4))
#define DR7_RW_INST 0x0
#define DR7_RW_WRITES 0x1
#define DR7_RW_IO 0x2
#define DR7_RW_ACCESS 0x3
#define DR7_LENGTH_1 0x0
#define DR7_LENGTH_2 0x1
#define DR7_LENGTH_8 0x2
#define DR7_LENGTH_4 0x3
#define DEBUG_STATUS_B0 (1<<0)
#define DEBUG_STATUS_B1 (1<<1)
#define DEBUG_STATUS_B2 (1<<2)
#define DEBUG_STATUS_B3 (1<<3)
#define DEBUG_STATUS_DB (1<<13)
#define DEBUG_STATUS_BS (1<<14)
#define DEBUG_STATUS_BT (1<<15)
/*
* exception error codes
*/
#define EXC_DE 0
#define EXC_DB 1
#define EXC_NMI 2
#define EXC_BP 3
#define EXC_OF 4
#define EXC_BR 5
#define EXC_UD 6
#define EXC_NM 7
#define EXC_DF 8
#define EXC_TS 10
#define EXC_NP 11
#define EXC_SS 12
#define EXC_GP 13
#define EXC_PF 14
#define EXC_MF 16
#define EXC_AC 17
#define EXC_MC 18
#define EXC_XF 19 /* SIMD exception. */
#define EXC_SX 30 /* Security exception (SVM only). */
/*
* eflag/rflag definitions.
*/
#define EFLAGS_IOPL_SHIFT 12
typedef enum x86_FLAGS {
EFLAGS_NONE = 0,
EFLAGS_CF = (1 << 0), /* User */
EFLAGS_SET = (1 << 1),
EFLAGS_PF = (1 << 2), /* User */
EFLAGS_AF = (1 << 4), /* User */
EFLAGS_ZF = (1 << 6), /* User */
EFLAGS_SF = (1 << 7), /* User */
EFLAGS_TF = (1 << 8), /* Priv */
EFLAGS_IF = (1 << 9), /* Priv */
EFLAGS_DF = (1 << 10), /* User */
EFLAGS_OF = (1 << 11), /* User */
EFLAGS_NT = (1 << 14), /* Priv */
EFLAGS_RF = (1 << 16), /* Priv */
EFLAGS_VM = (1 << 17), /* Priv */
EFLAGS_AC = (1 << 18), /* Priv */
EFLAGS_VIF = (1 << 19), /* Priv */
EFLAGS_VIP = (1 << 20), /* Priv */
EFLAGS_ID = (1 << 21), /* Priv */
EFLAGS_IOPL = 3 << EFLAGS_IOPL_SHIFT,
EFLAGS_ARITH = (EFLAGS_CF | EFLAGS_PF | EFLAGS_AF | EFLAGS_ZF |
EFLAGS_SF | EFLAGS_OF),
EFLAGS_USER = (EFLAGS_CF | EFLAGS_PF | EFLAGS_AF | EFLAGS_ZF |
EFLAGS_SF | EFLAGS_DF | EFLAGS_OF),
EFLAGS_PRIV = (EFLAGS_TF | EFLAGS_IF | EFLAGS_IOPL | EFLAGS_NT |
EFLAGS_RF | EFLAGS_VM | EFLAGS_AC | EFLAGS_VIF |
EFLAGS_VIP | EFLAGS_ID),
EFLAGS_ALL = (EFLAGS_CF | EFLAGS_PF | EFLAGS_AF | EFLAGS_ZF |
EFLAGS_SF | EFLAGS_DF | EFLAGS_OF | EFLAGS_TF |
EFLAGS_IF | EFLAGS_IOPL | EFLAGS_NT | EFLAGS_RF |
EFLAGS_VM | EFLAGS_AC | EFLAGS_VIF | EFLAGS_VIP |
EFLAGS_ID),
EFLAGS_ALL_16 = EFLAGS_ALL & 0xffff,
EFLAGS_REAL_32 = (EFLAGS_ALL & ~(EFLAGS_VIP | EFLAGS_VIF | EFLAGS_VM)),
EFLAGS_V8086_32 = (EFLAGS_ALL & ~(EFLAGS_VIP | EFLAGS_VIF |
EFLAGS_VM | EFLAGS_IOPL)),
EFLAGS_REAL_16 = EFLAGS_REAL_32 & 0xffff,
EFLAGS_V8086_16 = EFLAGS_V8086_32 & 0xffff,
EFLAGS_CLEAR_ON_EXC = (EFLAGS_TF | EFLAGS_VM | EFLAGS_RF | EFLAGS_NT),
EFLAGS__4 = 0x7fffffff /* ensure 4 byte encoding */
} x86_FLAGS;
#endif // ifndef _VM_BASIC_DEFS_H_
+353
View File
@@ -0,0 +1,353 @@
/*********************************************************
* 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
* 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 _X86APIC_H_
#define _X86APIC_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
/*
* This file describes all the APIC/IOAPIC register locations and formats
* that are defined by the x86 architecture.
*/
/*
* APIC registers
*/
#define APIC_DEFAULT_ADDRESS 0xfee00000
#define APIC_ADDRESS_ALIGNMENT 4096
#define APIC_ADDRESS_MASK (APIC_ADDRESS_ALIGNMENT-1)
#define APIC_VERSION_0x11 0x11
#define XAPIC_VERSION_0x14 0x14
#define X2APIC_VERSION_0x15 0x15
#define APIC_MAXLVT_0x4 0x4
#define XAPIC_MAXLVT_0x5 0x5
#define APIC_VERSION_MASK 0xff
#define APIC_MAX_LVT_MASK 0xff
#define APIC_MAX_LVT_SHIFT 16
#define APIC_EXTAPICSPACE_MASK 0x80000000
#define APIC_INVALID_ID 0xff
#define X2APIC_INVALID_ID 0xffffffff
#define APICR_ID 0x02
#define APICR_VERSION 0x03
#define APICR_TPR 0x08
#define APICR_APR 0x09
#define APICR_PPR 0x0a
#define APICR_EOI 0x0b
#define APICR_RMTREAD 0x0c
#define APICR_LDR 0x0d
#define APICR_DFR 0x0e
#define APICR_SVR 0x0f
#define APICR_ISR 0x10
#define APICR_TMR 0x18
#define APICR_IRR 0x20
#define APICR_ESR 0x28
#define APICR_CMCILVT 0x2f
#define APICR_ICRLO 0x30
#define APICR_ICRHI 0x31
#define APICR_TIMERLVT 0x32
#define APICR_THERMLVT 0x33
#define APICR_PCLVT 0x34
#define APICR_LVT0 0x35
#define APICR_LVT1 0x36
#define APICR_ERRLVT 0x37
#define APICR_INITCNT 0x38
#define APICR_CURCNT 0x39
#define APICR_DIVIDER 0x3e
#define APICR_SELFIPI 0x3f // X2 APIC only
#define APICR_EXTFEATURE 0x40
#define APICR_EXTLVT 0x50
#define X2APIC_READONLY_BITMASK \
((CONST64U(1) << APICR_ID) | (CONST64U(1) << APICR_VERSION) | \
(CONST64U(1) << APICR_APR) | (CONST64U(1) << APICR_PPR) | \
(CONST64U(1) << APICR_CURCNT) | (CONST64U(1) << APICR_ICRHI) | \
(CONST64U(1) << APICR_LDR) | (CONST64U(1) << APICR_DFR) | \
(MASK64(8) << APICR_ISR) | (MASK64(8) << APICR_IRR) | \
(MASK64(8) << APICR_TMR))
#define APICR_SIZE 0x540
#define APIC_TPR_RESERVED 0xffffff00
#define APIC_PR_MASK 0x000000ff
#define APIC_PR_XMASK 0x000000f0
#define APIC_PR_YMASK 0x0000000f
#define APIC_PR_X(_r) (((_r) & APIC_PR_XMASK) >> 4)
#define APIC_PR_Y(_r) (((_r) & APIC_PR_YMASK) >> 0)
#define APIC_SVR_ONES 0x0000000f
#define APIC_SVR_VECTOR 0x000000ff
#define APIC_SVR_APICENABLE 0x00000100
#define APIC_SVR_FOCUSCHECK 0x00000200
#define APIC_SVR_X2_RESERVED 0xffffee00
#define APIC_LVT_MASK 0x10000
#define APIC_LVT_DELVMODE_NMI 0x400
#define APIC_LVT_DELVMODE(_lvt) (_lvt & 0x700)
#define APIC_LVT_RESET_VALUE 0x00010000
#define APIC_LVT_TIMER_RESERVED 0xfff8ef00
#define APIC_LVT_ERROR_RESERVED 0xfffeef00
#define APIC_LVT_LINT_RESERVED 0xfffe0800
#define APIC_LVT_OTHER_RESERVED 0xfffee800 // CMCI, PC, THERM LVTs
#define APIC_EXTFEATURE_DEFAULT 0x00040004
#define APIC_EXTLVT_DEFAULT 0x00010000
/*
* Use APIC_MSR_BASEMASK as mask only for reading the MSR_APIC_BASE.
* Use VMCORESHARED->reservedAPIC as mask when writing MSR_APIC_BASE.
*/
#define APIC_MSR_BASEMASK CONST64U(0x0000fffffffff000)
#define APIC_MSR_X2APIC_ENABLED 0x00000400
#define APIC_MSR_ENABLED 0x00000800
#define APIC_MSR_BSP 0x00000100
#define APIC_VTE_VECTOR_MASK 0x000000ff
#define APIC_VTE_MODE_FIXED 0x00000000
#define APIC_VTE_MODE_SMI 0x00000200
#define APIC_VTE_MODE_NMI 0x00000400
#define APIC_VTE_MODE_EXTINT 0x00000700
#define APIC_VTE_MODE_MASK 0x00000700
#define APIC_VTE_DELVSTATUS 0x00001000
#define APIC_VTE_PINPOL 0x00002000
#define APIC_VTE_REMIRR 0x00004000
#define APIC_VTE_TRIGMODE 0x00008000
#define APIC_VTE_MASK 0x00010000
#define APIC_VTE_TMR_ONESHOT 0x00000000
#define APIC_VTE_TMR_PERIODIC 0x00020000
#define APIC_VTE_TMR_TSC_DEADLINE 0x00040000
#define APIC_VTE_TMR_MODE_MASK 0x00070000
/*
* Kernels 2.4.0-test8 and higher have the definition
* APIC_ID_MASK, so we use APIC_ID_BITS to avoid naming conflicts.
*/
#define APIC_ID_BITS 0x0f000000
#define XAPIC_ID_BITS 0xff000000
#define XAPIC_ID_MASK 0xff000000
#define X2APIC_ID_BITS 0xffffffff
#define APIC_ID_SHIFT 24
#define APIC_LDR_BITS 0xff000000
#define APIC_LDR_SHIFT 24
#define APIC_DIVIDER_BY_1 0x0000000b
#define APIC_DIVIDER_RESERVED 0xfffffff4
/* APIC illegal vectors */
#define APIC_MIN_LEGAL_VECTOR 16
/* APIC delivery modes */
#define APIC_DELMODE_FIXED 0
#define APIC_DELMODE_LOWEST 1
#define APIC_DELMODE_SMI 2
#define APIC_DELMODE_RSVD 3
#define APIC_DELMODE_NMI 4
#define APIC_DELMODE_INIT 5
#define APIC_DELMODE_STARTUP 6
#define APIC_DELMODE_EXTINT 7
/* APIC destination modes */
#define APIC_DESTMODE_PHYS 0
#define APIC_DESTMODE_LOGICAL 1
/* APIC polarities (active high/low) */
#define APIC_POLARITY_HIGH 0
#define APIC_POLARITY_LOW 1
/* APIC trigger types (edge/level) */
#define APIC_TRIGGER_EDGE 0
#define APIC_TRIGGER_LEVEL 1
/* APIC destination shorthands */
#define APIC_DEST_DEST 0
#define APIC_DEST_LOCAL 1
#define APIC_DEST_ALL_INC 2
#define APIC_DEST_ALL_EXC 3
/* APIC physical mode broadcasts */
#define APIC_DEST_BROADCAST 0x0f
#define XAPIC_DEST_BROADCAST 0xff
#define X2APIC_DEST_BROADCAST 0xffffffff
/* APIC IPI Command Register format */
#define APIC_ICRHI_RESERVED 0x00ffffff
#define APIC_ICRHI_DEST_MASK 0xff000000
#define APIC_ICRHI_DEST_OFFSET 24
#define X2APIC_ICR_DEST_OFFSET 32
#define APIC_ICRLO_RESERVED 0xfff32000
#define APIC_ICRLO_DEST_MASK 0x000c0000
#define APIC_ICRLO_DEST_OFFSET 18
#define APIC_ICRLO_TRIGGER_MASK 0x00008000
#define APIC_ICRLO_TRIGGER_OFFSET 15
#define APIC_ICRLO_LEVEL_MASK 0x00004000
#define APIC_ICRLO_LEVEL_OFFSET 14
#define APIC_ICRLO_STATUS_MASK 0x00001000
#define APIC_ICRLO_STATUS_OFFSET 12
#define APIC_ICRLO_DESTMODE_MASK 0x00000800
#define APIC_ICRLO_DESTMODE_OFFSET 11
#define APIC_ICRLO_DELMODE_MASK 0x00000700
#define APIC_ICRLO_DELMODE_OFFSET 8
#define APIC_ICRLO_VECTOR_MASK 0x000000ff
#define APIC_ICRLO_VECTOR_OFFSET 0
/* x2APIC Logical ID fields */
#define X2APIC_LDR_BITVEC_MASK 0x0000ffff
#define X2APIC_LDR_CLUSTER_MASK 0xffff0000
#define X2APIC_LDR_CLUSTER_SHIFT 16
/* APIC error register bits */
#define APIC_ERR_ILL_REG (1<<7)
#define APIC_REC_ILL_VEC (1<<6)
#define APIC_SENT_ILL_VEC (1<<5)
#define APIC_ERR_REDIR_IPI (1<<4) // X2APIC
#define X2APIC_SELFIPI_RESERVED 0xffffff00
/*
* APIC register accessors
*/
#define APIC_VERSION_REG(_apic) (_apic[APICR_VERSION][0])
#define APIC_MAX_LVT(_apic) ((APIC_VERSION_REG(_apic) >> \
APIC_MAX_LVT_SHIFT) & APIC_MAX_LVT_MASK)
#define APIC_LVT_ISMASKED(_lvt) (_lvt & APIC_LVT_MASK)
#define APIC_LVT_VECTOR(_lvt) (_lvt & 0xff)
#define APIC_SPINT_REG(_apic) (_apic[APICR_SVR][0])
#define APIC_TIMER_REG(_apic) (_apic[APICR_TIMERLVT][0])
#define APIC_THERM_REG(_apic) (_apic[APICR_THERMLVT][0])
#define APIC_PC_REG(_apic) (_apic[APICR_PCLVT][0])
#define APIC_LINT0_REG(_apic) (_apic[APICR_LVT0][0])
#define APIC_LINT1_REG(_apic) (_apic[APICR_LVT1][0])
#define APIC_ERR_REG(_apic) (_apic[APICR_ERRLVT][0])
#define APIC_INITCNT_REG(_apic) (_apic[APICR_INITCNT][0])
#define APIC_CURCNT_REG(_apic) (_apic[APICR_CURCNT][0])
#define APIC_SPINT_VECTOR(_apic) (APIC_SPINT_REG(_apic) & 0xff)
#define APIC_TIMER_VECTOR(_apic) (APIC_TIMER_REG(_apic) & 0xff)
#define APIC_PC_VECTOR(_apic) (APIC_PC_REG(_apic) & 0xff)
#define APIC_LINT0_VECTOR(_apic) (APIC_LINT0_REG(_apic) & 0xff)
#define APIC_LINT1_VECTOR(_apic) (APIC_LINT1_REG(_apic) & 0xff)
#define APIC_ERR_VECTOR(_apic) (APIC_ERR_REG(_apic) & 0xff)
/*
* I/O APIC registers
*/
#define IOAPIC_DEFAULT_ADDRESS 0xfec00000
#define IOAPIC_ADDRESS_ALIGNMENT 1024
#define IOAPIC_ADDRESS_MASK (IOAPIC_ADDRESS_ALIGNMENT-1)
#define IOAPIC_UVERSIONMASK 0xff
#define IOAPICID 0x00
#define IOAPICVER 0x01
#define IOAPICARB 0x02
#define IOREDTBL_FIRST 0x10
#define IOREDTBL_LAST 0x3f
#define IO_APIC_TIMER_PIN 2
#define IO_APIC_RTC_PIN 8
#define IO_APIC_REG0_RES2_MASK 0x00FFFFFF
#define IO_APIC_REG0_RES2_OFFSET 0
#define IO_APIC_REG0_RES1_MASK 0xF0000000
#define IO_APIC_REG0_RES1_OFFSET 28
#define IO_APIC_REG1_VERSION_MASK 0x000000FF
#define IO_APIC_REG1_VERSION_OFFSET 0
#define IO_APIC_REG1_RES2_MASK 0x0000FF00
#define IO_APIC_REG1_RES2_OFFSET 8
#define IO_APIC_REG1_ENTRIES_MASK 0x00FF0000
#define IO_APIC_REG1_ENTRIES_OFFSET 16
#define IO_APIC_REG1_RES1_MASK 0xFF000000
#define IO_APIC_REG1_RES1_OFFSET 24
#define IO_APIC_REG2_RES1_MASK 0x00FFFFFF
#define IO_APIC_REG2_RES1_OFFSET 0
#define IO_APIC_REG2_RES2_MASK 0xF0000000
#define IO_APIC_REG2_RES2_OFFSET 28
#define IO_APIC_ROUTE_VECTOR_MASK 0x000000FF
#define IO_APIC_ROUTE_VECTOR_OFFSET 0
#define IO_APIC_INTMASK_MASK 0x00010000
#define IO_APIC_INTMASK_OFFSET 16
#define IO_APIC_DELMODE_MASK 0x00000700
#define IO_APIC_DELMODE_OFFSET 8
#define IO_APIC_DESTMODE_MASK 0x00000800
#define IO_APIC_DESTMODE_OFFSET 11
#define IO_APIC_POLARITY_MASK 0x00002000
#define IO_APIC_POLARITY_OFFSET 13
#define IO_APIC_TRIGGER_MASK 0x00008000
#define IO_APIC_TRIGGER_OFFSET 15
#define IO_APIC_DEST_MASK 0xff000000
#define IO_APIC_DEST_OFFSET 24
#define IO_APIC_REG0_RES1(_reg) \
((_reg & IO_APIC_REG0_RES1_MASK) >> IO_APIC_REG0_RES1_OFFSET)
#define IO_APIC_REG0_RES2(_reg) \
((_reg & IO_APIC_REG0_RES2_MASK) >> IO_APIC_REG0_RES2_OFFSET)
#define IO_APIC_REG1_RES1(_reg) \
((_reg & IO_APIC_REG1_RES1_MASK) >> IO_APIC_REG1_RES1_OFFSET)
#define IO_APIC_REG1_RES2(_reg) \
((_reg & IO_APIC_REG1_RES2_MASK) >> IO_APIC_REG1_RES2_OFFSET)
#define IO_APIC_REG2_RES1(_reg) \
((_reg & IO_APIC_REG2_RES1_MASK) >> IO_APIC_REG2_RES1_OFFSET)
#define IO_APIC_REG2_RES2(_reg) \
((_reg & IO_APIC_REG2_RES2_MASK) >> IO_APIC_REG2_RES2_OFFSET)
#define IO_APIC_VERSION(_reg) \
((_reg & IO_APIC_REG1_VERSION_MASK) >> IO_APIC_REG1_VERSION_OFFSET)
#define IO_APIC_ENTRIES(_reg) \
((_reg & IO_APIC_REG1_ENTRIES_MASK) >> IO_APIC_REG1_ENTRIES_OFFSET)
#define IO_APIC_ENTRY_VECTOR(_entry) \
((_entry & IO_APIC_ROUTE_VECTOR_MASK) >> IO_APIC_ROUTE_VECTOR_OFFSET)
#define IO_APIC_ISMASKED(_entry) \
((_entry & IO_APIC_INTMASK_MASK) >> IO_APIC_INTMASK_OFFSET)
#define IO_APIC_ENTRY_DELMODE(_entry) \
((_entry & IO_APIC_DELMODE_MASK) >> IO_APIC_DELMODE_OFFSET)
#define IO_APIC_ENTRY_DESTMODE(_entry) \
((_entry & IO_APIC_DESTMODE_MASK) >> IO_APIC_DESTMODE_OFFSET)
#define IO_APIC_ENTRY_POLARITY(_entry) \
((_entry & IO_APIC_POLARITY_MASK) >> IO_APIC_POLARITY_OFFSET)
#define IO_APIC_ENTRY_TRIGGER(_entry) \
((_entry & IO_APIC_TRIGGER_MASK) >> IO_APIC_TRIGGER_OFFSET)
#define IO_APIC_ENTRY_DEST(_entry) \
((_entry & IO_APIC_DEST_MASK) >> IO_APIC_DEST_OFFSET)
//
// We emulate an IOAPIC with 24 redirection registers
//
#define IOAPIC_NUM_REDIR_REGS 24
#endif // _X86APIC_H_
File diff suppressed because it is too large. Load diff
Loaded 100 of 175 files, more files were not shown because too many files have changed in this diff. Show more