Compare commits

...
165 changed files with 70444 additions and 0 deletions

No files matched your search

+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.
+140
View File
@@ -0,0 +1,140 @@
#!/usr/bin/make -f
##########################################################
# 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
#
##########################################################
####
#### 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)
# 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
#
# 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:
+37
View File
@@ -0,0 +1,37 @@
#!/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)
obj-m += $(DRIVER).o
$(DRIVER)-y := $(subst $(SRCROOT)/, , $(patsubst %.c, %.o, \
$(wildcard $(SRCROOT)/linux/*.c $(SRCROOT)/common/*.c $(SRCROOT)/vmcore/*.c \
$(SRCROOT)/bootstrap/*.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/ bootstrap/ \
./,$(addprefix $(dir),.*.cmd .*.o.flags *.o)))
+151
View File
@@ -0,0 +1,151 @@
#!/usr/bin/make -f
##########################################################
# Copyright (C) 1998,2015,2017 VMware, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# 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')
C_TARGETS_LINUX := driver.o hostif.o driverLog.o
C_TARGETS_COMMON := vmx86.o memtrack.o phystrack.o cpuid.o task.o
C_TARGETS_VMCORE := moduleloop.o
C_TARGETS_BOOTSTRAP := bootstrap.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_BOOTSTRAP_D := ${C_TARGETS_BOOTSTRAP:.o=.d}
C_TARGETS := $(C_TARGETS_LINUX) $(C_TARGETS_COMMON) $(C_TARGETS_VMCORE) \
$(C_TARGETS_BOOTSTRAP)
####
#### 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 $<
$(C_TARGETS_BOOTSTRAP): %.o: $(SRCROOT)/bootstrap/%.c
$(ECHO) "Compiling bootstrap/$(<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) $< > $@
$(C_TARGETS_BOOTSTRAP_D): %.d: $(SRCROOT)/bootstrap/%.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
+53
View File
@@ -0,0 +1,53 @@
/*********************************************************
* 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
*
*********************************************************/
/*
* bootstrap.c --
*
* Implements the early VMM bootstraping code that is executed
* by the host (vmmon/VMKernel) to create the VMM context.
*/
#include "vm_basic_types.h"
#include "vm_basic_defs.h"
#include "bootstrap_vmm.h"
/*
*---------------------------------------------------------------------
*
* BSVMM_Validate --
*
* Validates the VMM bootstrap blob. For now, we do it by checking
* the magic number. Returns the bootstrap parameter table if
* successful, NULL otherwise.
*
*---------------------------------------------------------------------
*/
BSVMM_HostParams *
BSVMM_Validate(void *buf, uint32 nbytes)
{
BSVMM_HostParams *bsParams = buf;
if (nbytes < sizeof *bsParams) {
return NULL;
}
if (bsParams->magic != BOOTSTRAP_MAGIC) {
return NULL;
}
return bsParams;
}
File diff suppressed because it is too large. Load diff
+546
View File
@@ -0,0 +1,546 @@
/*********************************************************
* Copyright (C) 2016-2018 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
*
*********************************************************/
/*
* monLoaderVmmon.c --
*
* vmmon implementation of the MonLoader callouts.
*
*/
#ifdef __linux__
# include "driver-config.h"
# include <linux/string.h>
#else
# include <string.h>
#endif
#include "vm_assert.h"
#include "vcpuid.h"
#include "x86types.h"
#include "hostif.h"
#include "x86paging_common.h"
#include "x86paging_64.h"
#include "vmx86.h"
#include "monLoader.h"
#include "monLoaderLog.h"
#include "vmmblob.h"
#include "memtrack.h"
typedef struct MonLoaderEnvContext {
VMDriver *vm;
VMSharedRegion *shRegions;
} MonLoaderEnvContext;
/*
*----------------------------------------------------------------------
*
* MonLoaderCallout_Init --
*
* Initializes platform-specific MonLoader context.
*
* Returns:
* TRUE if successful, FALSE if not.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Bool
MonLoaderCallout_Init(void *args, MonLoaderEnvContext **ctx)
{
MonLoaderEnvContext *c;
MonLoaderArgs *mlArgs = (MonLoaderArgs *)args;
c = HostIF_AllocKernelMem(sizeof *c, FALSE);
if (c == NULL) {
Log("Failed to allocate memory for MonLoader context\n");
return FALSE;
}
memset(c, 0, sizeof *c);
c->vm = mlArgs->vm;
c->shRegions = mlArgs->shRegions;
*ctx = c;
return TRUE;
}
/*
*----------------------------------------------------------------------
*
* MonLoaderCallout_Cleanup --
*
* Cleans up platform-specific MonLoader context.
*
* Returns:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
MonLoaderCallout_CleanUp(MonLoaderEnvContext *ctx)
{
ASSERT(ctx != NULL);
Vmx86_CleanupVMMPages(ctx->vm);
HostIF_FreeKernelMem(ctx);
}
/*
*----------------------------------------------------------------------
*
* MonLoaderCallout_GetPageRoot --
*
* Gets the page root MPN for a VCPU.
*
* Returns:
* An MPN, or INVALID_MPN in case of error.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
MPN
MonLoaderCallout_GetPageRoot(MonLoaderEnvContext *ctx, // IN
Vcpuid vcpu) // IN
{
VMDriver *vm = ctx->vm;
if (vcpu >= vm->numVCPUs) {
return INVALID_MPN;
}
return vm->ptRootMpns[vcpu];
}
/*
*----------------------------------------------------------------------
*
* MonLoaderCallout_GetPTE --
*
* Gets the page table entry at index idx in a page table MPN.
*
* Returns:
* TRUE and sets *pte on success. FALSE otherwise.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Bool
MonLoaderCallout_GetPTE(MonLoaderEnvContext *ctx, // IN
MPN ptMPN, // IN
unsigned idx, // IN
Vcpuid vcpu, // IN
PT_L1E *pte) // OUT
{
VMDriver *vm = ctx->vm;
MA pteMA = MPN_2_MA(ptMPN) + idx * sizeof *pte;
ASSERT(idx < (PAGE_SIZE / sizeof *pte));
if (HostIF_ReadPhysical(vm, pteMA, PtrToVA64(pte), TRUE, sizeof *pte) != 0) {
Log("Failed to read PTE %d from MPN %"FMT64"x\n", idx, ptMPN);
return FALSE;
}
return TRUE;
}
Bool
MonLoaderCallout_ImportPage(MonLoaderEnvContext *ctx, // IN
MPN mpn, // IN
Vcpuid vcpu) // IN
{
return TRUE;
}
/*
*----------------------------------------------------------------------
*
* MonLoaderCallout_AllocMPN --
*
* Allocates and maps a new VMM page for the specified VCPU.
*
* Returns:
* An MPN on success, INVALID_MPN on failure.
*
* Side effects:
* The allocated page is accounted for and its mapping tracked.
*
*----------------------------------------------------------------------
*/
MPN
MonLoaderCallout_AllocMPN(MonLoaderEnvContext *ctx, // IN
Vcpuid vcpu) // IN
{
VMDriver *vm = ctx->vm;
MemTrackEntry *entry;
MPN mpn;
VPN vpn;
if (Vmx86_AllocLockedPages(vm, (VA64)&mpn, 1, TRUE, FALSE) != 1) {
Log("Failed to allocate page\n");
return INVALID_MPN;
}
vpn = Vmx86_MapPage(mpn);
if (vpn == 0) {
Log("Failed to map MPN 0x%"FMT64"x\n", mpn);
Vmx86_FreeLockedPages(vm, (VA64)&mpn, 1, TRUE);
return INVALID_MPN;
}
HostIF_VMLock(vm, 41);
entry = MemTrack_Add(vm->vmmTracker, vpn, mpn);
HostIF_VMUnlock(vm, 41);
if (entry == NULL) {
Log("Failed to track mapping from VPN 0x%"FMTVPN"x to MPN 0x%"FMT64"x\n",
vpn, mpn);
Vmx86_UnmapPage(vpn);
Vmx86_FreeLockedPages(vm, (VA64)&mpn, 1, TRUE);
return INVALID_MPN;
}
return mpn;
}
/*
*----------------------------------------------------------------------
*
* MonLoaderCallout_MapMPNInPTE --
*
* Maps an MPN into a page table at the specified index.
*
* Returns:
* TRUE on success, FALSE on failure.
*
* Side effects:
* A mapping is created.
*
*----------------------------------------------------------------------
*/
Bool
MonLoaderCallout_MapMPNInPTE(MonLoaderEnvContext *ctx, // IN
MPN ptMPN, // IN
unsigned idx, // IN
uint64 flags, // IN
MPN mpn, // IN
Vcpuid vcpu) // IN
{
VMDriver *vm = ctx->vm;
PT_L1E pte = LM_MAKE_PTE(mpn, 0, flags);
MA pteMA = MPN_2_MA(ptMPN) + idx * sizeof pte;
ASSERT(idx < (PAGE_SIZE / sizeof pte));
if (HostIF_WritePhysical(vm, pteMA, PtrToVA64(&pte), TRUE, sizeof pte) !=
0) {
Warning("Failed to map MPN %"FMT64"x\n", mpn);
return FALSE;
}
LOG(5, "MonLoader mapped MPN %"FMT64"x at PT index %u for VCPU %u\n",
mpn, idx, vcpu);
return TRUE;
}
/*
*----------------------------------------------------------------------
*
* MonLoaderCallout_FillPage --
*
* Fills a page with a pattern, given the MPN of the page.
*
* Returns:
* TRUE on success, FALSE if a mapping of the page was not found or
* invalid.
*
* Side effects:
* The page is filled.
*
*----------------------------------------------------------------------
*/
Bool
MonLoaderCallout_FillPage(MonLoaderEnvContext *ctx, // IN
uint8 pattern, // IN
MPN mpn, // IN
Vcpuid vcpu) // IN
{
VMDriver *vm = ctx->vm;
MemTrackEntry *entry;
HostIF_VMLock(vm, 42);
entry = MemTrack_LookupMPN(vm->vmmTracker, mpn);
HostIF_VMUnlock(vm, 42);
if (entry == NULL || entry->mpn != mpn || entry->vpn == 0) {
Log("Failed to look up MPN 0x%"FMT64"x\n", mpn);
return FALSE;
}
memset((void *)VPN_2_VA(entry->vpn), pattern, PAGE_SIZE);
return TRUE;
}
/*
*----------------------------------------------------------------------
*
* MonLoaderCallout_CopyFromBlob --
*
* Copies contents of up to PAGE_SIZE length from the blob at a
* given offset into the page specified by the given MPN. Zero-fills
* the remaining space.
*
* Returns:
* TRUE on success, FALSE on failure.
*
* Side effects:
* The page is filled with blob contents.
*
*----------------------------------------------------------------------
*/
Bool
MonLoaderCallout_CopyFromBlob(MonLoaderEnvContext *ctx, // IN
uint64 blobOffset, // IN
size_t copySize, // IN
MPN mpn, // IN
Vcpuid vcpu) // IN
{
MemTrackEntry *entry;
VMDriver *vm = ctx->vm;
uint64 blobSize = VmmBlob_GetSize(vm);
uint8 *blob = VmmBlob_GetPtr(vm);
uint8 *buf;
if (copySize > PAGE_SIZE || copySize == 0 || blobSize < copySize ||
blobOffset > blobSize - copySize) {
Log("Invalid VMM blob copy parameters: blobOffset 0x%"FMT64"x, "
"copySize 0x%"FMTSZ"x, blobSize 0x%"FMT64"x\n", blobOffset, copySize,
blobSize);
return FALSE;
}
HostIF_VMLock(vm, 44);
entry = MemTrack_LookupMPN(vm->vmmTracker, mpn);
HostIF_VMUnlock(vm, 44);
if (entry == NULL || entry->vpn == 0) {
Log("Failed to look up MPN 0x%"FMT64"x\n", mpn);
return FALSE;
}
buf = (uint8 *)VPN_2_VA(entry->vpn);
memcpy(buf, blob + blobOffset, copySize);
memset(buf + copySize, 0, PAGE_SIZE - copySize);
return TRUE;
}
/*
*----------------------------------------------------------------------
*
* MonLoaderFindSharedRegion --
*
* Searches the shared region table for the given index and returns
* the corresponding descriptor.
*
* Returns:
* A pointer to the shared region descriptor or NULL if not found.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static VMSharedRegion *
MonLoaderFindSharedRegion(MonLoaderEnvContext *ctx,
uint64 index)
{
int i;
for (i = 0; i < ML_SHARED_REGIONS_MAX; i++) {
if (ctx->shRegions[i].baseVpn == INVALID_VPN) {
/* Not found. */
return NULL;
} else if (ctx->shRegions[i].index == index) {
return &ctx->shRegions[i];
}
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* MonLoaderGetSharedRegionMPN --
*
* Gets shared page's MPN. Assumes vcpuid == 0 for the bootstrap.
*
* Returns:
* An MPN or INVALID_MPN.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static MPN
MonLoaderGetSharedRegionMPN(MonLoaderEnvContext *ctx,
uint64 index,
Vcpuid vcpuid,
unsigned pgOffset)
{
VMSharedRegion *s;
VA addr;
MPN mpn;
ASSERT(IS_BOOT_VCPUID(vcpuid));
if (index >= ML_SHARED_REGIONS_MAX) {
Log("Invalid shared region %"FMT64"x", index);
return INVALID_MPN;
}
s = MonLoaderFindSharedRegion(ctx, index);
if (s == NULL) {
return INVALID_MPN;
}
if (pgOffset >= s->numPages) {
return INVALID_MPN;
}
addr = VPN_2_VA(s->baseVpn) + pgOffset * PAGE_SIZE;
HostIF_VMLock(ctx->vm, 43);
if (HostIF_LookupUserMPN(ctx->vm, addr, &mpn) != PAGE_LOOKUP_SUCCESS) {
HostIF_VMUnlock(ctx->vm, 43);
Log("Failed to lookup MPN for shared region VA %"FMTVA"x\n", addr);
return INVALID_MPN;
}
HostIF_VMUnlock(ctx->vm, 43);
return mpn;
}
/*
*----------------------------------------------------------------------
*
* MonLoaderCallout_GetSharedUserPage --
*
* Gets a user-provided shared page's MPN for a VCPU.
*
* Returns:
* An MPN or INVALID_MPN.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
MPN
MonLoaderCallout_GetSharedUserPage(MonLoaderEnvContext *ctx,
uint64 subIndex, // IN
unsigned page, // IN
Vcpuid vcpu) // IN
{
if (subIndex == MONLOADER_HEADER_IDX) {
return VmmBlob_GetHeaderMpn(ctx->vm);
} else {
return MonLoaderGetSharedRegionMPN(ctx, subIndex, vcpu, page);
}
}
MPN
MonLoaderCallout_GetSharedHostPage(MonLoaderEnvContext *ctx, // IN
uint64 subIndex, // IN
unsigned page, // IN
Vcpuid vcpu) // IN
{
NOT_IMPLEMENTED();
}
/*
*----------------------------------------------------------------------
*
* MonLoaderCallout_IsPrivileged --
*
* Returns whether or not this is a privileged environment.
*
* Returns:
* TRUE if privileged, FALSE if not.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Bool
MonLoaderCallout_IsPrivileged(MonLoaderEnvContext *ctx) // IN
{
return TRUE;
}
/*
*----------------------------------------------------------------------
*
* MonLoaderCallout_GetBlobMpn --
*
* Returns the MPN backing the given VMM blob offset.
*
* Returns:
* An MPN, or INVALID_MPN
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
MPN
MonLoaderCallout_GetBlobMpn(MonLoaderEnvContext *ctx, // IN
uint64 offset) // IN
{
ASSERT((offset & (PAGE_SIZE - 1)) == 0);
return VmmBlob_GetMpn(ctx->vm, BYTES_2_PAGES(offset));
}
Bool
MonLoaderCallout_SetEntrypoint(MonLoaderEnvContext *ctx, // IN
uint16 codeSelector, // IN
VA64 code, // IN
uint16 stackSelector, // IN
VA64 stack) // IN
{
NOT_IMPLEMENTED();
}
+230
View File
@@ -0,0 +1,230 @@
/*********************************************************
* Copyright (C) 2017-2018 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
*
*********************************************************/
/*
* vmmblob.c --
*
* VMM blob management.
*/
#ifdef __linux__
# include "driver-config.h"
#endif
#include "vmware.h"
#include "vm_assert.h"
#include "hostif.h"
#include "vmmblob.h"
#include "monLoader.h"
#define VMMBLOB_SIZE_MAX (12 * 1024 * 1024)
/*
*----------------------------------------------------------------------
*
* VmmBlob_GetPtr --
*
* Returns a pointer to the buffer containing the VMM blob.
*
* Results:
* A pointer.
*
*----------------------------------------------------------------------
*/
uint8 *
VmmBlob_GetPtr(VMDriver *vm)
{
return vm->blobInfo->blobPtr;
}
/*
*----------------------------------------------------------------------
*
* VmmBlob_GetSize --
*
* Returns the size of the VMM blob in bytes.
*
* Results:
* Number of bytes.
*
*----------------------------------------------------------------------
*/
uint64
VmmBlob_GetSize(VMDriver *vm)
{
return vm->blobInfo->numBytes;
}
/*
*----------------------------------------------------------------------
*
* VmmBlob_GetMpn --
*
* Returns the MPN backing a VMM blob page.
*
* Results:
* An MPN, or INVALID_MPN.
*
*----------------------------------------------------------------------
*/
MPN
VmmBlob_GetMpn(VMDriver *vm, uint64 pgOffset)
{
VmmBlobInfo *bi = vm->blobInfo;
uint32 blobNumPages = CEILING(bi->numBytes, PAGE_SIZE);
MPN mpn = INVALID_MPN;
if (pgOffset < blobNumPages) {
mpn = bi->mpns[pgOffset];
}
return mpn;
}
/*
*----------------------------------------------------------------------
*
* VmmBlob_GetHeaderMpn --
*
* Returns the MPN backing the MonLoader header.
*
* Results:
* An MPN, or INVALID_MPN.
*
*----------------------------------------------------------------------
*/
MPN
VmmBlob_GetHeaderMpn(VMDriver *vm)
{
VmmBlobInfo *bi = vm->blobInfo;
uint64 headerOffset = (uint8 *)bi->header - (uint8 *)bi->blobPtr;
ASSERT((headerOffset & (PAGE_SIZE - 1)) == 0);
return VmmBlob_GetMpn(vm, BYTES_2_PAGES(headerOffset));
}
/*
*----------------------------------------------------------------------
*
* VmmBlob_Cleanup --
*
* Cleans up VMM blob state by freeing its memory and associated
* metadata.
*
* Results:
* None.
*
*----------------------------------------------------------------------
*/
void
VmmBlob_Cleanup(VmmBlobInfo *bi)
{
const uint32 numPages = CEILING(bi->numBytes, PAGE_SIZE);
HostIF_FreeKernelPages(numPages, bi->blobPtr);
HostIF_FreeKernelMem(bi->mpns);
HostIF_FreeKernelMem(bi);
}
/*
*----------------------------------------------------------------------
*
* VmmBlob_Load --
*
* Copies and instantiates a VMM bootstrap blob from userspace.
*
* Results:
* TRUE if successful, FALSE if not.
*
*----------------------------------------------------------------------
*/
Bool
VmmBlob_Load(UserVA64 blobAddr,
uint32 numBytes,
uint32 headerOffset,
VmmBlobInfo **blobInfo)
{
uint8 *blob = NULL;
MPN *mpns = NULL;
MonLoaderHeader *header;
VmmBlobInfo *bi = NULL;
uint32 numPages = CEILING(numBytes, PAGE_SIZE);
size_t fixedHdrSize = MonLoader_GetFixedHeaderSize();
if (numBytes > VMMBLOB_SIZE_MAX || headerOffset > numBytes ||
fixedHdrSize > numBytes - headerOffset) {
Warning("Invalid arguments for processing bootstrap. "
"Header offset: %u, Fixed header size: %"FMTSZ"u bytes, "
"Blob size: %u bytes\n", headerOffset, fixedHdrSize, numBytes);
goto error;
}
mpns = HostIF_AllocKernelMem(numPages * sizeof(*mpns), FALSE);
if (mpns == NULL) {
Warning("Memory allocation for VMM bootstrap blob failed\n");
goto error;
}
bi = HostIF_AllocKernelMem(sizeof *bi, FALSE);
if (bi == NULL) {
Warning("Memory allocation for VMM bootstrap blob failed\n");
goto error;
}
blob = HostIF_AllocKernelPages(numPages, mpns);
if (blob == NULL) {
Warning("Memory allocation for VMM bootstrap blob failed\n");
goto error;
}
if (HostIF_CopyFromUser(blob, blobAddr, numBytes) != 0) {
Warning("Error copying VMM bootstrap blob from userspace\n");
goto error;
}
header = (MonLoaderHeader *)(blob + headerOffset);
if (header->count > (numBytes - headerOffset - fixedHdrSize) /
sizeof (MonLoaderEntry)) {
Warning("Invalid arguments for processing bootstrap. "
"Header offset: %u, Number of header entries: %u, "
"Blob size: %u bytes\n", headerOffset, header->count, numBytes);
goto error;
}
bi->mpns = mpns;
bi->blobPtr = blob;
bi->numBytes = numBytes;
bi->header = header;
*blobInfo = bi;
return TRUE;
error:
if (blob != NULL) {
HostIF_FreeKernelPages(numPages, blob);
}
if (bi != NULL) {
HostIF_FreeKernelMem(bi);
}
if (mpns != NULL) {
HostIF_FreeKernelMem(mpns);
}
return FALSE;
}
+278
View File
@@ -0,0 +1,278 @@
/*********************************************************
* Copyright (C) 2011, 2016, 2018 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 "x86apic.h"
#include "x86msr.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_HYGON) {
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 and Hygon, high bits are explicitly MBZ, so no need.
*/
if (cpuVendor == CPUID_VENDOR_INTEL) {
/*
* Intel suggests using CPUID 0x80000008.eax[7-0] (physical
* address size), with 36 (24 bit MPNs) as a fallback.
*/
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
+151
View File
@@ -0,0 +1,151 @@
/*********************************************************
* Copyright (C) 1998, 2016-2018 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"
#include "x86svm.h"
#include "x86vt.h"
uint32 cpuidFeatures;
CpuidVendor cpuidVendor = CPUID_NUM_VENDORS;
uint32 cpuidVersion;
Bool hostSupportsVT;
Bool hostSupportsSVM;
Bool hostHasSpecCtrl;
/*
*-----------------------------------------------------------------------------
*
* 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);
cpuidVersion = 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) {
cpuidVendor = CPUID_VENDOR_INTEL;
} else if (strcmp(name, CPUID_AMD_VENDOR_STRING_FIXED) == 0) {
cpuidVendor = CPUID_VENDOR_AMD;
} else if (strcmp(name, CPUID_CYRIX_VENDOR_STRING_FIXED) == 0) {
cpuidVendor = CPUID_VENDOR_CYRIX;
} else if (strcmp(name, CPUID_HYGON_VENDOR_STRING_FIXED) == 0) {
cpuidVendor = CPUID_VENDOR_HYGON;
} else {
Warning("VMMON CPUID: Unrecognized CPU\n");
cpuidVendor = CPUID_VENDOR_UNKNOWN;
}
__GET_CPUID2(7, 0, &regs);
hostHasSpecCtrl = cpuidVendor == CPUID_VENDOR_INTEL &&
(CPUID_ISSET(7, EDX, IBRSIBPB, regs.edx) ||
CPUID_ISSET(7, EDX, STIBP, regs.edx));
hostSupportsVT = VT_CapableCPU();
hostSupportsSVM = SVM_CapableCPU();
}
/*
*-----------------------------------------------------------------------------
*
* 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;
}
+93
View File
@@ -0,0 +1,93 @@
/*********************************************************
* Copyright (C) 1998, 2016-2018 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;
extern uint32 cpuidVersion;
extern CpuidVendor cpuidVendor;
extern Bool hostSupportsVT;
extern Bool hostSupportsSVM;
extern Bool hostHasSpecCtrl;
void CPUID_Init(void);
Bool CPUID_AddressSizeSupported(void);
static INLINE uint32
CPUID_GetFeatures(void)
{
return cpuidFeatures;
}
static INLINE CpuidVendor
CPUID_GetVendor(void)
{
ASSERT(cpuidVendor != CPUID_NUM_VENDORS);
return cpuidVendor;
}
static INLINE uint32
CPUID_GetVersion(void)
{
return cpuidVersion;
}
static INLINE Bool
CPUID_HostSupportsVT(void)
{
return hostSupportsVT;
}
static INLINE Bool
CPUID_HostSupportsSVM(void)
{
return hostSupportsSVM;
}
static INLINE Bool
CPUID_HostSupportsHV(void)
{
return hostSupportsVT || hostSupportsSVM;
}
static INLINE Bool
CPUID_HostSupportsSpecCtrl(void)
{
return hostHasSpecCtrl;
}
static INLINE Bool
CPUID_SSE2Supported(void)
{
return CPUID_ISSET(1, EDX, SSE2, CPUID_GetFeatures());
}
#endif
+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-2018 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
EXTERN int HostIF_Init(VMDriver *vm, uint32 numVCPUs);
EXTERN int HostIF_LookupUserMPN(VMDriver *vm, VA64 uAddr, MPN *mpn);
EXTERN void *HostIF_MapCrossPage(VMDriver *vm, VA64 uAddr);
EXTERN void *HostIF_AllocPage(void);
EXTERN void HostIF_FreePage(void *ptr);
EXTERN VPN HostIF_MapPage(MPN mpn);
EXTERN void HostIF_UnmapPage(VPN vpn);
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_AllocKernelPages(unsigned numPages, MPN *mpns);
EXTERN void HostIF_FreeKernelPages(unsigned numPages, void *ptr);
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 uint8 HostIF_GetMonitorIPIVector(void);
EXTERN uint8 HostIF_GetHVIPIVector(void);
EXTERN void HostIF_GetTimerVectors(uint8 *v0, uint8 *v1);
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 void HostIF_IPI(VMDriver *vm, const VCPUSet *vcs);
EXTERN void HostIF_OneIPI(VMDriver *vm, Vcpuid v);
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 MPN HostIF_AllocLowPage(VMDriver *vm);
EXTERN int HostIF_ReadPhysical(VMDriver *vm, MA ma, VA64 addr,
Bool kernelBuffer, size_t len);
EXTERN int HostIF_WritePhysical(VMDriver *vm, MA ma, VA64 addr,
Bool kernelBuffer, size_t len);
EXTERN int HostIF_WriteMachinePage(MPN mpn, VA64 addr);
#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);
EXTERN int HostIF_CopyFromUser(void *dst, VA64 src, size_t len);
EXTERN int HostIF_CopyToUser(VA64 dst, const void *src, size_t len);
#if defined __APPLE__
EXTERN void HostIF_PageUnitTest(void);
#endif
#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, 2008, 2018 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_
+561
View File
@@ -0,0 +1,561 @@
/*********************************************************
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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 "vmx86.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 {
VMDriver *vm; /* The VM instance. */
unsigned numPages; /* Number of pages tracked. */
MemTrackDir1 dir1; /* First level directory. */
MemTrackHT vpnHashTable; /* VPN to entry hashtable. */
MemTrackHT *mpnHashTable; /* MPN to entry hashtable. */
} 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;
Bool freeBackMap = mt != NULL && mt->mpnHashTable != NULL;
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 (freeBackMap) {
if (mt->mpnHashTable->pages[idx] != NULL) {
HostIF_FreePage(mt->mpnHashTable->pages[idx]);
}
}
}
if (freeBackMap) {
HostIF_FreeKernelMem(mt->mpnHashTable);
}
HostIF_FreeKernelMem(mt);
}
/*
*----------------------------------------------------------------------
*
* MemTrack_Init --
*
* Allocate and initialize the tracker.
*
* Results:
* Handle used to access the tracker.
*
* Side effects:
* Memory allocation.
*
*----------------------------------------------------------------------
*/
MemTrack *
MemTrack_Init(VMDriver *vm) // IN:
{
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);
mt->vm = vm;
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;
}
mt->mpnHashTable = HostIF_AllocKernelMem(sizeof *mt->mpnHashTable, FALSE);
if (mt->mpnHashTable == NULL) {
Warning("MemTrack failed to allocate MPN hash table.\n");
goto error;
}
memset(mt->mpnHashTable, 0, sizeof *mt->mpnHashTable);
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;
}
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);
ASSERT(HostIF_VMLockIsHeld(mt->vm));
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);
MemTrackHTInsert(mt->mpnHashTable, ent, &ent->mpnChain, ent->mpn);
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);
ASSERT(HostIF_VMLockIsHeld(mt->vm));
while (next != NULL) {
if (next->vpn == vpn) {
return next;
}
next = next->vpnChain;
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* 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;
ASSERT(HostIF_VMLockIsHeld(mt->vm));
next = *MemTrackHTLookup(mt->mpnHashTable, mpn);
while (next != NULL) {
if (next->mpn == mpn) {
return next;
}
next = next->mpnChain;
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* 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;
}
+52
View File
@@ -0,0 +1,52 @@
/*********************************************************
* Copyright (C) 1998,2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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 and optionally by MPN.
*/
#ifndef _MEMTRACK_H_
#define _MEMTRACK_H_
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
struct MemTrack;
typedef struct MemTrackEntry {
VPN64 vpn;
MPN mpn;
struct MemTrackEntry *vpnChain;
struct MemTrackEntry *mpnChain;
} MemTrackEntry;
typedef void (MemTrackCleanupCb)(void *cData, MemTrackEntry *entry);
extern struct MemTrack *MemTrack_Init(VMDriver *vm);
extern unsigned MemTrack_Cleanup(struct MemTrack *mt, MemTrackCleanupCb *cb,
void *cbData);
extern MemTrackEntry *MemTrack_Add(struct MemTrack *mt, VPN64 vpn, MPN mpn);
extern MemTrackEntry *MemTrack_LookupVPN(struct MemTrack *mt, VPN64 vpn);
extern MemTrackEntry *MemTrack_LookupMPN(struct MemTrack *mt, MPN mpn);
#endif // _MEMTRACK_H_
+492
View File
@@ -0,0 +1,492 @@
/*********************************************************
* Copyright (C) 1998,2014,2019 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 and Mac use 2-level structures
* ready to hold 128GB (32bit) or 2TB (64bit) of memory.
*
* 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(__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 (PHYSTRACK_MAX_SUPPORTED_GB * 8)
#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,2019 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 (__linux__)
/* 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
+41
View File
@@ -0,0 +1,41 @@
/*********************************************************
* Copyright (C) 1998-2013,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 TASK_H
#define TASK_H
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "bootstrap_vmm.h"
struct InitBlock;
extern Bool Task_CreateCrossGDT(BSVMM_GDTInit *gdt);
extern int Task_InitCrosspage(VMDriver *vm, struct InitBlock *params);
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);
extern void Task_SwitchPTPPageCleanup(VMDriver *vm);
#endif
File diff suppressed because it is too large. Load diff
+226
View File
@@ -0,0 +1,226 @@
/*********************************************************
* Copyright (C) 1998-2018 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"
#include "bootstrap_vmm.h"
typedef struct TSCDelta {
Atomic_uint64 min;
Atomic_uint64 max;
} TSCDelta;
struct VmmBlobInfo;
/*
* 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;
Vcpuid numVCPUs; /* Number of vcpus in VM. */
struct VMDriver *nextDriver; /* Next on list of all VMDrivers */
struct VMHost *vmhost; /* Host-specific fields. */
MPN *ptRootMpns; /* numVCPUs-sized array. */
struct VmmBlobInfo *blobInfo; /* VMM bootstrap blob info. */
/* Pointers to the crossover pages shared with the monitor. */
struct VMCrossPage **crosspage; /* numVCPUs-sized array. */
struct MemTrack *ptpTracker; /* Tracks page table patch pages */
struct MemTrack *vmmTracker; /* Tracks allocated VMM pages */
VCPUSet *crosscallWaitSet; /* numVCPUs-sized array. */
APICDescriptor hostAPIC;
struct MemTrack *memtracker; /* Memory tracker pointer */
Bool checkFuncFailed;
struct PerfCounter *perfCounter;
VMMemMgmtInfo memInfo;
unsigned fastClockRate; /* Protected by FastClockLock. */
Atomic_uint64 ptscOffsetInfo; /* Volatile per PR 699101#29. */
Atomic_uint64 ptscLatest;
int64 *ptscOffsets; /* numVCPUs-sized array. */
Atomic_uint32 *currentHostCpu; /* numVCPUs-sized array. */
} VMDriver;
typedef struct MonLoaderArgs {
VMDriver *vm;
VMSharedRegion *shRegions;
} MonLoaderArgs;
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 void Vmx86_CacheNXState(void);
extern VMDriver *Vmx86_CreateVM(VA64 bsBlob,
uint32 bsBlobSize,
uint32 numVCPUs);
extern Bool Vmx86_ProcessBootstrap(VMDriver *vm,
VA64 bsBlobAddr,
uint32 numBytes,
uint32 headerOffset,
uint16 numVCPUs,
UserVA64 *ptRootVAs,
VMSharedRegion *shRegions);
extern int Vmx86_LookupUserMPN(VMDriver *vm, VA64 uAddr, MPN *mpn);
extern int Vmx86_ReleaseVM(VMDriver *vm);
extern int Vmx86_InitVM(VMDriver *vm, InitBlock *initParams);
extern int Vmx86_LateInitVM(VMDriver *vm);
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 MPN Vmx86_AllocLowPage(VMDriver *vm, Bool ignoreLimits);
extern void *Vmx86_Calloc(size_t numElements,
size_t elementSize,
int nonPageable);
extern void Vmx86_Free(void *ptr);
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_GetAllMSRs(MSRQuery *query);
extern void Vmx86_FlushVMCSAllCPUs(MA vmcs);
extern void Vmx86_MonTimerIPI(void);
extern void Vmx86_InitIDList(void);
extern Bool Vmx86_GetPageRoot(VMDriver *vm, Vcpuid vcpuid, MPN *mpn);
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);
extern Bool Vmx86_GetMonitorContext(VMDriver *vm, Vcpuid vcpuid,
Context64 *context);
extern void Vmx86_CleanupVMMPages(VMDriver *vm);
extern VPN Vmx86_MapPage(MPN mpn);
extern void Vmx86_UnmapPage(VPN vpn);
#endif
+105
View File
@@ -0,0 +1,105 @@
/*********************************************************
* 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
#if defined __cplusplus
extern "C" {
#endif
/*
* 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;
}
#if defined __cplusplus
} // extern "C"
#endif
#endif // _ADDRESS_DEFS_H_
+61
View File
@@ -0,0 +1,61 @@
/*********************************************************
* Copyright (C) 2006-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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 MAX_VCPUS
typedef
#include "vmware_pack_begin.h"
struct InitBlock {
uint32 magicNumber; /* Magic number (INIT_BLOCK_MAGIC) */
uint32 vmInitFailurePeriod;
VA64 crosspage[MAX_INITBLOCK_CPUS];
LPN64 monStartLPN;
LPN64 monEndLPN;
MPN crossGDTMPN;
uint16 numPTPPages;
}
#include "vmware_pack_end.h"
InitBlock;
#endif // _BASIC_INITBLOCK_H_
+65
View File
@@ -0,0 +1,65 @@
/*********************************************************
* Copyright (C) 2015,2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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
*
*********************************************************/
/*
* bootstrap_vmm.h --
*
* Public VMM bootstrap declarations.
*/
#ifndef _BOOTSTRAP_VMM_H
#define _BOOTSTRAP_VMM_H
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_USERLEVEL
#include "includeCheck.h"
#include "vm_basic_types.h"
#include "monAddrLayout.h"
#define BOOTSTRAP_MAGIC 42
#define BOOTSTRAP_MAX_GDT_DESCS 2
typedef struct BSVMM_GDTInitEntry {
uint16 index;
LA32 base;
VA32 limit;
uint32 type;
uint32 S;
uint32 DPL;
uint32 present;
uint32 longmode;
uint32 DB;
uint32 gran;
} BSVMM_GDTInitEntry;
typedef struct BSVMM_GDTInit {
BSVMM_GDTInitEntry entries[BOOTSTRAP_MAX_GDT_DESCS];
} BSVMM_GDTInit;
typedef struct BSVMM_HostParams {
uint32 magic;
VMM64_AddrLayout addrLayout;
BSVMM_GDTInit gdtInit;
} BSVMM_HostParams;
BSVMM_HostParams* BSVMM_Validate(void *buf, uint32 nbytes);
#endif
+479
View File
@@ -0,0 +1,479 @@
/*********************************************************
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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"
#if defined(__cplusplus)
extern "C" {
#endif
typedef struct ListItem {
struct ListItem *prev;
struct ListItem *next;
} ListItem;
/*
*----------------------------------------------------------------------
*
* CircList_IsEmpty --
*
* A NULL list is an empty list.
*
* Result:
* TRUE if list is empty, FALSE otherwise.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE Bool
CircList_IsEmpty(const ListItem *item) // IN
{
return item == NULL;
}
/*
*----------------------------------------------------------------------
*
* CircList_InitItem --
*
* Initialize item as a single-element circular list.
*
* Result:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE void
CircList_InitItem(ListItem *item) // OUT
{
item->prev = item->next = item;
}
/*
*----------------------------------------------------------------------
*
* CircList_First --
*
* Return first item in the list.
*
* Result:
* First item.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE ListItem *
CircList_First(ListItem *item) // IN
{
return item;
}
/*
*----------------------------------------------------------------------
*
* CircList_Last --
*
* Return last item in the list.
*
* Result:
* Last item.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE ListItem *
CircList_Last(ListItem *item)
{
return item->prev;
}
/*
* CIRC_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 CIRC_LIST_CONTAINER(ptr, type, member) \
VMW_CONTAINER_OF(ptr, type, member)
/*
* Historical name, left here to reduce churn.
* TODO: remove, all LIST_CONTAINER uses should be
* VMW_CONTAINER_OF and stop depending on circList.h
* to provide the definition.
*/
#define LIST_CONTAINER(ptr, type, member) VMW_CONTAINER_OF(ptr, type, member)
/*
* 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 CIRC_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 CIRC_LIST_SCAN(p, l) \
CIRC_LIST_SCAN_FROM(p, CircList_First(l), CircList_First(l), next)
/* scan the entire list where loop element may be destroyed */
#define CIRC_LIST_SCAN_SAFE(p, pn, l) \
if (!CircList_IsEmpty(l)) \
for (p = (l), (pn) = CircList_Next(p, l); (p) != NULL; \
(p) = (pn), (pn) = CircList_Next(p, l))
/* scan the entire list backwards where loop element may be destroyed */
#define CIRC_LIST_SCAN_BACK_SAFE(p, pn, l) \
if (!CircList_IsEmpty(l)) \
for (p = CircList_Last(l), (pn) = CircList_Prev(p, l); (p) != NULL; \
(p) = (pn), (pn) = CircList_Prev(p, l))
/*
*----------------------------------------------------------------------
*
* CircList_Next --
*
* 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 *
CircList_Next(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;
}
/*
*----------------------------------------------------------------------
*
* CircList_Prev --
*
* 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 *
CircList_Prev(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;
}
/*
*----------------------------------------------------------------------
*
* CircList_DeleteItem --
*
* 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
CircList_DeleteItem(ListItem *p, // IN
ListItem **headp) // IN/OUT
{
ListItem *next;
ASSERT(p != NULL);
ASSERT(headp != NULL);
next = p->next;
if (p == next) {
*headp = NULL;
} else {
next->prev = p->prev;
p->prev->next = next;
if (*headp == p) {
*headp = next;
}
}
}
/*
*----------------------------------------------------------------------
*
* CircList_Queue --
*
* 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
CircList_Queue(ListItem *p, // IN
ListItem **headp) // IN/OUT
{
ListItem *head;
head = *headp;
if (CircList_IsEmpty(head)) {
CircList_InitItem(p);
*headp = p;
} else {
p->prev = head->prev;
p->next = head;
p->prev->next = p;
head->prev = p;
}
}
/*
*----------------------------------------------------------------------
*
* CircList_Push --
*
* 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
CircList_Push(ListItem *p, // IN
ListItem **headp) // IN/OUT
{
CircList_Queue(p, headp);
*headp = p;
}
/*
*----------------------------------------------------------------------
*
* CircList_Splice --
*
* 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 *
CircList_Splice(ListItem *l1, // IN
ListItem *l2) // IN
{
ListItem *l1Last, *l2Last;
if (CircList_IsEmpty(l1)) {
return l2;
}
if (CircList_IsEmpty(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;
}
#if 0 /* Presently unused, enable if a use is found */
/*
*----------------------------------------------------------------------
*
* CircList_Split --
*
* 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
CircList_Split(ListItem *p, // IN
ListItem *l, // IN
ListItem **l1p, // OUT
ListItem **l2p) // OUT
{
ListItem *last;
if (p == CircList_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;
}
#endif
/*
*----------------------------------------------------------------------
*
* CircList_Size --
*
* Return the number of items in the list.
*
* Result:
* The number of items in the list.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE int
CircList_Size(ListItem *head) // IN
{
ListItem *li;
int ret = 0;
CIRC_LIST_SCAN(li, head) {
ret++;
}
return ret;
}
#if defined(__cplusplus)
} // extern "C"
#endif
#endif /* _CIRCLIST_H_ */
+67
View File
@@ -0,0 +1,67 @@
/*********************************************************
* Copyright (C) 2009-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
*
*********************************************************/
/*
* 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__ */
+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__ */
+82
View File
@@ -0,0 +1,82 @@
/*********************************************************
* Copyright (C) 2002-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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>
/*
* p4d level appeared in 4.12.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
# define compat_p4d_offset(pgd, address) p4d_offset(pgd, address)
# define compat_p4d_present(p4d) p4d_present(p4d)
# define compat_p4d_large(p4d) p4d_large(p4d)
# define compat_p4d_pfn(p4d) p4d_pfn(p4d)
# define COMPAT_P4D_MASK P4D_MASK
typedef p4d_t compat_p4d_t;
#else
# define compat_p4d_offset(pgd, address) (pgd)
# define compat_p4d_present(p4d) (1)
# define compat_p4d_large(p4d) (0)
# define compat_p4d_pfn(p4d) INVALID_MPN /* Not used */
# define COMPAT_P4D_MASK 0 /* Not used */
typedef pgd_t compat_p4d_t;
#endif
/* pud_pfn did not exist before 3.8. */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
# define pud_pfn(pud) INVALID_MPN
#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
#define VM_PAGE_KERNEL_EXEC PAGE_KERNEL_EXEC
#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__ */
+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__ */
+80
View File
@@ -0,0 +1,80 @@
/*********************************************************
* Copyright (C) 2005-2014,2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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_USERLEVEL
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMX
#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 1024
#define MAX_PCPUS_BITS 10 // MAX_PCPUS <= (1 << MAX_PCPUS_BITS)
#define MAX_PCPUS_MASK ((1 << MAX_PCPUS_BITS) - 1)
#endif
+77
View File
@@ -0,0 +1,77 @@
/*********************************************************
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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"
#if defined __cplusplus
extern "C" {
#endif
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;
#if defined __cplusplus
} // extern "C"
#endif
#endif // _CPUID_INFO_H
+59
View File
@@ -0,0 +1,59 @@
/*********************************************************
* Copyright (C) 2006-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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.
*
* The crossGDT size is exactly one page.
*
* The hosted world switch code is based on the assumption that by
* placing VMM descriptors at the end of the page, they will not
* overlap with host kernel descriptors in use when "crossing over".
*
* All necessary host segments must be from first page of GDT.
* In Nov 2006, host GDT limits easily met this constraint:
*
* Linux 64 bit: 80 (yes 80, not 7F)
* MacOS 64 bit: 8F
* Windows 64 bit: 6F
*/
#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[PAGE_SIZE / sizeof(Descriptor)];
} CrossGDT;
#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
+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
+634
View File
@@ -0,0 +1,634 @@
/*********************************************************
* Copyright (C) 1998-2018 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"
#include "bootstrap_vmm.h"
#include "contextinfo.h"
#if defined __cplusplus
extern "C" {
#endif
/*
* Maximum number of shared regions that can be passed to MonLoader.
*/
#define ML_SHARED_REGIONS_MAX 3
/*
*-----------------------------------------------------------------------------
*
* 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 (361 << 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(PROCESS_BOOTSTRAP),
IOCTLCMD(RELEASE_VM),
IOCTLCMD(GET_NUM_VMS),
IOCTLCMD(INIT_VM),
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(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(GET_NEXT_ANON_PAGE),
IOCTLCMD(GET_ALL_MSRS),
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),
IOCTLCMD(SEND_ONE_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),
#endif
#if defined _WIN32 || defined __APPLE__
IOCTLCMD(ALLOC_CONTIG_PAGES),
#endif
#if defined _WIN32
IOCTLCMD(FREE_CONTIG_PAGES),
IOCTLCMD(HARD_LIMIT_MONITOR_STATUS), // used by vmauthd on Windows
IOCTLCMD(CHANGE_HARD_LIMIT), // used by vmauthd on Windows
IOCTLCMD(READ_DISASM_PROC_BINARY),
IOCTLCMD(CHECK_CANDIDATE_VA64),
IOCTLCMD(SET_MEMORY_PARAMS),
IOCTLCMD(REMEMBER_KHZ_ESTIMATE),
IOCTLCMD(REMAP_SCATTER_LIST),
IOCTLCMD(UNMAP_SCATTER_LIST),
#endif
#if defined __APPLE__
IOCTLCMD(GET_NUM_RESPONDING_CPUS),
IOCTLCMD(ALLOC_LOW_PAGES),
IOCTLCMD(INIT_DRIVER),
IOCTLCMD(BLUEPILL),
#endif
#if defined __linux__
IOCTLCMD(SET_HOST_SWAP_SIZE),
#endif
IOCTLCMD(GET_UNAVAIL_PERF_CTRS),
IOCTLCMD(GET_MONITOR_CONTEXT),
// 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_PROCESS_BOOTSTRAP VMIOCTL_BUFFERED(PROCESS_BOOTSTRAP)
#define IOCTL_VMX86_GET_NUM_VMS VMIOCTL_BUFFERED(GET_NUM_VMS)
#define IOCTL_VMX86_INIT_VM VMIOCTL_BUFFERED(INIT_VM)
#define IOCTL_VMX86_RUN_VM VMIOCTL_NEITHER(RUN_VM)
#define IOCTL_VMX86_SEND_IPI VMIOCTL_NEITHER(SEND_IPI)
#define IOCTL_VMX86_SEND_ONE_IPI VMIOCTL_BUFFERED(SEND_ONE_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_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_GET_NEXT_ANON_PAGE VMIOCTL_BUFFERED(GET_NEXT_ANON_PAGE)
#define IOCTL_VMX86_READ_DISASM_PROC_BINARY \
VMIOCTL_BUFFERED(READ_DISASM_PROC_BINARY)
#define IOCTL_VMX86_CHECK_CANDIDATE_VA64 VMIOCTL_BUFFERED(CHECK_CANDIDATE_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_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_GET_UNAVAIL_PERF_CTRS VMIOCTL_NEITHER(GET_UNAVAIL_PERF_CTRS)
#define IOCTL_VMX86_GET_MONITOR_CONTEXT VMIOCTL_BUFFERED(GET_MONITOR_CONTEXT)
#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 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;
/*
* 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 {
/*
* Vectors we have allocated or stolen for the monitor interrupts.
*/
uint8 monitorIPIVector;
uint8 hvIPIVector;
} IPIVectors;
#endif
/*
* Arguments and return value for VM creation.
*/
typedef struct VMCreateBlock {
VA64 bsBlob; // IN: User VA of the VMM bootstrap blob.
uint32 bsBlobSize; // IN: Size of VMM bootstrap blob.
uint32 numVCPUs; // IN: Number of VCPUs.
uint16 vmid; // OUT: VM ID for the created VM.
} VMCreateBlock;
/*
* Information about a shared region.
*/
typedef struct VMSharedRegion {
uint32 index;
VPN baseVpn;
uint32 numPages;
} VMSharedRegion;
/*
* Arguments for VMM bootstrap processing.
*/
typedef struct VMProcessBootstrapBlock {
VA64 bsBlobAddr; // IN: User VA of the VMM bootstrap blob.
uint32 numBytes; // IN: Size of VMM bootstrap blob.
uint32 headerOffset; // IN: Offset of header in blob.
uint16 numVCPUs; // IN: Number of VCPUs.
VA64 ptRootVAs[MAX_VCPUS]; // IN: User VA of PT roots.
VMSharedRegion shRegions[ML_SHARED_REGIONS_MAX]; // IN: Shared regions.
} VMProcessBootstrapBlock;
/*
* Arguments for VMM context retrieval.
*/
typedef union {
Vcpuid vcpuid; // IN
Context64 context; // OUT
} VMMonContext;
#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
#if defined __cplusplus
} // extern "C"
#endif
#endif // ifndef _IOCONTROLS_H_
+161
View File
@@ -0,0 +1,161 @@
/*********************************************************
* 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
*
*********************************************************/
#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"
#if defined(__cplusplus)
extern "C" {
#endif
#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);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif
+468
View File
@@ -0,0 +1,468 @@
/*********************************************************
* Copyright (C) 1998-2018 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 CP_STUB_SIZE 16 /* A relative jmp instruction (5 bytes)
padded to the next 16 byte boundary. */
#define MODULECALL_TABLE \
MC(INTR) \
MC(SEMAWAIT) \
MC(SEMASIGNAL) \
MC(SEMAFORCEWAKEUP) \
MC(IPI) /* Hit multiple threads with IPI. */ \
MC(ONE_IPI) /* Hit a single 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) \
MC(VMCLEAR_VMCS_ALL_CPUS) \
MC(GET_PAGE_ROOT) \
MC(ALLOC_ANON_LOW_PAGE) \
MC(GET_MON_IPI_VECTOR) \
MC(GET_HV_IPI_VECTOR) \
MC(GET_HOST_TIMER_VECTORS) \
MC(BOOTSTRAP_CLEANUP)
/*
*----------------------------------------------------------------------
*
* ModuleCallType --
*
* Enumeration of support calls done by the module.
*
*----------------------------------------------------------------------
*/
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
#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 the host GDT and the crosspage
* can be accessed during worldswitch.
*
*----------------------------------------------------------------------
*/
#define MAX_SWITCH_PT_PATCHES 2
/*----------------------------------------------------------------------
*
* 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
/*----------------------------------------------------------------------
*
* VMMPageTablePatch
*
* 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 value zero is reserved to indicate an empty spot
* in the array of patches.
*
* o index
*
* The index of the PTE at the given page table.
*
* o ptIdx
*
* The index of the page table at the given level.
*
* o pte
*
* This is the PTE value which will be patched into the monitor
* page table.
*
*----------------------------------------------------------------------
*/
typedef
#include "vmware_pack_begin.h"
struct VMMPageTablePatch {
#define PTP_EMPTY (0U) /* Unused array entry. (must be 0) */
#define PTP_LEVEL_L1 (1U)
#define PTP_LEVEL_L2 (2U)
#define PTP_LEVEL_L3 (3U)
#define PTP_LEVEL_L4 (4U) /* root level */
uint32 level; /* [0, 4] (maximal size: 3 bits) */
uint32 pteIdx; /* Index of the PTE in the page table. */
uint64 pteGlobalIdx; /* Global index of the PTE in 'level'. */
LPN lpn; /* Logical page number mapped by patch. */
VM_PDPTE pte; /* PTE. */
}
#include "vmware_pack_end.h"
VMMPageTablePatch;
#define MODULECALL_NUM_ARGS 4
/*
* The cross page contains tiny stacks upon which interrupt and exception
* handlers in the switch path may temporarily run. Each 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
*
* 184 bytes is slightly more than enough as of 2015/03/17 -- fjacobs.
*/
#define TINY_STACK_SIZE 184
/*
*----------------------------------------------------------------------
*
* VMCrossPageData --
*
* Data which is stored on the VMCrossPage.
*
*----------------------------------------------------------------------
*/
typedef
#include "vmware_pack_begin.h"
struct VMCrossPageData {
uint32 version; // CROSSPAGE_VERSION
uint32 vmmonVersion; // VMMON_VERSION
/*
* The following stacks and contexts are ordered for performance and code
* simplicity. Both HostToVmm and VmmToHost strictly require this ordering.
* For any change to this data, both functions must be updated.
* Use VMX86_UCCOST to measure performance when changing the layout.
*/
/* A tiny stack and the host context. */
uint64 hostTinyStack[TINY_STACK_SIZE / sizeof(uint64)];
uint64 hostCR3; /* Edge of context saved/restored in assembly. */
uint64 hostRBX;
uint64 hostRBP;
uint64 hostRSI;
uint64 hostRDI;
uint64 hostR12;
uint64 hostR13;
uint64 hostR14;
uint64 hostR15;
uint64 hostRSP;
uint16 hostSS; /* Edge of context saved/restored in assembly. */
uint16 hostDS; /* Not saved/restored in assembly switch */
uint16 hostES; /* Not saved/restored in assembly switch */
uint16 hostPad;
/* A tiny stack and the monitor context. */
uint64 monTinyStack[TINY_STACK_SIZE / sizeof(uint64)];
uint64 monCR3; /* Edge of context saved/restored in assembly. */
uint64 monRBX;
uint64 monRBP;
uint64 monR12;
uint64 monR13;
uint64 monR14;
uint64 monR15;
uint64 monRSP;
uint16 monSS; /* Edge of context saved/restored in assembly. */
uint16 monDS; /* Not saved/restored in assembly switch */
uint16 monES; /* Not saved/restored in assembly switch */
uint16 monPad;
uint64 crosspageMA;
uint64 hostDR[8];
LA64 hostCrossPageLA; // where host has crosspage mapped
uint16 hostInitial64CS;
uint8 hostDRSaved; // Host DR spilled to hostDR[x].
uint8 hostDRInHW; // 0 -> shadowDR in h/w, 1 -> hostDR in h/w.
uint32 _pad0;
uint64 wsCR0;
uint64 wsCR4;
DTR64 crossGDTHKLADesc; // always uses host kernel linear address
uint16 _pad1[3];
DTR64 monGDTR;
uint16 _pad2[3];
/* A hardcoded value for monitor %rip which facilitates backtraces. */
uint64 monRIP;
Task64 monTask; /* vmm's task */
VMMPageTablePatch vmmPTP[MAX_SWITCH_PT_PATCHES]; /* page table patch */
LA64 vmmCrossPageLA;
LA64 vmmCrossGDTLA; // where crossGDT is mapped by PT patch
/*
* 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 vcpuSet field is an additional
* argument used in some calls. 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];
#if !defined(VMX86_SERVER)
VCPUSet vcpuSet;
#endif
int userCallType;
uint32 pcpuNum; /* Used as extra module call arg within vmmon. */
#if !defined(VMX86_SERVER)
uint64 ucTimeStamps[UCCOST_MAX];
#endif
SwitchedMSRState switchedMSRState;
/*
* 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]
/* TRUE if no bits are set in yieldVCPUs, FALSE otherwise. */
Bool yieldVCPUsIsEmpty;
uint8 _pad3[6];
VCPUSet yieldVCPUs;
/*
* 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 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 _pad4[6];
DTR64 switchHostIDTR; // baseLA = switchHostIDT's host kernel LA
uint16 _pad5[3];
DTR64 switchMonIDTR; // baseLA = switchMonIDT's monitor LA
uint16 _pad6[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.
*/
Gate64 switchHostIDT[NUM_EXCEPTIONS]; // hostCS:hostVA
Gate64 switchMonIDT[NUM_EXCEPTIONS]; // monCS:monVA
volatile Bool wsException[NUM_EXCEPTIONS]; // Tracks faults in worldswitch.
uint8 _pad7[4];
uint64 wsUD2; // IP of ud2 instr or 0 if unset.
uint64 specCtrl; /* host MSR_SPEC_CTRL value before world switch. */
}
#include "vmware_pack_end.h"
VMCrossPageData;
/*
*----------------------------------------------------------------------
*
* VMCrossPageCode --
*
* Code which is stored on the VMCrossPage.
*
*----------------------------------------------------------------------
*/
#define CODE_BLOCK_SIZE (PAGE_SIZE - sizeof(VMCrossPageData) - \
(2 + NUM_EXCEPTIONS) * CP_STUB_SIZE)
typedef
#include "vmware_pack_begin.h"
struct VMCrossPageCode {
uint8 toVmmFunc[CP_STUB_SIZE]; // Fixed-position stubs to jump
uint8 toHostFunc[CP_STUB_SIZE]; // to world switch functions
uint8 gateStubs[NUM_EXCEPTIONS *
CP_STUB_SIZE]; // Stubs for crossIDT.
uint8 codeBlock[CODE_BLOCK_SIZE]; // Code for worldswitch and
// fault handling.
}
#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->crosspage (kernel module) and CROSS_PAGE
* (monitor)
*
* Must be exactly one page long.
*
*----------------------------------------------------------------------
*/
typedef
#include "vmware_pack_begin.h"
struct VMCrossPage {
VMCrossPageData crosspageData;
VMCrossPageCode crosspageCode;
}
#include "vmware_pack_end.h"
VMCrossPage;
#define CROSSPAGE_VERSION_BASE 0xc09 /* 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
+100
View File
@@ -0,0 +1,100 @@
/*********************************************************
* Copyright (C) 2006,2009-2011,2013-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
*
*********************************************************/
/*
* 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) \
SWMSR(MSR_BNDCFGS)
/*
* 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
+57
View File
@@ -0,0 +1,57 @@
/*********************************************************
* Copyright (C) 2005-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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
*
*********************************************************/
/*
* monAddrLayout.h --
*
* Address layout of the monitor.
*/
#ifndef _MON_ADDR_LAYOUT_H
#define _MON_ADDR_LAYOUT_H
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_USERLEVEL
#include "includeCheck.h"
#pragma pack(push, 1)
typedef struct VMM64_AddrLayout {
/*
*All address are VPNs and all lengths are numPages
*/
uint64 monBase; // MONITOR_BASE_VPN
uint64 monL4Start; // MON_PAGE_TABLE_L4_START
uint32 monL4Len; // MON_PAGE_TABLE_L4_LEN
uint64 monL3Start; // MON_PAGE_TABLE_L3_START
uint32 monL3Len; // MON_PAGE_TABLE_L3_LEN
uint64 monL2Start; // MON_PAGE_TABLE_L2_START
uint32 monL2Len; // MON_PAGE_TABLE_L2_LEN
uint64 monL1Start; // MON_PAGE_TABLE_L1_START
uint32 monL1Len; // MON_PAGE_TABLE_L1_LEN
#ifndef VMX86_SERVER
uint64 monCpStart; // CROSS_PAGE_START
#endif
} VMM64_AddrLayout;
#pragma pack(pop)
#define VMM_MONAS_FIRST_L4OFF 1
#define VMM_MONAS_LAST_L4OFF 127
#endif
+303
View File
@@ -0,0 +1,303 @@
/*********************************************************
* Copyright (C) 2015-2018 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
*
*********************************************************/
/*
* monLoader.h --
*
* Describes the monitor loader, its header and support code for
* processing this header.
*
*
* Overview
* ========
*
* Before the monitor or its in-context bootstrap code can run, a monitor
* address space must be created and partially populated. This address space
* contains code and data statically built, empty but allocated space, shared
* and run-time initialized content. The monitor loader header regularizes
* encoding of address space information, allowing a common representation and
* common code to be re-used for different contexts (vmmon for hosted, vmkernel
* for ESX, and the VMX while deprivileging of bootstrap is ongoing).
*
* The Header
* ==========
*
* The monitor loader header contains a sequence of entries describing content.
* Each entry has a start and end VPN, an optional content source, permission
* flags to be applied when mapping, an optional subIndex specifying a shared
* region (for shared content types) and a flag specifying whether to process
* this entry for all VCPUs or just the bootstrap processor.
*
* Content types
* =============
*
* ADDRSPACE: Must be first. Describes the address space in which all other
* entries reside. Page tables from L4 to L1 will be allocated, in order,
* eagerly. These page tables will be wired with the permissions of this entry
* from L4 to L1. This allows easy access to the L1E for any VPN in the space.
*
* ML_CONTENT_PAGETABLE_Lx: Maps the page tables for a given level. It must be
* exactly the size of the tables preallocated by ADDRSPACE for the level.
*
* ML_CONTENT_ALLOCZERO: Allocates new MPNs, zeroes the pages and maps them.
*
* ML_CONTENT_COPY: Allocates new MPNs, maps them and copies from the specified
* source.
*
* ML_CONTENT_SHARE: Memory provided by user, host kernel, or VMM blob,
* and mapped into the monitor address space. The subIndex field
* specifies which region, as multiple regions may be shared for each
* source.
*
* Processing
* ==========
*
* The monitor loader can be built in different contexts. Each context must
* provide implementations of callout functions. To fully build the context,
* callouts for memory allocation, access and reporting of resources will be
* added, as will accounting functionality.
*
* Callouts
* ========
*
* Memory-accessing callouts take a Vcpuid as memory is tracked per-VCPU.
*
* MonLoaderCallout_AllocMPN(MPN): Allocate a new MPN.
* MonLoaderCallout_CleanUp(): Release temporary MonLoader callout resources.
* MonLoaderCallout_CopyFromBlob(blobOffset, size, MPN): Copy blob contents.
* MonLoaderCallout_FillPage(pattern, mpn): fill a page with a pattern.
* MonLoaderCallout_GetPTE(MPN, index, *pte): Get indexth PTE in a PT MPN.
* MonLoaderCallout_GetPageRoot(vcpu): Get a VCPU's page root.
* MonLoaderCallout_ImportPage(MPN): Import an MPN for tracking and future use.
* MonLoaderCallout_Init(): Initialize MonLoader callouts.
* MonLoaderCallout_GetSharedHostPage(subIdx, page): Get shared host page MPN.
* MonLoaderCallout_GetSharedUserPage(subIdx, page): Get shared user page MPN.
* MonLoaderCallout_SetEntrypoint(): Sets the entry code/stack for execution.
*
* Building vs Importing
* =====================
*
* While legacy VMX is still responsible for building part of the monitor
* context, the monitor loader must cooperate. Rather than building the
* context itself, the monitor loader verifies its environment matches its
* header's expectations. This includes verifying sufficient allocations,
* permissions of page table wiring and page table self-mapping.
*
* Errors
* ======
*
* To avoid ASSERTs across contexts, errors are returned and clean-up is done
* carefully if processing fails at any stage. Some errors are debug-only and
* essentially verify invariants for debug builds. The line in the table at
* which the error was encountered is returned for logging and debugging.
*
* Compatibility
* =============
*
* bootstrap-offsets.pl relies on MonLoaderContentType, MonLoaderSourceType and
* the structure of MonLoaderEntry to determine and set blob offsets for
* ML_CONTENT_COPY + ML_SOURCE_BLOB. If these are changed, the script should
* be updated accordingly.
*/
#ifndef _MON_LOADER
#define _MON_LOADER
#include "vm_basic_types.h"
#include "x86paging_common.h"
#include "x86types.h" /* PT_L1E */
#include "vcpuid.h" /* Vcpuid */
#define ML_NAME_MAX 16
/* ML perms are simple and abbreviated. */
#define ML_PERM_RWX (PTE_P | PTE_RW)
#define ML_PERM_RW (PTE_P | PTE_RW | PTE_NX)
#define ML_PERM_RO (PTE_P | PTE_NX)
#define ML_PERM_RX PTE_P
#define ML_PERM_MASK (PTE_P| PTE_RW | PTE_NX | PTE_US)
#define ML_PERMS_MATCH(x,p) (((x) & ML_PERM_MASK) == ((p) & ML_PERM_MASK))
#define LOADER_HEADER_MAGIC 0x8675309E98675309
typedef enum {
ML_CONTENT_INVALID = 0,
ML_CONTENT_ADDRSPACE, /* The static address space. */
ML_CONTENT_ALLOCZERO, /* Allocate, zero-fill and map. */
ML_CONTENT_COPY, /* Copy data from external source. */
ML_CONTENT_PAGETABLE_L4, /* Mappings for level 4 page tables in AS. */
ML_CONTENT_PAGETABLE_L3, /* Mappings for level 3 page tables in AS. */
ML_CONTENT_PAGETABLE_L2, /* Mappings for level 2 page tables in AS. */
ML_CONTENT_PAGETABLE_L1, /* Mappings for level 1 page tables in AS. */
ML_CONTENT_SHARE, /* Share data from external source. */
} MonLoaderContentType;
#define CONTENT_TO_PTLEVEL(x) (x == ML_CONTENT_PAGETABLE_L4 ? 4 : \
x == ML_CONTENT_PAGETABLE_L3 ? 3 : \
x == ML_CONTENT_PAGETABLE_L2 ? 2 : \
x == ML_CONTENT_PAGETABLE_L1 ? 1 : \
0)
/* Sources of content, for pages not zeroed, unmapped or otherwise special. */
typedef enum MonLoaderSourceType {
ML_SOURCE_INVALID = 0x0,
ML_SOURCE_NONE,
ML_SOURCE_BLOB,
ML_SOURCE_USER,
ML_SOURCE_HOST,
} MonLoaderSourceType;
/*
* NOTE: When modifying MonLoaderEntry, corresponding changes must be
* made to vmcore/make/misc/bootstrap-offsets.pl.
*/
typedef struct {
MonLoaderContentType content; /* Content type. */
MonLoaderSourceType source; /* Source, if any, for content. */
VPN monVPN; /* Destination in monitor AS. */
uint64 monPages; /* Size in pages. */
uint64 flags; /* PTE permissions */
unsigned allocs; /* MPNs allocated (all VCPUs). */
/* Set for source ML_SOURCE_BLOB: */
struct blobSrc {
uint64 offset; /* offset within the blob, in bytes. */
uint64 size; /* size of content, in bytes. */
} blobSrc;
uint64 bspOnly; /* Process only on BSP. */
uint64 subIndex; /* Region ID for ML_CONTENT_COPY. */
uint64 procVmmon; /* Processed by the vmmon on hosted. */
} MonLoaderEntry;
/* Packed for easy consumption by bootstrap-offsets.pl. */
#pragma pack(push, 1)
typedef struct MonLoaderHeader {
uint64 magic;
uint32 entrySize;
uint32 count;
/* cs:rip */
uint16 codeSelector;
VA64 codeEntrypoint;
/* ss:rip */
uint16 stackSelector;
VA64 stackEntrypoint;
MonLoaderEntry entries[];
} MonLoaderHeader;
#pragma pack(pop)
/* Environment context structure, defined by the environment. */
struct MonLoaderEnvContext;
/* Callout prototypes */
MPN MonLoaderCallout_AllocMPN(struct MonLoaderEnvContext *, Vcpuid);
void MonLoaderCallout_CleanUp(struct MonLoaderEnvContext *);
Bool MonLoaderCallout_CopyFromBlob(struct MonLoaderEnvContext *, uint64,
size_t, MPN, Vcpuid);
Bool MonLoaderCallout_FillPage(struct MonLoaderEnvContext *, uint8, MPN,
Vcpuid);
MPN MonLoaderCallout_GetPageRoot(struct MonLoaderEnvContext *, Vcpuid);
Bool MonLoaderCallout_GetPTE(struct MonLoaderEnvContext *, MPN, unsigned,
Vcpuid, PT_L1E *);
Bool MonLoaderCallout_ImportPage(struct MonLoaderEnvContext *, MPN, Vcpuid);
Bool MonLoaderCallout_Init(void *, struct MonLoaderEnvContext **);
Bool MonLoaderCallout_MapMPNInPTE(struct MonLoaderEnvContext *, MPN, unsigned,
uint64, MPN, Vcpuid);
MPN MonLoaderCallout_GetSharedUserPage(struct MonLoaderEnvContext *, uint64,
unsigned, Vcpuid);
MPN MonLoaderCallout_GetSharedHostPage(struct MonLoaderEnvContext *, uint64,
unsigned, Vcpuid);
Bool MonLoaderCallout_IsPrivileged(struct MonLoaderEnvContext *);
Bool MonLoaderCallout_SetEntrypoint(struct MonLoaderEnvContext *, uint16, VA64,
uint16, VA64);
MPN MonLoaderCallout_GetBlobMpn(struct MonLoaderEnvContext *, uint64);
typedef enum MonLoaderError {
ML_OK = 0,
ML_ERROR_ADDRSPACE_TOO_LARGE,
ML_ERROR_ALLOC,
ML_ERROR_ALREADY_MAPPED,
ML_ERROR_ARGS,
ML_ERROR_CALLOUT_INIT,
ML_ERROR_CALLOUT_COPY,
ML_ERROR_CALLOUT_ENTRYPOINT,
ML_ERROR_CALLOUT_GETPTE,
ML_ERROR_CALLOUT_MAPINPTE,
ML_ERROR_CALLOUT_PAGEROOT_GET,
ML_ERROR_CALLOUT_ZERO,
ML_ERROR_CONTENT_INVALID,
ML_ERROR_CONTEXT_INIT,
ML_ERROR_DUPLICATE,
ML_ERROR_INVALID_VPN,
ML_ERROR_MAGIC,
ML_ERROR_MAP,
ML_ERROR_NO_ADDRSPACE,
ML_ERROR_PAGE_TABLE_IMPORT,
ML_ERROR_PAGE_TABLE_MAP_SIZE,
ML_ERROR_PAGE_TABLE_VERIFY,
ML_ERROR_SHARE,
ML_ERROR_SIZE,
ML_ERROR_SOURCE_INVALID,
ML_ERROR_TABLE_MISSING,
} MonLoaderError;
/* A subindex above shared area subindices for sharing of MonLoaderHeader. */
#define MONLOADER_HEADER_IDX 6
MonLoaderError MonLoader_Process(MonLoaderHeader *header, unsigned numVCPUs,
void *args, unsigned *line, Vcpuid *vcpu);
/*
*----------------------------------------------------------------------
*
* MonLoader_GetFixedHeaderSize --
*
* Returns the size of the fixed portion of MonLoaderHeader.
*
*----------------------------------------------------------------------
*/
static INLINE size_t
MonLoader_GetFixedHeaderSize(void)
{
return sizeof(MonLoaderHeader);
}
/*
*----------------------------------------------------------------------
*
* MonLoader_GetFullHeaderSize --
*
* Returns the size of the full MonLoaderHeader, including the
* variable size portion.
*
*----------------------------------------------------------------------
*/
static INLINE size_t
MonLoader_GetFullHeaderSize(MonLoaderHeader *header)
{
return MonLoader_GetFixedHeaderSize() +
header->count * sizeof(MonLoaderEntry);
}
#endif /* !_MON_LOADER */
+66
View File
@@ -0,0 +1,66 @@
/*********************************************************
* Copyright (C) 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
*
*********************************************************/
/*
* monLoaderLog.h --
*
* Logging definitions for MonLoader.
*/
#ifndef _MONLOADER_LOG_H_
#define _MONLOADER_LOG_H_
#ifdef VMX86_VMX
#define LOGLEVEL_MODULE main
#include "loglevel_vmcore.h"
/*
* Redefine LOG() to match the vmkernel calling convention.
*/
#undef LOG_BYNAME
#undef LOG
#define LOG_BYNAME(_mod, _min, _fmt, ...) \
(DOLOG_BYNAME(_mod, _min) ? Log(_fmt "\n", ## __VA_ARGS__) : (void) 0)
#define LOG(_min, _fmt, ...) \
LOG_BYNAME(LOGLEVEL_MODULE, _min, _fmt, ## __VA_ARGS__)
#elif defined VMKERNEL
#define LOGLEVEL_MODULE MonLoader
#include "log.h"
#elif defined VMMON
#include "vm_assert.h"
#define ML_LOGLEVEL_VMMON 0 /* MonLoader/vmmon loglevel. */
#undef LOG
#define LOG(_min, _fmt, ...) \
do { \
if (vmx86_log && ML_LOGLEVEL_VMMON >= (_min)) { \
Log(_fmt "\n", ## __VA_ARGS__); \
} \
} while (0)
#else /* !defined VMX86_VMX && !defined VMKERNEL && !defined VMMON */
#error MonLoader cannot be built as part of this environment
#endif
#endif /* _MONLOADER_LOG_H_ */
+222
View File
@@ -0,0 +1,222 @@
/*********************************************************
* Copyright (C) 2007-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 _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.
*
* Assertion failures for the monitor's bootstrap are reduced to panics
* logging the current %rip. As such, no .assert_info section is created
* and VMX merely processes the panic.
*/
#ifndef VMM_BOOTSTRAP
#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))
#else
extern uint64 bsAssertRIP;
#define ASSERT_RECORDINFO(assembly, assertType, bugNr) \
__asm__ __volatile__("lea 0(%%rip), %0\n\t" \
: "=r"(bsAssertRIP)); \
Panic("Bootstrap: %s failure at rip=0x%lx", \
assertType == AssertType_AssertVerify ? "VERIFY" : "ASSERT", \
bsAssertRIP);
#endif /* VMM_BOOTSTRAP */
#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
@@ -0,0 +1,43 @@
/*********************************************************
* Copyright (C) 2010-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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_VMKERNEL
#define INCLUDE_ALLOW_DISTRIBUTE
#include "includeCheck.h"
#include "vm_basic_types.h"
#if defined __cplusplus
extern "C" {
#endif
#define MONACTION_INVALID MAX_UINT32
typedef uint32 MonitorIdemAction;
#if defined __cplusplus
} // extern "C"
#endif
#endif // _MONITORACTION_EXPORTED_H_
+83
View File
@@ -0,0 +1,83 @@
/*********************************************************
* Copyright (C) 2006,2009-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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_PxmID;
typedef uint64 NUMA_NodeMask;
typedef uint8 NUMA_MemRangeID;
/*
* Constants
*/
#define NUMA_MAX_NODES 64
#define NUMA_MAX_CPUS_PER_NODE (vmx86_server ? MAX_PCPUS : 32)
#ifdef VMKBOOT
#define NUMA_MAX_MEM_RANGES 64
#else
#define NUMA_MAX_MEM_RANGES 256
#endif
#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_PxmID id;
Bool isReliable;
Bool isVolatile;
} NUMA_MemRange;
typedef struct NUMA_MemRangesList {
uint64 numMemRanges;
NUMA_MemRange memRange[NUMA_MAX_MEM_RANGES];
} NUMA_MemRangesList;
typedef struct NUMA_MemRangesListRef {
uint64 numMemRanges;
const NUMA_MemRange *memRange;
} NUMA_MemRangesListRef;
#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_
+109
View File
@@ -0,0 +1,109 @@
/*********************************************************
* Copyright (C) 2010-2014,2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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"
#if defined __cplusplus
extern "C" {
#endif
/*
* 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 void
PageList_SetEntry(PageListEntry *ple, BPN bpn)
{
CompressedBPN_Write(&ple->cbpn, bpn);
ple->voided = FALSE;
}
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;
}
#if defined __cplusplus
} // extern "C"
#endif
#endif // _PAGELIST_H
+112
View File
@@ -0,0 +1,112 @@
/*********************************************************
* Copyright (C) 2009-2018 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;
} 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_
+142
View File
@@ -0,0 +1,142 @@
/*********************************************************
* Copyright (C) 2002,2014-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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"
/*
*-----------------------------------------------------------------------------
*
* PgtblVa2MPNLocked --
*
* Walks through the hardware page tables to try to find the pte
* associated to a virtual address. Then maps PTE to MPN.
*
* Results:
* INVALID_MPN on failure
* 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
// space of that process
{
pgd_t *pgd;
compat_p4d_t *p4d;
MPN mpn;
pgd = pgd_offset(mm, addr);
if (pgd_present(*pgd) == 0) {
return INVALID_MPN;
}
if (pgd_large(*pgd)) {
/* Linux kernel does not support PGD huge pages. */
/* return pgd_pfn(*pgd) + ((addr & PGD_MASK) >> PAGE_SHIFT); */
return INVALID_MPN;
}
p4d = compat_p4d_offset(pgd, addr);
if (compat_p4d_present(*p4d) == 0) {
return INVALID_MPN;
}
if (compat_p4d_large(*p4d)) {
mpn = compat_p4d_pfn(*p4d) + ((addr & ~COMPAT_P4D_MASK) >> PAGE_SHIFT);
} else {
pud_t *pud;
pud = pud_offset(p4d, addr);
if (pud_present(*pud) == 0) {
return INVALID_MPN;
}
if (pud_large(*pud)) {
mpn = pud_pfn(*pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT);
} else {
pmd_t *pmd;
pmd = pmd_offset(pud, addr);
if (pmd_present(*pmd) == 0) {
return INVALID_MPN;
}
if (pmd_large(*pmd)) {
mpn = pmd_pfn(*pmd) + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
} else {
pte_t *pte;
pte = pte_offset_map(pmd, addr);
if (pte_present(*pte) == 0) {
pte_unmap(pte);
return INVALID_MPN;
}
mpn = pte_pfn(*pte);
pte_unmap(pte);
}
}
}
if (mpn >= INVALID_MPN) {
mpn = INVALID_MPN;
}
return mpn;
}
/*
*-----------------------------------------------------------------------------
*
* 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;
spin_lock(&mm->page_table_lock);
mpn = PgtblVa2MPNLocked(mm, addr);
spin_unlock(&mm->page_table_lock);
return mpn;
}
#endif /* __PGTBL_H__ */
+73
View File
@@ -0,0 +1,73 @@
/*********************************************************
* 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 (32)
#define PSHARE_P2M_BUFFER_MPNS_DEFAULT (5)
#define PSHARE_P2M_BUFFER_SLOTS_PER_MPN (PAGE_SIZE / sizeof(PShare_P2MUpdate))
#define PSHARE_P2M_BUFFER_SLOTS_MIN (2)
#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 union {
MPN mpn;
uint64 vpmemRef;
} PShare_P2MUpdateReference;
#define PSHARE_SET_INVALID_P2MUPDATE_REFERENCE(ref) ((ref).vpmemRef = CONST64U(-1))
#define PSHARE_IS_INVALID_P2MUPDATE_REFERENCE(ref) ((ref).vpmemRef == CONST64U(-1))
typedef struct PShare_P2MUpdate {
BPN bpn;
PShare_P2MUpdateReference reference;
} PShare_P2MUpdate;
#endif
+263
View File
@@ -0,0 +1,263 @@
/*********************************************************
* Copyright (C) 1998-2014,2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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,
Bool stress,
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 "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_ */
+126
View File
@@ -0,0 +1,126 @@
/*********************************************************
* Copyright (C) 2003-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
*
*********************************************************/
/*
*
* 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"
#include "versioned_atomic.h"
#if defined __cplusplus
extern "C" {
#endif
/* 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;
VersionedAtomic vers;
} 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;
}
#if defined __cplusplus
} // extern "C"
#endif
#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
+73
View File
@@ -0,0 +1,73 @@
/*********************************************************
* Copyright (C) 1998-2014, 2016-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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"
#if defined __cplusplus
extern "C" {
#endif
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 2048
#define MAX_CORES_PER_SOCKET 64
#define MAX_VCPU_SOCKETS 128
#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 */
#if defined __cplusplus
} // extern "C"
#endif
#endif // ifndef _VCPUID_H_
+894
View File
@@ -0,0 +1,894 @@
/*********************************************************
* Copyright (C) 2002-2018 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_WITH_MAX(_vcpuSet, _v, _numVcpus) \
do { \
Vcpuid _v; \
const VCPUSet *__vcs = (_vcpuSet); \
unsigned _subsetIdx = 0; \
uint64 _subset = VCPUSet_Subset(__vcs, _subsetIdx); \
unsigned _maxSubsets = VCS_VCPUID_SUBSET_IDX((_numVcpus) - 1) + 1; \
ASSERT(_maxSubsets <= VCS_SUBSET_COUNT); \
while ((_v = VCPUSet_FindFirstInSubset(__vcs, &_subset, &_subsetIdx, \
_maxSubsets)) != VCPUID_INVALID) {\
#define ROF_EACH_VCPU_IN_SET_WITH_MAX() \
} \
} while (0)
#define FOR_EACH_VCPU_IN_SET(_vcpuSet, _v) \
FOR_EACH_VCPU_IN_SET_WITH_MAX(_vcpuSet, _v, MAX_VCPUS)
#define ROF_EACH_VCPU_IN_SET() \
} \
} while (0)
#define FOR_EACH_VCPU_IN_POPULATED_VCPUS(_vcpuSet, _v) \
FOR_EACH_VCPU_IN_SET_WITH_MAX(_vcpuSet, _v, NumVCPUs())
#define ROF_EACH_VCPU_IN_POPULATED_VCPUS() \
} \
} 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, _numVcpus) \
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_FindFirstInSubset --
*
* Find the first (lowest-numbered) Vcpuid in the given subset of a
* VCPUSet object. It is required that *subset is initialized to
* a subset of *vcs and *subsetIdx must hold the index of the subset
* stored in *subset.
*
* Results:
* Vcpuid if at least one is present in a set.
* VCPUID_INVALID if the set is empty.
*
* Side effects:
* This function is intended to be used for iterating over all bits
* of a VCPUSet, it will modify *subset to clear the bit associated
* with the returned Vcpuid (if any). The *subsetIdx argument may
* also be updated.
*
*----------------------------------------------------------------------
*/
static INLINE Vcpuid
VCPUSet_FindFirstInSubset(const VCPUSet *vcs, uint64 *subset,
unsigned *subsetIdx, unsigned maxSubsets)
{
ASSERT(*subsetIdx < maxSubsets && maxSubsets <= VCS_SUBSET_COUNT);
do {
if (*subset != 0) {
int bit;
bit = lssb64_0(*subset);
*subset &= ~(CONST64U(1) << bit);
return bit + (*subsetIdx << VCS_SUBSET_SHIFT);
}
++*subsetIdx;
if (*subsetIdx < maxSubsets) {
*subset = vcs->subset[*subsetIdx];
}
} while (*subsetIdx < maxSubsets);
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));
}
/*
*----------------------------------------------------------------------
*
* VCPUSet_AtomicTestInclude --
*
* Atomically add a single Vcpuid to a VCPUSet, and
* return TRUE iff the given Vcpuid was present in the VCPUSet.
*
*----------------------------------------------------------------------
*/
static INLINE Bool
VCPUSet_AtomicTestInclude(VCPUSet *vcs, Vcpuid v)
{
volatile uint64 *subset = &vcs->subset[VCS_VCPUID_SUBSET_IDX(v)];
ASSERT(v < MAX_VCPUS);
return Atomic_TestSetBit64(Atomic_VolatileToAtomic64(subset),
v & VCS_SUBSET_MASK);
}
#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 "ptr".
*
*----------------------------------------------------------------------
*/
static INLINE void
VCPUSet_UnpackCareful(unsigned numVCPUs, VCPUSet *vcs, const 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_FindSingleton --
*
* Return the VCPU in the set iff vcs contains exactly one VCPU.
* Return VCPUID_INVALID otherwise.
*
*----------------------------------------------------------------------
*/
static INLINE Vcpuid
VCPUSet_FindSingleton(const VCPUSet *vcs)
{
uint64 foundSub = 0;
uint32 foundIdx;
FOR_EACH_SUBSET_IN_SET(idx) {
uint64 sub = vcs->subset[idx];
if (sub != 0) {
if (foundSub != 0 || (sub & (sub - 1)) != 0) {
return VCPUID_INVALID;
}
foundSub = sub;
foundIdx = idx;
}
} ROF_EACH_SUBSET_IN_SET();
return foundSub != 0 ? lssb64_0(foundSub) + (foundIdx << VCS_SUBSET_SHIFT) :
VCPUID_INVALID;
}
/*
*----------------------------------------------------------------------
*
* 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_ */
+71
View File
@@ -0,0 +1,71 @@
/*********************************************************
* Copyright (C) 2002-2013, 2016-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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 "vcpuid.h"
#include "vm_assert.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 32
#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;
MY_ASSERTS(VCPUSET_ASSERTS,
ASSERT_ON_COMPILE(VCS_SUBSET_WIDTH * VCS_SUBSET_COUNT >= MAX_VCPUS);
/*
* Catch changes in VCPUSet which need to be reflected in
* bora/public/iocontrolsMacosTable.h.
*/
ASSERT_ON_COMPILE(VCS_SUBSET_COUNT == 32);
/*
* There is code that depends on sizeof(VCPUSet) being a power of
* 2 in at least vcpuHotPlug.c and possible other places.
*/
ASSERT_ON_COMPILE((sizeof(VCPUSet) & (sizeof(VCPUSet) - 1)) == 0);
)
#endif
+274
View File
@@ -0,0 +1,274 @@
/*********************************************************
* Copyright (C) 1998,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
*
*********************************************************/
/*
* versioned_atomic.h --
*
* This file implements versioned atomic synchronization, which allows
* concurrent accesses to shared data by a single writer and multiple
* readers. The algorithm is lock-free (it does not use a mutual exclusion
* mechanism), and the writer is wait-free (it never waits for readers).
*
* Many-writer/many-reader can be implemented on top of versioned atomics
* by adding an external mutual exclusion mechanism to serialize all
* writer threads into a single logical writer thread. This is preferable
* for cases where readers are expected to greatly outnumber writers.
*
* Implementation
* --------------
* This implementation is based on Leslie Lamport's paper "Concurrent
* Reading and Writing", Communications of the ACM, November 1977
* (http://url.eng.vmware.com/udcc ).
*
* Lamport's algorithm was designed for systems in which the reader and
* the writers run on separate computers and where the version variables
* (v0 and v1 in this implementation) are stored on a shared hard disk. So
* it did not assume that the version variables could be accessed
* atomically. Instead, it assumed that the version variables were made of
* multiple basic units of data, called "digits", and that each digit
* could be accessed atomically. The upper-left corner of page 4 of the
* paper precisely and concisely describes the algorithm, and in
* particular the order in which digits of the version variables must be
* accessed (left to right, right to left, or no particular order).
*
* This implementation is designed for systems in which the reader and the
* writers run on the same computer and where the version variables are
* stored in shared memory. So it assumes that the version variables can
* be accessed atomically. As a result, this implementation uses a
* simplified version of Lamport's algorithm, where:
* o Each left to right or right to left access in Lamport's algorithm is
* replaced with a single atomic access in this implementation.
* o Each access in no particular order in Lamport's algorithm is replaced
* with a single non-atomic access in this implementation.
* Note: The writer is the only thread which writes to version variables,
* so it is allowed to read them non-atomically.
*
* Multiple concurrent writers to the version variables are not allowed.
* Even if writers are working on lock-free or disjoint data, the version
* variables are not interlocked for read-modify-write. See PR514764.
*
* Recursive use of versioned atomics in writers is currently not
* supported. See PR514764.
*/
#ifndef _VERSIONED_ATOMIC_H
#define _VERSIONED_ATOMIC_H
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#include "includeCheck.h"
#include "vm_basic_asm.h"
#include "vm_assert.h"
#include "vm_atomic.h"
#if defined __cplusplus
extern "C" {
#endif
/*
* 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 {
uint32 v0;
uint32 v1;
} ALIGNED(4) VersionedAtomic;
/*
*-----------------------------------------------------------------------------
*
* VersionedAtomic_BeginWrite --
*
* Called by the writer to indicate that it is about to write to the
* shared data protected by 'versions'. Effectively locks out all readers
* until VersionedAtomic_EndWrite() is called.
*
* Results:
* None
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static INLINE void
VersionedAtomic_BeginWrite(VersionedAtomic *versions) // IN
{
/* Catch improper initialization or unsupported recursive use. */
ASSERT(versions->v1 == versions->v0);
/*
* Do not use Atomic_Inc32() below: it is more expensive than
* Atomic_Write32() and unnecessary: only the write needs to be atomic, not
* the whole read + inc + write.
*/
#if !defined VMM
/*
* Atomic_Write32() below requires the address to be naturally aligned, but
* currently only checks that condition when VMM is defined (tracked by
* PR1055836). So until that PR is fixed, we must check that condition here
* when VMM is not defined.
*/
ASSERT(((uintptr_t)&versions->v0 % sizeof versions->v0) == 0);
#endif
Atomic_Write32((Atomic_uint32 *)&versions->v0, versions->v0 + 1);
/*
* The write to 'versions->v0' must be observed by all other OS CPUs before
* the write(s) to the shared data.
*/
SMP_W_BARRIER_W();
}
/*
*-----------------------------------------------------------------------------
*
* VersionedAtomic_EndWrite --
*
* Called by the writer to indicate that it has finished writing to the
* shared data protected by 'versions'. Lets pending and new readers
* proceed.
*
* Results:
* None
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static INLINE void
VersionedAtomic_EndWrite(VersionedAtomic *versions) // IN
{
/*
* The write(s) to the shared data must be observed by all other OS CPUs
* before the write to 'versions->v1'.
*/
SMP_W_BARRIER_W();
ASSERT(versions->v1 + 1 == versions->v0);
#if !defined VMM
/*
* Atomic_Write32() below requires the address to be naturally aligned, but
* currently only checks that condition when VMM is defined (tracked by
* PR1055836). So until that PR is fixed, we must check that condition here
* when VMM is not defined.
*/
ASSERT(((uintptr_t)&versions->v1 % sizeof versions->v1) == 0);
#endif
Atomic_Write32((Atomic_uint32 *)&versions->v1, versions->v0);
}
/*
*-----------------------------------------------------------------------------
*
* VersionedAtomic_BeginTryRead --
*
* Called by a reader before it starts reading the shared data protected
* by 'versions'.
*
* Results:
* A version number for the caller to pass to the matching call to
* VersionedAtomic_EndTryRead(), if any.
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static INLINE uint32
VersionedAtomic_BeginTryRead(VersionedAtomic const *versions) // IN
{
uint32 readVersion = Atomic_Read32((Atomic_uint32 *)&versions->v1);
/*
* The read from 'versions->v1' must happen on this CPU before the read(s)
* from the shared data.
*/
SMP_R_BARRIER_R();
return readVersion;
}
/*
*-----------------------------------------------------------------------------
*
* VersionedAtomic_EndTryRead --
*
* Called by a reader after it has finished reading the shared data
* protected by 'versions', to confirm that the data is consistent, i.e.
* that the writer has not modified the data while the reader was reading
* it.
*
* Results:
* TRUE if the shared data read between VersionedAtomic_BeginTryRead() and
* this call is consistent.
* FALSE otherwise.
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static INLINE Bool
VersionedAtomic_EndTryRead(VersionedAtomic const *versions, // IN
uint32 readVersion) // IN
{
/*
* The read(s) from the shared data must happen on this CPU before the read
* from 'versions->v0'.
*/
SMP_R_BARRIER_R();
/*
* There is a theoretical ABA issue here: if the writer updates the shared
* data exactly 2^32 times while a reader reads it, the read will
* incorrectly be considered consistent. In practice, this issue is
* unlikely, so we ignore it. But should we need it, we could make the issue
* even less likely by using 64-bit version variables.
*/
return LIKELY( Atomic_Read32((Atomic_uint32 *)&versions->v0)
== readVersion);
}
#if defined __cplusplus
} // extern "C"
#endif
#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
+997
View File
@@ -0,0 +1,997 @@
/*********************************************************
* Copyright (C) 1998-2014,2016-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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) && !defined(USE_UBSAN)
#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)
#define RESTORE_FLAGS _Set_flags
#define ENABLE_INTERRUPTS() __asm__ __volatile__ ("sti": : :"memory")
#define CLEAR_INTERRUPTS() __asm__ __volatile__ ("cli": : :"memory")
#define RAISE_INTERRUPT(_x) __asm__ __volatile__("int %0" :: "g" (_x))
#define RETURN_FROM_INT() __asm__ __volatile__("iret" :: )
#if ! defined(VMKERNEL)
#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)
{
#ifndef VMM_BOOTSTRAP
ASSERT(oldVal == GET_XCR0());
if (newVal != oldVal) {
SET_XCR0(newVal);
}
#endif
}
#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
+137
View File
@@ -0,0 +1,137 @@
/*********************************************************
* 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_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_USERLEVEL
#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
+321
View File
@@ -0,0 +1,321 @@
/*********************************************************
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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);
NORETURN void Panic_NoSave(const char *fmt, ...) PRINTF_DECL(1, 2);
#define Panic(fmt...) do { \
Panic_SaveRegs(); \
Panic_NoSave(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())
#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 NOT_TESTED() Warning(_AssertNotTestedFmt "\n", __FILE__, __LINE__)
#else
#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
+558
View File
@@ -0,0 +1,558 @@
/*********************************************************
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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"
#if defined __cplusplus
extern "C" {
#endif
#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
#if defined __cplusplus
} // extern "C"
#endif
#endif // _VM_BASIC_ASM_X86_H_
+614
View File
@@ -0,0 +1,614 @@
/*********************************************************
* Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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_PC
*
* Returns the current program counter (i.e. instruction pointer i.e. rip
* register on x86_64). In the example below:
*
* foo.c
* L123: Foo(GET_CURRENT_PC())
*
* the return value from GET_CURRENT_PC will point a debugger to L123.
*/
#define GET_CURRENT_PC() ({ \
void *__rip; \
asm("lea 0(%%rip), %0;\n\t" \
: "=r" (__rip)); \
__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,444 @@
/*********************************************************
* Copyright (C) 2013-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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)
long _InterlockedXor(long volatile *, long);
#pragma intrinsic(_InterlockedXor)
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
}
/*
* Memory Barriers
* ===============
*
* Terminology
* -----------
*
* A compiler memory barrier prevents the compiler from re-ordering memory
* accesses accross the barrier. It is not a CPU instruction, it is a compiler
* directive (i.e. it does not emit any code).
*
* A CPU memory barrier prevents the CPU from re-ordering memory accesses
* accross the barrier. It is a CPU instruction.
*
* A memory barrier is the union of a compiler memory barrier and a CPU memory
* barrier. A compiler memory barrier is a useless construct by itself. It is
* only useful when combined with a CPU memory barrier, to implement a memory
* barrier.
*
* Semantics
* ---------
*
* At the time COMPILER_*_BARRIER were created (and references to them were
* added to the code), the code was only targetting x86. The intent of the code
* was really to use a memory barrier, but because x86 uses a strongly ordered
* memory model, the CPU would not re-order memory accesses, and the code could
* get away with using just a compiler memory barrier. So COMPILER_*_BARRIER
* were born and were implemented as compiler memory barriers _on x86_. But
* make no mistake, _the semantics that the code expects from
* COMPILER_*_BARRIER are that of a memory barrier_!
*
* DO NOT USE!
* -----------
*
* On at least one non-x86 architecture, COMPILER_*_BARRIER are
* 1) Misnomers
* 2) Not fine-grained enough to provide the best performance.
* For the above two reasons, usage of COMPILER_*_BARRIER is now deprecated.
* _Do not add new references to COMPILER_*_BARRIER._ Instead, precisely
* document the intent of your code by using
* <mem_type/purpose>_<before_access_type>_BARRIER_<after_access_type>.
* Existing references to COMPILER_*_BARRIER are being slowly but surely
* converted, and when no references are left, COMPILER_*_BARRIER will be
* retired.
*
* Thanks for pasting this whole comment into every architecture header.
*/
#if defined __GNUC__
# define COMPILER_READ_BARRIER() COMPILER_MEM_BARRIER()
# define COMPILER_WRITE_BARRIER() COMPILER_MEM_BARRIER()
# define COMPILER_MEM_BARRIER() __asm__ __volatile__("" ::: "memory")
#elif defined _MSC_VER
# define COMPILER_READ_BARRIER() _ReadBarrier()
# define COMPILER_WRITE_BARRIER() _WriteBarrier()
# define COMPILER_MEM_BARRIER() _ReadWriteBarrier()
#endif
/*
* Memory barriers. These take the form of
*
* <mem_type/purpose>_<before_access_type>_BARRIER_<after_access_type>
*
* where:
* <mem_type/purpose> is either SMP, DMA, or MMIO.
* <*_access type> is either R(load), W(store) or RW(any).
*
* Above every use of these memory barriers in the code, there _must_ be a
* comment to justify the use, i.e. a comment which:
*
* 1) Precisely identifies which memory accesses must not be re-ordered across
* the memory barrier.
* 2) Explains why it is important that the memory accesses not be re-ordered.
*
* Thanks for pasting this whole comment into every architecture header.
*
* On x86, we only need to care specifically about store-load reordering on
* normal memory types. In other cases, only a compiler barrier is needed.
* SMP_W_BARRIER_R is implemented with a locked xor operation (instead of the
* mfence instruction) for performance reasons. See PR 1674199 for more
* details.
*
* On x64, special instructions are only provided for load-load (lfence) and
* store-store (sfence) ordering, and they don't apply to normal memory.
*/
static INLINE void
SMP_W_BARRIER_R(void)
{
volatile long temp;
#if defined __GNUC__
__asm__ __volatile__ (
"lock xorl $1, %0"
: "+m" (temp)
: /* no additional inputs */
: "cc", "memory");
#elif defined _MSC_VER
_InterlockedXor(&temp, 1);
#else
#error SMP_W_BARRIER_R not defined for this compiler
#endif
}
#define SMP_R_BARRIER_R() COMPILER_READ_BARRIER()
#define SMP_R_BARRIER_W() COMPILER_MEM_BARRIER()
#define SMP_R_BARRIER_RW() COMPILER_MEM_BARRIER()
#define SMP_W_BARRIER_W() COMPILER_WRITE_BARRIER()
#define SMP_W_BARRIER_RW() SMP_W_BARRIER_R()
#define SMP_RW_BARRIER_R() SMP_W_BARRIER_R()
#define SMP_RW_BARRIER_W() COMPILER_MEM_BARRIER()
#define SMP_RW_BARRIER_RW() SMP_W_BARRIER_R()
/*
* Like the above, only for use with observers other than CPUs,
* i.e. DMA masters.
*/
#define DMA_R_BARRIER_R() SMP_R_BARRIER_R()
#define DMA_R_BARRIER_W() SMP_R_BARRIER_W()
#define DMA_R_BARRIER_RW() SMP_R_BARRIER_RW()
#define DMA_W_BARRIER_R() SMP_W_BARRIER_R()
#define DMA_W_BARRIER_W() SMP_W_BARRIER_W()
#define DMA_W_BARRIER_RW() SMP_W_BARRIER_RW()
#define DMA_RW_BARRIER_R() SMP_RW_BARRIER_R()
#define DMA_RW_BARRIER_W() SMP_RW_BARRIER_W()
#define DMA_RW_BARRIER_RW() SMP_RW_BARRIER_RW()
/*
* And finally a set for use with MMIO accesses.
*/
#define MMIO_R_BARRIER_R() SMP_R_BARRIER_R()
#define MMIO_R_BARRIER_W() SMP_R_BARRIER_W()
#define MMIO_R_BARRIER_RW() SMP_R_BARRIER_RW()
#define MMIO_W_BARRIER_R() SMP_W_BARRIER_R()
#define MMIO_W_BARRIER_W() SMP_W_BARRIER_W()
#define MMIO_W_BARRIER_RW() SMP_W_BARRIER_RW()
#define MMIO_RW_BARRIER_R() SMP_RW_BARRIER_R()
#define MMIO_RW_BARRIER_W() SMP_RW_BARRIER_W()
#define MMIO_RW_BARRIER_RW() SMP_RW_BARRIER_RW()
#endif // _VM_BASIC_ASM_X86_COMMON_H_
+798
View File
@@ -0,0 +1,798 @@
/*********************************************************
* Copyright (C) 2003-2018 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. */
#if !defined(VMKERNEL) && defined(__FreeBSD__)
#define __IS_FREEBSD__ 1
#else
#define __IS_FREEBSD__ 0
#endif
#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_SHIFT
#define MBYTES_SHIFT 20
#endif
#ifndef MBYTES_2_PAGES
#define MBYTES_2_PAGES(_nbytes) \
((uint64)(_nbytes) << (MBYTES_SHIFT - PAGE_SHIFT))
#endif
#ifndef PAGES_2_MBYTES
#define PAGES_2_MBYTES(_npages) ((_npages) >> (MBYTES_SHIFT - PAGE_SHIFT))
#endif
#ifndef ROUNDUP_PAGES_2_MBYTES
#define ROUNDUP_PAGES_2_MBYTES(_npages) \
(((_npages) + MASK(MBYTES_SHIFT - PAGE_SHIFT)) >> (MBYTES_SHIFT - PAGE_SHIFT))
#endif
#ifndef ROUNDDOWN_PAGES_2_MBYTES
#define ROUNDDOWN_PAGES_2_MBYTES(_npages) \
((_npages) >> (MBYTES_SHIFT - PAGE_SHIFT))
#endif
#ifndef GBYTES_2_PAGES
#define GBYTES_2_PAGES(_nbytes) ((uint64)(_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) >> MBYTES_SHIFT)
#endif
#ifndef MBYTES_2_BYTES
#define MBYTES_2_BYTES(_nbytes) ((uint64)(_nbytes) << MBYTES_SHIFT)
#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
#ifndef VM_PAE_LARGE_2_BYTES
#define VM_PAE_LARGE_2_BYTES(_2mbytes) ((_2mbytes) << VM_PAE_LARGE_PAGE_SHIFT)
#endif
#ifndef VM_1GB_PAGE_SHIFT
#define VM_1GB_PAGE_SHIFT 30
#endif
#ifndef VM_1GB_PAGE_SIZE
#define VM_1GB_PAGE_SIZE (1 << VM_1GB_PAGE_SHIFT)
#endif
#ifndef VM_1GB_2_PAGES
#define VM_1GB_2_PAGES (BYTES_2_PAGES(VM_1GB_PAGE_SIZE))
#endif
#ifndef VM_1GB_2_PDIRS
#define VM_1GB_2_PDIRS (VM_1GB_PAGE_SIZE / 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 // {
/*
* Standardize some Posix names on Windows.
*/
#ifdef _WIN32 // {
/* Conflict with definition of Visual Studio 2015 */
#if (_MSC_VER < 1900)
#define snprintf _snprintf
#endif
#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)
// The macOS kernel SDK defines va_copy in stdarg.h.
#include <stdarg.h>
#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.
*/
#if defined(_WIN32) && defined(_MSC_VER)
#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
/*
* 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
#if defined(__APPLE__) && defined(VMW_APPLE_SANDBOX)
#define vmw_apple_sandbox 1
#else
#define vmw_apple_sandbox 0
#endif
#if defined(__APPLE__) && defined(VMW_APPLE_APP_STORE)
#define vmw_apple_app_store 1
#else
#define vmw_apple_app_store 0
#endif
#ifdef VMM
#define VMM_ONLY(x) x
#else
#define VMM_ONLY(x)
#endif
#if defined(VMM) || defined(VMKERNEL)
#define USER_ONLY(x)
#else
#define USER_ONLY(x) x
#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
#define SIZE_512BIT 64
/*
* Allocate a variable of type _type, aligned to _align bytes, returning a
* pointer to the variable in _var. Potentially _align - 1 bytes may be
* wasted. On x86, GCC 6.3.0 behaves sub-optimally when variables are declared
* on the stack using the aligned attribute, so this pattern is preferred.
* See PRs 1795155, 1819963.
*/
#define WITH_PTR_TO_ALIGNED_VAR(_type, _align, _var) \
do { \
uint8 _buf_##_var[sizeof(_type) + (_align) - 1]; \
_type *_var = (_type *) ((uintptr_t)(_buf_##_var + (_align) - 1) & \
~((uintptr_t) ((_align) - 1)));
#define END_PTR_TO_ALIGNED_VAR \
} while (0)
#endif // ifndef _VM_BASIC_DEFS_H_
+197
View File
@@ -0,0 +1,197 @@
/*********************************************************
* Copyright (C) 2008-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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...
#if defined __cplusplus
extern "C" {
#endif
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;
}
/*
*-----------------------------------------------------------------------------
*
* IsZeroOrPowerOfTwo --
* IsZeroOrPowerOfTwo64 --
*
* Results:
* TRUE iff the value is 0 or a power of two.
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
static INLINE Bool
IsZeroOrPowerOfTwo64(uint64 x)
{
return !(x & (x - 1));
}
static INLINE Bool
IsZeroOrPowerOfTwo(uint32 x) // IN
{
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)
#if defined __cplusplus
} // extern "C"
#endif
#endif // ifndef _VM_BASIC_MATH_H_
File diff suppressed because it is too large. Load diff
+132
View File
@@ -0,0 +1,132 @@
/*********************************************************
* Copyright (C) 2014-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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_pagetable.h --
*
* Virtual memory page table definitions
*/
#ifndef _VM_PAGETABLE_H_
#define _VM_PAGETABLE_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"
#include "vm_basic_types.h"
#include "vm_basic_defs.h"
/*
* These definitions suit both the x64 and arm64 architectures. In particular
* - At all levels, a page table is a 4KB page containing 512 8-byte entries.
* - Each entry maps 39, 30, 21 and 12 bits at the respective page table
* levels (with standard page sizes).
*/
typedef uint64 PT_L4E;
typedef uint64 PT_L3E;
typedef uint64 PT_L2E;
typedef uint64 PT_L1E;
typedef enum {
PT_LEVEL_1 = 1,
PT_LEVEL_2,
PT_LEVEL_3,
PT_LEVEL_4,
PT_LEVEL_STOP = PT_LEVEL_1,
PT_MAX_LEVELS = PT_LEVEL_4
} PT_Level;
#define PT_PTE_SIZE 8
#define PT_LEVEL_SHIFT 9
#define PT_PTE_PFN_SHIFT PAGE_SHIFT
#define PT_ENTRIES_PER_PT (1 << PT_LEVEL_SHIFT)
#define PT_OFF_MASK (PT_ENTRIES_PER_PT - 1)
/* Align any page number type to the 2M containing page number. */
#define PT_2M_ALIGN_PN(x) ((x) & ~PT_OFF_MASK)
/*
* log2 of the
* address space size (in 4KB pages) covered by a level-_l page table entry.
*/
#define PT_LE_PG_SHIFT(_l) (PT_LEVEL_SHIFT * ((_l) - PT_LEVEL_1))
/* Address space size (in 4KB pages) covered by a level-_l page table entry. */
#define PT_PAGES_PER_LE(_l) ((uint64)1 << PT_LE_PG_SHIFT(_l))
#define PT_PAGES_PER_L4E PT_PAGES_PER_LE(PT_LEVEL_4)
#define PT_PAGES_PER_L3E PT_PAGES_PER_LE(PT_LEVEL_3)
#define PT_PAGES_PER_L2E PT_PAGES_PER_LE(PT_LEVEL_2)
#define PT_PAGES_PER_L1E PT_PAGES_PER_LE(PT_LEVEL_1)
/*
* log2 of the
* address space size (in bytes) covered by a level-_l page table entry.
*/
#define PT_LE_SHIFT(_l) (PAGE_SHIFT + PT_LE_PG_SHIFT(_l))
#define PT_L4E_SHIFT PT_LE_SHIFT(PT_LEVEL_4)
#define PT_L3E_SHIFT PT_LE_SHIFT(PT_LEVEL_3)
#define PT_L2E_SHIFT PT_LE_SHIFT(PT_LEVEL_2)
#define PT_L1E_SHIFT PT_LE_SHIFT(PT_LEVEL_1)
/* Address space size (in bytes) covered by a level-_l page table entry. */
#define PT_LE_SIZE(_l) ((uint64)1 << PT_LE_SHIFT(_l))
#define PT_L4E_SIZE PT_LE_SIZE(PT_LEVEL_4)
#define PT_L3E_SIZE PT_LE_SIZE(PT_LEVEL_3)
#define PT_L2E_SIZE PT_LE_SIZE(PT_LEVEL_2)
#define PT_L1E_SIZE PT_LE_SIZE(PT_LEVEL_1)
/*
* For a given LA,
* determine the offset (== index) of the level-_l page table entry.
*/
#define PT_LA_2_LOFF(_a, _l) (((_a) >> PT_LE_SHIFT(_l)) & PT_OFF_MASK)
#define PT_LA_2_L4OFF(_a) PT_LA_2_LOFF(_a, PT_LEVEL_4)
#define PT_LA_2_L3OFF(_a) PT_LA_2_LOFF(_a, PT_LEVEL_3)
#define PT_LA_2_L2OFF(_a) PT_LA_2_LOFF(_a, PT_LEVEL_2)
#define PT_LA_2_L1OFF(_a) PT_LA_2_LOFF(_a, PT_LEVEL_1)
/*
* For a given LPN,
* determine the offset (== index) of the level-_l page table entry.
*/
#define PT_LPN_2_LOFF(_a, _l) (((_a) >> PT_LE_PG_SHIFT(_l)) & PT_OFF_MASK)
#define PT_LPN_2_L4OFF(_a) PT_LPN_2_LOFF(_a, PT_LEVEL_4)
#define PT_LPN_2_L3OFF(_a) PT_LPN_2_LOFF(_a, PT_LEVEL_3)
#define PT_LPN_2_L2OFF(_a) PT_LPN_2_LOFF(_a, PT_LEVEL_2)
#define PT_LPN_2_L1OFF(_a) PT_LPN_2_LOFF(_a, PT_LEVEL_1)
/* Size (in bytes) of a 1GB page. */
#define PT_1G_PAGE_SIZE PT_L3E_SIZE
#define PT_1G_PAGE_MASK (PT_L3E_SIZE - 1)
/* Size (in bytes) of a 2MB page. */
#define PT_2M_PAGE_SIZE PT_L2E_SIZE
#define PT_2M_PAGE_MASK (PT_L2E_SIZE - 1)
#define PT_LE_NXT_PG(_a, _l) ((((_a) >> PT_LE_PG_SHIFT(_l)) + 1) \
<< PT_LE_PG_SHIFT(_l))
#endif
+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 */
+45
View File
@@ -0,0 +1,45 @@
/*********************************************************
* 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
#endif
+50
View File
@@ -0,0 +1,50 @@
/*********************************************************
* Copyright (C) 2017-2018 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
*
*********************************************************/
/*
* vmmblob.h --
*
* VMM blob management.
*/
#ifndef VMMBLOB_H
#define VMMBLOB_H
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#include "includeCheck.h"
struct VMDriver;
struct MonLoaderHeader;
typedef struct VmmBlobInfo {
uint8 *blobPtr;
uint32 numBytes;
MPN *mpns;
struct MonLoaderHeader *header;
} VmmBlobInfo;
void VmmBlob_Cleanup(VmmBlobInfo *bi);
Bool VmmBlob_Load(VA64 bsBlobAddr, uint32 numBytes, uint32 headerOffset,
VmmBlobInfo **blobInfo);
MPN VmmBlob_GetMpn(struct VMDriver *vm, uint64 blobOffset);
MPN VmmBlob_GetHeaderMpn(struct VMDriver *vm);
uint8 *VmmBlob_GetPtr(VMDriver *vm);
uint64 VmmBlob_GetSize(VMDriver *vm);
#endif /* VMMBLOB_H */
+114
View File
@@ -0,0 +1,114 @@
/*********************************************************
* Copyright (C) 2000-2015,2017-2018 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_CONTIG 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_2M_PAGE VMMEM_FLAG_BIT(2)
#define VMMEM_GUEST_1G_PAGE VMMEM_FLAG_BIT(3)
#define VMMEM_GUEST_CAN_FAIL VMMEM_FLAG_BIT(4)
#define VMMEM_GUEST_TEST_ZEROCOW VMMEM_FLAG_BIT(5)
#define VMMEM_GUEST_TRY_ZEROCOW VMMEM_FLAG_BIT(6)
#define VMMEM_GUEST_TRY_POISONCOW VMMEM_FLAG_BIT(7)
#define VMMEM_GUEST_PREALLOC VMMEM_FLAG_BIT(8)
#define VMMEM_GUEST_ALL_FLAGS MASK(9)
#define VMMEM_GUEST_TRY_COW (VMMEM_GUEST_TEST_ZEROCOW | \
VMMEM_GUEST_TRY_ZEROCOW | \
VMMEM_GUEST_TRY_POISONCOW)
#define VMMEM_GUEST_LARGE_PAGE (VMMEM_GUEST_2M_PAGE | \
VMMEM_GUEST_1G_PAGE)
#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_DIRTY VMMEM_FLAG_BIT(5)
#define VMMEM_PLATFORM_IS_2M_PAGE VMMEM_FLAG_BIT(6)
#define VMMEM_PLATFORM_IS_1G_PAGE VMMEM_FLAG_BIT(7)
#define VMMEM_PLATFORM_LARGE_RETRY VMMEM_FLAG_BIT(8)
#define VMMEM_PLATFORM_TRY_COW_SUCCESS VMMEM_FLAG_BIT(9)
#define VMMEM_PLATFORM_BACKED_LARGE (VMMEM_PLATFORM_IS_2M_PAGE | \
VMMEM_PLATFORM_IS_1G_PAGE)
#define MAX_PLATFORM_PAGE_INFO_PAGES 240
/*
* Structure used to query platform about the page state.
*/
typedef struct PlatformPageInfoList {
PgCnt64 numPages;
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-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
*
*********************************************************/
/*
* 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-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
*
*********************************************************/
/*
* 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-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
*
*********************************************************/
/*
* 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-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 __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__ */
+263
View File
@@ -0,0 +1,263 @@
/*********************************************************
* Copyright (C) 2006-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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_CACHE_CONTROL (CR0_CD | CR0_NW)
#define CR0_RESERVED CONST64U(0xffffffff1ffaffc0)
/*
* Note: The "Not Reserved" bits in CR0 are:
* PG, CD, NW, AM, WP, NE, ET, TS, EM, MP, PE
* | | | | | |
* | | +---------------+---+---+---> CR0_MUTABLE
* | |
* +---+--> CR0_CACHE_CONTROL
*
* (CR0_MUTABLE is defined in vmkernel/private/x86/cpu.h)
*/
#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
#define CR4_PKE 0x00400000
#define CR4_RESERVED CONST64U(0xffffffffff889800)
#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_VE 20 // Virtualization exception - VT only.
#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;
/*
* MPX bound configuration registers
*/
#define BNDCFG_EN 0x00000001
#define BNDCFG_BNDPRSV 0x00000002
#define BNDCFG_RSVD 0x00000ffc
#define BNDCFG_BDBASE CONST64U(0xfffffffffffff000)
#endif // ifndef _VM_BASIC_DEFS_H_
+354
View File
@@ -0,0 +1,354 @@
/*********************************************************
* Copyright (C) 1998,2015-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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 XAPIC_MAXLVT_0x6 0x6 // Intel only: Nehalem (1A) and onward
#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 guestReservedAPIC 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
+476
View File
@@ -0,0 +1,476 @@
/*********************************************************
* Copyright (C) 2003-2017 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 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
*
*********************************************************/
/*
* x86cpuid_asm.h
*
* CPUID-related assembly functions.
*/
#ifndef _X86CPUID_ASM_H_
#define _X86CPUID_ASM_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"
#include "vm_basic_asm.h"
#include "x86cpuid.h"
/*
* 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 _MSC_VER
#ifdef __cplusplus
extern "C" {
#endif
#ifdef VM_X86_64
/*
* intrinsic functions only supported by x86-64 windows as of 2k3sp1
*/
void __cpuid(int regs[4], int eax);
#pragma intrinsic(__cpuid)
/*
* __cpuidex has been supported since VS2008
*/
#if _MSC_VER >= 1500
void __cpuidex(int regs[4], int eax, int ecx);
#pragma intrinsic(__cpuidex)
#endif /* _MSC_VER >= 1500 */
#endif /* VM_X86_64 */
#ifdef __cplusplus
}
#endif
#endif /* _MSC_VER */
#ifdef __GNUC__ // {
/*
* Checked against the Intel manual and GCC --hpreg
*
* Need __volatile__ and "memory" since CPUID has a synchronizing effect.
* The CPUID may also change at runtime (APIC flag, etc).
*
*/
/*
* %ebx is reserved on i386 PIC. Apple's gcc-5493 (gcc 4.0) compiling
* for x86_64 incorrectly errors out saying %ebx is reserved. This is
* Apple bug 7304232.
*/
#if vm_x86_64 ? (defined __APPLE_CC__ && __APPLE_CC__ == 5493) : defined __PIC__
#if vm_x86_64
/*
* Note that this generates movq %rbx,%rbx; cpuid; xchgq %rbx,%rbx ...
* Unfortunately Apple's assembler does not have .ifnes, and I cannot
* figure out how to do that with .if. If we ever enable this code
* on other 64bit systems, both movq & xchgq should be surrounded by
* .ifnes \"%%rbx\", \"%q1\" & .endif
*/
#define VM_CPUID_BLOCK "movq %%rbx, %q1\n\t" \
"cpuid\n\t" \
"xchgq %%rbx, %q1\n\t"
#define VM_EBX_OUT(reg) "=&r"(reg)
#else
#define VM_CPUID_BLOCK "movl %%ebx, %1\n\t" \
"cpuid\n\t" \
"xchgl %%ebx, %1\n\t"
#define VM_EBX_OUT(reg) "=&rm"(reg)
#endif
#else
#define VM_CPUID_BLOCK "cpuid"
#define VM_EBX_OUT(reg) "=b"(reg)
#endif
static INLINE void
__GET_CPUID(int eax, // IN
CPUIDRegs *regs) // OUT
{
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (regs->eax), VM_EBX_OUT(regs->ebx), "=c" (regs->ecx), "=d" (regs->edx)
: "a" (eax)
: "memory"
);
}
static INLINE void
__GET_CPUID2(int eax, // IN
int ecx, // IN
CPUIDRegs *regs) // OUT
{
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (regs->eax), VM_EBX_OUT(regs->ebx), "=c" (regs->ecx), "=d" (regs->edx)
: "a" (eax), "c" (ecx)
: "memory"
);
}
static INLINE uint32
__GET_EAX_FROM_CPUID(int eax) // IN
{
uint32 ebx;
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (eax), VM_EBX_OUT(ebx)
: "a" (eax)
: "memory", "%ecx", "%edx"
);
return eax;
}
static INLINE uint32
__GET_EBX_FROM_CPUID(int eax) // IN
{
uint32 ebx;
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (eax), VM_EBX_OUT(ebx)
: "a" (eax)
: "memory", "%ecx", "%edx"
);
return ebx;
}
static INLINE uint32
__GET_ECX_FROM_CPUID(int eax) // IN
{
uint32 ecx;
uint32 ebx;
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (eax), VM_EBX_OUT(ebx), "=c" (ecx)
: "a" (eax)
: "memory", "%edx"
);
return ecx;
}
static INLINE uint32
__GET_EDX_FROM_CPUID(int eax) // IN
{
uint32 edx;
uint32 ebx;
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (eax), VM_EBX_OUT(ebx), "=d" (edx)
: "a" (eax)
: "memory", "%ecx"
);
return edx;
}
static INLINE uint32
__GET_EAX_FROM_CPUID4(int ecx) // IN
{
uint32 eax;
uint32 ebx;
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (eax), VM_EBX_OUT(ebx), "=c" (ecx)
: "a" (4), "c" (ecx)
: "memory", "%edx"
);
return eax;
}
#undef VM_CPUID_BLOCK
#undef VM_EBX_OUT
#elif defined(_MSC_VER) // } {
static INLINE void
__GET_CPUID(int input, CPUIDRegs *regs)
{
#ifdef VM_X86_64
__cpuid((int *)regs, input);
#else
__asm push esi
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, input
__asm mov esi, regs
__asm _emit 0x0f __asm _emit 0xa2
__asm mov 0x0[esi], eax
__asm mov 0x4[esi], ebx
__asm mov 0x8[esi], ecx
__asm mov 0xC[esi], edx
__asm pop edx
__asm pop ecx
__asm pop ebx
__asm pop esi
#endif
}
#ifdef VM_X86_64
#if _MSC_VER >= 1500
/*
* __cpuidex has been supported since VS2008
*/
static INLINE void
__GET_CPUID2(int inputEax, int inputEcx, CPUIDRegs *regs)
{
__cpuidex((int *)regs, inputEax, inputEcx);
}
#else // _MSC_VER >= 1500
/*
* No inline assembly in Win64. Implemented in bora/lib/misc in
* cpuidMasm64.asm.
*/
extern void
__GET_CPUID2(int inputEax, int inputEcx, CPUIDRegs *regs);
#endif // _MSC_VER >= 1500
#else // VM_X86_64
static INLINE void
__GET_CPUID2(int inputEax, int inputEcx, CPUIDRegs *regs)
{
__asm push esi
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, inputEax
__asm mov ecx, inputEcx
__asm mov esi, regs
__asm _emit 0x0f __asm _emit 0xa2
__asm mov 0x0[esi], eax
__asm mov 0x4[esi], ebx
__asm mov 0x8[esi], ecx
__asm mov 0xC[esi], edx
__asm pop edx
__asm pop ecx
__asm pop ebx
__asm pop esi
}
#endif
static INLINE uint32
__GET_EAX_FROM_CPUID(int input)
{
#ifdef VM_X86_64
CPUIDRegs regs;
__cpuid((int *)&regs, input);
return regs.eax;
#else
uint32 output;
//NOT_TESTED();
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, input
__asm _emit 0x0f __asm _emit 0xa2
__asm mov output, eax
__asm pop edx
__asm pop ecx
__asm pop ebx
return output;
#endif
}
static INLINE uint32
__GET_EBX_FROM_CPUID(int input)
{
#ifdef VM_X86_64
CPUIDRegs regs;
__cpuid((int *)&regs, input);
return regs.ebx;
#else
uint32 output;
//NOT_TESTED();
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, input
__asm _emit 0x0f __asm _emit 0xa2
__asm mov output, ebx
__asm pop edx
__asm pop ecx
__asm pop ebx
return output;
#endif
}
static INLINE uint32
__GET_ECX_FROM_CPUID(int input)
{
#ifdef VM_X86_64
CPUIDRegs regs;
__cpuid((int *)&regs, input);
return regs.ecx;
#else
uint32 output;
//NOT_TESTED();
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, input
__asm _emit 0x0f __asm _emit 0xa2
__asm mov output, ecx
__asm pop edx
__asm pop ecx
__asm pop ebx
return output;
#endif
}
static INLINE uint32
__GET_EDX_FROM_CPUID(int input)
{
#ifdef VM_X86_64
CPUIDRegs regs;
__cpuid((int *)&regs, input);
return regs.edx;
#else
uint32 output;
//NOT_TESTED();
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, input
__asm _emit 0x0f __asm _emit 0xa2
__asm mov output, edx
__asm pop edx
__asm pop ecx
__asm pop ebx
return output;
#endif
}
#ifdef VM_X86_64
/*
* No inline assembly in Win64. Implemented in bora/lib/misc in
* cpuidMasm64.asm.
*/
extern uint32
__GET_EAX_FROM_CPUID4(int inputEcx);
#else // VM_X86_64
static INLINE uint32
__GET_EAX_FROM_CPUID4(int inputEcx)
{
uint32 output;
//NOT_TESTED();
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, 4
__asm mov ecx, inputEcx
__asm _emit 0x0f __asm _emit 0xa2
__asm mov output, eax
__asm pop edx
__asm pop ecx
__asm pop ebx
return output;
}
#endif // VM_X86_64
#else // }
#error
#endif
#define CPUID_FOR_SIDE_EFFECTS() ((void)__GET_EAX_FROM_CPUID(0))
/* The first parameter is used as an rvalue and then as an lvalue. */
#define GET_CPUID(_ax, _bx, _cx, _dx) { \
CPUIDRegs regs; \
__GET_CPUID(_ax, &regs); \
_ax = regs.eax; \
_bx = regs.ebx; \
_cx = regs.ecx; \
_dx = regs.edx; \
}
#define GET_CPUID2(_ax, _bx, _cx, _dx) {\
CPUIDRegs regs; \
__GET_CPUID2(_ax, _cx, &regs); \
_ax = regs.eax; \
_bx = regs.ebx; \
_cx = regs.ecx; \
_dx = regs.edx; \
}
#endif
+601
View File
@@ -0,0 +1,601 @@
/*********************************************************
* 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
*
*********************************************************/
#ifndef _X86DESC_H_
#define _X86DESC_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"
#include "x86segdescrs.h"
#include "vm_assert.h"
/*
* Symbolic names for various offsets used to construct segment descriptors.
*/
/* Lower dword */
#define X86DESC_BASE_LO_SHIFT 16
#define X86DESC_LIMIT_LO_SHIFT 0
/* Upper dword */
#define X86DESC_BASE_HI_SHIFT 24
#define X86DESC_GRAN_SHIFT 23
#define X86DESC_DB_SHIFT 22
#define X86DESC_LONG_SHIFT 21
#define X86DESC_AVL_SHIFT 20
#define X86DESC_LIMIT_HI_SHIFT 16
#define X86DESC_P_SHIFT 15
#define X86DESC_DPL_SHIFT 13
#define X86DESC_S_SHIFT 12
#define X86DESC_TYPE_SHIFT 8
#define X86DESC_BASE_MID_SHIFT 0
#define X86DESC_TYPE_WIDTH 4
/*
* Descriptors store a 32-bit or 64-bit segment base in 3 parts
* (low, mid, high) and the 20-bit limit in 2 parts (low, high).
* The following macros extract these components from the original
* base and limit.
*/
#define BASE_LO(_dw) ((uint32)((_dw) & 0xffff))
#define BASE_MID(_dw) ((uint32)(((_dw) >> 16) & 0xff))
#define BASE_HI(_dw) ((uint32)(((_dw) >> 24) & 0xff))
#define BASE64_LO(_qw) ((uint64)((_qw) & 0xffffff))
#define BASE64_MID(_qw) ((uint64)(((_qw) >> 24) & 0xff))
#define BASE64_HI(_qw) ((uint64)((_qw) >> 32))
#define LIMIT_LO(_dw) ((uint32)((_dw) & 0xffff)) /* Descriptor */
#define LIMIT_HI(_dw) ((uint32)(((_dw) >> 16) & 0xf))
#define OFFSET_LO(_dw) ((uint32)((_dw) & 0xffff)) /* CallGate */
#define OFFSET_HI(_dw) ((uint32)(((_dw) >> 16) & 0xffff))
/*
* Accessor functions for descriptors.
*
* Note: The fields of a descriptor should always be accessed with the
* following functions. ANSI C specifies that any expression
* involving integer types smaller than an int have all the variables
* automatically promoted to a *signed* int. This means that
* expressions that use the fields of a descriptor directly will
* treat them as signed quantities. This could have unwanted effects,
* e.g. base and limit added together could result in a negative
* quantity. The functions that read the bitfields always return an
* unsigned integer so as to avoid any potential signed/unsigned
* problems. Functions to write the bitfields are also provided for
* consistency.
*/
static INLINE uint32 Desc_Type(const Descriptor *d) { return d->type; }
static INLINE uint32 Desc_S(const Descriptor *d) { return d->S; }
static INLINE uint32 Desc_DPL(const Descriptor *d) { return d->DPL; }
static INLINE uint32 Desc_Present(const Descriptor *d) { return d->present; }
static INLINE uint32 Desc_AVL(const Descriptor *d) { return d->AVL; }
static INLINE uint32 Desc_LongMode(const Descriptor *d) { return d->longmode; }
static INLINE uint32 Desc_DB(const Descriptor *d) { return d->DB; }
static INLINE uint32 Desc_Gran(const Descriptor *d) { return d->gran; }
static INLINE uint32 Desc64_Type(const Descriptor64 *d) { return d->type; }
static INLINE uint32 Desc64_S(const Descriptor64 *d) { return d->S; }
static INLINE uint32 Desc64_DPL(const Descriptor64 *d) { return d->DPL; }
static INLINE uint32 Desc64_Present(const Descriptor64 *d) { return d->present; }
static INLINE uint32 Desc64_AVL(const Descriptor64 *d) { return d->AVL; }
static INLINE uint32 Desc64_Gran(const Descriptor64 *d) { return d->gran; }
static INLINE uint32 Desc64_ExtAttrs(const Descriptor64 *d) { return d->ext_attrs; }
static INLINE LA32
Desc_GetBase(const Descriptor *d)
{
return (d->base_hi << 24) | (d->base_mid << 16) | d->base_lo;
}
static INLINE LA64
Desc64_GetBase(const Descriptor64 *d)
{
return ((uint64)d->base_hi << 32) |
((uint64)d->base_mid << 24) | (uint32)d->base_lo;
}
static INLINE LA32
Desc64_GetBaseHi(const Descriptor64 *d)
{
return d->base_hi;
}
static INLINE VA32
Desc_GetLimit(const Descriptor *d)
{
return (d->limit_hi << 16) | d->limit_lo;
}
static INLINE VA32
Desc64_GetLimit(const Descriptor64 *d)
{
return ((uint32)d->limit_hi << 16) | (uint32)d->limit_lo;
}
static INLINE Bool
Desc_EqualIgnoreAccessed(const Descriptor *d1, const Descriptor *d2)
{
const DescriptorUnion *du1 = (const DescriptorUnion*) d1;
const DescriptorUnion *du2 = (const DescriptorUnion*) d2;
uint32 mask = ~0u;
if (Desc_S(d1)) {
mask = ~(1u << 8);
}
return du1->word[0] == du2->word[0] &&
(du1->word[1] & mask) == (du2->word[1] & mask);
}
static INLINE Bool
Desc64_EqualIgnoreAccessed(const Descriptor64 *d1, const Descriptor64 *d2)
{
const Descriptor64Union *du1 = (const Descriptor64Union*) d1;
const Descriptor64Union *du2 = (const Descriptor64Union*) d2;
uint32 mask = ~0u;
if (Desc64_S(d1)) {
mask = ~(1u << 8);
}
return du1->word[0] == du2->word[0] &&
(du1->word[1] & mask) == (du2->word[1] & mask) &&
du1->qword[1] == du2->qword[1];
}
static INLINE void Desc_SetType(Descriptor *d, uint32 val) { d->type = val; }
static INLINE void Desc_SetS(Descriptor *d, uint32 val) { d->S = val; }
static INLINE void Desc_SetDPL(Descriptor *d, uint32 val) { d->DPL = val; }
static INLINE void Desc_SetPresent(Descriptor *d, uint32 val) { d->present = val; }
static INLINE void Desc_SetDB(Descriptor *d, uint32 val) { d->DB = val; }
static INLINE void Desc_SetLongmode(Descriptor *d, uint32 val) { d->longmode = val; }
static INLINE void Desc_SetGran(Descriptor *d, uint32 val) { d->gran = val; }
static INLINE void Desc64_SetType(Descriptor64 *d, uint32 val) { d->type = val; }
static INLINE void Desc64_SetS(Descriptor64 *d, uint32 val) { d->S = val; }
static INLINE void Desc64_SetDPL(Descriptor64 *d, uint32 val) { d->DPL = val; }
static INLINE void Desc64_SetPresent(Descriptor64 *d, uint32 val) { d->present = val; }
static INLINE void Desc64_SetGran(Descriptor64 *d, uint32 val) { d->gran = val; }
static INLINE void
Desc_SetBase(Descriptor *d, LA32 newBase)
{
d->base_hi = BASE_HI(newBase);
d->base_mid = BASE_MID(newBase);
d->base_lo = BASE_LO(newBase);
ASSERT(Desc_GetBase(d) == newBase);
}
static INLINE void
Desc64_SetBase(Descriptor64 *d, LA64 newBase)
{
d->base_hi = (uint32)BASE64_HI(newBase);
d->base_mid = (uint32)BASE64_MID(newBase);
d->base_lo = (uint32)BASE64_LO(newBase);
ASSERT(Desc64_GetBase(d) == newBase);
}
static INLINE void
Desc_SetLimit(Descriptor *d, VA32 newLimit)
{
d->limit_lo = LIMIT_LO(newLimit);
d->limit_hi = LIMIT_HI(newLimit);
ASSERT(Desc_GetLimit(d) == newLimit);
}
static INLINE void
Desc64_SetLimit(Descriptor64 *d, VA32 newLimit)
{
d->limit_lo = LIMIT_LO(newLimit);
d->limit_hi = LIMIT_HI(newLimit);
ASSERT(Desc64_GetLimit(d) == newLimit);
}
/*
*-----------------------------------------------------------------------------
*
* Desc_SetDescriptor --
*
* Set a descriptor with the specified properties.
*
* NOTE: the implementation of Desc_SetDescriptor() assumes a
* little-endian byte order.
*
*-----------------------------------------------------------------------------
*/
static INLINE void
Desc_SetDescriptor(Descriptor *d, LA32 base, VA32 limit, uint32 type,
uint32 S, uint32 DPL, uint32 present, uint32 DB,
uint32 gran)
{
DescriptorUnion *desc = (DescriptorUnion *) d;
desc->word[0] = BASE_LO(base) << X86DESC_BASE_LO_SHIFT |
LIMIT_LO(limit) << X86DESC_LIMIT_LO_SHIFT;
desc->word[1] = BASE_HI(base) << X86DESC_BASE_HI_SHIFT |
gran << X86DESC_GRAN_SHIFT |
DB << X86DESC_DB_SHIFT |
LIMIT_HI(limit) << X86DESC_LIMIT_HI_SHIFT |
present << X86DESC_P_SHIFT |
DPL << X86DESC_DPL_SHIFT |
S << X86DESC_S_SHIFT |
type << X86DESC_TYPE_SHIFT |
BASE_MID(base) << X86DESC_BASE_MID_SHIFT;
/*
* Assert that all the fields were properly filled in.
*/
ASSERT(Desc_GetBase(d) == base);
ASSERT(Desc_GetLimit(d) == limit);
ASSERT(Desc_Type(d) == type);
ASSERT(Desc_S(d) == S);
ASSERT(Desc_DPL(d) == DPL);
ASSERT(Desc_Present(d) == present);
ASSERT(Desc_DB(d) == DB);
ASSERT(Desc_Gran(d) == gran);
ASSERT(d->AVL == 0);
ASSERT(d->longmode == 0);
}
/*
* Accessor functions that operate directly on a descriptor. These
* are included only for backwards compatibility with existing macros.
*/
static INLINE uint32 DESC_TYPE(Descriptor d) { return d.type; }
static INLINE uint32 DESC_S(Descriptor d) { return d.S; }
static INLINE uint32 DESC_DPL(Descriptor d) { return d.DPL; }
static INLINE uint32 DESC_PRESENT(Descriptor d) { return d.present; }
#define DT_CODE(_d) ( DESC_S(_d) && (DESC_TYPE(_d) & 0x8) == 0x8)
#define DT_CONFORMING_CODE(_d) ( DESC_S(_d) && (DESC_TYPE(_d) & 0xc) == 0xc)
#define DT_NONCONFORMING_CODE(_d) ( DESC_S(_d) && (DESC_TYPE(_d) & 0xc) == 0x8)
#define DT_READABLE_CODE(_d) ( DESC_S(_d) && (DESC_TYPE(_d) & 0xa) == 0xa)
#define DT_DATA(_d) ( DESC_S(_d) && (DESC_TYPE(_d) & 0x8) == 0x0)
#define DT_WRITEABLE_DATA(_d) ( DESC_S(_d) && (DESC_TYPE(_d) & 0xa) == 0x2)
#define DT_EXPAND_DOWN(_d) ( DESC_S(_d) && (DESC_TYPE(_d) & 0xc) == 0x4)
#define DT_CALL_GATE(_d) (!DESC_S(_d) && (DESC_TYPE(_d) & 0x7) == 0x4)
#define DT_CALL_GATE32(_d) (!DESC_S(_d) && (DESC_TYPE(_d) & 0xf) == 0xc)
#define DT_LDT(_d) (!DESC_S(_d) && (DESC_TYPE(_d) & 0xf) == 0x2)
#define DT_TASK_GATE(_d) (!DESC_S(_d) && (DESC_TYPE(_d) & 0xf) == 0x5)
#define DT_TSS(_d) (!DESC_S(_d) && (DESC_TYPE(_d) & 0x5) == 0x1)
#define DT_AVAIL_TSS(_d) (!DESC_S(_d) && (DESC_TYPE(_d) & 0x7) == 0x1)
#define DT64_TSS(_d) (!Desc64_S(&_d) && (Desc64_Type(&_d) & 0xd) == 0x9)
#define DT64_AVAIL_TSS(_d) (!Desc64_S(&_d) && Desc64_Type(&_d) == 0x9)
#define DT64_LDT(_d) (!Desc64_S(&_d) && Desc64_Type(&_d) == 0x2)
#define DT_ACCESS 0x1
#define DT_32BIT 0x8
#define DT_TSS_BUSY 0x2
#define DATA_DESC 0x2
#define CODE_DESC 0xa
#define LDT_DESC 0x2
#define TASK_DESC 0x9 // TSS available
#define TASK_DESC_BUSY 0xb // TSS busy
#define TASK16_DESC 0x1 // 16-bit TSS available
#define TASK16_DESC_BUSY 0x3 // 16-bit TSS busy
/*
*-----------------------------------------------------------------------------
*
* Desc_SetSystemDescriptor64 --
*
* Set a 16 byte long mode system descriptor with the specified properties.
*
*-----------------------------------------------------------------------------
*/
static INLINE void
Desc_SetSystemDescriptor64(Descriptor *d, uint64 base, uint32 limit, uint32 type,
uint32 DPL, uint32 present, uint32 DB, uint32 gran)
{
uint32 baseHi = (uint32) (base >> 32);
uint32 baseLo = (uint32) base;
/*
* The first half of a 16-byte descriptor is a valid 8-byte descriptor
* so allow TASK16_DESC
*/
ASSERT(type == TASK_DESC || type == TASK_DESC_BUSY ||
type == TASK16_DESC || type == TASK16_DESC_BUSY || type == LDT_DESC);
Desc_SetDescriptor(d, baseLo, limit, type, 0, DPL, present, DB, gran);
*(uint32 *)(++d) = baseHi; // High 32 bits of base.
*(((uint32 *)d) + 1) = 0; // Bits 8-12 of highest word are 0, rest ignored.
}
/*
*----------------------------------------------------------------------
* Desc_DBSize --
* Given descriptor, return the code/stack size that it specifies.
*----------------------------------------------------------------------
*/
static INLINE int
Desc_DBSize(const Descriptor *desc)
{
/*
* Code/stack size is determined by the D/B bit; bit 22 of the 2nd word.
* Shift the bit to position 1, mask it out, add 2. Result: 2 or 4.
*/
int cSz = ((((const uint32*)desc)[1] >> 21) & 2) + 2;
ASSERT(cSz == (Desc_DB(desc) ? 4 : 2));
return cSz;
}
/*
*----------------------------------------------------------------------
*
* Desc_ExpandedLimit --
*
* Return the limit in bytes of the descriptor. This is correct for both
* expand up and expand down limits. For expand down limits, the page
* corresponding to the limit << 12 is *not* included in the segment when
* the granularity bit is set. This makes it correct to append 0xfff to
* make sure accesses to this first page raise a GP.
*
* Results:
* The limit in bytes of the descriptor.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE VA32
Desc_ExpandedLimit(const Descriptor *d)
{
VA32 limit = Desc_GetLimit(d);
if (Desc_Gran(d)) {
limit <<= 12;
limit |= 0xfff;
}
return limit;
}
static INLINE VA32
Desc64_ExpandedLimit(const Descriptor64 *d)
{
VA32 limit = Desc64_GetLimit(d);
if (Desc64_Gran(d)) {
limit <<= 12;
limit |= 0xfff;
}
return limit;
}
/*
*----------------------------------------------------------------------
*
* Desc_PackLimit --
*
* Convert the limit of a descriptor into a 21-bit packed representation
*
* Results:
* packed representation of the limit
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE uint32
Desc_PackLimit(VA32 limit)
{
if (limit < (1 << 20)) {
return limit;
} else {
ASSERT((limit & 0xfff) == 0xfff);
return (limit >> 12) | (1 << 20);
}
}
/*
*----------------------------------------------------------------------
*
* Desc_UnpackLimit --
*
* Decode the representation of the limit as encoded by Desk_PackLimit
*
* Results:
* unpacked representation of the limit
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE VA
Desc_UnpackLimit(uint32 limit)
{
ASSERT(limit < (1 << 21));
if (limit & (1 << 20)) {
limit = (limit << 12) | 0xfff;
}
return limit;
}
/*
* For expand-down segments, valid offsets range from limit+1 to
* 0xffff or 0xffffffff, depending on the D/B bit in the descriptor.
*/
static INLINE Bool
Desc_InBoundsExpandDown(VA vaddr, VA limit, uint32 size, VA supremum)
{
ASSERT(supremum == 0xffff || supremum == 0xffffffff);
return vaddr > limit && vaddr <= supremum && size - 1 <= supremum - vaddr;
}
/* For expand-up segments, valid offsets range from 0 to limit. */
static INLINE Bool
Desc_InBoundsExpandUp(VA vaddr, VA limit, uint32 size)
{
return vaddr <= limit && size - 1 <= limit - vaddr;
}
/* Interrupt Gates
*
*/
typedef struct InterruptGate32 {
unsigned offset_lo : 16;
unsigned segment : 16;
unsigned unused : 5;
unsigned zero : 3;
unsigned type : 5;
unsigned DPL : 2;
unsigned present : 1;
unsigned offset_hi : 16;
} InterruptGate32;
/*
* Call Gates.
*/
typedef struct Gate {
unsigned offset_lo : 16;
unsigned segment : 16;
unsigned params : 5;
unsigned unused : 3;
unsigned type : 5;
unsigned DPL : 2;
unsigned present : 1;
unsigned offset_hi : 16;
} Gate;
#define GATE_OFFSET(_gate) (((_gate).offset_hi << 16) | (_gate).offset_lo)
#define GATE_OFFSET_LO(_dw) (((int)(_dw)) & 0xffff)
#define GATE_OFFSET_HI(_dw) ((((int)(_dw)) >> 16) & 0xffff)
#define CALL_GATE 0x04
#define TASK_GATE 0x05
#define INTER_GATE 0x0e
#define TRAP_GATE 0x0f
#define INTER_GATE_16 0x06
#define TRAP_GATE_16 0x07
#define GT_CALL(_gate) (((_gate).type & 0x17) == 0x04)
#define GT_TASK(_gate) (((_gate).type & 0x1f) == 0x05)
#define GT_INTR(_gate) (((_gate).type & 0x17) == 0x06)
#define GT_TRAP(_gate) (((_gate).type & 0x17) == 0x07)
#define GT_32BIT 0x08
#define GT_32BIT_INTR 0xe
#define GT_32BIT_TRAP 0xf
#define GT_64BIT_INTR 0xe
#define GT_64BIT_TRAP 0xf
#define GT_64BIT_CALL 0xc
#define GT64_INTR(_gate) ((_gate).type == GT_64BIT_INTR)
#define GT64_TRAP(_gate) ((_gate).type == GT_64BIT_TRAP)
#define GT64_CALL(_gate) ((_gate).type == GT_64BIT_CALL)
static INLINE VA
CallGate_GetOffset(const Gate *cg)
{
return (cg->offset_hi << 16) | cg->offset_lo;
}
static INLINE void
CallGate_SetOffset(Gate *cg, VA32 offset)
{
cg->offset_lo = GATE_OFFSET_LO(offset);
cg->offset_hi = GATE_OFFSET_HI(offset);
ASSERT(CallGate_GetOffset(cg) == offset);
}
/*
* Long mode interrupt/trap Gates.
*/
typedef struct Gate64 {
unsigned offset_0_15 : 16;
unsigned segment : 16;
unsigned ist : 3;
unsigned reserved0 : 5;
unsigned type : 5;
unsigned DPL : 2;
unsigned present : 1;
unsigned offset_16_31 : 16;
unsigned offset_32_63 : 32;
unsigned reserved1 : 32;
} Gate64;
#define GATE64_OFFSET_HI(_gate) ((uint64)(_gate).offset_32_63 << 32)
#define GATE64_OFFSET(_gate) ((uint64)(_gate).offset_32_63 << 32 | \
(uint64)(_gate).offset_16_31 << 16 | \
(uint64)(_gate).offset_0_15)
/*
* Descriptor Table Registers.
*/
/*
* Need to pack the DTR struct so the offset starts right after the
* limit.
*/
#pragma pack(push, 1)
typedef struct DTR32 {
uint16 limit;
uint32 offset;
} DTR32;
#pragma pack(pop)
#pragma pack(push, 1)
typedef struct DTR64 {
uint16 limit;
uint64 offset;
} DTR64;
#pragma pack(pop)
#if defined VMM || defined FROBOS_LONGMODE || defined VM_X86_64
typedef DTR64 DTR;
#else
typedef DTR32 DTR;
#endif
typedef union DTRWords32 {
DTR32 dtr;
uint32 word[2];
} DTRWords32;
typedef union DTRWords64 {
DTR64 dtr;
uint64 word[2];
} DTRWords64;
#endif //_X86DESC_H_
+696
View File
@@ -0,0 +1,696 @@
/*********************************************************
* Copyright (C) 1998-2019 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
*
*********************************************************/
/*
* x86msr.h --
*
* MSR number definitions.
*/
#ifndef _X86MSR_H_
#define _X86MSR_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMX
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#include "includeCheck.h"
#include "vm_basic_types.h"
#include "community_source.h"
#if defined __cplusplus
extern "C" {
#endif
#define SIZEOF_X86_MSR 8
/*
* Results of calling rdmsr(msrNum) on all logical processors.
*/
#ifdef _MSC_VER
#pragma warning (disable :4200) // non-std extension: zero-sized array in struct
#endif
typedef
#include "vmware_pack_begin.h"
struct MSRReply {
/*
* Unique host logical CPU identifier. It does not change across queries, so
* we use it to correlate the replies of multiple queries.
*/
uint64 tag; // OUT
uint64 msrVal; // OUT
uint8 implemented; // OUT
uint8 _pad[7];
}
#include "vmware_pack_end.h"
MSRReply;
typedef
#include "vmware_pack_begin.h"
struct MSRQuery {
uint32 msrNum; // IN
uint32 numLogicalCPUs; // IN/OUT
MSRReply logicalCPUs[0]; // OUT
}
#include "vmware_pack_end.h"
MSRQuery;
#define MSR_TSC 0x00000010
#define MSR_PLATFORM_ID 0x00000017
#define MSR_APIC_BASE 0x0000001b
#define MSR_SMI_COUNT 0x00000034 // Intel Nehalem Family
#define MSR_CORE_THREAD_COUNT 0x00000035 // Intel Nehalem Family +
#define MSR_FEATCTL 0x0000003a
#define MSR_TSC_ADJUST 0x0000003b
#define MSR_SPEC_CTRL 0x00000048
#define MSR_PRED_CMD 0x00000049
#define MSR_BIOS_UPDT_TRIG 0x00000079
#define MSR_BIOS_SIGN_ID 0x0000008b
#define MSR_PERFCTR0 0x000000c1
#define MSR_PERFCTR1 0x000000c2
#define MSR_PLATFORM_INFO 0x000000ce // Intel Nehalem Family
#define MSR_MTRR_CAP 0x000000fe
#define MSR_L2CFG 0x0000011e
#define MSR_SYSENTER_CS 0x00000174
#define MSR_SYSENTER_ESP 0x00000175
#define MSR_SYSENTER_EIP 0x00000176
#define MSR_MCG_CAP 0x00000179
#define MSR_MCG_STATUS 0x0000017a
#define MSR_MCG_CTL 0x0000017b
#define MSR_MCG_EXT_CTL 0x000004d0
#define MSR_EVNTSEL0 0x00000186
#define MSR_EVNTSEL1 0x00000187
#define MSR_FLEX_RATIO 0x00000194 // Intel Nehalem Family
#define MSR_CLOCK_MODULATION 0x0000019a
#define MSR_MISC_ENABLE 0x000001a0
#define MSR_DEBUGCTL 0x000001d9
#define MSR_TSC_DEADLINE 0x000006e0
#define MSR_EFER 0xc0000080
#define MSR_FSBASE 0xc0000100
#define MSR_GSBASE 0xc0000101
#define MSR_KERNELGSBASE 0xc0000102
#define MSR_TSC_AUX 0xc0000103
#define MSR_BD_TSC_RATIO 0xc0000104
#define IA32_MSR_ARCH_CAPABILITIES 0x10a
#define MSR_ARCH_CAPABILITIES_RDCL_NO (1ULL << 0)
#define MSR_ARCH_CAPABILITIES_IBRS_ALL (1ULL << 1)
#define MSR_ARCH_CAPABILITIES_RSBA (1ULL << 2)
#define MSR_ARCH_CAPABILITIES_NOL1F_VMENTRY (1ULL << 3)
#define MSR_ARCH_CAPABILITIES_SSB_NO (1ULL << 4)
#define MSR_SPEC_CTRL_IBRS (1UL << 0)
#define MSR_SPEC_CTRL_STIBP (1UL << 1)
#define MSR_PRED_CMD_IBPB (1UL << 0)
#define MSR_MISC_FEATURES_ENABLES 0x140
/* Intel Core Architecture and later: use only architected counters. */
#define IA32_MSR_PERF_CAPABILITIES 0x345
#define MSR_PERF_CAPABILITIES_LBRFMT_SHIFT 0
#define MSR_PERF_CAPABILITIES_LBRFMT_MASK 0x3f
#define MSR_PERF_CAPABILITIES_PEBSTRAP (1u << 6)
#define MSR_PERF_CAPABILITIES_PEBSSAVEARCHREGS (1u << 7)
#define MSR_PERF_CAPABILITIES_PEBSRECORDFMT_SHIFT 8
#define MSR_PERF_CAPABILITIES_PEBSRECORDFMT_MASK 0xf
#define MSR_PERF_CAPABILITIES_FREEZE_WHILE_SMM (1u << 12)
#define MSR_PERF_CAPABILITIES_FULL_WIDTH_WRITES (1u << 13)
#define IA32_MSR_PEBS_ENABLE 0x3f1
typedef enum {
SL_PMC_FLAGS_NONE = 0x00, /* No flags. */
SL_PMC_FLAGS_LBR_VA32 = 0x01, /* LBR format: 32-bit VA. */
SL_PMC_FLAGS_LBR_LA64 = 0x02, /* LBR format: 64-bit LA. */
SL_PMC_FLAGS_LBR_VA64 = 0x04, /* LBR format: 64-bit VA. */
SL_PMC_FLAGS_LBR_PACKED_VA32 = 0x08, /* LBR format: 2x32-bit VAs. */
} StateLoggerPMCFlags;
#define MSR_MTRR_BASE0 0x00000200
#define MSR_MTRR_MASK0 0x00000201
#define MSR_MTRR_BASE1 0x00000202
#define MSR_MTRR_MASK1 0x00000203
#define MSR_MTRR_BASE2 0x00000204
#define MSR_MTRR_MASK2 0x00000205
#define MSR_MTRR_BASE3 0x00000206
#define MSR_MTRR_MASK3 0x00000207
#define MSR_MTRR_BASE4 0x00000208
#define MSR_MTRR_MASK4 0x00000209
#define MSR_MTRR_BASE5 0x0000020a
#define MSR_MTRR_MASK5 0x0000020b
#define MSR_MTRR_BASE6 0x0000020c
#define MSR_MTRR_MASK6 0x0000020d
#define MSR_MTRR_BASE7 0x0000020e
#define MSR_MTRR_MASK7 0x0000020f
#define MSR_MTRR_FIX64K_00000 0x00000250
#define MSR_MTRR_FIX16K_80000 0x00000258
#define MSR_MTRR_FIX16K_A0000 0x00000259
#define MSR_MTRR_FIX4K_C0000 0x00000268
#define MSR_MTRR_FIX4K_C8000 0x00000269
#define MSR_MTRR_FIX4K_D0000 0x0000026a
#define MSR_MTRR_FIX4K_D8000 0x0000026b
#define MSR_MTRR_FIX4K_E0000 0x0000026c
#define MSR_MTRR_FIX4K_E8000 0x0000026d
#define MSR_MTRR_FIX4K_F0000 0x0000026e
#define MSR_MTRR_FIX4K_F8000 0x0000026f
#define MSR_MTRR_DEF_TYPE 0x000002ff
#define MSR_CR_PAT 0x00000277
#define MSR_MC0_CTL 0x00000400
#define MSR_MC0_STATUS 0x00000401
#define MSR_MC0_ADDR 0x00000402
#define MSR_MC0_MISC 0x00000403
#define MSR_MC0_CTL2 0x00000280
#define MSR_DS_AREA 0x00000600
#define MSR_LASTBRANCHFROMIP 0x000001db // Intel P6 Family
#define MSR_LASTBRANCHTOIP 0x000001dc // Intel P6 Family
#define MSR_LASTINTFROMIP 0x000001dd // Intel P6 Family
#define MSR_LASTINTTOIP 0x000001de // Intel P6 Family
#define MSR_LER_FROM_LIP 0x000001d7 // Intel Pentium4 Family
#define MSR_LER_TO_LIP 0x000001d8 // Intel Pentium4 Family
#define MSR_LASTBRANCH_TOS 0x000001da // Intel Pentium4 Family
#define MSR_LASTBRANCH_0 0x000001db // Intel Pentium4 Family
#define MSR_LASTBRANCH_1 0x000001dc // Intel Pentium4 Family
#define MSR_LASTBRANCH_2 0x000001dd // Intel Pentium4 Family
#define MSR_LASTBRANCH_3 0x000001de // Intel Pentium4 Family
#define CORE_LBR_SIZE 8
#define CORE2_LBR_SIZE 4
/* Power Management MSRs */
#define MSR_PERF_STATUS 0x00000198 // Current Performance State (ro)
#define MSR_PERF_CTL 0x00000199 // Target Performance State (rw)
#define MSR_POWER_CTL 0x000001fc // Power Control Register
#define MSR_CST_CONFIG_CTL 0x000000e2 // C-state Configuration (CORE)
#define MSR_MISC_PWR_MGMT 0x000001aa // Misc Power Management (NHM)
#define MSR_ENERGY_PERF_BIAS 0x000001b0 // Performance Energy Bias Hint
#define MSR_PKG_C2_RESIDENCY 0x0000060d
#define MSR_PKG_C3_RESIDENCY 0x000003f8
#define MSR_PKG_C6_RESIDENCY 0x000003f9
#define MSR_PKG_C7_RESIDENCY 0x000003fa
#define MSR_CORE_C3_RESIDENCY 0x000003fc
#define MSR_CORE_C6_RESIDENCY 0x000003fd
#define MSR_CORE_C7_RESIDENCY 0x000003fe
/* MSR_POWER_CTL bits (Intel) */
#define MSR_POWER_CTL_C1E 0x00000002 // C1E enable (NHM)
/* P-State Hardware Coordination Feedback Capability (Intel) */
#define MSR_MPERF 0x000000e7 // Maximum Performance (rw)
#define MSR_APERF 0x000000e8 // Actual Performance (rw)
/* Software Controlled Clock Modulation and Thermal Monitors (Intel) */
#define MSR_CLOCK_MODULATION 0x0000019a // Thermal Monitor Control (rw)
#define MSR_THERM_INTERRUPT 0x0000019b // Thermal Interrupt Control (rw)
#define MSR_THERM_STATUS 0x0000019c // Thermal Monitor Status (rw)
#define MSR_THERM2_CTL 0x0000019d // Thermal Monitor 2 Control (ro)
/* x2APIC MSRs */
#define MSR_X2APIC_BASE 0x00000800
#define MSR_X2APIC_MAX 0x0000083f
#define MSR_X2APIC_LIMIT 0x00000bff
#define MSR_X2APIC_ID 0x00000802
#define MSR_X2APIC_VERSION 0x00000803
#define MSR_X2APIC_TPR 0x00000808
#define MSR_X2APIC_PPR 0x0000080a
#define MSR_X2APIC_EOI 0x0000080b
#define MSR_X2APIC_LDR 0x0000080d
#define MSR_X2APIC_SVR 0x0000080f
#define MSR_X2APIC_ISR 0x00000810
#define MSR_X2APIC_TMR 0x00000818
#define MSR_X2APIC_IRR 0x00000820
#define MSR_X2APIC_ESR 0x00000828
#define MSR_X2APIC_CMCILVT 0x0000082f
#define MSR_X2APIC_ICRLO 0x00000830
#define MSR_X2APIC_TIMERLVT 0x00000832
#define MSR_X2APIC_THERMLVT 0x00000833
#define MSR_X2APIC_PCLVT 0x00000834
#define MSR_X2APIC_LVT0 0x00000835
#define MSR_X2APIC_LVT1 0x00000836
#define MSR_X2APIC_ERRLVT 0x00000837
#define MSR_X2APIC_INITCNT 0x00000838
#define MSR_X2APIC_CURCNT 0x00000839
#define MSR_X2APIC_DIVIDER 0x0000083e
#define MSR_X2APIC_SELFIPI 0x0000083f
#define MSR_BNDCFGS 0x00000d90 // Sup. mode bounds configuration
#define MSR_XSS 0x00000da0 // Extended Supervisor State Mask
/* RTIT MSRs */
#define MSR_RTIT_CTL 0x00000570
#define MSR_RTIT_STATUS 0x00000571
#define MSR_RTIT_OUTPUT_BASE 0x00000560
#define MSR_RTIT_OUTPUT_MASK_PTRS 0x00000561
#define MSR_RTIT_CR3_MATCH 0x00000572
#define MSR_RTIT_ADDR0_A 0x00000580
#define MSR_RTIT_ADDR0_B 0x00000581
#define MSR_RTIT_ADDR1_A 0x00000582
#define MSR_RTIT_ADDR1_B 0x00000583
#define MSR_RTIT_ADDR2_A 0x00000584
#define MSR_RTIT_ADDR2_B 0x00000585
#define MSR_RTIT_ADDR3_A 0x00000586
#define MSR_RTIT_ADDR3_B 0x00000587
#define MSR_RTIT_NUM_OF_ADDR_REG 8
/* RTIT control MSR bits */
#define MSR_RTIT_CTL_TRACE_EN (1LL<<0) // Enable tracing
#define MSR_RTIT_CTL_CYC_EN (1LL<<1) // Enable CYC Packet
#define MSR_RTIT_CTL_OS (1LL<<2) // CPL0 filter
#define MSR_RTIT_CTL_USER (1LL<<3) // CPL > 0 filter
#define MSR_RTIT_CTL_FABRIC_EN (1LL<<6) // Trace output direction
#define MSR_RTIT_CTL_CR3_FILTER_EN (1LL<<7) // Enable CR3 filter
#define MSR_RTIT_CTL_TOPA (1LL<<8) // Enable ToPA output scheme
#define MSR_RTIT_CTL_MTC_EN (1LL<<9) // Enable MTC packet
#define MSR_RTIT_CTL_TSC_EN (1LL<<10) // Enable TSC packet
#define MSR_RTIT_CTL_DIS_RETC (1LL<<11) // Disable RET compression
#define MSR_RTIT_CTL_BRANCH_EN (1LL<<13) // Disable COFI-based packets
#define MSR_RTIT_CTL_RSVD CONST64U(0xffff0000f0841030) // Reserved bits
#define MSR_RTIT_CTL_MTCFREQ_MASK CONST64U(0xf)
#define MSR_RTIT_CTL_MTCFREQ_SHIFT 14
#define MSR_RTIT_CTL_MTCFREQ(_msr) \
(((_msr) >> MSR_RTIT_CTL_MTCFREQ_SHIFT) & MSR_RTIT_CTL_MTCFREQ_MASK)
#define MSR_RTIT_CTL_CYCTHRESH_MASK CONST64U(0xf)
#define MSR_RTIT_CTL_CYCTHRESH_SHIFT 19
#define MSR_RTIT_CTL_CYCTHRESH(_msr) \
(((_msr) >> MSR_RTIT_CTL_CYCTHRESH_SHIFT) & MSR_RTIT_CTL_CYCTHRESH_MASK)
#define MSR_RTIT_CTL_PSBFREQ_MASK CONST64U(0xf)
#define MSR_RTIT_CTL_PSBFREQ_SHIFT 24
#define MSR_RTIT_CTL_PSBFREQ(_msr) \
(((_msr) >> MSR_RTIT_CTL_PSBFREQ_SHIFT) & MSR_RTIT_CTL_PSBFREQ_MASK)
#define MSR_RTIT_CTL_ADDR0_CFG_MASK CONST64U(0xf)
#define MSR_RTIT_CTL_ADDR0_CFG_SHIFT 32
#define MSR_RTIT_CTL_ADDR0_CFG(_msr) \
(((_msr) >> MSR_RTIT_CTL_ADDR0_CFG_SHIFT) & MSR_RTIT_CTL_ADDR0_CFG_MASK)
#define MSR_RTIT_CTL_ADDR1_CFG_MASK CONST64U(0xf)
#define MSR_RTIT_CTL_ADDR1_CFG_SHIFT 36
#define MSR_RTIT_CTL_ADDR1_CFG(_msr) \
(((_msr) >> MSR_RTIT_CTL_ADDR1_CFG_SHIFT) & MSR_RTIT_CTL_ADDR1_CFG_MASK)
#define MSR_RTIT_CTL_ADDR2_CFG_MASK CONST64U(0xf)
#define MSR_RTIT_CTL_ADDR2_CFG_SHIFT 40
#define MSR_RTIT_CTL_ADDR2_CFG(_msr) \
(((_msr) >> MSR_RTIT_CTL_ADDR2_CFG_SHIFT) & MSR_RTIT_CTL_ADDR2_CFG_MASK)
#define MSR_RTIT_CTL_ADDR3_CFG_MASK CONST64U(0xf)
#define MSR_RTIT_CTL_ADDR3_CFG_SHIFT 44
#define MSR_RTIT_CTL_ADDR3_CFG(_msr) \
(((_msr) >> MSR_RTIT_CTL_ADDR3_CFG_SHIFT) & MSR_RTIT_CTL_ADDR3_CFG_MASK)
/* RTIT status MSR bits */
#define MSR_RTIT_STATUS_FILTER_EN (1LL<<0)
#define MSR_RTIT_STATUS_CONTEXT_EN (1LL<<1)
#define MSR_RTIT_STATUS_TRIGGER_EN (1LL<<2)
#define MSR_RTIT_STATUS_ERROR (1LL<<4)
#define MSR_RTIT_STATUS_STOPPED (1LL<<5)
#define MSR_RTIT_STATUS_RSVD CONST64U(0xfffe0000ffffffc8)
#define MSR_RTIT_STATUS_PKT_BYTES_CNT_MASK CONST64U(0x1ffff)
#define MSR_RTIT_STATUS_PKT_BYTES_CNT_SHIFT 32
#define MSR_RTIT_STATUS_PKT_BYTES_CNT(_msr) \
(((_msr) >> MSR_RTIT_STATUS_PKT_BYTES_CNT_SHIFT) & \
MSR_RTIT_STATUS_PKT_BYTES_CNT_MASK)
/* RTIT CR3 MSR bits */
#define MSR_RTIT_CR3_MATCH_MASK CONST64U(~0x1f)
/* RTIT output base MSR bits */
#define MSR_RTIT_OUTPUT_BASE_MASK CONST64U(~0x7f)
#define MSR_RTIT_OUTPUT_BASE_RSVD CONST64U(0x7f)
/* RTIT output mask ptrs MSR bits */
#define MSR_RTIT_OUTPUT_MASK_LOWERMASK CONST64U(0x7f)
/*
* Get the mask value for the single contiguous output region
* when MSR_RTIT_CTL.ToPA is masked
*/
#define MSR_RTIT_OUTPUT_MASK_MASK CONST64U(0xffffffff)
#define MSR_RTIT_OUTPUT_MASK(_msr) \
((_msr) & MSR_RTIT_OUTPUT_MASK_MASK)
/* Get the offset pointer of the ToPA table when MSR_RTIT_CTL.ToPA is set */
#define MSR_RTIT_OUTPUT_TABLE_OFFSET_MASK CONST64U(0x1ffffff)
#define MSR_RTIT_OUTPUT_TABLE_OFFSET_SHIFT 7
#define MSR_RTIT_OUTPUT_TABLE_OFFSET(_msr) \
((((_msr) >> MSR_RTIT_OUTPUT_TABLE_OFFSET_SHIFT) & \
MSR_RTIT_OUTPUT_TABLE_OFFSET_MASK) << 3)
#define MSR_RTIT_OUTPUT_TABLE_ENTRY(_msr) \
(((_msr) >> MSR_RTIT_OUTPUT_TABLE_OFFSET_SHIFT) & \
MSR_RTIT_OUTPUT_TABLE_OFFSET_MASK)
#define MSR_RTIT_OUTPUT_OFFSET_MASK CONST64U(0xffffffff)
#define MSR_RTIT_OUTPUT_OFFSET_SHIFT 32
#define MSR_RTIT_OUTPUT_OFFSET(_msr) \
(((_msr) >> MSR_RTIT_OUTPUT_OFFSET_SHIFT) & \
MSR_RTIT_OUTPUT_OFFSET_MASK)
#define MSR_RTIT_CR3_MATCH_RSVD CONST64U(0x1f)
/* SGX MSRs */
#define MSR_SGX_SVN_STATUS 0x00000500
/* SGX SVN status MSR fields */
#define MSR_SGX_SVN_STATUS_LOCK 0x1
#define MSR_SGX_SVN_STATUS_SINIT_SVN CONST64U(0xff0000)
#define MSR_SGX_SVN_STATUS_RSVD CONST64U(0xffffffffff00fffe)
/*
* SGX Flexible Launch Control MSRs.
* These MSRs store hash of Launch Enclave's public key.
*/
#define MSR_SGXLEPUBKEYHASH0 0x0000008c
#define MSR_SGXLEPUBKEYHASH1 0x0000008d
#define MSR_SGXLEPUBKEYHASH2 0x0000008e
#define MSR_SGXLEPUBKEYHASH3 0x0000008f
#define NUM_SGXLEPUBKEYHASH_MSRs (4)
/* MSR_CR_PAT power-on value */
#define MSR_CR_PAT_DEFAULT 0x0007040600070406ULL
/* MSR_MISC_ENABLE bits (Intel) */
#define MSR_MISC_ENABLE_FAST_STRINGS (1LL<<0) // Enable Fast string ops
#define MSR_MISC_ENABLE_FOPCODE_COMPAT (1LL<<2)
#define MSR_MISC_ENABLE_TM1 (1LL<<3) // Enable Thermal Monitor 1
#define MSR_MISC_ENABLE_EMON_AVAILABLE (1LL<<7) // Perf Monitoring Available
#define MSR_MISC_ENABLE_BTS_UNAVAILABLE (1LL<<11)
#define MSR_MISC_ENABLE_PEBS_UNAVAILABLE (1LL<<12)
#define MSR_MISC_ENABLE_TM2 (1LL<<13) // Enable Thermal Monitor 2
#define MSR_MISC_ENABLE_ESS (1LL<<16) // Enable Enhanced SpeedStep
#define MSR_MISC_ENABLE_LIMIT_CPUID (1LL<<22) // Enable CPUID maxval
#define MSR_MISC_ENABLE_C1E (1LL<<25) // C1E enable (Merom/Penryn)
#define MSR_MISC_ENABLE_ACNT2 (1LL<<27) // ACNT2 (Nehalem only, deprecated)
#define MSR_MISC_ENABLE_TURBO_DISABLE (1LL<<38) // Turbo Mode Disabled
/* DebugCtlMSR bits */
#define MSR_DEBUGCTL_LBR 0x00000001
#define MSR_DEBUGCTL_BTF 0x00000002
#define MSR_DEBUGCTL_TR 0x00000040
#define MSR_DEBUGCTL_BTS 0x00000080
#define MSR_DEBUGCTL_BTINT 0x00000100
#define MSR_DEBUGCTL_BTS_OFF_OS 0x00000200
#define MSR_DEBUGCTL_BTS_OFF_USR 0x00000400
#define MSR_DEBUGCTL_FREEZE_LBRS_ON_PMI 0x00000800
#define MSR_DEBUGCTL_FREEZE_PERFMON_ON_PMI 0x00001000
#define MSR_DEBUGCTL_ENABLE_UNCORE_PMI 0x00002000
#define MSR_DEBUGCTL_FREEZE_WHILE_SMM 0x00004000
#define MSR_DEBUGCTL_RTM 0x00008000
#define MSR_DEBUGCTL_RSVD 0xffffffffffff003cULL
/* Feature control bits */
#define MSR_FEATCTL_LOCK 0x00000001
#define MSR_FEATCTL_SMXE 0x00000002
#define MSR_FEATCTL_VMXE 0x00000004
#define MSR_FEATCTL_SENTERP 0x00007F00
#define MSR_FEATCTL_SENTERE 0x00008000
#define MSR_FEATCTL_FLCE 0x00020000
#define MSR_FEATCTL_SGXE 0x00040000
#define MSR_FEATCTL_LMCE 0x00100000
/* MSR_EFER bits. */
#define MSR_EFER_SCE 0x0000000000000001ULL /* Sys call ext'ns: r/w */
#define MSR_EFER_RAZ 0x00000000000000feULL /* Read as zero */
#define MSR_EFER_LME 0x0000000000000100ULL /* Long mode enable: r/w */
#define MSR_EFER_LMA 0x0000000000000400ULL /* Long mode active: r/o */
#define MSR_EFER_NXE 0x0000000000000800ULL /* No-exec enable: r/w */
#define MSR_EFER_SVME 0x0000000000001000ULL /* SVM(AMD) enabled? r/w */
#define MSR_EFER_LMSLE 0x0000000000002000ULL /* LM seg lim enable:r/w */
#define MSR_EFER_FFXSR 0x0000000000004000ULL /* Fast FXSAVE: r/w */
#define MSR_EFER_TCE 0x0000000000008000ULL /* Trans. cache ext. r/w */
#define MSR_EFER_MBZ 0xffffffffffff0200ULL /* Must be zero (resrvd) */
#define MSR_AMD_PATCH_LOADER 0xc0010020
/* This ifndef is necessary because this is defined by some kernel headers. */
#ifndef MSR_K7_HWCR
#define MSR_K7_HWCR 0xc0010015 // Available on AMD processors
#endif
#define MSR_K7_HWCR_SSEDIS 0x00008000ULL // Disable SSE bit
#define MSR_K7_HWCR_MONMWAITUSEREN 0x00000400ULL // Enable MONITOR/MWAIT CPL>0
#define MSR_K7_HWCR_TLBFFDIS 0x00000040ULL // Disable TLB Flush Filter
#define MSR_K7_HWCR_SMMLOCK 0x00000001ULL // Lock SMM environment
#ifndef MSR_K8_SYSCFG
#define MSR_K8_SYSCFG 0xc0010010
#endif
#define MSR_K8_SYSCFG_MTRRTOM2EN (1ULL<<21)
#define MSR_K8_SYSCFG_TOM2FORCEMEMTYPEWB (1ULL<<22)
#define MSR_K8_TOPMEM2 0xc001001d
/* AMD "Greyhound" MSRs */
#define MSR_GH_CMPHLT 0xc0010055 // Interrupt Pending & CMP Halt
#define MSR_GH_CMPHLT_C1E (1ULL<<27) // C1E on CMP Halt is enabled
#define MSR_GH_CMPHLT_SMI (1ULL<<28) // SMI on CMP Halt is enabled
#define MSR_GH_OSVW_LENGTH 0xc0010140 // OS visible workaround length
#define MSR_GH_OSVW_STATUS 0xc0010141 // OS visible workaround bits
#define MSR_GH_OSVW_C1E (1ULL<<1) // Workaround for C1E not needed
#define MSR_GH_PSTATE_LIMIT 0xc0010061 // P-state Limit Register
#define MSR_GH_PSTATE_CONTROL 0xc0010062 // P-state Control Register [2:0]
#define MSR_GH_PSTATE_STATUS 0xc0010063 // P-state Status Register [2:0]
#define MSR_GH_PSTATE0 0xc0010064 // P-state 0
#define MSR_GH_PSTATE1 0xc0010065 // P-state 1
#define MSR_GH_PSTATE2 0xc0010066 // P-state 2
#define MSR_GH_PSTATE3 0xc0010067 // P-state 3
#define MSR_GH_PSTATE4 0xc0010068 // P-state 4
#define MSR_GH_COFVID_CONTROL 0xc0010070 // COFVID Control Register
#define MSR_GH_COFVID_STATUS 0xc0010071 // COFVID Status Register
#define MSR_AMD_MCA_INTR_CFG 0xc0000410 // MCA Interrupt Configuration
/* SVM related MSRs */
#define MSR_VM_CR 0xc0010114
#define MSR_IGNNE 0xc0010115
#define MSR_SMM_CTL 0xc0010116
#define MSR_VM_HSAVE_PA 0xc0010117
#define MSR_VM_CR_DPD 0x0000000000000001ULL // Disable HDT
#define MSR_VM_CR_R_INIT 0x0000000000000002ULL
#define MSR_VM_CR_DIS_A20M 0x0000000000000004ULL
#define MSR_VM_CR_SVM_LOCK 0x0000000000000008ULL
#define MSR_VM_CR_SVME_DISABLE 0x0000000000000010ULL
#define MSR_VM_CR_RESERVED 0xffffffffffffffe0ULL
#define MSR_AMD_DE_CFG 0xc0011029 // Decode configuration
#define MSR_AMD_DE_CFG_BIT1 (1ULL<<1)
/* Syscall/Sysret related MSRs (x86_64) */
#define MSR_STAR 0xc0000081 // Also present on Athlons.
#define MSR_LSTAR 0xc0000082
#define MSR_CSTAR 0xc0000083
#define MSR_SFMASK 0xc0000084
/*
* Hyper-V synthetic MSRs.
*/
#define MSR_HYPERV_GUEST_OS_ID 0x40000000
#define MSR_HYPERV_HYPERCALL 0x40000001
#define MSR_HYPERV_VP_INDEX 0x40000002
#define MSR_HYPERV_RESET 0x40000003
#define MSR_HYPERV_VP_RUNTIME 0x40000010
#define MSR_HYPERV_TIME_REF_COUNT 0x40000020
#define MSR_HYPERV_REFERENCE_TSC 0x40000021
#define MSR_HYPERV_TIME_TSC_FREQUENCY 0x40000022
#define MSR_HYPERV_TIME_APIC_FREQUENCY 0x40000023
#define MSR_HYPERV_EOI 0x40000070
#define MSR_HYPERV_ICR 0x40000071
#define MSR_HYPERV_TPR 0x40000072
#define MSR_HYPERV_APIC_ASSIST_PAGE 0x40000073
#define MSR_HYPERV_SCONTROL 0x40000080
#define MSR_HYPERV_SVERSION 0x40000081
#define MSR_HYPERV_SIEFP 0x40000082
#define MSR_HYPERV_SIMP 0x40000083
#define MSR_HYPERV_EOM 0x40000084
#define MSR_HYPERV_SINT0 0x40000090
#define MSR_HYPERV_SINT1 0x40000091
#define MSR_HYPERV_SINT2 0x40000092
#define MSR_HYPERV_SINT3 0x40000093
#define MSR_HYPERV_SINT4 0x40000094
#define MSR_HYPERV_SINT5 0x40000095
#define MSR_HYPERV_SINT6 0x40000096
#define MSR_HYPERV_SINT7 0x40000097
#define MSR_HYPERV_SINT8 0x40000098
#define MSR_HYPERV_SINT9 0x40000099
#define MSR_HYPERV_SINT10 0x4000009A
#define MSR_HYPERV_SINT11 0x4000009B
#define MSR_HYPERV_SINT12 0x4000009C
#define MSR_HYPERV_SINT13 0x4000009D
#define MSR_HYPERV_SINT14 0x4000009E
#define MSR_HYPERV_SINT15 0x4000009F
#define MSR_HYPERV_STIMER0_CONFIG 0x400000B0
#define MSR_HYPERV_STIMER0_COUNT 0x400000B1
#define MSR_HYPERV_STIMER1_CONFIG 0x400000B2
#define MSR_HYPERV_STIMER1_COUNT 0x400000B3
#define MSR_HYPERV_STIMER2_CONFIG 0x400000B4
#define MSR_HYPERV_STIMER2_COUNT 0x400000B5
#define MSR_HYPERV_STIMER3_CONFIG 0x400000B6
#define MSR_HYPERV_STIMER3_COUNT 0x400000B7
#define MSR_HYPERV_POWER_STATE_TRIGGER_C1 0x400000C1
#define MSR_HYPERV_POWER_STATE_TRIGGER_C2 0x400000C2
#define MSR_HYPERV_POWER_STATE_TRIGGER_C3 0x400000C3
#define MSR_HYPERV_POWER_STATE_CONFIG_C1 0x400000D1
#define MSR_HYPERV_POWER_STATE_CONFIG_C2 0x400000D2
#define MSR_HYPERV_POWER_STATE_CONFIG_C3 0x400000D3
#define MSR_HYPERV_STATS_PARTITION_RETAIL_PAGE 0x400000E0
#define MSR_HYPERV_STATS_PARTITION_INTERNAL_PAGE 0x400000E1
#define MSR_HYPERV_STATS_VP_RETAIL_PAGE 0x400000E2
#define MSR_HYPERV_STATS_VP_INTERNAL_PAGE 0x400000E3
#define MSR_HYPERV_GUEST_IDLE 0x400000F0
#define MSR_HYPERV_SYNTH_DEBUG_CONTROL 0x400000F1
#define MSR_HYPERV_SYNTH_DEBUG_STATUS 0x400000F2
#define MSR_HYPERV_SYNTH_DEBUG_SEND_BUFFER 0x400000F3
#define MSR_HYPERV_SYNTH_DEBUG_RECEIVE_BUFFER 0x400000F4
#define MSR_HYPERV_SYNTH_DEBUG_PENDING_BUFFER 0x400000F5
/* Guest Crash Enlightenment MSRs */
#define MSR_HYPERV_CRASH_P0 0x40000100
#define MSR_HYPERV_CRASH_P1 0x40000101
#define MSR_HYPERV_CRASH_P2 0x40000102
#define MSR_HYPERV_CRASH_P3 0x40000103
#define MSR_HYPERV_CRASH_P4 0x40000104
#define MSR_HYPERV_CRASH_CTL 0x40000105
#define MSR_HYPERV_HYPERCALL_EN 1ULL
#define MSR_HYPERV_REFERENCE_TSC_EN 1ULL
#define MSR_HYPERV_VP_ASSIST_EN 1ULL
#define MSR_HYPERV_GUESTOSID_VENDOR_SHIFT 48
#define MSR_HYPERV_GUESTOSID_VENDOR_MASK 0xfULL
#define MSR_HYPERV_GUESTOSID_VENDOR_MICROSOFT 1ULL
#define MSR_HYPERV_GUESTOSID_OS_SHIFT 40
#define MSR_HYPERV_GUESTOSID_OS_MASK 0xfULL
#define MSR_HYPERV_GUESTOSID_OS_WINNT_DERIVATIVE 4ULL
/*
* MTRR bit description
*/
#define MTRR_CAP_WC 0x400
#define MTRR_CAP_FIX 0x100
#define MTRR_CAP_VCNT_MASK 0xff
#define MTRR_DEF_ENABLE 0x800
#define MTRR_DEF_FIXED_ENABLE 0x400
#define MTRR_DEF_TYPE_MASK 0xff
#define MTRR_BASE_TYPE_MASK 0xff
#define MTRR_MASK_VALID 0x800
typedef unsigned char MTRRType;
#define MTRR_TYPE_UC 0
#define MTRR_TYPE_WC 1
#define MTRR_TYPE_WT 4
#define MTRR_TYPE_WP 5
#define MTRR_TYPE_WB 6
/* PAT Memory Type Only */
/* UC- is equivalent to UC, except that the MTRR values take precedence */
#define MTRR_TYPE_UCM 7
/*
* This value is marked as reserved in the Intel manual. We use it to
* specify that type is unknown as it is very unlikely that Intel will
* use this value. Note that linux is taking the same liberty.
*/
#define MTRR_TYPE_UNKNOW 0xff
/*
* PERF_STATUS bits
*/
#define MSR_PERF_STATUS_MAX_BUS_RATIO_SHIFT 40
#define MSR_PERF_STATUS_MAX_BUS_RATIO_MASK 0x1f
/*
* PLATFORM_INFO bits
*/
#define MSR_PLATFORM_INFO_CPUID_FAULTING (1UL << 31) // Faulting is supported
#define MSR_PLATFORM_INFO_MIN_RATIO_SHIFT 40
#define MSR_PLATFORM_INFO_MIN_RATIO_MASK 0xff
#define MSR_PLATFORM_INFO_MAX_NONTURBO_RATIO_SHIFT 8
#define MSR_PLATFORM_INFO_MAX_NONTURBO_RATIO_MASK 0xff
/*
* MISC_FEATURES_ENABLES bits
*/
#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULTING 1
/*
* Platform Quality of Service
*/
#define MSR_INTEL_QOS_EVTSEL 0xc8d
#define MSR_INTEL_QOS_CTR 0xc8e
#define MSR_INTEL_QOS_ASSOC 0xc8f
static INLINE uint32
X86MSR_SysCallEIP(uint64 star)
{
return (uint32)star;
}
static INLINE uint16
X86MSR_SysCallCS(uint64 star)
{
return (uint16)(star >> 32);
}
static INLINE uint16
X86MSR_SysRetCS(uint64 star)
{
return (uint16)(star >> 48);
}
#if defined __cplusplus
}
#endif
#endif /* _X86MSR_H_ */
Loaded 100 of 165 files, more files were not shown because too many files have changed in this diff. Show more